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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [isofs/] [inode.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  linux/fs/isofs/inode.c
3
 *
4
 *  (C) 1991  Linus Torvalds - minix filesystem
5
 *      1992, 1993, 1994  Eric Youngdale Modified for ISO9660 filesystem.
6
 *      1994  Eberhard Moenkeberg - multi session handling.
7
 *      1995  Mark Dobie - allow mounting of some weird VideoCDs and PhotoCDs.
8
 *
9
 */
10
 
11
#include <linux/module.h>
12
 
13
#include <linux/stat.h>
14
#include <linux/sched.h>
15
#include <linux/iso_fs.h>
16
#include <linux/kernel.h>
17
#include <linux/major.h>
18
#include <linux/mm.h>
19
#include <linux/string.h>
20
#include <linux/locks.h>
21
#include <linux/malloc.h>
22
#include <linux/errno.h>
23
#include <linux/cdrom.h>
24
#include <linux/nls.h>
25
 
26
#include <asm/system.h>
27
#include <asm/segment.h>
28
 
29
/*
30
 * We have no support for "multi volume" CDs, but more and more disks carry
31
 * wrong information within the volume descriptors.
32
 */
33
#define IGNORE_WRONG_MULTI_VOLUME_SPECS
34
 
35
/*
36
 * A home-burnt Joliet level 3 cd-rom with a 100 MB zip file had more than
37
 * 100 file sections, so the limit should be larger than that.  What does the
38
 * ISO9660 standard say?  (Ulrik Dickow <ukd@kampsax.dk>)
39
 */
40
#define MAX_FILE_SECTIONS 1000
41
 
42
#ifdef LEAK_CHECK
43
static int check_malloc = 0;
44
static int check_bread = 0;
45
#endif
46
 
47
void isofs_put_super(struct super_block *sb)
48
{
49
        if (sb->u.isofs_sb.s_nls_iocharset) {
50
                unload_nls(sb->u.isofs_sb.s_nls_iocharset);
51
                sb->u.isofs_sb.s_nls_iocharset = NULL;
52
        }
53
        lock_super(sb);
54
 
55
#ifdef LEAK_CHECK
56
        printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
57
               check_malloc, check_bread);
58
#endif
59
        sb->s_dev = 0;
60
        unlock_super(sb);
61
        MOD_DEC_USE_COUNT;
62
        return;
63
}
64
 
65
static struct super_operations isofs_sops = {
66
        isofs_read_inode,
67
        NULL,                   /* notify_change */
68
        NULL,                   /* write_inode */
69
        NULL,                   /* put_inode */
70
        isofs_put_super,
71
        NULL,                   /* write_super */
72
        isofs_statfs,
73
        NULL
74
};
75
 
76
struct iso9660_options{
77
  char map;
78
  char rock;
79
  char joliet;
80
  char cruft;
81
  char unhide;
82
  unsigned char check;
83
  unsigned char conversion;
84
  unsigned int blocksize;
85
  mode_t mode;
86
  gid_t gid;
87
  uid_t uid;
88
  char *iocharset;
89
  unsigned char utf8;
90
};
91
 
92
static int parse_options(char *options, struct iso9660_options * popt)
93
{
94
        char *this_char,*value,*p;
95
        int len;
96
 
97
        popt->map = 'n';
98
        popt->rock = 'y';
99
        popt->joliet = 'y';
100
        popt->cruft = 'n';
101
        popt->unhide = 'n';
102
        popt->check = 's';              /* default: strict */
103
        popt->conversion = 'b';         /* default: no conversion */
104
        popt->blocksize = 1024;
105
        popt->mode = S_IRUGO;
106
        popt->gid = 0;
107
        popt->uid = 0;
108
        popt->iocharset = NULL;
109
        popt->utf8 = 0;
110
        if (!options) return 1;
111
        for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
112
                if (strncmp(this_char,"norock",6) == 0) {
113
                  popt->rock = 'n';
114
                  continue;
115
                }
116
                if (strncmp(this_char,"nojoliet",8) == 0) {
117
                  popt->joliet = 'n';
118
                  continue;
119
                }
120
                if (strncmp(this_char,"unhide",6) == 0) {
121
                  popt->unhide = 'y';
122
                  continue;
123
                }
124
                if (strncmp(this_char,"cruft",5) == 0) {
125
                  popt->cruft = 'y';
126
                  continue;
127
                }
128
                if (strncmp(this_char,"utf8",4) == 0) {
129
                  popt->utf8 = 1;
130
                  continue;
131
                }
132
                if ((value = strchr(this_char,'=')) != NULL)
133
                        *value++ = 0;
134
 
135
                if (!strcmp(this_char,"iocharset")) {
136
                        p = value;
137
                        while (*value && *value != ',') value++;
138
                        len = value - p;
139
                        if (len) {
140
                                popt->iocharset = kmalloc(len+1, GFP_KERNEL);
141
                                memcpy(popt->iocharset, p, len);
142
                                popt->iocharset[len] = 0;
143
                        } else {
144
                                popt->iocharset = NULL;
145
                                return 0;
146
                        }
147
                }
148
                else if (!strcmp(this_char,"map") && value) {
149
                        if (value[0] && !value[1] && strchr("on",*value))
150
                                popt->map = *value;
151
                        else if (!strcmp(value,"off")) popt->map = 'o';
152
                        else if (!strcmp(value,"normal")) popt->map = 'n';
153
                        else return 0;
154
                }
155
                else if (!strcmp(this_char,"check") && value) {
156
                        if (value[0] && !value[1] && strchr("rs",*value))
157
                                popt->check = *value;
158
                        else if (!strcmp(value,"relaxed")) popt->check = 'r';
159
                        else if (!strcmp(value,"strict")) popt->check = 's';
160
                        else return 0;
161
                }
162
                else if (!strcmp(this_char,"conv") && value) {
163
                        if (value[0] && !value[1] && strchr("btma",*value))
164
                                popt->conversion = *value;
165
                        else if (!strcmp(value,"binary")) popt->conversion = 'b';
166
                        else if (!strcmp(value,"text")) popt->conversion = 't';
167
                        else if (!strcmp(value,"mtext")) popt->conversion = 'm';
168
                        else if (!strcmp(value,"auto")) popt->conversion = 'a';
169
                        else return 0;
170
                }
171
                else if (value &&
172
                         (!strcmp(this_char,"block") ||
173
                          !strcmp(this_char,"mode") ||
174
                          !strcmp(this_char,"uid") ||
175
                          !strcmp(this_char,"gid"))) {
176
                  char * vpnt = value;
177
                  unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0);
178
                  if (*vpnt) return 0;
179
                  switch(*this_char) {
180
                  case 'b':
181
                    if (   ivalue != 512
182
                        && ivalue != 1024
183
                        && ivalue != 2048) return 0;
184
                    popt->blocksize = ivalue;
185
                    break;
186
                  case 'u':
187
                    popt->uid = ivalue;
188
                    break;
189
                  case 'g':
190
                    popt->gid = ivalue;
191
                    break;
192
                  case 'm':
193
                    popt->mode = ivalue;
194
                    break;
195
                  }
196
                }
