On Unix-like systems, the ls
command lists files. GNU's version of ls
also colors them according to their properties and the environment variable LS_COLORS
. The main file property that ls
bases its colors on is the file's mode. In this challenge, you will determine what keys from LS_COLORS ls
should look for a given mode.
File modes
A file's mode determines what type of a file it is (is it a normal file? a socket? a pipe? a directory?) and what permissions it has (can the owner execute it? can everyone write to it?).
The mode is given by a 16-bit unsigned integer. The highest 4 bits determine the file's type, the next 3 bits determine certain special attributes, and the remaining 9 bits determine user, group, and world permissions (3 bits each).
The grouping-up by 3s makes it very common write these permissions in octal:
type special permissions | type sp perms
---- ------- ----------- | -- -- -----
(bin) 1111 111 111 111 111 | (oct) 17 7 7 7 7
The top 4 bits will take on one of these values. Any other values can produce undefined behavior:
Binary Octal File type
--------- ----- ----------------
0b1100... 014... socket
0b1010... 012... symbolic link
0b1000... 010... regular file
0b0110... 006... block device
0b0100... 004... directory
0b0010... 002... character device
0b0001... 001... FIFO (named pipe)
The remaining 4 octets can have any value. each bit is a flag which can be set independently from the others:
????------------- Filetype, see above
----1------------ SUID: Execute this file with the UID set to its owner
-----1----------- SGID: Execute this file with the GID set to its group
------1---------- Sticky: Users with write permissions to this dir cannot move or delete files within owned by others
-------1--------- User read: The owner of the file can read this
--------1-------- User write: The owner of the file can write to this
---------1------- User exec: The owner of the file can execute this
-----------111--- Group r/w/x: The group of this file can read/write/execute
--------------111 Other r/w/x: All users can read/write/execute
LS_COLORS
GNU's ls
uses the environment variable LS_COLORS to add color to the files it lists. The variable LS_COLORS is a colon-delimited list of key=value
rules. Some of those keys are for file names (e.g.: *.tar=01;31
), but we care about the file type keys.
ln Symbolic link.
pi Named pipe
bd Block device
cd Character device
or Symbolic link pointing to a non-existent file
so Socket
tw Directory that is sticky and other-writable (+t,o+w)
ow Directory that is other-writable (o+w) and not sticky
st Directory with the sticky bit set (+t) and not other-writable
di Directory
su Normal file that is setuid (u+s)
sg Normal file that is setgid (g+s)
ex Executable normal file (i.e. has any 'x' bit set in permissions)
fi Normal file
Now when ls
finds a match in the above list, it only applies that color if that key exists in LS_COLORS. If a directory is sticky and other-writeable, but no tw
key is in LS_COLORS, it will fall back to ow
, then fall back to st
, then fall back to di
. The list above is ordered to give the same result as ls
.
Challenge
Take as an integer input any valid file mode, and output the fallback list of two-character codes.
Input: A file mode with a valid file type, in any convenient integer format that is at least 16 bits.
Output: The corresponding ordered list of two-character keys for a file with that mode, in fallback order.
Since all codes are two characters, the concatenated string (e.g.: "twowstdi"
) is also acceptable, as it is still unambiguous.
Additionally, printing the codes in reverse order (di st ow tw
) is also fine, as long as it is consistent for all inputs.
Example:
- Input:
17389
(in octal:0041755
) - Output:
["st", "di"]
(the sticky bit0001000
is set, and it is an directory0040000
.)
Test cases (these are in octal, and a symbolic equivalent for your convenience):
Input Symbolic Output | Note:
------- ---------- ------------- | -----
0140000 s--------- so | socket
0147777 srwsrwsrwt so | suid/sgid/sticky/other-writeable does not apply
0120000 l--------- ln | symbolic link (you MAY choose to output "or" instead)
0127777 lrwsrwsrwt ln |
0060000 b--------- bd | block device
0067777 brwsrwsrwt bd |
0020000 c--------- cd | character device
0027777 crwsrwsrwt cd |
0010000 p--------- pi | pipe
0017777 prwsrwsrwt pi |
0040755 drwxr-xr-x di | directory
0041755 drwxrwxr-t st di | sticky bit set
0040002 d-------w- ow di | other-writable
0041777 drwxrwxrwt tw ow st di | sticky + other-writeable
0046000 d--S--S--- di | suid/sgid only apply to normal files
0100000 ---------- fi | normal file
0100000 ---------T fi | sticky bit only applies to directories
0100100 ---x------ ex fi | executable file
0100010 ------x--- ex fi |
0100001 ---------x ex fi |
0104000 ---S------ su fi | suid
0106777 -rwsrwsrwx su sg ex fi | suid has priority over sgid and executable
0102000 ------S--- sg fi | sgid
0102777 -rwxrwsrwx sg ex fi | sgid has priority over executable
0110000 ?--------- <undefined> | Unknown filetype, any output is valid
Standard loopholes are forbidden. This is code-golf, so shorter answers are best.
Similar Challenges: File Permissions, Do I have permission?