emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 662bee7: file-attributes cleanup


From: Paul Eggert
Subject: [Emacs-diffs] master 662bee7: file-attributes cleanup
Date: Sun, 23 Sep 2018 21:33:05 -0400 (EDT)

branch: master
commit 662bee7d70ccd3903e123b08c7ec9108a1a2ce0b
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    file-attributes cleanup
    
    Mostly, this replaces magic-number calls like (nth 4 A) with
    more-informative calls like (file-attribute-access-time A).
    It also fixes some documentation and minor timestamp coding
    issues that I noticed while looking into this.
    * doc/lispref/files.texi (File Attributes):
    * lisp/files.el (file-attribute-size)
    (file-attribute-inode-number, file-attribute-device-number):
    * src/dired.c (Fdirectory_files_and_attributes)
    (Ffile_attributes):
    Mention which attributes must be integers, or nonnegative integers,
    as opposed to merely being numbers.  Remove no-longer-correct
    talk about representing large integers as conses of integers.
    * doc/lispref/files.texi (Magic File Names):
    * doc/misc/gnus.texi (Low-level interface to the spam-stat dictionary):
    * lisp/autorevert.el (auto-revert-find-file-function)
    (auto-revert-tail-mode, auto-revert-handler):
    * lisp/auth-source.el (auth-source-netrc-parse):
    * lisp/cedet/ede/files.el (ede--inode-for-dir):
    * lisp/cedet/semantic/db-file.el (object-write):
    * lisp/cedet/semantic/db-mode.el (semanticdb-kill-hook):
    * lisp/cedet/semantic/db.el (semanticdb-needs-refresh-p)
    (semanticdb-synchronize):
    * lisp/cedet/srecode/table.el (srecode-mode-table-new):
    * lisp/desktop.el (desktop-save, desktop-read):
    * lisp/dired-aux.el (dired-file-set-difference)
    (dired-do-chxxx, dired-do-chmod, dired-copy-file-recursive)
    (dired-create-files):
    * lisp/dired.el (dired-directory-changed-p, dired-readin):
    * lisp/dos-w32.el (w32-direct-print-region-helper):
    * lisp/emacs-lisp/autoload.el (autoload-generate-file-autoloads)
    (autoload-find-destination, update-directory-autoloads):
    * lisp/emacs-lisp/shadow.el (load-path-shadows-same-file-or-nonexistent):
    * lisp/epg.el (epg--start, epg-wait-for-completion):
    * lisp/eshell/em-ls.el (eshell-ls-filetype-p)
    (eshell-ls-applicable, eshell-ls-size-string)
    (eshell-ls-file, eshell-ls-dir, eshell-ls-files)
    (eshell-ls-entries):
    * lisp/eshell/em-pred.el (eshell-predicate-alist)
    (eshell-pred-file-type, eshell-pred-file-links)
    (eshell-pred-file-size):
    * lisp/eshell/em-unix.el (eshell-shuffle-files, eshell/cat)
    (eshell-du-sum-directory, eshell/du):
    * lisp/eshell/esh-util.el (eshell-read-passwd)
    (eshell-read-hosts):
    * lisp/files.el (remote-file-name-inhibit-cache)
    (find-file-noselect, insert-file-1, dir-locals-find-file)
    (dir-locals-read-from-dir, backup-buffer)
    (file-ownership-preserved-p, copy-directory)
    (read-file-modes):
    * lisp/find-lisp.el (find-lisp-format):
    * lisp/gnus/gnus-agent.el (gnus-agent-unfetch-articles)
    (gnus-agent-read-agentview, gnus-agent-expire-group-1)
    (gnus-agent-request-article, gnus-agent-regenerate-group)
    (gnus-agent-update-files-total-fetched-for)
    (gnus-agent-update-view-total-fetched-for):
    * lisp/gnus/gnus-cache.el (gnus-cache-read-active)
    (gnus-cache-update-file-total-fetched-for)
    (gnus-cache-update-overview-total-fetched-for):
    * lisp/gnus/gnus-cloud.el (gnus-cloud-file-new-p):
    * lisp/gnus/gnus-score.el (gnus-score-score-files):
    * lisp/gnus/gnus-start.el (gnus-save-newsrc-file)
    (gnus-master-read-slave-newsrc):
    * lisp/gnus/gnus-sum.el (gnus-summary-import-article):
    * lisp/gnus/gnus-util.el (gnus-file-newer-than)
    (gnus-cache-file-contents):
    * lisp/gnus/mail-source.el (mail-source-delete-old-incoming)
    (mail-source-callback, mail-source-movemail):
    * lisp/gnus/nneething.el (nneething-create-mapping)
    (nneething-make-head):
    * lisp/gnus/nnfolder.el (nnfolder-read-folder):
    * lisp/gnus/nnheader.el (nnheader-file-size)
    (nnheader-insert-nov-file):
    * lisp/gnus/nnmail.el (nnmail-activate):
    * lisp/gnus/nnmaildir.el (nnmaildir--group-maxnum)
    (nnmaildir--new-number, nnmaildir--update-nov)
    (nnmaildir--scan, nnmaildir-request-scan)
    (nnmaildir-request-update-info)
    (nnmaildir-request-expire-articles):
    * lisp/gnus/nnmh.el (nnmh-request-list-1)
    (nnmh-request-expire-articles, nnmh-update-gnus-unreads):
    * lisp/gnus/nnml.el (nnml-request-expire-articles):
    * lisp/gnus/spam-stat.el (spam-stat-save, spam-stat-load)
    (spam-stat-process-directory, spam-stat-test-directory):
    * lisp/ido.el (ido-directory-too-big-p)
    (ido-file-name-all-completions):
    * lisp/image-dired.el (image-dired-get-thumbnail-image)
    (image-dired-create-thumb-1):
    * lisp/info.el (info-insert-file-contents):
    * lisp/ls-lisp.el (ls-lisp-insert-directory)
    (ls-lisp-handle-switches, ls-lisp-classify-file)
    (ls-lisp-format):
    * lisp/mail/blessmail.el:
    * lisp/mail/feedmail.el (feedmail-default-date-generator)
    (feedmail-default-message-id-generator):
    * lisp/mail/mailabbrev.el (mail-abbrevs-sync-aliases)
    (mail-abbrevs-setup):
    * lisp/mail/mspools.el (mspools-size-folder):
    * lisp/mail/rmail.el (rmail-insert-inbox-text):
    * lisp/mail/sendmail.el (sendmail-sync-aliases):
    * lisp/mh-e/mh-alias.el (mh-alias-tstamp):
    * lisp/net/ange-ftp.el (ange-ftp-parse-netrc)
    (ange-ftp-write-region, ange-ftp-file-newer-than-file-p)
    (ange-ftp-cf1):
    * lisp/net/eudcb-mab.el (eudc-mab-query-internal):
    * lisp/net/eww.el (eww-read-bookmarks):
    * lisp/net/netrc.el (netrc-parse):
    * lisp/net/newst-backend.el (newsticker--image-get):
    * lisp/nxml/rng-loc.el (rng-get-parsed-schema-locating-file):
    * lisp/obsolete/fast-lock.el (fast-lock-save-cache):
    * lisp/obsolete/vc-arch.el (vc-arch-state)
    (vc-arch-diff3-rej-p):
    * lisp/org/ob-eval.el (org-babel--shell-command-on-region):
    * lisp/org/org-attach.el (org-attach-commit):
    * lisp/org/org-macro.el (org-macro-initialize-templates):
    * lisp/org/org.el (org-babel-load-file)
    (org-file-newer-than-p):
    * lisp/org/ox-html.el (org-html-format-spec):
    * lisp/org/ox-publish.el (org-publish-find-date)
    (org-publish-cache-ctime-of-src):
    * lisp/pcmpl-gnu.el (pcomplete/tar):
    * lisp/pcmpl-rpm.el (pcmpl-rpm-packages):
    * lisp/play/cookie1.el (cookie-snarf):
    * lisp/progmodes/cmacexp.el (c-macro-expansion):
    * lisp/ps-bdf.el (bdf-file-mod-time):
    * lisp/server.el (server-ensure-safe-dir):
    * lisp/simple.el (shell-command-on-region):
    * lisp/speedbar.el (speedbar-item-info-file-helper)
    (speedbar-check-obj-this-line):
    * lisp/thumbs.el (thumbs-cleanup-thumbsdir):
    * lisp/time.el (display-time-mail-check-directory)
    (display-time-file-nonempty-p):
    * lisp/url/url-cache.el (url-is-cached):
    * lisp/url/url-file.el (url-file-asynch-callback):
    * lisp/vc/diff-mode.el (diff-delete-if-empty):
    * lisp/vc/pcvs-info.el (cvs-fileinfo-from-entries):
    * lisp/vc/vc-bzr.el (vc-bzr-state-heuristic):
    * lisp/vc/vc-cvs.el (vc-cvs-checkout-model)
    (vc-cvs-state-heuristic, vc-cvs-merge-news)
    (vc-cvs-retrieve-tag, vc-cvs-parse-status, vc-cvs-parse-entry):
    * lisp/vc/vc-hg.el (vc-hg--slurp-hgignore-1)
    (vc-hg--ignore-patterns-valid-p)
    (vc-hg--cached-dirstate-search, vc-hg-state-fast):
    * lisp/vc/vc-hooks.el (vc-after-save):
    * lisp/vc/vc-rcs.el (vc-rcs-workfile-is-newer):
    * lisp/vc/vc-svn.el (vc-svn-merge-news, vc-svn-parse-status):
    * lisp/vc/vc.el (vc-checkout, vc-checkin, vc-revert-file):
    * lisp/xdg.el (xdg-mime-apps):
    Prefer (file-attribute-size A) to (nth 7 A), and similarly
    for other file attributes accessors.
    * doc/lispref/files.texi (File Attributes):
    * doc/lispref/intro.texi (Version Info):
    * doc/lispref/os.texi (Idle Timers):
    * lisp/erc/erc.el (erc-string-to-emacs-time):
    * lisp/files.el (file-attribute-access-time)
    (file-attribute-modification-time)
    (file-attribute-status-change-time):
    * lisp/net/tramp-compat.el:
    (tramp-compat-file-attribute-modification-time)
    (tramp-compat-file-attribute-size):
    * src/buffer.c (syms_of_buffer):
    * src/editfns.c (Fget_internal_run_time):
    * src/fileio.c (Fvisited_file_modtime)
    (Fset_visited_file_modtime):
    * src/keyboard.c (Fcurrent_idle_time):
    * src/process.c (Fprocess_attributes):
    Defer implementation details about timestamp format to the
    section that talks about timestamp format, to make it easier
    to change the documentation later if timestamp formats are
    extended.
    * lisp/gnus/gnus-util.el (gnus-file-newer-than):
    * lisp/speedbar.el (speedbar-check-obj-this-line):
    * lisp/vc/vc-rcs.el (vc-rcs-workfile-is-newer):
    Prefer time-less-p to doing it by hand.
    * lisp/ls-lisp.el (ls-lisp-format): Inode numbers are no longer conses.
    * lisp/vc/vc-bzr.el (vc-bzr-state-heuristic):
    Use eql, not eq, to compare integers that might be bignums.
    * lisp/org/ox-publish.el (org-publish-cache-ctime-of-src):
    Prefer float-time to doing time arithmetic by hand.
---
 doc/lispref/files.texi         | 25 ++++++++-------
 doc/lispref/intro.texi         |  2 +-
 doc/lispref/os.texi            |  3 +-
 doc/misc/gnus.texi             |  4 +--
 lisp/auth-source.el            |  6 ++--
 lisp/autorevert.el             |  9 +++---
 lisp/cedet/ede/files.el        |  2 +-
 lisp/cedet/semantic/db-file.el |  4 +--
 lisp/cedet/semantic/db-mode.el |  5 +--
 lisp/cedet/semantic/db.el      |  8 ++---
 lisp/cedet/srecode/table.el    |  4 +--
 lisp/desktop.el                | 11 +++++--
 lisp/dired-aux.el              | 38 ++++++++++++----------
 lisp/dired.el                  |  7 +++--
 lisp/dos-w32.el                |  2 +-
 lisp/emacs-lisp/autoload.el    | 23 +++++++++-----
 lisp/emacs-lisp/shadow.el      |  4 +--
 lisp/epg.el                    |  8 +++--
 lisp/erc/erc.el                |  3 +-
 lisp/eshell/em-ls.el           | 38 +++++++++++-----------
 lisp/eshell/em-pred.el         | 14 ++++++---
 lisp/eshell/em-unix.el         | 49 +++++++++++++++--------------
 lisp/eshell/esh-util.el        |  4 +--
 lisp/files.el                  | 71 +++++++++++++++++++++---------------------
 lisp/find-lisp.el              | 24 +++++++-------
 lisp/gnus/gnus-agent.el        | 54 +++++++++++++++++++-------------
 lisp/gnus/gnus-cache.el        | 11 ++++---
 lisp/gnus/gnus-cloud.el        |  3 +-
 lisp/gnus/gnus-score.el        |  3 +-
 lisp/gnus/gnus-start.el        | 16 ++++++----
 lisp/gnus/gnus-sum.el          |  9 ++++--
 lisp/gnus/gnus-util.el         |  7 ++---
 lisp/gnus/mail-source.el       |  8 +++--
 lisp/gnus/nneething.el         | 21 +++++++------
 lisp/gnus/nnfolder.el          |  2 +-
 lisp/gnus/nnheader.el          |  4 +--
 lisp/gnus/nnmail.el            |  3 +-
 lisp/gnus/nnmaildir.el         | 42 ++++++++++++++-----------
 lisp/gnus/nnmh.el              | 18 ++++++-----
 lisp/gnus/nnml.el              |  3 +-
 lisp/gnus/spam-stat.el         | 21 ++++++++-----
 lisp/ido.el                    |  5 +--
 lisp/image-dired.el            | 12 ++++---
 lisp/info.el                   |  6 ++--
 lisp/ls-lisp.el                | 55 ++++++++++----------------------
 lisp/mail/blessmail.el         |  6 ++--
 lisp/mail/feedmail.el          | 20 ++++++------
 lisp/mail/mailabbrev.el        |  6 ++--
 lisp/mail/mspools.el           |  2 +-
 lisp/mail/rmail.el             |  4 +--
 lisp/mail/sendmail.el          |  3 +-
 lisp/mh-e/mh-alias.el          |  3 +-
 lisp/net/ange-ftp.el           | 21 ++++++++-----
 lisp/net/eudcb-mab.el          |  3 +-
 lisp/net/eww.el                |  2 +-
 lisp/net/netrc.el              |  6 ++--
 lisp/net/newst-backend.el      |  3 +-
 lisp/net/tramp-compat.el       |  6 ++--
 lisp/nxml/rng-loc.el           |  2 +-
 lisp/obsolete/fast-lock.el     |  3 +-
 lisp/obsolete/vc-arch.el       |  7 +++--
 lisp/org/ob-eval.el            |  2 +-
 lisp/org/org-attach.el         |  2 +-
 lisp/org/org-macro.el          |  3 +-
 lisp/org/org.el                |  9 ++++--
 lisp/org/ox-html.el            |  3 +-
 lisp/org/ox-publish.el         |  9 +++---
 lisp/pcmpl-gnu.el              |  2 +-
 lisp/pcmpl-rpm.el              |  3 +-
 lisp/play/cookie1.el           |  6 ++--
 lisp/progmodes/cmacexp.el      |  3 +-
 lisp/ps-bdf.el                 | 10 +++---
 lisp/server.el                 |  6 ++--
 lisp/simple.el                 |  5 +--
 lisp/speedbar.el               | 21 +++++++------
 lisp/thumbs.el                 |  4 ++-
 lisp/time.el                   |  6 ++--
 lisp/url/url-cache.el          | 10 +++---
 lisp/url/url-file.el           |  2 +-
 lisp/vc/diff-mode.el           |  2 +-
 lisp/vc/pcvs-info.el           |  3 +-
 lisp/vc/vc-bzr.el              | 11 ++++---
 lisp/vc/vc-cvs.el              | 15 +++++----
 lisp/vc/vc-hg.el               | 17 +++++-----
 lisp/vc/vc-hooks.el            |  2 +-
 lisp/vc/vc-rcs.el              |  9 +++---
 lisp/vc/vc-svn.el              |  6 ++--
 lisp/vc/vc.el                  |  9 ++++--
 lisp/xdg.el                    |  4 ++-
 src/buffer.c                   | 10 +++---
 src/dired.c                    | 20 +++++-------
 src/editfns.c                  |  3 +-
 src/fileio.c                   | 12 +++----
 src/keyboard.c                 |  4 +--
 src/process.c                  |  5 ++-
 95 files changed, 544 insertions(+), 462 deletions(-)

diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index c50e358..5682919 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -1299,28 +1299,27 @@ Alternate names, also known as hard links, can be 
created by using the
 @item
 The file's @acronym{UID}, normally as a string
 (@code{file-attribute-user-id}).  However, if it does not correspond
-to a named user, the value is a number.
+to a named user, the value is an integer.
 
 @item
 The file's @acronym{GID}, likewise (@code{file-attribute-group-id}).
 
 @item
-The time of last access, as a list of four integers
address@hidden(@var{sec-high} @var{sec-low} @var{microsec} @var{picosec})}
-(@code{file-attribute-access-time}).  (This is similar to the value of
address@hidden; see @ref{Time of Day}.)  The value is truncated
+The time of last access as a Lisp timestamp
+(@code{file-attribute-status-change-time}).  The timestamp is in the
+style of @code{current-time} (@pxref{Time of Day}) and is truncated
 to that of the filesystem's timestamp resolution; for example, on some
 FAT-based filesystems, only the date of last access is recorded, so
 this time will always hold the midnight of the day of the last access.
 
 @cindex modification time of file
 @item
-The time of last modification as a list of four integers (as above)
+The time of last modification as a Lisp timestamp
 (@code{file-attribute-modification-time}).  This is the last time when
 the file's contents were modified.
 
 @item
-The time of last status change as a list of four integers (as above)
+The time of last status change as a Lisp timestamp
 (@code{file-attribute-status-change-time}).  This is the time of the
 last change to the file's access mode bits, its owner and group, and
 other information recorded in the filesystem for the file, beyond the
@@ -1337,11 +1336,12 @@ The file's modes, as a string of ten letters or dashes, 
as in
 An unspecified value, present for backward compatibility.
 
 @item
-The file's inode number (@code{file-attribute-inode-number}).
+The file's inode number (@code{file-attribute-inode-number}),
+a nonnegative integer.
 
 @item
 The filesystem number of the device that the file is on
address@hidden).
address@hidden), 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
@@ -2918,7 +2918,7 @@ are included.
 This is similar to @code{directory-files} in deciding which files
 to report on and how to report their names.  However, instead
 of returning a list of file names, it returns for each file a
-list @code{(@var{filename} @var{attributes})}, where @var{attributes}
+list @code{(@var{filename} . @var{attributes})}, where @var{attributes}
 is what @code{file-attributes} returns for that file.
 The optional argument @var{id-format} has the same meaning as the
 corresponding argument to @code{file-attributes} (@pxref{Definition
@@ -3410,8 +3410,9 @@ between consecutive checks.  For example:
   (let ((remote-file-name-inhibit-cache
          (- display-time-interval 5)))
     (and (file-exists-p file)
-         (< 0 (nth 7 (file-attributes
-                       (file-chase-links file)))))))
+         (< 0 (file-attribute-size
+               (file-attributes
+                (file-chase-links file)))))))
 @end example
 @end defopt
 
diff --git a/doc/lispref/intro.texi b/doc/lispref/intro.texi
index f421f3b..197f54e 100644
--- a/doc/lispref/intro.texi
+++ b/doc/lispref/intro.texi
@@ -493,7 +493,7 @@ giving a prefix argument makes @var{here} address@hidden
 
 @defvar emacs-build-time
 The value of this variable indicates the time at which Emacs was
-built.  It is a list of four integers, like the value of
+built.  It uses the style of
 @code{current-time} (@pxref{Time of Day}), or is @code{nil}
 if the information is not available.
 
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index 43ca9ed..8481fea 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -1991,8 +1991,7 @@ the idleness time, as described below.
 
 @defun current-idle-time
 If Emacs is idle, this function returns the length of time Emacs has
-been idle, as a list of four integers: @code{(@var{sec-high}
address@hidden @var{microsec} @var{picosec})}, using the same format as
+been idle, using the same format as
 @code{current-time} (@pxref{Time of Day}).
 
 When Emacs is not idle, @code{current-idle-time} returns @code{nil}.
diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi
index 6ccb9e5..40cc44a 100644
--- a/doc/misc/gnus.texi
+++ b/doc/misc/gnus.texi
@@ -25889,13 +25889,13 @@ Reset: (setq spam-stat (make-hash-table :test 'equal))
 Learn spam: (spam-stat-process-spam-directory "~/Mail/mail/spam")
 Learn non-spam: (spam-stat-process-non-spam-directory "~/Mail/mail/misc")
 Save table: (spam-stat-save)
-File size: (nth 7 (file-attributes spam-stat-file))
+File size: (file-attribute-size (file-attributes spam-stat-file))
 Number of words: (hash-table-count spam-stat)
 Test spam: (spam-stat-test-directory "~/Mail/mail/spam")
 Test non-spam: (spam-stat-test-directory "~/Mail/mail/misc")
 Reduce table size: (spam-stat-reduce-size)
 Save table: (spam-stat-save)
-File size: (nth 7 (file-attributes spam-stat-file))
+File size: (file-attribute-size (file-attributes spam-stat-file))
 Number of words: (hash-table-count spam-stat)
 Test spam: (spam-stat-test-directory "~/Mail/mail/spam")
 Test non-spam: (spam-stat-test-directory "~/Mail/mail/misc")
diff --git a/lisp/auth-source.el b/lisp/auth-source.el
index 261e972..eb262a1 100644
--- a/lisp/auth-source.el
+++ b/lisp/auth-source.el
@@ -956,7 +956,8 @@ Note that the MAX parameter is used so we can exit the 
parse early."
 
           (if (and (functionp cached-secrets)
                    (equal cached-mtime
-                          (nth 5 (file-attributes file))))
+                          (file-attribute-modification-time
+                           (file-attributes file))))
               (progn
                 (auth-source-do-trivia
                  "auth-source-netrc-parse: using CACHED file data for %s"
@@ -968,7 +969,8 @@ Note that the MAX parameter is used so we can exit the 
parse early."
             ;; (note for the irony-impaired: they are just obfuscated)
             (auth-source--aput
              auth-source-netrc-cache file
-             (list :mtime (nth 5 (file-attributes file))
+             (list :mtime (file-attribute-modification-time
+                           (file-attributes file))
                    :secret (let ((v (mapcar #'1+ (buffer-string))))
                              (lambda () (apply #'string (mapcar #'1- v)))))))
           (goto-char (point-min))
diff --git a/lisp/autorevert.el b/lisp/autorevert.el
index c60fe01..fc3469e 100644
--- a/lisp/autorevert.el
+++ b/lisp/autorevert.el
@@ -321,7 +321,7 @@ the list of old buffers.")
 
 (defun auto-revert-find-file-function ()
   (setq-local auto-revert-tail-pos
-              (nth 7 (file-attributes buffer-file-name))))
+              (file-attribute-size (file-attributes buffer-file-name))))
 
 (add-hook 'find-file-hook
          #'auto-revert-find-file-function)
@@ -434,7 +434,8 @@ Perform a full revert? ")
       (add-hook 'before-save-hook (lambda () (auto-revert-tail-mode 0)) nil t)
       (or (local-variable-p 'auto-revert-tail-pos) ; don't lose prior position
          (setq-local auto-revert-tail-pos
-                      (nth 7 (file-attributes buffer-file-name))))
+                      (file-attribute-size
+                       (file-attributes buffer-file-name))))
       ;; let auto-revert-mode set up the mechanism for us if it isn't already
       (or auto-revert-mode
          (let ((auto-revert-tail-mode t))
@@ -656,8 +657,8 @@ This is an internal function used by Auto-Revert Mode."
                        (and (file-readable-p buffer-file-name)
                             (/= auto-revert-tail-pos
                                 (setq size
-                                      (nth 7 (file-attributes
-                                              buffer-file-name)))))
+                                      (file-attribute-size
+                                       (file-attributes buffer-file-name)))))
                      (funcall (or buffer-stale-function
                                   #'buffer-stale--default-function)
                               t)))
diff --git a/lisp/cedet/ede/files.el b/lisp/cedet/ede/files.el
index c95402e..2c47481 100644
--- a/lisp/cedet/ede/files.el
+++ b/lisp/cedet/ede/files.el
@@ -113,7 +113,7 @@ of the anchor file for the project."
        (if ede--disable-inode
            (ede--put-inode-dir-hash dir 0)
          (let ((fattr (file-attributes dir)))
-           (ede--put-inode-dir-hash dir (nth 10 fattr))
+           (ede--put-inode-dir-hash dir (file-attribute-inode-number fattr))
            )))))
 
 (cl-defmethod ede--project-inode ((proj ede-project-placeholder))
diff --git a/lisp/cedet/semantic/db-file.el b/lisp/cedet/semantic/db-file.el
index 7035939..2d55c27 100644
--- a/lisp/cedet/semantic/db-file.el
+++ b/lisp/cedet/semantic/db-file.el
@@ -307,8 +307,8 @@ Argument OBJ is the object to write."
     ;; Make sure that the file size and other attributes are
     ;; up to date.
     (let ((fattr (file-attributes (semanticdb-full-filename obj))))
-      (oset obj fsize (nth 7 fattr))
-      (oset obj lastmodtime (nth 5 fattr))
+      (oset obj fsize (file-attribute-size fattr))
+      (oset obj lastmodtime (file-attribute-modification-time fattr))
       )
 
     ;; Do it!
diff --git a/lisp/cedet/semantic/db-mode.el b/lisp/cedet/semantic/db-mode.el
index 638f291..e61eb71 100644
--- a/lisp/cedet/semantic/db-mode.el
+++ b/lisp/cedet/semantic/db-mode.el
@@ -178,8 +178,9 @@ handle it later if need be."
            (let ((fattr (file-attributes
                          (semanticdb-full-filename
                           semanticdb-current-table))))
-             (oset semanticdb-current-table fsize (nth 7 fattr))
-             (oset semanticdb-current-table lastmodtime (nth 5 fattr))
+             (oset semanticdb-current-table fsize (file-attribute-size fattr))
+             (oset semanticdb-current-table lastmodtime
+                   (file-attribute-modification-time fattr))
              (oset semanticdb-current-table buffer nil)
              ))
        ;; If this messes up, just clear the system
diff --git a/lisp/cedet/semantic/db.el b/lisp/cedet/semantic/db.el
index 491752e..05484fc 100644
--- a/lisp/cedet/semantic/db.el
+++ b/lisp/cedet/semantic/db.el
@@ -611,8 +611,8 @@ The file associated with OBJ does not need to be in a 
buffer."
       ;; Buffer isn't loaded.  The only clue we have is if the file
       ;; is somehow different from our mark in the semanticdb table.
       (let* ((stats (file-attributes ff))
-            (actualsize (nth 7 stats))
-            (actualmod (nth 5 stats))
+            (actualsize (file-attribute-size stats))
+            (actualmod (file-attribute-modification-time stats))
             )
 
        (or (not (slot-boundp obj 'tags))
@@ -631,8 +631,8 @@ The file associated with OBJ does not need to be in a 
buffer."
   (oset table tags new-tags)
   (oset table pointmax (point-max))
   (let ((fattr (file-attributes (semanticdb-full-filename table))))
-    (oset table fsize (nth 7 fattr))
-    (oset table lastmodtime (nth 5 fattr))
+    (oset table fsize (file-attribute-size fattr))
+    (oset table lastmodtime (file-attribute-modification-time fattr))
     )
   ;; Assume it is now up to date.
   (oset table unmatched-syntax semantic-unmatched-syntax-cache)
diff --git a/lisp/cedet/srecode/table.el b/lisp/cedet/srecode/table.el
index ac968a6..af2e8b1 100644
--- a/lisp/cedet/srecode/table.el
+++ b/lisp/cedet/srecode/table.el
@@ -187,8 +187,8 @@ INIT are the initialization parameters for the new template 
table."
         (new (apply 'srecode-template-table
                     (file-name-nondirectory file)
                     :file file
-                    :filesize (nth 7 attr)
-                    :filedate (nth 5 attr)
+                    :filesize (file-attribute-size attr)
+                    :filedate (file-attribute-modification-time attr)
                     :major-mode mode
                     init
                     )))
diff --git a/lisp/desktop.el b/lisp/desktop.el
index a9fa287..1346fa3 100644
--- a/lisp/desktop.el
+++ b/lisp/desktop.el
@@ -1031,7 +1031,8 @@ without further confirmation."
   (setq desktop-dirname (file-name-as-directory (expand-file-name dirname)))
   (save-excursion
     (let ((eager desktop-restore-eager)
-         (new-modtime (nth 5 (file-attributes (desktop-full-file-name)))))
+         (new-modtime (file-attribute-modification-time
+                       (file-attributes (desktop-full-file-name)))))
       (when
          (or (not new-modtime)         ; nothing to overwrite
              (equal desktop-file-modtime new-modtime)
@@ -1134,7 +1135,9 @@ without further confirmation."
                (write-region (point-min) (point-max) (desktop-full-file-name) 
nil 'nomessage))
              (setq desktop-file-checksum checksum)
              ;; We remember when it was modified (which is presumably just 
now).
-             (setq desktop-file-modtime (nth 5 (file-attributes 
(desktop-full-file-name)))))))))))
+             (setq desktop-file-modtime (file-attribute-modification-time
+                                         (file-attributes
+                                          (desktop-full-file-name)))))))))))
 
 ;; ----------------------------------------------------------------------------
 ;;;###autoload
@@ -1238,7 +1241,9 @@ Using it may cause conflicts.  Use it anyway? " owner)))))
                           'window-configuration-change-hook)))
            (desktop-auto-save-disable)
            ;; Evaluate desktop buffer and remember when it was modified.
-           (setq desktop-file-modtime (nth 5 (file-attributes 
(desktop-full-file-name))))
+           (setq desktop-file-modtime (file-attribute-modification-time
+                                       (file-attributes
+                                        (desktop-full-file-name))))
            (load (desktop-full-file-name) t t t)
            ;; If it wasn't already, mark it as in-use, to bother other
            ;; desktop instances.
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index ce2ed13..1f13204 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -200,9 +200,12 @@ Examples of PREDICATE:
 
     (> mtime1 mtime2) - mark newer files
     (not (= size1 size2)) - mark files with different sizes
-    (not (string= (nth 8 fa1) (nth 8 fa2))) - mark files with different modes
-    (not (and (= (nth 2 fa1) (nth 2 fa2))   - mark files with different UID
-              (= (nth 3 fa1) (nth 3 fa2))))   and GID."
+    (not (string= (file-attribute-modes fa1)  - mark files with different modes
+                  (file-attribute-modes fa2)))
+    (not (and (= (file-attribute-user-id fa1) - mark files with different UID
+                 (file-attribute-user-id fa2))
+              (= (file-attribute-group-id fa1) - and GID.
+                 (file-attribute-group-id fa2))))"
   (interactive
    (list
     (let* ((target-dir (dired-dwim-target-directory))
@@ -269,12 +272,12 @@ condition.  Two file items are considered to match if 
they are equal
                                  (eval predicate
                                        `((fa1 . ,fa1)
                                          (fa2 . ,fa2)
-                                         (size1 . ,(nth 7 fa1))
-                                         (size2 . ,(nth 7 fa2))
+                                         (size1 . ,(file-attribute-size fa1))
+                                         (size2 . ,(file-attribute-size fa2))
                                          (mtime1
-                                          . ,(float-time (nth 5 fa1)))
+                                          . ,(float-time 
(file-attribute-modification-time fa1)))
                                          (mtime2
-                                          . ,(float-time (nth 5 fa2)))
+                                          . ,(float-time 
(file-attribute-modification-time fa2)))
                                          )))))
                    (setq list (cdr list)))
                  list)
@@ -308,11 +311,14 @@ List has a form of (file-name full-file-name 
(attribute-list))."
                    (cond ((eq op-symbol 'touch)
                           (format-time-string
                            "%Y%m%d%H%M.%S"
-                           (nth 5 (file-attributes default-file))))
+                           (file-attribute-modification-time
+                            (file-attributes default-file))))
                          ((eq op-symbol 'chown)
-                          (nth 2 (file-attributes default-file 'string)))
+                          (file-attribute-user-id
+                           (file-attributes default-file 'string)))
                          ((eq op-symbol 'chgrp)
-                          (nth 3 (file-attributes default-file 'string))))))
+                          (file-attribute-group-id
+                           (file-attributes default-file 'string))))))
         (prompt (concat "Change " attribute-name " of %s to"
                         (if (eq op-symbol 'touch)
                             " (default now): "
@@ -365,7 +371,7 @@ into the minibuffer."
         ;; The source of default file attributes is the file at point.
         (default-file (dired-get-filename t t))
         (modestr (when default-file
-                   (nth 8 (file-attributes default-file))))
+                   (file-attribute-modes (file-attributes default-file))))
         (default
           (and (stringp modestr)
                (string-match "^.\\(...\\)\\(...\\)\\(...\\)$" modestr)
@@ -1571,20 +1577,20 @@ If `ask', ask for user confirmation."
 
 (defun dired-copy-file-recursive (from to ok-flag &optional
                                       preserve-time top recursive)
-  (when (and (eq t (car (file-attributes from)))
+  (when (and (eq t (file-attribute-type (file-attributes from)))
             (file-in-directory-p to from))
     (error "Cannot copy `%s' into its subdirectory `%s'" from to))
   (let ((attrs (file-attributes from)))
     (if (and recursive
-            (eq t (car attrs))
+            (eq t (file-attribute-type attrs))
             (or (eq recursive 'always)
                 (yes-or-no-p (format "Recursive copies of %s? " from))))
        (copy-directory from to preserve-time)
       (or top (dired-handle-overwrite to))
       (condition-case err
-         (if (stringp (car attrs))
+         (if (stringp (file-attribute-type attrs))
              ;; It is a symlink
-             (make-symbolic-link (car attrs) to ok-flag)
+             (make-symbolic-link (file-attribute-type attrs) to ok-flag)
             (dired-maybe-create-dirs (file-name-directory to))
            (copy-file from to ok-flag preserve-time))
        (file-date-error
@@ -1765,7 +1771,7 @@ ESC or `q' to not overwrite any of the remaining files,
                 (setq to destname))
              ;; If DESTNAME is a subdirectory of FROM, not a symlink,
              ;; and the method in use is copying, signal an error.
-             (and (eq t (car (file-attributes destname)))
+             (and (eq t (file-attribute-type (file-attributes destname)))
                   (eq file-creator 'dired-copy-file)
                   (file-in-directory-p destname from)
                   (error "Cannot copy `%s' into its subdirectory `%s'"
diff --git a/lisp/dired.el b/lisp/dired.el
index 0ed1a4f..5c7bb95 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -850,8 +850,8 @@ If DIRNAME is already in a Dired buffer, that buffer is 
used without refresh."
   (not (let ((attributes (file-attributes dirname))
             (modtime (visited-file-modtime)))
         (or (eq modtime 0)
-            (not (eq (car attributes) t))
-            (equal (nth 5 attributes) modtime)))))
+            (not (eq (file-attribute-type attributes) t))
+            (equal (file-attribute-modification-time attributes) modtime)))))
 
 (defvar auto-revert-remote-files)
 
@@ -1092,7 +1092,8 @@ wildcards, erases the buffer, and builds the subdir-alist 
anew
       (dired-build-subdir-alist)
       (let ((attributes (file-attributes dirname)))
        (if (eq (car attributes) t)
-           (set-visited-file-modtime (nth 5 attributes))))
+           (set-visited-file-modtime (file-attribute-modification-time
+                                       attributes))))
       (set-buffer-modified-p nil)
       ;; No need to narrow since the whole buffer contains just
       ;; dired-readin's output, nothing else.  The hook can
diff --git a/lisp/dos-w32.el b/lisp/dos-w32.el
index a45a9d1..c19aa44 100644
--- a/lisp/dos-w32.el
+++ b/lisp/dos-w32.el
@@ -342,7 +342,7 @@ filesystem mounted on drive Z:, FILESYSTEM could be \"Z:\"."
               w32-direct-print-region-use-command-dot-com
               ;; file-attributes fails on LPT ports on Windows 9x but
               ;; not on NT, so handle both cases for safety.
-              (eq (or (nth 7 (file-attributes printer)) 0) 0))
+              (eq (or (file-attribute-size (file-attributes printer)) 0) 0))
          (write-region start end tempfile nil 0)
          (let ((w32-quote-process-args nil))
            (call-process "command.com" nil errbuf nil "/c"
diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el
index efeb056..3d73351 100644
--- a/lisp/emacs-lisp/autoload.el
+++ b/lisp/emacs-lisp/autoload.el
@@ -813,7 +813,8 @@ FILE's modification time."
                          (marker-buffer other-output-start)
                          "actual autoloads are elsewhere" load-name relfile
                         (if autoload-timestamps
-                            (nth 5 (file-attributes absfile))
+                            (file-attribute-modification-time
+                             (file-attributes absfile))
                           autoload--non-timestamp))
                         (insert ";;; Generated autoloads from " relfile "\n")))
                     (insert generate-autoload-section-trailer)))))))
