* net/dbus.el (dbus-hash-table=): Fix for new hash table key
[bpt/emacs.git] / lisp / net / tramp-fish.el
index e370c54..95091c2 100644 (file)
@@ -1,4 +1,3 @@
-;;; -*- coding: iso-8859-1; -*-
 ;;; tramp-fish.el --- Tramp access functions for FISH protocol
 
 ;; Copyright (C) 2006, 2007 Free Software Foundation, Inc.
@@ -10,8 +9,8 @@
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3 of the License, or
-;; (at your option) any later version.
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 (require 'tramp)
 (require 'tramp-cache)
-
-;; Pacify byte-compiler
-(eval-when-compile
-  (require 'cl)
-  (require 'custom))
-
-;; Avoid byte-compiler warnings if the byte-compiler supports this.
-;; Currently, XEmacs supports this.
-(eval-when-compile
-  (when (featurep 'xemacs)
-      (byte-compiler-options (warnings (- unused-vars)))))
-
-;; `directory-sep-char' is an obsolete variable in Emacs.  But it is
-;; used in XEmacs, so we set it here and there.  The following is needed
-;; to pacify Emacs byte-compiler.
-(eval-when-compile
-  (unless (boundp 'byte-compile-not-obsolete-var)
-    (defvar byte-compile-not-obsolete-var nil))
-  (setq byte-compile-not-obsolete-var 'directory-sep-char))
+(require 'tramp-compat)
 
 ;; Define FISH method ...
 (defcustom tramp-fish-method "fish"
@@ -263,6 +244,7 @@ Used instead of analyzing error codes of commands.")
     (make-symbolic-link . tramp-fish-handle-make-symbolic-link)
     (rename-file . tramp-fish-handle-rename-file)
     (set-file-modes . tramp-fish-handle-set-file-modes)
+    (set-file-times . tramp-fish-handle-set-file-times)
     (set-visited-file-modtime . ignore)
     (shell-command . tramp-handle-shell-command)
     (substitute-in-file-name . tramp-handle-substitute-in-file-name)
@@ -271,9 +253,8 @@ Used instead of analyzing error codes of commands.")
     (verify-visited-file-modtime . ignore)
     (write-region . tramp-fish-handle-write-region)
     (executable-find . tramp-fish-handle-executable-find)
-    (start-process . ignore)
-    (call-process . tramp-fish-handle-call-process)
-    (process-file . tramp-handle-process-file)
+    (start-file-process . ignore)
+    (process-file . tramp-fish-handle-process-file)
 )
   "Alist of handler functions for Tramp FISH method.
 Operations not mentioned here will be handled by the default Emacs primitives.")
@@ -327,10 +308,10 @@ pass to the OPERATION."
         v1 'file-error "Error with add-name-to-file %s" newname)))))
 
 (defun tramp-fish-handle-copy-file
-  (filename newname &optional ok-if-already-exists keep-date)
+  (filename newname &optional ok-if-already-exists keep-date preserve-uid-gid)
   "Like `copy-file' for Tramp files."
   (tramp-fish-do-copy-or-rename-file
-   'copy filename newname ok-if-already-exists keep-date))
+   'copy filename newname ok-if-already-exists keep-date preserve-uid-gid))
 
 (defun tramp-fish-handle-delete-directory (directory)
   "Like `delete-directory' for Tramp files."
@@ -365,8 +346,8 @@ pass to the OPERATION."
   ;; Unless NAME is absolute, concat DIR and NAME.
   (unless (file-name-absolute-p name)
     (setq name (concat (file-name-as-directory dir) name)))
-  ;; If NAME is not a tramp file, run the real handler
-  (if (or (tramp-completion-mode) (not (tramp-tramp-file-p name)))
+  ;; If NAME is not a Tramp file, run the real handler,
+  (if (or (tramp-completion-mode-p) (not (tramp-tramp-file-p name)))
       (tramp-drop-volume-letter
        (tramp-run-real-handler 'expand-file-name (list name nil)))
     ;; Dissect NAME.
@@ -387,7 +368,7 @@ pass to the OPERATION."
              (tramp-fish-send-command-and-check v "#PWD")
              (with-current-buffer (tramp-get-buffer v)
                (goto-char (point-min))
-               (buffer-substring (point) (tramp-line-end-position)))))
+               (buffer-substring (point) (tramp-compat-line-end-position)))))
          (setq localname (concat uname fname))))
       ;; There might be a double slash, for example when "~/"
       ;; expands to "/". Remove this.
@@ -400,7 +381,7 @@ pass to the OPERATION."
       ;; bound, because on Windows there would be problems with UNC
       ;; shares or Cygwin mounts.
       (tramp-let-maybe directory-sep-char ?/
-       (let ((default-directory (tramp-temporary-file-directory)))
+       (let ((default-directory (tramp-compat-temporary-file-directory)))
          (tramp-make-tramp-file-name
           method user host
           (tramp-drop-volume-letter
@@ -494,14 +475,14 @@ pass to the OPERATION."
       (tramp-error
        v 'file-error
        "Cannot make local copy of non-existing file `%s'" filename))
-    (let ((tmpfil (tramp-make-temp-file filename)))
-      (tramp-message v 4 "Fetching %s to tmp file %s..." filename tmpfil)
+    (let ((tmpfile (tramp-compat-make-temp-file filename)))
+      (tramp-message v 4 "Fetching %s to tmp file %s..." filename tmpfile)
       (when (tramp-fish-retrieve-data v)
        ;; Save file
        (with-current-buffer (tramp-get-buffer v)
-         (write-region (point-min) (point-max) tmpfil))
-       (tramp-message v 4 "Fetching %s to tmp file %s...done" filename tmpfil)
-       tmpfil))))
+         (write-region (point-min) (point-max) tmpfile))
+       (tramp-message v 4 "Fetching %s to tmp file %s...done" filename tmpfile)
+       tmpfile))))
 
 ;; This function should return "foo/" for directories and "bar" for
 ;; files.
@@ -698,6 +679,15 @@ target of the symlink differ."
       (tramp-error
        v 'file-error "Error while changing file's mode %s" filename))))
 
+(defun tramp-fish-handle-set-file-times (filename &optional time)
+  "Like `set-file-times' for Tramp files."
+  (with-parsed-tramp-file-name filename nil
+    (let ((time (if (or (null time) (equal time '(0 0))) (current-time) time)))
+      (zerop (process-file
+             "touch" nil nil nil "-t"
+             (format-time-string "%Y%m%d%H%M.%S" time)
+             (tramp-shell-quote-argument localname))))))
+
 (defun tramp-fish-handle-write-region
   (start end filename &optional append visit lockname confirm)
   "Like `write-region' for Tramp files."
@@ -731,21 +721,21 @@ target of the symlink differ."
 (defun tramp-fish-handle-executable-find (command)
   "Like `executable-find' for Tramp files."
   (with-temp-buffer
-    (if (zerop (call-process "which" nil t nil command))
+    (if (zerop (process-file "which" nil t nil command))
        (progn
          (goto-char (point-min))
-         (buffer-substring (point-min) (tramp-line-end-position))))))
+         (buffer-substring (point-min) (tramp-compat-line-end-position))))))
 
-(defun tramp-fish-handle-call-process
+(defun tramp-fish-handle-process-file
   (program &optional infile destination display &rest args)
-  "Like `call-process' for Tramp files."
+  "Like `process-file' for Tramp files."
   ;; The implementation is not complete yet.
   (when (and (numberp destination) (zerop destination))
     (error "Implementation does not handle immediate return"))
 
   (with-parsed-tramp-file-name default-directory nil
-    (let ((temp-name-prefix (tramp-make-tramp-temp-file v))
-         command input output stderr outbuf tmpfil ret)
+    (let (command input tmpinput output tmpoutput stderr tmpstderr
+                 outbuf tmpfile ret)
       ;; Compute command.
       (setq command (mapconcat 'tramp-shell-quote-argument
                               (cons program args) " "))
@@ -757,15 +747,14 @@ target of the symlink differ."
            ;; INFILE is on the same remote host.
            (setq input (with-parsed-tramp-file-name infile nil localname))
          ;; INFILE must be copied to remote host.
-         (setq input (concat temp-name-prefix ".in"))
-         (copy-file
-          infile
-          (tramp-make-tramp-file-name method user host input)
-          t)))
+         (setq input (tramp-make-tramp-temp-file v)
+               tmpinput (tramp-make-tramp-file-name method user host input))
+         (copy-file infile tmpinput t)))
       (when input (setq command (format "%s <%s" command input)))
 
       ;; Determine output.
-      (setq output (concat temp-name-prefix ".out"))
+      (setq output (tramp-make-tramp-temp-file v)
+           tmpoutput (tramp-make-tramp-file-name method user host output))
       (cond
        ;; Just a buffer
        ((bufferp destination)
@@ -791,7 +780,9 @@ target of the symlink differ."
                               (cadr destination) nil localname))
            ;; stderr must be copied to remote host.  The temporary
            ;; file must be deleted after execution.
-           (setq stderr (concat temp-name-prefix ".err"))))
+           (setq stderr (tramp-make-tramp-temp-file v)
+                 tmpstderr (tramp-make-tramp-file-name
+                            method user host stderr))))
         ;; stderr to be discarded
         ((null (cadr destination))
          (setq stderr "/dev/null"))))
@@ -800,9 +791,6 @@ target of the symlink differ."
        (setq outbuf (current-buffer))))
       (when stderr (setq command (format "%s 2>%s" command stderr)))
 
