OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [hfs/] [super.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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
 */
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
 */
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
 */
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
 */
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
 */
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
 */
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
 
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
 
513
static int __init init_hfs_fs(void)
514
{
515
        hfs_cat_init();
516
        return register_filesystem(&hfs_fs);
517
}
518
 
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.