197
                else return 1;
198
        }
199
        return 1;
200
}
201
 
202
/*
203
 * look if the driver can tell the multi session redirection value
204
 *
205
 * don't change this if you don't know what you do, please!
206
 * Multisession is legal only with XA disks.
207
 * A non-XA disk with more than one volume descriptor may do it right, but
208
 * usually is written in a nowhere standardized "multi-partition" manner.
209
 * Multisession uses absolute addressing (solely the first frame of the whole
210
 * track is #0), multi-partition uses relative addressing (each first frame of
211
 * each track is #0), and a track is not a session.
212
 *
213
 * A broken CDwriter software or drive firmware does not set new standards,
214
 * at least not if conflicting with the existing ones.
215
 *
216
 * emoenke@gwdg.de
217
 */
218
#define WE_OBEY_THE_WRITTEN_STANDARDS 1
219
 
220
static unsigned int isofs_get_last_session(kdev_t dev)
221
{
222
  struct cdrom_multisession ms_info;
223
  unsigned int vol_desc_start;
224
  struct inode inode_fake;
225
  extern struct file_operations * get_blkfops(unsigned int);
226
  int i;
227
 
228
  vol_desc_start=0;
229
  if (get_blkfops(MAJOR(dev))->ioctl!=NULL)
230
    {
231
      /* Whoops.  We must save the old FS, since otherwise
232
       * we would destroy the kernels idea about FS on root
233
       * mount in read_super... [chexum]
234
       */
235
      unsigned long old_fs=get_fs();
236
      inode_fake.i_rdev=dev;
237
      ms_info.addr_format=CDROM_LBA;
238
      set_fs(KERNEL_DS);
239
      i=get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
240
                                       NULL,
241
                                       CDROMMULTISESSION,
242
                                       (unsigned long) &ms_info);
243
      set_fs(old_fs);
244
#if 0 
245
      printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
246
      if (i==0)
247
        {
248
          printk("isofs.inode: XA disk: %s\n", ms_info.xa_flag ? "yes":"no");
249
          printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
250
        }
251
#endif 0
252
      if (i==0)
253
#if WE_OBEY_THE_WRITTEN_STANDARDS
254
        if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
255
#endif WE_OBEY_THE_WRITTEN_STANDARDS
256
          vol_desc_start=ms_info.addr.lba;
257
    }
258
  return vol_desc_start;
259
}
260
 
261
struct super_block *isofs_read_super(struct super_block *s,void *data,
262
                                     int silent)
263
{
264
        struct buffer_head *bh=NULL;
265
        int iso_blknum;
266
        unsigned int blocksize_bits;
267
        int high_sierra;
268
        kdev_t dev = s->s_dev;
269
        unsigned int vol_desc_start;
270
        int orig_zonesize;
271
        char *p;
272
        int joliet_level = 0;
273
 
274
        struct iso_volume_descriptor *vdp;
275
        struct hs_volume_descriptor *hdp;
276
 
277
        struct iso_primary_descriptor *pri = NULL;
278
        struct iso_supplementary_descriptor *sec = NULL;
279
        struct hs_primary_descriptor *h_pri = NULL;
280
 
281
        struct iso_directory_record *rootp;
282
 
283
        struct iso9660_options opt;
284
 
285
        MOD_INC_USE_COUNT;
286
 
287
        if (!parse_options((char *) data,&opt)) {
288
                s->s_dev = 0;
289
                MOD_DEC_USE_COUNT;
290
                return NULL;
291
        }
292
 
293
#if 0
294
        printk("map = %c\n", opt.map);
295
        printk("rock = %c\n", opt.rock);
296
        printk("joliet = %c\n", opt.joliet);
297
        printk("check = %c\n", opt.check);
298
        printk("cruft = %c\n", opt.cruft);
299
        printk("unhide = %c\n", opt.unhide);
300
        printk("conversion = %c\n", opt.conversion);
301
        printk("blocksize = %d\n", opt.blocksize);
302
        printk("gid = %d\n", opt.gid);
303
        printk("uid = %d\n", opt.uid);
304
#endif
305
 
306
        blocksize_bits = 0;
307
        {
308
          int i = opt.blocksize;
309
          while (i != 1){
310
            blocksize_bits++;
311
            i >>=1;
312
          }
313
        }
314
        set_blocksize(dev, opt.blocksize);
315
 
316
        lock_super(s);
317
 
318
        s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
319
 
320
        vol_desc_start = isofs_get_last_session(dev);
321
 
322
        for (iso_blknum = vol_desc_start+16;
323
             iso_blknum < vol_desc_start+100; iso_blknum++)
324
        {
325
            int b = iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits);
326
 
327
            if (!(bh = bread(dev,b,opt.blocksize))) {
328
                s->s_dev = 0;
329
                printk("isofs_read_super: bread failed, dev "
330
                       "%s iso_blknum %d block %d\n",
331
                       kdevname(dev), iso_blknum, b);
332
                unlock_super(s);
333
                MOD_DEC_USE_COUNT;
334
                return NULL;
335
            }
336
 
337
            vdp = (struct iso_volume_descriptor *)bh->b_data;
338
            hdp = (struct hs_volume_descriptor *)bh->b_data;
339
 
340
            if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
341
                if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
342
                    goto out;
343
                if (isonum_711 (hdp->type) == ISO_VD_END)
344
                    goto out;
345
 
346
                s->u.isofs_sb.s_high_sierra = 1;
347
                high_sierra = 1;
348
                opt.rock = 'n';
349
                h_pri = (struct hs_primary_descriptor *)vdp;
350
                break;
351
            }
