Exemplo n.º 1
0
Arquivo: fs.c Projeto: vonwenm/pbft
struct inode *FS_lookup(struct inode *dir, char *name) {
  struct dir_entry *de;
  int ret = FS_lookup_internal(dir, name);
  if (ret == -1) return 0;

  de = Directory_entry(dir, ret);
  return fetch_inode(de->inum);
}
Exemplo n.º 2
0
Arquivo: fs.c Projeto: vonwenm/pbft
struct inode *FS_fhandle_to_inode(fhandle *fh) {
  struct inode *ret;
  struct nfs_fhandle *nfh = (struct nfs_fhandle *)fh;
  
  /* Check bounds */
  if (nfh->inum < 0 || nfh->inum >= fs->num_inodes) {
    /* Stale file handle */
    return 0;
  }

  ret = fetch_inode(nfh->inum);
  if (nfh->generation != gen(ret)) {
    /* Stale file handle */
    return 0;
  } 

  return ret;
}
Exemplo n.º 3
0
int read_inode(struct inode *i_node, struct dir_extent *extent, size_t offset,
	size_t *new_offset)
{
	struct iso9660_dir_record *dir_rec;
	struct buf *bp;

	/* Find inode. */
	bp = fetch_inode(extent, &offset);
	if (bp == NULL)
		return EOF;

	dir_rec = (struct iso9660_dir_record*)(b_data(bp) + offset %
	          v_pri.logical_block_size_l);

	/* Parse basic ISO 9660 specs. */
	if (check_dir_record(dir_rec,
	    offset % v_pri.logical_block_size_l) != OK) {
		lmfs_put_block(bp, FULL_DATA_BLOCK);
		return EINVAL;
	}

	memset(&i_node->i_stat, 0, sizeof(struct stat));

	i_node->i_stat.st_ino = get_extent_absolute_block_id(extent,
	    offset / v_pri.logical_block_size_l) * v_pri.logical_block_size_l +
	    offset % v_pri.logical_block_size_l;

	read_inode_iso9660(i_node, dir_rec);

	/* Parse extensions. */
	read_inode_susp(i_node, dir_rec, bp,
	    offset % v_pri.logical_block_size_l);

	offset += dir_rec->length;
	read_inode_extents(i_node, dir_rec, extent, &offset);

	lmfs_put_block(bp, FULL_DATA_BLOCK);
	if (new_offset != NULL)
		*new_offset = offset;
	return OK;
}
Exemplo n.º 4
0
Arquivo: fs.c Projeto: vonwenm/pbft
nfsstat FS_unlink(struct inode *dir, char *name, int remove_dir) {
  struct inode *child;
  int child_num;
  int child_inum;
  struct dir_entry *d1, *d2;
  int refcnt;

  assert(dir->attr.type == NFDIR);
 
  if (strlen(name) > MAX_NAME_LEN) {
    return NFSERR_NAMETOOLONG;
  }
  
  child_num = FS_lookup_internal(dir, name);
  if (child_num == -1) {
    return NFSERR_NOENT;
  }

  child_inum = Directory_entry(dir, child_num)->inum;
  child = fetch_inode(child_inum);
  if (!remove_dir && child->attr.type == NFDIR) {
    return NFSERR_ISDIR;
  }

  if (remove_dir && child->attr.type != NFDIR) {
    return NFSERR_NOTDIR;
  }

  if (!strcmp(name, ".") || !strcmp(name, "..")) {
    return NFSERR_ACCES;
  }

#if 0
  /* TODO: Need to check acces control */
  if (~write_access ()) {
    return (NFSERR_PERM);
  }
#endif

  if (remove_dir && child->attr.size != 2 && child->attr.nlink == 2) {
    return NFSERR_NOTEMPTY;
  }

  d1 = Directory_entry(dir, child_num);
  d2 = Directory_entry(dir, dir->attr.size-1);
  if (d1 != d2) {
    Byz_modify2(d1, sizeof(struct dir_entry));
    bcopy((char*)d2, (char*)d1, sizeof(struct dir_entry));
  } 

  Byz_modify2(&(dir->attr), sizeof(dir->attr));
  dir->attr.size--;
  if (dir->attr.blocks > 0) {
    if (dir->attr.size <= NUM_INLINE_DIR_ENTRIES) {
      /* Can free first indirect block */
      FS_free_block(fetch_block(dir_block(dir)));
      dir_block(dir) = -1;
      dir->attr.blocks = 0;
    } else {
      if (dir->attr.blocks > 1 && 
	  dir->attr.size <= NUM_INLINE_DIR_ENTRIES+NUM_INDIRECT_DIR_ENTRIES) {
	/* Can free second indirect block */
	FS_free_block(fetch_block(dir_block1(dir)));
	dir_block1(dir) = -1;
	dir->attr.blocks = 1;
      }
    }
  }

  dir->attr.ctime.seconds = cur_time.tv_sec;
  dir->attr.ctime.useconds = cur_time.tv_usec;
  dir->attr.mtime = dir->attr.ctime;

  Byz_modify2(&(child->attr), sizeof(child->attr));
  refcnt = decr_refcnt(child);
  if (refcnt == 0) {
    /* Free child and its associated storage */
    if (child->attr.type == NFREG)
      FS_truncate(child, 0);
    FS_free_inode(child);
    return NFS_OK;
  } else {
    /* Update time of last status change for child */
    child->attr.ctime = dir->attr.ctime;
  }
  
  /* If it is a directory "." points to self so refcnt == 1 means it
     can be removed. We checked for emptyness before. */
  if (refcnt == 1 && child->attr.type == NFDIR) {
    /* Decrement reference count of parent */
    struct inode *parent = FS_lookup(child, "..");
    if (parent != dir) {
      Byz_modify1(&(parent->attr.nlink));
    }
    decr_refcnt(parent);
    FS_free_inode(child);
  }
  return NFS_OK; 
}
Exemplo n.º 5
0
void read_inode_extents(struct inode *i,
	const struct iso9660_dir_record *dir_rec,
	struct dir_extent *extent, size_t *offset)
{
	struct buf *bp;
	struct iso9660_dir_record *extent_rec;
	struct dir_extent *cur_extent = i->extent;
	int done = FALSE;