-      ;; If we have a temporary file, it must be removed after operation.
-      (when (and input (string-match temp-name-prefix input))
-       (setq command (format "%s; rm %s" command input)))
       ;; Goto working directory.
       (unless
          (tramp-fish-send-command-and-check
@@ -815,31 +803,31 @@ target of the symlink differ."
                       v (format
                          "#EXEC %s %s"
                          (tramp-shell-quote-argument command) output))
-               (error))
+               (error nil))
            ;; Check return code.
-           (setq tmpfil (file-local-copy
-                         (tramp-make-tramp-file-name method user host output)))
+           (setq tmpfile
+                 (file-local-copy
+                  (tramp-make-tramp-file-name method user host output)))
            (with-temp-buffer
-             (insert-file-contents tmpfil)
+             (insert-file-contents tmpfile)
              (goto-char (point-max))
              (forward-line -1)
              (looking-at "^###RESULT: \\([0-9]+\\)")
              (setq ret (string-to-number (match-string 1)))
              (delete-region (point) (point-max))
-             (write-region (point-min) (point-max) tmpfil))
+             (write-region (point-min) (point-max) tmpfile))
            ;; We should show the output anyway.
            (when outbuf
-             (with-current-buffer outbuf (insert-file-contents tmpfil))
-             (when display (display-buffer outbuf)))
-           ;; Remove output file.
-           (delete-file (tramp-make-tramp-file-name method user host output)))
+             (with-current-buffer outbuf (insert-file-contents tmpfile))
+             (when display (display-buffer outbuf))))
        ;; When the user did interrupt, we should do it also.
        (error (setq ret 1)))