@@ -849,7 +850,8 @@ FILE's modification time."
                                       ;; `emacs-internal' instead.
                                       nil nil 'emacs-mule-unix)
                                (if autoload-timestamps
-                                   (nth 5 (file-attributes relfile))
+                                   (file-attribute-modification-time
+                                   (file-attributes relfile))
                                  autoload--non-timestamp)))
                             (insert ";;; Generated autoloads from " relfile 
"\n")))
                         (insert generate-autoload-section-trailer))))
@@ -862,7 +864,7 @@ FILE's modification time."
                   ;; If the entries were added to some other buffer, then the 
file
                   ;; doesn't add entries to OUTFILE.
                   otherbuf))
-          (nth 5 (file-attributes absfile))))
+          (file-attribute-modification-time (file-attributes absfile))))
     (error
      ;; Probably unbalanced parens in forward-sexp. In that case, the
      ;; condition is scan-error, and the signal data includes point
@@ -943,7 +945,8 @@ removes any prior now out-of-date autoload entries."
            (existing-buffer (if buffer-file-name buf))
            (output-file (autoload-generated-file))
            (output-time (if (file-exists-p output-file)
-                            (nth 5 (file-attributes output-file))))
+                            (file-attribute-modification-time
+                            (file-attributes output-file))))
            (found nil))
       (with-current-buffer (autoload-find-generated-file)
         ;; This is to make generated-autoload-file have Unix EOLs, so
@@ -965,7 +968,8 @@ removes any prior now out-of-date autoload entries."
                    ;; Check if it is up to date.
                    (let ((begin (match-beginning 0))
                          (last-time (nth 4 form))
-                         (file-time (nth 5 (file-attributes file))))
+                         (file-time (file-attribute-modification-time
+                                    (file-attributes file))))
                      (if (and (or (null existing-buffer)
                                   (not (buffer-modified-p existing-buffer)))
                               (cond
@@ -1058,7 +1062,8 @@ write its autoloads into the specified file instead."
            generated-autoload-file))
         (output-time
          (if (file-exists-p generated-autoload-file)
-             (nth 5 (file-attributes generated-autoload-file)))))
+             (file-attribute-modification-time
+              (file-attributes generated-autoload-file)))))
 
     (with-current-buffer (autoload-find-generated-file)
       (save-excursion
@@ -1079,7 +1084,8 @@ write its autoloads into the specified file instead."
                   (if (member last-time (list t autoload--non-timestamp))
                       (setq last-time output-time))
                   (dolist (file file)
-                    (let ((file-time (nth 5 (file-attributes file))))
+                    (let ((file-time (file-attribute-modification-time
+                                      (file-attributes file))))
                       (when (and file-time
                                  (not (time-less-p last-time file-time)))
                         ;; file unchanged
@@ -1098,7 +1104,8 @@ write its autoloads into the specified file instead."
                                                    t autoload--non-timestamp))
                                           output-time
                                         oldtime))
-                                     (nth 5 (file-attributes file))))
+                                     (file-attribute-modification-time
+                                     (file-attributes file))))
                   ;; File hasn't changed.
                   nil)
                  (t
diff --git a/lisp/emacs-lisp/shadow.el b/lisp/emacs-lisp/shadow.el
index 2e53382..260ac36 100644
--- a/lisp/emacs-lisp/shadow.el
+++ b/lisp/emacs-lisp/shadow.el
@@ -161,8 +161,8 @@ See the documentation for `list-load-path-shadows' for 
further information."
             (or (equal (file-truename f1) (file-truename f2))
                 ;; As a quick test, avoiding spawning a process, compare file
                 ;; sizes.
-                (and (= (nth 7 (file-attributes f1))
-                        (nth 7 (file-attributes f2)))
+                (and (= (file-attribute-size (file-attributes f1))
+                        (file-attribute-size (file-attributes f2)))
                      (eq 0 (call-process "cmp" nil nil nil "-s" f1 f2))))))))
 
 (defvar load-path-shadows-font-lock-keywords
diff --git a/lisp/epg.el b/lisp/epg.el
index f79f204..8f26cd3 100644
--- a/lisp/epg.el
+++ b/lisp/epg.el
@@ -608,7 +608,9 @@ callback data (if any)."
     ;; for more details.
     (when (and agent-info (string-match "\\(.*\\):[0-9]+:[0-9]+" agent-info))
       (setq agent-file (match-string 1 agent-info)
-           agent-mtime (or (nth 5 (file-attributes agent-file)) '(0 0 0 0))))
+           agent-mtime (or (file-attribute-modification-time
+                            (file-attributes agent-file))
+                           '(0 0 0 0))))
     (if epg-debug
        (save-excursion
          (unless epg-debug-buffer
@@ -735,7 +737,9 @@ callback data (if any)."
   (if (with-current-buffer (process-buffer (epg-context-process context))
        (and epg-agent-file
             (time-less-p epg-agent-mtime
-                         (or (nth 5 (file-attributes epg-agent-file)) 0))))
+                         (or (file-attribute-modification-time
+                              (file-attributes epg-agent-file))
+                             0))))
       (redraw-frame))
   (epg-context-set-result-for
    context 'error
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index fc51009..a7e2742 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -6040,8 +6040,7 @@ non-nil value is found.
 ;; time routines
 
 (defun erc-string-to-emacs-time (string)
-  "Convert the long number represented by STRING into an Emacs format.
-Returns a list of the form (HIGH LOW), compatible with Emacs time format."
+  "Convert the long number represented by STRING into an Emacs timestamp."
   (let* ((n (string-to-number (concat string ".0"))))
     (list (truncate (/ n 65536))
           (truncate (mod n 65536)))))
diff --git a/lisp/eshell/em-ls.el b/lisp/eshell/em-ls.el
index 2b568a9..53de7f7 100644
--- a/lisp/eshell/em-ls.el
+++ b/lisp/eshell/em-ls.el
@@ -183,9 +183,9 @@ really need to stick around for very long."
   "The face used for highlighting junk file names.")
 
 (defsubst eshell-ls-filetype-p (attrs type)
-  "Test whether ATTRS specifies a directory."
-  (if (nth 8 attrs)
-      (eq (aref (nth 8 attrs) 0) type)))
+  "Test whether ATTRS specifies a file of type TYPE."
+  (if (file-attribute-modes attrs)
+      (eq (aref (file-attribute-modes attrs) 0) type)))
 
 (defmacro eshell-ls-applicable (attrs index func file)
   "Test whether, for ATTRS, the user can do what corresponds to INDEX.
@@ -193,8 +193,8 @@ ATTRS is a string of file modes.  See `file-attributes'.
 If we cannot determine the answer using ATTRS (e.g., if we need
 to know what group the user is in), compute the return value by
 calling FUNC with FILE as an argument."
-  `(let ((owner (nth 2 ,attrs))
-        (modes (nth 8 ,attrs)))
+  `(let ((owner (file-attribute-user-id ,attrs))
+        (modes (file-attribute-modes ,attrs)))
      (cond ((cond ((numberp owner)
                   (= owner (user-uid)))
                  ((stringp owner)
@@ -437,7 +437,7 @@ Sort entries alphabetically across.")
 
 (defsubst eshell-ls-size-string (attrs size-width)
   "Return the size string for ATTRS length, using SIZE-WIDTH."
-  (let* ((str (eshell-ls-printable-size (nth 7 attrs) t))
+  (let* ((str (eshell-ls-printable-size (file-attribute-size attrs) t))
         (len (length str)))
     (if (< len size-width)
        (concat (make-string (- size-width len) ? ) str)
@@ -503,19 +503,19 @@ whose cdr is the list of file attributes."
                 (if numeric-uid-gid
                     "%s%4d %-8s %-8s "
                   "%s%4d %-14s %-8s ")
-                (or (nth 8 attrs) "??????????")
-                (or (nth 1 attrs) 0)
-                (or (let ((user (nth 2 attrs)))
+                (or (file-attribute-modes attrs) "??????????")
+                (or (file-attribute-link-number attrs) 0)
+                (or (let ((user (file-attribute-user-id attrs)))
                       (and (stringp user)
                            (eshell-substring user 14)))
-                    (nth 2 attrs)
+                    (file-attribute-user-id attrs)
                     "")
-                (or (let ((group (nth 3 attrs)))
+                (or (let ((group (file-attribute-group-id attrs)))
                       (and (stringp group)
                            (eshell-substring group 8)))
-                    (nth 3 attrs)
+                    (file-attribute-group-id attrs)
                     ""))
-               (let* ((str (eshell-ls-printable-size (nth 7 attrs)))
+               (let* ((str (eshell-ls-printable-size (file-attribute-size 
attrs)))
                       (len (length str)))
                  ;; Let file sizes shorter than 9 align neatly.
                  (if (< len (or size-width 8))
@@ -585,12 +585,12 @@ relative to that directory."
            (let ((total 0.0))
              (setq size-width 0)
              (dolist (e entries)
-               (if (nth 7 (cdr e))
-                   (setq total (+ total (nth 7 (cdr e)))
+               (if (file-attribute-size (cdr e))
+                   (setq total (+ total (file-attribute-size (cdr e)))
                          size-width
                          (max size-width
                               (length (eshell-ls-printable-size
-                                       (nth 7 (cdr e))
+                                       (file-attribute-size (cdr e))
                                        (not
                                         ;; If we are under -l, count length
                                         ;; of sizes in bytes, not in blocks.
@@ -700,7 +700,7 @@ Each member of FILES is either a string or a cons cell of 
the form
       (if (not show-size)
          (setq display-files (mapcar 'eshell-ls-annotate files))
        (dolist (file files)
-         (let* ((str (eshell-ls-printable-size (nth 7 (cdr file)) t))
+         (let* ((str (eshell-ls-printable-size (file-attribute-size (cdr 
file)) t))
                 (len (length str)))
            (if (< len size-width)
                (setq str (concat (make-string (- size-width len) ? ) str)))
@@ -766,14 +766,14 @@ need to be printed."
                    (if show-size
                        (max size-width
                             (length (eshell-ls-printable-size
-                                     (nth 7 (cdr entry)) t))))))
+                                     (file-attribute-size (cdr entry)) t))))))
            (setq dirs (cons entry dirs)))
        (setq files (cons entry files)
              size-width
              (if show-size
                  (max size-width
                       (length (eshell-ls-printable-size
-                               (nth 7 (cdr entry)) t)))))))
+                               (file-attribute-size (cdr entry)) t)))))))
     (when files
       (eshell-ls-files (eshell-ls-sort-entries files)
                       size-width show-recursive)
diff --git a/lisp/eshell/em-pred.el b/lisp/eshell/em-pred.el
index b3b16d9..c3b942d 100644
--- a/lisp/eshell/em-pred.el
+++ b/lisp/eshell/em-pred.el
@@ -89,10 +89,12 @@ ordinary strings."
     (?t . (eshell-pred-file-mode 1000)) ; sticky bit
     (?U . #'(lambda (file)                   ; owned by effective uid
               (if (file-exists-p file)
-                  (= (nth 2 (file-attributes file)) (user-uid)))))
+                  (= (file-attribute-user-id (file-attributes file))
+                    (user-uid)))))
     ;; (?G . #'(lambda (file)               ; owned by effective gid
     ;;          (if (file-exists-p file)
-    ;;              (= (nth 2 (file-attributes file)) (user-uid)))))
+    ;;              (= (file-attribute-user-id (file-attributes file))
+    ;;                 (user-uid)))))
     (?* . #'(lambda (file)
               (and (file-regular-p file)
                    (not (file-symlink-p file))
@@ -460,7 +462,7 @@ that `ls -l' will show in the first column of its display. "
   `(lambda (file)
      (let ((attrs (eshell-file-attributes (directory-file-name file))))
        (if attrs
-          (memq (aref (nth 8 attrs) 0)
+          (memq (aref (file-attribute-modes attrs) 0)
                 ,(if (eq type ?%)
                      '(?b ?c)
                    (list 'quote (list type))))))))
@@ -489,7 +491,8 @@ that `ls -l' will show in the first column of its display. "
                   '<
                 (if (eq qual ?+)
                     '>
-                  '=)) (nth 1 attrs) ,amount))))))
+                  '=))
+             (file-attribute-link-number attrs) ,amount))))))
 
 (defun eshell-pred-file-size ()
   "Return a predicate to test whether a file is of a given size."
@@ -518,7 +521,8 @@ that `ls -l' will show in the first column of its display. "
                   '<
                 (if (eq qual ?+)
                     '>
-                  '=)) (nth 7 attrs) ,amount))))))
+                  '=))
+             (file-attribute-size attrs) ,amount))))))
 
 (defun eshell-pred-substitute (&optional repeat)
   "Return a modifier function that will substitute matches."
diff --git a/lisp/eshell/em-unix.el b/lisp/eshell/em-unix.el
index 9a99c53..3aecebc 100644
--- a/lisp/eshell/em-unix.el
+++ b/lisp/eshell/em-unix.el
@@ -370,12 +370,14 @@ Remove the DIRECTORY(ies), if they are empty.")
             (or (not (eshell-under-windows-p))
                 (eq system-type 'ms-dos))
             (setq attr (eshell-file-attributes (car files)))
-            (nth 10 attr-target) (nth 10 attr)
-            ;; Use equal, not -, since the inode and the device could
-            ;; cons cells.
-            (equal (nth 10 attr-target) (nth 10 attr))
-            (nth 11 attr-target) (nth 11 attr)
-            (equal (nth 11 attr-target) (nth 11 attr)))
+            (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)))
        (eshell-error (format-message "%s: `%s' and `%s' are the same file\n"
                                      command (car files) target)))
        (t
@@ -397,16 +399,16 @@ Remove the DIRECTORY(ies), if they are empty.")
                (let (eshell-warn-dot-directories)
                  (if (and (not deep)
                           (eq func 'rename-file)
-                          ;; Use equal, since the device might be a
-                          ;; cons cell.
-                          (equal (nth 11 (eshell-file-attributes
-                                          (file-name-directory
-                                           (directory-file-name
-                                            (expand-file-name source)))))
-                                 (nth 11 (eshell-file-attributes
-                                          (file-name-directory
-                                           (directory-file-name
-                                            (expand-file-name target)))))))
+                          (equal (file-attribute-device-number
+                                  (eshell-file-attributes
+                                   (file-name-directory
+                                    (directory-file-name
+                                     (expand-file-name source)))))
+                                 (file-attribute-device-number
+                                  (eshell-file-attributes
+                                   (file-name-directory
+                                    (directory-file-name
+                                     (expand-file-name target)))))))
                      (apply 'eshell-funcalln func source target args)
                  (unless (file-directory-p target)
                    (if em-verbose
@@ -612,7 +614,8 @@ symlink, then revert to the system's definition of cat."
                               (> (length arg) 0)
                               (eq (aref arg 0) ?-))
                          (let ((attrs (eshell-file-attributes arg)))
-                           (and attrs (memq (aref (nth 8 attrs) 0)
+                           (and attrs
+                                (memq (aref (file-attribute-modes attrs) 0)
                                             '(?d ?l ?-)))))
                (throw 'special t)))))
       (let ((ext-cat (eshell-search-path "cat")))
@@ -843,19 +846,19 @@ external command."
       (unless (string-match "\\`\\.\\.?\\'" (caar entries))
        (let* ((entry (concat path "/"
                              (caar entries)))
-              (symlink (and (stringp (cadr (car entries)))
-                            (cadr (car entries)))))
+              (symlink (and (stringp (file-attribute-type (cdar entries)))
+                            (file-attribute-type (cdar entries)))))
          (unless (or (and symlink (not dereference-links))
                      (and only-one-filesystem
                           (/= only-one-filesystem
-                              (nth 12 (car entries)))))
+                              (file-attribute-device-number (cdar entries)))))
            (if symlink
                (setq entry symlink))
            (setq size
                  (+ size
-                    (if (eq t (cadr (car entries)))
+                    (if (eq t (car (cdar entries)))
                         (eshell-du-sum-directory entry (1+ depth))
-                      (let ((file-size (nth 8 (car entries))))
+                      (let ((file-size (file-attribute-size (cdar entries))))
                         (prog1
                             file-size
                           (if show-all
@@ -926,7 +929,7 @@ Summarize disk usage of each FILE, recursively for 
directories.")
         (while args
           (if only-one-filesystem
               (setq only-one-filesystem
-                    (nth 11 (eshell-file-attributes
+                    (file-attribute-device-number (eshell-file-attributes
                              (file-name-as-directory (car args))))))
           (setq size (+ size (eshell-du-sum-directory
                               (directory-file-name (car args)) 0)))
diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el
index 5ef1ae4..8fe8c46 100644
--- a/lisp/eshell/esh-util.el
+++ b/lisp/eshell/esh-util.el
@@ -447,7 +447,7 @@ list."
          (not (symbol-value timestamp-var))
          (time-less-p
           (symbol-value timestamp-var)
-          (nth 5 (file-attributes file))))
+          (file-attribute-modification-time (file-attributes file))))
       (progn
        (set result-var (eshell-read-passwd-file file))
        (set timestamp-var (current-time))))
@@ -501,7 +501,7 @@ list."
          (not (symbol-value timestamp-var))
          (time-less-p
           (symbol-value timestamp-var)
-          (nth 5 (file-attributes file))))
+          (file-attribute-modification-time (file-attributes file))))
       (progn
        (set result-var (eshell-read-hosts-file file))
        (set timestamp-var (current-time))))
diff --git a/lisp/files.el b/lisp/files.el
index da4f2cd..7efbf05 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -1152,7 +1152,8 @@ consecutive checks.  For example:
   (defun display-time-file-nonempty-p (file)
     (let ((remote-file-name-inhibit-cache (- display-time-interval 5)))
       (and (file-exists-p file)
-           (< 0 (nth 7 (file-attributes (file-chase-links file)))))))"
+           (< 0 (file-attribute-size
+                 (file-attributes (file-chase-links file)))))))"
   :group 'files
   :version "24.1"
   :type `(choice
@@ -2155,10 +2156,10 @@ the various files."
        ;; Check to see if the file looks uncommonly large.
        (when (not (or buf nowarn))
           (when (eq (abort-if-file-too-large
-                     (nth 7 attributes) "open" filename t)
+                     (file-attribute-size attributes) "open" filename t)
                     'raw)
             (setf rawfile t))
-         (warn-maybe-out-of-memory (nth 7 attributes)))
+         (warn-maybe-out-of-memory (file-attribute-size attributes)))
        (if buf
            ;; We are using an existing buffer.
            (let (nonexistent)
@@ -2372,7 +2373,8 @@ This function ensures that none of these modifications 
will take place."
       (signal 'file-error (list "Opening input file" "Is a directory"
                                 filename)))
   ;; Check whether the file is uncommonly large
-  (abort-if-file-too-large (nth 7 (file-attributes filename)) "insert" 
filename)
+  (abort-if-file-too-large (file-attribute-size (file-attributes filename))
+                          "insert" filename)
   (let* ((buffer (find-buffer-visiting (abbreviate-file-name (file-truename 
filename))
                                        #'buffer-modified-p))
          (tem (funcall insert-func filename)))
@@ -3856,8 +3858,8 @@ Each element in this list has the form (DIR CLASS MTIME).
 DIR is the name of the directory.
 CLASS is the name of a variable class (a symbol).
 MTIME is the recorded modification time of the directory-local
-variables file associated with this entry.  This time is a list
-of integers (the same format as `file-attributes'), and is
+variables file associated with this entry.  This time is a Lisp
+timestamp (the same format as `current-time'), and is
 used to test whether the cache entry is still valid.
 Alternatively, MTIME can be nil, which means the entry is always
 considered valid.")
@@ -4061,7 +4063,9 @@ This function returns either:
                       (equal (nth 2 dir-elt)
                              (let ((latest 0))
                                (dolist (f cached-files latest)
-                                 (let ((f-time (nth 5 (file-attributes f))))
+                                 (let ((f-time
+                                        (file-attribute-modification-time
+                                         (file-attributes f))))
                                    (if (time-less-p latest f-time)
                                        (setq latest f-time)))))))))
             ;; This cache entry is OK.
@@ -4093,7 +4097,8 @@ Return the new class name, which is a symbol named DIR."
          (variables))
     (with-demoted-errors "Error reading dir-locals: %S"
       (dolist (file files)
-       (let ((file-time (nth 5 (file-attributes file))))
+       (let ((file-time (file-attribute-modification-time
+                         (file-attributes file))))
          (if (time-less-p latest file-time)
            (setq latest file-time)))
         (with-temp-buffer
@@ -4445,7 +4450,7 @@ BACKUPNAME is the backup file name, which is the old file 
renamed."
                                      (let ((attr (file-attributes
                                                   real-file-name
                                                   'integer)))
-                                       (<= (nth 2 attr)
+                                       (<= (file-attribute-user-id attr)
                                            copy-when-priv-mismatch))))
                             (not (file-ownership-preserved-p real-file-name
                                                              t)))))
@@ -4537,32 +4542,36 @@ the group would be preserved too."
        ;; Return t if the file doesn't exist, since it's true that no
        ;; information would be lost by an (attempted) delete and create.
        (or (null attributes)
-           (and (or (= (nth 2 attributes) (user-uid))
+           (and (or (= (file-attribute-user-id attributes) (user-uid))
                     ;; Files created on Windows by Administrator (RID=500)
                     ;; have the Administrators group (RID=544) recorded as
                     ;; their owner.  Rewriting them will still preserve the
                     ;; owner.
                     (and (eq system-type 'windows-nt)
-                         (= (user-uid) 500) (= (nth 2 attributes) 544)))
+                         (= (user-uid) 500)
+                         (= (file-attribute-user-id attributes) 544)))
                 (or (not group)
                     ;; On BSD-derived systems files always inherit the parent
                     ;; directory's group, so skip the group-gid test.
                     (memq system-type '(berkeley-unix darwin gnu/kfreebsd))
-                    (= (nth 3 attributes) (group-gid)))
+                    (= (file-attribute-group-id attributes) (group-gid)))
                 (let* ((parent (or (file-name-directory file) "."))
                        (parent-attributes (file-attributes parent 'integer)))
                   (and parent-attributes
                        ;; On some systems, a file created in a setuid directory
                        ;; inherits that directory's owner.
                        (or
-                        (= (nth 2 parent-attributes) (user-uid))
-                        (string-match "^...[^sS]" (nth 8 parent-attributes)))
+                        (= (file-attribute-user-id parent-attributes)
+                           (user-uid))
+                        (string-match
+                         "^...[^sS]"
+                         (file-attribute-modes parent-attributes)))
                        ;; On many systems, a file created in a setgid directory
                        ;; inherits that directory's group.  On some systems
                        ;; this happens even if the setgid bit is not set.
                        (or (not group)
-                           (= (nth 3 parent-attributes)
-                              (nth 3 attributes)))))))))))
+                           (= (file-attribute-group-id parent-attributes)
+                              (file-attribute-group-id attributes)))))))))))
 
 (defun file-name-sans-extension (filename)
   "Return FILENAME sans final \"extension\".
@@ -5722,7 +5731,8 @@ into NEWNAME instead."
 
       ;; Set directory attributes.
       (let ((modes (file-modes directory))
-           (times (and keep-time (nth 5 (file-attributes directory)))))
+           (times (and keep-time (file-attribute-modification-time
+                                  (file-attributes directory)))))
        (if modes (set-file-modes newname modes))
        (if times (set-file-times newname times))))))
 
@@ -7328,7 +7338,7 @@ based on existing mode bits, as in \"og+rX-w\"."
   (let* ((modes (or (if orig-file (file-modes orig-file) 0)
                    (error "File not found")))
         (modestr (and (stringp orig-file)
-                      (nth 8 (file-attributes orig-file))))
+                      (file-attribute-modes (file-attributes orig-file))))
         (default
           (and (stringp modestr)
                (string-match "^.\\(...\\)\\(...\\)\\(...\\)$" modestr)
@@ -7508,27 +7518,24 @@ returned."
 
 (defsubst file-attribute-access-time (attributes)
   "The last access time in ATTRIBUTES returned by `file-attributes'.
-This a list of integers (HIGH LOW USEC PSEC) in the same style
-as (current-time)."
+This a Lisp timestamp in the style of `current-time'."
   (nth 4 attributes))
 
 (defsubst file-attribute-modification-time (attributes)
   "The modification time in ATTRIBUTES returned by `file-attributes'.
 This is the time of the last change to the file's contents, and
-is a list of integers (HIGH LOW USEC PSEC) in the same style
-as (current-time)."
+is a Lisp timestamp in the style of `current-time'."
   (nth 5 attributes))
 
 (defsubst file-attribute-status-change-time (attributes)
   "The status modification time in ATTRIBUTES returned by `file-attributes'.
 This is the time of last change to the file's attributes: owner
-and group, access mode bits, etc, and is a list of integers (HIGH
-LOW USEC PSEC) in the same style as (current-time)."
+and group, access mode bits, etc., and is a Lisp timestamp in the
+style of `current-time'."
   (nth 6 attributes))
 
 (defsubst file-attribute-size (attributes)
-  "The size (in bytes) in ATTRIBUTES returned by `file-attributes'.
-This is a floating point number if the size is too large for an integer."
+  "The integer size (in bytes) in ATTRIBUTES returned by `file-attributes'."
   (nth 7 attributes))
 
 (defsubst file-attribute-modes (attributes)
@@ -7538,20 +7545,12 @@ This is a string of ten letters or dashes as in ls -l."
 
 (defsubst file-attribute-inode-number (attributes)
   "The inode number in ATTRIBUTES returned by `file-attributes'.
-If it is larger than what an Emacs integer can hold, this is of
-the form (HIGH . LOW): first the high bits, then the low 16 bits.
-If even HIGH is too large for an Emacs integer, this is instead
-of the form (HIGH MIDDLE . LOW): first the high bits, then the
-middle 24 bits, and finally the low 16 bits."
+It is a nonnegative integer."
   (nth 10 attributes))
 
 (defsubst file-attribute-device-number (attributes)
   "The file system device number in ATTRIBUTES returned by `file-attributes'.
-If it is larger than what an Emacs integer can hold, this is of
-the form (HIGH . LOW): first the high bits, then the low 16 bits.
-If even HIGH is too large for an Emacs integer, this is instead
-of the form (HIGH MIDDLE . LOW): first the high bits, then the
-middle 24 bits, and finally the low 16 bits."
+It is an integer."
   (nth 11 attributes))
 
 (defun file-attribute-collect (attributes &rest attr-names)
diff --git a/lisp/find-lisp.el b/lisp/find-lisp.el
index 0070e59..a3e4511 100644
--- a/lisp/find-lisp.el
+++ b/lisp/find-lisp.el
@@ -300,24 +300,24 @@ It is a function which takes two arguments, the directory 
and its parent."
   "Format one line of long ls output for file FILE-NAME.
 FILE-ATTR and FILE-SIZE give the file's attributes and size.
 SWITCHES and TIME-INDEX give the full switch list and time data."
-  (let ((file-type (nth 0 file-attr)))
+  (let ((file-type (file-attribute-type file-attr)))
     (concat (if (memq ?i switches)     ; inode number
-               (format "%6d " (nth 10 file-attr)))
+               (format "%6d " (file-attribute-inode-number file-attr)))
            ;; nil is treated like "" in concat
            (if (memq ?s switches)      ; size in K
-               (format "%4d " (1+ (/ (nth 7 file-attr) 1024))))
-           (nth 8 file-attr)           ; permission bits
+               (format "%4d " (1+ (/ (file-attribute-size file-attr) 1024))))
+           (file-attribute-modes file-attr)
            (format " %3d %-8s %-8s %8d "
-                   (nth 1 file-attr)   ; no. of links
-                   (if (numberp (nth 2 file-attr))
-                       (int-to-string (nth 2 file-attr))
-                     (nth 2 file-attr)) ; uid
+                   (file-attribute-link-number file-attr)
+                   (if (numberp (file-attribute-user-id file-attr))
+                       (int-to-string (file-attribute-user-id file-attr))
+                     (file-attribute-user-id file-attr))
                    (if (eq system-type 'ms-dos)
                        "root"          ; everything is root on MSDOS.
-                     (if (numberp (nth 3 file-attr))
-                         (int-to-string (nth 3 file-attr))
-                       (nth 3 file-attr))) ; gid
-                   (nth 7 file-attr)   ; size in bytes
+                     (if (numberp (file-attribute-group-id file-attr))
+                         (int-to-string (file-attribute-group-id file-attr))
+                       (file-attribute-group-id file-attr)))
+                   (file-attribute-size file-attr)
                    )
            (find-lisp-format-time file-attr switches now)
            " "
diff --git a/lisp/gnus/gnus-agent.el b/lisp/gnus/gnus-agent.el
index 532fd7e..18e6174 100644
--- a/lisp/gnus/gnus-agent.el
+++ b/lisp/gnus/gnus-agent.el
@@ -1603,7 +1603,8 @@ downloaded into the agent."
                                           (number-to-string have-this)))
                        (size-file
                         (float (or (and gnus-agent-total-fetched-hashtb
-                                        (nth 7 (file-attributes file-name)))
+                                        (file-attribute-size
+                                         (file-attributes file-name)))
                                    0)))
                        (file-name-coding-system
                         nnmail-pathname-coding-system))
@@ -2096,12 +2097,16 @@ doesn't exist, to valid the overview buffer."
           (let* (alist
                  (file-name-coding-system nnmail-pathname-coding-system)
                  (file-attributes (directory-files-and-attributes
-                                   (gnus-agent-article-name ""
-                                                            
gnus-agent-read-agentview) nil "^[0-9]+$" t)))
+                                   (gnus-agent-article-name
+                                    "" gnus-agent-read-agentview)
+                                   nil "^[0-9]+$" t)))
             (while file-attributes
               (let ((fa (pop file-attributes)))
-                (unless (nth 1 fa)
-                  (push (cons (string-to-number (nth 0 fa)) (time-to-days (nth 
5 fa))) alist))))
+                (unless (file-attribute-type (cdr fa))
+                  (push (cons (string-to-number (car fa))
+                              (time-to-days
+                               (file-attribute-access-time (cdr fa))))
+                        alist))))
             alist)
         (file-error nil))))))
 
