/* * 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; }
/* * 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; }
/* * 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); }
/* * 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; }
/* * 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; }
/* * 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; }