aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/gensquashfs.13
-rw-r--r--doc/tar2sqfs.13
-rw-r--r--include/highlevel.h8
-rw-r--r--lib/Makemodule.am1
-rw-r--r--lib/sqfs/write_export_table.c36
-rw-r--r--mkfs/mkfs.c5
-rw-r--r--mkfs/mkfs.h1
-rw-r--r--mkfs/options.c10
-rw-r--r--tar/tar2sqfs.c13
9 files changed, 77 insertions, 3 deletions
diff --git a/doc/gensquashfs.1 b/doc/gensquashfs.1
index c52ce70..a880453 100644
--- a/doc/gensquashfs.1
+++ b/doc/gensquashfs.1
@@ -61,6 +61,9 @@ mtime=<value>;0
If built with SELinux support, use the given SELinux label file to add context
labels to the elements packed into the SquashFS image.
.TP
+\fB\-\-exportable\fR, \fB\-e\fR
+Generate an export table for NFS support.
+.TP
\fB\-\-force\fR, \fB\-f\fR
Overwrite the output file if it exists.
.TP
diff --git a/doc/tar2sqfs.1 b/doc/tar2sqfs.1
index 3279794..8c7d20d 100644
--- a/doc/tar2sqfs.1
+++ b/doc/tar2sqfs.1
@@ -58,6 +58,9 @@ extended attributes and skip the ones that cannot be encoded in SquashFS.
\fB\-\-no\-skip\fR, \fB\-s\fR
Abort if a tar record cannot be read instead of skipping it.
.TP
+\fB\-\-exportable\fR, \fB\-e\fR
+Generate an export table for NFS support.
+.TP
\fB\-\-force\fR, \fB\-f\fR
Overwrite the output file if it exists.
.TP
diff --git a/include/highlevel.h b/include/highlevel.h
index 4bc3b7a..12884a0 100644
--- a/include/highlevel.h
+++ b/include/highlevel.h
@@ -75,4 +75,12 @@ int deserialize_fstree(fstree_t *out, sqfs_super_t *super, compressor_t *cmp,
int write_xattr(int outfd, fstree_t *fs, sqfs_super_t *super,
compressor_t *cmp);
+/*
+ Generate an NFS export table.
+
+ Returns 0 on success. Prints error messages to stderr on failure.
+ */
+int write_export_table(int outfd, fstree_t *fs, sqfs_super_t *super,
+ compressor_t *cmp);
+
#endif /* HIGHLEVEL_H */
diff --git a/lib/Makemodule.am b/lib/Makemodule.am
index 7e6ca82..ab2030c 100644
--- a/lib/Makemodule.am
+++ b/lib/Makemodule.am
@@ -35,6 +35,7 @@ libsquashfs_a_SOURCES += lib/sqfs/deserialize_fstree.c
libsquashfs_a_SOURCES += lib/sqfs/data_writer.c lib/sqfs/write_xattr.c
libsquashfs_a_SOURCES += include/data_writer.h include/frag_reader.h
libsquashfs_a_SOURCES += include/data_reader.h lib/sqfs/data_reader.c
+libsquashfs_a_SOURCES += lib/sqfs/write_export_table.c
libutil_a_SOURCES = lib/util/canonicalize_name.c lib/util/write_data.c
libutil_a_SOURCES += lib/util/read_data.c include/util.h
diff --git a/lib/sqfs/write_export_table.c b/lib/sqfs/write_export_table.c
new file mode 100644
index 0000000..eee4e01
--- /dev/null
+++ b/lib/sqfs/write_export_table.c
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+#include "highlevel.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+int write_export_table(int outfd, fstree_t *fs, sqfs_super_t *super,
+ compressor_t *cmp)
+{
+ uint64_t *table, start;
+ size_t i;
+ int ret;
+
+ table = malloc(sizeof(uint64_t) * fs->inode_tbl_size);
+
+ if (table == NULL) {
+ perror("Allocating NFS export table");
+ return -1;
+ }
+
+ for (i = 0; i < fs->inode_tbl_size; ++i) {
+ if (fs->inode_table[i] == NULL) {
+ table[i] = 0xFFFFFFFFFFFFFFFF;
+ } else {
+ table[i] = htole64(fs->inode_table[i]->inode_ref);
+ }
+ }
+
+ ret = sqfs_write_table(outfd, super, table, sizeof(table[0]),
+ fs->inode_tbl_size, &start, cmp);
+
+ super->export_table_start = start;
+ super->flags |= SQFS_FLAG_EXPORTABLE;
+ free(table);
+ return ret;
+}
diff --git a/mkfs/mkfs.c b/mkfs/mkfs.c
index f1c1f1b..91cb9bd 100644
--- a/mkfs/mkfs.c
+++ b/mkfs/mkfs.c
@@ -185,6 +185,11 @@ int main(int argc, char **argv)
if (data_writer_write_fragment_table(data))
goto out_data;
+ if (opt.exportable) {
+ if (write_export_table(outfd, &fs, &super, cmp))
+ goto out_data;
+ }
+
if (id_table_write(&idtbl, outfd, &super, cmp))
goto out_data;
diff --git a/mkfs/mkfs.h b/mkfs/mkfs.h
index 4031c74..70a2ed6 100644
--- a/mkfs/mkfs.h
+++ b/mkfs/mkfs.h
@@ -29,6 +29,7 @@ typedef struct {
int outmode;
int blksz;
int devblksz;
+ bool exportable;
bool quiet;
const char *infile;
const char *packdir;
diff --git a/mkfs/options.c b/mkfs/options.c
index 2dab6b8..fe2bc69 100644
--- a/mkfs/options.c
+++ b/mkfs/options.c
@@ -9,6 +9,7 @@ static struct option long_opts[] = {
{ "comp-extra", required_argument, NULL, 'X' },
{ "pack-file", required_argument, NULL, 'F' },
{ "pack-dir", required_argument, NULL, 'D' },
+ { "exportable", no_argument, NULL, 'e' },
{ "force", no_argument, NULL, 'f' },
{ "quiet", no_argument, NULL, 'q' },
#ifdef WITH_SELINUX
@@ -19,9 +20,9 @@ static struct option long_opts[] = {
};
#ifdef WITH_SELINUX
-static const char *short_opts = "s:F:D:X:c:b:B:d:fqhV";
+static const char *short_opts = "s:F:D:X:c:b:B:d:efqhV";
#else
-static const char *short_opts = "F:D:X:c:b:B:d:fqhV";
+static const char *short_opts = "F:D:X:c:b:B:d:efqhV";
#endif
extern char *__progname;
@@ -66,6 +67,7 @@ static const char *help_string =
" --selinux, -s <file> Specify an SELinux label file to get context\n"
" attributes from.\n"
#endif
+" --exportable, -e Generate an export table for NFS support.\n"
" --force, -f Overwrite the output file if it exists.\n"
" --quiet, -q Do not print out progress reports.\n"
" --help, -h Print help text and exit.\n"
@@ -123,6 +125,7 @@ void process_command_line(options_t *opt, int argc, char **argv)
opt->compressor = compressor_get_default();
opt->blksz = SQFS_DEFAULT_BLOCK_SIZE;
opt->devblksz = SQFS_DEVBLK_SIZE;
+ opt->exportable = false;
opt->quiet = false;
opt->infile = NULL;
opt->packdir = NULL;
@@ -166,6 +169,9 @@ void process_command_line(options_t *opt, int argc, char **argv)
case 'd':
opt->fs_defaults = optarg;
break;
+ case 'e':
+ opt->exportable = true;
+ break;
case 'f':
opt->outmode = O_WRONLY | O_CREAT | O_TRUNC;
break;
diff --git a/tar/tar2sqfs.c b/tar/tar2sqfs.c
index 3417fd0..8394b7f 100644
--- a/tar/tar2sqfs.c
+++ b/tar/tar2sqfs.c
@@ -26,13 +26,14 @@ static struct option long_opts[] = {
{ "comp-extra", required_argument, NULL, 'X' },
{ "no-skip", no_argument, NULL, 's' },
{ "no-xattr", no_argument, NULL, 'x' },
+ { "exportable", no_argument, NULL, 'e' },
{ "force", no_argument, NULL, 'f' },
{ "quiet", no_argument, NULL, 'q' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
};
-static const char *short_opts = "c:b:B:d:X:sxfqhV";
+static const char *short_opts = "c:b:B:d:X:sxefqhV";
static const char *usagestr =
"Usage: tar2sqfs [OPTIONS...] <sqfsfile>\n"
@@ -63,6 +64,7 @@ static const char *usagestr =
" --no-skip, -s Abort if a tar record cannot be read instead\n"
" of skipping it.\n"
" --no-xattr, -x Do not copy extended attributes from archive.\n"
+" --exportable, -e Generate an export table for NFS support.\n"
" --force, -f Overwrite the output file if it exists.\n"
" --quiet, -q Do not print out progress reports.\n"
" --help, -h Print help text and exit.\n"
@@ -85,6 +87,7 @@ static char *comp_extra = NULL;
static char *fs_defaults = NULL;
static bool dont_skip = false;
static bool no_xattr = false;
+static bool exportable = false;
static void process_args(int argc, char **argv)
{
@@ -137,6 +140,9 @@ static void process_args(int argc, char **argv)
case 's':
dont_skip = true;
break;
+ case 'e':
+ exportable = true;
+ break;
case 'f':
outmode = O_WRONLY | O_CREAT | O_TRUNC;
break;
@@ -388,6 +394,11 @@ int main(int argc, char **argv)
if (data_writer_write_fragment_table(data))
goto out;
+ if (exportable) {
+ if (write_export_table(outfd, &fs, &super, cmp))
+ goto out;
+ }
+
if (id_table_write(&idtbl, outfd, &super, cmp))
goto out;