@@ -3347,7 +3352,8 @@ missing NOV entry.  Run gnus-agent-regenerate-group to 
restore it.")))
                     (ignore-errors     ; Just being paranoid.
                       (let* ((file-name (nnheader-concat dir (number-to-string
                                                               article-number)))
-                             (size (float (nth 7 (file-attributes 
file-name)))))
+                             (size (float (file-attribute-size
+                                           (file-attributes file-name)))))
                         (cl-incf bytes-freed size)
                         (cl-incf size-files-deleted size)
                         (cl-incf files-deleted)
@@ -3800,7 +3806,7 @@ has been fetched."
            (buffer-read-only nil)
           (file-name-coding-system nnmail-pathname-coding-system))
       (when (and (file-exists-p file)
-                 (> (nth 7 (file-attributes file)) 0))
+                 (> (file-attribute-size (file-attributes file)) 0))
         (erase-buffer)
         (gnus-kill-all-overlays)
         (let ((coding-system-for-read gnus-cache-coding-system))
@@ -3945,9 +3951,11 @@ If REREAD is not nil, downloaded articles are marked as 
unread."
                 ;; This entry in the overview has been downloaded
                 (push (cons (car downloaded)
                             (time-to-days
-                             (nth 5 (file-attributes
-                                     (concat dir (number-to-string
-                                                  (car downloaded))))))) alist)
+                             (file-attribute-modification-time
+                              (file-attributes
+                               (concat dir (number-to-string
+                                            (car downloaded)))))))
+                      alist)
                 (setq downloaded (cdr downloaded))
                 (setq nov-arts (cdr nov-arts)))
                (t
@@ -4105,19 +4113,21 @@ agent has fetched."
               (let ((sum 0.0)
                     file)
                 (while (setq file (pop delta))
-                  (cl-incf sum (float (or (nth 7 (file-attributes
-                                               (nnheader-concat
-                                                path
-                                                (if (numberp file)
-                                                    (number-to-string file)
-                                                  file)))) 0))))
+                  (cl-incf sum (float (or (file-attribute-size
+                                           (file-attributes
+                                            (nnheader-concat
+                                             path
+                                             (if (numberp file)
+                                                 (number-to-string file)
+                                               file))))
+                                          0))))
                 (setq delta sum))
             (let ((sum (- (nth 2 entry)))
                   (info (directory-files-and-attributes
                          path nil "^-?[0-9]+$" t))
                   file)
               (while (setq file (pop info))
-                (cl-incf sum (float (or (nth 8 file) 0))))
+                (cl-incf sum (float (or (file-attribute-size (cdr file)) 0))))
               (setq delta sum))))
 
         (setq gnus-agent-need-update-total-fetched-for t)
@@ -4138,11 +4148,11 @@ modified."
                       (gnus-sethash path (make-list 3 0)
                                     gnus-agent-total-fetched-hashtb)))
            (file-name-coding-system nnmail-pathname-coding-system)
-           (size (or (nth 7 (file-attributes
-                             (nnheader-concat
-                              path (if agent-over
-                                       ".overview"
-                                     ".agentview"))))
+           (size (or (file-attribute-size (file-attributes
+                                           (nnheader-concat
+                                            path (if agent-over
+                                                     ".overview"
+                                                   ".agentview"))))
                      0)))
        (setq gnus-agent-need-update-total-fetched-for t)
        (setf (nth (if agent-over 1 0) entry) size)))))
diff --git a/lisp/gnus/gnus-cache.el b/lisp/gnus/gnus-cache.el
index 6afc52c..a16b61a 100644
--- a/lisp/gnus/gnus-cache.el
+++ b/lisp/gnus/gnus-cache.el
@@ -642,7 +642,8 @@ $ emacs -batch -l ~/.emacs -l gnus -f gnus-jog-cache"
   "Read the cache active file."
   (gnus-make-directory gnus-cache-directory)
   (if (or (not (file-exists-p gnus-cache-active-file))
-         (zerop (nth 7 (file-attributes gnus-cache-active-file)))
+         (zerop (file-attribute-size
+                 (file-attributes gnus-cache-active-file)))
          force)
       ;; There is no active file, so we generate one.
       (gnus-cache-generate-active)
@@ -854,7 +855,7 @@ supported."
            size)
 
        (if file
-          (setq size (or (nth 7 (file-attributes file)) 0))
+          (setq size (or (file-attribute-size (file-attributes file)) 0))
         (let* ((file-name-coding-system nnmail-pathname-coding-system)
                (files (directory-files (gnus-cache-file-name group "")
                                        t nil t))
@@ -862,8 +863,8 @@ supported."
           (setq size 0.0)
           (while (setq file (pop files))
             (setq attrs (file-attributes file))
-            (unless (nth 0 attrs)
-              (cl-incf size (float (nth 7 attrs)))))))
+            (unless (file-attribute-type attrs)
+              (cl-incf size (float (file-attribute-size attrs)))))))
 
        (setq gnus-cache-need-update-total-fetched-for t)
 
@@ -877,7 +878,7 @@ supported."
                       (gnus-sethash group (make-list 2 0)
                                     gnus-cache-total-fetched-hashtb)))
            (file-name-coding-system nnmail-pathname-coding-system)
-           (size (or (nth 7 (file-attributes
+           (size (or (file-attribute-size (file-attributes
                              (or file
                                  (gnus-cache-file-name group ".overview"))))
                      0)))
diff --git a/lisp/gnus/gnus-cloud.el b/lisp/gnus/gnus-cloud.el
index 16bd80d..1aa8e71 100644
--- a/lisp/gnus/gnus-cloud.el
+++ b/lisp/gnus/gnus-cloud.el
@@ -339,7 +339,8 @@ Use old data if FORCE-OLDER is not nil."
   (format-time-string "%FT%T%z" time))
 
 (defun gnus-cloud-file-new-p (file full)
-  (let ((timestamp (gnus-cloud-timestamp (nth 5 (file-attributes file))))
+  (let ((timestamp (gnus-cloud-timestamp (file-attribute-modification-time
+                                         (file-attributes file))))
         (old (cadr (assoc file gnus-cloud-file-timestamps))))
     (when (or full
               (null old)
diff --git a/lisp/gnus/gnus-score.el b/lisp/gnus/gnus-score.el
index 6878aa6..327cc69 100644
--- a/lisp/gnus/gnus-score.el
+++ b/lisp/gnus/gnus-score.el
@@ -2675,7 +2675,8 @@ the score file and its full name, including the 
directory.")
                (gnus-file-newer-than gnus-kill-files-directory
                                      (car gnus-score-file-list)))
        (setq gnus-score-file-list
-             (cons (nth 5 (file-attributes gnus-kill-files-directory))
+             (cons (file-attribute-modification-time
+                    (file-attributes gnus-kill-files-directory))
                    (nreverse
                     (directory-files
                      gnus-kill-files-directory t
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index 623055e..f15d645 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -2822,7 +2822,8 @@ If FORCE is non-nil, the .newsrc file is read."
           ;; Check timestamp of `gnus-current-startup-file'.eld against
           ;; `gnus-save-newsrc-file-last-timestamp'.
          (if (let* ((checkfile (concat gnus-current-startup-file ".eld"))
-                     (mtime (nth 5 (file-attributes checkfile))))
+                    (mtime (file-attribute-modification-time
+                            (file-attributes checkfile))))
                (and gnus-save-newsrc-file-last-timestamp
                      (time-less-p gnus-save-newsrc-file-last-timestamp
                                   mtime)
@@ -2843,7 +2844,8 @@ If FORCE is non-nil, the .newsrc file is read."
                   (gnus-run-hooks 'gnus-save-quick-newsrc-hook)
                   (save-buffer)
                   (setq gnus-save-newsrc-file-last-timestamp
-                        (nth 5 (file-attributes buffer-file-name))))
+                       (file-attribute-modification-time
+                        (file-attributes buffer-file-name))))
               (let ((coding-system-for-write gnus-ding-file-coding-system)
                     (version-control gnus-backup-startup-file)
                     (startup-file (concat gnus-current-startup-file ".eld"))
@@ -2880,7 +2882,8 @@ If FORCE is non-nil, the .newsrc file is read."
                        (rename-file working-file startup-file t)
                        (gnus-set-file-modes startup-file setmodes)
                        (setq gnus-save-newsrc-file-last-timestamp
-                              (nth 5 (file-attributes startup-file)))))
+                             (file-attribute-modification-time
+                              (file-attributes startup-file)))))
                   (condition-case nil
                       (delete-file working-file)
                     (file-error nil)))))
@@ -3053,11 +3056,12 @@ If FORCE is non-nil, the .newsrc file is read."
       (with-current-buffer (gnus-get-buffer-create " *gnus slave*")
        (setq slave-files
              (sort (mapcar (lambda (file)
-                             (list (nth 5 (file-attributes file)) file))
+                             (list (file-attribute-modification-time
+                                    (file-attributes file))
+                                   file))
                            slave-files)
                    (lambda (f1 f2)
-                     (or (< (caar f1) (caar f2))
-                         (< (nth 1 (car f1)) (nth 1 (car f2)))))))
+                     (time-less-p (car f1) (car f2)))))
        (while slave-files
          (erase-buffer)
          (setq file (nth 1 (car slave-files)))
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index ceb9842..f56b822 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -10340,16 +10340,19 @@ latter case, they will be copied into the relevant 
groups."
            (unless (re-search-forward "^date:" nil t)
              (goto-char (point-max))
              (setq atts (file-attributes file))
-             (insert "Date: " (message-make-date (nth 5 atts)) "\n")))
+             (insert "Date: " (message-make-date
+                               (file-attribute-modification-time atts))
+                     "\n")))
        ;; This doesn't look like an article, so we fudge some headers.
        (setq atts (file-attributes file)
              lines (count-lines (point-min) (point-max)))
        (insert "From: " (read-string "From: ") "\n"
                "Subject: " (read-string "Subject: ") "\n"
-               "Date: " (message-make-date (nth 5 atts)) "\n"
+               "Date: " (message-make-date
+                         (file-attribute-modification-time atts)) "\n"
                "Message-ID: " (message-make-message-id) "\n"
                "Lines: " (int-to-string lines) "\n"
-               "Chars: " (int-to-string (nth 7 atts)) "\n\n"))
+               "Chars: " (int-to-string (file-attribute-size atts)) "\n\n"))
       (setq group-art (gnus-request-accept-article group nil t))
       (kill-buffer (current-buffer)))
     (setq gnus-newsgroup-active (gnus-activate-group group))
diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el
index b30e4d1..2e4b054 100644
--- a/lisp/gnus/gnus-util.el
+++ b/lisp/gnus/gnus-util.el
@@ -277,10 +277,7 @@ Symbols are also allowed; their print names are used 
instead."
 ;;; Time functions.
 
 (defun gnus-file-newer-than (file date)
-  (let ((fdate (nth 5 (file-attributes file))))
-    (or (> (car fdate) (car date))
-       (and (= (car fdate) (car date))
-            (> (nth 1 fdate) (nth 1 date))))))
+  (time-less-p date (file-attribute-modification-time (file-attributes file))))
 
 ;;; Keymap macros.
 