352
 
353
            if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
354
                if (isonum_711 (vdp->type) == ISO_VD_END)
355
                    break;
356
                if (isonum_711 (vdp->type) == ISO_VD_PRIMARY) {
357
                    if (pri == NULL) {
358
                        pri = (struct iso_primary_descriptor *)vdp;
359
                    }
360
                } else if (isonum_711 (vdp->type) == ISO_VD_SUPPLEMENTARY) {
361
                    sec = (struct iso_supplementary_descriptor *)vdp;
362
                    if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) {
363
                        if (opt.joliet == 'y') {
364
                            if (sec->escape[2] == 0x40) {
365
                                joliet_level = 1;
366
                            } else if (sec->escape[2] == 0x43) {
367
                                joliet_level = 2;
368
                            } else if (sec->escape[2] == 0x45) {
369
                                joliet_level = 3;
370
                            }
371
                            printk("ISO9660 Extensions: Microsoft Joliet Level %d\n",
372
                                   joliet_level);
373
                        }
374
                        break;
375
                    } else {
376
                        /* Unknown supplementary volume descriptor */
377
                        sec = NULL;
378
                    }
379
                }
380
                /* Just skip any volume descriptors we don't recognize */
381
            }
382
 
383
            brelse(bh);
384
        }
385
        if ((pri == NULL) && (sec == NULL) && (h_pri == NULL)) {
386
            if (!silent)
387
                printk("Unable to identify CD-ROM format.\n");
388
            s->s_dev = 0;
389
            unlock_super(s);
390
            MOD_DEC_USE_COUNT;
391
            return NULL;
392
        }
393
        s->u.isofs_sb.s_joliet_level = joliet_level;
394
        if (joliet_level && opt.rock == 'n') {
395
            /* This is the case of Joliet with the norock mount flag.
396
             * A disc with both Joliet and Rock Ridge is handled later
397
             */
398
            pri = (struct iso_primary_descriptor *) sec;
399
        }
400
 
401
        if(high_sierra){
402
          rootp = (struct iso_directory_record *) h_pri->root_directory_record;
403
#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
404
          if (isonum_723 (h_pri->volume_set_size) != 1) {
405
            printk("Multi-volume disks not supported.\n");
406
            goto out;
407
          }
408
#endif IGNORE_WRONG_MULTI_VOLUME_SPECS
409
          s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size);
410
          s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size);
411
          s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size);
412
        } else {
413
          rootp = (struct iso_directory_record *) pri->root_directory_record;
414
#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
415
          if (isonum_723 (pri->volume_set_size) != 1) {
416
            printk("Multi-volume disks not supported.\n");
417
            goto out;
418
          }
419
#endif IGNORE_WRONG_MULTI_VOLUME_SPECS
420
          s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size);
421
          s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
422
          s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
423
        }
424
 
425
        s->u.isofs_sb.s_ninodes = 0; /* No way to figure this out easily */
426
 
427
        /* RDE: convert log zone size to bit shift */
428
 
429
        orig_zonesize = s -> u.isofs_sb.s_log_zone_size;
430
        switch (s -> u.isofs_sb.s_log_zone_size)
431
          { case  512: s -> u.isofs_sb.s_log_zone_size =  9; break;
432
            case 1024: s -> u.isofs_sb.s_log_zone_size = 10; break;
433
            case 2048: s -> u.isofs_sb.s_log_zone_size = 11; break;
434
 
435
            default:
436
              printk("Bad logical zone size %ld\n", s -> u.isofs_sb.s_log_zone_size);
437
              goto out;
438
          }
439
 
440
        s->s_magic = ISOFS_SUPER_MAGIC;
441
 
442
        /* The CDROM is read-only, has no nodes (devices) on it, and since
443
           all of the files appear to be owned by root, we really do not want
444
           to allow suid.  (suid or devices will not show up unless we have
445
           Rock Ridge extensions) */
446
 
447
        s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
448
 
449
        brelse(bh);
450
 
451
        /* RDE: data zone now byte offset! */
452
 
453
        s->u.isofs_sb.s_firstdatazone = ((isonum_733 (rootp->extent) +
454
                                           isonum_711 (rootp->ext_attr_length))
455
                                         << s -> u.isofs_sb.s_log_zone_size);
456
        printk(KERN_DEBUG "Max size:%ld   Log zone size:%ld\n",
457
               s->u.isofs_sb.s_max_size,
458
               1UL << s->u.isofs_sb.s_log_zone_size);
459
        printk(KERN_DEBUG "First datazone:%ld   Root inode number %ld\n",
460
               s->u.isofs_sb.s_firstdatazone >> s -> u.isofs_sb.s_log_zone_size,
461
               s->u.isofs_sb.s_firstdatazone);
462
        if(high_sierra) printk(KERN_DEBUG "Disc in High Sierra format.\n");
463
        unlock_super(s);
464
        /* set up enough so that it can read an inode */
465
 
