GNU bug report logs - #27952
26.0.50; Combine archive-int-to-mode and tar-grind-file-mode

Previous Next

Package: emacs;

Reported by: Tino Calancha <tino.calancha <at> gmail.com>

Date: Fri, 4 Aug 2017 13:55:01 UTC

Severity: wishlist

Tags: patch

Found in version 26.0.50

Done: Tino Calancha <tino.calancha <at> gmail.com>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 27952 in the body.
You can then email your comments to 27952 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to monnier <at> iro.umontreal.ca, bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Fri, 04 Aug 2017 13:55:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Tino Calancha <tino.calancha <at> gmail.com>:
New bug report received and forwarded. Copy sent to monnier <at> iro.umontreal.ca, bug-gnu-emacs <at> gnu.org. (Fri, 04 Aug 2017 13:55:01 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: 26.0.50; Combine archive-int-to-mode and tar-grind-file-mode
Date: Fri, 04 Aug 2017 21:32:24 +0900
Severity: wishlist
Tag: patch
X-Debbugs-CC: Stefan Monnier <monnier <at> iro.umontreal.ca>

These functions are almost identical; archive-int-to-mode has a FIXME
suggesting merging it with tar-grind-file-mode.

--8<-----------------------------cut here---------------start------------->8---
commit c6d36b04de7f6442653af7e4699bdad44ee57201
Author: Tino Calancha <tino.calancha <at> gmail.com>
Date:   Fri Aug 4 21:25:44 2017 +0900

    Combine archive-int-to-mode and tar-grind-file-mode
    
    These functions are almost identical.  Add a new function
    file-modes-number-to-symbolic; use it to define the other two.
    * lisp/files.el (file-modes-number-to-symbolic-1)
    (file-modes-number-to-symbolic): New defuns.
    * lisp/arc-mode.el (archive-int-to-mode): Define as a alias of
    file-modes-number-to-symbolic.
    * lisp/tar-mode.el (tar-grind-file-mode): Fix docstring.
    Use file-modes-number-to-symbolic.

diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index bd7548b704..8f3691b337 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -549,26 +549,7 @@ archive-l-e
 		      (aref str (- len i)))))
     result))
 
-(defun archive-int-to-mode (mode)
-  "Turn an integer like 0700 (i.e., 448) into a mode string like -rwx------."
-  ;; FIXME: merge with tar-grind-file-mode.
-  (string
-    (if (zerop (logand  8192 mode))
-	(if (zerop (logand 16384 mode)) ?- ?d)
-      ?c) ; completeness
-    (if (zerop (logand   256 mode)) ?- ?r)
-    (if (zerop (logand   128 mode)) ?- ?w)
-    (if (zerop (logand    64 mode))
-	(if (zerop (logand  1024 mode)) ?- ?S)
-      (if (zerop (logand  1024 mode)) ?x ?s))
-    (if (zerop (logand    32 mode)) ?- ?r)
-    (if (zerop (logand    16 mode)) ?- ?w)
-    (if (zerop (logand     8 mode))
-	(if (zerop (logand  2048 mode)) ?- ?S)
-      (if (zerop (logand  2048 mode)) ?x ?s))
-    (if (zerop (logand     4 mode)) ?- ?r)
-    (if (zerop (logand     2 mode)) ?- ?w)
-    (if (zerop (logand     1 mode)) ?- ?x)))
+(defalias 'archive-int-to-mode 'file-modes-number-to-symbolic)
 
 (defun archive-calc-mode (oldmode newmode &optional error)
   "From the integer OLDMODE and the string NEWMODE calculate a new file mode.
diff --git a/lisp/files.el b/lisp/files.el
index 89f6f9f44d..e776b00b91 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -7188,6 +7188,65 @@ file-modes-symbolic-to-number
 	  (error "Parse error in modes near `%s'" (substring modes 0))))
       num-modes)))
 
+(defun file-modes-number-to-symbolic-1 (mode)
+  (string
+   (if (zerop (logand  8192 mode))
+       (if (zerop (logand 16384 mode)) ?- ?d)
+     ?c) ; completeness
+   (if (zerop (logand   256 mode)) ?- ?r)
+   (if (zerop (logand   128 mode)) ?- ?w)
+   (if (zerop (logand    64 mode))
+       (if (zerop (logand  1024 mode)) ?- ?S)
+     (if (zerop (logand  1024 mode)) ?x ?s))
+   (if (zerop (logand    32 mode)) ?- ?r)
+   (if (zerop (logand    16 mode)) ?- ?w)
+   (if (zerop (logand     8 mode))
+       (if (zerop (logand  2048 mode)) ?- ?S)
+     (if (zerop (logand  2048 mode)) ?x ?s))
+   (if (zerop (logand     4 mode)) ?- ?r)
+   (if (zerop (logand     2 mode)) ?- ?w)
+   (if (zerop (logand     1 mode)) ?- ?x)))
+
+(defun file-modes-number-to-symbolic (mode &optional detailed from)
+  "Turn an integer like 0700 (i.e., 448) into a mode string like -rwx------.
+If optional arg DETAILED is non-nil, then use the format 'u=rwx,g=,o='.
+If optional argument FROM is non-nil, then it's the original file mode
+ to compare with MODE.  FROM is ignored unless DETAILED is non-nil.
+
+For instance, if MODE is 448, DETAILED is non-nil, and FROM is 400,
+the output is 'u+x,g-w'."
+  (let ((mode (file-modes-number-to-symbolic-1 mode))
+        (from (and from (substring (file-modes-number-to-symbolic-1 from) 1))))
+    (if (not detailed)
+        mode
+      (setq mode (substring mode 1))
+      (cond (from
+             (let ((res "u"))
+               (dotimes (i (length mode))
+                 (let ((x (aref mode i))
+                       (y (aref from i)))
+                   (when (= i 3) (setq res (concat res ",g")))
+                   (when (= i 6) (setq res (concat res ",o")))
+                   (setq res (concat res
+                                     (cond ((eq x y) "")
+                                           ((eq x ?-) (string ?- y))
+                                           ((eq y ?-) (string ?+ x)))))))
+               (replace-regexp-in-string
+                ",\\'" ""
+                (replace-regexp-in-string
+                 "u," ""
+                 (replace-regexp-in-string
+                  "g," ""
+                  (replace-regexp-in-string
+                   "o\\'" "" res))))))
+            (t
+             (replace-regexp-in-string
+              "-" ""
+              (format "u=%s,g=%s,o=%s"
+                      (substring mode 0 3)
+                      (substring mode 3 6)
+                      (substring mode 6))))))))
+
 (defun read-file-modes (&optional prompt orig-file)
   "Read file modes in octal or symbolic notation and return its numeric value.
 PROMPT is used as the prompt, default to \"File modes (octal or symbolic): \".
diff --git a/lisp/tar-mode.el b/lisp/tar-mode.el
index 1d453d2980..f41cc25532 100644
--- a/lisp/tar-mode.el
+++ b/lisp/tar-mode.el
@@ -469,24 +469,12 @@ tar-clip-time-string
     (concat " " (substring str 4 16) (format-time-string " %Y" time))))
 
 (defun tar-grind-file-mode (mode)
-  "Construct a `-rw--r--r--' string indicating MODE.
+  "Construct a `rw-r--r--' string indicating MODE.
 MODE should be an integer which is a file mode value."
-  (string
-   (if (zerop (logand 256 mode)) ?- ?r)
-   (if (zerop (logand 128 mode)) ?- ?w)
-   (if (zerop (logand 2048 mode))
-       (if (zerop (logand  64 mode)) ?- ?x)
-     (if (zerop (logand  64 mode)) ?S ?s))
-   (if (zerop (logand  32 mode)) ?- ?r)
-   (if (zerop (logand  16 mode)) ?- ?w)
-   (if (zerop (logand 1024 mode))
-       (if (zerop (logand   8 mode)) ?- ?x)
-     (if (zerop (logand   8 mode)) ?S ?s))
-   (if (zerop (logand   4 mode)) ?- ?r)
-   (if (zerop (logand   2 mode)) ?- ?w)
-   (if (zerop (logand 512 mode))
-       (if (zerop (logand   1 mode)) ?- ?x)
-     (if (zerop (logand   1 mode)) ?T ?t))))
+  (let ((str (substring (file-modes-number-to-symbolic mode) 1)))
+    (unless (zerop (logand 512 mode))
+      (aset mode 8 (if (zerop (logand 1 mode)) ?T ?t)))
+    str))
 
 (defun tar-header-block-summarize (tar-hblock &optional mod-p)
   "Return a line similar to the output of `tar -vtf'."

--8<-----------------------------cut here---------------end--------------->8---
In GNU Emacs 26.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.22.11)
 of 2017-08-04
