mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-23 07:19:15 +00:00
Further fixes while testing tramp-crypt
* doc/misc/tramp.texi (External methods): Remove experimental note for rclone. (Keeping files encrypted): Mark file encryption as experimental. * lisp/net/tramp-adb.el (tramp-adb-file-name-handler-alist): Use `tramp-handle-file-truename'. (tramp-adb-handle-file-truename): Remove. * lisp/net/tramp-crypt.el (tramp-crypt-file-name-handler-alist): Add `file-writable-p'. (tramp-crypt-send-command): Return t if no error. (tramp-crypt-do-encrypt-or-decrypt-file-name) (tramp-crypt-do-encrypt-or-decrypt-file): Raise an error if it fails. (tramp-crypt-do-copy-or-rename-file): Flush file properties also when copying a directory. (tramp-crypt-handle-file-writable-p): New defun. (tramp-crypt-handle-insert-directory): Check for library `text-property-search'. * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-set-file-uid-gid): Rename from `tramp-gvfs-set-file-uid-gid'. * lisp/net/tramp-sh.el (tramp-sh-handle-file-truename): Use `tramp-handle-file-truename' as fallback. * lisp/net/tramp.el (tramp-handle-file-truename): Let-bind `tramp-crypt-enabled' to nil. (tramp-handle-write-region): Set also file ownership. * test/lisp/net/tramp-tests.el (tramp-test17-insert-directory): Skip if needed.
This commit is contained in:
parent
54efe18959
commit
459bd56f46
@ -1185,9 +1185,6 @@ for accessing the system storage, you shall prefer this.
|
||||
@ref{GVFS-based methods} for example, methods @option{gdrive} and
|
||||
@option{nextcloud}.
|
||||
|
||||
@strong{Note}: The @option{rclone} method is experimental, don't use
|
||||
it in production systems!
|
||||
|
||||
@end table
|
||||
|
||||
|
||||
@ -1732,6 +1729,7 @@ Convenience method to access vagrant boxes. It is often used in
|
||||
multi-hop file names like
|
||||
@file{@value{prefix}vagrant@value{postfixhop}box|sudo@value{postfixhop}box@value{postfix}/path/to/file},
|
||||
where @samp{box} is the name of the vagrant box.
|
||||
|
||||
@end table
|
||||
|
||||
|
||||
@ -2655,6 +2653,9 @@ to direct all auto saves to that location.
|
||||
@section Protect remote files by encryption
|
||||
@cindex Encrypt remote directories
|
||||
|
||||
@strong{Note}: File encryption in @value{tramp} is experimental, don't
|
||||
use it in production systems!
|
||||
|
||||
Sometimes, it is desirable to protect files located on remote
|
||||
directories, like cloud storages. In order to do this, you might
|
||||
instruct @value{tramp} to encrypt all files copied to a given remote
|
||||
|
@ -136,7 +136,7 @@ It is used for TCP/IP devices."
|
||||
(file-selinux-context . tramp-handle-file-selinux-context)
|
||||
(file-symlink-p . tramp-handle-file-symlink-p)
|
||||
(file-system-info . tramp-adb-handle-file-system-info)
|
||||
(file-truename . tramp-adb-handle-file-truename)
|
||||
(file-truename . tramp-handle-file-truename)
|
||||
(file-writable-p . tramp-adb-handle-file-writable-p)
|
||||
(find-backup-file-name . tramp-handle-find-backup-file-name)
|
||||
;; `get-file-buffer' performed by default handler.
|
||||
@ -227,104 +227,6 @@ ARGUMENTS to pass to the OPERATION."
|
||||
(string-to-number (match-string 2))))
|
||||
(* 1024 (string-to-number (match-string 3)))))))))
|
||||
|
||||
;; This is derived from `tramp-sh-handle-file-truename'. Maybe the
|
||||
;; code could be shared?
|
||||
(defun tramp-adb-handle-file-truename (filename)
|
||||
"Like `file-truename' for Tramp files."
|
||||
;; Preserve trailing "/".
|
||||
(funcall
|
||||
(if (directory-name-p filename) #'file-name-as-directory #'identity)
|
||||
;; Quote properly.
|
||||
(funcall
|
||||
(if (tramp-compat-file-name-quoted-p filename)
|
||||
#'tramp-compat-file-name-quote #'identity)
|
||||
(with-parsed-tramp-file-name
|
||||
(tramp-compat-file-name-unquote (expand-file-name filename)) nil
|
||||
(tramp-make-tramp-file-name
|
||||
v
|
||||
(with-tramp-file-property v localname "file-truename"
|
||||
(let (result) ; result steps in reverse order
|
||||
(tramp-message v 4 "Finding true name for `%s'" filename)
|
||||
(let* ((steps (split-string localname "/" 'omit))
|
||||
(localnamedir (tramp-run-real-handler
|
||||
'file-name-as-directory (list localname)))
|
||||
(is-dir (string= localname localnamedir))
|
||||
(thisstep nil)
|
||||
(numchase 0)
|
||||
;; Don't make the following value larger than
|
||||
;; necessary. People expect an error message in a
|
||||
;; timely fashion when something is wrong; otherwise
|
||||
;; they might think that Emacs is hung. Of course,
|
||||
;; correctness has to come first.
|
||||
(numchase-limit 20)
|
||||
symlink-target)
|
||||
(while (and steps (< numchase numchase-limit))
|
||||
(setq thisstep (pop steps))
|
||||
(tramp-message
|
||||
v 5 "Check %s"
|
||||
(string-join
|
||||
(append '("") (reverse result) (list thisstep)) "/"))
|
||||
(setq symlink-target
|
||||
(tramp-compat-file-attribute-type
|
||||
(file-attributes
|
||||
(tramp-make-tramp-file-name
|
||||
v
|
||||
(string-join
|
||||
(append
|
||||
'("") (reverse result) (list thisstep)) "/")))))
|
||||
(cond ((string= "." thisstep)
|
||||
(tramp-message v 5 "Ignoring step `.'"))
|
||||
((string= ".." thisstep)
|
||||
(tramp-message v 5 "Processing step `..'")
|
||||
(pop result))
|
||||
((stringp symlink-target)
|
||||
;; It's a symlink, follow it.
|
||||
(tramp-message v 5 "Follow symlink to %s" symlink-target)
|
||||
(setq numchase (1+ numchase))
|
||||
(when (file-name-absolute-p symlink-target)
|
||||
(setq result nil))
|
||||
;; If the symlink was absolute, we'll get a string
|
||||
;; like "/user@host:/some/target"; extract the
|
||||
;; "/some/target" part from it.
|
||||
(when (tramp-tramp-file-p symlink-target)
|
||||
(unless (tramp-equal-remote filename symlink-target)
|
||||
(tramp-error
|
||||
v 'file-error
|
||||
"Symlink target `%s' on wrong host" symlink-target))
|
||||
(setq symlink-target localname))
|
||||
(setq steps
|
||||
(append (split-string symlink-target "/" 'omit)
|
||||
steps)))
|
||||
(t
|
||||
;; It's a file.
|
||||
(setq result (cons thisstep result)))))
|
||||
(when (>= numchase numchase-limit)
|
||||
(tramp-error
|
||||
v 'file-error
|
||||
"Maximum number (%d) of symlinks exceeded" numchase-limit))
|
||||
(setq result (reverse result))
|
||||
;; Combine list to form string.
|
||||
(setq result
|
||||
(if result
|
||||
(string-join (cons "" result) "/")
|
||||
"/"))
|
||||
(when (and is-dir (or (string-empty-p result)
|
||||
(not (string= (substring result -1) "/"))))
|
||||
(setq result (concat result "/"))))
|
||||
|
||||
;; Detect cycle.
|
||||
(when (and (file-symlink-p filename)
|
||||
(string-equal result localname))
|
||||
(tramp-error
|
||||
v 'file-error
|
||||
"Apparent cycle of symbolic links for %s" filename))
|
||||
;; If the resulting localname looks remote, we must quote it
|
||||
;; for security reasons.
|
||||
(when (file-remote-p result)
|
||||
(setq result (tramp-compat-file-name-quote result 'top)))
|
||||
(tramp-message v 4 "True name of `%s' is `%s'" localname result)
|
||||
result)))))))
|
||||
|
||||
(defun tramp-adb-handle-file-attributes (filename &optional id-format)
|
||||
"Like `file-attributes' for Tramp files."
|
||||
(unless id-format (setq id-format 'integer))
|
||||
|
@ -24,7 +24,7 @@
|
||||
;;; Commentary:
|
||||
|
||||
;; Access functions for crypted remote files. It uses encfs to
|
||||
;; encrypt/ decrypt the files on a remote directory. A remote
|
||||
;; encrypt / decrypt the files on a remote directory. A remote
|
||||
;; directory, which shall include crypted files, must be declared in
|
||||
;; `tramp-crypt-directories' via command `tramp-crypt-add-directory'.
|
||||
;; All files in that directory, including all subdirectories, are
|
||||
@ -189,8 +189,8 @@ If NAME doesn't belong to a crypted remote directory, retun nil."
|
||||
(file-selinux-context . ignore)
|
||||
(file-symlink-p . tramp-handle-file-symlink-p)
|
||||
(file-system-info . tramp-crypt-handle-file-system-info)
|
||||
;; (file-truename . tramp-crypt-handle-file-truename)
|
||||
;; (file-writable-p . ignore)
|
||||
;; `file-truename' performed by default handler.
|
||||
(file-writable-p . tramp-crypt-handle-file-writable-p)
|
||||
(find-backup-file-name . tramp-handle-find-backup-file-name)
|
||||
;; `get-file-buffer' performed by default handler.
|
||||
(insert-directory . tramp-crypt-handle-insert-directory)
|
||||
@ -351,7 +351,7 @@ connection if a previous connection has died for some reason."
|
||||
|
||||
(defun tramp-crypt-send-command (vec &rest args)
|
||||
"Send encfsctl command to connection VEC.
|
||||
ARGS are the arguments."
|
||||
ARGS are the arguments. It returns t if ran successful, and nil otherwise."
|
||||
(tramp-crypt-maybe-open-connection vec)
|
||||
(with-current-buffer (tramp-get-connection-buffer vec)
|
||||
(erase-buffer))
|
||||
@ -380,11 +380,12 @@ ARGS are the arguments."
|
||||
;; Save the password.
|
||||
(ignore-errors
|
||||
(and (functionp tramp-password-save-function)
|
||||
(funcall tramp-password-save-function)))))))
|
||||
(funcall tramp-password-save-function)))
|
||||
t))))
|
||||
|
||||
(defun tramp-crypt-do-encrypt-or-decrypt-file-name (op name)
|
||||
"Return encrypted/ decrypted NAME if NAME belongs to a crypted directory.
|
||||
OP must be `encrypt' or `decrypt'.
|
||||
"Return encrypted / decrypted NAME if NAME belongs to a crypted directory.
|
||||
OP must be `encrypt' or `decrypt'. Raise an error if this fails.
|
||||
Otherwise, return NAME."
|
||||
(if-let ((tramp-crypt-enabled t)
|
||||
(dir (tramp-crypt-file-name-p name))
|
||||
@ -399,9 +400,12 @@ Otherwise, return NAME."
|
||||
(unless (string-equal localname "/")
|
||||
(with-tramp-file-property
|
||||
crypt-vec localname (concat (symbol-name op) "-file-name")
|
||||
(tramp-crypt-send-command
|
||||
crypt-vec (if (eq op 'encrypt) "encode" "decode")
|
||||
(tramp-compat-temporary-file-directory) localname)
|
||||
(unless (tramp-crypt-send-command
|
||||
crypt-vec (if (eq op 'encrypt) "encode" "decode")
|
||||
(tramp-compat-temporary-file-directory) localname)
|
||||
(tramp-error
|
||||
crypt-vec "%s of file name %s failed."
|
||||
(if (eq op 'encrypt) "Encoding" "Decoding") name))
|
||||
(with-current-buffer (tramp-get-connection-buffer crypt-vec)
|
||||
(goto-char (point-min))
|
||||
(buffer-substring (point-min) (point-at-eol)))))))
|
||||
@ -419,9 +423,10 @@ Otherwise, return NAME."
|
||||
(tramp-crypt-do-encrypt-or-decrypt-file-name 'decrypt name))
|
||||
|
||||
(defun tramp-crypt-do-encrypt-or-decrypt-file (op root infile outfile)
|
||||
"Encrypt/ decrypt file INFILE to OUTFILE according to crypted directory ROOT.
|
||||
"Encrypt / decrypt file INFILE to OUTFILE according to crypted directory ROOT.
|
||||
Both files must be local files. OP must be `encrypt' or `decrypt'.
|
||||
If OP ist `decrypt', the basename of INFILE must be an encrypted file name."
|
||||
If OP ist `decrypt', the basename of INFILE must be an encrypted file name.
|
||||
Raise an error if this fails."
|
||||
(when-let ((tramp-crypt-enabled t)
|
||||
(dir (tramp-crypt-file-name-p root))
|
||||
(crypt-vec (tramp-crypt-dissect-file-name dir)))
|
||||
@ -429,10 +434,13 @@ If OP ist `decrypt', the basename of INFILE must be an encrypted file name."
|
||||
(if (eq op 'decrypt) 'binary coding-system-for-read))
|
||||
(coding-system-for-write
|
||||
(if (eq op 'encrypt) 'binary coding-system-for-write)))
|
||||
(tramp-crypt-send-command
|
||||
crypt-vec "cat" (and (eq op 'encrypt) "--reverse")
|
||||
(file-name-directory infile)
|
||||
(concat "/" (file-name-nondirectory infile)))
|
||||
(unless (tramp-crypt-send-command
|
||||
crypt-vec "cat" (and (eq op 'encrypt) "--reverse")
|
||||
(file-name-directory infile)
|
||||
(concat "/" (file-name-nondirectory infile)))
|
||||
(tramp-error
|
||||
crypt-vec "%s of file %s failed."
|
||||
(if (eq op 'encrypt) "Encrypting" "Decrypting") infile))
|
||||
(with-current-buffer (tramp-get-connection-buffer crypt-vec)
|
||||
(write-region nil nil outfile)))))
|
||||
|
||||
@ -520,16 +528,17 @@ absolute file names."
|
||||
(error "Unknown operation `%s', must be `copy' or `rename'" op))
|
||||
|
||||
(setq filename (file-truename filename))
|
||||
(if (file-directory-p filename)
|
||||
(progn
|
||||
(copy-directory filename newname keep-date t)
|
||||
(when (eq op 'rename) (delete-directory filename 'recursive)))
|
||||
(let ((t1 (tramp-crypt-file-name-p filename))
|
||||
(t2 (tramp-crypt-file-name-p newname))
|
||||
(encrypt-filename (tramp-crypt-encrypt-file-name filename))
|
||||
(encrypt-newname (tramp-crypt-encrypt-file-name newname))
|
||||
(msg-operation (if (eq op 'copy) "Copying" "Renaming")))
|
||||
|
||||
(let ((t1 (tramp-crypt-file-name-p filename))
|
||||
(t2 (tramp-crypt-file-name-p newname))
|
||||
(encrypt-filename (tramp-crypt-encrypt-file-name filename))
|
||||
(encrypt-newname (tramp-crypt-encrypt-file-name newname))
|
||||
(msg-operation (if (eq op 'copy) "Copying" "Renaming")))
|
||||
(if (file-directory-p filename)
|
||||
(progn
|
||||
(copy-directory filename newname keep-date t)
|
||||
(when (eq op 'rename)
|
||||
(delete-directory filename 'recursive)))
|
||||
|
||||
(with-parsed-tramp-file-name (if t1 filename newname) nil
|
||||
(unless (file-exists-p filename)
|
||||
@ -581,15 +590,15 @@ absolute file names."
|
||||
(rename-file filename tmpfile1 t))
|
||||
(tramp-crypt-encrypt-file t2 tmpfile1 tmpfile2)
|
||||
(rename-file tmpfile2 encrypt-newname ok-if-already-exists)))
|
||||
(delete-directory tmpdir 'recursive)))
|
||||
(delete-directory tmpdir 'recursive))))))
|
||||
|
||||
(when (and t1 (eq op 'rename))
|
||||
(with-parsed-tramp-file-name filename v1
|
||||
(tramp-flush-file-properties v1 v1-localname)))
|
||||
(when (and t1 (eq op 'rename))
|
||||
(with-parsed-tramp-file-name filename v1
|
||||
(tramp-flush-file-properties v1 v1-localname)))
|
||||
|
||||
(when t2
|
||||
(with-parsed-tramp-file-name newname v2
|
||||
(tramp-flush-file-properties v2 v2-localname))))))))
|
||||
(when t2
|
||||
(with-parsed-tramp-file-name newname v2
|
||||
(tramp-flush-file-properties v2 v2-localname)))))
|
||||
|
||||
(defun tramp-crypt-handle-copy-file
|
||||
(filename newname &optional ok-if-already-exists keep-date
|
||||
@ -692,28 +701,35 @@ absolute file names."
|
||||
;; #'file-system-info.
|
||||
'file-system-info (list (tramp-crypt-encrypt-file-name filename))))
|
||||
|
||||
(defun tramp-crypt-handle-file-writable-p (filename)
|
||||
"Like `file-writable-p' for Tramp files."
|
||||
(let (tramp-crypt-enabled)
|
||||
(file-writable-p (tramp-crypt-encrypt-file-name filename))))
|
||||
|
||||
(defun tramp-crypt-handle-insert-directory
|
||||
(filename switches &optional wildcard full-directory-p)
|
||||
"Like `insert-directory' for Tramp files."
|
||||
(let (tramp-crypt-enabled)
|
||||
(tramp-handle-insert-directory
|
||||
(tramp-crypt-encrypt-file-name filename)
|
||||
switches wildcard full-directory-p)
|
||||
(let* ((filename (file-name-as-directory filename))
|
||||
(enc (tramp-crypt-encrypt-file-name filename))
|
||||
match string)
|
||||
(goto-char (point-min))
|
||||
(while (setq match (text-property-search-forward 'dired-filename t t))
|
||||
(setq string
|
||||
(buffer-substring
|
||||
(prop-match-beginning match) (prop-match-end match))
|
||||
string (if (file-name-absolute-p string)
|
||||
(tramp-crypt-decrypt-file-name string)
|
||||
(substring
|
||||
(tramp-crypt-decrypt-file-name (concat enc string))
|
||||
(length filename))))
|
||||
(delete-region (prop-match-beginning match) (prop-match-end match))
|
||||
(insert (propertize string 'dired-filename t))))))
|
||||
;; This package has been added to Emacs 27.1.
|
||||
(when (load "text-property-search" 'noerror 'nomessage)
|
||||
(let (tramp-crypt-enabled)
|
||||
(tramp-handle-insert-directory
|
||||
(tramp-crypt-encrypt-file-name filename)
|
||||
switches wildcard full-directory-p)
|
||||
(let* ((filename (file-name-as-directory filename))
|
||||
(enc (tramp-crypt-encrypt-file-name filename))
|
||||
match string)
|
||||
(goto-char (point-min))
|
||||
(while (setq match (text-property-search-forward 'dired-filename t t))
|
||||
(setq string
|
||||
(buffer-substring
|
||||
(prop-match-beginning match) (prop-match-end match))
|
||||
string (if (file-name-absolute-p string)
|
||||
(tramp-crypt-decrypt-file-name string)
|
||||
(substring
|
||||
(tramp-crypt-decrypt-file-name (concat enc string))
|
||||
(length filename))))
|
||||
(delete-region (prop-match-beginning match) (prop-match-end match))
|
||||
(insert (propertize string 'dired-filename t)))))))
|
||||
|
||||
(defun tramp-crypt-handle-make-directory (dir &optional parents)
|
||||
"Like `make-directory' for Tramp files."
|
||||
|
@ -1589,7 +1589,7 @@ If FILE-SYSTEM is non-nil, return file system attributes."
|
||||
(current-time)
|
||||
time)))))
|
||||
|
||||
(defun tramp-gvfs-set-file-uid-gid (filename &optional uid gid)
|
||||
(defun tramp-gvfs-handle-set-file-uid-gid (filename &optional uid gid)
|
||||
"Like `tramp-set-file-uid-gid' for Tramp files."
|
||||
(with-parsed-tramp-file-name filename nil
|
||||
(tramp-flush-file-properties v localname)
|
||||
|
@ -1153,59 +1153,9 @@ component is used as the target of the symlink."
|
||||
(tramp-shell-quote-argument localname)))))
|
||||
|
||||
;; Do it yourself.
|
||||
(t (let ((steps (split-string localname "/" 'omit))
|
||||
(thisstep nil)
|
||||
(numchase 0)
|
||||
;; Don't make the following value larger than
|
||||
;; necessary. People expect an error message in a
|
||||
;; timely fashion when something is wrong;
|
||||
;; otherwise they might think that Emacs is hung.
|
||||
;; Of course, correctness has to come first.
|
||||
(numchase-limit 20)
|
||||
symlink-target)
|
||||
(while (and steps (< numchase numchase-limit))
|
||||
(setq thisstep (pop steps))
|
||||
(tramp-message
|
||||
v 5 "Check %s"
|
||||
(string-join
|
||||
(append '("") (reverse result) (list thisstep)) "/"))
|
||||
(setq symlink-target
|
||||
(tramp-compat-file-attribute-type
|
||||
(file-attributes
|
||||
(tramp-make-tramp-file-name
|
||||
v
|
||||
(string-join
|
||||
(append
|
||||
'("") (reverse result) (list thisstep)) "/")
|
||||
'nohop))))
|
||||
(cond ((string= "." thisstep)
|
||||
(tramp-message v 5 "Ignoring step `.'"))
|
||||
((string= ".." thisstep)
|
||||
(tramp-message v 5 "Processing step `..'")
|
||||
(pop result))
|
||||
((stringp symlink-target)
|
||||
;; It's a symlink, follow it.
|
||||
(tramp-message
|
||||
v 5 "Follow symlink to %s" symlink-target)
|
||||
(setq numchase (1+ numchase))
|
||||
(when (file-name-absolute-p symlink-target)
|
||||
(setq result nil))
|
||||
(setq steps
|
||||
(append
|
||||
(split-string symlink-target "/" 'omit)
|
||||
steps)))
|
||||
(t
|
||||
;; It's a file.
|
||||
(setq result (cons thisstep result)))))
|
||||
(when (>= numchase numchase-limit)
|
||||
(tramp-error
|
||||
v 'file-error
|
||||
"Maximum number (%d) of symlinks exceeded" numchase-limit))
|
||||
(setq result (reverse result)
|
||||
;; Combine list to form string.
|
||||
result
|
||||
(if result (string-join (cons "" result) "/") "/"))
|
||||
(when (string-empty-p result) (setq result "/")))))
|
||||
(t (setq
|
||||
result
|
||||
(tramp-file-local-name (tramp-handle-file-truename filename)))))
|
||||
|
||||
;; Detect cycle.
|
||||
(when (and (file-symlink-p filename)
|
||||
|
@ -3381,6 +3381,8 @@ User is always nil."
|
||||
;; something is wrong; otherwise they might think that Emacs
|
||||
;; is hung. Of course, correctness has to come first.
|
||||
(numchase-limit 20)
|
||||
;; Unquoting could enable encryption.
|
||||
tramp-crypt-enabled
|
||||
symlink-target)
|
||||
(with-parsed-tramp-file-name result v1
|
||||
;; We cache only the localname.
|
||||
@ -3900,7 +3902,11 @@ of."
|
||||
|
||||
(let ((tmpfile (tramp-compat-make-temp-file filename))
|
||||
(modes (tramp-default-file-modes
|
||||
filename (and (eq mustbenew 'excl) 'nofollow))))
|
||||
filename (and (eq mustbenew 'excl) 'nofollow)))
|
||||
(uid (tramp-compat-file-attribute-user-id
|
||||
(file-attributes filename 'integer)))
|
||||
(gid (tramp-compat-file-attribute-group-id
|
||||
(file-attributes filename 'integer))))
|
||||
(when (and append (file-exists-p filename))
|
||||
(copy-file filename tmpfile 'ok))
|
||||
;; The permissions of the temporary file should be set. If
|
||||
@ -3919,15 +3925,18 @@ of."
|
||||
(error
|
||||
(delete-file tmpfile)
|
||||
(tramp-error
|
||||
v 'file-error "Couldn't write region to `%s'" filename))))
|
||||
v 'file-error "Couldn't write region to `%s'" filename)))
|
||||
|
||||
(tramp-flush-file-properties v localname)
|
||||
(tramp-flush-file-properties v localname)
|
||||
|
||||
;; Set file modification time.
|
||||
(when (or (eq visit t) (stringp visit))
|
||||
(set-visited-file-modtime
|
||||
(tramp-compat-file-attribute-modification-time
|
||||
(file-attributes filename))))
|
||||
;; Set file modification time.
|
||||
(when (or (eq visit t) (stringp visit))
|
||||
(set-visited-file-modtime
|
||||
(tramp-compat-file-attribute-modification-time
|
||||
(file-attributes filename))))
|
||||
|
||||
;; Set the ownership.
|
||||
(tramp-set-file-uid-gid filename uid gid))
|
||||
|
||||
;; The end.
|
||||
(when (and (null noninteractive)
|
||||
|
@ -2925,6 +2925,9 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
|
||||
;; (this is performed by `dired'). If FULL is nil, it shows just
|
||||
;; one file. So we refrain from testing.
|
||||
(skip-unless (not (tramp--test-ange-ftp-p)))
|
||||
;; `insert-directory' of crypted remote directories works only since
|
||||
;; Emacs 27.1.
|
||||
(skip-unless (or (not (tramp--test-crypt-p)) (tramp--test-emacs27-p)))
|
||||
|
||||
(dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
|
||||
(let* ((tmp-name1
|
||||
|
Loading…
Reference in New Issue
Block a user