466
        /*
467
         * Force the blocksize to 512 for 512 byte sectors.  The file
468
         * read primitives really get it wrong in a bad way if we don't
469
         * do this.
470
         */
471
        if( orig_zonesize < opt.blocksize )
472
          {
473
            opt.blocksize = orig_zonesize;
474
            blocksize_bits = 0;
475
            {
476
              int i = opt.blocksize;
477
              while (i != 1){
478
                blocksize_bits++;
479
                i >>=1;
480
              }
481
            }
482
            set_blocksize(dev, opt.blocksize);
483
            printk(KERN_DEBUG "Forcing new log zone size:%d\n", opt.blocksize);
484
          }
485
 
486
        s->u.isofs_sb.s_nls_iocharset = NULL;
487
        if (joliet_level == 0) {
488
                if (opt.iocharset) {
489
                        kfree(opt.iocharset);
490
                        opt.iocharset = NULL;
491
                }
492
        } else if (opt.utf8 == 0) {
493
                p = opt.iocharset ? opt.iocharset : "iso8859-1";
494
                s->u.isofs_sb.s_nls_iocharset = load_nls(p);
495
                if (! s->u.isofs_sb.s_nls_iocharset) {
496
                        /* Fail only if explicit charset specified */
497
                        if (opt.iocharset) {
498
                                kfree(opt.iocharset);
499
                                goto out;
500
                        } else {
501
                                s->u.isofs_sb.s_nls_iocharset = load_nls_default();
502
                        }
503
                }
504
        }
505
        s->s_dev = dev;
506
        s->s_op = &isofs_sops;
507
        s->u.isofs_sb.s_mapping = opt.map;
508
        s->u.isofs_sb.s_rock = (opt.rock == 'y' ? 2 : 0);
509
        s->u.isofs_sb.s_name_check = opt.check;
510
        s->u.isofs_sb.s_conversion = opt.conversion;
511
        s->u.isofs_sb.s_cruft = opt.cruft;
512
        s->u.isofs_sb.s_unhide = opt.unhide;
513
        s->u.isofs_sb.s_uid = opt.uid;
514
        s->u.isofs_sb.s_gid = opt.gid;
515
        s->u.isofs_sb.s_utf8 = opt.utf8;
516
        /*
517
         * It would be incredibly stupid to allow people to mark every file on the disk
518
         * as suid, so we merely allow them to set the default permissions.
519
         */
520
        s->u.isofs_sb.s_mode = opt.mode & 0777;
521
        s->s_blocksize = opt.blocksize;
522
        s->s_blocksize_bits = blocksize_bits;
523
        s->s_mounted = iget(s, s->u.isofs_sb.s_firstdatazone);
524
 
525
        /*
526
         * If this disk has both Rock Ridge and Joliet on it, then we
527
         * want to use Rock Ridge by default.  This can be overridden
528
         * by using the norock mount option.  There is still one other
529
         * possibility that is not taken into account: a Rock Ridge
530
         * CD with Unicode names.  Until someone sees such a beast, it
531
         * will not be supported.
532
         */
533
        if (joliet_level && opt.rock == 'y' && s->u.isofs_sb.s_rock != 1) {
534
                iput(s->s_mounted);
535
                pri = (struct iso_primary_descriptor *) sec;
536
                rootp = (struct iso_directory_record *)
537
                        pri->root_directory_record;
538
                s->u.isofs_sb.s_firstdatazone =
539
                        ((isonum_733 (rootp->extent) +
540
                          isonum_711 (rootp->ext_attr_length))
541
                         << s -> u.isofs_sb.s_log_zone_size);
542
                s->s_mounted = iget(s, s->u.isofs_sb.s_firstdatazone);
543
                s->u.isofs_sb.s_rock = 0;
544
        }
545
        unlock_super(s);
546
 
547
        if (!(s->s_mounted)) {
548
                s->s_dev = 0;
549
                printk("get root inode failed\n");
550
                if (s->u.isofs_sb.s_nls_iocharset)
551
                        unload_nls(s->u.isofs_sb.s_nls_iocharset);
552
                if (opt.iocharset) kfree(opt.iocharset);
553
                MOD_DEC_USE_COUNT;
554
                return NULL;
555
        }
556
 
557
#ifdef DO_FUNKY_BROKEN_MEDIA_CHANGE_CHECK
558
        if(!check_disk_change(s->s_dev)) {
559
                return s;
560
        }
561
        if (s->u.isofs_sb.s_nls_iocharset)
562
                unload_nls(s->u.isofs_sb.s_nls_iocharset);
563
        if (opt.iocharset) kfree(opt.iocharset);
564
#else
565
        check_disk_change(s->s_dev);
566
        return s;
567
#endif  
568
 
569
 out: /* Kick out for various error conditions */
570
        brelse(bh);
571
        s->s_dev = 0;
572
        unlock_super(s);
573
        MOD_DEC_USE_COUNT;
574
        return NULL;
575
}
576
 
577
void isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
578
{
579
        struct statfs tmp;
580
 
581
        tmp.f_type = ISOFS_SUPER_MAGIC;
582
        tmp.f_bsize = sb->s_blocksize;
583
        tmp.f_blocks = (sb->u.isofs_sb.s_nzones
584
                  << (sb->u.isofs_sb.s_log_zone_size - sb->s_blocksize_bits));
585
        tmp.f_bfree = 0;
586
        tmp.f_bavail = 0;
587
        tmp.f_files = sb->u.isofs_sb.s_ninodes;
588
        tmp.f_ffree = 0;
589
        tmp.f_namelen = NAME_MAX;
590
        memcpy_tofs(buf, &tmp, bufsiz);
591
}
592
 
