File: /usr/src/linux/fs/hfs/super.c

1     /*
2      * linux/fs/hfs/super.c
3      *
4      * Copyright (C) 1995-1997  Paul H. Hargrove
5      * This file may be distributed under the terms of the GNU General Public License.
6      *
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.
10      *
11      * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
12      *
13      * "XXX" in a comment is a note to myself to consider changing something.
14      *
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.
18      *
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.
23      */
24     
25     #include "hfs.h"
26     #include <linux/hfs_fs_sb.h>
27     #include <linux/hfs_fs_i.h>
28     #include <linux/hfs_fs.h>
29     
30     #include <linux/config.h> /* for CONFIG_MAC_PARTITION */
31     #include <linux/blkdev.h>
32     #include <linux/module.h>
33     #include <linux/init.h>
34     
35     /*================ Forward declarations ================*/
36     
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 *);
41     
42     /*================ Global variables ================*/
43     
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,
50     };
51     
52     /*================ File-local variables ================*/
53     
54     static DECLARE_FSTYPE_DEV(hfs_fs, "hfs", hfs_read_super);
55     
56     /*================ File-local functions ================*/
57     
58     /* 
59      * hfs_read_inode()
60      *
61      * this doesn't actually do much. hfs_iget actually fills in the 
62      * necessary inode information.
63      */
64     static void hfs_read_inode(struct inode *inode)
65     {
66       inode->i_mode = 0;
67     }
68     
69     /*
70      * hfs_write_super()
71      *
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().
87      */
88     static void hfs_write_super(struct super_block *sb)
89     {
90     	struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
91     
92     	/* is this a valid hfs superblock? */
93     	if (!sb || sb->s_magic != HFS_SUPER_MAGIC) {
94     		return;
95     	}
96     
97     	if (!(sb->s_flags & MS_RDONLY)) {
98     		/* sync everything to the buffers */
99     		hfs_mdb_commit(mdb, 0);
100     	}
101     	sb->s_dirt = 0;
102     }
103     
104     /*
105      * hfs_put_super()
106      *
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.
110      */
111     static void hfs_put_super(struct super_block *sb)
112     {
113     	struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
114      
115     	if (!(sb->s_flags & MS_RDONLY)) {
116     		hfs_mdb_commit(mdb, 0);
117     		sb->s_dirt = 0;
118     	}
119     
120     	/* release the MDB's resources */
121     	hfs_mdb_put(mdb, sb->s_flags & MS_RDONLY);
122     
123     	/* restore default blocksize for the device */
124     	set_blocksize(sb->s_dev, BLOCK_SIZE);
125     }
126     
127     /*
128      * hfs_statfs()
129      *
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.
133      *
134      * changed f_files/f_ffree to reflect the fs_ablock/free_ablocks.
135      */
136     static int hfs_statfs(struct super_block *sb, struct statfs *buf)
137     {
138     	struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
139     
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;
148     
149     	return 0;
150     }
151     
152     /*
153      * parse_options()
154      * 
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.
157      */
158     static int parse_options(char *options, struct hfs_sb_info *hsb, int *part)
159     {
160     	char *this_char, *value;
161     	char names, fork;
162     
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;
180     
181     	if (!options) {
182     		goto done;
183     	}
184     	for (this_char = strtok(options,","); this_char;
185     	     this_char = strtok(NULL,",")) {
186     		if ((value = strchr(this_char,'=')) != NULL) {
187     			*value++ = 0;
188     		}
189     	/* Numeric-valued options */
190     		if (!strcmp(this_char, "version")) {
191     			if (!value || !*value) {
192     				return 0;
193     			}
194     			hsb->s_version = simple_strtoul(value,&value,0);
195     			if (*value) {
196     				return 0;
197     			}
198     		} else if (!strcmp(this_char,"uid")) {
199     			if (!value || !*value) {
200     				return 0;
201     			}
202     			hsb->s_uid = simple_strtoul(value,&value,0);
203     			if (*value) {
204     				return 0;
205     			}
206     		} else if (!strcmp(this_char,"gid")) {
207     			if (!value || !*value) {
208     				return 0;
209     			}
210     			hsb->s_gid = simple_strtoul(value,&value,0);
211     			if (*value) {
212     				return 0;
213     			}
214     		} else if (!strcmp(this_char,"umask")) {
215     			if (!value || !*value) {
216     				return 0;
217     			}
218     			hsb->s_umask = simple_strtoul(value,&value,8);
219     			if (*value) {
220     				return 0;
221     			}
222     		} else if (!strcmp(this_char,"part")) {
223     			if (!value || !*value) {
224     				return 0;
225     			}
226     			*part = simple_strtoul(value,&value,0);
227     			if (*value) {
228     				return 0;
229     			}
230     	/* String-valued options */
231     		} else if (!strcmp(this_char,"type") && value) {
232     			if (strlen(value) != 4) {
233     				return 0;
234     			}
235     			hsb->s_type = hfs_get_nl(value);
236     		} else if (!strcmp(this_char,"creator") && value) {
237     			if (strlen(value) != 4) {
238     				return 0;
239     			}
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;
245     			}
246     			hsb->s_quiet = 1;
247     		} else if (!strcmp(this_char,"afpd")) {
248     			if (value) {
249     				return 0;
250     			}
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;
265     			}
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;
275     			}
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;
283     			}
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;
292     			}
293     		} else {
294     			return 0;
295     		}
296     	}
297     
298     done:
299     	/* Parse the "fork" and "names" options */
300     	if (fork == '?') {
301     		fork = hsb->s_afpd ? 'n' : 'c';
302     	}
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;
310     
311     	case 's':
312     		hfs_warn("hfs_fs: AppleSingle not yet implemented.\n");
313     		return 0;
314     		/* break; */
315     	
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;
321     
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;
327     	}
328     
329     	if (names == '?') {
330     		names = fork;
331     	}
332     	switch (names) {
333     	default:
334     	case 'n':
335     		hsb->s_nameout = hfs_colon2mac;
336     		hsb->s_namein = hfs_mac2nat;
337     		break;
338     
339     	case 'c':
340     		hsb->s_nameout = hfs_colon2mac;
341     		hsb->s_namein = hfs_mac2cap;
342     		break;
343     
344     	case 't':
345     		hsb->s_nameout = hfs_triv2mac;
346     		hsb->s_namein = hfs_mac2triv;
347     		break;
348     
349     	case '7':
350     		hsb->s_nameout = hfs_prcnt2mac;
351     		hsb->s_namein = hfs_mac2seven;
352     		break;
353     
354     	case '8':
355     		hsb->s_nameout = hfs_prcnt2mac;
356     		hsb->s_namein = hfs_mac2eight;
357     		break;
358     
359     	case 'l':
360     		hsb->s_nameout = hfs_latin2mac;
361     		hsb->s_namein = hfs_mac2latin;
362     		break;
363     
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;
370     	}
371     
372     	return 1;
373     }
374     
375     /*================ Global functions ================*/
376     
377     /*
378      * hfs_read_super()
379      *
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.
387      */
388     struct super_block *hfs_read_super(struct super_block *s, void *data,
389     				   int silent)
390     {
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;
397     
398     	if (!parse_options((char *)data, HFS_SB(s), &part)) {
399     		hfs_warn("hfs_fs: unable to parse mount options.\n");
400     		goto bail3;
401     	}
402     
403     	/* set the device driver to 512-byte blocks */
404     	set_blocksize(dev, HFS_SECTOR_SIZE);
405     
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);
409     
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;
414     	  	}
415     	  	mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start);
416     	}
417     #else
418     	if (hfs_part_find(s, part, silent, &part_size, &part_start)) {
419     		goto bail2;
420     	}
421     
422     	mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start);
423     #endif
424     
425     	if (!mdb) {
426     		if (!silent) {
427     			hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n",
428     			       kdevname(dev));
429     		}
430     		goto bail2;
431     	}
432     
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;
437     	}
438     
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;
443     
444     	/* try to get the root inode */
445     	hfs_cat_build_key(htonl(HFS_POR_CNID),
446     			  (struct hfs_name *)(mdb->vname), &key);
447     
448     	root_inode = hfs_iget(hfs_cat_get(mdb, &key), HFS_ITYPE_NORM, NULL);
449     	if (!root_inode) 
450     		goto bail_no_root;
451     	  
452     	s->s_root = d_alloc_root(root_inode);
453     	if (!s->s_root) 
454     		goto bail_no_root;
455     
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;
460     
461     	/* everything's okay */
462     	return s;
463     
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;	
473     }
474     
475     static int __init init_hfs_fs(void)
476     {
477             hfs_cat_init();
478     	return register_filesystem(&hfs_fs);
479     }
480     
481     static void __exit exit_hfs_fs(void) {
482     	hfs_cat_free();
483     	unregister_filesystem(&hfs_fs);
484     }
485     
486     module_init(init_hfs_fs)
487     module_exit(exit_hfs_fs)
488     
489     #if defined(DEBUG_ALL) || defined(DEBUG_MEM)
490     long int hfs_alloc = 0;
491     #endif
492