예제 #1
0
파일: namei.c 프로젝트: dzavalishin/oskit
static int
affs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
{
	unsigned int (*toupper)(unsigned int) = affs_toupper;
	int	 alen = a->len;
	int      blen = b->len;
	int	 i;

	/* 'a' is the qstr of an already existing dentry, so the name
	 * must be valid. 'b' must be validated first.
	 */
	
	if (affs_check_name(b->name,b->len))
		return 1;

	/* If the names are longer than the allowed 30 chars,
	 * the excess is ignored, so their length may differ.
	 */
	if (alen > 30)
		alen = 30;
	if (blen > 30)
		blen = 30;
	if (alen != blen)
		return 1;

	/* Check whether to use the international 'toupper' routine */
	if (AFFS_I2FSTYPE(dentry->d_inode))
		toupper = affs_intl_toupper;

	for (i = 0; i < alen; i++)
		if (toupper(a->name[i]) != toupper(b->name[i]))
			return 1;
	
	return 0;
}
예제 #2
0
static inline int
__affs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b, toupper_t toupper)
{
	const u8 *aname = a->name;
	const u8 *bname = b->name;
	int len;

	/* 'a' is the qstr of an already existing dentry, so the name
	 * must be valid. 'b' must be validated first.
	 */

	if (affs_check_name(b->name,b->len))
		return 1;

	/* If the names are longer than the allowed 30 chars,
	 * the excess is ignored, so their length may differ.
	 */
	len = a->len;
	if (len >= 30) {
		if (b->len < 30)
			return 1;
		len = 30;
	} else if (len != b->len)
		return 1;

	for (; len > 0; len--)
		if (toupper(*aname++) != toupper(*bname++))
			return 1;

	return 0;
}
예제 #3
0
파일: namei.c 프로젝트: Abioy/kasan
static inline int __affs_compare_dentry(unsigned int len,
		const char *str, const struct qstr *name, toupper_t toupper,
		bool notruncate)
{
	const u8 *aname = str;
	const u8 *bname = name->name;

	/*
	 * 'str' is the name of an already existing dentry, so the name
	 * must be valid. 'name' must be validated first.
	 */

	if (affs_check_name(name->name, name->len, notruncate))
		return 1;

	/*
	 * If the names are longer than the allowed 30 chars,
	 * the excess is ignored, so their length may differ.
	 */
	if (len >= AFFSNAMEMAX) {
		if (name->len < AFFSNAMEMAX)
			return 1;
		len = AFFSNAMEMAX;
	} else if (len != name->len)
		return 1;

	for (; len > 0; len--)
		if (toupper(*aname++) != toupper(*bname++))
			return 1;

	return 0;
}
예제 #4
0
파일: namei.c 프로젝트: Abioy/kasan
int
affs_rename(struct inode *old_dir, struct dentry *old_dentry,
	    struct inode *new_dir, struct dentry *new_dentry)
{
	struct super_block *sb = old_dir->i_sb;
	struct buffer_head *bh = NULL;
	int retval;

	pr_debug("%s(old=%lu,\"%pd\" to new=%lu,\"%pd\")\n", __func__,
		 old_dir->i_ino, old_dentry, new_dir->i_ino, new_dentry);

	retval = affs_check_name(new_dentry->d_name.name,
				 new_dentry->d_name.len,
				 affs_nofilenametruncate(old_dentry));

	if (retval)
		return retval;

	/* Unlink destination if it already exists */
	if (new_dentry->d_inode) {
		retval = affs_remove_header(new_dentry);
		if (retval)
			return retval;
	}

	bh = affs_bread(sb, old_dentry->d_inode->i_ino);
	if (!bh)
		return -EIO;

	/* Remove header from its parent directory. */
	affs_lock_dir(old_dir);
	retval = affs_remove_hash(old_dir, bh);
	affs_unlock_dir(old_dir);
	if (retval)
		goto done;

	/* And insert it into the new directory with the new name. */
	affs_copy_name(AFFS_TAIL(sb, bh)->name, new_dentry);
	affs_fix_checksum(sb, bh);
	affs_lock_dir(new_dir);
	retval = affs_insert_hash(new_dir, bh);
	affs_unlock_dir(new_dir);
	/* TODO: move it back to old_dir, if error? */

done:
	mark_buffer_dirty_inode(bh, retval ? old_dir : new_dir);
	affs_brelse(bh);
	return retval;
}
예제 #5
0
/*
 * Note: the dentry argument is the parent dentry.
 */
