emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: backup method


From: Richard Stallman
Subject: Re: backup method
Date: Tue, 01 Feb 2005 08:30:35 -0500

    - if backup-by-copying is t, then when writing the backup file we may follow
      a symlink (planted by some other user) to some important file.

Simply writing a file in such a directory would raise the same issue,
right?  If so, it really has nothing to do with backups.

I think the fix is to treat files in such directories as precious.
Not because they really are precious, but because the handling of a
precious file might avoid the problem.

However, I think the existing code for basic-save-buffer-2 that handles
file-precious-flag is not entirely correct for this.  It tries to
find a name that does not exist, but doesn't protect against the
possibility that someone might create the name after it tests
but before it uses the name.

I wrote this patch to try to fix it.  I also tried fixing
backup-copy-buffer in a similar way, but isn't perfect;
someone could delete the file and create a symlink in between
the call to write-region and the call to copy-file.
So we would need an "exclusive" option in copy-file too.



*** files.el    28 Jan 2005 09:33:33 -0500      1.744
--- files.el    31 Jan 2005 08:33:15 -0500      
***************
*** 3312,3350 ****
          ;; This requires write access to the containing dir,
          ;; which is why we don't try it if we don't have that access.
          (let ((realname buffer-file-name)
!               tempname nogood i succeed
                (old-modtime (visited-file-modtime)))
!           (setq i 0)
!           (setq nogood t)
!           ;; Find the temporary name to write under.
!           (while nogood
!             (setq tempname (format
!                             (if (and (eq system-type 'ms-dos)
!                                      (not (msdos-long-file-names)))
!                                 "%s#%d.tm#" ; MSDOS limits files to 8+3
!                               (if (memq system-type '(vax-vms axp-vms))
!                                   "%s$tmp$%d"
!                                 "%s#tmp#%d"))
!                             dir i))
!             (setq nogood (file-exists-p tempname))
!             (setq i (1+ i)))
            (unwind-protect
!               (progn (clear-visited-file-modtime)
!                      (write-region (point-min) (point-max)
!                                    tempname nil realname
!                                    buffer-file-truename)
!                      (setq succeed t))
!             ;; If writing the temp file fails,
!             ;; delete the temp file.
!             (or succeed
!                 (progn
!                   (condition-case nil
!                       (delete-file tempname)
!                     (file-error nil))
!                   (set-visited-file-modtime old-modtime))))
!           ;; Since we have created an entirely new file
!           ;; and renamed it, make sure it gets the
!           ;; right permission bits set.
            (setq setmodes (or setmodes (cons (file-modes buffer-file-name)
                                              buffer-file-name)))
            ;; We succeeded in writing the temp file,
--- 3314,3354 ----
          ;; This requires write access to the containing dir,
          ;; which is why we don't try it if we don't have that access.
          (let ((realname buffer-file-name)
!               tempname succeed
!               (umask (default-file-modes))
                (old-modtime (visited-file-modtime)))
!           ;; Create temp files with strict access rights.  It's easy to
!           ;; loosen them later, whereas it's impossible to close the
!           ;; time-window of loose permissions otherwise.
            (unwind-protect
!               (progn
!                 (clear-visited-file-modtime)
!                 (set-default-file-modes ?\700)
!                 ;; Try various temporary names.
!                 ;; This code follows the example of make-temp-file,
!                 ;; but it calls write-region in the appropriate way
!                 ;; for saving the buffer.
!                 (while (condition-case ()
!                            (progn
!                              (setq tempname
!                                    (make-temp-name
!                                     (expand-file-name "tmp" dir)))
!                              (write-region (point-min) (point-max)
!                                            tempname nil  realname
!                                            buffer-file-truename 'excl)
!                              nil)
!                          (file-already-exists t))
!                   ;; The file was somehow created by someone else between
!                   ;; `make-temp-name' and `write-region', let's try again.
!                   nil)
!                 (setq succeed t))
!             ;; Reset the umask.
!             (set-default-file-modes umask)
!             ;; If we failed, restore the buffer's modtime.
!             (unless succeed
!               (set-visited-file-modtime old-modtime)))
!           ;; Since we have created an entirely new file,
!           ;; make sure it gets the right permission bits set.
            (setq setmodes (or setmodes (cons (file-modes buffer-file-name)
                                              buffer-file-name)))
            ;; We succeeded in writing the temp file,




reply via email to

[Prev in Thread] Current Thread [Next in Thread]