Fsutil enhanced to create and handle partitions.

This commit is contained in:
Sergey
2014-09-20 18:54:13 -07:00
parent f58c7a7426
commit dc66e6fdda
15 changed files with 254 additions and 93 deletions

View File

@@ -1,7 +1,7 @@
/*
* Block handling for 2.xBSD filesystem.
*
* Copyright (C) 2006-2011 Serge Vakulenko, <serge@vak.ru>
* Copyright (C) 2006-2014 Serge Vakulenko, <serge@vak.ru>
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for any purpose and without fee is hereby

View File

@@ -1,7 +1,7 @@
/*
* Data structures for 2.xBSD filesystem.
*
* Copyright (C) 2006-2011 Serge Vakulenko, <serge@vak.ru>
* Copyright (C) 2006-2014 Serge Vakulenko, <serge@vak.ru>
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for any purpose and without fee is hereby
@@ -62,6 +62,9 @@ typedef struct {
int writable;
int dirty; /* sync needed */
int modified; /* write_block was called */
unsigned char part_type;
unsigned part_offset;
unsigned part_nsectors;
unsigned isize; /* size in blocks of superblock + I list */
unsigned fsize; /* size in blocks of entire volume */
@@ -163,10 +166,11 @@ int fs_write32 (fs_t *fs, unsigned val);
int fs_read (fs_t *fs, unsigned char *data, int bytes);
int fs_write (fs_t *fs, unsigned char *data, int bytes);
int fs_open (fs_t *fs, const char *filename, int writable);
int fs_open (fs_t *fs, const char *filename, int writable, unsigned pindex);
void fs_close (fs_t *fs);
int fs_set_partition (fs_t *fs, unsigned pindex);
int fs_sync (fs_t *fs, int force);
int fs_create (fs_t *fs, const char *filename, unsigned kbytes,
int fs_create (fs_t *fs, const char *filename, int kbytes,
unsigned swap_kbytes);
int fs_check (fs_t *fs);
void fs_print (fs_t *fs, FILE *out);

View File

@@ -1,7 +1,7 @@
/*
* Check 2.xBSD filesystem.
*
* Copyright (C) 2006-2011 Serge Vakulenko, <serge@vak.ru>
* Copyright (C) 2006-2014 Serge Vakulenko, <serge@vak.ru>
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for any purpose and without fee is hereby

View File

@@ -1,7 +1,7 @@
/*
* Create new 2.xBSD filesystem.
*
* Copyright (C) 2006-2011 Serge Vakulenko, <serge@vak.ru>
* Copyright (C) 2006-2014 Serge Vakulenko, <serge@vak.ru>
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for any purpose and without fee is hereby
@@ -325,7 +325,7 @@ static int create_swap_file (fs_t *fs)
return 1;
}
int fs_create (fs_t *fs, const char *filename, unsigned kbytes,
int fs_create (fs_t *fs, const char *filename, int kbytes,
unsigned swap_kbytes)
{
int n;
@@ -336,9 +336,20 @@ int fs_create (fs_t *fs, const char *filename, unsigned kbytes,
fs->filename = filename;
fs->seek = 0;
fs->fd = open (fs->filename, O_CREAT | O_RDWR, 0666);
if (fs->fd < 0)
return 0;
if (kbytes < 0) {
fs->fd = open (fs->filename, O_RDWR);
if (fs->fd < 0)
return 0;
/* Get size and offset from partition table. */
if (! fs_set_partition (fs, -kbytes))
return 0;
kbytes = fs->part_nsectors / 2;
} else {
fs->fd = open (fs->filename, O_CREAT | O_RDWR, 0666);
if (fs->fd < 0)
return 0;
}
fs->writable = 1;
/* get total disk size
@@ -351,14 +362,14 @@ int fs_create (fs_t *fs, const char *filename, unsigned kbytes,
return 0;
/* make sure the file is of proper size */
offset = lseek (fs->fd, bytes-1, SEEK_SET);
if (offset != bytes-1)
offset = lseek (fs->fd, fs->part_offset + bytes-1, SEEK_SET);
if (offset != fs->part_offset + bytes-1)
return 0;
if (write (fs->fd, "", 1) != 1) {
perror ("write");
return 0;
}
lseek (fs->fd, 0, SEEK_SET);
lseek (fs->fd, fs->part_offset, SEEK_SET);
/* build a list of free blocks */
fs->swapsz = swap_kbytes * 1024 / BSDFS_BSIZE;

