emacs-diffs
[Top][All Lists]
Advanced

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

master 106456d01b 1/2: Use secondary groups when checking permissions in


From: Michael Albinus
Subject: master 106456d01b 1/2: Use secondary groups when checking permissions in Tramp (Bug#57044)
Date: Tue, 6 Sep 2022 06:34:04 -0400 (EDT)

branch: master
commit 106456d01bd9b9ffe82c00c4b09a9094a603438e
Author: Michael Albinus <michael.albinus@gmx.de>
Commit: Michael Albinus <michael.albinus@gmx.de>

    Use secondary groups when checking permissions in Tramp (Bug#57044)
    
    * lisp/net/tramp.el (tramp-check-cached-permissions): Check also for
    secondary groups.  (Bug#57044)
    (tramp-get-remote-groups):
    * lisp/net/tramp-adb.el (tramp-adb-handle-get-remote-groups):
    * lisp/net/tramp-sh.el (tramp-sh-handle-get-remote-groups):
    * lisp/net/tramp-sudoedit.el (tramp-sudoedit-handle-get-remote-groups):
    New defuns.
    
    * lisp/net/tramp.el (tramp-file-name-for-operation):
    * lisp/net/tramp-adb.el (tramp-adb-file-name-handler-alist):
    * lisp/net/tramp-archive.el (tramp-archive-file-name-handler-alist):
    * lisp/net/tramp-crypt.el (tramp-crypt-file-name-handler-alist):
    * lisp/net/tramp-gvfs.el (tramp-gvfs-file-name-handler-alist):
    * lisp/net/tramp-rclone.el (tramp-rclone-file-name-handler-alist):
    * lisp/net/tramp-sh.el (tramp-sh-file-name-handler-alist):
    * lisp/net/tramp-smb.el (tramp-smb-file-name-handler-alist):
    * lisp/net/tramp-sshfs.el (tramp-sshfs-file-name-handler-alist):
    * lisp/net/tramp-sudoedit.el (tramp-sudoedit-file-name-handler-alist):
    Add `tramp-get-remote-groups'.
    
    * lisp/net/tramp.el:
    * lisp/net/tramp-adb.el:
    * lisp/net/tramp-cache.el:
    * lisp/net/tramp-crypt.el:
    * lisp/net/tramp-fuse.el:
    * lisp/net/tramp-gvfs.el:
    * lisp/net/tramp-integration.el:
    * lisp/net/tramp-rclone.el:
    * lisp/net/tramp-sh.el:
    * lisp/net/tramp-smb.el:
    * lisp/net/tramp-sudoedit.el: Use `blank' in `rx' forms.
    
    * test/lisp/net/tramp-archive-tests.el:
    * test/lisp/net/tramp-tests.el: Use `blank' in `rx' forms.
---
 lisp/net/tramp-adb.el                | 74 ++++++++++++++++++++++++------------
 lisp/net/tramp-archive.el            |  1 +
 lisp/net/tramp-cache.el              |  2 +-
 lisp/net/tramp-crypt.el              |  1 +
 lisp/net/tramp-fuse.el               |  2 +-
 lisp/net/tramp-gvfs.el               |  7 ++--
 lisp/net/tramp-integration.el        |  8 ++--
 lisp/net/tramp-rclone.el             |  9 +++--
 lisp/net/tramp-sh.el                 | 55 ++++++++++++++++++++-------
 lisp/net/tramp-smb.el                | 49 ++++++++++++------------
 lisp/net/tramp-sshfs.el              |  1 +
 lisp/net/tramp-sudoedit.el           | 36 +++++++++++++++---
 lisp/net/tramp.el                    | 66 ++++++++++++++++++++------------
 test/lisp/net/tramp-archive-tests.el |  6 +--
 test/lisp/net/tramp-tests.el         |  8 ++--
 15 files changed, 213 insertions(+), 112 deletions(-)

diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index ab38ffa0cf..3fb28d91ea 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -55,7 +55,7 @@ It is used for TCP/IP devices."
 (defconst tramp-adb-method "adb"
   "When this method name is used, forward all calls to Android Debug Bridge.")
 
-(defcustom tramp-adb-prompt (rx bol (* (not (any "#$\n\r"))) (any "#$") space)
+(defcustom tramp-adb-prompt (rx bol (* (not (any "#$\n\r"))) (any "#$") blank)
   "Regexp used as prompt in almquist shell."
   :type 'regexp
   :version "28.1"
@@ -71,20 +71,20 @@ It is used for TCP/IP devices."
   "Regexp for date time format in ls output."))
 
 (defconst tramp-adb-ls-date-regexp
-  (rx space (regexp tramp-adb-ls-date-year-regexp)
-      space (regexp tramp-adb-ls-date-time-regexp)
-      space)
+  (rx blank (regexp tramp-adb-ls-date-year-regexp)
+      blank (regexp tramp-adb-ls-date-time-regexp)
+      blank)
   "Regexp for date format in ls output.")
 
 (defconst tramp-adb-ls-toolbox-regexp
-  (rx bol (* space) (group (+ (any ".-" alpha)))               ; \1 permissions
-      (? (+ space) (+ digit))                        ; links (Android 7/toybox)
-      (* space) (group (+ (not space)))                                ; \2 
username
-      (+ space) (group (+ (not space)))                                ; \3 
group
-      (+ space) (group (+ digit))                              ; \4 size
-      (+ space) (group (regexp tramp-adb-ls-date-year-regexp)
-                space (regexp tramp-adb-ls-date-time-regexp))  ; \5 date
-      space (group (* nonl)) eol)                              ; \6 filename
+  (rx bol (* blank) (group (+ (any ".-" alpha)))               ; \1 permissions
+      (? (+ blank) (+ digit))                        ; links (Android 7/toybox)
+      (* blank) (group (+ (not blank)))                                ; \2 
username
+      (+ blank) (group (+ (not blank)))                                ; \3 
group
+      (+ blank) (group (+ digit))                              ; \4 size
+      (+ blank) (group (regexp tramp-adb-ls-date-year-regexp)
+                blank (regexp tramp-adb-ls-date-time-regexp))  ; \5 date
+      blank (group (* nonl)) eol)                              ; \6 filename
   "Regexp for ls output.")
 
 ;;;###tramp-autoload
@@ -180,6 +180,7 @@ It is used for TCP/IP devices."
     (temporary-file-directory . tramp-handle-temporary-file-directory)
     (tramp-get-home-directory . ignore)
     (tramp-get-remote-gid . tramp-adb-handle-get-remote-gid)
+    (tramp-get-remote-groups . tramp-adb-handle-get-remote-groups)
     (tramp-get-remote-uid . tramp-adb-handle-get-remote-uid)
     (tramp-set-file-uid-gid . ignore)
     (unhandled-file-name-directory . ignore)
@@ -218,7 +219,7 @@ arguments to pass to the OPERATION."
        (mapcar
         (lambda (line)
           (when (string-match
-                 (rx bol (group (+ (not space))) (+ space) "device" eol) line)
+                 (rx bol (group (+ (not blank))) (+ blank) "device" eol) line)
             ;; Replace ":" by "#".
             `(nil ,(tramp-compat-string-replace
                     ":" tramp-prefix-port-format (match-string 1 line)))))
@@ -235,10 +236,10 @@ arguments to pass to the OPERATION."
        (goto-char (point-min))
        (forward-line)
        (when (looking-at
-              (rx (* space) (+ (not space))
-                  (+ space) (group (+ digit))
-                  (+ space) (group (+ digit))
-                  (+ space) (group (+ digit))))
+              (rx (* blank) (+ (not blank))
+                  (+ blank) (group (+ digit))
+                  (+ blank) (group (+ digit))
+                  (+ blank) (group (+ digit))))
          ;; The values are given as 1k numbers, so we must change
          ;; them to number of bytes.
          (list (* 1024 (string-to-number (match-string 1)))
@@ -362,12 +363,12 @@ Emacs dired can't find files."
     (goto-char (point-min))
     (while
        (search-forward-regexp
-        (rx space (group space (regexp tramp-adb-ls-date-year-regexp) space))
+        (rx blank (group blank (regexp tramp-adb-ls-date-year-regexp) blank))
         nil t)
       (replace-match "0\\1" "\\1" nil)
       ;; Insert missing "/".
       (when (looking-at-p
-            (rx (regexp tramp-adb-ls-date-time-regexp) (+ space) eol))
+            (rx (regexp tramp-adb-ls-date-time-regexp) (+ blank) eol))
        (end-of-line)
        (insert "/")))
     ;; Sort entries.
@@ -466,7 +467,7 @@ Emacs dired can't find files."
             nil
             (mapcar
              (lambda (l)
-               (and (not (string-match-p (rx bol (* space) eol) l)) l))
+               (and (not (string-match-p (rx bol (* blank) eol) l)) l))
              (split-string (buffer-string) "\n")))))))))))
 
 (defun tramp-adb-handle-file-local-copy (filename)
@@ -717,9 +718,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
       (setcar result 0)
       (dolist (line signals)
        (when (string-match
-              (rx bol (* space) (group (+ digit))
-                  (+ space) (+ (not space))
-                  (+ space) (group alpha (* nonl)) eol)
+              (rx bol (* blank) (group (+ digit))
+                  (+ blank) (+ (not blank))
+                  (+ blank) (group alpha (* nonl)) eol)
               line)
          (setcar
           (nthcdr (string-to-number (match-string 1 line)) result)
@@ -1066,6 +1067,31 @@ ID-FORMAT valid values are `string' and `integer'."
     (goto-char (point-min))
     (read (current-buffer))))
 
+(defun tramp-adb-handle-get-remote-groups (vec id-format)
+  "Like `tramp-get-remote-groups' for Tramp files.
+ID-FORMAT valid values are `string' and `integer'."
+  ;; The result is cached in `tramp-get-remote-groups'.
+  (tramp-adb-send-command vec "id")
+  (with-current-buffer (tramp-get-connection-buffer vec)
+    (let (groups-integer groups-string)
+      ;; Read the expression.
+      (goto-char (point-min))
+      (when (re-search-forward (rx bol (+ nonl) "groups=") nil 'noerror)
+       (while (looking-at
+               (rx (group (+ digit)) "(" (group (+ (any "_" word))) ")"))
+         (setq groups-integer (cons (string-to-number (match-string 1))
+                                    groups-integer)
+               groups-string (cons (match-string 2) groups-string))
+         (goto-char (match-end 0))
+         (skip-chars-forward ",")))
+      (tramp-set-connection-property
+       vec "groups-integer"
+       (setq groups-integer (nreverse groups-integer)))
+      (tramp-set-connection-property
+       vec "groups-string"
+       (setq groups-string (nreverse groups-string)))
+      (if (eq id-format 'integer) groups-integer groups-string))))
+
 (defun tramp-adb-get-device (vec)
   "Return full host name from VEC to be used in shell execution.
 E.g. a host name \"192.168.1.1#5555\" returns \"192.168.1.1:5555\"
@@ -1142,7 +1168,7 @@ error and non-nil on success."
          ;; We can't use stty to disable echo of command.  stty is said
          ;; to be added to toybox 0.7.6.  busybox shall have it, but this
          ;; isn't used any longer for Android.
-         (delete-matching-lines (rx (literal command)))
+         (delete-matching-lines (rx bol (literal command) eol))
          ;; When the local machine is W32, there are still trailing ^M.
          ;; There must be a better solution by setting the correct coding
          ;; system, but this requires changes in core Tramp.
diff --git a/lisp/net/tramp-archive.el b/lisp/net/tramp-archive.el
index c25d509671..21a1e94e41 100644
--- a/lisp/net/tramp-archive.el
+++ b/lisp/net/tramp-archive.el
@@ -297,6 +297,7 @@ It must be supported by libarchive(3).")
     (temporary-file-directory . tramp-archive-handle-temporary-file-directory)
     (tramp-get-home-directory . ignore)
     (tramp-get-remote-gid . ignore)
+    (tramp-get-remote-groups . ignore)
     (tramp-get-remote-uid . ignore)
     (tramp-set-file-uid-gid . ignore)
     (unhandled-file-name-directory . ignore)
diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el
index 4c745092a3..b9abcd3842 100644
--- a/lisp/net/tramp-cache.el
+++ b/lisp/net/tramp-cache.el
@@ -278,7 +278,7 @@ Remove also properties of all files in subdirectories."
 This is suppressed for temporary buffers."
   (save-match-data
     (unless (or (null (buffer-name))
-               (string-match-p (rx bos (| space "*")) (buffer-name)))
+               (string-match-p (rx bos (| blank "*")) (buffer-name)))
       (let ((bfn (if (stringp (buffer-file-name))
                     (buffer-file-name)
                   default-directory))
diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el
index e7bb1ebe33..3f5275624f 100644
--- a/lisp/net/tramp-crypt.el
+++ b/lisp/net/tramp-crypt.el
@@ -233,6 +233,7 @@ If NAME doesn't belong to an encrypted remote directory, 
return nil."
     (temporary-file-directory . tramp-handle-temporary-file-directory)
     ;; `tramp-get-home-directory' performed by default-handler.
     ;; `tramp-get-remote-gid' performed by default handler.
+    ;; `tramp-get-remote-groups' performed by default handler.
     ;; `tramp-get-remote-uid' performed by default handler.
     (tramp-set-file-uid-gid . tramp-crypt-handle-set-file-uid-gid)
     (unhandled-file-name-directory . ignore)
diff --git a/lisp/net/tramp-fuse.el b/lisp/net/tramp-fuse.el
index 4b51af070a..8761dd1c07 100644
--- a/lisp/net/tramp-fuse.el
+++ b/lisp/net/tramp-fuse.el
@@ -179,7 +179,7 @@ It has the same meaning as 
`remote-file-name-inhibit-cache'.")
           (tramp-set-file-property
           vec "/" "mounted"
            (when (string-match
-                 (rx bol (group (literal (tramp-fuse-mount-spec vec))) space)
+                 (rx bol (group (literal (tramp-fuse-mount-spec vec))) blank)
                  mount)
              (match-string 1 mount)))))))
 
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index 9c81bccffc..817246fcec 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -823,6 +823,7 @@ It has been changed in GVFS 1.14.")
     (temporary-file-directory . tramp-handle-temporary-file-directory)
     (tramp-get-home-directory . tramp-gvfs-handle-get-home-directory)
     (tramp-get-remote-gid . tramp-gvfs-handle-get-remote-gid)
