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 MODULE_LICENSE("GPL");
36 
37 /*================ Forward declarations ================*/
38 
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 *);
43 
44 /*================ Global variables ================*/
45 
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,
51 	statfs:		hfs_statfs,
52 	remount_fs:     hfs_remount,
53 };
54 
55 /*================ File-local variables ================*/
56 
57 static DECLARE_FSTYPE_DEV(hfs_fs, "hfs", hfs_read_super);
58 
59 /*================ File-local functions ================*/
60 
61 /*
62  * hfs_read_inode()
63  *
64  * this doesn't actually do much. hfs_iget actually fills in the
65  * necessary inode information.
66  */
hfs_read_inode(struct inode * inode)67 static void hfs_read_inode(struct inode *inode)
68 {
69   inode->i_mode = 0;
70 }
71 
72 /*
73  * hfs_write_super()
74  *
75  * Description:
76  *   This function is called by the VFS only. When the filesystem
77  *   is mounted r/w it updates the MDB on disk.
78  * Input Variable(s):
79  *   struct super_block *sb: Pointer to the hfs superblock
80  * Output Variable(s):
81  *   NONE
82  * Returns:
83  *   void
84  * Preconditions:
85  *   'sb' points to a "valid" (struct super_block).
86  * Postconditions:
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().
90  */
hfs_write_super(struct super_block * sb)91 static void hfs_write_super(struct super_block *sb)
92 {
93 	struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
94 
95 	/* is this a valid hfs superblock? */
96 	if (!sb || sb->s_magic != HFS_SUPER_MAGIC) {
97 		return;
98 	}
99 
100 	if (!(sb->s_flags & MS_RDONLY)) {
101 		/* sync everything to the buffers */
102 		hfs_mdb_commit(mdb, 0);
103 	}
104 	sb->s_dirt = 0;
105 }
106 
107 /*
108  * hfs_put_super()
109  *
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.
113  */
hfs_put_super(struct super_block * sb)114 static void hfs_put_super(struct super_block *sb)
115 {
116 	struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
117 
118 	if (!(sb->s_flags & MS_RDONLY)) {
119 		hfs_mdb_commit(mdb, 0);
120 		sb->s_dirt = 0;
121 	}
122 
123 	/* release the MDB's resources */
124 	hfs_mdb_put(mdb, sb->s_flags & MS_RDONLY);
125 
126 	/* restore default blocksize for the device */
127 	set_blocksize(sb->s_dev, BLOCK_SIZE);
128 }
129 
130 /*
131  * hfs_statfs()
132  *
133  * This is the statfs() entry in the super_operations structure for
134  * HFS filesystems.  The purpose is to return various data about the
135  * filesystem.
136  *
137  * changed f_files/f_ffree to reflect the fs_ablock/free_ablocks.
138  */
hfs_statfs(struct super_block * sb,struct statfs * buf)139 static int hfs_statfs(struct super_block *sb, struct statfs *buf)
140 {
141 	struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
142 
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;
151 
152 	return 0;
153 }
154 
155 /*
156  * parse_options()
157  *
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.
160  */
parse_options(char * options,struct hfs_sb_info * hsb,int * part)161 static int parse_options(char *options, struct hfs_sb_info *hsb, int *part)
162 {
163 	char *this_char, *value;
164 	char names, fork;
165 
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;
175 		hsb->s_quiet     = 0;
176 		hsb->s_afpd      = 0;
177 		/* default version. 0 just selects the defaults */
178 		hsb->s_version   = 0;
179 		hsb->s_conv = 'b';
180 		names = '?';
181 		fork = '?';
182 		*part = 0;
183 	}
184 
185 	if (!options) {
186 		goto done;
187 	}
188 	for (this_char = strtok(options,","); this_char;
189 	     this_char = strtok(NULL,",")) {
190 		if ((value = strchr(this_char,'=')) != NULL) {
191 			*value++ = 0;
192 		}
193 	/* Numeric-valued options */
194 		if (!strcmp(this_char, "version")) {
195 			if (!value || !*value) {
196 				return 0;
197 			}
198 			hsb->s_version = simple_strtoul(value,&value,0);
199 			if (*value) {
200 				return 0;
201 			}
202 		} else if (!strcmp(this_char,"uid")) {
203 			if (!value || !*value) {
204 				return 0;
205 			}
206 			hsb->s_uid = simple_strtoul(value,&value,0);
207 			if (*value) {
208 				return 0;
209 			}
210 		} else if (!strcmp(this_char,"gid")) {
211 			if (!value || !*value) {
212 				return 0;
213 			}
214 			hsb->s_gid = simple_strtoul(value,&value,0);
215 			if (*value) {
216 				return 0;
217 			}
218 		} else if (!strcmp(this_char,"umask")) {
219 			if (!value || !*value) {
220 				return 0;
221 			}
222 			hsb->s_umask = simple_strtoul(value,&value,8);
223 			if (*value) {
224 				return 0;
225 			}
226 		} else if (!strcmp(this_char,"part")) {
227 			if (!value || !*value) {
228 				return 0;
229 			}
230 			*part = simple_strtoul(value,&value,0);
231 			if (*value) {
232 				return 0;
233 			}
234 	/* String-valued options */
235 		} else if (!strcmp(this_char,"type") && value) {
236 			if (strlen(value) != 4) {
237 				return 0;
238 			}
239 			hsb->s_type = hfs_get_nl(value);
240 		} else if (!strcmp(this_char,"creator") && value) {
241 			if (strlen(value) != 4) {
242 				return 0;
243 			}
244 			hsb->s_creator = hfs_get_nl(value);
245 	/* Boolean-valued options */
246 		} else if (!strcmp(this_char,"quiet")) {
247 			if (value) {
248 				return 0;
249 			}
250 			hsb->s_quiet = 1;
251 		} else if (!strcmp(this_char,"afpd")) {
252 			if (value) {
253 				return 0;
254 			}
255 			hsb->s_afpd = 1;
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")) {
266 				names = *value;
267 			} else {
268 				return 0;
269 			}
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")) {
276 				fork = *value;
277 			} else {
278 				return 0;
279 			}
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');
285 			} else {
286 				return 0;
287 			}
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;
294 			} else {
295 				return 0;
296 			}
297 		} else {
298 			return 0;
299 		}
300 	}
301 
302 done:
303 	/* Parse the "fork" and "names" options */
304 	if (fork == '?') {
305 		fork = hsb->s_afpd ? 'n' : 'c';
306 	}
307 	switch (fork) {
308 	default:
309 	case 'c':
310 		hsb->s_ifill = hfs_cap_ifill;
311 		hsb->s_reserved1 = hfs_cap_reserved1;
312 		hsb->s_reserved2 = hfs_cap_reserved2;
313 		break;
314 
315 	case 's':
316 		hfs_warn("hfs_fs: AppleSingle not yet implemented.\n");
317 		return 0;
318 		/* break; */
319 
320 	case 'd':
321 		hsb->s_ifill = hfs_dbl_ifill;
322 		hsb->s_reserved1 = hfs_dbl_reserved1;
323 		hsb->s_reserved2 = hfs_dbl_reserved2;
324 		break;
325 
326 	case 'n':
327 		hsb->s_ifill = hfs_nat_ifill;
328 		hsb->s_reserved1 = hfs_nat_reserved1;
329 		hsb->s_reserved2 = hfs_nat_reserved2;
330 		break;
331 	}
332 
333 	if (names == '?') {
334 		names = fork;
335 	}
336 	switch (names) {
337 	default:
338 	case 'n':
339 		hsb->s_nameout = hfs_colon2mac;
340 		hsb->s_namein = hfs_mac2nat;
341 		break;
342 
343 	case 'c':
344 		hsb->s_nameout = hfs_colon2mac;
345 		hsb->s_namein = hfs_mac2cap;
346 		break;
347 
348 	case 't':
349 		hsb->s_nameout = hfs_triv2mac;
350 		hsb->s_namein = hfs_mac2triv;
351 		break;
352 
353 	case '7':
354 		hsb->s_nameout = hfs_prcnt2mac;
355 		hsb->s_namein = hfs_mac2seven;
356 		break;
357 
358 	case '8':
359 		hsb->s_nameout = hfs_prcnt2mac;
360 		hsb->s_namein = hfs_mac2eight;
361 		break;
362 
363 	case 'l':
364 		hsb->s_nameout = hfs_latin2mac;
365 		hsb->s_namein = hfs_mac2latin;
366 		break;
367 
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;
373 		break;
374 	}
375 
376 	return 1;
377 }
378 
379 /*================ Global functions ================*/
380 
381 /*
382  * hfs_read_super()
383  *
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.
391  */
hfs_read_super(struct super_block * s,void * data,int silent)392 struct super_block *hfs_read_super(struct super_block *s, void *data,
393 				   int silent)
394 {
395 	struct hfs_mdb *mdb;
396 	struct hfs_cat_key key;
397 	kdev_t dev = s->s_dev;
398 	int dev_blocksize;
399 	hfs_s32 part_size, part_start;
400 	struct inode *root_inode;
401 	int part;
402 
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");
406 		goto bail3;
407 	}
408 
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",
413 			 dev_blocksize);
414 		goto bail3;
415 	}
416 	s->s_blocksize_bits = HFS_SECTOR_SIZE_BITS;
417 	s->s_blocksize = HFS_SECTOR_SIZE;
418 
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);
422 
423 	/* erk. try parsing the partition table ourselves */
424 	if (!mdb) {
425 		if (hfs_part_find(s, part, silent, &part_size, &part_start)) {
426 	    		goto bail2;
427 	  	}
428 	  	mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start);
429 	}
430 #else
431 	if (hfs_part_find(s, part, silent, &part_size, &part_start)) {
432 		goto bail2;
433 	}
434 
435 	mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start);
436 #endif
437 
438 	if (!mdb) {
439 		if (!silent) {
440 			hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n",
441 			       kdevname(dev));
442 		}
443 		goto bail2;
444 	}
445 
446 	if (mdb->attrib & (HFS_SB_ATTRIB_HLOCK | HFS_SB_ATTRIB_SLOCK)) {
447 		if (!silent)
448 			hfs_warn("hfs_fs: Filesystem is marked locked, mounting read-only.\n");
449 		s->s_flags |= MS_RDONLY;
450 	}
451 
452 	HFS_SB(s)->s_mdb = mdb;
453 	if (HFS_ITYPE(mdb->next_id) != 0) {
454 		hfs_warn("hfs_fs: too many files.\n");
455 		goto bail1;
456 	}
457 
458 	s->s_magic = HFS_SUPER_MAGIC;
459 	s->s_op = &hfs_super_operations;
460 
461 	/* try to get the root inode */
462 	hfs_cat_build_key(htonl(HFS_POR_CNID),
463 			  (struct hfs_name *)(mdb->vname), &key);
464 
465 	root_inode = hfs_iget(hfs_cat_get(mdb, &key), HFS_ITYPE_NORM, NULL);
466 	if (!root_inode)
467 		goto bail_no_root;
468 
469 	s->s_root = d_alloc_root(root_inode);
470 	if (!s->s_root)
471 		goto bail_no_root;
472 
473 	/* fix up pointers. */
474 	HFS_I(root_inode)->entry->sys_entry[HFS_ITYPE_TO_INT(HFS_ITYPE_NORM)] =
475 	  s->s_root;
476 	s->s_root->d_op = &hfs_dentry_operations;
477 
478 	/* everything's okay */
479 	return s;
480 
481 bail_no_root:
482 	hfs_warn("hfs_fs: get root inode failed.\n");
483 	iput(root_inode);
484 bail1:
485 	hfs_mdb_put(mdb, s->s_flags & MS_RDONLY);
486 bail2:
487 	set_blocksize(dev, BLOCK_SIZE);
488 bail3:
489 	return NULL;
490 }
491 
hfs_remount(struct super_block * s,int * flags,char * data)492 int hfs_remount(struct super_block *s, int *flags, char *data)
493 {
494         int part; /* ignored */
495 
496         if (!parse_options(data, HFS_SB(s), &part)) {
497                 hfs_warn("hfs_fs: unable to parse mount options.\n");
498                 return -EINVAL;
499 	}
500 
501         if ((*flags & MS_RDONLY) == (s->s_flags & MS_RDONLY))
502                 return 0;
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;
507 			*flags |= MS_RDONLY;
508 	        }
509         }
510 	return 0;
511 }
512 
init_hfs_fs(void)513 static int __init init_hfs_fs(void)
514 {
515         hfs_cat_init();
516 	return register_filesystem(&hfs_fs);
517 }
518 
exit_hfs_fs(void)519 static void __exit exit_hfs_fs(void) {
520 	hfs_cat_free();
521 	unregister_filesystem(&hfs_fs);
522 }
523 
524 module_init(init_hfs_fs)
525 module_exit(exit_hfs_fs)
526 
527 #if defined(DEBUG_ALL) || defined(DEBUG_MEM)
528 long int hfs_alloc = 0;
529 #endif
530