diff --git a/lisp/tramp-sh.el b/lisp/tramp-sh.el index 05cd2778..7b289053 100644 --- a/lisp/tramp-sh.el +++ b/lisp/tramp-sh.el @@ -1295,43 +1295,93 @@ Operations not mentioned here will be handled by the normal Emacs functions.") (defun tramp-do-file-attributes-with-ls (vec localname) "Implement `file-attributes' for Tramp files using the ls(1) command." - (let (symlinkp dirp + (let ((optimized (tramp-compat-length< localname 255)) + symlinkp dirp res-inode res-filemodes res-numlinks res-uid-string res-gid-string res-uid-integer res-gid-integer res-size res-symlink-target res-context) (tramp-message vec 5 "file attributes with ls: %s" localname) - ;; We cannot send both commands combined, it could exceed NAME_MAX - ;; or PATH_MAX. Happened on macOS, for example. - (when (tramp-send-command-and-check - vec - (format "cd %s && (%s %s || %s -h %s)" - (tramp-shell-quote-argument - (tramp-run-real-handler - #'file-name-directory (list localname))) - (tramp-get-file-exists-command vec) - (if (string-empty-p (file-name-nondirectory localname)) - "." - (tramp-shell-quote-argument - (file-name-nondirectory localname))) - (tramp-get-test-command vec) - (if (string-empty-p (file-name-nondirectory localname)) - "." - (tramp-shell-quote-argument - (file-name-nondirectory localname))))) - (tramp-send-command - vec - (format "%s -ild %s %s; %s -lnd%s %s %s" - (tramp-get-ls-command vec) - ;; On systems which have no quoting style, file names - ;; with special characters could fail. - (tramp-sh--quoting-style-options vec) - (tramp-shell-quote-argument localname) - (tramp-get-ls-command vec) - (if (tramp-remote-selinux-p vec) "Z" "") - ;; On systems which have no quoting style, file names - ;; with special characters could fail. - (tramp-sh--quoting-style-options vec) - (tramp-shell-quote-argument localname))) + ;; We cannot send both commands combined, it could exceed + ;; NAME_MAX, LINE_MAX or PATH_MAX. Happened on macOS or NetBSD, + ;; for example. As a heuristic, we check whether the file name is + ;; less than 255. See Bug#65324. + (when (if optimized + (tramp-send-command-and-check + vec + (format "cd %s && (%s %s || %s -h %s)" + (tramp-shell-quote-argument + (tramp-run-real-handler + #'file-name-directory (list localname))) + (tramp-get-file-exists-command vec) + (if (string-empty-p (file-name-nondirectory localname)) + "." + (tramp-shell-quote-argument + (file-name-nondirectory localname))) + (tramp-get-test-command vec) + (if (string-empty-p (file-name-nondirectory localname)) + "." + (tramp-shell-quote-argument + (file-name-nondirectory localname))))) + + ;; Send single commands. + (or (tramp-send-command-and-check + vec + (format "cd %s && %s %s" + (tramp-shell-quote-argument + (tramp-run-real-handler + #'file-name-directory (list localname))) + (tramp-get-file-exists-command vec) + (if (string-empty-p (file-name-nondirectory localname)) + "." + (tramp-shell-quote-argument + (file-name-nondirectory localname))))) + (tramp-send-command-and-check + vec + (format "%s -h %s" + (tramp-get-test-command vec) + (if (string-empty-p (file-name-nondirectory localname)) + "." + (tramp-shell-quote-argument + (file-name-nondirectory localname))))))) + + (if optimized + (tramp-send-command + vec + (format "%s -ild %s %s; %s -lnd%s %s %s" + (tramp-get-ls-command vec) + ;; On systems which have no quoting style, file + ;; names with special characters could fail. + (tramp-sh--quoting-style-options vec) + (tramp-shell-quote-argument localname) + (tramp-get-ls-command vec) + (if (tramp-remote-selinux-p vec) "Z" "") + ;; On systems which have no quoting style, file + ;; names with special characters could fail. + (tramp-sh--quoting-style-options vec) + (tramp-shell-quote-argument localname))) + + ;; Send single commands. + (with-current-buffer (tramp-get-buffer vec) + (tramp-send-command + vec + (format "%s -ild %s %s" + (tramp-get-ls-command vec) + ;; On systems which have no quoting style, file + ;; names with special characters could fail. + (tramp-sh--quoting-style-options vec) + (tramp-shell-quote-argument localname))) + (narrow-to-region (point-max) (point-max)) + (tramp-send-command + vec + (format "%s -lnd%s %s %s" + (tramp-get-ls-command vec) + (if (tramp-remote-selinux-p vec) "Z" "") + ;; On systems which have no quoting style, file + ;; names with special characters could fail. + (tramp-sh--quoting-style-options vec) + (tramp-shell-quote-argument localname))) + (widen))) + ;; Parse `ls -l' output ... (with-current-buffer (tramp-get-buffer vec) (when (> (buffer-size) 0)