Input pipe for ar

0

While extracting a deb file, the simple curl pipe to ar is not working. I tried

curl http://example.com/path/to/package.deb | ar -xv -

and

curl http://example.com/path/to/package.deb | ar -xv

Looking at man 1 ar, I couldn't find any pointers to pipe usage. Does ar support input pipe?

Thanks!

Yusuf Gören

Posted 2019-09-09T18:09:50.093

Reputation: 3

Answers

0

Does ar support input pipe?

No. It appears ar needs its input to be seekable, it cannot read from a fifo. At least in my Debian 9.

First of all the tool does not recognize - as stdin. This command

ar -xv -

returns ar: -: No such file or directory. Omitting the operand doesn't make the tool use its stdin either.

There is a trick to force any tool (that expects a file) to use its stdin: /proc/self/fd/0 (other possibilities: /dev/fd/0, /dev/stdin). E.g. you can save an output stream from whatever as a sparse file, even if whatever knows nothing about sparse files; you use cp despite it doesn't normally read its stdin:

whatever | cp --sparse=always /proc/self/fd/0 output_file

You can try this trick with ar:

curl http://example.com/path/to/package.deb | ar -xv /proc/self/fd/0

but you will get ar: /proc/self/fd/0: Illegal seek. In my Debian strace revealed the tool uses lseek(2) with a negative offset. This fails for a pipe.

With my limited knowledge I found no apparent reason (here) to seek necessarily. Even if in theory one can parse an ar archive without seeking and going back, apparently in practice ar does seek.

Process substitution also creates an unseekable fifo. This will fail in the same way:

ar -xv <(curl http://example.com/path/to/package.deb)

I think there is no other way than to create a (temporary) seekable file first. In general you can do this explicitly:

tmpf="$(mktemp)" && {
  curl http://example.com/path/to/package.deb > "$tmpf" && ar -xv -- "$tmpf"
  rm -- "$tmpf"
}

In zsh there is another form of process substitution that creates and manages a temporary file implicitly:

# in zsh
ar -xv =(curl http://example.com/path/to/package.deb)

This one will work.

Kamil Maciorowski

Posted 2019-09-09T18:09:50.093

Reputation: 38 429

Thanks a lot for the detailed answer! I'm currently working in zsh and I had not know about =(...) process substitution! – Yusuf Gören – 2019-09-09T20:15:36.067