Exemple #1
0
/*
 * cap_lookup()
 *
 * This is the lookup() entry in the inode_operations structure for
 * HFS directories in the CAP scheme.  The purpose is to generate the
 * inode corresponding to an entry in a directory, given the inode for
 * the directory and the name (and its length) of the entry.
 */
static struct dentry *cap_lookup(struct inode * dir, struct dentry *dentry)
{
	ino_t dtype;
	struct hfs_name cname;
	struct hfs_cat_entry *entry;
	struct hfs_cat_key key;
	struct inode *inode = NULL;

	dentry->d_op = &hfs_dentry_operations;
	entry = HFS_I(dir)->entry;
	dtype = HFS_ITYPE(dir->i_ino);

	/* Perform name-mangling */
	hfs_nameout(dir, &cname, dentry->d_name.name, 
		    dentry->d_name.len);

	/* no need to check for "."  or ".." */

	/* Check for special directories if in a normal directory.
	   Note that cap_dupdir() does an iput(dir). */
	if (dtype==HFS_CAP_NDIR) {
		/* Check for ".resource", ".finderinfo" and ".rootinfo" */
		if (hfs_streq(cname.Name, cname.Len, 
			      DOT_RESOURCE->Name, DOT_RESOURCE_LEN)) {
			++entry->count; /* __hfs_iget() eats one */
			inode = hfs_iget(entry, HFS_CAP_RDIR, dentry);
			goto done;
		} else if (hfs_streq(cname.Name, cname.Len, 
				     DOT_FINDERINFO->Name, 
				     DOT_FINDERINFO_LEN)) {
			++entry->count; /* __hfs_iget() eats one */
			inode = hfs_iget(entry, HFS_CAP_FDIR, dentry);
			goto done;
		} else if ((entry->cnid == htonl(HFS_ROOT_CNID)) &&
			   hfs_streq(cname.Name, cname.Len, 
				     DOT_ROOTINFO->Name, DOT_ROOTINFO_LEN)) {
			++entry->count; /* __hfs_iget() eats one */
			inode = hfs_iget(entry, HFS_CAP_FNDR, dentry);
			goto done;
		}
	}

	/* Do an hfs_iget() on the mangled name. */
	hfs_cat_build_key(entry->cnid, &cname, &key);
	inode = hfs_iget(hfs_cat_get(entry->mdb, &key),
			 HFS_I(dir)->file_type, dentry);

	/* Don't return a resource fork for a directory */
	if (inode && (dtype == HFS_CAP_RDIR) && 
	    (HFS_I(inode)->entry->type == HFS_CDR_DIR)) {
	        iput(inode); /* this does an hfs_cat_put */
		inode = NULL;
	}

done:
	d_add(dentry, inode);
	return NULL;
}
Exemple #2
0
/*
 * hfs_lookup()
 */
static struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry,
				 struct nameidata *nd)
{
	hfs_cat_rec rec;
	struct hfs_find_data fd;
	struct inode *inode = NULL;
	int res;

	hfs_find_init(HFS_SB(dir->i_sb)->cat_tree, &fd);
	hfs_cat_build_key(dir->i_sb, fd.search_key, dir->i_ino, &dentry->d_name);
	res = hfs_brec_read(&fd, &rec, sizeof(rec));
	if (res) {
		hfs_find_exit(&fd);
		if (res == -ENOENT) {
			/* No such entry */
			inode = NULL;
			goto done;
		}
		return ERR_PTR(res);
	}
	inode = hfs_iget(dir->i_sb, &fd.search_key->cat, &rec);
	hfs_find_exit(&fd);
	if (!inode)
		return ERR_PTR(-EACCES);
done:
	d_add(dentry, inode);
	return NULL;
}
Exemple #3
0
/*
 * hfs_lookup()
 */
static struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry,
				 unsigned int flags)
{
	hfs_cat_rec rec;
	struct hfs_find_data fd;
	struct inode *inode = NULL;
	int res;

	res = hfs_find_init(HFS_SB(dir->i_sb)->cat_tree, &fd);
	if (res)
		return ERR_PTR(res);
	hfs_cat_build_key(dir->i_sb, fd.search_key, dir->i_ino, &dentry->d_name);
	res = hfs_brec_read(&fd, &rec, sizeof(rec));
	if (res) {
		if (res != -ENOENT)
			inode = ERR_PTR(res);
	} else {
		inode = hfs_iget(dir->i_sb, &fd.search_key->cat, &rec);
		if (!inode)
			inode = ERR_PTR(-EACCES);
	}
	hfs_find_exit(&fd);
	return d_splice_alias(inode, dentry);
}
Exemple #4
0
/*
 * hfs_read_super()
 *
 * This is the function that is responsible for mounting an HFS
 * filesystem.	It performs all the tasks necessary to get enough data
 * from the disk to read the root inode.  This includes parsing the
 * mount options, dealing with Macintosh partitions, reading the
 * superblock and the allocation bitmap blocks, calling
 * hfs_btree_init() to get the necessary data about the extents and
 * catalog B-trees and, finally, reading the root inode into memory.
 */
static int hfs_fill_super(struct super_block *sb, void *data, int silent)
{
	struct hfs_sb_info *sbi;
	struct hfs_find_data fd;
	hfs_cat_rec rec;
	struct inode *root_inode;
	int res;

	sbi = kzalloc(sizeof(struct hfs_sb_info), GFP_KERNEL);
	if (!sbi)
		return -ENOMEM;

	sb->s_fs_info = sbi;

	res = -EINVAL;
	if (!parse_options((char *)data, sbi)) {
		printk(KERN_ERR "hfs: unable to parse mount options.\n");
		goto bail;
	}

	sb->s_op = &hfs_super_operations;
	sb->s_flags |= MS_NODIRATIME;
	mutex_init(&sbi->bitmap_lock);

	res = hfs_mdb_get(sb);
	if (res) {
		if (!silent)
			printk(KERN_WARNING "hfs: can't find a HFS filesystem on dev %s.\n",
				hfs_mdb_name(sb));
		res = -EINVAL;
		goto bail;
	}

	/* try to get the root inode */
	hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
	res = hfs_cat_find_brec(sb, HFS_ROOT_CNID, &fd);
	if (!res) {
		if (fd.entrylength > sizeof(rec) || fd.entrylength < 0) {
			res =  -EIO;
			goto bail;
		}
		hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, fd.entrylength);
	}
	if (res) {
		hfs_find_exit(&fd);
		goto bail_no_root;
	}
	res = -EINVAL;
	root_inode = hfs_iget(sb, &fd.search_key->cat, &rec);
	hfs_find_exit(&fd);
	if (!root_inode)
		goto bail_no_root;

	sb->s_d_op = &hfs_dentry_operations;
	res = -ENOMEM;
	sb->s_root = d_alloc_root(root_inode);
	if (!sb->s_root)
		goto bail_iput;

	/* everything's okay */
	return 0;

bail_iput:
	iput(root_inode);
bail_no_root:
	printk(KERN_ERR "hfs: get root inode failed.\n");
bail:
	hfs_mdb_put(sb);
	return res;
}
Exemple #5
0
/*
 * hfs_read_super()
 *
 * This is the function that is responsible for mounting an HFS
 * filesystem.	It performs all the tasks necessary to get enough data
 * from the disk to read the root inode.  This includes parsing the
 * mount options, dealing with Macintosh partitions, reading the
 * superblock and the allocation bitmap blocks, calling
 * hfs_btree_init() to get the necessary data about the extents and
 * catalog B-trees and, finally, reading the root inode into memory.
 */
