Commit Graph

40 Commits (f5baf2630ab0cf51306bb94311e7eed84caa730d)

Author SHA1 Message Date
FRIGN 7b2465c101 Add maxdepth to recurse()
This also makes more sense.
2015-04-20 11:12:40 +01:00
FRIGN e14d9412f8 Properly handle recursion in recurse()
The restructuring of recurse() in the last few weeks actually broke
the recursion-flags in different tools.
As a long-term goal, the recursor should have a field "maxdepth"
which should be "1" for the non-Rflag-case. "0" stands for unlimited.
2015-04-20 11:12:40 +01:00
FRIGN 3111908b03 Refactor recurse() again
Okay, why yet another recurse()-refactor?
The last one added the recursor-struct, which simplified things
on the user-end, but there was still one thing that bugged me a lot:
Previously, all fn()'s were forced to (l)stat the paths themselves.
This does not work well when you try to keep up with H-, L- and P-
flags at the same time, as each utility-function would have to set
the right function-pointer for (l)stat every single time.

This is not desirable. Furthermore, recurse should be easy to use
and not involve trouble finding the right (l)stat-function to do it
So, what we needed was a stat-argument for each fn(), so it is
directly accessible. This was impossible to do though when the
fn()'s are still directly called by the programs to "start" the
Thus, the fundamental change is to make recurse() the function to
go, while designing the fn()'s in a way they can "live" with st
being NULL (we don't want a null-pointer-deref).

What you can see in this commit is the result of this work. Why
all this trouble instead of using nftw?
The special thing about recurse() is that you tell the function
when to recurse() in your fn(). You don't need special flags to
tell nftw() to skip the subtree, just to give an example.

The only single downside to this is that now, you are not allowed
to unconditionally call recurse() from your fn(). It has to be
a directory.
However, that is a cost I think is easily weighed up by the

Another thing is the history: I added a procedure at the end of
the outmost recurse to free the history. This way we don't leak

A simple optimization on the side:

-		if (h->dev == st.st_dev && h->ino == st.st_ino)
+		if (h->ino == st.st_ino && h->dev == st.st_dev)

First compare the likely difference in inode-numbers instead of
checking the unlikely condition that the device-numbers are
2015-03-19 01:08:19 +01:00
FRIGN 3fa85f0f5e Fix argument parsing in test(1) and chmod(1)
We just take the raw argument list as is. Using arg.h, arguments
beginning with - would have been "eaten up".
Writing a special "bailout" for arg.h was not a good option,
not because it's not impossible (done in 6 LOC), but because it
is a shoehorning around a corner case present for a few programs
which are broken by design by POSIX.
2015-03-13 23:50:09 +01:00
FRIGN 9fd4a745f8 Add history and config-struct to recurse
For loop detection, a history is mandatory. In the process of also
adding a flexible struct to recurse, the recurse-definition was moved
to fs.h.
The motivation behind the struct is to allow easy extensions to the
recurse-function without having to change the prototypes of all
functions in the process.
Adding flags is really simple as well now.

Using the recursor-struct, it's also easier to see which defaults
apply to a program (for instance, which type of follow, ...).

Another change was to add proper stat-lstat-usage in recurse. It
was wrong before.
2015-03-13 00:29:48 +01:00
FRIGN 01de5df8e6 Audit du(1) and refactor recurse()
While auditing du(1) I realized that there's no way the over 100 lines
of procedures in du() would pass the audit.
Instead, I decided to rewrite this section using recurse() from libutil.
However, the issue was that you'd need some kind of payload to count
the number of bytes in the subdirectories and use them in the higher
The solution is to add a "void *data" data pointer to each recurse-
function-prototype, which we might also be able to use in other
recurse() itself had to be augmented with a recurse_samedev-flag, which
basically prevents recurse from leaving the current device.

Now, let's take a closer look at the audit:
1) Removing the now unnecessary util-functions push, pop, xrealpath,
   rename print() to printpath(), localize some global variables.
2) Only pass the block count to nblks instead of the entire stat-
3) Fix estrtonum to use the minimum of LLONG_MAX and SIZE_MAX.
4) Use idiomatic argv+argc-loop
5) Report proper exit-status.
2015-03-11 23:21:52 +01:00
Hiltjo Posthuma 0c17cd0fb3 staticize some functions 2015-03-07 13:33:39 +01:00
FRIGN aea256c288 Audit chmod(1)
1) Update manpage, refactor the HLP-section and other wordings.
2) BUGFIX: If chmod() fails, don't recurse.
3) Rewrite the arg-loop, fixing several issues:
   BUGFIX: Handle multi-flags (e.g. -RH)
   BUGFIX: Properly handle the termination flag --, error on e.g. --x
   BUGFIX: Error out on an empty flag -.
4) Refactor logic after the arg-loop, which is now simpler thanks
   to argv-incremention.
2015-03-05 19:08:28 +01:00
FRIGN 8dc92fbd6c Refactor enmasse() and recurse() to reflect depth
The HLP-changes to sbase have been a great addition of functionality,
but they kind of "polluted" the enmasse() and recurse() prototypes.
As this will come in handy in the future, knowing at which "depth"
you are inside a recursing function is an important functionality.

