Hello maintainers,

I was trying out the new `--set-mtime-command` option in tar 1.35.90 and
ran into some behavior I couldn't explain: whatever timestamp my helper
command printed, tar either complained that the output didn't match my
format string, or quietly stored a completely wrong mtime.

After poking at it a bit, I went and read the code, and I think I found
the cause.  In sys_exec_setmtime_script() (src/system.c), the loop that
reads the command's output advances the buffer length with the poll()
return value instead of the number of bytes read:

```
  src/system.c:973    ssize_t nread = read (pfd.fd, buffer + buflen,
                                            bufsize - buflen);
  ...
  src/system.c:982    buflen += n;
```

`n` here is the return value of poll(), which is always 1 in this
single-fd loop, so it isn't the byte count -- that's `nread`.  Once
xpalloc() has grown the buffer beyond one byte, a multi-byte read()
only bumps buflen by 1, and everything after the first byte gets
dropped.  That explains what I was seeing: only the first character of
the command's output ever reaches strptime()/parse_datetime().

I checked current git master and the same line is still there
(src/system.c:996), so it looks like it affects master too.

A one-line change fixes it for me:

```
  -      buflen += n;
  +      buflen += nread;
```

Steps to reproduce:

```
  $ mkdir /tmp/bug && cd /tmp/bug
  $ echo hello > f.txt
  $ printf '#!/bin/sh\necho 1700000000\n' > mtime.sh && chmod +x mtime.sh

  $ tar -cf a.tar --set-mtime-command="$PWD/mtime.sh" \
        --set-mtime-format=%s f.txt
  $ echo "exit=$?"
  exit=0
  $ tar --utc -tvf a.tar
  -rw-rw-r-- user/user  6 1970-01-01 00:00 f.txt
```

The command prints 1700000000 (2023-11-14), but tar stores epoch 1
(1970-01-01) -- it kept only the first byte "1" -- and still exits 0,
so the wrong timestamp goes in silently.

With a human-readable format the same truncation shows up as an error
instead:

```
  $ printf '#!/bin/sh\necho "2020-01-02 03:04:05"\n' > mtime.sh
  $ tar -cf a.tar --set-mtime-command="$PWD/mtime.sh" \
        --set-mtime-format="%Y-%m-%d %H:%M:%S" f.txt
  tar: output from "...mtime.sh f.txt" does not satisfy format string: 2
  tar: Exiting with failure status due to previous errors
```

(only the first byte "2" makes it through).

With the one-line change above, both cases work as I'd expect: the
first records 2023-11-14 and the second records 2020-01-02.

I built tar 1.35.90 from source on GNU/Linux to confirm all of this.
Hope this helps, and thanks for tar!

Best regards,
Xinting Zhou

Reply via email to