diff options
| author | Paul Eggert | 2017-10-01 22:31:39 -0700 |
|---|---|---|
| committer | Paul Eggert | 2017-10-01 22:33:20 -0700 |
| commit | 135bca574c31b7bf6df6c63d28f180956928dde7 (patch) | |
| tree | 1259c514b5304e7b1dbb8a9098f0a6dd63e00003 | |
| parent | 4829a3b033b119b088947d14b73efc197b2547fa (diff) | |
| download | emacs-135bca574c31b7bf6df6c63d28f180956928dde7.tar.gz emacs-135bca574c31b7bf6df6c63d28f180956928dde7.zip | |
Port file-system-info to non-Microsoft
* admin/merge-gnulib (GNULIB_MODULES): Add fsusage.
* doc/emacs/files.texi (Directories): Remove documentation of
now-obsolete directory-free-space-program and
directory-free-space-args.
* etc/NEWS: Mention change.
* etc/PROBLEMS: Slow df is no longer a problem.
* lib/fsusage.c, lib/fsusage.h, m4/fsusage.m4:
New files, copied from Gnulib.
* lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate.
* lisp/dired.el (dired-free-space-program)
(dired-free-space-args): These aliases are now obsolete.
* lisp/files.el (directory-free-space-program)
(directory-free-space-args): Now obsolete.
(get-free-disk-space): Just call file-system-info instead
of the now-obsolete directory-free-space-program.
* nt/gnulib-cfg.mk (OMIT_GNULIB_MODULE_fsusage): New macro.
* src/fileio.c: Include fsusage.h.
(blocks_to_bytes, Ffile_system_info) [!DOS_NT]: New functions.
(syms_of_fileio) [!DOS_NT]: Defsubr file-system-info.
| -rwxr-xr-x | admin/merge-gnulib | 2 | ||||
| -rw-r--r-- | doc/emacs/files.texi | 7 | ||||
| -rw-r--r-- | etc/NEWS | 4 | ||||
| -rw-r--r-- | etc/PROBLEMS | 10 | ||||
| -rw-r--r-- | lib/fsusage.c | 288 | ||||
| -rw-r--r-- | lib/fsusage.h | 40 | ||||
| -rw-r--r-- | lib/gnulib.mk.in | 13 | ||||
| -rw-r--r-- | lisp/dired.el | 6 | ||||
| -rw-r--r-- | lisp/files.el | 49 | ||||
| -rw-r--r-- | m4/fsusage.m4 | 336 | ||||
| -rw-r--r-- | m4/gnulib-comp.m4 | 9 | ||||
| -rw-r--r-- | nt/gnulib-cfg.mk | 1 | ||||
| -rw-r--r-- | src/fileio.c | 39 |
13 files changed, 750 insertions, 54 deletions
diff --git a/admin/merge-gnulib b/admin/merge-gnulib index 60104e86c69..4b1dc592b94 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib | |||
| @@ -33,7 +33,7 @@ GNULIB_MODULES=' | |||
| 33 | d-type diffseq dtoastr dtotimespec dup2 | 33 | d-type diffseq dtoastr dtotimespec dup2 |
| 34 | environ execinfo explicit_bzero faccessat | 34 | environ execinfo explicit_bzero faccessat |
| 35 | fcntl fcntl-h fdatasync fdopendir | 35 | fcntl fcntl-h fdatasync fdopendir |
| 36 | filemode filevercmp flexmember fstatat fsync | 36 | filemode filevercmp flexmember fstatat fsusage fsync |
| 37 | getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog | 37 | getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog |
| 38 | ignore-value intprops largefile lstat | 38 | ignore-value intprops largefile lstat |
| 39 | manywarnings memrchr minmax mkostemp mktime nstrftime | 39 | manywarnings memrchr minmax mkostemp mktime nstrftime |
diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index 18f1c28571b..2c4a0ca30ce 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi | |||
| @@ -1279,13 +1279,8 @@ default), and @code{list-directory-verbose-switches} is a string | |||
| 1279 | giving the switches to use in a verbose listing (@code{"-l"} by | 1279 | giving the switches to use in a verbose listing (@code{"-l"} by |
| 1280 | default). | 1280 | default). |
| 1281 | 1281 | ||
| 1282 | @vindex directory-free-space-program | ||
| 1283 | @vindex directory-free-space-args | ||
| 1284 | In verbose directory listings, Emacs adds information about the | 1282 | In verbose directory listings, Emacs adds information about the |
| 1285 | amount of free space on the disk that contains the directory. To do | 1283 | amount of free space on the disk that contains the directory. |
| 1286 | this, it runs the program specified by | ||
| 1287 | @code{directory-free-space-program} with arguments | ||
| 1288 | @code{directory-free-space-args}. | ||
| 1289 | 1284 | ||
| 1290 | The command @kbd{M-x delete-directory} prompts for a directory's name | 1285 | The command @kbd{M-x delete-directory} prompts for a directory's name |
| 1291 | using the minibuffer, and deletes the directory if it is empty. If | 1286 | using the minibuffer, and deletes the directory if it is empty. If |
| @@ -73,6 +73,10 @@ calling 'eldoc-message' directly. | |||
| 73 | 73 | ||
| 74 | * Lisp Changes in Emacs 27.1 | 74 | * Lisp Changes in Emacs 27.1 |
| 75 | 75 | ||
| 76 | ** The 'file-system-info' function is now available on all platforms. | ||
| 77 | instead of just Microsoft platforms. This fixes a get-free-disk-space | ||
| 78 | bug on OS X 10.8 and later (Bug#28639). | ||
| 79 | |||
| 76 | 80 | ||
| 77 | * Changes in Emacs 27.1 on Non-Free Operating Systems | 81 | * Changes in Emacs 27.1 on Non-Free Operating Systems |
| 78 | 82 | ||
diff --git a/etc/PROBLEMS b/etc/PROBLEMS index 94c78b696db..2da99324b5f 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS | |||
| @@ -557,7 +557,7 @@ and then choose /usr/bin/netkit-ftp. | |||
| 557 | 557 | ||
| 558 | *** Dired is very slow. | 558 | *** Dired is very slow. |
| 559 | 559 | ||
| 560 | This could happen if invocation of the 'df' program takes a long | 560 | This could happen if getting a file system's status takes a long |
| 561 | time. Possible reasons for this include: | 561 | time. Possible reasons for this include: |
| 562 | 562 | ||
| 563 | - ClearCase mounted filesystems (VOBs) that sometimes make 'df' | 563 | - ClearCase mounted filesystems (VOBs) that sometimes make 'df' |
| @@ -565,12 +565,8 @@ time. Possible reasons for this include: | |||
| 565 | 565 | ||
| 566 | - slow automounters on some old versions of Unix; | 566 | - slow automounters on some old versions of Unix; |
| 567 | 567 | ||
| 568 | - slow operation of some versions of 'df'. | 568 | To work around the problem, you could use Git or some other |
| 569 | 569 | free-software program, instead of ClearCase. | |
| 570 | To work around the problem, you could either (a) set the variable | ||
| 571 | 'directory-free-space-program' to nil, and thus prevent Emacs from | ||
| 572 | invoking 'df'; (b) use 'df' from the GNU Coreutils package; or | ||
| 573 | (c) use CVS, which is Free Software, instead of ClearCase. | ||
| 574 | 570 | ||
| 575 | *** ps-print commands fail to find prologue files ps-prin*.ps. | 571 | *** ps-print commands fail to find prologue files ps-prin*.ps. |
| 576 | 572 | ||
diff --git a/lib/fsusage.c b/lib/fsusage.c new file mode 100644 index 00000000000..a0f763be05f --- /dev/null +++ b/lib/fsusage.c | |||
| @@ -0,0 +1,288 @@ | |||
| 1 | /* fsusage.c -- return space usage of mounted file systems | ||
| 2 | |||
| 3 | Copyright (C) 1991-1992, 1996, 1998-1999, 2002-2006, 2009-2017 Free Software | ||
| 4 | Foundation, Inc. | ||
| 5 | |||
| 6 | This program is free software: you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 3 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ | ||
| 18 | |||
| 19 | #include <config.h> | ||
| 20 | |||
| 21 | #include "fsusage.h" | ||
| 22 | |||
| 23 | #include <limits.h> | ||
| 24 | #include <sys/types.h> | ||
| 25 | |||
| 26 | #if STAT_STATVFS || STAT_STATVFS64 /* POSIX 1003.1-2001 (and later) with XSI */ | ||
| 27 | # include <sys/statvfs.h> | ||
| 28 | #else | ||
| 29 | /* Don't include backward-compatibility files unless they're needed. | ||
| 30 | Eventually we'd like to remove all this cruft. */ | ||
| 31 | # include <fcntl.h> | ||
| 32 | # include <unistd.h> | ||
| 33 | # include <sys/stat.h> | ||
| 34 | #if HAVE_SYS_PARAM_H | ||
| 35 | # include <sys/param.h> | ||
| 36 | #endif | ||
| 37 | #if HAVE_SYS_MOUNT_H | ||
| 38 | # include <sys/mount.h> | ||
| 39 | #endif | ||
| 40 | #if HAVE_SYS_VFS_H | ||
| 41 | # include <sys/vfs.h> | ||
| 42 | #endif | ||
| 43 | # if HAVE_SYS_FS_S5PARAM_H /* Fujitsu UXP/V */ | ||
| 44 | # include <sys/fs/s5param.h> | ||
| 45 | # endif | ||
| 46 | # if HAVE_SYS_STATFS_H | ||
| 47 | # include <sys/statfs.h> | ||
| 48 | # endif | ||
| 49 | # if HAVE_DUSTAT_H /* AIX PS/2 */ | ||
| 50 | # include <sys/dustat.h> | ||
| 51 | # endif | ||
| 52 | # include "full-read.h" | ||
| 53 | #endif | ||
| 54 | |||
| 55 | /* Many space usage primitives use all 1 bits to denote a value that is | ||
| 56 | not applicable or unknown. Propagate this information by returning | ||
| 57 | a uintmax_t value that is all 1 bits if X is all 1 bits, even if X | ||
| 58 | is unsigned and narrower than uintmax_t. */ | ||
| 59 | #define PROPAGATE_ALL_ONES(x) \ | ||
| 60 | ((sizeof (x) < sizeof (uintmax_t) \ | ||
| 61 | && (~ (x) == (sizeof (x) < sizeof (int) \ | ||
| 62 | ? - (1 << (sizeof (x) * CHAR_BIT)) \ | ||
| 63 | : 0))) \ | ||
| 64 | ? UINTMAX_MAX : (uintmax_t) (x)) | ||
| 65 | |||
| 66 | /* Extract the top bit of X as an uintmax_t value. */ | ||
| 67 | #define EXTRACT_TOP_BIT(x) ((x) \ | ||
| 68 | & ((uintmax_t) 1 << (sizeof (x) * CHAR_BIT - 1))) | ||
| 69 | |||
| 70 | /* If a value is negative, many space usage primitives store it into an | ||
| 71 | integer variable by assignment, even if the variable's type is unsigned. | ||
| 72 | So, if a space usage variable X's top bit is set, convert X to the | ||
| 73 | uintmax_t value V such that (- (uintmax_t) V) is the negative of | ||
| 74 | the original value. If X's top bit is clear, just yield X. | ||
| 75 | Use PROPAGATE_TOP_BIT if the original value might be negative; | ||
| 76 | otherwise, use PROPAGATE_ALL_ONES. */ | ||
| 77 | #define PROPAGATE_TOP_BIT(x) ((x) | ~ (EXTRACT_TOP_BIT (x) - 1)) | ||
| 78 | |||
| 79 | #ifdef STAT_STATVFS | ||
| 80 | /* Return true if statvfs works. This is false for statvfs on systems | ||
| 81 | with GNU libc on Linux kernels before 2.6.36, which stats all | ||
| 82 | preceding entries in /proc/mounts; that makes df hang if even one | ||
| 83 | of the corresponding file systems is hard-mounted but not available. */ | ||
| 84 | # if ! (__linux__ && (__GLIBC__ || __UCLIBC__)) | ||
| 85 | /* The FRSIZE fallback is not required in this case. */ | ||
| 86 | # undef STAT_STATFS2_FRSIZE | ||
| 87 | static int statvfs_works (void) { return 1; } | ||
| 88 | # else | ||
| 89 | # include <string.h> /* for strverscmp */ | ||
| 90 | # include <sys/utsname.h> | ||
| 91 | # include <sys/statfs.h> | ||
| 92 | # define STAT_STATFS2_BSIZE 1 | ||
| 93 | |||
| 94 | static int | ||
| 95 | statvfs_works (void) | ||
| 96 | { | ||
| 97 | static int statvfs_works_cache = -1; | ||
| 98 | struct utsname name; | ||
| 99 | if (statvfs_works_cache < 0) | ||
| 100 | statvfs_works_cache = (uname (&name) == 0 | ||
| 101 | && 0 <= strverscmp (name.release, "2.6.36")); | ||
| 102 | return statvfs_works_cache; | ||
| 103 | } | ||
| 104 | # endif | ||
| 105 | #endif | ||
| 106 | |||
| 107 | |||
| 108 | /* Fill in the fields of FSP with information about space usage for | ||
| 109 | the file system on which FILE resides. | ||
| 110 | DISK is the device on which FILE is mounted, for space-getting | ||
| 111 | methods that need to know it. | ||
| 112 | Return 0 if successful, -1 if not. When returning -1, ensure that | ||
| 113 | ERRNO is either a system error value, or zero if DISK is NULL | ||
| 114 | on a system that requires a non-NULL value. */ | ||
| 115 | int | ||
| 116 | get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp) | ||
| 117 | { | ||
| 118 | #ifdef STAT_STATVFS /* POSIX, except pre-2.6.36 glibc/Linux */ | ||
| 119 | |||
| 120 | if (statvfs_works ()) | ||
| 121 | { | ||
| 122 | struct statvfs vfsd; | ||
| 123 | |||
| 124 | if (statvfs (file, &vfsd) < 0) | ||
| 125 | return -1; | ||
| 126 | |||
| 127 | /* f_frsize isn't guaranteed to be supported. */ | ||
| 128 | fsp->fsu_blocksize = (vfsd.f_frsize | ||
| 129 | ? PROPAGATE_ALL_ONES (vfsd.f_frsize) | ||
| 130 | : PROPAGATE_ALL_ONES (vfsd.f_bsize)); | ||
| 131 | |||
| 132 | fsp->fsu_blocks = PROPAGATE_ALL_ONES (vfsd.f_blocks); | ||
| 133 | fsp->fsu_bfree = PROPAGATE_ALL_ONES (vfsd.f_bfree); | ||
| 134 | fsp->fsu_bavail = PROPAGATE_TOP_BIT (vfsd.f_bavail); | ||
| 135 | fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (vfsd.f_bavail) != 0; | ||
| 136 | fsp->fsu_files = PROPAGATE_ALL_ONES (vfsd.f_files); | ||
| 137 | fsp->fsu_ffree = PROPAGATE_ALL_ONES (vfsd.f_ffree); | ||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | |||
| 141 | #endif | ||
| 142 | |||
| 143 | #if defined STAT_STATVFS64 /* AIX */ | ||
| 144 | |||
| 145 | struct statvfs64 fsd; | ||
| 146 | |||
| 147 | if (statvfs64 (file, &fsd) < 0) | ||
| 148 | return -1; | ||
| 149 | |||
| 150 | /* f_frsize isn't guaranteed to be supported. */ | ||
| 151 | fsp->fsu_blocksize = (fsd.f_frsize | ||
| 152 | ? PROPAGATE_ALL_ONES (fsd.f_frsize) | ||
| 153 | : PROPAGATE_ALL_ONES (fsd.f_bsize)); | ||
| 154 | |||
| 155 | #elif defined STAT_STATFS2_FS_DATA /* Ultrix */ | ||
| 156 | |||
| 157 | struct fs_data fsd; | ||
| 158 | |||
| 159 | if (statfs (file, &fsd) != 1) | ||
| 160 | return -1; | ||
| 161 | |||
| 162 | fsp->fsu_blocksize = 1024; | ||
| 163 | fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.fd_req.btot); | ||
| 164 | fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.fd_req.bfree); | ||
| 165 | fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.fd_req.bfreen); | ||
| 166 | fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.fd_req.bfreen) != 0; | ||
| 167 | fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.fd_req.gtot); | ||
| 168 | fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.fd_req.gfree); | ||
| 169 | |||
| 170 | #elif defined STAT_STATFS3_OSF1 /* OSF/1 */ | ||
| 171 | |||
| 172 | struct statfs fsd; | ||
| 173 | |||
| 174 | if (statfs (file, &fsd, sizeof (struct statfs)) != 0) | ||
| 175 | return -1; | ||
| 176 | |||
| 177 | fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize); | ||
| 178 | |||
| 179 | #elif defined STAT_STATFS2_FRSIZE /* 2.6 < glibc/Linux < 2.6.36 */ | ||
| 180 | |||
| 181 | struct statfs fsd; | ||
| 182 | |||
| 183 | if (statfs (file, &fsd) < 0) | ||
| 184 | return -1; | ||
| 185 | |||
| 186 | fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_frsize); | ||
| 187 | |||
| 188 | #elif defined STAT_STATFS2_BSIZE /* glibc/Linux < 2.6, 4.3BSD, SunOS 4, \ | ||
| 189 | Mac OS X < 10.4, FreeBSD < 5.0, \ | ||
| 190 | NetBSD < 3.0, OpenBSD < 4.4 */ | ||
| 191 | |||
| 192 | struct statfs fsd; | ||
| 193 | |||
| 194 | if (statfs (file, &fsd) < 0) | ||
| 195 | return -1; | ||
| 196 | |||
| 197 | fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize); | ||
| 198 | |||
| 199 | # ifdef STATFS_TRUNCATES_BLOCK_COUNTS | ||
| 200 | |||
| 201 | /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the | ||
| 202 | struct statfs are truncated to 2GB. These conditions detect that | ||
| 203 | truncation, presumably without botching the 4.1.1 case, in which | ||
| 204 | the values are not truncated. The correct counts are stored in | ||
| 205 | undocumented spare fields. */ | ||
| 206 | if (fsd.f_blocks == 0x7fffffff / fsd.f_bsize && fsd.f_spare[0] > 0) | ||
| 207 | { | ||
| 208 | fsd.f_blocks = fsd.f_spare[0]; | ||
| 209 | fsd.f_bfree = fsd.f_spare[1]; | ||
| 210 | fsd.f_bavail = fsd.f_spare[2]; | ||
| 211 | } | ||
| 212 | # endif /* STATFS_TRUNCATES_BLOCK_COUNTS */ | ||
| 213 | |||
| 214 | #elif defined STAT_STATFS2_FSIZE /* 4.4BSD and older NetBSD */ | ||
| 215 | |||
| 216 | struct statfs fsd; | ||
| 217 | |||
| 218 | if (statfs (file, &fsd) < 0) | ||
| 219 | return -1; | ||
| 220 | |||
| 221 | fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize); | ||
| 222 | |||
| 223 | #elif defined STAT_STATFS4 /* SVR3, Dynix, old Irix, old AIX, \ | ||
| 224 | Dolphin */ | ||
| 225 | |||
| 226 | # if !_AIX && !defined _SEQUENT_ && !defined DOLPHIN | ||
| 227 | # define f_bavail f_bfree | ||
| 228 | # endif | ||
| 229 | |||
| 230 | struct statfs fsd; | ||
| 231 | |||
| 232 | if (statfs (file, &fsd, sizeof fsd, 0) < 0) | ||
| 233 | return -1; | ||
| 234 | |||
| 235 | /* Empirically, the block counts on most SVR3 and SVR3-derived | ||
| 236 | systems seem to always be in terms of 512-byte blocks, | ||
| 237 | no matter what value f_bsize has. */ | ||
| 238 | # if _AIX || defined _CRAY | ||
| 239 | fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize); | ||
| 240 | # else | ||
| 241 | fsp->fsu_blocksize = 512; | ||
| 242 | # endif | ||
| 243 | |||
| 244 | #endif | ||
| 245 | |||
| 246 | #if (defined STAT_STATVFS64 || defined STAT_STATFS3_OSF1 \ | ||
| 247 | || defined STAT_STATFS2_FRSIZE || defined STAT_STATFS2_BSIZE \ | ||
| 248 | || defined STAT_STATFS2_FSIZE || defined STAT_STATFS4) | ||
| 249 | |||
| 250 | fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks); | ||
| 251 | fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree); | ||
| 252 | fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.f_bavail); | ||
| 253 | fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.f_bavail) != 0; | ||
| 254 | fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.f_files); | ||
| 255 | fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.f_ffree); | ||
| 256 | |||
| 257 | #endif | ||
| 258 | |||
| 259 | (void) disk; /* avoid argument-unused warning */ | ||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | |||
| 263 | #if defined _AIX && defined _I386 | ||
| 264 | /* AIX PS/2 does not supply statfs. */ | ||
| 265 | |||
| 266 | int | ||
| 267 | statfs (char *file, struct statfs *fsb) | ||
| 268 | { | ||
| 269 | struct stat stats; | ||
| 270 | struct dustat fsd; | ||
| 271 | |||
| 272 | if (stat (file, &stats) != 0) | ||
| 273 | return -1; | ||
| 274 | if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd))) | ||
| 275 | return -1; | ||
| 276 | fsb->f_type = 0; | ||
| 277 | fsb->f_bsize = fsd.du_bsize; | ||
| 278 | fsb->f_blocks = fsd.du_fsize - fsd.du_isize; | ||
| 279 | fsb->f_bfree = fsd.du_tfree; | ||
| 280 | fsb->f_bavail = fsd.du_tfree; | ||
| 281 | fsb->f_files = (fsd.du_isize - 2) * fsd.du_inopb; | ||
| 282 | fsb->f_ffree = fsd.du_tinode; | ||
| 283 | fsb->f_fsid.val[0] = fsd.du_site; | ||
| 284 | fsb->f_fsid.val[1] = fsd.du_pckno; | ||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | #endif /* _AIX && _I386 */ | ||
diff --git a/lib/fsusage.h b/lib/fsusage.h new file mode 100644 index 00000000000..f78edc6a0cb --- /dev/null +++ b/lib/fsusage.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | /* fsusage.h -- declarations for file system space usage info | ||
| 2 | |||
| 3 | Copyright (C) 1991-1992, 1997, 2003-2006, 2009-2017 Free Software | ||
| 4 | Foundation, Inc. | ||
| 5 | |||
| 6 | This program is free software: you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 3 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ | ||
| 18 | |||
| 19 | /* Space usage statistics for a file system. Blocks are 512-byte. */ | ||
| 20 | |||
| 21 | #if !defined FSUSAGE_H_ | ||
| 22 | # define FSUSAGE_H_ | ||
| 23 | |||
| 24 | # include <stdint.h> | ||
| 25 | # include <stdbool.h> | ||
| 26 | |||
| 27 | struct fs_usage | ||
| 28 | { | ||
| 29 | uintmax_t fsu_blocksize; /* Size of a block. */ | ||
| 30 | uintmax_t fsu_blocks; /* Total blocks. */ | ||
| 31 | uintmax_t fsu_bfree; /* Free blocks available to superuser. */ | ||
| 32 | uintmax_t fsu_bavail; /* Free blocks available to non-superuser. */ | ||
| 33 | bool fsu_bavail_top_bit_set; /* 1 if fsu_bavail represents a value < 0. */ | ||
| 34 | uintmax_t fsu_files; /* Total file nodes. */ | ||
| 35 | uintmax_t fsu_ffree; /* Free file nodes. */ | ||
| 36 | }; | ||
| 37 | |||
| 38 | int get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp); | ||
| 39 | |||
| 40 | #endif | ||
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index 0f795b3d820..e9358a6855d 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | # the same distribution terms as the rest of that program. | 21 | # the same distribution terms as the rest of that program. |
| 22 | # | 22 | # |
| 23 | # Generated by gnulib-tool. | 23 | # Generated by gnulib-tool. |
| 24 | # Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=tzset --avoid=unsetenv --avoid=utime --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 d-type diffseq dtoastr dtotimespec dup2 environ execinfo explicit_bzero faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr minmax mkostemp mktime nstrftime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strtoimax symlink sys_stat sys_time tempname time time_r time_rz timegm timer-time timespec-add timespec-sub unlocked-io update-copyright utimens vla warnings | 24 | # Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=tzset --avoid=unsetenv --avoid=utime --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 d-type diffseq dtoastr dtotimespec dup2 environ execinfo explicit_bzero faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsusage fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr minmax mkostemp mktime nstrftime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strtoimax symlink sys_stat sys_time tempname time time_r time_rz timegm timer-time timespec-add timespec-sub unlocked-io update-copyright utimens vla warnings |
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | MOSTLYCLEANFILES += core *.stackdump | 27 | MOSTLYCLEANFILES += core *.stackdump |
| @@ -1516,6 +1516,17 @@ EXTRA_libgnu_a_SOURCES += at-func.c fstatat.c | |||
| 1516 | endif | 1516 | endif |
| 1517 | ## end gnulib module fstatat | 1517 | ## end gnulib module fstatat |
| 1518 | 1518 | ||
| 1519 | ## begin gnulib module fsusage | ||
| 1520 | ifeq (,$(OMIT_GNULIB_MODULE_fsusage)) | ||
| 1521 | |||
| 1522 | |||
| 1523 | EXTRA_DIST += fsusage.c fsusage.h | ||
| 1524 | |||
| 1525 | EXTRA_libgnu_a_SOURCES += fsusage.c | ||
| 1526 | |||
| 1527 | endif | ||
| 1528 | ## end gnulib module fsusage | ||
| 1529 | |||
| 1519 | ## begin gnulib module fsync | 1530 | ## begin gnulib module fsync |
| 1520 | ifeq (,$(OMIT_GNULIB_MODULE_fsync)) | 1531 | ifeq (,$(OMIT_GNULIB_MODULE_fsync)) |
| 1521 | 1532 | ||
diff --git a/lisp/dired.el b/lisp/dired.el index 9e09d349f7c..1ec3ac4f99c 100644 --- a/lisp/dired.el +++ b/lisp/dired.el | |||
| @@ -198,8 +198,10 @@ The target is used in the prompt for file copy, rename etc." | |||
| 198 | 198 | ||
| 199 | ; These variables were deleted and the replacements are on files.el. | 199 | ; These variables were deleted and the replacements are on files.el. |
| 200 | ; We leave aliases behind for back-compatibility. | 200 | ; We leave aliases behind for back-compatibility. |
| 201 | (defvaralias 'dired-free-space-program 'directory-free-space-program) | 201 | (define-obsolete-variable-alias 'dired-free-space-program |
| 202 | (defvaralias 'dired-free-space-args 'directory-free-space-args) | 202 | 'directory-free-space-program "27.1") |
| 203 | (define-obsolete-variable-alias 'dired-free-space-args | ||
| 204 | 'directory-free-space-args "27.1") | ||
| 203 | 205 | ||
| 204 | ;;; Hook variables | 206 | ;;; Hook variables |
| 205 | 207 | ||
diff --git a/lisp/files.el b/lisp/files.el index 336bbc8648d..194c87ab680 100644 --- a/lisp/files.el +++ b/lisp/files.el | |||
| @@ -6386,58 +6386,33 @@ if you want to specify options, use `directory-free-space-args'. | |||
| 6386 | 6386 | ||
| 6387 | A value of nil disables this feature. | 6387 | A value of nil disables this feature. |
| 6388 | 6388 | ||
| 6389 | If the function `file-system-info' is defined, it is always used in | 6389 | This variable is obsolete; Emacs no longer uses it." |
| 6390 | preference to the program given by this variable." | ||
| 6391 | :type '(choice (string :tag "Program") (const :tag "None" nil)) | 6390 | :type '(choice (string :tag "Program") (const :tag "None" nil)) |
| 6392 | :group 'dired) | 6391 | :group 'dired) |
| 6392 | (make-obsolete-variable 'directory-free-space-program | ||
| 6393 | "ignored, as Emacs uses `file-system-info' instead" | ||
| 6394 | "27.1") | ||
| 6393 | 6395 | ||
| 6394 | (defcustom directory-free-space-args | 6396 | (defcustom directory-free-space-args |
| 6395 | (purecopy (if (eq system-type 'darwin) "-k" "-Pk")) | 6397 | (purecopy (if (eq system-type 'darwin) "-k" "-Pk")) |
| 6396 | "Options to use when running `directory-free-space-program'." | 6398 | "Options to use when running `directory-free-space-program'." |
| 6397 | :type 'string | 6399 | :type 'string |
| 6398 | :group 'dired) | 6400 | :group 'dired) |
| 6401 | (make-obsolete-variable 'directory-free-space-args | ||
| 6402 | "ignored, as Emacs uses `file-system-info' instead" | ||
| 6403 | "27.1") | ||
| 6399 | 6404 | ||
| 6400 | (defun get-free-disk-space (dir) | 6405 | (defun get-free-disk-space (dir) |
| 6401 | "Return the amount of free space on directory DIR's file system. | 6406 | "Return the amount of free space on directory DIR's file system. |
| 6402 | The return value is a string describing the amount of free | 6407 | The return value is a string describing the amount of free |
| 6403 | space (normally, the number of free 1KB blocks). | 6408 | space (normally, the number of free 1KB blocks). |
| 6404 | 6409 | ||
| 6405 | This function calls `file-system-info' if it is available, or | 6410 | If DIR's free space cannot be obtained, or if DIR is a remote |
| 6406 | invokes the program specified by `directory-free-space-program' | 6411 | directory, this function returns nil." |
| 6407 | and `directory-free-space-args'. If the system call or program | ||
| 6408 | is unsuccessful, or if DIR is a remote directory, this function | ||
| 6409 | returns nil." | ||
| 6410 | (unless (file-remote-p (expand-file-name dir)) | 6412 | (unless (file-remote-p (expand-file-name dir)) |
| 6411 | ;; Try to find the number of free blocks. Non-Posix systems don't | 6413 | (let ((avail (nth 2 (file-system-info dir)))) |
| 6412 | ;; always have df, but might have an equivalent system call. | 6414 | (if avail |
| 6413 | (if (fboundp 'file-system-info) | 6415 | (format "%.0f" (/ avail 1024)))))) |
| 6414 | (let ((fsinfo (file-system-info dir))) | ||
| 6415 | (if fsinfo | ||
| 6416 | (format "%.0f" (/ (nth 2 fsinfo) 1024)))) | ||
| 6417 | (setq dir (expand-file-name dir)) | ||
| 6418 | (save-match-data | ||
| 6419 | (with-temp-buffer | ||
| 6420 | (when (and directory-free-space-program | ||
| 6421 | ;; Avoid failure if the default directory does | ||
| 6422 | ;; not exist (Bug#2631, Bug#3911). | ||
| 6423 | (let ((default-directory | ||
| 6424 | (locate-dominating-file dir 'file-directory-p))) | ||
| 6425 | (eq (process-file directory-free-space-program | ||
| 6426 | nil t nil | ||
| 6427 | directory-free-space-args | ||
| 6428 | (file-relative-name dir)) | ||
| 6429 | 0))) | ||
| 6430 | ;; Assume that the "available" column is before the | ||
| 6431 | ;; "capacity" column. Find the "%" and scan backward. | ||
| 6432 | (goto-char (point-min)) | ||
| 6433 | (forward-line 1) | ||
| 6434 | (when (re-search-forward | ||
| 6435 | "[[:space:]]+[^[:space:]]+%[^%]*$" | ||
| 6436 | (line-end-position) t) | ||
| 6437 | (goto-char (match-beginning 0)) | ||
| 6438 | (let ((endpt (point))) | ||
| 6439 | (skip-chars-backward "^[:space:]") | ||
| 6440 | (buffer-substring-no-properties (point) endpt))))))))) | ||
| 6441 | 6416 | ||
| 6442 | ;; The following expression replaces `dired-move-to-filename-regexp'. | 6417 | ;; The following expression replaces `dired-move-to-filename-regexp'. |
| 6443 | (defvar directory-listing-before-filename-regexp | 6418 | (defvar directory-listing-before-filename-regexp |
diff --git a/m4/fsusage.m4 b/m4/fsusage.m4 new file mode 100644 index 00000000000..1d6ad41cd3c --- /dev/null +++ b/m4/fsusage.m4 | |||
| @@ -0,0 +1,336 @@ | |||
| 1 | # serial 32 | ||
| 2 | # Obtaining file system usage information. | ||
| 3 | |||
| 4 | # Copyright (C) 1997-1998, 2000-2001, 2003-2017 Free Software Foundation, Inc. | ||
| 5 | # | ||
| 6 | # This file is free software; the Free Software Foundation | ||
| 7 | # gives unlimited permission to copy and/or distribute it, | ||
| 8 | # with or without modifications, as long as this notice is preserved. | ||
| 9 | |||
| 10 | # Written by Jim Meyering. | ||
| 11 | |||
| 12 | AC_DEFUN([gl_FSUSAGE], | ||
| 13 | [ | ||
| 14 | AC_CHECK_HEADERS_ONCE([sys/param.h]) | ||
| 15 | AC_CHECK_HEADERS_ONCE([sys/vfs.h sys/fs_types.h]) | ||
| 16 | AC_CHECK_HEADERS([sys/mount.h], [], [], | ||
| 17 | [AC_INCLUDES_DEFAULT | ||
| 18 | [#if HAVE_SYS_PARAM_H | ||
| 19 | #include <sys/param.h> | ||
| 20 | #endif]]) | ||
| 21 | gl_FILE_SYSTEM_USAGE([gl_cv_fs_space=yes], [gl_cv_fs_space=no]) | ||
| 22 | ]) | ||
| 23 | |||
| 24 | # Try to determine how a program can obtain file system usage information. | ||
| 25 | # If successful, define the appropriate symbol (see fsusage.c) and | ||
| 26 | # execute ACTION-IF-FOUND. Otherwise, execute ACTION-IF-NOT-FOUND. | ||
| 27 | # | ||
| 28 | # gl_FILE_SYSTEM_USAGE([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) | ||
| 29 | |||
| 30 | AC_DEFUN([gl_FILE_SYSTEM_USAGE], | ||
| 31 | [ | ||
| 32 | dnl Enable large-file support. This has the effect of changing the size | ||
| 33 | dnl of field f_blocks in 'struct statvfs' from 32 bit to 64 bit on | ||
| 34 | dnl glibc/Hurd, HP-UX 11, Solaris (32-bit mode). It also changes the size | ||
| 35 | dnl of field f_blocks in 'struct statfs' from 32 bit to 64 bit on | ||
| 36 | dnl Mac OS X >= 10.5 (32-bit mode). | ||
| 37 | AC_REQUIRE([AC_SYS_LARGEFILE]) | ||
| 38 | |||
| 39 | AC_MSG_CHECKING([how to get file system space usage]) | ||
| 40 | ac_fsusage_space=no | ||
| 41 | |||
| 42 | # Perform only the link test since it seems there are no variants of the | ||
| 43 | # statvfs function. This check is more than just AC_CHECK_FUNCS([statvfs]) | ||
| 44 | # because that got a false positive on SCO OSR5. Adding the declaration | ||
| 45 | # of a 'struct statvfs' causes this test to fail (as it should) on such | ||
| 46 | # systems. That system is reported to work fine with STAT_STATFS4 which | ||
| 47 | # is what it gets when this test fails. | ||
| 48 | if test $ac_fsusage_space = no; then | ||
| 49 | # glibc/{Hurd,kFreeBSD}, FreeBSD >= 5.0, NetBSD >= 3.0, | ||
| 50 | # OpenBSD >= 4.4, AIX, HP-UX, IRIX, Solaris, Cygwin, Interix, BeOS. | ||
| 51 | AC_CACHE_CHECK([for statvfs function (SVR4)], [fu_cv_sys_stat_statvfs], | ||
| 52 | [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h> | ||
| 53 | #ifdef __osf__ | ||
| 54 | "Do not use Tru64's statvfs implementation" | ||
| 55 | #endif | ||
| 56 | |||
| 57 | #include <sys/statvfs.h> | ||
| 58 | |||
| 59 | struct statvfs fsd; | ||
| 60 | |||
| 61 | #if defined __APPLE__ && defined __MACH__ | ||
| 62 | #include <limits.h> | ||
| 63 | /* On Mac OS X >= 10.5, f_blocks in 'struct statvfs' is a 32-bit quantity; | ||
| 64 | that commonly limits file systems to 4 TiB. Whereas f_blocks in | ||
| 65 | 'struct statfs' is a 64-bit type, thanks to the large-file support | ||
| 66 | that was enabled above. In this case, don't use statvfs(); use statfs() | ||
| 67 | instead. */ | ||
| 68 | int check_f_blocks_size[sizeof fsd.f_blocks * CHAR_BIT <= 32 ? -1 : 1]; | ||
| 69 | #endif | ||
| 70 | ]], | ||
| 71 | [[statvfs (0, &fsd);]])], | ||
| 72 | [fu_cv_sys_stat_statvfs=yes], | ||
| 73 | [fu_cv_sys_stat_statvfs=no])]) | ||
| 74 | if test $fu_cv_sys_stat_statvfs = yes; then | ||
| 75 | ac_fsusage_space=yes | ||
| 76 | # AIX >= 5.2 has statvfs64 that has a wider f_blocks field than statvfs. | ||
| 77 | # glibc, HP-UX, IRIX, Solaris have statvfs64 as well, but on these systems | ||
| 78 | # statvfs with large-file support is already equivalent to statvfs64. | ||
| 79 | AC_CACHE_CHECK([whether to use statvfs64], | ||
| 80 | [fu_cv_sys_stat_statvfs64], | ||
| 81 | [AC_LINK_IFELSE( | ||
| 82 | [AC_LANG_PROGRAM( | ||
| 83 | [[#include <sys/types.h> | ||
| 84 | #include <sys/statvfs.h> | ||
| 85 | struct statvfs64 fsd; | ||
| 86 | int check_f_blocks_larger_in_statvfs64 | ||
| 87 | [sizeof (((struct statvfs64 *) 0)->f_blocks) | ||
| 88 | > sizeof (((struct statvfs *) 0)->f_blocks) | ||
| 89 | ? 1 : -1]; | ||
| 90 | ]], | ||
| 91 | [[statvfs64 (0, &fsd);]])], | ||
| 92 | [fu_cv_sys_stat_statvfs64=yes], | ||
| 93 | [fu_cv_sys_stat_statvfs64=no]) | ||
| 94 | ]) | ||
| 95 | if test $fu_cv_sys_stat_statvfs64 = yes; then | ||
| 96 | AC_DEFINE([STAT_STATVFS64], [1], | ||
| 97 | [ Define if statvfs64 should be preferred over statvfs.]) | ||
| 98 | else | ||
| 99 | AC_DEFINE([STAT_STATVFS], [1], | ||
| 100 | [ Define if there is a function named statvfs. (SVR4)]) | ||
| 101 | fi | ||
| 102 | fi | ||
| 103 | fi | ||
| 104 | |||
| 105 | # Check for this unconditionally so we have a | ||
| 106 | # good fallback on glibc/Linux > 2.6 < 2.6.36 | ||
| 107 | AC_MSG_CHECKING([for two-argument statfs with statfs.f_frsize member]) | ||
| 108 | AC_CACHE_VAL([fu_cv_sys_stat_statfs2_frsize], | ||
| 109 | [AC_RUN_IFELSE([AC_LANG_SOURCE([[ | ||
| 110 | #ifdef HAVE_SYS_PARAM_H | ||
| 111 | #include <sys/param.h> | ||
| 112 | #endif | ||
| 113 | #ifdef HAVE_SYS_MOUNT_H | ||
| 114 | #include <sys/mount.h> | ||
| 115 | #endif | ||
| 116 | #ifdef HAVE_SYS_VFS_H | ||
| 117 | #include <sys/vfs.h> | ||
| 118 | #endif | ||
| 119 | int | ||
| 120 | main () | ||
| 121 | { | ||
| 122 | struct statfs fsd; | ||
| 123 | fsd.f_frsize = 0; | ||
| 124 | return statfs (".", &fsd) != 0; | ||
| 125 | }]])], | ||
| 126 | [fu_cv_sys_stat_statfs2_frsize=yes], | ||
| 127 | [fu_cv_sys_stat_statfs2_frsize=no], | ||
| 128 | [fu_cv_sys_stat_statfs2_frsize=no])]) | ||
| 129 | AC_MSG_RESULT([$fu_cv_sys_stat_statfs2_frsize]) | ||
| 130 | if test $fu_cv_sys_stat_statfs2_frsize = yes; then | ||
| 131 | ac_fsusage_space=yes | ||
| 132 | AC_DEFINE([STAT_STATFS2_FRSIZE], [1], | ||
| 133 | [ Define if statfs takes 2 args and struct statfs has a field named f_frsize. | ||
| 134 | (glibc/Linux > 2.6)]) | ||
| 135 | fi | ||
| 136 | |||
| 137 | if test $ac_fsusage_space = no; then | ||
| 138 | # DEC Alpha running OSF/1 | ||
| 139 | AC_MSG_CHECKING([for 3-argument statfs function (DEC OSF/1)]) | ||
| 140 | AC_CACHE_VAL([fu_cv_sys_stat_statfs3_osf1], | ||
| 141 | [AC_RUN_IFELSE([AC_LANG_SOURCE([[ | ||
| 142 | #include <sys/param.h> | ||
| 143 | #include <sys/types.h> | ||
| 144 | #include <sys/mount.h> | ||
| 145 | int | ||
| 146 | main () | ||
| 147 | { | ||
| 148 | struct statfs fsd; | ||
| 149 | fsd.f_fsize = 0; | ||
| 150 | return statfs (".", &fsd, sizeof (struct statfs)) != 0; | ||
| 151 | }]])], | ||
| 152 | [fu_cv_sys_stat_statfs3_osf1=yes], | ||
| 153 | [fu_cv_sys_stat_statfs3_osf1=no], | ||
| 154 | [fu_cv_sys_stat_statfs3_osf1=no])]) | ||
| 155 | AC_MSG_RESULT([$fu_cv_sys_stat_statfs3_osf1]) | ||
| 156 | if test $fu_cv_sys_stat_statfs3_osf1 = yes; then | ||
| 157 | ac_fsusage_space=yes | ||
| 158 | AC_DEFINE([STAT_STATFS3_OSF1], [1], | ||
| 159 | [ Define if statfs takes 3 args. (DEC Alpha running OSF/1)]) | ||
| 160 | fi | ||
| 161 | fi | ||
| 162 | |||
| 163 | if test $ac_fsusage_space = no; then | ||
| 164 | # glibc/Linux, Mac OS X, FreeBSD < 5.0, NetBSD < 3.0, OpenBSD < 4.4. | ||
| 165 | # (glibc/{Hurd,kFreeBSD}, FreeBSD >= 5.0, NetBSD >= 3.0, | ||
| 166 | # OpenBSD >= 4.4, AIX, HP-UX, OSF/1, Cygwin already handled above.) | ||
| 167 | # (On IRIX you need to include <sys/statfs.h>, not only <sys/mount.h> and | ||
| 168 | # <sys/vfs.h>.) | ||
| 169 | # (On Solaris, statfs has 4 arguments.) | ||
| 170 | AC_MSG_CHECKING([for two-argument statfs with statfs.f_bsize dnl | ||
| 171 | member (AIX, 4.3BSD)]) | ||
| 172 | AC_CACHE_VAL([fu_cv_sys_stat_statfs2_bsize], | ||
| 173 | [AC_RUN_IFELSE([AC_LANG_SOURCE([[ | ||
| 174 | #ifdef HAVE_SYS_PARAM_H | ||
| 175 | #include <sys/param.h> | ||
| 176 | #endif | ||
| 177 | #ifdef HAVE_SYS_MOUNT_H | ||
| 178 | #include <sys/mount.h> | ||
| 179 | #endif | ||
| 180 | #ifdef HAVE_SYS_VFS_H | ||
| 181 | #include <sys/vfs.h> | ||
| 182 | #endif | ||
| 183 | int | ||
| 184 | main () | ||
| 185 | { | ||
| 186 | struct statfs fsd; | ||
| 187 | fsd.f_bsize = 0; | ||
| 188 | return statfs (".", &fsd) != 0; | ||
| 189 | }]])], | ||
| 190 | [fu_cv_sys_stat_statfs2_bsize=yes], | ||
| 191 | [fu_cv_sys_stat_statfs2_bsize=no], | ||
| 192 | [fu_cv_sys_stat_statfs2_bsize=no])]) | ||
| 193 | AC_MSG_RESULT([$fu_cv_sys_stat_statfs2_bsize]) | ||
| 194 | if test $fu_cv_sys_stat_statfs2_bsize = yes; then | ||
| 195 | ac_fsusage_space=yes | ||
| 196 | AC_DEFINE([STAT_STATFS2_BSIZE], [1], | ||
| 197 | [ Define if statfs takes 2 args and struct statfs has a field named f_bsize. | ||
| 198 | (4.3BSD, SunOS 4, HP-UX, AIX PS/2)]) | ||
| 199 | fi | ||
| 200 | fi | ||
| 201 | |||
| 202 | if test $ac_fsusage_space = no; then | ||
| 203 | # SVR3 | ||
| 204 | # (Solaris already handled above.) | ||
| 205 | AC_MSG_CHECKING([for four-argument statfs (AIX-3.2.5, SVR3)]) | ||
| 206 | AC_CACHE_VAL([fu_cv_sys_stat_statfs4], | ||
| 207 | [AC_RUN_IFELSE([AC_LANG_SOURCE([[ | ||
| 208 | #include <sys/types.h> | ||
| 209 | #include <sys/statfs.h> | ||
| 210 | int | ||
| 211 | main () | ||
| 212 | { | ||
| 213 | struct statfs fsd; | ||
| 214 | return statfs (".", &fsd, sizeof fsd, 0) != 0; | ||
| 215 | }]])], | ||
| 216 | [fu_cv_sys_stat_statfs4=yes], | ||
| 217 | [fu_cv_sys_stat_statfs4=no], | ||
| 218 | [fu_cv_sys_stat_statfs4=no])]) | ||
| 219 | AC_MSG_RESULT([$fu_cv_sys_stat_statfs4]) | ||
| 220 | if test $fu_cv_sys_stat_statfs4 = yes; then | ||
| 221 | ac_fsusage_space=yes | ||
| 222 | AC_DEFINE([STAT_STATFS4], [1], | ||
| 223 | [ Define if statfs takes 4 args. (SVR3, Dynix, old Irix, old AIX, Dolphin)]) | ||
| 224 | fi | ||
| 225 | fi | ||
| 226 | |||
| 227 | if test $ac_fsusage_space = no; then | ||
| 228 | # 4.4BSD and older NetBSD | ||
| 229 | # (OSF/1 already handled above.) | ||
| 230 | # (On AIX, you need to include <sys/statfs.h>, not only <sys/mount.h>.) | ||
| 231 | # (On Solaris, statfs has 4 arguments and 'struct statfs' is not declared in | ||
| 232 | # <sys/mount.h>.) | ||
| 233 | AC_MSG_CHECKING([for two-argument statfs with statfs.f_fsize dnl | ||
| 234 | member (4.4BSD and NetBSD)]) | ||
| 235 | AC_CACHE_VAL([fu_cv_sys_stat_statfs2_fsize], | ||
| 236 | [AC_RUN_IFELSE([AC_LANG_SOURCE([[ | ||
| 237 | #include <sys/types.h> | ||
| 238 | #ifdef HAVE_SYS_PARAM_H | ||
| 239 | #include <sys/param.h> | ||
| 240 | #endif | ||
| 241 | #ifdef HAVE_SYS_MOUNT_H | ||
| 242 | #include <sys/mount.h> | ||
| 243 | #endif | ||
| 244 | int | ||
| 245 | main () | ||
| 246 | { | ||
| 247 | struct statfs fsd; | ||
| 248 | fsd.f_fsize = 0; | ||
| 249 | return statfs (".", &fsd) != 0; | ||
| 250 | }]])], | ||
| 251 | [fu_cv_sys_stat_statfs2_fsize=yes], | ||
| 252 | [fu_cv_sys_stat_statfs2_fsize=no], | ||
| 253 | [fu_cv_sys_stat_statfs2_fsize=no])]) | ||
| 254 | AC_MSG_RESULT([$fu_cv_sys_stat_statfs2_fsize]) | ||
| 255 | if test $fu_cv_sys_stat_statfs2_fsize = yes; then | ||
| 256 | ac_fsusage_space=yes | ||
| 257 | AC_DEFINE([STAT_STATFS2_FSIZE], [1], | ||
| 258 | [ Define if statfs takes 2 args and struct statfs has a field named f_fsize. | ||
| 259 | (4.4BSD, NetBSD)]) | ||
| 260 | fi | ||
| 261 | fi | ||
| 262 | |||
| 263 | if test $ac_fsusage_space = no; then | ||
| 264 | # Ultrix | ||
| 265 | AC_MSG_CHECKING([for two-argument statfs with struct fs_data (Ultrix)]) | ||
| 266 | AC_CACHE_VAL([fu_cv_sys_stat_fs_data], | ||
| 267 | [AC_RUN_IFELSE([AC_LANG_SOURCE([[ | ||
| 268 | #include <sys/types.h> | ||
| 269 | #ifdef HAVE_SYS_PARAM_H | ||
| 270 | #include <sys/param.h> | ||
| 271 | #endif | ||
| 272 | #ifdef HAVE_SYS_MOUNT_H | ||
| 273 | #include <sys/mount.h> | ||
| 274 | #endif | ||
| 275 | #ifdef HAVE_SYS_FS_TYPES_H | ||
| 276 | #include <sys/fs_types.h> | ||
| 277 | #endif | ||
| 278 | int | ||
| 279 | main () | ||
| 280 | { | ||
| 281 | struct fs_data fsd; | ||
| 282 | /* Ultrix's statfs returns 1 for success, | ||
| 283 | 0 for not mounted, -1 for failure. */ | ||
| 284 | return statfs (".", &fsd) != 1; | ||
| 285 | }]])], | ||
| 286 | [fu_cv_sys_stat_fs_data=yes], | ||
| 287 | [fu_cv_sys_stat_fs_data=no], | ||
| 288 | [fu_cv_sys_stat_fs_data=no])]) | ||
| 289 | AC_MSG_RESULT([$fu_cv_sys_stat_fs_data]) | ||
| 290 | if test $fu_cv_sys_stat_fs_data = yes; then | ||
| 291 | ac_fsusage_space=yes | ||
| 292 | AC_DEFINE([STAT_STATFS2_FS_DATA], [1], | ||
| 293 | [ Define if statfs takes 2 args and the second argument has | ||
| 294 | type struct fs_data. (Ultrix)]) | ||
| 295 | fi | ||
| 296 | fi | ||
| 297 | |||
| 298 | AS_IF([test $ac_fsusage_space = yes], [$1], [$2]) | ||
| 299 | |||
| 300 | ]) | ||
| 301 | |||
| 302 | |||
| 303 | # Check for SunOS statfs brokenness wrt partitions 2GB and larger. | ||
| 304 | # If <sys/vfs.h> exists and struct statfs has a member named f_spare, | ||
| 305 | # enable the work-around code in fsusage.c. | ||
| 306 | AC_DEFUN([gl_STATFS_TRUNCATES], | ||
| 307 | [ | ||
| 308 | AC_MSG_CHECKING([for statfs that truncates block counts]) | ||
| 309 | AC_CACHE_VAL([fu_cv_sys_truncating_statfs], | ||
| 310 | [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ | ||
| 311 | #if !defined(sun) && !defined(__sun) | ||
| 312 | choke -- this is a workaround for a Sun-specific problem | ||
| 313 | #endif | ||
| 314 | #include <sys/types.h> | ||
| 315 | #include <sys/vfs.h>]], | ||
| 316 | [[struct statfs t; long c = *(t.f_spare); | ||
| 317 | if (c) return 0;]])], | ||
| 318 | [fu_cv_sys_truncating_statfs=yes], | ||
| 319 | [fu_cv_sys_truncating_statfs=no])]) | ||
| 320 | if test $fu_cv_sys_truncating_statfs = yes; then | ||
| 321 | AC_DEFINE([STATFS_TRUNCATES_BLOCK_COUNTS], [1], | ||
| 322 | [Define if the block counts reported by statfs may be truncated to 2GB | ||
| 323 | and the correct values may be stored in the f_spare array. | ||
| 324 | (SunOS 4.1.2, 4.1.3, and 4.1.3_U1 are reported to have this problem. | ||
| 325 | SunOS 4.1.1 seems not to be affected.)]) | ||
| 326 | fi | ||
| 327 | AC_MSG_RESULT([$fu_cv_sys_truncating_statfs]) | ||
| 328 | ]) | ||
| 329 | |||
| 330 | |||
| 331 | # Prerequisites of lib/fsusage.c not done by gl_FILE_SYSTEM_USAGE. | ||
| 332 | AC_DEFUN([gl_PREREQ_FSUSAGE_EXTRA], | ||
| 333 | [ | ||
| 334 | AC_CHECK_HEADERS([dustat.h sys/fs/s5param.h sys/statfs.h]) | ||
| 335 | gl_STATFS_TRUNCATES | ||
| 336 | ]) | ||
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index c5517529f09..cb255fcf6d9 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 | |||
| @@ -87,6 +87,7 @@ AC_DEFUN([gl_EARLY], | |||
| 87 | # Code from module flexmember: | 87 | # Code from module flexmember: |
| 88 | # Code from module fpending: | 88 | # Code from module fpending: |
| 89 | # Code from module fstatat: | 89 | # Code from module fstatat: |
| 90 | # Code from module fsusage: | ||
| 90 | # Code from module fsync: | 91 | # Code from module fsync: |
| 91 | # Code from module getdtablesize: | 92 | # Code from module getdtablesize: |
| 92 | # Code from module getgroups: | 93 | # Code from module getgroups: |
| @@ -256,6 +257,11 @@ AC_DEFUN([gl_INIT], | |||
| 256 | AC_LIBOBJ([fstatat]) | 257 | AC_LIBOBJ([fstatat]) |
| 257 | fi | 258 | fi |
| 258 | gl_SYS_STAT_MODULE_INDICATOR([fstatat]) | 259 | gl_SYS_STAT_MODULE_INDICATOR([fstatat]) |
| 260 | gl_FSUSAGE | ||
| 261 | if test $gl_cv_fs_space = yes; then | ||
| 262 | AC_LIBOBJ([fsusage]) | ||
| 263 | gl_PREREQ_FSUSAGE_EXTRA | ||
| 264 | fi | ||
| 259 | gl_FUNC_FSYNC | 265 | gl_FUNC_FSYNC |
| 260 | if test $HAVE_FSYNC = 0; then | 266 | if test $HAVE_FSYNC = 0; then |
| 261 | AC_LIBOBJ([fsync]) | 267 | AC_LIBOBJ([fsync]) |
| @@ -864,6 +870,8 @@ AC_DEFUN([gl_FILE_LIST], [ | |||
| 864 | lib/fpending.c | 870 | lib/fpending.c |
| 865 | lib/fpending.h | 871 | lib/fpending.h |
| 866 | lib/fstatat.c | 872 | lib/fstatat.c |
| 873 | lib/fsusage.c | ||
| 874 | lib/fsusage.h | ||
| 867 | lib/fsync.c | 875 | lib/fsync.c |
| 868 | lib/ftoastr.c | 876 | lib/ftoastr.c |
| 869 | lib/ftoastr.h | 877 | lib/ftoastr.h |
| @@ -995,6 +1003,7 @@ AC_DEFUN([gl_FILE_LIST], [ | |||
| 995 | m4/flexmember.m4 | 1003 | m4/flexmember.m4 |
| 996 | m4/fpending.m4 | 1004 | m4/fpending.m4 |
| 997 | m4/fstatat.m4 | 1005 | m4/fstatat.m4 |
| 1006 | m4/fsusage.m4 | ||
| 998 | m4/fsync.m4 | 1007 | m4/fsync.m4 |
| 999 | m4/getdtablesize.m4 | 1008 | m4/getdtablesize.m4 |
| 1000 | m4/getgroups.m4 | 1009 | m4/getgroups.m4 |
diff --git a/nt/gnulib-cfg.mk b/nt/gnulib-cfg.mk index 419099ece33..f62166759de 100644 --- a/nt/gnulib-cfg.mk +++ b/nt/gnulib-cfg.mk | |||
| @@ -49,6 +49,7 @@ OMIT_GNULIB_MODULE_dirent = true | |||
| 49 | OMIT_GNULIB_MODULE_dirfd = true | 49 | OMIT_GNULIB_MODULE_dirfd = true |
| 50 | OMIT_GNULIB_MODULE_fcntl = true | 50 | OMIT_GNULIB_MODULE_fcntl = true |
| 51 | OMIT_GNULIB_MODULE_fcntl-h = true | 51 | OMIT_GNULIB_MODULE_fcntl-h = true |
| 52 | OMIT_GNULIB_MODULE_fsusage = true | ||
| 52 | OMIT_GNULIB_MODULE_inttypes-incomplete = true | 53 | OMIT_GNULIB_MODULE_inttypes-incomplete = true |
| 53 | OMIT_GNULIB_MODULE_open = true | 54 | OMIT_GNULIB_MODULE_open = true |
| 54 | OMIT_GNULIB_MODULE_pipe2 = true | 55 | OMIT_GNULIB_MODULE_pipe2 = true |
diff --git a/src/fileio.c b/src/fileio.c index adb3534532c..11370279d1b 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -96,6 +96,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 96 | #include <acl.h> | 96 | #include <acl.h> |
| 97 | #include <allocator.h> | 97 | #include <allocator.h> |
| 98 | #include <careadlinkat.h> | 98 | #include <careadlinkat.h> |
| 99 | #include <fsusage.h> | ||
| 99 | #include <stat-time.h> | 100 | #include <stat-time.h> |
| 100 | #include <tempname.h> | 101 | #include <tempname.h> |
| 101 | 102 | ||
| @@ -5765,6 +5766,40 @@ effect except for flushing STREAM's data. */) | |||
| 5765 | return (set_binary_mode (fileno (fp), binmode) == O_BINARY) ? Qt : Qnil; | 5766 | return (set_binary_mode (fileno (fp), binmode) == O_BINARY) ? Qt : Qnil; |
| 5766 | } | 5767 | } |
| 5767 | 5768 | ||
| 5769 | #ifndef DOS_NT | ||
| 5770 | |||
| 5771 | /* Yield a Lisp float as close as possible to BLOCKSIZE * BLOCKS, with | ||
| 5772 | the result negated if NEGATE. */ | ||
| 5773 | static Lisp_Object | ||
| 5774 | blocks_to_bytes (uintmax_t blocksize, uintmax_t blocks, bool negate) | ||
| 5775 | { | ||
| 5776 | /* On typical platforms the following code is accurate to 53 bits, | ||
| 5777 | which is close enough. BLOCKSIZE is invariably a power of 2, so | ||
| 5778 | converting it to double does not lose information. */ | ||
| 5779 | double bs = blocksize; | ||
| 5780 | return make_float (negate ? -bs * -blocks : bs * blocks); | ||
| 5781 | } | ||
| 5782 | |||
| 5783 | DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0, | ||
| 5784 | doc: /* Return storage information about the file system FILENAME is on. | ||
| 5785 | Value is a list of numbers (TOTAL FREE AVAIL), where TOTAL is the total | ||
| 5786 | storage of the file system, FREE is the free storage, and AVAIL is the | ||
| 5787 | storage available to a non-superuser. All 3 numbers are in bytes. | ||
| 5788 | If the underlying system call fails, value is nil. */) | ||
| 5789 | (Lisp_Object filename) | ||
| 5790 | { | ||
| 5791 | Lisp_Object encoded = ENCODE_FILE (Fexpand_file_name (filename, Qnil)); | ||
| 5792 | struct fs_usage u; | ||
| 5793 | if (get_fs_usage (SSDATA (encoded), NULL, &u) != 0) | ||
| 5794 | return Qnil; | ||
| 5795 | return list3 (blocks_to_bytes (u.fsu_blocksize, u.fsu_blocks, false), | ||
| 5796 | blocks_to_bytes (u.fsu_blocksize, u.fsu_bfree, false), | ||
| 5797 | blocks_to_bytes (u.fsu_blocksize, u.fsu_bavail, | ||
| 5798 | u.fsu_bavail_top_bit_set)); | ||
| 5799 | } | ||
| 5800 | |||
| 5801 | #endif /* !DOS_NT */ | ||
| 5802 | |||
| 5768 | void | 5803 | void |
| 5769 | init_fileio (void) | 5804 | init_fileio (void) |
| 5770 | { | 5805 | { |
| @@ -6115,6 +6150,10 @@ This includes interactive calls to `delete-file' and | |||
| 6115 | 6150 | ||
| 6116 | defsubr (&Sset_binary_mode); | 6151 | defsubr (&Sset_binary_mode); |
| 6117 | 6152 | ||
| 6153 | #ifndef DOS_NT | ||
| 6154 | defsubr (&Sfile_system_info); | ||
| 6155 | #endif | ||
| 6156 | |||
| 6118 | #ifdef HAVE_SYNC | 6157 | #ifdef HAVE_SYNC |
| 6119 | defsubr (&Sunix_sync); | 6158 | defsubr (&Sunix_sync); |
| 6120 | #endif | 6159 | #endif |