~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/hfs/super.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.