From 227f1bec4acad039c6f1f1e8fa4b95b82ff830c2 Mon Sep 17 00:00:00 2001 From: Juergen Hoetzel Date: Sun, 18 Oct 2015 11:28:46 +0200 Subject: [PATCH] (tramp-gvfs-get-attributes): New defun to read a gvfs attributes of a file Use `tramp-gvfs-get-attributes' in `tramp-gvfs-handle-file-attributes' instead of calling "gvfs-info" directly. Also use `tramp-gvfs-get-attributes' in `tramp-gvfs-handle-file-name-all-completions' to translate IDs to human readable display-names (google-drive). --- lisp/tramp-gvfs.el | 241 ++++++++++++++++++++++++++++------------------------- 1 file changed, 126 insertions(+), 115 deletions(-) diff --git a/lisp/tramp-gvfs.el b/lisp/tramp-gvfs.el index b9d2fa2..8a4a953 100644 --- a/lisp/tramp-gvfs.el +++ b/lisp/tramp-gvfs.el @@ -405,6 +405,25 @@ Every entry is a list (NAME ADDRESS).") (defconst tramp-hal-interface-device "org.freedesktop.Hal.Device" "The device interface of the HAL daemon.") +(defconst tramp-gvfs-file-attributes-regexp + (concat "^\\s-*" + (regexp-opt '("type" + "standard::display-name" + "standard::symlink-target" + "unix::nlink" + "unix::uid" + "owner::user" + "unix::gid" + "owner::group" + "time::access" + "time::modified" + "time::changed" + "standard::size" + "unix::mode" + "unix::inode" + "unix::device") t) + ":\\s-+\\(.*\\)$") + "Regexp to parse GVFS file attributes.") ;; New handlers should be added here. (defconst tramp-gvfs-file-name-handler-alist @@ -785,9 +804,8 @@ file names." (tramp-run-real-handler 'expand-file-name (list localname)))))) -(defun tramp-gvfs-handle-file-attributes (filename &optional id-format) - "Like `file-attributes' for Tramp files." - (unless id-format (setq id-format 'integer)) +(defun tramp-gvfs-get-attributes (filename) + "Return GVFS attributes association list of FILENAME." (ignore-errors ;; Don't modify `last-coding-system-used' by accident. (let ((last-coding-system-used last-coding-system-used) @@ -795,125 +813,111 @@ file names." (append '("LANG=C.utf8" "LANGUAGE=C.utf8" "LC_ALL=C.utf8") process-environment)) - dirp res-symlink-target res-numlinks res-uid res-gid res-access - res-mod res-change res-size res-filemodes res-inode res-device) + result) (with-parsed-tramp-file-name filename nil (with-tramp-file-property - v localname (format "file-attributes-%s" id-format) - (tramp-message v 5 "file attributes: %s" localname) + v localname (format "file-gvsfs-attributes") + (tramp-message v 5 "file gvfs attributes: %s" localname) (tramp-gvfs-send-command v "gvfs-info" (tramp-gvfs-url-file-name filename)) ;; Parse output ... (with-current-buffer (tramp-get-connection-buffer v) (goto-char (point-min)) - (when (re-search-forward "attributes:" nil t) - ;; ... directory or symlink - (goto-char (point-min)) - (setq dirp (if (re-search-forward "type:\\s-+directory" nil t) t)) - (goto-char (point-min)) - (setq res-symlink-target - (if (re-search-forward - "standard::symlink-target:\\s-+\\(.*\\)$" nil t) - (match-string 1))) - ;; ... number links - (goto-char (point-min)) - (setq res-numlinks - (if (re-search-forward - "unix::nlink:\\s-+\\([0-9]+\\)" nil t) - (string-to-number (match-string 1)) 0)) - ;; ... uid and gid - (goto-char (point-min)) - (setq res-uid - (or (if (eq id-format 'integer) - (if (re-search-forward - "unix::uid:\\s-+\\([0-9]+\\)" nil t) - (string-to-number (match-string 1))) - (if (re-search-forward - "owner::user:\\s-+\\(\\S-+\\)" nil t) - (match-string 1))) - (tramp-get-local-uid id-format))) - (setq res-gid - (or (if (eq id-format 'integer) - (if (re-search-forward - "unix::gid:\\s-+\\([0-9]+\\)" nil t) - (string-to-number (match-string 1))) - (if (re-search-forward - "owner::group:\\s-+\\(\\S-+\\)" nil t) - (match-string 1))) - (tramp-get-local-gid id-format))) - ;; ... last access, modification and change time - (goto-char (point-min)) - (setq res-access - (if (re-search-forward - "time::access:\\s-+\\([0-9]+\\)" nil t) - (seconds-to-time (string-to-number (match-string 1))) - '(0 0))) - (goto-char (point-min)) - (setq res-mod - (if (re-search-forward - "time::modified:\\s-+\\([0-9]+\\)" nil t) - (seconds-to-time (string-to-number (match-string 1))) - '(0 0))) - (goto-char (point-min)) - (setq res-change - (if (re-search-forward - "time::changed:\\s-+\\([0-9]+\\)" nil t) - (seconds-to-time (string-to-number (match-string 1))) - '(0 0))) - ;; ... size - (goto-char (point-min)) - (setq res-size - (if (re-search-forward - "standard::size:\\s-+\\([0-9]+\\)" nil t) - (string-to-number (match-string 1)) 0)) - ;; ... file mode flags - (goto-char (point-min)) - (setq res-filemodes - (if (re-search-forward "unix::mode:\\s-+\\([0-9]+\\)" nil t) - (tramp-file-mode-from-int - (string-to-number (match-string 1))) - (if dirp "drwx------" "-rwx------"))) - ;; ... inode and device - (goto-char (point-min)) - (setq res-inode - (if (re-search-forward - "unix::inode:\\s-+\\([0-9]+\\)" nil t) - (string-to-number (match-string 1)) - (tramp-get-inode v))) - (goto-char (point-min)) - (setq res-device - (if (re-search-forward - "unix::device:\\s-+\\([0-9]+\\)" nil t) - (string-to-number (match-string 1)) - (tramp-get-device v))) - - ;; Return data gathered. - (list - ;; 0. t for directory, string (name linked to) for - ;; symbolic link, or nil. - (or dirp res-symlink-target) - ;; 1. Number of links to file. - res-numlinks - ;; 2. File uid. - res-uid - ;; 3. File gid. - res-gid - ;; 4. Last access time, as a list of integers. - ;; 5. Last modification time, likewise. - ;; 6. Last status change time, likewise. - res-access res-mod res-change - ;; 7. Size in bytes (-1, if number is out of range). - res-size - ;; 8. File modes. - res-filemodes - ;; 9. t if file's gid would change if file were deleted - ;; and recreated. - nil - ;; 10. Inode number. - res-inode - ;; 11. Device number. - res-device - )))))))) + (while (re-search-forward tramp-gvfs-file-attributes-regexp nil t) + (push (cons (match-string 1) (match-string 2)) result)) + result)))))) + +(defun tramp-gvfs-handle-file-attributes (filename &optional id-format) + "Like `file-attributes' for Tramp files." + (unless id-format (setq id-format 'integer)) + (ignore-errors + ;; Don't modify `last-coding-system-used' by accident. + (let ((attributes (tramp-gvfs-get-attributes filename)) + dirp res-symlink-target res-numlinks res-uid res-gid res-access + res-mod res-change res-size res-filemodes res-inode res-device) + (when attributes + ;; ... directory or symlink + (setq dirp (if (equal "directory" (cdr (assoc "type" attributes))) t)) + (setq res-symlink-target + (cdr (assoc "standard::symlink-target" attributes))) + ;; ... number links + (setq res-numlinks (let ((n (cdr (assoc "unix::nlink" attributes)))) + (if n (string-to-number n) 0))) + ;; ... uid and gid + (setq res-uid + (if (eq id-format 'integer) + (let ((n (cdr (assoc "unix::uid" attributes)))) + (if n (string-to-number n) + (tramp-get-local-uid 'integer))) + (or (cdr (assoc "owner::user" attributes)) + (tramp-get-local-uid id-format)))) + (setq res-gid + (if (eq id-format 'integer) + (let ((n (cdr (assoc "unix::gid" attributes)))) + (if n (string-to-number n) + (tramp-get-local-gid 'integer))) + (or (cdr (assoc "owner::group" attributes)) + (tramp-get-local-gid id-format)))) + ;; ... last access, modification and change time + (setq res-access + (let ((n (cdr (assoc "time::access" attributes)))) + (if n (seconds-to-time (string-to-number n)) + '(0 0)))) + (setq res-mod + (let ((n (cdr (assoc "time::modified" attributes)))) + (if n (seconds-to-time (string-to-number n)) + '(0 0)))) + (setq res-change + (let ((n (cdr (assoc "time::changed" attributes)))) + (if n (seconds-to-time (string-to-number n)) + '(0 0)))) + ;; ... size + (setq res-size + (let ((n (cdr (assoc "standard::size" attributes)))) + (if n (string-to-number n) 0))) + ;; ... file mode flags + (setq res-filemodes + (let ((n (cdr (assoc "unix::mode" attributes)))) + (if n (tramp-file-mode-from-int + (string-to-number (match-string 1))) + (if dirp "drwx------" "-rwx------")))) + ;; ... inode and device + (setq res-inode + (let ((n (cdr (assoc "unix::inode" attributes)))) + (if n (string-to-number n) + (tramp-get-inode v)))) + (setq res-device + (let ((n (cdr (assoc "unix::device" attributes)))) + (if n (string-to-number n) + (tramp-get-device v)))) + + ;; Return data gathered. + (list + ;; 0. t for directory, string (name linked to) for + ;; symbolic link, or nil. + (or dirp res-symlink-target) + ;; 1. Number of links to file. + res-numlinks + ;; 2. File uid. + res-uid + ;; 3. File gid. + res-gid + ;; 4. Last access time, as a list of integers. + ;; 5. Last modification time, likewise. + ;; 6. Last status change time, likewise. + res-access res-mod res-change + ;; 7. Size in bytes (-1, if number is out of range). + res-size + ;; 8. File modes. + res-filemodes + ;; 9. t if file's gid would change if file were deleted + ;; and recreated. + nil + ;; 10. Inode number. + res-inode + ;; 11. Device number. + res-device + ))))) (defun tramp-gvfs-handle-file-directory-p (filename) "Like `file-directory-p' for Tramp files." @@ -986,6 +990,13 @@ file names." (goto-char (point-max)) (while (zerop (forward-line -1)) (setq entry (buffer-substring (point) (point-at-eol))) + ;; use display-name if available (google-drive) + (let ((display-name + (cdr (assoc "standard::display-name" + (tramp-gvfs-get-attributes + (concat directory "/" entry)))))) + (unless (equal display-name entry) + (setq entry display-name))) (when (string-match filename entry) (if (file-directory-p (expand-file-name entry directory)) (push (concat entry "/") result) -- 2.6.1