Fsutil: able to create filesystem contents from manifest.

This commit is contained in:
Serge Vakulenko
2014-08-01 17:49:59 -07:00
parent cb4ca7f73a
commit 8f4aad27f9
3 changed files with 196 additions and 70 deletions

View File

@@ -27,9 +27,9 @@ DUINOMITEEUART = sys/pic32/duinomite-e-uart/DUINOMITE-E-UART
PINGUINO = sys/pic32/pinguino-micro/PINGUINO-MICRO PINGUINO = sys/pic32/pinguino-micro/PINGUINO-MICRO
DIP = sys/pic32/dip/DIP DIP = sys/pic32/dip/DIP
BAREMETAL = sys/pic32/baremetal/BAREMETAL BAREMETAL = sys/pic32/baremetal/BAREMETAL
RETROONE = sys/pic32/retroone/RETROONE RETROONE = sys/pic32/retroone/RETROONE
FUBARINO = sys/pic32/fubarino/FUBARINO FUBARINO = sys/pic32/fubarino/FUBARINO
FUBARINOBIG = sys/pic32/fubarino/FUBARINO-UART2CONS-UART1-SRAMC FUBARINOBIG = sys/pic32/fubarino/FUBARINO-UART2CONS-UART1-SRAMC
MMBMX7 = sys/pic32/mmb-mx7/MMB-MX7 MMBMX7 = sys/pic32/mmb-mx7/MMB-MX7
# Select target board # Select target board
@@ -100,19 +100,15 @@ BDEVS = dev/rd0!b0:0 dev/rd0a!b0:1 dev/rd0b!b0:2 dev/rd0c!b0:3 dev/rd0
BDEVS += dev/rd1!b1:0 dev/rd1a!b1:1 dev/rd1b!b1:2 dev/rd1c!b1:3 dev/rd1d!b1:4 BDEVS += dev/rd1!b1:0 dev/rd1a!b1:1 dev/rd1b!b1:2 dev/rd1c!b1:3 dev/rd1d!b1:4
BDEVS += dev/rd2!b2:0 dev/rd2a!b2:1 dev/rd2b!b2:2 dev/rd2c!b2:3 dev/rd2d!b2:4 BDEVS += dev/rd2!b2:0 dev/rd2a!b2:1 dev/rd2b!b2:2 dev/rd2c!b2:3 dev/rd2d!b2:4
BDEVS += dev/rd3!b3:0 dev/rd3a!b3:1 dev/rd3b!b3:2 dev/rd3c!b3:3 dev/rd3d!b3:4 BDEVS += dev/rd3!b3:0 dev/rd3a!b3:1 dev/rd3b!b3:2 dev/rd3c!b3:3 dev/rd3d!b3:4
BDEVS += dev/swap!b4:64 dev/swap0!b4:0 dev/swap1!b4:1 dev/swap2!b4:2 BDEVS += dev/swap!b4:64 dev/swap0!b4:0 dev/swap1!b4:1 dev/swap2!b4:2
D_CONSOLE = dev/console!c0:0 D_CONSOLE = dev/console!c0:0
D_MEM = dev/mem!c1:0 dev/kmem!c1:1 dev/null!c1:2 dev/zero!c1:3 D_MEM = dev/mem!c1:0 dev/kmem!c1:1 dev/null!c1:2 dev/zero!c1:3
D_TTY = dev/tty!c2:0 D_TTY = dev/tty!c2:0
D_FD = dev/stdin!c3:0 dev/stdout!c3:1 dev/stderr!c3:2 D_FD = dev/stdin!c3:0 dev/stdout!c3:1 dev/stderr!c3:2
D_TEMP = dev/temp0!c4:0 dev/temp1!c4:1 dev/temp2!c4:2 D_TEMP = dev/temp0!c4:0 dev/temp1!c4:1 dev/temp2!c4:2
U_DIRS = $(addsuffix /,$(shell find u -type d ! -path '*/.svn*')) CDEVS = $(D_CONSOLE) $(D_MEM) $(D_TTY) $(D_FD) $(D_TEMP)
U_FILES = $(shell find u -type f ! -path '*/.svn/*')
#U_ALL = $(patsubst u/%,%,$(U_DIRS) $(U_FILES))
CDEVS = $(D_CONSOLE) $(D_MEM) $(D_TTY) $(D_FD) $(D_TEMP)
all: tools build kernel all: tools build kernel
$(MAKE) fs $(MAKE) fs

