428
+ − 1 ;;; auto-save.el -- Safer autosaving for EFS and tmp.
+ − 2
+ − 3 ;; Copyright (C) 1997 Free Software Foundation, Inc.
+ − 4 ;; Copyright (C) 1992 by Sebastian Kremer <sk@thp.uni-koeln.de>
793
+ − 5 ;; Copyright (C) 2001, 2002 Ben Wing.
428
+ − 6
+ − 7 ;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
+ − 8 ;; Maintainer: XEmacs Development Team
+ − 9 ;; Keywords: extensions, dumped
+ − 10 ;; Version: 1.26
+ − 11
+ − 12 ;; XEmacs is free software; you can redistribute it and/or modify it
+ − 13 ;; under the terms of the GNU General Public License as published by
793
+ − 14 ;; the Free Software Foundation; either version 2, or (at your option)
428
+ − 15 ;; any later version.
+ − 16
+ − 17 ;; XEmacs is distributed in the hope that it will be useful, but
+ − 18 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
+ − 19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ − 20 ;; General Public License for more details.
+ − 21
+ − 22 ;; You should have received a copy of the GNU General Public License
+ − 23 ;; along with XEmacs; see the file COPYING. If not, write to the Free
+ − 24 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ − 25 ;; 02111-1307, USA.
+ − 26
+ − 27 ;;; Synched up with: Not in FSF
+ − 28
+ − 29 ;;; Commentary:
+ − 30
+ − 31 ;; This file is dumped with XEmacs.
+ − 32
+ − 33 ;; Combines autosaving for efs (to a local or remote directory)
+ − 34 ;; with the ability to do autosaves to a fixed directory on a local
+ − 35 ;; disk, in case NFS is slow. The auto-save file used for
+ − 36 ;; /usr/foo/bar/baz.txt
+ − 37 ;; will be
464
+ − 38 ;; AUTOSAVE/#=2Fusr=2Ffoo=2Fbar=2Fbaz.txt#"
428
+ − 39 ;; assuming AUTOSAVE is the non-nil value of the variable
+ − 40 ;; `auto-save-directory'.
+ − 41
+ − 42 ;; Autosaves even if the current directory is not writable.
+ − 43
+ − 44 ;; Can limit autosave names to 14 characters using a hash function,
+ − 45 ;; see `auto-save-hash-p'.
+ − 46
+ − 47 ;; See `auto-save-directory' and `make-auto-save-file-name' and
+ − 48 ;; references therein for complete documentation.
+ − 49
+ − 50 ;; `M-x recover-all-files' will effectively do recover-file on all
+ − 51 ;; files whose autosave file is newer (one of the benefits of having
+ − 52 ;; all autosave files in the same place).
+ − 53
+ − 54 ;; This file is dumped with XEmacs.
+ − 55
+ − 56 ;; If you want to autosave in the fixed directory /tmp/USER-autosave/
+ − 57 ;; (setq auto-save-directory
+ − 58 ;; (concat "/tmp/" (user-login-name) "-autosave/"))
+ − 59
+ − 60 ;; If you don't want to save in /tmp (e.g., because it is swap
464
+ − 61 ;; mounted) but rather in ~/.autosave/
428
+ − 62 ;; (setq auto-save-directory (expand-file-name "~/.autosave/"))
+ − 63
+ − 64 ;; If you want to save each file in its own directory (the default)
+ − 65 ;; (setq auto-save-directory nil)
+ − 66 ;; You still can take advantage of autosaving efs remote files
+ − 67 ;; in a fixed local directory, `auto-save-directory-fallback' will
+ − 68 ;; be used.
+ − 69
+ − 70 ;; If you want to use 14 character hashed autosave filenames
+ − 71 ;; (setq auto-save-hash-p t)
+ − 72
+ − 73 ;; Finally, put this line after the others in your ~/.emacs:
+ − 74 ;; (require 'auto-save)
+ − 75
+ − 76
+ − 77 ;;; Acknowledgement:
+ − 78
+ − 79 ;; This code is loosely derived from autosave-in-tmp.el by Jamie
+ − 80 ;; Zawinski <jwz@jwz.org> (the version I had was last modified 22
+ − 81 ;; dec 90 jwz) and code submitted to ange-ftp-lovers on Sun, 5 Apr
+ − 82 ;; 92 23:20:47 EDT by drw@BOURBAKI.MIT.EDU (Dale R. Worley).
+ − 83 ;; auto-save.el tries to cover the functionality of those two
+ − 84 ;; packages.
+ − 85
+ − 86 ;; Valuable comments and help from Dale Worley, Andy Norman, Jamie
+ − 87 ;; Zawinski and Sandy Rutherford are gratefully acknowledged.
+ − 88
+ − 89 (defconst auto-save-version "1.26"
+ − 90 "Version number of auto-save.")
+ − 91
+ − 92 (provide 'auto-save)
+ − 93
+ − 94
+ − 95 ;;; Customization:
+ − 96
+ − 97 (defgroup auto-save nil
+ − 98 "Autosaving with support for efs and /tmp."
+ − 99 :group 'data)
+ − 100
+ − 101 (put 'auto-save-interval 'custom-type 'integer)
+ − 102 (put 'auto-save-interval 'factory-value '(300))
+ − 103 (custom-add-to-group 'auto-save 'auto-save-interval 'custom-variable)
+ − 104
+ − 105 (defcustom auto-save-directory nil
+ − 106
+ − 107 ;; Don't make this user-variable-p, it should be set in .emacs and
+ − 108 ;; left at that. In particular, it should remain constant across
+ − 109 ;; several Emacs session to make recover-all-files work.
+ − 110
+ − 111 ;; However, it's OK for it to be customizable, as most of the
+ − 112 ;; customizable variables are set at the time `.emacs' is read.
+ − 113 ;; -hniksic
+ − 114
+ − 115 "If non-nil, fixed directory for autosaving: all autosave files go
+ − 116 there. If this directory does not yet exist at load time, it is
+ − 117 created and its mode is set to 0700 so that nobody else can read your
+ − 118 autosave files.
+ − 119
+ − 120 If nil, each autosave files goes into the same directory as its
+ − 121 corresponding visited file.
+ − 122
+ − 123 A non-nil `auto-save-directory' could be on a local disk such as in
+ − 124 /tmp, then auto-saves will always be fast, even if NFS or the
+ − 125 automounter is slow. In the usual case of /tmp being locally mounted,
+ − 126 note that if you run emacs on two different machines, they will not
+ − 127 see each other's auto-save files.
+ − 128
+ − 129 The value \(expand-file-name \"~/.autosave/\"\) might be better if /tmp
+ − 130 is mounted from swap (possible in SunOS, type `df /tmp' to find out)
+ − 131 and thus vanishes after a reboot, or if your system is particularly
+ − 132 thorough when cleaning up /tmp, clearing even non-empty subdirectories.
+ − 133
+ − 134 It should never be an efs remote filename because that would
+ − 135 defeat `efs-auto-save-remotely'.
+ − 136
+ − 137 Unless you set `auto-save-hash-p', you shouldn't set this to a
+ − 138 directory in a filesystem that does not support long filenames, since
+ − 139 a file named
+ − 140
+ − 141 /home/sk/lib/emacs/lisp/auto-save.el
+ − 142
+ − 143 will have a longish filename like
+ − 144
464
+ − 145 AUTO-SAVE-DIRECTORY/#=2Fhome=2Fsk=2Flib=2Femacs=2Flisp=2Fauto-save.el#
428
+ − 146
+ − 147 as auto save file.
+ − 148
+ − 149 See also variables `auto-save-directory-fallback',
+ − 150 `efs-auto-save' and `efs-auto-save-remotely'."
+ − 151 :type '(choice (const :tag "Same as file" nil)
+ − 152 directory)
+ − 153 :group 'auto-save)
+ − 154
+ − 155
+ − 156 (defcustom auto-save-hash-p nil
+ − 157 "If non-nil, hashed autosave names of length 14 are used.
+ − 158 This is to avoid autosave filenames longer than 14 characters.
+ − 159 The directory used is `auto-save-hash-directory' regardless of
+ − 160 `auto-save-directory'.
+ − 161 Hashing defeats `recover-all-files', you have to recover files
+ − 162 individually by doing `recover-file'."
+ − 163 :type 'boolean
+ − 164 :group 'auto-save)
+ − 165
+ − 166 ;;; This defvar is in efs.el now, but doesn't hurt to give it here as
+ − 167 ;;; well so that loading first auto-save.el does not abort.
+ − 168
+ − 169 ;; #### Now that `auto-save' is dumped, this is looks obnoxious.
+ − 170 (or (boundp 'efs-auto-save) (defvar efs-auto-save 0))
+ − 171 (or (boundp 'efs-auto-save-remotely) (defvar efs-auto-save-remotely nil))
+ − 172
+ − 173 (defcustom auto-save-offer-delete nil
+ − 174 "*If non-nil, `recover-all-files' offers to delete autosave files
+ − 175 that are out of date or were dismissed for recovering.
+ − 176 Special value 'always deletes those files silently."
+ − 177 :type '(choice (const :tag "on" t)
+ − 178 (const :tag "off" nil)
+ − 179 (const :tag "Delete silently" always))
+ − 180 :group 'auto-save)
+ − 181
+ − 182 ;;;; end of customization
+ − 183
+ − 184
+ − 185 ;;; Preparations to be done at load time
+ − 186
+ − 187 ;; Do not call expand-file-name! This is evaluated at dump time now!
+ − 188 (defvar auto-save-directory-fallback "~/.autosave/"
+ − 189 ;; not user-variable-p, see above
+ − 190 "Directory used for local autosaving of remote files if
+ − 191 both `auto-save-directory' and `efs-auto-save-remotely' are nil.
+ − 192 Also used if a working directory to be used for autosaving is not writable.
+ − 193 This *must* always be the name of directory that exists or can be
+ − 194 created by you, never nil.")
+ − 195
+ − 196 (defvar auto-save-hash-directory
+ − 197 (expand-file-name "hash/" (or auto-save-directory
+ − 198 auto-save-directory-fallback))
+ − 199 "If non-nil, directory used for hashed autosave filenames.")
+ − 200
+ − 201 (defun auto-save-checked-directory (dir)
+ − 202 "Make sure the directory DIR exists and return it expanded if non-nil."
+ − 203 (when dir
+ − 204 (setq dir (expand-file-name dir))
+ − 205 ;; Make sure directory exists
+ − 206 (unless (file-directory-p dir)
+ − 207 ;; Else we create and chmod 0700 the directory
+ − 208 (setq dir (directory-file-name dir)) ; some systems need this
+ − 209 (make-directory dir)
+ − 210 (set-file-modes dir #o700))
+ − 211 dir))
+ − 212
+ − 213 ;; This make no sense at dump time
+ − 214 ;; (mapc #'auto-save-check-directory
+ − 215 ; '(auto-save-directory auto-save-directory-fallback))
+ − 216
+ − 217 ;(and auto-save-hash-p
+ − 218 ; (auto-save-check-directory 'auto-save-hash-directory))
+ − 219
+ − 220
+ − 221 ;;; Computing an autosave name for a file and vice versa
+ − 222
464
+ − 223 (defun make-auto-save-file-name (&optional file-name)
428
+ − 224 "Return file name to use for auto-saves of current buffer.
+ − 225 Does not consider `auto-save-visited-file-name'; that is checked
+ − 226 before calling this function.
+ − 227
+ − 228 Offers to autosave all files in the same `auto-save-directory'. All
+ − 229 autosave files can then be recovered at once with function
+ − 230 `recover-all-files'.
+ − 231
+ − 232 Takes care to make autosave files for files accessed through efs
+ − 233 be local files if variable `efs-auto-save-remotely' is nil.
+ − 234
+ − 235 Takes care of slashes in buffer names to prevent autosave errors.
+ − 236
+ − 237 Takes care that autosave files for buffers not visiting any file (such
+ − 238 as `*mail*') from two simultaneous Emacses don't collide by prepending
+ − 239 the Emacs pid.
+ − 240
+ − 241 Uses 14 character autosave names if `auto-save-hash-p' is true.
+ − 242
+ − 243 Autosaves even if the current directory is not writable, using
+ − 244 directory `auto-save-directory-fallback'.
+ − 245
+ − 246 You can redefine this for customization (he he :-).
+ − 247 See also function `auto-save-file-name-p'."
+ − 248
+ − 249 ;; We have to be very careful about not signalling an error in this
+ − 250 ;; function since files.el does not provide for this (e.g. find-file
+ − 251 ;; would fail for each new file).
+ − 252
+ − 253 (setq file-name (or file-name
+ − 254 buffer-file-truename
+ − 255 (and buffer-file-name
+ − 256 (expand-file-name buffer-file-name))))
793
+ − 257 (with-trapping-errors
+ − 258 :operation 'make-auto-save-file-name
+ − 259 :error-form
+ − 260 (let ((fname
+ − 261 (if file-name
+ − 262 (concat (file-name-directory file-name)
+ − 263 "#"
+ − 264 (file-name-nondirectory file-name)
+ − 265 "#")
+ − 266 (expand-file-name
+ − 267 (concat "#%" (auto-save-escape-name (buffer-name))
+ − 268 "#")))))
+ − 269 (if (or (file-writable-p fname)
+ − 270 (file-exists-p fname))
+ − 271 fname
+ − 272 (expand-file-name (concat "~/"
+ − 273 (file-name-nondirectory fname)))))
+ − 274 (let (
+ − 275 ;; So autosavename looks like #%...#, roughly as with the
+ − 276 ;; old make-auto-save-file-name function. The
+ − 277 ;; make-temp-name inserts the pid of this Emacs: this
+ − 278 ;; avoids autosaving from two Emacses into the same file.
+ − 279 ;; It cannot be recovered automatically then because in
+ − 280 ;; the next Emacs session (the one after the crash) the
+ − 281 ;; pid will be different, but file-less buffers like
+ − 282 ;; *mail* must be recovered manually anyway.
428
+ − 283
793
+ − 284 ;; jwz: putting the emacs PID in the auto-save file name is bad
+ − 285 ;; news, because that defeats auto-save-recovery of *mail*
+ − 286 ;; buffers -- the (sensible) code in sendmail.el calls
+ − 287 ;; (make-auto-save-file-name) to determine whether there is
+ − 288 ;; unsent, auto-saved mail to recover. If that mail came from a
+ − 289 ;; previous emacs process (far and away the most likely case)
+ − 290 ;; then this can never succeed as the pid differs.
+ − 291 ;;(name-prefix (if file-name nil (make-temp-name "#%")))
+ − 292 (name-prefix (if file-name nil "#%"))
428
+ − 293
793
+ − 294 (save-name (or file-name
+ − 295 ;; Prevent autosave errors. Buffername
+ − 296 ;; (to become non-dir part of filename) will
+ − 297 ;; be escaped twice. Don't care.
+ − 298 (auto-save-escape-name (buffer-name))))
+ − 299 (remote-p (and-fboundp 'efs-ftp-path
+ − 300 (stringp file-name)
+ − 301 (efs-ftp-path file-name))))
+ − 302 ;; Return the appropriate auto save file name:
+ − 303 (expand-file-name;; a buffername needs this, a filename not
+ − 304 (cond (remote-p
+ − 305 (if efs-auto-save-remotely
+ − 306 (auto-save-name-in-same-directory save-name)
+ − 307 ;; We have to use the `fixed-directory' now since the
+ − 308 ;; `same-directory' would be remote.
+ − 309 ;; It will use the fallback if needed.
+ − 310 (auto-save-name-in-fixed-directory save-name)))
+ − 311 ;; Else it is a local file (or a buffer without a file,
+ − 312 ;; hence the name-prefix).
+ − 313 ((or auto-save-directory auto-save-hash-p)
+ − 314 ;; Hashed files always go into the special hash dir,
+ − 315 ;; never in the same directory, to make recognizing
+ − 316 ;; reliable.
+ − 317 (auto-save-name-in-fixed-directory save-name name-prefix))
+ − 318 (t
+ − 319 (auto-save-name-in-same-directory save-name name-prefix)))))))
464
+ − 320
+ − 321 (defun auto-save-file-name-p (filename)
+ − 322 "Return non-nil if FILENAME can be yielded by `make-auto-save-file-name'.
+ − 323 FILENAME should lack slashes.
+ − 324 You can redefine this for customization."
+ − 325 (string-match "\\`#.*#\\'" filename))
428
+ − 326
+ − 327 (defun auto-save-original-name (savename)
+ − 328 "Reverse of `make-auto-save-file-name'.
+ − 329 Returns nil if SAVENAME was not associated with a file (e.g., it came
+ − 330 from an autosaved `*mail*' buffer) or does not appear to be an
+ − 331 autosave file at all.
+ − 332 Hashed files are not understood, see `auto-save-hash-p'."
+ − 333 (let ((basename (file-name-nondirectory savename))
+ − 334 (savedir (file-name-directory savename)))
+ − 335 (cond ((or (not (auto-save-file-name-p basename))
+ − 336 (string-match "^#%" basename))
+ − 337 nil)
+ − 338 ;; now we know it looks like #...# thus substring is safe to use
+ − 339 ((or (equal savedir
+ − 340 (and auto-save-directory
+ − 341 (expand-file-name auto-save-directory)))
+ − 342 ; 2nd arg may be nil
+ − 343 (equal savedir
+ − 344 (expand-file-name auto-save-directory-fallback)))
+ − 345 ;; it is of the `-fixed-directory' type
464
+ − 346 (auto-save-unescape-name (substring basename 1 -1)))
428
+ − 347 (t
+ − 348 ;; else it is of `-same-directory' type
+ − 349 (concat savedir (substring basename 1 -1))))))
+ − 350
+ − 351 (defun auto-save-name-in-fixed-directory (filename &optional prefix)
464
+ − 352 ;; Escape and enclose the whole FILENAME in `#' to make an auto
428
+ − 353 ;; save file in the auto-save-directory, or if that is nil, in
+ − 354 ;; auto-save-directory-fallback (which must be the name of an
+ − 355 ;; existing directory). If the results would be too long for 14
+ − 356 ;; character filenames, and `auto-save-hash-p' is set, hash FILENAME
+ − 357 ;; into a shorter name.
+ − 358 ;; Optional PREFIX is string to use instead of "#" to prefix name.
+ − 359 (let ((base-name (concat (or prefix "#")
464
+ − 360 (auto-save-escape-name filename)
428
+ − 361 "#")))
+ − 362 (if (and auto-save-hash-p
+ − 363 auto-save-hash-directory
+ − 364 (> (length base-name) 14))
+ − 365 (expand-file-name (auto-save-cyclic-hash-14 filename)
+ − 366 (auto-save-checked-directory auto-save-hash-directory))
+ − 367 (expand-file-name base-name
+ − 368 (auto-save-checked-directory
+ − 369 (or auto-save-directory
+ − 370 auto-save-directory-fallback))))))
+ − 371
+ − 372 (defun auto-save-name-in-same-directory (filename &optional prefix)
+ − 373 ;; Enclose the non-directory part of FILENAME in `#' to make an auto
+ − 374 ;; save file in the same directory as FILENAME. But if this
+ − 375 ;; directory is not writable, use auto-save-directory-fallback.
+ − 376 ;; FILENAME is assumed to be in non-directory form (no trailing slash).
440
+ − 377 ;; It may be a name without a directory part (presumably it really
428
+ − 378 ;; comes from a buffer name then), the fallback is used then.
+ − 379 ;; Optional PREFIX is string to use instead of "#" to prefix name.
+ − 380 (let ((directory (file-name-directory filename)))
+ − 381 (or (null directory)
+ − 382 (file-writable-p directory)
+ − 383 (setq directory (auto-save-checked-directory
+ − 384 auto-save-directory-fallback)))
+ − 385 (concat directory ; (concat nil) is ""
+ − 386 (or prefix "#")
+ − 387 (file-name-nondirectory filename)
+ − 388 "#")))
+ − 389
464
+ − 390 (defconst auto-save-reserved-chars
+ − 391 '(
+ − 392 ?\0 ?\1 ?\2 ?\3 ?\4 ?\5 ?\6 ?\7 ?\10 ?\11 ?\12 ?\13 ?\14 ?\15 ?\16
+ − 393 ?\17 ?\20 ?\21 ?\22 ?\23 ?\24 ?\25 ?\26 ?\27 ?\30 ?\31 ?\32 ?\33
+ − 394 ?\34 ?\35 ?\36 ?\37 ?\40 ?? ?* ?: ?< ?> ?| ?/ ?\\ ?& ?^ ?% ?= ?\")
+ − 395 "List of characters disallowed (or potentially disallowed) in filenames.
+ − 396 Includes everything that can get us into trouble under MS Windows or Unix.")
+ − 397
+ − 398 ;; This code based on code in Bill Perry's url.el.
+ − 399
+ − 400 (defun auto-save-escape-name (str)
+ − 401 "Escape any evil nasty characters in a potential filename.
+ − 402 Uses quoted-printable-style escaping -- e.g. the dreaded =3D.
+ − 403 Does not use URL escaping (with %) because filenames beginning with #% are
+ − 404 a special signal for non-file buffers."
+ − 405 (mapconcat
+ − 406 (function
+ − 407 (lambda (char)
+ − 408 (if (memq char auto-save-reserved-chars)
+ − 409 (if (< char 16)
+ − 410 (upcase (format "=0%x" char))
+ − 411 (upcase (format "=%x" char)))
+ − 412 (char-to-string char))))
+ − 413 str ""))
+ − 414
+ − 415 (defun auto-save-unhex (x)
+ − 416 (if (> x ?9)
+ − 417 (if (>= x ?a)
+ − 418 (+ 10 (- x ?a))
+ − 419 (+ 10 (- x ?A)))
+ − 420 (- x ?0)))
428
+ − 421
464
+ − 422 (defun auto-save-unescape-name (str)
+ − 423 "Undo any escaping of evil nasty characters in a file name.
+ − 424 See `auto-save-escape-name'."
+ − 425 (setq str (or str ""))
+ − 426 (let ((tmp "")
+ − 427 (case-fold-search t))
+ − 428 (while (string-match "=[0-9a-f][0-9a-f]" str)
+ − 429 (let* ((start (match-beginning 0))
+ − 430 (ch1 (auto-save-unhex (elt str (+ start 1))))
+ − 431 (code (+ (* 16 ch1)
+ − 432 (auto-save-unhex (elt str (+ start 2))))))
+ − 433 (setq tmp (concat tmp (substring str 0 start)
+ − 434 (char-to-string code))
+ − 435 str (substring str (match-end 0)))))
+ − 436 (setq tmp (concat tmp str))
+ − 437 tmp))
+ − 438
+ − 439 ;; The old versions are below.
428
+ − 440
464
+ − 441 ;(defun auto-save-escape-name (s)
+ − 442 ; ;; "Quote any slashes in string S by replacing them with the two
+ − 443 ; ;;characters `\\!'.
+ − 444 ; ;;Also, replace any backslash by double backslash, to make it one-to-one."
+ − 445 ; (let ((limit 0))
+ − 446 ; (while (string-match "[/\\]" s limit)
+ − 447 ; (setq s (concat (substring s 0 (match-beginning 0))
+ − 448 ; (if (string= (substring s
+ − 449 ; (match-beginning 0)
+ − 450 ; (match-end 0))
+ − 451 ; "/")
+ − 452 ; "\\!"
+ − 453 ; "\\\\")
+ − 454 ; (substring s (match-end 0))))
+ − 455 ; (setq limit (1+ (match-end 0)))))
+ − 456 ; s)
+ − 457
+ − 458 ;(defun auto-save-unescape-name (s)
+ − 459 ; ;;"Reverse of `auto-save-escape-name'."
+ − 460 ; (let (pos)
+ − 461 ; (while (setq pos (string-match "\\\\[\\!]" s pos))
+ − 462 ; (setq s (concat (substring s 0 pos)
+ − 463 ; (if (eq ?! (aref s (1+ pos))) "/" "\\")
+ − 464 ; (substring s (+ pos 2)))
+ − 465 ; pos (1+ pos))))
+ − 466 ; s)
428
+ − 467
+ − 468
+ − 469 ;;; Hashing for autosave names
+ − 470
+ − 471 ;;; Hashing function contributed by Andy Norman <ange@hplb.hpl.hp.com>
+ − 472 ;;; based upon C code from pot@fly.cnuce.cnr.IT (Francesco Potorti`).
+ − 473
+ − 474 (defun auto-save-cyclic-hash-14 (s)
+ − 475 ;; "Hash string S into a string of length 14.
+ − 476 ;; A 7-bytes cyclic code for burst correction is calculated on a
+ − 477 ;; byte-by-byte basis. The polynomial used is D^7 + D^6 + D^3 +1.
+ − 478 ;; The resulting string consists of hexadecimal digits [0-9a-f].
+ − 479 ;; In particular, it contains no slash, so it can be used as autosave name."
+ − 480 (let ((crc (make-vector 7 ?\0)))
+ − 481 (mapc
+ − 482 (lambda (new)
+ − 483 (setq new (+ new (aref crc 6)))
+ − 484 (aset crc 6 (+ (aref crc 5) new))
+ − 485 (aset crc 5 (aref crc 4))
+ − 486 (aset crc 4 (aref crc 3))
+ − 487 (aset crc 3 (+ (aref crc 2) new))
+ − 488 (aset crc 2 (aref crc 1))
+ − 489 (aset crc 1 (aref crc 0))
+ − 490 (aset crc 0 new))
+ − 491 s)
+ − 492 (format "%02x%02x%02x%02x%02x%02x%02x"
+ − 493 (logand 255 (aref crc 0))
+ − 494 (logand 255 (aref crc 1))
+ − 495 (logand 255 (aref crc 2))
+ − 496 (logand 255 (aref crc 3))
+ − 497 (logand 255 (aref crc 4))
+ − 498 (logand 255 (aref crc 5))
+ − 499 (logand 255 (aref crc 6)))))
+ − 500
+ − 501 ;; #### It is unclear to me how the following function is useful. It
+ − 502 ;; should be used in `auto-save-name-in-same-directory', if anywhere.
+ − 503 ;; -hniksic
+ − 504
+ − 505 ;; This leaves two characters that could be used to wrap it in `#' or
+ − 506 ;; make two filenames from it: one for autosaving, and another for a
464
+ − 507 ;; file containing the name of the autosaved file, to make hashing
428
+ − 508 ;; reversible.
+ − 509 ;(defun auto-save-cyclic-hash-12 (s)
+ − 510 ; "Outputs the 12-characters ascii hex representation of a 6-bytes
+ − 511 ;cyclic code for burst correction calculated on STRING on a
+ − 512 ;byte-by-byte basis. The used polynomial is D^6 + D^5 + D^4 + D^3 +1."
+ − 513 ; (let ((crc (make-string 6 0)))
+ − 514 ; (mapc
+ − 515 ; (lambda (new)
+ − 516 ; (setq new (+ new (aref crc 5)))
+ − 517 ; (aset crc 5 (+ (aref crc 4) new))
+ − 518 ; (aset crc 4 (+ (aref crc 3) new))
+ − 519 ; (aset crc 3 (+ (aref crc 2) new))
+ − 520 ; (aset crc 2 (aref crc 1))
+ − 521 ; (aset crc 1 (aref crc 0))
+ − 522 ; (aset crc 0 new))
+ − 523 ; s)
+ − 524 ; (format "%02x%02x%02x%02x%02x%02x"
+ − 525 ; (aref crc 0)
+ − 526 ; (aref crc 1)
+ − 527 ; (aref crc 2)
+ − 528 ; (aref crc 3)
+ − 529 ; (aref crc 4)
+ − 530 ; (aref crc 5))))
+ − 531
+ − 532
+ − 533
+ − 534 ;;; Recovering files
+ − 535
+ − 536 (defun recover-all-files (&optional silent)
+ − 537 "Do recover-file for all autosave files which are current.
+ − 538 Only works if you have a non-nil `auto-save-directory'.
+ − 539
+ − 540 Optional prefix argument SILENT means to be silent about non-current
+ − 541 autosave files. This is useful if invoked automatically at Emacs
+ − 542 startup.
+ − 543
+ − 544 If `auto-save-offer-delete' is t, this function will offer to delete
+ − 545 old or rejected autosave files.
+ − 546
+ − 547 Hashed files (see `auto-save-hash-p') are not understood, use
+ − 548 `recover-file' to recover them individually."
+ − 549 (interactive "P")
+ − 550 (let ((savefiles (directory-files auto-save-directory
+ − 551 t "\\`#" nil t))
+ − 552 afile ; the auto save file
+ − 553 file ; its original file
+ − 554 (total 0) ; # of files offered to recover
+ − 555 (count 0)) ; # of files actually recovered
+ − 556 (or (equal (expand-file-name auto-save-directory)
+ − 557 (expand-file-name auto-save-directory-fallback))
+ − 558 (setq savefiles
+ − 559 (nconc savefiles
+ − 560 (directory-files auto-save-directory-fallback
+ − 561 t "\\`#" nil t))))
+ − 562 (while savefiles
+ − 563 (setq afile (car savefiles)
+ − 564 file (auto-save-original-name afile)
+ − 565 savefiles (cdr savefiles))
+ − 566 (cond ((and file (not (file-newer-than-file-p afile file)))
793
+ − 567 (warn "Autosave file \"%s\" is not current" afile))
428
+ − 568 (t
+ − 569 (incf total)
+ − 570 (with-output-to-temp-buffer "*Directory*"
464
+ − 571 (buffer-disable-undo standard-output)
+ − 572 (save-excursion
+ − 573 (set-buffer "*Directory*")
+ − 574 (setq default-directory (file-name-directory afile))
+ − 575 (insert-directory afile "-l")
+ − 576 (when file
+ − 577 (setq default-directory (file-name-directory file))
+ − 578 (insert-directory file "-l"))))
428
+ − 579 (if (yes-or-no-p (format "Recover %s from auto save file? "
+ − 580 (or file "non-file buffer")))
+ − 581 (let* ((obuf (current-buffer)))
+ − 582 (set-buffer (if file
+ − 583 (find-file-noselect file t)
+ − 584 (generate-new-buffer "*recovered*")))
+ − 585 (setq buffer-read-only nil)
+ − 586 (erase-buffer)
771
+ − 587 ;; see comment in `revert-buffer' in files.el about
+ − 588 ;; why it's safe to always use `escape-quoted'.
+ − 589 (let ((coding-system-for-read 'escape-quoted))
+ − 590 (insert-file-contents afile nil))
428
+ − 591 (ignore-errors
+ − 592 (after-find-file nil))
+ − 593 (setq buffer-auto-save-file-name nil)
+ − 594 (incf count)
+ − 595 (message "\
+ − 596 Auto-save off in buffer \"%s\" till you do M-x auto-save-mode."
+ − 597 (buffer-name))
+ − 598 (set-buffer obuf)
+ − 599 (sit-for 1))
+ − 600 ;; If not used for recovering, offer to delete
+ − 601 ;; autosave file
+ − 602 (and auto-save-offer-delete
+ − 603 (or (eq 'always auto-save-offer-delete)
+ − 604 (yes-or-no-p
+ − 605 (format "Delete autosave file for `%s'? " file)))
+ − 606 (delete-file afile))))))
+ − 607 (if (zerop total)
+ − 608 (or silent (message "Nothing to recover."))
+ − 609 (message "%d/%d file%s recovered." count total (if (= count 1) "" "s"))))
+ − 610 (and (get-buffer "*Directory*")
+ − 611 (kill-buffer "*Directory*")))
+ − 612
+ − 613 ;;; auto-save.el ends here