* lisp/net/tramp-adb.el (tramp-adb-handle-file-executable-p):
Check also for sticky bit.
(tramp-adb-handle-file-readable-p): Simplify.
* lisp/net/tramp-gvfs.el (tramp-gvfs-handle-file-executable-p):
Check also for sticky bit. Force `file-attributes' check.
* lisp/net/tramp-sh.el (tramp-sh-handle-file-executable-p):
Check also for sticky bit.
(tramp-sh-handle-file-readable-p)
(tramp-sh-handle-file-writable-p): Simplify.
* lisp/net/tramp-sudoedit.el (tramp-sudoedit-handle-file-executable-p):
Check also for sticky bit.
(tramp-sudoedit-handle-file-readable-p)
(tramp-sudoedit-handle-file-writable-p): Simplify.
* lisp/net/tramp.el (tramp-use-file-attributes): Fix docstring.
(tramp-handle-file-readable-p, tramp-handle-file-writable-p):
Force `file-attributes' check. Use `file-truename' for symbolic links.
(tramp-check-cached-permissions): New optional argument FORCE.
Fix symlink check. Check also for sticky bit. (Bug#77402)
* test/lisp/net/tramp-tests.el
(tramp-test20-file-modes-without-file-attributes)
(tramp-test21-file-links-without-file-attributes): New tests.
(cherry picked from commit
3f9ac99fc7e024678dff1ac3ff38e617ef2606fe)
(with-tramp-file-property v localname "file-executable-p"
;; Examine `file-attributes' cache to see if request can be
;; satisfied without remote operation.
- (if (tramp-use-file-attributes v)
- (or (tramp-check-cached-permissions v ?x)
- (tramp-check-cached-permissions v ?s))
- (tramp-adb-send-command-and-check
- v (format "test -x %s" (tramp-shell-quote-argument localname)))))))
+ (or (tramp-check-cached-permissions v ?x)
+ (tramp-check-cached-permissions v ?s)
+ (tramp-check-cached-permissions v ?t)
+ (tramp-adb-send-command-and-check
+ v (format "test -x %s" (tramp-shell-quote-argument localname)))))))
(defun tramp-adb-handle-file-exists-p (filename)
"Like `file-exists-p' for Tramp files."
(with-tramp-file-property v localname "file-readable-p"
;; Examine `file-attributes' cache to see if request can be
;; satisfied without remote operation.
- (if (tramp-use-file-attributes v)
- (tramp-handle-file-readable-p filename)
- (tramp-adb-send-command-and-check
- v (format "test -r %s" (tramp-shell-quote-argument localname)))))))
+ (or (tramp-handle-file-readable-p filename)
+ (tramp-adb-send-command-and-check
+ v (format "test -r %s" (tramp-shell-quote-argument localname)))))))
(defun tramp-adb-handle-file-writable-p (filename)
"Like `file-writable-p' for Tramp files."
"Like `file-executable-p' for Tramp files."
(with-parsed-tramp-file-name (expand-file-name filename) nil
(with-tramp-file-property v localname "file-executable-p"
- (or (tramp-check-cached-permissions v ?x)
- (tramp-check-cached-permissions v ?s)))))
+ (or (tramp-check-cached-permissions v ?x 'force)
+ (tramp-check-cached-permissions v ?s 'force)
+ (tramp-check-cached-permissions v ?t 'force)))))
(defun tramp-gvfs-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
(with-tramp-file-property v localname "file-executable-p"
;; Examine `file-attributes' cache to see if request can be
;; satisfied without remote operation.
- (if (tramp-use-file-attributes v)
- (or (tramp-check-cached-permissions v ?x)
- (tramp-check-cached-permissions v ?s))
- (tramp-run-test v "-x" localname)))))
+ (or (tramp-check-cached-permissions v ?x)
+ (tramp-check-cached-permissions v ?s)
+ (tramp-check-cached-permissions v ?t)
+ (tramp-run-test v "-x" localname)))))
(defun tramp-sh-handle-file-readable-p (filename)
"Like `file-readable-p' for Tramp files."
(with-tramp-file-property v localname "file-readable-p"
;; Examine `file-attributes' cache to see if request can be
;; satisfied without remote operation.
- (if (tramp-use-file-attributes v)
- (tramp-handle-file-readable-p filename)
- (tramp-run-test v "-r" localname)))))
+ (or (tramp-handle-file-readable-p filename)
+ (tramp-run-test v "-r" localname)))))
;; Functions implemented using the basic functions above.
(if (file-exists-p filename)
;; Examine `file-attributes' cache to see if request can be
;; satisfied without remote operation.
- (if (tramp-use-file-attributes v)
- (tramp-check-cached-permissions v ?w)
- (tramp-run-test v "-w" localname))
+ (or (tramp-check-cached-permissions v ?w)
+ (tramp-run-test v "-w" localname))
;; If file doesn't exist, check if directory is writable.
- (and
- (file-directory-p (file-name-directory filename))
- (file-writable-p (file-name-directory filename)))))))
+ (and (file-directory-p (file-name-directory filename))
+ (file-writable-p (file-name-directory filename)))))))
(defun tramp-sh-handle-file-ownership-preserved-p (filename &optional group)
"Like `file-ownership-preserved-p' for Tramp files."
(with-tramp-file-property v localname "file-executable-p"
;; Examine `file-attributes' cache to see if request can be
;; satisfied without remote operation.
- (if (tramp-use-file-attributes v)
- (or (tramp-check-cached-permissions v ?x)
- (tramp-check-cached-permissions v ?s))
- (tramp-sudoedit-send-command
- v "test" "-x" (file-name-unquote localname))))))
+ (or (tramp-check-cached-permissions v ?x)
+ (tramp-check-cached-permissions v ?s)
+ (tramp-check-cached-permissions v ?t)
+ (tramp-sudoedit-send-command
+ v "test" "-x" (file-name-unquote localname))))))
(defun tramp-sudoedit-handle-file-exists-p (filename)
"Like `file-exists-p' for Tramp files."
(with-tramp-file-property v localname "file-readable-p"
;; Examine `file-attributes' cache to see if request can be
;; satisfied without remote operation.
- (if (tramp-use-file-attributes v)
- (tramp-handle-file-readable-p filename)
- (tramp-sudoedit-send-command
- v "test" "-r" (file-name-unquote localname))))))
+ (or (tramp-handle-file-readable-p filename)
+ (tramp-sudoedit-send-command
+ v "test" "-r" (file-name-unquote localname))))))
(defun tramp-sudoedit-handle-set-file-modes (filename mode &optional flag)
"Like `set-file-modes' for Tramp files."
(if (file-exists-p filename)
;; Examine `file-attributes' cache to see if request can be
;; satisfied without remote operation.
- (if (tramp-use-file-attributes v)
- (tramp-check-cached-permissions v ?w)
- (tramp-sudoedit-send-command
- v "test" "-w" (file-name-unquote localname)))
+ (or (tramp-check-cached-permissions v ?w)
+ (tramp-sudoedit-send-command
+ v "test" "-w" (file-name-unquote localname)))
;; If file doesn't exist, check if directory is writable.
(and
(file-directory-p (file-name-directory filename))
nil)))
(defcustom tramp-use-file-attributes t
- "Whether to use \"file-attributes\" file property for check.
+ "Whether to use \"file-attributes\" connection property for check.
This is relevant for read, write, and execute permissions. On some file
systems using NFS4_ACL, the permission string as returned from `stat' or
`ls', is not sufficient to provide more fine-grained information.
"Like `file-readable-p' for Tramp files."
(with-parsed-tramp-file-name (expand-file-name filename) nil
(with-tramp-file-property v localname "file-readable-p"
- (or (tramp-check-cached-permissions v ?r)
+ (or (tramp-check-cached-permissions v ?r 'force)
;; `tramp-check-cached-permissions' doesn't handle symbolic
;; links.
- (when-let ((symlink (file-symlink-p filename)))
- (and (stringp symlink)
- (file-readable-p
- (concat (file-remote-p filename) symlink))))))))
+ (and-let* ((symlink (file-symlink-p filename))
+ ((stringp symlink))
+ ((file-readable-p (file-truename filename)))))))))
(defun tramp-handle-file-regular-p (filename)
"Like `file-regular-p' for Tramp files."
(with-parsed-tramp-file-name (expand-file-name filename) nil
(with-tramp-file-property v localname "file-writable-p"
(if (file-exists-p filename)
- (tramp-check-cached-permissions v ?w)
+ (or (tramp-check-cached-permissions v ?w 'force)
+ ;; `tramp-check-cached-permissions' doesn't handle
+ ;; symbolic links.
+ (and-let* ((symlink (file-symlink-p filename))
+ ((stringp symlink))
+ ((file-writable-p (file-truename filename))))))
;; If file doesn't exist, check if directory is writable.
(and (file-directory-p (file-name-directory filename))
(file-writable-p (file-name-directory filename)))))))
(when vec (tramp-message vec 7 "locale %s" (or locale "C")))
(or locale "C"))))
-(defun tramp-check-cached-permissions (vec access)
+(defun tramp-check-cached-permissions (vec access &optional force)
"Check `file-attributes' caches for VEC.
-Return t if according to the cache access type ACCESS is known to
-be granted."
- (when-let ((offset (cond
- ((eq ?r access) 1)
- ((eq ?w access) 2)
- ((eq ?x access) 3)
- ((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)))
- (or
- ;; Not a symlink.
- (eq t (file-attribute-type file-attr))
- (null (file-attribute-type file-attr)))
+Return t if according to the cache access type ACCESS is known to be
+granted, if `tramp-use-file-attributes' mandates this. If FORCE is
+non-nil, use connection property \"file-attributes\" mandatory."
+ (when-let* ((offset (cond
+ ((eq ?r access) 1)
+ ((eq ?w access) 2)
+ ((eq ?x access) 3)
+ ((eq ?s access) 3)
+ ((eq ?t access) 3)))
+ ((or force (tramp-use-file-attributes vec)))
+ (file-attr (file-attributes (tramp-make-tramp-file-name vec)))
+ ;; Not a symlink.
+ ((not (stringp (file-attribute-type file-attr))))
+ (remote-uid (tramp-get-remote-uid vec 'integer))
+ (remote-gid (tramp-get-remote-gid vec 'integer)))
(or
;; World accessible.
(eq access (aref (file-attribute-modes file-attr) (+ offset 6)))
(ignore-errors (delete-file tmp-name1))
(ignore-errors (delete-file tmp-name2)))))))
+(tramp--test-deftest-without-file-attributes tramp-test20-file-modes)
+
;; Method "smb" could run into "NT_STATUS_REVISION_MISMATCH" error.
(defmacro tramp--test-ignore-add-name-to-file-error (&rest body)
"Run BODY, ignoring \"error with add-name-to-file\" file error."
(should (string-equal (file-truename dir1) (expand-file-name dir1)))
(should (string-equal (file-truename dir2) (expand-file-name dir2)))))))
+(tramp--test-deftest-without-file-attributes tramp-test21-file-links)
+
(ert-deftest tramp-test22-file-times ()
"Check `set-file-times' and `file-newer-than-file-p'."
(skip-unless (tramp--test-enabled))