Exemple #1
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 #2
0
int dfs_ftruncate(struct file *filp, off64_t size) {
  struct inode *inode;
  int rc;
  unsigned int blocks;
  blkno_t blk;
  struct buf *buf;

  if (size > DFS_MAXFILESIZE) return -EFBIG;

  inode = (struct inode *) filp->data;
  if (S_ISDIR(inode->desc->mode)) return -EISDIR;

  if (size < 0) return -EINVAL;
  if (size == inode->desc->size) return 0;

  blocks = ((size_t) size + inode->fs->blocksize - 1) / inode->fs->blocksize;

  if (size > inode->desc->size) {
    while (inode->desc->blocks < blocks) {
      blk = expand_inode(inode);
      if (blk == NOBLOCK) return -ENOSPC;

      buf = alloc_buffer(inode->fs->cache, blk);
      if (!buf) return -EIO;

      memset(buf->data, 0, inode->fs->blocksize);

      mark_buffer_updated(inode->fs->cache, buf);
      release_buffer(inode->fs->cache, buf);
    }
  } else {
    rc = truncate_inode(inode, blocks);
    if (rc < 0) return rc;
  }

  inode->desc->size = size;
  mark_inode_dirty(inode);

  filp->flags |= F_MODIFIED;

  return 0;
}
Exemple #3
0
int dfs_chsize(struct file *filp, vfs_loff_t size)
{
  struct inode *inode;
  int rc;
  unsigned int blocks;

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

  if (size < 0 || size > inode->desc->size) return -1;

  inode->desc->size = size;
  mark_inode_dirty(inode);

  filp->flags |= F_MODIFIED;
  if (filp->pos > size) filp->pos = size;

  blocks = (size + inode->fs->blocksize - 1) / inode->fs->blocksize;
  rc = truncate_inode(inode, blocks);
  if (rc < 0) return rc;

  return 0;
}
Exemple #4
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 #5
0
int delete_dir_entry(struct inode *dir, char *name, int len)
{
  unsigned int block;
  vfs_blkno_t blk;
  vfs_blkno_t lastblk;
  struct buf *buf;
  char *p;
  struct dentry *de;
  struct dentry *prevde;
  struct dentry *nextde;

  if (len <= 0 || len >= MAXPATH) return -1;
  if (!VFS_S_ISDIR(dir->desc->mode)) return -1;

  for (block = 0; block < dir->desc->blocks; block++)
  {
    blk = get_inode_block(dir, block);
    buf = get_buffer(dir->fs->cache, blk);
    if (!buf) return -1;

    p = buf->data;
    prevde = NULL;
    while (p < buf->data + dir->fs->blocksize)
    {
      de = (struct dentry *) p;

      if (fnmatch(name, len, de->name, de->namelen))
      {
        if (prevde)
        {
          // Merge entry with previous entry
          prevde->reclen += de->reclen;
          memset(de, 0, sizeof(struct dentry) + NAME_ALIGN_LEN(de->namelen));
          mark_buffer_updated(buf);
        }
        else if (de->reclen == dir->fs->blocksize)
        {
          // Block is empty, swap this block with last block and truncate
          if (block != dir->desc->blocks - 1)
          {
            lastblk = get_inode_block(dir, dir->desc->blocks - 1);
            set_inode_block(dir, block, lastblk);
            set_inode_block(dir, dir->desc->blocks - 1, buf->blkno);
          }

          truncate_inode(dir, dir->desc->blocks - 1);
          dir->desc->size -= dir->fs->blocksize;
          mark_buffer_invalid(buf);
        }
        else
        {
          // Merge with next entry
          nextde = (struct dentry *) (p + de->reclen);
          de->ino = nextde->ino;
          de->reclen += nextde->reclen;
          de->namelen = nextde->namelen;
          memcpy(de->name, nextde->name, nextde->namelen); // TODO: should be memmove?
          mark_buffer_updated(buf);
        }

        release_buffer(dir->fs->cache, buf);

        dir->desc->mtime = time(NULL);
        mark_inode_dirty(dir);

        return 0;
      }

      prevde = de;
      p += de->reclen;
    }

    release_buffer(dir->fs->cache, buf);
  }

  return -1;
}
/*===========================================================================*
 *				common_open				     *
 *===========================================================================*/
