Function: backup-buffer
backup-buffer is a byte-compiled function defined in files.el.gz.
Signature
(backup-buffer)
Documentation
Make a backup of the disk file visited by the current buffer, if appropriate.
This is normally done before saving the buffer the first time.
A backup may be done by renaming or by copying; see documentation of
variable make-backup-files. If it's done by renaming, then the file is
no longer accessible under its old name.
The value is non-nil after a backup was made by renaming.
It has the form (MODES EXTENDED-ATTRIBUTES BACKUPNAME).
MODES is the result of file-modes on the original
file; this means that the caller, after saving the buffer, should change
the modes of the new file to agree with the old modes.
EXTENDED-ATTRIBUTES is the result of file-extended-attributes
on the original file; this means that the caller, after saving
the buffer, should change the extended attributes of the new file
to agree with the old attributes.
BACKUPNAME is the backup file name, which is the old file renamed.
Probably introduced at or before Emacs version 19.11.
Source Code
;; Defined in /usr/src/emacs/lisp/files.el.gz
(defun backup-buffer ()
"Make a backup of the disk file visited by the current buffer, if appropriate.
This is normally done before saving the buffer the first time.
A backup may be done by renaming or by copying; see documentation of
variable `make-backup-files'. If it's done by renaming, then the file is
no longer accessible under its old name.
The value is non-nil after a backup was made by renaming.
It has the form (MODES EXTENDED-ATTRIBUTES BACKUPNAME).
MODES is the result of `file-modes' on the original
file; this means that the caller, after saving the buffer, should change
the modes of the new file to agree with the old modes.
EXTENDED-ATTRIBUTES is the result of `file-extended-attributes'
on the original file; this means that the caller, after saving
the buffer, should change the extended attributes of the new file
to agree with the old attributes.
BACKUPNAME is the backup file name, which is the old file renamed."
(when (and make-backup-files (not backup-inhibited) (not buffer-backed-up))
(let ((attributes (file-attributes buffer-file-name)))
(when (and attributes (memq (aref (elt attributes 8) 0) '(?- ?l)))
;; If specified name is a symbolic link, chase it to the target.
;; This makes backups in the directory where the real file is.
(let* ((real-file-name (file-chase-links buffer-file-name))
(backup-info (find-backup-file-name real-file-name)))
(when backup-info
(let* ((backupname (car backup-info))
(targets (cdr backup-info))
(old-versions
;; If have old versions to maybe delete,
;; ask the user to confirm now, before doing anything.
;; But don't actually delete til later.
(and targets
(booleanp delete-old-versions)
(or delete-old-versions
(y-or-n-p
(format "Delete excess backup versions of %s? "
real-file-name)))
targets))
(modes (file-modes buffer-file-name))
(extended-attributes
(file-extended-attributes buffer-file-name))
(copy-when-priv-mismatch
backup-by-copying-when-privileged-mismatch)
(make-copy
(or file-precious-flag backup-by-copying
;; Don't rename a suid or sgid file.
(and modes (< 0 (logand modes #o6000)))
(not (file-writable-p
(file-name-directory real-file-name)))
(and backup-by-copying-when-linked
(< 1 (file-nlinks real-file-name)))
(and (or backup-by-copying-when-mismatch
(and (integerp copy-when-priv-mismatch)
(let ((attr (file-attributes
real-file-name
'integer)))
(or (<= (file-attribute-user-id attr)
copy-when-priv-mismatch)
(<= (file-attribute-group-id attr)
copy-when-priv-mismatch)))))
(not (file-ownership-preserved-p real-file-name
t)))))
setmodes)
(condition-case ()
(progn
;; Actually make the backup file.
(if make-copy
(backup-buffer-copy real-file-name backupname
modes extended-attributes)
;; rename-file should delete old backup.
(rename-file real-file-name backupname t)
(setq setmodes (list modes extended-attributes
backupname)))
(setq buffer-backed-up t)
;; Now delete the old versions, if desired.
(dolist (old-version old-versions)
(delete-file old-version)))
(file-error nil))
;; If trouble writing the backup, write it in .emacs.d/%backup%.
(when (not buffer-backed-up)
(setq backupname (locate-user-emacs-file "%backup%~"))
(message "Cannot write backup file; backing up in %s"
backupname)
(sleep-for 1)
(backup-buffer-copy real-file-name backupname
modes extended-attributes)
(setq buffer-backed-up t))
setmodes)))))))