Exemplo n.º 1
0
int fat_directory_expand(fat_directory_t *di)
{
	int rc;
	fat_cluster_t mcl, lcl;

	if (!FAT_IS_FAT32(di->bs) && di->nodep->firstc == FAT_CLST_ROOT) {
		/* Can't grow the root directory on FAT12/16. */
		return ENOSPC;
	}
	rc = fat_alloc_clusters(di->bs, di->nodep->idx->service_id, 1, &mcl,
	    &lcl);
	if (rc != EOK)
		return rc;
	rc = fat_zero_cluster(di->bs, di->nodep->idx->service_id, mcl);
	if (rc != EOK) {
		(void) fat_free_clusters(di->bs, di->nodep->idx->service_id,
		    mcl);
		return rc;
	}
	rc = fat_append_clusters(di->bs, di->nodep, mcl, lcl);
	if (rc != EOK) {
		(void) fat_free_clusters(di->bs, di->nodep->idx->service_id,
		    mcl);
		return rc;
	}
	di->nodep->size += BPS(di->bs) * SPC(di->bs);
	di->nodep->dirty = true;		/* need to sync node */
	di->blocks = di->nodep->size / BPS(di->bs);
	
	return EOK;
}
Exemplo n.º 2
0
/***** Make a directory */
static int vxext_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
	struct super_block *sb = dir->i_sb;
	struct fat_slot_info sinfo;
	struct inode *inode;
	unsigned char msdos_name[MSDOS_NAME];
	struct timespec ts;
	int err, is_hid, cluster;

	mutex_lock(&MSDOS_SB(sb)->s_lock);

	err = vxext_format_name(dentry->d_name.name, dentry->d_name.len,
				msdos_name, &MSDOS_SB(sb)->options);
	if (err)
		goto out;
	is_hid = (dentry->d_name.name[0] == '.') && (msdos_name[0] != '.');
	/* foo vs .foo situation */
	if (!fat_scan(dir, msdos_name, &sinfo)) {
		brelse(sinfo.bh);
		err = -EINVAL;
		goto out;
	}

	ts = CURRENT_TIME_SEC;
	cluster = fat_alloc_new_dir(dir, &ts);
	if (cluster < 0) {
		err = cluster;
		goto out;
	}
	err = vxext_add_entry(dir, msdos_name, 1, is_hid, cluster, &ts, &sinfo);
	if (err)
		goto out_free;
	inc_nlink(dir);

	inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
	brelse(sinfo.bh);
	if (IS_ERR(inode)) {
		err = PTR_ERR(inode);
		/* the directory was completed, just return a error */
		goto out;
	}
	set_nlink(inode, 2);
	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
	/* timestamp is already written, so mark_inode_dirty() is unneeded. */

	d_instantiate(dentry, inode);

	mutex_unlock(&MSDOS_SB(sb)->s_lock);
	fat_flush_inodes(sb, dir, inode);
	return 0;

out_free:
	fat_free_clusters(dir, cluster);
out:
	mutex_unlock(&MSDOS_SB(sb)->s_lock);
	return err;
}
Exemplo n.º 3
0
static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
	struct super_block *sb = dir->i_sb;
	struct fat_slot_info sinfo;
	struct inode *inode;
	unsigned char msdos_name[MSDOS_NAME];
	struct timespec ts;
	int err, is_hid, cluster;

	lock_super(sb);

	err = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
				msdos_name, &MSDOS_SB(sb)->options);
	if (err)
		goto out;
	is_hid = (dentry->d_name.name[0] == '.') && (msdos_name[0] != '.');
	/*                       */
	if (!fat_scan(dir, msdos_name, &sinfo)) {
		brelse(sinfo.bh);
		err = -EINVAL;
		goto out;
	}

	ts = CURRENT_TIME_SEC;
	cluster = fat_alloc_new_dir(dir, &ts);
	if (cluster < 0) {
		err = cluster;
		goto out;
	}
	err = msdos_add_entry(dir, msdos_name, 1, is_hid, cluster, &ts, &sinfo);
	if (err)
		goto out_free;
	inc_nlink(dir);

	inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
	brelse(sinfo.bh);
	if (IS_ERR(inode)) {
		err = PTR_ERR(inode);
		/*                                                  */
		goto out;
	}
	set_nlink(inode, 2);
	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
	/*                                                                  */

	d_instantiate(dentry, inode);

	unlock_super(sb);
	fat_flush_inodes(sb, dir, inode);
	return 0;

out_free:
	fat_free_clusters(dir, cluster);