static inline int
__affs_hash_dentry(struct dentry *dentry, struct qstr *qstr, toupper_t toupper)
{
	const u8 *name = qstr->name;
	unsigned long hash;
	int i;

	i = affs_check_name(qstr->name,qstr->len);
	if (i)
		return i;

	hash = init_name_hash();
	i = min(qstr->len, 30u);
	for (; i > 0; name++, i--)
		hash = partial_name_hash(toupper(*name), hash);
	qstr->hash = end_name_hash(hash);

	return 0;
}
예제 #6
0
파일: namei.c 프로젝트: Abioy/kasan
/*
 * Note: the dentry argument is the parent dentry.
 */
static inline int
__affs_hash_dentry(struct qstr *qstr, toupper_t toupper, bool notruncate)
{
	const u8 *name = qstr->name;
	unsigned long hash;
	int retval;
	u32 len;

	retval = affs_check_name(qstr->name, qstr->len, notruncate);
	if (retval)
		return retval;

	hash = init_name_hash();
	len = min(qstr->len, AFFSNAMEMAX);
	for (; len > 0; name++, len--)
		hash = partial_name_hash(toupper(*name), hash);
	qstr->hash = end_name_hash(hash);

	return 0;
}
예제 #7
0
파일: namei.c 프로젝트: dzavalishin/oskit
/*
 * Note: the dentry argument is the parent dentry.
 */
static int
affs_hash_dentry(struct dentry *dentry, struct qstr *qstr)
{
	unsigned int (*toupper)(unsigned int) = affs_toupper;
	unsigned long	 hash;
	int		 i;

	if ((i = affs_check_name(qstr->name,qstr->len)))
		return i;

	/* Check whether to use the international 'toupper' routine */
	if (AFFS_I2FSTYPE(dentry->d_inode))
		toupper = affs_intl_toupper;
	hash = init_name_hash();
	for (i = 0; i < qstr->len && i < 30; i++)
		hash = partial_name_hash(toupper(qstr->name[i]), hash);
	qstr->hash = end_name_hash(hash);

	return 0;
}
예제 #8
0
파일: namei.c 프로젝트: dzavalishin/oskit
int
affs_rename(struct inode *old_dir, struct dentry *old_dentry,
	    struct inode *new_dir, struct dentry *new_dentry)
{
	struct inode		*old_inode = old_dentry->d_inode;
	struct inode		*new_inode = new_dentry->d_inode;
	struct buffer_head	*old_bh;
	struct buffer_head	*new_bh;
	unsigned long		 old_ino;
	unsigned long		 new_ino;
	int			 retval;

	pr_debug("AFFS: rename(old=%lu,\"%*s\" (inode=%p) to new=%lu,\"%*s\" (inode=%p))\n",
		 old_dir->i_ino,old_dentry->d_name.len,old_dentry->d_name.name,old_inode,
		 new_dir->i_ino,new_dentry->d_name.len,new_dentry->d_name.name,new_inode);
	
	if ((retval = affs_check_name(new_dentry->d_name.name,new_dentry->d_name.len)))
		goto out;

	new_bh = NULL;
	retval = -ENOENT;
	old_bh = affs_find_entry(old_dir,old_dentry,&old_ino);
	if (!old_bh)
		goto end_rename;

	new_bh = affs_find_entry(new_dir,new_dentry,&new_ino);
	if (new_bh && !new_inode) {
		affs_error(old_inode->i_sb,"affs_rename",
			   "No inode for entry found (key=%lu)\n",new_ino);
		goto end_rename;
	}
	if (S_ISDIR(old_inode->i_mode)) {
		if (new_inode) {
			retval = -ENOTEMPTY;
			if (!empty_dir(new_bh,AFFS_I2HSIZE(new_inode)))
				goto end_rename;
		}

		retval = -ENOENT;
		if (affs_parent_ino(old_inode) != old_dir->i_ino)
			goto end_rename;
	}
	/* Unlink destination if it already exists */
	if (new_inode) {
		if ((retval = affs_remove_header(new_bh,new_dir)) < 0)
			goto end_rename;
		new_inode->i_nlink = retval;
		mark_inode_dirty(new_inode);
		if (new_inode->i_ino == new_ino)
			new_inode->i_nlink = 0;
	}
	/* Remove header from its parent directory. */
	if ((retval = affs_remove_hash(old_bh,old_dir)))
		goto end_rename;
	/* And insert it into the new directory with the new name. */
	affs_copy_name(FILE_END(old_bh->b_data,old_inode)->file_name,new_dentry->d_name.name);
	if ((retval = affs_insert_hash(new_dir->i_ino,old_bh,new_dir)))
		goto end_rename;
	affs_fix_checksum(AFFS_I2BSIZE(new_dir),old_bh->b_data,5);

