int sCreat(int pinum, int type, char *name) { int i,j; int newBlockPtr=-1; int newDirEnt=-1; int newF=1; //Check if valid pinum if(pinum<0 || pinum>=NUMINODES) return -1; //check name size if(strlen(name) < 1 || strlen(name) > 60) return -1; //Get the parent inode lseek(fdImage, BYOFF_INODE(pinum), SEEK_SET); inode_t pinode; read(fdImage, &pinode, sizeof(pinode)); //should be a directory if(pinode.type!=MFS_DIRECTORY) return -1; //scan all directory entries to check if name already exists, also save the first unassigned directory entry for later use dir_t dirBlock; for(i=0; i<14; i++) { if(pinode.blockPtrs[i]!=-1)//valid blockPtr { //printf("Parent inode:%d points to blockPtr[%d]:%d\n",pinum,i,pinode.blockPtrs[i]); //Go to that block lseek(fdImage, pinode.blockPtrs[i], SEEK_SET); read(fdImage, &dirBlock, sizeof(dir_t)); //Check all entries in the directory block for(j=0; j<NUM_DIR_ENTS; j++) { if(dirBlock.dirEnt[j].inum!=-1)//valid inode number { //printf("Valid directory entry number:%d name:%s and inode num:%d\n",j,dirBlock.dirEnt[j].name,dirBlock.dirEnt[j].inum); if( strcmp(dirBlock.dirEnt[j].name, name)==0 )//name match return 0;//file or directory name already exists so success } else//unused dirent { if(newF)//save the first unused dir entry to be overwritten later { //printf("Parent inode:%d points to blockPtr[%d]:%d\n",pinum,i,pinode.blockPtrs[i]); //printf("Within parent inode the first unused dir ent is %d\n",j); newBlockPtr=i; newDirEnt=j; newF=0; } } } } } //TODO //Corner case where no unused dirEntry was found. Meaning we have to assign a whole new data block of directory entries and update the pinode size //This could fail if all the data blocks of this directory are filled with valid data entries. No room for more //Find a free inode number int freeInode= getFreeInum(); if(freeInode<0)//no free inode was found then no more space for new files return -1; int d=-1; //if directory type then initialize it with . and .. directory ent if(type==MFS_DIRECTORY) { d = allocDataBlock(); if(d<0)//out of data blocks return -1; //printf("Dir Inode:%d with data block:%d\n",freeInode,d); } //Create the new inode allocInode(type, freeInode, d); if(type==MFS_DIRECTORY)//and initialize it if directory { assert(d!=-1); dirDataInit(freeInode, pinum, d); } //Write the name:inum directory entry //Go to the parent directory's data block lseek(fdImage, pinode.blockPtrs[newBlockPtr], SEEK_SET); read(fdImage, &dirBlock, sizeof(dir_t)); //Edit the unused directory entry inside it dirBlock.dirEnt[newDirEnt].inum=freeInode; sprintf(dirBlock.dirEnt[newDirEnt].name, name); //Write down the updated directory entry data block lseek(fdImage, pinode.blockPtrs[newBlockPtr], SEEK_SET); write(fdImage, &dirBlock, sizeof(dir_t)); //printf("New inode number:%d and name:%s and directory blockPtr:%d entry number:%d\n", freeInode, name, newBlockPtr, newDirEnt); fsync(fdImage); return 0; }
/* * Build the initial inodes. * inode 1 is always the root directory (identifiable by the fact that . == ..) * inode 2 (and possibly others) are files to hold the identifiable bad blocks. */ void buildInodes(void) { Inode = (struct wufs_inode *)calloc(SB->sb_inodes,sizeof(struct wufs_inode)); if (!Inode) { fprintf(stderr,"Could not allocated memory for the inodes.\n"); exit(1); } /* create root directory file: */ /* 1. allocate the inode */ int rootInode = allocInode(); /* allocate a directory */ struct wufs_inode *rino = &Inode[rootInode-1]; rino->in_mode = S_IFDIR + 0755; /* mark as directory */ /* 2. allocate space for the directory file */ int rootDir = allocBlock(); /* allocate directory store */ RootDir = (struct wufs_dirent *)calloc(WUFS_BLOCKSIZE,1); if (!RootDir) { fprintf(stderr,"Could not allocate memory to hold root directory image.\n"); exit(1); } rino->in_block[0] = rootDir; /* tell me something I don't know */ if (Verbose) { fprintf(stderr,"Root directory is at inode %d, using block %d.\n", rootInode, rootDir); } /* 3. populate the directory file: */ struct wufs_dirent *dp = RootDir; /* ... add "." directory */ dp->de_ino = rootInode; strcpy(dp->de_name,"."); rino->in_size += WUFS_DIRENTSIZE; rino->in_nlinks++; dp++; /* ... add ".." directory */ dp->de_ino = rootInode; strcpy(dp->de_name,".."); rino->in_size += WUFS_DIRENTSIZE; rino->in_nlinks++; dp++; /* We now collect all the bad blocks, bundled together into exactly one "file" */ /* keep count of remaining bad blocks to be bundled */ int bbc = BadBlocks; if (bbc) { int bblock = SB->sb_first_block; /* first possible bad block */ /* ... add bad block file to root dir */ char* fileName = ".badblockfilexactlythirtychars"; if (Verbose) { fprintf(stderr,"Placing the following bad blocks in /%s:\n", fileName); } /* * first, we check to see if we can add another bad block file without * extending the root directory to a second block. If so, we give up. * (Woof. This system is a dog.) */ if ((dp - RootDir) >= WUFS_DIRENTS_PER_BLOCK) { fprintf(stderr,"Too many bad blocks to store in root directory.\n"); exit(1); } if (bbc > SB->sb_max_fsize) { fprintf(stderr, "Too many bad blocks to write to a single file.\n"); exit(1); } /* allocate inode to hold some bad block pointers */ int bbinonum = allocInode(); struct wufs_inode *bbino = &Inode[bbinonum-1]; int n = 0; /* create indirect block if necessary */ if (bbc > WUFS_INODE_DIRECT) { indirect = calloc(1, sizeof(struct wufs_bptr)); } /* place several bad blocks into this file */ while (bbc && (n < WUFS_INODE_PTR_CT)) { bblock = findNextSet(BMap,bblock,SB->sb_blocks); /* sanity check: shouldn't run out of bad blocks before bbc hits zero */ if (bblock == -1) { fprintf(stderr,"Internal error: lost bad block while building root directory.\n"); exit(1); } /* take care: step over root directory block (only one allocated) */ if (bblock != rootDir) { if (Verbose) { fprintf(stderr," %d",bblock); fflush(stderr); } if (n < WUFS_INODE_DIRECT) { bbino->in_block[n] = bblock; } else { indirect->bp_block[n - WUFS_INODE_DIRECT] = bblock; } /* one more bad block, taken care of */ n++; bbino->in_size += WUFS_BLOCKSIZE; bbc--; } bblock++; } if (indirect) { indirect_addr = bbino->in_block[WUFS_INODE_BPTRS - 1] = allocBlock(); if (Verbose) fprintf(stderr, "\nrequired indirect block at address %d.", indirect_addr); } if (Verbose) { fprintf(stderr,"\n"); } /* add the file to the root directory */ dp->de_ino = bbinonum; strncpy(dp->de_name,fileName,WUFS_NAMELEN); rino->in_size += WUFS_DIRENTSIZE; bbino->in_nlinks++; dp++; } }
void initImage(char *imgName) { int i=0; fdImage=open(imgName, O_RDWR); //Image does not exist if(fdImage<0) { fdImage=open(imgName, O_RDWR | O_CREAT, S_IRWXU); //create new super block superblock_t superblock; superblock.size=4;// 5: 1.unused, 2.superblock, 3.inode-block, 4.bitmap-block, 5.1st data block superblock.nblocks=0;//1 data block to hold root directory entries superblock.ninodes=0;//only root inode //Get to start of superblock lseek(fdImage, BYOFF_SUPER, SEEK_SET); //write the super block write(fdImage, &superblock, sizeof(superblock_t)); super=superblock; //Create all the inodes and mark them as unused lseek(fdImage, BYOFF_INODE(0), SEEK_SET); inode_t inode; for(i=0; i<14; i++) inode.blockPtrs[i]=-1;//data block pointers unassigned inode.type=MFS_UNUSED;//unused inode inode.size=0;//No data blocks for the inode for (i=0; i<NUMINODES; i++) { lseek(fdImage, BYOFF_INODE(i), SEEK_SET); write(fdImage, &inode, sizeof(inode_t)); } //Set the datablock bitmap to all zeros char zeroBuffer[MFS_BLOCK_SIZE]; memset(zeroBuffer,0, sizeof(zeroBuffer)); lseek(fdImage,BYOFF_BIT(0),SEEK_SET); write(fdImage, &zeroBuffer, sizeof(zeroBuffer)); //Allocate and write the root inode allocInode(MFS_DIRECTORY, ROOTINO, 0); //Find a free data block and set it marked to used in the data bitmap int freeBlock=allocDataBlock(); //First root directory data block dirDataInit(ROOTINO, ROOTINO, freeBlock);//initialize with . and .. //int //int freeInode=getFreeInum(); //allocInode(MFS_DIRECTORY, freeInode, ); //Test by another inode //printf("Test BYOFF_BLOCK(0):%d BYOFF_BLOCK(1):%d BYOFF_BLOCK(2):%d\n",BYOFF_BLOCK(0), BYOFF_BLOCK(1), BYOFF_BLOCK(2)); fsync(fdImage); } else { //Do nothing for now //Get to start of superblock lseek(fdImage, BYOFF_SUPER, SEEK_SET); //read the super block read(fdImage, &super, sizeof(superblock_t)); } }