diff options
| author | Sam Steingold | 2000-07-25 23:26:01 +0000 |
|---|---|---|
| committer | Sam Steingold | 2000-07-25 23:26:01 +0000 |
| commit | 25759a92ce408ae70ea20ddabed3867c3cdbf567 (patch) | |
| tree | 3b7172bbd299f3bc574255952341b1e1ea455ac9 | |
| parent | 5044b74a7b8053a5c18b050b21b829582c36dcf0 (diff) | |
| download | emacs-25759a92ce408ae70ea20ddabed3867c3cdbf567.tar.gz emacs-25759a92ce408ae70ea20ddabed3867c3cdbf567.zip | |
Get modtime over the net
| -rw-r--r-- | lisp/ChangeLog | 8 | ||||
| -rw-r--r-- | lisp/net/ange-ftp.el | 541 |
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 @@ | |||
| 1 | 2000-07-25 Sam Steingold <sds@gnu.org> | 1 | 2000-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 | |||
| 643 | the full remote name, and HOST, USER, and NAME are the numbers of | 643 | the full remote name, and HOST, USER, and NAME are the numbers of |
| 644 | parenthesized expressions in REGEXP for the components (in that order)." | 644 | parenthesized 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'. |
| 1094 | If the optional parameter NEW is given and the non-directory parts match, | 1094 | If the optional parameter NEW is given and the non-directory parts match, |
| 1095 | only return the directory part of FILE." | 1095 | only 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. |
| 1796 | MSG is an optional message to output before and after the command. | 1796 | MSG is an optional message to output before and after the command. |
| 1797 | If CONT is non-nil then it is either a function or a list of function and | 1797 | If CONT is non-nil then it is either a function or a list of function |
| 1798 | some arguments. The function will be called when the ftp command has completed. | 1798 | and some arguments. The function will be called when the ftp command |
| 1799 | If CONT is nil then this routine will return \( RESULT . LINE \) where RESULT | 1799 | has completed. |
| 1800 | If CONT is nil then this routine will return \(RESULT . LINE\) where RESULT | ||
| 1800 | is whether the command was successful, and LINE is the line from the FTP | 1801 | is whether the command was successful, and LINE is the line from the FTP |
| 1801 | process that caused the command to complete. | 1802 | process that caused the command to complete. |
| 1802 | If NOWAIT is given then the routine will return immediately the command has | 1803 | If 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. |
| 1989 | PROC is the FTP-client's process. This routine uses the smart-gateway | 1990 | PROC is the FTP-client's process. This routine uses the smart-gateway |
| 1990 | host specified in ``ange-ftp-gateway-host''." | 1991 | host 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. |
| 2188 | MSG is an optional status message to be output before and after issuing the | 2189 | MSG is an optional status message to be output before and after issuing the |
| 2189 | command. | 2190 | command. |
| 2190 | See the documentation for ange-ftp-raw-send-cmd for a description of CONT | 2191 | See the documentation for `ange-ftp-raw-send-cmd' for a description of CONT |
| 2191 | and NOWAIT." | 2192 | and 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." | |||
| 3988 | Each element has the form (TYPE . FUNC). | 3997 | Each element has the form (TYPE . FUNC). |
| 3989 | FUNC should take one argument, a file name, and return a list | 3998 | FUNC should take one argument, a file name, and return a list |
| 3990 | of the form (COMPRESSING NEWNAME). | 3999 | of the form (COMPRESSING NEWNAME). |
| 3991 | COMPRESSING should be t if the specified file should be compressed, | 4000 | COMPRESSING should be t if the specified file should be compressed, |
| 3992 | and nil if it should be uncompressed (that is, if it is a compressed file). | 4001 | and nil if it should be uncompressed (that is, if it is a compressed file). |
| 3993 | NEWNAME should be the name to give the new compressed or uncompressed file.") | 4002 | NEWNAME 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 |