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
|
# copy over files from git or as distributed
|
||||||
for (git, dist, target) in [
|
for (git, dist, target) in [
|
||||||
("./mmdebstrap", "/usr/bin/mmdebstrap", "mmdebstrap"),
|
("./mmdebstrap", "/usr/bin/mmdebstrap", "mmdebstrap"),
|
||||||
("./taridshift", "/usr/bin/mmtaridshift", "taridshift"),
|
|
||||||
("./tarfilter", "/usr/bin/mmtarfilter", "tarfilter"),
|
("./tarfilter", "/usr/bin/mmtarfilter", "tarfilter"),
|
||||||
(
|
(
|
||||||
"./proxysolver",
|
"./proxysolver",
|
||||||
|
|
|
@ -52,7 +52,7 @@ Skip-If:
|
||||||
fmt == "squashfs" and dist == "oldstable" # squashfs-tools-ng is not available
|
fmt == "squashfs" and dist == "oldstable" # squashfs-tools-ng is not available
|
||||||
fmt == "ext2" and dist == "oldstable" # genext2fs does not support SOURCE_DATE_EPOCH
|
fmt == "ext2" and dist == "oldstable" # genext2fs does not support SOURCE_DATE_EPOCH
|
||||||
|
|
||||||
Test: taridshift-utility
|
Test: tarfilter-idshift
|
||||||
Needs-QEMU: true
|
Needs-QEMU: true
|
||||||
Skip-If: dist == "oldstable" # python3 tarfile module does not preserve xattrs
|
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
|
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
|
GNU tar --strip-components, tar members that have less or equal components in
|
||||||
their path are not passed through.
|
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(
|
parser.add_argument(
|
||||||
"--path-exclude",
|
"--path-exclude",
|
||||||
|
@ -100,6 +103,12 @@ their path are not passed through.
|
||||||
type=int,
|
type=int,
|
||||||
help="Strip NUMBER leading components from file names",
|
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()
|
args = parser.parse_args()
|
||||||
if (
|
if (
|
||||||
not hasattr(args, "pathfilter")
|
not hasattr(args, "pathfilter")
|
||||||
|
@ -165,6 +174,15 @@ their path are not passed through.
|
||||||
for k, v in member.pax_headers.items()
|
for k, v in member.pax_headers.items()
|
||||||
if not pax_filter_should_skip(k)
|
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():
|
if member.isfile():
|
||||||
with in_tar.extractfile(member) as file:
|
with in_tar.extractfile(member) as file:
|
||||||
out_tar.addfile(member, 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/subuid -
|
||||||
echo user:100000:65536 | cmp /etc/subgid -
|
echo user:100000:65536 | cmp /etc/subgid -
|
||||||
sysctl -w kernel.unprivileged_userns_clone=1
|
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
|
# extended attributes
|
||||||
# run through tarshift no-op to create a tarball that should be bit-by-bit
|
# 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 }} \
|
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
|
# make sure that xattrs are set in the original tarball
|
||||||
mkdir /tmp/debian-chroot
|
mkdir /tmp/debian-chroot
|
||||||
tar --xattrs --xattrs-include='*' --directory /tmp/debian-chroot -xf /tmp/debian-chroot.tar ./bin/ping
|
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/bin
|
||||||
rmdir /tmp/debian-chroot
|
rmdir /tmp/debian-chroot
|
||||||
# shift the uid/gid forward by 100000 and backward by 100000
|
# shift the uid/gid forward by 100000 and backward by 100000
|
||||||
./taridshift 100000 < /tmp/debian-chroot.tar > /tmp/debian-chroot-shifted.tar
|
./tarfilter --idshift 100000 < /tmp/debian-chroot.tar > /tmp/debian-chroot-shifted.tar
|
||||||
./taridshift -100000 < /tmp/debian-chroot-shifted.tar > /tmp/debian-chroot-shiftedback.tar
|
./tarfilter --idshift -100000 < /tmp/debian-chroot-shifted.tar > /tmp/debian-chroot-shiftedback.tar
|
||||||
# the tarball before and after the roundtrip through taridshift should be bit
|
# the tarball before and after the roundtrip through tarfilter should be bit
|
||||||
# by bit identical
|
# by bit identical
|
||||||
cmp /tmp/debian-chroot.tar /tmp/debian-chroot-shiftedback.tar
|
cmp /tmp/debian-chroot.tar /tmp/debian-chroot-shiftedback.tar
|
||||||
# manually adjust uid/gid and compare "tar -t" output
|
# manually adjust uid/gid and compare "tar -t" output
|
Loading…
Reference in a new issue