/* * Get the inumber for the given file. Also makes sure that the cursor * is within the file. */ int Fileops_getinumber(int fd, int *size) { int inumber; struct inode in; int err; 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 return inumber; }
/* * Output to the specified file the checksum of all allocated inodes. * * This is used by the grading script, so be careful not to change its output * format. */ void DumpInodeChecksum(struct unixfilesystem *fs, FILE *f) { for (int inumber = 1; inumber < fs->superblock.s_isize*16; inumber++) { struct inode in; if (inode_iget(fs, inumber, &in) < 0) { fprintf(stderr,"Can't read inode %d \n", inumber); return; } if ((in.i_mode & IALLOC) == 0) { // Skip this inode if it's not allocated. continue; } char chksum[CHKSUMFILE_SIZE]; if (chksumfile_byinumber(fs, inumber, chksum) < 0) { fprintf(stderr, "Inode %d can't compute chksum\n", inumber); continue; } char chksumstring[CHKSUMFILE_STRINGSIZE]; chksumfile_cvt2string(chksum, chksumstring); int size = inode_getsize(&in); fprintf(f, "Inode %d mode 0x%x size %d checksum %s\n",inumber,in.i_mode, size, chksumstring); } }
/* * Print all the entries in the specified directory. */ void PrintDirectory(struct unixfilesystem *fs, char *pathname) { int inumber = pathname_lookup(fs, pathname); if (inumber < 0) { fprintf(stderr, "Can't find %s\n", pathname); return; } struct direntv6 direntries[1000]; int numentries = GetDirEntries(fs, inumber, direntries, 1000); if (numentries < 0) { fprintf(stderr, "Can't read entries from %s\n", pathname); return; } struct inode in; int i, rowLength = 0; for (i = 0; i < numentries; i++) { inode_iget(fs, direntries[i].d_inumber, &in); printf("%s",direntries[i].d_name); if ((in.i_mode & IFMT) == IFDIR) printf("/"); printf("\t"); rowLength += strlen(direntries[i].d_name) + 1; if ((i+1) % 6 == 0) puts(""); } }
/* * 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 the specified file block from the specified inode. * Return the number of valid bytes in the block, -1 on error. */ int file_getblock(struct unixfilesystem *fs, int inumber, int blockNum, void *buf) { // First retrieve the inode in question struct inode node; int inode_iget_status = inode_iget(fs, inumber, &node); if (inode_iget_status == -1) return -1; // Then we want to get the block int block = inode_indexlookup(fs, &node, blockNum); if (!block) return -1; // Now retrive the contents of the block and put it into the buffer int sector_status = diskimg_readsector(fs->dfd, block, buf); // Figure out what the size was supposed to be int inodesize = inode_getsize(&node); // Now figure out what the valid number of bytes to return is int bytesRemaining = inodesize - blockNum * 512; if (bytesRemaining < 512) { return bytesRemaining; } return sector_status; }
struct unixfilesystem * unixfilesystem_format(int dfd) { uint16_t bootblock[256]; bootblock[0] = BOOTBLOCK_MAGIC_NUM; diskimg_writesector(dfd, BOOTBLOCK_SECTOR, bootblock); struct unixfilesystem *fs = malloc(sizeof(struct unixfilesystem)); if (fs == NULL) { fprintf(stderr,"Out of memory.\n"); return NULL; } fs->dfd = dfd; // 144 inodes in total, so we have 8 blocks // to store inodes, plus 2 start blocks, // we have 10 blocks in use, and we allocate the entire volume 110 blocks // so the rest 100 blocks is file blocks, and all blocks formats to free. fs->superblock.s_isize = 144; fs->superblock.s_fsize = 110; // 110 blocks of entire volume fs->superblock.s_ninode = fs->superblock.s_isize; // at begining, free inodes number = total inodes number int i; // consider s_inode as bitmap for (i = 0;i < 100;i++) fs->superblock.s_inode[i] = 0; fs->superblock.s_nfree = fs->superblock.s_fsize ; // at begining, free blocks number = total blocks number // consider s_free as bitmap for (i = 0;i < 100;i++) fs->superblock.s_free[i] = 0; diskimg_writesector(dfd, SUPERBLOCK_SECTOR, &fs->superblock); int inumber = filsys_allocInode(fs); if (inumber != ROOT_INUMBER) { fprintf(stderr, "ROOT_INUMBER is not 1, format failed\n"); return -1; } struct inode in; inode_iget(fs, inumber, &in); // format the root dir, and set the i_mode field to DIR inode_format(&in); //in.i_mode &= (0xffff - IFMT); in.i_mode |= IFDIR; inode_iwrite(fs, ROOT_INUMBER, &in); fs->workDirInumber = ROOT_INUMBER; strcpy(fs->workDirName, "/"); return fs; }
/* * 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; }
int remove_file(struct unixfilesystem *fs, int inumber) { struct inode in; int err = inode_iget(fs, inumber, &in); if (err < 0) return -1; if (!(in.i_mode & IALLOC) || ((in.i_mode & IFMT) == IFDIR)) { /* Not allocated or is a directory */ fprintf(stderr, "The input path is not a file and cannot be removed"); return -1; } if (in.i_nlink == 1) // only one link, so overwrite the file { char zeros[DISKIMG_SECTOR_SIZE] = {0}; int size = inode_getsize(&in); int blockNum = 0; // overwrite the file with zeros for (blockNum = 0; blockNum < size / DISKIMG_SECTOR_SIZE; blockNum++) { char buf[DISKIMG_SECTOR_SIZE]; int blockAddress = inode_indexlookup(fs, &in, blockNum); if (blockAddress == -1) { fprintf(stderr, "Error looking up block number %d in inode %d", blockNum, inumber); return -1; } if (diskimg_writesector(fs->dfd, blockAddress, &zeros) == -1) { fprintf(stderr, "Error overwriting file"); return -1; } } } else // multiple links to file, so only remove this link { in.i_nlink--; } return 0; }
/* * 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]); }
/* * Return true if specified pathname is a regular file. */ int Fileops_isfile(char *pathname) { numisfiles++; int inumber = pathname_lookup(unixfs, pathname); if (inumber < 0) { return 0; } struct inode in; int err = inode_iget(unixfs, inumber, &in); if (err < 0) return 0; if (!(in.i_mode & IALLOC) || ((in.i_mode & IFMT) != 0)) { /* Not allocated or not a file */ return 0; } return 1; /* Must be a file */ }
/* * Fetch the specified file block from the specified inode. * Return the number of valid bytes in the block, -1 on error. */ int file_getblock(struct unixfilesystem *fs, int inumber, int blockNum, void *buf) { //fprintf(stderr, "in file_getblock, size %d, inum: %d\n", cacheMemSizeInKB, inumber); struct inode in; int getResult = inode_iget(fs, inumber, &in); int sectorNum = inode_indexlookup(fs, &in, blockNum); int bytesRead = diskimg_readsector(fs->dfd, sectorNum, buf); if ((getResult == -1) || (bytesRead == -1) || (sectorNum == -1)) return -1; int size = inode_getsize(&in); if ((size % BYTES_PER_BLOCK) == 0) { return BYTES_PER_BLOCK; } else { int numblocks = (size / BYTES_PER_BLOCK); if (blockNum == numblocks) { return size % BYTES_PER_BLOCK; } else { return BYTES_PER_BLOCK; } } }
/* * Fetch the specified file block from the specified inode. * Return the number of valid bytes in the block, -1 on error. */ int file_getblock(struct unixfilesystem *fs, int inumber, int blockNum, void *buf) { // Consider inumber = 17, blocknumber = 5: // – Find the inode struct inode inp; if(inode_iget(fs, inumber, &inp) < 0){ printf("Error getting inode %i\n", inumber); return -1; } int filesize = inode_getsize(&inp); int partial = (filesize % DISKIMG_SECTOR_SIZE == 0) ? 0 : 1; int blocks = (filesize / DISKIMG_SECTOR_SIZE) + partial; // – Find the sector number int sectorNum = inode_indexlookup(fs, &inp, blockNum); if(sectorNum == -1){ printf("Error getting data sector %i\n", blockNum); return -1; } if((sectorNum > (int)fs->superblock.s_fsize) || (sectorNum < fs->superblock.s_isize + INODE_START_SECTOR)){ printf("sectorNum: %i blockNum: %i blocks: %i inode: %i\n", sectorNum, blockNum, blocks, inumber); } // – Read the data in the sector into the buffer if (diskimg_readsector(fs->dfd, sectorNum, buf) != DISKIMG_SECTOR_SIZE) { fprintf(stderr, "Error reading sector %i for block %i of %i\n", sectorNum, blockNum, blocks); return -1; } //Determine value of valid bytes in the block if(blockNum == blocks - 1){ if(partial) { return (filesize % DISKIMG_SECTOR_SIZE); }else{ return DISKIMG_SECTOR_SIZE; } }else{ return DISKIMG_SECTOR_SIZE; } }
/* * 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; }
/* * Fetch the specified file block from the specified inode. * Return the number of valid bytes in the block, -1 on error. */ int file_getblock(struct unixfilesystem *fs, int inumber, int blockNum, void *buf) { //Find the inode struct inode inp; if(inode_iget(fs, inumber, &inp) < 0){ printf("Error getting inode %i\n", inumber); return -1; } //Find the sector number for the blockNum int sectorNum = inode_indexlookup(fs, &inp, blockNum); if(sectorNum == -1){ printf("Error getting data sector %i\n", blockNum); return -1; } //Read the data in the sector into the buffer if (diskimg_readsector(fs->dfd, sectorNum, buf) != DISKIMG_SECTOR_SIZE) { fprintf(stderr, "Error reading sector %i for block %i\n", sectorNum, blockNum); return -1; } //Return number of valid bytes in the block return validBytes(&inp, blockNum); }
/* * 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; }
/* * Output to the specified file the checksum of the specified pathname and * inode as well as all its children if it is a directory. * * This is used by the grading script, so be careful not to change its output * format. */ void DumpPathAndChildren(struct unixfilesystem *fs, const char *pathname, int inumber, FILE *f) { struct inode in; if (inode_iget(fs, inumber, &in) < 0) { fprintf(stderr,"Can't read inode %d \n", inumber); return; } assert(in.i_mode & IALLOC); char chksum1[CHKSUMFILE_SIZE]; if (chksumfile_byinumber(fs, inumber, chksum1) < 0) { fprintf(stderr,"Can't checksum inode %d path %s\n", inumber, pathname); return; } char chksum2[CHKSUMFILE_SIZE]; if (chksumfile_bypathname(fs, pathname, chksum2) < 0) { fprintf(stderr,"Can't checksum inode %d path %s\n", inumber, pathname); return; } if (!chksumfile_compare(chksum1, chksum2)) { fprintf(stderr,"Pathname checksum of %s differs from inode %d\n", pathname, inumber); return; } char chksumstring[CHKSUMFILE_STRINGSIZE]; chksumfile_cvt2string(chksum2, chksumstring); int size = inode_getsize(&in); fprintf(f, "Path %s %d mode 0x%x size %d checksum %s\n",pathname,inumber,in.i_mode, size, chksumstring); if (pathname[1] == 0) { /* pathame == "/" */ pathname++; /* Delete extra / character */ } if ((in.i_mode & IFMT) == IFDIR) { const unsigned int MAXPATH = 1024; if (strlen(pathname) > MAXPATH-16) { fprintf(stderr, "Too deep of directories %s\n", pathname); } struct direntv6 direntries[10000]; int numentries = GetDirEntries(fs, inumber, direntries, 10000); for (int i = 0; i < numentries; i++) { char *n; n = direntries[i].d_name; if (n[0] == '.') { if ((n[1] == 0) || ((n[1] == '.') && (n[2] == 0))) { /* Skip over "." and ".." */ continue; } } char nextpath[MAXPATH]; sprintf(nextpath, "%s/%s",pathname, direntries[i].d_name); DumpPathAndChildren(fs, nextpath, direntries[i].d_inumber, f); } } }
/* * 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; }