Repository revision: db5d38ddb0de83d8f920b7a128fe3fd5156fdf85




Added tag(s) patch. Request was from npostavs <at> users.sourceforge.net to control <at> debbugs.gnu.org. (Sat, 05 Aug 2017 01:24:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Wed, 16 Aug 2017 11:44:02 GMT) Full text and rfc822 format available.

Message #10 received at 27952 <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: 27952 <at> debbugs.gnu.org
Cc: Eli Zaretskii <eliz <at> gnu.org>, stefan monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#27952: 26.0.50;
 Combine archive-int-to-mode and tar-grind-file-mode
Date: Wed, 16 Aug 2017 20:43:17 +0900
Tino Calancha <tino.calancha <at> gmail.com> writes:

> These functions are almost identical; archive-int-to-mode has a FIXME
> suggesting merging it with tar-grind-file-mode.
*)  Updated the patch after Bug#28092 has being fixed.
**) Now `archive-int-to-mode' also shows the sticky bit info as
    `tar-grind-file-mode' does:
     (archive-int-to-mode 996)
     => "-rwxr--r-T"
     (archive-int-to-mode 997)
     => "-rwxr--r-t"
     (tar-grind-file-mode 996)
     => "rwxr--r-T"
     (tar-grind-file-mode 997)
     => "rwxr--r-t"
     ;; `archive-int-to-mode' already was showing the 's' bit info, so
     ;; the fact that wasn't showing the sticky bit must be a mistake.

***) Added new tests.

Please, let me know if you want to have this patch in.
Tino

--8<-----------------------------cut here---------------start------------->8---
commit 74d1a07379a88f62fdb0e497111fdf4845723806
Author: Tino Calancha <tino.calancha <at> gmail.com>
Date:   Wed Aug 16 20:23:34 2017 +0900

    Combine archive-int-to-mode and tar-grind-file-mode
    
    These functions are almost identical.  Extract a new function
    'file-modes-number-to-symbolic' from them; use it to define
    'archive-int-to-mode' and 'tar-grind-file-mode' (Bug#27952).
    * lisp/files.el (file-modes-number-to-symbolic-1):
    New defun extracted from 'archive-int-to-mode' and 'tar-grind-file-mode'.
    (file-modes-number-to-symbolic):
    New defun;  like `file-modes-number-to-symbolic-1' with 2 optional arguments:
    'detailed' and 'from'.
    
    * lisp/tar-mode.el (tar-grind-file-mode)
    * lisp/arc-mode.el (archive-int-to-mode):
    Use file-modes-number-to-symbolic in its definition.
    
    * test/lisp/arc-mode-tests.el (arc-mode-test-archive-int-to-mode):
    Update test.
    
    * test/lisp/files-tests.el (file-modes-symbolic-to-number)
    (file-modes-number-to-symbolic)
    (file-modes-number-to-symbolic-inverse): Add tests.

diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index 938c143b8e..c1987ee774 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -550,25 +550,10 @@ archive-l-e
     result))
 
 (defun archive-int-to-mode (mode)
-  "Turn an integer like 0700 (i.e., 448) into a mode string like -rwx------."
-  ;; FIXME: merge with tar-grind-file-mode.
-  (string
-    (if (zerop (logand  8192 mode))
-	(if (zerop (logand 16384 mode)) ?- ?d)
-      ?c) ; completeness
-    (if (zerop (logand   256 mode)) ?- ?r)
-    (if (zerop (logand   128 mode)) ?- ?w)
-    (if (zerop (logand    64 mode))
-	(if (zerop (logand  2048 mode)) ?- ?S)
-      (if (zerop (logand  2048 mode)) ?x ?s))
-    (if (zerop (logand    32 mode)) ?- ?r)
-    (if (zerop (logand    16 mode)) ?- ?w)
-    (if (zerop (logand     8 mode))
-	(if (zerop (logand  1024 mode)) ?- ?S)
-      (if (zerop (logand  1024 mode)) ?x ?s))
-    (if (zerop (logand     4 mode)) ?- ?r)
-    (if (zerop (logand     2 mode)) ?- ?w)
-    (if (zerop (logand     1 mode)) ?- ?x)))
+  "Construct a `-rw-r--r--' string indicating MODE.
+MODE should be an integer which is a file mode value.
+For instance, if mode is 448, then it produces `-rwx------'."
+  (file-modes-number-to-symbolic mode))
 
 (defun archive-calc-mode (oldmode newmode &optional error)
   "From the integer OLDMODE and the string NEWMODE calculate a new file mode.
diff --git a/lisp/files.el b/lisp/files.el
index b05d453b0e..664ea943d9 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -7143,6 +7143,95 @@ file-modes-rights-to-number
 	      op char-right)))
     num-rights))
 
+(defun file-modes-number-to-symbolic-1 (mode)
+  (string
+   (if (zerop (logand  8192 mode))
+       (if (zerop (logand 16384 mode)) ?- ?d)
+     ?c) ; completeness
+   (if (zerop (logand   256 mode)) ?- ?r)
+   (if (zerop (logand   128 mode)) ?- ?w)
+   (if (zerop (logand    64 mode))
+       (if (zerop (logand  2048 mode)) ?- ?S)
+     (if (zerop (logand  2048 mode)) ?x ?s))
+   (if (zerop (logand    32 mode)) ?- ?r)
+   (if (zerop (logand    16 mode)) ?- ?w)
+   (if (zerop (logand     8 mode))
+       (if (zerop (logand  1024 mode)) ?- ?S)
+     (if (zerop (logand  1024 mode)) ?x ?s))
+   (if (zerop (logand     4 mode)) ?- ?r)
+   (if (zerop (logand     2 mode)) ?- ?w)
+   (if (zerop (logand 512 mode))
+       (if (zerop (logand   1 mode)) ?- ?x)
+     (if (zerop (logand   1 mode)) ?T ?t))))
+
+(defun file-modes-number-to-symbolic (mode &optional detailed from)
+  "Turn an integer like 0700 (i.e., 448) into a mode string like -rwx------.
+If optional arg DETAILED is non-nil, then use the format 'u=rwx,g=,o='.
+If optional argument FROM is non-nil, then it's the original file mode
+ to compare with MODE.  FROM is ignored unless DETAILED is non-nil.
+
+For instance, if MODE is 448, DETAILED is non-nil, and FROM is 400,
+the output is 'u+x,g-w'.
+
+Note: This is not the inverse of `file-modes-symbolic-to-number';
+The reason is that this function might return an string containing 'S'
+or 'T' i.e., not valid characters for `file-modes-symbolic-to-number'.
+For example, (file-modes-symbolic-to-number \"o=t\") returns 512;
+and (file-modes-number-to-symbolic 512 t) returns \"o=T\"."
+  (let ((mode (file-modes-number-to-symbolic-1 mode))
+        (from (and from (substring (file-modes-number-to-symbolic-1 from) 1))))
+    (if (not detailed)
+        mode
+      (let ((replace-fn (lambda (x)
+                          (replace-regexp-in-string
+                           ",\\`" ""
+                           (replace-regexp-in-string
+                            "u=," ""
+                            (replace-regexp-in-string
+                             "g=," ""
+                             (replace-regexp-in-string
+                              "o=\\'" "" x)))))))
+        (setq mode (substring mode 1))
+        (cond (from
+               (let* ((res "u")
+                      (special-bit-fn (lambda (x y c C &optional inv) ; c or C in (x y)
+                                        (cond ((eq x c) ; xc
+                                               (cond ((eq y ?-) (string (if inv ?- ?+) ?x c))
+                                                     ((eq y ?x) (string (if inv ?- ?+) c))
+                                                     ((eq y C) (string (if inv ?- ?+) ?x))))
+                                              ((eq x C) ; just c
+                                               (cond ((eq y ?-) (string (if inv ?- ?+) c))
+                                                     ((eq y ?x) (if inv (string ?+ ?x c) (string ?- ?x ?+ c)))
+                                                     ((eq y c) (string (if inv ?+ ?-) ?x))))
+                                              (t nil))))
+                      (compare-fn (lambda (x y)
+                                    (cond ((eq x y) "")
+                                          ;; sticky bit or setuid setgid changes.
+                                          ((or (eq x ?t) (eq x ?T) (eq y ?t) (eq y ?T)
+                                               (eq x ?s) (eq x ?S) (eq y ?s) (eq y ?S))
+                                           (if (or (eq x ?t) (eq x ?T) (eq y ?t) (eq y ?T))
+                                               (or (funcall special-bit-fn x y ?t ?T)
+                                                   (funcall special-bit-fn y x ?t ?T 'inv))
+                                             (or (funcall special-bit-fn x y ?s ?S)
+                                                 (funcall special-bit-fn y x ?s ?S 'inv))))
+                                          ((eq x ?-) (string ?- y))
+                                          ((eq y ?-) (string ?+ x))))))
+                 (dotimes (i (length mode))
+                   (let ((x (aref mode i))
+                         (y (aref from i)))
+                     (when (= i 3) (setq res (concat res ",g")))
+                     (when (= i 6) (setq res (concat res ",o")))
+                     (setq res (concat res (funcall compare-fn x y)))))
+                 (funcall replace-fn res)))
+              (t
+               (funcall replace-fn
+                        (replace-regexp-in-string
+                         "-" ""
+                         (format "u=%s,g=%s,o=%s"
+                                 (substring mode 0 3)
+                                 (substring mode 3 6)
+                                 (substring mode 6))))))))))
+
 (defun file-modes-symbolic-to-number (modes &optional from)
   "Convert symbolic file modes to numeric file modes.
 MODES is the string to convert, it should match
diff --git a/lisp/tar-mode.el b/lisp/tar-mode.el
index b0d3177694..1843cfcc4a 100644
--- a/lisp/tar-mode.el
+++ b/lisp/tar-mode.el
@@ -470,23 +470,9 @@ tar-clip-time-string
 
 (defun tar-grind-file-mode (mode)
   "Construct a `rw-r--r--' string indicating MODE.
-MODE should be an integer which is a file mode value."
-  (string
-   (if (zerop (logand 256 mode)) ?- ?r)
-   (if (zerop (logand 128 mode)) ?- ?w)
-   (if (zerop (logand 2048 mode))
-       (if (zerop (logand  64 mode)) ?- ?x)
-     (if (zerop (logand  64 mode)) ?S ?s))
-   (if (zerop (logand  32 mode)) ?- ?r)
-   (if (zerop (logand  16 mode)) ?- ?w)
-   (if (zerop (logand 1024 mode))
-       (if (zerop (logand   8 mode)) ?- ?x)
-     (if (zerop (logand   8 mode)) ?S ?s))
-   (if (zerop (logand   4 mode)) ?- ?r)
-   (if (zerop (logand   2 mode)) ?- ?w)
-   (if (zerop (logand 512 mode))
-       (if (zerop (logand   1 mode)) ?- ?x)
-     (if (zerop (logand   1 mode)) ?T ?t))))
+MODE should be an integer which is a file mode value.
+For instance, if mode is 448, then it produces `rwx------'."
+  (substring (file-modes-number-to-symbolic mode) 1))
 
 (defun tar-header-block-summarize (tar-hblock &optional mod-p)
   "Return a line similar to the output of `tar -vtf'."
diff --git a/test/lisp/arc-mode-tests.el b/test/lisp/arc-mode-tests.el
index 8c8465d366..f136becf55 100644
--- a/test/lisp/arc-mode-tests.el
+++ b/test/lisp/arc-mode-tests.el
@@ -26,7 +26,7 @@
   (let ((alist (list (cons 448 "-rwx------")
                      (cons 420 "-rw-r--r--")
                      (cons 292 "-r--r--r--")
-                     (cons 512 "----------")
+                     (cons 512 "---------T")
                      (cons 1024 "------S---") ; Bug#28092
                      (cons 2048 "---S------"))))
     (dolist (x alist)
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index a2f2b74312..fc3017027d 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -344,6 +344,71 @@ files-tests--with-temp-file
         (cdr path-res)
         (insert-directory-wildcard-in-dir-p (car path-res)))))))
 
