Skip to content

Commit ce4de57

Browse files
authored
Merge pull request #22 from josch/fromstdin
read from stdin if filename equals '-' for -D and -a options
2 parents 41b19b4 + 9fd4447 commit ce4de57

File tree

4 files changed

+72
-20
lines changed

4 files changed

+72
-20
lines changed

README.md

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ It does not require you to mount the image file to copy files on it, nor
1616
does it require that you become the superuser to make device nodes.
1717

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

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

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

6871
**-N, --number-of-inodes inodes**
6972

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

7281
**-L, --volume-label name**
7382

7483
Set the volume label for the filesystem.
7584

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

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

8194
**-m, --reserved-percentage N**
8295

genext2fs.c

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3583,17 +3583,25 @@ populate_fs(filesystem *fs, struct fslayer *fslayers, int nlayers, int squash_ui
35833583
if(fs && !(nod = find_path(fs, EXT2_ROOT_INO, pdest)))
35843584
error_msg_and_die("path %s not found in filesystem", pdest);
35853585
}
3586+
/* do not compute stats when input is to be read from stdin */
3587+
if (stats != NULL && strcmp(fslayers[i].path, "-") == 0) {
3588+
continue;
3589+
}
35863590
stat(fslayers[i].path, &st);
35873591
switch(fslayers[i].type)
35883592
{
35893593
case FSLAYER_TABLE:
3590-
if((st.st_mode & S_IFMT) != S_IFREG)
3594+
if(strcmp(fslayers[i].path, "-") == 0)
3595+
fh = stdin;
3596+
else if((st.st_mode & S_IFMT) != S_IFREG)
35913597
error_msg_and_die("%s should be a file", fslayers[i].path);
3598+
else
3599+
fh = xfopen(fslayers[i].path, "rb");
35923600
if(fs)
35933601
fprintf(stderr, "nodes fixup and creation from device table %s\n", fslayers[i].path);
3594-
fh = xfopen(fslayers[i].path, "rb");
35953602
add2fs_from_file(fs, nod, fh, fs_timestamp, stats);
3596-
fclose(fh);
3603+
if(strcmp(fslayers[i].path, "-") != 0)
3604+
fclose(fh);
35973605
break;
35983606
case FSLAYER_DIR:
35993607
if((st.st_mode & S_IFMT) != S_IFDIR)
@@ -3611,13 +3619,17 @@ populate_fs(filesystem *fs, struct fslayer *fslayers, int nlayers, int squash_ui
36113619
perror_msg_and_die("close");
36123620
break;
36133621
case FSLAYER_TAR:
3614-
if((st.st_mode & S_IFMT) != S_IFREG)
3622+
if(strcmp(fslayers[i].path, "-") == 0)
3623+
fh = stdin;
3624+
else if((st.st_mode & S_IFMT) != S_IFREG)
36153625
error_msg_and_die("%s should be a file", fslayers[i].path);
3626+
else
3627+
fh = xfopen(fslayers[i].path, "rb");
36163628
if(fs)
36173629
fprintf(stderr, "copying from tar archive %s\n", fslayers[i].path);
3618-
fh = xfopen(fslayers[i].path, "rb");
36193630
add2fs_from_tarball(fs, nod, fh, squash_uids, squash_perms, fs_timestamp, stats);
3620-
fclose(fh);
3631+
if(strcmp(fslayers[i].path, "-") != 0)
3632+
fclose(fh);
36213633
break;
36223634
}
36233635
}
@@ -3833,6 +3845,15 @@ main(int argc, char **argv)
38333845
if(creator_os < 0)
38343846
error_msg_and_die("Creator OS unknown.");
38353847

3848+
int numstdin = 0;
3849+
for(i = 0; i < nlayers; i++)
3850+
if (strcmp(layers[i].path, "-") == 0)
3851+
numstdin++;
3852+
if (numstdin == 1 && nbinodes == -1 && bytes_per_inode == -1)
3853+
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.");
3854+
if (numstdin > 1)
3855+
error_msg_and_die("only one input can come from stdin");
3856+
38363857
if(fsin)
38373858
{
38383859
fprintf(stderr, "starting from existing image %s", fsin);

test-gen.lib

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,16 @@ dgen () {
5151
# fgen - Exercises the -D option of genext2fs.
5252
# Creates an image with the devices listed in the given spec file.
5353
fgen () {
54-
blocks=$1; fname=$3
54+
stdin=$1; blocks=$2; fname=$4
5555
echo Testing $blocks blocks with with devices file $fname
5656
gen_setup
5757
cp $origin_dir/$fname $test_dir
5858
TZ=UTC-11 touch -t 200502070321.43 $test_dir/$fname
59-
./genext2fs -N 92 -b $blocks -D $test_dir/$fname -f -o Linux $test_img
59+
if [ "$stdin" = "y" ]; then
60+
./genext2fs -N 92 -b $blocks -D - -f -o Linux $test_img < $test_dir/$fname
61+
else
62+
./genext2fs -N 92 -b $blocks -D $test_dir/$fname -f -o Linux $test_img
63+
fi
6064
}
6165

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

8088
# agen - Exercises the -a option of genext2fs.
8189
# Creates an image with a file of given size.
8290
agen () {
83-
blocks=$1; blocksz=$2; tarball=$3
91+
stdin=$1; blocks=$2; blocksz=$3; tarball=$4
8492
echo Testing $blocks blocks of $blocksz bytes with tarball
8593
gen_setup
8694
echo $tarball | base64 -d | gzip -dc > "$test_dir/input.tar"
87-
./genext2fs -B $blocksz -N 17 -b $blocks -a "$test_dir/input.tar" -f -o Linux $test_img
95+
if [ "$stdin" = "y" ]; then
96+
./genext2fs -B $blocksz -N 17 -b $blocks -a - -f -o Linux $test_img < "$test_dir/input.tar"
97+
else
98+
./genext2fs -B $blocksz -N 17 -b $blocks -a "$test_dir/input.tar" -f -o Linux $test_img
99+
fi
88100
}

test.sh

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,29 @@ dtest () {
3535
ftest () {
3636
expected_digest=$1
3737
shift
38-
fgen $@
38+
fgen y $@
39+
md5cmp $expected_digest
40+
fgen n $@
3941
md5cmp $expected_digest
4042
gen_cleanup
4143
}
4244

4345
ltest () {
4446
expected_digest=$1
4547
shift
46-
lgen $@
48+
lgen y $@
49+
md5cmp $expected_digest
50+
lgen n $@
4751
md5cmp $expected_digest
4852
gen_cleanup
4953
}
5054

5155
atest() {
5256
expected_digest=$1
5357
shift
54-
agen $@
58+
agen y $@
59+
md5cmp $expected_digest
60+
agen n $@
5561
md5cmp $expected_digest
5662
gen_cleanup
5763
}

0 commit comments

Comments
 (0)