Exemple #1
0
/* open file and return fd; to make our life easier, always open RW */
int fs_open(const char *filename, int flags, int mode)
{
    int flag, fd;
    struct inode_s *ino, *dir;

    ino = dir = NULL;

    flag = (flags & O_CREAT) ? FS_SEARCH_CREAT : FS_SEARCH_GET;

    dir = current_dir();

    if ( (ino = find_inode(dir, filename, flag)) == NULL)
        goto err;

    release_inode(dir);

    if (ino->i_zone[0] == 0 && (flags & O_CREAT))
        fill_inode(ino, mode);

    if (flags & O_TRUNC) {
        ino->i_size = 0;
        ino->i_dirty = 1;
    }

    if ( (fd = get_fd(ino, (flags & O_APPEND) ? ino->i_size : 0)) == ERROR)
        goto err;

    return fd;

err:
    release_inode(dir);
    release_inode(ino);

    return ERROR;
}
Exemple #2
0
/* make new device file in /dev folder, with type, major and minor numbers */
int fs_make_dev(const char *name, int type, dev_t major, dev_t minor)
{
    struct inode_s *ino, *dev;

    ino = dev = NULL;

    if ( (dev = find_inode(NULL, "/dev", FS_SEARCH_CREAT)) == NULL)
        debug_panic("fs_make_dev: error searching/creating /dev");

    if ( (ino = find_inode(dev, name, FS_SEARCH_CREAT)) == NULL)
        goto err;

    ino->i_zone[0] = major;
    ino->i_zone[1] = minor;
    ino->i_dirty = 1;

    release_inode(dev);
    release_inode(ino);

    return OK;

err:
    release_inode(dev);
    release_inode(ino);

    return ERROR;
}
Exemple #3
0
static struct inode *truncate_existing(struct filsys *fs, char *name, int len)
{
  struct inode *inode;
  vfs_ino_t ino;

  ino = lookup_name(fs, DFS_INODE_ROOT, name, len);
  if (ino == -1) return NULL;
  
  inode = get_inode(fs, ino);
  if (!inode) return NULL;

  if (VFS_S_ISDIR(inode->desc->mode))
  {
    release_inode(inode);
    return NULL;
  }

  if (truncate_inode(inode, 0) < 0)
  {
    release_inode(inode);
    return NULL;
  }
  inode->desc->size = 0;
  mark_inode_dirty(inode);

  return inode;
}
Exemple #4
0
static bool_t L2_Translate_m (USDCallback_cl          *self,
			      USD_StreamID             sid          /* IN */,
			      USD_ClientID             cid          /* IN */,
			      const FileIO_Request    *req          /* IN */,
			      USD_Extent              *extent       /* OUT */,
			      uint32_t                *notification /* OUT */ )
{
    ext2fs_st    *st = self->st;
    Client_st    *cur;
    Ext2_Handle   handle;
    struct inode *ino;

    FTRC("entered: self=%p, st=%p.\n", self, st);

    if (req->nblocks == 0) {
	/* Inode prefectch */
	ino = get_inode(st, req->user1);
	release_inode(st, ino);
	return False;
    }

    /* All checked once by L1 (XXX are there concurrency problems?) */
    cur    = (Client_st *)(word_t)cid;	
    handle = req->user1;
    ino    = cur->handles[handle].ino; 

    translate(st, ino, req, extent);

    FTRC("leaving, returning true.\n");
    return(True);
}
Exemple #5
0
int dfs_opendir(struct file *filp, char *name)
{
  struct filsys *fs;
  int len;
  vfs_ino_t ino;
  struct inode *inode;

  fs = (struct filsys *) filp->fs->data;
  len = strlen(name);

  ino = lookup_name(fs, DFS_INODE_ROOT, name, len);
  if (ino == -1) return -1;
  
  inode = get_inode(fs, ino);
  if (!inode) return -1;

  if (!VFS_S_ISDIR(inode->desc->mode))
  {
    release_inode(inode);
    return -1;
  }

  filp->data = inode;
  return 0;
}
Exemple #6
0
static int create_new(struct filsys *fs, char *name, ino_t ino, int mode, struct inode **retval) {
  struct inode *dir;
  struct inode *inode;
  int rc;
  int len = strlen(name);

  rc = diri(fs, &name, &len, &dir);
  if (rc < 0) return rc;

  rc = find_dir_entry(dir, name, len, NULL);
  if (rc != -ENOENT) {
    release_inode(dir);
    return rc >= 0 ? -EEXIST : rc;
  }

  if (ino == NOINODE) {
    inode = alloc_inode(dir, S_IFREG | (mode & S_IRWXUGO));
    if (!inode) rc = -ENOSPC;
  } else {
    rc = get_inode(fs, ino, &inode);
    if (rc < 0) inode = NULL;
    if (inode) {
      inode->desc->ctime = inode->desc->mtime = time(NULL);
      inode->desc->uid = inode->desc->gid = 0;
      inode->desc->mode = S_IFREG | 0700;
      inode->desc->linkcount++;
      mark_inode_dirty(inode);
    }
  }

  if (!inode) {
    release_inode(dir);
    return rc;
  }

  rc = add_dir_entry(dir, name, len, inode->ino);
  if (rc < 0) {
    unlink_inode(inode);
    release_inode(inode);
    release_inode(dir);
    return rc;
  }

  release_inode(dir);
  *retval = inode;
  return 0;
}
Exemple #7
0
int dfs_destroy(struct file *filp) {
  struct inode *inode;

  inode = (struct inode *) filp->data;
  release_inode(inode);

  return 0;
}
Exemple #8
0
//******** rmdir ********************
int8_t cnrmdir(const char* name)
{
	char parent_name[512];
	char entry_name[256];
	dir_entry* entry;
	inode dir_inode;
	memset(&dir_inode, 0, sizeof(inode));

	strcpy(parent_name, name);
	strcat(parent_name, "/..");

	dir_ptr* parent = cnopendir(parent_name);
	check(parent != NULL, "Cannot open parent directory");

	//Copy the entire directory minus the entry
	dir_ptr* new_parent = calloc(1,sizeof(dir_ptr));
	new_parent->data = calloc(parent->inode_st.blocks, sizeof(block));
	dir_entry* new_dir_entry = (dir_entry*)new_parent->data;
	new_parent->inode_st = parent->inode_st;
	new_parent->inode_id = parent->inode_id;
	new_parent->inode_st.size = 0;
	new_parent->index = 0;

	while((entry = cnreaddir(parent)))
	{
		memcpy(entry_name, entry->name, entry->name_len);
		entry_name[entry->name_len] = 0;
		if(strcmp(entry_name, name) == 0)  //If this is the directory we want
		{
			inode_read(entry->inode, &dir_inode);
			check(dir_inode.size == 24, "Directory is not empty");
			release_block(dir_inode.data0[0]);  //Release target directory block
			release_inode(entry->inode);        //Release target inode
			continue;
		}
		new_dir_entry->entry_len = entry->entry_len;
		new_dir_entry->name_len = entry->name_len;
		new_dir_entry->file_type = entry->file_type;
		new_dir_entry->inode = entry->inode;
		memcpy(new_dir_entry->name, entry->name, entry->name_len);
		new_parent->inode_st.size += entry->entry_len;
		new_parent->index += entry->entry_len;
		new_dir_entry = (dir_entry*)((uint8_t*)new_parent->data+new_parent->index);
	}

	inode_write(new_parent->inode_id, &new_parent->inode_st);
	llwrite(&new_parent->inode_st, new_parent->data);

	free(new_parent->data);
	free(new_parent);
	cnclosedir(parent);
	return 0;
error:
	if(new_parent != NULL && new_parent->data != NULL) free(new_parent->data);
	if(new_parent != NULL) free(new_parent);
	if(parent != NULL) cnclosedir(parent);
	return -1;
}
Exemple #9
0
static struct inode *create_new(struct filsys *fs, char *name, int len, int mode)
{
  struct inode *dir;
  struct inode *inode;
  struct inode *oldinode;
  vfs_ino_t oldino;

  dir = parse_name(fs, &name, &len);
  if (!dir) return NULL;

  inode = alloc_inode(dir, VFS_S_IFREG | mode);
  if (!inode)
  {
    release_inode(dir);
    return NULL;
  }

  inode->desc->linkcount++;
  mark_inode_dirty(inode);

  oldino = modify_dir_entry(dir, name, len, inode->ino);
  if (oldino != -1)
  {
    oldinode = get_inode(fs, oldino);
    if (oldinode)
    {
      unlink_inode(oldinode);
      release_inode(oldinode);
    }
  }
  else
  {
    if (add_dir_entry(dir, name, len, inode->ino) < 0)
    {
      unlink_inode(inode);
      release_inode(inode);
      release_inode(dir);
      return NULL;
    }
  }

  release_inode(dir);
  return inode;
}
Exemple #10
0
static struct inode *create_always(struct filsys *fs, char *name, int len, vfs_ino_t ino, int mode)
{
  struct inode *dir;
  struct inode *inode;

  dir = parse_name(fs, &name, &len);
  if (!dir) return NULL;

  if (find_dir_entry(dir, name, len) != -1)
  {
    release_inode(dir);
    return NULL;
  }

  if (ino == -1)
    inode = alloc_inode(dir, VFS_S_IFREG | mode);
  else
  {
    inode = get_inode(fs, ino);
    if (inode->desc->ctime == 0) inode->desc->ctime = time(NULL);
    inode->desc->mode = VFS_S_IFREG | mode;
  }

  if (!inode)
  {
    release_inode(dir);
    return NULL;
  }

  inode->desc->linkcount++;
  mark_inode_dirty(inode);

  if (add_dir_entry(dir, name, len, inode->ino) < 0)
  {
    unlink_inode(inode);
    release_inode(inode);
    release_inode(dir);
    return NULL;
  }

  release_inode(dir);
  return inode;
}
Exemple #11
0
/* remove file/dir from fs */
int fs_unlink(const char *pathname)
{
    struct inode_s *ino, *dir;

    ino = dir = NULL;

    dir = current_dir();
    if ( (ino = find_inode(dir, pathname, FS_SEARCH_REMOVE)) == NULL)
        goto err;
    rm_inode(ino->i_num);
    release_inode(dir);
    release_inode(ino);

    return OK;

err:
    release_inode(dir);
    release_inode(ino);
    return ERROR;
}
Exemple #12
0
static int truncate_existing(struct filsys *fs, char *name, struct inode **retval) {
  struct inode *inode;
  int rc;

  rc = namei(fs, name, &inode);
  if (rc < 0) return rc;

  if (S_ISDIR(inode->desc->mode)) {
    release_inode(inode);
    return -EISDIR;
  }

  rc = truncate_inode(inode, 0); 
  if (rc < 0) {
    release_inode(inode);
    return rc;
  }
  inode->desc->size = 0;
  mark_inode_dirty(inode);

  *retval = inode;
  return 0;
}
Exemple #13
0
int dfs_close(struct file *filp)
{
  struct inode *inode;

  inode = (struct inode *) filp->data;
  if (filp->flags & F_MODIFIED) 
  {
    inode->desc->mtime = time(NULL);
    mark_inode_dirty(inode);
  }

  release_inode(inode);

  return 0;
}
Exemple #14
0
int fs_chdir(const char *path)
{
    struct inode_s *ino, *dir;

    ino = dir = NULL;

    dir = current_dir();
    if ( (ino = find_inode(dir, path, FS_SEARCH_GET)) == NULL)
        goto err;
    release_inode(dir);

    if (!IS_DIR(ino->i_mode))
        goto err;

    set_current_dir(ino);
    release_inode(ino);

    return OK;

err:
    release_inode(dir);
    release_inode(ino);
    return ERROR;
}
Exemple #15
0
static struct inode *open_always(struct filsys *fs, char *name, int len, int mode)
{
  struct inode *dir;
  struct inode *inode;
  vfs_ino_t ino;

  dir = parse_name(fs, &name, &len);
  if (!dir) return NULL;

  ino = find_dir_entry(dir, name, len);
  if (ino == -1)
  {
    inode = alloc_inode(dir, VFS_S_IFREG | mode);
    if (!inode) 
    {
      release_inode(dir);
      return NULL;
    }

    inode->desc->linkcount++;
    mark_inode_dirty(inode);

    if (add_dir_entry(dir, name, len, inode->ino) < 0)
    {
      unlink_inode(inode);
      release_inode(inode);
      release_inode(dir);
      return NULL;
    }
  }
  else
  {
    inode = get_inode(fs, ino);
    if (!inode) 
    {
      release_inode(dir);
      return NULL;
    }

    if (VFS_S_ISDIR(inode->desc->mode))
    {
      release_inode(dir);
      release_inode(inode);
      return NULL;
    }
  }

  release_inode(dir);
  return inode;
}
Exemple #16
0
static struct inode *open_existing(struct filsys *fs, char *name, int len)
{
  struct inode *inode;
  vfs_ino_t ino;

  ino = lookup_name(fs, DFS_INODE_ROOT, name, len);
  if (ino == -1) return NULL;
  
  inode = get_inode(fs, ino);
  if (!inode) return NULL;

  if (VFS_S_ISDIR(inode->desc->mode))
  {
    release_inode(inode);
    return NULL;
  }

  return inode;
}
Exemple #17
0
int fs_getdents(int fd, char *buf, size_t n)
{
    unsigned int i, pos;
    struct inode_s *dir, *ino;
    struct dir_entry_s dentry;
    struct dirent *dent;
    struct file_s *flip;

    flip = get_file(fd);
    dir = flip->f_ino;

    if (!IS_DIR(dir->i_mode))
        return ERROR;

    i = 0;
    pos = flip->f_pos;
    while (n >= sizeof(struct dirent) + 1) {
        if (next_entry(dir, &pos, &dentry) == ERROR)
            break;
        ino = get_inode(dentry.num);
        dent = (struct dirent *) (buf + i);
        dent->d_ino = dentry.num; 
        dent->d_off = pos - sizeof(struct dir_entry_s);
        dent->d_reclen = mystrncpy(dent->d_name, dentry.name, MAX_NAME) + 
                         1 +                      /* add the \0 */
                         sizeof(ino_t) +          /* add the d_ino */
                         sizeof(off_t) +          /* add the d_off */
                         sizeof(unsigned short) + /* add the d_reclen */
                         1;                       /* add the d_type */
        /* add d_type */
        *(buf + i + dent->d_reclen - 1) = (IS_DIR(ino->i_mode) ? DT_DIR :
                                          IS_FILE(ino->i_mode) ? DT_REG :
                                          IS_CHAR(ino->i_mode) ? DT_CHR :
                                                                 DT_UNK);
        i += dent->d_reclen;
        n -= dent->d_reclen;
        release_inode(ino);
    }
    flip->f_pos = pos;

    return i;
}
Exemple #18
0
struct inode *parse_name(struct filsys *fs, char **name, int *len)
{
  char *start;
  char *p;
  vfs_ino_t ino;
  struct inode *dir;

  if (*len == 0) return get_inode(fs, DFS_INODE_ROOT);

  start = *name;
  p = start + *len - 1;
  while (p > start && *p != PS1 && *p != PS2) p--;

  if (p == start)
  {
    if (*p == PS1 || *p == PS2)
    {
      (*name)++;
      (*len)--;
    }

    return get_inode(fs, DFS_INODE_ROOT);
  }

  ino = lookup_name(fs, DFS_INODE_ROOT, start, p - start);
  if (ino == -1) return NULL;

  dir = get_inode(fs, ino);
  if (!dir) return NULL;

  if (!VFS_S_ISDIR(dir->desc->mode))
  {
    release_inode(dir);
    return NULL;
  }

  *name = p + 1;
  *len -= p - start + 1;
  return dir;
}
Exemple #19
0
vfs_ino_t lookup_name(struct filsys *fs, vfs_ino_t ino, char *name, int len)
{
  char *p;
  int l;
  struct inode *inode;

  while (1)
  {
    // Skip path separator
    if (*name == PS1 || *name == PS2)
    {
      name++;
      len--;
    }
    if (len == 0) return ino;

    // Find next part of name
    p = name;
    l = 0;
    while (l < len && *p != PS1 && *p != PS2)
    {
      l++;
      p++;
    }

    // Find inode for next name part
    inode = get_inode(fs, ino);
    if (!inode) return -1;
    ino = find_dir_entry(inode, name, l);
    release_inode(inode);
    if (ino == -1) return -1;

    // If we have parsed the whole name return the inode number
    if (l == len) return ino;

    // Prepare for next name part
    name = p;
    len -= l;
  }
}
Exemple #20
0
/* rename oldpath to newpath */
int fs_rename(const char *oldpath, const char *newpath)
{
    struct inode_s *dir, *last_dir, *ino;
    char path[MAX_PATH], name[MAX_NAME];

    dir = last_dir = ino = NULL;

    /* get last component of path */
    process_path(newpath, path, name);
    if (name[0] == '\0') {
        char tmp[MAX_PATH];
        process_path(oldpath, tmp, name);
    }

    dir = current_dir();
    /* get last directory of target path */
    if ( (last_dir = find_inode(dir, path, FS_SEARCH_GET)) == NULL)
        goto err;

    /* remove entry from the old directory */
    if ( (ino = find_inode(dir, oldpath, FS_SEARCH_REMOVE)) == NULL)
        goto err;

    /* new entry in the last directory of path (or old one if file exists) */
    if (add_entry(last_dir, ino->i_num, name) == ERROR)
        goto err;

    /* check if oldpath was a dir, and update '..' in that case */
    if (IS_DIR(ino->i_mode)) {
        add_entry(ino, last_dir->i_num, "..");
        last_dir->i_nlinks++;
    }

    release_inode(last_dir);
    release_inode(dir);
    release_inode(ino);

    return OK;

err:
    release_inode(last_dir);
    release_inode(dir);
    release_inode(ino);

    return ERROR;
}
Exemple #21
0
/* create new directory */
int fs_mkdir(const char *pathname, mode_t mode)
{
    struct inode_s *ino, *dir, *tmpdir;
    char path[MAX_PATH], name[MAX_NAME];

    ino = dir = tmpdir = NULL;

    process_path(pathname, path, name);
    tmpdir = current_dir();
    /* get inode numbers from parent and new dir */
    if ( (dir = find_inode(tmpdir, path, FS_SEARCH_GET)) == NULL)
        goto err;
    release_inode(tmpdir);
    if ( (ino = find_inode(dir, name, FS_SEARCH_ADD)) == NULL)
        goto err;

    /* fill new dir inode */
    fill_inode(ino, mode);
    ino->i_mode = (ino->i_mode & ~I_TYPE) | I_DIRECTORY;

    /* add '.' */
    empty_entry(ino, ino->i_num, ".");
    ino->i_nlinks++;

    /* and '..' */
    empty_entry(ino, dir->i_num, "..");
    dir->i_nlinks++;
    dir->i_dirty = 1;

    /* update dir size */
    ino->i_size = DIRENTRY_SIZE * 2;

    release_inode(dir);
    release_inode(ino);

    return OK;

err:
    release_inode(tmpdir);
    release_inode(dir);
    release_inode(ino);

    return ERROR;
}
Exemple #22
0
/* remove directory (only if it is empty) */
int fs_rmdir(const char *pathname)
{
    struct inode_s *ino, *dir, *tmpdir;
    char path[MAX_PATH], name[MAX_NAME];

    ino = dir = tmpdir = NULL;

    process_path(pathname, path, name);
    tmpdir = current_dir();
    /* get inode numbers from parent and new dir */
    if ( (dir = find_inode(tmpdir, path, FS_SEARCH_GET)) == NULL)
        goto err;
    release_inode(tmpdir);
    if ( (ino = find_inode(dir, name, FS_SEARCH_ADD)) == NULL)
        goto err;

    /* check if its a dir and it is empty */
    if (!IS_DIR(ino->i_mode) || ino->i_size != DIRENTRY_SIZE * 2)
        goto err;

    /* this cant give an error */
    release_inode(find_inode(dir, name, FS_SEARCH_REMOVE));

    /* free blocks and inode */
    rm_inode(ino->i_num);

    release_inode(dir);
    release_inode(ino);

    return OK;

err:
    release_inode(tmpdir);
    release_inode(dir);
    release_inode(ino);

    return ERROR;
}
Exemple #23
0
static int open_always(struct filsys *fs, char *name, int mode, struct inode **retval) {
  struct inode *dir;
  struct inode *inode;
  ino_t ino;
  int rc;
  int len = strlen(name);

  rc = diri(fs, &name, &len, &dir);
  if (rc < 0) return rc;

  rc = find_dir_entry(dir, name, len, &ino);
  if (rc < 0 && rc != -ENOENT) {
    release_inode(dir);
    return rc;
  }

  if (rc == -ENOENT) {
    inode = alloc_inode(dir, S_IFREG | (mode & S_IRWXUGO));
    if (!inode) {
      release_inode(dir);
      return -ENOSPC;
    }

    rc = add_dir_entry(dir, name, len, inode->ino);
    if (rc < 0) {
      unlink_inode(inode);
      release_inode(inode);
      release_inode(dir);
      return rc;
    }
  } else {
    rc = get_inode(fs, ino, &inode);
    if (rc < 0) {
      release_inode(dir);
      return rc;
    }
  }

  release_inode(dir);
  *retval = inode;
  return 0;
}
Exemple #24
0
struct filsys *create_filesystem(vfs_devno_t devno, int blocksize, int inode_ratio, int quick)
{
  struct filsys *fs;
  unsigned int blocks;
  unsigned int first_block;
  struct groupdesc *gd;
  struct buf *buf;
  unsigned int i, j;
  vfs_ino_t ino;
  struct inode *root;
  char *buffer;

  // Allocate file system
  fs = (struct filsys *) malloc(sizeof(struct filsys));
  memset(fs, 0, sizeof(struct filsys));

  // Allocate super block
  fs->super = (struct superblock *) malloc(SECTORSIZE);
  memset(fs->super, 0, SECTORSIZE);
  fs->super_dirty = 1;

  // Set device number and block size
  fs->devno = devno;
  fs->blocksize = blocksize;

  // Initialize buffer cache
  fs->cache = init_buffer_pool(devno, CACHEBUFFERS, fs->blocksize);

  // Set signature, version and block size in super block
  fs->super->signature = DFS_SIGNATURE;
  fs->super->version = DFS_VERSION;
  fs->super->log_block_size = bits(blocksize);

  // Each group has as many blocks as can be represented by the block bitmap block
  fs->super->blocks_per_group = fs->blocksize * 8;

  // Get the device size in sectors from the device and convert it to blocks
  fs->super->block_count = dev_getsize(fs->devno) / (fs->blocksize / SECTORSIZE);

  // Set cache size
  fs->super->cache_buffers = CACHEBUFFERS;
  if (fs->super->cache_buffers > fs->super->block_count) fs->super->cache_buffers = 64;

  // The number of inodes in a group is computed as a ratio of the size of group
  fs->inodes_per_block = fs->blocksize / sizeof(struct inodedesc);
  if (fs->super->blocks_per_group < fs->super->block_count)
    fs->super->inodes_per_group = fs->blocksize * fs->super->blocks_per_group / inode_ratio;
  else
    fs->super->inodes_per_group = fs->blocksize * fs->super->block_count / inode_ratio;
  if (fs->super->inodes_per_group > fs->blocksize * 8) fs->super->inodes_per_group = fs->blocksize * 8;
  fs->inode_blocks_per_group = (fs->super->inodes_per_group * sizeof(struct inodedesc) + fs->blocksize - 1) / fs->blocksize;

  // Calculate the number of block pointers per block directory page
  fs->log_blkptrs_per_block = fs->super->log_block_size - 2;

  // Calculate the number of group descriptors and the number of blocks to store them
  fs->super->group_count = (fs->super->block_count + fs->super->blocks_per_group - 1) / fs->super->blocks_per_group;
  fs->groupdescs_per_block = fs->blocksize / sizeof(struct groupdesc);
  fs->groupdesc_blocks = (fs->super->group_count * sizeof(struct groupdesc) + fs->blocksize - 1) / fs->blocksize;

  // The reserved blocks are allocated right after the super block
  fs->super->first_reserved_block = 1;
  if (fs->blocksize <= SECTORSIZE) fs->super->first_reserved_block++;
  fs->super->reserved_blocks = RESERVED_BLOCKS;

  // The group descriptor table starts after the superblock and reserved blocks
  fs->super->groupdesc_table_block = fs->super->first_reserved_block + fs->super->reserved_blocks;

  // If the last group is too small to hold the bitmaps and inode table skip it
  blocks =  fs->super->block_count % fs->super->blocks_per_group;
  if (blocks > 0 && blocks < fs->inode_blocks_per_group + 2) fs->super->group_count--;
  if (fs->super->group_count == 0) panic("filesystem too small");

  // Zero all blocks on disk
  if (!quick)
  {
    buffer = (char *) malloc(fs->blocksize);
    memset(buffer, 0, fs->blocksize);

    for (i = fs->super->groupdesc_table_block + fs->groupdesc_blocks; i < fs->super->block_count; i++)
    {
      dev_write(fs->devno, buffer, fs->blocksize, i);
    }

    free(buffer);
  }

  // Allocate group descriptors
  fs->groupdesc_buffers = (struct buf **) malloc(sizeof(struct buf *) * fs->groupdesc_blocks);
  fs->groups = (struct group *) malloc(sizeof(struct group) * fs->super->group_count);

  for (i = 0; i < fs->groupdesc_blocks; i++)
  {
    fs->groupdesc_buffers[i] = alloc_buffer(fs->cache, fs->super->groupdesc_table_block + i);
  }

  for (i = 0; i < fs->super->group_count; i++)
  {
    gd = (struct groupdesc *) fs->groupdesc_buffers[i / fs->groupdescs_per_block]->data;
    gd += (i % fs->groupdescs_per_block);

    fs->groups[i].desc = gd;
    fs->groups[i].first_free_block = 0;
    fs->groups[i].first_free_inode = 0;
  }

  // Reserve inode for root directory
  fs->super->reserved_inodes = RESERVED_INODES;

  // Set inode count based on group count
  fs->super->inode_count = fs->super->inodes_per_group * fs->super->group_count;

  // All blocks and inodes initially free
  fs->super->free_inode_count = fs->super->inode_count;
  fs->super->free_block_count = fs->super->block_count;

  // Initialize block bitmaps
  for (i = 0; i < fs->super->group_count; i++)
  {
    gd = fs->groups[i].desc;
    blocks = 0;
    first_block = fs->super->blocks_per_group * i;

    // The first group needs blocks for the super block and the group descriptors
    if (i == 0) blocks = fs->super->groupdesc_table_block + fs->groupdesc_blocks;

    // Next blocks in group are the block bitmap, inode bitmap and the inode table
    gd->block_bitmap_block = first_block + blocks++;
    gd->inode_bitmap_block = first_block + blocks++;
    gd->inode_table_block = first_block + blocks;
    blocks += fs->inode_blocks_per_group;

    // Update block bitmap
    buf = alloc_buffer(fs->cache, gd->block_bitmap_block);
    set_bits(buf->data, 0, blocks);
    mark_buffer_updated(buf);
    release_buffer(fs->cache, buf);

    // Determine the block count for the group. The last group may be truncated
    if (fs->super->blocks_per_group * (i + 1) > fs->super->block_count)
      gd->block_count = fs->super->block_count - fs->super->blocks_per_group * i;
    else
      gd->block_count = fs->super->blocks_per_group;

    // Set the count of free blocks and inodes for group
    gd->free_inode_count = fs->super->inodes_per_group;
    gd->free_block_count = gd->block_count - blocks;

    // Update super block
    fs->super->free_block_count -= blocks;

    mark_group_desc_dirty(fs, i);
  }