+    (tramp-get-remote-groups . ignore)
     (tramp-get-remote-uid . tramp-gvfs-handle-get-remote-uid)
     (tramp-set-file-uid-gid . tramp-gvfs-handle-set-file-uid-gid)
     (unhandled-file-name-directory . ignore)
@@ -1496,9 +1497,9 @@ If FILE-SYSTEM is non-nil, return file system attributes."
 
     (while (string-match
            (rx bol (+ nonl) ":"
-               space (group (+ nonl)) ":"
-               space (group (regexp (regexp-opt tramp-gio-events)))
-               (? (group space (group (+ nonl)))) eol)
+               blank (group (+ nonl)) ":"
+               blank (group (regexp (regexp-opt tramp-gio-events)))
+               (? (group blank (group (+ nonl)))) eol)
            string)
 
       (let ((file (match-string 1 string))
diff --git a/lisp/net/tramp-integration.el b/lisp/net/tramp-integration.el
index afc3e94580..61b2c2ecb7 100644
--- a/lisp/net/tramp-integration.el
+++ b/lisp/net/tramp-integration.el
@@ -218,11 +218,11 @@ NAME must be equal to `tramp-current-connection'."
    :mode 'tramp-info-lookup-mode :topic 'symbol
    :regexp (rx (+ (not (any "\t\n \"'(),[]`‘’"))))
    :doc-spec '(("(tramp)Function Index" nil
-               (rx bol space (+ "-") space (* nonl) ": ")
-               (rx (| space eol)))
+               (rx bol blank (+ "-") blank (* nonl) ": ")
+               (rx (| blank eol)))
               ("(tramp)Variable Index" nil
-               (rx bol space (+ "-") space (* nonl) ": ")
-               (rx (| space eol)))))
+               (rx bol blank (+ "-") blank (* nonl) ": ")
+               (rx (| blank eol)))))
 
   (add-hook
    'tramp-integration-unload-hook
diff --git a/lisp/net/tramp-rclone.el b/lisp/net/tramp-rclone.el
index 435faf8329..b40755bc0e 100644
--- a/lisp/net/tramp-rclone.el
+++ b/lisp/net/tramp-rclone.el
@@ -147,6 +147,7 @@
     (temporary-file-directory . tramp-handle-temporary-file-directory)
     (tramp-get-home-directory . ignore)
     (tramp-get-remote-gid . ignore)
+    (tramp-get-remote-groups . ignore)
     (tramp-get-remote-uid . ignore)
     (tramp-set-file-uid-gid . ignore)
     (unhandled-file-name-directory . ignore)
@@ -186,7 +187,7 @@ arguments to pass to the OPERATION."
     (delq nil
          (mapcar
           (lambda (line)
-            (when (string-match (rx bol (group (+ (not space))) ":" eol) line)
+            (when (string-match (rx bol (group (+ (not blank))) ":" eol) line)
               `(nil ,(match-string 1 line))))
           (tramp-process-lines nil tramp-rclone-program "listremotes")))))
 
@@ -300,11 +301,11 @@ file names."
        (let (total used free)
          (goto-char (point-min))
          (while (not (eobp))
-           (when (looking-at (rx "Total: " (+ space) (group (+ digit))))
+           (when (looking-at (rx "Total: " (+ blank) (group (+ digit))))
              (setq total (string-to-number (match-string 1))))
-           (when (looking-at (rx "Used: " (+ space) (group (+ digit))))
+           (when (looking-at (rx "Used: " (+ blank) (group (+ digit))))
              (setq used (string-to-number (match-string 1))))
-           (when (looking-at (rx "Free: " (+ space) (group (+ digit))))
+           (when (looking-at (rx "Free: " (+ blank) (group (+ digit))))
              (setq free (string-to-number (match-string 1))))
            (forward-line))
          (when used
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index dfb87059bd..ff153d955b 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -1082,6 +1082,7 @@ Format specifiers \"%s\" are replaced before the script 
is used.")
     (temporary-file-directory . tramp-handle-temporary-file-directory)
     (tramp-get-home-directory . tramp-sh-handle-get-home-directory)
     (tramp-get-remote-gid . tramp-sh-handle-get-remote-gid)
+    (tramp-get-remote-groups . tramp-sh-handle-get-remote-groups)
     (tramp-get-remote-uid . tramp-sh-handle-get-remote-uid)
     (tramp-set-file-uid-gid . tramp-sh-handle-set-file-uid-gid)
     (unhandled-file-name-directory . ignore)
@@ -1539,6 +1540,32 @@ ID-FORMAT valid values are `string' and `integer'."
      ((tramp-get-remote-python vec)
       (tramp-get-remote-gid-with-python vec id-format)))))
 
+(defun tramp-sh-handle-get-remote-groups (vec id-format)
+  "Like `tramp-get-remote-groups' for Tramp files.
+ID-FORMAT valid values are `string' and `integer'."
+  ;; The result is cached in `tramp-get-remote-groups'.
+  (when (tramp-get-remote-id vec)
+    (tramp-send-command vec (tramp-get-remote-id vec)))
+  (with-current-buffer (tramp-get-connection-buffer vec)
+    (let (groups-integer groups-string)
+      ;; Read the expression.
+      (goto-char (point-min))
+      (when (re-search-forward (rx bol (+ nonl) "groups=") nil 'noerror)
+       (while (looking-at
+               (rx (group (+ digit)) "(" (group (+ (any "_" word))) ")"))
+         (setq groups-integer (cons (string-to-number (match-string 1))
+                                    groups-integer)
+               groups-string (cons (match-string 2) groups-string))
+         (goto-char (match-end 0))
+         (skip-chars-forward ",")))
+      (tramp-set-connection-property
+       vec "groups-integer"
+       (setq groups-integer (nreverse groups-integer)))
+      (tramp-set-connection-property
+       vec "groups-string"
+       (setq groups-string (nreverse groups-string)))
+      (if (eq id-format 'integer) groups-integer groups-string))))
+
 (defun tramp-sh-handle-set-file-uid-gid (filename &optional uid gid)
   "Like `tramp-set-file-uid-gid' for Tramp files."
   ;; Modern Unices allow chown only for root.  So we might need
@@ -2660,7 +2687,7 @@ The method used must be an out-of-band method."
          (narrow-to-region beg-marker end-marker)
          ;; Check for "--dired" output.
          (when (re-search-backward
-                (rx bol "//DIRED//" (+ space) (group (+ nonl)) eol)
+                (rx bol "//DIRED//" (+ blank) (group (+ nonl)) eol)
                 nil 'noerror)
            (let ((beg (match-beginning 1))
                  (end (match-end 0)))
@@ -2733,7 +2760,7 @@ The method used must be an out-of-band method."
          ;; Try to insert the amount of free space.
          (goto-char (point-min))
          ;; First find the line to put it on.
-         (when (and (re-search-forward (rx bol (group (* space) "total")) nil 
t)
+         (when (and (re-search-forward (rx bol (group (* blank) "total")) nil 
t)
                     ;; Emacs 29.1 or later.
                     (not (fboundp 'dired--insert-disk-space)))
            (when-let ((available (get-free-disk-space ".")))
@@ -3837,7 +3864,7 @@ Fall back to normal file name handler if no Tramp handler 
exists."
           ((string-match
            (rx "Supported arguments for "
                "GIO_USE_FILE_MONITOR environment variable:\n"
-               (* space) (group (+ alpha)) " - 20")
+               (* blank) (group (+ alpha)) " - 20")
            string)
           (setq pos (match-end 0))
            (intern
@@ -3849,10 +3876,10 @@ Fall back to normal file name handler if no Tramp 
handler exists."
       (setq string (tramp-compat-string-replace "\n\n" "\n" string))
 
       (while (string-match
-             (rx bol (+ (not (any ":"))) ":" space
-                 (group (+ (not (any ":")))) ":" space
+             (rx bol (+ (not (any ":"))) ":" blank
+                 (group (+ (not (any ":")))) ":" blank
                  (group (regexp (regexp-opt tramp-gio-events)))
-                 (? space (group (+ (not (any ":"))))) eol)
+                 (? blank (group (+ (not (any ":"))))) eol)
              string)
 
         (let* ((file (match-string 1 string))
@@ -3926,9 +3953,9 @@ Fall back to normal file name handler if no Tramp handler 
exists."
          (goto-char (point-min))
          (forward-line)
          (when (looking-at
-                (rx (? bol "/" (* (not space)) space) (* space)
-                    (group (+ digit)) (+ space)
-                    (group (+ digit)) (+ space)
+                (rx (? bol "/" (* (not blank)) blank) (* blank)
+                    (group (+ digit)) (+ blank)
+                    (group (+ digit)) (+ blank)
                     (group (+ digit))))
            (mapcar
             (lambda (d)
@@ -4068,7 +4095,7 @@ This function expects to be in the right *tramp* buffer."
       (unless (or ignore-path (tramp-check-remote-uname vec 
tramp-sunos-unames))
        (tramp-send-command vec (format "which \\%s | wc -w" progname))
        (goto-char (point-min))
-       (if (looking-at-p (rx bol (* space) "1" eol))
+       (if (looking-at-p (rx bol (* blank) "1" eol))
            (setq result (concat "\\" progname))))
       (unless result
        (when ignore-tilde
@@ -4976,9 +5003,9 @@ Goes through the list `tramp-inline-compress-commands'."
                     string
                     (and
                      (string-match
-                      (rx bol (+ (not (any space "#"))) space
-                          (+ (not space)) space
-                          (group (+ (not space))) eol)
+                      (rx bol (+ (not (any blank "#"))) blank
+                          (+ (not blank)) blank
+                          (group (+ (not blank))) eol)
                       string)
                      (match-string 1 string))
                     found
@@ -5393,7 +5420,7 @@ raises an error."
                     (unless noerror signal-hook-function)))
                (read (current-buffer)))
            ;; Error handling.
-           (when (re-search-forward (rx (not space)) (line-end-position) t)
+           (when (re-search-forward (rx (not blank)) (line-end-position) t)
              (error nil)))
        (error (unless noerror
                 (tramp-error
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index 3d65520282..930f4f707b 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -98,9 +98,9 @@ this variable \"client min protocol=NT1\"."
   "Regexp of SMB server identification.")
 
 (defconst tramp-smb-prompt
-  (rx bol (| (: (| "smb:" "PS") space (+ nonl) "> ")
-            (: (+ space) "Server"
-               (+ space) "Comment" eol)))
+  (rx bol (| (: (| "smb:" "PS") blank (+ nonl) "> ")
+            (: (+ blank) "Server"
+               (+ blank) "Comment" eol)))
   "Regexp used as prompt in smbclient or powershell.")
 
 (defconst tramp-smb-wrong-passwd-regexp
@@ -110,10 +110,10 @@ this variable \"client min protocol=NT1\"."
 
 (defconst tramp-smb-errors
   (rx (| ;; Connection error / timeout / unknown command.
-       (: "Connection" (? " to " (+ (not space))) " failed")
+       (: "Connection" (? " to " (+ (not blank))) " failed")
        "Read from server failed, maybe it closed the connection"
        "Call timed out: server did not respond"
-       (: (+ (not space)) ": command not found")
+       (: (+ (not blank)) ": command not found")
        "Server doesn't support UNIX CIFS calls"
        (| ;; Samba.
        "ERRDOS"
@@ -298,6 +298,7 @@ See `tramp-actions-before-shell' for more info.")
     (temporary-file-directory . tramp-handle-temporary-file-directory)
     (tramp-get-home-directory . tramp-smb-handle-get-home-directory)
     (tramp-get-remote-gid . ignore)
+    (tramp-get-remote-groups . ignore)
     (tramp-get-remote-uid . ignore)
     (tramp-set-file-uid-gid . ignore)
     (unhandled-file-name-directory . ignore)
@@ -884,28 +885,28 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
          (while (not (eobp))
            (cond
             ((looking-at
-              (rx "Size:" (+ space) (group (+ digit)) (+ space)
-                  "Blocks:" (+ space) (+ digit) (+ space) (group (+ 
wordchar))))
+              (rx "Size:" (+ blank) (group (+ digit)) (+ blank)
+                  "Blocks:" (+ blank) (+ digit) (+ blank) (group (+ 
wordchar))))
              (setq size (string-to-number (match-string 1))
                    id (if (string-equal "directory" (match-string 2)) t
                         (if (string-equal "symbolic" (match-string 2)) ""))))
             ((looking-at
-              (rx "Inode:" (+ space) (group (+ digit)) (+ space)
-                  "Links:" (+ space) (group (+ digit))))
+              (rx "Inode:" (+ blank) (group (+ digit)) (+ blank)
+                  "Links:" (+ blank) (group (+ digit))))
              (setq inode (string-to-number (match-string 1))
                    link (string-to-number (match-string 2))))
             ((looking-at
-              (rx "Access:" (+ space)
-                  "(" (+ digit) "/" (group (+ (not space))) ")" (+ space)
-                  "Uid:" (+ space) (group (+ digit)) (+ whitespace)
-                  "Gid:" (+ space) (group (+ digit))))
+              (rx "Access:" (+ blank)
+                  "(" (+ digit) "/" (group (+ (not blank))) ")" (+ blank)
+                  "Uid:" (+ blank) (group (+ digit)) (+ blank)
+                  "Gid:" (+ blank) (group (+ digit))))
              (setq mode (match-string 1)
                    uid (match-string 2)
                    gid (match-string 3)))
             ((looking-at
-              (rx "Access:" (+ space)
+              (rx "Access:" (+ blank)
                   (group (+ digit)) "-" (group (+ digit)) "-"
-                  (group (+ digit)) (+ space)
+                  (group (+ digit)) (+ blank)
                   (group (+ digit)) ":" (group (+ digit)) ":"
                   (group (+ digit))))
              (setq atime
@@ -917,9 +918,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
                     (string-to-number (match-string 2)) ;; month
                     (string-to-number (match-string 1))))) ;; year
             ((looking-at
-              (rx "Modify:" (+ space)
+              (rx "Modify:" (+ blank)
                   (group (+ digit)) "-" (group (+ digit)) "-"
-                  (group (+ digit)) (+ space)
+                  (group (+ digit)) (+ blank)
                   (group (+ digit)) ":" (group (+ digit)) ":"
                   (group (+ digit))))
              (setq mtime
@@ -931,9 +932,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
                     (string-to-number (match-string 2)) ;; month
                     (string-to-number (match-string 1))))) ;; year
             ((looking-at
-              (rx "Change:" (+ space)
+              (rx "Change:" (+ blank)
                   (group (+ digit)) "-" (group (+ digit)) "-"
-                  (group (+ digit)) (+ space)
+                  (group (+ digit)) (+ blank)
                   (group (+ digit)) ":" (group (+ digit)) ":"
                   (group (+ digit))))
              (setq ctime
@@ -1008,7 +1009,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
            (goto-char (point-min))
            (forward-line)
            (when (looking-at
-                  (rx (* space) (group (+ digit))
+                  (rx (* blank) (group (+ digit))
                       " blocks of size " (group (+ digit))
                       ". " (group (+ digit)) " blocks available"))
              (setq blocksize (string-to-number (match-string 2))
@@ -1660,7 +1661,7 @@ If VEC has no cifs capabilities, exchange \"/\" by 
\"\\\\\"."
        (setq localname (replace-match "$" nil nil localname 1)))
 
       ;; A trailing space is not supported.
-      (when (string-match-p (rx space eol) localname)
+      (when (string-match-p (rx blank eol) localname)
        (tramp-error
         vec 'file-error
         "Invalid file name %s" (tramp-make-tramp-file-name vec localname)))
@@ -1853,9 +1854,9 @@ are listed.  Result is the list (LOCALNAME MODE SIZE 
MTIME)."
 
        ;; localname.
        (if (string-match
-            (rx bol (+ space)
-                (group (not space) (? (* nonl) (not space)))
-                (* space) eol)
+            (rx bol (+ blank)
+                (group (not blank) (? (* nonl) (not blank)))
+                (* blank) eol)
             line)
            (setq localname (match-string 1 line))
          (cl-return))))
diff --git a/lisp/net/tramp-sshfs.el b/lisp/net/tramp-sshfs.el
index 31720a605e..b89e1282d2 100644
--- a/lisp/net/tramp-sshfs.el
+++ b/lisp/net/tramp-sshfs.el
@@ -150,6 +150,7 @@
     (temporary-file-directory . tramp-handle-temporary-file-directory)
     (tramp-get-home-directory . ignore)
     (tramp-get-remote-gid . ignore)
+    (tramp-get-remote-groups . ignore)
     (tramp-get-remote-uid . ignore)
     (tramp-set-file-uid-gid . ignore)
     (unhandled-file-name-directory . ignore)
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index 893afcdbbe..ef0954ab83 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -143,6 +143,7 @@ See `tramp-actions-before-shell' for more info.")
     (temporary-file-directory . tramp-handle-temporary-file-directory)
     (tramp-get-home-directory . tramp-sudoedit-handle-get-home-directory)
     (tramp-get-remote-gid . tramp-sudoedit-handle-get-remote-gid)
+    (tramp-get-remote-groups . tramp-sudoedit-handle-get-remote-groups)
     (tramp-get-remote-uid . tramp-sudoedit-handle-get-remote-uid)
     (tramp-set-file-uid-gid . tramp-sudoedit-handle-set-file-uid-gid)
     (unhandled-file-name-directory . ignore)
@@ -473,7 +474,7 @@ the result will be a local, non-Tramp, file name."
        (delq
         nil
         (mapcar
-         (lambda (l) (and (not (string-match-p (rx bol (* space) eol) l)) l))
+         (lambda (l) (and (not (string-match-p (rx bol (* blank) eol) l)) l))
          (split-string
           (tramp-get-buffer-string (tramp-get-connection-buffer v))
           "\n" 'omit))))))))
@@ -535,9 +536,9 @@ the result will be a local, non-Tramp, file name."
          (goto-char (point-min))
          (forward-line)
          (when (looking-at
-                (rx (* space) (group (+ digit))
-                    (+ space) (group (+ digit))
-                    (+ space) (group (+ digit))))
+                (rx (* blank) (group (+ digit))
+                    (+ blank) (group (+ digit))
+                    (+ blank) (group (+ digit))))
            (list (string-to-number (match-string 1))
                  ;; The second value is the used size.  We need the
                  ;; free size.
@@ -732,6 +733,31 @@ ID-FORMAT valid values are `string' and `integer'."
       (tramp-sudoedit-send-command-and-read vec "id" "-g")
     (tramp-sudoedit-send-command-string vec "id" "-gn")))
 
+(defun tramp-sudoedit-handle-get-remote-groups (vec id-format)
+  "Like `tramp-get-remote-groups' for Tramp files.
+ID-FORMAT valid values are `string' and `integer'."
+  ;; The result is cached in `tramp-get-remote-groups'.
+  (tramp-sudoedit-send-command vec "id")
+  (with-current-buffer (tramp-get-connection-buffer vec)
+    (let (groups-integer groups-string)
+      ;; Read the expression.
+      (goto-char (point-min))
+      (when (re-search-forward (rx bol (+ nonl) "groups=") nil 'noerror)
+       (while (looking-at
+               (rx (group (+ digit)) "(" (group (+ (any "_" word))) ")"))
+         (setq groups-integer (cons (string-to-number (match-string 1))
+                                    groups-integer)
+               groups-string (cons (match-string 2) groups-string))
+         (goto-char (match-end 0))
+         (skip-chars-forward ",")))
+      (tramp-set-connection-property
+       vec "groups-integer"
+       (setq groups-integer (nreverse groups-integer)))
+      (tramp-set-connection-property
+       vec "groups-string"
+       (setq groups-string (nreverse groups-string)))
+      (if (eq id-format 'integer) groups-integer groups-string))))
+
 (defun tramp-sudoedit-handle-set-file-uid-gid (filename &optional uid gid)
   "Like `tramp-set-file-uid-gid' for Tramp files."
   (tramp-skeleton-set-file-modes-times-uid-gid filename
@@ -846,7 +872,7 @@ In case there is no valid Lisp expression, it raises an 
error."
       (condition-case nil
          (prog1 (read (current-buffer))
            ;; Error handling.
-           (when (re-search-forward (rx (not space)) (line-end-position) t)
+           (when (re-search-forward (rx (not blank)) (line-end-position) t)
              (error nil)))
        (error (tramp-error
                vec 'file-error
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index b24525de3a..cfc005d270 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -598,7 +598,7 @@ if you need to change this."
   :type 'string)
 
 (defcustom tramp-login-prompt-regexp
-  (rx (* nonl) (| "user" "login") (? space (* nonl)) ":" (* space))
+  (rx (* nonl) (| "user" "login") (? blank (* nonl)) ":" (* blank))
   "Regexp matching login-like prompts.
 The regexp should match at end of buffer.
 
@@ -612,9 +612,9 @@ Sometimes the prompt is reported to look like \"login 
as:\"."
   ;; connection initialization; Tramp redefines the prompt afterwards.
   (rx (| bol "\r")
       (* (not (any "\n#$%>]")))
-      (? "#") (any "#$%>]") (* space)
+      (? "#") (any "#$%>]") (* blank)
       ;; Escape characters.
-      (* "[" (* (any ";" digit)) alpha (* space)))
+      (* "[" (* (any ";" digit)) alpha (* blank)))
   "Regexp to match prompts from remote shell.
 Normally, Tramp expects you to configure `shell-prompt-pattern'
 correctly, but sometimes it happens that you are connecting to a
@@ -631,7 +631,7 @@ This regexp must match both `tramp-initial-end-of-output' 
and
 (defcustom tramp-password-prompt-regexp
   (rx bol (* nonl)
       (group (regexp (regexp-opt password-word-equivalents)))
-      (* nonl) ":" (? "\^@") (* space))
+      (* nonl) ":" (? "\^@") (* blank))
   "Regexp matching password-like prompts.
 The regexp should match at end of buffer.
 
@@ -664,7 +664,7 @@ The regexp should match at end of buffer."
 (defcustom tramp-yesno-prompt-regexp
   (rx "Are you sure you want to continue connecting (yes/no"
       (? "/[fingerprint]") ")?"
-      (* space))
+      (* blank))
   "Regular expression matching all yes/no queries which need to be confirmed.
 The confirmation should be done with yes or no.
 The regexp should match at end of buffer.
@@ -674,7 +674,7 @@ See also `tramp-yn-prompt-regexp'."
 (defcustom tramp-yn-prompt-regexp
   (rx (| "Store key in cache? (y/n)"
         "Update cached key? (y/n, Return cancels connection)")
-      (* space))
+      (* blank))
   "Regular expression matching all y/n queries which need to be confirmed.
 The confirmation should be done with y or n.
 The regexp should match at end of buffer.
@@ -693,7 +693,7 @@ files conditionalize this setup based on the TERM 
environment variable."
 (defcustom tramp-terminal-prompt-regexp
   (rx (| (: "TERM = (" (* nonl) ")")
         (: "Terminal type? [" (* nonl) "]"))
-      (* space))
+      (* blank))
   "Regular expression matching all terminal setting prompts.
 The regexp should match at end of buffer.
 The answer will be provided by `tramp-action-terminal', which see."
@@ -736,7 +736,7 @@ The regexp should match at end of buffer."
   :type 'regexp)
 
 (defcustom tramp-operation-not-permitted-regexp
-  (rx (| (: "preserving times" (* nonl)) "set mode") ":" (* space)
+  (rx (| (: "preserving times" (* nonl)) "set mode") ":" (* blank)
       "Operation not permitted")
   "Regular expression matching keep-date problems in (s)cp operations.
 Copying has been performed successfully already, so this message can
@@ -749,7 +749,7 @@ be ignored safely."
         "Permission denied"
         "is a directory"
         "not a regular file")
-      (* space))
+      (* blank))
   "Regular expression matching copy problems in (s)cp operations."
   :type 'regexp)
 
@@ -931,7 +931,7 @@ Used in `tramp-make-tramp-file-name'.")
   "Regexp matching delimiter between method and user or host names.
 Derived from `tramp-postfix-method-format'.")
 
-(defconst tramp-user-regexp (rx (+ (not (any "/:|" space))))
+(defconst tramp-user-regexp (rx (+ (not (any "/:|" blank))))
   "Regexp matching user names.")
 
 (defconst tramp-prefix-domain-format "%"
@@ -1945,9 +1945,9 @@ of `current-buffer'."
 
 (defconst tramp-debug-outline-regexp
   (rx ;; Timestamp.
-      (+ digit) ":" (+ digit) ":" (+ digit) "." (+ digit) space
+      (+ digit) ":" (+ digit) ":" (+ digit) "." (+ digit) blank
       ;; Thread.
-      (? (group "#<thread " (+ nonl) ">") space)
+      (? (group "#<thread " (+ nonl) ">") blank)
        ;; Function name, verbosity.
       (+ (any "-" alnum)) " (" (group (+ digit)) ") #")
   "Used for highlighting Tramp debug buffers in `outline-mode'.")
@@ -2636,8 +2636,8 @@ Must be handled by the callers."
       (tramp-get-default-directory (process-buffer (nth 0 args)))))
    ;; VEC.
    ((member operation
-           '(tramp-get-home-directory
-             tramp-get-remote-gid tramp-get-remote-uid))
+           '(tramp-get-home-directory tramp-get-remote-gid
+             tramp-get-remote-groups tramp-get-remote-uid))
     (tramp-make-tramp-file-name (nth 0 args)))
    ;; Unknown file primitive.
    (t (error "Unknown file I/O primitive: %s" operation))))
@@ -3218,7 +3218,7 @@ Either user or host may be nil."
    (let (result
         (regexp
          (rx bol (group (regexp tramp-host-regexp))
-             (? (+ space) (group (regexp tramp-user-regexp))))))
+             (? (+ blank) (group (regexp tramp-user-regexp))))))
      (when (re-search-forward regexp (line-end-position) t)
        (setq result (append (list (match-string 2) (match-string 1)))))
      (forward-line 1)
@@ -3243,10 +3243,10 @@ User is always nil."
    "Return a (user host) tuple allowed to access.
 User is always nil."
    (tramp-parse-group
-    (rx (| (: bol (* space) "Host")
+    (rx (| (: bol (* blank) "Host")
           (: bol (+ nonl)) ;; ???
           (group (regexp tramp-host-regexp))))
-    1 (rx space)))
+    1 (rx blank)))
 
 ;; Generic function.
 (defun tramp-parse-shostkeys-sknownhosts (dirname regexp)
@@ -3287,7 +3287,7 @@ User is always nil."
 User is always nil."
    (tramp-parse-group
     (rx bol (group (| (regexp tramp-ipv6-regexp) (regexp tramp-host-regexp))))
-    1 (rx space)))
+    1 (rx blank)))
 
 (defun tramp-parse-passwd (filename)
   "Return a list of (user host) tuples allowed to access.
@@ -4266,7 +4266,7 @@ Let-bind it when necessary.")
 (defun tramp-ps-time ()
   "Read printed time oif \"ps\" in format \"[[DD-]hh:]mm:ss\".
 Return it as number of seconds.  Used in `tramp-process-attributes-ps-format'."
-  (search-forward-regexp (rx (+ space)))
+  (search-forward-regexp (rx (+ blank)))
   (search-forward-regexp (rx (? (? (group (+ digit)) "-")
                                   (group (+ digit)) ":")
                                   (group (+ digit)) ":"
@@ -4386,17 +4386,17 @@ It is not guaranteed, that all process attributes as 
described in
                       (cond
                        ((eq (cdr elt) 'number) (read (current-buffer)))
                        ((eq (cdr elt) 'string)
-                        (search-forward-regexp (rx (+ (not space))))
+                        (search-forward-regexp (rx (+ (not blank))))
                         (match-string 0))
                        ((numberp (cdr elt))
-                        (search-forward-regexp (rx (+ space)))
+                        (search-forward-regexp (rx (+ blank)))
                         (search-forward-regexp
                         (rx (+ nonl)) (+ (point) (cdr elt)))
                         (string-trim (match-string 0)))
                        ((fboundp (cdr elt))
                         (funcall (cdr elt)))
                        ((null (cdr elt))
-                        (search-forward-regexp (rx (+ whitespace)))
+                        (search-forward-regexp (rx (+ blank)))
                         (buffer-substring (point) (line-end-position)))))
                      res))
                   ;; `nice' could be `-'.
@@ -4840,7 +4840,7 @@ support symbolic links."
 
 (defun tramp-handle-shell-command (command &optional output-buffer 
error-buffer)
   "Like `shell-command' for Tramp files."
-  (let* ((asynchronous (string-match-p (rx (* space) "&" (* space) eos) 
command))
+  (let* ((asynchronous (string-match-p (rx (* blank) "&" (* blank) eos) 
command))
         (command (substring command 0 asynchronous))
         current-buffer-p
         (output-buffer-p output-buffer)
@@ -5838,7 +5838,8 @@ be granted."
                       ((eq ?s access) 3)))
             (file-attr (file-attributes (tramp-make-tramp-file-name vec)))
             (remote-uid (tramp-get-remote-uid vec 'integer))
-            (remote-gid (tramp-get-remote-gid vec 'integer)))
+            (remote-gid (tramp-get-remote-gid vec 'integer))
+            (remote-groups (tramp-get-remote-groups vec 'integer)))
     (or
      ;; Not a symlink.
      (eq t (file-attribute-type file-attr))
@@ -5861,7 +5862,12 @@ be granted."
          (equal remote-gid tramp-unknown-id-integer)
          (equal remote-gid (file-attribute-group-id file-attr))
          (equal tramp-unknown-id-integer
-                (file-attribute-group-id file-attr)))))))
+                (file-attribute-group-id file-attr))))
+     ;; Group accessible and owned by user's secondary group.
+     (and
+      (eq access
+         (aref (file-attribute-modes file-attr) (+ offset 3)))
+      (member (file-attribute-group-id file-attr) remote-groups)))))
 
 (defmacro tramp-convert-file-attributes (vec localname id-format attr)
   "Convert `file-attributes' ATTR generated Tramp backend functions.
@@ -5999,6 +6005,16 @@ ID-FORMAT valid values are `string' and `integer'."
       (and (equal id-format 'integer) tramp-unknown-id-integer)
       (and (equal id-format 'string) tramp-unknown-id-string)))
 
+(defun tramp-get-remote-groups (vec id-format)
+  "The list of groups of the remote connection VEC, in ID-FORMAT.
+ID-FORMAT valid values are `string' and `integer'."
+  (or (and (tramp-file-name-p vec)
+          (with-tramp-connection-property vec (format "groups-%s" id-format)
+            (tramp-file-name-handler #'tramp-get-remote-groups vec id-format)))
+      ;; Ensure there is a valid result.
+      (and (equal id-format 'integer) (list tramp-unknown-id-integer))
+      (and (equal id-format 'string) (list tramp-unknown-id-string))))
+
 (defun tramp-local-host-p (vec)
   "Return t if this points to the local host, nil otherwise.
 This handles also chrooted environments, which are not regarded as local."
diff --git a/test/lisp/net/tramp-archive-tests.el 
b/test/lisp/net/tramp-archive-tests.el
index aa5d1cc496..d0892bf708 100644
--- a/test/lisp/net/tramp-archive-tests.el
+++ b/test/lisp/net/tramp-archive-tests.el
@@ -622,7 +622,7 @@ This checks also `file-name-as-directory', 
`file-name-directory',
            (goto-char (point-min))
            (should
             (looking-at-p
-             (rx bol (+ nonl) space (literal tramp-archive-test-archive) 
eol))))
+             (rx bol (+ nonl) blank (literal tramp-archive-test-archive) 
eol))))
          (with-temp-buffer
            (insert-directory
             (file-name-as-directory tramp-archive-test-archive)
@@ -633,11 +633,11 @@ This checks also `file-name-as-directory', 
`file-name-directory',
              (rx-to-string
               `(:
                 ;; There might be a summary line.
-                (? "total" (+ nonl) (+ digit) (? space)
+                (? "total" (+ nonl) (+ digit) (? blank)
                    (? (any "EGKMPTYZk")) (? "i") (? "B") "\n")
                 ;; We don't know in which order the files appear.
                 (= ,(length (directory-files tramp-archive-test-archive))
-                   (+ nonl) space
+                   (+ nonl) blank
                    (regexp
                     ,(regexp-opt (directory-files tramp-archive-test-archive)))
                    (? " ->" (+ nonl)) "\n"))))))
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index fed1d881c5..f42f6838c8 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -3222,13 +3222,13 @@ This tests also `file-directory-p' and 
`file-accessible-directory-p'."
              (insert-directory tmp-name1 "-al")
              (goto-char (point-min))
              (should
-              (looking-at-p (rx bol (+ nonl) space (literal tmp-name1) eol))))
+              (looking-at-p (rx bol (+ nonl) blank (literal tmp-name1) eol))))
            (with-temp-buffer
              (insert-directory (file-name-as-directory tmp-name1) "-al")
              (goto-char (point-min))
              (should
               (looking-at-p
-               (rx bol (+ nonl) space (literal tmp-name1) "/" eol))))
+               (rx bol (+ nonl) blank (literal tmp-name1) "/" eol))))
            (with-temp-buffer
              (insert-directory
               (file-name-as-directory tmp-name1) "-al" nil 'full-directory-p)
@@ -3238,11 +3238,11 @@ This tests also `file-directory-p' and 
`file-accessible-directory-p'."
                (rx-to-string
                 `(:
                   ;; There might be a summary line.
-                  (? "total" (+ nonl) (+ digit) (? space)
+                  (? "total" (+ nonl) (+ digit) (? blank)
                      (? (any "EGKMPTYZk")) (? "i") (? "B") "\n")
                   ;; We don't know in which order ".", ".." and "foo" appear.
                   (= ,(length (directory-files tmp-name1))
-                     (+ nonl) space
+                     (+ nonl) blank
                      (regexp ,(regexp-opt (directory-files tmp-name1)))
                      (? " ->" (+ nonl)) "\n"))))))
 



reply via email to

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