struct super_block *hfs_read_super(struct super_block *s, void *data,
				   int silent)
{
	struct hfs_mdb *mdb;
	struct hfs_cat_key key;
	kdev_t dev = s->s_dev;
	hfs_s32 part_size, part_start;
	struct inode *root_inode;
	int part;

	if (!parse_options((char *)data, HFS_SB(s), &part)) {
		hfs_warn("hfs_fs: unable to parse mount options.\n");
		goto bail3;
	}

	/* set the device driver to 512-byte blocks */
	set_blocksize(dev, HFS_SECTOR_SIZE);
	s->s_blocksize_bits = HFS_SECTOR_SIZE_BITS;
	s->s_blocksize = HFS_SECTOR_SIZE;

#ifdef CONFIG_MAC_PARTITION
	/* check to see if we're in a partition */
	mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, 0);

	/* erk. try parsing the partition table ourselves */
	if (!mdb) {
		if (hfs_part_find(s, part, silent, &part_size, &part_start)) {
	    		goto bail2;
	  	}
	  	mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start);
	}
#else
	if (hfs_part_find(s, part, silent, &part_size, &part_start)) {
		goto bail2;
	}

	mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start);
#endif

	if (!mdb) {
		if (!silent) {
			hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n",
			       kdevname(dev));
		}
		goto bail2;
	}

	HFS_SB(s)->s_mdb = mdb;
	if (HFS_ITYPE(mdb->next_id) != 0) {
		hfs_warn("hfs_fs: too many files.\n");
		goto bail1;
	}

	s->s_magic = HFS_SUPER_MAGIC;
	s->s_op = &hfs_super_operations;

	/* try to get the root inode */
	hfs_cat_build_key(htonl(HFS_POR_CNID),
			  (struct hfs_name *)(mdb->vname), &key);

	root_inode = hfs_iget(hfs_cat_get(mdb, &key), HFS_ITYPE_NORM, NULL);
	if (!root_inode) 
		goto bail_no_root;
	  
	s->s_root = d_alloc_root(root_inode);
	if (!s->s_root) 
		goto bail_no_root;

	/* fix up pointers. */
	HFS_I(root_inode)->entry->sys_entry[HFS_ITYPE_TO_INT(HFS_ITYPE_NORM)] =
	  s->s_root;
	s->s_root->d_op = &hfs_dentry_operations;

	/* everything's okay */
	return s;

bail_no_root: 
	hfs_warn("hfs_fs: get root inode failed.\n");
	iput(root_inode);
bail1:
	hfs_mdb_put(mdb, s->s_flags & MS_RDONLY);
bail2:
	set_blocksize(dev, BLOCK_SIZE);
bail3:
	return NULL;	
}
/*
 * hfs_read_super()
 *
 * This is the function that is responsible for mounting an HFS
 * filesystem.	It performs all the tasks necessary to get enough data
 * from the disk to read the root inode.  This includes parsing the
 * mount options, dealing with Macintosh partitions, reading the
 * superblock and the allocation bitmap blocks, calling
 * hfs_btree_init() to get the necessary data about the extents and
 * catalog B-trees and, finally, reading the root inode into memory.
 */
static int hfs_fill_super(struct super_block *sb, void *data, int silent)
{
	struct hfs_sb_info *sbi;
	struct hfs_find_data fd;
	hfs_cat_rec rec;
	struct inode *root_inode;
	int res;

	sbi = kmalloc(sizeof(struct hfs_sb_info), GFP_KERNEL);
	if (!sbi)
		return -ENOMEM;
	sb->s_fs_info = sbi;
	memset(sbi, 0, sizeof(struct hfs_sb_info));
	INIT_HLIST_HEAD(&sbi->rsrc_inodes);

	res = -EINVAL;
	if (!parse_options((char *)data, sbi)) {
		hfs_warn("hfs_fs: unable to parse mount options.\n");
		goto bail3;
	}

	sb->s_op = &hfs_super_operations;
	sb->s_flags |= MS_NODIRATIME;
	init_MUTEX(&sbi->bitmap_lock);

	res = hfs_mdb_get(sb);
	if (res) {
		if (!silent)
			hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n",
				hfs_mdb_name(sb));
		res = -EINVAL;
		goto bail2;
	}

	/* try to get the root inode */
	hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
	res = hfs_cat_find_brec(sb, HFS_ROOT_CNID, &fd);
	if (!res)
		hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, fd.entrylength);
	if (res) {
		hfs_find_exit(&fd);
		goto bail_no_root;
	}
	root_inode = hfs_iget(sb, &fd.search_key->cat, &rec);
	hfs_find_exit(&fd);
	if (!root_inode)
		goto bail_no_root;

	sb->s_root = d_alloc_root(root_inode);
	if (!sb->s_root)
		goto bail_iput;

	sb->s_root->d_op = &hfs_dentry_operations;

	/* everything's okay */
	return 0;

