Add support for using mtree(5) manifest files to define the image
to be created. The support is based on mtree version 2.0, as used in libarchive, but adds new features on top of it. The current implementation is fully functional, but is envisioned to grow at least the following additional features over time: o Add support for the /include special command so that manifest files can be constructed using includable fragments. o Add support specifying a search path to locate content files. o Content file filters: commands that provide file contents on stdout. The manifest file eliminates the need to first construct a tree as root in order to create an image and allows images (releases) to be created directly from object trees and/or source trees. Reviewed by: deo Sponsored by: Juniper Networks, Inc
This commit is contained in:
parent
6842f5f27f
commit
20c059f23d
@ -7,6 +7,7 @@ CFLAGS+=-I${.CURDIR}
|
||||
SRCS= cd9660.c ffs.c \
|
||||
getid.c \
|
||||
makefs.c \
|
||||
mtree.c \
|
||||
walk.c
|
||||
MAN= makefs.8
|
||||
|
||||
@ -26,4 +27,7 @@ SRCS+= misc.c spec.c
|
||||
.PATH: ${.CURDIR}/../../sys/ufs/ffs
|
||||
SRCS+= ffs_tables.c
|
||||
|
||||
DPADD= ${LIBSBUF}
|
||||
LDADD= -lsbuf
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -294,10 +294,12 @@ cd9660_write_file(FILE *fd, cd9660node *writenode)
|
||||
INODE_WARNX(("%s: writing inode %d blocks at %" PRIu32,
|
||||
__func__, (int)inode->st.st_ino, inode->ino));
|
||||
inode->flags |= FI_WRITTEN;
|
||||
cd9660_compute_full_filename(writenode,
|
||||
temp_file_name, 0);
|
||||
if (writenode->node->contents == NULL)
|
||||
cd9660_compute_full_filename(writenode,
|
||||
temp_file_name, 0);
|
||||
ret = cd9660_copy_file(fd, writenode->fileDataSector,
|
||||
temp_file_name);
|
||||
(writenode->node->contents != NULL) ?
|
||||
writenode->node->contents : temp_file_name);
|
||||
if (ret == 0)
|
||||
goto out;
|
||||
}
|
||||
|
@ -776,9 +776,11 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
continue; /* skip hard-linked entries */
|
||||
cur->inode->flags |= FI_WRITTEN;
|
||||
|
||||
if (snprintf(path, sizeof(path), "%s/%s", dir, cur->name)
|
||||
>= sizeof(path))
|
||||
errx(1, "Pathname too long.");
|
||||
if (cur->contents == NULL) {
|
||||
if (snprintf(path, sizeof(path), "%s/%s", dir,
|
||||
cur->name) >= sizeof(path))
|
||||
errx(1, "Pathname too long.");
|
||||
}
|
||||
|
||||
if (cur->child != NULL)
|
||||
continue; /* child creates own inode */
|
||||
@ -802,7 +804,8 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
if (membuf != NULL) {
|
||||
ffs_write_file(&din, cur->inode->ino, membuf, fsopts);
|
||||
} else if (S_ISREG(cur->type)) {
|
||||
ffs_write_file(&din, cur->inode->ino, path, fsopts);
|
||||
ffs_write_file(&din, cur->inode->ino,
|
||||
(cur->contents) ? cur->contents : path, fsopts);
|
||||
} else {
|
||||
assert (! S_ISDIR(cur->type));
|
||||
ffs_write_inode(&din, cur->inode->ino, fsopts);
|
||||
|
@ -40,7 +40,7 @@
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm makefs
|
||||
.Nd create a file system image from a directory tree
|
||||
.Nd create a file system image from a directory tree or a mtree manifest
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl x
|
||||
@ -57,14 +57,16 @@
|
||||
.Op Fl s Ar image-size
|
||||
.Op Fl t Ar fs-type
|
||||
.Ar image-file
|
||||
.Ar directory
|
||||
.Ar directory | manifest
|
||||
.Sh DESCRIPTION
|
||||
The utility
|
||||
.Nm
|
||||
creates a file system image into
|
||||
.Ar image-file
|
||||
from the directory tree
|
||||
.Ar directory .
|
||||
.Ar directory
|
||||
or from the mtree manifest
|
||||
.Ar manifest .
|
||||
No special devices or privileges are required to perform this task.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
@ -106,6 +108,8 @@ as an
|
||||
.Xr mtree 8
|
||||
.Sq specfile
|
||||
specification.
|
||||
This option has no effect when the image is created from a mtree manifest
|
||||
rather than a directory.
|
||||
.Pp
|
||||
If a specfile entry exists in the underlying file system, its
|
||||
permissions and modification time will be used unless specifically
|
||||
@ -330,6 +334,7 @@ Use RockRidge extensions (for longer filenames, etc.).
|
||||
Volume set identifier of the image.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr mtree 5 ,
|
||||
.Xr mtree 8 ,
|
||||
.Xr newfs 8
|
||||
.Sh HISTORY
|
||||
|
@ -38,6 +38,8 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
@ -80,11 +82,13 @@ int main(int, char *[]);
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct stat sb;
|
||||
struct timeval start;
|
||||
fstype_t *fstype;
|
||||
fsinfo_t fsoptions;
|
||||
fsnode *root;
|
||||
int ch, len;
|
||||
char *subtree;
|
||||
char *specfile;
|
||||
|
||||
setprogname(argv[0]);
|
||||
@ -244,26 +248,47 @@ main(int argc, char *argv[])
|
||||
if (fsoptions.onlyspec != 0 && specfile == NULL)
|
||||
errx(1, "-x requires -F mtree-specfile.");
|
||||
|
||||
/* walk the tree */
|
||||
TIMER_START(start);
|
||||
root = walk_dir(argv[1], NULL);
|
||||
TIMER_RESULTS(start, "walk_dir");
|
||||
/* Accept '-' as meaning "read from standard input". */
|
||||
if (strcmp(argv[1], "-") == 0)
|
||||
sb.st_mode = S_IFREG;
|
||||
else {
|
||||
if (stat(argv[1], &sb) == -1)
|
||||
err(1, "Can't stat `%s'", argv[1]);
|
||||
}
|
||||
|
||||
switch (sb.st_mode & S_IFMT) {
|
||||
case S_IFDIR: /* walk the tree */
|
||||
subtree = argv[1];
|
||||
TIMER_START(start);
|
||||
root = walk_dir(subtree, NULL);
|
||||
TIMER_RESULTS(start, "walk_dir");
|
||||
break;
|
||||
case S_IFREG: /* read the manifest file */
|
||||
subtree = ".";
|
||||
TIMER_START(start);
|
||||
root = read_mtree(argv[1], NULL);
|
||||
TIMER_RESULTS(start, "manifest");
|
||||
break;
|
||||
default:
|
||||
errx(1, "%s: not a file or directory", argv[1]);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
if (specfile) { /* apply a specfile */
|
||||
TIMER_START(start);
|
||||
apply_specfile(specfile, argv[1], root, fsoptions.onlyspec);
|
||||
apply_specfile(specfile, subtree, root, fsoptions.onlyspec);
|
||||
TIMER_RESULTS(start, "apply_specfile");
|
||||
}
|
||||
|
||||
if (debug & DEBUG_DUMP_FSNODES) {
|
||||
printf("\nparent: %s\n", argv[1]);
|
||||
printf("\nparent: %s\n", subtree);
|
||||
dump_fsnodes(".", root);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
/* build the file system */
|
||||
TIMER_START(start);
|
||||
fstype->make_fs(argv[0], argv[1], root, &fsoptions);
|
||||
fstype->make_fs(argv[0], subtree, root, &fsoptions);
|
||||
TIMER_RESULTS(start, "make_fs");
|
||||
|
||||
free_fsnodes(root);
|
||||
@ -311,7 +336,7 @@ usage(void)
|
||||
"usage: %s [-t fs-type] [-o fs-options] [-d debug-mask] [-B endian]\n"
|
||||
"\t[-S sector-size] [-M minimum-size] [-m maximum-size] [-s image-size]\n"
|
||||
"\t[-b free-blocks] [-f free-files] [-F mtree-specfile] [-x]\n"
|
||||
"\t[-N userdb-dir] image-file directory\n",
|
||||
"\t[-N userdb-dir] image-file directory | manifest\n",
|
||||
prog);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -93,11 +93,13 @@ typedef struct _fsnode {
|
||||
uint32_t type; /* type of entry */
|
||||
fsinode *inode; /* actual inode data */
|
||||
char *symlink; /* symlink target */
|
||||
char *contents; /* file to provide contents */
|
||||
char *name; /* file name */
|
||||
int flags; /* misc flags */
|
||||
} fsnode;
|
||||
|
||||
#define FSNODE_F_HASSPEC 0x01 /* fsnode has a spec entry */
|
||||
#define FSNODE_F_OPTIONAL 0x02 /* fsnode is optional */
|
||||
|
||||
/*
|
||||
* fsinfo_t - contains various settings and parameters pertaining to
|
||||
@ -147,6 +149,7 @@ typedef struct {
|
||||
void apply_specfile(const char *, const char *, fsnode *, int);
|
||||
void dump_fsnodes(const char *, fsnode *);
|
||||
const char * inode_type(mode_t);
|
||||
fsnode * read_mtree(const char *, fsnode *);
|
||||
int set_option(option_t *, const char *, const char *);
|
||||
fsnode * walk_dir(const char *, fsnode *);
|
||||
void free_fsnodes(fsnode *);
|
||||
|
1051
usr.sbin/makefs/mtree.c
Normal file
1051
usr.sbin/makefs/mtree.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user