-      (unless ret
-       ;; Provide error file.
-       (when (and stderr (string-match temp-name-prefix stderr))
-         (rename-file (tramp-make-tramp-file-name method user host stderr)
-                      (cadr destination) t)))
+
+      ;; Provide error file.
+      (when tmpstderr (rename-file tmpstderr (cadr destination) t))
+      ;; Cleanup.
+      (when tmpinput (delete-file tmpinput))
+      (when tmpoutput (delete-file tmpoutput))
       ;; Return exit status.
       ret)))
 
@@ -847,7 +835,7 @@ target of the symlink differ."
 ;; Internal file name functions
 
 (defun tramp-fish-do-copy-or-rename-file
-  (op filename newname &optional ok-if-already-exists keep-date)
+  (op filename newname &optional ok-if-already-exists keep-date preserve-uid-gid)
   "Copy or rename a remote file.
 OP must be `copy' or `rename' and indicates the operation to
 perform.  FILENAME specifies the file to copy or rename, NEWNAME
@@ -881,7 +869,7 @@ file names."
           ;; directly.
           ((tramp-equal-remote filename newname)
            (tramp-fish-do-copy-or-rename-file-directly
-            op filename newname keep-date))
+            op filename newname keep-date preserve-uid-gid))
           ;; No shortcut was possible.  So we copy the
           ;; file first.  If the operation was `rename', we go
           ;; back and delete the original file (if the copy was
@@ -911,12 +899,13 @@ file names."
          (tramp-flush-file-property v (file-name-directory localname)))))))
 
 (defun tramp-fish-do-copy-or-rename-file-directly
-  (op filename newname keep-date)
+  (op filename newname keep-date preserve-uid-gid)
   "Invokes `COPY' or `RENAME' on the remote system.
 OP must be one of `copy' or `rename', indicating `cp' or `mv',
 respectively.  VEC specifies the connection.  LOCALNAME1 and
 LOCALNAME2 specify the two arguments of `cp' or `mv'.  If