View File

@@ -79,16 +79,14 @@ static void print_help (char *progname)
printf ("\n"); printf ("\n");
printf ("Usage:\n"); printf ("Usage:\n");
printf (" %s [--verbose] filesys.img\n", progname); printf (" %s [--verbose] filesys.img\n", progname);
printf (" %s --add filesys.img files...\n", progname);
printf (" %s --extract filesys.img\n", progname);
printf (" %s --check [--fix] filesys.img\n", progname); printf (" %s --check [--fix] filesys.img\n", progname);
printf (" %s --new=kbytes [--swap=kbytes] [--manifest=file] filesys.img [dir]\n", progname); printf (" %s --new=kbytes [--swap=kbytes] [--manifest=file] filesys.img [dir]\n", progname);
printf (" %s --mount filesys.img dir\n", progname); printf (" %s --mount filesys.img dir\n", progname);
printf (" %s --add filesys.img files...\n", progname);
printf (" %s --extract filesys.img\n", progname);
printf (" %s --scan dir > file\n", progname); printf (" %s --scan dir > file\n", progname);
printf ("\n"); printf ("\n");
printf ("Options:\n"); printf ("Options:\n");
printf (" -a, --add Add files to filesystem.\n");
printf (" -x, --extract Extract all files.\n");
printf (" -c, --check Check filesystem, use -c -f to fix.\n"); printf (" -c, --check Check filesystem, use -c -f to fix.\n");
printf (" -f, --fix Fix bugs in filesystem.\n"); printf (" -f, --fix Fix bugs in filesystem.\n");
printf (" -n NUM, --new=NUM Create new filesystem, size in kbytes.\n"); printf (" -n NUM, --new=NUM Create new filesystem, size in kbytes.\n");
@@ -96,6 +94,8 @@ static void print_help (char *progname)
printf (" -s NUM, --swap=NUM Size of swap area in kbytes.\n"); printf (" -s NUM, --swap=NUM Size of swap area in kbytes.\n");
printf (" -M file, --manifest=file List of files and attributes to create.\n"); printf (" -M file, --manifest=file List of files and attributes to create.\n");
printf (" -m, --mount Mount the filesystem.\n"); printf (" -m, --mount Mount the filesystem.\n");
printf (" -a, --add Add files to filesystem.\n");
printf (" -x, --extract Extract all files.\n");
printf (" -S, --scan Create a manifest from directory contents.\n"); printf (" -S, --scan Create a manifest from directory contents.\n");
printf (" -v, --verbose Be verbose.\n"); printf (" -v, --verbose Be verbose.\n");
printf (" -V, --version Print version information and then exit.\n"); printf (" -V, --version Print version information and then exit.\n");
@@ -297,7 +297,7 @@ void scanner (fs_inode_t *dir, fs_inode_t *inode,
/* /*
* Create a directory. * Create a directory.
*/ */
void add_directory (fs_t *fs, char *name) void add_directory (fs_t *fs, char *name, int mode, int owner, int group)
{ {
fs_inode_t dir, parent; fs_inode_t dir, parent;
char buf [BSDFS_BSIZE], *p; char buf [BSDFS_BSIZE], *p;
@@ -315,7 +315,9 @@ void add_directory (fs_t *fs, char *name)
} }
/* Create directory. */ /* Create directory. */
int done = fs_inode_by_name (fs, &dir, name, INODE_OP_CREATE, INODE_MODE_FDIR | 0777); mode &= 07777;
mode |= INODE_MODE_FDIR;
int done = fs_inode_by_name (fs, &dir, name, INODE_OP_CREATE, mode);
if (! done) { if (! done) {
fprintf (stderr, "%s: directory inode create failed\n", name); fprintf (stderr, "%s: directory inode create failed\n", name);
return; return;
@@ -324,7 +326,9 @@ void add_directory (fs_t *fs, char *name)
/* The directory already existed. */ /* The directory already existed. */
return; return;
} }
fs_inode_save (&dir, 0); dir.uid = owner;
dir.gid = group;
fs_inode_save (&dir, 1);
/* Make parent link '..' */ /* Make parent link '..' */
strcpy (buf, name); strcpy (buf, name);
@@ -345,83 +349,166 @@ void add_directory (fs_t *fs, char *name)
/* /*
* Create a device node. * Create a device node.
*/ */
void add_device (fs_t *fs, char *name, char *spec) void add_device (fs_t *fs, char *name, int mode, int owner, int group,
int type, int majr, int minr)
{ {
fs_inode_t dev; fs_inode_t dev;
int majr, minr;
char type;
if (sscanf (spec, "%c%d:%d", &type, &majr, &minr) != 3 || mode &= 07777;
(type != 'c' && type != 'b') || mode |= (type == 'b') ? INODE_MODE_FBLK : INODE_MODE_FCHR;
majr < 0 || majr > 255 || minr < 0 || minr > 255) { if (! fs_inode_by_name (fs, &dev, name, INODE_OP_CREATE, mode)) {
fprintf (stderr, "%s: invalid device specification\n", spec);
fprintf (stderr, "expected c<major>:<minor> or b<major>:<minor>\n");
return;
}
if (! fs_inode_by_name (fs, &dev, name, INODE_OP_CREATE, 0666 |
((type == 'b') ? INODE_MODE_FBLK : INODE_MODE_FCHR))) {
fprintf (stderr, "%s: device inode create failed\n", name); fprintf (stderr, "%s: device inode create failed\n", name);
return; return;
} }
dev.addr[1] = majr << 8 | minr; dev.addr[1] = majr << 8 | minr;
dev.uid = owner;
dev.gid = group;
time (&dev.mtime); time (&dev.mtime);
fs_inode_save (&dev, 1); fs_inode_save (&dev, 1);
} }
/* /*
* Copy file to filesystem. * Copy regular file to filesystem.
* When name is ended by slash as "name/", directory is created.
*/ */
void add_file (fs_t *fs, char *name) void add_file (fs_t *fs, const char *path, const char *dirname,
int mode, int owner, int group)
{ {
fs_file_t file; fs_file_t file;
FILE *fd; FILE *fd;
char accpath [BSDFS_BSIZE];
unsigned char data [BSDFS_BSIZE]; unsigned char data [BSDFS_BSIZE];
struct stat st; struct stat st;
char *p;
int len; int len;
if (dirname && *dirname) {
/* Concatenate directory name and file name. */
strcpy (accpath, dirname);
len = strlen (accpath);
if (accpath[len-1] != '/' && path[0] != '/')
strcat (accpath, "/");
strcat (accpath, path);
} else {
/* Use filename relative to current directory. */
strcpy (accpath, path);
}
fd = fopen (accpath, "r");
if (! fd) {
perror (accpath);
return;
}
fstat (fileno(fd), &st);
if (mode == -1)
mode = st.st_mode;
mode &= 07777;
mode |= INODE_MODE_FREG;
if (! fs_file_create (fs, &file, path, mode)) {
fprintf (stderr, "%s: cannot create\n", path);
return;
}
for (;;) {
len = fread (data, 1, sizeof (data), fd);
/* printf ("read %d bytes from %s\n", len, accpath);*/
if (len < 0)
perror (accpath);
if (len <= 0)
break;
if (! fs_file_write (&file, data, len)) {
fprintf (stderr, "%s: write error\n", path);
break;
}
}
file.inode.uid = owner;
file.inode.gid = group;
file.inode.mtime = st.st_mtime;
file.inode.dirty = 1;
fs_file_close (&file);
fclose (fd);
}
/*
* Create a symlink.
*/
void add_symlink (fs_t *fs, const char *path, const char *link,
int mode, int owner, int group)
{
fs_file_t file;
int len;
mode &= 07777;
mode |= INODE_MODE_FLNK;
if (! fs_file_create (fs, &file, path, mode)) {
fprintf (stderr, "%s: cannot create\n", path);
return;
}
len = strlen (link);
if (! fs_file_write (&file, (unsigned char*) link, len)) {
fprintf (stderr, "%s: write error\n", path);
return;
}
file.inode.uid = owner;
file.inode.gid = group;
time (&file.inode.mtime);
file.inode.dirty = 1;
fs_file_close (&file);
}
/*
* Create a hard link.
*/
void add_hardlink (fs_t *fs, const char *path, const char *link)
{
fs_inode_t source, target;
/* Find source. */
if (! fs_inode_by_name (fs, &source, link, INODE_OP_LOOKUP, 0)) {
fprintf (stderr, "%s: link source not found\n", link);
return;
}
if ((source.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) {
fprintf (stderr, "%s: cannot link directories\n", link);
return;
}
/* Create target link. */
if (! fs_inode_by_name (fs, &target, path, INODE_OP_LINK, source.number)) {
fprintf (stderr, "%s: link failed\n", path);
return;
}
}
/*
* Create a file/device/directory in the filesystem.
* When name is ended by slash as "name/", directory is created.
*/
void add_object (fs_t *fs, char *name)
{
int majr, minr;
char type;
char *p;
if (verbose) { if (verbose) {
printf ("%s\n", name); printf ("%s\n", name);
} }
p = strrchr (name, '/'); p = strrchr (name, '/');
if (p && p[1] == 0) { if (p && p[1] == 0) {
*p = 0; *p = 0;
add_directory (fs, name); add_directory (fs, name, 0777, 0, 0);
return; return;
} }
p = strrchr (name, '!'); p = strrchr (name, '!');
if (p) { if (p) {
*p++ = 0; *p++ = 0;
add_device (fs, name, p); if (sscanf (p, "%c%d:%d", &type, &majr, &minr) != 3 ||
return; (type != 'c' && type != 'b') ||
} majr < 0 || majr > 255 || minr < 0 || minr > 255) {
fd = fopen (name, "r"); fprintf (stderr, "%s: invalid device specification\n", p);
if (! fd) { fprintf (stderr, "expected c<major>:<minor> or b<major>:<minor>\n");
perror (name); return;
return;
}
stat (name, &st);
if (! fs_file_create (fs, &file, name, st.st_mode)) {
fprintf (stderr, "%s: cannot create\n", name);
return;
}
for (;;) {
len = fread (data, 1, sizeof (data), fd);
/* printf ("read %d bytes from %s\n", len, name);*/
if (len < 0)
perror (name);
if (len <= 0)
break;
if (! fs_file_write (&file, data, len)) {
fprintf (stderr, "%s: write error\n", name);
break;
} }
add_device (fs, name, 0666, 0, 0, type, majr, minr);
return;
} }
file.inode.mtime = st.st_mtime; add_file (fs, name, 0, -1, 0, 0);
file.inode.dirty = 1;
fs_file_close (&file);
fclose (fd);
} }
/* /*
@@ -430,9 +517,52 @@ void add_file (fs_t *fs, char *name)
*/ */
void add_contents (fs_t *fs, const char *dirname, const char *manifest) void add_contents (fs_t *fs, const char *dirname, const char *manifest)
{ {
printf ("TODO: add contents from directory '%s'\n", dirname); manifest_t m;
if (manifest) void *cursor;
printf ("TODO: use manifest '%s'\n", manifest); char *path, *link;
int filetype, mode, owner, group, majr, minr;
if (manifest) {
/* Load manifest from file. */
if (! manifest_load (&m, manifest)) {
fprintf (stderr, "%s: cannot read\n", manifest);
return;
}
} else {
/* Create manifest from directory contents. */
if (! manifest_scan (&m, dirname)) {
fprintf (stderr, "%s: cannot read\n", dirname);
return;
}
}
/* For every file in the manifest,
* add it to the target filesystem. */
cursor = 0;
while ((filetype = manifest_iterate (&m, &cursor, &path, &link, &mode,
&owner, &group, &majr, &minr)) != 0)
{
switch (filetype) {
case 'd':
add_directory (fs, path, mode, owner, group);
break;
case 'f':
add_file (fs, path, dirname, mode, owner, group);
break;
case 'l':
add_hardlink (fs, path, link);
break;
case 's':
add_symlink (fs, path, link, mode, owner, group);
break;
case 'b':
add_device (fs, path, mode, owner, group, 'b', majr, minr);
break;
case 'c':
add_device (fs, path, mode, owner, group, 'c', majr, minr);
break;
}
}
} }
int main (int argc, char **argv) int main (int argc, char **argv)
@@ -561,7 +691,7 @@ int main (int argc, char **argv)
if (add) { if (add) {
/* Add files i+1..argc-1 to filesystem. */ /* Add files i+1..argc-1 to filesystem. */
while (++i < argc) while (++i < argc)
add_file (&fs, argv[i]); add_object (&fs, argv[i]);
fs_sync (&fs, 0); fs_sync (&fs, 0);
fs_close (&fs); fs_close (&fs);
return 0; return 0;

View File

@@ -234,7 +234,7 @@ int manifest_scan (manifest_t *m, const char *dirname)
*/ */
void manifest_print (manifest_t *m) void manifest_print (manifest_t *m)
{ {
void *cursor = 0; void *cursor;
char *path, *link; char *path, *link;
int filetype, mode, owner, group, major, minor; int filetype, mode, owner, group, major, minor;