Example #1
0
static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
{
	const unsigned char *name = dentry->d_name.name;
	unsigned len = dentry->d_name.len;
	struct inode *result = NULL;
	struct buffer_head *bh;
	struct fnode *fnode;
	fnode_secno fno;
	int r;
	struct hpfs_dirent dee;
	int err;
	if ((err = hpfs_chk_name(name, &len)))
		return err==-ENOENT ? -EINVAL : err;
	lock_kernel();
	err = -ENOSPC;
	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
	if (!fnode)
		goto bail;
	memset(&dee, 0, sizeof dee);
	if (!(mode & 0222)) dee.read_only = 1;
	dee.archive = 1;
	dee.hidden = name[0] == '.';
	dee.fnode = fno;
	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());

	result = new_inode(dir->i_sb);
	if (!result)
		goto bail1;

	hpfs_init_inode(result);
	result->i_ino = fno;
	result->i_mode |= S_IFREG;
	result->i_mode &= ~0111;
	result->i_op = &hpfs_file_iops;
	result->i_fop = &hpfs_file_ops;
	result->i_nlink = 1;
	hpfs_decide_conv(result, name, len);
	hpfs_i(result)->i_parent_dir = dir->i_ino;
	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
	result->i_ctime.tv_nsec = 0;
	result->i_mtime.tv_nsec = 0;
	result->i_atime.tv_nsec = 0;
	hpfs_i(result)->i_ea_size = 0;
	if (dee.read_only)
		result->i_mode &= ~0222;
	result->i_blocks = 1;
	result->i_size = 0;
	result->i_data.a_ops = &hpfs_aops;
	hpfs_i(result)->mmu_private = 0;

	mutex_lock(&hpfs_i(dir)->i_mutex);
	r = hpfs_add_dirent(dir, name, len, &dee, 0);
	if (r == 1)
		goto bail2;
	if (r == -1) {
		err = -EEXIST;
		goto bail2;
	}
	fnode->len = len;
	memcpy(fnode->name, name, len > 15 ? 15 : len);
	fnode->up = dir->i_ino;
	mark_buffer_dirty(bh);
	brelse(bh);

	insert_inode_hash(result);

	if (result->i_uid != current_fsuid() ||
	    result->i_gid != current_fsgid() ||
	    result->i_mode != (mode | S_IFREG)) {
		result->i_uid = current_fsuid();
		result->i_gid = current_fsgid();
		result->i_mode = mode | S_IFREG;
		hpfs_write_inode_nolock(result);
	}
	d_instantiate(dentry, result);
	mutex_unlock(&hpfs_i(dir)->i_mutex);
	unlock_kernel();
	return 0;

bail2:
	mutex_unlock(&hpfs_i(dir)->i_mutex);
	iput(result);
bail1:
	brelse(bh);
	hpfs_free_sectors(dir->i_sb, fno, 1);
bail:
	unlock_kernel();
	return err;
}
Example #2
0
static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
		struct inode *new_dir, struct dentry *new_dentry)
{
	const unsigned char *old_name = old_dentry->d_name.name;
	unsigned old_len = old_dentry->d_name.len;
	const unsigned char *new_name = new_dentry->d_name.name;
	unsigned new_len = new_dentry->d_name.len;
	struct inode *i = old_dentry->d_inode;
	struct inode *new_inode = new_dentry->d_inode;
	struct quad_buffer_head qbh, qbh1;
	struct hpfs_dirent *dep, *nde;
	struct hpfs_dirent de;
	dnode_secno dno;
	int r;
	struct buffer_head *bh;
	struct fnode *fnode;
	int err;
	if ((err = hpfs_chk_name(new_name, &new_len))) return err;
	err = 0;
	hpfs_adjust_length(old_name, &old_len);

	lock_kernel();
	/* order doesn't matter, due to VFS exclusion */
	mutex_lock(&hpfs_i(i)->i_parent_mutex);
	if (new_inode)
		mutex_lock(&hpfs_i(new_inode)->i_parent_mutex);
	mutex_lock(&hpfs_i(old_dir)->i_mutex);
	if (new_dir != old_dir)
		mutex_lock(&hpfs_i(new_dir)->i_mutex);

	/* Erm? Moving over the empty non-busy directory is perfectly legal */
	if (new_inode && S_ISDIR(new_inode->i_mode)) {
		err = -EINVAL;
		goto end1;
	}