PRIVATE int common_open(register int oflags, mode_t omode)
{
/* Common code from do_creat and do_open. */

  struct inode *rip, *ldirp;
  int r, b, exist = TRUE;
  dev_t dev;
  mode_t bits;
  off_t pos;
  struct filp *fil_ptr, *filp2;

  /* Remap the bottom two bits of oflags. */
  bits = (mode_t) mode_map[oflags & O_ACCMODE];

  /* See if file descriptor and filp slots are available. */
  if ( (r = get_fd(0, bits, &m_in.fd, &fil_ptr)) != OK) return(r);

  /* If O_CREATE is set, try to make the file. */ 
  if (oflags & O_CREAT) {
  	/* Create a new inode by calling new_node(). */
        omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
    	rip = new_node(&ldirp, user_path, omode, NO_ZONE, oflags&O_EXCL, NULL);
    	r = err_code;
        put_inode(ldirp);
    	if (r == OK) exist = FALSE;      /* we just created the file */
	else if (r != EEXIST) return(r); /* other error */
	else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL 
					    flag is set this is an error */
  } else {
	 /* Scan path name. */
    	if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
  }

  /* Claim the file descriptor and filp slot and fill them in. */
  fp->fp_filp[m_in.fd] = fil_ptr;
  FD_SET(m_in.fd, &fp->fp_filp_inuse);
  fil_ptr->filp_count = 1;
  fil_ptr->filp_ino = rip;
  fil_ptr->filp_flags = oflags;

  /* Only do the normal open code if we didn't just create the file. */
  if (exist) {
  	/* Check protections. */
  	if ((r = forbidden(rip, bits)) == OK) {
  		/* Opening reg. files directories and special files differ. */
	  	switch (rip->i_mode & I_TYPE) {
    		   case I_REGULAR: 
			/* Truncate regular file if O_TRUNC. */
			if (oflags & O_TRUNC) {
				if ((r = forbidden(rip, W_BIT)) !=OK) break;
				truncate_inode(rip, 0);
				wipe_inode(rip);
				/* Send the inode from the inode cache to the
				 * block cache, so it gets written on the next
				 * cache flush.
				 */
				rw_inode(rip, WRITING);
			}
			break;
 
	    	   case I_DIRECTORY: 
			/* Directories may be read but not written. */
			r = (bits & W_BIT ? EISDIR : OK);
			break;

	     	   case I_CHAR_SPECIAL:
     		   case I_BLOCK_SPECIAL:
			/* Invoke the driver for special processing. */
			dev = (dev_t) rip->i_zone[0];
			r = dev_open(dev, who_e, bits | (oflags & ~O_ACCMODE));
			break;

		   case I_NAMED_PIPE:
			oflags |= O_APPEND;	/* force append mode */
			fil_ptr->filp_flags = oflags;
			r = pipe_open(rip, bits, oflags);
			if (r != ENXIO) {
				/* See if someone else is doing a rd or wt on
				 * the FIFO.  If so, use its filp entry so the
				 * file position will be automatically shared.
				 */
				b = (bits & R_BIT ? R_BIT : W_BIT);
				fil_ptr->filp_count = 0; /* don't find self */
				if ((filp2 = find_filp(rip, b)) != NIL_FILP) {
					/* Co-reader or writer found. Use it.*/
					fp->fp_filp[m_in.fd] = filp2;
					filp2->filp_count++;
					filp2->filp_ino = rip;
					filp2->filp_flags = oflags;

					/* i_count was incremented incorrectly
					 * by eatpath above, not knowing that
					 * we were going to use an existing
					 * filp entry.  Correct this error.
					 */
					rip->i_count--;
				} else {
					/* Nobody else found.  Restore filp. */
					fil_ptr->filp_count = 1;
					if (b == R_BIT)
					     pos = rip->i_zone[V2_NR_DZONES+0];
					else
					     pos = rip->i_zone[V2_NR_DZONES+1];
					fil_ptr->filp_pos = pos;
				}
			}
			break;
 		}
  	}
  }

  /* If error, release inode. */
  if (r != OK) {
	if (r == SUSPEND) return(r);		/* Oops, just suspended */
	fp->fp_filp[m_in.fd] = NIL_FILP;
  	FD_CLR(m_in.fd, &fp->fp_filp_inuse);
	fil_ptr->filp_count= 0;
	put_inode(rip);
	return(r);
  }
  
  return(m_in.fd);
}