Instead of having a special HLP-flag passed to enmasse, each sub-
function needs to provide it on its own and can calculate results
based on the current depth (for instance, 'H' implies 'P' at
depth > 0).
A special case is recurse(), because it actually depends on the
follow-type. A new flag "recurse_follow" brings consistency into
what used to be spread across different naming conventions (fflag,
HLP_flag, ...).

This also fixes numerous bugs with the behaviour of HLP in the
tools using it.
2015-03-02 22:50:38 +01:00
sin 9da1deaab9 chmod: Add -HLP flags and update manpage 2015-02-16 16:47:07 +00:00
sin 8f068589fb Fix recurse() prototype and convert char to int flags 2015-02-16 16:23:12 +00:00
Tai Chi Minh Ralph Eastwood 82bc92da51 recurse: add symlink derefencing flags -H and -L 2015-02-16 15:53:55 +00:00
FRIGN 31572c8b0e Clean up #includes 2015-02-14 21:12:23 +01:00
FRIGN b55de3d1a2 Add mandoc-manpage for chmod(1)
and mark it as finished in README.

One small rationale on the way the manpage is set up: Looking at
the coreutils manpage, it does not invite to be a quick reference
guide, whereas I wrote this manpage to be short and concise in regard
to the information the advanced user needs.
No one needs to explain what an octal number is. That's not part of
the scope of this manpage.
Also, nobody wants to read a block of text just to find out how
to build an octal mode string.
2015-01-17 21:59:37 +00:00
FRIGN eff58b5531 Refactor chmod(1)
Clean the mess.
2015-01-16 23:08:36 +00:00
FRIGN 1436518f9d Use < 0 instead of == -1 2014-11-19 20:09:29 +00:00
FRIGN ec8246bbc6 Un-boolify sbase
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.
2014-11-14 10:54:20 +00:00
FRIGN 7d2683ddf2 Sort includes and more cleanup and fixes in util/ 2014-11-14 10:54:10 +00:00
FRIGN eee98ed3a4 Fix coding style
It was about damn time. Consistency is very important in such a
big codebase.
2014-11-13 18:08:43 +00:00
sin 0c5b7b9155 Stop using EXIT_{SUCCESS,FAILURE} 2014-10-02 23:46:59 +01:00
Hiltjo Posthuma 90861840b7 chmod: process file series behaviour
continue processing files if a chmod on a file in a series failed, but return with an error status code.

Signed-off-by: Hiltjo Posthuma <>
2014-04-24 11:51:43 +01:00
Hiltjo Posthuma bd99b92e91 parsemode: rework
- 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 <>
2014-04-24 11:51:33 +01:00
sin f488547779 Don't bail out if chmod(2) or chown(2) fails
Keep processing all the files specified.
2014-04-22 13:46:28 +01:00
Hiltjo Posthuma 560340341f make parsemode() generic
use for uudecode and chmod

Signed-off-by: Hiltjo Posthuma <>
2014-04-09 15:40:32 +01:00
sin d9a1030d57 We do symbolic options for chmod(1)
Don't bomb out if the argument is not a valid octal number, it
could very well be something like "chmod +x test".
2014-03-04 11:05:01 +00:00
dsp 2e98468788 check for valid octal input and crude range check on that for validity 2014-02-01 19:50:52 +00:00
Markus Wichmann a55cc8c95e Make chmod and ls recognize sticky bit (S_ISVTX). 2013-10-20 10:41:32 +01:00
Markus Wichmann 35053c1d48 Make chmod honor S_ISVTX. 2013-10-20 10:41:31 +01:00
sin d8718d4159 Do not interpret -[rwxs] as options in chmod(1)
To chmod recursively use `-R' as opposed to `-r' so we can
distinguish it from the mode `-r'.
2013-10-11 17:02:58 +01:00
sin b5a511dacf Exit with EXIT_SUCCESS/EXIT_FAILURE instead of 0 and 1
Fixed for consistency purposes.
2013-10-07 16:44:22 +01:00
stateless 7216a53a7e Remove unnecessary exit(1) in usage()
Signed-off-by: Christoph Lohmann <>
2013-06-19 19:58:19 +02:00
Christoph Lohmann 4d38f60685 Eliminating the getopt disgrace. 2013-06-14 20:20:47 +02:00
Connor Lane Smith 20d526391d chmod, chown: remove redundant flag 2012-05-25 21:52:01 +01:00
Connor Lane Smith 0cca0c209b whoops, chmod = 2011-06-11 00:31:44 +01:00
Connor Lane Smith 26723ba0dc symbolic chmod, thanks pancake 2011-06-11 00:30:07 +01:00
Connor Lane Smith 954106050f rename estrtol 2011-06-10 14:55:01 +01:00
Connor Lane Smith ba456787cb chmod: strnum 2011-06-10 05:44:00 +01:00
Connor Lane Smith d90ced2047 consistent error check 2011-06-04 12:20:41 +01:00
Connor Lane Smith 04bac53826 chmod: no S_ISVTX 2011-05-29 20:38:03 +01:00
Connor Lane Smith 2dfe5c6b8b octal-only chmod 2011-05-27 23:48:07 +01:00