emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] Changes to emacs/lisp/net/tramp-smb.el,v


From: Michael Albinus
Subject: [Emacs-diffs] Changes to emacs/lisp/net/tramp-smb.el,v
Date: Sun, 08 Jul 2007 18:03:21 +0000

CVSROOT:        /cvsroot/emacs
Module name:    emacs
Changes by:     Michael Albinus <albinus>       07/07/08 18:03:20

Index: net/tramp-smb.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/net/tramp-smb.el,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -b -r1.26 -r1.27
--- net/tramp-smb.el    28 May 2007 10:32:52 -0000      1.26
+++ net/tramp-smb.el    8 Jul 2007 18:03:19 -0000       1.27
@@ -1,6 +1,7 @@
 ;;; tramp-smb.el --- Tramp access functions for SMB servers -*- coding: 
iso-8859-1; -*-
 
-;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, 
Inc.
+;; Copyright (C) 2002, 2003, 2004, 2005, 2006,
+;;   2007 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <address@hidden>
 ;; Keywords: comm, processes
@@ -9,8 +10,8 @@
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,9 +19,8 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs; see the file COPYING.  If not, see
+;; <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
@@ -29,6 +29,7 @@
 ;;; Code:
 
 (require 'tramp)
+(require 'tramp-cache)
 
 ;; Pacify byte-compiler
 (eval-when-compile (require 'custom))
@@ -36,10 +37,8 @@
 ;; Avoid byte-compiler warnings if the byte-compiler supports this.
 ;; Currently, XEmacs supports this.
 (eval-when-compile
-  (when (fboundp 'byte-compiler-options)
-    (let (unused-vars) ; Pacify Emacs byte-compiler
-      (defalias 'warnings 'identity) ; Pacify Emacs byte-compiler
-      (byte-compiler-options (warnings (- unused-vars))))))
+  (when (featurep 'xemacs)
+      (byte-compiler-options (warnings (- unused-vars)))))
 
 ;; Define SMB method ...
 (defcustom tramp-smb-method "smb"
@@ -53,7 +52,12 @@
 ;; Add a default for `tramp-default-method-alist'. Rule: If there is
 ;; a domain in USER, it must be the SMB method.
 (add-to-list 'tramp-default-method-alist
-            (list "" "%" tramp-smb-method))
+            `(nil "%" ,tramp-smb-method))
+
+;; Add a default for `tramp-default-user-alist'. Rule: For the SMB method,
+;; the anonymous user is chosen.
+(add-to-list 'tramp-default-user-alist
+            `(,tramp-smb-method nil ""))
 
 ;; Add completion function for SMB method.
 (tramp-set-completion-function
@@ -69,11 +73,13 @@
   "Regexp used as prompt in smbclient.")
 
 (defconst tramp-smb-errors
+  ;; `regexp-opt' not possible because of first string.
   (mapconcat
    'identity
-   '(; Connection error
+   '(;; Connection error / timeout
      "Connection to \\S-+ failed"
-     ; Samba
+     "Read from server failed, maybe it closed the connection"
+     ;; Samba
      "ERRDOS"
      "ERRSRV"
      "ERRbadfile"
@@ -82,34 +88,48 @@
      "ERRnoaccess"
      "ERRnomem"
      "ERRnosuchshare"
-     ; Windows NT 4.0, Windows 5.0 (Windows 2000), Windows 5.1 (Windows XP)
+     ;; Windows 4.0 (Windows NT), Windows 5.0 (Windows 2000),
+     ;; Windows 5.1 (Windows XP), Windows 5.2 (Windows Server 2003)
      "NT_STATUS_ACCESS_DENIED"
      "NT_STATUS_ACCOUNT_LOCKED_OUT"
      "NT_STATUS_BAD_NETWORK_NAME"
      "NT_STATUS_CANNOT_DELETE"
+     "NT_STATUS_DIRECTORY_NOT_EMPTY"
+     "NT_STATUS_DUPLICATE_NAME"
+     "NT_STATUS_FILE_IS_A_DIRECTORY"
      "NT_STATUS_LOGON_FAILURE"
      "NT_STATUS_NETWORK_ACCESS_DENIED"
      "NT_STATUS_NO_SUCH_FILE"
+     "NT_STATUS_OBJECT_NAME_COLLISION"
      "NT_STATUS_OBJECT_NAME_INVALID"
      "NT_STATUS_OBJECT_NAME_NOT_FOUND"
      "NT_STATUS_SHARING_VIOLATION"
+     "NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE"
      "NT_STATUS_WRONG_PASSWORD")
    "\\|")
   "Regexp for possible error strings of SMB servers.
 Used instead of analyzing error codes of commands.")
 
-(defvar tramp-smb-share nil
-  "Holds the share name for the current buffer.
-This variable is local to each buffer.")
-(make-variable-buffer-local 'tramp-smb-share)
-
-(defvar tramp-smb-share-cache nil
-  "Caches the share names accessible to host related to the current buffer.
-This variable is local to each buffer.")
-(make-variable-buffer-local 'tramp-smb-share-cache)
+(defconst tramp-smb-actions-with-share
+  '((tramp-smb-prompt tramp-action-succeed)
+    (tramp-password-prompt-regexp tramp-action-password)
+    (tramp-wrong-passwd-regexp tramp-action-permission-denied)
+    (tramp-smb-errors tramp-action-permission-denied)
+    (tramp-process-alive-regexp tramp-action-process-alive))
+  "List of pattern/action pairs.
+This list is used for login to SMB servers.
+
+See `tramp-actions-before-shell' for more info.")
+
+(defconst tramp-smb-actions-without-share
+  '((tramp-password-prompt-regexp tramp-action-password)
+    (tramp-wrong-passwd-regexp tramp-action-permission-denied)
+    (tramp-smb-errors tramp-action-permission-denied)
+    (tramp-process-alive-regexp tramp-action-out-of-band))
+  "List of pattern/action pairs.
+This list is used for login to SMB servers.
 
-(defvar tramp-smb-inodes nil
-  "Keeps virtual inodes numbers for SMB files.")
+See `tramp-actions-before-shell' for more info.")
 
 ;; New handlers should be added here.
 (defconst tramp-smb-file-name-handler-alist
@@ -124,8 +144,8 @@
     (directory-file-name . tramp-handle-directory-file-name)
     (directory-files . tramp-smb-handle-directory-files)
     (directory-files-and-attributes . 
tramp-smb-handle-directory-files-and-attributes)
-    (dired-call-process . tramp-smb-not-handled)
-    (dired-compress-file . tramp-smb-not-handled)
+    (dired-call-process . ignore)
+    (dired-compress-file . ignore)
     ;; `dired-uncache' performed by default handler
     ;; `expand-file-name' not necessary because we cannot expand "~/"
     (file-accessible-directory-p . tramp-smb-handle-file-directory-p)
@@ -143,10 +163,10 @@
     (file-name-nondirectory . tramp-handle-file-name-nondirectory)
     ;; `file-name-sans-versions' performed by default handler
     (file-newer-than-file-p . tramp-smb-handle-file-newer-than-file-p)
-    (file-ownership-preserved-p . tramp-smb-not-handled)
+    (file-ownership-preserved-p . ignore)
     (file-readable-p . tramp-smb-handle-file-exists-p)
     (file-regular-p . tramp-handle-file-regular-p)
-    (file-symlink-p . tramp-smb-not-handled)
+    (file-symlink-p . tramp-handle-file-symlink-p)
     ;; `file-truename' performed by default handler
     (file-writable-p . tramp-smb-handle-file-writable-p)
     (find-backup-file-name . tramp-handle-find-backup-file-name)
@@ -157,15 +177,15 @@
     (load . tramp-handle-load)
     (make-directory . tramp-smb-handle-make-directory)
     (make-directory-internal . tramp-smb-handle-make-directory-internal)
-    (make-symbolic-link . tramp-smb-not-handled)
+    (make-symbolic-link . ignore)
     (rename-file . tramp-smb-handle-rename-file)
-    (set-file-modes . tramp-smb-not-handled)
-    (set-visited-file-modtime . tramp-smb-not-handled)
-    (shell-command . tramp-smb-not-handled)
+    (set-file-modes . ignore)
+    (set-visited-file-modtime . ignore)
+    (shell-command . ignore)
     (substitute-in-file-name . tramp-smb-handle-substitute-in-file-name)
     (unhandled-file-name-directory . 
tramp-handle-unhandled-file-name-directory)
-    (vc-registered . tramp-smb-not-handled)
-    (verify-visited-file-modtime . tramp-smb-not-handled)
+    (vc-registered . ignore)
+    (verify-visited-file-modtime . ignore)
     (write-region . tramp-smb-handle-write-region)
 )
   "Alist of handler functions for Tramp SMB method.
@@ -174,13 +194,7 @@
 (defun tramp-smb-file-name-p (filename)
   "Check if it's a filename for SMB servers."
   (let ((v (tramp-dissect-file-name filename)))
-    (string=
-     (tramp-find-method
-      (tramp-file-name-multi-method v)
-      (tramp-file-name-method v)
-      (tramp-file-name-user v)
-      (tramp-file-name-host v))
-     tramp-smb-method)))
+    (string= (tramp-file-name-method v) tramp-smb-method)))
 
 (defun tramp-smb-file-name-handler (operation &rest args)
   "Invoke the SMB related OPERATION.
@@ -188,9 +202,7 @@
 pass to the OPERATION."
   (let ((fn (assoc operation tramp-smb-file-name-handler-alist)))
     (if fn
-       (if (eq (cdr fn) 'tramp-smb-not-handled)
-           (apply (cdr fn) operation args)
-         (save-match-data (apply (cdr fn) args)))
+       (save-match-data (apply (cdr fn) args))
       (tramp-run-real-handler operation args))))
 
 (add-to-list 'tramp-foreign-file-name-handler-alist
@@ -199,14 +211,9 @@
 
 ;; File name primitives
 
-(defun tramp-smb-not-handled (operation &rest args)
-  "Default handler for all functions which are disrecarded."
-  (tramp-message 10 "Won't be handled: %s %s" operation args)
-  nil)
-
 (defun tramp-smb-handle-copy-file
   (filename newname &optional ok-if-already-exists keep-date)
-  "Like `copy-file' for tramp files.
+  "Like `copy-file' for Tramp files.
 KEEP-DATE is not handled in case NEWNAME resides on an SMB server."
   (setq filename (expand-file-name filename)
        newname (expand-file-name newname))
@@ -214,126 +221,135 @@
   (let ((tmpfile (file-local-copy filename)))
 
     (if tmpfile
-       ;; remote filename
+       ;; Remote filename.
        (rename-file tmpfile newname ok-if-already-exists)
 
-      ;; remote newname
+      ;; Remote newname.
       (when (file-directory-p newname)
        (setq newname (expand-file-name
                       (file-name-nondirectory filename) newname)))
+
+      (with-parsed-tramp-file-name newname nil
       (when (and (not ok-if-already-exists)
                 (file-exists-p newname))
-       (error "copy-file: file %s already exists" newname))
+         (tramp-error v 'file-already-exists newname))
 
-      (with-parsed-tramp-file-name newname nil
-       (save-excursion
+       ;; We must also flush the cache of the directory, because
+       ;; file-attributes reads the values from there.
+       (tramp-flush-file-property v (file-name-directory localname))
+       (tramp-flush-file-property v localname)
          (let ((share (tramp-smb-get-share localname))
                (file (tramp-smb-get-localname localname t)))
            (unless share
-             (error "Target `%s' must contain a share name" filename))
-           (tramp-smb-maybe-open-connection user host share)
-           (tramp-message-for-buffer
-            nil tramp-smb-method user host
-            5 "Copying file %s to file %s..." filename newname)
+           (tramp-error
+            v 'file-error "Target `%s' must contain a share name" newname))
+         (tramp-message v 0 "Copying file %s to file %s..." filename newname)
            (if (tramp-smb-send-command
-                user host (format "put %s \"%s\"" filename file))
-               (tramp-message-for-buffer
-                nil tramp-smb-method user host
-                5 "Copying file %s to file %s...done" filename newname)
-             (error "Cannot copy `%s'" filename))))))))
+              v (format "put %s \"%s\"" filename file))
+             (tramp-message
+              v 0 "Copying file %s to file %s...done" filename newname)
+           (tramp-error v 'file-error "Cannot copy `%s'" filename)))))))
 
 (defun tramp-smb-handle-delete-directory (directory)
-  "Like `delete-directory' for tramp files."
+  "Like `delete-directory' for Tramp files."
   (setq directory (directory-file-name (expand-file-name directory)))
   (when (file-exists-p directory)
     (with-parsed-tramp-file-name directory nil
-      (save-excursion
-       (let ((share (tramp-smb-get-share localname))
-             (dir (tramp-smb-get-localname (file-name-directory localname) t))
+      ;; We must also flush the cache of the directory, because
+      ;; file-attributes reads the values from there.
+      (tramp-flush-file-property v (file-name-directory localname))
+      (tramp-flush-directory-property v localname)
+      (let ((dir (tramp-smb-get-localname (file-name-directory localname) t))
              (file (file-name-nondirectory localname)))
-         (tramp-smb-maybe-open-connection user host share)
-         (if (and
-              (tramp-smb-send-command user host (format "cd \"%s\"" dir))
-              (tramp-smb-send-command user host (format "rmdir \"%s\"" file)))
-             ;; Go Home
-             (tramp-smb-send-command user host (format "cd \\"))
+       (unwind-protect
+           (unless (and
+                    (tramp-smb-send-command v (format "cd \"%s\"" dir))
+                    (tramp-smb-send-command v (format "rmdir \"%s\"" file)))
            ;; Error
-           (tramp-smb-send-command user host (format "cd \\"))
-           (error "Cannot delete directory `%s'" directory)))))))
+             (with-current-buffer (tramp-get-connection-buffer v)
+               (goto-char (point-min))
+               (search-forward-regexp tramp-smb-errors nil t)
+               (tramp-error
+                v 'file-error "%s `%s'" (match-string 0) directory)))
+         ;; Always go home
+         (tramp-smb-send-command v (format "cd \\")))))))
 
 (defun tramp-smb-handle-delete-file (filename)
-  "Like `delete-file' for tramp files."
+  "Like `delete-file' for Tramp files."
   (setq filename (expand-file-name filename))
   (when (file-exists-p filename)
     (with-parsed-tramp-file-name filename nil
-      (save-excursion
-       (let ((share (tramp-smb-get-share localname))
-             (dir (tramp-smb-get-localname (file-name-directory localname) t))
+      ;; We must also flush the cache of the directory, because
+      ;; file-attributes reads the values from there.
+      (tramp-flush-file-property v (file-name-directory localname))
+      (tramp-flush-file-property v localname)
+      (let ((dir (tramp-smb-get-localname (file-name-directory localname) t))
              (file (file-name-nondirectory localname)))
-         (tramp-smb-maybe-open-connection user host share)
-         (if (and
-              (tramp-smb-send-command user host (format "cd \"%s\"" dir))
-              (tramp-smb-send-command user host (format "rm \"%s\"" file)))
-             ;; Go Home
-             (tramp-smb-send-command user host (format "cd \\"))
+       (unwind-protect
+           (unless (and
+                    (tramp-smb-send-command v (format "cd \"%s\"" dir))
+                    (tramp-smb-send-command v (format "rm \"%s\"" file)))
            ;; Error
-           (tramp-smb-send-command user host (format "cd \\"))
-           (error "Cannot delete file `%s'" filename)))))))
+             (with-current-buffer (tramp-get-connection-buffer v)
+               (goto-char (point-min))
+               (search-forward-regexp tramp-smb-errors nil t)
+               (tramp-error
+                v 'file-error "%s `%s'" (match-string 0) filename)))
+         ;; Always go home
+         (tramp-smb-send-command v (format "cd \\")))))))
 
 (defun tramp-smb-handle-directory-files
   (directory &optional full match nosort)
-  "Like `directory-files' for tramp files."
-  (setq directory (directory-file-name (expand-file-name directory)))
-  (with-parsed-tramp-file-name directory nil
-    (save-excursion
-      (let* ((share (tramp-smb-get-share localname))
-            (file (tramp-smb-get-localname localname nil))
-            (entries (tramp-smb-get-file-entries user host share file)))
-       ;; Just the file names are needed
-       (setq entries (mapcar 'car entries))
+  "Like `directory-files' for Tramp files."
+  (let ((result (mapcar 'directory-file-name
+                       (file-name-all-completions "" directory))))
        ;; Discriminate with regexp
        (when match
-         (setq entries
+      (setq result
                (delete nil
                        (mapcar (lambda (x) (when (string-match match x) x))
-                               entries))))
-       ;; Make absolute localnames if necessary
+                           result))))
+    ;; Append directory
        (when full
-         (setq entries
-               (mapcar (lambda (x)
-                         (concat (file-name-as-directory directory) x))
-                       entries)))
+      (setq result
+           (mapcar
+            (lambda (x) (expand-file-name x directory))
+            result)))
        ;; Sort them if necessary
-       (unless nosort (setq entries (sort entries 'string-lessp)))
+    (unless nosort (setq result (sort result 'string-lessp)))
        ;; That's it
-       entries))))
+    result))
 
 (defun tramp-smb-handle-directory-files-and-attributes
   (directory &optional full match nosort id-format)
-  "Like `directory-files-and-attributes' for tramp files."
+  "Like `directory-files-and-attributes' for Tramp files."
   (mapcar
    (lambda (x)
      ;; We cannot call `file-attributes' for backward compatibility reasons.
      ;; Its optional parameter ID-FORMAT is introduced with Emacs 22.
      (cons x (tramp-smb-handle-file-attributes
-       (if full x (concat (file-name-as-directory directory) x)) id-format)))
+       (if full x (expand-file-name x directory)) id-format)))
    (directory-files directory full match nosort)))
 
 (defun tramp-smb-handle-file-attributes (filename &optional id-format)
-  "Like `file-attributes' for tramp files."
+  "Like `file-attributes' for Tramp files."
+  ;; Reading just the filename entry via "dir localname" is not
+  ;; possible, because when filename is a directory, some smbclient
+  ;; versions return the content of the directory, and other versions
+  ;; don't.  Therefore, the whole content of the upper directory is
+  ;; retrieved, and the entry of the filename is extracted from.
   (with-parsed-tramp-file-name filename nil
-    (save-excursion
-      (let* ((share (tramp-smb-get-share localname))
-            (file (tramp-smb-get-localname localname nil))
-            (entries (tramp-smb-get-file-entries user host share file))
+    (with-file-property v localname (format "file-attributes-%s" id-format)
+      (let* ((entries (tramp-smb-get-file-entries
+                      (file-name-directory filename)))
             (entry (and entries
-                        (assoc (file-name-nondirectory file) entries)))
+                        (assoc (file-name-nondirectory filename) entries)))
             (uid (if (and id-format (equal id-format 'string)) "nobody" -1))
             (gid (if (and id-format (equal id-format 'string)) "nogroup" -1))
-            (inode (tramp-smb-get-inode share file))
-            (device (tramp-get-device nil tramp-smb-method user host)))
+            (inode (tramp-get-inode filename))
+            (device (tramp-get-device v)))
 
-       ; check result
+        ;; Check result.
        (when entry
          (list (and (string-match "d" (nth 1 entry))
                     t)         ;0 file type
@@ -350,63 +366,42 @@
                device))))))    ;11 file system number
 
 (defun tramp-smb-handle-file-directory-p (filename)
-  "Like `file-directory-p' for tramp files."
-  (with-parsed-tramp-file-name filename nil
-    (save-excursion
-      (let* ((share (tramp-smb-get-share localname))
-            (file (tramp-smb-get-localname localname nil))
-            (entries (tramp-smb-get-file-entries user host share file))
-            (entry (and entries
-                        (assoc (file-name-nondirectory file) entries))))
-       (and entry
-            (string-match "d" (nth 1 entry))
-            t)))))
+  "Like `file-directory-p' for Tramp files."
+  (and (file-exists-p filename)
+       (eq ?d (aref (nth 8 (file-attributes filename)) 0))))
 
 (defun tramp-smb-handle-file-exists-p (filename)
-  "Like `file-exists-p' for tramp files."
-  (with-parsed-tramp-file-name filename nil
-    (save-excursion
-      (let* ((share (tramp-smb-get-share localname))
-            (file (tramp-smb-get-localname localname nil))
-            (entries (tramp-smb-get-file-entries user host share file)))
-       (and entries
-            (member (file-name-nondirectory file) (mapcar 'car entries))
-            t)))))
+  "Like `file-exists-p' for Tramp files."
+  (not (null (file-attributes filename))))
 
 (defun tramp-smb-handle-file-local-copy (filename)
-  "Like `file-local-copy' for tramp files."
+  "Like `file-local-copy' for Tramp files."
   (with-parsed-tramp-file-name filename nil
-    (save-excursion
-      (let ((share (tramp-smb-get-share localname))
-           (file (tramp-smb-get-localname localname t))
+    (let ((file (tramp-smb-get-localname localname t))
            (tmpfil (tramp-make-temp-file filename)))
        (unless (file-exists-p filename)
-         (error "Cannot make local copy of non-existing file `%s'" filename))
-       (tramp-message-for-buffer
-        nil tramp-smb-method user host
-        5 "Fetching %s to tmp file %s..." filename tmpfil)
-       (tramp-smb-maybe-open-connection user host share)
-       (if (tramp-smb-send-command
-            user host (format "get \"%s\" %s" file tmpfil))
-           (tramp-message-for-buffer
-            nil tramp-smb-method user host
-            5 "Fetching %s to tmp file %s...done" filename tmpfil)
-         (error "Cannot make local copy of file `%s'" filename))
-       tmpfil))))
+       (tramp-error
+        v 'file-error
+        "Cannot make local copy of non-existing file `%s'" filename))
+      (tramp-message v 4 "Fetching %s to tmp file %s..." filename tmpfil)
+      (if (tramp-smb-send-command v (format "get \"%s\" %s" file tmpfil))
+         (tramp-message
+          v 4 "Fetching %s to tmp file %s...done" filename tmpfil)
+       (tramp-error
+        v 'file-error
+        "Cannot make local copy of file `%s'" filename))
+      tmpfil)))
 
 ;; This function should return "foo/" for directories and "bar" for
 ;; files.
 (defun tramp-smb-handle-file-name-all-completions (filename directory)
-  "Like `file-name-all-completions' for tramp files."
-  (with-parsed-tramp-file-name directory nil
-    (save-match-data
-      (save-excursion
-       (let* ((share (tramp-smb-get-share localname))
-              (file (tramp-smb-get-localname localname nil))
-              (entries (tramp-smb-get-file-entries user host share file)))
-
+  "Like `file-name-all-completions' for Tramp files."
          (all-completions
           filename
+   (with-parsed-tramp-file-name directory nil
+     (with-file-property v localname "file-name-all-completions"
+       (save-match-data
+        (let ((entries (tramp-smb-get-file-entries directory)))
           (mapcar
            (lambda (x)
              (list
@@ -416,51 +411,59 @@
            entries)))))))
 
 (defun tramp-smb-handle-file-newer-than-file-p (file1 file2)
-  "Like `file-newer-than-file-p' for tramp files."
+  "Like `file-newer-than-file-p' for Tramp files."
   (cond
    ((not (file-exists-p file1)) nil)
    ((not (file-exists-p file2)) t)
-   (t (tramp-smb-time-less-p (file-attributes file2)
-                            (file-attributes file1)))))
+   (t (tramp-time-less-p (nth 5 (file-attributes file2))
+                        (nth 5 (file-attributes file1))))))
 
 (defun tramp-smb-handle-file-writable-p (filename)
-  "Like `file-writable-p' for tramp files."
-  (if (not (file-exists-p filename))
+  "Like `file-writable-p' for Tramp files."
+  (if (file-exists-p filename)
+      (string-match "w" (or (nth 8 (file-attributes filename)) ""))
       (let ((dir (file-name-directory filename)))
        (and (file-exists-p dir)
-            (file-writable-p dir)))
-    (with-parsed-tramp-file-name filename nil
-      (save-excursion
-       (let* ((share (tramp-smb-get-share localname))
-              (file (tramp-smb-get-localname localname nil))
-              (entries (tramp-smb-get-file-entries user host share file))
-              (entry (and entries
-                          (assoc (file-name-nondirectory file) entries))))
-         (and share entry
-              (string-match "w" (nth 1 entry))
-              t))))))
+          (file-writable-p dir)))))
 
 (defun tramp-smb-handle-insert-directory
   (filename switches &optional wildcard full-directory-p)
-  "Like `insert-directory' for tramp files.
-WILDCARD and FULL-DIRECTORY-P are not handled."
+  "Like `insert-directory' for Tramp files."
   (setq filename (expand-file-name filename))
-  (when (file-directory-p filename)
-    ;; This check is a little bit strange, but in `dired-add-entry'
-    ;; this function is called with a non-directory ...
+  (when full-directory-p
+    ;; Called from `dired-add-entry'.
     (setq filename (file-name-as-directory filename)))
   (with-parsed-tramp-file-name filename nil
+    (tramp-flush-file-property v (file-name-directory localname))
     (save-match-data
-      (let* ((share (tramp-smb-get-share localname))
-            (file (tramp-smb-get-localname localname nil))
-            (entries (tramp-smb-get-file-entries user host share file)))
+      (let ((base (file-name-nondirectory filename))
+           ;; We should not destroy the cache entry.
+           (entries (copy-sequence
+                     (tramp-smb-get-file-entries
+                      (file-name-directory filename)))))
+
+       (when wildcard
+         (string-match "\\." base)
+         (setq base (replace-match "\\\\." nil nil base))
+         (string-match "\\*" base)
+         (setq base (replace-match ".*" nil nil base))
+         (string-match "\\?" base)
+         (setq base (replace-match ".?" nil nil base)))
 
-       ;; Delete dummy "" entry, useless entries
+       ;; Filter entries.
        (setq entries
-             (if (file-directory-p filename)
-                 (delq (assoc "" entries) entries)
+             (delq
+              nil
+              (if (or wildcard (zerop (length base)))
+                  ;; Check for matching entries.
+                  (mapcar
+                   (lambda (x)
+                     (when (string-match
+                            (format "^%s" base) (nth 0 x))
+                       x))
+                   entries)
                ;; We just need the only and only entry FILENAME.
-               (list (assoc (file-name-nondirectory filename) entries))))
+                (list (assoc base entries)))))
 
        ;; Sort entries
        (setq entries
@@ -468,14 +471,15 @@
               entries
               (lambda (x y)
                 (if (string-match "t" switches)
-                    ; sort by date
-                    (tramp-smb-time-less-p (nth 3 y) (nth 3 x))
-                  ; sort by name
+                    ;; Sort by date.
+                    (tramp-time-less-p (nth 3 y) (nth 3 x))
+                  ;; Sort by name.
                   (string-lessp (nth 0 x) (nth 0 y))))))
 
-       ;; Print entries
+       ;; Print entries.
        (mapcar
         (lambda (x)
+          (when (not (zerop (length (nth 0 x))))
           (insert
            (format
             "%10s %3d %-8s %-8s %8s %s %s\n"
@@ -483,22 +487,22 @@
             1 "nobody" "nogroup"
             (nth 2 x) ; size
             (format-time-string
-             (if (tramp-smb-time-less-p
-                  (tramp-smb-time-subtract (current-time) (nth 3 x))
-                  tramp-smb-half-a-year)
+               (if (tramp-time-less-p
+                    (tramp-time-subtract (current-time) (nth 3 x))
+                    tramp-half-a-year)
                  "%b %e %R"
                "%b %e  %Y")
              (nth 3 x)) ; date
             (nth 0 x))) ; file name
           (forward-line)
-          (beginning-of-line))
+            (beginning-of-line)))
         entries)))))
 
 (defun tramp-smb-handle-make-directory (dir &optional parents)
-  "Like `make-directory' for tramp files."
+  "Like `make-directory' for Tramp files."
   (setq dir (directory-file-name (expand-file-name dir)))
   (unless (file-name-absolute-p dir)
-    (setq dir (concat default-directory dir)))
+    (setq dir (expand-file-name dir default-directory)))
   (with-parsed-tramp-file-name dir nil
     (save-match-data
       (let* ((share (tramp-smb-get-share localname))
@@ -510,26 +514,28 @@
        (when (file-directory-p ldir)
          (make-directory-internal dir))
        (unless (file-directory-p dir)
-         (error "Couldn't make directory %s" dir))))))
+         (tramp-error v 'file-error "Couldn't make directory %s" dir))))))
 
 (defun tramp-smb-handle-make-directory-internal (directory)
-  "Like `make-directory-internal' for tramp files."
+  "Like `make-directory-internal' for Tramp files."
   (setq directory (directory-file-name (expand-file-name directory)))
   (unless (file-name-absolute-p directory)
-    (setq directory (concat default-directory directory)))
+    (setq directory (expand-file-name directory default-directory)))
   (with-parsed-tramp-file-name directory nil
     (save-match-data
-      (let* ((share (tramp-smb-get-share localname))
-            (file (tramp-smb-get-localname localname nil)))
+      (let* ((file (tramp-smb-get-localname localname t)))
        (when (file-directory-p (file-name-directory directory))
-         (tramp-smb-maybe-open-connection user host share)
-         (tramp-smb-send-command user host (format "mkdir \"%s\"" file)))
+         (tramp-smb-send-command v (format "mkdir \"%s\"" file))
+         ;; We must also flush the cache of the directory, because
+         ;; file-attributes reads the values from there.
+         (tramp-flush-file-property v (file-name-directory localname)))
        (unless (file-directory-p directory)
-         (error "Couldn't make directory %s" directory))))))
+         (tramp-error
+          v 'file-error "Couldn't make directory %s" directory))))))
 
 (defun tramp-smb-handle-rename-file
   (filename newname &optional ok-if-already-exists)
-  "Like `rename-file' for tramp files."
+  "Like `rename-file' for Tramp files."
   (setq filename (expand-file-name filename)
        newname (expand-file-name newname))
 
@@ -543,29 +549,26 @@
       (when (file-directory-p newname)
        (setq newname (expand-file-name
                      (file-name-nondirectory filename) newname)))
-      (when (and (not ok-if-already-exists)
-                (file-exists-p newname))
-         (error "rename-file: file %s already exists" newname))
 
       (with-parsed-tramp-file-name newname nil
-       (save-excursion
-         (let ((share (tramp-smb-get-share localname))
-               (file (tramp-smb-get-localname localname t)))
-           (tramp-smb-maybe-open-connection user host share)
-           (tramp-message-for-buffer
-            nil tramp-smb-method user host
-            5 "Copying file %s to file %s..." filename newname)
-           (if (tramp-smb-send-command
-                user host (format "put %s \"%s\"" filename file))
-               (tramp-message-for-buffer
-                nil tramp-smb-method user host
-                5 "Copying file %s to file %s...done" filename newname)
-             (error "Cannot rename `%s'" filename)))))))
+       (when (and (not ok-if-already-exists)
+                  (file-exists-p newname))
+         (tramp-error v 'file-already-exists newname))
+       ;; We must also flush the cache of the directory, because
+       ;; file-attributes reads the values from there.
+       (tramp-flush-file-property v (file-name-directory localname))
+       (tramp-flush-file-property v localname)
+       (let ((file (tramp-smb-get-localname localname t)))
+         (tramp-message v 0 "Copying file %s to file %s..." filename newname)
+         (if (tramp-smb-send-command v (format "put %s \"%s\"" filename file))
+             (tramp-message
+              v 0 "Copying file %s to file %s...done" filename newname)
+           (tramp-error v 'file-error "Cannot rename `%s'" filename))))))
 
   (delete-file filename))
 
 (defun tramp-smb-handle-substitute-in-file-name (filename)
-  "Like `handle-substitute-in-file-name' for tramp files.
+  "Like `handle-substitute-in-file-name' for Tramp files.
 Catches errors for shares like \"C$/\", which are common in Microsoft Windows."
   (condition-case nil
       (tramp-run-real-handler 'substitute-in-file-name (list filename))
@@ -573,20 +576,23 @@
 
 (defun tramp-smb-handle-write-region
   (start end filename &optional append visit lockname confirm)
-  "Like `write-region' for tramp files."
-  (unless (eq append nil)
-    (error "Cannot append to file using tramp (`%s')" filename))
+  "Like `write-region' for Tramp files."
   (setq filename (expand-file-name filename))
+  (with-parsed-tramp-file-name filename nil
+    (unless (eq append nil)
+      (tramp-error
+        v 'file-error "Cannot append to file using tramp (`%s')" filename))
   ;; XEmacs takes a coding system as the seventh argument, not `confirm'
   (when (and (not (featurep 'xemacs))
             confirm (file-exists-p filename))
     (unless (y-or-n-p (format "File %s exists; overwrite anyway? "
                               filename))
-      (error "File not overwritten")))
-  (with-parsed-tramp-file-name filename nil
-    (save-excursion
-      (let ((share (tramp-smb-get-share localname))
-           (file (tramp-smb-get-localname localname t))
+       (tramp-error v 'file-error "File not overwritten")))
+    ;; We must also flush the cache of the directory, because
+    ;; file-attributes reads the values from there.
+    (tramp-flush-file-property v (file-name-directory localname))
+    (tramp-flush-file-property v localname)
+    (let ((file (tramp-smb-get-localname localname t))
            (curbuf (current-buffer))
            tmpfil)
        ;; Write region into a tmp file.
@@ -600,23 +606,19 @@
             (list start end tmpfil append 'no-message lockname confirm)
           (list start end tmpfil append 'no-message lockname)))
 
-       (tramp-smb-maybe-open-connection user host share)
-       (tramp-message-for-buffer
-        nil tramp-smb-method user host
-        5 "Writing tmp file %s to file %s..." tmpfil filename)
-       (if (tramp-smb-send-command
-            user host (format "put %s \"%s\"" tmpfil file))
-           (tramp-message-for-buffer
-            nil tramp-smb-method user host
-            5 "Writing tmp file %s to file %s...done" tmpfil filename)
-         (error "Cannot write `%s'" filename))
+      (tramp-message v 5 "Writing tmp file %s to file %s..." tmpfil filename)
+      (if (tramp-smb-send-command v (format "put %s \"%s\"" tmpfil file))
+         (tramp-message
+          v 5 "Writing tmp file %s to file %s...done" tmpfil filename)
+       (tramp-error v 'file-error "Cannot write `%s'" filename))
 
        (delete-file tmpfil)
        (unless (equal curbuf (current-buffer))
-         (error "Buffer has changed from `%s' to `%s'"
-                curbuf (current-buffer)))
+       (tramp-error
+        v 'file-error
+        "Buffer has changed from `%s' to `%s'" curbuf (current-buffer)))
        (when (eq visit t)
-         (set-visited-file-modtime))))))
+       (set-visited-file-modtime)))))
 
 
 ;; Internal file name functions
@@ -652,51 +654,53 @@
 
 ;; Share names of a host are cached. It is very unlikely that the
 ;; shares do change during connection.
-(defun tramp-smb-get-file-entries (user host share localname)
-  "Read entries which match LOCALNAME.
+(defun tramp-smb-get-file-entries (directory)
+  "Read entries which match DIRECTORY.
 Either the shares are listed, or the `dir' command is executed.
-Only entries matching the localname are returned.
 Result is a list of (LOCALNAME MODE SIZE MONTH DAY TIME YEAR)."
-  (save-excursion
-    (save-match-data
-      (let ((base (or (and (> (length localname) 0)
-                          (string-match "\\([^/]+\\)$" localname)
-                          (regexp-quote (match-string 1 localname)))
-                     ""))
+  (with-parsed-tramp-file-name directory nil
+    (setq localname (or localname "/"))
+    (with-file-property v localname "file-entries"
+      (with-current-buffer (tramp-get-buffer v)
+       (let* ((share (tramp-smb-get-share localname))
+              (file (tramp-smb-get-localname localname nil))
+              (cache (tramp-get-connection-property v "share-cache" nil))
            res entry)
-       (set-buffer (tramp-get-buffer nil tramp-smb-method user host))
-       (if (and (not share) tramp-smb-share-cache)
+
+         (if (and (not share) cache)
            ;; Return cached shares
-           (setq res tramp-smb-share-cache)
+             (setq res cache)
+
          ;; Read entries
-         (tramp-smb-maybe-open-connection user host share)
-         (when share
-           (tramp-smb-send-command
-            user host
-            (format "dir %s"
-                    (if (zerop (length localname)) "" (concat "\"" localname 
"*\"")))))
-         (goto-char (point-min))
+           (setq file (file-name-as-directory file))
+           (when (string-match "^\\./" file)
+             (setq file (substring file 1)))
+           (if share
+               (tramp-smb-send-command v (format "dir \"%s*\"" file))
+             ;; `tramp-smb-maybe-open-connection' lists also the share names
+             (tramp-smb-maybe-open-connection v))
+
          ;; Loop the listing
+           (goto-char (point-min))
          (unless (re-search-forward tramp-smb-errors nil t)
            (while (not (eobp))
              (setq entry (tramp-smb-read-file-entry share))
              (forward-line)
              (when entry (add-to-list 'res entry))))
-         (unless share
+
            ;; Cache share entries
-           (setq tramp-smb-share-cache res)))
+           (unless share
+             (tramp-set-connection-property v "share-cache" res)))
 
        ;; Add directory itself
        (add-to-list 'res '("" "drwxrwxrwx" 0 (0 0)))
 
        ;; There's a very strange error (debugged with XEmacs 21.4.14)
-       ;; If there's no short delay, it returns nil.  No idea about
+         ;; If there's no short delay, it returns nil.  No idea about.
        (when (featurep 'xemacs) (sleep-for 0.01))
 
-       ;; Check for matching entries
-       (delq nil (mapcar
-                  (lambda (x) (and (string-match base (nth 0 x)) x))
-                  res))))))
+         ;; Return entries
+         (delq nil res))))))
 
 ;; Return either a share name (if SHARE is nil), or a file name
 ;;
@@ -721,7 +725,7 @@
 ;; \s-                                    - space delimeter
 ;; \w\{3,3\}                              - month
 ;; \s-                                    - space delimeter
-;; [ 19][0-9]                             - day
+;; [ 12][0-9]                             - day
 ;; \s-                                    - space delimeter
 ;; [0-9]\{2,2\}:[0-9]\{2,2\}:[0-9]\{2,2\} - time
 ;; \s-                                    - space delimeter
@@ -756,18 +760,20 @@
   "Parse entry in SMB output buffer.
 If SHARE is result, entries are of type dir. Otherwise, shares are listed.
 Result is the list (LOCALNAME MODE SIZE MTIME)."
-  (let ((line (buffer-substring (point) (tramp-point-at-eol)))
+;; We are called from `tramp-smb-get-file-entries', which sets the
+;; current buffer.
+  (let ((line (buffer-substring (point) (tramp-line-end-position)))
        localname mode size month day hour min sec year mtime)
 
     (if (not share)
 
-       ; Read share entries
-       (when (string-match "^\\s-+\\(\\S-+\\)\\s-+Disk" line)
+       ;; Read share entries.
+       (when (string-match "^\\s-+\\(\\S-\\(.*\\S-\\)?\\)\\s-+Disk" line)
          (setq localname (match-string 1 line)
                mode "dr-xr-xr-x"
                size 0))
 
-      ; Real listing
+      ;; Real listing.
       (block nil
 
        ;; year
@@ -833,84 +839,68 @@
            (if (and sec min hour day month year)
                (encode-time
                 sec min hour day
-                (cdr (assoc (downcase month) tramp-smb-parse-time-months))
+                (cdr (assoc (downcase month) tramp-parse-time-months))
                 year)
              '(0 0)))
       (list localname mode size mtime))))
 
-;; Inodes don't exist for SMB files.  Therefore we must generate virtual ones.
-;; Used in `find-buffer-visiting'.
-;; The method applied might be not so efficient (Ange-FTP uses hashes). But
-;; performance isn't the major issue given that file transfer will take time.
-
-(defun tramp-smb-get-inode (share file)
-  "Returns the virtual inode number.
-If it doesn't exist, generate a new one."
-  (let ((string (concat share "/" (directory-file-name file))))
-    (unless (assoc string tramp-smb-inodes)
-      (add-to-list 'tramp-smb-inodes
-                  (list string (length tramp-smb-inodes))))
-    (nth 1 (assoc string tramp-smb-inodes))))
-
 
 ;; Connection functions
 
-(defun tramp-smb-send-command (user host command)
-  "Send the COMMAND to USER at HOST (logged into an SMB session).
-Erases temporary buffer before sending the command.  Returns nil if
-there has been an error message from smbclient."
-  (save-excursion
-    (set-buffer (tramp-get-buffer nil tramp-smb-method user host))
-    (erase-buffer)
-    (tramp-send-command nil tramp-smb-method user host command nil t)
-    (tramp-smb-wait-for-output user host)))
+(defun tramp-smb-send-command (vec command)
+  "Send the COMMAND to connection VEC.
+Returns nil if there has been an error message from smbclient."
+  (tramp-smb-maybe-open-connection vec)
+  (tramp-message vec 6 "%s" command)
+  (tramp-send-string vec command)
+  (tramp-smb-wait-for-output vec))
 
-(defun tramp-smb-maybe-open-connection (user host share)
-  "Maybe open a connection to HOST, logging in as USER, using 
`tramp-smb-program'.
+(defun tramp-smb-maybe-open-connection (vec)
+  "Maybe open a connection to HOST, log in as USER, using `tramp-smb-program'.
 Does not do anything if a connection is already open, but re-opens the
 connection if a previous connection has died for some reason."
-  (let ((process-connection-type tramp-process-connection-type)
-       (p (get-buffer-process
-           (tramp-get-buffer nil tramp-smb-method user host))))
-    (save-excursion
-      (set-buffer (tramp-get-buffer nil tramp-smb-method user host))
-      ;; Check whether it is still the same share
-      (unless (and p (processp p) (string-equal tramp-smb-share share))
-       (when (and p (processp p))
-         (delete-process p)
-         (setq p nil)))
+  (let* ((share (tramp-smb-get-share (tramp-file-name-localname vec)))
+        (buf (tramp-get-buffer vec))
+        (p (get-buffer-process buf)))
+
       ;; If too much time has passed since last command was sent, look
-      ;; whether process is still alive.  If it isn't, kill it.
-      (when (and tramp-last-cmd-time
-                (> (tramp-time-diff (current-time) tramp-last-cmd-time) 60)
-                p (processp p) (memq (process-status p) '(run open)))
-       (unless (and p (processp p) (memq (process-status p) '(run open)))
+    ;; whether has been an error message; maybe due to connection timeout.
+    (with-current-buffer buf
+      (goto-char (point-min))
+      (when (and (> (tramp-time-diff
+                    (current-time)
+                    (tramp-get-connection-property
+                     p "last-cmd-time" '(0 0 0)))
+                   60)
+                p (processp p) (memq (process-status p) '(run open))
+                (re-search-forward tramp-smb-errors nil t))
          (delete-process p)
-         (setq p nil))))
-    (unless (and p (processp p) (memq (process-status p) '(run open)))
-      (when (and p (processp p))
-        (delete-process p))
-      (tramp-smb-open-connection user host share))))
-
-(defun tramp-smb-open-connection (user host share)
-  "Open a connection using `tramp-smb-program'.
-This starts the command `smbclient //HOST/SHARE -U USER', then waits
-for a remote password prompt.  It queries the user for the password,
-then sends the password to the remote host.
+       (setq p nil)))
 
-Domain names in USER and port numbers in HOST are acknowledged."
+    ;; Check whether it is still the same share.
+    (unless
+       (and p (processp p) (memq (process-status p) '(run open))
+            (string-equal
+             share
+             (tramp-get-connection-property p "smb-share" "")))
 
-  (when (and (fboundp 'executable-find)
-            (not (funcall 'executable-find tramp-smb-program)))
+      (save-match-data
+       ;; There might be unread output from checking for share names.
+       (when buf (with-current-buffer buf (erase-buffer)))
+       (when (and p (processp p)) (delete-process p))
+
+       (unless (let ((default-directory
+                       (tramp-temporary-file-directory)))
+                 (executable-find tramp-smb-program))
     (error "Cannot find command %s in %s" tramp-smb-program exec-path))
 
-  (save-match-data
-    (let* ((buffer (tramp-get-buffer nil tramp-smb-method user host))
+       (let* ((user (tramp-file-name-user vec))
+              (host (tramp-file-name-host vec))
           (real-user user)
           (real-host host)
           domain port args)
 
-      ; Check for domain ("user%domain") and port ("host#port")
+         ;; Check for domain ("user%domain") and port ("host#port").
       (when (and user (string-match "\\(.+\\)%\\(.+\\)" user))
        (setq real-user (or (match-string 1 user) user)
              domain (match-string 2 user)))
@@ -923,49 +913,60 @@
          (setq args (list (concat "//" real-host "/" share)))
        (setq args (list "-L" real-host )))
 
-      (if real-user
+         (if (not (zerop (length real-user)))
          (setq args (append args (list "-U" real-user)))
        (setq args (append args (list "-N"))))
 
       (when domain (setq args (append args (list "-W" domain))))
       (when port   (setq args (append args (list "-p" port))))
+         (setq args (append args (list "-s" "/dev/null")))
 
-      ; OK, let's go
-      (tramp-pre-connection nil tramp-smb-method user host tramp-chunksize)
-      (tramp-message 7 "Opening connection for //address@hidden/%s..."
-                    user host (or share ""))
-
-      (let* ((default-directory (tramp-temporary-file-directory))
-            ;; If we omit the conditional here, then we would use
-            ;; `undecided-dos' in some cases.  With the conditional,
-            ;; we use nil in these cases.  Which one is right?
-            (coding-system-for-read (unless (and (not (featurep 'xemacs))
-                                                 (> emacs-major-version 20))
-                                      tramp-dos-coding-system))
-            (p (apply #'start-process (buffer-name buffer) buffer
-                      tramp-smb-program args)))
-
-       (tramp-message 9 "Started process %s" (process-command p))
+         ;; OK, let's go.
+         (tramp-message
+          vec 3 "Opening connection for //%s%s/%s..."
+          (if (not (zerop (length user))) (concat user "@") "")
+          host (or share ""))
+
+         (let* ((coding-system-for-read nil)
+                (process-connection-type tramp-process-connection-type)
+                (p (let ((default-directory (tramp-temporary-file-directory)))
+                     (apply #'start-process
+                            (tramp-buffer-name vec) (tramp-get-buffer vec)
+                            tramp-smb-program args))))
+
+           (tramp-message
+            vec 6 "%s" (mapconcat 'identity (process-command p) " "))
+           (set-process-sentinel p 'tramp-flush-connection-property)
        (tramp-set-process-query-on-exit-flag p nil)
-       (set-buffer buffer)
-       (setq tramp-smb-share share)
+           (tramp-set-connection-property p "smb-share" share)
+
+           ;; Set variables for computing the prompt for reading password.
+           (setq tramp-current-method tramp-smb-method
+                 tramp-current-user user
+                 tramp-current-host host)
+
+           ;; Set chunksize.  Otherwise, `tramp-send-string' might
+           ;; try it itself.
+           (tramp-set-connection-property p "chunksize" tramp-chunksize)
+
+           ;; Play login scenario.
+           (tramp-process-actions
+            p vec
+            (if share
+                tramp-smb-actions-with-share
+              tramp-smb-actions-without-share))
 
-        ; send password
-       (when real-user
-         (let ((pw-prompt "Password:"))
-           (tramp-message 9 "Sending password")
-           (tramp-enter-password p pw-prompt user host)))
-
-       (unless (tramp-smb-wait-for-output user host)
-         (tramp-clear-passwd user host)
-         (error "Cannot open connection //address@hidden/%s"
-                user host (or share "")))))))
+           (tramp-message
+            vec 3 "Opening connection for //%s%s/%s...done"
+            (if (not (zerop (length user))) (concat user "@") "")
+            host (or share ""))))))))
 
 ;; We don't use timeouts.  If needed, the caller shall wrap around.
-(defun tramp-smb-wait-for-output (user host)
+(defun tramp-smb-wait-for-output (vec)
   "Wait for output from smbclient command.
 Returns nil if an error message has appeared."
-  (let ((proc (get-buffer-process (current-buffer)))
+  (with-current-buffer (tramp-get-buffer vec)
+    (let ((p (get-buffer-process (current-buffer)))
        (found (progn (goto-char (point-min))
                      (re-search-forward tramp-smb-prompt nil t)))
        (err   (progn (goto-char (point-min))
@@ -974,10 +975,10 @@
     ;; Algorithm: get waiting output.  See if last line contains
     ;; tramp-smb-prompt sentinel or tramp-smb-errors strings.
     ;; If not, wait a bit and again get waiting output.
-    (while (not found)
+      (while (and (not found) (not err))
 
       ;; Accept pending output.
-      (tramp-accept-process-output proc)
+       (tramp-accept-process-output p)
 
       ;; Search for prompt.
       (goto-char (point-min))
@@ -987,65 +988,37 @@
       (goto-char (point-min))
       (setq err (re-search-forward tramp-smb-errors nil t)))
 
-    ;; Add output to debug buffer if appropriate.
-    (when tramp-debug-buffer
-      (append-to-buffer
-       (tramp-get-debug-buffer nil tramp-smb-method user host)
-       (point-min) (point-max)))
-
-    ;; Return value is whether no error message has appeared.
-    (not err)))
+      ;; When the process is still alive, read pending output.
+      (while (and (not found) (memq (process-status p) '(run open)))
 
+       ;; Accept pending output.
+       (tramp-accept-process-output p)
 
-;; Snarfed code from time-date.el and parse-time.el
-
-(defconst tramp-smb-half-a-year '(241 17024)
-"Evaluated by \"(days-to-time 183)\".")
+       ;; Search for prompt.
+       (goto-char (point-min))
+       (setq found (re-search-forward tramp-smb-prompt nil t)))
 
-(defconst tramp-smb-parse-time-months '(("jan" . 1) ("feb" . 2) ("mar" . 3)
-                           ("apr" . 4) ("may" . 5) ("jun" . 6)
-                           ("jul" . 7) ("aug" . 8) ("sep" . 9)
-                           ("oct" . 10) ("nov" . 11) ("dec" . 12))
-"Alist mapping month names to integers.")
-
-(defun tramp-smb-time-less-p (t1 t2)
-  "Say whether time value T1 is less than time value T2."
-  (unless t1 (setq t1 '(0 0)))
-  (unless t2 (setq t2 '(0 0)))
-  (or (< (car t1) (car t2))
-      (and (= (car t1) (car t2))
-          (< (nth 1 t1) (nth 1 t2)))))
-
-(defun tramp-smb-time-subtract (t1 t2)
-  "Subtract two time values.
-Return the difference in the format of a time value."
-  (unless t1 (setq t1 '(0 0)))
-  (unless t2 (setq t2 '(0 0)))
-  (let ((borrow (< (cadr t1) (cadr t2))))
-    (list (- (car t1) (car t2) (if borrow 1 0))
-         (- (+ (if borrow 65536 0) (cadr t1)) (cadr t2)))))
+      ;; Return value is whether no error message has appeared.
+      (tramp-message vec 6 "\n%s" (buffer-string))
+      (not err))))
 
 
 (provide 'tramp-smb)
 
 ;;; TODO:
 
-;; * Provide a local smb.conf. The default one might not be readable.
 ;; * Error handling in case password is wrong.
 ;; * Read password from "~/.netrc".
 ;; * Return more comprehensive file permission string.  Think whether it is
 ;;   possible to implement `set-file-modes'.
-;; * Handle WILDCARD and FULL-DIRECTORY-P in
-;;   `tramp-smb-handle-insert-directory'.
 ;; * Handle links (FILENAME.LNK).
 ;; * Maybe local tmp files should have the same extension like the original
 ;;   files.  Strange behaviour with jka-compr otherwise?
-;; * Copy files in dired from SMB to another method doesn't work.
 ;; * Try to remove the inclusion of dummy "" directory.  Seems to be at
 ;;   several places, especially in `tramp-smb-handle-insert-directory'.
-;; * Provide variables for debug.
 ;; * (RMS) Use unwind-protect to clean up the state so as to make the state
 ;;   regular again.
+;; * Make it multi-hop capable.
 
 ;;; arch-tag: fcc9dbec-7503-4d73-b638-3c8aa59575f5
 ;;; tramp-smb.el ends here




reply via email to

[Prev in Thread] Current Thread [Next in Thread]