It actually makes the binaries smaller, the code easier to read
(gems like "val == true", "val == false" are gone) and actually
predictable in the sense of that we actually know what we're
working with (one bitwise operator was quite adventurous and
should now be fixed).
This is also more consistent with the other suckless projects
around which don't use boolean types.
I found quite a lot of bugs, so I ended up pretty much rewriting as I
followed the spec¹.
Now, it works as follows:
- Determine a mask (who) of bits that can be modified for the subsequent
operations. If none are specified, select all file mode bits.
- In a loop, determine which operation (+, -, =) to apply.
- If the next character is a permcopy (u, g, o), set the new permissions
(perm) corresponding to the bits set in the user, group or other parts
of the existing mode.
- Otherwise, set the new permissions by looping through the next r, w,
x, s, t characters.
- Now, the set of bits we want to add or remove is (who & perm). Set or
remove these bits according the the operation (first clearing the
appropriate bits if the operation is =).
- Continue from the top if the next character is a comma, otherwise,
process the next operation.
I tested this on some made up inputs, and I believe it is working
correctly now:
parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed
parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed
parsemode("+x", 0644, 023), before: 0754, now: 0754, still works
parsemode("+w", 0444, 022), before: 0644, now: 0644, still works
parsemode("+w", 0444, 0), before: 0666, now: 0666, still works
parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed
parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed
parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed
parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed
parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed
parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed
parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed
parsemode(",", 0654, 0), before: error, now: error, still works
¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
- for octal input: reset mode to 0.
- take umask into account.
- make '=rwx' etc work.
- we wont support crazy but valid modes like "a+rw,g=x,o=g"
- uudecode: use parsemode, mask is 0.
Signed-off-by: Hiltjo Posthuma <hiltjo@codemadness.org>