out:
	unlock_super(sb);
	return err;
}
Exemplo n.º 4
0
static long fat_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
{      
	int err = 0;
	struct inode *inode = file->f_mapping->host;
	int cluster, nr_cluster, fclus, dclus, free_bytes, nr_bytes;
	struct super_block *sb = inode->i_sb;
	struct msdos_sb_info *sbi = MSDOS_SB(sb);
	if (mode & ~FALLOC_FL_KEEP_SIZE)
		return -EOPNOTSUPP;
	if ((offset + len) <= MSDOS_I(inode)->mmu_private) {
		fat_msg(sb, KERN_ERR,
				"fat_fallocate():Blocks already allocated");
		return -EINVAL;
	}
	if ((mode & FALLOC_FL_KEEP_SIZE)) {
		if (inode->i_size > 0) {
			err = fat_get_cluster(inode, FAT_ENT_EOF,
					&fclus, &dclus);
			if (err < 0) {
				fat_msg(sb, KERN_ERR,
						"fat_fallocate():fat_get_cluster() error");
				return err;
			}
			free_bytes = ((fclus+1) << sbi->cluster_bits) -
				(inode->i_size);
			nr_bytes = (offset + len - inode->i_size) - free_bytes;
		} else
			nr_bytes = (offset + len - inode->i_size);
		nr_cluster = (nr_bytes + (sbi->cluster_size - 1)) >>
			sbi->cluster_bits;
		mutex_lock(&inode->i_mutex);
		while (nr_cluster-- > 0) {
			err = fat_alloc_clusters(inode, &cluster, 1);
			if (err) {
				fat_msg(sb, KERN_ERR,
						"fat_fallocate():fat_alloc_clusters() error");
				goto error;
			}
			err = fat_chain_add(inode, cluster, 1);
			if (err) {
				fat_free_clusters(inode, cluster);
				goto error;
			}
		}
		err = fat_get_cluster(inode, FAT_ENT_EOF, &fclus, &dclus);
		if (err < 0) {
			fat_msg(sb, KERN_ERR,
					"fat_fallocate():fat_get_cluster() error");
			goto error;
		}
		MSDOS_I(inode)->mmu_private = (fclus + 1) << sbi->cluster_bits;
	} else {
Exemplo n.º 5
0
static int
fatfs_remove(vnode_t dvp, vnode_t vp, char *name)
{
    struct fatfsmount *fmp;
    struct fatfs_node np;
    struct fat_dirent *de;
    int error;

    if (*name == '\0')
        return ENOENT;

    fmp = dvp->v_mount->m_data;
    mutex_lock(&fmp->lock);

    error = fatfs_lookup_node(dvp, name, &np);
    if (error)
        goto out;
    de = &np.dirent;
    if (IS_DIR(de)) {
        error = EISDIR;
        goto out;
    }
    if (!IS_FILE(de)) {
        error = EPERM;
        goto out;
    }

    /* Remove clusters */
    error = fat_free_clusters(fmp, (de->cluster_hi << 16) | de->cluster);
    if (error)
        goto out;

    /* remove directory */
    de->name[0] = 0xe5;
    error = fatfs_put_node(fmp, &np);
out:
    mutex_unlock(&fmp->lock);
    return error;
}
Exemplo n.º 6
0
static int
fatfs_truncate(vnode_t vp, off_t length)
{
    struct fatfsmount *fmp;
    struct fatfs_node *np;
    struct fat_dirent *de;
    int error;

    fmp = vp->v_mount->m_data;
    mutex_lock(&fmp->lock);

    np = vp->v_data;
    de = &np->dirent;

    if (length == 0) {
        /* Remove clusters */
        error = fat_free_clusters(fmp, (de->cluster_hi << 16) | de->cluster);
        if (error)
            goto out;
    } else if (length > vp->v_size) {
        error = fat_expand_file(fmp, vp->v_blkno, length);
        if (error) {
            error = EIO;
            goto out;
        }
    }

    /* Update directory entry */
    de->size = length;
    error = fatfs_put_node(fmp, np);
    if (error)
        goto out;
    vp->v_size = length;
out:
    mutex_unlock(&fmp->lock);
    return error;
}
Exemplo n.º 7
0
Arquivo: fat.c Projeto: mitlab/oggbox
int fat_open(const char *name, int flags, int mode, int *rerrno) {
  int i;
  int8_t fd;
  (*rerrno) = 0;
  
//   printf("fat_open(%s, %x)\n", name, flags);
  fd = fat_get_next_file();
  if(fd < 0) {
    (*rerrno) = ENFILE;
    return -1;   /* too many open files */
  }

//   printf("Lookup path\n");
  i = fat_lookup_path(fd, name, rerrno);
  if((flags & O_RDWR)) {
    file_num[fd].flags |= (FAT_FLAG_READ | FAT_FLAG_WRITE);
  } else {
    if((flags & O_WRONLY) == 0) {
      file_num[fd].flags |= FAT_FLAG_READ;
    } else {
      file_num[fd].flags |= FAT_FLAG_WRITE;
    }
  }
  
  if(flags & O_APPEND) {
    file_num[fd].flags |= FAT_FLAG_APPEND;
  }
  if((i == -1) && ((*rerrno) == ENOENT)) {
    /* file doesn't exist */
    if((flags & (O_CREAT)) == 0) {
      /* tried to open a non-existent file with no create */
      file_num[fd].flags = 0;
      (*rerrno) = ENOENT;
      return -1;
    } else {
      /* opening a new file for writing */
      /* only create files in directories that aren't read only */
      if(fatfs.read_only) {
        file_num[fd].flags = 0;
        (*rerrno) = EROFS;
        return -1;
      }
      /* create an empty file structure ready for use */
      file_num[fd].sector = 0;
      file_num[fd].cluster = 0;
      file_num[fd].sectors_left = 0;
      file_num[fd].cursor = 0;
      file_num[fd].error = 0;
      if(mode & S_IWUSR) {
        file_num[fd].attributes = 0;
      } else {
        file_num[fd].attributes = FAT_ATT_RO;
      }
      file_num[fd].size = 0;
      file_num[fd].full_first_cluster = 0;
      file_num[fd].entry_sector = 0;
      file_num[fd].entry_number = 0;
      file_num[fd].file_sector = 0;
      file_num[fd].created = time(NULL);
      file_num[fd].modified = 0;
      file_num[fd].accessed = 0;
      
      memset(file_num[fd].buffer, 0, 512);
      
      file_num[fd].flags |= FAT_FLAG_FS_DIRTY;
      (*rerrno) = 0;    /* file not found but we're aloud to create it so success */
      return fd;
    }
  } else if(i == 0) {
    /* file does exist */
    if(flags & (O_CREAT | O_EXCL)) {
      /* tried to force creation of an existing file */
      file_num[fd].flags = 0;
      (*rerrno) = EEXIST;
      return -1;
    } else {
      if((flags & (O_WRONLY | O_RDWR)) == 0) {
        /* read existing file */
        file_num[fd].file_sector = 0;
        return fd;
      } else {
        /* file opened for write access, check permissions */
        if(fatfs.read_only) {
          /* requested write on read only filesystem */
          file_num[fd].flags = 0;
          (*rerrno) = EROFS;
          return -1;
        }
        if(file_num[fd].attributes & FAT_ATT_RO) {
          /* The file is read-only refuse permission */
          file_num[fd].flags = 0;
          (*rerrno) = EACCES;
          return -1;
        }
        if(file_num[fd].attributes & FAT_ATT_SUBDIR) {
          /* Tried to open a directory for writing */
          file_num[fd].flags = 0;
          (*rerrno) = EISDIR;
          return -1;
        }
        if(flags & O_TRUNC) {
          /* Need to truncate the file to zero length */
          fat_free_clusters(file_num[fd].full_first_cluster);
          file_num[fd].size = 0;
          file_num[fd].full_first_cluster = 0;
          file_num[fd].sector = 0;
          file_num[fd].cluster = 0;
          file_num[fd].sectors_left = 0;
          file_num[fd].file_sector = 0;
          file_num[fd].created = time(NULL);
          file_num[fd].modified = time(NULL);
          file_num[fd].flags |= FAT_FLAG_FS_DIRTY;
        }
        file_num[fd].file_sector = 0;
        return fd;
      }
    }
  } else {
    file_num[fd].flags = 0;
    return -1;
  }
}
Exemplo n.º 8
0
/* Free all clusters after the skip'th cluster. */
static int fat_free(struct inode *inode, int skip)
{
	struct super_block *sb = inode->i_sb;
	int err, wait, free_start, i_start, i_logstart;

	if (MSDOS_I(inode)->i_start == 0)
		return 0;

	fat_cache_inval_inode(inode);

	wait = IS_DIRSYNC(inode);
	i_start = free_start = MSDOS_I(inode)->i_start;
	i_logstart = MSDOS_I(inode)->i_logstart;

	/* First, we write the new file size. */
	if (!skip) {
		MSDOS_I(inode)->i_start = 0;
		MSDOS_I(inode)->i_logstart = 0;
	}
	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
	inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
	if (wait) {
		err = fat_sync_inode(inode);
		if (err) {
			MSDOS_I(inode)->i_start = i_start;
			MSDOS_I(inode)->i_logstart = i_logstart;
			return err;
		}
	} else
		mark_inode_dirty(inode);

	/* Write a new EOF, and get the remaining cluster chain for freeing. */
	if (skip) {
		struct fat_entry fatent;
		int ret, fclus, dclus;

		ret = fat_get_cluster(inode, skip - 1, &fclus, &dclus);
		if (ret < 0)
			return ret;
		else if (ret == FAT_ENT_EOF)
			return 0;

		fatent_init(&fatent);
		ret = fat_ent_read(inode, &fatent, dclus);
		if (ret == FAT_ENT_EOF) {
			fatent_brelse(&fatent);
			return 0;
		} else if (ret == FAT_ENT_FREE) {
			fat_fs_panic(sb,
				     "%s: invalid cluster chain (i_pos %lld)",
				     __FUNCTION__, MSDOS_I(inode)->i_pos);
			ret = -EIO;
		} else if (ret > 0) {
			err = fat_ent_write(inode, &fatent, FAT_ENT_EOF, wait);
			if (err)
				ret = err;
		}
		fatent_brelse(&fatent);
		if (ret < 0)
			return ret;

		free_start = ret;
	}
	inode->i_blocks = skip << (MSDOS_SB(sb)->cluster_bits - 9);

	/* Freeing the remained cluster chain */
	return fat_free_clusters(inode, free_start);
}