	new_dir->i_ctime   = new_dir->i_mtime = old_dir->i_ctime
			   = old_dir->i_mtime = CURRENT_TIME;
	new_dir->i_version = ++event;
	old_dir->i_version = ++event;
	retval             = 0;
	mark_inode_dirty(new_dir);
	mark_inode_dirty(old_dir);
	mark_buffer_dirty(old_bh,1);
	
end_rename:
	affs_brelse(old_bh);
	affs_brelse(new_bh);
out:
	return retval;
}
예제 #9
0
int
affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode,
	       struct dentry *dentry, int type)
{
	struct buffer_head	*dir_bh;
	struct buffer_head	*inode_bh;
	struct buffer_head	*link_bh;
	int			 retval;
	const unsigned char	*name = dentry->d_name.name;
	int			 len  = dentry->d_name.len;

	pr_debug("AFFS: add_entry(dir=%lu,inode=%lu,\"%*s\",type=%d)\n",dir->i_ino,inode->i_ino,
		 len,name,type);

	if ((retval = affs_check_name(name,len)))
		return retval;
	if (len > 30)
		len = 30;

	dir_bh   = affs_bread(dir->i_dev,dir->i_ino,AFFS_I2BSIZE(dir));
	inode_bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
	link_bh  = NULL;
	retval   = -EIO;
	if (!dir_bh || !inode_bh)
		goto addentry_done;
	if (link) {
		link_bh = affs_bread(link->i_dev,link->i_ino,AFFS_I2BSIZE(link));
		if (!link_bh)
			goto addentry_done;
	}
	((struct dir_front *)inode_bh->b_data)->primary_type = cpu_to_be32(T_SHORT);
	((struct dir_front *)inode_bh->b_data)->own_key      = cpu_to_be32(inode->i_ino);
	DIR_END(inode_bh->b_data,inode)->dir_name[0]         = len;
	strncpy(DIR_END(inode_bh->b_data,inode)->dir_name + 1,name,len);
	DIR_END(inode_bh->b_data,inode)->secondary_type = cpu_to_be32(type);
	DIR_END(inode_bh->b_data,inode)->parent         = cpu_to_be32(dir->i_ino);

	lock_super(inode->i_sb);
	retval = affs_insert_hash(dir->i_ino,inode_bh,dir);

	if (link_bh) {
		LINK_END(inode_bh->b_data,inode)->original   = cpu_to_be32(link->i_ino);
		LINK_END(inode_bh->b_data,inode)->link_chain =
						FILE_END(link_bh->b_data,link)->link_chain;
		FILE_END(link_bh->b_data,link)->link_chain   = cpu_to_be32(inode->i_ino);
		affs_fix_checksum(AFFS_I2BSIZE(link),link_bh->b_data,5);
		link->i_version = ++global_event;
		mark_inode_dirty(link);
		mark_buffer_dirty(link_bh,1);
	}
	affs_fix_checksum(AFFS_I2BSIZE(inode),inode_bh->b_data,5);
	affs_fix_checksum(AFFS_I2BSIZE(dir),dir_bh->b_data,5);
	dir->i_version = ++global_event;
	dir->i_mtime   = dir->i_atime = dir->i_ctime = CURRENT_TIME;
	unlock_super(inode->i_sb);

	mark_inode_dirty(dir);
	mark_inode_dirty(inode);
	mark_buffer_dirty(dir_bh,1);
	mark_buffer_dirty(inode_bh,1);

addentry_done:
	affs_brelse(dir_bh);
	affs_brelse(inode_bh);
	affs_brelse(link_bh);

	return retval;
}