aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2017-10-01 22:31:39 -0700
committerPaul Eggert2017-10-01 22:33:20 -0700
commit135bca574c31b7bf6df6c63d28f180956928dde7 (patch)
tree1259c514b5304e7b1dbb8a9098f0a6dd63e00003
parent4829a3b033b119b088947d14b73efc197b2547fa (diff)
downloademacs-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-xadmin/merge-gnulib2
-rw-r--r--doc/emacs/files.texi7
-rw-r--r--etc/NEWS4
-rw-r--r--etc/PROBLEMS10
-rw-r--r--lib/fsusage.c288
-rw-r--r--lib/fsusage.h40
-rw-r--r--lib/gnulib.mk.in13
-rw-r--r--lisp/dired.el6
-rw-r--r--lisp/files.el49
-rw-r--r--m4/fsusage.m4336
-rw-r--r--m4/gnulib-comp.m49
-rw-r--r--nt/gnulib-cfg.mk1
-rw-r--r--src/fileio.c39
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
1279giving the switches to use in a verbose listing (@code{"-l"} by 1279giving the switches to use in a verbose listing (@code{"-l"} by
1280default). 1280default).
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
1285amount of free space on the disk that contains the directory. To do 1283amount of free space on the disk that contains the directory.
1286this, 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
1291using the minibuffer, and deletes the directory if it is empty. If 1286using the minibuffer, and deletes the directory if it is empty. If
diff --git a/etc/NEWS b/etc/NEWS
index 42c1b048169..28789a956ae 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -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.
77instead of just Microsoft platforms. This fixes a get-free-disk-space
78bug 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
560This could happen if invocation of the 'df' program takes a long 560This could happen if getting a file system's status takes a long
561time. Possible reasons for this include: 561time. 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'. 568To work around the problem, you could use Git or some other
569 569free-software program, instead of ClearCase.
570To work around the problem, you could either (a) set the variable
571'directory-free-space-program' to nil, and thus prevent Emacs from
572invoking '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
87static 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
94static int
95statvfs_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. */
115int
116get_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
266int
267statfs (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
27struct 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
38int 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
27MOSTLYCLEANFILES += core *.stackdump 27MOSTLYCLEANFILES += core *.stackdump
@@ -1516,6 +1516,17 @@ EXTRA_libgnu_a_SOURCES += at-func.c fstatat.c
1516endif 1516endif
1517## end gnulib module fstatat 1517## end gnulib module fstatat
1518 1518
1519## begin gnulib module fsusage
1520ifeq (,$(OMIT_GNULIB_MODULE_fsusage))
1521
1522
1523EXTRA_DIST += fsusage.c fsusage.h
1524
1525EXTRA_libgnu_a_SOURCES += fsusage.c
1526
1527endif
1528## end gnulib module fsusage
1529
1519## begin gnulib module fsync 1530## begin gnulib module fsync
1520ifeq (,$(OMIT_GNULIB_MODULE_fsync)) 1531ifeq (,$(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
6387A value of nil disables this feature. 6387A value of nil disables this feature.
6388 6388
6389If the function `file-system-info' is defined, it is always used in 6389This variable is obsolete; Emacs no longer uses it."
6390preference 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.
6402The return value is a string describing the amount of free 6407The return value is a string describing the amount of free
6403space (normally, the number of free 1KB blocks). 6408space (normally, the number of free 1KB blocks).
6404 6409
6405This function calls `file-system-info' if it is available, or 6410If DIR's free space cannot be obtained, or if DIR is a remote
6406invokes the program specified by `directory-free-space-program' 6411directory, this function returns nil."
6407and `directory-free-space-args'. If the system call or program
6408is unsuccessful, or if DIR is a remote directory, this function
6409returns 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
12AC_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
30AC_DEFUN([gl_FILE_SYSTEM_USAGE],
31[
32dnl Enable large-file support. This has the effect of changing the size
33dnl of field f_blocks in 'struct statvfs' from 32 bit to 64 bit on
34dnl glibc/Hurd, HP-UX 11, Solaris (32-bit mode). It also changes the size
35dnl of field f_blocks in 'struct statfs' from 32 bit to 64 bit on
36dnl Mac OS X >= 10.5 (32-bit mode).
37AC_REQUIRE([AC_SYS_LARGEFILE])
38
39AC_MSG_CHECKING([how to get file system space usage])
40ac_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.
48if 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
59struct 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. */
68int 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
103fi
104
105# Check for this unconditionally so we have a
106# good fallback on glibc/Linux > 2.6 < 2.6.36
107AC_MSG_CHECKING([for two-argument statfs with statfs.f_frsize member])
108AC_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])])
129AC_MSG_RESULT([$fu_cv_sys_stat_statfs2_frsize])
130if 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)])
135fi
136
137if 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
161fi
162
163if 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
171member (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
200fi
201
202if 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
225fi
226
227if 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
234member (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
261fi
262
263if 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
296fi
297
298AS_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.
306AC_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)
312choke -- 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.
332AC_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
49OMIT_GNULIB_MODULE_dirfd = true 49OMIT_GNULIB_MODULE_dirfd = true
50OMIT_GNULIB_MODULE_fcntl = true 50OMIT_GNULIB_MODULE_fcntl = true
51OMIT_GNULIB_MODULE_fcntl-h = true 51OMIT_GNULIB_MODULE_fcntl-h = true
52OMIT_GNULIB_MODULE_fsusage = true
52OMIT_GNULIB_MODULE_inttypes-incomplete = true 53OMIT_GNULIB_MODULE_inttypes-incomplete = true
53OMIT_GNULIB_MODULE_open = true 54OMIT_GNULIB_MODULE_open = true
54OMIT_GNULIB_MODULE_pipe2 = true 55OMIT_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. */
5773static Lisp_Object
5774blocks_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
5783DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0,
5784 doc: /* Return storage information about the file system FILENAME is on.
5785Value is a list of numbers (TOTAL FREE AVAIL), where TOTAL is the total
5786storage of the file system, FREE is the free storage, and AVAIL is the
5787storage available to a non-superuser. All 3 numbers are in bytes.
5788If 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
5768void 5803void
5769init_fileio (void) 5804init_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