@@ -1434,7 +1431,7 @@ SPEC is a predicate specifier that contains stuff like 
`or', `and',
 
 (defun gnus-cache-file-contents (file variable function)
   "Cache the contents of FILE in VARIABLE.  The contents come from FUNCTION."
-  (let ((time (nth 5 (file-attributes file)))
+  (let ((time (file-attribute-modification-time (file-attributes file)))
        contents value)
     (if (or (null (setq value (symbol-value variable)))
            (not (equal (car value) file))
diff --git a/lisp/gnus/mail-source.el b/lisp/gnus/mail-source.el
index 0e1c073..5af2920 100644
--- a/lisp/gnus/mail-source.el
+++ b/lisp/gnus/mail-source.el
@@ -602,7 +602,8 @@ If CONFIRM is non-nil, ask for confirmation before removing 
a file."
       (let* ((ffile (car files))
             (bfile (replace-regexp-in-string "\\`.*/\\([^/]+\\)\\'" "\\1"
                                              ffile))
-            (filetime (nth 5 (file-attributes ffile))))
+            (filetime (file-attribute-modification-time
+                       (file-attributes ffile))))
        (setq files (cdr files))
        (when (and (> (time-to-number-of-days (time-subtract now filetime))
                      diff)
@@ -618,7 +619,8 @@ Deleting old (> %s day(s)) incoming mail file `%s'." diff 
bfile)
 (defun mail-source-callback (callback info)
   "Call CALLBACK on the mail file.  Pass INFO on to CALLBACK."
   (if (or (not (file-exists-p mail-source-crash-box))
-         (zerop (nth 7 (file-attributes mail-source-crash-box))))
+         (zerop (file-attribute-size
+                 (file-attributes mail-source-crash-box))))
       (progn
        (when (file-exists-p mail-source-crash-box)
          (delete-file mail-source-crash-box))
@@ -670,7 +672,7 @@ Deleting old (> %s day(s)) incoming mail file `%s'." diff 
bfile)
        ((not (file-exists-p from))
        ;; There is no inbox.
        (setq to nil))
-       ((zerop (nth 7 (file-attributes from)))
+       ((zerop (file-attribute-size (file-attributes from)))
        ;; Empty file.
        (setq to nil))
        (t
diff --git a/lisp/gnus/nneething.el b/lisp/gnus/nneething.el
index abd17c5..10ac702 100644
--- a/lisp/gnus/nneething.el
+++ b/lisp/gnus/nneething.el
@@ -215,8 +215,9 @@ included.")
        (setq nneething-map
              (mapcar (lambda (n)
                        (list (cdr n) (car n)
-                             (nth 5 (file-attributes
-                                     (nneething-file-name (car n))))))
+                             (file-attribute-modification-time
+                              (file-attributes
+                               (nneething-file-name (car n))))))
                      nneething-map)))
       ;; Remove files matching the exclusion regexp.
       (when nneething-exclude-files
@@ -244,7 +245,7 @@ included.")
        (while map
          (if (and (member (cadr (car map)) files)
                  ;; We also remove files that have changed mod times.
-                  (equal (nth 5 (file-attributes
+                  (equal (file-attribute-modification-time (file-attributes
                                  (nneething-file-name (cadr (car map)))))
                          (cadr (cdar map))))
              (progn
@@ -262,7 +263,7 @@ included.")
          (setq touched t)
          (setcdr nneething-active (1+ (cdr nneething-active)))
          (push (list (cdr nneething-active) (car files)
-                     (nth 5 (file-attributes
+                     (file-attribute-modification-time (file-attributes
                              (nneething-file-name (car files)))))
                nneething-map))
        (setq files (cdr files)))
@@ -318,15 +319,17 @@ included.")
      "Subject: " (file-name-nondirectory file) (or extra-msg "") "\n"
      "Message-ID: <nneething-" (nneething-encode-file-name file)
      "@" (system-name) ">\n"
-     (if (equal '(0 0) (nth 5 atts)) ""
-       (concat "Date: " (current-time-string (nth 5 atts)) "\n"))
+     (if (zerop (float-time (file-attribute-modification-time atts))) ""
+       (concat "Date: "
+              (current-time-string (file-attribute-modification-time atts))
+              "\n"))
      (or (when buffer
           (with-current-buffer buffer
             (when (re-search-forward "<address@hidden>" 1000 t)
               (concat "From: " (match-string 0) "\n"))))
-        (nneething-from-line (nth 2 atts) file))
-     (if (> (string-to-number (int-to-string (nth 7 atts))) 0)
-        (concat "Chars: " (int-to-string (nth 7 atts)) "\n")
+        (nneething-from-line (file-attribute-user-id atts) file))
+     (if (> (file-attribute-size atts) 0)
+        (concat "Chars: " (int-to-string (file-attribute-size atts)) "\n")
        "")
      (if buffer
         (with-current-buffer buffer
diff --git a/lisp/gnus/nnfolder.el b/lisp/gnus/nnfolder.el
index 11a3986..8ef6f2a 100644
--- a/lisp/gnus/nnfolder.el
+++ b/lisp/gnus/nnfolder.el
@@ -862,7 +862,7 @@ deleted.  Point is left where the deleted region was."
     (mm-enable-multibyte) ;; Use multibyte buffer for future copying.
     (buffer-disable-undo)
     (if (equal (cadr (assoc group nnfolder-scantime-alist))
-              (nth 5 (file-attributes file)))
+              (file-attribute-modification-time (file-attributes file)))
        ;; This looks up-to-date, so we don't do any scanning.
        (if (file-exists-p file)
            buffer
diff --git a/lisp/gnus/nnheader.el b/lisp/gnus/nnheader.el
index b9ce204..83a9c3f 100644
--- a/lisp/gnus/nnheader.el
+++ b/lisp/gnus/nnheader.el
@@ -896,7 +896,7 @@ without formatting."
 
 (defun nnheader-file-size (file)
   "Return the file size of FILE or 0."
-  (or (nth 7 (file-attributes file)) 0))
+  (or (file-attribute-size (file-attributes file)) 0))
 
 (defun nnheader-find-etc-directory (package &optional file first)
   "Go through `load-path' and find the \"../etc/PACKAGE\" directory.
@@ -951,7 +951,7 @@ find-file-hook, etc.
     (mm-insert-file-contents filename visit beg end replace)))
 
 (defun nnheader-insert-nov-file (file first)
-  (let ((size (nth 7 (file-attributes file)))
+  (let ((size (file-attribute-size (file-attributes file)))
        (cutoff (* 32 1024)))
     (when size
       (if (< size cutoff)
diff --git a/lisp/gnus/nnmail.el b/lisp/gnus/nnmail.el
index 08db5ab..13c4303 100644
--- a/lisp/gnus/nnmail.el
+++ b/lisp/gnus/nnmail.el
@@ -1534,7 +1534,8 @@ See the documentation for the variable 
`nnmail-split-fancy' for details."
            (and (setq file (ignore-errors
                              (symbol-value (intern (format "%s-active-file"
                                                            backend)))))
-                (setq file-time (nth 5 (file-attributes file)))
+                (setq file-time (file-attribute-modification-time
+                                 (file-attributes file)))
                 (or (not
                      (setq timestamp
                            (condition-case ()
diff --git a/lisp/gnus/nnmaildir.el b/lisp/gnus/nnmaildir.el
index fbabf57..afaf3dc 100644
--- a/lisp/gnus/nnmaildir.el
+++ b/lisp/gnus/nnmaildir.el
@@ -318,15 +318,15 @@ This variable is set by `nnmaildir-request-article'.")
        (setq attr (file-attributes
                    (concat dir (number-to-string number-opened))))
        (or attr (throw 'return (1- number-opened)))
-       (setq ino-opened (nth 10 attr)
-             nlink (nth 1 attr)
+       (setq ino-opened (file-attribute-inode-number attr)
+             nlink (file-attribute-link-number attr)
              number-linked (+ number-opened nlink))
        (if (or (< nlink 1) (< number-linked nlink))
            (signal 'error '("Arithmetic overflow")))
        (setq attr (file-attributes
                    (concat dir (number-to-string number-linked))))
        (or attr (throw 'return (1- number-linked)))
-       (unless (equal ino-opened (nth 10 attr))
+       (unless (equal ino-opened (file-attribute-inode-number attr))
          (setq number-opened number-linked))))))
 
 ;; Make the given server, if non-nil, be the current server.  Then make the
@@ -392,8 +392,8 @@ This variable is set by `nnmaildir-request-article'.")
          (setq make-new-file nil
                previous-number-link 0))
        (let* ((attr (file-attributes path-open))
-              (nlink (nth 1 attr)))
-         (setq ino-open (nth 10 attr)
+              (nlink (file-attribute-link-number attr)))
+         (setq ino-open (file-attribute-inode-number attr)
                number-link (+ number-open nlink))
          (if (or (< nlink 1) (< number-link nlink))
              (signal 'error '("Arithmetic overflow"))))
@@ -412,7 +412,7 @@ This variable is set by `nnmaildir-request-article'.")
                  number-open number-link))
           ((nnmaildir--eexist-p err)
            (let ((attr (file-attributes path-link)))
-             (unless (equal (nth 10 attr) ino-open)
+             (unless (equal (file-attribute-inode-number attr) ino-open)
                (setq number-open number-link
                      number-link 0))))
           (t (signal (car err) (cdr err)))))))))
@@ -437,8 +437,8 @@ This variable is set by `nnmaildir-request-article'.")
       (unless attr
        (nnmaildir--expired-article group article)
        (throw 'return nil))
-      (setq mtime (nth 5 attr)
-           attr (nth 7 attr)
+      (setq mtime (file-attribute-modification-time attr)
+           attr (file-attribute-size attr)
            nov (nnmaildir--art-nov article)
            dir (nnmaildir--nndir dir)
            novdir (nnmaildir--nov-dir dir)
@@ -794,29 +794,33 @@ This variable is set by `nnmaildir-request-article'.")
       (setq read-only (nnmaildir--param pgname 'read-only)
            ls (or (nnmaildir--param pgname 'directory-files) srv-ls))
       (unless read-only
-       (setq x (nth 11 (file-attributes tdir)))
-       (unless (and (equal x (nth 11 nattr)) (equal x (nth 11 cattr)))
+       (setq x (file-attribute-device-number (file-attributes tdir)))
+       (unless (and (equal x (file-attribute-device-number nattr))
+                    (equal x (file-attribute-device-number cattr)))
          (setf (nnmaildir--srv-error nnmaildir--cur-server)
                (concat "Maildir spans filesystems: " absdir))
          (throw 'return nil))
        (dolist (file (funcall ls tdir 'full "\\`[^.]" 'nosort))
          (setq x (file-attributes file))
-         (if (or (> (cadr x) 1) (time-less-p (nth 4 x) 36h-ago))
+         (if (or (> (file-attribute-link-number x) 1)
+                 (time-less-p (file-attribute-access-time x) 36h-ago))
              (delete-file file))))
       (or scan-msgs
          isnew
          (throw 'return t))
-      (setq nattr (nth 5 nattr))
+      (setq nattr (file-attribute-modification-time nattr))
       (if (equal nattr (nnmaildir--grp-new group))
          (setq nattr nil))
       (if read-only (setq dir (and (or isnew nattr) ndir))
        (when (or isnew nattr)
          (dolist (file  (funcall ls ndir nil "\\`[^.]" 'nosort))
            (setq x (concat ndir file))
-           (and (time-less-p (nth 5 (file-attributes x)) nil)
+           (and (time-less-p (file-attribute-modification-time
+                              (file-attributes x))
+                             nil)
                 (rename-file x (concat cdir (nnmaildir--ensure-suffix file)))))
          (setf (nnmaildir--grp-new group) nattr))
-       (setq cattr (nth 5 (file-attributes cdir)))
+       (setq cattr (file-attribute-modification-time (file-attributes cdir)))
        (if (equal cattr (nnmaildir--grp-cur group))
            (setq cattr nil))
        (setq dir (and (or isnew cattr) cdir)))
@@ -903,7 +907,7 @@ This variable is set by `nnmaildir-request-article'.")
                (if (nnmaildir--srv-gnm nnmaildir--cur-server)
                    (nnmail-get-new-mail 'nnmaildir nil nil scan-group))
              (unintern scan-group groups))
-         (setq x (nth 5 (file-attributes srv-dir))
+         (setq x (file-attribute-modification-time (file-attributes srv-dir))
                scan-group (null scan-group))
          (if (equal x (nnmaildir--srv-mtime nnmaildir--cur-server))
              (if scan-group
@@ -936,7 +940,7 @@ This variable is set by `nnmaildir-request-article'.")
            (dolist (grp x)
              (unintern grp groups))
            (setf (nnmaildir--srv-mtime nnmaildir--cur-server)
-                 (nth 5 (file-attributes srv-dir))))
+                 (file-attribute-modification-time (file-attributes srv-dir))))
          (and scan-group
               (nnmaildir--srv-gnm nnmaildir--cur-server)
               (nnmail-get-new-mail 'nnmaildir nil nil))))))
@@ -993,7 +997,7 @@ This variable is set by `nnmaildir-request-article'.")
         (curdir (nnmaildir--cur
                  (nnmaildir--srvgrp-dir
                   (nnmaildir--srv-dir nnmaildir--cur-server) gname)))
-        (curdir-mtime (nth 5 (file-attributes curdir)))
+        (curdir-mtime (file-attribute-modification-time (file-attributes 
curdir)))
         pgname flist always-marks never-marks old-marks dir
         all-marks marks ranges markdir read ls
         old-mmth new-mmth mtime existing missing deactivate-mark)
@@ -1046,7 +1050,7 @@ This variable is set by `nnmaildir-request-article'.")
          ;; a filename flag, get the later of the mtimes for markdir and
          ;; curdir, otherwise only the markdir counts.
          (setq mtime
-               (let ((markdir-mtime (nth 5 (file-attributes markdir))))
+               (let ((markdir-mtime (file-attribute-modification-time 
(file-attributes markdir))))
                  (cond
                   ((null (nnmaildir--mark-to-flag mark))
                    markdir-mtime)
@@ -1599,7 +1603,7 @@ This variable is set by `nnmaildir-request-article'.")
             (nnmaildir--expired-article group article))
            ((and no-force
                  (progn
-                   (setq time (nth 5 time)
+                   (setq time (file-attribute-modification-time time)
                          bound-iter boundary)
                    (while (and bound-iter time
                                (= (car bound-iter) (car time)))
diff --git a/lisp/gnus/nnmh.el b/lisp/gnus/nnmh.el
index 33be64f..d0f8ec2 100644
--- a/lisp/gnus/nnmh.el
+++ b/lisp/gnus/nnmh.el
@@ -210,8 +210,10 @@ as unread by Gnus.")
        min rdir num subdirectoriesp file)
     ;; Recurse down directories.
     (setq subdirectoriesp
-         ;; nth 1 of file-attributes always 1 on MS Windows :(
-         (/= (nth 1 (file-attributes (file-truename dir))) 2))
+         ;; link number always 1 on MS Windows :(
+         (/= (file-attribute-link-number
+              (file-attributes (file-truename dir)))
+             2))
     (dolist (rdir files)
       (if (or (not subdirectoriesp)
              (file-regular-p rdir))
@@ -263,7 +265,8 @@ as unread by Gnus.")
 
     (while (and articles is-old)
       (setq article (concat dir (int-to-string (car articles))))
-      (when (setq mod-time (nth 5 (file-attributes article)))
+      (when (setq mod-time (file-attribute-modification-time
+                           (file-attributes article)))
        (if (and (nnmh-deletable-article-p newsgroup (car articles))
                 (setq is-old
                       (nnmail-expired-article-p newsgroup mod-time force)))
@@ -534,8 +537,8 @@ as unread by Gnus.")
          art)
       (while (setq art (pop arts))
        (when (not (equal
-                   (nth 5 (file-attributes
-                           (concat dir (int-to-string (car art)))))
+                   (file-attribute-modification-time
+                    (file-attributes (concat dir (int-to-string (car art)))))
                    (cdr art)))
          (setq articles (delq art articles))
          (push (car art) new))))
@@ -546,8 +549,9 @@ as unread by Gnus.")
                 (mapcar
                  (lambda (art)
                    (cons art
-                         (nth 5 (file-attributes
-                                 (concat dir (int-to-string art))))))
+                         (file-attribute-modification-time
+                          (file-attributes
+                           (concat dir (int-to-string art))))))
                  new)))
     ;; Make Gnus mark all new articles as unread.
     (when new
diff --git a/lisp/gnus/nnml.el b/lisp/gnus/nnml.el
index 6307e13..e7a5b99 100644
--- a/lisp/gnus/nnml.el
+++ b/lisp/gnus/nnml.el
@@ -344,7 +344,8 @@ non-nil.")
     (while (and articles is-old)
       (if (and (setq article (nnml-article-to-file
                              (setq number (pop articles))))
-              (setq mod-time (nth 5 (file-attributes article)))
+              (setq mod-time (file-attribute-modification-time
+                              (file-attributes article)))
               (nnml-deletable-article-p group number)
               (setq is-old (nnmail-expired-article-p group mod-time force
                                                      nnml-inhibit-expiry)))
diff --git a/lisp/gnus/spam-stat.el b/lisp/gnus/spam-stat.el
index 9205295..3625132 100644
--- a/lisp/gnus/spam-stat.el
+++ b/lisp/gnus/spam-stat.el
@@ -77,13 +77,13 @@
 ;; Learn spam: (spam-stat-process-spam-directory "~/Mail/mail/spam")
 ;; Learn non-spam: (spam-stat-process-non-spam-directory "~/Mail/mail/misc")
 ;; Save table: (spam-stat-save)
-;; File size: (nth 7 (file-attributes spam-stat-file))
+;; File size: (file-attribute-size (file-attributes spam-stat-file))
 ;; Number of words: (hash-table-count spam-stat)
 ;; Test spam: (spam-stat-test-directory "~/Mail/mail/spam")
 ;; Test non-spam: (spam-stat-test-directory "~/Mail/mail/misc")
 ;; Reduce table size: (spam-stat-reduce-size)
 ;; Save table: (spam-stat-save)
-;; File size: (nth 7 (file-attributes spam-stat-file))
+;; File size: (file-attribute-size (file-attributes spam-stat-file))
 ;; Number of words: (hash-table-count spam-stat)
 ;; Test spam: (spam-stat-test-directory "~/Mail/mail/spam")
 ;; Test non-spam: (spam-stat-test-directory "~/Mail/mail/misc")
@@ -424,7 +424,8 @@ spam-stat (spam-stat-to-hash-table '(" spam-stat-ngood 
spam-stat-nbad))
          (insert ")))"))))
     (message "Saved %s."  spam-stat-file)
     (setq spam-stat-dirty nil
-          spam-stat-last-saved-at (nth 5 (file-attributes spam-stat-file)))))
+          spam-stat-last-saved-at (file-attribute-modification-time
+                                  (file-attributes spam-stat-file)))))
 
 (defun spam-stat-load ()
   "Read the `spam-stat' hash table from disk."
@@ -434,12 +435,14 @@ spam-stat (spam-stat-to-hash-table '(" spam-stat-ngood 
spam-stat-nbad))
           ((or (not (boundp 'spam-stat-last-saved-at))
                (null spam-stat-last-saved-at)
                (not (equal spam-stat-last-saved-at
-                           (nth 5 (file-attributes spam-stat-file)))))
+                           (file-attribute-modification-time
+                           (file-attributes spam-stat-file)))))
            (progn
              (load-file spam-stat-file)
              (setq spam-stat-dirty nil
                    spam-stat-last-saved-at
-                   (nth 5 (file-attributes spam-stat-file)))))
+                   (file-attribute-modification-time
+                   (file-attributes spam-stat-file)))))
           (t (message "Spam stat file not loaded: no change in disk.")))))
 
 (defun spam-stat-to-hash-table (entries)
@@ -561,8 +564,10 @@ check the variable `spam-stat-score-data'."
       (dolist (f files)
        (when (and (file-readable-p f)
                   (file-regular-p f)
-                   (> (nth 7 (file-attributes f)) 0)
-                  (< (time-to-number-of-days (time-since (nth 5 
(file-attributes f))))
+                   (> (file-attribute-size (file-attributes f)) 0)
+                  (< (time-to-number-of-days
+                      (time-since (file-attribute-modification-time
+                                   (file-attributes f))))
                      spam-stat-process-directory-age))
          (setq count (1+ count))
          (message "Reading %s: %.2f%%" dir (/ count max))
@@ -607,7 +612,7 @@ display non-spam files; otherwise display spam files."
       (dolist (f files)
        (when (and (file-readable-p f)
                   (file-regular-p f)
-                   (> (nth 7 (file-attributes f)) 0))
+                   (> (file-attribute-size (file-attributes f)) 0))
          (setq count (1+ count))
          (message "Reading %.2f%%, score %.2f"
                   (/ count max) (/ score count))
diff --git a/lisp/ido.el b/lisp/ido.el
index f9a9607..64d8203 100644
--- a/lisp/ido.el
+++ b/lisp/ido.el
@@ -1750,7 +1750,8 @@ is enabled then some keybindings are changed in the 
keymap."
         (ido-final-slash dir)
         (not (ido-is-unc-host dir))
         (file-directory-p dir)
-        (> (nth 7 (file-attributes (file-truename dir))) 
ido-max-directory-size))))
+        (> (file-attribute-size (file-attributes (file-truename dir)))
+           ido-max-directory-size))))
 
 (defun ido-set-current-directory (dir &optional subdir no-merge)
   ;; Set ido's current directory to DIR or DIR/SUBDIR
@@ -3610,7 +3611,7 @@ Uses and updates `ido-dir-file-cache'."
             (ftp (ido-is-ftp-directory dir))
             (unc (ido-is-unc-host dir))
             (attr (if (or ftp unc) nil (file-attributes dir)))
-            (mtime (nth 5 attr))
+            (mtime (file-attribute-modification-time attr))
             valid)
        (when cached        ; should we use the cached entry ?
          (cond
diff --git a/lisp/image-dired.el b/lisp/image-dired.el
index 1acb319..17e566d 100644
--- a/lisp/image-dired.el
+++ b/lisp/image-dired.el
@@ -587,8 +587,9 @@ Create the thumbnails directory if it does not exist."
   (let* ((thumb-file (image-dired-thumb-name file))
         (thumb-attr (file-attributes thumb-file)))
     (when (or (not thumb-attr)
-             (time-less-p (nth 5 thumb-attr)
-                          (nth 5 (file-attributes file))))
+             (time-less-p (file-attribute-modification-time thumb-attr)
+                          (file-attribute-modification-time
+                           (file-attributes file))))
       (image-dired-create-thumb file thumb-file))
     (create-image thumb-file)
 ;;     (list 'image :type 'jpeg
@@ -752,7 +753,8 @@ Increase at own risk.")
   (let* ((width (int-to-string (image-dired-thumb-size 'width)))
          (height (int-to-string (image-dired-thumb-size 'height)))
         (modif-time (format-time-string
-                     "%s" (nth 5 (file-attributes original-file))))
+                     "%s" (file-attribute-modification-time
+                           (file-attributes original-file))))
          (thumbnail-nq8-file (replace-regexp-in-string ".png\\'" "-nq8.png"
                                                        thumbnail-file))
          (spec
@@ -2652,8 +2654,8 @@ tags to their respective image file.  Internal function 
used by
 ;;            (mapcar
 ;;             (lambda (f)
 ;;               (let ((fattribs (file-attributes f)))
-;;                 ;; Get last access time and file size
-;;                 `(,(nth 4 fattribs) ,(nth 7 fattribs) ,f)))
+;;                 `(,(file-attribute-access-time fattribs)
+;;                   ,(file-attribute-size fattribs) ,f)))
 ;;             (directory-files (image-dired-dir) t ".+\\.thumb\\..+$"))
 ;;            ;; Sort function. Compare time between two files.
 ;;            (lambda (l1 l2)
diff --git a/lisp/info.el b/lisp/info.el
index ab2c51d..f2e2957 100644
--- a/lisp/info.el
+++ b/lisp/info.el
@@ -654,9 +654,11 @@ Do the right thing if the file has been compressed or 
zipped."
 
     ;; Clear the caches of modified Info files.
     (let* ((attribs-old (cdr (assoc fullname Info-file-attributes)))
-          (modtime-old (and attribs-old (nth 5 attribs-old)))
+          (modtime-old (and attribs-old
+                            (file-attribute-modification-time attribs-old)))
           (attribs-new (and (stringp fullname) (file-attributes fullname)))
-          (modtime-new (and attribs-new (nth 5 attribs-new))))
+          (modtime-new (and attribs-new
+                            (file-attribute-modification-time attribs-new))))
       (when (and modtime-old modtime-new
                 (time-less-p modtime-old modtime-new))
        (setq Info-index-nodes (remove (assoc (or Info-current-file filename)
diff --git a/lisp/ls-lisp.el b/lisp/ls-lisp.el
index adb86dd..95f3163 100644
--- a/lisp/ls-lisp.el
+++ b/lisp/ls-lisp.el
@@ -385,13 +385,13 @@ not contain `d', so that a full listing is expected."
          ;; files we are about to display.
          (dolist (elt file-alist)
            (setq attr (cdr elt)
-                 fuid (nth 2 attr)
+                 fuid (file-attribute-user-id attr)
                  uid-len (if (stringp fuid) (string-width fuid)
                            (length (format "%d" fuid)))
-                 fgid (nth 3 attr)
+                 fgid (file-attribute-group-id attr)
                  gid-len (if (stringp fgid) (string-width fgid)
                            (length (format "%d" fgid)))
-                 file-size (nth 7 attr))
+                 file-size (file-attribute-size attr))
            (if (> uid-len max-uid-len)
                (setq max-uid-len uid-len))
            (if (> gid-len max-gid-len)
@@ -418,7 +418,7 @@ not contain `d', so that a full listing is expected."
                  files (cdr files)
                  short (car elt)
                  attr (cdr elt)
-                 file-size (nth 7 attr))
+                 file-size (file-attribute-size attr))
            (and attr
                 (setq sum (+ file-size
                              ;; Even if neither SUM nor file's size
@@ -474,7 +474,7 @@ not contain `d', so that a full listing is expected."
                   (if (memq ?F switches)
                       (ls-lisp-classify-file file fattr)
                     file)
-                  fattr (nth 7 fattr)
+                  fattr (file-attribute-size fattr)
                                  switches time-index))
        (message "%s: doesn't exist or is inaccessible" file)
        (ding) (sit-for 2)))))          ; to show user the message!
@@ -659,10 +659,9 @@ SWITCHES is a list of characters.  Default sorting is 
alphabetic."
                  (sort (copy-sequence file-alist) ; modifies its argument!
                        (cond ((memq ?S switches)
                               (lambda (x y) ; sorted on size
-                                ;; 7th file attribute is file size
                                 ;; Make largest file come first
-                                (< (nth 7 (cdr y))
-                                   (nth 7 (cdr x)))))
+                                (< (file-attribute-size (cdr y))
+                                   (file-attribute-size (cdr x)))))
                              ((setq index (ls-lisp-time-index switches))
                               (lambda (x y) ; sorted on time
                                 (time-less-p (nth index (cdr y))
@@ -719,8 +718,8 @@ FATTR is the file attributes returned by `file-attributes' 
for the file.
 The file type indicators are `/' for directories, `@' for symbolic
 links, `|' for FIFOs, `=' for sockets, `*' for regular files that
 are executable, and nothing for other types of files."
-  (let* ((type (car fattr))
-        (modestr (nth 8 fattr))
+  (let* ((type (file-attribute-type fattr))
+        (modestr (file-attribute-modes fattr))
         (typestr (substring modestr 0 1))
          (file-name (propertize filename 'dired-filename t)))
     (cond
@@ -773,35 +772,13 @@ FOLLOWED by null and full filename, SOLELY for full alpha 
sort."
   "Format one line of long ls output for file FILE-NAME.
 FILE-ATTR and FILE-SIZE give the file's attributes and size.
 SWITCHES and TIME-INDEX give the full switch list and time data."
-  (let ((file-type (nth 0 file-attr))
+  (let ((file-type (file-attribute-type file-attr))
        ;; t for directory, string (name linked to)
        ;; for symbolic link, or nil.
-       (drwxrwxrwx (nth 8 file-attr))) ; attribute string ("drwxrwxrwx")
+       (drwxrwxrwx (file-attribute-modes file-attr)))
     (concat (if (memq ?i switches)     ; inode number
-               (let ((inode (nth 10 file-attr)))
-                 (if (consp inode)
-                     (if (consp (cdr inode))
-                         ;; 2^(24+16) = 1099511627776.0, but
-                         ;; multiplying by it and then adding the
-                         ;; other members of the cons cell in one go
-                         ;; loses precision, since a double does not
-                         ;; have enough significant digits to hold a
-                         ;; full 64-bit value.  So below we split
-                         ;; 1099511627776 into high 13 and low 5
-                         ;; digits and compute in two parts.
-                         (let ((p1 (* (car inode) 10995116.0))
-                               (p2 (+ (* (car inode) 27776.0)
-                                      (* (cadr inode) 65536.0)
-                                      (cddr inode))))
-                           (format " %13.0f%05.0f "
-                                   ;; Use floor to emulate integer
-                                   ;; division.
-                                   (+ p1 (floor p2 100000.0))
-                                   (mod p2 100000.0)))
-                       (format " %18.0f "
-                               (+ (* (car inode) 65536.0)
-                                  (cdr inode))))
-                   (format " %18d " inode))))
+               (let ((inode (file-attribute-inode-number file-attr)))
+                 (format " %18d " inode)))
            ;; nil is treated like "" in concat
            (if (memq ?s switches)      ; size in K, rounded up
                ;; In GNU ls, -h affects the size in blocks, displayed
@@ -819,14 +796,14 @@ SWITCHES and TIME-INDEX give the full switch list and 
time data."
                          (fceiling (/ file-size 1024.0)))))
            drwxrwxrwx                  ; attribute string
            (if (memq 'links ls-lisp-verbosity)
-               (format "%3d" (nth 1 file-attr))) ; link count
+               (format "%3d" (file-attribute-link-number file-attr)))
            ;; Numeric uid/gid are more confusing than helpful;
            ;; Emacs should be able to make strings of them.
            ;; They tend to be bogus on non-UNIX platforms anyway so
            ;; optionally hide them.
            (if (memq 'uid ls-lisp-verbosity)
                ;; uid can be a string or an integer
-               (let ((uid (nth 2 file-attr)))
+               (let ((uid (file-attribute-user-id file-attr)))
                   (format (if (stringp uid)
                              ls-lisp-uid-s-fmt
                            ls-lisp-uid-d-fmt)
@@ -834,7 +811,7 @@ SWITCHES and TIME-INDEX give the full switch list and time 
data."
            (if (not (memq ?G switches)) ; GNU ls -- shows group by default
                (if (or (memq ?g switches) ; UNIX ls -- no group by default
                        (memq 'gid ls-lisp-verbosity))
-                    (let ((gid (nth 3 file-attr)))
+                    (let ((gid (file-attribute-group-id file-attr)))
                       (format (if (stringp gid)
                                  ls-lisp-gid-s-fmt
                                ls-lisp-gid-d-fmt)
diff --git a/lisp/mail/blessmail.el b/lisp/mail/blessmail.el
index 8261f17..62e9873 100644
--- a/lisp/mail/blessmail.el
+++ b/lisp/mail/blessmail.el
@@ -49,15 +49,15 @@
   (setq attr (file-attributes dirname))
   (if (not (eq t (car attr)))
       (insert (format "echo %s is not a directory\n" rmail-spool-directory))
-    (setq modes (nth 8 attr))
+    (setq modes (file-attribute-modes attr))
     (cond ((= ?w (aref modes 8))
           ;; Nothing needs to be done.
           )
          ((= ?w (aref modes 5))
-          (insert "chgrp " (number-to-string (nth 3 attr))
+          (insert "chgrp " (number-to-string (file-attribute-group-id attr))
                   " $* && chmod g+s $*\n"))
          ((= ?w (aref modes 2))
-          (insert "chown " (number-to-string (nth 2 attr))
+          (insert "chown " (number-to-string (file-attribute-user-id attr))
                   " $* && chmod u+s $*\n"))
          (t
           (insert "chown root $* && chmod u+s $*\n"))))
diff --git a/lisp/mail/feedmail.el b/lisp/mail/feedmail.el
index ec4a116..2b63343 100644
--- a/lisp/mail/feedmail.el
+++ b/lisp/mail/feedmail.el
@@ -2815,16 +2815,13 @@ return that value."
 (defun feedmail-default-date-generator (maybe-file)
   "Default function for generating Date: header contents."
   (feedmail-say-debug ">in-> feedmail-default-date-generator")
-  (when maybe-file
-    (feedmail-say-debug (concat "4 cre " (feedmail-rfc822-date (nth 4 
(file-attributes maybe-file)))))
-    (feedmail-say-debug (concat "5 mod " (feedmail-rfc822-date (nth 5 
(file-attributes maybe-file)))))
-    (feedmail-say-debug (concat "6 sta " (feedmail-rfc822-date (nth 6 
(file-attributes maybe-file))))))
-  (let ((date-time))
-    (if (and (not feedmail-queue-use-send-time-for-date) maybe-file)
-       (setq date-time (nth 5 (file-attributes maybe-file))))
-    (feedmail-rfc822-date date-time))
-  )
-
+  (let ((attr (and maybe-file (file-attributes maybe-file))))
+    (when attr
+      (feedmail-say-debug (concat "4 cre " (feedmail-rfc822-date 
(file-attribute-access-time attr))))
+      (feedmail-say-debug (concat "5 mod " (feedmail-rfc822-date 
(file-attribute-modification-time attr))))
+      (feedmail-say-debug (concat "6 sta " (feedmail-rfc822-date 
(file-attribute-status-change-time attr)))))
+    (feedmail-rfc822-date (and attr (not feedmail-queue-use-send-time-for-date)
+                              (file-attribute-modification-time attr)))))
 
 (defun feedmail-fiddle-date (maybe-file)
   "Fiddle Date:.  See documentation of `feedmail-date-generator'."
@@ -2874,7 +2871,8 @@ probably not appropriate for you."
              (concat (if (equal (match-beginning 1) (match-end 1)) "" "-") 
end-stuff))
       (setq end-stuff (concat "@" end-stuff)))
     (if (and (not feedmail-queue-use-send-time-for-message-id) maybe-file)
-       (setq date-time (nth 5 (file-attributes maybe-file))))
+       (setq date-time (file-attribute-modification-time
+                        (file-attributes maybe-file))))
     (format "<%d-%s%s%s>"
            (mod (random) 10000)
            (format-time-string "%a%d%b%Y%H%M%S" date-time)
diff --git a/lisp/mail/mailabbrev.el b/lisp/mail/mailabbrev.el
index 0ce1a3b..e5456d9 100644
--- a/lisp/mail/mailabbrev.el
+++ b/lisp/mail/mailabbrev.el
@@ -163,7 +163,8 @@ no aliases, which is represented by this being a table with 
no entries.)")
 (defun mail-abbrevs-sync-aliases ()
   (when mail-personal-alias-file
     (if (file-exists-p mail-personal-alias-file)
-       (let ((modtime (nth 5 (file-attributes mail-personal-alias-file))))
+       (let ((modtime (file-attribute-modification-time
+                       (file-attributes mail-personal-alias-file))))
          (if (not (equal mail-abbrev-modtime modtime))
              (progn
                (setq mail-abbrev-modtime modtime)
@@ -176,7 +177,8 @@ no aliases, which is represented by this being a table with 
no entries.)")
           (file-exists-p mail-personal-alias-file))
       (progn
        (setq mail-abbrev-modtime
-             (nth 5 (file-attributes mail-personal-alias-file)))
+             (file-attribute-modification-time
+              (file-attributes mail-personal-alias-file)))
        (build-mail-abbrevs)))
   (mail-abbrevs-sync-aliases)
   (add-function :around (local 'abbrev-expand-function)
diff --git a/lisp/mail/mspools.el b/lisp/mail/mspools.el
index aa91f36..2e8765e 100644
--- a/lisp/mail/mspools.el
+++ b/lisp/mail/mspools.el
@@ -387,7 +387,7 @@ nil."
   (let ((file (concat mspools-folder-directory spool))
        size)
     (setq file (or (file-symlink-p file) file))
-    (setq size (nth 7 (file-attributes file)))
+    (setq size (file-attribute-size (file-attributes file)))
     ;; size could be nil if the sym-link points to a non-existent file
     ;; so check this first.
     (if (and size  (> size 0))
diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el
index 9416d04..73a17ee 100644
--- a/lisp/mail/rmail.el
+++ b/lisp/mail/rmail.el
@@ -2028,10 +2028,10 @@ Value is the size of the newly read mail after 
conversion."
                          "the remote server"
                        proto)))
            ((and (file-exists-p tofile)
-                 (/= 0 (nth 7 (file-attributes tofile))))
+                 (/= 0 (file-attribute-size (file-attributes tofile))))
             (message "Getting mail from %s..." tofile))
            ((and (file-exists-p file)
-                 (/= 0 (nth 7 (file-attributes file))))
+                 (/= 0 (file-attribute-size (file-attributes file))))
             (message "Getting mail from %s..." file)))
       ;; Set TOFILE if have not already done so, and
       ;; rename or copy the file FILE to TOFILE if and as appropriate.
diff --git a/lisp/mail/sendmail.el b/lisp/mail/sendmail.el
index 50dd810..6fc91a3 100644
--- a/lisp/mail/sendmail.el
+++ b/lisp/mail/sendmail.el
@@ -561,7 +561,8 @@ This also saves the value of `send-mail-function' via 
Customize."
 
 (defun sendmail-sync-aliases ()
   (when mail-personal-alias-file
-    (let ((modtime (nth 5 (file-attributes mail-personal-alias-file))))
+    (let ((modtime (file-attribute-modification-time
+                   (file-attributes mail-personal-alias-file))))
       (or (equal mail-alias-modtime modtime)
          (setq mail-alias-modtime modtime
                mail-aliases t)))))
diff --git a/lisp/mh-e/mh-alias.el b/lisp/mh-e/mh-alias.el
index fa91042..257d6b3 100644
--- a/lisp/mh-e/mh-alias.el
+++ b/lisp/mh-e/mh-alias.el
@@ -78,7 +78,8 @@ If ARG is non-nil, set timestamp with the current time."
                     (function
                      (lambda (file)
                        (when (and file (file-exists-p file))
-                         (setq stamp (nth 5 (file-attributes file)))
+                         (setq stamp (file-attribute-modification-time
+                                     (file-attributes file)))
                          (or (> (car stamp) (car mh-alias-tstamp))
                              (and (= (car stamp) (car mh-alias-tstamp))
                                   (> (cadr stamp) (cadr mh-alias-tstamp)))))))
diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el
index 2fc7ac2..1aa7944 100644
--- a/lisp/net/ange-ftp.el
+++ b/lisp/net/ange-ftp.el
@@ -1361,11 +1361,13 @@ only return the directory part of FILE."
                  (ange-ftp-real-expand-file-name ange-ftp-netrc-filename)))
       (setq attr (ange-ftp-real-file-attributes file)))
     (if (and attr                      ; file exists.
-            (not (equal (nth 5 attr) ange-ftp-netrc-modtime))) ; file changed
+            (not (equal (file-attribute-modification-time attr)
+                        ange-ftp-netrc-modtime)))      ; file changed
        (save-match-data
          (if (or ange-ftp-disable-netrc-security-check
-                 (and (eq (nth 2 attr) (user-uid)) ; Same uids.
-                      (string-match ".r..------" (nth 8 attr))))
+                 (and (eq (file-attribute-user-id attr) (user-uid)) ; Same 
uids.
+                      (string-match ".r..------"
+                                    (file-attribute-modes attr))))
              (with-current-buffer
                ;; we are cheating a bit here.  I'm trying to do the equivalent
                ;; of find-file on the .netrc file, but then nuke it afterwards.
@@ -1389,7 +1391,8 @@ only return the directory part of FILE."
            (ange-ftp-message "%s either not owned by you or badly protected."
                              ange-ftp-netrc-filename)
            (sit-for 1))
-         (setq ange-ftp-netrc-modtime (nth 5 attr))))))
+         (setq ange-ftp-netrc-modtime
+               (file-attribute-modification-time attr))))))
 
 ;; Return a list of prefixes of the form 'address@hidden:' to be used when
 ;; completion is done in the root directory.
@@ -3242,7 +3245,8 @@ system TYPE.")
                ;; tell the process filter what size the transfer will be.
                (let ((attr (file-attributes temp)))
                  (if attr
-                     (ange-ftp-set-xfer-size host user (nth 7 attr))))
+                     (ange-ftp-set-xfer-size host user
+                                             (file-attribute-size attr))))
 
                ;; put or append the file.
                (let ((result (ange-ftp-send-cmd host user
@@ -3481,8 +3485,8 @@ system TYPE.")
   (let ((f1-parsed (ange-ftp-ftp-name f1))
         (f2-parsed (ange-ftp-ftp-name f2)))
     (if (or f1-parsed f2-parsed)
-        (let ((f1-mt (nth 5 (file-attributes f1)))
-              (f2-mt (nth 5 (file-attributes f2))))
+        (let ((f1-mt (file-attribute-modification-time (file-attributes f1)))
+              (f2-mt (file-attribute-modification-time (file-attributes f2))))
           (cond ((null f1-mt) nil)
                 ((null f2-mt) t)
                (t (time-less-p f2-mt f1-mt))))
@@ -3782,7 +3786,8 @@ so return the size on the remote host exactly. See RFC 
3659."
            ;; tell the process filter what size the file is.
            (let ((attr (file-attributes (or temp2 filename))))
              (if attr
-                 (ange-ftp-set-xfer-size t-host t-user (nth 7 attr))))
+                 (ange-ftp-set-xfer-size t-host t-user
+                                         (file-attribute-size attr))))
 
            (ange-ftp-send-cmd
             t-host
diff --git a/lisp/net/eudcb-mab.el b/lisp/net/eudcb-mab.el
index a213484..a69c77b 100644
--- a/lisp/net/eudcb-mab.el
+++ b/lisp/net/eudcb-mab.el
@@ -53,7 +53,8 @@ RETURN-ATTRS is a list of attributes to return, defaulting to
 
   (let ((fmt-string "%ln:%fn:%p:%e")
        (mab-buffer (get-buffer-create " *mab contacts*"))
-       (modified (nth 5 (file-attributes eudc-contacts-file)))
+       (modified (file-attribute-modification-time
+                  (file-attributes eudc-contacts-file)))
        result)
     (with-current-buffer mab-buffer
       (make-local-variable 'eudc-buffer-time)
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 97fdabd..64cc1a5 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -1667,7 +1667,7 @@ If CHARSET is nil then use UTF-8."
 (defun eww-read-bookmarks ()
   (let ((file (expand-file-name "eww-bookmarks" eww-bookmarks-directory)))
     (setq eww-bookmarks
-         (unless (zerop (or (nth 7 (file-attributes file)) 0))
+         (unless (zerop (or (file-attribute-size (file-attributes file)) 0))
            (with-temp-buffer
              (insert-file-contents file)
              (read (current-buffer)))))))
diff --git a/lisp/net/netrc.el b/lisp/net/netrc.el
index ec743dc..7b974eb 100644
--- a/lisp/net/netrc.el
+++ b/lisp/net/netrc.el
@@ -63,12 +63,14 @@
                        "port"))
              alist elem result pair)
           (if (and netrc-cache
-                  (equal (car netrc-cache) (nth 5 (file-attributes file))))
+                  (equal (car netrc-cache) (file-attribute-modification-time
+                                             (file-attributes file))))
              (insert (base64-decode-string (rot13-string (cdr netrc-cache))))
            (insert-file-contents file)
            (when (string-match "\\.gpg\\'" file)
              ;; Store the contents of the file heavily encrypted in memory.
-             (setq netrc-cache (cons (nth 5 (file-attributes file))
+             (setq netrc-cache (cons (file-attribute-modification-time
+                                       (file-attributes file))
                                      (rot13-string
                                       (base64-encode-string
                                        (buffer-string)))))))
diff --git a/lisp/net/newst-backend.el b/lisp/net/newst-backend.el
index 32893d2..b6fbdfb 100644
--- a/lisp/net/newst-backend.el
+++ b/lisp/net/newst-backend.el
@@ -1800,7 +1800,8 @@ download it from URL first."
   (let ((image-name (concat directory feed-name)))
     (if (and (file-exists-p image-name)
              (time-less-p nil
-                          (time-add (nth 5 (file-attributes image-name))
+                          (time-add (file-attribute-modification-time
+                                    (file-attributes image-name))
                                     (seconds-to-time 86400))))
         (newsticker--debug-msg "%s: Getting image for %s skipped"
                                (format-time-string "%A, %H:%M")
diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el
index 9af57fb..bcfaf40 100644
--- a/lisp/net/tramp-compat.el
+++ b/lisp/net/tramp-compat.el
@@ -142,15 +142,15 @@ returned."
   (defsubst tramp-compat-file-attribute-modification-time (attributes)
     "The modification time in ATTRIBUTES returned by `file-attributes'.
 This is the time of the last change to the file's contents, and
-is a list of integers (HIGH LOW USEC PSEC) in the same style
-as (current-time)."
+is a Lisp timestamp in the style of `current-time'."
     (nth 5 attributes)))
 
 (if (fboundp 'file-attribute-size)
     (defalias 'tramp-compat-file-attribute-size 'file-attribute-size)
   (defsubst tramp-compat-file-attribute-size (attributes)
     "The size (in bytes) in ATTRIBUTES returned by `file-attributes'.
-This is a floating point number if the size is too large for an integer."
+If the size is too large for a fixnum, this is a bignum in Emacs 27
+and later, and is a float in Emacs 26 and earlier."
     (nth 7 attributes)))
 
 (if (fboundp 'file-attribute-modes)
diff --git a/lisp/nxml/rng-loc.el b/lisp/nxml/rng-loc.el
index a9a1950..75d9831 100644
--- a/lisp/nxml/rng-loc.el
+++ b/lisp/nxml/rng-loc.el
@@ -407,7 +407,7 @@ or nil."
   "Return a list of rules for the schema locating file FILE."
   (setq file (expand-file-name file))
   (let ((cached (assoc file rng-schema-locating-file-alist))
-       (mtime (nth 5 (file-attributes file)))
+       (mtime (file-attribute-modification-time (file-attributes file)))
        parsed)
     (cond ((not mtime)
           (when cached
diff --git a/lisp/obsolete/fast-lock.el b/lisp/obsolete/fast-lock.el
index 41e48c3..21db321 100644
--- a/lisp/obsolete/fast-lock.el
+++ b/lisp/obsolete/fast-lock.el
@@ -441,7 +441,8 @@ See `fast-lock-mode'."
             ;; Only save if user's restrictions are satisfied.
             (and min-size (>= (buffer-size) min-size))
             (or fast-lock-save-others
-                (eq (user-uid) (nth 2 (file-attributes buffer-file-name))))
+                (eq (user-uid) (file-attribute-user-id
+                                (file-attributes buffer-file-name))))
             ;;
             ;; Only save if there are `face' properties to save.
             (text-property-not-all (point-min) (point-max) 'face nil))
diff --git a/lisp/obsolete/vc-arch.el b/lisp/obsolete/vc-arch.el
index 414ae77..9860c9d 100644
--- a/lisp/obsolete/vc-arch.el
+++ b/lisp/obsolete/vc-arch.el
@@ -304,8 +304,9 @@ Only the value `maybe' can be trusted :-(."
                ;; Buh?  Unexpected format.
                'edited
              (let ((ats (file-attributes file)))
-               (if (and (eq (nth 7 ats) (string-to-number (match-string 2)))
-                        (equal (format-time-string "%s" (nth 5 ats))
+               (if (and (eq (file-attribute-size ats) (string-to-number 
(match-string 2)))
+                        (equal (format-time-string
+                                "%s" (file-attribute-modification-time ats))
                                (match-string 1)))
                    'up-to-date
                  'edited)))))))))
@@ -402,7 +403,7 @@ CALLBACK expects (ENTRIES &optional MORE-TO-COME); see
 
 (defun vc-arch-diff3-rej-p (rej)
   (let ((attrs (file-attributes rej)))
-    (and attrs (< (nth 7 attrs) 60)
+    (and attrs (< (file-attribute-size attrs) 60)
         (with-temp-buffer
           (insert-file-contents rej)
           (goto-char (point-min))
diff --git a/lisp/org/ob-eval.el b/lisp/org/ob-eval.el
index 2bfaa08..f8cb285 100644
--- a/lisp/org/ob-eval.el
+++ b/lisp/org/ob-eval.el
@@ -120,7 +120,7 @@ function in various versions of Emacs.
       (delete-file input-file))
 
     (when (and error-file (file-exists-p error-file))
-      (when (< 0 (nth 7 (file-attributes error-file)))
+      (when (< 0 (file-attribute-size (file-attributes error-file)))
        (with-current-buffer (get-buffer-create error-buffer)
          (let ((pos-from-end (- (point-max) (point))))
            (or (bobp)
diff --git a/lisp/org/org-attach.el b/lisp/org/org-attach.el
index 9774e3a..203e71e 100644
--- a/lisp/org/org-attach.el
+++ b/lisp/org/org-attach.el
@@ -352,7 +352,7 @@ This checks for the existence of a \".git\" directory in 
that directory."
                   (shell-command-to-string
                    "git ls-files -zmo --exclude-standard") "\0" t))
           (if (and use-annex
-                   (>= (nth 7 (file-attributes new-or-modified))
+                   (>= (file-attribute-size (file-attributes new-or-modified))
                        org-attach-git-annex-cutoff))
               (call-process "git" nil nil nil "annex" "add" new-or-modified)
             (call-process "git" nil nil nil "add" new-or-modified))
diff --git a/lisp/org/org-macro.el b/lisp/org/org-macro.el
index 1033db2..e50b2f9 100644
--- a/lisp/org/org-macro.el
+++ b/lisp/org/org-macro.el
@@ -159,7 +159,8 @@ function installs the following ones: \"property\",
                          (format "(eval (format-time-string \"$1\" (or (and 
(org-string-nw-p \"$2\") (org-macro--vc-modified-time %s)) '%s)))"
                                  (prin1-to-string visited-file)
                                  (prin1-to-string
-                                  (nth 5 (file-attributes visited-file)))))))))
+                                  (file-attribute-modification-time
+                                   (file-attributes visited-file)))))))))
     ;; Initialize and install "n" macro.
     (org-macro--counter-initialize)
     (funcall update-templates
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 21d9cd8..873ae6b 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -230,8 +230,9 @@ file to byte-code before it is loaded."
   (let* ((age (lambda (file)
                (float-time
                 (time-subtract (current-time)
-                               (nth 5 (or (file-attributes (file-truename 
file))
-                                          (file-attributes file)))))))
+                               (file-attribute-modification-time
+                                (or (file-attributes (file-truename file))
+                                    (file-attributes file)))))))
         (base-name (file-name-sans-extension file))
         (exported-file (concat base-name ".el")))
     ;; tangle if the Org file is newer than the elisp file
@@ -22381,7 +22382,9 @@ returned by, e.g., `current-time'."
        ;; (e.g. HFS+) do not retain any finer granularity.  As
        ;; a consequence, make sure we return non-nil when the two
        ;; times are equal.
-       (not (time-less-p (cl-subseq (nth 5 (file-attributes file)) 0 2)
+       (not (time-less-p (cl-subseq (file-attribute-modification-time
+                                    (file-attributes file))
+                                   0 2)
                         (cl-subseq time 0 2)))))
 
 (defun org-compile-file (source process ext &optional err-msg log-buf spec)
diff --git a/lisp/org/ox-html.el b/lisp/org/ox-html.el
index 39f7d83..6166a4a 100644
--- a/lisp/org/ox-html.el
+++ b/lisp/org/ox-html.el
@@ -1935,7 +1935,8 @@ INFO is a plist used as a communication channel."
       (?c . ,(plist-get info :creator))
       (?C . ,(let ((file (plist-get info :input-file)))
               (format-time-string timestamp-format
-                                  (and file (nth 5 (file-attributes file))))))
+                                  (and file (file-attribute-modification-time
+                                             (file-attributes file))))))
       (?v . ,(or (plist-get info :html-validation-link) "")))))
 
 (defun org-html--build-pre/postamble (type info)
diff --git a/lisp/org/ox-publish.el b/lisp/org/ox-publish.el
index ba5a023..80ef239 100644
--- a/lisp/org/ox-publish.el
+++ b/lisp/org/ox-publish.el
@@ -879,7 +879,8 @@ If FILE is an Org file and provides a DATE keyword use it.  
In
 any other case use the file system's modification time.  Return
 time in `current-time' format."
   (let ((file (org-publish--expand-file-name file project)))
-    (if (file-directory-p file) (nth 5 (file-attributes file))
+    (if (file-directory-p file) (file-attribute-modification-time
+                                 (file-attributes file))
       (let ((date (org-publish-find-property file :date project)))
        ;; DATE is a secondary string.  If it contains a time-stamp,
        ;; convert it to internal format.  Otherwise, use FILE
@@ -889,7 +890,8 @@ time in `current-time' format."
                      (let ((value (org-element-interpret-data ts)))
                        (and (org-string-nw-p value)
                             (org-time-string-to-time value))))))
-             ((file-exists-p file) (nth 5 (file-attributes file)))
+             ((file-exists-p file) (file-attribute-modification-time
+                                     (file-attributes file)))
              (t (error "No such file: \"%s\"" file)))))))
 
 (defun org-publish-sitemap-default-entry (entry style project)
@@ -1348,8 +1350,7 @@ does not exist."
               (expand-file-name (or (file-symlink-p file) file)
                                 (file-name-directory file)))))
     (if (not attr) (error "No such file: \"%s\"" file)
-      (+ (ash (car (nth 5 attr)) 16)
-        (cadr (nth 5 attr))))))
+      (floor (float-time (file-attribute-modification-time attr))))))
 
 
 (provide 'ox-publish)
diff --git a/lisp/pcmpl-gnu.el b/lisp/pcmpl-gnu.el
index 16c9926..c4e5a67 100644
--- a/lisp/pcmpl-gnu.el
+++ b/lisp/pcmpl-gnu.el
@@ -316,7 +316,7 @@
     (while (pcomplete-here
            (if (and complete-within
                      (let* ((fa (file-attributes (pcomplete-arg 1)))
-                            (size (nth 7 fa)))
+                            (size (file-attribute-size fa)))
                        (and (numberp size)
                             (or (null large-file-warning-threshold)
                                 (< size large-file-warning-threshold)))))
diff --git a/lisp/pcmpl-rpm.el b/lisp/pcmpl-rpm.el
index 74ddb8b..7f164c9 100644
--- a/lisp/pcmpl-rpm.el
+++ b/lisp/pcmpl-rpm.el
@@ -71,7 +71,8 @@
   "Return a list of all installed rpm packages."
   (if (and pcmpl-rpm-cache
            pcmpl-rpm-cache-time
-           (let ((mtime (nth 5 (file-attributes pcmpl-rpm-cache-stamp-file))))
+           (let ((mtime (file-attribute-modification-time
+                         (file-attributes pcmpl-rpm-cache-stamp-file))))
              (and mtime (not (time-less-p pcmpl-rpm-cache-time mtime)))))
       pcmpl-rpm-packages
     (message "Getting list of installed rpms...")
diff --git a/lisp/play/cookie1.el b/lisp/play/cookie1.el
index 5ae2cb4..7a6a56b 100644
--- a/lisp/play/cookie1.el
+++ b/lisp/play/cookie1.el
@@ -125,7 +125,8 @@ and subsequent calls on the same file won't go to disk."
   (setq phrase-file (cookie-check-file phrase-file))
   (let ((sym (intern-soft phrase-file cookie-cache)))
     (and sym (not (equal (symbol-function sym)
-                        (nth 5 (file-attributes phrase-file))))
+                        (file-attribute-modification-time
+                          (file-attributes phrase-file))))
         (yes-or-no-p (concat phrase-file
                              " has changed.  Read new contents? "))
         (setq sym nil))
@@ -133,7 +134,8 @@ and subsequent calls on the same file won't go to disk."
        (symbol-value sym)
       (setq sym (intern phrase-file cookie-cache))
       (if startmsg (message "%s" startmsg))
-      (fset sym (nth 5 (file-attributes phrase-file)))
+      (fset sym (file-attribute-modification-time
+                 (file-attributes phrase-file)))
       (let (result)
        (with-temp-buffer
          (insert-file-contents (expand-file-name phrase-file))
diff --git a/lisp/progmodes/cmacexp.el b/lisp/progmodes/cmacexp.el
index 742ac80..7dcfb10 100644
--- a/lisp/progmodes/cmacexp.el
+++ b/lisp/progmodes/cmacexp.el
@@ -383,7 +383,8 @@ Optional arg DISPLAY non-nil means show messages in the 
echo area."
                       (not (member (file-name-nondirectory shell-file-name)
                                    msdos-shells)))
                   (eq exit-status 0))
-             (zerop (nth 7 (file-attributes (expand-file-name tempname))))
+             (zerop (file-attribute-size
+                     (file-attributes (expand-file-name tempname))))
              (progn
                (goto-char (point-min))
                ;; Put the messages inside a comment, so they won't get in
diff --git a/lisp/ps-bdf.el b/lisp/ps-bdf.el
index 301142e..f9632f0 100644
--- a/lisp/ps-bdf.el
+++ b/lisp/ps-bdf.el
@@ -70,13 +70,12 @@ for BDFNAME."
 
 (defsubst bdf-file-mod-time (filename)
   "Return modification time of FILENAME.
-The value is a list of integers in the same format as `current-time'."
-  (nth 5 (file-attributes filename)))
+The value is a timestamp in the same format as `current-time'."
+  (file-attribute-modification-time (file-attributes filename)))
 
 (defun bdf-file-newer-than-time (filename mod-time)
   "Return non-nil if and only if FILENAME is newer than MOD-TIME.
-MOD-TIME is a modification time as a list of integers in the same
-format as `current-time'."
+MOD-TIME is a modification time in the same format as `current-time'."
   (let ((new-mod-time (bdf-file-mod-time filename)))
     (time-less-p mod-time new-mod-time)))
 
@@ -168,8 +167,7 @@ FONT-INFO is a list of the following format:
     (BDFFILE MOD-TIME FONT-BOUNDING-BOX
      RELATIVE-COMPOSE BASELINE-OFFSET CODE-RANGE MAXLEN OFFSET-VECTOR)
 
-MOD-TIME is last modification time as a list of integers in the
-same format as `current-time'.
+MOD-TIME is last modification time in the same format as `current-time'.
 
 SIZE is a size of the font on 72 dpi device.  This value is got
 from SIZE record of the font.
diff --git a/lisp/server.el b/lisp/server.el
index fd02448..50684a2 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -540,13 +540,13 @@ Creates the directory if necessary and makes sure:
       (setq attrs (file-attributes dir 'integer)))
 
     ;; Check that it's safe for use.
-    (let* ((uid (nth 2 attrs))
+    (let* ((uid (file-attribute-user-id attrs))
           (w32 (eq system-type 'windows-nt))
            (unsafe (cond
-                    ((not (eq t (car attrs)))
+                    ((not (eq t (file-attribute-type attrs)))
                      (if (null attrs) "its attributes can't be checked"
                        (format "it is a %s"
-                               (if (stringp (car attrs))
+                               (if (stringp (file-attribute-type attrs))
                                    "symlink" "file"))))
                     ((and w32 (zerop uid)) ; on FAT32?
                      (display-warning
diff --git a/lisp/simple.el b/lisp/simple.el
index ffd7fcc..f0fcbf5 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -3827,7 +3827,8 @@ interactively, this is t."
             ;; No output; error?
               (let ((output
                      (if (and error-file
-                              (< 0 (nth 7 (file-attributes error-file))))
+                              (< 0 (file-attribute-size
+                                   (file-attributes error-file))))
                          (format "some error output%s"
                                  (if shell-command-default-error-buffer
                                      (format " to the \"%s\" buffer"
@@ -3850,7 +3851,7 @@ interactively, this is t."
               )))))
 
     (when (and error-file (file-exists-p error-file))
-      (if (< 0 (nth 7 (file-attributes error-file)))
+      (if (< 0 (file-attribute-size (file-attributes error-file)))
          (with-current-buffer (get-buffer-create error-buffer)
            (let ((pos-from-end (- (point-max) (point))))
              (or (bobp)
diff --git a/lisp/speedbar.el b/lisp/speedbar.el
index 48829d4..f3ea048 100644
--- a/lisp/speedbar.el
+++ b/lisp/speedbar.el
@@ -1466,9 +1466,10 @@ Return nil if not applicable.  If FILENAME, then use that
 instead of reading it from the speedbar buffer."
   (let* ((item (or filename (speedbar-line-file)))
         (attr (if item (file-attributes item) nil)))
-    (if (and item attr) (dframe-message "%s %-6d %s" (nth 8 attr)
-                                         (nth 7 attr) item)
-      nil)))
+    (if (and item attr)
+       (dframe-message "%s %-6d %s"
+                       (file-attribute-modes attr)
+                       (file-attribute-size attr) item))))
 
 (defun speedbar-item-info-tag-helper ()
   "Display info about a tag that is on the current line.
@@ -3008,13 +3009,13 @@ the file being checked."
                                              (cdr (car oa))))))
          nil
        ;; Find out if the object is out of date or not.
-       (let ((date1 (nth 5 (file-attributes fulln)))
-             (date2 (nth 5 (file-attributes (concat
-                                             (file-name-sans-extension fulln)
-                                              (cdr (car oa)))))))
-         (if (or (< (car date1) (car date2))
-                 (and (= (car date1) (car date2))
-                      (< (nth 1 date1) (nth 1 date2))))
+       (let ((date1 (file-attribute-modification-time
+                     (file-attributes fulln)))
+             (date2 (file-attribute-modification-time
+                     (file-attributes (concat
+                                       (file-name-sans-extension fulln)
+                                       (cdr (car oa)))))))
+         (if (time-less-p date1 date2)
              (car speedbar-obj-indicator)
            (cdr speedbar-obj-indicator)))))))
 
diff --git a/lisp/thumbs.el b/lisp/thumbs.el
index 26c9935..067a32b 100644
--- a/lisp/thumbs.el
+++ b/lisp/thumbs.el
@@ -210,7 +210,9 @@ reached."
           (mapcar
            (lambda (f)
              (let ((fattribs-list (file-attributes f)))
-               `(,(nth 4 fattribs-list) ,(nth 7 fattribs-list) ,f)))
+               `(,(file-attribute-access-time fattribs-list)
+                 ,(file-attribute-size fattribs-list)
+                 ,f)))
            (directory-files (thumbs-thumbsdir) t (image-file-name-regexp)))
           (lambda (l1 l2) (time-less-p (car l1) (car l2)))))
         (dirsize (apply '+ (mapcar (lambda (x) (cadr x)) files-list))))
diff --git a/lisp/time.el b/lisp/time.el
index 94f7009..f8d933d 100644
--- a/lisp/time.el
+++ b/lisp/time.el
@@ -365,7 +365,8 @@ Switches from the 1 to 5 to 15 minute load average, and 
then back to 1."
     (while (and mail-files (= size 0))
       ;; Count size of regular files only.
       (setq size (+ size (or (and (file-regular-p (car mail-files))
-                                 (nth 7 (file-attributes (car mail-files))))
+                                 (file-attribute-size
+                                  (file-attributes (car mail-files))))
                             0)))
       (setq mail-files (cdr mail-files)))
     (if (> size 0)
@@ -483,7 +484,8 @@ update which can wait for the next redisplay."
 (defun display-time-file-nonempty-p (file)
   (let ((remote-file-name-inhibit-cache (- display-time-interval 5)))
     (and (file-exists-p file)
-        (< 0 (nth 7 (file-attributes (file-chase-links file)))))))
+        (< 0 (file-attribute-size
+              (file-attributes (file-chase-links file)))))))
 
 ;;;###autoload
 (define-minor-mode display-time-mode
diff --git a/lisp/url/url-cache.el b/lisp/url/url-cache.el
index 309c96c..3765d9d 100644
--- a/lisp/url/url-cache.el
+++ b/lisp/url/url-cache.el
@@ -86,10 +86,10 @@ FILE can be created or overwritten."
 The actual return value is the last modification time of the cache file."
   (let* ((fname (url-cache-create-filename url))
         (attribs (file-attributes fname)))
-    (and fname                         ; got a filename
-        (file-exists-p fname)          ; file exists
-        (not (eq (nth 0 attribs) t))   ; Its not a directory
-        (nth 5 attribs))))             ; Can get last mod-time
+    (and fname
+        (file-exists-p fname)
+        (not (eq (file-attribute-type attribs) t))
+        (file-attribute-modification-time attribs))))
 
 (defun url-cache-create-filename-human-readable (url)
   "Return a filename in the local cache for URL."
@@ -226,7 +226,7 @@ considered \"expired\"."
              (setq deleted-files (1+ deleted-files))))
           ((time-less-p
             (time-add
-             (nth 5 (file-attributes file))
+             (file-attribute-modification-time (file-attributes file))
              (seconds-to-time url-cache-expire-time))
             now)
            (delete-file file)
diff --git a/lisp/url/url-file.el b/lisp/url/url-file.el
index 1c7c20e..02542cc 100644
--- a/lisp/url/url-file.el
+++ b/lisp/url/url-file.el
@@ -70,7 +70,7 @@ to them."
            buff func
            func args
            args efs))
-  (let ((size (nth 7 (file-attributes name))))
+  (let ((size (file-attribute-size (file-attributes name))))
     (with-current-buffer buff
       (goto-char (point-max))
       (if (/= -1 size)
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index b91a2ba..6c189c1 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -1450,7 +1450,7 @@ modified lines of the diff."
   ;; can just remove the file altogether.  Very handy for .rej files if we
   ;; remove hunks as we apply them.
   (when (and buffer-file-name
-            (eq 0 (nth 7 (file-attributes buffer-file-name))))
+            (eq 0 (file-attribute-size (file-attributes buffer-file-name))))
     (delete-file buffer-file-name)))
 
 (defun diff-delete-empty-files ()
diff --git a/lisp/vc/pcvs-info.el b/lisp/vc/pcvs-info.el
index edcfc6e..2947733 100644
--- a/lisp/vc/pcvs-info.el
+++ b/lisp/vc/pcvs-info.el
@@ -451,7 +451,8 @@ DIR can also be a file."
               ((not (file-exists-p (concat dir f))) (setq type 'MISSING))
               ((equal rev "0") (setq type 'ADDED rev nil))
               ((equal date "Result of merge") (setq subtype 'MERGED))
-              ((let ((mtime (nth 5 (file-attributes (concat dir f))))
+              ((let ((mtime (file-attribute-modification-time
+                             (file-attributes (concat dir f))))
                      (system-time-locale "C"))
                  (setq timestamp (format-time-string "%c" mtime t))
                  ;; Solaris sometimes uses "Wed Sep 05", not "Wed Sep  5".
diff --git a/lisp/vc/vc-bzr.el b/lisp/vc/vc-bzr.el
index 630932f..aa3d144 100644
--- a/lisp/vc/vc-bzr.el
+++ b/lisp/vc/vc-bzr.el
@@ -268,8 +268,8 @@ in the repository root directory of FILE."
                  ;; If file is in dirstate, can only be added (b#8025).
                  ((or (not (match-beginning 4))
                       (eq (char-after (match-beginning 4)) ?a)) 'added)
-                 ((or (and (eq (string-to-number (match-string 3))
-                               (nth 7 (file-attributes file)))
+                 ((or (and (eql (string-to-number (match-string 3))
+                               (file-attribute-size (file-attributes file)))
                            (equal (match-string 5)
                                   (save-match-data (vc-bzr-sha1 file)))
                            ;; For a file, does the executable state match?
@@ -281,7 +281,8 @@ in the repository root directory of FILE."
                                        ?x
                                        (mapcar
                                         'identity
-                                        (nth 8 (file-attributes file))))))
+                                       (file-attribute-modes
+                                        (file-attributes file))))))
                                  (if (eq (char-after (match-beginning 7))
                                          ?y)
                                      exe
@@ -291,8 +292,8 @@ in the repository root directory of FILE."
                        ;; checkouts \2 is empty and we need to
                        ;; look for size in \6.
                        (eq (match-beginning 2) (match-end 2))
-                       (eq (string-to-number (match-string 6))
-                           (nth 7 (file-attributes file)))
+                       (eql (string-to-number (match-string 6))
+                            (file-attribute-size (file-attributes file)))
                        (equal (match-string 5)
                               (vc-bzr-sha1 file))))
                   'up-to-date)
diff --git a/lisp/vc/vc-cvs.el b/lisp/vc/vc-cvs.el
index 54ece6c..ac98d99 100644
--- a/lisp/vc/vc-cvs.el
+++ b/lisp/vc/vc-cvs.el
@@ -57,7 +57,7 @@
                     ;; (We actually shouldn't trust this, but there is
                     ;; no other way to learn this from CVS at the
                     ;; moment (version 1.9).)
-                    (string-match "r-..-..-." (nth 8 attrib)))
+                   (string-match "r-..-..-." (file-attribute-modes attrib)))
                'announce
              'implicit))))))
 
@@ -257,7 +257,7 @@ See also variable `vc-cvs-sticky-date-format-string'."
   ;; If the file has not changed since checkout, consider it `up-to-date'.
   ;; Otherwise consider it `edited'.
   (let ((checkout-time (vc-file-getprop file 'vc-checkout-time))
-        (lastmod (nth 5 (file-attributes file))))
+        (lastmod (file-attribute-modification-time (file-attributes file))))
     (cond
      ((equal checkout-time lastmod) 'up-to-date)
      ((string= (vc-working-revision file) "0") 'added)
@@ -524,7 +524,8 @@ The changes are between FIRST-REVISION and SECOND-REVISION."
                     (string= (match-string 1) "P "))
                 (vc-file-setprop file 'vc-state 'up-to-date)
                 (vc-file-setprop file 'vc-checkout-time
-                                 (nth 5 (file-attributes file)))
+                                (file-attribute-modification-time
+                                 (file-attributes file)))
                 0);; indicate success to the caller
                ;; Merge successful, but our own changes are still in the file
                ((string= (match-string 1) "M ")
@@ -748,7 +749,8 @@ If UPDATE is non-nil, then update (resynch) any affected 
buffers."
                    (vc-file-setprop file 'vc-state 'up-to-date)
                    (vc-file-setprop file 'vc-working-revision nil)
                    (vc-file-setprop file 'vc-checkout-time
-                                    (nth 5 (file-attributes file))))
+                                    (file-attribute-modification-time
+                                     (file-attributes file))))
                   ((or (string= state "M")
                        (string= state "C"))
                    (vc-file-setprop file 'vc-state 'edited)
@@ -931,7 +933,8 @@ state."
         (cond
          ((string-match "Up-to-date" status)
           (vc-file-setprop file 'vc-checkout-time
-                           (nth 5 (file-attributes file)))
+                           (file-attribute-modification-time
+                            (file-attributes file)))
           'up-to-date)
          ((string-match "Locally Modified" status)             'edited)
          ((string-match "Needs Merge" status)                  'needs-merge)
@@ -1174,7 +1177,7 @@ is non-nil."
     ;; (which is based on textual comparison), because there can be problems
     ;; generating a time string that looks exactly like the one from CVS.
     (let* ((time (match-string 2))
-           (mtime (nth 5 (file-attributes file)))
+           (mtime (file-attribute-modification-time (file-attributes file)))
            (parsed-time (progn (require 'parse-time)
                                (parse-time-string (concat time " +0000")))))
       (cond ((and (not (string-match "\\+" time))
diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el
index 76eec88..3696573 100644
--- a/lisp/vc/vc-hg.el
+++ b/lisp/vc/vc-hg.el
@@ -833,7 +833,7 @@ if we don't understand a construct, we signal
     (with-temp-buffer
       (let ((attr (file-attributes hgignore)))
         (when attr (insert-file-contents hgignore))
-        (push (list hgignore (nth 5 attr) (nth 7 attr))
+        (push (list hgignore (file-attribute-modification-time attr) 
(file-attribute-size attr))
               vc-hg--hgignore-filenames))
       (while (not (eobp))
         ;; This list of pattern-file commands isn't complete, but it
@@ -897,8 +897,8 @@ REPO must be the directory name of an hg repository."
              (saved-mtime (nth 1 fs))
              (saved-size (nth 2 fs))
              (attr (file-attributes (nth 0 fs)))
-             (current-mtime (nth 5 attr))
-             (current-size (nth 7 attr)))
+             (current-mtime (file-attribute-modification-time attr))
+             (current-size (file-attribute-size attr)))
         (unless (and (equal saved-mtime current-mtime)
                      (equal saved-size current-size))
           (setf valid nil))))
@@ -968,8 +968,8 @@ Avoids the need to repeatedly scan dirstate on repeated 
calls to
 `vc-hg-state', as we see during registration queries.")
 
 (defun vc-hg--cached-dirstate-search (dirstate dirstate-attr ascii-fname)
-  (let* ((mtime (nth 5 dirstate-attr))
-         (size (nth 7 dirstate-attr))
+  (let* ((mtime (file-attribute-modification-time dirstate-attr))
+         (size (file-attribute-size dirstate-attr))
          (cache vc-hg--dirstate-scan-cache)
          )
     (if (and cache
@@ -1012,7 +1012,7 @@ hg binary."
          ;; Repository must be in an understood format
          (not (vc-hg--requirements-understood-p repo))
          ;; Dirstate too small to be valid
-         (< (nth 7 dirstate-attr) 40)
+         (< (file-attribute-size dirstate-attr) 40)
          (progn
            (setf repo-relative-filename
                  (file-relative-name truename repo))
@@ -1036,8 +1036,9 @@ hg binary."
               ((eq state ?n)
                (let ((vc-hg-size (nth 2 dirstate-entry))
                      (vc-hg-mtime (nth 3 dirstate-entry))
-                     (fs-size (nth 7 stat))
-                     (fs-mtime (vc-hg--time-to-integer (nth 5 stat))))
+                     (fs-size (file-attribute-size stat))
+                     (fs-mtime (vc-hg--time-to-integer
+                               (file-attribute-modification-time stat))))
                  (if (and (eql vc-hg-size fs-size) (eql vc-hg-mtime fs-mtime))
                      'up-to-date
                    'edited)))
diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el
index f1b622b..84e11f2 100644
--- a/lisp/vc/vc-hooks.el
+++ b/lisp/vc/vc-hooks.el
@@ -658,7 +658,7 @@ Before doing that, check if there are any old backups and 
get rid of them."
       ;; If the file was saved in the same second in which it was
       ;; checked out, clear the checkout-time to avoid confusion.
       (if (equal (vc-file-getprop file 'vc-checkout-time)
-                (nth 5 (file-attributes file)))
+                (file-attribute-modification-time (file-attributes file)))
          (vc-file-setprop file 'vc-checkout-time nil))
       (if (vc-state-refresh file backend)
          (vc-mode-line file backend)))
diff --git a/lisp/vc/vc-rcs.el b/lisp/vc/vc-rcs.el
index 9fa52bf..51a4443 100644
--- a/lisp/vc/vc-rcs.el
+++ b/lisp/vc/vc-rcs.el
@@ -955,11 +955,10 @@ Uses `rcs2log' which only works for RCS and CVS."
   "Return non-nil if FILE is newer than its RCS master.
 This likely means that FILE has been changed with respect
 to its master version."
-  (let ((file-time (nth 5 (file-attributes file)))
-       (master-time (nth 5 (file-attributes (vc-master-name file)))))
-    (or (> (nth 0 file-time) (nth 0 master-time))
-       (and (= (nth 0 file-time) (nth 0 master-time))
-            (> (nth 1 file-time) (nth 1 master-time))))))
+  (let ((file-time (file-attribute-modification-time (file-attributes file)))
+       (master-time (file-attribute-modification-time
+                     (file-attributes (vc-master-name file)))))
+    (time-less-p master-time file-time)))
 
 (defun vc-rcs-find-most-recent-rev (branch)
   "Find most recent revision on BRANCH."
diff --git a/lisp/vc/vc-svn.el b/lisp/vc/vc-svn.el
index 2cbf34b..4b1a34b 100644
--- a/lisp/vc/vc-svn.el
+++ b/lisp/vc/vc-svn.el
@@ -479,7 +479,8 @@ The changes are between FIRST-VERSION and SECOND-VERSION."
                ((string= (match-string 2) "U")
                 (vc-file-setprop file 'vc-state 'up-to-date)
                 (vc-file-setprop file 'vc-checkout-time
-                                 (nth 5 (file-attributes file)))
+                                 (file-attribute-modification-time
+                                 (file-attributes file)))
                 0);; indicate success to the caller
                ;; Merge successful, but our own changes are still in the file
                ((string= (match-string 2) "G")
@@ -729,7 +730,8 @@ Set file properties accordingly.  If FILENAME is non-nil, 
return its status."
           (if (eq (char-after (match-beginning 1)) ?*)
               'needs-update
              (vc-file-setprop file 'vc-checkout-time
-                              (nth 5 (file-attributes file)))
+                              (file-attribute-modification-time
+                              (file-attributes file)))
             'up-to-date))
          ((eq status ?A)
           ;; If the file was actually copied, (match-string 2) is "-".
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index 487594b..d3d66d6 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -1481,7 +1481,8 @@ After check-out, runs the normal hook `vc-checkout-hook'."
                              nil)
                         'up-to-date
                        'edited))
-        (vc-checkout-time . ,(nth 5 (file-attributes file))))))
+        (vc-checkout-time . ,(file-attribute-modification-time
+                             (file-attributes file))))))
   (vc-resynch-buffer file t t)
   (run-hooks 'vc-checkout-hook))
 
@@ -1558,7 +1559,8 @@ Runs the normal hooks `vc-before-checkin-hook' and 
`vc-checkin-hook'."
          (vc-call-backend backend 'checkin files comment rev)
          (mapc 'vc-delete-automatic-version-backups files))
        `((vc-state . up-to-date)
-         (vc-checkout-time . ,(nth 5 (file-attributes file)))
+         (vc-checkout-time . ,(file-attribute-modification-time
+                              (file-attributes file)))
          (vc-working-revision . nil)))
      (message "Checking in %s...done" (vc-delistify files)))
    'vc-checkin-hook
@@ -2568,7 +2570,8 @@ its name; otherwise return nil."
        (vc-delete-automatic-version-backups file))
      (vc-call revert file backup-file))
    `((vc-state . up-to-date)
-     (vc-checkout-time . ,(nth 5 (file-attributes file)))))
+     (vc-checkout-time . ,(file-attribute-modification-time
+                          (file-attributes file)))))
   (vc-resynch-buffer file t t))
 
 ;;;###autoload
diff --git a/lisp/xdg.el b/lisp/xdg.el
index a896eb8..f818324 100644
--- a/lisp/xdg.el
+++ b/lisp/xdg.el
@@ -295,7 +295,9 @@ Results are cached in `xdg-mime-table'."
               (files ()))
     (let ((mtim1 (get 'xdg-mime-table 'mtime))
           (mtim2 (cl-loop for f in caches when (file-readable-p f)
-                          maximize (float-time (nth 5 (file-attributes f))))))
+                          maximize (float-time
+                                   (file-attribute-modification-time
+                                    (file-attributes f))))))
       ;; If one of the MIME/Desktop cache files has been modified:
       (when (or (null mtim1) (time-less-p mtim1 mtim2))
         (setq xdg-mime-table nil)))
diff --git a/src/buffer.c b/src/buffer.c
index 1f18dbd..024e64f 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -6010,11 +6010,11 @@ An entry (TEXT . POSITION) represents the deletion of 
the string TEXT
 from (abs POSITION).  If POSITION is positive, point was at the front
 of the text being deleted; if negative, point was at the end.
 
-An entry (t HIGH LOW USEC PSEC) indicates that the buffer was previously
-unmodified; (HIGH LOW USEC PSEC) is in the same style as (current-time)
-and is the visited file's modification time, as of that time.  If the
-modification time of the most recent save is different, this entry is
-obsolete.
+An entry (t . TIMESTAMP), where TIMESTAMP is in the style of
+`current-time', indicates that the buffer was previously unmodified;
+TIMESTAMP is the visited file's modification time, as of that time.
+If the modification time of the most recent save is different, this
+entry is obsolete.
 
 An entry (t . 0) means the buffer was previously unmodified but
 its time stamp was unknown because it was not associated with a file.
diff --git a/src/dired.c b/src/dired.c
index 70c5bb2..7ad401c 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -347,7 +347,7 @@ DEFUN ("directory-files-and-attributes", 
Fdirectory_files_and_attributes,
        doc: /* Return a list of names of files and their attributes in 
DIRECTORY.
 Value is a list of the form:
 
-  ((FILE1 FILE1-ATTRS) (FILE2 FILE2-ATTRS) ...)
+  ((FILE1 . FILE1-ATTRS) (FILE2 . FILE2-ATTRS) ...)
 
 where each FILEn-ATTRS is the attributes of FILEn as returned
 by `file-attributes'.
@@ -866,26 +866,22 @@ provided: `file-attribute-type', 
`file-attribute-link-number',
 Elements of the attribute list are:
  0. t for directory, string (name linked to) for symbolic link, or nil.
  1. Number of links to file.
- 2. File uid as a string or a number.  If a string value cannot be
-  looked up, an integer value is returned, which could be a fixnum,
-  if it's small enough, otherwise a bignum.
+ 2. File uid as a string or (if ID-FORMAT is `integer' or a string value
+  cannot be looked up) as an integer.
  3. File gid, likewise.
- 4. Last access time, as a list of integers (HIGH LOW USEC PSEC) in the
-  same style as (current-time).
+ 4. Last access time, in the style of `current-time'.
   (See a note below about access time on FAT-based filesystems.)
  5. Last modification time, likewise.  This is the time of the last
   change to the file's contents.
  6. Last status change time, likewise.  This is the time of last change
   to the file's attributes: owner and group, access mode bits, etc.
- 7. Size in bytes, which could be a fixnum, if it's small enough,
-  otherwise a bignum.
+ 7. Size in bytes, as an integer.
  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, which could be a fixnum, if it's small enough,
-  otherwise a bignum.
-11. Filesystem device number.  If it is larger than what a fixnum
-  can hold, it is a bignum.
+10. inode number, as a nonnegative integer.
+11. Filesystem device number, as an integer.
 
+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.
 
diff --git a/src/editfns.c b/src/editfns.c
index 047a73f..ec6e8ba 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -1656,8 +1656,7 @@ See `current-time-string' for the various forms of a time 
value.  */)
 DEFUN ("get-internal-run-time", Fget_internal_run_time, Sget_internal_run_time,
        0, 0, 0,
        doc: /* Return the current run time used by Emacs.
-The time is returned as a list (HIGH LOW USEC PSEC), using the same
-style as (current-time).
+The time is returned as in the style of `current-time'.
 
 On systems that can't determine the run time, `get-internal-run-time'
 does the same thing as `current-time'.  */)
diff --git a/src/fileio.c b/src/fileio.c
index 5ca7c59..7fb8658 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -5454,10 +5454,9 @@ See Info node `(elisp)Modification Time' for more 
details.  */)
 DEFUN ("visited-file-modtime", Fvisited_file_modtime,
        Svisited_file_modtime, 0, 0, 0,
        doc: /* Return the current buffer's recorded visited file modification 
time.
-The value is a list of the form (HIGH LOW USEC PSEC), like the time values that
-`file-attributes' returns.  If the current buffer has no recorded file
-modification time, this function returns 0.  If the visited file
-doesn't exist, return -1.
+Return a Lisp timestamp (as in `current-time') if the current buffer
+has a recorded file modification time, 0 if it doesn't, and -1 if the
+visited file doesn't exist.
 See Info node `(elisp)Modification Time' for more details.  */)
   (void)
 {
@@ -5473,9 +5472,8 @@ DEFUN ("set-visited-file-modtime", 
Fset_visited_file_modtime,
 Useful if the buffer was not read from the file normally
 or if the file itself has been changed for some known benign reason.
 An argument specifies the modification time value to use
-\(instead of that of the visited file), in the form of a list
-\(HIGH LOW USEC PSEC) or an integer flag as returned by
-`visited-file-modtime'.  */)
+\(instead of that of the visited file), in the form of a time value as
+in `current-time' or an integer flag as returned by `visited-file-modtime'.  
*/)
   (Lisp_Object time_flag)
 {
   if (!NILP (time_flag))
diff --git a/src/keyboard.c b/src/keyboard.c
index 008d3b9..1c1f151 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -4377,8 +4377,8 @@ timer_check (void)
 
 DEFUN ("current-idle-time", Fcurrent_idle_time, Scurrent_idle_time, 0, 0, 0,
        doc: /* Return the current length of Emacs idleness, or nil.
-The value when Emacs is idle is a list of four integers (HIGH LOW USEC PSEC)
-in the same style as (current-time).
+The value when Emacs is idle is a Lisp timestamp in the style of
+`current-time'.
 
 The value when Emacs is not idle is nil.
 
diff --git a/src/process.c b/src/process.c
index b4ba641..a9638df 100644
--- a/src/process.c
+++ b/src/process.c
@@ -7934,8 +7934,7 @@ integer or floating point values.
  majflt  -- number of major page faults (number)
  cminflt -- cumulative number of minor page faults (number)
  cmajflt -- cumulative number of major page faults (number)
- utime   -- user time used by the process, in (current-time) format,
-              which is a list of integers (HIGH LOW USEC PSEC)
+ utime   -- user time used by the process, in `current-time' format
  stime   -- system time used by the process (current-time)
  time    -- sum of utime and stime (current-time)
  cutime  -- user time used by the process and its children (current-time)
@@ -7947,7 +7946,7 @@ integer or floating point values.
  start   -- time the process started (current-time)
  vsize   -- virtual memory size of the process in KB's (number)
  rss     -- resident set size of the process in KB's (number)
- etime   -- elapsed time the process is running, in (HIGH LOW USEC PSEC) format
+ etime   -- elapsed time the process is running (current-time)
  pcpu    -- percents of CPU time used by the process (floating-point number)
  pmem    -- percents of total physical memory used by process's resident set
               (floating-point number)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]