	if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) {
		hpfs_error(i->i_sb, "lookup succeeded but map dirent failed");
		err = -ENOENT;
		goto end1;
	}
	copy_de(&de, dep);
	de.hidden = new_name[0] == '.';

	if (new_inode) {
		int r;
		if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 1)) != 2) {
			if ((nde = map_dirent(new_dir, hpfs_i(new_dir)->i_dno, new_name, new_len, NULL, &qbh1))) {
				clear_nlink(new_inode);
				copy_de(nde, &de);
				memcpy(nde->name, new_name, new_len);
				hpfs_mark_4buffers_dirty(&qbh1);
				hpfs_brelse4(&qbh1);
				goto end;
			}
			hpfs_error(new_dir->i_sb, "hpfs_rename: could not find dirent");
			err = -EFSERROR;
			goto end1;
		}
		err = r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
		goto end1;
	}

	if (new_dir == old_dir) hpfs_brelse4(&qbh);

	hpfs_lock_creation(i->i_sb);
	if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de, 1))) {
		hpfs_unlock_creation(i->i_sb);
		if (r == -1) hpfs_error(new_dir->i_sb, "hpfs_rename: dirent already exists!");
		err = r == 1 ? -ENOSPC : -EFSERROR;
		if (new_dir != old_dir) hpfs_brelse4(&qbh);
		goto end1;
	}

	if (new_dir == old_dir)
		if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) {
			hpfs_unlock_creation(i->i_sb);
			hpfs_error(i->i_sb, "lookup succeeded but map dirent failed at #2");
			err = -ENOENT;
			goto end1;
		}

	if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 0))) {
		hpfs_unlock_creation(i->i_sb);
		hpfs_error(i->i_sb, "hpfs_rename: could not remove dirent");
		err = r == 2 ? -ENOSPC : -EFSERROR;
		goto end1;
	}
	hpfs_unlock_creation(i->i_sb);

	end:
	hpfs_i(i)->i_parent_dir = new_dir->i_ino;
	if (S_ISDIR(i->i_mode)) {
		inc_nlink(new_dir);
		drop_nlink(old_dir);
	}
	if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
		fnode->up = new_dir->i_ino;
		fnode->len = new_len;
		memcpy(fnode->name, new_name, new_len>15?15:new_len);
		if (new_len < 15) memset(&fnode->name[new_len], 0, 15 - new_len);
		mark_buffer_dirty(bh);
		brelse(bh);
	}
	hpfs_i(i)->i_conv = hpfs_sb(i->i_sb)->sb_conv;
	hpfs_decide_conv(i, new_name, new_len);
end1:
	if (old_dir != new_dir)
		mutex_unlock(&hpfs_i(new_dir)->i_mutex);
	mutex_unlock(&hpfs_i(old_dir)->i_mutex);
	mutex_unlock(&hpfs_i(i)->i_parent_mutex);
	if (new_inode)
		mutex_unlock(&hpfs_i(new_inode)->i_parent_mutex);
	unlock_kernel();
	return err;
}
Example #3
0
File: dir.c Project: 274914765/C
struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
    const char *name = dentry->d_name.name;
    unsigned len = dentry->d_name.len;
    struct quad_buffer_head qbh;
    struct hpfs_dirent *de;
    ino_t ino;
    int err;
    struct inode *result = NULL;
    struct hpfs_inode_info *hpfs_result;

    lock_kernel();
    if ((err = hpfs_chk_name((char *)name, &len))) {
        if (err == -ENAMETOOLONG) {
            unlock_kernel();
            return ERR_PTR(-ENAMETOOLONG);
        }
        goto end_add;
    }

    /*
     * '.' and '..' will never be passed here.
     */

    de = map_dirent(dir, hpfs_i(dir)->i_dno, (char *) name, len, NULL, &qbh);

    /*
     * This is not really a bailout, just means file not found.
     */

    if (!de) goto end;

    /*
     * Get inode number, what we're after.
     */

    ino = de->fnode;

    /*
     * Go find or make an inode.
     */

    result = iget_locked(dir->i_sb, ino);
    if (!result) {
        hpfs_error(dir->i_sb, "hpfs_lookup: can't get inode");
        goto bail1;
    }
    if (result->i_state & I_NEW) {
        hpfs_init_inode(result);
        if (de->directory)
            hpfs_read_inode(result);
        else if (de->ea_size && hpfs_sb(dir->i_sb)->sb_eas)
            hpfs_read_inode(result);
        else {
            result->i_mode |= S_IFREG;
            result->i_mode &= ~0111;
            result->i_op = &hpfs_file_iops;
            result->i_fop = &hpfs_file_ops;
            result->i_nlink = 1;
        }
        unlock_new_inode(result);
    }
    hpfs_result = hpfs_i(result);
    if (!de->directory) hpfs_result->i_parent_dir = dir->i_ino;

    hpfs_decide_conv(result, (char *)name, len);

    if (de->has_acl || de->has_xtd_perm) if (!(dir->i_sb->s_flags & MS_RDONLY)) {
        hpfs_error(result->i_sb, "ACLs or XPERM found. This is probably HPFS386. This driver doesn't support it now. Send me some info on these structures");
        goto bail1;
    }

    /*
     * Fill in the info from the directory if this is a newly created
     * inode.
     */

    if (!result->i_ctime.tv_sec) {
        if (!(result->i_ctime.tv_sec = local_to_gmt(dir->i_sb, de->creation_date)))
            result->i_ctime.tv_sec = 1;
        result->i_ctime.tv_nsec = 0;
        result->i_mtime.tv_sec = local_to_gmt(dir->i_sb, de->write_date);
        result->i_mtime.tv_nsec = 0;
        result->i_atime.tv_sec = local_to_gmt(dir->i_sb, de->read_date);
        result->i_atime.tv_nsec = 0;
        hpfs_result->i_ea_size = de->ea_size;
        if (!hpfs_result->i_ea_mode && de->read_only)
            result->i_mode &= ~0222;
        if (!de->directory) {
            if (result->i_size == -1) {
                result->i_size = de->file_size;
                result->i_data.a_ops = &hpfs_aops;
                hpfs_i(result)->mmu_private = result->i_size;
            /*
             * i_blocks should count the fnode and any anodes.
             * We count 1 for the fnode and don't bother about
             * anodes -- the disk heads are on the directory band
             * and we want them to stay there.
             */
                result->i_blocks = 1 + ((result->i_size + 511) >> 9);
            }
        }
    }