pathconf() is just an insane interface to use. All sane operating-
systems set sane values for PATH_MAX. Due to the by-runtime-nature of
pathconf(), it actually weakens the programs depending on its values.
Given over 3 years it has still not been possible to implement a sane
and easy to use apathmax()-utility-function, and after discussing this
on IRC, we'll dump this garbage.
We are careful enough not to overflow PATH_MAX and even if, any user
is able to set another limit in config.mk if he so desires.
I marked out -m, -s and -x, because they are either visual flags
for interactive mode, which are better solved with tools made for this
job, or superfluous in another sense.
For example, -s basically "steals" the job from du.
In general, some of these options might still be easy to implement.
The options -S and -f are important though, as they are sorting-options
with real use.
Only add empty lines before returns, everything else is ok.
Also add the STANDARDS-section to the manpage, which was only
present as a heading until now.
1) Specify default in manpage under flag.
2) Boolean and return value style fixes.
3) argv-argc-centric loop.
4) No need to check for argc == 1 before the fflag-subroutine.
5) Remove indentation.
6) Empty line before return.
1) Get rid of strtop(), which was a NiH-version of estrtonum().
2) Boolean-style-fixes.
3) Update usage, reflecting num-idiom, also update manpage accordingly.
4) Don't break after usage().
5) Rewrite main loop with *argv instead of argv[i].
6) Don't play around with who < 0 and stuff.
7) Rename status to ret for consistency.
It has become a common idiom in sbase to check strlcat() and strlcpy()
using
if (strl{cat, cpy}(dst, src, siz) >= siz)
eprintf("path too long\n");
However, this was not carried out consistently and to this very day,
some tools employed unchecked calls to these functions, effectively
allowing silent truncations to happen, which in turn may lead to
security issues.
To finally put an end to this, the e*-functions detect truncation
automatically and the caller can lean back and enjoy coding without
trouble. :)
1) Add usage().
2) Idiomatic argv0-setter. We don't use arg.h, as we do not process
flags or arguments.
3) Remove program-name from eprintf-call. This is done in the eprintf-
function itself when the DEBUG-define is set.
We'll activate it by default later.
4) Add empty line before return.
After the audit, I had this noted down as a TODO-item, but
considered the function to be tested enough to hold the line
until I came to rewrite it.
Admittedly, I didn't take a closer look at the previous loop
and there probably were some edge-cases which caused trouble, but
so far so good, the new version of this commit should be safe
and considered audited.
1) Refactor the manpage with num-options, optimize wording to be more
concise and to the point, pid also specifies process groups.
2) Make int sig const.
3) Remove prototypes.
4) /* not reached */ consistency.
5) Refactor usage() with eprintf.
6) Refactor arg-parser with a switch, use estrtonum
7) Use return instead of exit() in main()
8) argc-argv-correctness.
1) Use num-wording in the manpage, remove offensive remark against
the beloved -num-syntax <3.
2) Style changes.
3) Report errors of getline.
4) argv-argc-centric argument loop.
5) Rename r to ret for consistency.
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.
1) Any path passed to mkdir -p beginning with '/' failed, because
it would cut out the first '/' immediately, passing "" to mkdir.
2) Running mkdir -p with a path/to/dir without trailing '/' would
not create the directory.
This is due to a wrong flag-check I added in the main-loop.
It should now work as expected.
3) With the p-flag given, don't report an error in case the last
dir also exists.
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.
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
hierarchies.
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-applications.
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-
pointer.
3) Fix estrtonum to use the minimum of LLONG_MAX and SIZE_MAX.
4) Use idiomatic argv+argc-loop
5) Report proper exit-status.
1) Add check to parselist() to warn about an empty list.
2) Remove all "cut: "-prefixes from error-messages and other style
changes.
3) != -1 --> >= 0 and check for ferror on fp after getline.
4) Update usage with argv0.
5) argv-centric loop refactor
6) Properly report exit-status.
7) Add empty line before return.
1) Use the LIMIT()-macro in util.h instead of defining our own.
2) Drop nextline() and finish(), not needed anymore. Use
fputs in printline instead of printf.
--> BUGFIX: Finish exited with status 1, but actually should
exit with status 0 if ferror(f) == 0.
3) Don't use /dev/fd/0 and use idiomatic <stdin> and fp = stdin
instead.
4) Refactor loop to use getline() instead of some handrolled
nextline-function.
--> BUGFIX: Line-length was limited to LINE_MAX before, now
it's factually unlimited.
5) Combine diff >= 0 and diff <= 0 into one loop with a beginning
continue-condition (diff && i == (diff < 0)).
6) BUGFIX: If diff == 0, don't print one buffer after EOFing on the
other.
1) Remove the return-value-enum, which is not necessary for a simple
program like this.
2) Don't disallow both l and s to be specified. This is undefined
behaviour defined by POSIX, so we don't start demanding things
from the user.
3) Replace exit() with return (we are in main).
4) Refactor main loop to never return in the loop, but actually
set the same-value and break, which increases readability.
5) Remove the final fclose()'s. The OS will take care of them, no
need to become cleansy here.
6) Use idiomatic return-value using same. This concludes the
increase of readability in the main-loop.
After a short correspondence with Otto Moerbeek it turned out
mallocarray() is only in the OpenBSD-Kernel, because the kernel-
malloc doesn't have realloc.
Userspace applications should rather use reallocarray with an
explicit NULL-pointer.
Assuming reallocarray() will become available in c-stdlibs in the
next few years, we nip mallocarray() in the bud to allow an easy
transition to a system-provided version when the day comes.
1) Reorder local variables.
2) Cleanup error messages, use %zu for size_t.
3) combine putchar(' ') and fputs to substitute printf(" %s", s).
4) Fix usage().
5) argv-argc-usage-fix.
6) Add empty line before return.
A function used only in the OpenBSD-Kernel as of now, but it surely
provides a helpful interface when you just don't want to make sure
the incoming pointer to erealloc() is really NULL so it behaves
like malloc, making it a bit more safer.
Talking about *allocarray(): It's definitely a major step in code-
hardening. Especially as a system administrator, you should be
able to trust your core tools without having to worry about segfaults
like this, which can easily lead to privilege escalation.
How do the GNU coreutils handle this?
$ strings -n 4611686018427387903
strings: invalid minimum string length -1
$ strings -n 4611686018427387904
strings: invalid minimum string length 0
They silently overflow...
In comparison, sbase:
$ strings -n 4611686018427387903
mallocarray: out of memory
$ strings -n 4611686018427387904
mallocarray: out of memory
The first out of memory is actually a true OOM returned by malloc,
whereas the second one is a detected overflow, which is not marked
in a special way.
Now tell me which diagnostic error-messages are easier to understand.