View File

@@ -1,7 +1,7 @@
/*
* File i/o routines for 2.xBSD filesystem.
*
* Copyright (C) 2006-2011 Serge Vakulenko, <serge@vak.ru>
* Copyright (C) 2006-2014 Serge Vakulenko, <serge@vak.ru>
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for any purpose and without fee is hereby

View File

@@ -1,7 +1,7 @@
/*
* Utility for dealing with 2.xBSD filesystem images.
*
* Copyright (C) 2006-2011 Serge Vakulenko, <serge@vak.ru>
* Copyright (C) 2006-2014 Serge Vakulenko, <serge@vak.ru>
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for any purpose and without fee is hereby
@@ -42,28 +42,32 @@ int check;
int fix;
int mount;
int scan;
int repartition;
unsigned kbytes;
unsigned swap_kbytes;
unsigned pindex;
static const char *program_version =
"BSD 2.x file system utility, version 1.1\n"
"BSD 2.x file system utility, version 1.2\n"
"Copyright (C) 2011-2014 Serge Vakulenko";
static const char *program_bug_address = "<serge@vak.ru>";
static struct option program_options[] = {
{ "help", no_argument, 0, 'h' },
{ "version", no_argument, 0, 'V' },
{ "verbose", no_argument, 0, 'v' },
{ "add", no_argument, 0, 'a' },
{ "extract", no_argument, 0, 'x' },
{ "check", no_argument, 0, 'c' },
{ "fix", no_argument, 0, 'f' },
{ "mount", no_argument, 0, 'm' },
{ "scan", no_argument, 0, 'S' },
{ "new", required_argument, 0, 'n' },
{ "swap", required_argument, 0, 's' },
{ "manifest", required_argument, 0, 'M' },
{ "help", no_argument, 0, 'h' },
{ "version", no_argument, 0, 'V' },
{ "verbose", no_argument, 0, 'v' },
{ "add", no_argument, 0, 'a' },
{ "extract", no_argument, 0, 'x' },
{ "check", no_argument, 0, 'c' },
{ "fix", no_argument, 0, 'f' },
{ "mount", no_argument, 0, 'm' },
{ "scan", no_argument, 0, 'S' },
{ "new", no_argument, 0, 'n' },
{ "size", required_argument, 0, 's' },
{ "manifest", required_argument, 0, 'M' },
{ "partition", required_argument, 0, 'p' },
{ "repartition", required_argument, 0, 'r' },
{ 0 }
};
@@ -78,12 +82,13 @@ static void print_help (char *progname)
"see the BSD 3-Clause License for more details.\n");
printf ("\n");
printf ("Usage:\n");
printf (" %s [--verbose] 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 --mount filesys.img dir\n", progname);
printf (" %s --add filesys.img files...\n", progname);
printf (" %s --extract filesys.img\n", progname);
printf (" %s [--verbose] [--partition=n] disk.img\n", progname);
printf (" %s --check [--fix] [--partition=n] disk.img\n", progname);
printf (" %s --new [--size=kbytes | --partition=n] [--manifest=file] disk.img [dir]\n", progname);
printf (" %s --mount [--partition=n] disk.img dir\n", progname);
printf (" %s --add [--partition=n] disk.img files...\n", progname);
printf (" %s --extract [--partition=n] disk.img\n", progname);
printf (" %s --repartition=format disk.img\n", progname);
printf (" %s --scan dir > file\n", progname);
printf ("\n");
printf ("Options:\n");
@@ -91,11 +96,16 @@ static void print_help (char *progname)
printf (" -f, --fix Fix bugs in filesystem.\n");
printf (" -n NUM, --new=NUM Create new filesystem, size in kbytes.\n");
printf (" Add files from specified directory (optional)\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 (" -s NUM, --size=NUM Size of filesystem in kbytes.\n");
printf (" -M file, --manifest=file\n");
printf (" List of files and attributes to create.\n");
printf (" -m, --mount Mount the filesystem.\n");
printf (" -a, --add Add files to filesystem.\n");
printf (" -x, --extract Extract all files.\n");
printf (" -r format, --repartition=format\n");
printf (" Install new partition table.\n");
printf (" -p NUM, --partition=NUM\n");
printf (" Select a partition.\n");
printf (" -S, --scan Create a manifest from directory contents.\n");
printf (" -v, --verbose Be verbose.\n");
printf (" -V, --version Print version information and then exit.\n");
@@ -578,6 +588,91 @@ void add_contents (fs_t *fs, const char *dirname, const char *manifest)
ndirs, nfiles, ndevs, nlinks, nsymlinks);
}
void create_partition_table (const char *filename, char *format)
{
unsigned char buf [512], *entry;
unsigned pindex, offset;
int fd, activated = 0;
/* Initialize an empty partition table. */
memset (buf, 0, sizeof(buf));
buf[510] = 0x55;
buf[511] = 0xaa;
/* Parse format string and fill partition entries. */
offset = 2;
char *p = strtok (format, ":");
for (pindex=1; p && pindex<=4; pindex++) {
char *q, *endptr;
unsigned type, len;
/* Split into type and length. */
q = strchr (p, '=');
if (! q) {
fprintf (stderr, "%s: wrong format '%s' for partition %u\n",
filename, p, pindex);
exit(-1);
}
*q++ = 0;
/* Get length in sectors. */
len = strtoul (q, &endptr, 0);
if (*endptr == 'k')
len *= 2;
else if (*endptr == 'm' || *endptr == 'M')
len *= 2*1024;
else if (*endptr != '\0') {
fprintf (stderr, "%s: wrong length '%s' for partition %u\n",
filename, q, pindex);
exit(-1);
}
/* Get type of partition. */
if (strcmp (p, "fs") == 0)
type = 0xb7;
else if (strcmp (p, "swap") == 0)
type = 0xb8;
else {
type = strtoul (p, &endptr, 16);
if (*endptr != '\0') {
fprintf (stderr, "%s: wrong type '%s' for partition %u\n",
filename, p, pindex);
exit(-1);
}
}
printf ("Allocated partition %u, type %02x, start %u, size %u sectors\n",
pindex, type, offset, len);
/* Fill partition entry. */
entry = &buf [446 + (pindex-1)*16];
entry [4] = type;
*(unsigned*) &entry [8] = offset;
*(unsigned*) &entry [12] = len;
/* Make first FS active. */
if (type == 0xb7 && ! activated) {
entry [0] = 0x80;
activated = 1;
}
p = strtok (NULL, ":");
offset += len;
}
/* Open or create the file. */
fd = open (filename, O_CREAT | O_RDWR, 0666);
if (fd < 0) {
fprintf (stderr, "%s: cannot create file\n", filename);
exit(-1);
}
/* Write the partition table to file. */
if (write (fd, buf, 512) != 512) {
fprintf (stderr, "%s: error writing partition table\n", filename);
exit(-1);
}
}
int main (int argc, char **argv)
{
int i, key;
@@ -585,9 +680,10 @@ int main (int argc, char **argv)
fs_inode_t inode;
manifest_t m;
const char *manifest = 0;
char *partition_format = 0;
for (;;) {
key = getopt_long (argc, argv, "vaxmSn:cfs:M:",
key = getopt_long (argc, argv, "vaxmSncfs:M:p:r:",
program_options, 0);
if (key == -1)
break;
@@ -603,7 +699,6 @@ int main (int argc, char **argv)
break;
case 'n':
++newfs;
kbytes = strtol (optarg, 0, 0);
break;
case 'c':
++check;
@@ -618,11 +713,22 @@ int main (int argc, char **argv)
++scan;
break;
case 's':
swap_kbytes = strtol (optarg, 0, 0);
kbytes = strtol (optarg, 0, 0);
break;
case 'M':
manifest = optarg;
break;
case 'p':
pindex = strtol (optarg, 0, 0);
if (pindex < 1 || pindex > 4) {
fprintf (stderr, "Incorrect partition index %u\n", pindex);
return -1;
}
break;
case 'r':
++repartition;
partition_format = optarg;
break;
case 'V':
printf ("%s\n", program_version);
return 0;
@@ -635,7 +741,7 @@ int main (int argc, char **argv)
}
}
i = optind;
if (extract + newfs + check + add + mount + scan > 1) {
if (extract + newfs + check + add + mount + scan + repartition > 1) {
print_help (argv[0]);
return -1;
}
@@ -646,17 +752,24 @@ int main (int argc, char **argv)
print_help (argv[0]);
return -1;
}
if (kbytes < BSDFS_BSIZE * 10 / 1024) {
if (! pindex && kbytes < BSDFS_BSIZE * 10 / 1024) {
/* Need at least 10 blocks. */
fprintf (stderr, "%s: too small\n", argv[i]);
if (! kbytes)
fprintf (stderr, "%s: size not specified\n", argv[i]);
else
fprintf (stderr, "%s: too small\n", argv[i]);
return -1;
}
if (! fs_create (&fs, argv[i], kbytes, swap_kbytes)) {
if (! fs_create (&fs, argv[i], pindex ? -pindex : kbytes, 0)) {
fprintf (stderr, "%s: cannot create filesystem\n", argv[i]);
return -1;
}
printf ("Created filesystem %s - %u kbytes\n", argv[i], kbytes);
if (pindex)
printf ("Created filesystem at partition %u of %s - %u kbytes\n",
pindex, argv[i], fs.part_nsectors/2);
else
printf ("Created filesystem %s - %u kbytes\n", argv[i], kbytes);
if (i == argc-2) {
/* Add the contents from the specified directory.
@@ -673,7 +786,7 @@ int main (int argc, char **argv)
print_help (argv[0]);
return -1;
}
if (! fs_open (&fs, argv[i], fix)) {
if (! fs_open (&fs, argv[i], fix, pindex)) {
fprintf (stderr, "%s: cannot open\n", argv[i]);
return -1;
}
@@ -696,12 +809,22 @@ int main (int argc, char **argv)
return 0;
}
if (repartition) {
/* Install a new partition table. */
if (i != argc-1) {
print_help (argv[0]);
return -1;
}
create_partition_table (argv[i], partition_format);
return 0;
}
/* Add or extract or info. */
if (i >= argc) {
print_help (argv[0]);
return -1;
}
if (! fs_open (&fs, argv[i], (add + mount != 0))) {
if (! fs_open (&fs, argv[i], (add + mount != 0), pindex)) {
fprintf (stderr, "%s: cannot open\n", argv[i]);
return -1;
}

View File

@@ -1,7 +1,7 @@
/*
* Inode routines for 2.xBSD filesystem.
*
* Copyright (C) 2006-2011 Serge Vakulenko, <serge@vak.ru>
* Copyright (C) 2006-2014 Serge Vakulenko, <serge@vak.ru>
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for any purpose and without fee is hereby

View File

@@ -131,11 +131,7 @@ static void add_entry (manifest_t *m, int filetype, char *path, char *link,
/*
* Compare two entries of file traverse scan.
*/
#ifdef __APPLE__
static int ftsent_compare (const FTSENT *const *a, const FTSENT *const *b)
#else
static int ftsent_compare (const FTSENT **a, const FTSENT **b)
#endif
{
return strcmp((*a)->fts_name, (*b)->fts_name);
}

View File

@@ -1,7 +1,7 @@
/*
* Superblock routines for 2.xBSD filesystem.
*
* Copyright (C) 2006-2011 Serge Vakulenko, <serge@vak.ru>
* Copyright (C) 2006-2014 Serge Vakulenko, <serge@vak.ru>
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for any purpose and without fee is hereby
@@ -33,7 +33,7 @@ extern int verbose;
int fs_seek (fs_t *fs, unsigned long offset)
{
/* printf ("seek %ld, block %ld\n", offset, offset / BSDFS_BSIZE);*/
if (lseek (fs->fd, offset, 0) < 0) {
if (lseek (fs->fd, fs->part_offset + offset, 0) < 0) {
if (verbose)
printf ("error seeking %ld, block %ld\n",
offset, offset / BSDFS_BSIZE);
@@ -145,7 +145,48 @@ int fs_write (fs_t *fs, unsigned char *data, int bytes)
return 1;
}
int fs_open (fs_t *fs, const char *filename, int writable)
int fs_set_partition (fs_t *fs, unsigned pindex)
{
unsigned char buf [512], *entry;
if (pindex > 4 || pindex < 1) {
fprintf (stderr, "%s: incorrect partition index=%u\n",
fs->filename, pindex);
return 0;
}
if (read (fs->fd, buf, 512) != 512) {
fprintf (stderr, "%s: cannot read partition table\n", fs->filename);
return 0;
}
if (buf[510] != 0x55 || buf[511] != 0xaa) {
fprintf (stderr, "%s: Warning: unexpected type of RetroBSD partition\n",
fs->filename);
}
/* Read partition entry. */
entry = &buf [446 + (pindex-1)*16];
fs->part_type = entry [4];
fs->part_offset = *(unsigned*) &entry [8];
fs->part_nsectors = *(unsigned*) &entry [12];
if (fs->part_type == 0) {
fprintf (stderr, "%s: Partition %u not allocated.\n",
fs->filename, pindex);
return 0;
}
if (fs->part_type != 0xb7) {
fprintf (stderr, "%s: Warning: unexpected type of RetroBSD partition\n",
fs->filename);
}
if (fs->part_offset & 1) {
fprintf (stderr, "%s: Incorrect partition offset=%u, must be even\n",
fs->filename, fs->part_offset);
return 0;
}
fs->part_offset *= 512;
//printf ("Partition %u, type %02x, offset=%uk, length=%uk\n", pindex, fs->part_type, fs->part_offset/1024, fs->part_nsectors/2);
return 1;
}
int fs_open (fs_t *fs, const char *filename, int writable, unsigned pindex)
{
int i;
unsigned magic;
@@ -159,6 +200,12 @@ int fs_open (fs_t *fs, const char *filename, int writable)
return 0;
fs->writable = writable;
if (pindex > 0) {
/* Get offset from partition table. */
if (! fs_set_partition (fs, pindex))
return 0;
}
if (! fs_read32 (fs, &magic) || /* magic word */
magic != FSMAGIC1) {
if (verbose)

View File

@@ -31,7 +31,7 @@ int main(int argc, char *argv[])
char buf[BUFSZ];
unsigned int tl;
unsigned char ok = 0;
int q __attribute__((unused));
int q __attribute__((unused));
char *output = NULL;
char *files[4] = {NULL,NULL,NULL,NULL};

View File

@@ -30,7 +30,7 @@ start_address = 0x9fc00000 # user program
#
sdcard_port = 1 # SPI1
sdcard0_size = 340 # Mbytes
sdcard0_file_name = ../../sdcard.rd
sdcard0_file_name = ../../sdcard.img
#
# UARTs 1..6

View File

@@ -23,7 +23,7 @@ start_address = 0x9d001000 # user program
#
sdcard_port = 4 # SPI4
sdcard0_size = 340 # Mbytes
sdcard0_file_name = ../../sdcard.rd
sdcard0_file_name = ../../sdcard.img
#
# UARTs 1..6

View File

@@ -23,7 +23,7 @@ start_address = 0x9d006000 # user program
#
sdcard_port = 4 # SPI4
sdcard0_size = 340 # Mbytes
sdcard0_file_name = ../../filesys.img
sdcard0_file_name = ../../sdcard.img
#
# UARTs 1..6

View File

@@ -23,7 +23,7 @@ start_address = 0x9d006000 # user program
#
sdcard_port = 1 # SPI1
sdcard0_size = 340 # Mbytes
sdcard0_file_name = ../../filesys.img
sdcard0_file_name = ../../sdcard.img
#sdcard1_size = 2 # Mbytes
#sdcard1_file_name = ../../home.img