comparison lisp/net/tramp.el @ 104866:3d5d2850cbef

* net/tramp.el (tramp-perl-file-attributes): Print "nil" when lstat fails. (tramp-do-file-attributes-with-ls): Check for file existence at remote end. (tramp-do-file-attributes-with-stat): Likewise. (tramp-convert-file-attributes): Return nil when attr is nil.
author Michael Albinus <michael.albinus@gmx.de>
date Sun, 06 Sep 2009 14:18:54 +0000
parents 5d5bbec3b1c8
children ebd8445069df
comparison
equal deleted inserted replaced
104865:68c0ccdf0374 104866:3d5d2850cbef
1592 ;; The device number is returned as "-1", because there will be a virtual 1592 ;; The device number is returned as "-1", because there will be a virtual
1593 ;; device number set in `tramp-handle-file-attributes'. 1593 ;; device number set in `tramp-handle-file-attributes'.
1594 (defconst tramp-perl-file-attributes 1594 (defconst tramp-perl-file-attributes
1595 "%s -e ' 1595 "%s -e '
1596 @stat = lstat($ARGV[0]); 1596 @stat = lstat($ARGV[0]);
1597 if (!@stat) {
1598 print \"nil\\n\";
1599 exit 0;
1600 }
1597 if (($stat[2] & 0170000) == 0120000) 1601 if (($stat[2] & 0170000) == 0120000)
1598 { 1602 {
1599 $type = readlink($ARGV[0]); 1603 $type = readlink($ARGV[0]);
1600 $type = \"\\\"$type\\\"\"; 1604 $type = \"\\\"$type\\\"\";
1601 } 1605 }
2522 res-inode res-filemodes res-numlinks 2526 res-inode res-filemodes res-numlinks
2523 res-uid res-gid res-size res-symlink-target) 2527 res-uid res-gid res-size res-symlink-target)
2524 (tramp-message vec 5 "file attributes with ls: %s" localname) 2528 (tramp-message vec 5 "file attributes with ls: %s" localname)
2525 (tramp-send-command 2529 (tramp-send-command
2526 vec 2530 vec
2527 (format "%s %s %s" 2531 (format "(%s %s || %s -h %s) && %s %s %s"
2532 (tramp-get-file-exists-command vec)
2533 (tramp-shell-quote-argument localname)
2534 (tramp-get-test-command vec)
2535 (tramp-shell-quote-argument localname)
2528 (tramp-get-ls-command vec) 2536 (tramp-get-ls-command vec)
2529 (if (eq id-format 'integer) "-ildn" "-ild") 2537 (if (eq id-format 'integer) "-ildn" "-ild")
2530 (tramp-shell-quote-argument localname))) 2538 (tramp-shell-quote-argument localname)))
2531 ;; parse `ls -l' output ... 2539 ;; parse `ls -l' output ...
2532 (with-current-buffer (tramp-get-buffer vec) 2540 (with-current-buffer (tramp-get-buffer vec)
2533 (goto-char (point-min)) 2541 (when (> (buffer-size) 0)
2534 ;; ... inode 2542 (goto-char (point-min))
2535 (setq res-inode 2543 ;; ... inode
2536 (condition-case err 2544 (setq res-inode
2537 (read (current-buffer)) 2545 (condition-case err
2538 (invalid-read-syntax 2546 (read (current-buffer))
2539 (when (and (equal (cadr err) 2547 (invalid-read-syntax
2540 "Integer constant overflow in reader") 2548 (when (and (equal (cadr err)
2541 (string-match 2549 "Integer constant overflow in reader")
2542 "^[0-9]+\\([0-9][0-9][0-9][0-9][0-9]\\)\\'" 2550 (string-match
2543 (car (cddr err)))) 2551 "^[0-9]+\\([0-9][0-9][0-9][0-9][0-9]\\)\\'"
2544 (let* ((big (read (substring (car (cddr err)) 0 2552 (car (cddr err))))
2545 (match-beginning 1)))) 2553 (let* ((big (read (substring (car (cddr err)) 0
2546 (small (read (match-string 1 (car (cddr err))))) 2554 (match-beginning 1))))
2547 (twiddle (/ small 65536))) 2555 (small (read (match-string 1 (car (cddr err)))))
2548 (cons (+ big twiddle) 2556 (twiddle (/ small 65536)))
2549 (- small (* twiddle 65536)))))))) 2557 (cons (+ big twiddle)
2550 ;; ... file mode flags 2558 (- small (* twiddle 65536))))))))
2551 (setq res-filemodes (symbol-name (read (current-buffer)))) 2559 ;; ... file mode flags
2552 ;; ... number links 2560 (setq res-filemodes (symbol-name (read (current-buffer))))
2553 (setq res-numlinks (read (current-buffer))) 2561 ;; ... number links
2554 ;; ... uid and gid 2562 (setq res-numlinks (read (current-buffer)))
2555 (setq res-uid (read (current-buffer))) 2563 ;; ... uid and gid
2556 (setq res-gid (read (current-buffer))) 2564 (setq res-uid (read (current-buffer)))
2557 (if (eq id-format 'integer) 2565 (setq res-gid (read (current-buffer)))
2558 (progn 2566 (if (eq id-format 'integer)
2559 (unless (numberp res-uid) (setq res-uid -1)) 2567 (progn
2560 (unless (numberp res-gid) (setq res-gid -1))) 2568 (unless (numberp res-uid) (setq res-uid -1))
2561 (progn 2569 (unless (numberp res-gid) (setq res-gid -1)))
2562 (unless (stringp res-uid) (setq res-uid (symbol-name res-uid))) 2570 (progn
2563 (unless (stringp res-gid) (setq res-gid (symbol-name res-gid))))) 2571 (unless (stringp res-uid) (setq res-uid (symbol-name res-uid)))
2564 ;; ... size 2572 (unless (stringp res-gid) (setq res-gid (symbol-name res-gid)))))
2565 (setq res-size (read (current-buffer))) 2573 ;; ... size
2566 ;; From the file modes, figure out other stuff. 2574 (setq res-size (read (current-buffer)))
2567 (setq symlinkp (eq ?l (aref res-filemodes 0))) 2575 ;; From the file modes, figure out other stuff.
2568 (setq dirp (eq ?d (aref res-filemodes 0))) 2576 (setq symlinkp (eq ?l (aref res-filemodes 0)))
2569 ;; if symlink, find out file name pointed to 2577 (setq dirp (eq ?d (aref res-filemodes 0)))
2570 (when symlinkp 2578 ;; if symlink, find out file name pointed to
2571 (search-forward "-> ") 2579 (when symlinkp
2572 (setq res-symlink-target 2580 (search-forward "-> ")
2573 (buffer-substring (point) (tramp-compat-line-end-position)))) 2581 (setq res-symlink-target
2574 ;; return data gathered 2582 (buffer-substring (point) (tramp-compat-line-end-position))))
2575 (list 2583 ;; return data gathered
2576 ;; 0. t for directory, string (name linked to) for symbolic 2584 (list
2577 ;; link, or nil. 2585 ;; 0. t for directory, string (name linked to) for symbolic
2578 (or dirp res-symlink-target) 2586 ;; link, or nil.
2579 ;; 1. Number of links to file. 2587 (or dirp res-symlink-target)
2580 res-numlinks 2588 ;; 1. Number of links to file.
2581 ;; 2. File uid. 2589 res-numlinks
2582 res-uid 2590 ;; 2. File uid.
2583 ;; 3. File gid. 2591 res-uid
2584 res-gid 2592 ;; 3. File gid.
2585 ;; 4. Last access time, as a list of two integers. First 2593 res-gid
2586 ;; integer has high-order 16 bits of time, second has low 16 2594 ;; 4. Last access time, as a list of two integers. First
2587 ;; bits. 2595 ;; integer has high-order 16 bits of time, second has low 16
2588 ;; 5. Last modification time, likewise. 2596 ;; bits.
2589 ;; 6. Last status change time, likewise. 2597 ;; 5. Last modification time, likewise.
2590 '(0 0) '(0 0) '(0 0) ;CCC how to find out? 2598 ;; 6. Last status change time, likewise.
2591 ;; 7. Size in bytes (-1, if number is out of range). 2599 '(0 0) '(0 0) '(0 0) ;CCC how to find out?
2592 res-size 2600 ;; 7. Size in bytes (-1, if number is out of range).
2593 ;; 8. File modes, as a string of ten letters or dashes as in ls -l. 2601 res-size
2594 res-filemodes 2602 ;; 8. File modes, as a string of ten letters or dashes as in ls -l.
2595 ;; 9. t if file's gid would change if file were deleted and 2603 res-filemodes
2596 ;; recreated. Will be set in `tramp-convert-file-attributes' 2604 ;; 9. t if file's gid would change if file were deleted and
2597 t 2605 ;; recreated. Will be set in `tramp-convert-file-attributes'
2598 ;; 10. inode number. 2606 t
2599 res-inode 2607 ;; 10. inode number.
2600 ;; 11. Device number. Will be replaced by a virtual device number. 2608 res-inode
2601 -1 2609 ;; 11. Device number. Will be replaced by a virtual device number.
2602 )))) 2610 -1
2611 )))))
2603 2612
2604 (defun tramp-do-file-attributes-with-perl 2613 (defun tramp-do-file-attributes-with-perl
2605 (vec localname &optional id-format) 2614 (vec localname &optional id-format)
2606 "Implement `file-attributes' for Tramp files using a Perl script." 2615 "Implement `file-attributes' for Tramp files using a Perl script."
2607 (tramp-message vec 5 "file attributes with perl: %s" localname) 2616 (tramp-message vec 5 "file attributes with perl: %s" localname)
2617 "Implement `file-attributes' for Tramp files using stat(1) command." 2626 "Implement `file-attributes' for Tramp files using stat(1) command."
2618 (tramp-message vec 5 "file attributes with stat: %s" localname) 2627 (tramp-message vec 5 "file attributes with stat: %s" localname)
2619 (tramp-send-command-and-read 2628 (tramp-send-command-and-read
2620 vec 2629 vec
2621 (format 2630 (format
2622 "%s -c '((\"%%N\") %%h %s %s %%X.0 %%Y.0 %%Z.0 %%s.0 \"%%A\" t %%i.0 -1)' %s" 2631 "((%s %s || %s -h %s) && %s -c '((\"%%N\") %%h %s %s %%X.0 %%Y.0 %%Z.0 %%s.0 \"%%A\" t %%i.0 -1)' %s || echo nil)"
2632 (tramp-get-file-exists-command vec)
2633 (tramp-shell-quote-argument localname)
2634 (tramp-get-test-command vec)
2635 (tramp-shell-quote-argument localname)
2623 (tramp-get-remote-stat vec) 2636 (tramp-get-remote-stat vec)
2624 (if (eq id-format 'integer) "%u" "\"%U\"") 2637 (if (eq id-format 'integer) "%u" "\"%U\"")
2625 (if (eq id-format 'integer) "%g" "\"%G\"") 2638 (if (eq id-format 'integer) "%g" "\"%G\"")
2626 (tramp-shell-quote-argument localname)))) 2639 (tramp-shell-quote-argument localname))))
2627 2640
7053 7066
7054 (defun tramp-convert-file-attributes (vec attr) 7067 (defun tramp-convert-file-attributes (vec attr)
7055 "Convert file-attributes ATTR generated by perl script, stat or ls. 7068 "Convert file-attributes ATTR generated by perl script, stat or ls.
7056 Convert file mode bits to string and set virtual device number. 7069 Convert file mode bits to string and set virtual device number.
7057 Return ATTR." 7070 Return ATTR."
7058 ;; Convert last access time. 7071 (when attr
7059 (unless (listp (nth 4 attr)) 7072 ;; Convert last access time.
7060 (setcar (nthcdr 4 attr) 7073 (unless (listp (nth 4 attr))
7061 (list (floor (nth 4 attr) 65536) 7074 (setcar (nthcdr 4 attr)
7062 (floor (mod (nth 4 attr) 65536))))) 7075 (list (floor (nth 4 attr) 65536)
7063 ;; Convert last modification time. 7076 (floor (mod (nth 4 attr) 65536)))))
7064 (unless (listp (nth 5 attr)) 7077 ;; Convert last modification time.
7065 (setcar (nthcdr 5 attr) 7078 (unless (listp (nth 5 attr))
7066 (list (floor (nth 5 attr) 65536) 7079 (setcar (nthcdr 5 attr)
7067 (floor (mod (nth 5 attr) 65536))))) 7080 (list (floor (nth 5 attr) 65536)
7068 ;; Convert last status change time. 7081 (floor (mod (nth 5 attr) 65536)))))
7069 (unless (listp (nth 6 attr)) 7082 ;; Convert last status change time.
7070 (setcar (nthcdr 6 attr) 7083 (unless (listp (nth 6 attr))
7071 (list (floor (nth 6 attr) 65536) 7084 (setcar (nthcdr 6 attr)
7072 (floor (mod (nth 6 attr) 65536))))) 7085 (list (floor (nth 6 attr) 65536)
7073 ;; Convert file size. 7086 (floor (mod (nth 6 attr) 65536)))))
7074 (when (< (nth 7 attr) 0) 7087 ;; Convert file size.
7075 (setcar (nthcdr 7 attr) -1)) 7088 (when (< (nth 7 attr) 0)
7076 (when (and (floatp (nth 7 attr)) 7089 (setcar (nthcdr 7 attr) -1))
7077 (<= (nth 7 attr) (tramp-compat-most-positive-fixnum))) 7090 (when (and (floatp (nth 7 attr))
7078 (setcar (nthcdr 7 attr) (round (nth 7 attr)))) 7091 (<= (nth 7 attr) (tramp-compat-most-positive-fixnum)))
7079 ;; Convert file mode bits to string. 7092 (setcar (nthcdr 7 attr) (round (nth 7 attr))))
7080 (unless (stringp (nth 8 attr)) 7093 ;; Convert file mode bits to string.
7081 (setcar (nthcdr 8 attr) (tramp-file-mode-from-int (nth 8 attr))) 7094 (unless (stringp (nth 8 attr))
7082 (when (stringp (car attr)) 7095 (setcar (nthcdr 8 attr) (tramp-file-mode-from-int (nth 8 attr)))
7083 (aset (nth 8 attr) 0 ?l))) 7096 (when (stringp (car attr))
7084 ;; Convert directory indication bit. 7097 (aset (nth 8 attr) 0 ?l)))
7085 (when (string-match "^d" (nth 8 attr)) 7098 ;; Convert directory indication bit.
7086 (setcar attr t)) 7099 (when (string-match "^d" (nth 8 attr))
7087 ;; Convert symlink from `tramp-handle-file-attributes-with-stat'. 7100 (setcar attr t))
7088 (when (consp (car attr)) 7101 ;; Convert symlink from `tramp-do-file-attributes-with-stat'.
7089 (if (and (stringp (caar attr)) 7102 (when (consp (car attr))
7090 (string-match ".+ -> .\\(.+\\)." (caar attr))) 7103 (if (and (stringp (caar attr))
7091 (setcar attr (match-string 1 (caar attr))) 7104 (string-match ".+ -> .\\(.+\\)." (caar attr)))
7092 (setcar attr nil))) 7105 (setcar attr (match-string 1 (caar attr)))
7093 ;; Set file's gid change bit. 7106 (setcar attr nil)))
7094 (setcar (nthcdr 9 attr) 7107 ;; Set file's gid change bit.
7095 (if (numberp (nth 3 attr)) 7108 (setcar (nthcdr 9 attr)
7096 (not (= (nth 3 attr) 7109 (if (numberp (nth 3 attr))
7097 (tramp-get-remote-gid vec 'integer))) 7110 (not (= (nth 3 attr)
7098 (not (string-equal 7111 (tramp-get-remote-gid vec 'integer)))
7099 (nth 3 attr) 7112 (not (string-equal
7100 (tramp-get-remote-gid vec 'string))))) 7113 (nth 3 attr)
7101 ;; Convert inode. 7114 (tramp-get-remote-gid vec 'string)))))
7102 (unless (listp (nth 10 attr)) 7115 ;; Convert inode.
7103 (setcar (nthcdr 10 attr) 7116 (unless (listp (nth 10 attr))
7104 (condition-case nil 7117 (setcar (nthcdr 10 attr)
7105 (cons (floor (nth 10 attr) 65536) 7118 (condition-case nil
7106 (floor (mod (nth 10 attr) 65536))) 7119 (cons (floor (nth 10 attr) 65536)
7107 ;; Inodes can be incredible huge. We must hide this. 7120 (floor (mod (nth 10 attr) 65536)))
7108 (error (tramp-get-inode vec))))) 7121 ;; Inodes can be incredible huge. We must hide this.
7109 ;; Set virtual device number. 7122 (error (tramp-get-inode vec)))))
7110 (setcar (nthcdr 11 attr) 7123 ;; Set virtual device number.
7111 (tramp-get-device vec)) 7124 (setcar (nthcdr 11 attr)
7112 attr) 7125 (tramp-get-device vec))
7126 attr))
7113 7127
7114 (defun tramp-get-inode (vec) 7128 (defun tramp-get-inode (vec)
7115 "Returns the virtual inode number. 7129 "Returns the virtual inode number.
7116 If it doesn't exist, generate a new one." 7130 If it doesn't exist, generate a new one."
7117 (let ((string (tramp-make-tramp-file-name 7131 (let ((string (tramp-make-tramp-file-name