/* * Lookup the specified name (name) in the directory (dirinumber). If found, return the * directory entry in dirEnt. Return 0 on success and something negative on failure. */ int directory_findname(struct unixfilesystem *fs, const char *name, int dirinumber, struct direntv6 *dirEnt) { struct inode ino; if(inode_iget(fs, dirinumber, &ino) == -1) return -1; if((ino.i_mode & IFMT) != IFDIR) return -1; //traverse the inodes datablocks forloop //compare the given file with directory entries int size = inode_getsize(&ino); int numBlocks = (size + DISKIMG_SECTOR_SIZE - 1) / DISKIMG_SECTOR_SIZE; for(int block = 0; block < numBlocks; block++) { struct direntv6 buffer[DISKIMG_SECTOR_SIZE / sizeof(struct direntv6)]; //an array of direntv6s int validBytes = file_getblock(fs, dirinumber, block, &buffer); if(validBytes < 0) return -1; int dirsPerBlock = validBytes / sizeof(struct direntv6); //calculate the number of dirsPerBlock based on validBytes of block for(int dir = 0; dir < dirsPerBlock; dir++) { if(strcmp(name, buffer[dir].d_name) == 0) { //copy memory into the direntv6 only if name is found in block memcpy(dirEnt, &buffer[dir], sizeof(struct direntv6)); return 0; } } } return -1; }
/* * Fetch as many entries from a directory that will fit in the specified array. Return the * number of entries found. */ int GetDirEntries(struct unixfilesystem *fs, int inumber, struct direntv6 *entries, int maxNumEntries) { struct inode in; int err = inode_iget(fs, inumber, &in); if (err < 0) { fprintf(stderr, "GetDirEntries using inode_iget err\n"); return err; } if (!(in.i_mode & IALLOC) || ((in.i_mode & IFMT) != IFDIR)) { /* Not allocated or not a directory */ fprintf(stderr, "GetDirEntries inode is not dir or not allocated %d %d\n",in.i_mode & IALLOC, (in.i_mode & IFMT) == IFDIR); return -1; } if (maxNumEntries < 1) { fprintf(stderr, "maxNumEntries = %d\n",maxNumEntries); return -1; } int size = inode_getsize(&in); assert((size % sizeof(struct direntv6)) == 0); int count = 0; /* block number in the directory */ int numBlocks = (size + DISKIMG_SECTOR_SIZE - 1) / DISKIMG_SECTOR_SIZE; /* buf to get bytes from diskimg */ char buf[DISKIMG_SECTOR_SIZE]; struct direntv6 *dir = (struct direntv6 *) buf; // use direntv6 handle int bno; for (bno = 0; bno < numBlocks; bno++) { int bytesLeft, numEntriesInBlock, i; bytesLeft = file_getblock(fs, inumber, bno, dir); if (bytesLeft < 0) { fprintf(stderr, "Error reading directory\n"); return -1; } numEntriesInBlock = bytesLeft / sizeof(struct direntv6); for (i = 0; i < numEntriesInBlock ; i++) { entries[count] = dir[i]; count++; if (count >= maxNumEntries) return count; } } return count; }
/* * Lookup the specified name (name) in the directory (dirinumber). If found, return the * directory entry in dirEnt. Return 0 on success and something negative on failure. */ int directory_findname(struct unixfilesystem *fs, const char *name, int dirinumber, struct direntv6 *dirEnt) { //return -1; //fprintf(stderr, "directory_lookupname(name=%s dirinumber=%d)\n", name, dirinumber); struct inode in; int err = inode_iget(fs, dirinumber, &in); if (err < 0) { fprintf(stderr, "director_findname get inode error"); return -1; } if (!(in.i_mode & IALLOC) || ((in.i_mode & IFMT) != IFDIR)) { fprintf(stderr, "director_findname dir inode is not IFDIR"); return -1; } int size = inode_getsize(&in); assert((size % sizeof(struct direntv6)) == 0); /* block number in the directory */ int numBlocks = (size + DISKIMG_SECTOR_SIZE - 1) / DISKIMG_SECTOR_SIZE; /* buf to get bytes from diskimg */ char buf[DISKIMG_SECTOR_SIZE]; struct direntv6 *dir = (struct direntv6 *) buf; // use direntv6 handle int bno; for (bno = 0; bno < numBlocks; bno++) { int bytesLeft, numEntriesInBlock, i; bytesLeft = file_getblock(fs, dirinumber, bno, dir); if (bytesLeft < 0) { fprintf(stderr, "Error reading directory\n"); return -1; } numEntriesInBlock = bytesLeft / sizeof(struct direntv6); for (i = 0; i < numEntriesInBlock ; i++) { //printf("list = %s\n", dir[i].d_name); if (strcmp(dir[i].d_name, name) == 0) { *dirEnt = dir[i]; return 0; } } } //printf("Dir %d find name not find %s\n",dirinumber, name); return -1; }
/* * Lookup the specified name (name) in the directory (dirinumber). If found, return the * directory entry in dirEnt. Return 0 on success and something negative on failure. */ int directory_findname(struct unixfilesystem *fs, const char *name, int dirinumber, struct direntv6 *dirEnt) { // First fetch the inode corresponding to dirinumber struct inode in; int err = inode_iget(fs, dirinumber, &in); if (err < 0) return err; // Get the number of blocks int size = inode_getsize(&in); printf("size: %d\n", size); int numBlocks = (size + DISKIMG_SECTOR_SIZE - 1) / DISKIMG_SECTOR_SIZE; // Next access the block that has the directory entries int numdirent = DISKIMG_SECTOR_SIZE / sizeof(struct direntv6); struct direntv6 dir[numdirent]; // Cached for the strncp function int targetlen = strlen(name); // Loop through the blocks for (int bno = 0; bno < numBlocks; bno++) { // Get the number of bytes we want to consider int bytes = file_getblock(fs, dirinumber, bno, dir); // Loop through the directory entries for (int i = 0; i < numdirent; i++) { // Use strncmp to see if we have a match on the character name if (strncmp(dir[i].d_name, name, targetlen) == 0) { // Found it! Set values of dirEnt and return success strncpy(dirEnt->d_name, dir[i].d_name, targetlen); dirEnt->d_inumber = dir[i].d_inumber; return 0; } } } return -1; }
/* * Fetch the next character from the file. Return -1 if at end of file. */ int Fileops_getchar(int fd,int inumber, int size) { int inumber; struct inode in; unsigned char buf[DISKIMG_SECTOR_SIZE]; int bytesMoved; int err, size; int blockNo, blockOffset; numgetchars++; if (openFileTable[fd].pathname == NULL) return -1; // fd not opened. inumber = pathname_lookup(unixfs, openFileTable[fd].pathname); if (inumber < 0) { return inumber; // Can't find file } err = inode_iget(unixfs, inumber,&in); if (err < 0) { return err; } if (!(in.i_mode & IALLOC)) { return -1; } size = inode_getsize(&in); if (openFileTable[fd].cursor >= size) return -1; // Finished with file blockNo = openFileTable[fd].cursor / DISKIMG_SECTOR_SIZE; blockOffset = openFileTable[fd].cursor % DISKIMG_SECTOR_SIZE; bytesMoved = file_getblock(unixfs, inumber,blockNo,buf); if (bytesMoved < 0) { return -1; } assert(bytesMoved > blockOffset); openFileTable[fd].cursor += 1; return (int)(buf[blockOffset]); }
/* * Compute the checksum of a inumber. Assumes chksum arguments points to a * CHKSUMFILE_SIZE byte array. Returns the length of the checksum, or -1 if * it encounters an error. */ int chksumfile_byinumber(struct unixfilesystem *fs, int inumber, void *chksum) { SHA_CTX shactx; if (!SHA1_Init(&shactx)) { // An error occurred initializing the SHA1 context. return -1; } struct inode in; int err = inode_iget(fs, inumber, &in); if (err < 0) { return err; } if (!(in.i_mode & IALLOC)) { // The inode isn't allocated, so we can't hash it. return -1; } int size = inode_getsize(&in); for (int offset = 0; offset < size; offset += DISKIMG_SECTOR_SIZE) { char buf[DISKIMG_SECTOR_SIZE]; int bno = offset/DISKIMG_SECTOR_SIZE; int bytesMoved = file_getblock(fs, inumber, bno, buf); if (bytesMoved < 0) return -1; if (!SHA1_Update(&shactx, buf, bytesMoved)) return -1; } if (!SHA1_Final(chksum, &shactx)) return -1; return SHA_DIGEST_LENGTH; }
/* * Lookup the specified name (name) in the directory (dirinumber). If found, return the * directory entry in dirEnt. Return 0 on success and something negative on failure. */ int directory_findname(struct unixfilesystem *fs, const char *name, int dirinumber, struct direntv6 *dirEnt) { struct inode directory; if (inode_iget(fs, dirinumber, &directory)) return -1; int mode = directory.i_mode; //Checks that directory is indeed a directory. if ((mode & IFMT) != IFDIR) return -1; int dirSize = inode_getsize(&directory); int dirBlocks = dirSize / DISKIMG_SECTOR_SIZE; int check = 0; for (int i=0; i <= dirBlocks; i++) { struct direntv6 filenames[DIRENTV6_IN_SECTOR]; int validBytes = file_getblock (fs, dirinumber, i, filenames); int validFiles = validBytes / sizeof(struct direntv6); check = search_for_filename(filenames, validFiles, name, dirEnt); if(check) break; } return check-1; }
/* * Updates the file block to the correct block. */ int Fileops_getblock(int inum, int blockNo, unsigned char *buf) { return file_getblock(unixfs, inum,blockNo,buf); }
/* * add one entry to the directory initialized by entry name * detail impletation is read the last block of the directory and add the item. * it is kind of troublesome to consider the block shortage problem and others */ int directory_addItem(struct unixfilesystem *fs, const char *entryName, int dirinumber, int FileType) { struct inode dirIn; int err = inode_iget(fs, dirinumber, &dirIn); if (err < 0) { fprintf(stderr, "directory_addItem get dir inode failed\n"); return -1; } if (!(dirIn.i_mode & IALLOC) || ((dirIn.i_mode & IFMT) != IFDIR)) { fprintf(stderr, "directory_addItem dir inode is not DIR or ALLOCATED"); return -1; } /* * inode_size % DISKIMG_SECTOR_SIZE == 0 * means no space left in inode, so we need alloc a new block */ int inode_size = inode_getsize(&dirIn); if (inode_size % DISKIMG_SECTOR_SIZE == 0) { err = filsys_allocBlocks(fs, &dirIn, 1); if (err < 0) { fprintf(stderr, "directory_addItem can't apply new blocks and inode_size = %d\n",inode_size); } } /* increase dir's inode_size first to make the file_getblock works legal */ inode_setsize(&dirIn, inode_size + sizeof(struct direntv6)); inode_iwrite(fs, dirinumber, &dirIn); /* Save dir's inode_size first */ /* Read the last item of directory, change and write it back because we handle the overflow problem in above code, so just do the normal routine */ char buf[DISKIMG_SECTOR_SIZE]; { /* Read Last block of directory, because inode_size has increased before, now the inode_size is the old one, but easy to compute if inode_size % DISKIMG_SECTOR_SIZE == 0 then inode_lastBlockNum = new allocated blockNum. */ int inode_lastBlockNum = inode_size / DISKIMG_SECTOR_SIZE; struct direntv6 *dirEnt = (struct direntv6 *)buf; //printf("directory i_mode = %d %d\n", in.i_mode, dirinumber); file_getblock(fs, dirinumber, inode_lastBlockNum, buf); // last block is inode_BlockNum /* locate the entry id */ int dirEnt_last = (inode_size % DISKIMG_SECTOR_SIZE) / sizeof(struct direntv6); strcpy(dirEnt[dirEnt_last].d_name, entryName); // copy name int inumber_new = filsys_allocInode(fs); // allocate an new inode and copy to dirEnt. if (inumber_new < 0) { fprintf(stderr, "directory_addItem can't apply new Inode"); } dirEnt[dirEnt_last].d_inumber = inumber_new; //printf("new allocated inumber = %d , entryName = %s, dir_bno = %d\n", inumber_new, entryName, inode_lastBlockNum); /* initialize new inode and save */ struct inode in_new; inode_iget(fs, inumber_new, &in_new); inode_format(&in_new); in_new.i_mode |= FileType; // set inode mode. inode_iwrite(fs, inumber_new, &in_new); // save new allocated inode /* write buf back to the block */ file_writeblock(fs, dirinumber, inode_lastBlockNum, buf); } inode_iwrite(fs, dirinumber, &dirIn); /* Save dir's inode */ return 0; }
/* * Lookup the specified name (name) in the directory (dirinumber). If found, return the * directory entry in dirEnt. Return 0 on success and something negative on failure. */ int directory_findname(struct unixfilesystem *fs, const char *name, int dirinumber, struct direntv6 *dirEnt) { // Get the directory's inode struct inode inp; int success = inode_iget(fs, dirinumber, &inp); // Return -1 on error if (success == -1){ return -1; } // The dirinumber does not match to a directory if ((inp.i_mode & IFMT) != IFDIR) { return -1; } // The size of the directory int size = inode_getsize(&inp); // Total number of dirent's int numDirEnts = size/ sizeof(struct direntv6); // The number of dirEnt's in one block int numDirEntsInBlock = DISKIMG_SECTOR_SIZE / sizeof(struct direntv6); // The number of blocks the struct consistst of int numBlocks = numDirEnts / numDirEntsInBlock; // If the number of dirEnts don't fully occupy a block, add one if(numDirEnts % numDirEntsInBlock !=0) numBlocks +=1; // Look through all of the blocks in the inode for(int block = 0; block < numBlocks; block++){ // Create a buffer struct direntv6 dirEntTable[numDirEntsInBlock]; // Had &dirEntTable success = file_getblock(fs,dirinumber,block,dirEntTable); // Check for error if (success < 0){ return -1; } // Look over all of the dirEnt's in a block for(int d = 0; d < numDirEntsInBlock; d++){ struct direntv6 dir = dirEntTable[d]; // See if the strings match if(strcmp(name,dir.d_name) == 0){ // Copy the dir into dirEnt and return memcpy(dirEnt,&dir,sizeof(struct direntv6)); return 0; } } } // return -1 on no match return -1; }