aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman1994-07-05 20:23:13 +0000
committerRichard M. Stallman1994-07-05 20:23:13 +0000
commit05ef1cdab942719e44c830dfd19b915702972e0e (patch)
treed43bf078a8837f02c531c0502f17f362f843fe0d
parent30dc01ea24f61c5f0a2561b8a36c2e259811d6e1 (diff)
downloademacs-05ef1cdab942719e44c830dfd19b915702972e0e.tar.gz
emacs-05ef1cdab942719e44c830dfd19b915702972e0e.zip
(file-truename): Use iteration when possible.
Avoid recalculating the same truename twice in one invocation. Error check for infinite link loop. (debugger): Make it a risky-local-variable.
-rw-r--r--lisp/files.el97
1 files changed, 64 insertions, 33 deletions
diff --git a/lisp/files.el b/lisp/files.el
index 66f3ac21721..5cf294ab54c 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -329,11 +329,18 @@ accessible."
329 (funcall handler 'file-local-copy file) 329 (funcall handler 'file-local-copy file)
330 nil))) 330 nil)))
331 331
332(defun file-truename (filename) 332(defun file-truename (filename &optional counter prev-dirs)
333 "Return the truename of FILENAME, which should be absolute. 333 "Return the truename of FILENAME, which should be absolute.
334The truename of a file name is found by chasing symbolic links 334The truename of a file name is found by chasing symbolic links
335both at the level of the file and at the level of the directories 335both at the level of the file and at the level of the directories
336containing it, until no links are left at any level." 336containing it, until no links are left at any level.
337
338The arguments COUNTER and PREV-DIRS are used only in recursive calls.
339Do not specify them in other calls."
340 ;; COUNTER can be a cons cell whose car is the count of how many more links
341 ;; to chase before getting an error.
342 ;; PREV-DIRS can be a cons cell whose car is an alist
343 ;; of truenames we've just recently computed.
337 (if (or (string= filename "~") 344 (if (or (string= filename "~")
338 (and (string= (substring filename 0 1) "~") 345 (and (string= (substring filename 0 1) "~")
339 (string-match "~[^/]*" filename))) 346 (string-match "~[^/]*" filename)))
@@ -341,37 +348,60 @@ containing it, until no links are left at any level."
341 (setq filename (expand-file-name filename)) 348 (setq filename (expand-file-name filename))
342 (if (string= filename "") 349 (if (string= filename "")
343 (setq filename "/")))) 350 (setq filename "/"))))
344 (let ((handler (find-file-name-handler filename 'file-truename))) 351 (or counter (setq counter (list 100)))
345 ;; For file name that has a special handler, call handler. 352 (or prev-dirs (setq prev-dirs (list nil)))
346 ;; This is so that ange-ftp can save time by doing a no-op. 353 (let (done)
347 (if handler 354 ;; If this file directly leads to a link, process that iteratively
348 (funcall handler 'file-truename filename) 355 ;; so that we don't use lots of stack.
349 (let ((dir (file-name-directory filename)) 356 (while (not done)
350 target dirfile) 357 (setcar counter (1- (car counter)))
351 ;; Get the truename of the directory. 358 (if (< (car counter) 0)
352 (setq dirfile (directory-file-name dir)) 359 (error "Apparent cycle of symbolic links for %s" filename))
353 ;; If these are equal, we have the (or a) root directory. 360 (let ((handler (find-file-name-handler filename 'file-truename)))
354 (or (string= dir dirfile) 361 ;; For file name that has a special handler, call handler.
355 (setq dir (file-name-as-directory (file-truename dirfile)))) 362 ;; This is so that ange-ftp can save time by doing a no-op.
356 (if (equal ".." (file-name-nondirectory filename)) 363 (if handler
357 (directory-file-name (file-name-directory (directory-file-name dir))) 364 (setq filename (funcall handler 'file-truename filename)
358 (if (equal "." (file-name-nondirectory filename)) 365 done t)
359 (directory-file-name dir) 366 (let ((dir (file-name-directory filename))
360 ;; Put it back on the file name. 367 target dirfile)
361 (setq filename (concat dir (file-name-nondirectory filename))) 368 ;; Get the truename of the directory.
362 ;; Is the file name the name of a link? 369 (setq dirfile (directory-file-name dir))
363 (setq target (file-symlink-p filename)) 370 ;; If these are equal, we have the (or a) root directory.
364 (if target 371 (or (string= dir dirfile)
365 ;; Yes => chase that link, then start all over 372 ;; If this is the same dir we last got the truename for,
366 ;; since the link may point to a directory name that uses links. 373 ;; save time--don't recalculate.
367 ;; We can't safely use expand-file-name here 374 (if (assoc dir (car prev-dirs))
368 ;; since target might look like foo/../bar where foo 375 (setq dir (cdr (assoc dir (car prev-dirs))))
369 ;; is itself a link. Instead, we handle . and .. above. 376 (let ((old dir)
370 (if (file-name-absolute-p target) 377 (new (file-name-as-directory (file-truename dirfile counter prev-dirs))))
371 (file-truename target) 378 (setcar prev-dirs (cons (cons old new) (car prev-dirs)))
372 (file-truename (concat dir target))) 379 (setq dir new))))
373 ;; No, we are done! 380 (if (equal ".." (file-name-nondirectory filename))
374 filename))))))) 381 (setq filename
382 (directory-file-name (file-name-directory (directory-file-name dir)))
383 done t)
384 (if (equal "." (file-name-nondirectory filename))
385 (setq filename (directory-file-name dir)
386 done t)
387 ;; Put it back on the file name.
388 (setq filename (concat dir (file-name-nondirectory filename)))
389 ;; Is the file name the name of a link?
390 (setq target (file-symlink-p filename))
391 (if target
392 ;; Yes => chase that link, then start all over
393 ;; since the link may point to a directory name that uses links.
394 ;; We can't safely use expand-file-name here
395 ;; since target might look like foo/../bar where foo
396 ;; is itself a link. Instead, we handle . and .. above.
397 (setq filename
398 (if (file-name-absolute-p target)
399 target
400 (concat dir target))
401 done nil)
402 ;; No, we are done!
403 (setq done t))))))))
404 filename))
375 405
376(defun file-chase-links (filename) 406(defun file-chase-links (filename)
377 "Chase links in FILENAME until a name that is not a link. 407 "Chase links in FILENAME until a name that is not a link.
@@ -1105,6 +1135,7 @@ If `enable-local-variables' is nil, this function does not check for a
1105 "Variables to be ignored in a file's local variable spec.") 1135 "Variables to be ignored in a file's local variable spec.")
1106 1136
1107;; Get confirmation before setting these variables as locals in a file. 1137;; Get confirmation before setting these variables as locals in a file.
1138(put 'debugger 'risky-local-variable t)
1108(put 'enable-local-eval 'risky-local-variable t) 1139(put 'enable-local-eval 'risky-local-variable t)
1109(put 'eval 'risky-local-variable t) 1140(put 'eval 'risky-local-variable t)
1110(put 'file-name-handler-alist 'risky-local-variable t) 1141(put 'file-name-handler-alist 'risky-local-variable t)