593
int isofs_bmap(struct inode * inode,int block)
594
{
595
        off_t b_off, offset, size;
596
        struct inode *ino;
597
        unsigned int firstext;
598
        unsigned long nextino;
599
        int i;
600
 
601
        if (block<0) {
602
                printk("_isofs_bmap: block<0\n");
603
                return 0;
604
        }
605
 
606
        b_off = block << ISOFS_BUFFER_BITS(inode);
607
 
608
        /*
609
         * If we are beyond the end of this file, don't give out any
610
         * blocks.
611
         */
612
        if( (b_off > inode->i_size) ||
613
                ((b_off ==  inode->i_size) && (b_off & (PAGE_SIZE - 1))) )
614
          {
615
            off_t       max_legal_read_offset;
616
 
617
            /*
618
             * If we are *way* beyond the end of the file, print a message.
619
             * Access beyond the end of the file up to the next page boundary
620
             * is normal because of the way the page cache works.
621
             * In this case, we just return 0 so that we can properly fill
622
             * the page with useless information without generating any
623
             * I/O errors.
624
             */
625
            max_legal_read_offset = (inode->i_size + PAGE_SIZE - 1)
626
              & ~(PAGE_SIZE - 1);
627
            if( b_off >= max_legal_read_offset )
628
              {
629
 
630
                printk("_isofs_bmap: block>= EOF(%d, %ld)\n", block,
631
                       inode->i_size);
632
              }
633
            return 0;
634
          }
635
 
636
        offset = 0;
637
        firstext = inode->u.isofs_i.i_first_extent;
638
        size = inode->u.isofs_i.i_section_size;
639
        nextino = inode->u.isofs_i.i_next_section_ino;
640
#ifdef DEBUG
641
        printk("first inode: inode=%lu nextino=%lu firstext=%u size=%lu\n",
642
                inode->i_ino, nextino, firstext, size);
643
#endif
644
        i = 0;
645
        if (nextino) {
646
                while(b_off >= offset + size) {
647
                        offset += size;
648
 
649
                        if(nextino == 0) return 0;
650
                        ino = iget(inode->i_sb, nextino);
651
                        if(!ino) return 0;
652
                        firstext = ino->u.isofs_i.i_first_extent;
653
                        size = ino->u.isofs_i.i_section_size;
654
#ifdef DEBUG
655
                        printk("read inode: inode=%lu ino=%lu nextino=%lu firstext=%u size=%lu\n",
656
                               inode->i_ino, nextino, ino->u.isofs_i.i_next_section_ino, firstext, size);
657
#endif
658
                        nextino = ino->u.isofs_i.i_next_section_ino;
659
                        iput(ino);
660
 
661
                        if(++i > MAX_FILE_SECTIONS) {
662
                                printk("isofs_bmap: More than %d file sections ?!?, aborting...\n",
663
                                       MAX_FILE_SECTIONS);
664
                                printk("isofs_bmap: ino=%lu block=%d firstext=%u size=%u nextino=%lu\n",
665
                                       inode->i_ino, block, firstext, (unsigned)size, nextino);
666
                                return 0;
667
                        }
668
                }
669
        }
670
#ifdef DEBUG
671
        printk("isofs_bmap: mapped inode:block %lu:%d to block %lu\n",
672
                inode->i_ino, block, (b_off - offset + firstext) >> ISOFS_BUFFER_BITS(inode));
673
#endif
674
        return (b_off - offset + firstext) >> ISOFS_BUFFER_BITS(inode);
675
}
676
 
677
 
678
static void test_and_set_uid(uid_t *p, uid_t value)
679
{
680
        if(value) {
681
                *p = value;
682
#if 0
683
                printk("Resetting to %d\n", value);
684
#endif
685
        }
686
}
687
 
688
static int isofs_read_level3_size(struct inode * inode)
689
{
690
        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
691
        struct buffer_head * bh = NULL;
692
        struct iso_directory_record * raw_inode = NULL;         /* quiet gcc */
693
        unsigned char *pnt = NULL;
694
        void *cpnt = NULL;
695
        int block = 0;                   /* Quiet GCC */
696
        unsigned long ino;
697
        int i;
698
 
699
        inode->i_size = 0;
700
        inode->u.isofs_i.i_next_section_ino = 0;
701
        ino = inode->i_ino;
702
        i = 0;
703
        do {
704
                if(i > MAX_FILE_SECTIONS) {
705
                        printk("isofs_read_level3_size: More than %d file sections ?!?, aborting...\n"
706
                               "isofs_read_level3_size: inode=%lu ino=%lu\n", MAX_FILE_SECTIONS,
707
                               inode->i_ino, ino);
708
                        return 0;
709
                }
710
 
711
                if(bh == NULL || block != ino >> ISOFS_BUFFER_BITS(inode)) {
712
                        if(bh) brelse(bh);
713
                        block = ino >> ISOFS_BUFFER_BITS(inode);
714
                        if (!(bh=bread(inode->i_dev,block, bufsize))) {
715
                                printk("unable to read i-node block");
716
                                return 1;
717
                        }
718
                }
719
                pnt = ((unsigned char *) bh->b_data
720
                       + (ino & (bufsize - 1)));
721
 
722
                if ((ino & (bufsize - 1)) + *pnt > bufsize){
723
                        int frag1, offset;
724
 
725
                        offset = (ino & (bufsize - 1));
726
                        frag1 = bufsize - offset;
727
                        cpnt = kmalloc(*pnt,GFP_KERNEL);
728
                        if (cpnt == NULL) {
729
                                printk(KERN_INFO "NoMem ISO inode %lu\n",inode->i_ino);
730
                                brelse(bh);
731
                                return 1;
732
                        }
733
                        memcpy(cpnt, bh->b_data + offset, frag1);
734
                        brelse(bh);
735
                        if (!(bh = bread(inode->i_dev,++block, bufsize))) {
736
                                kfree(cpnt);
737
                                printk("unable to read i-node block");
738
                                return 1;
739
                        }
740
                        offset += *pnt - bufsize;
741
                        memcpy((char *)cpnt+frag1, bh->b_data, offset);
742
                        pnt = ((unsigned char *) cpnt);
743
                }
744
 
745
                if(*pnt == 0) {
746
                        ino = (ino & ~(ISOFS_BLOCK_SIZE - 1)) + ISOFS_BLOCK_SIZE;
747
                        continue;
748
                }
749
                raw_inode = ((struct iso_directory_record *) pnt);
750
 
751
                inode->i_size += isonum_733 (raw_inode->size);
752
                if(i == 1) inode->u.isofs_i.i_next_section_ino = ino;
753
 
754
                ino += *pnt;
755
                if (cpnt) {
756
                        kfree (cpnt);
757
                        cpnt = NULL;
758
                }
759
                i++;
760
        } while(raw_inode->flags[-inode->i_sb->u.isofs_sb.s_high_sierra] & 0x80);
761
        brelse(bh);
762
        return 0;
763
}
764
 
