// Create a directory int makeDir(int fd, char *dname, int uid, int gid, int attributes){ printf("Creating new directory %s\n",dname); int parINodeNo, inodeNo; struct INode parent_in; struct DirEntry d; //Tokenize the dname, check for validity and find its parent directory parINodeNo = currDirINode; readINode(fd, parINodeNo, &parent_in); // Check if the dname already exists in the INode in if( fileExists(fd, dname, parent_in, &d)!=-1 ){ printf("Directory already exists!\n\n"); return -1; } // Initialize an inode and data block for new directory struct INode in; in.i_atime = 0; bzero(in.i_blocks, 13); in.i_blocks[0] = allocBlock(fd); in.i_gen = 0; in.i_gid = gid; in.i_uid = uid; in.i_nlinks = 0; in.i_mode = attributes; bzero(d.d_entry.d_name, MAXNAMELENGTH); strcpy(d.d_entry.d_name, "."); int allocatedINode = allocINode(fd, &in); d.d_entry.d_inode = allocatedINode; d.d_offset = 0; allocDirEntry(fd, &in, &d); bzero(d.d_entry.d_name, MAXNAMELENGTH); strcpy(d.d_entry.d_name, ".."); d.d_entry.d_inode = parINodeNo; allocDirEntry(fd, &in, &d); writeInode(fd, allocatedINode, &in); // Add its DirEntry in its parent INode and rewrite Inode entry bzero(d.d_entry.d_name, MAXNAMELENGTH); strcpy(d.d_entry.d_name, dname); d.d_entry.d_inode = allocatedINode; allocDirEntry(fd, &parent_in, &d); writeInode(fd, parINodeNo, &parent_in); printf("\n"); return 0; }
int main(int argc, char *argv[]) { int i; int fd; int fd2; int ret; int curr; int *fat; int blocks; int diskSize; int fileCount; int fileArgs; char *imageFile; struct stat sbuf; int firstFreeBlock; bootSector bSector; directoryEntry *directory; int writeBoot = 0; if(argc <= 1) { printf ("usage: buildFat [-b <boot block> ] <diskImage> <files>\n"); exit(-1); } curr = 2; if(!strcmp(argv[1], "-b")) { /* it's a boot disk */ printf("writing boot block\n"); curr += 2; writeBoot = 1; } imageFile = argv[curr - 1]; printf("image file = %s\n", imageFile); ret = stat(imageFile, &sbuf); if(ret) { perror("stat"); exit(EXIT_FAILURE); } fileArgs = argc - curr; if(fileArgs == 0) { printf ("WARNING: file count is zero in disk image being built.\n"); } diskSize = sbuf.st_size; if(diskSize % SECTOR_SIZE != 0) { printf("image is not a multiple of 512 bytes\n"); exit(EXIT_FAILURE); } blocks = diskSize / SECTOR_SIZE; bSector.magic = PFAT_MAGIC; bSector.fileAllocationOffset = 1; bSector.fileAllocationLength = roundToNextBlock(blocks) / SECTOR_SIZE * 4; fat = (int *)calloc(blocks, sizeof(int)); bSector.rootDirectoryOffset = bSector.fileAllocationLength + 1; if(fileArgs == 0) { printf("WARNING: building an empty FAT filesystem\n"); } fd = open(imageFile, O_WRONLY, 0); if(fd < 0) { perror("image File open:"); exit(-1); } if(writeBoot) { /* copy boot block */ char buffer[SECTOR_SIZE]; fd2 = open(argv[2], O_RDONLY, 0); ret = read(fd2, buffer, SECTOR_SIZE); if(ret != SECTOR_SIZE) { printf("unable to read boot record\n"); } lseek(fd, 0, SEEK_SET); ret = write(fd, buffer, SECTOR_SIZE); if(ret != SECTOR_SIZE) { printf("unable to write boot record\n"); } close(fd2); } firstFreeBlock = bSector.rootDirectoryOffset + roundToNextBlock(sizeof(directoryEntry) * fileArgs) / SECTOR_SIZE; printf("first data blocks is %d\n", firstFreeBlock); directory = (directoryEntry *) malloc(sizeof(directoryEntry) * fileArgs); for(i = 0, fileCount = 0; i < fileArgs; i++) { int j; int numBlocks; directoryEntry *dir; if(!strcmp(argv[i + curr], "-d")) { // treat the next argument as a directory to create int writeSubDir = 0; i++; const char *dirname = argv[i + curr]; char *ptr; if((ptr = strchr(dirname, '/'))) { *ptr = '\0'; ptr++; // sub-directory, get the block writeSubDir = 1; dir = (directoryEntry *) malloc(512); strncpy(dir->fileName, ptr, sizeof(dir->fileName)); } else { dir = allocDirEntry(directory); fileCount++; strncpy(dir->fileName, dirname, sizeof(dir->fileName)); } dir->directory = 1; dir->fileSize = SECTOR_SIZE; dir->firstBlock = firstFreeBlock; fat[firstFreeBlock] = firstFreeBlock + 1; ++firstFreeBlock; fat[firstFreeBlock++] = FAT_ENTRY_EOF; if(writeSubDir) { // find the directory entry int j; for(j = 0; j < fileCount; j++) { if(!strcmp(directory[j].fileName, dirname)) { lseek(fd, directory[j].firstBlock * SECTOR_SIZE, SEEK_SET); write(fd, dir, 512); break; } } if(i == fileCount) abort(); writeSubDir = 0; } continue; } else { const char *filename = argv[i + curr]; dir = allocDirEntry(directory); dir->firstBlock = firstFreeBlock; ret = stat(filename, &sbuf); if(ret != 0) { printf("buildFat FATAL ERROR: Error stat()ing %s: %s\n", filename, strerror(errno)); exit(EXIT_FAILURE); } assert(ret == 0); numBlocks = roundToNextBlock(sbuf.st_size) / SECTOR_SIZE; dir->fileSize = sbuf.st_size; if(writeBoot) { if(i == 0) { /* setup.bin */ bSector.setupStart = firstFreeBlock; bSector.setupSize = numBlocks; printf("setup file starts at %d, %d sectors long\n", bSector.setupStart, bSector.setupSize); } else if(i == 1) { /* kernel.exe */ bSector.kernelStart = firstFreeBlock; bSector.kernelSize = numBlocks; printf("kernel file starts at %d, %d sectors long\n", bSector.kernelStart, bSector.kernelSize); } } for(j = 0; j < numBlocks - 1; j++) { fat[firstFreeBlock] = firstFreeBlock + 1; ++firstFreeBlock; if(firstFreeBlock > (diskSize / SECTOR_SIZE)) { printf("Error: %s is full\n", imageFile); exit(-1); } } fat[firstFreeBlock++] = FAT_ENTRY_EOF; lseek(fd, dir->firstBlock * SECTOR_SIZE, SEEK_SET); /* copy the file to the disk */ fd2 = open(filename, O_RDONLY, 0); assert(fd2 >= 0); /* failure is -1, not 0 -ns */ /* Remove leading directory path components */ if(strrchr(filename, '/') != 0) filename = strrchr(filename, '/') + 1; if(strlen(filename) > sizeof(dir->fileName)) { printf ("warning: file %s name too long, will be truncated!\n", filename); } /* Set filename in directory entry */ strncpy(dir->fileName, filename, sizeof(dir->fileName)); /* printf("file %s starts at block %d\n", dir->fileName, dir->firstBlock); */ lseek(fd, dir->firstBlock * SECTOR_SIZE, SEEK_SET); /* copy the file to the disk */ for(j = 0; j < numBlocks; j++) { int ret2; char buffer[SECTOR_SIZE]; ret = read(fd2, buffer, SECTOR_SIZE); assert(ret >= 0); ret2 = write(fd, buffer, ret); assert(ret2 == ret); } close(fd2); fileCount++; } } bSector.rootDirectoryCount = fileCount; lseek(fd, SECTOR_SIZE, SEEK_SET); ret = write(fd, fat, sizeof(int) * blocks); assert(ret == (int)(sizeof(int) * blocks)); lseek(fd, bSector.rootDirectoryOffset * SECTOR_SIZE, SEEK_SET); printf("putting the directory with %d files at sector %d\n", fileCount, bSector.rootDirectoryOffset); ret = write(fd, directory, sizeof(directoryEntry) * fileCount); assert(ret == (int)(sizeof(directoryEntry) * fileCount)); /* write out boot record */ lseek(fd, PFAT_BOOT_RECORD_OFFSET, SEEK_SET); ret = write(fd, &bSector, sizeof(bSector)); assert(ret == sizeof(bSector)); close(fd); exit(0); }
//============== UFS INTERFACE LAYER ========================== int init_FS(int fd){ // Boot block dummy block (Because no boot loader nothing...) bzero(nullbuf, BLOCKSIZE); write(fd, nullbuf, BLOCKSIZE); // Initialize variables int i; nsuperblocks = 1; ninodeblocks = 8; nbootblocks = 1; nrootdirblocks = 1; ndatablocks = TOTALBLOCKS - nsuperblocks - ninodeblocks - nbootblocks - nrootdirblocks; INODETABLESIZE = (ninodeblocks*BLOCKSIZE)/sizeof(struct INode); MAXDIRENTRIES = BLOCKSIZE/ sizeof(struct DirEntry); DATABLOCKSTART = BLOCKSIZE*(TOTALBLOCKS - ndatablocks); INODEBLOCKSTART = BLOCKSIZE*(nsuperblocks+nbootblocks); //Initialize super block strcpy(s.sb_vname, "root"); s.sb_ninodes = (ninodeblocks*BLOCKSIZE)/sizeof(struct INode); s.sb_nblocks = ndatablocks; s.sb_nfreeblocks = s.sb_nblocks; s.sb_nfreeinodes = s.sb_ninodes; s.sb_flags = 0; bzero(s.sb_freeblocks, CACHESIZE); bzero(s.sb_freeinodes, CACHESIZE); s.sb_freeblockindex = CACHESIZE; s.sb_freeinodeindex = CACHESIZE; s.sb_chktime = time(NULL); s.sb_ctime = time(NULL); write(fd, &s, sizeof(struct SuperBlock)); write(fd, nullbuf, (nsuperblocks*BLOCKSIZE) - sizeof(struct SuperBlock)); printf("Superblock initialized!\n"); // Write initialized list of inodes nullINode.i_size = 0; nullINode.i_atime = 0; nullINode.i_ctime = 0; nullINode.i_mtime = 0; bzero(nullINode.i_blocks, 13); nullINode.i_mode = 0; nullINode.i_uid = 0; nullINode.i_gid = 0; nullINode.i_gen = 0; nullINode.i_nlinks = 0; for(i=0; i<INODETABLESIZE; i++) write(fd, &nullINode, sizeof(struct INode)); write(fd, &nullbuf, BLOCKSIZE%sizeof(struct INode)); printf("Inodes initialized!\n"); // Write initialized list of directory entries // Fill the remaining empty datablocks printf("%d\n",ndatablocks+nrootdirblocks ); for(i=0; i<ndatablocks+nrootdirblocks; i++) write(fd, &nullbuf, BLOCKSIZE); printf("All data blocks initialized!\n"); // Write free block information (data structures) struct INode in; in.i_atime = 0; bzero(in.i_blocks, 13); in.i_blocks[0] = allocBlock(fd); in.i_gen = 0; in.i_gid = 1; in.i_uid = 1; in.i_nlinks = 0; in.i_mode = 0; struct DirEntry d; bzero(d.d_entry.d_name, MAXNAMELENGTH); strcpy(d.d_entry.d_name,"."); s.sb_rootdir = currDirINode = d.d_entry.d_inode = allocINode(fd, &in); d.d_offset = 0; allocDirEntry(fd, &in, &d); writeInode(fd, s.sb_rootdir, &in); updateSB(fd); printf("\n"); o.ofo_inode = NULL; o.ofo_mode = o.ofo_ref = 0; return 0; }