POSIX only specifies the -H, -L, and -P options for use with -R, and
the default is left to the implementation. Without -R, symlinks must
be followed.
Most implementations use -P as the default with -R, which makes sense
to me as default behavior (the source and destination trees are the same).
Since we use the same code for -R and without it, and we allow -H, -L,
and -P without -R, set the default based on the presence of -R. Without
it, use -L as before, as required by POSIX, and with it, use -P to match
the behavior of other implementations.
Previously, when the destination file was created with fopen, we needed
to use fchmod to set its permissions.
Now that we pass in the mode to creat, we already get the desired
behavior of creating the file with the same mode as the source file
modified by the user's file creation mask.
This fixes the issue where a directory or special file created with
mkdir/mknod does not end up with the appropriate mode with -p or -a
(since it may have been narrowed by the umask).
This also allows us to clear the SUID and SGID bits from the mode if the
chown fails, as specified by POSIX.
If we are just copying data from one file to another, we don't need to
fill a complete buffer, just read a chunk at a time, and write it to the
output.
Otherwise, we run into problems in a typical autoconf-based build
system:
- config.status is created at some point between two seconds.
- config.status is run, generating Makefile by first writing to a file
in /tmp, and then mv-ing it to Makefile.
- If this mv happens before the beginning of the next second, Makefile
will be created with the same tv_sec as config.status, but with
tv_nsec = 0.
- When make runs, it sees that Makefile is older than config.status,
and re-runs config.status to generate Makefile.
1) Rename cp_HLPflag -> cp_follow for consistency.
2) Use function-pointers for stat to clear up the code.
3) BUGFIX: TERMINATE THE RESULT BUFFER OF READLINK !!!
It's something I noticed earlier and it actually lead to some
pretty insane behaviour on our side using glibc (musl somehow
magically solves this).
Basically, symlinks used to contain the data of the file they
pointed to. I wondered for weeks where this came from and now
this has finally been solved.
4) BUGFIX: Do not unconditionally unlink target-files. Even GNU
coreutils do it wrong.
The basic idea is this:
If fflag == 0 --> don't touch target files if they exist.
If fflag == 1 --> unlink all and don't error out when we try
to unlink a file which doesn't exist.
5) Use estrlcpy and estrlcat instead of snprintf for path building.
6) Make it clearer what happens in preserve.
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.
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.
The -d option is a GNU extension and is equivalent to its "-P
--preserve=links" options.
Since we don't implement the --preserve=links functionality anyway (it
means preserve hard links between files), just call it -P, which is
specified by POSIX.
Additionally, there is no need to check for cp_Pflag again before
copying the symlink itself because the only way the mode in the stat
will indicate a symlink is if we used lstat (which we only do if -P is
specified).