765
void isofs_read_inode(struct inode * inode)
766
{
767
        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
768
        struct buffer_head * bh;
769
        struct iso_directory_record * raw_inode;
770
        unsigned char *pnt = NULL;
771
        void *cpnt = NULL;
772
        int high_sierra;
773
        int block;
774
        int volume_seq_no ;
775
        int i;
776
 
777
        block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);
778
        if (!(bh=bread(inode->i_dev,block, bufsize))) {
779
          printk("unable to read i-node block");
780
          goto fail;
781
        }
782
 
783
        pnt = ((unsigned char *) bh->b_data
784
               + (inode->i_ino & (bufsize - 1)));
785
        raw_inode = ((struct iso_directory_record *) pnt);
786
        high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
787
 
788
        if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){
789
                int frag1, offset;
790
 
791
                offset = (inode->i_ino & (bufsize - 1));
792
                frag1 = bufsize - offset;
793
                cpnt = kmalloc(*pnt,GFP_KERNEL);
794
                if (cpnt == NULL) {
795
                        printk(KERN_INFO "NoMem ISO inode %lu\n",inode->i_ino);
796
                        brelse(bh);
797
                        goto fail;
798
                }
799
                memcpy(cpnt, bh->b_data + offset, frag1);
800
                brelse(bh);
801
                if (!(bh = bread(inode->i_dev,++block, bufsize))) {
802
                        kfree(cpnt);
803
                        printk("unable to read i-node block");
804
                        goto fail;
805
                }
806
                offset += *pnt - bufsize;
807
                memcpy((char *)cpnt+frag1, bh->b_data, offset);
808
                pnt = ((unsigned char *) cpnt);
809
                raw_inode = ((struct iso_directory_record *) pnt);
810
        }
811
 
812
        if (raw_inode->flags[-high_sierra] & 2) {
813
                inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
814
                inode->i_nlink = 1; /* Set to 1.  We know there are 2, but
815
                                       the find utility tries to optimize
816
                                       if it is 2, and it screws up.  It is
817
                                       easier to give 1 which tells find to
818
                                       do it the hard way. */
819
        } else {
820
                inode->i_mode = inode->i_sb->u.isofs_sb.s_mode; /* Everybody gets to read the file. */
821
                inode->i_nlink = 1;
822
                inode->i_mode |= S_IFREG;
823
/* If there are no periods in the name, then set the execute permission bit */
824
                for(i=0; i< raw_inode->name_len[0]; i++)
825
                        if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
826
                                break;
827
                if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';')
828
                        inode->i_mode |= S_IXUGO; /* execute permission */
829
        }
830
        inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
831
        inode->i_gid = inode->i_sb->u.isofs_sb.s_gid;
832
 
833
        inode->u.isofs_i.i_section_size = isonum_733 (raw_inode->size);
834
        if(raw_inode->flags[-high_sierra] & 0x80) {
835
                if(isofs_read_level3_size(inode)) goto fail;
836
        } else {
837
                inode->i_size = isonum_733 (raw_inode->size);
838
        }
839
 
840
        /* There are defective discs out there - we do this to protect
841
           ourselves.  A cdrom will never contain more than 800Mb
842
           Allow 1Gig for DVD however - Ulrich Habel */
843
        if((inode->i_size < 0 || inode->i_size > 1073741824) &&
844
            inode->i_sb->u.isofs_sb.s_cruft == 'n') {
845
          printk("Warning: defective cdrom.  Enabling \"cruft\" mount option.\n");
846
          inode->i_sb->u.isofs_sb.s_cruft = 'y';
847
        }
848
 
849
/* Some dipshit decided to store some other bit of information in the high
850
   byte of the file length.  Catch this and holler.  WARNING: this will make
851
   it impossible for a file to be > 16Mb on the CDROM!!!*/
852
 
853
        if(inode->i_sb->u.isofs_sb.s_cruft == 'y' &&
854
           inode->i_size & 0xff000000){
855
/*        printk("Illegal format on cdrom.  Pester manufacturer.\n"); */
856
          inode->i_size &= 0x00ffffff;
857
        }
858
 
859
        if (raw_inode->interleave[0]) {
860
                printk("Interleaved files not (yet) supported.\n");
861
                inode->i_size = 0;
862
        }
863
 
864
        /* I have no idea what file_unit_size is used for, so
865
           we will flag it for now */
866
        if(raw_inode->file_unit_size[0] != 0){
867
                printk("File unit size != 0 for ISO file (%ld).\n",inode->i_ino);
868
        }
869
 
870
        /* I have no idea what other flag bits are used for, so
871
           we will flag it for now */
872
#ifdef DEBUG
873
        if((raw_inode->flags[-high_sierra] & ~2)!= 0){
874
                printk("Unusual flag settings for ISO file (%ld %x).\n",
875
                       inode->i_ino, raw_inode->flags[-high_sierra]);
876
        }
877
#endif
878
 
879
#ifdef DEBUG
880
        printk("Get inode %d: %d %d: %d\n",inode->i_ino, block,
881
               ((int)pnt) & 0x3ff, inode->i_size);
882
#endif
883
 
884
        inode->i_mtime = inode->i_atime = inode->i_ctime =
