4

I have a tarball containing many files with root:root owner and/or special device inodes. cpio only accepts paths existing in the file system when it is creating a cpio archive. And I don't want to have to sudo in order to transform tar into cpio, while I want to preserve all the permissions, owners, and special inodes.

Is there some clean way of handling this?

EDIT1:

I believe that fakeroot can be seen as somewhat clean way. However it does not scale as expected - nearly 1,000x speed difference:

[user@computer root]$ ls -l ../fanbox.tar
-rw-rw-r-- 1 user user 56555520 May 22 03:33 ../fanbox.tar
[user@computer root]$ time tar -x --delay-directory-restore -f ../fanbox.tar
tar: dev/null: Cannot mknod: Operation not permitted
tar: dev/random: Cannot mknod: Operation not permitted
tar: dev/urandom: Cannot mknod: Operation not permitted
tar: Exiting with failure status due to previous errors

real    0m0.255s
user    0m0.062s
sys 0m0.193s
[user@computer root]$ rm -rf *
[user@computer root]$ time fakeroot tar -x --delay-directory-restore -f ../fanbox.tar

real    3m49.381s
user    0m0.812s
sys 0m2.760s
[user@computer root]$ 

Based on the output of time command I guess it is because of the communication between fakeroot and faked.

For reference, there is no much difference between a 2M tarball and 50M tarball when I changed fakeroot into sudo bash in my script. And also I believe that the problem is the number of files in the tarball, not the size: I used the same script on a ~10M tarball with two 5M binaries, and the script is not so slow.

6
  • 2
    what exactly do you want to transform? you could look into the pax command, i.e. pax -r -f filename.tar -s'/^\///' will remove the leading slash from files in the archive allowing you to extract the file into any directory
    – Subbeh
    May 18, 2018 at 6:17
  • I will need to be root to preserve owner and to just create the special nodes. That forces me to write in my shell script something like sudo rm -rf root each time, which is definitely not a clean way.
    – Thiner
    May 18, 2018 at 6:20
  • Why do you like to convert into an inferior format anyway?
    – schily
    Jun 6, 2018 at 14:35
  • @schily You cannot make a linux initramfs with a tarball, I believe.
    – Thiner
    Jun 18, 2018 at 7:48
  • The content of a filesystem can be filled up by either tar or cpio
    – schily
    Jun 18, 2018 at 8:00

3 Answers 3

3

You can use fakeroot. As the name says, it fakes the root user, by intercepting serveral syscalls with a LD_LIBRARY_PATH/LD_PRELOAD library wrapper, to have the process believe it's running as root. This has been created for the purpose of building and packaging applications without having to be root, including using make install which typically would be run as root. It's especially well suited to create archives.

During this, a forked daemon faked will run in order to remember all faked file ownership rights or informations on special files the child processes believes they made. So all operations have to be done in the same "instance", or faked will exit and forget what it was remembering.

$ fakeroot
# tar xf ...
# find foo ... | cpio -o ...
# exit
$ 

Other example showing faked's interaction:

$ mknod /tmp/vaporware b 8 0
mknod: /tmp/vaporware: Operation not permitted
$ fakeroot
# mknod /tmp/vaporware b 8 0
# ls -l /tmp/vaporware
brw-r--r-- 1 root root 8, 0 May 18 08:33 /tmp/vaporware
# exit
$ ls -l /tmp/vaporware
-rw-r--r--. 1 user user 0 May 18 08:33 /tmp/vaporware
2
  • Sorry for undoing the acception. fakeroot does not scale. When I do the same on a 50MB tar file, basically when I untar the file in a fakeroot environment, it becomes annoyingly slow, like 1min or so. Untaring the same tarball outside fakeroot finishes almost instantly. I cannot imagine what would happen if the size gets higher. Any better methods?
    – Thiner
    May 22, 2018 at 7:34
  • thanks for explaining. and sorry, that was the only rabbit I had in my hat for this... there are variants of fakeroot based on other interception methods. for example fakeroot-ng based on ptrace instead of LD_PRELOAD. You could give it a shot and see if it works faster
    – A.B
    May 22, 2018 at 12:49
2

Try using bsd tar (not GNU tar) -- the magic is to put an @ before your tarball filename:

bsdtar --format=cpio -cf - @root.tar.gz > root.cpio
1
  • Special files were not converted correctly this way. (Debian Buster)
    – Tino
    Jan 9, 2021 at 5:48
0

You can use lxc-usernsexec as environment to extract and recreate an archive.

lxc-usernsexec
mkdir tmp
cd tmp
tar xf ../archive.tar
find . -print0 | cpio -0o > ../archive.cpio
exit

This assumes that you have set up linux containers correctly, such that the $HOME/.config/lxc/default.conf exists (and /etc/subuid and /etc/subgid are setup correctly). For more information see

https://wiki.debian.org/LXC#Unprivileged_container

Note on Debian Buster:

$ lxc-usernsexec 
Failed to find subuid or subgid allocation

This seems to be a bug, but following script repairs this:

#!/bin/bash

ARGS=()

while read -ru6 what equals rest
do
        [ ".$what" = ".lxc.idmap" ] || continue
        [ ".$equals" = ".=" ] || continue
        ARGS+=(-m "${rest// /:}")
done 6<"$HOME/.config/lxc/default.conf"

exec /usr/bin/lxc-usernsexec "${ARGS[@]}" -- "$@"

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .