mirror of
https://github.com/DoctorWkt/unix-jun72.git
synced 2026-01-13 15:27:49 +00:00
We can now create directories recursively. Not tested fully yet, but
seems to work.
This commit is contained in:
parent
143fa275d3
commit
0a1bda9a62
487
tools/mkfs.c
487
tools/mkfs.c
@ -1,18 +1,14 @@
|
||||
/*
|
||||
* Program to create a 1st Edition UNIX filesystem.
|
||||
* (c) 2008 Warren Toomey, GPL3.
|
||||
*
|
||||
*
|
||||
* Other contributors, add your name above.
|
||||
*
|
||||
* TODO: add large file functionality
|
||||
* ensure that swap is not used on RF disk images.
|
||||
* deal with errors instead of exiting :-)
|
||||
*
|
||||
* in the long run, have the ability to read from/write to
|
||||
* existing images, a la an ftp client.
|
||||
*
|
||||
* $Revision: 1.22 $
|
||||
* $Date: 2008/05/17 02:30:05 $
|
||||
*
|
||||
* TODO: deal with errors instead of exiting :-)
|
||||
* in the long run, have the ability to read from/write to existing
|
||||
* images, a la an ftp client.
|
||||
*
|
||||
* $Revision: 1.24 $ $Date: 2008/05/17 07:36:00 $
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
@ -26,7 +22,6 @@
|
||||
|
||||
#define BLKSIZE 512 /* 512 bytes per block */
|
||||
#define RF_SIZE 1024 /* Number of blocks on RF11 */
|
||||
#define RF_NOSAWPSIZE 944 /* RF11 blocks excluding swap */
|
||||
#define RF_INODES 512 /* Cold UNIX sets 512 i-nodes on RF */
|
||||
#define RK_SIZE 4864 /* Number of blocks on RK03, should be 4872 */
|
||||
#define INODE_RATIO 4 /* Disksize to i-node ratio */
|
||||
@ -34,11 +29,13 @@
|
||||
#define NUMDIRECTBLKS 8 /* Only 8 direct blocks in an i-node */
|
||||
#define BLKSPERINDIRECT 256 /* 256 block pointers in an indirect block */
|
||||
|
||||
/* V1 UNIX reserves 64 blocks on the end of RF11 for kernel images, then
|
||||
/*
|
||||
* V1 UNIX reserves 64 blocks on the end of RF11 for kernel images, then
|
||||
* SWPSIZ blocks per process for swap areas.
|
||||
*/
|
||||
#define KERNBLKS 64 /* Hard coded in V1 kernel source */
|
||||
#define SWPSIZ 33 /* Was hard-coded to 17, now 33 for C compiler */
|
||||
#define SWPSIZ 33 /* Was hard-coded to 17, now 33 for C
|
||||
compiler */
|
||||
#define NPROC 16 /* Hard coded in V1 kernel source */
|
||||
#define RF_NOSWAPSIZE (RF_SIZE - KERNBLKS - (SWPSIZ*NPROC))
|
||||
|
||||
@ -93,12 +90,12 @@ struct fileperm { /* We read an external file to determine */
|
||||
uint16_t flags; /* apply to the files which we add to the */
|
||||
uint8_t uid; /* filesystem. */
|
||||
uint32_t mtime;
|
||||
} permlist[PERMLISTSIZE];
|
||||
} permlist[PERMLISTSIZE];
|
||||
|
||||
|
||||
unsigned char buf[BLKSIZE]; /* A block buffer */
|
||||
uint16_t disksize; /* Number of blocks on disk */
|
||||
uint16_t icount=0; /* Number of i-nodes created */
|
||||
uint16_t icount = 0; /* Number of i-nodes created */
|
||||
uint16_t nextfreeblock; /* The next free block available */
|
||||
uint8_t *freemap; /* In-memory free-map */
|
||||
uint8_t *inodemap; /* In-memory inode bitmap */
|
||||
@ -107,14 +104,15 @@ struct v1inode *inodelist; /* In-memory i-node list */
|
||||
struct directory *rootdir; /* The root directory */
|
||||
|
||||
FILE *diskfh; /* Disk filehandle */
|
||||
int debug=0; /* Enable debugging output */
|
||||
int debug = 0; /* Enable debugging output */
|
||||
int makedevflag = 0; /* Do we make the /dev directory? */
|
||||
|
||||
|
||||
/* Write the superblock out to the image */
|
||||
void write_superblock(void)
|
||||
{
|
||||
uint16_t freemapsize= disksize / 8;
|
||||
uint16_t inodemapmapsize= icount / 8;
|
||||
uint16_t freemapsize = disksize / 8;
|
||||
uint16_t inodemapmapsize = icount / 8;
|
||||
|
||||
if (debug) printf("Writing freemap and inodemap from block 0\n");
|
||||
fseek(diskfh, 0, SEEK_SET);
|
||||
@ -123,21 +121,20 @@ void write_superblock(void)
|
||||
fwrite(&inodemapmapsize, sizeof(inodemapmapsize), 1, diskfh);
|
||||
fwrite(inodemap, sizeof(uint8_t), ((icount - ROOTDIR_INUM) / 8), diskfh);
|
||||
if (debug) {
|
||||
long posn= ftell(diskfh);
|
||||
long block= posn/BLKSIZE;
|
||||
long off= posn/BLKSIZE;
|
||||
long posn = ftell(diskfh);
|
||||
long block = posn / BLKSIZE;
|
||||
long off = posn / BLKSIZE;
|
||||
printf("ending up at posn %ld, block %ld, offset %ld\n", posn, block, off);
|
||||
printf("Writing inodelist from block 2\n");
|
||||
}
|
||||
fseek(diskfh, 2 * BLKSIZE, SEEK_SET);
|
||||
if (debug)
|
||||
printf("Writing %d inodes, each size %d, total %d\n",
|
||||
icount, sizeof(struct v1inode), icount * sizeof(struct v1inode));
|
||||
fwrite(&inodelist[1], sizeof(struct v1inode), icount-1, diskfh);
|
||||
if (debug) printf("Writing %d inodes, each size %d, total %d\n",
|
||||
icount, sizeof(struct v1inode), icount * sizeof(struct v1inode));
|
||||
fwrite(&inodelist[1], sizeof(struct v1inode), icount - 1, diskfh);
|
||||
if (debug) {
|
||||
long posn= ftell(diskfh);
|
||||
long block= posn/BLKSIZE;
|
||||
long off= posn/BLKSIZE;
|
||||
long posn = ftell(diskfh);
|
||||
long block = posn / BLKSIZE;
|
||||
long off = posn / BLKSIZE;
|
||||
printf("ending up at posn %ld, block %ld, offset %ld\n", posn, block, off);
|
||||
}
|
||||
}
|
||||
@ -151,6 +148,7 @@ void block_inuse(int n)
|
||||
if (n >= disksize) {
|
||||
printf("Cannot mark block %d >= disk size %d\n", n, disksize); exit(1);
|
||||
}
|
||||
|
||||
offset = n / 8;
|
||||
bitmask = bitmap[n % 8];
|
||||
freemap[offset] &= bitmask;
|
||||
@ -165,6 +163,7 @@ void inode_inuse(int n)
|
||||
if (n >= icount) {
|
||||
printf("Cannot mark inode %d >= icount %d\n", n, icount); exit(1);
|
||||
}
|
||||
|
||||
inodelist[n].flags |= I_ALLOCATED;
|
||||
offset = (n - ROOTDIR_INUM) / 8;
|
||||
bitmask = bitmap[(n - ROOTDIR_INUM) % 8];
|
||||
@ -175,18 +174,20 @@ void inode_inuse(int n)
|
||||
int alloc_inode(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 42; i < icount; i++) {
|
||||
if (inodelist[i].flags == 0) {
|
||||
inode_inuse(i);
|
||||
return (i);
|
||||
inode_inuse(i); return (i);
|
||||
}
|
||||
}
|
||||
printf("Cannot allocate a new i-node\n"); exit(1);
|
||||
|
||||
printf("Cannot allocate a new i-node\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate N contiguous blocks. Returns the first block number,
|
||||
* or dies if this is impossible.
|
||||
* Allocate N contiguous blocks. Returns the first block number, or dies if
|
||||
* this is impossible.
|
||||
*/
|
||||
uint16_t alloc_blocks(int n)
|
||||
{
|
||||
@ -195,73 +196,81 @@ uint16_t alloc_blocks(int n)
|
||||
if (nextfreeblock + n >= disksize) {
|
||||
printf("Unable to allocate %d more blocks\n", n); exit(1);
|
||||
}
|
||||
for (i = nextfreeblock; i < n + nextfreeblock; i++)
|
||||
block_inuse(i);
|
||||
|
||||
for (i = nextfreeblock; i < n + nextfreeblock; i++) block_inuse(i);
|
||||
nextfreeblock += n;
|
||||
return (firstblock);
|
||||
}
|
||||
|
||||
/* Allocate N contiguous blocks, and write a single indirect block
|
||||
* with those block numbers in it. Return the indirect block number;
|
||||
* the contiguous blocks come directly after the indirect block.
|
||||
/*
|
||||
* Allocate N contiguous blocks, and write a single indirect block with those
|
||||
* block numbers in it. Return the indirect block number; the contiguous
|
||||
* blocks come directly after the indirect block.
|
||||
*/
|
||||
int alloc_indirect_blocks(int n)
|
||||
{
|
||||
uint16_t blkptr[BLKSPERINDIRECT]; /* Blk pointers in the indirect blk */
|
||||
uint16_t indirect_blknum; /* Number of the indirect block */
|
||||
uint16_t i,b;
|
||||
uint16_t indirect_blknum; /* Number of the indirect block */
|
||||
uint16_t i, b;
|
||||
|
||||
if ( n > BLKSPERINDIRECT) {
|
||||
if (n > BLKSPERINDIRECT) {
|
||||
printf("Unable to allocate more than %d blocks in indirect\n", n); exit(1);
|
||||
}
|
||||
|
||||
/* Obtain N+1 blocks, the first will be the indirect block */
|
||||
indirect_blknum= alloc_blocks(n+1);
|
||||
indirect_blknum = alloc_blocks(n + 1);
|
||||
if (debug)
|
||||
printf("Allocated %d blocks, indirect is block %d\n", n+1, indirect_blknum);
|
||||
printf("Allocated %d blocks, indirect is block %d\n",
|
||||
n + 1, indirect_blknum);
|
||||
|
||||
/* Fill the indirect block with the block numbers */
|
||||
memset(blkptr, 0, BLKSIZE);
|
||||
for (i=0,b=indirect_blknum+1; i< n; i++, b++)
|
||||
blkptr[i]= b;
|
||||
for (i = 0, b = indirect_blknum + 1; i < n; i++, b++) blkptr[i] = b;
|
||||
|
||||
/* Write the indirect bock out to the image */
|
||||
fseek(diskfh, indirect_blknum * BLKSIZE, SEEK_SET);
|
||||
fwrite(blkptr, BLKSIZE, 1, diskfh);
|
||||
if (debug)
|
||||
printf("Wrote indirect block at %d\n", indirect_blknum);
|
||||
if (debug) printf("Wrote indirect block at %d\n", indirect_blknum);
|
||||
|
||||
/* Return the indirect block number */
|
||||
return(indirect_blknum);
|
||||
return (indirect_blknum);
|
||||
}
|
||||
|
||||
/* Add a filename and i-number to the given directory */
|
||||
void add_direntry(struct directory *d, uint16_t inum, char *name)
|
||||
{
|
||||
if (d == NULL) {
|
||||
printf("I need a struct directory * please\n"); exit(1);
|
||||
printf("I need a struct directory * please\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Removed for /dev/creation */
|
||||
if (inum < ROOTDIR_INUM) {
|
||||
printf("Illegal inum %d in add_direntry\n", inum); exit(1);
|
||||
printf("Illegal inum %d in add_direntry\n", inum);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (name && strlen(name) > 8) {
|
||||
printf("Name %s too long\n", name); exit(1);
|
||||
printf("Name %s too long\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Find an entry in the directory which is empty */
|
||||
if (d->nextfree >= d->numentries) {
|
||||
printf("Unable to add directory entry\n"); exit(1);
|
||||
printf("Unable to add directory entry\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
d->entry[d->nextfree].inode = inum;
|
||||
strncpy(d->entry[d->nextfree].name, name, 8);
|
||||
d->nextfree++;
|
||||
}
|
||||
|
||||
/* Search for an return a struct fileperm pointer, given a directory
|
||||
* and filename. If no match is found, NULL is returned.
|
||||
/*
|
||||
* Search for an return a struct fileperm pointer, given a directory and
|
||||
* filename. If no match is found, NULL is returned.
|
||||
*/
|
||||
struct fileperm *search_fileperm(char *dir, char *file)
|
||||
{
|
||||
@ -271,24 +280,26 @@ struct fileperm *search_fileperm(char *dir, char *file)
|
||||
snprintf(name, BLKSIZE, "%s/%s", dir, file);
|
||||
if (debug) printf("Searching permlist for %s\n", name);
|
||||
|
||||
for (i=0; permlist[i].name; i++) {
|
||||
for (i = 0; permlist[i].name; i++) {
|
||||
if (!strcmp(permlist[i].name, name)) {
|
||||
if (debug) printf("Found permlist entry for %s\n", name);
|
||||
return(&permlist[i]);
|
||||
return (&permlist[i]);
|
||||
}
|
||||
}
|
||||
return(NULL);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a directory with the given name. Allocate an i-node for it, and a
|
||||
* set of blocks. Attach it to /. Return the struct allocated. If name is
|
||||
* "/", we are making the root directory itself.
|
||||
* set of blocks. Attach it to the parent directory. Return the struct
|
||||
* allocated. If name is "/", we are making the root directory itself.
|
||||
*/
|
||||
struct directory *create_dir(char *name, int numblocks)
|
||||
struct directory *create_dir(char *name, int numblocks,
|
||||
struct directory *parent)
|
||||
{
|
||||
struct directory *d;
|
||||
uint16_t inum, blk;
|
||||
uint16_t inum, parent_inum, blk;
|
||||
int i;
|
||||
|
||||
if (numblocks > 8) {
|
||||
@ -299,38 +310,46 @@ struct directory *create_dir(char *name, int numblocks)
|
||||
printf("Name %s too long\n", name); exit(1);
|
||||
}
|
||||
|
||||
d = (struct directory *)calloc(1, sizeof(struct directory));
|
||||
d->numentries= numblocks * DIRENTPERBLOCK;
|
||||
d->nextfree= 0;
|
||||
d->entry= (struct v1dirent *)calloc(d->numentries, sizeof(struct v1dirent));
|
||||
/* Cold UNIX only uses 1 block for root directory */
|
||||
if (!strcmp(name, "/")) numblocks = 1;
|
||||
|
||||
d = (struct directory *)calloc(1, sizeof(struct directory));
|
||||
d->numentries = numblocks * DIRENTPERBLOCK;
|
||||
d->nextfree = 0;
|
||||
d->entry = (struct v1dirent *)calloc(d->numentries, sizeof(struct v1dirent));
|
||||
|
||||
/* If the root directory, use the special i-number for it */
|
||||
/* Otherwise, allocate an i-node and some blocks for the directory */
|
||||
if (!strcmp(name, "/")) {
|
||||
inum = ROOTDIR_INUM;
|
||||
rootdir = parent = d; /* So later, root's .. points to itself */
|
||||
} else
|
||||
inum = alloc_inode();
|
||||
|
||||
/* Allocate an i-node and some blocks for the directory */
|
||||
if (strcmp(name, "/")) inum = alloc_inode();
|
||||
else inum = ROOTDIR_INUM;
|
||||
d->block = alloc_blocks(numblocks);
|
||||
d->inum= inum;
|
||||
d->inum = inum;
|
||||
if (debug) printf("In create_dir, got back inum %d blk %d, %d config blks\n",
|
||||
inum, d->block, numblocks);
|
||||
inum, d->block, numblocks);
|
||||
|
||||
/* Mark the i-node as a directory */
|
||||
inodelist[inum].flags |= I_DIR | I_UREAD | I_UWRITE | I_OREAD;
|
||||
inodelist[inum].nlinks= 2; /* Size is determined at write-time */
|
||||
for (i=0, blk=d->block; i < numblocks; i++, blk++)
|
||||
inodelist[inum].block[i]= blk;
|
||||
inodelist[inum].nlinks = 2; /* Size is determined at write-time */
|
||||
for (i = 0, blk = d->block; i < numblocks; i++, blk++)
|
||||
inodelist[inum].block[i] = blk;
|
||||
|
||||
/* If the directory is not /, attach it to rootdir */
|
||||
/* Attach this directory to its parent, but not if root */
|
||||
parent_inum = parent->inum;
|
||||
if (strcmp(name, "/")) {
|
||||
add_direntry(rootdir, inum, name);
|
||||
/* Update rootdir's nlinks in its inode */
|
||||
inodelist[ROOTDIR_INUM].nlinks++;
|
||||
add_direntry(parent, inum, name);
|
||||
/* Update the parent's nlinks */
|
||||
inodelist[parent_inum].nlinks++;
|
||||
}
|
||||
|
||||
/* and add entries for . and .. */
|
||||
add_direntry(d, ROOTDIR_INUM, "..");
|
||||
/* Add entries for . and .. */
|
||||
add_direntry(d, parent_inum, "..");
|
||||
add_direntry(d, inum, ".");
|
||||
|
||||
if (debug)
|
||||
printf("Created dir for %s, inum %d\n", name, inum);
|
||||
if (debug) printf("Created dir for %s, inum %d\n", name, inum);
|
||||
return (d);
|
||||
}
|
||||
|
||||
@ -343,16 +362,65 @@ void write_dir(struct directory *d, char *name)
|
||||
|
||||
if (debug)
|
||||
printf("Writing dir %s, size %d, %d blks from block %d (offset 0x%x) on\n",
|
||||
name, d->numentries * sizeof(struct v1dirent),
|
||||
d->numentries / DIRENTPERBLOCK, d->block,
|
||||
d->block * BLKSIZE);
|
||||
name, d->numentries * sizeof(struct v1dirent),
|
||||
d->numentries / DIRENTPERBLOCK, d->block,
|
||||
d->block * BLKSIZE);
|
||||
|
||||
/* Directory size is the # of bytes of the in-use directory entries */
|
||||
inodelist[d->inum].size= d->nextfree * sizeof(struct v1dirent);
|
||||
inodelist[d->inum].size = d->nextfree * sizeof(struct v1dirent);
|
||||
fseek(diskfh, d->block * BLKSIZE, SEEK_SET);
|
||||
fwrite(d->entry, d->numentries * sizeof(struct v1dirent), 1, diskfh);
|
||||
}
|
||||
|
||||
/*
|
||||
* Following the cold UNIX rf output, make /dev. In /dev, make devices with
|
||||
* specific i-nums, which I guess act like early major/minor device numbers.
|
||||
*/
|
||||
void add_devdir(void)
|
||||
{
|
||||
struct dev {
|
||||
char *name;
|
||||
uint16_t inum;
|
||||
} devlist[] = {
|
||||
{ "tty", 1 },
|
||||
{ "ppt", 2 },
|
||||
{ "mem", 3 },
|
||||
{ "rf0", 4 },
|
||||
{ "rk0", 5 },
|
||||
{ "tap0", 6 },
|
||||
{ "tap1", 7 },
|
||||
{ "tap2", 8 },
|
||||
{ "tap3", 9 },
|
||||
{ "tap4", 10 },
|
||||
{ "tap5", 11 },
|
||||
{ "tap6", 12 },
|
||||
{ "tap7", 13 },
|
||||
{ "tty0", 14 },
|
||||
{ "tty1", 15 },
|
||||
{ "tty2", 16 },
|
||||
{ "tty3", 17 },
|
||||
{ "tty4", 18 },
|
||||
{ "tty5", 19 },
|
||||
{ "tty6", 20 },
|
||||
{ "tty7", 21 },
|
||||
{ "lpr", 22 },
|
||||
{ "tty8", 1 },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
struct directory *d;
|
||||
int i;
|
||||
|
||||
d = create_dir("dev", 1, rootdir); /* Cold UNIX only uses 1 block */
|
||||
|
||||
for (i = 0; devlist[i].name != NULL; i++) {
|
||||
add_direntry(d, devlist[i].inum, devlist[i].name);
|
||||
}
|
||||
|
||||
/* And write the directory out */
|
||||
write_dir(d, "dev");
|
||||
}
|
||||
|
||||
/* Create a file in a given directory. Returns the first block number. */
|
||||
/* Does not actually copy the file's bits onto the image. */
|
||||
/* At present we cannot deal with very large files, i.e. > 1 indirect block */
|
||||
@ -360,15 +428,17 @@ int create_file(struct directory *d, char *name, int size, struct fileperm *p)
|
||||
{
|
||||
uint16_t inum;
|
||||
uint16_t firstblock;
|
||||
uint32_t epoch=0;
|
||||
uint32_t epoch = 0;
|
||||
int i, blk, numblocks;
|
||||
|
||||
if (d == NULL) {
|
||||
printf("I need a struct directory * please\n"); exit(1);
|
||||
}
|
||||
|
||||
if (name == NULL) {
|
||||
printf("I need a filename please\n"); exit(1);
|
||||
}
|
||||
|
||||
if (size > BLKSPERINDIRECT * BLKSIZE) {
|
||||
printf("File %s is a very large file, skipping", name); return (0);
|
||||
}
|
||||
@ -406,19 +476,18 @@ int create_file(struct directory *d, char *name, int size, struct fileperm *p)
|
||||
memcpy(inodelist[inum].mtime, &epoch, sizeof(uint32_t));
|
||||
memcpy(inodelist[inum].ctime, &epoch, sizeof(uint32_t));
|
||||
inodelist[inum].flags |= I_MODFILE | I_EXEC | I_UREAD | I_UWRITE |
|
||||
I_OREAD | I_OWRITE;
|
||||
I_OREAD | I_OWRITE;
|
||||
}
|
||||
|
||||
/* Add the i-node and filename to the directory */
|
||||
add_direntry(d, inum, name);
|
||||
if (debug)
|
||||
printf("Created file %s size %d inum %d\n", name, size, inum);
|
||||
if (debug) printf("Created file %s size %d inum %d\n", name, size, inum);
|
||||
return (firstblock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open up the file given by the fullname, and copy
|
||||
* size bytes into the image starting at firstblock.
|
||||
* Open up the file given by the fullname, and copy size bytes into the image
|
||||
* starting at firstblock.
|
||||
*/
|
||||
void copy_file(char *fullname, int firstblock, int size)
|
||||
{
|
||||
@ -427,7 +496,7 @@ void copy_file(char *fullname, int firstblock, int size)
|
||||
|
||||
if (debug)
|
||||
printf("Copying %s size %d to block %d (offset 0x%x) on\n",
|
||||
fullname, size, firstblock, firstblock * BLKSIZE);
|
||||
fullname, size, firstblock, firstblock * BLKSIZE);
|
||||
if ((zin = fopen(fullname, "r")) == NULL) {
|
||||
printf("Unable to read %s to copy onto image\n", fullname); exit(1);
|
||||
}
|
||||
@ -436,14 +505,15 @@ void copy_file(char *fullname, int firstblock, int size)
|
||||
while ((cnt = fread(buf, 1, BLKSIZE, zin)) > 0)
|
||||
fwrite(buf, 1, cnt, diskfh);
|
||||
|
||||
fclose(zin); fflush(diskfh);
|
||||
fclose(zin);
|
||||
fflush(diskfh);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a directory /dir on the image. Add all the
|
||||
* files in basedir/dir into /dir on the image.
|
||||
* Make a directory /dir on the image. Add all the files in basedir/dir into
|
||||
* /dir on the image.
|
||||
*/
|
||||
void add_files(char *basedir, char *dir)
|
||||
void add_files(char *basedir, char *dir, struct directory *parent)
|
||||
{
|
||||
struct directory *d;
|
||||
DIR *D;
|
||||
@ -452,18 +522,24 @@ void add_files(char *basedir, char *dir)
|
||||
char fullname[BLKSIZE];
|
||||
uint16_t firstblock;
|
||||
struct fileperm *perms;
|
||||
char *noslashdir = dir;
|
||||
|
||||
/* If dir is /, trim it for later snprintfs */
|
||||
if (!strcmp(dir, "/")) noslashdir = "";
|
||||
|
||||
/* Get the full external directory name */
|
||||
snprintf(fullname, BLKSIZE, "%s/%s", basedir, dir);
|
||||
snprintf(fullname, BLKSIZE, "%s/%s", basedir, noslashdir);
|
||||
|
||||
/* Open the external directory */
|
||||
D = opendir(fullname);
|
||||
if (D == NULL) {
|
||||
printf("Cannot opendir %s\n", fullname); exit(1);
|
||||
}
|
||||
if (D == NULL) { printf("Cannot opendir %s\n", fullname); exit(1); }
|
||||
|
||||
/* Create the image directory */
|
||||
d = create_dir(dir, DIRBLOCKS);
|
||||
d = create_dir(dir, DIRBLOCKS, parent);
|
||||
|
||||
/* Now create the /dev directory by hand */
|
||||
if (makedevflag && !strcmp(dir, "/"))
|
||||
add_devdir();
|
||||
|
||||
/* Walk the directory */
|
||||
while ((dp = readdir(D)) != NULL) {
|
||||
@ -471,11 +547,20 @@ void add_files(char *basedir, char *dir)
|
||||
if (!strcmp(dp->d_name, "..")) continue;
|
||||
|
||||
/* Stat the entry found */
|
||||
snprintf(fullname, BLKSIZE, "%s/%s/%s", basedir, dir, dp->d_name);
|
||||
snprintf(fullname, BLKSIZE, "%s/%s/%s", basedir, noslashdir, dp->d_name);
|
||||
if (stat(fullname, &sb) < 0) {
|
||||
printf("Cannot stat %s\n", fullname); continue;
|
||||
}
|
||||
|
||||
/* If it is a directory, recursively add it */
|
||||
if (S_ISDIR(sb.st_mode)) {
|
||||
char bdir[BLKSIZE];
|
||||
snprintf(bdir, BLKSIZE, "%s/%s", basedir, noslashdir);
|
||||
if (debug) printf("Recursing into %s/%s\n", bdir, dp->d_name);
|
||||
add_files(bdir, dp->d_name, d);
|
||||
if (debug) printf("Back from into %s/%s\n", bdir, dp->d_name);
|
||||
}
|
||||
|
||||
/* Skip if it is not a regular file */
|
||||
if (!S_ISREG(sb.st_mode)) continue;
|
||||
|
||||
@ -490,7 +575,7 @@ void add_files(char *basedir, char *dir)
|
||||
}
|
||||
|
||||
/* Search for any known permissions for this file */
|
||||
perms= search_fileperm(dir, dp->d_name);
|
||||
perms = search_fileperm(dir, dp->d_name);
|
||||
|
||||
/* Create the file's i-node */
|
||||
/* and copy the file into the image */
|
||||
@ -503,140 +588,47 @@ void add_files(char *basedir, char *dir)
|
||||
write_dir(d, dir);
|
||||
}
|
||||
|
||||
/* Following the cold UNIX rf output, make /dev. In /dev,
|
||||
* make devices with specific i-nums, which I guess act like
|
||||
* early major/minor device numbers.
|
||||
*/
|
||||
void add_devdir(void)
|
||||
{
|
||||
struct dev {
|
||||
char *name;
|
||||
uint16_t inum;
|
||||
} devlist[] = {
|
||||
{ "tty", 1 },
|
||||
{ "ppt", 2 },
|
||||
{ "mem", 3 },
|
||||
{ "rf0", 4 },
|
||||
{ "rk0", 5 },
|
||||
{ "tap0", 6 },
|
||||
{ "tap1", 7 },
|
||||
{ "tap2", 8 },
|
||||
{ "tap3", 9 },
|
||||
{ "tap4", 10 },
|
||||
{ "tap5", 11 },
|
||||
{ "tap6", 12 },
|
||||
{ "tap7", 13 },
|
||||
{ "tty0", 14 },
|
||||
{ "tty1", 15 },
|
||||
{ "tty2", 16 },
|
||||
{ "tty3", 17 },
|
||||
{ "tty4", 18 },
|
||||
{ "tty5", 19 },
|
||||
{ "tty6", 20 },
|
||||
{ "tty7", 21 },
|
||||
{ "lpr", 22 },
|
||||
{ "tty8", 1 },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
struct directory *d;
|
||||
int i;
|
||||
|
||||
d = create_dir("dev", 1); /* cold UNIX only uses 1 block */
|
||||
|
||||
for (i=0; devlist[i].name !=NULL; i++) {
|
||||
add_direntry(d, devlist[i].inum, devlist[i].name);
|
||||
}
|
||||
|
||||
/* And write the directory out */
|
||||
write_dir(d, "dev");
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a top-level directory, find all of the subdirectories,
|
||||
* and add them and their files into the image.
|
||||
*/
|
||||
void process_topdir(char *topdir)
|
||||
{
|
||||
DIR *D;
|
||||
struct dirent *dp;
|
||||
struct stat sb;
|
||||
char fullname[BLKSIZE];
|
||||
|
||||
/* Open the top directory */
|
||||
D = opendir(topdir);
|
||||
if (D == NULL) {
|
||||
printf("Cannot opendir %s\n", topdir); exit(1);
|
||||
}
|
||||
|
||||
/* Walk the directory */
|
||||
while ((dp = readdir(D)) != NULL) {
|
||||
if (!strcmp(dp->d_name, ".")) continue; /* Skip . and .. */
|
||||
if (!strcmp(dp->d_name, "..")) continue;
|
||||
|
||||
/* Stat the entry found */
|
||||
snprintf(fullname, BLKSIZE, "%s/%s", topdir, dp->d_name);
|
||||
if (stat(fullname, &sb) < 0) {
|
||||
printf("Cannot stat %s\n", fullname); continue;
|
||||
}
|
||||
|
||||
/* Skip if it is not a directory */
|
||||
if (!S_ISDIR(sb.st_mode)) continue;
|
||||
|
||||
/* Skip if the name is too long */
|
||||
if (strlen(dp->d_name) > 8) {
|
||||
printf("Skipping long dirname %s for now\n", fullname); continue;
|
||||
}
|
||||
|
||||
/* Now process that directory and its files */
|
||||
add_files(topdir, dp->d_name);
|
||||
}
|
||||
closedir(D);
|
||||
}
|
||||
|
||||
/* Open and parse the file to obtain a list of V1 file owner/perm/dates.
|
||||
* The file has a very specific format. Lines before '======' are ignored.
|
||||
* After that, each line represents one file, and has pcre line format:
|
||||
*
|
||||
*
|
||||
* ^[-xu][-r][-w][-r][-w] +\d+.*\/\S+ *\d+
|
||||
*
|
||||
* First 5 chars represent x=executable, u=setuid, r=read, w=write.
|
||||
* Spaces separate the permissions and the decimal userid.
|
||||
* Then we look for a / which begins the full pathname.
|
||||
* Spaces seperate the full pathname and the timestamp which is in 1/60th
|
||||
* of a second since the beginning of the year.
|
||||
* Open and parse the file to obtain a list of V1 file owner/perm/dates. The
|
||||
* file has a very specific format. Lines before '======' are ignored. After
|
||||
* that, each line represents one file, and has pcre line format:
|
||||
*
|
||||
*
|
||||
* ^[-xu][-r][-w][-r][-w] +\d+.*\/\S+ *\d+
|
||||
*
|
||||
* First 5 chars represent x=executable, u=setuid, r=read, w=write. Spaces
|
||||
* separate the permissions and the decimal userid. Then we look for a /
|
||||
* which begins the full pathname. Spaces seperate the full pathname and the
|
||||
* timestamp which is in 1/60th of a second since the beginning of the year.
|
||||
*/
|
||||
void read_permsfile(char *file)
|
||||
{
|
||||
FILE *zin;
|
||||
char linebuf[BLKSIZE];
|
||||
char *cptr, *sptr;
|
||||
int posn=0;
|
||||
int posn = 0;
|
||||
|
||||
if (file==NULL) return;
|
||||
if ((zin= fopen(file, "r"))==NULL) return;
|
||||
if (file == NULL) return;
|
||||
if ((zin = fopen(file, "r")) == NULL) return;
|
||||
|
||||
/* Find line beginning with = */
|
||||
while (1) {
|
||||
if (fgets(linebuf, BLKSIZE-1, zin)==NULL) {
|
||||
if (fgets(linebuf, BLKSIZE - 1, zin) == NULL) {
|
||||
fclose(zin); return;
|
||||
}
|
||||
if (linebuf[0]== '=') break;
|
||||
if (linebuf[0] == '=') break;
|
||||
}
|
||||
|
||||
/* Now read and parse each line */
|
||||
while (1) {
|
||||
if ((posn >= PERMLISTSIZE) || (fgets(linebuf, BLKSIZE-1, zin)==NULL)) {
|
||||
if ((posn >= PERMLISTSIZE) || (fgets(linebuf, BLKSIZE - 1, zin) == NULL)) {
|
||||
fclose(zin); return;
|
||||
}
|
||||
|
||||
/* Skip if junk permissions */
|
||||
if (linebuf[0] != '-' && linebuf[0] != 'x' && linebuf[0] != 'u')
|
||||
continue;
|
||||
if (linebuf[0] != '-' && linebuf[0] != 'x' && linebuf[0] != 'u') continue;
|
||||
|
||||
/* Get the permissions */
|
||||
permlist[posn].flags=0;
|
||||
permlist[posn].flags = 0;
|
||||
if (linebuf[0] == 'x') permlist[posn].flags |= I_EXEC;
|
||||
if (linebuf[0] == 'u') permlist[posn].flags |= I_SETUID | I_EXEC;
|
||||
if (linebuf[1] == 'r') permlist[posn].flags |= I_UREAD;
|
||||
@ -645,30 +637,31 @@ void read_permsfile(char *file)
|
||||
if (linebuf[4] == 'w') permlist[posn].flags |= I_OWRITE;
|
||||
|
||||
/* Get the userid */
|
||||
permlist[posn].uid= strtol(&linebuf[5], NULL , 10);
|
||||
|
||||
permlist[posn].uid = strtol(&linebuf[5], NULL, 10);
|
||||
|
||||
/* Search for the full pathname, skip line if not found */
|
||||
if ((cptr= strchr(linebuf, '/'))==NULL) continue;
|
||||
if ((cptr = strchr(linebuf, '/')) == NULL) continue;
|
||||
|
||||
/* Find the space after the full name, skip if not found */
|
||||
/* Null-terminate the filename */
|
||||
if ((sptr= strchr(cptr, ' '))==NULL) continue;
|
||||
*(sptr++)= '\0';
|
||||
if ((sptr = strchr(cptr, ' ')) == NULL) continue;
|
||||
*(sptr++) = '\0';
|
||||
|
||||
/* Copy the pathname minus the leading slash */
|
||||
/* However, if it starts with "/usr/", skip "/usr/" */
|
||||
if (!strncmp(cptr, "/usr/", 5))
|
||||
cptr+= 5;
|
||||
cptr += 5;
|
||||
else
|
||||
cptr++;
|
||||
permlist[posn].name= strdup(cptr);
|
||||
|
||||
permlist[posn].name = strdup(cptr);
|
||||
|
||||
/* Finally get the timestamp */
|
||||
permlist[posn].mtime= strtol(sptr, NULL , 10);
|
||||
permlist[posn].mtime = strtol(sptr, NULL, 10);
|
||||
|
||||
if (debug) {
|
||||
printf("0%2o %2d %10d %s\n", permlist[posn].flags, permlist[posn].uid,
|
||||
permlist[posn].mtime, permlist[posn].name);
|
||||
permlist[posn].mtime, permlist[posn].name);
|
||||
}
|
||||
posn++;
|
||||
}
|
||||
@ -688,16 +681,17 @@ void usage(void)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int makedevflag=0; /* Do we make the /dev directory? */
|
||||
int i,ch;
|
||||
int i, ch;
|
||||
int numiblocks;
|
||||
int fs_size; /* Equal to disksize minus any swap */
|
||||
int fs_size; /* Equal to disksize minus any swap */
|
||||
|
||||
/* Get any optional arguments */
|
||||
while ((ch = getopt(argc, argv, "dp:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'd': debug=1; break;
|
||||
case 'p': read_permsfile(optarg); break;
|
||||
case 'd':
|
||||
debug = 1; break;
|
||||
case 'p':
|
||||
read_permsfile(optarg); break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -717,7 +711,7 @@ int main(int argc, char *argv[])
|
||||
} else {
|
||||
disksize = RF_SIZE;
|
||||
fs_size = RF_NOSWAPSIZE;
|
||||
makedevflag=1;
|
||||
makedevflag = 1;
|
||||
}
|
||||
|
||||
/* Create the image */
|
||||
@ -727,43 +721,43 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* Make the image full-sized */
|
||||
for (i = 0; i < fs_size; i++)
|
||||
for (i = 0; i < disksize; i++)
|
||||
fwrite(buf, BLKSIZE, 1, diskfh);
|
||||
|
||||
/* Create the free-map: fortunately RK_SIZE and RF_SIZE are divisible by 8 */
|
||||
/* Make all the blocks free to start with */
|
||||
freemap = (uint8_t *)malloc(disksize / 8);
|
||||
freemap = (uint8_t *) malloc(disksize / 8);
|
||||
for (i = 0; i < disksize / 8; i++)
|
||||
freemap[i] = 0xff;
|
||||
|
||||
/* Mark blocks 0 and 1 as in-use */
|
||||
block_inuse(0); block_inuse(1);
|
||||
block_inuse(0);
|
||||
block_inuse(1);
|
||||
|
||||
/* Choose disksize/INODE_RATIO as the number of i-nodes to allocate */
|
||||
/* if we haven't already given icount a value. */
|
||||
/* Make sure that it is divisible by 8 */
|
||||
if (icount==0)
|
||||
if (icount == 0)
|
||||
icount = 8 * (disksize / INODE_RATIO / 8);
|
||||
|
||||
/* Create the inode bitmap and inode list */
|
||||
inodemap = (uint8_t *)calloc(1, (icount - ROOTDIR_INUM) / 8);
|
||||
inodemap = (uint8_t *) calloc(1, (icount - ROOTDIR_INUM) / 8);
|
||||
inodelist = (struct v1inode *)calloc(icount, sizeof(struct v1inode));
|
||||
|
||||
/* Mark special i-nodes 0 to ROOTDIR_INUM-1 as allocated */
|
||||
/* We follow the output of cold UNIX here. */
|
||||
for (i = 0; i < ROOTDIR_INUM; i++) {
|
||||
inodelist[i].flags |= I_ALLOCATED|I_UREAD|I_UWRITE|I_OREAD|I_OWRITE;
|
||||
inodelist[i].nlinks= 1;
|
||||
inodelist[i].uid= 1;
|
||||
inodelist[i].mtime[3]= 0x38;
|
||||
inodelist[i].flags |= I_ALLOCATED | I_UREAD | I_UWRITE | I_OREAD | I_OWRITE;
|
||||
inodelist[i].nlinks = 1;
|
||||
inodelist[i].uid = 1;
|
||||
inodelist[i].mtime[3] = 0x38;
|
||||
}
|
||||
|
||||
/* INODEPERBLOCK i-nodes fit into a block, so work out how many blocks the */
|
||||
/* inodelist occupies. Round up to ensure a partial block => full block */
|
||||
/* Mark the blocks from 2 up as being in-use */
|
||||
numiblocks = (icount + INODEPERBLOCK -1) / INODEPERBLOCK;
|
||||
if (debug)
|
||||
printf("%d i-nodes, %d i-node blocks\n", icount, numiblocks);
|
||||
numiblocks = (icount + INODEPERBLOCK - 1) / INODEPERBLOCK;
|
||||
if (debug) printf("%d i-nodes, %d i-node blocks\n", icount, numiblocks);
|
||||
nextfreeblock = 2 + numiblocks;
|
||||
for (i = 2; i < nextfreeblock; i++)
|
||||
block_inuse(i);
|
||||
@ -772,14 +766,9 @@ int main(int argc, char *argv[])
|
||||
/* Mark the root directory i-node (ROOTDIR_INUM) as in-use */
|
||||
/* Create the root directory */
|
||||
inode_inuse(ROOTDIR_INUM);
|
||||
rootdir = create_dir("/", 1); /* cold UNIX only uses 1 block */
|
||||
|
||||
/* Now create the /dev directory by hand */
|
||||
if (makedevflag)
|
||||
add_devdir();
|
||||
|
||||
/* Walk the top directory argument, dealing with the subdirs */
|
||||
process_topdir(argv[0]);
|
||||
add_files(argv[0], "/", rootdir);
|
||||
|
||||
/* Write out the root directory */
|
||||
write_dir(rootdir, "/");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user