Function: file-name-non-special

file-name-non-special is a byte-compiled function defined in files.el.gz.

Signature

(file-name-non-special OPERATION &rest ARGUMENTS)

Source Code

;; Defined in /usr/src/emacs/lisp/files.el.gz
;; We depend on being the last handler on the list,
;; so that anything else that does need handling
;; has been handled already.
;; So it is safe for us to inhibit *all* magic file name handlers for
;; operations, which return a file name.  See Bug#29579.

(defun file-name-non-special (operation &rest arguments)
  (let ((inhibit-file-name-handlers
         (cons 'file-name-non-special
               (and (eq inhibit-file-name-operation operation)
                    inhibit-file-name-handlers)))
        (inhibit-file-name-operation operation)
        ;; Some operations respect file name handlers in
        ;; `default-directory'.  Because core function like
        ;; `call-process' don't care about file name handlers in
        ;; `default-directory', we here have to resolve the directory
        ;; into a local one.  For `process-file',
        ;; `start-file-process', and `shell-command', this fixes
        ;; Bug#25949.
        (default-directory
	  (if (memq operation
                    '(insert-directory process-file start-file-process
                                       make-process shell-command
                                       temporary-file-directory))
	      (directory-file-name
	       (expand-file-name
		(unhandled-file-name-directory default-directory)))
	    default-directory))
	;; Get a list of the indices of the args that are file names.
	(file-arg-indices
	 (cdr (or (assq operation
			'(;; The first seven are special because they
			  ;; return a file name.  We want to include
			  ;; the /: in the return value.  So just
			  ;; avoid stripping it in the first place.
                          (abbreviate-file-name)
                          (directory-file-name)
                          (file-name-as-directory)
                          (file-name-directory)
                          (file-name-sans-versions)
                          (file-remote-p)
                          (find-backup-file-name)
                          ;; `identity' means just return the first
			  ;; arg not stripped of its quoting.
			  (substitute-in-file-name identity)
                          ;; `expand-file-name' shall do special case
                          ;; for the first argument starting with
                          ;; "/:~".  (Bug#65685)
                          (expand-file-name expand-file-name)
			  ;; `add' means add "/:" to the result.
			  (file-truename add 0)
                          ;;`insert-file-contents' needs special handling.
			  (insert-file-contents insert-file-contents 0)
			  ;; `unquote-then-quote' means set buffer-file-name
			  ;; temporarily to unquoted filename.
			  (verify-visited-file-modtime unquote-then-quote)
                          ;; Unquote `buffer-file-name' temporarily.
                          (make-auto-save-file-name buffer-file-name)
                          (set-visited-file-modtime buffer-file-name)
                          ;; Use a temporary local copy.
			  (copy-file local-copy)
			  (rename-file local-copy)
                          (copy-directory local-copy)
			  ;; List the arguments that are filenames.
			  (file-name-completion 0 1)
			  (file-name-all-completions 0 1)
                          (file-equal-p 0 1)
                          (file-newer-than-file-p 0 1)
			  (write-region 2 5)
			  (file-in-directory-p 0 1)
			  (make-symbolic-link 0 1)
			  (add-name-to-file 0 1)
                          ;; These file-notify-* operations take a
                          ;; descriptor.
                          (file-notify-rm-watch)
                          (file-notify-valid-p)
                          ;; `make-process' uses keyword arguments and
                          ;; doesn't mangle its filenames in any way.
                          ;; It already strips /: from the binary
                          ;; filename, so we don't have to do this
                          ;; here.
                          (make-process)))
		  ;; For all other operations, treat the first
		  ;; argument only as the file name.
		  '(nil 0))))
	method
	;; Copy ARGUMENTS so we can replace elements in it.
	(arguments (copy-sequence arguments)))
    (if (symbolp (car file-arg-indices))
	(setq method (pop file-arg-indices)))
    ;; Strip off the /: from the file names that have it.
    (save-match-data                    ;FIXME: Why?
      (while (consp file-arg-indices)
	(let ((pair (nthcdr (car file-arg-indices) arguments)))
	  (when (car pair)
	    (setcar pair (file-name-unquote (car pair) t))))
	(setq file-arg-indices (cdr file-arg-indices))))
    ;; In general, we don't want any file name handler, see Bug#47625,
    ;; Bug#48349.  For some few cases, operations with two file name
    ;; arguments which might be bound to different file name handlers,
    ;; we still need this.
    (let ((tramp-mode (and tramp-mode (eq method 'local-copy))))
      (pcase method
        ('identity (car arguments))
        ('expand-file-name
         (when (string-prefix-p "/:~" (car arguments))
           (setcar arguments (file-name-unquote (car arguments) t)))
         (apply operation arguments))
        ('add (file-name-quote (apply operation arguments) t))
        ('buffer-file-name
         (let ((buffer-file-name (file-name-unquote buffer-file-name t)))
           (apply operation arguments)))
        ('insert-file-contents
         (let ((visit (nth 1 arguments)))
           (unwind-protect
               (apply operation arguments)
             (when (and visit buffer-file-name)
               (setq buffer-file-name (file-name-quote buffer-file-name t))))))
        ('unquote-then-quote
         ;; We can't use `cl-letf' with `(buffer-local-value)' here
         ;; because it wouldn't work during bootstrapping.
         (let ((buffer (current-buffer)))
           ;; `unquote-then-quote' is used only for the
           ;; `verify-visited-file-modtime' action, which takes a
           ;; buffer as only optional argument.
           (with-current-buffer (or (car arguments) buffer)
             (let ((buffer-file-name (file-name-unquote buffer-file-name t)))
               ;; Make sure to hide the temporary buffer change from
               ;; the underlying operation.
               (with-current-buffer buffer
                 (apply operation arguments))))))
        ('local-copy
         (let ((source (car arguments))
               (target (car (cdr arguments)))
               (prefix (expand-file-name
                        "file-name-non-special" temporary-file-directory))
               tmpfile)
           (cond
            ;; If source is remote, we must create a local copy.
            ((file-remote-p source)
             (setq tmpfile (make-temp-name prefix))
             (apply operation source tmpfile (cddr arguments))
             (setq source tmpfile))
            ;; If source is quoted, and the unquoted source looks
            ;; remote, we must create a local copy.
            ((file-name-quoted-p source t)
             (setq source (file-name-unquote source t))
             (when (file-remote-p source)
               (setq tmpfile (make-temp-name prefix))
               (let (file-name-handler-alist)
                 (apply operation source tmpfile (cddr arguments)))
               (setq source tmpfile))))
           ;; If target is quoted, and the unquoted target looks
           ;; remote, we must disable the file name handler.
           (when (file-name-quoted-p target t)
             (setq target (file-name-unquote target t))
             (when (file-remote-p target)
               (setq file-name-handler-alist nil)))
           ;; Do it.
           (setcar arguments source)
           (setcar (cdr arguments) target)
           (apply operation arguments)
           ;; Cleanup.
           (when (and tmpfile (file-exists-p tmpfile))
             (if (file-directory-p tmpfile)
                 (delete-directory tmpfile 'recursive) (delete-file tmpfile)))))
        (_
         (apply operation arguments))))))