From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Paul Eggert Newsgroups: gmane.emacs.bugs Subject: bug#28639: 26.0.60; get-free-disk-space gives wrong number on OS X 10.8 and later Date: Sun, 1 Oct 2017 22:50:20 -0700 Organization: UCLA Computer Science Department Message-ID: <8a096d33-cdd0-b760-f398-ede651625691@cs.ucla.edu> References: <83h8vl77lz.fsf@gnu.org> <4b35fd50-3506-542a-4da1-cac44b5ae14e@cs.ucla.edu> <83d1695kq2.fsf@gnu.org> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------AB77116C5205FBEBFAF963F1" X-Trace: blaine.gmane.org 1506923489 10228 195.159.176.226 (2 Oct 2017 05:51:29 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Mon, 2 Oct 2017 05:51:29 +0000 (UTC) User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.3.0 Cc: 28639-done@debbugs.gnu.org To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Mon Oct 02 07:51:23 2017 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dytdS-0001vc-2K for geb-bug-gnu-emacs@m.gmane.org; Mon, 02 Oct 2017 07:51:22 +0200 Original-Received: from localhost ([::1]:50747 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dytdZ-0007s0-FA for geb-bug-gnu-emacs@m.gmane.org; Mon, 02 Oct 2017 01:51:29 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:44891) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dytdE-0007jr-1y for bug-gnu-emacs@gnu.org; Mon, 02 Oct 2017 01:51:12 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dytd9-0000u6-8K for bug-gnu-emacs@gnu.org; Mon, 02 Oct 2017 01:51:08 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:34644) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dytd9-0000tq-10 for bug-gnu-emacs@gnu.org; Mon, 02 Oct 2017 01:51:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1dytd8-0007LH-N3 for bug-gnu-emacs@gnu.org; Mon, 02 Oct 2017 01:51:02 -0400 Resent-From: Paul Eggert Original-Sender: "Debbugs-submit" Resent-To: bug-gnu-emacs@gnu.org Resent-Date: Mon, 02 Oct 2017 05:51:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: cc-closed 28639 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Mail-Followup-To: 28639@debbugs.gnu.org, eggert@cs.ucla.edu, mituharu@math.s.chiba-u.ac.jp Original-Received: via spool by 28639-done@debbugs.gnu.org id=D28639.150692343428182 (code D ref 28639); Mon, 02 Oct 2017 05:51:02 +0000 Original-Received: (at 28639-done) by debbugs.gnu.org; 2 Oct 2017 05:50:34 +0000 Original-Received: from localhost ([127.0.0.1]:43325 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dytce-0007KR-VC for submit@debbugs.gnu.org; Mon, 02 Oct 2017 01:50:34 -0400 Original-Received: from zimbra.cs.ucla.edu ([131.179.128.68]:42764) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dytcb-0007K9-Vv for 28639-done@debbugs.gnu.org; Mon, 02 Oct 2017 01:50:32 -0400 Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id 12A7616022A; Sun, 1 Oct 2017 22:50:24 -0700 (PDT) Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id AM7N4ew9JjQ0; Sun, 1 Oct 2017 22:50:20 -0700 (PDT) Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id C3ABC160D8D; Sun, 1 Oct 2017 22:50:20 -0700 (PDT) X-Virus-Scanned: amavisd-new at zimbra.cs.ucla.edu Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id 3wlBAalrvG4e; Sun, 1 Oct 2017 22:50:20 -0700 (PDT) Original-Received: from [192.168.1.9] (unknown [47.154.18.85]) by zimbra.cs.ucla.edu (Postfix) with ESMTPSA id 8357516022A; Sun, 1 Oct 2017 22:50:20 -0700 (PDT) In-Reply-To: <83d1695kq2.fsf@gnu.org> Content-Language: en-US X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:137766 Archived-At: This is a multi-part message in MIME format. --------------AB77116C5205FBEBFAF963F1 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: quoted-printable Eli Zaretskii wrote: >> Should be doable. I assume this would be for 'master', not 'emacs-26'? > Yes, I think so. Unless the original bug is extremely annoying and > cannot wait, that is. I installed the attached into master, as I guess the original bug is mere= ly=20 mildly annoying. We can backport it to emacs-26 if I guessed wrong. As th= is=20 should fix the bug I'm boldly marking it as done. It strikes me that Emacs's support for fsusage on Microsoft platforms sho= uld be=20 migrated into Gnulib, so that the support could benefit non-Emacs program= s like=20 GNU 'df' (and also simplify Emacs proper). That is lower priority, though= . --------------AB77116C5205FBEBFAF963F1 Content-Type: text/x-patch; name="0001-Port-file-system-info-to-non-Microsoft.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="0001-Port-file-system-info-to-non-Microsoft.patch" =46rom 135bca574c31b7bf6df6c63d28f180956928dde7 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 1 Oct 2017 22:31:39 -0700 Subject: [PATCH] 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. --- admin/merge-gnulib | 2 +- doc/emacs/files.texi | 7 +- etc/NEWS | 4 + etc/PROBLEMS | 10 +- lib/fsusage.c | 288 +++++++++++++++++++++++++++++++++++++++++++ lib/fsusage.h | 40 ++++++ lib/gnulib.mk.in | 13 +- lisp/dired.el | 6 +- lisp/files.el | 49 ++------ m4/fsusage.m4 | 336 +++++++++++++++++++++++++++++++++++++++++++++= ++++++ m4/gnulib-comp.m4 | 9 ++ nt/gnulib-cfg.mk | 1 + src/fileio.c | 39 ++++++ 13 files changed, 750 insertions(+), 54 deletions(-) create mode 100644 lib/fsusage.c create mode 100644 lib/fsusage.h create mode 100644 m4/fsusage.m4 diff --git a/admin/merge-gnulib b/admin/merge-gnulib index 60104e8..4b1dc59 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib @@ -33,7 +33,7 @@ GNULIB_MODULES=3D 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 diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index 18f1c28..2c4a0ca 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -1279,13 +1279,8 @@ Directories giving the switches to use in a verbose listing (@code{"-l"} by default). =20 -@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. =20 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 diff --git a/etc/NEWS b/etc/NEWS index 42c1b04..28789a9 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -73,6 +73,10 @@ calling 'eldoc-message' directly. =0C * Lisp Changes in Emacs 27.1 =20 +** 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). + =0C * Changes in Emacs 27.1 on Non-Free Operating Systems =20 diff --git a/etc/PROBLEMS b/etc/PROBLEMS index 94c78b6..2da9932 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS @@ -557,7 +557,7 @@ and then choose /usr/bin/netkit-ftp. =20 *** Dired is very slow. =20 -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: =20 - ClearCase mounted filesystems (VOBs) that sometimes make 'df' @@ -565,12 +565,8 @@ time. Possible reasons for this include: =20 - slow automounters on some old versions of Unix; =20 - - 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. =20 *** ps-print commands fail to find prologue files ps-prin*.ps. =20 diff --git a/lib/fsusage.c b/lib/fsusage.c new file mode 100644 index 0000000..a0f763b --- /dev/null +++ b/lib/fsusage.c @@ -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 S= oftware + 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 = =2E */ + +#include + +#include "fsusage.h" + +#include +#include + +#if STAT_STATVFS || STAT_STATVFS64 /* POSIX 1003.1-2001 (and later) with= XSI */ +# include +#else +/* Don't include backward-compatibility files unless they're needed. + Eventually we'd like to remove all this cruft. */ +# include +# include +# include +#if HAVE_SYS_PARAM_H +# include +#endif +#if HAVE_SYS_MOUNT_H +# include +#endif +#if HAVE_SYS_VFS_H +# include +#endif +# if HAVE_SYS_FS_S5PARAM_H /* Fujitsu UXP/V */ +# include +# endif +# if HAVE_SYS_STATFS_H +# include +# endif +# if HAVE_DUSTAT_H /* AIX PS/2 */ +# include +# 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) =3D=3D (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 unsign= ed. + 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 /* for strverscmp */ +# include +# include +# define STAT_STATFS2_BSIZE 1 + +static int +statvfs_works (void) +{ + static int statvfs_works_cache =3D -1; + struct utsname name; + if (statvfs_works_cache < 0) + statvfs_works_cache =3D (uname (&name) =3D=3D 0 + && 0 <=3D 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 =3D (vfsd.f_frsize + ? PROPAGATE_ALL_ONES (vfsd.f_frsize) + : PROPAGATE_ALL_ONES (vfsd.f_bsize)); + + fsp->fsu_blocks =3D PROPAGATE_ALL_ONES (vfsd.f_blocks); + fsp->fsu_bfree =3D PROPAGATE_ALL_ONES (vfsd.f_bfree); + fsp->fsu_bavail =3D PROPAGATE_TOP_BIT (vfsd.f_bavail); + fsp->fsu_bavail_top_bit_set =3D EXTRACT_TOP_BIT (vfsd.f_bavail) !=3D= 0; + fsp->fsu_files =3D PROPAGATE_ALL_ONES (vfsd.f_files); + fsp->fsu_ffree =3D 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 =3D (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) !=3D 1) + return -1; + + fsp->fsu_blocksize =3D 1024; + fsp->fsu_blocks =3D PROPAGATE_ALL_ONES (fsd.fd_req.btot); + fsp->fsu_bfree =3D PROPAGATE_ALL_ONES (fsd.fd_req.bfree); + fsp->fsu_bavail =3D PROPAGATE_TOP_BIT (fsd.fd_req.bfreen); + fsp->fsu_bavail_top_bit_set =3D EXTRACT_TOP_BIT (fsd.fd_req.bfreen) !=3D= 0; + fsp->fsu_files =3D PROPAGATE_ALL_ONES (fsd.fd_req.gtot); + fsp->fsu_ffree =3D PROPAGATE_ALL_ONES (fsd.fd_req.gfree); + +#elif defined STAT_STATFS3_OSF1 /* OSF/1 */ + + struct statfs fsd; + + if (statfs (file, &fsd, sizeof (struct statfs)) !=3D 0) + return -1; + + fsp->fsu_blocksize =3D 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 =3D PROPAGATE_ALL_ONES (fsd.f_frsize); + +#elif defined STAT_STATFS2_BSIZE /* glibc/Linux < 2.6, 4.3BSD, Su= nOS 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 =3D 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 =3D=3D 0x7fffffff / fsd.f_bsize && fsd.f_spare[0] > 0= ) + { + fsd.f_blocks =3D fsd.f_spare[0]; + fsd.f_bfree =3D fsd.f_spare[1]; + fsd.f_bavail =3D 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 =3D PROPAGATE_ALL_ONES (fsd.f_fsize); + +#elif defined STAT_STATFS4 /* SVR3, Dynix, old Irix, old AI= X, \ + 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 =3D PROPAGATE_ALL_ONES (fsd.f_bsize); +# else + fsp->fsu_blocksize =3D 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 =3D PROPAGATE_ALL_ONES (fsd.f_blocks); + fsp->fsu_bfree =3D PROPAGATE_ALL_ONES (fsd.f_bfree); + fsp->fsu_bavail =3D PROPAGATE_TOP_BIT (fsd.f_bavail); + fsp->fsu_bavail_top_bit_set =3D EXTRACT_TOP_BIT (fsd.f_bavail) !=3D 0;= + fsp->fsu_files =3D PROPAGATE_ALL_ONES (fsd.f_files); + fsp->fsu_ffree =3D 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) !=3D 0) + return -1; + if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd))) + return -1; + fsb->f_type =3D 0; + fsb->f_bsize =3D fsd.du_bsize; + fsb->f_blocks =3D fsd.du_fsize - fsd.du_isize; + fsb->f_bfree =3D fsd.du_tfree; + fsb->f_bavail =3D fsd.du_tfree; + fsb->f_files =3D (fsd.du_isize - 2) * fsd.du_inopb; + fsb->f_ffree =3D fsd.du_tinode; + fsb->f_fsid.val[0] =3D fsd.du_site; + fsb->f_fsid.val[1] =3D fsd.du_pckno; + return 0; +} + +#endif /* _AIX && _I386 */ diff --git a/lib/fsusage.h b/lib/fsusage.h new file mode 100644 index 0000000..f78edc6 --- /dev/null +++ b/lib/fsusage.h @@ -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 = =2E */ + +/* Space usage statistics for a file system. Blocks are 512-byte. */ + +#if !defined FSUSAGE_H_ +# define FSUSAGE_H_ + +# include +# include + +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-superuse= r. */ + 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 *f= sp); + +#endif diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index 0f795b3..e9358a6 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -21,7 +21,7 @@ # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --lib=3Dlibgnu --source-base=3Dlib = --m4-base=3Dm4 --doc-base=3Ddoc --tests-base=3Dtests --aux-dir=3Dbuild-au= x --avoid=3Dclose --avoid=3Ddup --avoid=3Dfchdir --avoid=3Dfstat --avoid=3D= malloc-posix --avoid=3Dmsvc-inval --avoid=3Dmsvc-nothrow --avoid=3Dopenat= -die --avoid=3Dopendir --avoid=3Draise --avoid=3Dsave-cwd --avoid=3Dselec= t --avoid=3Dsetenv --avoid=3Dsigprocmask --avoid=3Dstat --avoid=3Dstdarg = --avoid=3Dstdbool --avoid=3Dthreadlib --avoid=3Dtzset --avoid=3Dunsetenv = --avoid=3Dutime --avoid=3Dutime-h --gnu-make --makefile-name=3Dgnulib.mk.= in --conditional-dependencies --no-libtool --macro-prefix=3Dgl --no-vc-fi= les alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-st= ream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 c= rypto/sha1 crypto/sha256 crypto/sha512 d-type diffseq dtoastr dtotimespec= dup2 environ execinfo explicit_bzero faccessat fcntl fcntl-h fdatasync f= dopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-g= nu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefi= le lstat manywarnings memrchr minmax mkostemp mktime nstrftime pipe2 psel= ect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen = stat-time std-gnu11 stdalign stddef stdio stpcpy strtoimax symlink sys_st= at sys_time tempname time time_r time_rz timegm timer-time timespec-add t= imespec-sub unlocked-io update-copyright utimens vla warnings +# Reproduce by: gnulib-tool --import --lib=3Dlibgnu --source-base=3Dlib = --m4-base=3Dm4 --doc-base=3Ddoc --tests-base=3Dtests --aux-dir=3Dbuild-au= x --avoid=3Dclose --avoid=3Ddup --avoid=3Dfchdir --avoid=3Dfstat --avoid=3D= malloc-posix --avoid=3Dmsvc-inval --avoid=3Dmsvc-nothrow --avoid=3Dopenat= -die --avoid=3Dopendir --avoid=3Draise --avoid=3Dsave-cwd --avoid=3Dselec= t --avoid=3Dsetenv --avoid=3Dsigprocmask --avoid=3Dstat --avoid=3Dstdarg = --avoid=3Dstdbool --avoid=3Dthreadlib --avoid=3Dtzset --avoid=3Dunsetenv = --avoid=3Dutime --avoid=3Dutime-h --gnu-make --makefile-name=3Dgnulib.mk.= in --conditional-dependencies --no-libtool --macro-prefix=3Dgl --no-vc-fi= les alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-st= ream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 c= rypto/sha1 crypto/sha256 crypto/sha512 d-type diffseq dtoastr dtotimespec= dup2 environ execinfo explicit_bzero faccessat fcntl fcntl-h fdatasync f= dopendir 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 pi= pe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str = socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strtoimax symlin= k sys_stat sys_time tempname time time_r time_rz timegm timer-time timesp= ec-add timespec-sub unlocked-io update-copyright utimens vla warnings =20 =20 MOSTLYCLEANFILES +=3D core *.stackdump @@ -1516,6 +1516,17 @@ EXTRA_libgnu_a_SOURCES +=3D at-func.c fstatat.c endif ## end gnulib module fstatat =20 +## begin gnulib module fsusage +ifeq (,$(OMIT_GNULIB_MODULE_fsusage)) + + +EXTRA_DIST +=3D fsusage.c fsusage.h + +EXTRA_libgnu_a_SOURCES +=3D fsusage.c + +endif +## end gnulib module fsusage + ## begin gnulib module fsync ifeq (,$(OMIT_GNULIB_MODULE_fsync)) =20 diff --git a/lisp/dired.el b/lisp/dired.el index 9e09d34..1ec3ac4 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -198,8 +198,10 @@ dired-copy-preserve-time =20 ; 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") =20 ;;; Hook variables =20 diff --git a/lisp/files.el b/lisp/files.el index 336bbc8..194c87a 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -6386,58 +6386,33 @@ directory-free-space-program =20 A value of nil disables this feature. =20 -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") =20 (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") =20 (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). =20 -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)))))) =20 ;; The following expression replaces `dired-move-to-filename-regexp'. (defvar directory-listing-before-filename-regexp diff --git a/m4/fsusage.m4 b/m4/fsusage.m4 new file mode 100644 index 0000000..1d6ad41 --- /dev/null +++ b/m4/fsusage.m4 @@ -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 + #endif]]) + gl_FILE_SYSTEM_USAGE([gl_cv_fs_space=3Dyes], [gl_cv_fs_space=3Dno]) +]) + +# Try to determine how a program can obtain file system usage informatio= n. +# 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 siz= e +dnl of field f_blocks in 'struct statfs' from 32 bit to 64 bit on +dnl Mac OS X >=3D 10.5 (32-bit mode). +AC_REQUIRE([AC_SYS_LARGEFILE]) + +AC_MSG_CHECKING([how to get file system space usage]) +ac_fsusage_space=3Dno + +# 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([statvf= s]) +# 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 =3D no; then + # glibc/{Hurd,kFreeBSD}, FreeBSD >=3D 5.0, NetBSD >=3D 3.0, + # OpenBSD >=3D 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 +#ifdef __osf__ +"Do not use Tru64's statvfs implementation" +#endif + +#include + +struct statvfs fsd; + +#if defined __APPLE__ && defined __MACH__ +#include +/* On Mac OS X >=3D 10.5, f_blocks in 'struct statvfs' is a 32-bit quant= ity; + 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 statf= s() + instead. */ +int check_f_blocks_size[sizeof fsd.f_blocks * CHAR_BIT <=3D 32 ? -1 : 1]= ; +#endif +]], + [[statvfs (0, &fsd);]])], + [fu_cv_sys_stat_statvfs=3Dyes], + [fu_cv_sys_stat_statvfs=3Dno])]) + if test $fu_cv_sys_stat_statvfs =3D yes; then + ac_fsusage_space=3Dyes + # AIX >=3D 5.2 has statvfs64 that has a wider f_blocks field than st= atvfs. + # glibc, HP-UX, IRIX, Solaris have statvfs64 as well, but on these s= ystems + # statvfs with large-file support is already equivalent to statvfs64= =2E + AC_CACHE_CHECK([whether to use statvfs64], + [fu_cv_sys_stat_statvfs64], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + 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=3Dyes], + [fu_cv_sys_stat_statvfs64=3Dno]) + ]) + if test $fu_cv_sys_stat_statvfs64 =3D 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 +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif +#ifdef HAVE_SYS_VFS_H +#include +#endif + int + main () + { + struct statfs fsd; + fsd.f_frsize =3D 0; + return statfs (".", &fsd) !=3D 0; + }]])], + [fu_cv_sys_stat_statfs2_frsize=3Dyes], + [fu_cv_sys_stat_statfs2_frsize=3Dno], + [fu_cv_sys_stat_statfs2_frsize=3Dno])]) +AC_MSG_RESULT([$fu_cv_sys_stat_statfs2_frsize]) +if test $fu_cv_sys_stat_statfs2_frsize =3D yes; then + ac_fsusage_space=3Dyes + AC_DEFINE([STAT_STATFS2_FRSIZE], [1], +[ Define if statfs takes 2 args and struct statfs has a field named f_f= rsize. + (glibc/Linux > 2.6)]) +fi + +if test $ac_fsusage_space =3D 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 +#include +#include + int + main () + { + struct statfs fsd; + fsd.f_fsize =3D 0; + return statfs (".", &fsd, sizeof (struct statfs)) !=3D 0; + }]])], + [fu_cv_sys_stat_statfs3_osf1=3Dyes], + [fu_cv_sys_stat_statfs3_osf1=3Dno], + [fu_cv_sys_stat_statfs3_osf1=3Dno])]) + AC_MSG_RESULT([$fu_cv_sys_stat_statfs3_osf1]) + if test $fu_cv_sys_stat_statfs3_osf1 =3D yes; then + ac_fsusage_space=3Dyes + AC_DEFINE([STAT_STATFS3_OSF1], [1], + [ Define if statfs takes 3 args. (DEC Alpha running OS= F/1)]) + fi +fi + +if test $ac_fsusage_space =3D no; then + # glibc/Linux, Mac OS X, FreeBSD < 5.0, NetBSD < 3.0, OpenBSD < 4.4. + # (glibc/{Hurd,kFreeBSD}, FreeBSD >=3D 5.0, NetBSD >=3D 3.0, + # OpenBSD >=3D 4.4, AIX, HP-UX, OSF/1, Cygwin already handled above.) + # (On IRIX you need to include , not only = and + # .) + # (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 +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif +#ifdef HAVE_SYS_VFS_H +#include +#endif + int + main () + { + struct statfs fsd; + fsd.f_bsize =3D 0; + return statfs (".", &fsd) !=3D 0; + }]])], + [fu_cv_sys_stat_statfs2_bsize=3Dyes], + [fu_cv_sys_stat_statfs2_bsize=3Dno], + [fu_cv_sys_stat_statfs2_bsize=3Dno])]) + AC_MSG_RESULT([$fu_cv_sys_stat_statfs2_bsize]) + if test $fu_cv_sys_stat_statfs2_bsize =3D yes; then + ac_fsusage_space=3Dyes + AC_DEFINE([STAT_STATFS2_BSIZE], [1], +[ Define if statfs takes 2 args and struct statfs has a field named f_b= size. + (4.3BSD, SunOS 4, HP-UX, AIX PS/2)]) + fi +fi + +if test $ac_fsusage_space =3D 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 +#include + int + main () + { + struct statfs fsd; + return statfs (".", &fsd, sizeof fsd, 0) !=3D 0; + }]])], + [fu_cv_sys_stat_statfs4=3Dyes], + [fu_cv_sys_stat_statfs4=3Dno], + [fu_cv_sys_stat_statfs4=3Dno])]) + AC_MSG_RESULT([$fu_cv_sys_stat_statfs4]) + if test $fu_cv_sys_stat_statfs4 =3D yes; then + ac_fsusage_space=3Dyes + 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 =3D no; then + # 4.4BSD and older NetBSD + # (OSF/1 already handled above.) + # (On AIX, you need to include , not only .= ) + # (On Solaris, statfs has 4 arguments and 'struct statfs' is not decla= red in + # .) + 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 +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif + int + main () + { + struct statfs fsd; + fsd.f_fsize =3D 0; + return statfs (".", &fsd) !=3D 0; + }]])], + [fu_cv_sys_stat_statfs2_fsize=3Dyes], + [fu_cv_sys_stat_statfs2_fsize=3Dno], + [fu_cv_sys_stat_statfs2_fsize=3Dno])]) + AC_MSG_RESULT([$fu_cv_sys_stat_statfs2_fsize]) + if test $fu_cv_sys_stat_statfs2_fsize =3D yes; then + ac_fsusage_space=3Dyes + AC_DEFINE([STAT_STATFS2_FSIZE], [1], +[ Define if statfs takes 2 args and struct statfs has a field named f_f= size. + (4.4BSD, NetBSD)]) + fi +fi + +if test $ac_fsusage_space =3D 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 +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif +#ifdef HAVE_SYS_FS_TYPES_H +#include +#endif + int + main () + { + struct fs_data fsd; + /* Ultrix's statfs returns 1 for success, + 0 for not mounted, -1 for failure. */ + return statfs (".", &fsd) !=3D 1; + }]])], + [fu_cv_sys_stat_fs_data=3Dyes], + [fu_cv_sys_stat_fs_data=3Dno], + [fu_cv_sys_stat_fs_data=3Dno])]) + AC_MSG_RESULT([$fu_cv_sys_stat_fs_data]) + if test $fu_cv_sys_stat_fs_data =3D yes; then + ac_fsusage_space=3Dyes + 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 =3D yes], [$1], [$2]) + +]) + + +# Check for SunOS statfs brokenness wrt partitions 2GB and larger. +# If 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 +#include ]], + [[struct statfs t; long c =3D *(t.f_spare); + if (c) return 0;]])], + [fu_cv_sys_truncating_statfs=3Dyes], + [fu_cv_sys_truncating_statfs=3Dno])]) + if test $fu_cv_sys_truncating_statfs =3D 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 probl= em. + 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 +]) diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index c551752..cb255fc 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -87,6 +87,7 @@ AC_DEFUN # 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 AC_LIBOBJ([fstatat]) fi gl_SYS_STAT_MODULE_INDICATOR([fstatat]) + gl_FSUSAGE + if test $gl_cv_fs_space =3D yes; then + AC_LIBOBJ([fsusage]) + gl_PREREQ_FSUSAGE_EXTRA + fi gl_FUNC_FSYNC if test $HAVE_FSYNC =3D 0; then AC_LIBOBJ([fsync]) @@ -864,6 +870,8 @@ AC_DEFUN 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 m4/flexmember.m4 m4/fpending.m4 m4/fstatat.m4 + m4/fsusage.m4 m4/fsync.m4 m4/getdtablesize.m4 m4/getgroups.m4 diff --git a/nt/gnulib-cfg.mk b/nt/gnulib-cfg.mk index 419099e..f621667 100644 --- a/nt/gnulib-cfg.mk +++ b/nt/gnulib-cfg.mk @@ -49,6 +49,7 @@ OMIT_GNULIB_MODULE_dirent =3D OMIT_GNULIB_MODULE_dirfd =3D true OMIT_GNULIB_MODULE_fcntl =3D true OMIT_GNULIB_MODULE_fcntl-h =3D true +OMIT_GNULIB_MODULE_fsusage =3D true OMIT_GNULIB_MODULE_inttypes-incomplete =3D true OMIT_GNULIB_MODULE_open =3D true OMIT_GNULIB_MODULE_pipe2 =3D true diff --git a/src/fileio.c b/src/fileio.c index adb3534..1137027 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -96,6 +96,7 @@ along with GNU Emacs. If not, see . */ #include #include #include +#include #include #include =20 @@ -5765,6 +5766,40 @@ effect except for flushing STREAM's data. */) return (set_binary_mode (fileno (fp), binmode) =3D=3D O_BINARY) ? Qt := Qnil; } =0C +#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 =3D 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 =3D ENCODE_FILE (Fexpand_file_name (filename, Qnil= )); + struct fs_usage u; + if (get_fs_usage (SSDATA (encoded), NULL, &u) !=3D 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 */ +=0C void init_fileio (void) { @@ -6115,6 +6150,10 @@ This includes interactive calls to `delete-file' a= nd =20 defsubr (&Sset_binary_mode); =20 +#ifndef DOS_NT + defsubr (&Sfile_system_info); +#endif + #ifdef HAVE_SYNC defsubr (&Sunix_sync); #endif --=20 2.7.4 --------------AB77116C5205FBEBFAF963F1--