`Restic ls` understanding file mode with JSON

Hi everybody,

I use ‘Restic ls’ to see the content of my snapshots. Without json flag, I can see

drwxrwxr-x  1000  1000      0 2021-04-29 20:48:56 /sources/.truc/.machin
-rw-rw-r--  1000  1000     17 2021-04-30 00:56:46 /sources/.truc/.machin/super.txt

For me, as linux user, no problem for that.

When I use the json flag, I can see :

{"name":".machin","type":"dir","path":"/sources/.truc/.machin","uid":1000,"gid":1000,"mode":2147484157,"mtime":"2021-04-29T18:48:56.637091998Z","atime":"2021-04-29T18:48:56.637091998Z","ctime":"2021-09-25T13:46:33.254747234Z","struct_type":"node"}
{"name":"super.txt","type":"file","path":"/sources/.truc/.machin/super.txt","uid":1000,"gid":1000,"size":17,"mode":436,"mtime":"2021-04-29T22:56:46.004718365Z","atime":"2021-04-29T22:56:46.004718365Z","ctime":"2021-09-25T13:46:33.254747234Z","struct_type":"node"}

Here, no “drwxrwxr-x”, but a property “mode” with “strange” value. After using my brain a long time, I find the idea to change the base of the number. For the file, 436 becomes 664. All right. But with the directory it becomes 20000000775.

I don’t know how to correctly deal with this value. Yes I can extract the 3 last chars to have the user-group-other permissions, and with the “type” to “dir” I can calculate “drwxrwxr-x” but it’s my interpretation. How it will work with links, sticky bits ? It’s magic for me.

Note that for with the “find” command, I can found either “mode” either “permissions”. That is greater for me, and it can be good to normalize that :slight_smile:

Regards,

I found on Python the stat.filemode function. The logic seems to be there, but unfortunally sudo is 35309 with python and 8389101 with restic. The value returned by stat.filemode is not correct and incomplete.

Special bits are defined here: fs package - io/fs - pkg.go.dev . For the directory the mode is 0x800001fd or (1 << 31) | 0o775. And 1 << 31 == ModeDir gives the expected result. ModeAppend would be 1 << 30 and so on.

Thanks @MichaelEischer for your answer. It seems you say all is good, and explain a Go logic. I don’t know Go, and I don’t unserstand 0x800001fd or (1 << 31) (I see chinese signs). As a CLI user requesting JSON, I expect to be able to read a “standard” value, not a Go value. What standard tool (available in all languages including python) can I use to obtain the infos (type, permissions, sticky bits, etc) ?

Regards

0x800001fd is the same as 0o20000000775, just in hexadecimal instead of octal. 1 << 31 a different way of writing 0x80000000, it means “shifting” the left value 1 thirty-one times to the left. And a left-shift is just a multiplication by two. That is its 1 * 2^31 = 0x80000000.

I’m not aware of a standalone way to reformat the mode to a more common format. The go datatype has a String() method that is apparently able to reformat the output. But that would require some go programming.

For me an API, CLI, etc should not Input or Output language-specific informations. JSON for example is not GO-specific and everybody can read and manipulate it as he wants. I don’t know what is standard for that, I seen some functions in python, but I don’t know if it based on a standard.

The bad thing now I have the information is I cannot really deal with it except if I accept to make a lot of code to transform this value, what I will no do. I can open an issue for that, to add, like a quick win, the “permissions” property like “find” command. I am not expert for a long term and strong solution, what I would like simply is to see the same value than in my bash “ls -la” :slight_smile:

Note about that : /usr/bin/sudo

  • with ls -la we can see : -rwsr-xr-x
  • with restic find we can see : urwxr-xr-x

Restic (Go) is probably more complete, but we can see that with the same “format”, the result is different … :nauseated_face:

Regards

You are right that this is pretty go-specific, and that it would be useful to have the information that is included in the standard format also be included in the json format.

But that requires implementation of this new functionality, and probably a bit of design. Given that json does not include any specifications for this type of information, the specification would need to be designed. One possibility could be something like "unix_infostring":"-rwsr-xr-x" but that would need to be discussed.

Probably the best way to start that process would indeed be to request such a feature as a new issue on GitHub.

In the meantime, the suggestions above can potentially be of help. The bit operators can be implemented in another language such as Python, and hopefully that will be sufficient to address your most immediate problems.

Thanks for your answers. I will open a PR on the repository.

Regards