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.
This commit is contained in:
parent
4829a3b033
commit
135bca574c
13 changed files with 750 additions and 54 deletions
|
@ -33,7 +33,7 @@ GNULIB_MODULES='
|
|||
d-type diffseq dtoastr dtotimespec dup2
|
||||
environ execinfo explicit_bzero faccessat
|
||||
fcntl fcntl-h fdatasync fdopendir
|
||||
filemode filevercmp flexmember fstatat fsync
|
||||
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
|
||||
|
|
|
@ -1279,13 +1279,8 @@ default), and @code{list-directory-verbose-switches} is a string
|
|||
giving the switches to use in a verbose listing (@code{"-l"} by
|
||||
default).
|
||||
|
||||
@vindex directory-free-space-program
|
||||
@vindex directory-free-space-args
|
||||
In verbose directory listings, Emacs adds information about the
|
||||
amount of free space on the disk that contains the directory. To do
|
||||
this, it runs the program specified by
|
||||
@code{directory-free-space-program} with arguments
|
||||
@code{directory-free-space-args}.
|
||||
amount of free space on the disk that contains the directory.
|
||||
|
||||
The command @kbd{M-x delete-directory} prompts for a directory's name
|
||||
using the minibuffer, and deletes the directory if it is empty. If
|
||||
|
|
4
etc/NEWS
4
etc/NEWS
|
@ -73,6 +73,10 @@ calling 'eldoc-message' directly.
|
|||
|
||||
* Lisp Changes in Emacs 27.1
|
||||
|
||||
** The 'file-system-info' function is now available on all platforms.
|
||||
instead of just Microsoft platforms. This fixes a get-free-disk-space
|
||||
bug on OS X 10.8 and later (Bug#28639).
|
||||
|
||||
|
||||
* Changes in Emacs 27.1 on Non-Free Operating Systems
|
||||
|
||||
|
|
10
etc/PROBLEMS
10
etc/PROBLEMS
|
@ -557,7 +557,7 @@ and then choose /usr/bin/netkit-ftp.
|
|||
|
||||
*** Dired is very slow.
|
||||
|
||||
This could happen if invocation of the 'df' program takes a long
|
||||
This could happen if getting a file system's status takes a long
|
||||
time. Possible reasons for this include:
|
||||
|
||||
- ClearCase mounted filesystems (VOBs) that sometimes make 'df'
|
||||
|
@ -565,12 +565,8 @@ time. Possible reasons for this include:
|
|||
|
||||
- slow automounters on some old versions of Unix;
|
||||
|
||||
- slow operation of some versions of 'df'.
|
||||
|
||||
To work around the problem, you could either (a) set the variable
|
||||
'directory-free-space-program' to nil, and thus prevent Emacs from
|
||||
invoking 'df'; (b) use 'df' from the GNU Coreutils package; or
|
||||
(c) use CVS, which is Free Software, instead of ClearCase.
|
||||
To work around the problem, you could use Git or some other
|
||||
free-software program, instead of ClearCase.
|
||||
|
||||
*** ps-print commands fail to find prologue files ps-prin*.ps.
|
||||
|
||||
|
|
288
lib/fsusage.c
Normal file
288
lib/fsusage.c
Normal file
|
@ -0,0 +1,288 @@
|
|||
/* fsusage.c -- return space usage of mounted file systems
|
||||
|
||||
Copyright (C) 1991-1992, 1996, 1998-1999, 2002-2006, 2009-2017 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "fsusage.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if STAT_STATVFS || STAT_STATVFS64 /* POSIX 1003.1-2001 (and later) with XSI */
|
||||
# include <sys/statvfs.h>
|
||||
#else
|
||||
/* Don't include backward-compatibility files unless they're needed.
|
||||
Eventually we'd like to remove all this cruft. */
|
||||
# include <fcntl.h>
|
||||
# include <unistd.h>
|
||||
# include <sys/stat.h>
|
||||
#if HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#if HAVE_SYS_MOUNT_H
|
||||
# include <sys/mount.h>
|
||||
#endif
|
||||
#if HAVE_SYS_VFS_H
|
||||
# include <sys/vfs.h>
|
||||
#endif
|
||||
# if HAVE_SYS_FS_S5PARAM_H /* Fujitsu UXP/V */
|
||||
# include <sys/fs/s5param.h>
|
||||
# endif
|
||||
# if HAVE_SYS_STATFS_H
|
||||
# include <sys/statfs.h>
|
||||
# endif
|
||||
# if HAVE_DUSTAT_H /* AIX PS/2 */
|
||||
# include <sys/dustat.h>
|
||||
# endif
|
||||
# include "full-read.h"
|
||||
#endif
|
||||
|
||||
/* Many space usage primitives use all 1 bits to denote a value that is
|
||||
not applicable or unknown. Propagate this information by returning
|
||||
a uintmax_t value that is all 1 bits if X is all 1 bits, even if X
|
||||
is unsigned and narrower than uintmax_t. */
|
||||
#define PROPAGATE_ALL_ONES(x) \
|
||||
((sizeof (x) < sizeof (uintmax_t) \
|
||||
&& (~ (x) == (sizeof (x) < sizeof (int) \
|
||||
? - (1 << (sizeof (x) * CHAR_BIT)) \
|
||||
: 0))) \
|
||||
? UINTMAX_MAX : (uintmax_t) (x))
|
||||
|
||||
/* Extract the top bit of X as an uintmax_t value. */
|
||||
#define EXTRACT_TOP_BIT(x) ((x) \
|
||||
& ((uintmax_t) 1 << (sizeof (x) * CHAR_BIT - 1)))
|
||||
|
||||
/* If a value is negative, many space usage primitives store it into an
|
||||
integer variable by assignment, even if the variable's type is unsigned.
|
||||
So, if a space usage variable X's top bit is set, convert X to the
|
||||
uintmax_t value V such that (- (uintmax_t) V) is the negative of
|
||||
the original value. If X's top bit is clear, just yield X.
|
||||
Use PROPAGATE_TOP_BIT if the original value might be negative;
|
||||
otherwise, use PROPAGATE_ALL_ONES. */
|
||||
#define PROPAGATE_TOP_BIT(x) ((x) | ~ (EXTRACT_TOP_BIT (x) - 1))
|
||||
|
||||
#ifdef STAT_STATVFS
|
||||
/* Return true if statvfs works. This is false for statvfs on systems
|
||||
with GNU libc on Linux kernels before 2.6.36, which stats all
|
||||
preceding entries in /proc/mounts; that makes df hang if even one
|
||||
of the corresponding file systems is hard-mounted but not available. */
|
||||
# if ! (__linux__ && (__GLIBC__ || __UCLIBC__))
|
||||
/* The FRSIZE fallback is not required in this case. */
|
||||
# undef STAT_STATFS2_FRSIZE
|
||||
static int statvfs_works (void) { return 1; }
|
||||
# else
|
||||
# include <string.h> /* for strverscmp */
|
||||
# include <sys/utsname.h>
|
||||
# include <sys/statfs.h>
|
||||
# define STAT_STATFS2_BSIZE 1
|
||||
|
||||
static int
|
||||
statvfs_works (void)
|
||||
{
|
||||
static int statvfs_works_cache = -1;
|
||||
struct utsname name;
|
||||
if (statvfs_works_cache < 0)
|
||||
statvfs_works_cache = (uname (&name) == 0
|
||||
&& 0 <= strverscmp (name.release, "2.6.36"));
|
||||
return statvfs_works_cache;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Fill in the fields of FSP with information about space usage for
|
||||
the file system on which FILE resides.
|
||||
DISK is the device on which FILE is mounted, for space-getting
|
||||
methods that need to know it.
|
||||
Return 0 if successful, -1 if not. When returning -1, ensure that
|
||||
ERRNO is either a system error value, or zero if DISK is NULL
|
||||
on a system that requires a non-NULL value. */
|
||||
int
|
||||
get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
|
||||
{
|
||||
#ifdef STAT_STATVFS /* POSIX, except pre-2.6.36 glibc/Linux */
|
||||
|
||||
if (statvfs_works ())
|
||||
{
|
||||
struct statvfs vfsd;
|
||||
|
||||
if (statvfs (file, &vfsd) < 0)
|
||||
return -1;
|
||||
|
||||
/* f_frsize isn't guaranteed to be supported. */
|
||||
fsp->fsu_blocksize = (vfsd.f_frsize
|
||||
? PROPAGATE_ALL_ONES (vfsd.f_frsize)
|
||||
: PROPAGATE_ALL_ONES (vfsd.f_bsize));
|
||||
|
||||
fsp->fsu_blocks = PROPAGATE_ALL_ONES (vfsd.f_blocks);
|
||||
fsp->fsu_bfree = PROPAGATE_ALL_ONES (vfsd.f_bfree);
|
||||
fsp->fsu_bavail = PROPAGATE_TOP_BIT (vfsd.f_bavail);
|
||||
fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (vfsd.f_bavail) != 0;
|
||||
fsp->fsu_files = PROPAGATE_ALL_ONES (vfsd.f_files);
|
||||
fsp->fsu_ffree = PROPAGATE_ALL_ONES (vfsd.f_ffree);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined STAT_STATVFS64 /* AIX */
|
||||
|
||||
struct statvfs64 fsd;
|
||||
|
||||
if (statvfs64 (file, &fsd) < 0)
|
||||
return -1;
|
||||
|
||||
/* f_frsize isn't guaranteed to be supported. */
|
||||
fsp->fsu_blocksize = (fsd.f_frsize
|
||||
? PROPAGATE_ALL_ONES (fsd.f_frsize)
|
||||
: PROPAGATE_ALL_ONES (fsd.f_bsize));
|
||||
|
||||
#elif defined STAT_STATFS2_FS_DATA /* Ultrix */
|
||||
|
||||
struct fs_data fsd;
|
||||
|
||||
if (statfs (file, &fsd) != 1)
|
||||
return -1;
|
||||
|
||||
fsp->fsu_blocksize = 1024;
|
||||
fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.fd_req.btot);
|
||||
fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.fd_req.bfree);
|
||||
fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.fd_req.bfreen);
|
||||
fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.fd_req.bfreen) != 0;
|
||||
fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.fd_req.gtot);
|
||||
fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.fd_req.gfree);
|
||||
|
||||
#elif defined STAT_STATFS3_OSF1 /* OSF/1 */
|
||||
|
||||
struct statfs fsd;
|
||||
|
||||
if (statfs (file, &fsd, sizeof (struct statfs)) != 0)
|
||||
return -1;
|
||||
|
||||
fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
|
||||
|
||||
#elif defined STAT_STATFS2_FRSIZE /* 2.6 < glibc/Linux < 2.6.36 */
|
||||
|
||||
struct statfs fsd;
|
||||
|
||||
if (statfs (file, &fsd) < 0)
|
||||
return -1;
|
||||
|
||||
fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_frsize);
|
||||
|
||||
#elif defined STAT_STATFS2_BSIZE /* glibc/Linux < 2.6, 4.3BSD, SunOS 4, \
|
||||
Mac OS X < 10.4, FreeBSD < 5.0, \
|
||||
NetBSD < 3.0, OpenBSD < 4.4 */
|
||||
|
||||
struct statfs fsd;
|
||||
|
||||
if (statfs (file, &fsd) < 0)
|
||||
return -1;
|
||||
|
||||
fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize);
|
||||
|
||||
# ifdef STATFS_TRUNCATES_BLOCK_COUNTS
|
||||
|
||||
/* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the
|
||||
struct statfs are truncated to 2GB. These conditions detect that
|
||||
truncation, presumably without botching the 4.1.1 case, in which
|
||||
the values are not truncated. The correct counts are stored in
|
||||
undocumented spare fields. */
|
||||
if (fsd.f_blocks == 0x7fffffff / fsd.f_bsize && fsd.f_spare[0] > 0)
|
||||
{
|
||||
fsd.f_blocks = fsd.f_spare[0];
|
||||
fsd.f_bfree = fsd.f_spare[1];
|
||||
fsd.f_bavail = fsd.f_spare[2];
|
||||
}
|
||||
# endif /* STATFS_TRUNCATES_BLOCK_COUNTS */
|
||||
|
||||
#elif defined STAT_STATFS2_FSIZE /* 4.4BSD and older NetBSD */
|
||||
|
||||
struct statfs fsd;
|
||||
|
||||
if (statfs (file, &fsd) < 0)
|
||||
return -1;
|
||||
|
||||
fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
|
||||
|
||||
#elif defined STAT_STATFS4 /* SVR3, Dynix, old Irix, old AIX, \
|
||||
Dolphin */
|
||||
|
||||
# if !_AIX && !defined _SEQUENT_ && !defined DOLPHIN
|
||||
# define f_bavail f_bfree
|
||||
# endif
|
||||
|
||||
struct statfs fsd;
|
||||
|
||||
if (statfs (file, &fsd, sizeof fsd, 0) < 0)
|
||||
return -1;
|
||||
|
||||
/* Empirically, the block counts on most SVR3 and SVR3-derived
|
||||
systems seem to always be in terms of 512-byte blocks,
|
||||
no matter what value f_bsize has. */
|
||||
# if _AIX || defined _CRAY
|
||||
fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize);
|
||||
# else
|
||||
fsp->fsu_blocksize = 512;
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#if (defined STAT_STATVFS64 || defined STAT_STATFS3_OSF1 \
|
||||
|| defined STAT_STATFS2_FRSIZE || defined STAT_STATFS2_BSIZE \
|
||||
|| defined STAT_STATFS2_FSIZE || defined STAT_STATFS4)
|
||||
|
||||
fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks);
|
||||
fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree);
|
||||
fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.f_bavail);
|
||||
fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.f_bavail) != 0;
|
||||
fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.f_files);
|
||||
fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.f_ffree);
|
||||
|
||||
#endif
|
||||
|
||||
(void) disk; /* avoid argument-unused warning */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined _AIX && defined _I386
|
||||
/* AIX PS/2 does not supply statfs. */
|
||||
|
||||
int
|
||||
statfs (char *file, struct statfs *fsb)
|
||||
{
|
||||
struct stat stats;
|
||||
struct dustat fsd;
|
||||
|
||||
if (stat (file, &stats) != 0)
|
||||
return -1;
|
||||
if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd)))
|
||||
return -1;
|
||||
fsb->f_type = 0;
|
||||
fsb->f_bsize = fsd.du_bsize;
|
||||
fsb->f_blocks = fsd.du_fsize - fsd.du_isize;
|
||||
fsb->f_bfree = fsd.du_tfree;
|
||||
fsb->f_bavail = fsd.du_tfree;
|
||||
fsb->f_files = (fsd.du_isize - 2) * fsd.du_inopb;
|
||||
fsb->f_ffree = fsd.du_tinode;
|
||||
fsb->f_fsid.val[0] = fsd.du_site;
|
||||
fsb->f_fsid.val[1] = fsd.du_pckno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _AIX && _I386 */
|
40
lib/fsusage.h
Normal file
40
lib/fsusage.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* fsusage.h -- declarations for file system space usage info
|
||||
|
||||
Copyright (C) 1991-1992, 1997, 2003-2006, 2009-2017 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Space usage statistics for a file system. Blocks are 512-byte. */
|
||||
|
||||
#if !defined FSUSAGE_H_
|
||||
# define FSUSAGE_H_
|
||||
|
||||
# include <stdint.h>
|
||||
# include <stdbool.h>
|
||||
|
||||
struct fs_usage
|
||||
{
|
||||
uintmax_t fsu_blocksize; /* Size of a block. */
|
||||
uintmax_t fsu_blocks; /* Total blocks. */
|
||||
uintmax_t fsu_bfree; /* Free blocks available to superuser. */
|
||||
uintmax_t fsu_bavail; /* Free blocks available to non-superuser. */
|
||||
bool fsu_bavail_top_bit_set; /* 1 if fsu_bavail represents a value < 0. */
|
||||
uintmax_t fsu_files; /* Total file nodes. */
|
||||
uintmax_t fsu_ffree; /* Free file nodes. */
|
||||
};
|
||||
|
||||
int get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp);
|
||||
|
||||
#endif
|
|
@ -21,7 +21,7 @@
|
|||
# the same distribution terms as the rest of that program.
|
||||
#
|
||||
# Generated by gnulib-tool.
|
||||
# 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
|
||||
# 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
|
||||
|
||||
|
||||
MOSTLYCLEANFILES += core *.stackdump
|
||||
|
@ -1516,6 +1516,17 @@ EXTRA_libgnu_a_SOURCES += at-func.c fstatat.c
|
|||
endif
|
||||
## end gnulib module fstatat
|
||||
|
||||
## begin gnulib module fsusage
|
||||
ifeq (,$(OMIT_GNULIB_MODULE_fsusage))
|
||||
|
||||
|
||||
EXTRA_DIST += fsusage.c fsusage.h
|
||||
|
||||
EXTRA_libgnu_a_SOURCES += fsusage.c
|
||||
|
||||
endif
|
||||
## end gnulib module fsusage
|
||||
|
||||
## begin gnulib module fsync
|
||||
ifeq (,$(OMIT_GNULIB_MODULE_fsync))
|
||||
|
||||
|
|
|
@ -198,8 +198,10 @@ The target is used in the prompt for file copy, rename etc."
|
|||
|
||||
; These variables were deleted and the replacements are on files.el.
|
||||
; We leave aliases behind for back-compatibility.
|
||||
(defvaralias 'dired-free-space-program 'directory-free-space-program)
|
||||
(defvaralias 'dired-free-space-args 'directory-free-space-args)
|
||||
(define-obsolete-variable-alias 'dired-free-space-program
|
||||
'directory-free-space-program "27.1")
|
||||
(define-obsolete-variable-alias 'dired-free-space-args
|
||||
'directory-free-space-args "27.1")
|
||||
|
||||
;;; Hook variables
|
||||
|
||||
|
|
|
@ -6386,58 +6386,33 @@ if you want to specify options, use `directory-free-space-args'.
|
|||
|
||||
A value of nil disables this feature.
|
||||
|
||||
If the function `file-system-info' is defined, it is always used in
|
||||
preference to the program given by this variable."
|
||||
This variable is obsolete; Emacs no longer uses it."
|
||||
:type '(choice (string :tag "Program") (const :tag "None" nil))
|
||||
:group 'dired)
|
||||
(make-obsolete-variable 'directory-free-space-program
|
||||
"ignored, as Emacs uses `file-system-info' instead"
|
||||
"27.1")
|
||||
|
||||
(defcustom directory-free-space-args
|
||||
(purecopy (if (eq system-type 'darwin) "-k" "-Pk"))
|
||||
"Options to use when running `directory-free-space-program'."
|
||||
:type 'string
|
||||
:group 'dired)
|
||||
(make-obsolete-variable 'directory-free-space-args
|
||||
"ignored, as Emacs uses `file-system-info' instead"
|
||||
"27.1")
|
||||
|
||||
(defun get-free-disk-space (dir)
|
||||
"Return the amount of free space on directory DIR's file system.
|
||||
The return value is a string describing the amount of free
|
||||
space (normally, the number of free 1KB blocks).
|
||||
|
||||
This function calls `file-system-info' if it is available, or
|
||||
invokes the program specified by `directory-free-space-program'
|
||||
and `directory-free-space-args'. If the system call or program
|
||||
is unsuccessful, or if DIR is a remote directory, this function
|
||||
returns nil."
|
||||
If DIR's free space cannot be obtained, or if DIR is a remote
|
||||
directory, this function returns nil."
|
||||
(unless (file-remote-p (expand-file-name dir))
|
||||
;; Try to find the number of free blocks. Non-Posix systems don't
|
||||
;; always have df, but might have an equivalent system call.
|
||||
(if (fboundp 'file-system-info)
|
||||
(let ((fsinfo (file-system-info dir)))
|
||||
(if fsinfo
|
||||
(format "%.0f" (/ (nth 2 fsinfo) 1024))))
|
||||
(setq dir (expand-file-name dir))
|
||||
(save-match-data
|
||||
(with-temp-buffer
|
||||
(when (and directory-free-space-program
|
||||
;; Avoid failure if the default directory does
|
||||
;; not exist (Bug#2631, Bug#3911).
|
||||
(let ((default-directory
|
||||
(locate-dominating-file dir 'file-directory-p)))
|
||||
(eq (process-file directory-free-space-program
|
||||
nil t nil
|
||||
directory-free-space-args
|
||||
(file-relative-name dir))
|
||||
0)))
|
||||
;; Assume that the "available" column is before the
|
||||
;; "capacity" column. Find the "%" and scan backward.
|
||||
(goto-char (point-min))
|
||||
(forward-line 1)
|
||||
(when (re-search-forward
|
||||
"[[:space:]]+[^[:space:]]+%[^%]*$"
|
||||
(line-end-position) t)
|
||||
(goto-char (match-beginning 0))
|
||||
(let ((endpt (point)))
|
||||
(skip-chars-backward "^[:space:]")
|
||||
(buffer-substring-no-properties (point) endpt)))))))))
|
||||
(let ((avail (nth 2 (file-system-info dir))))
|
||||
(if avail
|
||||
(format "%.0f" (/ avail 1024))))))
|
||||
|
||||
;; The following expression replaces `dired-move-to-filename-regexp'.
|
||||
(defvar directory-listing-before-filename-regexp
|
||||
|
|
336
m4/fsusage.m4
Normal file
336
m4/fsusage.m4
Normal file
|
@ -0,0 +1,336 @@
|
|||
# serial 32
|
||||
# Obtaining file system usage information.
|
||||
|
||||
# Copyright (C) 1997-1998, 2000-2001, 2003-2017 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# Written by Jim Meyering.
|
||||
|
||||
AC_DEFUN([gl_FSUSAGE],
|
||||
[
|
||||
AC_CHECK_HEADERS_ONCE([sys/param.h])
|
||||
AC_CHECK_HEADERS_ONCE([sys/vfs.h sys/fs_types.h])
|
||||
AC_CHECK_HEADERS([sys/mount.h], [], [],
|
||||
[AC_INCLUDES_DEFAULT
|
||||
[#if HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif]])
|
||||
gl_FILE_SYSTEM_USAGE([gl_cv_fs_space=yes], [gl_cv_fs_space=no])
|
||||
])
|
||||
|
||||
# Try to determine how a program can obtain file system usage information.
|
||||
# If successful, define the appropriate symbol (see fsusage.c) and
|
||||
# execute ACTION-IF-FOUND. Otherwise, execute ACTION-IF-NOT-FOUND.
|
||||
#
|
||||
# gl_FILE_SYSTEM_USAGE([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
|
||||
|
||||
AC_DEFUN([gl_FILE_SYSTEM_USAGE],
|
||||
[
|
||||
dnl Enable large-file support. This has the effect of changing the size
|
||||
dnl of field f_blocks in 'struct statvfs' from 32 bit to 64 bit on
|
||||
dnl glibc/Hurd, HP-UX 11, Solaris (32-bit mode). It also changes the size
|
||||
dnl of field f_blocks in 'struct statfs' from 32 bit to 64 bit on
|
||||
dnl Mac OS X >= 10.5 (32-bit mode).
|
||||
AC_REQUIRE([AC_SYS_LARGEFILE])
|
||||
|
||||
AC_MSG_CHECKING([how to get file system space usage])
|
||||
ac_fsusage_space=no
|
||||
|
||||
# Perform only the link test since it seems there are no variants of the
|
||||
# statvfs function. This check is more than just AC_CHECK_FUNCS([statvfs])
|
||||
# because that got a false positive on SCO OSR5. Adding the declaration
|
||||
# of a 'struct statvfs' causes this test to fail (as it should) on such
|
||||
# systems. That system is reported to work fine with STAT_STATFS4 which
|
||||
# is what it gets when this test fails.
|
||||
if test $ac_fsusage_space = no; then
|
||||
# glibc/{Hurd,kFreeBSD}, FreeBSD >= 5.0, NetBSD >= 3.0,
|
||||
# OpenBSD >= 4.4, AIX, HP-UX, IRIX, Solaris, Cygwin, Interix, BeOS.
|
||||
AC_CACHE_CHECK([for statvfs function (SVR4)], [fu_cv_sys_stat_statvfs],
|
||||
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
|
||||
#ifdef __osf__
|
||||
"Do not use Tru64's statvfs implementation"
|
||||
#endif
|
||||
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
struct statvfs fsd;
|
||||
|
||||
#if defined __APPLE__ && defined __MACH__
|
||||
#include <limits.h>
|
||||
/* On Mac OS X >= 10.5, f_blocks in 'struct statvfs' is a 32-bit quantity;
|
||||
that commonly limits file systems to 4 TiB. Whereas f_blocks in
|
||||
'struct statfs' is a 64-bit type, thanks to the large-file support
|
||||
that was enabled above. In this case, don't use statvfs(); use statfs()
|
||||
instead. */
|
||||
int check_f_blocks_size[sizeof fsd.f_blocks * CHAR_BIT <= 32 ? -1 : 1];
|
||||
#endif
|
||||
]],
|
||||
[[statvfs (0, &fsd);]])],
|
||||
[fu_cv_sys_stat_statvfs=yes],
|
||||
[fu_cv_sys_stat_statvfs=no])])
|
||||
if test $fu_cv_sys_stat_statvfs = yes; then
|
||||
ac_fsusage_space=yes
|
||||
# AIX >= 5.2 has statvfs64 that has a wider f_blocks field than statvfs.
|
||||
# glibc, HP-UX, IRIX, Solaris have statvfs64 as well, but on these systems
|
||||
# statvfs with large-file support is already equivalent to statvfs64.
|
||||
AC_CACHE_CHECK([whether to use statvfs64],
|
||||
[fu_cv_sys_stat_statvfs64],
|
||||
[AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <sys/types.h>
|
||||
#include <sys/statvfs.h>
|
||||
struct statvfs64 fsd;
|
||||
int check_f_blocks_larger_in_statvfs64
|
||||
[sizeof (((struct statvfs64 *) 0)->f_blocks)
|
||||
> sizeof (((struct statvfs *) 0)->f_blocks)
|
||||
? 1 : -1];
|
||||
]],
|
||||
[[statvfs64 (0, &fsd);]])],
|
||||
[fu_cv_sys_stat_statvfs64=yes],
|
||||
[fu_cv_sys_stat_statvfs64=no])
|
||||
])
|
||||
if test $fu_cv_sys_stat_statvfs64 = yes; then
|
||||
AC_DEFINE([STAT_STATVFS64], [1],
|
||||
[ Define if statvfs64 should be preferred over statvfs.])
|
||||
else
|
||||
AC_DEFINE([STAT_STATVFS], [1],
|
||||
[ Define if there is a function named statvfs. (SVR4)])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for this unconditionally so we have a
|
||||
# good fallback on glibc/Linux > 2.6 < 2.6.36
|
||||
AC_MSG_CHECKING([for two-argument statfs with statfs.f_frsize member])
|
||||
AC_CACHE_VAL([fu_cv_sys_stat_statfs2_frsize],
|
||||
[AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MOUNT_H
|
||||
#include <sys/mount.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_VFS_H
|
||||
#include <sys/vfs.h>
|
||||
#endif
|
||||
int
|
||||
main ()
|
||||
{
|
||||
struct statfs fsd;
|
||||
fsd.f_frsize = 0;
|
||||
return statfs (".", &fsd) != 0;
|
||||
}]])],
|
||||
[fu_cv_sys_stat_statfs2_frsize=yes],
|
||||
[fu_cv_sys_stat_statfs2_frsize=no],
|
||||
[fu_cv_sys_stat_statfs2_frsize=no])])
|
||||
AC_MSG_RESULT([$fu_cv_sys_stat_statfs2_frsize])
|
||||
if test $fu_cv_sys_stat_statfs2_frsize = yes; then
|
||||
ac_fsusage_space=yes
|
||||
AC_DEFINE([STAT_STATFS2_FRSIZE], [1],
|
||||
[ Define if statfs takes 2 args and struct statfs has a field named f_frsize.
|
||||
(glibc/Linux > 2.6)])
|
||||
fi
|
||||
|
||||
if test $ac_fsusage_space = no; then
|
||||
# DEC Alpha running OSF/1
|
||||
AC_MSG_CHECKING([for 3-argument statfs function (DEC OSF/1)])
|
||||
AC_CACHE_VAL([fu_cv_sys_stat_statfs3_osf1],
|
||||
[AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mount.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
struct statfs fsd;
|
||||
fsd.f_fsize = 0;
|
||||
return statfs (".", &fsd, sizeof (struct statfs)) != 0;
|
||||
}]])],
|
||||
[fu_cv_sys_stat_statfs3_osf1=yes],
|
||||
[fu_cv_sys_stat_statfs3_osf1=no],
|
||||
[fu_cv_sys_stat_statfs3_osf1=no])])
|
||||
AC_MSG_RESULT([$fu_cv_sys_stat_statfs3_osf1])
|
||||
if test $fu_cv_sys_stat_statfs3_osf1 = yes; then
|
||||
ac_fsusage_space=yes
|
||||
AC_DEFINE([STAT_STATFS3_OSF1], [1],
|
||||
[ Define if statfs takes 3 args. (DEC Alpha running OSF/1)])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $ac_fsusage_space = no; then
|
||||
# glibc/Linux, Mac OS X, FreeBSD < 5.0, NetBSD < 3.0, OpenBSD < 4.4.
|
||||
# (glibc/{Hurd,kFreeBSD}, FreeBSD >= 5.0, NetBSD >= 3.0,
|
||||
# OpenBSD >= 4.4, AIX, HP-UX, OSF/1, Cygwin already handled above.)
|
||||
# (On IRIX you need to include <sys/statfs.h>, not only <sys/mount.h> and
|
||||
# <sys/vfs.h>.)
|
||||
# (On Solaris, statfs has 4 arguments.)
|
||||
AC_MSG_CHECKING([for two-argument statfs with statfs.f_bsize dnl
|
||||
member (AIX, 4.3BSD)])
|
||||
AC_CACHE_VAL([fu_cv_sys_stat_statfs2_bsize],
|
||||
[AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MOUNT_H
|
||||
#include <sys/mount.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_VFS_H
|
||||
#include <sys/vfs.h>
|
||||
#endif
|
||||
int
|
||||
main ()
|
||||
{
|
||||
struct statfs fsd;
|
||||
fsd.f_bsize = 0;
|
||||
return statfs (".", &fsd) != 0;
|
||||
}]])],
|
||||
[fu_cv_sys_stat_statfs2_bsize=yes],
|
||||
[fu_cv_sys_stat_statfs2_bsize=no],
|
||||
[fu_cv_sys_stat_statfs2_bsize=no])])
|
||||
AC_MSG_RESULT([$fu_cv_sys_stat_statfs2_bsize])
|
||||
if test $fu_cv_sys_stat_statfs2_bsize = yes; then
|
||||
ac_fsusage_space=yes
|
||||
AC_DEFINE([STAT_STATFS2_BSIZE], [1],
|
||||
[ Define if statfs takes 2 args and struct statfs has a field named f_bsize.
|
||||
(4.3BSD, SunOS 4, HP-UX, AIX PS/2)])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $ac_fsusage_space = no; then
|
||||
# SVR3
|
||||
# (Solaris already handled above.)
|
||||
AC_MSG_CHECKING([for four-argument statfs (AIX-3.2.5, SVR3)])
|
||||
AC_CACHE_VAL([fu_cv_sys_stat_statfs4],
|
||||
[AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <sys/types.h>
|
||||
#include <sys/statfs.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
struct statfs fsd;
|
||||
return statfs (".", &fsd, sizeof fsd, 0) != 0;
|
||||
}]])],
|
||||
[fu_cv_sys_stat_statfs4=yes],
|
||||
[fu_cv_sys_stat_statfs4=no],
|
||||
[fu_cv_sys_stat_statfs4=no])])
|
||||
AC_MSG_RESULT([$fu_cv_sys_stat_statfs4])
|
||||
if test $fu_cv_sys_stat_statfs4 = yes; then
|
||||
ac_fsusage_space=yes
|
||||
AC_DEFINE([STAT_STATFS4], [1],
|
||||
[ Define if statfs takes 4 args. (SVR3, Dynix, old Irix, old AIX, Dolphin)])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $ac_fsusage_space = no; then
|
||||
# 4.4BSD and older NetBSD
|
||||
# (OSF/1 already handled above.)
|
||||
# (On AIX, you need to include <sys/statfs.h>, not only <sys/mount.h>.)
|
||||
# (On Solaris, statfs has 4 arguments and 'struct statfs' is not declared in
|
||||
# <sys/mount.h>.)
|
||||
AC_MSG_CHECKING([for two-argument statfs with statfs.f_fsize dnl
|
||||
member (4.4BSD and NetBSD)])
|
||||
AC_CACHE_VAL([fu_cv_sys_stat_statfs2_fsize],
|
||||
[AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MOUNT_H
|
||||
#include <sys/mount.h>
|
||||
#endif
|
||||
int
|
||||
main ()
|
||||
{
|
||||
struct statfs fsd;
|
||||
fsd.f_fsize = 0;
|
||||
return statfs (".", &fsd) != 0;
|
||||
}]])],
|
||||
[fu_cv_sys_stat_statfs2_fsize=yes],
|
||||
[fu_cv_sys_stat_statfs2_fsize=no],
|
||||
[fu_cv_sys_stat_statfs2_fsize=no])])
|
||||
AC_MSG_RESULT([$fu_cv_sys_stat_statfs2_fsize])
|
||||
if test $fu_cv_sys_stat_statfs2_fsize = yes; then
|
||||
ac_fsusage_space=yes
|
||||
AC_DEFINE([STAT_STATFS2_FSIZE], [1],
|
||||
[ Define if statfs takes 2 args and struct statfs has a field named f_fsize.
|
||||
(4.4BSD, NetBSD)])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $ac_fsusage_space = no; then
|
||||
# Ultrix
|
||||
AC_MSG_CHECKING([for two-argument statfs with struct fs_data (Ultrix)])
|
||||
AC_CACHE_VAL([fu_cv_sys_stat_fs_data],
|
||||
[AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MOUNT_H
|
||||
#include <sys/mount.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_FS_TYPES_H
|
||||
#include <sys/fs_types.h>
|
||||
#endif
|
||||
int
|
||||
main ()
|
||||
{
|
||||
struct fs_data fsd;
|
||||
/* Ultrix's statfs returns 1 for success,
|
||||
0 for not mounted, -1 for failure. */
|
||||
return statfs (".", &fsd) != 1;
|
||||
}]])],
|
||||
[fu_cv_sys_stat_fs_data=yes],
|
||||
[fu_cv_sys_stat_fs_data=no],
|
||||
[fu_cv_sys_stat_fs_data=no])])
|
||||
AC_MSG_RESULT([$fu_cv_sys_stat_fs_data])
|
||||
if test $fu_cv_sys_stat_fs_data = yes; then
|
||||
ac_fsusage_space=yes
|
||||
AC_DEFINE([STAT_STATFS2_FS_DATA], [1],
|
||||
[ Define if statfs takes 2 args and the second argument has
|
||||
type struct fs_data. (Ultrix)])
|
||||
fi
|
||||
fi
|
||||
|
||||
AS_IF([test $ac_fsusage_space = yes], [$1], [$2])
|
||||
|
||||
])
|
||||
|
||||
|
||||
# Check for SunOS statfs brokenness wrt partitions 2GB and larger.
|
||||
# If <sys/vfs.h> exists and struct statfs has a member named f_spare,
|
||||
# enable the work-around code in fsusage.c.
|
||||
AC_DEFUN([gl_STATFS_TRUNCATES],
|
||||
[
|
||||
AC_MSG_CHECKING([for statfs that truncates block counts])
|
||||
AC_CACHE_VAL([fu_cv_sys_truncating_statfs],
|
||||
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#if !defined(sun) && !defined(__sun)
|
||||
choke -- this is a workaround for a Sun-specific problem
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/vfs.h>]],
|
||||
[[struct statfs t; long c = *(t.f_spare);
|
||||
if (c) return 0;]])],
|
||||
[fu_cv_sys_truncating_statfs=yes],
|
||||
[fu_cv_sys_truncating_statfs=no])])
|
||||
if test $fu_cv_sys_truncating_statfs = yes; then
|
||||
AC_DEFINE([STATFS_TRUNCATES_BLOCK_COUNTS], [1],
|
||||
[Define if the block counts reported by statfs may be truncated to 2GB
|
||||
and the correct values may be stored in the f_spare array.
|
||||
(SunOS 4.1.2, 4.1.3, and 4.1.3_U1 are reported to have this problem.
|
||||
SunOS 4.1.1 seems not to be affected.)])
|
||||
fi
|
||||
AC_MSG_RESULT([$fu_cv_sys_truncating_statfs])
|
||||
])
|
||||
|
||||
|
||||
# Prerequisites of lib/fsusage.c not done by gl_FILE_SYSTEM_USAGE.
|
||||
AC_DEFUN([gl_PREREQ_FSUSAGE_EXTRA],
|
||||
[
|
||||
AC_CHECK_HEADERS([dustat.h sys/fs/s5param.h sys/statfs.h])
|
||||
gl_STATFS_TRUNCATES
|
||||
])
|
|
@ -87,6 +87,7 @@ AC_DEFUN([gl_EARLY],
|
|||
# Code from module flexmember:
|
||||
# Code from module fpending:
|
||||
# Code from module fstatat:
|
||||
# Code from module fsusage:
|
||||
# Code from module fsync:
|
||||
# Code from module getdtablesize:
|
||||
# Code from module getgroups:
|
||||
|
@ -256,6 +257,11 @@ AC_DEFUN([gl_INIT],
|
|||
AC_LIBOBJ([fstatat])
|
||||
fi
|
||||
gl_SYS_STAT_MODULE_INDICATOR([fstatat])
|
||||
gl_FSUSAGE
|
||||
if test $gl_cv_fs_space = yes; then
|
||||
AC_LIBOBJ([fsusage])
|
||||
gl_PREREQ_FSUSAGE_EXTRA
|
||||
fi
|
||||
gl_FUNC_FSYNC
|
||||
if test $HAVE_FSYNC = 0; then
|
||||
AC_LIBOBJ([fsync])
|
||||
|
@ -864,6 +870,8 @@ AC_DEFUN([gl_FILE_LIST], [
|
|||
lib/fpending.c
|
||||
lib/fpending.h
|
||||
lib/fstatat.c
|
||||
lib/fsusage.c
|
||||
lib/fsusage.h
|
||||
lib/fsync.c
|
||||
lib/ftoastr.c
|
||||
lib/ftoastr.h
|
||||
|
@ -995,6 +1003,7 @@ AC_DEFUN([gl_FILE_LIST], [
|
|||
m4/flexmember.m4
|
||||
m4/fpending.m4
|
||||
m4/fstatat.m4
|
||||
m4/fsusage.m4
|
||||
m4/fsync.m4
|
||||
m4/getdtablesize.m4
|
||||
m4/getgroups.m4
|
||||
|
|
|
@ -49,6 +49,7 @@ OMIT_GNULIB_MODULE_dirent = true
|
|||
OMIT_GNULIB_MODULE_dirfd = true
|
||||
OMIT_GNULIB_MODULE_fcntl = true
|
||||
OMIT_GNULIB_MODULE_fcntl-h = true
|
||||
OMIT_GNULIB_MODULE_fsusage = true
|
||||
OMIT_GNULIB_MODULE_inttypes-incomplete = true
|
||||
OMIT_GNULIB_MODULE_open = true
|
||||
OMIT_GNULIB_MODULE_pipe2 = true
|
||||
|
|
39
src/fileio.c
39
src/fileio.c
|
@ -96,6 +96,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include <acl.h>
|
||||
#include <allocator.h>
|
||||
#include <careadlinkat.h>
|
||||
#include <fsusage.h>
|
||||
#include <stat-time.h>
|
||||
#include <tempname.h>
|
||||
|
||||
|
@ -5765,6 +5766,40 @@ effect except for flushing STREAM's data. */)
|
|||
return (set_binary_mode (fileno (fp), binmode) == O_BINARY) ? Qt : Qnil;
|
||||
}
|
||||
|
||||
#ifndef DOS_NT
|
||||
|
||||
/* Yield a Lisp float as close as possible to BLOCKSIZE * BLOCKS, with
|
||||
the result negated if NEGATE. */
|
||||
static Lisp_Object
|
||||
blocks_to_bytes (uintmax_t blocksize, uintmax_t blocks, bool negate)
|
||||
{
|
||||
/* On typical platforms the following code is accurate to 53 bits,
|
||||
which is close enough. BLOCKSIZE is invariably a power of 2, so
|
||||
converting it to double does not lose information. */
|
||||
double bs = blocksize;
|
||||
return make_float (negate ? -bs * -blocks : bs * blocks);
|
||||
}
|
||||
|
||||
DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0,
|
||||
doc: /* Return storage information about the file system FILENAME is on.
|
||||
Value is a list of numbers (TOTAL FREE AVAIL), where TOTAL is the total
|
||||
storage of the file system, FREE is the free storage, and AVAIL is the
|
||||
storage available to a non-superuser. All 3 numbers are in bytes.
|
||||
If the underlying system call fails, value is nil. */)
|
||||
(Lisp_Object filename)
|
||||
{
|
||||
Lisp_Object encoded = ENCODE_FILE (Fexpand_file_name (filename, Qnil));
|
||||
struct fs_usage u;
|
||||
if (get_fs_usage (SSDATA (encoded), NULL, &u) != 0)
|
||||
return Qnil;
|
||||
return list3 (blocks_to_bytes (u.fsu_blocksize, u.fsu_blocks, false),
|
||||
blocks_to_bytes (u.fsu_blocksize, u.fsu_bfree, false),
|
||||
blocks_to_bytes (u.fsu_blocksize, u.fsu_bavail,
|
||||
u.fsu_bavail_top_bit_set));
|
||||
}
|
||||
|
||||
#endif /* !DOS_NT */
|
||||
|
||||
void
|
||||
init_fileio (void)
|
||||
{
|
||||
|
@ -6115,6 +6150,10 @@ This includes interactive calls to `delete-file' and
|
|||
|
||||
defsubr (&Sset_binary_mode);
|
||||
|
||||
#ifndef DOS_NT
|
||||
defsubr (&Sfile_system_info);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYNC
|
||||
defsubr (&Sunix_sync);
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue