示例#1
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)
{
  
	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;
}
示例#4
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)
{

    // 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;

}
示例#5
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]);
}
/*
 * 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;
}
示例#7
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)
{
  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;
}
示例#8
0
/*
 * 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;
}
示例#10
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;
}