mirror of
https://github.com/DoctorWkt/unix-jun72.git
synced 2026-04-05 05:23:12 +00:00
Added debug argument. Added code to parse a file with V1 permissions.
I can't work out why ls -l isn't showing the timestamp yet.
This commit is contained in:
178
tools/mkfs.c
178
tools/mkfs.c
@@ -11,12 +11,10 @@
|
||||
* in the long run, have the ability to read from/write to
|
||||
* existing images, a la an ftp client.
|
||||
*
|
||||
* $Revision: 1.19 $
|
||||
* $Date: 2008/05/05 00:08:01 $
|
||||
* $Revision: 1.20 $
|
||||
* $Date: 2008/05/06 08:56:17 $
|
||||
*/
|
||||
|
||||
int debug=1;
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
@@ -81,6 +79,15 @@ struct directory { /* Internal structure for each dir */
|
||||
struct v1dirent *entry;
|
||||
};
|
||||
|
||||
#define PERMLISTSIZE 500
|
||||
struct fileperm { /* We read an external file to determine */
|
||||
char *name; /* a list of struct fileperms which we can */
|
||||
uint16_t flags; /* apply to the files which we add to the */
|
||||
uint8_t uid; /* filesystem. */
|
||||
uint32_t mtime;
|
||||
} 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 */
|
||||
@@ -92,6 +99,8 @@ struct v1inode *inodelist; /* In-memory i-node list */
|
||||
struct directory *rootdir; /* The root directory */
|
||||
|
||||
FILE *diskfh; /* Disk filehandle */
|
||||
int debug=0; /* Enable debugging output */
|
||||
|
||||
|
||||
/* Write the superblock out to the image */
|
||||
void write_superblock(void)
|
||||
@@ -243,6 +252,26 @@ void add_direntry(struct directory *d, uint16_t inum, char *name)
|
||||
d->nextfree++;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
int i;
|
||||
char name[BLKSIZE];
|
||||
|
||||
snprintf(name, BLKSIZE, "%s/%s", dir, file);
|
||||
if (debug) printf("Searching permlist for %s\n", name);
|
||||
|
||||
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(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
|
||||
@@ -319,10 +348,11 @@ void write_dir(struct directory *d, char *name)
|
||||
/* 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 */
|
||||
int create_file(struct directory *d, char *name, int size)
|
||||
int create_file(struct directory *d, char *name, int size, struct fileperm *p)
|
||||
{
|
||||
uint16_t inum;
|
||||
uint16_t firstblock;
|
||||
uint32_t epoch=0;
|
||||
int i, blk, numblocks;
|
||||
|
||||
if (d == NULL) {
|
||||
@@ -353,11 +383,24 @@ int create_file(struct directory *d, char *name, int size)
|
||||
}
|
||||
|
||||
/* Make the i-node reflect the file */
|
||||
inodelist[inum].flags |= I_EXEC | I_UREAD | I_UWRITE | I_OREAD | I_OWRITE;
|
||||
inodelist[inum].nlinks = 1;
|
||||
inodelist[inum].uid = 0;
|
||||
inodelist[inum].size = size;
|
||||
|
||||
/* If we have existing permissions, use them. Otherwise, just */
|
||||
/* make some default permissions and set uid to 0 */
|
||||
if (p) {
|
||||
inodelist[inum].uid = p->uid;
|
||||
memcpy(inodelist[inum].mtime, &p->mtime, sizeof(uint32_t));
|
||||
memcpy(inodelist[inum].ctime, &p->mtime, sizeof(uint32_t));
|
||||
inodelist[inum].flags |= I_MODFILE | p->flags;
|
||||
} else {
|
||||
inodelist[inum].uid = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
/* Add the i-node and filename to the directory */
|
||||
add_direntry(d, inum, name);
|
||||
if (debug)
|
||||
@@ -400,6 +443,7 @@ void add_files(char *basedir, char *dir)
|
||||
struct stat sb;
|
||||
char fullname[BLKSIZE];
|
||||
uint16_t firstblock;
|
||||
struct fileperm *perms;
|
||||
|
||||
/* Get the full external directory name */
|
||||
snprintf(fullname, BLKSIZE, "%s/%s", basedir, dir);
|
||||
@@ -437,9 +481,12 @@ void add_files(char *basedir, char *dir)
|
||||
printf("Skipping long filename %s for now\n", fullname); continue;
|
||||
}
|
||||
|
||||
/* Search for any known permissions for this file */
|
||||
perms= search_fileperm(dir, dp->d_name);
|
||||
|
||||
/* Create the file's i-node */
|
||||
/* and copy the file into the image */
|
||||
firstblock = create_file(d, dp->d_name, sb.st_size);
|
||||
firstblock = create_file(d, dp->d_name, sb.st_size, perms);
|
||||
copy_file(fullname, firstblock, sb.st_size);
|
||||
}
|
||||
closedir(D);
|
||||
@@ -539,29 +586,122 @@ void process_topdir(char *topdir)
|
||||
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.
|
||||
*/
|
||||
void read_permsfile(char *file)
|
||||
{
|
||||
FILE *zin;
|
||||
char linebuf[BLKSIZE];
|
||||
char *cptr, *sptr;
|
||||
int posn=0;
|
||||
|
||||
if (file==NULL) return;
|
||||
if ((zin= fopen(file, "r"))==NULL) return;
|
||||
|
||||
/* Find line beginning with = */
|
||||
while (1) {
|
||||
if (fgets(linebuf, BLKSIZE-1, zin)==NULL) {
|
||||
fclose(zin); return;
|
||||
}
|
||||
if (linebuf[0]== '=') break;
|
||||
}
|
||||
|
||||
/* Now read and parse each line */
|
||||
while (1) {
|
||||
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;
|
||||
|
||||
/* Get the permissions */
|
||||
permlist[posn].flags=0;
|
||||
if (linebuf[0] == 'x') permlist[posn].flags |= I_EXEC;
|
||||
if (linebuf[0] == 'u') permlist[posn].flags |= I_SETUID;
|
||||
if (linebuf[1] == 'r') permlist[posn].flags |= I_UREAD;
|
||||
if (linebuf[2] == 'w') permlist[posn].flags |= I_UWRITE;
|
||||
if (linebuf[3] == 'r') permlist[posn].flags |= I_OREAD;
|
||||
if (linebuf[4] == 'w') permlist[posn].flags |= I_OWRITE;
|
||||
|
||||
/* Get the userid */
|
||||
permlist[posn].uid= strtol(&linebuf[5], NULL , 10);
|
||||
|
||||
/* Search for the full pathname, skip line if not found */
|
||||
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';
|
||||
|
||||
/* Copy the pathname minus the leading slash */
|
||||
/* However, if it starts with "/usr/", skip "/usr/" */
|
||||
if (!strncmp(cptr, "/usr/", 5))
|
||||
cptr+= 5;
|
||||
else
|
||||
cptr++;
|
||||
permlist[posn].name= strdup(cptr);
|
||||
|
||||
/* Finally get the timestamp */
|
||||
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);
|
||||
}
|
||||
posn++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
printf("Usage: mkfs topdir image rk/rf\n");
|
||||
printf("Usage: mkfs [-d] [-p permsfile] topdir image rk/rf\n");
|
||||
printf("\ttopdir is an existing dir which holds bin/, etc/, tmp/ ...\n");
|
||||
printf("\timage will be the image created\n");
|
||||
printf("\tlast argument is either 'rk' or 'rf'\n");
|
||||
printf("\t-d enables debugging output\n");
|
||||
printf("\t-p reads the named file to obtain a list of V1 file permissions\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int makedevflag=0; /* Do we make the /dev directory? */
|
||||
int i;
|
||||
int i,ch;
|
||||
int numiblocks;
|
||||
int fs_size; /* Equal to disksize - 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;
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/* Get the image name and the type of disk */
|
||||
if (argc != 4) usage();
|
||||
if (strcmp(argv[3], "rk") && strcmp(argv[3], "rf")) usage();
|
||||
if (argc != 3) usage();
|
||||
if (strcmp(argv[2], "rk") && strcmp(argv[2], "rf")) usage();
|
||||
|
||||
/* Set the disk size */
|
||||
if (argv[3][1] == 'k') { /* RK device */
|
||||
if (argv[2][1] == 'k') { /* RK device */
|
||||
/* XXX: I can't seem to go past 4864 to 4872 blocks, and I haven't */
|
||||
/* worked out why yet. */
|
||||
disksize = RK_SIZE;
|
||||
@@ -573,9 +713,9 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* Create the image */
|
||||
diskfh = fopen(argv[2], "w+");
|
||||
diskfh = fopen(argv[1], "w+");
|
||||
if (diskfh == NULL) {
|
||||
printf("Unable to create image %s\n", argv[2]); exit(1);
|
||||
printf("Unable to create image %s\n", argv[1]); exit(1);
|
||||
}
|
||||
|
||||
/* Make the image full-sized */
|
||||
@@ -584,7 +724,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* Create the free-map: fortunately RK_SIZE and RF_SIZE are divisible by 8 */
|
||||
/* Make all the blocks free to start with */
|
||||
freemap = (char *)malloc(disksize / 8);
|
||||
freemap = (uint8_t *)malloc(disksize / 8);
|
||||
for (i = 0; i < disksize / 8; i++)
|
||||
freemap[i] = 0xff;
|
||||
|
||||
@@ -598,7 +738,7 @@ int main(int argc, char *argv[])
|
||||
icount = 8 * (disksize / INODE_RATIO / 8);
|
||||
|
||||
/* Create the inode bitmap and inode list */
|
||||
inodemap = (char *)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 */
|
||||
@@ -631,7 +771,7 @@ int main(int argc, char *argv[])
|
||||
add_devdir();
|
||||
|
||||
/* Walk the top directory argument, dealing with the subdirs */
|
||||
process_topdir(argv[1]);
|
||||
process_topdir(argv[0]);
|
||||
|
||||
/* Write out the root directory */
|
||||
write_dir(rootdir, "/");
|
||||
|
||||
Reference in New Issue
Block a user