Fsutil: able to create filesystem contents from manifest.
This commit is contained in:
24
Makefile
24
Makefile
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user