(format
"%s@%s.%s" (user-login-name) (system-name)
(tramp-get-lock-pid file))))
+
+ ;; Protect against security hole.
+ (with-parsed-tramp-file-name file nil
+ (when (and (not tramp-allow-unsafe-temporary-files)
+ (file-in-directory-p lockname temporary-file-directory)
+ (zerop (or (tramp-compat-file-attribute-user-id
+ (file-attributes file 'integer))
+ tramp-unknown-id-integer))
+ (not (with-tramp-connection-property
+ (tramp-get-process v) "unsafe-temporary-file"
+ (yes-or-no-p
+ (concat
+ "Lock file on local temporary directory, "
+ "do you want to continue? ")))))
+ (tramp-error v 'file-error "Unsafe lock file name")))
+
+ ;; Do the lock.
(let (create-lockfiles signal-hook-function)
(condition-case nil
(make-symbolic-link info lockname 'ok-if-already-exists)
(error
- (write-region info nil lockname)
- (set-file-modes lockname #o0644))))))))
+ (with-file-modes #o0644
+ (write-region info nil lockname)))))))))
(defun tramp-handle-make-lock-file-name (file)
"Like `make-lock-file-name' for Tramp files."
- (when (and create-lockfiles
- ;; This variable has been introduced with Emacs 28.1.
- (not (bound-and-true-p remote-file-name-inhibit-locks)))
- (with-parsed-tramp-file-name file nil
- (let ((result
- ;; Run plain `make-lock-file-name'.
- (tramp-run-real-handler #'make-lock-file-name (list file))))
- ;; Protect against security hole.
- (when (and (not tramp-allow-unsafe-temporary-files)
- (file-in-directory-p result temporary-file-directory)
- (zerop (or (tramp-compat-file-attribute-user-id
- (file-attributes file 'integer))
- tramp-unknown-id-integer))
- (not (with-tramp-connection-property
- (tramp-get-process v) "unsafe-temporary-file"
- (yes-or-no-p
- (concat
- "Lock file on local temporary directory, "
- "do you want to continue? ")))))
- (tramp-error v 'file-error "Unsafe lock file name"))
- result))))
+ (and create-lockfiles
+ ;; This variable has been introduced with Emacs 28.1.
+ (not (bound-and-true-p remote-file-name-inhibit-locks))
+ (tramp-run-real-handler 'make-lock-file-name (list file))))
(defun tramp-handle-unlock-file (file)
"Like `unlock-file' for Tramp files."
(when-let ((lockname (tramp-compat-make-lock-file-name file)))
(condition-case err
(delete-file lockname)
- (error (userlock--handle-unlock-error err)))))
+ ;; `userlock--handle-unlock-error' exists since Emacs 28.1.
+ (error (tramp-compat-funcall 'userlock--handle-unlock-error err)))))
(defun tramp-handle-load (file &optional noerror nomessage nosuffix must-suffix)
"Like `load' for Tramp files."
(declare-function tramp-smb-get-localname "tramp-smb")
(defvar ange-ftp-make-backup-files)
(defvar auto-save-file-name-transforms)
+(defvar lock-file-name-transforms)
+(defvar remote-file-name-inhibit-locks)
(defvar tramp-connection-properties)
(defvar tramp-copy-size-limit)
(defvar tramp-display-escape-sequence-regexp)
(setq auth-source-save-behavior nil
password-cache-expiry nil
remote-file-name-inhibit-cache nil
+ tramp-allow-unsafe-temporary-files t
tramp-cache-read-persistent-data t ;; For auth-sources.
tramp-copy-size-limit nil
tramp-persistency-file-name nil
(dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
- (tmp-name2 (tramp--test-make-temp-name nil quoted)))
+ (tmp-name2 (tramp--test-make-temp-name nil quoted))
+ tramp-allow-unsafe-temporary-files)
(unwind-protect
(progn
;; Create temporary file. This shall check for sensible
;; files, owned by root.
- (let ((tramp-auto-save-directory temporary-file-directory)
- tramp-allow-unsafe-temporary-files)
+ (let ((tramp-auto-save-directory temporary-file-directory))
(write-region "foo" nil tmp-name1)
(when (zerop (or (tramp-compat-file-attribute-user-id
(file-attributes tmp-name1))
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
(ange-ftp-make-backup-files t)
+ tramp-allow-unsafe-temporary-files
;; These settings are not used by Tramp, so we ignore them.
version-control delete-old-versions
(kept-old-versions (default-toplevel-value 'kept-old-versions))
;; Create temporary file. This shall check for sensible
;; files, owned by root.
(let ((backup-directory-alist `(("." . ,temporary-file-directory)))
- tramp-allow-unsafe-temporary-files
tramp-backup-directory-alist)
(write-region "foo" nil tmp-name1)
(when (zerop (or (tramp-compat-file-attribute-user-id
(skip-unless (not (tramp--test-ange-ftp-p)))
;; Since Emacs 28.1.
(skip-unless (and (fboundp 'lock-file) (fboundp 'unlock-file)))
+ (skip-unless (and (fboundp 'file-locked-p) (fboundp 'make-lock-file-name)))
+ ;; `lock-file', `unlock-file', `file-locked-p' and
+ ;; `make-lock-file-name' exists since Emacs 28.1. We don't want to
+ ;; see compiler warnings for older Emacsen.
(dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
(remote-file-name-inhibit-cache t)
(remote-file-name-inhibit-locks nil)
(create-lockfiles t)
+ tramp-allow-unsafe-temporary-files
(inhibit-message t)
;; tramp-rclone.el and tramp-sshfs.el cache the mounted files.
(tramp-cleanup-connection-hook
(unwind-protect
(progn
;; A simple file lock.
- (should-not (file-locked-p tmp-name1))
- (lock-file tmp-name1)
- (should (eq (file-locked-p tmp-name1) t))
+ (should-not (with-no-warnings (file-locked-p tmp-name1)))
+ (with-no-warnings (lock-file tmp-name1))
+ (should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
;; If it is locked already, nothing changes.
- (lock-file tmp-name1)
- (should (eq (file-locked-p tmp-name1) t))
+ (with-no-warnings (lock-file tmp-name1))
+ (should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
;; A new connection changes process id, and also the
;; lockname contents.
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
- (should (stringp (file-locked-p tmp-name1)))
+ (should (stringp (with-no-warnings (file-locked-p tmp-name1))))
;; When `remote-file-name-inhibit-locks' is set, nothing happens.
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
(let ((remote-file-name-inhibit-locks t))
- (lock-file tmp-name1)
- (should-not (file-locked-p tmp-name1)))
+ (with-no-warnings (lock-file tmp-name1))
+ (should-not (with-no-warnings (file-locked-p tmp-name1))))
;; When `lock-file-name-transforms' is set, another lock
;; file is used.
(let ((lock-file-name-transforms `((".*" ,tmp-name2))))
(should
(string-equal
- (make-lock-file-name tmp-name1)
- (make-lock-file-name tmp-name2)))
- (lock-file tmp-name1)
- (should (eq (file-locked-p tmp-name1) t))
- (unlock-file tmp-name1)
- (should-not (file-locked-p tmp-name1)))
+ (with-no-warnings (make-lock-file-name tmp-name1))
+ (with-no-warnings (make-lock-file-name tmp-name2))))
+ (with-no-warnings (lock-file tmp-name1))
+ (should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
+ (with-no-warnings (unlock-file tmp-name1))
+ (should-not (with-no-warnings (file-locked-p tmp-name1))))
;; Steal the file lock.
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
(cl-letf (((symbol-function #'read-char) (lambda (&rest _args) ?s)))
- (lock-file tmp-name1))
- (should (eq (file-locked-p tmp-name1) t))
+ (with-no-warnings (lock-file tmp-name1)))
+ (should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
;; Ignore the file lock.
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
(cl-letf (((symbol-function #'read-char) (lambda (&rest _args) ?p)))
- (lock-file tmp-name1))
- (should (stringp (file-locked-p tmp-name1)))
+ (with-no-warnings (lock-file tmp-name1)))
+ (should (stringp (with-no-warnings (file-locked-p tmp-name1))))
;; Quit the file lock machinery.
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
(cl-letf (((symbol-function #'read-char) (lambda (&rest _args) ?q)))
- (should-error (lock-file tmp-name1) :type 'file-locked)
+ (with-no-warnings
+ (should-error
+ (lock-file tmp-name1)
+ :type 'file-locked))
;; The same for `write-region'.
(should-error
- (write-region "foo" nil tmp-name1) :type 'file-locked)
+ (write-region "foo" nil tmp-name1)
+ :type 'file-locked)
(should-error
(write-region "foo" nil tmp-name1 nil nil tmp-name1)
:type 'file-locked)
;; The same for `set-visited-file-name'.
(with-temp-buffer
(should-error
- (set-visited-file-name tmp-name1) :type 'file-locked)))
- (should (stringp (file-locked-p tmp-name1)))
+ (set-visited-file-name tmp-name1)
+ :type 'file-locked)))
+ (should (stringp (with-no-warnings (file-locked-p tmp-name1))))
(should-not (file-exists-p tmp-name1)))
;; Cleanup.
(ignore-errors (delete-file tmp-name1))
- (unlock-file tmp-name1)
- (unlock-file tmp-name2)
- (should-not (file-locked-p tmp-name1))
- (should-not (file-locked-p tmp-name2))))))
+ (with-no-warnings (unlock-file tmp-name1))
+ (with-no-warnings (unlock-file tmp-name2))
+ (should-not (with-no-warnings (file-locked-p tmp-name1)))
+ (should-not (with-no-warnings (file-locked-p tmp-name2))))
+
+ (unwind-protect
+ ;; Create temporary file. This shall check for sensible
+ ;; files, owned by root.
+ (let ((lock-file-name-transforms auto-save-file-name-transforms))
+ (write-region "foo" nil tmp-name1)
+ (when (zerop (or (tramp-compat-file-attribute-user-id
+ (file-attributes tmp-name1))
+ tramp-unknown-id-integer))
+ (tramp-cleanup-connection
+ tramp-test-vec 'keep-debug 'keep-password)
+ (cl-letf (((symbol-function #'yes-or-no-p) #'ignore))
+ (should-error
+ (write-region "foo" nil tmp-name1)
+ :type 'file-error))
+ (tramp-cleanup-connection
+ tramp-test-vec 'keep-debug 'keep-password)
+ (cl-letf (((symbol-function #'yes-or-no-p)
+ #'tramp--test-always))
+ (write-region "foo" nil tmp-name1))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file tmp-name1))
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)))))
;; The functions were introduced in Emacs 26.1.
(ert-deftest tramp-test40-make-nearby-temp-file ()