diff options
| author | Michael Albinus | 2009-10-07 11:31:21 +0000 |
|---|---|---|
| committer | Michael Albinus | 2009-10-07 11:31:21 +0000 |
| commit | c2dc9732f76a0f90613519fd34f88df9dcba6c48 (patch) | |
| tree | de683fd768feedc1ba62a3ba79714bf44414fa2a | |
| parent | e946faaf51d3b5a1f6f9bc061546dd195c132a93 (diff) | |
| download | emacs-c2dc9732f76a0f90613519fd34f88df9dcba6c48.tar.gz emacs-c2dc9732f76a0f90613519fd34f88df9dcba6c48.zip | |
* net/tramp-smb.el (tramp-smb-errors): Add error messages.
(tramp-smb-file-name-handler-alist): Add handler for
`copy-directory', `expand-file-name', `set-file-modes'.
(tramp-smb-handle-copy-directory)
(tramp-smb-handle-expand-file-name)
(tramp-smb-handle-set-file-modes): New defuns.
(tramp-smb-handle-copy-file): Handle KEPP-DATE.
(tramp-smb-handle-file-attributes): Simplify check for retrieving
entry.
(tramp-smb-handle-insert-directory): Don't flush the cache.
(tramp-smb-maybe-open-connection): Check for samba client and
server versions.
| -rw-r--r-- | lisp/ChangeLog | 18 | ||||
| -rw-r--r-- | lisp/net/tramp-smb.el | 244 |
2 files changed, 201 insertions, 61 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 445aa4ad7d7..60181af667d 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,21 @@ | |||
| 1 | 2009-10-07 Michael Albinus <michael.albinus@gmx.de> | ||
| 2 | |||
| 3 | * net/tramp-cache.el (tramp-flush-connection-property): Add trace | ||
| 4 | message. | ||
| 5 | |||
| 6 | * net/tramp-smb.el (tramp-smb-errors): Add error messages. | ||
| 7 | (tramp-smb-file-name-handler-alist): Add handler for | ||
| 8 | `copy-directory', `expand-file-name', `set-file-modes'. | ||
| 9 | (tramp-smb-handle-copy-directory) | ||
| 10 | (tramp-smb-handle-expand-file-name) | ||
| 11 | (tramp-smb-handle-set-file-modes): New defuns. | ||
| 12 | (tramp-smb-handle-copy-file): Handle KEEP-DATE. | ||
| 13 | (tramp-smb-handle-file-attributes): Simplify check for retrieving | ||
| 14 | entry. | ||
| 15 | (tramp-smb-handle-insert-directory): Don't flush the cache. | ||
| 16 | (tramp-smb-maybe-open-connection): Check for samba client and | ||
| 17 | server versions. | ||
| 18 | |||
| 1 | 2009-10-07 Eli Zaretskii <eliz@gnu.org> | 19 | 2009-10-07 Eli Zaretskii <eliz@gnu.org> |
| 2 | 20 | ||
| 3 | * emacs-lisp/autoload.el (batch-update-autoloads): Fix last change | 21 | * emacs-lisp/autoload.el (batch-update-autoloads): Fix last change |
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index 48d015013c0..ff2a5d13cb7 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el | |||
| @@ -68,11 +68,13 @@ | |||
| 68 | ;; `regexp-opt' not possible because of first string. | 68 | ;; `regexp-opt' not possible because of first string. |
| 69 | (mapconcat | 69 | (mapconcat |
| 70 | 'identity | 70 | 'identity |
| 71 | '(;; Connection error / timeout | 71 | '(;; Connection error / timeout / unknown command. |
| 72 | "Connection to \\S-+ failed" | 72 | "Connection to \\S-+ failed" |
| 73 | "Read from server failed, maybe it closed the connection" | 73 | "Read from server failed, maybe it closed the connection" |
| 74 | "Call timed out: server did not respond" | 74 | "Call timed out: server did not respond" |
| 75 | ;; Samba | 75 | "\\S-+: command not found" |
| 76 | "Server doesn't support UNIX CIFS calls" | ||
| 77 | ;; Samba. | ||
| 76 | "ERRDOS" | 78 | "ERRDOS" |
| 77 | "ERRSRV" | 79 | "ERRSRV" |
| 78 | "ERRbadfile" | 80 | "ERRbadfile" |
| @@ -82,7 +84,7 @@ | |||
| 82 | "ERRnomem" | 84 | "ERRnomem" |
| 83 | "ERRnosuchshare" | 85 | "ERRnosuchshare" |
| 84 | ;; Windows 4.0 (Windows NT), Windows 5.0 (Windows 2000), | 86 | ;; Windows 4.0 (Windows NT), Windows 5.0 (Windows 2000), |
| 85 | ;; Windows 5.1 (Windows XP), Windows 5.2 (Windows Server 2003) | 87 | ;; Windows 5.1 (Windows XP), Windows 5.2 (Windows Server 2003). |
| 86 | "NT_STATUS_ACCESS_DENIED" | 88 | "NT_STATUS_ACCESS_DENIED" |
| 87 | "NT_STATUS_ACCOUNT_LOCKED_OUT" | 89 | "NT_STATUS_ACCOUNT_LOCKED_OUT" |
| 88 | "NT_STATUS_BAD_NETWORK_NAME" | 90 | "NT_STATUS_BAD_NETWORK_NAME" |
| @@ -128,20 +130,22 @@ See `tramp-actions-before-shell' for more info.") | |||
| 128 | ;; New handlers should be added here. | 130 | ;; New handlers should be added here. |
| 129 | (defconst tramp-smb-file-name-handler-alist | 131 | (defconst tramp-smb-file-name-handler-alist |
| 130 | '( | 132 | '( |
| 131 | ;; `access-file' performed by default handler | 133 | ;; `access-file' performed by default handler. |
| 132 | (add-name-to-file . tramp-smb-handle-copy-file) ;; we're on Windows, honey. | 134 | (add-name-to-file . tramp-smb-handle-copy-file) ;; we're on Windows, honey. |
| 133 | ;; `byte-compiler-base-file-name' performed by default handler | 135 | ;; `byte-compiler-base-file-name' performed by default handler. |
| 136 | (copy-directory . tramp-smb-handle-copy-directory) | ||
| 134 | (copy-file . tramp-smb-handle-copy-file) | 137 | (copy-file . tramp-smb-handle-copy-file) |
| 135 | (delete-directory . tramp-smb-handle-delete-directory) | 138 | (delete-directory . tramp-smb-handle-delete-directory) |
| 136 | (delete-file . tramp-smb-handle-delete-file) | 139 | (delete-file . tramp-smb-handle-delete-file) |
| 137 | ;; `diff-latest-backup-file' performed by default handler | 140 | ;; `diff-latest-backup-file' performed by default handler. |
| 138 | (directory-file-name . tramp-handle-directory-file-name) | 141 | (directory-file-name . tramp-handle-directory-file-name) |
| 139 | (directory-files . tramp-smb-handle-directory-files) | 142 | (directory-files . tramp-smb-handle-directory-files) |
| 140 | (directory-files-and-attributes . tramp-smb-handle-directory-files-and-attributes) | 143 | (directory-files-and-attributes |
| 144 | . tramp-smb-handle-directory-files-and-attributes) | ||
| 141 | (dired-call-process . ignore) | 145 | (dired-call-process . ignore) |
| 142 | (dired-compress-file . ignore) | 146 | (dired-compress-file . ignore) |
| 143 | (dired-uncache . tramp-handle-dired-uncache) | 147 | (dired-uncache . tramp-handle-dired-uncache) |
| 144 | ;; `expand-file-name' not necessary because we cannot expand "~/" | 148 | (expand-file-name . tramp-smb-handle-expand-file-name) |
| 145 | (file-accessible-directory-p . tramp-smb-handle-file-directory-p) | 149 | (file-accessible-directory-p . tramp-smb-handle-file-directory-p) |
| 146 | (file-attributes . tramp-smb-handle-file-attributes) | 150 | (file-attributes . tramp-smb-handle-file-attributes) |
| 147 | (file-directory-p . tramp-smb-handle-file-directory-p) | 151 | (file-directory-p . tramp-smb-handle-file-directory-p) |
| @@ -155,17 +159,17 @@ See `tramp-actions-before-shell' for more info.") | |||
| 155 | (file-name-completion . tramp-handle-file-name-completion) | 159 | (file-name-completion . tramp-handle-file-name-completion) |
| 156 | (file-name-directory . tramp-handle-file-name-directory) | 160 | (file-name-directory . tramp-handle-file-name-directory) |
| 157 | (file-name-nondirectory . tramp-handle-file-name-nondirectory) | 161 | (file-name-nondirectory . tramp-handle-file-name-nondirectory) |
| 158 | ;; `file-name-sans-versions' performed by default handler | 162 | ;; `file-name-sans-versions' performed by default handler. |
| 159 | (file-newer-than-file-p . tramp-smb-handle-file-newer-than-file-p) | 163 | (file-newer-than-file-p . tramp-smb-handle-file-newer-than-file-p) |
| 160 | (file-ownership-preserved-p . ignore) | 164 | (file-ownership-preserved-p . ignore) |
| 161 | (file-readable-p . tramp-smb-handle-file-exists-p) | 165 | (file-readable-p . tramp-smb-handle-file-exists-p) |
| 162 | (file-regular-p . tramp-handle-file-regular-p) | 166 | (file-regular-p . tramp-handle-file-regular-p) |
| 163 | (file-symlink-p . tramp-handle-file-symlink-p) | 167 | (file-symlink-p . tramp-handle-file-symlink-p) |
| 164 | ;; `file-truename' performed by default handler | 168 | ;; `file-truename' performed by default handler. |
| 165 | (file-writable-p . tramp-smb-handle-file-writable-p) | 169 | (file-writable-p . tramp-smb-handle-file-writable-p) |
| 166 | (find-backup-file-name . tramp-handle-find-backup-file-name) | 170 | (find-backup-file-name . tramp-handle-find-backup-file-name) |
| 167 | ;; `find-file-noselect' performed by default handler | 171 | ;; `find-file-noselect' performed by default handler. |
| 168 | ;; `get-file-buffer' performed by default handler | 172 | ;; `get-file-buffer' performed by default handler. |
| 169 | (insert-directory . tramp-smb-handle-insert-directory) | 173 | (insert-directory . tramp-smb-handle-insert-directory) |
| 170 | (insert-file-contents . tramp-handle-insert-file-contents) | 174 | (insert-file-contents . tramp-handle-insert-file-contents) |
| 171 | (load . tramp-handle-load) | 175 | (load . tramp-handle-load) |
| @@ -173,7 +177,8 @@ See `tramp-actions-before-shell' for more info.") | |||
| 173 | (make-directory-internal . tramp-smb-handle-make-directory-internal) | 177 | (make-directory-internal . tramp-smb-handle-make-directory-internal) |
| 174 | (make-symbolic-link . ignore) | 178 | (make-symbolic-link . ignore) |
| 175 | (rename-file . tramp-smb-handle-rename-file) | 179 | (rename-file . tramp-smb-handle-rename-file) |
| 176 | (set-file-modes . ignore) | 180 | (set-file-modes . tramp-smb-handle-set-file-modes) |
| 181 | (set-file-times . ignore) | ||
| 177 | (set-visited-file-modtime . ignore) | 182 | (set-visited-file-modtime . ignore) |
| 178 | (shell-command . ignore) | 183 | (shell-command . ignore) |
| 179 | (substitute-in-file-name . tramp-smb-handle-substitute-in-file-name) | 184 | (substitute-in-file-name . tramp-smb-handle-substitute-in-file-name) |
| @@ -203,7 +208,50 @@ pass to the OPERATION." | |||
| 203 | (cons 'tramp-smb-file-name-p 'tramp-smb-file-name-handler)) | 208 | (cons 'tramp-smb-file-name-p 'tramp-smb-file-name-handler)) |
| 204 | 209 | ||
| 205 | 210 | ||
| 206 | ;; File name primitives | 211 | ;; File name primitives. |
| 212 | |||
| 213 | (defun tramp-smb-handle-copy-directory | ||
| 214 | (dirname newname &optional keep-date parents) | ||
| 215 | "Like `copy-directory' for Tramp files." | ||
| 216 | (setq dirname (expand-file-name dirname) | ||
| 217 | newname (expand-file-name newname)) | ||
| 218 | (let ((t1 (tramp-tramp-file-p dirname)) | ||
| 219 | (t2 (tramp-tramp-file-p newname))) | ||
| 220 | (with-parsed-tramp-file-name (if t1 dirname newname) nil | ||
| 221 | (if (or (null t1) (null t2)) | ||
| 222 | ;; We can copy recursively. | ||
| 223 | (let ((prompt (tramp-smb-send-command v "prompt")) | ||
| 224 | (recurse (tramp-smb-send-command v "recurse"))) | ||
| 225 | (unless (file-directory-p newname) | ||
| 226 | (make-directory newname parents)) | ||
| 227 | (unwind-protect | ||
| 228 | (unless | ||
| 229 | (and | ||
| 230 | prompt recurse | ||
| 231 | (tramp-smb-send-command | ||
| 232 | v (format "cd \"%s\"" | ||
| 233 | (tramp-smb-get-localname localname t))) | ||
| 234 | (tramp-smb-send-command | ||
| 235 | v (format "lcd \"%s\"" (if t1 newname dirname))) | ||
| 236 | (if t1 | ||
| 237 | (tramp-smb-send-command v "mget *") | ||
| 238 | (tramp-smb-send-command v "mput *"))) | ||
| 239 | ;; Error. | ||
| 240 | (with-current-buffer (tramp-get-connection-buffer v) | ||
| 241 | (goto-char (point-min)) | ||
| 242 | (search-forward-regexp tramp-smb-errors nil t) | ||
| 243 | (tramp-error | ||
| 244 | v 'file-error | ||
| 245 | "%s `%s'" (match-string 0) (if t1 dirname newname)))) | ||
| 246 | ;; Always go home. | ||
| 247 | (tramp-smb-send-command v (format "cd \\")) | ||
| 248 | ;; Toggle prompt and recurse OFF. | ||
| 249 | (if prompt (tramp-smb-send-command v "prompt")) | ||
| 250 | (if recurse (tramp-smb-send-command v "recurse")))) | ||
| 251 | |||
| 252 | ;; We must do it file-wise. | ||
| 253 | (tramp-run-real-handler | ||
| 254 | 'copy-directory (list dirname newname keep-date parents)))))) | ||
| 207 | 255 | ||
| 208 | (defun tramp-smb-handle-copy-file | 256 | (defun tramp-smb-handle-copy-file |
| 209 | (filename newname &optional ok-if-already-exists keep-date preserve-uid-gid) | 257 | (filename newname &optional ok-if-already-exists keep-date preserve-uid-gid) |
| @@ -247,7 +295,10 @@ PRESERVE-UID-GID is completely ignored." | |||
| 247 | v (format "put %s \"%s\"" filename file)) | 295 | v (format "put %s \"%s\"" filename file)) |
| 248 | (tramp-message | 296 | (tramp-message |
| 249 | v 0 "Copying file %s to file %s...done" filename newname) | 297 | v 0 "Copying file %s to file %s...done" filename newname) |
| 250 | (tramp-error v 'file-error "Cannot copy `%s'" filename))))))) | 298 | (tramp-error v 'file-error "Cannot copy `%s'" filename)))))) |
| 299 | |||
| 300 | ;; KEEP-DATE handling. | ||
| 301 | (when keep-date (set-file-times newname (nth 5 (file-attributes filename))))) | ||
| 251 | 302 | ||
| 252 | (defun tramp-smb-handle-delete-directory (directory &optional recursive) | 303 | (defun tramp-smb-handle-delete-directory (directory &optional recursive) |
| 253 | "Like `delete-directory' for Tramp files." | 304 | "Like `delete-directory' for Tramp files." |
| @@ -273,13 +324,13 @@ PRESERVE-UID-GID is completely ignored." | |||
| 273 | (unless (and | 324 | (unless (and |
| 274 | (tramp-smb-send-command v (format "cd \"%s\"" dir)) | 325 | (tramp-smb-send-command v (format "cd \"%s\"" dir)) |
| 275 | (tramp-smb-send-command v (format "rmdir \"%s\"" file))) | 326 | (tramp-smb-send-command v (format "rmdir \"%s\"" file))) |
| 276 | ;; Error | 327 | ;; Error. |
| 277 | (with-current-buffer (tramp-get-connection-buffer v) | 328 | (with-current-buffer (tramp-get-connection-buffer v) |
| 278 | (goto-char (point-min)) | 329 | (goto-char (point-min)) |
| 279 | (search-forward-regexp tramp-smb-errors nil t) | 330 | (search-forward-regexp tramp-smb-errors nil t) |
| 280 | (tramp-error | 331 | (tramp-error |
| 281 | v 'file-error "%s `%s'" (match-string 0) directory))) | 332 | v 'file-error "%s `%s'" (match-string 0) directory))) |
| 282 | ;; Always go home | 333 | ;; Always go home. |
| 283 | (tramp-smb-send-command v (format "cd \\"))))))) | 334 | (tramp-smb-send-command v (format "cd \\"))))))) |
| 284 | 335 | ||
| 285 | (defun tramp-smb-handle-delete-file (filename) | 336 | (defun tramp-smb-handle-delete-file (filename) |
| @@ -297,13 +348,13 @@ PRESERVE-UID-GID is completely ignored." | |||
| 297 | (unless (and | 348 | (unless (and |
| 298 | (tramp-smb-send-command v (format "cd \"%s\"" dir)) | 349 | (tramp-smb-send-command v (format "cd \"%s\"" dir)) |
| 299 | (tramp-smb-send-command v (format "rm \"%s\"" file))) | 350 | (tramp-smb-send-command v (format "rm \"%s\"" file))) |
| 300 | ;; Error | 351 | ;; Error. |
| 301 | (with-current-buffer (tramp-get-connection-buffer v) | 352 | (with-current-buffer (tramp-get-connection-buffer v) |
| 302 | (goto-char (point-min)) | 353 | (goto-char (point-min)) |
| 303 | (search-forward-regexp tramp-smb-errors nil t) | 354 | (search-forward-regexp tramp-smb-errors nil t) |
| 304 | (tramp-error | 355 | (tramp-error |
| 305 | v 'file-error "%s `%s'" (match-string 0) filename))) | 356 | v 'file-error "%s `%s'" (match-string 0) filename))) |
| 306 | ;; Always go home | 357 | ;; Always go home. |
| 307 | (tramp-smb-send-command v (format "cd \\"))))))) | 358 | (tramp-smb-send-command v (format "cd \\"))))))) |
| 308 | 359 | ||
| 309 | (defun tramp-smb-handle-directory-files | 360 | (defun tramp-smb-handle-directory-files |
| @@ -311,21 +362,21 @@ PRESERVE-UID-GID is completely ignored." | |||
| 311 | "Like `directory-files' for Tramp files." | 362 | "Like `directory-files' for Tramp files." |
| 312 | (let ((result (mapcar 'directory-file-name | 363 | (let ((result (mapcar 'directory-file-name |
| 313 | (file-name-all-completions "" directory)))) | 364 | (file-name-all-completions "" directory)))) |
| 314 | ;; Discriminate with regexp | 365 | ;; Discriminate with regexp. |
| 315 | (when match | 366 | (when match |
| 316 | (setq result | 367 | (setq result |
| 317 | (delete nil | 368 | (delete nil |
| 318 | (mapcar (lambda (x) (when (string-match match x) x)) | 369 | (mapcar (lambda (x) (when (string-match match x) x)) |
| 319 | result)))) | 370 | result)))) |
| 320 | ;; Append directory | 371 | ;; Append directory. |
| 321 | (when full | 372 | (when full |
| 322 | (setq result | 373 | (setq result |
| 323 | (mapcar | 374 | (mapcar |
| 324 | (lambda (x) (expand-file-name x directory)) | 375 | (lambda (x) (expand-file-name x directory)) |
| 325 | result))) | 376 | result))) |
| 326 | ;; Sort them if necessary | 377 | ;; Sort them if necessary. |
| 327 | (unless nosort (setq result (sort result 'string-lessp))) | 378 | (unless nosort (setq result (sort result 'string-lessp))) |
| 328 | ;; That's it | 379 | ;; That's it. |
| 329 | result)) | 380 | result)) |
| 330 | 381 | ||
| 331 | (defun tramp-smb-handle-directory-files-and-attributes | 382 | (defun tramp-smb-handle-directory-files-and-attributes |
| @@ -337,6 +388,35 @@ PRESERVE-UID-GID is completely ignored." | |||
| 337 | (if full x (expand-file-name x directory)) id-format))) | 388 | (if full x (expand-file-name x directory)) id-format))) |
| 338 | (directory-files directory full match nosort))) | 389 | (directory-files directory full match nosort))) |
| 339 | 390 | ||
| 391 | (defun tramp-smb-handle-expand-file-name (name &optional dir) | ||
| 392 | "Like `expand-file-name' for Tramp files." | ||
| 393 | ;; If DIR is not given, use DEFAULT-DIRECTORY or "/". | ||
| 394 | (setq dir (or dir default-directory "/")) | ||
| 395 | ;; Unless NAME is absolute, concat DIR and NAME. | ||
| 396 | (unless (file-name-absolute-p name) | ||
| 397 | (setq name (concat (file-name-as-directory dir) name))) | ||
| 398 | ;; If NAME is not a Tramp file, run the real handler. | ||
| 399 | (if (not (tramp-tramp-file-p name)) | ||
| 400 | (tramp-run-real-handler 'expand-file-name (list name nil)) | ||
| 401 | ;; Dissect NAME. | ||
| 402 | (with-parsed-tramp-file-name name nil | ||
| 403 | (unless (tramp-run-real-handler 'file-name-absolute-p (list localname)) | ||
| 404 | (setq localname (concat "/" localname))) | ||
| 405 | ;; Tilde expansion if necessary. We use the user name as share, | ||
| 406 | ;; which is offen the case in work groups. | ||
| 407 | (when (string-match "\\`~[^/]*" localname) | ||
| 408 | (setq localname | ||
| 409 | (replace-match | ||
| 410 | (if (zerop (length (match-string 0 localname))) | ||
| 411 | (tramp-file-name-real-user v) | ||
| 412 | (match-string 0 localname)) | ||
| 413 | nil nil localname))) | ||
| 414 | ;; No tilde characters in file name, do normal | ||
| 415 | ;; `expand-file-name' (this does "/./" and "/../"). | ||
| 416 | (tramp-make-tramp-file-name | ||
| 417 | method user host | ||
| 418 | (tramp-run-real-handler 'expand-file-name (list localname)))))) | ||
| 419 | |||
| 340 | (defun tramp-smb-handle-file-attributes (filename &optional id-format) | 420 | (defun tramp-smb-handle-file-attributes (filename &optional id-format) |
| 341 | "Like `file-attributes' for Tramp files." | 421 | "Like `file-attributes' for Tramp files." |
| 342 | ;; Reading just the filename entry via "dir localname" is not | 422 | ;; Reading just the filename entry via "dir localname" is not |
| @@ -348,8 +428,7 @@ PRESERVE-UID-GID is completely ignored." | |||
| 348 | (with-file-property v localname (format "file-attributes-%s" id-format) | 428 | (with-file-property v localname (format "file-attributes-%s" id-format) |
| 349 | (let* ((entries (tramp-smb-get-file-entries | 429 | (let* ((entries (tramp-smb-get-file-entries |
| 350 | (file-name-directory filename))) | 430 | (file-name-directory filename))) |
| 351 | (entry (and entries | 431 | (entry (assoc (file-name-nondirectory filename) entries)) |
| 352 | (assoc (file-name-nondirectory filename) entries))) | ||
| 353 | (uid (if (and id-format (equal id-format 'string)) "nobody" -1)) | 432 | (uid (if (and id-format (equal id-format 'string)) "nobody" -1)) |
| 354 | (gid (if (and id-format (equal id-format 'string)) "nogroup" -1)) | 433 | (gid (if (and id-format (equal id-format 'string)) "nogroup" -1)) |
| 355 | (inode (tramp-get-inode v)) | 434 | (inode (tramp-get-inode v)) |
| @@ -442,7 +521,6 @@ PRESERVE-UID-GID is completely ignored." | |||
| 442 | ;; Called from `dired-add-entry'. | 521 | ;; Called from `dired-add-entry'. |
| 443 | (setq filename (file-name-as-directory filename))) | 522 | (setq filename (file-name-as-directory filename))) |
| 444 | (with-parsed-tramp-file-name filename nil | 523 | (with-parsed-tramp-file-name filename nil |
| 445 | (tramp-flush-file-property v (file-name-directory localname)) | ||
| 446 | (save-match-data | 524 | (save-match-data |
| 447 | (let ((base (file-name-nondirectory filename)) | 525 | (let ((base (file-name-nondirectory filename)) |
| 448 | ;; We should not destroy the cache entry. | 526 | ;; We should not destroy the cache entry. |
| @@ -527,10 +605,10 @@ PRESERVE-UID-GID is completely ignored." | |||
| 527 | (save-match-data | 605 | (save-match-data |
| 528 | (let* ((share (tramp-smb-get-share localname)) | 606 | (let* ((share (tramp-smb-get-share localname)) |
| 529 | (ldir (file-name-directory dir))) | 607 | (ldir (file-name-directory dir))) |
| 530 | ;; Make missing directory parts | 608 | ;; Make missing directory parts. |
| 531 | (when (and parents share (not (file-directory-p ldir))) | 609 | (when (and parents share (not (file-directory-p ldir))) |
| 532 | (make-directory ldir parents)) | 610 | (make-directory ldir parents)) |
| 533 | ;; Just do it | 611 | ;; Just do it. |
| 534 | (when (file-directory-p ldir) | 612 | (when (file-directory-p ldir) |
| 535 | (make-directory-internal dir)) | 613 | (make-directory-internal dir)) |
| 536 | (unless (file-directory-p dir) | 614 | (unless (file-directory-p dir) |
| @@ -592,6 +670,17 @@ PRESERVE-UID-GID is completely ignored." | |||
| 592 | 670 | ||
| 593 | (delete-file filename)) | 671 | (delete-file filename)) |
| 594 | 672 | ||
| 673 | (defun tramp-smb-handle-set-file-modes (filename mode) | ||
| 674 | "Like `set-file-modes' for Tramp files." | ||
| 675 | (with-parsed-tramp-file-name filename nil | ||
| 676 | (tramp-flush-file-property v localname) | ||
| 677 | (unless (tramp-smb-send-command | ||
| 678 | v (format "chmod \"%s\" %s" | ||
| 679 | (tramp-smb-get-localname localname t) | ||
| 680 | (tramp-decimal-to-octal mode))) | ||
| 681 | (tramp-error | ||
| 682 | v 'file-error "Error while changing file's mode %s" filename)))) | ||
| 683 | |||
| 595 | (defun tramp-smb-handle-substitute-in-file-name (filename) | 684 | (defun tramp-smb-handle-substitute-in-file-name (filename) |
| 596 | "Like `handle-substitute-in-file-name' for Tramp files. | 685 | "Like `handle-substitute-in-file-name' for Tramp files. |
| 597 | \"//\" substitutes only in the local filename part. Catches | 686 | \"//\" substitutes only in the local filename part. Catches |
| @@ -652,7 +741,7 @@ errors for shares like \"C$/\", which are common in Microsoft Windows." | |||
| 652 | (set-visited-file-modtime))))) | 741 | (set-visited-file-modtime))))) |
| 653 | 742 | ||
| 654 | 743 | ||
| 655 | ;; Internal file name functions | 744 | ;; Internal file name functions. |
| 656 | 745 | ||
| 657 | (defun tramp-smb-get-share (localname) | 746 | (defun tramp-smb-get-share (localname) |
| 658 | "Returns the share name of LOCALNAME." | 747 | "Returns the share name of LOCALNAME." |
| @@ -677,7 +766,7 @@ If CONVERT is non-nil exchange \"/\" by \"\\\\\"." | |||
| 677 | (match-string 1 res) | 766 | (match-string 1 res) |
| 678 | ""))) | 767 | ""))) |
| 679 | 768 | ||
| 680 | ;; Sometimes we have discarded `substitute-in-file-name' | 769 | ;; Sometimes we have discarded `substitute-in-file-name'. |
| 681 | (when (string-match "\\(\\$\\$\\)\\(/\\|$\\)" res) | 770 | (when (string-match "\\(\\$\\$\\)\\(/\\|$\\)" res) |
| 682 | (setq res (replace-match "$" nil nil res 1))) | 771 | (setq res (replace-match "$" nil nil res 1))) |
| 683 | 772 | ||
| @@ -699,19 +788,19 @@ Result is a list of (LOCALNAME MODE SIZE MONTH DAY TIME YEAR)." | |||
| 699 | res entry) | 788 | res entry) |
| 700 | 789 | ||
| 701 | (if (and (not share) cache) | 790 | (if (and (not share) cache) |
| 702 | ;; Return cached shares | 791 | ;; Return cached shares. |
| 703 | (setq res cache) | 792 | (setq res cache) |
| 704 | 793 | ||
| 705 | ;; Read entries | 794 | ;; Read entries. |
| 706 | (setq file (file-name-as-directory file)) | 795 | (setq file (file-name-as-directory file)) |
| 707 | (when (string-match "^\\./" file) | 796 | (when (string-match "^\\./" file) |
| 708 | (setq file (substring file 1))) | 797 | (setq file (substring file 1))) |
| 709 | (if share | 798 | (if share |
| 710 | (tramp-smb-send-command v (format "dir \"%s*\"" file)) | 799 | (tramp-smb-send-command v (format "dir \"%s*\"" file)) |
| 711 | ;; `tramp-smb-maybe-open-connection' lists also the share names | 800 | ;; `tramp-smb-maybe-open-connection' lists also the share names. |
| 712 | (tramp-smb-maybe-open-connection v)) | 801 | (tramp-smb-maybe-open-connection v)) |
| 713 | 802 | ||
| 714 | ;; Loop the listing | 803 | ;; Loop the listing. |
| 715 | (goto-char (point-min)) | 804 | (goto-char (point-min)) |
| 716 | (unless (re-search-forward tramp-smb-errors nil t) | 805 | (unless (re-search-forward tramp-smb-errors nil t) |
| 717 | (while (not (eobp)) | 806 | (while (not (eobp)) |
| @@ -719,23 +808,23 @@ Result is a list of (LOCALNAME MODE SIZE MONTH DAY TIME YEAR)." | |||
| 719 | (forward-line) | 808 | (forward-line) |
| 720 | (when entry (add-to-list 'res entry)))) | 809 | (when entry (add-to-list 'res entry)))) |
| 721 | 810 | ||
| 722 | ;; Cache share entries | 811 | ;; Cache share entries. |
| 723 | (unless share | 812 | (unless share |
| 724 | (tramp-set-connection-property v "share-cache" res))) | 813 | (tramp-set-connection-property v "share-cache" res))) |
| 725 | 814 | ||
| 726 | ;; Add directory itself | 815 | ;; Add directory itself. |
| 727 | (add-to-list 'res '("" "drwxrwxrwx" 0 (0 0))) | 816 | (add-to-list 'res '("" "drwxrwxrwx" 0 (0 0))) |
| 728 | 817 | ||
| 729 | ;; There's a very strange error (debugged with XEmacs 21.4.14) | 818 | ;; There's a very strange error (debugged with XEmacs 21.4.14) |
| 730 | ;; If there's no short delay, it returns nil. No idea about. | 819 | ;; If there's no short delay, it returns nil. No idea about. |
| 731 | (when (featurep 'xemacs) (sleep-for 0.01)) | 820 | (when (featurep 'xemacs) (sleep-for 0.01)) |
| 732 | 821 | ||
| 733 | ;; Return entries | 822 | ;; Return entries. |
| 734 | (delq nil res)))))) | 823 | (delq nil res)))))) |
| 735 | 824 | ||
| 736 | ;; Return either a share name (if SHARE is nil), or a file name | 825 | ;; Return either a share name (if SHARE is nil), or a file name. |
| 737 | ;; | 826 | ;; |
| 738 | ;; If shares are listed, the following format is expected | 827 | ;; If shares are listed, the following format is expected: |
| 739 | ;; | 828 | ;; |
| 740 | ;; \s-\{8,8} - leading spaces | 829 | ;; \s-\{8,8} - leading spaces |
| 741 | ;; \S-\(.*\S-\)\s-* - share name, 14 char | 830 | ;; \S-\(.*\S-\)\s-* - share name, 14 char |
| @@ -807,13 +896,13 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." | |||
| 807 | ;; Real listing. | 896 | ;; Real listing. |
| 808 | (block nil | 897 | (block nil |
| 809 | 898 | ||
| 810 | ;; year | 899 | ;; year. |
| 811 | (if (string-match "\\([0-9]+\\)$" line) | 900 | (if (string-match "\\([0-9]+\\)$" line) |
| 812 | (setq year (string-to-number (match-string 1 line)) | 901 | (setq year (string-to-number (match-string 1 line)) |
| 813 | line (substring line 0 -5)) | 902 | line (substring line 0 -5)) |
| 814 | (return)) | 903 | (return)) |
| 815 | 904 | ||
| 816 | ;; time | 905 | ;; time. |
| 817 | (if (string-match "\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\)$" line) | 906 | (if (string-match "\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\)$" line) |
| 818 | (setq hour (string-to-number (match-string 1 line)) | 907 | (setq hour (string-to-number (match-string 1 line)) |
| 819 | min (string-to-number (match-string 2 line)) | 908 | min (string-to-number (match-string 2 line)) |
| @@ -821,24 +910,24 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." | |||
| 821 | line (substring line 0 -9)) | 910 | line (substring line 0 -9)) |
| 822 | (return)) | 911 | (return)) |
| 823 | 912 | ||
| 824 | ;; day | 913 | ;; day. |
| 825 | (if (string-match "\\([0-9]+\\)$" line) | 914 | (if (string-match "\\([0-9]+\\)$" line) |
| 826 | (setq day (string-to-number (match-string 1 line)) | 915 | (setq day (string-to-number (match-string 1 line)) |
| 827 | line (substring line 0 -3)) | 916 | line (substring line 0 -3)) |
| 828 | (return)) | 917 | (return)) |
| 829 | 918 | ||
| 830 | ;; month | 919 | ;; month. |
| 831 | (if (string-match "\\(\\w+\\)$" line) | 920 | (if (string-match "\\(\\w+\\)$" line) |
| 832 | (setq month (match-string 1 line) | 921 | (setq month (match-string 1 line) |
| 833 | line (substring line 0 -4)) | 922 | line (substring line 0 -4)) |
| 834 | (return)) | 923 | (return)) |
| 835 | 924 | ||
| 836 | ;; weekday | 925 | ;; weekday. |
| 837 | (if (string-match "\\(\\w+\\)$" line) | 926 | (if (string-match "\\(\\w+\\)$" line) |
| 838 | (setq line (substring line 0 -5)) | 927 | (setq line (substring line 0 -5)) |
| 839 | (return)) | 928 | (return)) |
| 840 | 929 | ||
| 841 | ;; size | 930 | ;; size. |
| 842 | (if (string-match "\\([0-9]+\\)$" line) | 931 | (if (string-match "\\([0-9]+\\)$" line) |
| 843 | (let ((length (- (max 10 (1+ (length (match-string 1 line))))))) | 932 | (let ((length (- (max 10 (1+ (length (match-string 1 line))))))) |
| 844 | (setq size (string-to-number (match-string 1 line))) | 933 | (setq size (string-to-number (match-string 1 line))) |
| @@ -847,7 +936,7 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." | |||
| 847 | (setq line (substring line 0 length))) | 936 | (setq line (substring line 0 length))) |
| 848 | (return)) | 937 | (return)) |
| 849 | 938 | ||
| 850 | ;; mode: ARCH, DIR, HIDDEN, RONLY, SYSTEM, VOLID | 939 | ;; mode: ARCH, DIR, HIDDEN, RONLY, SYSTEM, VOLID. |
| 851 | (if (string-match "\\([ADHRSV]+\\)?$" line) | 940 | (if (string-match "\\([ADHRSV]+\\)?$" line) |
| 852 | (setq | 941 | (setq |
| 853 | mode (or (match-string 1 line) "") | 942 | mode (or (match-string 1 line) "") |
| @@ -860,7 +949,7 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." | |||
| 860 | line (substring line 0 -7)) | 949 | line (substring line 0 -7)) |
| 861 | (return)) | 950 | (return)) |
| 862 | 951 | ||
| 863 | ;; localname | 952 | ;; localname. |
| 864 | (if (string-match "^\\s-+\\(\\S-\\(.*\\S-\\)?\\)\\s-*$" line) | 953 | (if (string-match "^\\s-+\\(\\S-\\(.*\\S-\\)?\\)\\s-*$" line) |
| 865 | (setq localname (match-string 1 line)) | 954 | (setq localname (match-string 1 line)) |
| 866 | (return)))) | 955 | (return)))) |
| @@ -876,7 +965,7 @@ Result is the list (LOCALNAME MODE SIZE MTIME)." | |||
| 876 | (list localname mode size mtime)))) | 965 | (list localname mode size mtime)))) |
| 877 | 966 | ||
| 878 | 967 | ||
| 879 | ;; Connection functions | 968 | ;; Connection functions. |
| 880 | 969 | ||
| 881 | (defun tramp-smb-send-command (vec command) | 970 | (defun tramp-smb-send-command (vec command) |
| 882 | "Send the COMMAND to connection VEC. | 971 | "Send the COMMAND to connection VEC. |
| @@ -894,8 +983,32 @@ connection if a previous connection has died for some reason." | |||
| 894 | (buf (tramp-get-buffer vec)) | 983 | (buf (tramp-get-buffer vec)) |
| 895 | (p (get-buffer-process buf))) | 984 | (p (get-buffer-process buf))) |
| 896 | 985 | ||
| 986 | ;; Check whether we still have the same smbclient version. | ||
| 987 | ;; Otherwise, we must delete the connection cache, because | ||
| 988 | ;; capabilities migh have changed. | ||
| 989 | (unless (processp p) | ||
| 990 | (unless (let ((default-directory | ||
| 991 | (tramp-compat-temporary-file-directory))) | ||
| 992 | (executable-find tramp-smb-program)) | ||
| 993 | (tramp-error | ||
| 994 | vec 'file-error | ||
| 995 | "Cannot find command %s in %s" tramp-smb-program exec-path)) | ||
| 996 | |||
| 997 | (let* ((default-directory (tramp-compat-temporary-file-directory)) | ||
| 998 | (smbclient-version | ||
| 999 | (shell-command-to-string (concat tramp-smb-program " -V")))) | ||
| 1000 | (unless (string-equal | ||
| 1001 | smbclient-version | ||
| 1002 | (tramp-get-connection-property vec "smbclient-version" "")) | ||
| 1003 | (tramp-flush-directory-property vec "") | ||
| 1004 | (tramp-flush-connection-property vec) | ||
| 1005 | (tramp-set-connection-property | ||
| 1006 | vec "smbclient-version" smbclient-version) | ||
| 1007 | (setq buf (tramp-get-buffer vec))))) | ||
| 1008 | |||
| 897 | ;; If too much time has passed since last command was sent, look | 1009 | ;; If too much time has passed since last command was sent, look |
| 898 | ;; whether has been an error message; maybe due to connection timeout. | 1010 | ;; whether there has been an error message; maybe due to |
| 1011 | ;; connection timeout. | ||
| 899 | (with-current-buffer buf | 1012 | (with-current-buffer buf |
| 900 | (goto-char (point-min)) | 1013 | (goto-char (point-min)) |
| 901 | (when (and (> (tramp-time-diff | 1014 | (when (and (> (tramp-time-diff |
| @@ -920,11 +1033,6 @@ connection if a previous connection has died for some reason." | |||
| 920 | (when buf (with-current-buffer buf (erase-buffer))) | 1033 | (when buf (with-current-buffer buf (erase-buffer))) |
| 921 | (when (and p (processp p)) (delete-process p)) | 1034 | (when (and p (processp p)) (delete-process p)) |
| 922 | 1035 | ||
| 923 | (unless (let ((default-directory | ||
| 924 | (tramp-compat-temporary-file-directory))) | ||
| 925 | (executable-find tramp-smb-program)) | ||
| 926 | (error "Cannot find command %s in %s" tramp-smb-program exec-path)) | ||
| 927 | |||
| 928 | (let* ((user (tramp-file-name-user vec)) | 1036 | (let* ((user (tramp-file-name-user vec)) |
| 929 | (host (tramp-file-name-host vec)) | 1037 | (host (tramp-file-name-host vec)) |
| 930 | (real-user (tramp-file-name-real-user vec)) | 1038 | (real-user (tramp-file-name-real-user vec)) |
| @@ -962,17 +1070,12 @@ connection if a previous connection has died for some reason." | |||
| 962 | (tramp-message | 1070 | (tramp-message |
| 963 | vec 6 "%s" (mapconcat 'identity (process-command p) " ")) | 1071 | vec 6 "%s" (mapconcat 'identity (process-command p) " ")) |
| 964 | (tramp-set-process-query-on-exit-flag p nil) | 1072 | (tramp-set-process-query-on-exit-flag p nil) |
| 965 | (tramp-set-connection-property p "smb-share" share) | ||
| 966 | 1073 | ||
| 967 | ;; Set variables for computing the prompt for reading password. | 1074 | ;; Set variables for computing the prompt for reading password. |
| 968 | (setq tramp-current-method tramp-smb-method | 1075 | (setq tramp-current-method tramp-smb-method |
| 969 | tramp-current-user user | 1076 | tramp-current-user user |
| 970 | tramp-current-host host) | 1077 | tramp-current-host host) |
| 971 | 1078 | ||
| 972 | ;; Set chunksize. Otherwise, `tramp-send-string' might | ||
| 973 | ;; try it itself. | ||
| 974 | (tramp-set-connection-property p "chunksize" tramp-chunksize) | ||
| 975 | |||
| 976 | ;; Play login scenario. | 1079 | ;; Play login scenario. |
| 977 | (tramp-process-actions | 1080 | (tramp-process-actions |
| 978 | p vec | 1081 | p vec |
| @@ -980,6 +1083,26 @@ connection if a previous connection has died for some reason." | |||
| 980 | tramp-smb-actions-with-share | 1083 | tramp-smb-actions-with-share |
| 981 | tramp-smb-actions-without-share)) | 1084 | tramp-smb-actions-without-share)) |
| 982 | 1085 | ||
| 1086 | ;; Check server version. | ||
| 1087 | (with-current-buffer (tramp-get-connection-buffer vec) | ||
| 1088 | (goto-char (point-min)) | ||
| 1089 | (search-forward-regexp | ||
| 1090 | "Domain=\\[[^]]*\\] OS=\\[[^]]*\\] Server=\\[[^]]*\\]" nil t) | ||
| 1091 | (let ((smbserver-version (match-string 0))) | ||
| 1092 | (when (not (string-equal | ||
| 1093 | smbserver-version | ||
| 1094 | (tramp-get-connection-property | ||
| 1095 | vec "smbserver-version" ""))) | ||
| 1096 | (tramp-flush-directory-property vec "") | ||
| 1097 | (tramp-flush-connection-property vec) | ||
| 1098 | (tramp-set-connection-property | ||
| 1099 | vec "smbserver-version" smbserver-version)))) | ||
| 1100 | |||
| 1101 | ;; Set chunksize. Otherwise, `tramp-send-string' might | ||
| 1102 | ;; try it itself. | ||
| 1103 | (tramp-set-connection-property p "smb-share" share) | ||
| 1104 | (tramp-set-connection-property p "chunksize" tramp-chunksize) | ||
| 1105 | |||
| 983 | (tramp-message | 1106 | (tramp-message |
| 984 | vec 3 "Opening connection for //%s%s/%s...done" | 1107 | vec 3 "Opening connection for //%s%s/%s...done" |
| 985 | (if (not (zerop (length user))) (concat user "@") "") | 1108 | (if (not (zerop (length user))) (concat user "@") "") |
| @@ -1033,8 +1156,7 @@ Returns nil if an error message has appeared." | |||
| 1033 | 1156 | ||
| 1034 | ;; * Error handling in case password is wrong. | 1157 | ;; * Error handling in case password is wrong. |
| 1035 | ;; * Read password from "~/.netrc". | 1158 | ;; * Read password from "~/.netrc". |
| 1036 | ;; * Return more comprehensive file permission string. Think whether it is | 1159 | ;; * Return more comprehensive file permission string. |
| 1037 | ;; possible to implement `set-file-modes'. | ||
| 1038 | ;; * Handle links (FILENAME.LNK). | 1160 | ;; * Handle links (FILENAME.LNK). |
| 1039 | ;; * Try to remove the inclusion of dummy "" directory. Seems to be at | 1161 | ;; * Try to remove the inclusion of dummy "" directory. Seems to be at |
| 1040 | ;; several places, especially in `tramp-smb-handle-insert-directory'. | 1162 | ;; several places, especially in `tramp-smb-handle-insert-directory'. |