Function: tramp-skeleton-write-region
tramp-skeleton-write-region is a macro defined in tramp.el.gz.
Signature
(tramp-skeleton-write-region START END FILENAME APPEND VISIT LOCKNAME MUSTBENEW &rest BODY)
Documentation
Skeleton for tramp-*-handle-write-region.
BODY is the backend specific code.
Source Code
;; Defined in /usr/src/emacs/lisp/net/tramp.el.gz
(defmacro tramp-skeleton-write-region
(start end filename append visit lockname mustbenew &rest body)
"Skeleton for `tramp-*-handle-write-region'.
BODY is the backend specific code."
(declare (indent 7) (debug t))
;; Sometimes, there is another file name handler responsible for
;; VISIT, for example `jka-compr-handler'. We must respect this.
;; See Bug#55166.
`(let* ((filename (expand-file-name ,filename))
(lockname (file-truename (or ,lockname filename)))
(handler (and (stringp ,visit)
(let ((inhibit-file-name-handlers
`(tramp-file-name-handler
tramp-crypt-file-name-handler
. ,inhibit-file-name-handlers))
(inhibit-file-name-operation 'write-region))
(find-file-name-handler ,visit 'write-region))))
;; We use this to save the value of
;; `last-coding-system-used' after writing the tmp file. At
;; the end of the function, we set `last-coding-system-used'
;; to this saved value. This way, any intermediary coding
;; systems used while talking to the remote shell or
;; suchlike won't hose this variable. This approach was
;; snarfed from ange-ftp.el.
coding-system-used)
(with-parsed-tramp-file-name filename nil
(if handler
(progn
(tramp-message
v 5 "Calling handler `%s' for visiting `%s'" handler ,visit)
(funcall
handler 'write-region
,start ,end filename ,append ,visit lockname ,mustbenew))
(when (and ,mustbenew (file-exists-p filename)
(or (eq ,mustbenew 'excl)
(not
(y-or-n-p
(format
"File %s exists; overwrite anyway?" filename)))))
(tramp-error v 'file-already-exists filename))
(let ((file-locked (eq (file-locked-p lockname) t))
(uid (or (file-attribute-user-id
(file-attributes filename 'integer))
(tramp-get-remote-uid v 'integer)))
(gid (or (file-attribute-group-id
(file-attributes filename 'integer))
(tramp-get-remote-gid v 'integer)))
(attributes (file-extended-attributes filename))
(curbuf (current-buffer)))
;; Lock file.
(when (and (not (auto-save-file-name-p
(file-name-nondirectory filename)))
(tramp-tramp-file-p lockname)
(not file-locked))
(setq file-locked t)
(lock-file lockname))
;; The body.
,@body
;; We must also flush the cache of the directory, because
;; `file-attributes' reads the values from there.
(tramp-flush-file-properties v localname)
;; Set the "file-exists-p" file property, because it is
;; likely that it is needed shortly after `write-region'.
(tramp-set-file-property v localname "file-exists-p" t)
(let (last-coding-system-used (need-chown t))
;; Set file modification time.
(when-let* (((or (eq ,visit t) (stringp ,visit)))
(file-attr (file-attributes filename 'integer)))
(set-visited-file-modtime
;; We must pass modtime explicitly, because FILENAME
;; can be different from (buffer-file-name), f.e. if
;; `file-precious-flag' is set.
(or (file-attribute-modification-time file-attr)
(current-time)))
(when (and (= (file-attribute-user-id file-attr) uid)
(= (file-attribute-group-id file-attr) gid))
(setq need-chown nil)))
;; Set the ownership.
(when need-chown
(tramp-set-file-uid-gid filename uid gid))
;; Set extended attributes. We ignore possible errors,
;; because ACL strings or SELinux contexts could be incompatible.
(when attributes
(ignore-errors
(set-file-extended-attributes filename attributes)))
;; Unlock file.
(when file-locked
(unlock-file lockname))
;; Sanity check.
(unless (equal curbuf (current-buffer))
(tramp-error
v 'file-error
"Buffer has changed from `%s' to `%s'" curbuf (current-buffer)))
(when (and (null noninteractive)
(or (eq ,visit t) (string-or-null-p ,visit)))
(tramp-message v 0 "Wrote %s" filename))
(run-hooks 'tramp-handle-write-region-hook))))
;; Make `last-coding-system-used' have the right value.
(when coding-system-used
(setq last-coding-system-used coding-system-used)))))