-KEEP-DATE is non-nil, preserve the time stamp when copying."
+KEEP-DATE is non-nil, preserve the time stamp when copying.
+PRESERVE-UID-GID is completely ignored."
   (with-parsed-tramp-file-name filename v1
     (with-parsed-tramp-file-name newname v2
       (tramp-fish-send-command
@@ -926,11 +915,8 @@ KEEP-DATE is non-nil, preserve the time stamp when copying."
               (tramp-shell-quote-argument v1-localname)
               (tramp-shell-quote-argument v2-localname)))))
   ;; KEEP-DATE handling.
-  (when keep-date
-    (let ((modtime (nth 5 (file-attributes filename))))
-      (when (and (not (null modtime))
-                (not (equal modtime '(0 0))))
-       (tramp-touch newname modtime))))
+  (when (and keep-date (functionp 'set-file-times))
+    (set-file-times newname (nth 5 (file-attributes filename))))
   ;; Set the mode.
   (set-file-modes newname (file-modes filename)))
 
@@ -942,7 +928,8 @@ Result is a list of (LOCALNAME LINK COUNT UID GID ATIME MTIME CTIME
 SIZE MODE WEIRD INODE DEVICE)."
   (block nil
     (with-current-buffer (tramp-get-buffer vec)
-      ;; #LIST does not work properly with trailing "/", at least in .fishsrv.pl
+      ;; #LIST does not work properly with trailing "/", at least in
+      ;; .fishsrv.pl.
       (when (string-match "/$" localname)
        (setq localname (concat localname ".")))
 
@@ -955,7 +942,7 @@ SIZE MODE WEIRD INODE DEVICE)."
        ;; Read number of entries
        (goto-char (point-min))
        (condition-case nil
-           (unless (integerp (setq num (read (current-buffer)))) (error))
+           (unless (integerp (setq num (read (current-buffer)))) (error nil))
          (error (return nil)))
        (forward-line)
        (delete-region (point-min) (point))
@@ -963,7 +950,7 @@ SIZE MODE WEIRD INODE DEVICE)."
        ;; Read return code
        (goto-char (point-min))
        (condition-case nil
-           (unless (looking-at tramp-fish-continue-prompt-regexp) (error))
+           (unless (looking-at tramp-fish-continue-prompt-regexp) (error nil))
          (error (return nil)))
        (forward-line)
        (delete-region (point-min) (point))
@@ -974,13 +961,13 @@ SIZE MODE WEIRD INODE DEVICE)."
            ;; Add inode and device.
            (add-to-list
             'res (append item
-                         (list (tramp-get-inode (car item))
+                         (list (tramp-get-inode vec)
                                (tramp-get-device vec))))))
 
        ;; Read return code
        (goto-char (point-min))
        (condition-case nil
-           (unless (looking-at tramp-fish-ok-prompt-regexp) (error))
+           (unless (looking-at tramp-fish-ok-prompt-regexp) (error nil))
          (error (tramp-error
                  vec 'file-error
                  "`%s' does not return a valid Lisp expression: `%s'"
@@ -1065,7 +1052,7 @@ Returns the size of the data."
        ;; Read filesize
        (goto-char (point-min))
        (condition-case nil
-           (unless (integerp (setq size (read (current-buffer)))) (error))
+           (unless (integerp (setq size (read (current-buffer)))) (error nil))
          (error (return nil)))
        (forward-line)
        (delete-region (point-min) (point))
@@ -1073,7 +1060,7 @@ Returns the size of the data."
        ;; Read return code
        (goto-char (point-min))
        (condition-case nil
-           (unless (looking-at tramp-fish-continue-prompt-regexp) (error))
+           (unless (looking-at tramp-fish-continue-prompt-regexp) (error nil))
          (error (return nil)))
        (forward-line)
        (delete-region (point-min) (point))
@@ -1089,7 +1076,7 @@ Returns the size of the data."
        ;; Read return code
        (goto-char (+ (point-min) size))
        (condition-case nil
-           (unless (looking-at tramp-fish-ok-prompt-regexp) (error))
+           (unless (looking-at tramp-fish-ok-prompt-regexp) (error nil))
          (error (return nil)))
        (delete-region (+ (point-min) size) (point-max))
        size))))
@@ -1126,7 +1113,8 @@ connection if a previous connection has died for some reason."
             (coding-system-for-read 'binary)
             (coding-system-for-write 'binary)
             ;; This must be done in order to avoid our file name handler.
-            (p (let ((default-directory (tramp-temporary-file-directory)))
+            (p (let ((default-directory
+                       (tramp-compat-temporary-file-directory)))
                  (start-process
                   (or (tramp-get-connection-property vec "process-name" nil)
                       (tramp-buffer-name vec))