  // Zero out block and inode bitmaps and inode tables
  if (quick)
  {
    buffer = (char *) malloc(fs->blocksize);
    memset(buffer, 0, fs->blocksize);

    for (i = 0; i < fs->super->group_count; i++)
    {
      gd = fs->groups[i].desc;

      dev_write(fs->devno, buffer, fs->blocksize, gd->block_bitmap_block);
      dev_write(fs->devno, buffer, fs->blocksize, gd->inode_bitmap_block);
      for (j = 0; j < fs->inode_blocks_per_group; j++)
      {
        dev_write(fs->devno, buffer, fs->blocksize, gd->inode_table_block + j);
      }
    }

    free(buffer);
  }

  // Reserve inodes
  for (i = 0; i < RESERVED_INODES; i++)
  {
    ino = new_inode(fs, 0, 0);
    if (ino != i) panic("unexpected inode");
  }

  // Create root directory
  root = get_inode(fs, DFS_INODE_ROOT);
  root->desc->mode = VFS_S_IFDIR | VFS_S_IRWXU | VFS_S_IRWXG | VFS_S_IRWXO;
  root->desc->ctime = root->desc->mtime = time(NULL);
  root->desc->linkcount = 1;
  mark_buffer_updated(root->buf);
  release_inode(root);

  return fs;
}
Exemple #25
0
static IDCOffer_clp Mount_m(MountLocal_cl     *self, 
			    IDCOffer_clp       drive,
			    uint32_t           partition,
			    MountLocal_Options options, 
			    Context_clp        settings)
{
    IDCOffer_clp  res;
    ext2fs_st	 *st;
    Type_Any      any;
    Heap_clp      heap;
    struct inode *root            = NULL;
    uint32_t      blockcache_size = 1024*128; /* Size of blockcache in bytes */
    CSClientStubMod_cl *stubmod_clp; 


    TRC(printf("ext2fs: mount %d from %p\n", partition, drive));
    /* It's probably a good idea to have a separate heap for the filesystem.
       For now let's just use Pvs(heap), but eventually create a stretch
       of our own. */

    heap = Pvs(heap);

    if(!(st = Heap$Malloc(heap, sizeof(*st)))) {
	fprintf(stderr, "ext2fs: cannot allocate state.\n");
	RAISE_MountLocal$Failure();
    }

    /* Where is this declared? */
    bzero(st, sizeof(*st));

    /* Fill in the fields that we can initialise without accessing the
       filesystem */
    st->heap = heap;

    st->entrymod     = NAME_FIND("modules>EntryMod", EntryMod_clp);
    st->shmtransport = NAME_FIND("modules>ShmTransport", IDCTransport_clp);
    st->csidc        = NAME_FIND("modules>CSIDCTransport", CSIDCTransport_clp);


    st->client.entry = Pvs(entry);
    /* It's not clearn how many entries we are going to require yet
       We probably want separate ones for the USDCallback and the
       FSClient offers. We need to arrange that the entry threads die
       properly when the FS is unmounted. */


    /* Interpret mount flags */
    st->fs.readonly = SET_IN(options,MountLocal_Option_ReadOnly);
    st->fs.debug    = SET_IN(options,MountLocal_Option_Debug);


    /* Place the drive in the state. */
    st->disk.partition     = partition;
    st->disk.drive_offer   = drive;
    st->disk.drive_binding = IDCOffer$Bind(drive, Pvs(gkpr), &any);
    st->disk.usddrive      = NARROW(&any, USDDrive_clp);

 
    TRC(printf("ext2fs: state at [%p, %p]\n",st, (void *)st + sizeof(*st)));
    DBO(printf("ext2fs: debugging output is switched on\n"));

    /* Connect to the disk */
    init_usd(st);

    /* We need a stretch shared between us and the USD to allow us to read
       and write metadata. We'll use this stretch as a cache of blocks read
       from the disk. Because we won't know the blocksize until we have
       managed to read the superblock, we'd better make this buffer a
       multiple of 8k long (8k is currently the maximum blocksize). */

    st->cache.str = Gatekeeper$GetStretch(Pvs(gkpr), IDCOffer$PDID(drive), 
					  blockcache_size, 
					  SET_ELEM(Stretch_Right_Read) |
					  SET_ELEM(Stretch_Right_Write), 
					  PAGE_WIDTH, PAGE_WIDTH);
    st->cache.buf = STR_RANGE(st->cache.str, &st->cache.size);

    TRC(printf("ext2fs: buf is %d bytes at %p\n", st->cache.size,
	       st->cache.buf));
    if (st->cache.size < blockcache_size) {
	printf("ext2fs: warning: couldn't allocate a large blockcache\n");
    }

    /* Now we can get at the disk. Read the superblock, and calculate
       constants from it. */
    if (!read_superblock(st)) {
	printf("ext2fs: couldn't read superblock\n");
	shutdown_usd(st);
	RAISE_MountLocal$BadFS(MountLocal_Problem_BadSuperblock);
    }

    /* XXX should sanity check filesystem size with partition size */
    TRC(printf("ext2fs: filesystem size %d blocks (%d phys)\n"
	   "	    partition size %d blocks (%d phys)\n",
	   st->superblock->s_blocks_count,
	   PHYS_BLKS(st, st->superblock->s_blocks_count),
	   LOGICAL_BLKS(st, st->disk.partition_size),
	   st->disk.partition_size));
    if (st->disk.partition_size < 
	PHYS_BLKS(st, st->superblock->s_blocks_count)) {
	printf("WARNING - filesystem is larger than partition **********\n");
	/* XXX should probably give up now */
    }

    /* Now that we know the logical block size we can initialise the block
       cache */
    init_block_cache(st);

    /* From this point on, all access to the filesystem should be done
       through the block cache. DON'T call logical_read, call bread
       instead. Remember to free blocks once you're finished with them. */

    init_groups(st);

    if(!init_inodes(st)) {
	fprintf(stderr, "ext2fs: failed to initialise inode cache.\n");
	shutdown_usd(st);
	RAISE_MountLocal$Failure();
    }

    /* Checking this probably isn't a bad idea, but let's wait until later */

    /* Ok, now we are capable of reading the root inode (I hope!) */
    TRC(printf("ext2fs: checking root inode.\n"));
    root = get_inode(st, EXT2_ROOT_INO);
    if(!root) {
	fprintf(stderr, "ext2fs: failed to read root inode.\n");
	shutdown_usd(st);
	RAISE_MountLocal$BadFS(MountLocal_Problem_BadRoot);
    }
    
    if(!S_ISDIR(root->i_mode)) {
	fprintf(stderr, "ext2fs: urk!\n"
		"	 inode %d does not refer to a directory\n", 
		EXT2_ROOT_INO);
	shutdown_usd(st);
	RAISE_MountLocal$BadFS(MountLocal_Problem_BadRoot);
    }

    release_inode(st, root);

    /* *thinks* should probably do something about deallocating state
       if we fail, too. */

    /* Initialise the list of clients */
    LINK_INIT(&st->client.clients);
    /* We create a server for the local domain; it lives in the head
       of the list of clients. The call to CSIDCTransport$Offer() will
       set up client-side stubs for this domain and put them in the
       object table. */
    create_client(st, &st->client.clients, NULL);

    /* Now we do all the export stuff */
    CL_INIT(st->client.callback, &client_callback_ms, st);
    ANY_INIT(&any, Ext2_clp, &st->client.clients.cl);
    stubmod_clp = Heap$Malloc(st->heap, sizeof(*stubmod_clp)); 
    CLP_INIT(stubmod_clp, &stubmod_ms, NULL);
    res = CSIDCTransport$Offer (
	st->csidc, &any, FSClient_clp__code, stubmod_clp,
	&st->client.callback, /* XXX produces a warning */
	st->heap, Pvs(gkpr), st->client.entry, &st->client.service);

    TRC(printf("ext2fs: offer at %p\n",res));

    return res;
}
Exemple #26
0
static int create_always(struct filsys *fs, char *name, int mode, struct inode **retval) {
  struct inode *dir;
  struct inode *inode;
  struct inode *oldinode;
  ino_t oldino;
  int rc;
  int len = strlen(name);

  rc = diri(fs, &name, &len, &dir);
  if (rc < 0) return rc;

  rc = find_dir_entry(dir, name, len, &oldino);
  if (rc == 0) {
    rc = get_inode(fs, oldino, &oldinode);
    if (rc < 0) {
      release_inode(dir);
      return rc;
    }

    if (S_ISDIR(oldinode->desc->mode) && oldinode->desc->linkcount == 1) {
      release_inode(dir);
      return -EISDIR;
    }

    inode = alloc_inode(dir, S_IFREG | (mode & S_IRWXUGO));
    if (!inode) {
      release_inode(dir);
      return -ENOSPC;
    }

    rc = modify_dir_entry(dir, name, len, inode->ino, NULL);
    if (rc < 0) {
      unlink_inode(inode);
      release_inode(inode);
      release_inode(dir);
      return rc;
    }

    unlink_inode(oldinode);
    release_inode(oldinode);
  } else if (rc == -ENOENT) {
    inode = alloc_inode(dir, S_IFREG | (mode & S_IRWXUGO));
    if (!inode) {
      release_inode(dir);
      return -ENOSPC;
    }

    rc = add_dir_entry(dir, name, len, inode->ino);
    if (rc < 0) {
      unlink_inode(inode);
      release_inode(inode);
      release_inode(dir);
      return rc;
    }
  } else {
    release_inode(dir);
    return rc;
  }

  release_inode(dir);
  *retval = inode;
  return 0;
}