From cbd04ad3d572850775f18bde868c71abcde733ed Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Thu, 13 Oct 2022 21:13:45 +0200 Subject: [PATCH] Clarify structure of file-attribute's device number * doc/lispref/buffers.texi (Buffer File Name): Fix description of buffer-file-number. * doc/lispref/files.texi (File Attributes): Clarify type of device number. Describe file-attribute-file-number. (Bug#58446) * etc/NEWS: Mention file-attribute-file-number. * lisp/files.el (buffer-file-number, file-attribute-device-number) (file-attribute-collect): Fix docstring. (file-attribute-file-number): New defsubst. (find-buffer-visiting, find-file-noselect) (set-visited-file-name, basic-save-buffer): * lisp/startup.el (normal-top-level-add-subdirs-to-load-path): * lisp/eshell/em-unix.el (eshell-shuffle-files): Use it. * src/dired.c (Ffile_attributes): Fix docstring. --- doc/lispref/buffers.texi | 4 ++-- doc/lispref/files.texi | 13 ++++++++----- etc/NEWS | 9 +++++++-- lisp/eshell/em-unix.el | 6 ++---- lisp/files.el | 24 +++++++++++++++--------- lisp/startup.el | 2 +- src/dired.c | 5 +++-- 7 files changed, 38 insertions(+), 25 deletions(-) diff --git a/doc/lispref/buffers.texi b/doc/lispref/buffers.texi index 6a1d125701c..b46b6c52d86 100644 --- a/doc/lispref/buffers.texi +++ b/doc/lispref/buffers.texi @@ -427,12 +427,12 @@ It is a permanent local, unaffected by @end defvar @defvar buffer-file-number -This buffer-local variable holds the file number and directory device +This buffer-local variable holds the inode number and directory device number of the file visited in the current buffer, or @code{nil} if no file or a nonexistent file is visited. It is a permanent local, unaffected by @code{kill-all-local-variables}. -The value is normally a list of the form @code{(@var{filenum} +The value is normally a list of the form @code{(@var{inodenum} @var{devnum})}. This pair of numbers uniquely identifies the file among all files accessible on the system. See the function @code{file-attributes}, in @ref{File Attributes}, for more information diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 0e8efa3297c..b9d4e87dc73 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -1405,13 +1405,16 @@ a nonnegative integer. @item The filesystem number of the device that the file is on -@code{file-attribute-device-number}), an integer. -This element and the file's inode number -together give enough information to distinguish any two files on the -system---no two files can have the same values for both of these -numbers. +(@code{file-attribute-device-number}), an integer or a cons cell of +integers. The latter is sometimes used by remote files, in order to +distinguish the remote filesystems from the local ones. @end enumerate +The file's inode and device numbers together give enough information +to distinguish any two files on the system---no two files can have the +same values for both of these numbers. This tupel is returned by +@code{file-attribute-file-number}. + For example, here are the file attributes for @file{files.texi}: @example diff --git a/etc/NEWS b/etc/NEWS index ca857056fd8..7808c3beb20 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1872,7 +1872,7 @@ If non-nil, multiple revisions can be queried. This is done using 'completing-read-multiple'. --- -*** New function 'vc-read-multiple-revisions' +*** New function 'vc-read-multiple-revisions'. This function invokes 'vc-read-revision' with a non-nil value for MULTIPLE. @@ -1880,7 +1880,7 @@ MULTIPLE. *** New command 'vc-prepare-patch'. Patches for any version control system can be prepared using VC. The command will query what commits to send and will compose messages for -your mail user agent. The behaviour of 'vc-prepare-patch' can be +your mail user agent. The behavior of 'vc-prepare-patch' can be modified by the user options 'vc-prepare-patches-separately' and 'vc-default-patch-addressee'. @@ -3147,6 +3147,11 @@ The following generalized variables have been made obsolete: * Lisp Changes in Emacs 29.1 ++++ +** New accessor function 'file-attribute-file-number'. +It returns the list of the inode and device numbers retrieved by +'file-attributes'. This value can be used to identify a file uniquely. + +++ ** New macro 'while-let'. This is like 'when-let', but repeats until a binding form is nil. diff --git a/lisp/eshell/em-unix.el b/lisp/eshell/em-unix.el index 40b83010f94..378b0ceeeae 100644 --- a/lisp/eshell/em-unix.el +++ b/lisp/eshell/em-unix.el @@ -372,12 +372,10 @@ Remove the DIRECTORY(ies), if they are empty.") (setq attr (eshell-file-attributes (car files))) (file-attribute-inode-number attr-target) (file-attribute-inode-number attr) - (equal (file-attribute-inode-number attr-target) - (file-attribute-inode-number attr)) (file-attribute-device-number attr-target) (file-attribute-device-number attr) - (equal (file-attribute-device-number attr-target) - (file-attribute-device-number attr))) + (equal (file-attribute-file-number attr-target) + (file-attribute-file-number attr))) (eshell-error (format-message "%s: `%s' and `%s' are the same file\n" command (car files) target))) (t diff --git a/lisp/files.el b/lisp/files.el index 94d110f0b7d..1a301485517 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -208,8 +208,8 @@ if the file has changed on disk and you have not edited the buffer." :group 'find-file) (defvar-local buffer-file-number nil - "The device number and file number of the file visited in the current buffer. -The value is a list of the form (FILENUM DEVNUM). + "The inode and device numbers of the file visited in the current buffer. +The value is a list of the form (INODENUM DEVNUM). This pair of numbers uniquely identifies the file. If the buffer is visiting a new file, the value is nil.") (put 'buffer-file-number 'permanent-local t) @@ -2163,7 +2163,7 @@ If there is no such live buffer, return nil." (setq list (cdr list))) found) (let* ((attributes (file-attributes truename)) - (number (nthcdr 10 attributes)) + (number (file-attribute-file-number attributes)) (list (buffer-list)) found) (and buffer-file-numbers-unique (car-safe number) ;Make sure the inode is not just nil. @@ -2366,7 +2366,7 @@ the various files." (let* ((buf (get-file-buffer filename)) (truename (abbreviate-file-name (file-truename filename))) (attributes (file-attributes truename)) - (number (nthcdr 10 attributes)) + (number (file-attribute-file-number attributes)) ;; Find any buffer for a file that has same truename. (other (and (not buf) (find-buffer-visiting @@ -4744,7 +4744,7 @@ the old visited file has been renamed to the new name FILENAME." (setq buffer-file-name truename)))) (setq buffer-file-number (if filename - (nthcdr 10 (file-attributes buffer-file-name)) + (file-attribute-file-number (file-attributes buffer-file-name)) nil)) ;; write-file-functions is normally used for things like ftp-find-file ;; that visit things that are not local files as if they were files. @@ -5733,7 +5733,7 @@ Before and after saving the buffer, this function runs (setq save-buffer-coding-system last-coding-system-used) (setq buffer-file-coding-system last-coding-system-used)) (setq buffer-file-number - (nthcdr 10 (file-attributes buffer-file-name))) + (file-attribute-file-number (file-attributes buffer-file-name))) (if setmodes (condition-case () (progn @@ -8658,19 +8658,25 @@ It is a nonnegative integer." (defsubst file-attribute-device-number (attributes) "The file system device number in ATTRIBUTES returned by `file-attributes'. -It is an integer." +It is an integer or a cons cell of integers." (nth 11 attributes)) +(defsubst file-attribute-file-number (attributes) + "The inode and device numbers in ATTRIBUTES returned by `file-attributes'. +The value is a list of the form (INODENUM DEVNUM). +This pair of numbers uniquely identifies the file." + (nthcdr 10 attributes)) + (defun file-attribute-collect (attributes &rest attr-names) "Return a sublist of ATTRIBUTES returned by `file-attributes'. ATTR-NAMES are symbols with the selected attribute names. Valid attribute names are: type, link-number, user-id, group-id, access-time, modification-time, status-change-time, size, modes, -inode-number and device-number." +inode-number, device-number and file-number." (let ((all '(type link-number user-id group-id access-time modification-time status-change-time - size modes inode-number device-number)) + size modes inode-number device-number file-number)) result) (while attr-names (let ((attr (pop attr-names))) diff --git a/lisp/startup.el b/lisp/startup.el index 04de7e42fea..c7faf4abc6f 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -458,7 +458,7 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'." ;; The Windows version doesn't report meaningful inode numbers, so ;; use the canonicalized absolute file name of the directory instead. (setq attrs (or canonicalized - (nthcdr 10 (file-attributes this-dir)))) + (file-attribute-file-number (file-attributes this-dir)))) (unless (member attrs normal-top-level-add-subdirs-inode-list) (push attrs normal-top-level-add-subdirs-inode-list) (dolist (file contents) diff --git a/src/dired.c b/src/dired.c index c2c099f0a5f..32c083ad7b0 100644 --- a/src/dired.c +++ b/src/dired.c @@ -923,11 +923,12 @@ Elements of the attribute list are: 8. File modes, as a string of ten letters or dashes as in ls -l. 9. An unspecified value, present only for backward compatibility. 10. inode number, as a nonnegative integer. -11. Filesystem device number, as an integer. +11. Filesystem device number, as an integer or a cons cell of integers. Large integers are bignums, so `eq' might not work on them. On most filesystems, the combination of the inode and the device -number uniquely identifies the file. +number uniquely identifies the file. This is provided by the access +function `file-attribute-file-number'. On MS-Windows, performance depends on `w32-get-true-file-attributes', which see. -- 2.39.5