comparison lisp/net/tramp.el @ 82942:5cf3cd03cb50

* net/tramp.el (tramp-handle-set-file-times): Flush the file properties. (tramp-set-file-uid-gid, tramp-get-local-uid) (tramp-get-local-gid): New defuns. (tramp-handle-copy-file): Handle new parameter PRESERVE-UID-GID. (tramp-do-copy-or-rename-file): New parameter PRESERVE-UID-GID. Improve fast track. (tramp-do-copy-or-rename-file-directly): Sync parameter list with the other tramp-do-copy-or-rename-file-* functions. Major rewrite. (tramp-handle-file-local-copy, tramp-handle-insert-file-contents) (tramp-handle-write-region): Improve fast track. (tramp-handle-file-remote-p): IDENTIFICATION can also be 'localname. (tramp-maybe-open-connection): Let `process-adaptive-read-buffering' be nil.
author Michael Albinus <michael.albinus@gmx.de>
date Tue, 28 Aug 2007 20:09:58 +0000
parents 6e5814967ffb
children 38bcf4ef30c3 b83d0dadb2a7
comparison
equal deleted inserted replaced
82941:68020ac5ef24 82942:5cf3cd03cb50
2504 (defun tramp-handle-set-file-times (filename &optional time) 2504 (defun tramp-handle-set-file-times (filename &optional time)
2505 "Like `set-file-times' for Tramp files." 2505 "Like `set-file-times' for Tramp files."
2506 (zerop 2506 (zerop
2507 (if (file-remote-p filename) 2507 (if (file-remote-p filename)
2508 (with-parsed-tramp-file-name filename nil 2508 (with-parsed-tramp-file-name filename nil
2509 (tramp-flush-file-property v localname)
2509 (let ((time (if (or (null time) (equal time '(0 0))) 2510 (let ((time (if (or (null time) (equal time '(0 0)))
2510 (current-time) 2511 (current-time)
2511 time)) 2512 time))
2512 (utc 2513 (utc
2513 ;; With GNU Emacs, `format-time-string' has an 2514 ;; With GNU Emacs, `format-time-string' has an
2525 (if utc "TZ=UTC; export TZ;" "") 2526 (if utc "TZ=UTC; export TZ;" "")
2526 (if utc 2527 (if utc
2527 (format-time-string "%Y%m%d%H%M.%S" time t) 2528 (format-time-string "%Y%m%d%H%M.%S" time t)
2528 (format-time-string "%Y%m%d%H%M.%S" time)) 2529 (format-time-string "%Y%m%d%H%M.%S" time))
2529 (tramp-shell-quote-argument localname))))) 2530 (tramp-shell-quote-argument localname)))))
2531
2530 ;; We handle also the local part, because in older Emacsen, 2532 ;; We handle also the local part, because in older Emacsen,
2531 ;; without `set-file-times', this function is an alias for this. 2533 ;; without `set-file-times', this function is an alias for this.
2532 ;; We are local, so we don't need the UTC settings. 2534 ;; We are local, so we don't need the UTC settings.
2533 (call-process 2535 (call-process
2534 "touch" nil nil nil "-t" 2536 "touch" nil nil nil "-t"
2535 (format-time-string "%Y%m%d%H%M.%S" time) 2537 (format-time-string "%Y%m%d%H%M.%S" time)
2536 (tramp-shell-quote-argument filename))))) 2538 (tramp-shell-quote-argument filename)))))
2539
2540 (defun tramp-set-file-uid-gid (filename &optional uid gid)
2541 "Set the ownership for FILENAME.
2542 If UID and GID are provided, these values are used; otherwise uid
2543 and gid of the corresponding user is taken. Both parameters must be integers."
2544 ;; CCC: Modern Unices allow chown only for root. So we might need
2545 ;; another implementation, see `dired-do-chown'. OTOH, it is
2546 ;; mostly working with su(do)? when it is needed, so it shall
2547 ;; succeed in the majority of cases.
2548 (if (file-remote-p filename)
2549 (with-parsed-tramp-file-name filename nil
2550 (let ((uid (or (and (integerp uid) uid)
2551 (tramp-get-remote-uid v 'integer)))
2552 (gid (or (and (integerp gid) gid)
2553 (tramp-get-remote-gid v 'integer))))
2554 (tramp-send-command
2555 v (format
2556 "chown %d:%d %s" uid gid
2557 (tramp-shell-quote-argument localname)))))
2558
2559 ;; We handle also the local part, because there doesn't exist
2560 ;; `set-file-uid-gid'.
2561 (let ((uid (or (and (integerp uid) uid) (tramp-get-local-uid 'integer)))
2562 (gid (or (and (integerp gid) gid) (tramp-get-local-uid 'integer)))
2563 (default-directory (tramp-temporary-file-directory)))
2564 (call-process
2565 "chown" nil nil nil
2566 (format "%d:%d" uid gid) (tramp-shell-quote-argument filename)))))
2537 2567
2538 ;; Simple functions using the `test' command. 2568 ;; Simple functions using the `test' command.
2539 2569
2540 (defun tramp-handle-file-executable-p (filename) 2570 (defun tramp-handle-file-executable-p (filename)
2541 "Like `file-executable-p' for Tramp files." 2571 "Like `file-executable-p' for Tramp files."
2838 (tramp-shell-quote-argument v2-localname)) 2868 (tramp-shell-quote-argument v2-localname))
2839 "error with add-name-to-file, see buffer `%s' for details" 2869 "error with add-name-to-file, see buffer `%s' for details"
2840 (buffer-name)))))) 2870 (buffer-name))))))
2841 2871
2842 (defun tramp-handle-copy-file 2872 (defun tramp-handle-copy-file
2843 (filename newname &optional ok-if-already-exists keep-date) 2873 (filename newname &optional ok-if-already-exists keep-date preserve-uid-gid)
2844 "Like `copy-file' for Tramp files." 2874 "Like `copy-file' for Tramp files."
2845 ;; Check if both files are local -- invoke normal copy-file. 2875 ;; Check if both files are local -- invoke normal copy-file.
2846 ;; Otherwise, use tramp from local system. 2876 ;; Otherwise, use tramp from local system.
2847 (setq filename (expand-file-name filename)) 2877 (setq filename (expand-file-name filename))
2848 (setq newname (expand-file-name newname)) 2878 (setq newname (expand-file-name newname))
2849 ;; At least one file a tramp file? 2879 ;; At least one file a tramp file?
2850 (if (or (tramp-tramp-file-p filename) 2880 (if (or (tramp-tramp-file-p filename)
2851 (tramp-tramp-file-p newname)) 2881 (tramp-tramp-file-p newname))
2852 (tramp-do-copy-or-rename-file 2882 (tramp-do-copy-or-rename-file
2853 'copy filename newname ok-if-already-exists keep-date) 2883 'copy filename newname ok-if-already-exists keep-date preserve-uid-gid)
2854 (tramp-run-real-handler 2884 (tramp-run-real-handler
2855 'copy-file (list filename newname ok-if-already-exists keep-date)))) 2885 'copy-file
2886 (list filename newname ok-if-already-exists keep-date preserve-uid-gid))))
2856 2887
2857 (defun tramp-handle-rename-file 2888 (defun tramp-handle-rename-file
2858 (filename newname &optional ok-if-already-exists) 2889 (filename newname &optional ok-if-already-exists)
2859 "Like `rename-file' for Tramp files." 2890 "Like `rename-file' for Tramp files."
2860 ;; Check if both files are local -- invoke normal rename-file. 2891 ;; Check if both files are local -- invoke normal rename-file.
2863 (setq newname (expand-file-name newname)) 2894 (setq newname (expand-file-name newname))
2864 ;; At least one file a tramp file? 2895 ;; At least one file a tramp file?
2865 (if (or (tramp-tramp-file-p filename) 2896 (if (or (tramp-tramp-file-p filename)
2866 (tramp-tramp-file-p newname)) 2897 (tramp-tramp-file-p newname))
2867 (tramp-do-copy-or-rename-file 2898 (tramp-do-copy-or-rename-file
2868 'rename filename newname ok-if-already-exists t) 2899 'rename filename newname ok-if-already-exists t t)
2869 (tramp-run-real-handler 2900 (tramp-run-real-handler
2870 'rename-file (list filename newname ok-if-already-exists)))) 2901 'rename-file (list filename newname ok-if-already-exists))))
2871 2902
2872 (defun tramp-do-copy-or-rename-file 2903 (defun tramp-do-copy-or-rename-file
2873 (op filename newname &optional ok-if-already-exists keep-date) 2904 (op filename newname &optional ok-if-already-exists keep-date preserve-uid-gid)
2874 "Copy or rename a remote file. 2905 "Copy or rename a remote file.
2875 OP must be `copy' or `rename' and indicates the operation to perform. 2906 OP must be `copy' or `rename' and indicates the operation to perform.
2876 FILENAME specifies the file to copy or rename, NEWNAME is the name of 2907 FILENAME specifies the file to copy or rename, NEWNAME is the name of
2877 the new file (for copy) or the new name of the file (for rename). 2908 the new file (for copy) or the new name of the file (for rename).
2878 OK-IF-ALREADY-EXISTS means don't barf if NEWNAME exists already. 2909 OK-IF-ALREADY-EXISTS means don't barf if NEWNAME exists already.
2879 KEEP-DATE means to make sure that NEWNAME has the same timestamp 2910 KEEP-DATE means to make sure that NEWNAME has the same timestamp
2880 as FILENAME. 2911 as FILENAME. PRESERVE-UID-GID, when non-nil, instructs to keep
2912 the uid and gid if both files are on the same host.
2881 2913
2882 This function is invoked by `tramp-handle-copy-file' and 2914 This function is invoked by `tramp-handle-copy-file' and
2883 `tramp-handle-rename-file'. It is an error if OP is neither of `copy' 2915 `tramp-handle-rename-file'. It is an error if OP is neither of `copy'
2884 and `rename'. FILENAME and NEWNAME must be absolute file names." 2916 and `rename'. FILENAME and NEWNAME must be absolute file names."
2885 (unless (memq op '(copy rename)) 2917 (unless (memq op '(copy rename))
2903 ;; Shortcut: if method, host, user are the same for both 2935 ;; Shortcut: if method, host, user are the same for both
2904 ;; files, we invoke `cp' or `mv' on the remote host 2936 ;; files, we invoke `cp' or `mv' on the remote host
2905 ;; directly. 2937 ;; directly.
2906 ((tramp-equal-remote filename newname) 2938 ((tramp-equal-remote filename newname)
2907 (tramp-do-copy-or-rename-file-directly 2939 (tramp-do-copy-or-rename-file-directly
2908 op v1 v1-localname v2-localname keep-date)) 2940 op filename newname
2941 ok-if-already-exists keep-date preserve-uid-gid))
2942
2909 ;; If both source and target are Tramp files, 2943 ;; If both source and target are Tramp files,
2910 ;; both are using the same copy-program, then we 2944 ;; both are using the same copy-program, then we
2911 ;; can invoke rcp directly. Note that 2945 ;; can invoke rcp directly. Note that
2912 ;; default-directory should point to a local 2946 ;; default-directory should point to a local
2913 ;; directory if we want to invoke rcp. 2947 ;; directory if we want to invoke rcp.
2915 (tramp-method-out-of-band-p v1) 2949 (tramp-method-out-of-band-p v1)
2916 (> (nth 7 (file-attributes filename)) 2950 (> (nth 7 (file-attributes filename))
2917 tramp-copy-size-limit)) 2951 tramp-copy-size-limit))
2918 (tramp-do-copy-or-rename-file-out-of-band 2952 (tramp-do-copy-or-rename-file-out-of-band
2919 op filename newname keep-date)) 2953 op filename newname keep-date))
2954
2920 ;; No shortcut was possible. So we copy the 2955 ;; No shortcut was possible. So we copy the
2921 ;; file first. If the operation was `rename', we go 2956 ;; file first. If the operation was `rename', we go
2922 ;; back and delete the original file (if the copy was 2957 ;; back and delete the original file (if the copy was
2923 ;; successful). The approach is simple-minded: we 2958 ;; successful). The approach is simple-minded: we
2924 ;; create a new buffer, insert the contents of the 2959 ;; create a new buffer, insert the contents of the
2931 op filename newname keep-date)))))) 2966 op filename newname keep-date))))))
2932 2967
2933 ;; One file is a Tramp file, the other one is local. 2968 ;; One file is a Tramp file, the other one is local.
2934 ((or t1 t2) 2969 ((or t1 t2)
2935 (with-parsed-tramp-file-name (if t1 filename newname) nil 2970 (with-parsed-tramp-file-name (if t1 filename newname) nil
2936 ;; If the Tramp file has an out-of-band method, the corresponding 2971 (cond
2937 ;; copy-program can be invoked. 2972 ;; Fast track on local machine.
2938 (if (and (tramp-method-out-of-band-p v) 2973 ((tramp-local-host-p v)
2939 (> (nth 7 (file-attributes filename)) 2974 (tramp-do-copy-or-rename-file-directly
2940 tramp-copy-size-limit)) 2975 op filename newname
2941 (tramp-do-copy-or-rename-file-out-of-band 2976 ok-if-already-exists keep-date preserve-uid-gid))
2942 op filename newname keep-date) 2977
2943 ;; Use the generic method via a Tramp buffer. 2978 ;; If the Tramp file has an out-of-band method, the corresponding
2944 (tramp-do-copy-or-rename-file-via-buffer 2979 ;; copy-program can be invoked.
2945 op filename newname keep-date)))) 2980 ((and (tramp-method-out-of-band-p v)
2981 (> (nth 7 (file-attributes filename))
2982 tramp-copy-size-limit))
2983 (tramp-do-copy-or-rename-file-out-of-band
2984 op filename newname keep-date))
2985
2986 ;; Use the inline method via a Tramp buffer.
2987 (t (tramp-do-copy-or-rename-file-via-buffer
2988 op filename newname keep-date)))))
2946 2989
2947 (t 2990 (t
2948 ;; One of them must be a Tramp file. 2991 ;; One of them must be a Tramp file.
2949 (error "Tramp implementation says this cannot happen"))) 2992 (error "Tramp implementation says this cannot happen")))
2993
2950 ;; When newname did exist, we have wrong cached values. 2994 ;; When newname did exist, we have wrong cached values.
2951 (when t2 2995 (when t2
2952 (with-parsed-tramp-file-name newname nil 2996 (with-parsed-tramp-file-name newname nil
2953 (tramp-flush-file-property v localname)))))) 2997 (tramp-flush-file-property v localname))))))
2954 2998
2975 ;; If the operation was `rename', delete the original file. 3019 ;; If the operation was `rename', delete the original file.
2976 (unless (eq op 'copy) 3020 (unless (eq op 'copy)
2977 (delete-file filename)))) 3021 (delete-file filename))))
2978 3022
2979 (defun tramp-do-copy-or-rename-file-directly 3023 (defun tramp-do-copy-or-rename-file-directly
2980 (op vec localname1 localname2 keep-date) 3024 (op filename newname ok-if-already-exists keep-date preserve-uid-gid)
2981 "Invokes `cp' or `mv' on the remote system. 3025 "Invokes `cp' or `mv' on the remote system.
2982 OP must be one of `copy' or `rename', indicating `cp' or `mv', 3026 OP must be one of `copy' or `rename', indicating `cp' or `mv',
2983 respectively. VEC specifies the connection. LOCALNAME1 and 3027 respectively. FILENAME specifies the file to copy or rename,
2984 LOCALNAME2 specify the two arguments of `cp' or `mv'. If 3028 NEWNAME is the name of the new file (for copy) or the new name of
2985 KEEP-DATE is non-nil, preserve the time stamp when copying." 3029 the file (for rename). Both files must reside on the same host.
2986 ;; CCC: What happens to the timestamp when renaming? 3030 KEEP-DATE means to make sure that NEWNAME has the same timestamp
2987 (let ((cmd (cond ((and (eq op 'copy) keep-date) "cp -f -p") 3031 as FILENAME. PRESERVE-UID-GID, when non-nil, instructs to keep
2988 ((eq op 'copy) "cp -f") 3032 the uid and gid from FILENAME."
2989 ((eq op 'rename) "mv -f") 3033 (with-parsed-tramp-file-name (if t1 filename newname) nil
2990 (t (tramp-error 3034 (let* ((cmd (cond ((and (eq op 'copy) preserve-uid-gid) "cp -f -p")
2991 vec 'file-error 3035 ((eq op 'copy) "cp -f")
2992 "Unknown operation `%s', must be `copy' or `rename'" 3036 ((eq op 'rename) "mv -f")
2993 op))))) 3037 (t (tramp-error
2994 (tramp-send-command 3038 vec 'file-error
2995 vec 3039 "Unknown operation `%s', must be `copy' or `rename'"
2996 (format "%s %s %s" 3040 op))))
2997 cmd 3041 (t1 (tramp-tramp-file-p filename))
2998 (tramp-shell-quote-argument localname1) 3042 (t2 (tramp-tramp-file-p newname))
2999 (tramp-shell-quote-argument localname2))) 3043 (localname1
3000 (with-current-buffer (tramp-get-buffer vec) 3044 (if t1 (tramp-handle-file-remote-p filename 'localname) filename))
3001 (goto-char (point-min)) 3045 (localname2
3002 (unless 3046 (if t2 (tramp-handle-file-remote-p newname 'localname) newname))
3003 (or 3047 (prefix (tramp-handle-file-remote-p (if t1 filename newname)))
3004 (and (eq op 'copy) keep-date 3048 (tmpfile (tramp-make-temp-file localname1)))
3005 ;; Mask cp -f error. 3049
3006 (re-search-forward tramp-operation-not-permitted-regexp nil t)) 3050 (cond
3007 (zerop (tramp-send-command-and-check vec nil))) 3051 ;; Both files are on a remote host, with same user.
3008 (tramp-error-with-buffer 3052 ((and t1 t2)
3009 nil vec 'file-error 3053 (tramp-send-command
3010 "Copying directly failed, see buffer `%s' for details." 3054 v
3011 (buffer-name)))) 3055 (format "%s %s %s" cmd
3012 ;; Set the mode. 3056 (tramp-shell-quote-argument localname1)
3013 ;; CCC: Maybe `chmod --reference=localname1 localname2' could be used 3057 (tramp-shell-quote-argument localname2)))
3014 ;; where available? 3058 (with-current-buffer (tramp-get-buffer v)
3015 (unless (or (eq op 'rename) keep-date) 3059 (goto-char (point-min))
3016 (set-file-modes 3060 (unless
3017 (tramp-make-tramp-file-name 3061 (or
3018 (tramp-file-name-method vec) 3062 (and keep-date
3019 (tramp-file-name-user vec) 3063 ;; Mask cp -f error.
3020 (tramp-file-name-host vec) 3064 (re-search-forward
3021 localname2) 3065 tramp-operation-not-permitted-regexp nil t))
3022 (file-modes (tramp-make-tramp-file-name 3066 (zerop (tramp-send-command-and-check v nil)))
3023 (tramp-file-name-method vec) 3067 (tramp-error-with-buffer
3024 (tramp-file-name-user vec) 3068 nil v 'file-error
3025 (tramp-file-name-host vec) 3069 "Copying directly failed, see buffer `%s' for details."
3026 localname1)))))) 3070 (buffer-name)))))
3071
3072 ;; We are on the local host.
3073 ((or t1 t2)
3074 (cond
3075 ;; We can do it directly.
3076 ((and (file-readable-p localname1)
3077 (file-writable-p (file-name-directory localname2)))
3078 (if (eq op 'copy)
3079 (copy-file
3080 localname1 localname2 ok-if-already-exists
3081 keep-date preserve-uid-gid)
3082 (rename-file localname1 localname2 ok-if-already-exists)))
3083
3084 ;; We can do it directly with `tramp-send-command'
3085 ((and (file-readable-p (concat prefix localname1))
3086 (file-writable-p
3087 (file-name-directory (concat prefix localname2))))
3088 (tramp-do-copy-or-rename-file-directly
3089 op (concat prefix localname1) (concat prefix localname2)
3090 ok-if-already-exists keep-date t)
3091 ;; We must change the ownership to the local user.
3092 (tramp-set-file-uid-gid
3093 (concat prefix localname2)
3094 (tramp-get-local-uid 'integer)
3095 (tramp-get-local-gid 'integer)))
3096
3097 ;; We need a temporary file in between.
3098 (t
3099 ;; Create the temporary file.
3100 (cond
3101 (t1
3102 (tramp-send-command
3103 v (format
3104 "%s %s %s" cmd
3105 (tramp-shell-quote-argument localname1)
3106 (tramp-shell-quote-argument tmpfile)))
3107 ;; We must change the ownership as remote user.
3108 (tramp-set-file-uid-gid
3109 (concat prefix tmpfile)
3110 (tramp-get-local-uid 'integer)
3111 (tramp-get-local-gid 'integer)))
3112 (t2
3113 (if (eq op 'copy)
3114 (copy-file
3115 localname1 tmpfile ok-if-already-exists
3116 keep-date preserve-uid-gid)
3117 (rename-file localname1 tmpfile ok-if-already-exists))
3118 ;; We must change the ownership as local user.
3119 (tramp-set-file-uid-gid
3120 tmpfile
3121 (tramp-get-remote-uid v 'integer)
3122 (tramp-get-remote-gid v 'integer))))
3123
3124 ;; Move the temporary file to its destination.
3125 (cond
3126 (t2
3127 (tramp-send-command
3128 v (format
3129 "%s %s %s" cmd
3130 (tramp-shell-quote-argument tmpfile)
3131 (tramp-shell-quote-argument localname2))))
3132 (t1
3133 (if (eq op 'copy)
3134 (copy-file
3135 tmpfile localname2 ok-if-already-exists
3136 keep-date preserve-uid-gid)
3137 (rename-file tmpfile localname2 ok-if-already-exists))))
3138
3139 ;; Remove temporary file.
3140 (when (eq op 'copy) (delete-file tmpfile))))))
3141
3142 ;; Set the time and mode. Mask possible errors.
3143 ;; Won't be applied for 'rename.
3144 (condition-case nil
3145 (when (and keep-date (not preserve-uid-gid))
3146 (set-file-times newname (nth 5 (file-attributes filename)))
3147 (set-file-modes newname (file-modes filename)))
3148 (error)))))
3149
3027 3150
3028 (defun tramp-do-copy-or-rename-file-out-of-band (op filename newname keep-date) 3151 (defun tramp-do-copy-or-rename-file-out-of-band (op filename newname keep-date)
3029 "Invoke rcp program to copy. 3152 "Invoke rcp program to copy.
3030 One of FILENAME and NEWNAME must be a Tramp name, the other must 3153 One of FILENAME and NEWNAME must be a Tramp name, the other must
3031 be a local filename. The method used must be an out-of-band method." 3154 be a local filename. The method used must be an out-of-band method."
3667 "Like `file-local-copy' for Tramp files." 3790 "Like `file-local-copy' for Tramp files."
3668 3791
3669 (with-parsed-tramp-file-name filename nil 3792 (with-parsed-tramp-file-name filename nil
3670 (let ((rem-enc (tramp-get-remote-coding v "remote-encoding")) 3793 (let ((rem-enc (tramp-get-remote-coding v "remote-encoding"))
3671 (loc-dec (tramp-get-local-coding v "local-decoding")) 3794 (loc-dec (tramp-get-local-coding v "local-decoding"))
3672 tmpfil) 3795 (tmpfil (tramp-make-temp-file filename)))
3673 (unless (file-exists-p filename) 3796 (unless (file-exists-p filename)
3674 (tramp-error 3797 (tramp-error
3675 v 'file-error 3798 v 'file-error
3676 "Cannot make local copy of non-existing file `%s'" filename)) 3799 "Cannot make local copy of non-existing file `%s'" filename))
3677 (setq tmpfil (tramp-make-temp-file filename))
3678 3800
3679 (cond 3801 (cond
3680 ;; Fast track on local machine. 3802 ;; `copy-file' handles direct copy and out-of-band methods.
3681 ((tramp-local-host-p v) 3803 ((or (tramp-local-host-p v)
3682 (tramp-do-copy-or-rename-file-directly 'copy v localname tmpfil t) 3804 (and (tramp-method-out-of-band-p v)
3683 (tramp-send-command v (format "chown %s %s" (user-login-name) tmpfil))) 3805 (> (nth 7 (file-attributes filename)) tramp-copy-size-limit)))
3684
3685 ;; `copy-file' handles out-of-band methods.
3686 ((and (tramp-method-out-of-band-p v)
3687 (> (nth 7 (file-attributes filename)) tramp-copy-size-limit))
3688 (copy-file filename tmpfil t t)) 3806 (copy-file filename tmpfil t t))
3689 3807
3690 ;; Use inline encoding for file transfer. 3808 ;; Use inline encoding for file transfer.
3691 (rem-enc 3809 (rem-enc
3692 (save-excursion 3810 (save-excursion
3721 filename loc-dec) 3839 filename loc-dec)
3722 (tramp-call-local-coding-command loc-dec tmpfil2 tmpfil) 3840 (tramp-call-local-coding-command loc-dec tmpfil2 tmpfil)
3723 (delete-file tmpfil2))) 3841 (delete-file tmpfil2)))
3724 (tramp-message v 5 "Decoding remote file %s...done" filename) 3842 (tramp-message v 5 "Decoding remote file %s...done" filename)
3725 ;; Set proper permissions. 3843 ;; Set proper permissions.
3726 (set-file-modes tmpfil (file-modes filename)))) 3844 (set-file-modes tmpfil (file-modes filename))
3845 ;; Set local user ownership.
3846 (tramp-set-file-uid-gid tmpfil)))
3727 3847
3728 ;; Oops, I don't know what to do. 3848 ;; Oops, I don't know what to do.
3729 (t (tramp-error 3849 (t (tramp-error
3730 v 'file-error "Wrong method specification for `%s'" method))) 3850 v 'file-error "Wrong method specification for `%s'" method)))
3731 3851
3741 (and p (processp p) (memq (process-status p) '(run open))))) 3861 (and p (processp p) (memq (process-status p) '(run open)))))
3742 (cond 3862 (cond
3743 ((eq identification 'method) method) 3863 ((eq identification 'method) method)
3744 ((eq identification 'user) user) 3864 ((eq identification 'user) user)
3745 ((eq identification 'host) host) 3865 ((eq identification 'host) host)
3866 ((eq identification 'localname) localname)
3746 (t (tramp-make-tramp-file-name method user host ""))))))) 3867 (t (tramp-make-tramp-file-name method user host "")))))))
3747 3868
3748 (defun tramp-handle-insert-file-contents 3869 (defun tramp-handle-insert-file-contents
3749 (filename &optional visit beg end replace) 3870 (filename &optional visit beg end replace)
3750 "Like `insert-file-contents' for Tramp files." 3871 "Like `insert-file-contents' for Tramp files."
3751 (barf-if-buffer-read-only) 3872 (barf-if-buffer-read-only)
3752 (setq filename (expand-file-name filename)) 3873 (setq filename (expand-file-name filename))
3753 (with-parsed-tramp-file-name filename nil 3874 (let (coding-system-used result)
3754 (if (not (file-exists-p filename)) 3875 (with-parsed-tramp-file-name filename nil
3755 (progn 3876
3756 (when visit 3877 (if (not (file-exists-p filename))
3757 (setq buffer-file-name filename) 3878 (progn
3758 (set-visited-file-modtime) 3879 (when visit
3759 (set-buffer-modified-p nil)) 3880 (setq buffer-file-name filename)
3760 (tramp-error 3881 (set-visited-file-modtime)
3761 v 'file-error "File %s not found on remote host" filename) 3882 (set-buffer-modified-p nil))
3762 (list (expand-file-name filename) 0)) 3883 (tramp-error
3763 ;; `insert-file-contents-literally' takes care to avoid calling 3884 v 'file-error "File %s not found on remote host" filename)
3764 ;; jka-compr. By let-binding inhibit-file-name-operation, we 3885 (list (expand-file-name filename) 0))
3765 ;; propagate that care to the file-local-copy operation. 3886
3766 (let ((local-copy 3887 (if (and (tramp-local-host-p v)
3767 (let ((inhibit-file-name-operation 3888 (file-readable-p localname))
3768 (when (eq inhibit-file-name-operation 3889 ;; Short track: if we are on the local host, we can run directly.
3769 'insert-file-contents) 3890 (insert-file-contents localname visit beg end replace)
3770 'file-local-copy))) 3891
3771 (file-local-copy filename))) 3892 ;; `insert-file-contents-literally' takes care to avoid calling
3772 coding-system-used result) 3893 ;; jka-compr. By let-binding inhibit-file-name-operation, we
3773 (tramp-message v 4 "Inserting local temp file `%s'..." local-copy) 3894 ;; propagate that care to the file-local-copy operation.
3774 (setq result (insert-file-contents local-copy nil beg end replace)) 3895 (let ((local-copy
3896 (let ((inhibit-file-name-operation
3897 (when (eq inhibit-file-name-operation
3898 'insert-file-contents)
3899 'file-local-copy)))
3900 (file-local-copy filename))))
3901 (tramp-message v 4 "Inserting local temp file `%s'..." local-copy)
3902 (setq result (insert-file-contents local-copy nil beg end replace))
3903 ;; Now `last-coding-system-used' has right value. Remember it.
3904 (when (boundp 'last-coding-system-used)
3905 (setq coding-system-used (symbol-value 'last-coding-system-used)))
3906 (tramp-message v 4 "Inserting local temp file `%s'...done" local-copy)
3907 (delete-file local-copy)
3908 (when (boundp 'last-coding-system-used)
3909 (set 'last-coding-system-used coding-system-used))))
3910
3775 (when visit 3911 (when visit
3912 (setq buffer-read-only (file-writable-p filename))
3776 (setq buffer-file-name filename) 3913 (setq buffer-file-name filename)
3777 (set-visited-file-modtime) 3914 (set-visited-file-modtime)
3778 (set-buffer-modified-p nil)) 3915 (set-buffer-modified-p nil))
3779 ;; Now `last-coding-system-used' has right value. Remember it.
3780 (when (boundp 'last-coding-system-used)
3781 (setq coding-system-used (symbol-value 'last-coding-system-used)))
3782 (tramp-message v 4 "Inserting local temp file `%s'...done" local-copy)
3783 (delete-file local-copy)
3784 (when (boundp 'last-coding-system-used)
3785 (set 'last-coding-system-used coding-system-used))
3786 (list (expand-file-name filename) 3916 (list (expand-file-name filename)
3787 (cadr result)))))) 3917 (cadr result))))))
3788
3789 3918
3790 (defun tramp-handle-find-backup-file-name (filename) 3919 (defun tramp-handle-find-backup-file-name (filename)
3791 "Like `find-backup-file-name' for Tramp files." 3920 "Like `find-backup-file-name' for Tramp files."
3792 (with-parsed-tramp-file-name filename nil 3921 (with-parsed-tramp-file-name filename nil
3793 ;; We set both variables. It doesn't matter whether it is 3922 ;; We set both variables. It doesn't matter whether it is
3890 ;; (setq lockname (expand-file-name lockname))) 4019 ;; (setq lockname (expand-file-name lockname)))
3891 ;; (unless (or (eq lockname nil) 4020 ;; (unless (or (eq lockname nil)
3892 ;; (string= lockname filename)) 4021 ;; (string= lockname filename))
3893 ;; (error 4022 ;; (error
3894 ;; "tramp-handle-write-region: LOCKNAME must be nil or equal FILENAME")) 4023 ;; "tramp-handle-write-region: LOCKNAME must be nil or equal FILENAME"))
4024
3895 ;; XEmacs takes a coding system as the seventh argument, not `confirm' 4025 ;; XEmacs takes a coding system as the seventh argument, not `confirm'
3896 (when (and (not (featurep 'xemacs)) confirm (file-exists-p filename)) 4026 (when (and (not (featurep 'xemacs)) confirm (file-exists-p filename))
3897 (unless (y-or-n-p (format "File %s exists; overwrite anyway? " filename)) 4027 (unless (y-or-n-p (format "File %s exists; overwrite anyway? " filename))
3898 (tramp-error v 'file-error "File not overwritten"))) 4028 (tramp-error v 'file-error "File not overwritten")))
4029
3899 (let ((rem-dec (tramp-get-remote-coding v "remote-decoding")) 4030 (let ((rem-dec (tramp-get-remote-coding v "remote-decoding"))
3900 (loc-enc (tramp-get-local-coding v "local-encoding")) 4031 (loc-enc (tramp-get-local-coding v "local-encoding"))
3901 (modes (save-excursion (file-modes filename))) 4032 (modes (save-excursion (file-modes filename)))
3902 ;; We use this to save the value of `last-coding-system-used' 4033 ;; We use this to save the value of `last-coding-system-used'
3903 ;; after writing the tmp file. At the end of the function, 4034 ;; after writing the tmp file. At the end of the function,
3908 coding-system-used 4039 coding-system-used
3909 ;; Write region into a tmp file. This isn't really needed if we 4040 ;; Write region into a tmp file. This isn't really needed if we
3910 ;; use an encoding function, but currently we use it always 4041 ;; use an encoding function, but currently we use it always
3911 ;; because this makes the logic simpler. 4042 ;; because this makes the logic simpler.
3912 (tmpfil (tramp-make-temp-file filename))) 4043 (tmpfil (tramp-make-temp-file filename)))
3913 ;; We say `no-message' here because we don't want the visited file 4044
3914 ;; modtime data to be clobbered from the temp file. We call 4045 (if (and (tramp-local-host-p v)
3915 ;; `set-visited-file-modtime' ourselves later on. 4046 (file-writable-p (file-name-directory localname)))
3916 (tramp-run-real-handler 4047 ;; Short track: if we are on the local host, we can run directly.
3917 'write-region 4048 (if confirm
3918 (if confirm ; don't pass this arg unless defined for backward compat. 4049 (write-region
3919 (list start end tmpfil append 'no-message lockname confirm) 4050 start end localname append 'no-message lockname confirm)
3920 (list start end tmpfil append 'no-message lockname))) 4051 (write-region start end localname append 'no-message lockname))
3921 ;; Now, `last-coding-system-used' has the right value. Remember it. 4052
3922 (when (boundp 'last-coding-system-used) 4053 ;; We say `no-message' here because we don't want the visited file
3923 (setq coding-system-used (symbol-value 'last-coding-system-used))) 4054 ;; modtime data to be clobbered from the temp file. We call
3924 ;; The permissions of the temporary file should be set. If 4055 ;; `set-visited-file-modtime' ourselves later on.
3925 ;; filename does not exist (eq modes nil) it has been renamed to 4056 (tramp-run-real-handler
3926 ;; the backup file. This case `save-buffer' handles 4057 'write-region
3927 ;; permissions. 4058 (if confirm ; don't pass this arg unless defined for backward compat.
3928 (when modes (set-file-modes tmpfil modes)) 4059 (list start end tmpfil append 'no-message lockname confirm)
3929 4060 (list start end tmpfil append 'no-message lockname)))
3930 ;; This is a bit lengthy due to the different methods possible for 4061 ;; Now, `last-coding-system-used' has the right value. Remember it.
3931 ;; file transfer. First, we check whether the method uses an rcp 4062 (when (boundp 'last-coding-system-used)
3932 ;; program. If so, we call it. Otherwise, both encoding and 4063 (setq coding-system-used (symbol-value 'last-coding-system-used)))
3933 ;; decoding command must be specified. However, if the method 4064 ;; The permissions of the temporary file should be set. If
3934 ;; _also_ specifies an encoding function, then that is used for 4065 ;; filename does not exist (eq modes nil) it has been renamed to
3935 ;; encoding the contents of the tmp file. 4066 ;; the backup file. This case `save-buffer' handles
3936 (cond ;; Fast track on local machine. 4067 ;; permissions.
3937 ((tramp-local-host-p v) 4068 (when modes (set-file-modes tmpfil modes))
3938 (tramp-do-copy-or-rename-file-directly 4069
3939 'rename v tmpfil localname t)) 4070 ;; This is a bit lengthy due to the different methods possible for
3940 4071 ;; file transfer. First, we check whether the method uses an rcp
3941 ;; `copy-file' handles out-of-band methods 4072 ;; program. If so, we call it. Otherwise, both encoding and
3942 ((and (tramp-method-out-of-band-p v) 4073 ;; decoding command must be specified. However, if the method
3943 (integerp start) 4074 ;; _also_ specifies an encoding function, then that is used for
3944 (> (- end start) tramp-copy-size-limit)) 4075 ;; encoding the contents of the tmp file.
3945 (rename-file tmpfil filename t)) 4076 (cond
3946 4077 ;; `rename-file' handles direct copy and out-of-band methods.
3947 ;; Use inline file transfer 4078 ((or (tramp-local-host-p v)
3948 (rem-dec 4079 (and (tramp-method-out-of-band-p v)
3949 ;; Encode tmpfil 4080 (integerp start)
3950 (tramp-message v 5 "Encoding region...") 4081 (> (- end start) tramp-copy-size-limit)))
3951 (unwind-protect 4082 (rename-file tmpfil filename t))
3952 (with-temp-buffer 4083
3953 ;; Use encoding function or command. 4084 ;; Use inline file transfer
3954 (if (and (symbolp loc-enc) (fboundp loc-enc)) 4085 (rem-dec
3955 (progn 4086 ;; Encode tmpfil
3956 (tramp-message 4087 (tramp-message v 5 "Encoding region...")
3957 v 5 "Encoding region using function `%s'..." 4088 (unwind-protect
3958 (symbol-name loc-enc)) 4089 (with-temp-buffer
3959 (let ((coding-system-for-read 'binary)) 4090 ;; Use encoding function or command.
3960 (insert-file-contents-literally tmpfil)) 4091 (if (and (symbolp loc-enc) (fboundp loc-enc))
3961 ;; CCC. The following `let' is a workaround for 4092 (progn
3962 ;; the base64.el that comes with pgnus-0.84. If 4093 (tramp-message
3963 ;; both of the following conditions are 4094 v 5 "Encoding region using function `%s'..."
3964 ;; satisfied, it tries to write to a local file 4095 (symbol-name loc-enc))
3965 ;; in default-directory, but at this point, 4096 (let ((coding-system-for-read 'binary))
3966 ;; default-directory is remote. 4097 (insert-file-contents-literally tmpfil))
3967 ;; (CALL-PROCESS-REGION can't write to remote 4098 ;; CCC. The following `let' is a workaround for
3968 ;; files, it seems.) The file in question is a 4099 ;; the base64.el that comes with pgnus-0.84. If
3969 ;; tmp file anyway. 4100 ;; both of the following conditions are
3970 (let ((default-directory 4101 ;; satisfied, it tries to write to a local file
3971 (tramp-temporary-file-directory))) 4102 ;; in default-directory, but at this point,
3972 (funcall loc-enc (point-min) (point-max)))) 4103 ;; default-directory is remote.
3973 4104 ;; (CALL-PROCESS-REGION can't write to remote
3974 (tramp-message 4105 ;; files, it seems.) The file in question is a
3975 v 5 "Encoding region using command `%s'..." loc-enc) 4106 ;; tmp file anyway.
3976 (unless (equal 0 (tramp-call-local-coding-command 4107 (let ((default-directory
3977 loc-enc tmpfil t)) 4108 (tramp-temporary-file-directory)))
3978 (tramp-error 4109 (funcall loc-enc (point-min) (point-max))))
3979 v 'file-error 4110
3980 (concat "Cannot write to `%s', local encoding" 4111 (tramp-message
3981 " command `%s' failed") 4112 v 5 "Encoding region using command `%s'..." loc-enc)
3982 filename loc-enc))) 4113 (unless (equal 0 (tramp-call-local-coding-command
3983 4114 loc-enc tmpfil t))
3984 ;; Send buffer into remote decoding command which 4115 (tramp-error
3985 ;; writes to remote file. Because this happens on the 4116 v 'file-error
3986 ;; remote host, we cannot use the function. 4117 "Cannot write to `%s', local encoding command `%s' failed"
3987 (goto-char (point-max)) 4118 filename loc-enc)))
3988 (unless (bolp) (newline)) 4119
3989 (tramp-message 4120 ;; Send buffer into remote decoding command which
3990 v 5 "Decoding region into remote file %s..." filename) 4121 ;; writes to remote file. Because this happens on the
3991 (tramp-send-command 4122 ;; remote host, we cannot use the function.
3992 v 4123 (goto-char (point-max))
3993 (format 4124 (unless (bolp) (newline))
3994 "%s >%s <<'EOF'\n%sEOF" 4125 (tramp-message
3995 rem-dec 4126 v 5 "Decoding region into remote file %s..." filename)
3996 (tramp-shell-quote-argument localname) 4127 (tramp-send-command
3997 (buffer-string))) 4128 v
3998 (tramp-barf-unless-okay 4129 (format
3999 v nil 4130 "%s >%s <<'EOF'\n%sEOF"
4131 rem-dec
4132 (tramp-shell-quote-argument localname)
4133 (buffer-string)))
4134 (tramp-barf-unless-okay
4135 v nil
4136 "Couldn't write region to `%s', decode using `%s' failed"
4137 filename rem-dec)
4138 ;; When `file-precious-flag' is set, the region is
4139 ;; written to a temporary file. Check that the
4140 ;; checksum is equal to that from the local tmpfil.
4141 (when file-precious-flag
4142 (erase-buffer)
4143 (and
4144 ;; cksum runs locally
4145 (let ((default-directory (tramp-temporary-file-directory)))
4146 (zerop (call-process "cksum" tmpfil t)))
4147 ;; cksum runs remotely
4148 (zerop
4149 (tramp-send-command-and-check
4150 v
4151 (format "cksum <%s" (tramp-shell-quote-argument localname))))
4152 ;; ... they are different
4153 (not
4154 (string-equal
4155 (buffer-string)
4156 (with-current-buffer (tramp-get-buffer v) (buffer-string))))
4157 (tramp-error
4158 v 'file-error
4000 (concat "Couldn't write region to `%s'," 4159 (concat "Couldn't write region to `%s',"
4001 " decode using `%s' failed") 4160 " decode using `%s' failed")
4002 filename rem-dec) 4161 filename rem-dec)))
4003 ;; When `file-precious-flag' is set, the region is 4162 (tramp-message
4004 ;; written to a temporary file. Check that the 4163 v 5 "Decoding region into remote file %s...done" filename)
4005 ;; checksum is equal to that from the local tmpfil. 4164 (tramp-flush-file-property v localname))
4006 (when file-precious-flag 4165
4007 (erase-buffer) 4166 ;; Save exit.
4008 (and 4167 (delete-file tmpfil)))
4009 ;; cksum runs locally 4168
4010 (let ((default-directory 4169 ;; That's not expected.
4011 (tramp-temporary-file-directory))) 4170 (t
4012 (zerop (call-process "cksum" tmpfil t))) 4171 (tramp-error
4013 ;; cksum runs remotely 4172 v 'file-error
4014 (zerop 4173 (concat "Method `%s' should specify both encoding and "
4015 (tramp-send-command-and-check 4174 "decoding command or an rcp program")
4016 v 4175 method))))
4017 (format
4018 "cksum <%s"
4019 (tramp-shell-quote-argument localname))))
4020 ;; ... they are different
4021 (not
4022 (string-equal
4023 (buffer-string)
4024 (with-current-buffer (tramp-get-buffer v)
4025 (buffer-string))))
4026 (tramp-error
4027 v 'file-error
4028 (concat "Couldn't write region to `%s',"
4029 " decode using `%s' failed")
4030 filename rem-dec)))
4031 (tramp-message
4032 v 5 "Decoding region into remote file %s...done" filename)
4033 (tramp-flush-file-property v localname))
4034
4035 ;; Save exit.
4036 (delete-file tmpfil)))
4037
4038 ;; That's not expected.
4039 (t
4040 (tramp-error
4041 v 'file-error
4042 (concat "Method `%s' should specify both encoding and "
4043 "decoding command or an rcp program")
4044 method)))
4045 4176
4046 (when (or (eq visit t) (stringp visit)) 4177 (when (or (eq visit t) (stringp visit))
4047 (set-visited-file-modtime 4178 (set-visited-file-modtime
4048 ;; We must pass modtime explicitely, because filename can be different 4179 ;; We must pass modtime explicitely, because filename can be different
4049 ;; from (buffer-file-name), f.e. if `file-precious-flag' is set. 4180 ;; from (buffer-file-name), f.e. if `file-precious-flag' is set.
4050 (nth 5 (file-attributes filename)))) 4181 (nth 5 (file-attributes filename))))
4182 ;; Set the ownership.
4183 (tramp-set-file-uid-gid filename)
4051 ;; Make `last-coding-system-used' have the right value. 4184 ;; Make `last-coding-system-used' have the right value.
4052 (when (boundp 'last-coding-system-used) 4185 (when coding-system-used
4053 (set 'last-coding-system-used coding-system-used)) 4186 (set 'last-coding-system-used coding-system-used))
4054 (when (or (eq visit t) (null visit) (stringp visit)) 4187 (when (or (eq visit t) (null visit) (stringp visit))
4055 (tramp-message v 0 "Wrote %s" filename)) 4188 (tramp-message v 0 "Wrote %s" filename))
4056 (run-hooks 'tramp-handle-write-region-hook)))) 4189 (run-hooks 'tramp-handle-write-region-hook))))
4057 4190
5915 (setenv "PROMPT_COMMAND") 6048 (setenv "PROMPT_COMMAND")
5916 (setenv "PS1" "$ ") 6049 (setenv "PS1" "$ ")
5917 (let* ((target-alist (tramp-compute-multi-hops vec)) 6050 (let* ((target-alist (tramp-compute-multi-hops vec))
5918 (process-environment (copy-sequence process-environment)) 6051 (process-environment (copy-sequence process-environment))
5919 (process-connection-type tramp-process-connection-type) 6052 (process-connection-type tramp-process-connection-type)
6053 (process-adaptive-read-buffering nil)
5920 (coding-system-for-read nil) 6054 (coding-system-for-read nil)
5921 ;; This must be done in order to avoid our file name handler. 6055 ;; This must be done in order to avoid our file name handler.
5922 (p (let ((default-directory (tramp-temporary-file-directory))) 6056 (p (let ((default-directory (tramp-temporary-file-directory)))
5923 (start-process 6057 (start-process
5924 (or (tramp-get-connection-property vec "process-name" nil) 6058 (or (tramp-get-connection-property vec "process-name" nil)
6702 (if (equal id-format 'integer) "" "n") 6836 (if (equal id-format 'integer) "" "n")
6703 (if (equal id-format 'integer) 6837 (if (equal id-format 'integer)
6704 "" "| sed -e s/^/\\\"/ -e s/\$/\\\"/"))))) 6838 "" "| sed -e s/^/\\\"/ -e s/\$/\\\"/")))))
6705 ;; The command might not always return a number. 6839 ;; The command might not always return a number.
6706 (if (and (equal id-format 'integer) (not (integerp res))) -1 res)))) 6840 (if (and (equal id-format 'integer) (not (integerp res))) -1 res))))
6841
6842 (defun tramp-get-local-uid (id-format)
6843 (if (equal id-format 'integer) (user-uid) (user-login-name)))
6844
6845 (defun tramp-get-local-gid (id-format)
6846 (nth 3 (file-attributes "~/" id-format)))
6707 6847
6708 ;; Some predefined connection properties. 6848 ;; Some predefined connection properties.
6709 (defun tramp-get-remote-coding (vec prop) 6849 (defun tramp-get-remote-coding (vec prop)
6710 ;; Local coding handles properties like remote coding. So we could 6850 ;; Local coding handles properties like remote coding. So we could
6711 ;; call it without pain. 6851 ;; call it without pain.