bail_iput:
	iput(root_inode);
bail_no_root:
	hfs_warn("hfs_fs: get root inode failed.\n");
	hfs_mdb_put(sb);
bail2:
bail3:
	kfree(sbi);
	return res;
}
Exemple #7
0
/*
 * nat_lookup()
 *
 * This is the lookup() entry in the inode_operations structure for
 * HFS directories in the Netatalk scheme.  The purpose is to generate
 * the inode corresponding to an entry in a directory, given the inode
 * for the directory and the name (and its length) of the entry.
 */
static int nat_lookup(struct inode * dir, const char * name,
		      int len, struct inode ** result)
{
	ino_t dtype;
	struct hfs_name cname;
	struct hfs_cat_entry *entry;
	struct hfs_cat_key key;
	struct inode *inode = NULL;

	if (!dir || !S_ISDIR(dir->i_mode)) {
		goto done;
	}

	entry = HFS_I(dir)->entry;
	dtype = HFS_ITYPE(dir->i_ino);

	if (len && !name) {
		*result = NULL;
		iput(dir);
		return -EINVAL;
	}

	/* Perform name-mangling */
	hfs_nameout(dir, &cname, name, len);

	/* Check for "." */
	if (hfs_streq(&cname, DOT)) {
		/* this little trick skips the iget and iput */
		*result = dir;
		return 0;
	}

	/* Check for "..". */
	if (hfs_streq(&cname, DOT_DOT)) {
		struct hfs_cat_entry *parent;

		if (dtype != HFS_NAT_NDIR) {
			/* Case for ".." in ".AppleDouble" */
			parent = entry;
			++entry->count; /* __hfs_iget() eats one */
		} else {
			/* Case for ".." in a normal directory */
			parent = hfs_cat_parent(entry);
		}
		inode = __hfs_iget(parent, HFS_NAT_NDIR, 0);
		goto done;
	}

	/* Check for ".AppleDouble" if in a normal directory,
	   and for ".Parent" in ".AppleDouble". */
	if (dtype==HFS_NAT_NDIR) {
		/* Check for ".AppleDouble" */
		if (hfs_streq(&cname, DOT_APPLEDOUBLE)) {
			++entry->count; /* __hfs_iget() eats one */
			inode = __hfs_iget(entry, HFS_NAT_HDIR, 1);
			goto done;
		}
	} else if (dtype==HFS_NAT_HDIR) {
		if (hfs_streq(&cname, DOT_PARENT)) {
			++entry->count; /* __hfs_iget() eats one */
			inode = __hfs_iget(entry, HFS_NAT_HDR, 0);
			goto done;
		}
	}

	/* Do an hfs_iget() on the mangled name. */
	hfs_cat_build_key(entry->cnid, &cname, &key);
	inode = hfs_iget(entry->mdb, &key, HFS_I(dir)->file_type);

	/* Don't return a header file for a directory other than .Parent */
	if (inode && (dtype == HFS_NAT_HDIR) &&
	    (HFS_I(inode)->entry != entry) &&
	    (HFS_I(inode)->entry->type == HFS_CDR_DIR)) {
		iput(inode);
		inode = NULL;
	}

done:
	iput(dir);
	*result = inode;
	return inode ? 0 : -ENOENT;
}