From: Michael Albinus Date: Tue, 6 Sep 2022 10:33:19 +0000 (+0200) Subject: Use secondary groups when checking permissions in Tramp (Bug#57044) X-Git-Tag: emacs-29.0.90~1856^2~705 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=106456d01bd9b9ffe82c00c4b09a9094a603438e;p=emacs.git 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. --- diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index ab38ffa0cf9..3fb28d91eae 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 c25d5096719..21a1e94e418 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 4c745092a3e..b9abcd38424 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 e7bb1ebe338..3f5275624fe 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 4b51af070aa..8761dd1c07b 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 9c81bccffc9..817246fcec6 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 afc3e945802..61b2c2ecb7c 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 435faf83294..b40755bc0ec 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 dfb87059bdf..ff153d955be 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 3d65520282b..930f4f707bb 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 31720a605ec..b89e1282d21 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 893afcdbbee..ef0954ab83f 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 b24525de3a5..cfc005d270c 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 "#") space) + (? (group "#") 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 aa5d1cc496c..d0892bf7081 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 fed1d881c57..f42f6838c86 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"))))))