885
          iso_date(raw_inode->date, high_sierra);
886
 
887
        inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) +
888
                                           isonum_711 (raw_inode->ext_attr_length))
889
          << inode -> i_sb -> u.isofs_sb.s_log_zone_size;
890
 
891
        inode->u.isofs_i.i_backlink = 0xffffffff; /* Will be used for previous directory */
892
        switch (inode->i_sb->u.isofs_sb.s_conversion){
893
        case 'a':
894
          inode->u.isofs_i.i_file_format = ISOFS_FILE_UNKNOWN; /* File type */
895
          break;
896
        case 'b':
897
          inode->u.isofs_i.i_file_format = ISOFS_FILE_BINARY; /* File type */
898
          break;
899
        case 't':
900
          inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT; /* File type */
901
          break;
902
        case 'm':
903
          inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT_M; /* File type */
904
          break;
905
        }
906
 
907
/* Now test for possible Rock Ridge extensions which will override some of
908
   these numbers in the inode structure. */
909
 
910
        if (!high_sierra) {
911
          parse_rock_ridge_inode(raw_inode, inode);
912
          /* hmm..if we want uid or gid set, override the rock ridge setting */
913
         test_and_set_uid(&inode->i_uid, inode->i_sb->u.isofs_sb.s_uid);
914
        }
915
 
916
#ifdef DEBUG
917
        printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
918
#endif
919
        brelse(bh);
920
 
921
        inode->i_op = NULL;
922
 
923
        /* get the volume sequence number */
924
        volume_seq_no = isonum_723 (raw_inode->volume_sequence_number) ;
925
 
926
        /*
927
         * Disable checking if we see any volume number other than 0 or 1.
928
         * We could use the cruft option, but that has multiple purposes, one
929
         * of which is limiting the file size to 16Mb.  Thus we silently allow
930
         * volume numbers of 0 to go through without complaining.
931
         */
932
        if (inode->i_sb->u.isofs_sb.s_cruft == 'n' &&
933
            (volume_seq_no != 0) && (volume_seq_no != 1)) {
934
          printk("Warning: defective cdrom (volume sequence number). Enabling \"cruft\" mount option.\n");
935
          inode->i_sb->u.isofs_sb.s_cruft = 'y';
936
        }
937
 
938
#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
939
        if (inode->i_sb->u.isofs_sb.s_cruft != 'y' &&
940
            (volume_seq_no != 0) && (volume_seq_no != 1)) {
941
                printk("Multi volume CD somehow got mounted.\n");
942
        } else
943
#endif IGNORE_WRONG_MULTI_VOLUME_SPECS
944
        {
945
          if (S_ISREG(inode->i_mode))
946
            inode->i_op = &isofs_file_inode_operations;
947
          else if (S_ISDIR(inode->i_mode))
948
            inode->i_op = &isofs_dir_inode_operations;
949
          else if (S_ISLNK(inode->i_mode))
950
            inode->i_op = &isofs_symlink_inode_operations;
951
          else if (S_ISCHR(inode->i_mode))
952
            inode->i_op = &chrdev_inode_operations;
953
          else if (S_ISBLK(inode->i_mode))
954
            inode->i_op = &blkdev_inode_operations;
955
          else if (S_ISFIFO(inode->i_mode))
956
            init_fifo(inode);
957
        }
958
        if (cpnt) {
959
                kfree (cpnt);
960
                cpnt = NULL;
961
        }
962
        return;
963
      fail:
964
        /* With a data error we return this information */
965
        inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
966
        inode->u.isofs_i.i_first_extent = 0;
967
        inode->u.isofs_i.i_backlink = 0xffffffff;
968
        inode->i_size = 0;
969
        inode->i_nlink = 1;
970
        inode->i_uid = inode->i_gid = 0;
971
        inode->i_mode = S_IFREG;  /*Regular file, no one gets to read*/
972
        inode->i_op = NULL;
973
        return;
974
}
975
 
976
/* There are times when we need to know the inode number of a parent of
977
   a particular directory.  When control passes through a routine that
978
   has access to the parent information, it fills it into the inode structure,
979
   but sometimes the inode gets flushed out of the queue, and someone
980
   remembers the number.  When they try to open up again, we have lost
981
   the information.  The '..' entry on the disc points to the data area
982
   for a particular inode, so we can follow these links back up, but since
983
   we do not know the inode number, we do not actually know how large the
984
   directory is.  The disc is almost always correct, and there is
985
   enough error checking on the drive itself, but an open ended search
986
   makes me a little nervous.
987
 
988
   The bsd iso filesystem uses the extent number for an inode, and this
989
   would work really nicely for us except that the read_inode function
990
   would not have any clean way of finding the actual directory record
991
   that goes with the file.  If we had such info, then it would pay
992
   to change the inode numbers and eliminate this function.
993
*/
994
 
