[Toybox] [PATCH] cpio: Implement -u (copy unconditionally)
enh
enh at google.com
Thu Feb 25 08:23:52 PST 2021
could be. i usually copy & paste the commit message and diff stats into the
body but leave the actual diff (well, the whole patch file) as an
attachment.
On Thu, Feb 25, 2021 at 8:21 AM Yi-yo Chiang <yochiang at google.com> wrote:
> Thanks for checking, Rob and Elliott!
> It intriguing that in my personal, non-work mailbox, my own mail from this
> address got filtered to spam too, and Rob's mail in the thread got silently
> dropped... despite me pressing the "report not spam" button multiple times
> already 🤔
>
> Perhaps gmail doesn't like big block of c-code?
>
> On Thu, Feb 25, 2021 at 10:21 AM enh via Toybox <toybox at lists.landley.net>
> wrote:
>
>> No hurry, I was just checking that something like that hadn't happened 😀
>>
>> On Wed, Feb 24, 2021, 17:04 Rob Landley <rob at landley.net> wrote:
>>
>>> Ah, sorry. His email (and the follow up) wound up in gmail's spam filter
>>> again.
>>>
>>> I'll try to take a look tonight.
>>>
>>> Rob
>>>
>>> On 2/24/21 12:17 PM, enh via Toybox wrote:
>>> > ping?
>>> >
>>> > On Sun, Feb 14, 2021 at 5:13 AM Yi-Yo Chiang via Toybox
>>> > <toybox at lists.landley.net <mailto:toybox at lists.landley.net>> wrote:
>>> >
>>> > If -u is specified, then replace any existing files or directories.
>>> >
>>> > If -u is not specified and the path to be inflated already exist,
>>> then
>>> > report EEXIST error. This behaves slightly different from GNU
>>> cpio, as
>>> > GNU cpio checks the timestamp and replaces when the timestamp of
>>> the
>>> > existing file is older than the one from the archive. This still
>>> > conforms to SUSv2 as it doesn't define how to behave when -u is not
>>> > specified.
>>> >
>>> > There is an exception, if we are creating an existing directory,
>>> then
>>> > don't report any error or try to rmdir() the directory as we can
>>> > "create" the directory by chmod() / chown() the existing one.
>>> >
>>> > ---
>>> > tests/cpio.test | 16 ++++++++++++++++
>>> > toys/posix/cpio.c | 46
>>> ++++++++++++++++++++++++++++++++++++----------
>>> > 2 files changed, 52 insertions(+), 10 deletions(-)
>>> >
>>> > diff --git a/tests/cpio.test b/tests/cpio.test
>>> > index 6ab3665a..7e2955a1 100755
>>> > --- a/tests/cpio.test
>>> > +++ b/tests/cpio.test
>>> > @@ -42,4 +42,20 @@ touch a; chmod a-rwx a; ln -s a/cant b
>>> > toyonly testing "archives unreadable empty files" "cpio -o -H
>>> newc|cpio
>>> > -it" "b\na\n" "" "b\na\n"
>>> > chmod u+rw a; rm -f a b
>>> >
>>> > +mkdir a
>>> > +echo "old" >a/b
>>> > +echo "a/b" | cpio -o -H newc >a.cpio
>>> > +rm -rf a
>>> > +testing "-i doesn't create leading directories" "cpio -i <a.cpio
>>> > 2>/dev/null; [ -e a ] || echo yes" "yes\n" "" ""
>>> > +rm -rf a
>>> > +testing "-id creates leading directories" "cpio -id <a.cpio &&
>>> cat a/b"
>>> > "old\n" "" ""
>>> > +rm -rf a a.cpio
>>> >
>>> > +mkdir a
>>> > +echo "old" >a/b
>>> > +find a | cpio -o -H newc >a.cpio
>>> > +testing "-i keeps existing files" "echo new >a/b && cpio -i
>>> <a.cpio
>>> > 2>/dev/null; cat a/b" "new\n" "" ""
>>> > +testing "-id keeps existing files" "echo new >a/b && cpio -id
>>> <a.cpio
>>> > 2>/dev/null; cat a/b" "new\n" "" ""
>>> > +testing "-iu replaces existing files; no error" "echo new >a/b &&
>>> cpio -iu
>>> > <a.cpio && cat a/b" "old\n" "" ""
>>> > +testing "-idu replaces existing files; no error" "echo new >a/b
>>> && cpio
>>> > -idu <a.cpio && cat a/b" "old\n" "" ""
>>> > +rm -rf a a.cpio
>>> > diff --git a/toys/posix/cpio.c b/toys/posix/cpio.c
>>> > index 31c777c9..795f890c 100644
>>> > --- a/toys/posix/cpio.c
>>> > +++ b/toys/posix/cpio.c
>>> > @@ -22,7 +22,7 @@ config CPIO
>>> > default y
>>> > help
>>> > usage: cpio -{o|t|i|p DEST} [-v] [--verbose] [-F FILE]
>>> > [--no-preserve-owner]
>>> > - [ignored: -mdu -H newc]
>>> > + [ignored: -m -H newc]
>>> >
>>> > Copy files into and out of a "newc" format cpio archive.
>>> >
>>> > @@ -32,6 +32,7 @@ config CPIO
>>> > -o Create archive (stdin=list of files, stdout=archive)
>>> > -t Test files (list only, stdin=archive, stdout=list of files)
>>> > -d Create directories if needed
>>> > + -u Copy unconditionally
>>> > -v Verbose
>>> > --no-preserve-owner (don't set ownership during extract)
>>> > */
>>> > @@ -113,7 +114,8 @@ void cpio_main(void)
>>> > if (FLAG(i) || FLAG(t)) for (;;) {
>>> > char *name, *tofree, *data;
>>> > unsigned size, mode, uid, gid, timestamp;
>>> > - int test = FLAG(t), err = 0;
>>> > + int test = FLAG(t), err = 0, exist = 0;
>>> > + struct stat st;
>>> >
>>> > // Read header and name.
>>> > if (!(size =readall(afd, toybuf, 110))) break;
>>> > @@ -137,25 +139,50 @@ void cpio_main(void)
>>> > // (This output is unaffected by --quiet.)
>>> > if (FLAG(t) || FLAG(v)) puts(name);
>>> >
>>> > - if (!test && FLAG(d) && strrchr(name, '/') && mkpath(name)) {
>>> > + if (!test) exist = !lstat(name, &st);
>>> > +
>>> > + // Create leading directories if |name| doesn't exist.
>>> > + if (!test && !exist && FLAG(d) && strrchr(name, '/') &&
>>> mkpath(name)) {
>>> > perror_msg("mkpath '%s'", name);
>>> > test++;
>>> > }
>>> >
>>> > + // Don't report error or try to rmdir(name) if we want to
>>> mkdir(name)
>>> > later.
>>> > + if (!test && exist && !(S_ISDIR(st.st_mode) &&
>>> S_ISDIR(mode))) {
>>> > + if (!FLAG(u)) {
>>> > + errno = EEXIST;
>>> > + perror_msg_raw(name);
>>> > + test++;
>>> > + } else if (S_ISDIR(st.st_mode) ? rmdir(name) :
>>> unlink(name)) {
>>> > + perror_msg("remove '%s'", name);
>>> > + test++;
>>> > + } else {
>>> > + exist = 0;
>>> > + }
>>> > + }
>>> > +
>>> > // Consume entire record even if it couldn't create file, so
>>> we're
>>> > // properly aligned with next file.
>>> >
>>> > if (S_ISDIR(mode)) {
>>> > - if (!test) err = mkdir(name, mode);
>>> > + if (!test) {
>>> > + // If |name| already exist as a directory, then just do a
>>> chmod()
>>> > to fix
>>> > + // up the directory permissions.
>>> > + if (!exist) err = mkdir(name, mode);
>>> > + else if (S_ISDIR(st.st_mode)) err = chmod(name, mode);
>>> > + else err = errno = EEXIST;
>>> > + }
>>> > } else if (S_ISLNK(mode)) {
>>> > data = strpad(afd, size, 0);
>>> > - if (!test) err = symlink(data, name);
>>> > + if (!test) {
>>> > + err = symlink(data, name);
>>> > + // Can't get a filehandle to a symlink, so do special
>>> chown
>>> > + if (!err && !geteuid() && !FLAG(no_preserve_owner))
>>> > + err = lchown(name, uid, gid);
>>> > + }
>>> > free(data);
>>> > - // Can't get a filehandle to a symlink, so do special chown
>>> > - if (!err && !geteuid() && !FLAG(no_preserve_owner))
>>> > - err = lchown(name, uid, gid);
>>> > } else if (S_ISREG(mode)) {
>>> > - int fd = test ? 0 : open(name,
>>> O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
>>> > mode);
>>> > + int fd = test ? 0 : open(name,
>>> O_CREAT|O_EXCL|O_WRONLY|O_NOFOLLOW, mode);
>>> >
>>> > // If write fails, we still need to read/discard data to
>>> continue with
>>> > // archive. Since doing so overwrites errno, report error
>>> now
>>> > @@ -197,7 +224,6 @@ void cpio_main(void)
>>> > && !FLAG(no_preserve_owner))
>>> > {
>>> > int fd = open(name, O_RDONLY|O_NOFOLLOW);
>>> > - struct stat st;
>>> >
>>> > if (fd != -1 && !fstat(fd, &st) && (st.st_mode&S_IFMT) ==
>>> > (mode&S_IFMT))
>>> > err = fchown(fd, uid, gid);
>>> > --
>>> > 2.30.0.478.g8a0d178c01-goog
>>> >
>>> > _______________________________________________
>>> > Toybox mailing list
>>> > Toybox at lists.landley.net <mailto:Toybox at lists.landley.net>
>>> > http://lists.landley.net/listinfo.cgi/toybox-landley.net
>>> >
>>> >
>>> > _______________________________________________
>>> > Toybox mailing list
>>> > Toybox at lists.landley.net
>>> > http://lists.landley.net/listinfo.cgi/toybox-landley.net
>>> >
>>> _______________________________________________
>>> Toybox mailing list
>>> Toybox at lists.landley.net
>>> http://lists.landley.net/listinfo.cgi/toybox-landley.net
>>>
>> _______________________________________________
>> Toybox mailing list
>> Toybox at lists.landley.net
>> http://lists.landley.net/listinfo.cgi/toybox-landley.net
>>
>
>
> --
>
> Yi-yo Chiang
> Software Engineer
> yochiang at google.com
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.landley.net/pipermail/toybox-landley.net/attachments/20210225/3c18ba4b/attachment-0001.htm>
More information about the Toybox
mailing list