tarfilter --idshift now provides taridshift
This commit is contained in:
parent
226f86fea9
commit
902bc55c4d
5 changed files with 26 additions and 76 deletions
|
@ -96,7 +96,6 @@ def main():
|
|||
# copy over files from git or as distributed
|
||||
for (git, dist, target) in [
|
||||
("./mmdebstrap", "/usr/bin/mmdebstrap", "mmdebstrap"),
|
||||
("./taridshift", "/usr/bin/mmtaridshift", "taridshift"),
|
||||
("./tarfilter", "/usr/bin/mmtarfilter", "tarfilter"),
|
||||
(
|
||||
"./proxysolver",
|
||||
|
|
|
@ -52,7 +52,7 @@ Skip-If:
|
|||
fmt == "squashfs" and dist == "oldstable" # squashfs-tools-ng is not available
|
||||
fmt == "ext2" and dist == "oldstable" # genext2fs does not support SOURCE_DATE_EPOCH
|
||||
|
||||
Test: taridshift-utility
|
||||
Test: tarfilter-idshift
|
||||
Needs-QEMU: true
|
||||
Skip-If: dist == "oldstable" # python3 tarfile module does not preserve xattrs
|
||||
|
||||
|
|
20
tarfilter
20
tarfilter
|
@ -68,7 +68,10 @@ Both types of options use Unix shell-style wildcards:
|
|||
Thirdly, strip leading directory components off of tar members. Just as with
|
||||
GNU tar --strip-components, tar members that have less or equal components in
|
||||
their path are not passed through.
|
||||
"""
|
||||
|
||||
Lastly, shift user id and group id of each entry by the value given by the
|
||||
--idshift argument. The resulting uid or gid must not be negative.
|
||||
""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--path-exclude",
|
||||
|
@ -100,6 +103,12 @@ their path are not passed through.
|
|||
type=int,
|
||||
help="Strip NUMBER leading components from file names",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--idshift",
|
||||
metavar="NUM",
|
||||
type=int,
|
||||
help="Integer value by which to shift the uid and gid of each entry",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
if (
|
||||
not hasattr(args, "pathfilter")
|
||||
|
@ -165,6 +174,15 @@ their path are not passed through.
|
|||
for k, v in member.pax_headers.items()
|
||||
if not pax_filter_should_skip(k)
|
||||
}
|
||||
if args.idshift:
|
||||
if args.idshift < 0 and -args.idshift > member.uid:
|
||||
print("uid cannot be negative", file=sys.stderr)
|
||||
exit(1)
|
||||
if args.idshift < 0 and -args.idshift > member.gid:
|
||||
print("gid cannot be negative", file=sys.stderr)
|
||||
exit(1)
|
||||
member.uid += args.idshift
|
||||
member.gid += args.idshift
|
||||
if member.isfile():
|
||||
with in_tar.extractfile(member) as file:
|
||||
out_tar.addfile(member, file)
|
||||
|
|
67
taridshift
67
taridshift
|
@ -1,67 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# This script is in the public domain
|
||||
#
|
||||
# Author: Johannes Schauer Marin Rodrigues <josch@mister-muffin.de>
|
||||
#
|
||||
# This script accepts a tarball on standard input and prints a tarball on
|
||||
# standard output with the same contents but all uid and gid ownership
|
||||
# information shifted by the value given as first command line argument.
|
||||
#
|
||||
# A tool like this should be written in C but libarchive has issues:
|
||||
# https://github.com/libarchive/libarchive/issues/587
|
||||
# https://github.com/libarchive/libarchive/pull/1288/ (needs 3.4.1)
|
||||
# Should these issues get fixed, then a good template is tarfilter.c in the
|
||||
# examples directory of libarchive.
|
||||
#
|
||||
# We are not using Perl either, because Archive::Tar slurps the whole tarball
|
||||
# into memory.
|
||||
#
|
||||
# We could also use Go but meh...
|
||||
# https://stackoverflow.com/a/59542307/784669
|
||||
|
||||
import tarfile
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="""\
|
||||
Accepts a tarball on standard input and prints a tarball on standard output
|
||||
with the same contents but all uid and gid ownership information shifted by the
|
||||
value given as first command line argument.
|
||||
"""
|
||||
)
|
||||
parser.add_argument(
|
||||
"idshift",
|
||||
metavar="NUM",
|
||||
type=int,
|
||||
help="Integer value by which to shift the uid and gid of each entry",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
# starting with Python 3.8, the default format became PAX_FORMAT, so this
|
||||
# is only for compatibility with older versions of Python 3
|
||||
with tarfile.open(fileobj=sys.stdin.buffer, mode="r|*") as in_tar, tarfile.open(
|
||||
fileobj=sys.stdout.buffer, mode="w|", format=tarfile.PAX_FORMAT
|
||||
) as out_tar:
|
||||
for member in in_tar:
|
||||
if args.idshift < 0 and -args.idshift > member.uid:
|
||||
print("uid cannot be negative", file=sys.stderr)
|
||||
exit(1)
|
||||
if args.idshift < 0 and -args.idshift > member.gid:
|
||||
print("gid cannot be negative", file=sys.stderr)
|
||||
exit(1)
|
||||
|
||||
member.uid += args.idshift
|
||||
member.gid += args.idshift
|
||||
if member.isfile():
|
||||
with in_tar.extractfile(member) as file:
|
||||
out_tar.addfile(member, file)
|
||||
else:
|
||||
out_tar.addfile(member)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -10,12 +10,12 @@ adduser --gecos user --disabled-password user
|
|||
echo user:100000:65536 | cmp /etc/subuid -
|
||||
echo user:100000:65536 | cmp /etc/subgid -
|
||||
sysctl -w kernel.unprivileged_userns_clone=1
|
||||
# include iputils-ping so that we can verify that taridshift does not remove
|
||||
# include iputils-ping so that we can verify that tarfilter does not remove
|
||||
# extended attributes
|
||||
# run through tarshift no-op to create a tarball that should be bit-by-bit
|
||||
# identical to a round trip through "taridshift X" and "taridshift -X"
|
||||
# identical to a round trip through "tarfilter --idshift X" and "tarfilter --idshift -X"
|
||||
runuser -u user -- {{ CMD }} --mode=unshare --variant=apt --include=iputils-ping {{ DIST }} - {{ MIRROR }} \
|
||||
| ./taridshift 0 > /tmp/debian-chroot.tar
|
||||
| ./tarfilter --idshift 0 > /tmp/debian-chroot.tar
|
||||
# make sure that xattrs are set in the original tarball
|
||||
mkdir /tmp/debian-chroot
|
||||
tar --xattrs --xattrs-include='*' --directory /tmp/debian-chroot -xf /tmp/debian-chroot.tar ./bin/ping
|
||||
|
@ -25,9 +25,9 @@ rm /tmp/debian-chroot/bin/ping
|
|||
rmdir /tmp/debian-chroot/bin
|
||||
rmdir /tmp/debian-chroot
|
||||
# shift the uid/gid forward by 100000 and backward by 100000
|
||||
./taridshift 100000 < /tmp/debian-chroot.tar > /tmp/debian-chroot-shifted.tar
|
||||
./taridshift -100000 < /tmp/debian-chroot-shifted.tar > /tmp/debian-chroot-shiftedback.tar
|
||||
# the tarball before and after the roundtrip through taridshift should be bit
|
||||
./tarfilter --idshift 100000 < /tmp/debian-chroot.tar > /tmp/debian-chroot-shifted.tar
|
||||
./tarfilter --idshift -100000 < /tmp/debian-chroot-shifted.tar > /tmp/debian-chroot-shiftedback.tar
|
||||
# the tarball before and after the roundtrip through tarfilter should be bit
|
||||
# by bit identical
|
||||
cmp /tmp/debian-chroot.tar /tmp/debian-chroot-shiftedback.tar
|
||||
# manually adjust uid/gid and compare "tar -t" output
|
Loading…
Reference in a new issue