4 * Copyright (C) 1995-1997 Paul H. Hargrove
5 * This file may be distributed under the terms of the GNU 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 /*================ Forward declarations ================*/
37 static void hfs_read_inode(struct inode
*);
38 static void hfs_put_super(struct super_block
*);
39 static int hfs_statfs(struct super_block
*, struct statfs
*, int);
40 static void hfs_write_super(struct super_block
*);
42 /*================ Global variables ================*/
44 static struct super_operations hfs_super_operations
= {
45 hfs_read_inode
, /* read_inode */
46 NULL
, /* write_inode */
47 hfs_put_inode
, /* put_inode - in inode.c */
48 NULL
, /* delete_inode */
49 hfs_notify_change
, /* notify_change - in inode.c */
50 hfs_put_super
, /* put_super */
51 hfs_write_super
, /* write_super */
52 hfs_statfs
, /* statfs */
56 /*================ File-local variables ================*/
58 static struct file_system_type hfs_fs
= {
64 /*================ File-local functions ================*/
69 * this doesn't actually do much. hfs_iget actually fills in the
70 * necessary inode information.
72 static void hfs_read_inode(struct inode
*inode
)
82 * This function is called by the VFS only. When the filesystem
83 * is mounted r/w it updates the MDB on disk.
85 * struct super_block *sb: Pointer to the hfs superblock
91 * 'sb' points to a "valid" (struct super_block).
93 * The MDB is marked 'unsuccessfully unmounted' by clearing bit 8 of drAtrb
94 * (hfs_put_super() must set this flag!). Some MDB fields are updated
95 * and the MDB buffer is written to disk by calling hfs_mdb_commit().
97 static void hfs_write_super(struct super_block
*sb
)
99 struct hfs_mdb
*mdb
= HFS_SB(sb
)->s_mdb
;
101 /* is this a valid hfs superblock? */
102 if (!sb
|| sb
->s_magic
!= HFS_SUPER_MAGIC
) {
106 if (!(sb
->s_flags
& MS_RDONLY
)) {
107 /* sync everything to the buffers */
108 hfs_mdb_commit(mdb
, 0);
116 * This is the put_super() entry in the super_operations structure for
117 * HFS filesystems. The purpose is to release the resources
118 * associated with the superblock sb.
120 static void hfs_put_super(struct super_block
*sb
)
122 struct hfs_mdb
*mdb
= HFS_SB(sb
)->s_mdb
;
124 if (!(sb
->s_flags
& MS_RDONLY
)) {
125 hfs_mdb_commit(mdb
, 0);
129 /* release the MDB's resources */
130 hfs_mdb_put(mdb
, sb
->s_flags
& MS_RDONLY
);
132 /* restore default blocksize for the device */
133 set_blocksize(sb
->s_dev
, BLOCK_SIZE
);
141 * This is the statfs() entry in the super_operations structure for
142 * HFS filesystems. The purpose is to return various data about the
145 * changed f_files/f_ffree to reflect the fs_ablock/free_ablocks.
147 static int hfs_statfs(struct super_block
*sb
, struct statfs
*buf
, int len
)
149 struct hfs_mdb
*mdb
= HFS_SB(sb
)->s_mdb
;
152 tmp
.f_type
= HFS_SUPER_MAGIC
;
153 tmp
.f_bsize
= HFS_SECTOR_SIZE
;
154 tmp
.f_blocks
= mdb
->alloc_blksz
* mdb
->fs_ablocks
;
155 tmp
.f_bfree
= mdb
->alloc_blksz
* mdb
->free_ablocks
;
156 tmp
.f_bavail
= tmp
.f_bfree
;
157 tmp
.f_files
= mdb
->fs_ablocks
;
158 tmp
.f_ffree
= mdb
->free_ablocks
;
159 tmp
.f_namelen
= HFS_NAMELEN
;
161 return copy_to_user(buf
, &tmp
, len
) ? -EFAULT
: 0;
167 * adapted from linux/fs/msdos/inode.c written 1992,93 by Werner Almesberger
168 * This function is called by hfs_read_super() to parse the mount options.
170 static int parse_options(char *options
, struct hfs_sb_info
*hsb
, int *part
)
172 char *this_char
, *value
;
175 /* initialize the sb with defaults */
176 memset(hsb
, 0, sizeof(*hsb
));
177 hsb
->magic
= HFS_SB_MAGIC
;
178 hsb
->s_uid
= current
->uid
;
179 hsb
->s_gid
= current
->gid
;
180 hsb
->s_umask
= current
->fs
->umask
;
181 hsb
->s_type
= 0x3f3f3f3f; /* == '????' */
182 hsb
->s_creator
= 0x3f3f3f3f; /* == '????' */
183 hsb
->s_lowercase
= 0;
186 /* default version. 0 just selects the defaults */
196 for (this_char
= strtok(options
,","); this_char
;
197 this_char
= strtok(NULL
,",")) {
198 if ((value
= strchr(this_char
,'=')) != NULL
) {
201 /* Numeric-valued options */
202 if (!strcmp(this_char
, "version")) {
203 if (!value
|| !*value
) {
206 hsb
->s_version
= simple_strtoul(value
,&value
,0);
210 } else if (!strcmp(this_char
,"uid")) {
211 if (!value
|| !*value
) {
214 hsb
->s_uid
= simple_strtoul(value
,&value
,0);
218 } else if (!strcmp(this_char
,"gid")) {
219 if (!value
|| !*value
) {
222 hsb
->s_gid
= simple_strtoul(value
,&value
,0);
226 } else if (!strcmp(this_char
,"umask")) {
227 if (!value
|| !*value
) {
230 hsb
->s_umask
= simple_strtoul(value
,&value
,8);
234 } else if (!strcmp(this_char
,"part")) {
235 if (!value
|| !*value
) {
238 *part
= simple_strtoul(value
,&value
,0);
242 /* String-valued options */
243 } else if (!strcmp(this_char
,"type") && value
) {
244 if (strlen(value
) != 4) {
247 hsb
->s_type
= hfs_get_nl(value
);
248 } else if (!strcmp(this_char
,"creator") && value
) {
249 if (strlen(value
) != 4) {
252 hsb
->s_creator
= hfs_get_nl(value
);
253 /* Boolean-valued options */
254 } else if (!strcmp(this_char
,"quiet")) {
259 } else if (!strcmp(this_char
,"afpd")) {
264 /* Multiple choice options */
265 } else if (!strcmp(this_char
,"names") && value
) {
266 if ((*value
&& !value
[1] && strchr("ntal78c",*value
)) ||
267 !strcmp(value
,"netatalk") ||
268 !strcmp(value
,"trivial") ||
269 !strcmp(value
,"alpha") ||
270 !strcmp(value
,"latin") ||
271 !strcmp(value
,"7bit") ||
272 !strcmp(value
,"8bit") ||
273 !strcmp(value
,"cap")) {
278 } else if (!strcmp(this_char
,"fork") && value
) {
279 if ((*value
&& !value
[1] && strchr("nsdc",*value
)) ||
280 !strcmp(value
,"netatalk") ||
281 !strcmp(value
,"single") ||
282 !strcmp(value
,"double") ||
283 !strcmp(value
,"cap")) {
288 } else if (!strcmp(this_char
,"case") && value
) {
289 if ((*value
&& !value
[1] && strchr("la",*value
)) ||
290 !strcmp(value
,"lower") ||
291 !strcmp(value
,"asis")) {
292 hsb
->s_lowercase
= (*value
== 'l');
296 } else if (!strcmp(this_char
,"conv") && value
) {
297 if ((*value
&& !value
[1] && strchr("bta",*value
)) ||
298 !strcmp(value
,"binary") ||
299 !strcmp(value
,"text") ||
300 !strcmp(value
,"auto")) {
301 hsb
->s_conv
= *value
;
311 /* Parse the "fork" and "names" options */
313 fork
= hsb
->s_afpd
? 'n' : 'c';
318 hsb
->s_ifill
= hfs_cap_ifill
;
319 hsb
->s_reserved1
= hfs_cap_reserved1
;
320 hsb
->s_reserved2
= hfs_cap_reserved2
;
324 hfs_warn("hfs_fs: AppleSingle not yet implemented.\n");
329 hsb
->s_ifill
= hfs_dbl_ifill
;
330 hsb
->s_reserved1
= hfs_dbl_reserved1
;
331 hsb
->s_reserved2
= hfs_dbl_reserved2
;
335 hsb
->s_ifill
= hfs_nat_ifill
;
336 hsb
->s_reserved1
= hfs_nat_reserved1
;
337 hsb
->s_reserved2
= hfs_nat_reserved2
;
347 hsb
->s_nameout
= hfs_colon2mac
;
348 hsb
->s_namein
= hfs_mac2nat
;
352 hsb
->s_nameout
= hfs_colon2mac
;
353 hsb
->s_namein
= hfs_mac2cap
;
357 hsb
->s_nameout
= hfs_triv2mac
;
358 hsb
->s_namein
= hfs_mac2triv
;
362 hsb
->s_nameout
= hfs_prcnt2mac
;
363 hsb
->s_namein
= hfs_mac2seven
;
367 hsb
->s_nameout
= hfs_prcnt2mac
;
368 hsb
->s_namein
= hfs_mac2eight
;
372 hsb
->s_nameout
= hfs_latin2mac
;
373 hsb
->s_namein
= hfs_mac2latin
;
376 case 'a': /* 's' and 'd' are unadvertised aliases for 'alpha', */
377 case 's': /* since 'alpha' is the default if fork=s or fork=d. */
378 case 'd': /* (It is also helpful for poor typists!) */
379 hsb
->s_nameout
= hfs_prcnt2mac
;
380 hsb
->s_namein
= hfs_mac2alpha
;
387 /*================ Global functions ================*/
392 * This is the function that is responsible for mounting an HFS
393 * filesystem. It performs all the tasks necessary to get enough data
394 * from the disk to read the root inode. This includes parsing the
395 * mount options, dealing with Macintosh partitions, reading the
396 * superblock and the allocation bitmap blocks, calling
397 * hfs_btree_init() to get the necessary data about the extents and
398 * catalog B-trees and, finally, reading the root inode into memory.
400 struct super_block
*hfs_read_super(struct super_block
*s
, void *data
,
404 struct hfs_cat_key key
;
405 kdev_t dev
= s
->s_dev
;
406 hfs_s32 part_size
, part_start
;
407 struct inode
*root_inode
;
410 if (!parse_options((char *)data
, HFS_SB(s
), &part
)) {
411 hfs_warn("hfs_fs: unable to parse mount options.\n");
415 /* in case someone tries to unload the module while we wait on I/O */
420 /* set the device driver to 512-byte blocks */
421 set_blocksize(dev
, HFS_SECTOR_SIZE
);
423 #ifdef CONFIG_MAC_PARTITION
424 /* check to see if we're in a partition */
425 mdb
= hfs_mdb_get(s
, s
->s_flags
& MS_RDONLY
, 0);
427 /* erk. try parsing the partition table ourselves */
429 if (hfs_part_find(s
, part
, silent
, &part_size
, &part_start
)) {
432 mdb
= hfs_mdb_get(s
, s
->s_flags
& MS_RDONLY
, part_start
);
435 if (hfs_part_find(s
, part
, silent
, &part_size
, &part_start
)) {
439 mdb
= hfs_mdb_get(s
, s
->s_flags
& MS_RDONLY
, part_start
);
444 hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n",
450 HFS_SB(s
)->s_mdb
= mdb
;
451 if (HFS_ITYPE(mdb
->next_id
) != 0) {
452 hfs_warn("hfs_fs: too many files.\n");
456 s
->s_magic
= HFS_SUPER_MAGIC
;
457 s
->s_blocksize_bits
= HFS_SECTOR_SIZE_BITS
;
458 s
->s_blocksize
= HFS_SECTOR_SIZE
;
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 */
483 hfs_warn("hfs_fs: get root inode failed.\n");
486 hfs_mdb_put(mdb
, s
->s_flags
& MS_RDONLY
);
488 set_blocksize(dev
, BLOCK_SIZE
);
496 int __init
init_hfs_fs(void)
499 return register_filesystem(&hfs_fs
);
503 int init_module(void) {
506 #if defined(DEBUG_SIZES) || defined(DEBUG_ALL)
507 hfs_warn("HFS inode: %d bytes available\n",
508 sizeof(struct ext2_inode_info
)-sizeof(struct hfs_inode_info
));
509 hfs_warn("HFS super_block: %d bytes available\n",
510 sizeof(struct ext2_sb_info
)-sizeof(struct hfs_sb_info
));
511 if ((sizeof(struct hfs_inode_info
)>sizeof(struct ext2_inode_info
)) ||
512 (sizeof(struct hfs_sb_info
)>sizeof(struct ext2_sb_info
))) {
513 return -ENOMEM
; /* well sort of */
516 error
= init_hfs_fs();
518 /* register_symtab(NULL); */
523 void cleanup_module(void) {
525 unregister_filesystem(&hfs_fs
);
529 #if defined(DEBUG_ALL) || defined(DEBUG_MEM)
530 long int hfs_alloc
= 0;