Skip to content

Commit

Permalink
read from stdin if filename equals '-' for -D and -a options
Browse files Browse the repository at this point in the history
  • Loading branch information
josch committed Jun 24, 2020
1 parent a1b9c69 commit 9fd4447
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 20 deletions.
23 changes: 18 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ It does not require you to mount the image file to copy files on it, nor
does it require that you become the superuser to make device nodes.

The filesystem image is created in the file *output-image*. If not
specified, it is sent to stdout.
specified, it is sent to stdout. The `-d` and `-a` options support reading
from stdin if a single hyphen is given as an argument. Thus, genext2fs
can be used as part of a pipeline without any temporary files.

By default, the maximum number of inodes in the filesystem is the
minimum number required to accommodate the initial contents. In this
Expand Down Expand Up @@ -51,7 +53,8 @@ All specified inodes receive the mtime of **spec-file** itself.
**-a, --tarball file[:path]**

Add the given archive (tarball) contents at a particular path (by default
the root).
the root). If **file** is a hyphen, then the tarball will be read from
standard input.
Note: if not compiled with `libarchive`, genext2fs will use a builtin
tarball parser with very primitive capabilities (e.g. no sparse file
support, generally no support other than for modern GNU tar without
Expand All @@ -67,16 +70,26 @@ Size of a filesystem block in bytes.

**-N, --number-of-inodes inodes**

Maximum number of inodes.
Minimum number of inodes. The required inode number will be computed
automatically for all input that is not read from stdin. The number given
by this option sets the minimum number of inodes. If you add anything
from standard input, you should set this value because in that case the
required number of inodes cannot be precomputed. The value set by this
option will be overwritten by the value computed from the `-i` option,
if the resulting number of inodes is larger.

**-L, --volume-label name**

Set the volume label for the filesystem.

**-i, --bytes-per-inode ratio**

Used to calculate the maximum number of inodes from the available
blocks.
Used to calculate the minimum number of inodes from the available blocks.
Inodes are computed by multiplying the number of blocks (`-b`) by the blocksize
(1024) and dividing that by the **ratio** given in this option. If the result
is larger, then the number of required inodes counted from the input or the
minimum number of inodes from the `-N` option, then the value computed by
this option is used.

**-m, --reserved-percentage N**

Expand Down
33 changes: 27 additions & 6 deletions genext2fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -3583,17 +3583,25 @@ populate_fs(filesystem *fs, struct fslayer *fslayers, int nlayers, int squash_ui
if(fs && !(nod = find_path(fs, EXT2_ROOT_INO, pdest)))
error_msg_and_die("path %s not found in filesystem", pdest);
}
/* do not compute stats when input is to be read from stdin */
if (stats != NULL && strcmp(fslayers[i].path, "-") == 0) {
continue;
}
stat(fslayers[i].path, &st);
switch(fslayers[i].type)
{
case FSLAYER_TABLE:
if((st.st_mode & S_IFMT) != S_IFREG)
if(strcmp(fslayers[i].path, "-") == 0)
fh = stdin;
else if((st.st_mode & S_IFMT) != S_IFREG)
error_msg_and_die("%s should be a file", fslayers[i].path);
else
fh = xfopen(fslayers[i].path, "rb");
if(fs)
fprintf(stderr, "nodes fixup and creation from device table %s\n", fslayers[i].path);
fh = xfopen(fslayers[i].path, "rb");
add2fs_from_file(fs, nod, fh, fs_timestamp, stats);
fclose(fh);
if(strcmp(fslayers[i].path, "-") != 0)
fclose(fh);
break;
case FSLAYER_DIR:
if((st.st_mode & S_IFMT) != S_IFDIR)
Expand All @@ -3611,13 +3619,17 @@ populate_fs(filesystem *fs, struct fslayer *fslayers, int nlayers, int squash_ui
perror_msg_and_die("close");
break;
case FSLAYER_TAR:
if((st.st_mode & S_IFMT) != S_IFREG)
if(strcmp(fslayers[i].path, "-") == 0)
fh = stdin;
else if((st.st_mode & S_IFMT) != S_IFREG)
error_msg_and_die("%s should be a file", fslayers[i].path);
else
fh = xfopen(fslayers[i].path, "rb");
if(fs)
fprintf(stderr, "copying from tar archive %s\n", fslayers[i].path);
fh = xfopen(fslayers[i].path, "rb");
add2fs_from_tarball(fs, nod, fh, squash_uids, squash_perms, fs_timestamp, stats);
fclose(fh);
if(strcmp(fslayers[i].path, "-") != 0)
fclose(fh);
break;
}
}
Expand Down Expand Up @@ -3833,6 +3845,15 @@ main(int argc, char **argv)
if(creator_os < 0)
error_msg_and_die("Creator OS unknown.");

int numstdin = 0;
for(i = 0; i < nlayers; i++)
if (strcmp(layers[i].path, "-") == 0)
numstdin++;
if (numstdin == 1 && nbinodes == -1 && bytes_per_inode == -1)
fprintf(stderr, "Cannot count the required inodes for input from stdin -- use the -N or -i options to set the number of inodes or work with temporary files.");
if (numstdin > 1)
error_msg_and_die("only one input can come from stdin");

if(fsin)
{
fprintf(stderr, "starting from existing image %s", fsin);
Expand Down
24 changes: 18 additions & 6 deletions test-gen.lib
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,16 @@ dgen () {
# fgen - Exercises the -D option of genext2fs.
# Creates an image with the devices listed in the given spec file.
fgen () {
blocks=$1; fname=$3
stdin=$1; blocks=$2; fname=$4
echo Testing $blocks blocks with with devices file $fname
gen_setup
cp $origin_dir/$fname $test_dir
TZ=UTC-11 touch -t 200502070321.43 $test_dir/$fname
./genext2fs -N 92 -b $blocks -D $test_dir/$fname -f -o Linux $test_img
if [ "$stdin" = "y" ]; then
./genext2fs -N 92 -b $blocks -D - -f -o Linux $test_img < $test_dir/$fname
else
./genext2fs -N 92 -b $blocks -D $test_dir/$fname -f -o Linux $test_img
fi
}

# lgen - Exercises the -d option of genext2fs, with symlink
Expand All @@ -66,23 +70,31 @@ fgen () {
# NB: some systems including early versions of Mac OS X cannot
# change symlink timestamps; this test will fail on those systems.
lgen () {
blocks=$1; blocksz=$2; appendage=$3; devtable=$4
stdin=$1; blocks=$2; blocksz=$3; appendage=$4; devtable=$5
echo Testing $blocks blocks of $blocksz bytes with symlink ...$appendage and devices file $devtable
gen_setup
cd $test_dir
target=12345678901234567890123456789012345678901234567890$appendage
ln -s $target symlink
TZ=UTC-11 touch -h -t 201309241353.59 symlink .
cd ..
./genext2fs -B $blocksz -N 234 -b $blocks -d $test_dir -D $origin_dir/$devtable -f -o Linux -q $test_img
if [ "$stdin" = "y" ]; then
./genext2fs -B $blocksz -N 234 -b $blocks -d $test_dir -D - -f -o Linux -q $test_img < $origin_dir/$devtable
else
./genext2fs -B $blocksz -N 234 -b $blocks -d $test_dir -D $origin_dir/$devtable -f -o Linux -q $test_img
fi
}

# agen - Exercises the -a option of genext2fs.
# Creates an image with a file of given size.
agen () {
blocks=$1; blocksz=$2; tarball=$3
stdin=$1; blocks=$2; blocksz=$3; tarball=$4
echo Testing $blocks blocks of $blocksz bytes with tarball
gen_setup
echo $tarball | base64 -d | gzip -dc > "$test_dir/input.tar"
./genext2fs -B $blocksz -N 17 -b $blocks -a "$test_dir/input.tar" -f -o Linux $test_img
if [ "$stdin" = "y" ]; then
./genext2fs -B $blocksz -N 17 -b $blocks -a - -f -o Linux $test_img < "$test_dir/input.tar"
else
./genext2fs -B $blocksz -N 17 -b $blocks -a "$test_dir/input.tar" -f -o Linux $test_img
fi
}
12 changes: 9 additions & 3 deletions test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,29 @@ dtest () {
ftest () {
expected_digest=$1
shift
fgen $@
fgen y $@
md5cmp $expected_digest
fgen n $@
md5cmp $expected_digest
gen_cleanup
}

ltest () {
expected_digest=$1
shift
lgen $@
lgen y $@
md5cmp $expected_digest
lgen n $@
md5cmp $expected_digest
gen_cleanup
}

atest() {
expected_digest=$1
shift
agen $@
agen y $@
md5cmp $expected_digest
agen n $@
md5cmp $expected_digest
gen_cleanup
}
Expand Down

0 comments on commit 9fd4447

Please sign in to comment.