aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Steingold2000-07-25 23:26:01 +0000
committerSam Steingold2000-07-25 23:26:01 +0000
commit25759a92ce408ae70ea20ddabed3867c3cdbf567 (patch)
tree3b7172bbd299f3bc574255952341b1e1ea455ac9
parent5044b74a7b8053a5c18b050b21b829582c36dcf0 (diff)
downloademacs-25759a92ce408ae70ea20ddabed3867c3cdbf567.tar.gz
emacs-25759a92ce408ae70ea20ddabed3867c3cdbf567.zip
Get modtime over the net
-rw-r--r--lisp/ChangeLog8
-rw-r--r--lisp/net/ange-ftp.el541
2 files changed, 280 insertions, 269 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 54957fb9b1b..246fa78a463 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,13 @@
12000-07-25 Sam Steingold <sds@gnu.org> 12000-07-25 Sam Steingold <sds@gnu.org>
2 2
3 * net/ange-ftp.el: Get modtime over the net.
4 (ange-ftp-file-modtime): New function.
5 (ange-ftp-write-region, ange-ftp-insert-file-contents,
6 ange-ftp-file-attributes, ange-ftp-verify-visited-file-modtime):
7 Use it.
8 (ange-ftp-dot-to-slash): New function.
9 (ange-ftp-fix-name-for-vms): Use it.
10
3 * midnight.el (midnight-buffer-display-time): Use 11 * midnight.el (midnight-buffer-display-time): Use
4 `with-current-buffer'. 12 `with-current-buffer'.
5 13
diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el
index 1c114913585..693be20a8ac 100644
--- a/lisp/net/ange-ftp.el
+++ b/lisp/net/ange-ftp.el
@@ -338,7 +338,7 @@
338;; would report any failures to automatically recognize a MTS host as a bug. 338;; would report any failures to automatically recognize a MTS host as a bug.
339;; 339;;
340;; Filename syntax: 340;; Filename syntax:
341;; 341;;
342;; MTS filenames are entered in a UNIX-y way. For example, if your account 342;; MTS filenames are entered in a UNIX-y way. For example, if your account
343;; was YYYY, the file FILE in the account XXXX: on mtsg.ubc.ca would be 343;; was YYYY, the file FILE in the account XXXX: on mtsg.ubc.ca would be
344;; entered as 344;; entered as
@@ -355,14 +355,14 @@
355;; is. 355;; is.
356 356
357;; CMS support: 357;; CMS support:
358;; 358;;
359;; Ange-ftp has full support for hosts running 359;; Ange-ftp has full support for hosts running
360;; CMS. It should be able to automatically recognize any CMS machine. 360;; CMS. It should be able to automatically recognize any CMS machine.
361;; However, if it fails to do this, you can use the command 361;; However, if it fails to do this, you can use the command
362;; ange-ftp-add-cms-host. As well, you can set the variable 362;; ange-ftp-add-cms-host. As well, you can set the variable
363;; ange-ftp-cms-host-regexp in your .emacs file. We would be grateful if you 363;; ange-ftp-cms-host-regexp in your .emacs file. We would be grateful if you
364;; would report any failures to automatically recognize a CMS host as a bug. 364;; would report any failures to automatically recognize a CMS host as a bug.
365;; 365;;
366;; Filename syntax: 366;; Filename syntax:
367;; 367;;
368;; CMS filenames are entered in a UNIX-y way. In otherwords, minidisks are 368;; CMS filenames are entered in a UNIX-y way. In otherwords, minidisks are
@@ -387,7 +387,7 @@
387;; ------------------------------------------------------------------ 387;; ------------------------------------------------------------------
388;; Bugs: 388;; Bugs:
389;; ------------------------------------------------------------------ 389;; ------------------------------------------------------------------
390;; 390;;
391;; 1. Umask problems: 391;; 1. Umask problems:
392;; Be warned that files created by using ange-ftp will take account of the 392;; Be warned that files created by using ange-ftp will take account of the
393;; umask of the ftp daemon process rather than the umask of the creating 393;; umask of the ftp daemon process rather than the umask of the creating
@@ -423,7 +423,7 @@
423;; 6. For CMS support, we send too many cd's. Since cd's are cheap, I haven't 423;; 6. For CMS support, we send too many cd's. Since cd's are cheap, I haven't
424;; worried about this too much. Eventually, we should have some caching 424;; worried about this too much. Eventually, we should have some caching
425;; of the current minidisk. 425;; of the current minidisk.
426;; 426;;
427;; 7. Some CMS machines do not assign a default minidisk when you ftp them as 427;; 7. Some CMS machines do not assign a default minidisk when you ftp them as
428;; anonymous. It is then necessary to guess a valid minidisk name, and cd 428;; anonymous. It is then necessary to guess a valid minidisk name, and cd
429;; to it. This is (understandably) beyond ange-ftp. 429;; to it. This is (understandably) beyond ange-ftp.
@@ -459,7 +459,7 @@
459;; 12. The dired support for non-Unix-like systems does not currently work. 459;; 12. The dired support for non-Unix-like systems does not currently work.
460;; It needs to be reimplemented by modifying the parse-...-listing 460;; It needs to be reimplemented by modifying the parse-...-listing
461;; functions to convert the directory listing to ls -l format. 461;; functions to convert the directory listing to ls -l format.
462;; 462;;
463;; 13. The famous @ bug. As mentioned above in TIPS, ULTRIX marks symlinks 463;; 13. The famous @ bug. As mentioned above in TIPS, ULTRIX marks symlinks
464;; with a trailing @ in a ls -alF listing. In order to account for this 464;; with a trailing @ in a ls -alF listing. In order to account for this
465;; ange-ftp looks to chop trailing @'s off of symlink names when it is 465;; ange-ftp looks to chop trailing @'s off of symlink names when it is
@@ -495,7 +495,7 @@
495;; 495;;
496;; For mail to be posted directly to ange-ftp-lovers, send to one of the 496;; For mail to be posted directly to ange-ftp-lovers, send to one of the
497;; following addresses: 497;; following addresses:
498;; 498;;
499;; ange-ftp-lovers@anorman.hpl.hp.com 499;; ange-ftp-lovers@anorman.hpl.hp.com
500;; or 500;; or
501;; ange-ftp-lovers%anorman.hpl.hp.com@hplb.hpl.hp.com 501;; ange-ftp-lovers%anorman.hpl.hp.com@hplb.hpl.hp.com
@@ -518,7 +518,7 @@
518;; whenever they see a file name of the appropriate sort. 518;; whenever they see a file name of the appropriate sort.
519 519
520;; Checklist for adding non-UNIX support for TYPE 520;; Checklist for adding non-UNIX support for TYPE
521;; 521;;
522;; The following functions may need TYPE versions: 522;; The following functions may need TYPE versions:
523;; (not all functions will be needed for every OS) 523;; (not all functions will be needed for every OS)
524;; 524;;
@@ -574,14 +574,14 @@
574;; points. These errors provide a code, which is an integer, greater than 1. 574;; points. These errors provide a code, which is an integer, greater than 1.
575;; To aid debugging. the error codes, and the functions in which they reside 575;; To aid debugging. the error codes, and the functions in which they reside
576;; are listed below. 576;; are listed below.
577;; 577;;
578;; 1: See ange-ftp-ls 578;; 1: See ange-ftp-ls
579;; 579;;
580 580
581;; ----------------------------------------------------------- 581;; -----------------------------------------------------------
582;; Hall of fame: 582;; Hall of fame:
583;; ----------------------------------------------------------- 583;; -----------------------------------------------------------
584;; 584;;
585;; Thanks to Roland McGrath for improving the filename syntax handling, 585;; Thanks to Roland McGrath for improving the filename syntax handling,
586;; for suggesting many enhancements and for numerous cleanups to the code. 586;; for suggesting many enhancements and for numerous cleanups to the code.
587;; 587;;
@@ -629,7 +629,7 @@
629;;;; ------------------------------------------------------------ 629;;;; ------------------------------------------------------------
630 630
631(defgroup ange-ftp nil 631(defgroup ange-ftp nil
632 "Accessing remote files and directories using FTP 632 "Accessing remote files and directories using FTP
633 made as simple and transparent as possible." 633 made as simple and transparent as possible."
634 :group 'files 634 :group 'files
635 :prefix "ange-ftp-") 635 :prefix "ange-ftp-")
@@ -643,7 +643,7 @@ where REGEXP is a regular expression matching
643the full remote name, and HOST, USER, and NAME are the numbers of 643the full remote name, and HOST, USER, and NAME are the numbers of
644parenthesized expressions in REGEXP for the components (in that order)." 644parenthesized expressions in REGEXP for the components (in that order)."
645 :group 'ange-ftp 645 :group 'ange-ftp
646 :type '(list regexp 646 :type '(list regexp
647 (integer :tag "Host group") 647 (integer :tag "Host group")
648 (integer :tag "User group") 648 (integer :tag "User group")
649 (integer :tag "Name group"))) 649 (integer :tag "Name group")))
@@ -703,7 +703,7 @@ These mean that the FTP process should (or already has) been killed."
703 :group 'ange-ftp 703 :group 'ange-ftp
704 :type 'regexp) 704 :type 'regexp)
705 705
706(defcustom ange-ftp-tmp-name-template 706(defcustom ange-ftp-tmp-name-template
707 (expand-file-name "ange-ftp" temporary-file-directory) 707 (expand-file-name "ange-ftp" temporary-file-directory)
708 "*Template used to create temporary files." 708 "*Template used to create temporary files."
709 :group 'ange-ftp 709 :group 'ange-ftp
@@ -911,7 +911,7 @@ Some AT&T folks claim to use something called `pftp' here."
911 :type '(repeat string)) 911 :type '(repeat string))
912 912
913(defcustom ange-ftp-nslookup-program nil 913(defcustom ange-ftp-nslookup-program nil
914 "*If non-nil, this is a string naming the nslookup program." 914 "*If non-nil, this is a string naming the nslookup program."
915 :group 'ange-ftp 915 :group 'ange-ftp
916 :type '(choice (const :tag "None" nil) 916 :type '(choice (const :tag "None" nil)
917 string)) 917 string))
@@ -957,16 +957,16 @@ SIZE, if supplied, should be a prime number."
957(defun ange-ftp-map-hashtable (fun tbl) 957(defun ange-ftp-map-hashtable (fun tbl)
958 "Call FUNCTION on each key and value in HASHTABLE." 958 "Call FUNCTION on each key and value in HASHTABLE."
959 (mapatoms 959 (mapatoms
960 (function 960 (function
961 (lambda (sym) 961 (lambda (sym)
962 (funcall fun (get sym 'key) (get sym 'val)))) 962 (funcall fun (get sym 'key) (get sym 'val))))
963 tbl)) 963 tbl))
964 964
965(defmacro ange-ftp-make-hash-key (key) 965(defmacro ange-ftp-make-hash-key (key)
966 "Convert KEY into a suitable key for a hashtable." 966 "Convert KEY into a suitable key for a hashtable."
967 (` (if (stringp (, key)) 967 `(if (stringp ,key)
968 (, key) 968 ,key
969 (prin1-to-string (, key))))) 969 (prin1-to-string ,key)))
970 970
971(defun ange-ftp-get-hash-entry (key tbl) 971(defun ange-ftp-get-hash-entry (key tbl)
972 "Return the value associated with KEY in HASHTABLE." 972 "Return the value associated with KEY in HASHTABLE."
@@ -1090,7 +1090,7 @@ Args are as in `message': a format string, plus arguments to be formatted."
1090 (message "%s" msg)))) 1090 (message "%s" msg))))
1091 1091
1092(defun ange-ftp-abbreviate-filename (file &optional new) 1092(defun ange-ftp-abbreviate-filename (file &optional new)
1093 "Abbreviate the file name FILE relative to the default-directory. 1093 "Abbreviate the file name FILE relative to the `default-directory'.
1094If the optional parameter NEW is given and the non-directory parts match, 1094If the optional parameter NEW is given and the non-directory parts match,
1095only return the directory part of FILE." 1095only return the directory part of FILE."
1096 (save-match-data 1096 (save-match-data
@@ -1140,11 +1140,11 @@ only return the directory part of FILE."
1140;;;; ------------------------------------------------------------ 1140;;;; ------------------------------------------------------------
1141 1141
1142(defmacro ange-ftp-generate-passwd-key (host user) 1142(defmacro ange-ftp-generate-passwd-key (host user)
1143 (` (concat (downcase (, host)) "/" (, user)))) 1143 `(concat (downcase ,host) "/" ,user))
1144 1144
1145(defmacro ange-ftp-lookup-passwd (host user) 1145(defmacro ange-ftp-lookup-passwd (host user)
1146 (` (ange-ftp-get-hash-entry (ange-ftp-generate-passwd-key (, host) (, user)) 1146 `(ange-ftp-get-hash-entry (ange-ftp-generate-passwd-key ,host ,user)
1147 ange-ftp-passwd-hashtable))) 1147 ange-ftp-passwd-hashtable))
1148 1148
1149(defun ange-ftp-set-passwd (host user passwd) 1149(defun ange-ftp-set-passwd (host user passwd)
1150 "For a given HOST and USER, set or change the associated PASSWORD." 1150 "For a given HOST and USER, set or change the associated PASSWORD."
@@ -1183,19 +1183,19 @@ only return the directory part of FILE."
1183 ;; look up password in the hash table first; user might have overridden the 1183 ;; look up password in the hash table first; user might have overridden the
1184 ;; defaults. 1184 ;; defaults.
1185 (cond ((ange-ftp-lookup-passwd host user)) 1185 (cond ((ange-ftp-lookup-passwd host user))
1186 1186
1187 ;; See if default user and password set. 1187 ;; See if default user and password set.
1188 ((and (stringp ange-ftp-default-user) 1188 ((and (stringp ange-ftp-default-user)
1189 ange-ftp-default-password 1189 ange-ftp-default-password
1190 (string-equal user ange-ftp-default-user)) 1190 (string-equal user ange-ftp-default-user))
1191 ange-ftp-default-password) 1191 ange-ftp-default-password)
1192 1192
1193 ;; See if default user and password set from .netrc file. 1193 ;; See if default user and password set from .netrc file.
1194 ((and (stringp ange-ftp-netrc-default-user) 1194 ((and (stringp ange-ftp-netrc-default-user)
1195 ange-ftp-netrc-default-password 1195 ange-ftp-netrc-default-password
1196 (string-equal user ange-ftp-netrc-default-user)) 1196 (string-equal user ange-ftp-netrc-default-user))
1197 ange-ftp-netrc-default-password) 1197 ange-ftp-netrc-default-password)
1198 1198
1199 ;; anonymous ftp password is handled specially since there is an 1199 ;; anonymous ftp password is handled specially since there is an
1200 ;; unwritten rule about how that is used on the Internet. 1200 ;; unwritten rule about how that is used on the Internet.
1201 ((and (or (string-equal user "anonymous") 1201 ((and (or (string-equal user "anonymous")
@@ -1204,13 +1204,13 @@ only return the directory part of FILE."
1204 (if (stringp ange-ftp-generate-anonymous-password) 1204 (if (stringp ange-ftp-generate-anonymous-password)
1205 ange-ftp-generate-anonymous-password 1205 ange-ftp-generate-anonymous-password
1206 user-mail-address)) 1206 user-mail-address))
1207 1207
1208 ;; see if same user has logged in to other hosts; if so then prompt 1208 ;; see if same user has logged in to other hosts; if so then prompt
1209 ;; with the password that was used there. 1209 ;; with the password that was used there.
1210 (t 1210 (t
1211 (let* ((other (ange-ftp-get-host-with-passwd user)) 1211 (let* ((other (ange-ftp-get-host-with-passwd user))
1212 (passwd (if other 1212 (passwd (if other
1213 1213
1214 ;; found another machine with the same user. 1214 ;; found another machine with the same user.
1215 ;; Try that account. 1215 ;; Try that account.
1216 (read-passwd 1216 (read-passwd
@@ -1218,7 +1218,7 @@ only return the directory part of FILE."
1218 user host user other) 1218 user host user other)
1219 nil 1219 nil
1220 (ange-ftp-lookup-passwd other user)) 1220 (ange-ftp-lookup-passwd other user))
1221 1221
1222 ;; I give up. Ask the user for the password. 1222 ;; I give up. Ask the user for the password.
1223 (read-passwd 1223 (read-passwd
1224 (format "Password for %s@%s: " user host))))) 1224 (format "Password for %s@%s: " user host)))))
@@ -1233,7 +1233,7 @@ only return the directory part of FILE."
1233;; manually by calling ange-ftp-set-account. For the moment, ange-ftp doesn't 1233;; manually by calling ange-ftp-set-account. For the moment, ange-ftp doesn't
1234;; check to see whether the FTP process is actually prompting for an account 1234;; check to see whether the FTP process is actually prompting for an account
1235;; password. 1235;; password.
1236 1236
1237(defun ange-ftp-set-account (host user account) 1237(defun ange-ftp-set-account (host user account)
1238 "For a given HOST and USER, set or change the associated ACCOUNT password." 1238 "For a given HOST and USER, set or change the associated ACCOUNT password."
1239 (interactive (list (read-string "Host: ") 1239 (interactive (list (read-string "Host: ")
@@ -1404,9 +1404,9 @@ only return the directory part of FILE."
1404 1404
1405(defmacro ange-ftp-ftp-name-component (n ns name) 1405(defmacro ange-ftp-ftp-name-component (n ns name)
1406 "Extract the Nth ftp file name component from NS." 1406 "Extract the Nth ftp file name component from NS."
1407 (` (let ((elt (nth (, n) (, ns)))) 1407 `(let ((elt (nth ,n ,ns)))
1408 (if (match-beginning elt) 1408 (if (match-beginning elt)
1409 (substring (, name) (match-beginning elt) (match-end elt)))))) 1409 (substring ,name (match-beginning elt) (match-end elt)))))
1410 1410
1411(defvar ange-ftp-ftp-name-arg "") 1411(defvar ange-ftp-ftp-name-arg "")
1412(defvar ange-ftp-ftp-name-res nil) 1412(defvar ange-ftp-ftp-name-res nil)
@@ -1611,14 +1611,14 @@ good, skip, fatal, or unknown."
1611 1611
1612 ;; Eliminate nulls. 1612 ;; Eliminate nulls.
1613 (while (string-match "\000+" str) 1613 (while (string-match "\000+" str)
1614 (setq str (replace-match "" nil nil str))) 1614 (setq str (replace-match "" nil nil str)))
1615 1615
1616 ;; see if the buffer is still around... it could have been deleted. 1616 ;; see if the buffer is still around... it could have been deleted.
1617 (if (buffer-name buffer) 1617 (if (buffer-name buffer)
1618 (unwind-protect 1618 (unwind-protect
1619 (progn 1619 (progn
1620 (set-buffer (process-buffer proc)) 1620 (set-buffer (process-buffer proc))
1621 1621
1622 ;; handle hash mark printing 1622 ;; handle hash mark printing
1623 (and ange-ftp-process-busy 1623 (and ange-ftp-process-busy
1624 (string-match "^#+$" str) 1624 (string-match "^#+$" str)
@@ -1631,7 +1631,7 @@ good, skip, fatal, or unknown."
1631 (progn 1631 (progn
1632 (setq ange-ftp-process-string (concat ange-ftp-process-string 1632 (setq ange-ftp-process-string (concat ange-ftp-process-string
1633 str)) 1633 str))
1634 1634
1635 ;; if we gave an empty password to the USER command earlier 1635 ;; if we gave an empty password to the USER command earlier
1636 ;; then we should send a null password now. 1636 ;; then we should send a null password now.
1637 (if (string-match "Password: *$" ange-ftp-process-string) 1637 (if (string-match "Password: *$" ange-ftp-process-string)
@@ -1662,7 +1662,7 @@ good, skip, fatal, or unknown."
1662 (ange-ftp-message "%s...done" ange-ftp-process-msg) 1662 (ange-ftp-message "%s...done" ange-ftp-process-msg)
1663 (ange-ftp-repaint-minibuffer) 1663 (ange-ftp-repaint-minibuffer)
1664 (setq ange-ftp-process-msg nil))) 1664 (setq ange-ftp-process-msg nil)))
1665 1665
1666 ;; is there a continuation we should be calling? if so, 1666 ;; is there a continuation we should be calling? if so,
1667 ;; we'd better call it, making sure we only call it once. 1667 ;; we'd better call it, making sure we only call it once.
1668 (if ange-ftp-process-continue 1668 (if ange-ftp-process-continue
@@ -1794,9 +1794,10 @@ good, skip, fatal, or unknown."
1794(defun ange-ftp-raw-send-cmd (proc cmd &optional msg cont nowait) 1794(defun ange-ftp-raw-send-cmd (proc cmd &optional msg cont nowait)
1795 "Low-level routine to send the given ftp CMD to the ftp PROCESS. 1795 "Low-level routine to send the given ftp CMD to the ftp PROCESS.
1796MSG is an optional message to output before and after the command. 1796MSG is an optional message to output before and after the command.
1797If CONT is non-nil then it is either a function or a list of function and 1797If CONT is non-nil then it is either a function or a list of function
1798some arguments. The function will be called when the ftp command has completed. 1798and some arguments. The function will be called when the ftp command
1799If CONT is nil then this routine will return \( RESULT . LINE \) where RESULT 1799has completed.
1800If CONT is nil then this routine will return \(RESULT . LINE\) where RESULT
1800is whether the command was successful, and LINE is the line from the FTP 1801is whether the command was successful, and LINE is the line from the FTP
1801process that caused the command to complete. 1802process that caused the command to complete.
1802If NOWAIT is given then the routine will return immediately the command has 1803If NOWAIT is given then the routine will return immediately the command has
@@ -1891,7 +1892,7 @@ on the gateway machine to do the ftp instead."
1891 (use-smart-ftp (and (not ange-ftp-gateway-host) 1892 (use-smart-ftp (and (not ange-ftp-gateway-host)
1892 (ange-ftp-use-smart-gateway-p host))) 1893 (ange-ftp-use-smart-gateway-p host)))
1893 (ftp-prog (if (or use-gateway 1894 (ftp-prog (if (or use-gateway
1894 use-smart-ftp) 1895 use-smart-ftp)
1895 ange-ftp-gateway-ftp-program-name 1896 ange-ftp-gateway-ftp-program-name
1896 ange-ftp-ftp-program-name)) 1897 ange-ftp-ftp-program-name))
1897 (args (append (list ftp-prog) ange-ftp-ftp-program-args)) 1898 (args (append (list ftp-prog) ange-ftp-ftp-program-args))
@@ -1987,7 +1988,7 @@ on the gateway machine to do the ftp instead."
1987(defun ange-ftp-smart-login (host user pass account proc) 1988(defun ange-ftp-smart-login (host user pass account proc)
1988 "Connect to the FTP-server on HOST as USER using PASSWORD and ACCOUNT. 1989 "Connect to the FTP-server on HOST as USER using PASSWORD and ACCOUNT.
1989PROC is the FTP-client's process. This routine uses the smart-gateway 1990PROC is the FTP-client's process. This routine uses the smart-gateway
1990host specified in ``ange-ftp-gateway-host''." 1991host specified in `ange-ftp-gateway-host'."
1991 (let ((result (ange-ftp-raw-send-cmd 1992 (let ((result (ange-ftp-raw-send-cmd
1992 proc 1993 proc
1993 (format "open %s %s" 1994 (format "open %s %s"
@@ -1997,7 +1998,7 @@ host specified in ``ange-ftp-gateway-host''."
1997 host 1998 host
1998 ange-ftp-gateway-host)))) 1999 ange-ftp-gateway-host))))
1999 (or (car result) 2000 (or (car result)
2000 (ange-ftp-error host user 2001 (ange-ftp-error host user
2001 (concat "OPEN request failed: " 2002 (concat "OPEN request failed: "
2002 (cdr result)))) 2003 (cdr result))))
2003 (setq result (ange-ftp-raw-send-cmd 2004 (setq result (ange-ftp-raw-send-cmd
@@ -2089,13 +2090,13 @@ Create a new process if needed."
2089 (ange-ftp-get-account host user)))) 2090 (ange-ftp-get-account host user))))
2090 ;; grab a suitable process. 2091 ;; grab a suitable process.
2091 (setq proc (ange-ftp-start-process host user name)) 2092 (setq proc (ange-ftp-start-process host user name))
2092 2093
2093 ;; login to FTP server. 2094 ;; login to FTP server.
2094 (if (and (ange-ftp-use-smart-gateway-p host) 2095 (if (and (ange-ftp-use-smart-gateway-p host)
2095 ange-ftp-gateway-host) 2096 ange-ftp-gateway-host)
2096 (ange-ftp-smart-login host user pass account proc) 2097 (ange-ftp-smart-login host user pass account proc)
2097 (ange-ftp-normal-login host user pass account proc)) 2098 (ange-ftp-normal-login host user pass account proc))
2098 2099
2099 ;; Tell client to send back hash-marks as progress. It isn't usually 2100 ;; Tell client to send back hash-marks as progress. It isn't usually
2100 ;; fatal if this command fails. 2101 ;; fatal if this command fails.
2101 (ange-ftp-guess-hash-mark-size proc) 2102 (ange-ftp-guess-hash-mark-size proc)
@@ -2187,7 +2188,7 @@ for a host of type TYPE.")
2187 "Find an ftp process connected to HOST logged in as USER and send it CMD. 2188 "Find an ftp process connected to HOST logged in as USER and send it CMD.
2188MSG is an optional status message to be output before and after issuing the 2189MSG is an optional status message to be output before and after issuing the
2189command. 2190command.
2190See the documentation for ange-ftp-raw-send-cmd for a description of CONT 2191See the documentation for `ange-ftp-raw-send-cmd' for a description of CONT
2191and NOWAIT." 2192and NOWAIT."
2192 ;; Handle conversion to remote file name syntax and remote ls option 2193 ;; Handle conversion to remote file name syntax and remote ls option
2193 ;; capability. 2194 ;; capability.
@@ -2199,10 +2200,10 @@ and NOWAIT."
2199 cmd2 cmd3 host-type fix-name-func) 2200 cmd2 cmd3 host-type fix-name-func)
2200 2201
2201 (cond 2202 (cond
2202 2203
2203 ;; pwd case (We don't care what host-type.) 2204 ;; pwd case (We don't care what host-type.)
2204 ((null cmd1)) 2205 ((null cmd1))
2205 2206
2206 ;; cmd == 'dir "remote-name" "local-name" "ls-switches" 2207 ;; cmd == 'dir "remote-name" "local-name" "ls-switches"
2207 ((progn 2208 ((progn
2208 (setq cmd2 (nth 2 cmd) 2209 (setq cmd2 (nth 2 cmd)
@@ -2233,7 +2234,7 @@ and NOWAIT."
2233 (or (memq host-type ange-ftp-dumb-host-types) 2234 (or (memq host-type ange-ftp-dumb-host-types)
2234 (setq cmd0 'ls 2235 (setq cmd0 'ls
2235 cmd1 (format "\"%s %s\"" cmd3 cmd1)))) 2236 cmd1 (format "\"%s %s\"" cmd3 cmd1))))
2236 2237
2237 ;; First argument is the remote name 2238 ;; First argument is the remote name
2238 ((progn 2239 ((progn
2239 (setq fix-name-func (or (cdr (assq host-type 2240 (setq fix-name-func (or (cdr (assq host-type
@@ -2250,8 +2251,8 @@ and NOWAIT."
2250 ((eq cmd0 'rename) 2251 ((eq cmd0 'rename)
2251 (setq cmd1 (funcall fix-name-func cmd1) 2252 (setq cmd1 (funcall fix-name-func cmd1)
2252 cmd2 (funcall fix-name-func cmd2)))) 2253 cmd2 (funcall fix-name-func cmd2))))
2253 2254
2254 ;; Turn the command into one long string 2255 ;; Turn the command into one long string
2255 (setq cmd0 (symbol-name cmd0)) 2256 (setq cmd0 (symbol-name cmd0))
2256 (setq cmd (concat cmd0 2257 (setq cmd (concat cmd0
2257 (and cmd1 (concat " " cmd1)) 2258 (and cmd1 (concat " " cmd1))
@@ -2264,27 +2265,21 @@ and NOWAIT."
2264 (ange-ftp-get-process host user) 2265 (ange-ftp-get-process host user)
2265 cmd 2266 cmd
2266 msg 2267 msg
2267 (list 2268 (list (lambda (result line host user cmd msg cont nowait)
2268 (function (lambda (result line host user 2269 (or cont (setq afsc-result result
2269 cmd msg cont nowait) 2270 afsc-line line))
2270 (or cont 2271 (if result (ange-ftp-call-cont cont result line)
2271 (setq afsc-result result 2272 (ange-ftp-raw-send-cmd
2272 afsc-line line)) 2273 (ange-ftp-get-process host user)
2273 (if result 2274 cmd
2274 (ange-ftp-call-cont cont result line) 2275 msg
2275 (ange-ftp-raw-send-cmd 2276 (list (lambda (result line cont)
2276 (ange-ftp-get-process host user) 2277 (or cont (setq afsc-result result
2277 cmd 2278 afsc-line line))
2278 msg 2279 (ange-ftp-call-cont cont result line))
2279 (list 2280 cont))
2280 (function (lambda (result line cont) 2281 nowait))
2281 (or cont 2282 host user cmd msg cont nowait)
2282 (setq afsc-result result
2283 afsc-line line))
2284 (ange-ftp-call-cont cont result line)))
2285 cont)
2286 nowait))))
2287 host user cmd msg cont nowait)
2288 nowait) 2283 nowait)
2289 2284
2290 (if nowait 2285 (if nowait
@@ -2324,7 +2319,7 @@ Works by doing a pwd and examining the directory syntax."
2324 (if (string-match 2319 (if (string-match
2325 "^450 No current working directory defined$" 2320 "^450 No current working directory defined$"
2326 (cdr result)) 2321 (cdr result))
2327 2322
2328 ;; We'll assume that if pwd bombs with this 2323 ;; We'll assume that if pwd bombs with this
2329 ;; error message, then it's CMS. 2324 ;; error message, then it's CMS.
2330 (progn 2325 (progn
@@ -2345,7 +2340,7 @@ Works by doing a pwd and examining the directory syntax."
2345 (ange-ftp-add-mts-host host) 2340 (ange-ftp-add-mts-host host)
2346 (setq ange-ftp-host-cache host 2341 (setq ange-ftp-host-cache host
2347 ange-ftp-host-type-cache 'mts)) 2342 ange-ftp-host-type-cache 'mts))
2348 2343
2349 ;; try for CMS 2344 ;; try for CMS
2350 ((string-match ange-ftp-cms-name-template dir) 2345 ((string-match ange-ftp-cms-name-template dir)
2351 (ange-ftp-add-cms-host host) 2346 (ange-ftp-add-cms-host host)
@@ -2413,10 +2408,10 @@ which can parse the output from a DIR listing for a host of type TYPE.")
2413 2408
2414;; With no-error nil, this function returns: 2409;; With no-error nil, this function returns:
2415;; an error if file is not an ange-ftp-name 2410;; an error if file is not an ange-ftp-name
2416;; (This should never happen.) 2411;; (This should never happen.)
2417;; an error if either the listing is unreadable or there is an ftp error. 2412;; an error if either the listing is unreadable or there is an ftp error.
2418;; the listing (a string), if everything works. 2413;; the listing (a string), if everything works.
2419;; 2414;;
2420;; With no-error t, it returns: 2415;; With no-error t, it returns:
2421;; an error if not an ange-ftp-name 2416;; an error if not an ange-ftp-name
2422;; error if listing is unreadable (most likely caused by a slow connection) 2417;; error if listing is unreadable (most likely caused by a slow connection)
@@ -2527,7 +2522,7 @@ away in the internal cache."
2527 ;; weiand: changed: month ends with . or , or ., 2522 ;; weiand: changed: month ends with . or , or .,
2528;;old (month (concat l l "+ *")) 2523;;old (month (concat l l "+ *"))
2529 (month (concat l l "+[.]?,? *")) 2524 (month (concat l l "+[.]?,? *"))
2530 ;; Recognize any non-ASCII character. 2525 ;; Recognize any non-ASCII character.
2531 ;; The purpose is to match a Kanji character. 2526 ;; The purpose is to match a Kanji character.
2532 (k "[^\0-\177]") 2527 (k "[^\0-\177]")
2533 (s " ") 2528 (s " ")
@@ -2577,16 +2572,16 @@ The main reason for this alist is to deal with file versions in VMS.")
2577 2572
2578(defmacro ange-ftp-parse-filename () 2573(defmacro ange-ftp-parse-filename ()
2579 ;;Extract the filename from the current line of a dired-like listing. 2574 ;;Extract the filename from the current line of a dired-like listing.
2580 (` (let ((eol (progn (end-of-line) (point)))) 2575 `(let ((eol (progn (end-of-line) (point))))
2581 (beginning-of-line) 2576 (beginning-of-line)
2582 (if (re-search-forward ange-ftp-date-regexp eol t) 2577 (if (re-search-forward ange-ftp-date-regexp eol t)
2583 (progn 2578 (progn
2584 (skip-chars-forward " ") 2579 (skip-chars-forward " ")
2585 (skip-chars-forward "^ " eol) 2580 (skip-chars-forward "^ " eol)
2586 (skip-chars-forward " " eol) 2581 (skip-chars-forward " " eol)
2587 ;; We bomb on filenames starting with a space. 2582 ;; We bomb on filenames starting with a space.
2588 (buffer-substring (point) eol)))))) 2583 (buffer-substring (point) eol)))))
2589 2584
2590;; This deals with the F switch. Should also do something about 2585;; This deals with the F switch. Should also do something about
2591;; unquoting names obtained with the SysV b switch and the GNU Q 2586;; unquoting names obtained with the SysV b switch and the GNU Q
2592;; switch. See Sebastian's dired-get-filename. 2587;; switch. See Sebastian's dired-get-filename.
@@ -2594,54 +2589,51 @@ The main reason for this alist is to deal with file versions in VMS.")
2594(defmacro ange-ftp-ls-parser () 2589(defmacro ange-ftp-ls-parser ()
2595 ;; Note that switches is dynamically bound. 2590 ;; Note that switches is dynamically bound.
2596 ;; Meant to be called by ange-ftp-parse-dired-listing 2591 ;; Meant to be called by ange-ftp-parse-dired-listing
2597 (` (let ((tbl (ange-ftp-make-hashtable)) 2592 `(let ((tbl (ange-ftp-make-hashtable))
2598 (used-F (and (stringp switches) 2593 (used-F (and (stringp switches)
2599 (string-match "F" switches))) 2594 (string-match "F" switches)))
2600 file-type symlink directory file) 2595 file-type symlink directory file)
2601 (while (setq file (ange-ftp-parse-filename)) 2596 (while (setq file (ange-ftp-parse-filename))
2602 (beginning-of-line) 2597 (beginning-of-line)
2603 (skip-chars-forward "\t 0-9") 2598 (skip-chars-forward "\t 0-9")
2604 (setq file-type (following-char) 2599 (setq file-type (following-char)
2605 directory (eq file-type ?d)) 2600 directory (eq file-type ?d))
2606 (if (eq file-type ?l) 2601 (if (eq file-type ?l)
2607 (if (string-match " -> " file) 2602 (if (string-match " -> " file)
2608 (setq symlink (substring file (match-end 0)) 2603 (setq symlink (substring file (match-end 0))
2609 file (substring file 0 (match-beginning 0))) 2604 file (substring file 0 (match-beginning 0)))
2610 ;; Shouldn't happen 2605 ;; Shouldn't happen
2611 (setq symlink "")) 2606 (setq symlink ""))
2612 (setq symlink nil)) 2607 (setq symlink nil))
2613 ;; Only do a costly regexp search if the F switch was used. 2608 ;; Only do a costly regexp search if the F switch was used.
2614 (if (and used-F 2609 (if (and used-F
2615 (not (string-equal file "")) 2610 (not (string-equal file ""))
2616 (looking-at 2611 (looking-at
2617 ".[-r][-w]\\([^ ]\\)[-r][-w]\\([^ ]\\)[-r][-w]\\([^ ]\\)")) 2612 ".[-r][-w]\\([^ ]\\)[-r][-w]\\([^ ]\\)[-r][-w]\\([^ ]\\)"))
2618 (let ((socket (eq file-type ?s)) 2613 (let ((socket (eq file-type ?s))
2619 (executable 2614 (executable
2620 (and (not symlink) ; x bits don't mean a thing for symlinks 2615 (and (not symlink) ; x bits don't mean a thing for symlinks
2621 (string-match "[xst]" 2616 (string-match
2622 (concat 2617 "[xst]"
2623 (buffer-substring 2618 (concat (buffer-substring
2624 (match-beginning 1) 2619 (match-beginning 1) (match-end 1))
2625 (match-end 1)) 2620 (buffer-substring
2626 (buffer-substring 2621 (match-beginning 2) (match-end 2))
2627 (match-beginning 2) 2622 (buffer-substring
2628 (match-end 2)) 2623 (match-beginning 3) (match-end 3)))))))
2629 (buffer-substring 2624 ;; Some ls's with the F switch mark symlinks with an @ (ULTRIX)
2630 (match-beginning 3) 2625 ;; and others don't. (sigh...) Beware, that some Unix's don't
2631 (match-end 3))))))) 2626 ;; seem to believe in the F-switch
2632 ;; Some ls's with the F switch mark symlinks with an @ (ULTRIX) 2627 (if (or (and symlink (string-match "@$" file))
2633 ;; and others don't. (sigh...) Beware, that some Unix's don't 2628 (and directory (string-match "/$" file))
2634 ;; seem to believe in the F-switch 2629 (and executable (string-match "*$" file))
2635 (if (or (and symlink (string-match "@$" file)) 2630 (and socket (string-match "=$" file)))
2636 (and directory (string-match "/$" file)) 2631 (setq file (substring file 0 -1)))))
2637 (and executable (string-match "*$" file)) 2632 (ange-ftp-put-hash-entry file (or symlink directory) tbl)
2638 (and socket (string-match "=$" file))) 2633 (forward-line 1))
2639 (setq file (substring file 0 -1))))) 2634 (ange-ftp-put-hash-entry "." t tbl)
2640 (ange-ftp-put-hash-entry file (or symlink directory) tbl) 2635 (ange-ftp-put-hash-entry ".." t tbl)
2641 (forward-line 1)) 2636 tbl))
2642 (ange-ftp-put-hash-entry "." t tbl)
2643 (ange-ftp-put-hash-entry ".." t tbl)
2644 tbl)))
2645 2637
2646;;; The dl stuff for descriptive listings 2638;;; The dl stuff for descriptive listings
2647 2639
@@ -2667,19 +2659,19 @@ match subdirectories as well.")
2667(defmacro ange-ftp-dl-parser () 2659(defmacro ange-ftp-dl-parser ()
2668 ;; Parse the current buffer, which is assumed to be a descriptive 2660 ;; Parse the current buffer, which is assumed to be a descriptive
2669 ;; listing, and return a hashtable. 2661 ;; listing, and return a hashtable.
2670 (` (let ((tbl (ange-ftp-make-hashtable))) 2662 `(let ((tbl (ange-ftp-make-hashtable)))
2671 (while (not (eobp)) 2663 (while (not (eobp))
2672 (ange-ftp-put-hash-entry 2664 (ange-ftp-put-hash-entry
2673 (buffer-substring (point) 2665 (buffer-substring (point)
2674 (progn 2666 (progn
2675 (skip-chars-forward "^ /\n") 2667 (skip-chars-forward "^ /\n")
2676 (point))) 2668 (point)))
2677 (eq (following-char) ?/) 2669 (eq (following-char) ?/)
2678 tbl) 2670 tbl)
2679 (forward-line 1)) 2671 (forward-line 1))
2680 (ange-ftp-put-hash-entry "." t tbl) 2672 (ange-ftp-put-hash-entry "." t tbl)
2681 (ange-ftp-put-hash-entry ".." t tbl) 2673 (ange-ftp-put-hash-entry ".." t tbl)
2682 tbl))) 2674 tbl))
2683 2675
2684;; Parse the current buffer which is assumed to be in a dired-like listing 2676;; Parse the current buffer which is assumed to be in a dired-like listing
2685;; format, and return a hashtable as the result. If the listing is not really 2677;; format, and return a hashtable as the result. If the listing is not really
@@ -2762,10 +2754,10 @@ NO-ERROR, if a listing for DIRECTORY cannot be obtained."
2762;; Given NAME, return the file part that can be used for looking up the 2754;; Given NAME, return the file part that can be used for looking up the
2763;; file's entry in a hashtable. 2755;; file's entry in a hashtable.
2764(defmacro ange-ftp-get-file-part (name) 2756(defmacro ange-ftp-get-file-part (name)
2765 (` (let ((file (file-name-nondirectory (, name)))) 2757 `(let ((file (file-name-nondirectory ,name)))
2766 (if (string-equal file "") 2758 (if (string-equal file "")
2767 "." 2759 "."
2768 file)))) 2760 file)))
2769 2761
2770;; Return whether ange-ftp-file-entry-p and ange-ftp-get-file-entry are 2762;; Return whether ange-ftp-file-entry-p and ange-ftp-get-file-entry are
2771;; allowed to determine if NAME is a sub-directory by listing it directly, 2763;; allowed to determine if NAME is a sub-directory by listing it directly,
@@ -2776,23 +2768,23 @@ NO-ERROR, if a listing for DIRECTORY cannot be obtained."
2776;; subdirectory. This is of course an OS dependent judgement. 2768;; subdirectory. This is of course an OS dependent judgement.
2777 2769
2778(defmacro ange-ftp-allow-child-lookup (dir file) 2770(defmacro ange-ftp-allow-child-lookup (dir file)
2779 (` (not 2771 `(not
2780 (let* ((efile (, file)) ; expand once. 2772 (let* ((efile ,file) ; expand once.
2781 (edir (, dir)) 2773 (edir ,dir)
2782 (parsed (ange-ftp-ftp-name edir)) 2774 (parsed (ange-ftp-ftp-name edir))
2783 (host-type (ange-ftp-host-type 2775 (host-type (ange-ftp-host-type
2784 (car parsed)))) 2776 (car parsed))))
2785 (or 2777 (or
2786 ;; Deal with dired 2778 ;; Deal with dired
2787 (and (boundp 'dired-local-variables-file) ; in the dired-x package 2779 (and (boundp 'dired-local-variables-file) ; in the dired-x package
2788 (stringp dired-local-variables-file) 2780 (stringp dired-local-variables-file)
2789 (string-equal dired-local-variables-file efile)) 2781 (string-equal dired-local-variables-file efile))
2790 ;; No dots in dir names in vms. 2782 ;; No dots in dir names in vms.
2791 (and (eq host-type 'vms) 2783 (and (eq host-type 'vms)
2792 (string-match "\\." efile)) 2784 (string-match "\\." efile))
2793 ;; No subdirs in mts of cms. 2785 ;; No subdirs in mts of cms.
2794 (and (memq host-type '(mts cms)) 2786 (and (memq host-type '(mts cms))
2795 (not (string-equal "/" (nth 2 parsed))))))))) 2787 (not (string-equal "/" (nth 2 parsed))))))))
2796 2788
2797(defun ange-ftp-file-entry-p (name) 2789(defun ange-ftp-file-entry-p (name)
2798 "Given NAME, return whether there is a file entry for it." 2790 "Given NAME, return whether there is a file entry for it."
@@ -2840,7 +2832,7 @@ this also returns nil."
2840 2832
2841(defun ange-ftp-internal-delete-file-entry (name &optional dir-p) 2833(defun ange-ftp-internal-delete-file-entry (name &optional dir-p)
2842 (if dir-p 2834 (if dir-p
2843 (progn 2835 (progn
2844 (setq name (file-name-as-directory name)) 2836 (setq name (file-name-as-directory name))
2845 (ange-ftp-del-hash-entry name ange-ftp-files-hashtable) 2837 (ange-ftp-del-hash-entry name ange-ftp-files-hashtable)
2846 (setq name (directory-file-name name)))) 2838 (setq name (directory-file-name name))))
@@ -2867,14 +2859,13 @@ this also returns nil."
2867 "Get rid of entry for HOST, USER pair from file entry information hashtable." 2859 "Get rid of entry for HOST, USER pair from file entry information hashtable."
2868 (let ((new-tbl (ange-ftp-make-hashtable (length ange-ftp-files-hashtable)))) 2860 (let ((new-tbl (ange-ftp-make-hashtable (length ange-ftp-files-hashtable))))
2869 (ange-ftp-map-hashtable 2861 (ange-ftp-map-hashtable
2870 (function 2862 (lambda (key val)
2871 (lambda (key val) 2863 (let ((parsed (ange-ftp-ftp-name key)))
2872 (let ((parsed (ange-ftp-ftp-name key))) 2864 (if parsed
2873 (if parsed 2865 (let ((h (nth 0 parsed))
2874 (let ((h (nth 0 parsed)) 2866 (u (nth 1 parsed)))
2875 (u (nth 1 parsed))) 2867 (or (and (equal host h) (equal user u))
2876 (or (and (equal host h) (equal user u)) 2868 (ange-ftp-put-hash-entry key val new-tbl))))))
2877 (ange-ftp-put-hash-entry key val new-tbl)))))))
2878 ange-ftp-files-hashtable) 2869 ange-ftp-files-hashtable)
2879 (setq ange-ftp-files-hashtable new-tbl))) 2870 (setq ange-ftp-files-hashtable new-tbl)))
2880 2871
@@ -2956,7 +2947,7 @@ logged in as user USER and cd'd to directory DIR."
2956 (line (cdr result))) 2947 (line (cdr result)))
2957 (setq res 2948 (setq res
2958 (if (string-match ange-ftp-expand-dir-regexp line) 2949 (if (string-match ange-ftp-expand-dir-regexp line)
2959 (substring line 2950 (substring line
2960 (match-beginning 1) 2951 (match-beginning 1)
2961 (match-end 1)))))) 2952 (match-end 1))))))
2962 (or res 2953 (or res
@@ -2985,25 +2976,25 @@ logged in as user USER and cd'd to directory DIR."
2985 (let ((host (car parsed)) 2976 (let ((host (car parsed))
2986 (user (nth 1 parsed)) 2977 (user (nth 1 parsed))
2987 (name (nth 2 parsed))) 2978 (name (nth 2 parsed)))
2988 2979
2989 ;; See if remote name is absolute. If so then just expand it and 2980 ;; See if remote name is absolute. If so then just expand it and
2990 ;; replace the name component of the overall name. 2981 ;; replace the name component of the overall name.
2991 (cond ((string-match "^/" name) 2982 (cond ((string-match "^/" name)
2992 name) 2983 name)
2993 2984
2994 ;; Name starts with ~ or ~user. Resolve that part of the name 2985 ;; Name starts with ~ or ~user. Resolve that part of the name
2995 ;; making it absolute then re-expand it. 2986 ;; making it absolute then re-expand it.
2996 ((string-match "^~[^/]*" name) 2987 ((string-match "^~[^/]*" name)
2997 (let* ((tilda (substring name 2988 (let* ((tilda (substring name
2998 (match-beginning 0) 2989 (match-beginning 0)
2999 (match-end 0))) 2990 (match-end 0)))
3000 (rest (substring name (match-end 0))) 2991 (rest (substring name (match-end 0)))
3001 (dir (ange-ftp-expand-dir host user tilda))) 2992 (dir (ange-ftp-expand-dir host user tilda)))
3002 (if dir 2993 (if dir
3003 (setq name (concat dir rest)) 2994 (setq name (concat dir rest))
3004 (error "User \"%s\" is not known" 2995 (error "User \"%s\" is not known"
3005 (substring tilda 1))))) 2996 (substring tilda 1)))))
3006 2997
3007 ;; relative name. Tack on homedir and re-expand. 2998 ;; relative name. Tack on homedir and re-expand.
3008 (t 2999 (t
3009 (let ((dir (ange-ftp-expand-dir host user "~"))) 3000 (let ((dir (ange-ftp-expand-dir host user "~")))
@@ -3012,7 +3003,7 @@ logged in as user USER and cd'd to directory DIR."
3012 (ange-ftp-real-file-name-as-directory dir) 3003 (ange-ftp-real-file-name-as-directory dir)
3013 name)) 3004 name))
3014 (error "Unable to obtain CWD"))))) 3005 (error "Unable to obtain CWD")))))
3015 3006
3016 ;; If name starts with //, preserve that, for apollo system. 3007 ;; If name starts with //, preserve that, for apollo system.
3017 (if (not (string-match "^//" name)) 3008 (if (not (string-match "^//" name))
3018 (progn 3009 (progn
@@ -3027,10 +3018,10 @@ logged in as user USER and cd'd to directory DIR."
3027 (setq name (substring name 2)))) 3018 (setq name (substring name 2))))
3028 (if (string-match "^//" name) 3019 (if (string-match "^//" name)
3029 (setq name (substring name 1))))) 3020 (setq name (substring name 1)))))
3030 3021
3031 ;; Now substitute the expanded name back into the overall filename. 3022 ;; Now substitute the expanded name back into the overall filename.
3032 (ange-ftp-replace-name-component n name)) 3023 (ange-ftp-replace-name-component n name))
3033 3024
3034 ;; non-ange-ftp name. Just expand normally. 3025 ;; non-ange-ftp name. Just expand normally.
3035 (if (eq (string-to-char n) ?/) 3026 (if (eq (string-to-char n) ?/)
3036 (ange-ftp-real-expand-file-name n) 3027 (ange-ftp-real-expand-file-name n)
@@ -3077,7 +3068,7 @@ system TYPE.")
3077 'ange-ftp-real-file-name-as-directory) 3068 'ange-ftp-real-file-name-as-directory)
3078 name)) 3069 name))
3079 (ange-ftp-real-file-name-as-directory name)))) 3070 (ange-ftp-real-file-name-as-directory name))))
3080 3071
3081(defun ange-ftp-file-name-directory (name) 3072(defun ange-ftp-file-name-directory (name)
3082 "Documented as original." 3073 "Documented as original."
3083 (let ((parsed (ange-ftp-ftp-name name))) 3074 (let ((parsed (ange-ftp-ftp-name name)))
@@ -3171,11 +3162,11 @@ system TYPE.")
3171 (format "FTP Error: \"%s\"" (cdr result)) 3162 (format "FTP Error: \"%s\"" (cdr result))
3172 filename))))) 3163 filename)))))
3173 (ange-ftp-del-tmp-name temp) 3164 (ange-ftp-del-tmp-name temp)
3174 (if binary 3165 (if binary
3175 (ange-ftp-set-ascii-mode host user))) 3166 (ange-ftp-set-ascii-mode host user)))
3176 (if (eq visit t) 3167 (if (eq visit t)
3177 (progn 3168 (progn
3178 (set-visited-file-modtime '(0 0)) 3169 (set-visited-file-modtime (ange-ftp-file-modtime filename))
3179 (ange-ftp-set-buffer-mode) 3170 (ange-ftp-set-buffer-mode)
3180 (setq buffer-file-name filename) 3171 (setq buffer-file-name filename)
3181 (set-buffer-modified-p nil))) 3172 (set-buffer-modified-p nil)))
@@ -3248,16 +3239,17 @@ system TYPE.")
3248 (ange-ftp-del-tmp-name temp)) 3239 (ange-ftp-del-tmp-name temp))
3249 (if visit 3240 (if visit
3250 (progn 3241 (progn
3251 (set-visited-file-modtime '(0 0)) 3242 (set-visited-file-modtime
3243 (ange-ftp-file-modtime filename))
3252 (setq buffer-file-name filename))) 3244 (setq buffer-file-name filename)))
3253 (setq last-coding-system-used coding-system-used) 3245 (setq last-coding-system-used coding-system-used)
3254 (list filename size)) 3246 (list filename size))
3255 (signal 'file-error 3247 (signal 'file-error
3256 (list 3248 (list
3257 "Opening input file" 3249 "Opening input file"
3258 filename)))) 3250 filename))))
3259 (ange-ftp-real-insert-file-contents filename visit beg end replace)))) 3251 (ange-ftp-real-insert-file-contents filename visit beg end replace))))
3260 3252
3261(defun ange-ftp-expand-symlink (file dir) 3253(defun ange-ftp-expand-symlink (file dir)
3262 (if (file-name-absolute-p file) 3254 (if (file-name-absolute-p file)
3263 (ange-ftp-replace-name-component dir file) 3255 (ange-ftp-replace-name-component dir file)
@@ -3354,7 +3346,7 @@ system TYPE.")
3354 -1 ;2 uid 3346 -1 ;2 uid
3355 -1 ;3 gid 3347 -1 ;3 gid
3356 '(0 0) ;4 atime 3348 '(0 0) ;4 atime
3357 '(0 0) ;5 mtime 3349 (ange-ftp-file-modtime file) ;5 mtime
3358 '(0 0) ;6 ctime 3350 '(0 0) ;6 ctime
3359 -1 ;7 size 3351 -1 ;7 size
3360 (concat (if (stringp dirp) "l" (if dirp "d" "-")) 3352 (concat (if (stringp dirp) "l" (if dirp "d" "-"))
@@ -3405,10 +3397,29 @@ system TYPE.")
3405 (ange-ftp-delete-file-entry file)) 3397 (ange-ftp-delete-file-entry file))
3406 (ange-ftp-real-delete-file file)))) 3398 (ange-ftp-real-delete-file file))))
3407 3399
3400(defun ange-ftp-file-modtime (file)
3401 (let* ((parsed (ange-ftp-ftp-name file))
3402 (res (ange-ftp-send-cmd (car parsed) (cadr parsed)
3403 (list 'quote "mdtm" (caddr parsed)))))
3404 (if (= ?5 (aref (cdr res) 0)) '(0 0)
3405 (encode-time ; MDTM returns "YYYYMMDDHHMMSS" GMT
3406 (string-to-number (substring (cdr res) 16 18))
3407 (string-to-number (substring (cdr res) 14 16))
3408 (string-to-number (substring (cdr res) 12 14))
3409 (string-to-number (substring (cdr res) 10 12))
3410 (string-to-number (substring (cdr res) 8 10))
3411 (string-to-number (substring (cdr res) 4 8))
3412 0))))
3413
3408(defun ange-ftp-verify-visited-file-modtime (buf) 3414(defun ange-ftp-verify-visited-file-modtime (buf)
3409 (let ((name (buffer-file-name buf))) 3415 (let ((name (buffer-file-name buf)))
3410 (if (and (stringp name) (ange-ftp-ftp-name name)) 3416 (if (and (stringp name) (ange-ftp-ftp-name name))
3411 t 3417 (let ((file-mdtm (ange-ftp-file-modtime name))
3418 (buf-mdtm (with-current-buffer buf (visited-file-modtime))))
3419 (or (zerop (car file-mdtm))
3420 (< (car file-mdtm) (car buf-mdtm))
3421 (and (= (car file-mdtm) (car buf-mdtm))
3422 (< (cadr file-mdtm) (cdr buf-mdtm)))))
3412 (ange-ftp-real-verify-visited-file-modtime buf)))) 3423 (ange-ftp-real-verify-visited-file-modtime buf))))
3413 3424
3414;;;; ------------------------------------------------------------ 3425;;;; ------------------------------------------------------------
@@ -3433,7 +3444,7 @@ system TYPE.")
3433;; ;; check to see if we can overwrite 3444;; ;; check to see if we can overwrite
3434;; (if (or (not ok-if-already-exists) 3445;; (if (or (not ok-if-already-exists)
3435;; (numberp ok-if-already-exists)) 3446;; (numberp ok-if-already-exists))
3436;; (ange-ftp-barf-or-query-if-file-exists newname "copy to it" 3447;; (ange-ftp-barf-or-query-if-file-exists newname "copy to it"
3437;; (numberp ok-if-already-exists))) 3448;; (numberp ok-if-already-exists)))
3438;; (let ((proc (start-process " *copy*" 3449;; (let ((proc (start-process " *copy*"
3439;; (generate-new-buffer "*copy*") 3450;; (generate-new-buffer "*copy*")
@@ -3447,7 +3458,7 @@ system TYPE.")
3447;; (set-buffer (process-buffer proc)) 3458;; (set-buffer (process-buffer proc))
3448;; (make-variable-buffer-local 'copy-cont) 3459;; (make-variable-buffer-local 'copy-cont)
3449;; (setq copy-cont cont)))) 3460;; (setq copy-cont cont))))
3450;; 3461;;
3451;; (defun ange-ftp-copy-file-locally-sentinel (proc status) 3462;; (defun ange-ftp-copy-file-locally-sentinel (proc status)
3452;; (save-excursion 3463;; (save-excursion
3453;; (set-buffer (process-buffer proc)) 3464;; (set-buffer (process-buffer proc))
@@ -3506,12 +3517,12 @@ system TYPE.")
3506 ;; check to see if we can overwrite 3517 ;; check to see if we can overwrite
3507 (if (or (not ok-if-already-exists) 3518 (if (or (not ok-if-already-exists)
3508 (numberp ok-if-already-exists)) 3519 (numberp ok-if-already-exists))
3509 (ange-ftp-barf-or-query-if-file-exists newname "copy to it" 3520 (ange-ftp-barf-or-query-if-file-exists newname "copy to it"
3510 (numberp ok-if-already-exists))) 3521 (numberp ok-if-already-exists)))
3511 3522
3512 ;; do the copying. 3523 ;; do the copying.
3513 (if f-parsed 3524 (if f-parsed
3514 3525
3515 ;; filename was remote. 3526 ;; filename was remote.
3516 (progn 3527 (progn
3517 (if (or (ange-ftp-use-gateway-p f-host) 3528 (if (or (ange-ftp-use-gateway-p f-host)
@@ -3519,7 +3530,7 @@ system TYPE.")
3519 ;; have to use intermediate file if we are getting via 3530 ;; have to use intermediate file if we are getting via
3520 ;; gateway machine or we are doing a remote to remote copy. 3531 ;; gateway machine or we are doing a remote to remote copy.
3521 (setq temp1 (ange-ftp-make-tmp-name f-host))) 3532 (setq temp1 (ange-ftp-make-tmp-name f-host)))
3522 3533
3523 (if binary 3534 (if binary
3524 (ange-ftp-set-binary-mode f-host f-user)) 3535 (ange-ftp-set-binary-mode f-host f-user))
3525 3536
@@ -3575,12 +3586,12 @@ system TYPE.")
3575 (if result 3586 (if result
3576 ;; We now have to copy either temp1 or filename to newname. 3587 ;; We now have to copy either temp1 or filename to newname.
3577 (if t-parsed 3588 (if t-parsed
3578 3589
3579 ;; newname was remote. 3590 ;; newname was remote.
3580 (progn 3591 (progn
3581 (if (ange-ftp-use-gateway-p t-host) 3592 (if (ange-ftp-use-gateway-p t-host)
3582 (setq temp2 (ange-ftp-make-tmp-name t-host))) 3593 (setq temp2 (ange-ftp-make-tmp-name t-host)))
3583 3594
3584 ;; make sure data is moved into the right place for the 3595 ;; make sure data is moved into the right place for the
3585 ;; outgoing transfer. gateway temporary files complicate 3596 ;; outgoing transfer. gateway temporary files complicate
3586 ;; things nicely. 3597 ;; things nicely.
@@ -3592,7 +3603,7 @@ system TYPE.")
3592 (setq temp2 temp1 temp1 nil)) 3603 (setq temp2 temp1 temp1 nil))
3593 (if temp2 3604 (if temp2
3594 (ange-ftp-real-copy-file filename temp2 t))) 3605 (ange-ftp-real-copy-file filename temp2 t)))
3595 3606
3596 (if binary 3607 (if binary
3597 (ange-ftp-set-binary-mode t-host t-user)) 3608 (ange-ftp-set-binary-mode t-host t-user))
3598 3609
@@ -3612,7 +3623,7 @@ system TYPE.")
3612 (list (function ange-ftp-cf2) 3623 (list (function ange-ftp-cf2)
3613 newname t-host t-user binary temp1 temp2 cont) 3624 newname t-host t-user binary temp1 temp2 cont)
3614 nowait)) 3625 nowait))
3615 3626
3616 ;; newname wasn't remote. 3627 ;; newname wasn't remote.
3617 (ange-ftp-cf2 t nil newname t-host t-user binary temp1 temp2 cont)) 3628 (ange-ftp-cf2 t nil newname t-host t-user binary temp1 temp2 cont))
3618 3629
@@ -3634,17 +3645,17 @@ system TYPE.")
3634 (list "Opening output file" 3645 (list "Opening output file"
3635 (format "FTP Error: \"%s\"" line) 3646 (format "FTP Error: \"%s\"" line)
3636 newname))))) 3647 newname)))))
3637 3648
3638 (ange-ftp-add-file-entry newname)) 3649 (ange-ftp-add-file-entry newname))
3639 3650
3640 ;; cleanup. 3651 ;; cleanup.
3641 (if binary 3652 (if binary
3642 (ange-ftp-set-ascii-mode t-host t-user))) 3653 (ange-ftp-set-ascii-mode t-host t-user)))
3643 3654
3644 ;; newname was local. 3655 ;; newname was local.
3645 (if temp1 3656 (if temp1
3646 (ange-ftp-real-copy-file temp1 newname t))) 3657 (ange-ftp-real-copy-file temp1 newname t)))
3647 3658
3648 ;; clean up 3659 ;; clean up
3649 (and temp1 (ange-ftp-del-tmp-name temp1)) 3660 (and temp1 (ange-ftp-del-tmp-name temp1))
3650 (and temp2 (ange-ftp-del-tmp-name temp2)) 3661 (and temp2 (ange-ftp-del-tmp-name temp2))
@@ -3776,16 +3787,15 @@ system TYPE.")
3776 3787
3777 ;; see whether each matching file is a directory or not... 3788 ;; see whether each matching file is a directory or not...
3778 (mapcar 3789 (mapcar
3779 (function 3790 (lambda (file)
3780 (lambda (file) 3791 (let ((ent (ange-ftp-get-hash-entry file tbl)))
3781 (let ((ent (ange-ftp-get-hash-entry file tbl))) 3792 (if (and ent
3782 (if (and ent 3793 (or (not (stringp ent))
3783 (or (not (stringp ent)) 3794 (file-directory-p
3784 (file-directory-p 3795 (ange-ftp-expand-symlink ent
3785 (ange-ftp-expand-symlink ent 3796 ange-ftp-this-dir))))
3786 ange-ftp-this-dir)))) 3797 (concat file "/")
3787 (concat file "/") 3798 file)))
3788 file))))
3789 completions))) 3799 completions)))
3790 3800
3791 (if (or (and (eq system-type 'windows-nt) 3801 (if (or (and (eq system-type 'windows-nt)
@@ -3807,10 +3817,9 @@ system TYPE.")
3807 (ange-ftp-real-file-name-as-directory ange-ftp-this-dir)) ;real? 3817 (ange-ftp-real-file-name-as-directory ange-ftp-this-dir)) ;real?
3808 (let* ((tbl (ange-ftp-get-files ange-ftp-this-dir)) 3818 (let* ((tbl (ange-ftp-get-files ange-ftp-this-dir))
3809 (ange-ftp-completion-ignored-pattern 3819 (ange-ftp-completion-ignored-pattern
3810 (mapconcat (function 3820 (mapconcat (lambda (s) (if (stringp s)
3811 (lambda (s) (if (stringp s) 3821 (concat (regexp-quote s) "$")
3812 (concat (regexp-quote s) "$") 3822 "/")) ; / never in filename
3813 "/"))) ; / never in filename
3814 completion-ignored-extensions 3823 completion-ignored-extensions
3815 "\\|"))) 3824 "\\|")))
3816 (save-match-data 3825 (save-match-data
@@ -3988,7 +3997,7 @@ directory, so that Emacs will know its current contents."
3988Each element has the form (TYPE . FUNC). 3997Each element has the form (TYPE . FUNC).
3989FUNC should take one argument, a file name, and return a list 3998FUNC should take one argument, a file name, and return a list
3990of the form (COMPRESSING NEWNAME). 3999of the form (COMPRESSING NEWNAME).
3991COMPRESSING should be t if the specified file should be compressed, 4000COMPRESSING should be t if the specified file should be compressed,
3992and nil if it should be uncompressed (that is, if it is a compressed file). 4001and nil if it should be uncompressed (that is, if it is a compressed file).
3993NEWNAME should be the name to give the new compressed or uncompressed file.") 4002NEWNAME should be the name to give the new compressed or uncompressed file.")
3994 4003
@@ -4040,7 +4049,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4040 (ange-ftp-copy-file-internal tmp2 nfile t nil msg2)))) 4049 (ange-ftp-copy-file-internal tmp2 nfile t nil msg2))))
4041 (ange-ftp-del-tmp-name tmp1) 4050 (ange-ftp-del-tmp-name tmp1)
4042 (ange-ftp-del-tmp-name tmp2)))) 4051 (ange-ftp-del-tmp-name tmp2))))
4043 4052
4044;; Copy FILE to this machine, uncompress it, and copy out to NFILE. 4053;; Copy FILE to this machine, uncompress it, and copy out to NFILE.
4045(defun ange-ftp-uncompress (file nfile) 4054(defun ange-ftp-uncompress (file nfile)
4046 (let* ((parsed (ange-ftp-ftp-name file)) 4055 (let* ((parsed (ange-ftp-ftp-name file))
@@ -4117,14 +4126,14 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4117(and (memq system-type '(ms-dos windows-nt)) 4126(and (memq system-type '(ms-dos windows-nt))
4118 (or (assoc "^[a-zA-Z]:/[^/:]*\\'" file-name-handler-alist) 4127 (or (assoc "^[a-zA-Z]:/[^/:]*\\'" file-name-handler-alist)
4119 (setq file-name-handler-alist 4128 (setq file-name-handler-alist
4120 (cons '("^[a-zA-Z]:/[^/:]*\\'" . 4129 (cons '("^[a-zA-Z]:/[^/:]*\\'" .
4121 ange-ftp-completion-hook-function) 4130 ange-ftp-completion-hook-function)
4122 file-name-handler-alist)))) 4131 file-name-handler-alist))))
4123 4132
4124;;; The above two forms are sufficient to cause this file to be loaded 4133;;; The above two forms are sufficient to cause this file to be loaded
4125;;; if the user ever uses a file name with a colon in it. 4134;;; if the user ever uses a file name with a colon in it.
4126 4135
4127;;; This sets the mode 4136;;; This sets the mode
4128(or (memq 'ange-ftp-set-buffer-mode find-file-hooks) 4137(or (memq 'ange-ftp-set-buffer-mode find-file-hooks)
4129 (setq find-file-hooks 4138 (setq find-file-hooks
4130 (cons 'ange-ftp-set-buffer-mode find-file-hooks))) 4139 (cons 'ange-ftp-set-buffer-mode find-file-hooks)))
@@ -4254,7 +4263,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4254;; Here we support using dired on remote hosts. 4263;; Here we support using dired on remote hosts.
4255;; I have turned off the support for using dired on foreign directory formats. 4264;; I have turned off the support for using dired on foreign directory formats.
4256;; That involves too many unclean hooks. 4265;; That involves too many unclean hooks.
4257;; It would be cleaner to support such operations by 4266;; It would be cleaner to support such operations by
4258;; converting the foreign directory format to something dired can understand; 4267;; converting the foreign directory format to something dired can understand;
4259;; something close to ls -l output. 4268;; something close to ls -l output.
4260;; The logical place to do this is in the functions ange-ftp-parse-...-listing. 4269;; The logical place to do this is in the functions ange-ftp-parse-...-listing.
@@ -4335,7 +4344,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4335 1)) 4344 1))
4336 (apply 'call-process program nil (not discard) nil arguments))) 4345 (apply 'call-process program nil (not discard) nil arguments)))
4337 4346
4338(defvar ange-ftp-remote-shell "rsh" 4347(defvar ange-ftp-remote-shell "rsh"
4339 "Remote shell to use for chmod, if FTP server rejects the `chmod' command.") 4348 "Remote shell to use for chmod, if FTP server rejects the `chmod' command.")
4340 4349
4341;; Handle an attempt to run chmod on a remote file 4350;; Handle an attempt to run chmod on a remote file
@@ -4348,23 +4357,22 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4348 (if (equal "--" (car rest)) 4357 (if (equal "--" (car rest))
4349 (setq rest (cdr rest))) 4358 (setq rest (cdr rest)))
4350 (mapcar 4359 (mapcar
4351 (function 4360 (lambda (file)
4352 (lambda (file) 4361 (setq file (expand-file-name file))
4353 (setq file (expand-file-name file)) 4362 (let ((parsed (ange-ftp-ftp-name file)))
4354 (let ((parsed (ange-ftp-ftp-name file))) 4363 (if parsed
4355 (if parsed 4364 (let* ((host (nth 0 parsed))
4356 (let* ((host (nth 0 parsed)) 4365 (user (nth 1 parsed))
4357 (user (nth 1 parsed)) 4366 (name (ange-ftp-quote-string (nth 2 parsed)))
4358 (name (ange-ftp-quote-string (nth 2 parsed))) 4367 (abbr (ange-ftp-abbreviate-filename file))
4359 (abbr (ange-ftp-abbreviate-filename file)) 4368 (result (ange-ftp-send-cmd host user
4360 (result (ange-ftp-send-cmd host user 4369 (list 'chmod mode name)
4361 (list 'chmod mode name) 4370 (format "doing chmod %s"
4362 (format "doing chmod %s" 4371 abbr))))
4363 abbr)))) 4372 (or (car result)
4364 (or (car result) 4373 (call-process
4365 (call-process 4374 ange-ftp-remote-shell
4366 ange-ftp-remote-shell 4375 nil t nil host dired-chmod-program mode name))))))
4367 nil t nil host dired-chmod-program mode name)))))))
4368 rest)) 4376 rest))
4369 (setq ange-ftp-ls-cache-file nil) ;Stop confusing Dired. 4377 (setq ange-ftp-ls-cache-file nil) ;Stop confusing Dired.
4370 0) 4378 0)
@@ -4430,7 +4438,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4430;; name-constructor marker-char))) 4438;; name-constructor marker-char)))
4431 4439
4432;;(defun ange-ftp-dcf-1 (file-creator operation fn-list name-constructor 4440;;(defun ange-ftp-dcf-1 (file-creator operation fn-list name-constructor
4433;; target marker-char buffer overwrite-query 4441;; target marker-char buffer overwrite-query
4434;; overwrite-backup-query failures skipped 4442;; overwrite-backup-query failures skipped
4435;; success-count total) 4443;; success-count total)
4436;; (let ((old-buf (current-buffer))) 4444;; (let ((old-buf (current-buffer)))
@@ -4440,7 +4448,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4440;; (if (null fn-list) 4448;; (if (null fn-list)
4441;; (ange-ftp-dcf-3 failures operation total skipped 4449;; (ange-ftp-dcf-3 failures operation total skipped
4442;; success-count buffer) 4450;; success-count buffer)
4443 4451
4444;; (let* ((from (car fn-list)) 4452;; (let* ((from (car fn-list))
4445;; (to (funcall name-constructor from))) 4453;; (to (funcall name-constructor from)))
4446;; (if (equal to from) 4454;; (if (equal to from)
@@ -4489,7 +4497,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4489;; buffer to from 4497;; buffer to from
4490;; overwrite 4498;; overwrite
4491;; overwrite-confirmed 4499;; overwrite-confirmed
4492;; overwrite-query 4500;; overwrite-query
4493;; overwrite-backup-query 4501;; overwrite-backup-query
4494;; failures skipped success-count 4502;; failures skipped success-count
4495;; total) 4503;; total)
@@ -4505,7 +4513,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4505;; buffer to from 4513;; buffer to from
4506;; overwrite 4514;; overwrite
4507;; overwrite-confirmed 4515;; overwrite-confirmed
4508;; overwrite-query 4516;; overwrite-query
4509;; overwrite-backup-query 4517;; overwrite-backup-query
4510;; failures skipped success-count 4518;; failures skipped success-count
4511;; total)))))))) 4519;; total))))))))
@@ -4519,7 +4527,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4519;; buffer to from 4527;; buffer to from
4520;; overwrite 4528;; overwrite
4521;; overwrite-confirmed 4529;; overwrite-confirmed
4522;; overwrite-query 4530;; overwrite-query
4523;; overwrite-backup-query 4531;; overwrite-backup-query
4524;; failures skipped success-count 4532;; failures skipped success-count
4525;; total) 4533;; total)
@@ -4540,13 +4548,13 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4540;; (setq success-count (1+ success-count)) 4548;; (setq success-count (1+ success-count))
4541;; (message "%s: %d of %d" operation success-count total) 4549;; (message "%s: %d of %d" operation success-count total)
4542;; (dired-add-file to actual-marker-char)) 4550;; (dired-add-file to actual-marker-char))
4543 4551
4544;; (ange-ftp-dcf-1 file-creator operation (cdr fn-list) 4552;; (ange-ftp-dcf-1 file-creator operation (cdr fn-list)
4545;; name-constructor 4553;; name-constructor
4546;; target 4554;; target
4547;; marker-char 4555;; marker-char
4548;; buffer 4556;; buffer
4549;; overwrite-query 4557;; overwrite-query
4550;; overwrite-backup-query 4558;; overwrite-backup-query
4551;; failures skipped success-count 4559;; failures skipped success-count
4552;; total)) 4560;; total))
@@ -4719,6 +4727,13 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4719;;;; VMS support. 4727;;;; VMS support.
4720;;;; ------------------------------------------------------------ 4728;;;; ------------------------------------------------------------
4721 4729
4730(defun ange-ftp-dot-to-slash (string)
4731 (mapconcat (lambda (char)
4732 (if (= char ?.)
4733 (vector ?/)
4734 (vector char)))
4735 string ""))
4736
4722;; Convert NAME from UNIX-ish to VMS. If REVERSE given then convert from VMS 4737;; Convert NAME from UNIX-ish to VMS. If REVERSE given then convert from VMS
4723;; to UNIX-ish. 4738;; to UNIX-ish.
4724(defun ange-ftp-fix-name-for-vms (name &optional reverse) 4739(defun ange-ftp-fix-name-for-vms (name &optional reverse)
@@ -4737,13 +4752,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4737 (setq file 4752 (setq file
4738 (substring name (match-beginning 3) (match-end 3)))) 4753 (substring name (match-beginning 3) (match-end 3))))
4739 (and dir 4754 (and dir
4740 (setq dir (apply (function concat) 4755 (setq dir (ange-ftp-dot-to-slash (substring dir 1 -1))))
4741 (mapcar (function
4742 (lambda (char)
4743 (if (= char ?.)
4744 (vector ?/)
4745 (vector char))))
4746 (substring dir 1 -1)))))
4747 (concat (and drive 4756 (concat (and drive
4748 (concat "/" drive "/")) 4757 (concat "/" drive "/"))
4749 dir (and dir "/") 4758 dir (and dir "/")
@@ -4756,13 +4765,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4756 name (substring name (match-end 0)))) 4765 name (substring name (match-end 0))))
4757 (setq tmp (file-name-directory name)) 4766 (setq tmp (file-name-directory name))
4758 (if tmp 4767 (if tmp
4759 (setq dir (apply (function concat) 4768 (setq dir (ange-ftp-dot-to-slash (substring tmp 0 -1))))
4760 (mapcar (function
4761 (lambda (char)
4762 (if (= char ?/)
4763 (vector ?.)
4764 (vector char))))
4765 (substring tmp 0 -1)))))
4766 (setq file (file-name-nondirectory name)) 4769 (setq file (file-name-nondirectory name))
4767 (concat drive 4770 (concat drive
4768 (and dir (concat "[" (if drive nil ".") dir "]")) 4771 (and dir (concat "[" (if drive nil ".") dir "]"))
@@ -4797,7 +4800,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4797 ((string-match "^/[-A-Z0-9_$]+:/$" dir-name) 4800 ((string-match "^/[-A-Z0-9_$]+:/$" dir-name)
4798 (error "Cannot get listing for device.")) 4801 (error "Cannot get listing for device."))
4799 ((ange-ftp-fix-name-for-vms dir-name)))) 4802 ((ange-ftp-fix-name-for-vms dir-name))))
4800 4803
4801(or (assq 'vms ange-ftp-fix-dir-name-func-alist) 4804(or (assq 'vms ange-ftp-fix-dir-name-func-alist)
4802 (setq ange-ftp-fix-dir-name-func-alist 4805 (setq ange-ftp-fix-dir-name-func-alist
4803 (cons '(vms . ange-ftp-fix-dir-name-for-vms) 4806 (cons '(vms . ange-ftp-fix-dir-name-for-vms)
@@ -4879,7 +4882,7 @@ Other orders of $ and _ seem to all work just fine.")
4879 (save-match-data 4882 (save-match-data
4880 (let ((file (ange-ftp-get-file-part name))) 4883 (let ((file (ange-ftp-get-file-part name)))
4881 (if (string-match ";[0-9]+$" file) 4884 (if (string-match ";[0-9]+$" file)
4882 ;; In VMS you can't delete a file without an explicit 4885 ;; In VMS you can't delete a file without an explicit
4883 ;; version number, or wild-card (e.g. FOO;*) 4886 ;; version number, or wild-card (e.g. FOO;*)
4884 ;; For now, we give up on wildcards. 4887 ;; For now, we give up on wildcards.
4885 (let ((files (ange-ftp-get-hash-entry 4888 (let ((files (ange-ftp-get-hash-entry
@@ -5125,7 +5128,7 @@ Other orders of $ and _ seem to all work just fine.")
5125;;(or (assq 'vms ange-ftp-dired-ls-trim-alist) 5128;;(or (assq 'vms ange-ftp-dired-ls-trim-alist)
5126;; (setq ange-ftp-dired-ls-trim-alist 5129;; (setq ange-ftp-dired-ls-trim-alist
5127;; (cons '(vms . ange-ftp-dired-vms-ls-trim) 5130;; (cons '(vms . ange-ftp-dired-vms-ls-trim)
5128;; ange-ftp-dired-ls-trim-alist))) 5131;; ange-ftp-dired-ls-trim-alist)))
5129 5132
5130(defun ange-ftp-vms-sans-version (name &rest args) 5133(defun ange-ftp-vms-sans-version (name &rest args)
5131 (save-match-data 5134 (save-match-data
@@ -5594,7 +5597,7 @@ Other orders of $ and _ seem to all work just fine.")
5594 (setq ange-ftp-parse-list-func-alist 5597 (setq ange-ftp-parse-list-func-alist
5595 (cons '(cms . ange-ftp-parse-cms-listing) 5598 (cons '(cms . ange-ftp-parse-cms-listing)
5596 ange-ftp-parse-list-func-alist))) 5599 ange-ftp-parse-list-func-alist)))
5597 5600
5598;;;;; Tree dired support: 5601;;;;; Tree dired support:
5599 5602
5600;;(defconst ange-ftp-dired-cms-re-exe 5603;;(defconst ange-ftp-dired-cms-re-exe