	/*
	 * No need to search extents if file is empty or has final directory
	 * record flag set.
	 */
	if (cur_extent == NULL ||
	    ((dir_rec->file_flags & D_NOT_LAST_EXTENT) == 0))
		return;

	while (!done) {
		bp = fetch_inode(extent, offset);
		if (bp == NULL)
			return;

		bp = read_extent_block(extent,
		    *offset / v_pri.logical_block_size_l);
		extent_rec = (struct iso9660_dir_record*)(b_data(bp) +
		    *offset % v_pri.logical_block_size_l);

		if (check_dir_record(dir_rec,
		    *offset % v_pri.logical_block_size_l) != OK) {
			lmfs_put_block(bp, FULL_DATA_BLOCK);
			return;
		}

		/* Extent entries should share the same name. */
		if ((dir_rec->length_file_id == extent_rec->length_file_id) &&
		    (memcmp(dir_rec->file_id, extent_rec->file_id,
		    dir_rec->length_file_id) == 0)) {
			/* Add the extent at the end of the linked list. */
			assert(cur_extent->next == NULL);
			cur_extent->next = alloc_extent();
			cur_extent->next->location = dir_rec->loc_extent_l +
			    dir_rec->ext_attr_rec_length;
			cur_extent->next->length = dir_rec->data_length_l /
			    v_pri.logical_block_size_l;
			if (dir_rec->data_length_l % v_pri.logical_block_size_l)
				cur_extent->next->length++;

			i->i_stat.st_size += dir_rec->data_length_l;
			i->i_stat.st_blocks += cur_extent->next->length;

			cur_extent = cur_extent->next;
			*offset += extent_rec->length;
		}
		else
			done = TRUE;

		/* Check if not last extent bit is not set. */
		if ((dir_rec->file_flags & D_NOT_LAST_EXTENT) == 0)
			done = TRUE;

		lmfs_put_block(bp, FULL_DATA_BLOCK);
	}
}