Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / fs / hfs / super.c
blob8c91758d60ee7de085d252fede6dbc5e395db93a
1 /*
2 * linux/fs/hfs/super.c
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.
25 #include "hfs.h"
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 *);
40 static void hfs_write_super(struct super_block *);
42 /*================ Global variables ================*/
44 static struct super_operations hfs_super_operations = {
45 read_inode: hfs_read_inode,
46 put_inode: hfs_put_inode,
47 put_super: hfs_put_super,
48 write_super: hfs_write_super,
49 statfs: hfs_statfs,
52 /*================ File-local variables ================*/
54 static DECLARE_FSTYPE_DEV(hfs_fs, "hfs", hfs_read_super);
56 /*================ File-local functions ================*/
58 /*
59 * hfs_read_inode()
61 * this doesn't actually do much. hfs_iget actually fills in the
62 * necessary inode information.
64 static void hfs_read_inode(struct inode *inode)
66 inode->i_mode = 0;
70 * hfs_write_super()
72 * Description:
73 * This function is called by the VFS only. When the filesystem
74 * is mounted r/w it updates the MDB on disk.
75 * Input Variable(s):
76 * struct super_block *sb: Pointer to the hfs superblock
77 * Output Variable(s):
78 * NONE
79 * Returns:
80 * void
81 * Preconditions:
82 * 'sb' points to a "valid" (struct super_block).
83 * Postconditions:
84 * The MDB is marked 'unsuccessfully unmounted' by clearing bit 8 of drAtrb
85 * (hfs_put_super() must set this flag!). Some MDB fields are updated
86 * and the MDB buffer is written to disk by calling hfs_mdb_commit().
88 static void hfs_write_super(struct super_block *sb)
90 struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
92 /* is this a valid hfs superblock? */
93 if (!sb || sb->s_magic != HFS_SUPER_MAGIC) {
94 return;
97 if (!(sb->s_flags & MS_RDONLY)) {
98 /* sync everything to the buffers */
99 hfs_mdb_commit(mdb, 0);
101 sb->s_dirt = 0;
105 * hfs_put_super()
107 * This is the put_super() entry in the super_operations structure for
108 * HFS filesystems. The purpose is to release the resources
109 * associated with the superblock sb.
111 static void hfs_put_super(struct super_block *sb)
113 struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
115 if (!(sb->s_flags & MS_RDONLY)) {
116 hfs_mdb_commit(mdb, 0);
117 sb->s_dirt = 0;
120 /* release the MDB's resources */
121 hfs_mdb_put(mdb, sb->s_flags & MS_RDONLY);
123 /* restore default blocksize for the device */
124 set_blocksize(sb->s_dev, BLOCK_SIZE);
128 * hfs_statfs()
130 * This is the statfs() entry in the super_operations structure for
131 * HFS filesystems. The purpose is to return various data about the
132 * filesystem.
134 * changed f_files/f_ffree to reflect the fs_ablock/free_ablocks.
136 static int hfs_statfs(struct super_block *sb, struct statfs *buf)
138 struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
140 buf->f_type = HFS_SUPER_MAGIC;
141 buf->f_bsize = HFS_SECTOR_SIZE;
142 buf->f_blocks = mdb->alloc_blksz * mdb->fs_ablocks;
143 buf->f_bfree = mdb->alloc_blksz * mdb->free_ablocks;
144 buf->f_bavail = buf->f_bfree;
145 buf->f_files = mdb->fs_ablocks;
146 buf->f_ffree = mdb->free_ablocks;
147 buf->f_namelen = HFS_NAMELEN;
149 return 0;
153 * parse_options()
155 * adapted from linux/fs/msdos/inode.c written 1992,93 by Werner Almesberger
156 * This function is called by hfs_read_super() to parse the mount options.
158 static int parse_options(char *options, struct hfs_sb_info *hsb, int *part)
160 char *this_char, *value;
161 char names, fork;
163 /* initialize the sb with defaults */
164 memset(hsb, 0, sizeof(*hsb));
165 hsb->magic = HFS_SB_MAGIC;
166 hsb->s_uid = current->uid;
167 hsb->s_gid = current->gid;
168 hsb->s_umask = current->fs->umask;
169 hsb->s_type = 0x3f3f3f3f; /* == '????' */
170 hsb->s_creator = 0x3f3f3f3f; /* == '????' */
171 hsb->s_lowercase = 0;
172 hsb->s_quiet = 0;
173 hsb->s_afpd = 0;
174 /* default version. 0 just selects the defaults */
175 hsb->s_version = 0;
176 hsb->s_conv = 'b';
177 names = '?';
178 fork = '?';
179 *part = 0;
181 if (!options) {
182 goto done;
184 for (this_char = strtok(options,","); this_char;
185 this_char = strtok(NULL,",")) {
186 if ((value = strchr(this_char,'=')) != NULL) {
187 *value++ = 0;
189 /* Numeric-valued options */
190 if (!strcmp(this_char, "version")) {
191 if (!value || !*value) {
192 return 0;
194 hsb->s_version = simple_strtoul(value,&value,0);
195 if (*value) {
196 return 0;
198 } else if (!strcmp(this_char,"uid")) {
199 if (!value || !*value) {
200 return 0;
202 hsb->s_uid = simple_strtoul(value,&value,0);
203 if (*value) {
204 return 0;
206 } else if (!strcmp(this_char,"gid")) {
207 if (!value || !*value) {
208 return 0;
210 hsb->s_gid = simple_strtoul(value,&value,0);
211 if (*value) {
212 return 0;
214 } else if (!strcmp(this_char,"umask")) {
215 if (!value || !*value) {
216 return 0;
218 hsb->s_umask = simple_strtoul(value,&value,8);
219 if (*value) {
220 return 0;
222 } else if (!strcmp(this_char,"part")) {
223 if (!value || !*value) {
224 return 0;
226 *part = simple_strtoul(value,&value,0);
227 if (*value) {
228 return 0;
230 /* String-valued options */
231 } else if (!strcmp(this_char,"type") && value) {
232 if (strlen(value) != 4) {
233 return 0;
235 hsb->s_type = hfs_get_nl(value);
236 } else if (!strcmp(this_char,"creator") && value) {
237 if (strlen(value) != 4) {
238 return 0;
240 hsb->s_creator = hfs_get_nl(value);
241 /* Boolean-valued options */
242 } else if (!strcmp(this_char,"quiet")) {
243 if (value) {
244 return 0;
246 hsb->s_quiet = 1;
247 } else if (!strcmp(this_char,"afpd")) {
248 if (value) {
249 return 0;
251 hsb->s_afpd = 1;
252 /* Multiple choice options */
253 } else if (!strcmp(this_char,"names") && value) {
254 if ((*value && !value[1] && strchr("ntal78c",*value)) ||
255 !strcmp(value,"netatalk") ||
256 !strcmp(value,"trivial") ||
257 !strcmp(value,"alpha") ||
258 !strcmp(value,"latin") ||
259 !strcmp(value,"7bit") ||
260 !strcmp(value,"8bit") ||
261 !strcmp(value,"cap")) {
262 names = *value;
263 } else {
264 return 0;
266 } else if (!strcmp(this_char,"fork") && value) {
267 if ((*value && !value[1] && strchr("nsdc",*value)) ||
268 !strcmp(value,"netatalk") ||
269 !strcmp(value,"single") ||
270 !strcmp(value,"double") ||
271 !strcmp(value,"cap")) {
272 fork = *value;
273 } else {
274 return 0;
276 } else if (!strcmp(this_char,"case") && value) {
277 if ((*value && !value[1] && strchr("la",*value)) ||
278 !strcmp(value,"lower") ||
279 !strcmp(value,"asis")) {
280 hsb->s_lowercase = (*value == 'l');
281 } else {
282 return 0;
284 } else if (!strcmp(this_char,"conv") && value) {
285 if ((*value && !value[1] && strchr("bta",*value)) ||
286 !strcmp(value,"binary") ||
287 !strcmp(value,"text") ||
288 !strcmp(value,"auto")) {
289 hsb->s_conv = *value;
290 } else {
291 return 0;
293 } else {
294 return 0;
298 done:
299 /* Parse the "fork" and "names" options */
300 if (fork == '?') {
301 fork = hsb->s_afpd ? 'n' : 'c';
303 switch (fork) {
304 default:
305 case 'c':
306 hsb->s_ifill = hfs_cap_ifill;
307 hsb->s_reserved1 = hfs_cap_reserved1;
308 hsb->s_reserved2 = hfs_cap_reserved2;
309 break;
311 case 's':
312 hfs_warn("hfs_fs: AppleSingle not yet implemented.\n");
313 return 0;
314 /* break; */
316 case 'd':
317 hsb->s_ifill = hfs_dbl_ifill;
318 hsb->s_reserved1 = hfs_dbl_reserved1;
319 hsb->s_reserved2 = hfs_dbl_reserved2;
320 break;
322 case 'n':
323 hsb->s_ifill = hfs_nat_ifill;
324 hsb->s_reserved1 = hfs_nat_reserved1;
325 hsb->s_reserved2 = hfs_nat_reserved2;
326 break;
329 if (names == '?') {
330 names = fork;
332 switch (names) {
333 default:
334 case 'n':
335 hsb->s_nameout = hfs_colon2mac;
336 hsb->s_namein = hfs_mac2nat;
337 break;
339 case 'c':
340 hsb->s_nameout = hfs_colon2mac;
341 hsb->s_namein = hfs_mac2cap;
342 break;
344 case 't':
345 hsb->s_nameout = hfs_triv2mac;
346 hsb->s_namein = hfs_mac2triv;
347 break;
349 case '7':
350 hsb->s_nameout = hfs_prcnt2mac;
351 hsb->s_namein = hfs_mac2seven;
352 break;
354 case '8':
355 hsb->s_nameout = hfs_prcnt2mac;
356 hsb->s_namein = hfs_mac2eight;
357 break;
359 case 'l':
360 hsb->s_nameout = hfs_latin2mac;
361 hsb->s_namein = hfs_mac2latin;
362 break;
364 case 'a': /* 's' and 'd' are unadvertised aliases for 'alpha', */
365 case 's': /* since 'alpha' is the default if fork=s or fork=d. */
366 case 'd': /* (It is also helpful for poor typists!) */
367 hsb->s_nameout = hfs_prcnt2mac;
368 hsb->s_namein = hfs_mac2alpha;
369 break;
372 return 1;
375 /*================ Global functions ================*/
378 * hfs_read_super()
380 * This is the function that is responsible for mounting an HFS
381 * filesystem. It performs all the tasks necessary to get enough data
382 * from the disk to read the root inode. This includes parsing the
383 * mount options, dealing with Macintosh partitions, reading the
384 * superblock and the allocation bitmap blocks, calling
385 * hfs_btree_init() to get the necessary data about the extents and
386 * catalog B-trees and, finally, reading the root inode into memory.
388 struct super_block *hfs_read_super(struct super_block *s, void *data,
389 int silent)
391 struct hfs_mdb *mdb;
392 struct hfs_cat_key key;
393 kdev_t dev = s->s_dev;
394 hfs_s32 part_size, part_start;
395 struct inode *root_inode;
396 int part;
398 if (!parse_options((char *)data, HFS_SB(s), &part)) {
399 hfs_warn("hfs_fs: unable to parse mount options.\n");
400 goto bail3;
403 /* set the device driver to 512-byte blocks */
404 set_blocksize(dev, HFS_SECTOR_SIZE);
406 #ifdef CONFIG_MAC_PARTITION
407 /* check to see if we're in a partition */
408 mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, 0);
410 /* erk. try parsing the partition table ourselves */
411 if (!mdb) {
412 if (hfs_part_find(s, part, silent, &part_size, &part_start)) {
413 goto bail2;
415 mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start);
417 #else
418 if (hfs_part_find(s, part, silent, &part_size, &part_start)) {
419 goto bail2;
422 mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start);
423 #endif
425 if (!mdb) {
426 if (!silent) {
427 hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n",
428 kdevname(dev));
430 goto bail2;
433 HFS_SB(s)->s_mdb = mdb;
434 if (HFS_ITYPE(mdb->next_id) != 0) {
435 hfs_warn("hfs_fs: too many files.\n");
436 goto bail1;
439 s->s_magic = HFS_SUPER_MAGIC;
440 s->s_blocksize_bits = HFS_SECTOR_SIZE_BITS;
441 s->s_blocksize = HFS_SECTOR_SIZE;
442 s->s_op = &hfs_super_operations;
444 /* try to get the root inode */
445 hfs_cat_build_key(htonl(HFS_POR_CNID),
446 (struct hfs_name *)(mdb->vname), &key);
448 root_inode = hfs_iget(hfs_cat_get(mdb, &key), HFS_ITYPE_NORM, NULL);
449 if (!root_inode)
450 goto bail_no_root;
452 s->s_root = d_alloc_root(root_inode);
453 if (!s->s_root)
454 goto bail_no_root;
456 /* fix up pointers. */
457 HFS_I(root_inode)->entry->sys_entry[HFS_ITYPE_TO_INT(HFS_ITYPE_NORM)] =
458 s->s_root;
459 s->s_root->d_op = &hfs_dentry_operations;
461 /* everything's okay */
462 return s;
464 bail_no_root:
465 hfs_warn("hfs_fs: get root inode failed.\n");
466 iput(root_inode);
467 bail1:
468 hfs_mdb_put(mdb, s->s_flags & MS_RDONLY);
469 bail2:
470 set_blocksize(dev, BLOCK_SIZE);
471 bail3:
472 return NULL;
475 static int __init init_hfs_fs(void)
477 hfs_cat_init();
478 return register_filesystem(&hfs_fs);
481 static void __exit exit_hfs_fs(void) {
482 hfs_cat_free();
483 unregister_filesystem(&hfs_fs);
486 module_init(init_hfs_fs)
487 module_exit(exit_hfs_fs)
489 #if defined(DEBUG_ALL) || defined(DEBUG_MEM)
490 long int hfs_alloc = 0;
491 #endif