4 * Copyright (C) 1995-1997 Paul H. Hargrove
5 * This file may be distributed under the terms of the GNU General Public License.
7 * This file contains hfs_read_super(), some of the super_ops and
8 * init_module() and cleanup_module(). The remaining super_ops are in
9 * inode.c since they deal with inodes.
11 * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
13 * "XXX" in a comment is a note to myself to consider changing something.
15 * In function preconditions the term "valid" applied to a pointer to
16 * a structure means that the pointer is non-NULL and the structure it
17 * points to has all fields initialized to consistent values.
19 * The code in this file initializes some structures which contain
20 * pointers by calling memset(&foo, 0, sizeof(foo)).
21 * This produces the desired behavior only due to the non-ANSI
22 * assumption that the machine representation of NULL is all zeros.
26 #include <linux/hfs_fs_sb.h>
27 #include <linux/hfs_fs_i.h>
28 #include <linux/hfs_fs.h>
30 #include <linux/config.h> /* for CONFIG_MAC_PARTITION */
31 #include <linux/blkdev.h>
32 #include <linux/module.h>
33 #include <linux/init.h>
35 MODULE_LICENSE("GPL");
37 /*================ Forward declarations ================*/
39 static void hfs_read_inode(struct inode *);
40 static void hfs_put_super(struct super_block *);
41 static int hfs_statfs(struct super_block *, struct statfs *);
42 static void hfs_write_super(struct super_block *);
44 /*================ Global variables ================*/
46 static struct super_operations hfs_super_operations = {
47 read_inode: hfs_read_inode,
48 put_inode: hfs_put_inode,
49 put_super: hfs_put_super,
50 write_super: hfs_write_super,
52 remount_fs: hfs_remount,
55 /*================ File-local variables ================*/
57 static DECLARE_FSTYPE_DEV(hfs_fs, "hfs", hfs_read_super);
59 /*================ File-local functions ================*/
64 * this doesn't actually do much. hfs_iget actually fills in the
65 * necessary inode information.
67 static void hfs_read_inode(struct inode *inode)
76 * This function is called by the VFS only. When the filesystem
77 * is mounted r/w it updates the MDB on disk.
79 * struct super_block *sb: Pointer to the hfs superblock
85 * 'sb' points to a "valid" (struct super_block).
87 * The MDB is marked 'unsuccessfully unmounted' by clearing bit 8 of drAtrb
88 * (hfs_put_super() must set this flag!). Some MDB fields are updated
89 * and the MDB buffer is written to disk by calling hfs_mdb_commit().
91 static void hfs_write_super(struct super_block *sb)
93 struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
95 /* is this a valid hfs superblock? */
96 if (!sb || sb->s_magic != HFS_SUPER_MAGIC) {
100 if (!(sb->s_flags & MS_RDONLY)) {
101 /* sync everything to the buffers */
102 hfs_mdb_commit(mdb, 0);
110 * This is the put_super() entry in the super_operations structure for
111 * HFS filesystems. The purpose is to release the resources
112 * associated with the superblock sb.
114 static void hfs_put_super(struct super_block *sb)
116 struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
118 if (!(sb->s_flags & MS_RDONLY)) {
119 hfs_mdb_commit(mdb, 0);
123 /* release the MDB's resources */
124 hfs_mdb_put(mdb, sb->s_flags & MS_RDONLY);
126 /* restore default blocksize for the device */
127 set_blocksize(sb->s_dev, BLOCK_SIZE);
133 * This is the statfs() entry in the super_operations structure for
134 * HFS filesystems. The purpose is to return various data about the
137 * changed f_files/f_ffree to reflect the fs_ablock/free_ablocks.
139 static int hfs_statfs(struct super_block *sb, struct statfs *buf)
141 struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
143 buf->f_type = HFS_SUPER_MAGIC;
144 buf->f_bsize = HFS_SECTOR_SIZE;
145 buf->f_blocks = mdb->alloc_blksz * mdb->fs_ablocks;
146 buf->f_bfree = mdb->alloc_blksz * mdb->free_ablocks;
147 buf->f_bavail = buf->f_bfree;
148 buf->f_files = mdb->fs_ablocks;
149 buf->f_ffree = mdb->free_ablocks;
150 buf->f_namelen = HFS_NAMELEN;
158 * adapted from linux/fs/msdos/inode.c written 1992,93 by Werner Almesberger
159 * This function is called by hfs_read_super() to parse the mount options.
161 static int parse_options(char *options, struct hfs_sb_info *hsb, int *part)
163 char *this_char, *value;
166 if (hsb->magic != HFS_SB_MAGIC) {
167 /* initialize the sb with defaults */
168 hsb->magic = HFS_SB_MAGIC;
169 hsb->s_uid = current->uid;
170 hsb->s_gid = current->gid;
171 hsb->s_umask = current->fs->umask;
172 hsb->s_type = 0x3f3f3f3f; /* == '????' */
173 hsb->s_creator = 0x3f3f3f3f; /* == '????' */
174 hsb->s_lowercase = 0;
177 /* default version. 0 just selects the defaults */
188 for (this_char = strtok(options,","); this_char;
189 this_char = strtok(NULL,",")) {
190 if ((value = strchr(this_char,'=')) != NULL) {
193 /* Numeric-valued options */
194 if (!strcmp(this_char, "version")) {
195 if (!value || !*value) {
198 hsb->s_version = simple_strtoul(value,&value,0);
202 } else if (!strcmp(this_char,"uid")) {
203 if (!value || !*value) {
206 hsb->s_uid = simple_strtoul(value,&value,0);
210 } else if (!strcmp(this_char,"gid")) {
211 if (!value || !*value) {
214 hsb->s_gid = simple_strtoul(value,&value,0);
218 } else if (!strcmp(this_char,"umask")) {
219 if (!value || !*value) {
222 hsb->s_umask = simple_strtoul(value,&value,8);
226 } else if (!strcmp(this_char,"part")) {
227 if (!value || !*value) {
230 *part = simple_strtoul(value,&value,0);
234 /* String-valued options */
235 } else if (!strcmp(this_char,"type") && value) {
236 if (strlen(value) != 4) {
239 hsb->s_type = hfs_get_nl(value);
240 } else if (!strcmp(this_char,"creator") && value) {
241 if (strlen(value) != 4) {
244 hsb->s_creator = hfs_get_nl(value);
245 /* Boolean-valued options */
246 } else if (!strcmp(this_char,"quiet")) {
251 } else if (!strcmp(this_char,"afpd")) {
256 /* Multiple choice options */
257 } else if (!strcmp(this_char,"names") && value) {
258 if ((*value && !value[1] && strchr("ntal78c",*value)) ||
259 !strcmp(value,"netatalk") ||
260 !strcmp(value,"trivial") ||
261 !strcmp(value,"alpha") ||
262 !strcmp(value,"latin") ||
263 !strcmp(value,"7bit") ||
264 !strcmp(value,"8bit") ||
265 !strcmp(value,"cap")) {
270 } else if (!strcmp(this_char,"fork") && value) {
271 if ((*value && !value[1] && strchr("nsdc",*value)) ||
272 !strcmp(value,"netatalk") ||
273 !strcmp(value,"single") ||
274 !strcmp(value,"double") ||
275 !strcmp(value,"cap")) {
280 } else if (!strcmp(this_char,"case") && value) {
281 if ((*value && !value[1] && strchr("la",*value)) ||
282 !strcmp(value,"lower") ||
283 !strcmp(value,"asis")) {
284 hsb->s_lowercase = (*value == 'l');
288 } else if (!strcmp(this_char,"conv") && value) {
289 if ((*value && !value[1] && strchr("bta",*value)) ||
290 !strcmp(value,"binary") ||
291 !strcmp(value,"text") ||
292 !strcmp(value,"auto")) {
293 hsb->s_conv = *value;
303 /* Parse the "fork" and "names" options */
305 fork = hsb->s_afpd ? 'n' : 'c';
310 hsb->s_ifill = hfs_cap_ifill;
311 hsb->s_reserved1 = hfs_cap_reserved1;
312 hsb->s_reserved2 = hfs_cap_reserved2;
316 hfs_warn("hfs_fs: AppleSingle not yet implemented.\n");
321 hsb->s_ifill = hfs_dbl_ifill;
322 hsb->s_reserved1 = hfs_dbl_reserved1;
323 hsb->s_reserved2 = hfs_dbl_reserved2;
327 hsb->s_ifill = hfs_nat_ifill;
328 hsb->s_reserved1 = hfs_nat_reserved1;
329 hsb->s_reserved2 = hfs_nat_reserved2;
339 hsb->s_nameout = hfs_colon2mac;
340 hsb->s_namein = hfs_mac2nat;
344 hsb->s_nameout = hfs_colon2mac;
345 hsb->s_namein = hfs_mac2cap;
349 hsb->s_nameout = hfs_triv2mac;
350 hsb->s_namein = hfs_mac2triv;
354 hsb->s_nameout = hfs_prcnt2mac;
355 hsb->s_namein = hfs_mac2seven;
359 hsb->s_nameout = hfs_prcnt2mac;
360 hsb->s_namein = hfs_mac2eight;
364 hsb->s_nameout = hfs_latin2mac;
365 hsb->s_namein = hfs_mac2latin;
368 case 'a': /* 's' and 'd' are unadvertised aliases for 'alpha', */
369 case 's': /* since 'alpha' is the default if fork=s or fork=d. */
370 case 'd': /* (It is also helpful for poor typists!) */
371 hsb->s_nameout = hfs_prcnt2mac;
372 hsb->s_namein = hfs_mac2alpha;
379 /*================ Global functions ================*/
384 * This is the function that is responsible for mounting an HFS
385 * filesystem. It performs all the tasks necessary to get enough data
386 * from the disk to read the root inode. This includes parsing the
387 * mount options, dealing with Macintosh partitions, reading the
388 * superblock and the allocation bitmap blocks, calling
389 * hfs_btree_init() to get the necessary data about the extents and
390 * catalog B-trees and, finally, reading the root inode into memory.
392 struct super_block *hfs_read_super(struct super_block *s, void *data,
396 struct hfs_cat_key key;
397 kdev_t dev = s->s_dev;
399 hfs_s32 part_size, part_start;
400 struct inode *root_inode;
403 memset(HFS_SB(s), 0, sizeof(*(HFS_SB(s))));
404 if (!parse_options((char *)data, HFS_SB(s), &part)) {
405 hfs_warn("hfs_fs: unable to parse mount options.\n");
409 /* set the device driver to 512-byte blocks */
410 if (set_blocksize(dev, HFS_SECTOR_SIZE) < 0) {
411 dev_blocksize = get_hardsect_size(dev);
412 hfs_warn("hfs_fs: unsupported device block size: %d\n",
416 s->s_blocksize_bits = HFS_SECTOR_SIZE_BITS;
417 s->s_blocksize = HFS_SECTOR_SIZE;
419 #ifdef CONFIG_MAC_PARTITION
420 /* check to see if we're in a partition */
421 mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, 0);
423 /* erk. try parsing the partition table ourselves */
425 if (hfs_part_find(s, part, silent, &part_size, &part_start)) {
428 mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start);
431 if (hfs_part_find(s, part, silent, &part_size, &part_start)) {
435 mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start);
440 hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n",
446 if (mdb->attrib & (HFS_SB_ATTRIB_HLOCK | HFS_SB_ATTRIB_SLOCK)) {
448 hfs_warn("hfs_fs: Filesystem is marked locked, mounting read-only.\n");
449 s->s_flags |= MS_RDONLY;
452 HFS_SB(s)->s_mdb = mdb;
453 if (HFS_ITYPE(mdb->next_id) != 0) {
454 hfs_warn("hfs_fs: too many files.\n");
458 s->s_magic = HFS_SUPER_MAGIC;
459 s->s_op = &hfs_super_operations;
461 /* try to get the root inode */
462 hfs_cat_build_key(htonl(HFS_POR_CNID),
463 (struct hfs_name *)(mdb->vname), &key);
465 root_inode = hfs_iget(hfs_cat_get(mdb, &key), HFS_ITYPE_NORM, NULL);
469 s->s_root = d_alloc_root(root_inode);
473 /* fix up pointers. */
474 HFS_I(root_inode)->entry->sys_entry[HFS_ITYPE_TO_INT(HFS_ITYPE_NORM)] =
476 s->s_root->d_op = &hfs_dentry_operations;
478 /* everything's okay */
482 hfs_warn("hfs_fs: get root inode failed.\n");
485 hfs_mdb_put(mdb, s->s_flags & MS_RDONLY);
487 set_blocksize(dev, BLOCK_SIZE);
492 int hfs_remount(struct super_block *s, int *flags, char *data)
494 int part; /* ignored */
496 if (!parse_options(data, HFS_SB(s), &part)) {
497 hfs_warn("hfs_fs: unable to parse mount options.\n");
501 if ((*flags & MS_RDONLY) == (s->s_flags & MS_RDONLY))
503 if (!(*flags & MS_RDONLY)) {
504 if (HFS_SB(s)->s_mdb->attrib & (HFS_SB_ATTRIB_HLOCK | HFS_SB_ATTRIB_SLOCK)) {
505 hfs_warn("hfs_fs: Filesystem is marked locked, leaving it read-only.\n");
506 s->s_flags |= MS_RDONLY;
513 static int __init init_hfs_fs(void)
516 return register_filesystem(&hfs_fs);
519 static void __exit exit_hfs_fs(void) {
521 unregister_filesystem(&hfs_fs);
524 module_init(init_hfs_fs)
525 module_exit(exit_hfs_fs)
527 #if defined(DEBUG_ALL) || defined(DEBUG_MEM)
528 long int hfs_alloc = 0;