995
int isofs_lookup_grandparent(struct inode * parent, int extent)
996
{
997
        unsigned long bufsize = ISOFS_BUFFER_SIZE(parent);
998
        unsigned char bufbits = ISOFS_BUFFER_BITS(parent);
999
        unsigned int block,offset;
1000
        int parent_dir, inode_number;
1001
        int old_offset;
1002
        void * cpnt = NULL;
1003
        int result;
1004
        int directory_size;
1005
        struct buffer_head * bh;
1006
        struct iso_directory_record * de;
1007
 
1008
        offset = 0;
1009
        block = extent << (ISOFS_ZONE_BITS(parent) - bufbits);
1010
        if (!(bh = bread(parent->i_dev, block, bufsize)))  return -1;
1011
 
1012
        while (1 == 1) {
1013
                de = (struct iso_directory_record *) (bh->b_data + offset);
1014
                if (*((unsigned char *) de) == 0)
1015
                {
1016
                        brelse(bh);
1017
                        printk("Directory .. not found\n");
1018
                        return -1;
1019
                }
1020
 
1021
                offset += *((unsigned char *) de);
1022
 
1023
                if (offset >= bufsize)
1024
                {
1025
                        printk(".. Directory not in first block"
1026
                               " of directory.\n");
1027
                        brelse(bh);
1028
                        return -1;
1029
                }
1030
 
1031
                if (de->name_len[0] == 1 && de->name[0] == 1)
1032
                {
1033
                        parent_dir = find_rock_ridge_relocation(de, parent);
1034
                        directory_size = isonum_733 (de->size);
1035
                        brelse(bh);
1036
                        break;
1037
                }
1038
        }
1039
#ifdef DEBUG
1040
        printk("Parent dir:%x\n",parent_dir);
1041
#endif
1042
        /* Now we know the extent where the parent dir starts on. */
1043
 
1044
        result = -1;
1045
 
1046
        offset = 0;
1047
        block = parent_dir << (ISOFS_ZONE_BITS(parent) - bufbits);
1048
        if (!block || !(bh = bread(parent->i_dev,block, bufsize)))
1049
        {
1050
                return -1;
1051
        }
1052
 
1053
        for(;;)
1054
        {
1055
                de = (struct iso_directory_record *) (bh->b_data + offset);
1056
                inode_number = (block << bufbits)+(offset & (bufsize - 1));
1057
 
1058
                /* If the length byte is zero, we should move on to the next
1059
                   CDROM sector.  If we are at the end of the directory, we
1060
                   kick out of the while loop. */
1061
 
1062
                if (*((unsigned char *) de) == 0)
1063
                {
1064
                        brelse(bh);
1065
                        offset = 0;
1066
                        block++;
1067
                        directory_size -= bufsize;
1068
                        if(directory_size < 0) return -1;
1069
                        if((block & 1) && (ISOFS_ZONE_BITS(parent) - bufbits) == 1)
1070
                        {
1071
                                return -1;
1072
                        }
1073
                        if((block & 3) && (ISOFS_ZONE_BITS(parent) - bufbits) == 2)
1074
                        {
1075
                                return -1;
1076
                        }
1077
                        if (!block
1078
                            || !(bh = bread(parent->i_dev,block, bufsize)))
1079
                        {
1080
                                return -1;
1081
                        }
1082
                        continue;
1083
                }
1084
 
1085
                /* Make sure that the entire directory record is in the current
1086
                   bh block.  If not, we malloc a buffer, and put the two
1087
                   halves together, so that we can cleanly read the block.  */
1088
 
1089
                old_offset = offset;
1090
                offset += *((unsigned char *) de);
1091
 
1092
                if (offset >= bufsize)
1093
                {
1094
                        unsigned int frag1;
1095
                        frag1 = bufsize - old_offset;
1096
                        cpnt = kmalloc(*((unsigned char *) de),GFP_KERNEL);
1097
                        if (!cpnt) return -1;
1098
                        memcpy(cpnt, bh->b_data + old_offset, frag1);
1099
                        de = (struct iso_directory_record *) ((char *)cpnt);
1100
                        brelse(bh);
1101
                        offset -= bufsize;
1102
                        directory_size -= bufsize;
1103
                        if(directory_size < 0)
1104
                        {
1105
                                printk("Directory size < 0\n");
1106
                                return -1;
1107
                        }
1108
                        block++;
1109
                        if(!(bh = bread(parent->i_dev,block,bufsize))) {
1110
                                kfree(cpnt);
1111
                                return -1;
1112
                        }
1113
                        memcpy((char *)cpnt+frag1, bh->b_data, offset);
1114
                }
1115
 
1116
                if (find_rock_ridge_relocation(de, parent) == extent){
1117
                        result = inode_number;
1118
                        goto out;
1119
                }
1120
 
1121
                if (cpnt) {
1122
                        kfree(cpnt);
1123
                        cpnt = NULL;
1124
                }
1125
        }
1126
 
1127
        /* We go here for any condition we cannot handle.
1128
           We also drop through to here at the end of the directory. */
1129
 
1130
 out:
1131
        if (cpnt) {
1132
                kfree(cpnt);
1133
                cpnt = NULL;
1134
        }
1135
        brelse(bh);
1136
#ifdef DEBUG
1137
        printk("Resultant Inode %d\n",result);
1138
#endif
1139
        return result;
1140
}
1141
 
1142
#ifdef LEAK_CHECK
1143
#undef malloc
1144
#undef free_s
1145
#undef bread
1146
#undef brelse
1147
 
1148
void * leak_check_malloc(unsigned int size){
1149
  void * tmp;
1150
  check_malloc++;
1151
  tmp = kmalloc(size, GFP_KERNEL);
1152
  return tmp;
1153
}
1154
 
1155
void leak_check_free_s(void * obj, int size){
1156
  check_malloc--;
1157
  return kfree_s(obj, size);
1158
}
1159
 
1160
struct buffer_head * leak_check_bread(int dev, int block, int size){
1161
  check_bread++;
1162
  return bread(dev, block, size);
1163
}
1164
 
1165
void leak_check_brelse(struct buffer_head * bh){
1166
  check_bread--;
1167
  return brelse(bh);
1168
}
1169
 
1170
#endif
1171
 
1172
static struct file_system_type iso9660_fs_type = {
1173
        isofs_read_super, "iso9660", 1, NULL
1174
};
1175
 
1176
int init_iso9660_fs(void)
1177
{
1178
        return register_filesystem(&iso9660_fs_type);
1179
}
1180
 
1181
#ifdef MODULE
1182
int init_module(void)
1183
{
1184
        int status;
1185
 
1186
        if ((status = init_iso9660_fs()) == 0)
1187
                register_symtab(0);
1188
        return status;
1189
}
1190
 
1191
void cleanup_module(void)
1192
{
1193
        unregister_filesystem(&iso9660_fs_type);
1194
}
1195
 
1196
#endif
1197
 

powered by: WebSVN 2.1.0

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