From 1089dc98b778d1c6eb190dbd840d40c33aea9bea Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Sun, 10 Jan 2016 13:07:21 +0100 Subject: [PATCH] Handle too long commands in Tramp * lisp/net/tramp-sh.el (tramp-sh-handle-make-symbolic-link) (tramp-do-file-attributes-with-ls): Send sequence of commands, in order to not exceed shell command line limit. * test/automated/tramp-tests.el (tramp--test-darwin-p): Remove. (tramp--test-utf8): Include Arabic file name, again. --- lisp/net/tramp-sh.el | 216 ++++++++++++++++++---------------- test/automated/tramp-tests.el | 10 +- 2 files changed, 115 insertions(+), 111 deletions(-) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 1357db0ac42..7ace8864f88 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -1100,15 +1100,19 @@ target of the symlink differ." ;; Right, they are on the same host, regardless of user, method, ;; etc. We now make the link on the remote machine. This will ;; occur as the user that FILENAME belongs to. - (tramp-send-command-and-check - l - (format - "cd %s && %s -sf %s %s" - (tramp-shell-quote-argument cwd) - ln - (tramp-shell-quote-argument filename) - (tramp-shell-quote-argument l-localname)) - t)))) + (and (tramp-send-command-and-check + l (format "cd %s" (tramp-shell-quote-argument cwd))) + (tramp-send-command-and-check + l (format + "%s -sf %s %s" + ln + (tramp-shell-quote-argument filename) + ;; The command could exceed PATH_MAX, so we use + ;; relative file names. However, relative file names + ;; could start with "-". `tramp-shell-quote-argument' + ;; does not handle this, we must do it ourselves. + (tramp-shell-quote-argument + (concat "./" (file-name-nondirectory l-localname))))))))) (defun tramp-sh-handle-file-truename (filename) "Like `file-truename' for Tramp files." @@ -1266,100 +1270,108 @@ target of the symlink differ." res-inode res-filemodes res-numlinks res-uid res-gid res-size res-symlink-target) (tramp-message vec 5 "file attributes with ls: %s" localname) - (tramp-send-command - vec - (format "(%s %s || %s -h %s) && %s %s %s %s" - (tramp-get-file-exists-command vec) - (tramp-shell-quote-argument localname) - (tramp-get-test-command vec) - (tramp-shell-quote-argument localname) - (tramp-get-ls-command vec) - (if (eq id-format 'integer) "-ildn" "-ild") - ;; On systems which have no quoting style, file names - ;; with special characters could fail. - (cond - ((tramp-get-ls-command-with-quoting-style vec) - "--quoting-style=c") - ((tramp-get-ls-command-with-w-option vec) - "-w") - (t "")) - (tramp-shell-quote-argument localname))) - ;; Parse `ls -l' output ... - (with-current-buffer (tramp-get-buffer vec) - (when (> (buffer-size) 0) - (goto-char (point-min)) - ;; ... inode - (setq res-inode - (condition-case err - (read (current-buffer)) - (invalid-read-syntax - (when (and (equal (cadr err) - "Integer constant overflow in reader") - (string-match - "^[0-9]+\\([0-9][0-9][0-9][0-9][0-9]\\)\\'" - (car (cddr err)))) - (let* ((big (read (substring (car (cddr err)) 0 - (match-beginning 1)))) - (small (read (match-string 1 (car (cddr err))))) - (twiddle (/ small 65536))) - (cons (+ big twiddle) - (- small (* twiddle 65536)))))))) - ;; ... file mode flags - (setq res-filemodes (symbol-name (read (current-buffer)))) - ;; ... number links - (setq res-numlinks (read (current-buffer))) - ;; ... uid and gid - (setq res-uid (read (current-buffer))) - (setq res-gid (read (current-buffer))) - (if (eq id-format 'integer) + ;; We cannot send all three commands combined, it could exceed + ;; NAME_MAX or PATH_MAX. Happened on Mac OS X, for example. + (when (or (tramp-send-command-and-check + vec + (format "%s %s" + (tramp-get-file-exists-command vec) + (tramp-shell-quote-argument localname))) + (tramp-send-command-and-check + vec + (format "%s -h %s" + (tramp-get-test-command vec) + (tramp-shell-quote-argument localname)))) + (tramp-send-command + vec + (format "%s %s %s %s" + (tramp-get-ls-command vec) + (if (eq id-format 'integer) "-ildn" "-ild") + ;; On systems which have no quoting style, file names + ;; with special characters could fail. + (cond + ((tramp-get-ls-command-with-quoting-style vec) + "--quoting-style=c") + ((tramp-get-ls-command-with-w-option vec) + "-w") + (t "")) + (tramp-shell-quote-argument localname))) + ;; Parse `ls -l' output ... + (with-current-buffer (tramp-get-buffer vec) + (when (> (buffer-size) 0) + (goto-char (point-min)) + ;; ... inode + (setq res-inode + (condition-case err + (read (current-buffer)) + (invalid-read-syntax + (when (and (equal (cadr err) + "Integer constant overflow in reader") + (string-match + "^[0-9]+\\([0-9][0-9][0-9][0-9][0-9]\\)\\'" + (car (cddr err)))) + (let* ((big (read (substring (car (cddr err)) 0 + (match-beginning 1)))) + (small (read (match-string 1 (car (cddr err))))) + (twiddle (/ small 65536))) + (cons (+ big twiddle) + (- small (* twiddle 65536)))))))) + ;; ... file mode flags + (setq res-filemodes (symbol-name (read (current-buffer)))) + ;; ... number links + (setq res-numlinks (read (current-buffer))) + ;; ... uid and gid + (setq res-uid (read (current-buffer))) + (setq res-gid (read (current-buffer))) + (if (eq id-format 'integer) + (progn + (unless (numberp res-uid) (setq res-uid -1)) + (unless (numberp res-gid) (setq res-gid -1))) (progn - (unless (numberp res-uid) (setq res-uid -1)) - (unless (numberp res-gid) (setq res-gid -1))) - (progn - (unless (stringp res-uid) (setq res-uid (symbol-name res-uid))) - (unless (stringp res-gid) (setq res-gid (symbol-name res-gid))))) - ;; ... size - (setq res-size (read (current-buffer))) - ;; From the file modes, figure out other stuff. - (setq symlinkp (eq ?l (aref res-filemodes 0))) - (setq dirp (eq ?d (aref res-filemodes 0))) - ;; If symlink, find out file name pointed to. - (when symlinkp - (search-forward "-> ") - (setq res-symlink-target - (if (tramp-get-ls-command-with-quoting-style vec) - (read (current-buffer)) - (buffer-substring (point) (point-at-eol))))) - ;; 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. Normally this - ;; would be in the same format as `current-time', but the - ;; subseconds part is not currently implemented, and (0 0) - ;; denotes an unknown time. - ;; 5. Last modification time, likewise. - ;; 6. Last status change time, likewise. - '(0 0) '(0 0) '(0 0) ;CCC how to find out? - ;; 7. Size in bytes (-1, if number is out of range). - res-size - ;; 8. File modes, as a string of ten letters or dashes as in ls -l. - res-filemodes - ;; 9. t if file's gid would change if file were deleted and - ;; recreated. Will be set in `tramp-convert-file-attributes'. - t - ;; 10. Inode number. - res-inode - ;; 11. Device number. Will be replaced by a virtual device number. - -1 - ))))) + (unless (stringp res-uid) (setq res-uid (symbol-name res-uid))) + (unless (stringp res-gid) (setq res-gid (symbol-name res-gid))))) + ;; ... size + (setq res-size (read (current-buffer))) + ;; From the file modes, figure out other stuff. + (setq symlinkp (eq ?l (aref res-filemodes 0))) + (setq dirp (eq ?d (aref res-filemodes 0))) + ;; If symlink, find out file name pointed to. + (when symlinkp + (search-forward "-> ") + (setq res-symlink-target + (if (tramp-get-ls-command-with-quoting-style vec) + (read (current-buffer)) + (buffer-substring (point) (point-at-eol))))) + ;; 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. Normally + ;; this would be in the same format as `current-time', but + ;; the subseconds part is not currently implemented, and (0 + ;; 0) denotes an unknown time. + ;; 5. Last modification time, likewise. + ;; 6. Last status change time, likewise. + '(0 0) '(0 0) '(0 0) ;CCC how to find out? + ;; 7. Size in bytes (-1, if number is out of range). + res-size + ;; 8. File modes, as a string of ten letters or dashes as in ls -l. + res-filemodes + ;; 9. t if file's gid would change if file were deleted and + ;; recreated. Will be set in `tramp-convert-file-attributes'. + t + ;; 10. Inode number. + res-inode + ;; 11. Device number. Will be replaced by a virtual device number. + -1 + )))))) (defun tramp-do-file-attributes-with-perl (vec localname &optional id-format) diff --git a/test/automated/tramp-tests.el b/test/automated/tramp-tests.el index c956f9cd008..915b30f5e08 100644 --- a/test/automated/tramp-tests.el +++ b/test/automated/tramp-tests.el @@ -1785,14 +1785,6 @@ Several special characters do not work properly there." (file-truename tramp-test-temporary-file-directory) nil (string-match "^HP-UX" (tramp-get-connection-property v "uname" "")))) -(defun tramp--test-darwin-p () - "Check, whether the remote host runs Mac OS X. -Several special characters do not work properly there." - ;; We must refill the cache. `file-truename' does it. - (with-parsed-tramp-file-name - (file-truename tramp-test-temporary-file-directory) nil - (string-match "^Darwin" (tramp-get-connection-property v "uname" "")))) - (defun tramp--test-check-files (&rest files) "Run a simple but comprehensive test over every file in FILES." ;; We must use `file-truename' for the temporary directory, because @@ -2046,7 +2038,7 @@ Use the `ls' command." (file-name-coding-system 'utf-8)) (tramp--test-check-files (unless (tramp--test-hpux-p) "Γυρίστε το Γαλαξία με Ώτο Στοπ") - (unless (or (tramp--test-hpux-p) (tramp--test-darwin-p)) + (unless (tramp--test-hpux-p) "أصبح بوسعك الآن تنزيل نسخة كاملة من موسوعة ويكيبيديا العربية لتصفحها بلا اتصال بالإنترنت") "银河系漫游指南系列" "Автостопом по гала́ктике"))) -- 2.39.2