+(ert-deftest file-modes-symbolic-to-number ()
+  (let ((alist '(("a=rwx" . 511)
+                 ("o=t" . 512)
+                 ("o=xt" . 513)
+                 ("o=tx" . 513) ; Order doesn't matter.
+                 ("u=rwx,g=rx,o=rx" . 493)
+                 ("u=rwx,g=,o=" . 448)
+                 ("u=rwx" . 448) ; Empty permissions can be ignored.
+                 ("u=rw,g=r,o=r" . 420)
+                 ("u=rw,g=r,o=t" . 928)
+                 ("u=rw,g=r,o=xt" . 929)
+                 ("u=rwxs,g=rs,o=xt" . 4065)
+                 ("u=rws,g=rs,o=t" . 4000)
+                 ("u=rws,g=rs,o=r" . 3492)
+                 ("a=r" . 292)
+                 ("u=S")
+                 ("u=T")
+                 ("u=Z"))))
+    (dolist (x alist)
+      (if (cdr-safe x)
+          (equal (cdr-safe x) (file-modes-symbolic-to-number (car x)))
+        (should-error (file-modes-symbolic-to-number (car x)))))))
+
+(ert-deftest file-modes-number-to-symbolic ()
+  (let ((from 644)
+        (fn #'file-modes-number-to-symbolic)
+        ;; Alist of the form (MODE RES1 RES2 RES3),
+        ;; MODE is the first argument of FN.
+        ;; RES1, the result of calling FN with 1 argument.
+        ;; RES2, the result of calling FN with 2nd arg non-nil.
+        ;; RES3, the result of calling FN with 2nd arg non-nil and 3rd arg FROM.
+        (alist '((493 "-rwxr-xr-x" "u=rwx,g=rx,o=rx" "u+r+x,g+r+x,o+xt")
+                 (448 "-rwx------" "u=rwx,g=,o=" "u+r+x,o-r-t")
+                 (420 "-rw-r--r--" "u=rw,g=r,o=r" "u+r,g+r,o-t")
+                 (928 "-rw-r----T" "u=rw,g=rx,o=r" "u+r,g+r,o-r")
+                 (929 "-rw-r----t" "u=rw,g=rx,o=rx" "u+r,g+r,o-r+x")
+                 (4065 "-rwsr-S--t" "u=rws,g=rS,o=t" "u+r+xs,g+r+s,o-r+x")
+                 (4000 "-rwSr-S--T" "u=rwS,g=rS,o=T" "u+r+s,g+r+s,o-r")
+                 (3492 "-rwSr-Sr--" "u=rwS,g=rS,o=r" "u+r+s,g+r+s,o-t")
+                 (292 "-r--r--r--" "u=r,g=r,o=r" "u+r-w,g+r,o-t")
+                 ("u=S")
+                 ("u=T")
+                 ("u=Z"))))
+    (dolist (x alist)
+      (cond ((cdr-safe x)
+             (let ((res1 (cadr x)) (res2 (caddr x)) (res3 (cadddr x)))
+               (equal res1 (funcall fn (car x)))
+               ;; FROM is ignored when DETAILED is nil.
+               (equal res1 (funcall fn (car x) nil from))
+               (equal res2 (funcall fn (car x) 'detailed))
+               (equal res3 (funcall fn (car x) 'detailed from))))
+            (t (should-error (funcall fn (car x))))))))
+
+(ert-deftest file-modes-number-to-symbolic-inverse ()
+  (dotimes (i 4096) ; from 0 to 7777 in octal.
+    ;; If neithr sticky bit nor set_uid not set_gid are set, then
+    ;; `file-modes-symbolic-to-number' is the inverse of
+    ;; `file-modes-number-to-symbolic'.
+    (when (and (zerop (logand i 512))
+               (zerop (logand i 1024))
+               (zerop (logand i 2048)))
+      (should
+       (= i
+          (file-modes-symbolic-to-number
+           (file-modes-number-to-symbolic i t)))))))
 
 (provide 'files-tests)
 ;;; files-tests.el ends here

--8<-----------------------------cut here---------------end--------------->8---
In GNU Emacs 26.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.22.11)
 of 2017-08-16
Repository revision: 400934b694087f4fe94755d78cbd1569efdb1fa8




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Wed, 16 Aug 2017 11:59:02 GMT) Full text and rfc822 format available.

Message #13 received at 27952 <at> debbugs.gnu.org (full text, mbox):

From: npostavs <at> users.sourceforge.net
To: Tino Calancha <tino.calancha <at> gmail.com>
Cc: Eli Zaretskii <eliz <at> gnu.org>, 27952 <at> debbugs.gnu.org,
 stefan monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#27952: 26.0.50;
 Combine archive-int-to-mode and tar-grind-file-mode
Date: Wed, 16 Aug 2017 08:00:03 -0400
Tino Calancha <tino.calancha <at> gmail.com> writes:

> +                          (replace-regexp-in-string
> +                           ",\\`" ""

This regex doesn't match anything, did you mean \\' at the end?

>  (defun tar-grind-file-mode (mode)
>    "Construct a `rw-r--r--' string indicating MODE.

> +MODE should be an integer which is a file mode value.
> +For instance, if mode is 448, then it produces `rwx------'."

IMO, it's clearer if you write #o700 instead of 448 here, perhaps in the
code too.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Wed, 16 Aug 2017 12:09:02 GMT) Full text and rfc822 format available.

Message #16 received at 27952 <at> debbugs.gnu.org (full text, mbox):

From: Andreas Schwab <schwab <at> suse.de>
To: Tino Calancha <tino.calancha <at> gmail.com>
Cc: 27952 <at> debbugs.gnu.org, stefan monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#27952: 26.0.50;
 Combine archive-int-to-mode and tar-grind-file-mode
Date: Wed, 16 Aug 2017 14:08:10 +0200
On Aug 16 2017, Tino Calancha <tino.calancha <at> gmail.com> wrote:

> +Note: This is not the inverse of `file-modes-symbolic-to-number';
> +The reason is that this function might return an string containing 'S'
> +or 'T' i.e., not valid characters for `file-modes-symbolic-to-number'.
> +For example, (file-modes-symbolic-to-number \"o=t\") returns 512;
> +and (file-modes-number-to-symbolic 512 t) returns \"o=T\"."

Why would it use uppercase T in the detailed case?  Uppercase is only
needed when it would overlay the 'x' position in the non-detailed case.

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab <at> suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Wed, 16 Aug 2017 13:11:03 GMT) Full text and rfc822 format available.

Message #19 received at 27952 <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: Andreas Schwab <schwab <at> suse.de>
Cc: 27952 <at> debbugs.gnu.org, stefan monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#27952: 26.0.50; Combine archive-int-to-mode and
 tar-grind-file-mode
Date: Wed, 16 Aug 2017 22:10:17 +0900 (JST)

On Wed, 16 Aug 2017, Andreas Schwab wrote:

> On Aug 16 2017, Tino Calancha <tino.calancha <at> gmail.com> wrote:
>
>> +Note: This is not the inverse of `file-modes-symbolic-to-number';
>> +The reason is that this function might return an string containing 'S'
>> +or 'T' i.e., not valid characters for `file-modes-symbolic-to-number'.
>> +For example, (file-modes-symbolic-to-number \"o=t\") returns 512;
>> +and (file-modes-number-to-symbolic 512 t) returns \"o=T\"."
>
> Why would it use uppercase T in the detailed case?  Uppercase is only
> needed when it would overlay the 'x' position in the non-detailed case.
Not special reason i think.  To keep more similar with
the case when DETAILED is nil.
 (file-modes-number-to-symbolic 512)
=> "---------T"

At the end of the function that is changed into
"o=T"
with:

(funcall replace-fn
   (replace-regexp-in-string
      "-" "" ...

I liked like this when i wrote the patch.  We could changed it in
case is confusing.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Wed, 16 Aug 2017 13:14:01 GMT) Full text and rfc822 format available.

Message #22 received at 27952 <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: npostavs <at> users.sourceforge.net
Cc: Eli Zaretskii <eliz <at> gnu.org>, 27952 <at> debbugs.gnu.org,
 stefan monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#27952: 26.0.50; Combine archive-int-to-mode and
 tar-grind-file-mode
Date: Wed, 16 Aug 2017 22:13:48 +0900 (JST)

On Wed, 16 Aug 2017, npostavs <at> users.sourceforge.net wrote:

> Tino Calancha <tino.calancha <at> gmail.com> writes:
>
>> +                          (replace-regexp-in-string
>> +                           ",\\`" ""
>
> This regex doesn't match anything, did you mean \\' at the end?
Yes, you are right.  I wanted to drop comma at the end.

>>  (defun tar-grind-file-mode (mode)
>>    "Construct a `rw-r--r--' string indicating MODE.
>
>> +MODE should be an integer which is a file mode value.
>> +For instance, if mode is 448, then it produces `rwx------'."
>
> IMO, it's clearer if you write #o700 instead of 448 here, perhaps in the
> code too.
Yeah, for those people not having nbc.el (num-base-converters) might be
easier to follow.  Opps, i am the only one having nbc.el! :-)




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Mon, 24 Jun 2019 20:36:02 GMT) Full text and rfc822 format available.

Message #25 received at 27952 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Tino Calancha <tino.calancha <at> gmail.com>
Cc: 27952 <at> debbugs.gnu.org, stefan monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#27952: 26.0.50;
 Combine archive-int-to-mode and tar-grind-file-mode
Date: Mon, 24 Jun 2019 22:35:03 +0200
Tino Calancha <tino.calancha <at> gmail.com> writes:

> These functions are almost identical; archive-int-to-mode has a FIXME
> suggesting merging it with tar-grind-file-mode.

Tino, there were some suggestions about some syntactical issues, but
otherwise I don't think anybody objected to the patch.  Did you continue
to work on it?  It doesn't seem to have been applied.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Mon, 24 Jun 2019 20:43:03 GMT) Full text and rfc822 format available.

Message #28 received at 27952 <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: 27952 <at> debbugs.gnu.org, stefan monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#27952: 26.0.50; Combine archive-int-to-mode and
 tar-grind-file-mode
Date: Tue, 25 Jun 2019 05:42:50 +0900 (JST)

Probably I wasn't happy enough with my patch and that's why I forget
about it (I maybe started the fishing season and that got all my 
attention; I cannot remember).

I will work on this again since next weekend and try to prepare the 
simples patch as possible.

Thank you for the reminder!
Tino

> Tino Calancha <tino.calancha <at> gmail.com> writes:
>
>> These functions are almost identical; archive-int-to-mode has a FIXME
>> suggesting merging it with tar-grind-file-mode.
>
> Tino, there were some suggestions about some syntactical issues, but
> otherwise I don't think anybody objected to the patch.  Did you continue
> to work on it?  It doesn't seem to have been applied.
>
> -- 
> (domestic pets only, the antidote for overdose, milk.)
>   bloggy blog: http://lars.ingebrigtsen.no
>




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Mon, 11 Nov 2019 03:08:02 GMT) Full text and rfc822 format available.

Message #31 received at 27952 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Kangas <stefan <at> marxist.se>
To: Tino Calancha <tino.calancha <at> gmail.com>
Cc: Lars Ingebrigtsen <larsi <at> gnus.org>, 27952 <at> debbugs.gnu.org,
 stefan monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#27952: 26.0.50; Combine archive-int-to-mode and
 tar-grind-file-mode
Date: Mon, 11 Nov 2019 04:07:45 +0100
Tino Calancha <tino.calancha <at> gmail.com> writes:

> Probably I wasn't happy enough with my patch and that's why I forget
> about it (I maybe started the fishing season and that got all my attention; I
> cannot remember).
>
> I will work on this again since next weekend and try to prepare the simples
> patch as possible.

That was 19 weeks ago.  Were you able to make any progress here?

Thanks in advance.

Best regards,
Stefan Kangas




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Wed, 13 Nov 2019 16:59:02 GMT) Full text and rfc822 format available.

Message #34 received at 27952 <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: Stefan Kangas <stefan <at> marxist.se>
Cc: Lars Ingebrigtsen <larsi <at> gnus.org>, 27952 <at> debbugs.gnu.org,
 stefan monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#27952: 26.0.50; Combine archive-int-to-mode and
 tar-grind-file-mode
Date: Wed, 13 Nov 2019 17:58:45 +0100 (CET)

On Mon, 11 Nov 2019, Stefan Kangas wrote:

> Tino Calancha <tino.calancha <at> gmail.com> writes:
>
>> I will work on this again since next weekend and try to prepare the simples
>> patch as possible.
>
> That was 19 weeks ago.  Were you able to make any progress here?
I am in the process to 'recover' my copyright freedom; currently I can 
not submit any work > 15 lines.

PD: After November 30th 2019 I will be back (as Terminator).




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Mon, 04 May 2020 11:56:01 GMT) Full text and rfc822 format available.

Message #37 received at 27952 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Kangas <stefan <at> marxist.se>
To: Tino Calancha <tino.calancha <at> gmail.com>
Cc: Lars Ingebrigtsen <larsi <at> gnus.org>, 27952 <at> debbugs.gnu.org,
 stefan monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#27952: 26.0.50; Combine archive-int-to-mode and
 tar-grind-file-mode
Date: Mon, 04 May 2020 13:55:46 +0200
Tino Calancha <tino.calancha <at> gmail.com> writes:

> On Mon, 11 Nov 2019, Stefan Kangas wrote:
>
>> Tino Calancha <tino.calancha <at> gmail.com> writes:
>>
>>> I will work on this again since next weekend and try to prepare the simples
>>> patch as possible.
>>
>> That was 19 weeks ago.  Were you able to make any progress here?
>
> I am in the process to 'recover' my copyright freedom; currently I can not
> submit any work > 15 lines.

Just another friendly ping, 6 months later.  Please let us know if
there has been any progress here.  Thanks in advance.

Best regards,
Stefan Kangas




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Fri, 08 May 2020 19:54:02 GMT) Full text and rfc822 format available.

Message #40 received at 27952 <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: Stefan Kangas <stefan <at> marxist.se>
Cc: Lars Ingebrigtsen <larsi <at> gnus.org>, 27952 <at> debbugs.gnu.org,
 stefan monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#27952: 26.0.50; Combine archive-int-to-mode and
 tar-grind-file-mode
Date: Fri, 8 May 2020 21:53:24 +0200 (CEST)

On Mon, 4 May 2020, Stefan Kangas wrote:

> Just another friendly ping, 6 months later.  Please let us know if
> there has been any progress here.  Thanks in advance.
Thank you for the reminder!
As I pointed out before, I wasn't really satisfied with my original
patch; the one adding a function with > 1 arguments: too complex and I
suspect failing side cases.

Instead, I propose the following easy one:

--8<-----------------------------cut here---------------start------------->8---
commit dc126c15c181afed9d236f4c1077e2c7f02b01df
Author: Tino Calancha <tino.calancha <at> gmail.com>
Date:   Fri May 8 21:29:05 2020 +0200

    Combine archive-int-to-mode and tar-grind-file-mode

    Add a new function, file-modes-number-to-symbolic.
    Make archive-int-to-mode and alias of it; use it
    to define tar-grind-file-mode (Bug#27952).

    * lisp/files.el (file-modes-number-to-symbolic): New defun.
    * lisp/arc-mode.el (archive-int-to-mode): Make it an alias.
    * lisp/tar-mode.el (tar-grind-file-mode):
    Use file-modes-number-to-symbolic.

    * test/lisp/arc-mode-tests.el (arc-mode-test-archive-int-to-mode)
    * test/lisp/tar-mode-tests.el (tar-mode-test-tar-grind-file-mode):
    Update test.

    * test/lisp/files-tests.el (files-tests-file-modes-symbolic-to-number)
    (files-tests-file-modes-number-to-symbolic): New tests.

    * doc/lispref/files.texi (Changing Files): Document the new funtion.
    * etc/NEWS (Lisp Changes in Emacs 28.1): Announce it.

diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index b3ad9b9964..686dbdb1ca 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -1909,6 +1909,11 @@ Changing Files
 all.
 @end defun

+@defun file-modes-number-to-symbolic modes
+This function converts a numeric file mode specification in
+@var{modes} into the equivalent symbolic form.
+@end defun
+
 @defun set-file-times filename &optional time flag
 This function sets the access and modification times of @var{filename}
 to @var{time}.  The return value is @code{t} if the times are successfully
diff --git a/etc/NEWS b/etc/NEWS
index ac93a76ff9..26426fc42b 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -372,6 +372,10 @@ Use macro 'with-current-buffer-window' with action alist entry 'body-function'.

 * Lisp Changes in Emacs 28.1

++++
+** New function 'file-modes-number-to-symbolic' to convert a numeric
+file mode specification into symbolic form.
+
 ** New macro 'dlet' to dynamically bind variables.

 ** The variable 'force-new-style-backquotes' has been removed.
diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index c918f06c80..0c801c67a5 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -563,28 +563,7 @@ archive-l-e
 		      (aref str (- len i)))))
     result))

-(defun archive-int-to-mode (mode)
-  "Turn an integer like 0700 (i.e., 448) into a mode string like -rwx------."
-  ;; FIXME: merge with tar-grind-file-mode.
-  (if (null mode)
-      "??????????"
-    (string
-     (if (zerop (logand  8192 mode))
-	 (if (zerop (logand 16384 mode)) ?- ?d)
-       ?c)                              ; completeness
-     (if (zerop (logand   256 mode)) ?- ?r)
-     (if (zerop (logand   128 mode)) ?- ?w)
-     (if (zerop (logand    64 mode))
-	 (if (zerop (logand  2048 mode)) ?- ?S)
-       (if (zerop (logand  2048 mode)) ?x ?s))
-     (if (zerop (logand    32 mode)) ?- ?r)
-     (if (zerop (logand    16 mode)) ?- ?w)
-     (if (zerop (logand     8 mode))
-	 (if (zerop (logand  1024 mode)) ?- ?S)
-       (if (zerop (logand  1024 mode)) ?x ?s))
-     (if (zerop (logand     4 mode)) ?- ?r)
-     (if (zerop (logand     2 mode)) ?- ?w)
-     (if (zerop (logand     1 mode)) ?- ?x))))
+(defalias 'archive-int-to-mode 'file-modes-number-to-symbolic)

 (defun archive-calc-mode (oldmode newmode)
   "From the integer OLDMODE and the string NEWMODE calculate a new file mode.
diff --git a/lisp/files.el b/lisp/files.el
index c34fe00388..dba704f7a4 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -7552,6 +7552,27 @@ file-modes-rights-to-number
 	      op char-right)))
     num-rights))

+(defun file-modes-number-to-symbolic (mode)
+  (string
+   (if (zerop (logand  8192 mode))
+       (if (zerop (logand 16384 mode)) ?- ?d)
+     ?c) ; completeness
+   (if (zerop (logand   256 mode)) ?- ?r)
+   (if (zerop (logand   128 mode)) ?- ?w)
+   (if (zerop (logand    64 mode))
+       (if (zerop (logand  2048 mode)) ?- ?S)
+     (if (zerop (logand  2048 mode)) ?x ?s))
+   (if (zerop (logand    32 mode)) ?- ?r)
+   (if (zerop (logand    16 mode)) ?- ?w)
+   (if (zerop (logand     8 mode))
+       (if (zerop (logand  1024 mode)) ?- ?S)
+     (if (zerop (logand  1024 mode)) ?x ?s))
+   (if (zerop (logand     4 mode)) ?- ?r)
+   (if (zerop (logand     2 mode)) ?- ?w)
+   (if (zerop (logand 512 mode))
+       (if (zerop (logand   1 mode)) ?- ?x)
+     (if (zerop (logand   1 mode)) ?T ?t))))
+
 (defun file-modes-symbolic-to-number (modes &optional from)
   "Convert symbolic file modes to numeric file modes.
 MODES is the string to convert, it should match
diff --git a/lisp/tar-mode.el b/lisp/tar-mode.el
index a3c1715b1e..73978ffc4a 100644
--- a/lisp/tar-mode.el
+++ b/lisp/tar-mode.el
@@ -480,23 +480,9 @@ tar-clip-time-string

 (defun tar-grind-file-mode (mode)
   "Construct a `rw-r--r--' string indicating MODE.
-MODE should be an integer which is a file mode value."
-  (string
-   (if (zerop (logand 256 mode)) ?- ?r)
-   (if (zerop (logand 128 mode)) ?- ?w)
-   (if (zerop (logand 2048 mode))
-       (if (zerop (logand  64 mode)) ?- ?x)
-     (if (zerop (logand  64 mode)) ?S ?s))
-   (if (zerop (logand  32 mode)) ?- ?r)
-   (if (zerop (logand  16 mode)) ?- ?w)
-   (if (zerop (logand 1024 mode))
-       (if (zerop (logand   8 mode)) ?- ?x)
-     (if (zerop (logand   8 mode)) ?S ?s))
-   (if (zerop (logand   4 mode)) ?- ?r)
-   (if (zerop (logand   2 mode)) ?- ?w)
-   (if (zerop (logand 512 mode))
-       (if (zerop (logand   1 mode)) ?- ?x)
-     (if (zerop (logand   1 mode)) ?T ?t))))
+MODE should be an integer which is a file mode value.
+For instance, if mode is #o700, then it produces `rwx------'."
+  (substring (file-modes-number-to-symbolic mode) 1))

 (defun tar-header-block-summarize (tar-hblock &optional mod-p)
   "Return a line similar to the output of `tar -vtf'."
diff --git a/test/lisp/arc-mode-tests.el b/test/lisp/arc-mode-tests.el
index df658b9813..22ca7e2ec5 100644
--- a/test/lisp/arc-mode-tests.el
+++ b/test/lisp/arc-mode-tests.el
@@ -28,7 +28,7 @@ arc-mode-tests-data-directory
   (let ((alist (list (cons 448 "-rwx------")
                      (cons 420 "-rw-r--r--")
                      (cons 292 "-r--r--r--")
-                     (cons 512 "----------")
+                     (cons 512 "---------T")
                      (cons 1024 "------S---") ; Bug#28092
                      (cons 2048 "---S------"))))
     (dolist (x alist)
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index 05d9ceebf1..4b902fd82a 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -1164,6 +1164,42 @@ files-tests-file-attributes-equal
     (should-not (make-directory a/b t))
     (delete-directory dir 'recursive)))

+(ert-deftest files-tests-file-modes-symbolic-to-number ()
+  (let ((alist (list (cons "a=rwx" #o777)
+                     (cons "o=t" #o1000)
+                     (cons "o=xt" #o1001)
+                     (cons "o=tx" #o1001) ; Order doesn't matter.
+                     (cons "u=rwx,g=rx,o=rx" #o755)
+                     (cons "u=rwx,g=,o=" #o700)
+                     (cons "u=rwx" #o700) ; Empty permissions can be ignored.
+                     (cons "u=rw,g=r,o=r" #o644)
+                     (cons "u=rw,g=r,o=t" #o1640)
+                     (cons "u=rw,g=r,o=xt" #o1641)
+                     (cons "u=rwxs,g=rs,o=xt" #o7741)
+                     (cons "u=rws,g=rs,o=t" #o7640)
+                     (cons "u=rws,g=rs,o=r" #o6644)
+                     (cons "a=r" #o444)
+                     (cons "u=S" nil)
+                     (cons "u=T" nil)
+                     (cons "u=Z" nil))))
+    (dolist (x alist)
+      (if (cdr-safe x)
+          (should (equal (cdr x) (file-modes-symbolic-to-number (car x))))
+        (should-error (file-modes-symbolic-to-number (car x)))))))
+
+(ert-deftest files-tests-file-modes-number-to-symbolic ()
+  (let ((alist (list (cons #o755 "-rwxr-xr-x")
+                     (cons #o700 "-rwx------")
+                     (cons #o644 "-rw-r--r--")
+                     (cons #o1640 "-rw-r----T")
+                     (cons #o1641 "-rw-r----t")
+                     (cons #o7741 "-rwsr-S--t")
+                     (cons #o7640 "-rwSr-S--T")
+                     (cons #o6644 "-rwSr-Sr--")
+                     (cons #o444 "-r--r--r--"))))
+    (dolist (x alist)
+      (should (equal (cdr x) (file-modes-number-to-symbolic (car x)))))))
+
 (ert-deftest files-tests-no-file-write-contents ()
   "Test that `write-contents-functions' permits saving a file.
 Usually `basic-save-buffer' will prompt for a file name if the
diff --git a/test/lisp/tar-mode-tests.el b/test/lisp/tar-mode-tests.el
index bc41b863da..f05389df60 100644
--- a/test/lisp/tar-mode-tests.el
+++ b/test/lisp/tar-mode-tests.el
@@ -29,7 +29,8 @@ tar-mode-tests-data-directory
                      (cons 420 "rw-r--r--")
                      (cons 292 "r--r--r--")
                      (cons 512 "--------T")
-                     (cons 1024 "-----S---"))))
+                     (cons 1024 "-----S---")
+                     (cons 2048 "--S------"))))
     (dolist (x alist)
       (should (equal (cdr x) (tar-grind-file-mode (car x)))))))


--8<-----------------------------cut here---------------end--------------->8---
In GNU Emacs 28.0.50 (build 4, x86_64-pc-linux-gnu, GTK+ Version 3.24.5, cairo version 1.16.0)
 of 2020-05-08 built on calancha-pc.dy.bbexcite.jp
Repository revision: 4b8e6939bf7664fda33a7aaa03d2d8069358ff7b
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12004000
System Description: Debian GNU/Linux 10 (buster)




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Fri, 08 May 2020 20:07:01 GMT) Full text and rfc822 format available.

Message #43 received at 27952 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Tino Calancha <tino.calancha <at> gmail.com>
Cc: 27952 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>,
 Stefan Kangas <stefan <at> marxist.se>
Subject: Re: bug#27952: 26.0.50; Combine archive-int-to-mode and
 tar-grind-file-mode
Date: Fri, 08 May 2020 16:06:27 -0400
> +(defalias 'archive-int-to-mode 'file-modes-number-to-symbolic)

Make it a `define-obsolete-function-alias`.

>  (defun tar-grind-file-mode (mode)
>    "Construct a `rw-r--r--' string indicating MODE.
[...]
> +MODE should be an integer which is a file mode value.
> +For instance, if mode is #o700, then it produces `rwx------'."
> +  (substring (file-modes-number-to-symbolic mode) 1))

LGTM.  A second step might be to mark this function as obsolete and
update all the call sites so they are happy with the output format of
`file-modes-number-to-symbolic`.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Fri, 08 May 2020 20:21:02 GMT) Full text and rfc822 format available.

Message #46 received at 27952 <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 27952 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>,
 Stefan Kangas <stefan <at> marxist.se>, Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#27952: 26.0.50; Combine archive-int-to-mode and
 tar-grind-file-mode
Date: Fri, 8 May 2020 22:20:15 +0200 (CEST)

On Fri, 8 May 2020, Stefan Monnier wrote:

>> +(defalias 'archive-int-to-mode 'file-modes-number-to-symbolic)
>
> Make it a `define-obsolete-function-alias`.
OK.

>>  (defun tar-grind-file-mode (mode)
>>    "Construct a `rw-r--r--' string indicating MODE.
> [...]
>> +MODE should be an integer which is a file mode value.
>> +For instance, if mode is #o700, then it produces `rwx------'."
>> +  (substring (file-modes-number-to-symbolic mode) 1))
>
> LGTM.
Good.  Then, I will merge it next week.

> A second step might be to mark this function as obsolete and
> update all the call sites so they are happy with the output format of
> `file-modes-number-to-symbolic`.
It sounds good; it's funny having those 2 defun with almost identical 
output.
Maybe you can add a TODO in the code asking for this; people feel 
encouraged to contribute when they found those FIXME/TODOs.

Amended patch follows:

--8<-----------------------------cut here---------------start------------->8---
commit 043ecae1c0828bcad94083ef456195ae21675a1a
Author: Tino Calancha <tino.calancha <at> gmail.com>
Date:   Fri May 8 22:14:03 2020 +0200

    Combine archive-int-to-mode and tar-grind-file-mode

    Add a new function, file-modes-number-to-symbolic.
    Make archive-int-to-mode and obsolete alias of it; use it
    to define tar-grind-file-mode (Bug#27952).

    * lisp/files.el (file-modes-number-to-symbolic): New defun.
    * lisp/arc-mode.el (archive-int-to-mode): Make it an obsolete alias.
    * lisp/tar-mode.el (tar-grind-file-mode):
    Use file-modes-number-to-symbolic.

    * test/lisp/arc-mode-tests.el (arc-mode-test-archive-int-to-mode)
    * test/lisp/tar-mode-tests.el (tar-mode-test-tar-grind-file-mode):
    Update test.

    * test/lisp/files-tests.el (files-tests-file-modes-symbolic-to-number)
    (files-tests-file-modes-number-to-symbolic): New tests.

    * doc/lispref/files.texi (Changing Files): Document the new funtion.
    * etc/NEWS (Lisp Changes in Emacs 28.1): Announce it.

diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index b3ad9b9964..686dbdb1ca 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -1909,6 +1909,11 @@ Changing Files
 all.
 @end defun

+@defun file-modes-number-to-symbolic modes
+This function converts a numeric file mode specification in
+@var{modes} into the equivalent symbolic form.
+@end defun
+
 @defun set-file-times filename &optional time flag
 This function sets the access and modification times of @var{filename}
 to @var{time}.  The return value is @code{t} if the times are successfully
diff --git a/etc/NEWS b/etc/NEWS
index ac93a76ff9..26426fc42b 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -372,6 +372,10 @@ Use macro 'with-current-buffer-window' with action alist entry 'body-function'.

 * Lisp Changes in Emacs 28.1

++++
+** New function 'file-modes-number-to-symbolic' to convert a numeric
+file mode specification into symbolic form.
+
 ** New macro 'dlet' to dynamically bind variables.

 ** The variable 'force-new-style-backquotes' has been removed.
diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index c918f06c80..6ce64fe24b 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -563,28 +563,8 @@ archive-l-e
 		      (aref str (- len i)))))
     result))

-(defun archive-int-to-mode (mode)
-  "Turn an integer like 0700 (i.e., 448) into a mode string like -rwx------."
-  ;; FIXME: merge with tar-grind-file-mode.
-  (if (null mode)
-      "??????????"
-    (string
-     (if (zerop (logand  8192 mode))
-	 (if (zerop (logand 16384 mode)) ?- ?d)
-       ?c)                              ; completeness
-     (if (zerop (logand   256 mode)) ?- ?r)
-     (if (zerop (logand   128 mode)) ?- ?w)
-     (if (zerop (logand    64 mode))
-	 (if (zerop (logand  2048 mode)) ?- ?S)
-       (if (zerop (logand  2048 mode)) ?x ?s))
-     (if (zerop (logand    32 mode)) ?- ?r)
-     (if (zerop (logand    16 mode)) ?- ?w)
-     (if (zerop (logand     8 mode))
-	 (if (zerop (logand  1024 mode)) ?- ?S)
-       (if (zerop (logand  1024 mode)) ?x ?s))
-     (if (zerop (logand     4 mode)) ?- ?r)
-     (if (zerop (logand     2 mode)) ?- ?w)
-     (if (zerop (logand     1 mode)) ?- ?x))))
+(define-obsolete-function-alias 'archive-int-to-mode
+  'file-modes-number-to-symbolic "28.1")

 (defun archive-calc-mode (oldmode newmode)
   "From the integer OLDMODE and the string NEWMODE calculate a new file mode.
diff --git a/lisp/files.el b/lisp/files.el
index c34fe00388..dba704f7a4 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -7552,6 +7552,27 @@ file-modes-rights-to-number
 	      op char-right)))
     num-rights))

+(defun file-modes-number-to-symbolic (mode)
+  (string
+   (if (zerop (logand  8192 mode))
+       (if (zerop (logand 16384 mode)) ?- ?d)
+     ?c) ; completeness
+   (if (zerop (logand   256 mode)) ?- ?r)
+   (if (zerop (logand   128 mode)) ?- ?w)
+   (if (zerop (logand    64 mode))
+       (if (zerop (logand  2048 mode)) ?- ?S)
+     (if (zerop (logand  2048 mode)) ?x ?s))
+   (if (zerop (logand    32 mode)) ?- ?r)
+   (if (zerop (logand    16 mode)) ?- ?w)
+   (if (zerop (logand     8 mode))
+       (if (zerop (logand  1024 mode)) ?- ?S)
+     (if (zerop (logand  1024 mode)) ?x ?s))
+   (if (zerop (logand     4 mode)) ?- ?r)
+   (if (zerop (logand     2 mode)) ?- ?w)
+   (if (zerop (logand 512 mode))
+       (if (zerop (logand   1 mode)) ?- ?x)
+     (if (zerop (logand   1 mode)) ?T ?t))))
+
 (defun file-modes-symbolic-to-number (modes &optional from)
   "Convert symbolic file modes to numeric file modes.
 MODES is the string to convert, it should match
diff --git a/lisp/tar-mode.el b/lisp/tar-mode.el
index a3c1715b1e..73978ffc4a 100644
--- a/lisp/tar-mode.el
+++ b/lisp/tar-mode.el
@@ -480,23 +480,9 @@ tar-clip-time-string

 (defun tar-grind-file-mode (mode)
   "Construct a `rw-r--r--' string indicating MODE.
-MODE should be an integer which is a file mode value."
-  (string
-   (if (zerop (logand 256 mode)) ?- ?r)
-   (if (zerop (logand 128 mode)) ?- ?w)
-   (if (zerop (logand 2048 mode))
-       (if (zerop (logand  64 mode)) ?- ?x)
-     (if (zerop (logand  64 mode)) ?S ?s))
-   (if (zerop (logand  32 mode)) ?- ?r)
-   (if (zerop (logand  16 mode)) ?- ?w)
-   (if (zerop (logand 1024 mode))
-       (if (zerop (logand   8 mode)) ?- ?x)
-     (if (zerop (logand   8 mode)) ?S ?s))
-   (if (zerop (logand   4 mode)) ?- ?r)
-   (if (zerop (logand   2 mode)) ?- ?w)
-   (if (zerop (logand 512 mode))
-       (if (zerop (logand   1 mode)) ?- ?x)
-     (if (zerop (logand   1 mode)) ?T ?t))))
+MODE should be an integer which is a file mode value.
+For instance, if mode is #o700, then it produces `rwx------'."
+  (substring (file-modes-number-to-symbolic mode) 1))

 (defun tar-header-block-summarize (tar-hblock &optional mod-p)
   "Return a line similar to the output of `tar -vtf'."
diff --git a/test/lisp/arc-mode-tests.el b/test/lisp/arc-mode-tests.el
index df658b9813..22ca7e2ec5 100644
--- a/test/lisp/arc-mode-tests.el
+++ b/test/lisp/arc-mode-tests.el
@@ -28,7 +28,7 @@ arc-mode-tests-data-directory
   (let ((alist (list (cons 448 "-rwx------")
                      (cons 420 "-rw-r--r--")
                      (cons 292 "-r--r--r--")
-                     (cons 512 "----------")
+                     (cons 512 "---------T")
                      (cons 1024 "------S---") ; Bug#28092
                      (cons 2048 "---S------"))))
     (dolist (x alist)
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index 05d9ceebf1..4b902fd82a 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -1164,6 +1164,42 @@ files-tests-file-attributes-equal
     (should-not (make-directory a/b t))
     (delete-directory dir 'recursive)))

+(ert-deftest files-tests-file-modes-symbolic-to-number ()
+  (let ((alist (list (cons "a=rwx" #o777)
+                     (cons "o=t" #o1000)
+                     (cons "o=xt" #o1001)
+                     (cons "o=tx" #o1001) ; Order doesn't matter.
+                     (cons "u=rwx,g=rx,o=rx" #o755)
+                     (cons "u=rwx,g=,o=" #o700)
+                     (cons "u=rwx" #o700) ; Empty permissions can be ignored.
+                     (cons "u=rw,g=r,o=r" #o644)
+                     (cons "u=rw,g=r,o=t" #o1640)
+                     (cons "u=rw,g=r,o=xt" #o1641)
+                     (cons "u=rwxs,g=rs,o=xt" #o7741)
+                     (cons "u=rws,g=rs,o=t" #o7640)
+                     (cons "u=rws,g=rs,o=r" #o6644)
+                     (cons "a=r" #o444)
+                     (cons "u=S" nil)
+                     (cons "u=T" nil)
+                     (cons "u=Z" nil))))
+    (dolist (x alist)
+      (if (cdr-safe x)
+          (should (equal (cdr x) (file-modes-symbolic-to-number (car x))))
+        (should-error (file-modes-symbolic-to-number (car x)))))))
+
+(ert-deftest files-tests-file-modes-number-to-symbolic ()
+  (let ((alist (list (cons #o755 "-rwxr-xr-x")
+                     (cons #o700 "-rwx------")
+                     (cons #o644 "-rw-r--r--")
+                     (cons #o1640 "-rw-r----T")
+                     (cons #o1641 "-rw-r----t")
+                     (cons #o7741 "-rwsr-S--t")
+                     (cons #o7640 "-rwSr-S--T")
+                     (cons #o6644 "-rwSr-Sr--")
+                     (cons #o444 "-r--r--r--"))))
+    (dolist (x alist)
+      (should (equal (cdr x) (file-modes-number-to-symbolic (car x)))))))
+
 (ert-deftest files-tests-no-file-write-contents ()
   "Test that `write-contents-functions' permits saving a file.
 Usually `basic-save-buffer' will prompt for a file name if the
diff --git a/test/lisp/tar-mode-tests.el b/test/lisp/tar-mode-tests.el
index bc41b863da..f05389df60 100644
--- a/test/lisp/tar-mode-tests.el
+++ b/test/lisp/tar-mode-tests.el
@@ -29,7 +29,8 @@ tar-mode-tests-data-directory
                      (cons 420 "rw-r--r--")
                      (cons 292 "r--r--r--")
                      (cons 512 "--------T")
-                     (cons 1024 "-----S---"))))
+                     (cons 1024 "-----S---")
+                     (cons 2048 "--S------"))))
     (dolist (x alist)
       (should (equal (cdr x) (tar-grind-file-mode (car x)))))))

--8<-----------------------------cut here---------------end--------------->8---

In GNU Emacs 28.0.50 (build 4, x86_64-pc-linux-gnu, GTK+ Version 3.24.5, 
cairo version 1.16.0)
 of 2020-05-08 built on calancha-pc.dy.bbexcite.jp
Repository revision: 4b8e6939bf7664fda33a7aaa03d2d8069358ff7b
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12004000
System Description: Debian GNU/Linux 10 (buster)





Reply sent to Tino Calancha <tino.calancha <at> gmail.com>:
You have taken responsibility. (Thu, 14 May 2020 16:48:02 GMT) Full text and rfc822 format available.

Notification sent to Tino Calancha <tino.calancha <at> gmail.com>:
bug acknowledged by developer. (Thu, 14 May 2020 16:48:02 GMT) Full text and rfc822 format available.

Message #51 received at 27952-done <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: 27952-done <at> debbugs.gnu.org
Subject: Re: bug#27952: 26.0.50; Combine archive-int-to-mode and
 tar-grind-file-mode
Date: Thu, 14 May 2020 18:47:34 +0200
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:

> LGTM.

Fixed in master branch as commit
'Combine archive-int-to-mode and tar-grind-file-mode'
(3a284e578625e617fdc6085ae11da2b4e41bb59b)




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Thu, 14 May 2020 17:25:01 GMT) Full text and rfc822 format available.

Message #54 received at 27952 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Tino Calancha <tino.calancha <at> gmail.com>
Cc: 27952 <at> debbugs.gnu.org
Subject: Re: bug#27952: 26.0.50;
 Combine archive-int-to-mode and tar-grind-file-mode
Date: Thu, 14 May 2020 20:23:34 +0300
> From: Tino Calancha <tino.calancha <at> gmail.com>
> Date: Thu, 14 May 2020 18:47:34 +0200
> 
> Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
> 
> > LGTM.
> 
> Fixed in master branch as commit
> 'Combine archive-int-to-mode and tar-grind-file-mode'
> (3a284e578625e617fdc6085ae11da2b4e41bb59b)

The fix triggers compilation warnings:

  In archive--summarize-descs:
  arc-mode.el:1509:45: Warning: `archive-int-to-mode' is an obsolete function
      (as of 28.1); use `file-modes-number-to-symbolic' instead.
  arc-mode.el:1574:70: Warning: `archive-int-to-mode' is an obsolete function
      (as of 28.1); use `file-modes-number-to-symbolic' instead.

Would it be possible to eliminate these warnings, please?

Thanks.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Thu, 14 May 2020 20:09:02 GMT) Full text and rfc822 format available.

Message #57 received at 27952 <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 27952 <at> debbugs.gnu.org, Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#27952: 26.0.50; Combine archive-int-to-mode and
 tar-grind-file-mode
Date: Thu, 14 May 2020 22:08:36 +0200 (CEST)

On Thu, 14 May 2020, Eli Zaretskii wrote:

> The fix triggers compilation warnings:
>
>  In archive--summarize-descs:
>  arc-mode.el:1509:45: Warning: `archive-int-to-mode' is an obsolete function
>      (as of 28.1); use `file-modes-number-to-symbolic' instead.
>  arc-mode.el:1574:70: Warning: `archive-int-to-mode' is an obsolete function
>      (as of 28.1); use `file-modes-number-to-symbolic' instead.
>
> Would it be possible to eliminate these warnings, please?
Sorry, I missed that.  Pushed a fix 
(065f6a1d8b5c7dc8f1bf758e22f2e9a7d17b47d4)
Thank you.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#27952; Package emacs. (Fri, 15 May 2020 06:23:02 GMT) Full text and rfc822 format available.

Message #60 received at 27952 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Tino Calancha <tino.calancha <at> gmail.com>
Cc: 27952 <at> debbugs.gnu.org
Subject: Re: bug#27952: 26.0.50; Combine archive-int-to-mode and
 tar-grind-file-mode
Date: Fri, 15 May 2020 09:22:30 +0300
> From: Tino Calancha <tino.calancha <at> gmail.com>
> Date: Thu, 14 May 2020 22:08:36 +0200 (CEST)
> cc: Tino Calancha <tino.calancha <at> gmail.com>, 27952 <at> debbugs.gnu.org
> 
> >  In archive--summarize-descs:
> >  arc-mode.el:1509:45: Warning: `archive-int-to-mode' is an obsolete function
> >      (as of 28.1); use `file-modes-number-to-symbolic' instead.
> >  arc-mode.el:1574:70: Warning: `archive-int-to-mode' is an obsolete function
> >      (as of 28.1); use `file-modes-number-to-symbolic' instead.
> >
> > Would it be possible to eliminate these warnings, please?
> Sorry, I missed that.  Pushed a fix 
> (065f6a1d8b5c7dc8f1bf758e22f2e9a7d17b47d4)

Thanks, compiles cleanly now.




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Fri, 12 Jun 2020 11:24:07 GMT) Full text and rfc822 format available.

This bug report was last modified 3 years and 316 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.