linux-old/fs/isofs/inode.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/isofs/inode.c
   3 *
   4 *  (C) 1991  Linus Torvalds - minix filesystem
   5 *      1992, 1993, 1994  Eric Youngdale Modified for ISO 9660 filesystem.
   6 *      1994  Eberhard Moenkeberg - multi session handling.
   7 *      1995  Mark Dobie - allow mounting of some weird VideoCDs and PhotoCDs.
   8 *      1997  Gordon Chaffee - Joliet CDs
   9 *      1998  Eric Lammerts - ISO 9660 Level 3
  10 */
  11
  12#include <linux/config.h>
  13#include <linux/module.h>
  14
  15#include <linux/stat.h>
  16#include <linux/sched.h>
  17#include <linux/iso_fs.h>
  18#include <linux/kernel.h>
  19#include <linux/major.h>
  20#include <linux/mm.h>
  21#include <linux/string.h>
  22#include <linux/locks.h>
  23#include <linux/slab.h>
  24#include <linux/errno.h>
  25#include <linux/cdrom.h>
  26#include <linux/init.h>
  27#include <linux/nls.h>
  28#include <linux/ctype.h>
  29#include <linux/smp_lock.h>
  30#include <linux/blkdev.h>
  31
  32#include <asm/system.h>
  33#include <asm/uaccess.h>
  34
  35#include "zisofs.h"
  36
  37#define BEQUIET
  38
  39#ifdef LEAK_CHECK
  40static int check_malloc = 0;
  41static int check_bread = 0;
  42#endif
  43
  44static int isofs_hashi(struct dentry *parent, struct qstr *qstr);
  45static int isofs_hash(struct dentry *parent, struct qstr *qstr);
  46static int isofs_dentry_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
  47static int isofs_dentry_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
  48
  49#ifdef CONFIG_JOLIET
  50static int isofs_hashi_ms(struct dentry *parent, struct qstr *qstr);
  51static int isofs_hash_ms(struct dentry *parent, struct qstr *qstr);
  52static int isofs_dentry_cmpi_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);
  53static int isofs_dentry_cmp_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);
  54#endif
  55
  56static void isofs_put_super(struct super_block *sb)
  57{
  58#ifdef CONFIG_JOLIET
  59        if (sb->u.isofs_sb.s_nls_iocharset) {
  60                unload_nls(sb->u.isofs_sb.s_nls_iocharset);
  61                sb->u.isofs_sb.s_nls_iocharset = NULL;
  62        }
  63#endif
  64
  65#ifdef LEAK_CHECK
  66        printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
  67               check_malloc, check_bread);
  68#endif
  69
  70        return;
  71}
  72
  73static void isofs_read_inode(struct inode *);
  74static int isofs_statfs (struct super_block *, struct statfs *);
  75
  76static struct super_operations isofs_sops = {
  77        read_inode:     isofs_read_inode,
  78        put_super:      isofs_put_super,
  79        statfs:         isofs_statfs,
  80};
  81
  82static struct dentry_operations isofs_dentry_ops[] = {
  83        {
  84                d_hash:         isofs_hash,
  85                d_compare:      isofs_dentry_cmp,
  86        },
  87        {
  88                d_hash:         isofs_hashi,
  89                d_compare:      isofs_dentry_cmpi,
  90        },
  91#ifdef CONFIG_JOLIET
  92        {
  93                d_hash:         isofs_hash_ms,
  94                d_compare:      isofs_dentry_cmp_ms,
  95        },
  96        {
  97                d_hash:         isofs_hashi_ms,
  98                d_compare:      isofs_dentry_cmpi_ms,
  99        }
 100#endif
 101};
 102
 103struct iso9660_options{
 104        char map;
 105        char rock;
 106        char joliet;
 107        char cruft;
 108        char unhide;
 109        char nocompress;
 110        unsigned char check;
 111        unsigned int blocksize;
 112        mode_t mode;
 113        gid_t gid;
 114        uid_t uid;
 115        char *iocharset;
 116        unsigned char utf8;
 117        /* LVE */
 118        s32 session;
 119        s32 sbsector;
 120};
 121
 122/*
 123 * Compute the hash for the isofs name corresponding to the dentry.
 124 */
 125static int
 126isofs_hash_common(struct dentry *dentry, struct qstr *qstr, int ms)
 127{
 128        const char *name;
 129        int len;
 130
 131        len = qstr->len;
 132        name = qstr->name;
 133        if (ms) {
 134                while (len && name[len-1] == '.')
 135                        len--;
 136        }
 137
 138        qstr->hash = full_name_hash(name, len);
 139
 140        return 0;
 141}
 142
 143/*
 144 * Compute the hash for the isofs name corresponding to the dentry.
 145 */
 146static int
 147isofs_hashi_common(struct dentry *dentry, struct qstr *qstr, int ms)
 148{
 149        const char *name;
 150        int len;
 151        char c;
 152        unsigned long hash;
 153
 154        len = qstr->len;
 155        name = qstr->name;
 156        if (ms) {
 157                while (len && name[len-1] == '.')
 158                        len--;
 159        }
 160
 161        hash = init_name_hash();
 162        while (len--) {
 163                c = tolower(*name++);
 164                hash = partial_name_hash(tolower(c), hash);
 165        }
 166        qstr->hash = end_name_hash(hash);
 167
 168        return 0;
 169}
 170
 171/*
 172 * Case insensitive compare of two isofs names.
 173 */
 174static int
 175isofs_dentry_cmpi_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
 176{
 177        int alen, blen;
 178
 179        /* A filename cannot end in '.' or we treat it like it has none */
 180        alen = a->len;
 181        blen = b->len;
 182        if (ms) {
 183                while (alen && a->name[alen-1] == '.')
 184                        alen--;
 185                while (blen && b->name[blen-1] == '.')
 186                        blen--;
 187        }
 188        if (alen == blen) {
 189                if (strnicmp(a->name, b->name, alen) == 0)
 190                        return 0;
 191        }
 192        return 1;
 193}
 194
 195/*
 196 * Case sensitive compare of two isofs names.
 197 */
 198static int
 199isofs_dentry_cmp_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
 200{
 201        int alen, blen;
 202
 203        /* A filename cannot end in '.' or we treat it like it has none */
 204        alen = a->len;
 205        blen = b->len;
 206        if (ms) {
 207                while (alen && a->name[alen-1] == '.')
 208                        alen--;
 209                while (blen && b->name[blen-1] == '.')
 210                        blen--;
 211        }
 212        if (alen == blen) {
 213                if (strncmp(a->name, b->name, alen) == 0)
 214                        return 0;
 215        }
 216        return 1;
 217}
 218
 219static int
 220isofs_hash(struct dentry *dentry, struct qstr *qstr)
 221{
 222        return isofs_hash_common(dentry, qstr, 0);
 223}
 224
 225static int
 226isofs_hashi(struct dentry *dentry, struct qstr *qstr)
 227{
 228        return isofs_hashi_common(dentry, qstr, 0);
 229}
 230
 231static int
 232isofs_dentry_cmp(struct dentry *dentry,struct qstr *a,struct qstr *b)
 233{
 234        return isofs_dentry_cmp_common(dentry, a, b, 0);
 235}
 236
 237static int
 238isofs_dentry_cmpi(struct dentry *dentry,struct qstr *a,struct qstr *b)
 239{
 240        return isofs_dentry_cmpi_common(dentry, a, b, 0);
 241}
 242
 243#ifdef CONFIG_JOLIET
 244static int
 245isofs_hash_ms(struct dentry *dentry, struct qstr *qstr)
 246{
 247        return isofs_hash_common(dentry, qstr, 1);
 248}
 249
 250static int
 251isofs_hashi_ms(struct dentry *dentry, struct qstr *qstr)
 252{
 253        return isofs_hashi_common(dentry, qstr, 1);
 254}
 255
 256static int
 257isofs_dentry_cmp_ms(struct dentry *dentry,struct qstr *a,struct qstr *b)
 258{
 259        return isofs_dentry_cmp_common(dentry, a, b, 1);
 260}
 261
 262static int
 263isofs_dentry_cmpi_ms(struct dentry *dentry,struct qstr *a,struct qstr *b)
 264{
 265        return isofs_dentry_cmpi_common(dentry, a, b, 1);
 266}
 267#endif
 268
 269static int parse_options(char *options, struct iso9660_options * popt)
 270{
 271        char *this_char,*value;
 272
 273        popt->map = 'n';
 274        popt->rock = 'y';
 275        popt->joliet = 'y';
 276        popt->cruft = 'n';
 277        popt->unhide = 'n';
 278        popt->check = 'u';              /* unset */
 279        popt->nocompress = 0;
 280        popt->blocksize = 1024;
 281        popt->mode = S_IRUGO | S_IXUGO; /* r-x for all.  The disc could
 282                                           be shared with DOS machines so
 283                                           virtually anything could be
 284                                           a valid executable. */
 285        popt->gid = 0;
 286        popt->uid = 0;
 287        popt->iocharset = NULL;
 288        popt->utf8 = 0;
 289        popt->session=-1;
 290        popt->sbsector=-1;
 291        if (!options) return 1;
 292        for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
 293                if (strncmp(this_char,"norock",6) == 0) {
 294                  popt->rock = 'n';
 295                  continue;
 296                }
 297                if (strncmp(this_char,"nojoliet",8) == 0) {
 298                  popt->joliet = 'n';
 299                  continue;
 300                }
 301                if (strncmp(this_char,"unhide",6) == 0) {
 302                  popt->unhide = 'y';
 303                  continue;
 304                }
 305                if (strncmp(this_char,"cruft",5) == 0) {
 306                  popt->cruft = 'y';
 307                  continue;
 308                }
 309                if (strncmp(this_char,"utf8",4) == 0) {
 310                  popt->utf8 = 1;
 311                  continue;
 312                }
 313                if (strncmp(this_char,"nocompress",10) == 0) {
 314                  popt->nocompress = 1;
 315                  continue;
 316                }
 317                if ((value = strchr(this_char,'=')) != NULL)
 318                        *value++ = 0;
 319
 320#ifdef CONFIG_JOLIET
 321                if (!strcmp(this_char,"iocharset") && value) {
 322                        popt->iocharset = value;
 323                        while (*value && *value != ',')
 324                                value++;
 325                        if (value == popt->iocharset)
 326                                return 0;
 327                        *value = 0;
 328                } else
 329#endif
 330                if (!strcmp(this_char,"map") && value) {
 331                        if (value[0] && !value[1] && strchr("ano",*value))
 332                                popt->map = *value;
 333                        else if (!strcmp(value,"off")) popt->map = 'o';
 334                        else if (!strcmp(value,"normal")) popt->map = 'n';
 335                        else if (!strcmp(value,"acorn")) popt->map = 'a';
 336                        else return 0;
 337                }
 338                if (!strcmp(this_char,"session") && value) {
 339                        char * vpnt = value;
 340                        unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0);
 341                        if(ivalue < 0 || ivalue >99) return 0;
 342                        popt->session=ivalue+1;
 343                }
 344                if (!strcmp(this_char,"sbsector") && value) {
 345                        char * vpnt = value;
 346                        unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0);
 347                        if(ivalue < 0 || ivalue >660*512) return 0;
 348                        popt->sbsector=ivalue;
 349                }
 350                else if (!strcmp(this_char,"check") && value) {
 351                        if (value[0] && !value[1] && strchr("rs",*value))
 352                                popt->check = *value;
 353                        else if (!strcmp(value,"relaxed")) popt->check = 'r';
 354                        else if (!strcmp(value,"strict")) popt->check = 's';
 355                        else return 0;
 356                }
 357                else if (!strcmp(this_char,"conv") && value) {
 358                        /* no conversion is done anymore;
 359                           we still accept the same mount options,
 360                           but ignore them */
 361                        if (value[0] && !value[1] && strchr("btma",*value)) ;
 362                        else if (!strcmp(value,"binary")) ;
 363                        else if (!strcmp(value,"text")) ;
 364                        else if (!strcmp(value,"mtext")) ;
 365                        else if (!strcmp(value,"auto")) ;
 366                        else return 0;
 367                }
 368                else if (value &&
 369                         (!strcmp(this_char,"block") ||
 370                          !strcmp(this_char,"mode") ||
 371                          !strcmp(this_char,"uid") ||
 372                          !strcmp(this_char,"gid"))) {
 373                  char * vpnt = value;
 374                  unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0);
 375                  if (*vpnt) return 0;
 376                  switch(*this_char) {
 377                  case 'b':
 378                    if (   ivalue != 512
 379                        && ivalue != 1024
 380                        && ivalue != 2048) return 0;
 381                    popt->blocksize = ivalue;
 382                    break;
 383                  case 'u':
 384                    popt->uid = ivalue;
 385                    break;
 386                  case 'g':
 387                    popt->gid = ivalue;
 388                    break;
 389                  case 'm':
 390                    popt->mode = ivalue;
 391                    break;
 392                  }
 393                }
 394                else return 1;
 395        }
 396        return 1;
 397}
 398
 399/*
 400 * look if the driver can tell the multi session redirection value
 401 *
 402 * don't change this if you don't know what you do, please!
 403 * Multisession is legal only with XA disks.
 404 * A non-XA disk with more than one volume descriptor may do it right, but
 405 * usually is written in a nowhere standardized "multi-partition" manner.
 406 * Multisession uses absolute addressing (solely the first frame of the whole
 407 * track is #0), multi-partition uses relative addressing (each first frame of
 408 * each track is #0), and a track is not a session.
 409 *
 410 * A broken CDwriter software or drive firmware does not set new standards,
 411 * at least not if conflicting with the existing ones.
 412 *
 413 * emoenke@gwdg.de
 414 */
 415#define WE_OBEY_THE_WRITTEN_STANDARDS 1
 416
 417static unsigned int isofs_get_last_session(struct super_block *sb,s32 session )
 418{
 419        struct cdrom_multisession ms_info;
 420        unsigned int vol_desc_start;
 421        struct block_device *bdev = sb->s_bdev;
 422        int i;
 423
 424        vol_desc_start=0;
 425        ms_info.addr_format=CDROM_LBA;
 426        if(session >= 0 && session <= 99) {
 427                struct cdrom_tocentry Te;
 428                Te.cdte_track=session;
 429                Te.cdte_format=CDROM_LBA;
 430                i = ioctl_by_bdev(bdev, CDROMREADTOCENTRY, (unsigned long) &Te);
 431                if (!i) {
 432                        printk(KERN_DEBUG "Session %d start %d type %d\n",
 433                               session, Te.cdte_addr.lba,
 434                               Te.cdte_ctrl&CDROM_DATA_TRACK);
 435                        if ((Te.cdte_ctrl&CDROM_DATA_TRACK) == 4)
 436                                return Te.cdte_addr.lba;
 437                }
 438                        
 439                printk(KERN_ERR "Invalid session number or type of track\n");
 440        }
 441        i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info);
 442        if(session > 0) printk(KERN_ERR "Invalid session number\n");
 443#if 0
 444        printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
 445        if (i==0) {
 446                printk("isofs.inode: XA disk: %s\n",ms_info.xa_flag?"yes":"no");
 447                printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
 448        }
 449#endif
 450        if (i==0)
 451#if WE_OBEY_THE_WRITTEN_STANDARDS
 452        if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
 453#endif
 454                vol_desc_start=ms_info.addr.lba;
 455        return vol_desc_start;
 456}
 457
 458/*
 459 * Initialize the superblock and read the root inode.
 460 *
 461 * Note: a check_disk_change() has been done immediately prior
 462 * to this call, so we don't need to check again.
 463 */
 464static struct super_block *isofs_read_super(struct super_block *s, void *data,
 465                                            int silent)
 466{
 467        kdev_t                          dev = s->s_dev;
 468        struct buffer_head            * bh = NULL, *pri_bh = NULL;
 469        struct hs_primary_descriptor  * h_pri = NULL;
 470        struct iso_primary_descriptor * pri = NULL;
 471        struct iso_supplementary_descriptor *sec = NULL;
 472        struct iso_directory_record   * rootp;
 473        int                             joliet_level = 0;
 474        int                             high_sierra;
 475        int                             iso_blknum, block;
 476        int                             orig_zonesize;
 477        int                             table;
 478        unsigned int                    blocksize, blocksize_bits;
 479        unsigned int                    vol_desc_start;
 480        unsigned long                   first_data_zone;
 481        struct inode                  * inode;
 482        struct iso9660_options          opt;
 483
 484        if (!parse_options((char *) data, &opt))
 485                goto out_unlock;
 486
 487        /*
 488         * First of all, get the hardware blocksize for this device.
 489         * If we don't know what it is, or the hardware blocksize is
 490         * larger than the blocksize the user specified, then use
 491         * that value.
 492         */
 493        blocksize = get_hardsect_size(dev);
 494        if(blocksize > opt.blocksize) {
 495            /*
 496             * Force the blocksize we are going to use to be the
 497             * hardware blocksize.
 498             */
 499            opt.blocksize = blocksize;
 500        }
 501
 502        blocksize_bits = 0;
 503        {
 504          int i = opt.blocksize;
 505          while (i != 1){
 506            blocksize_bits++;
 507            i >>=1;
 508          }
 509        }
 510
 511        set_blocksize(dev, opt.blocksize);
 512        s->s_blocksize = opt.blocksize;
 513
 514        s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
 515
 516        vol_desc_start = (opt.sbsector != -1) ?
 517                opt.sbsector : isofs_get_last_session(s,opt.session);
 518
 519        for (iso_blknum = vol_desc_start+16;
 520             iso_blknum < vol_desc_start+100; iso_blknum++)
 521        {
 522            struct hs_volume_descriptor   * hdp;
 523            struct iso_volume_descriptor  * vdp;
 524
 525            block = iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits);
 526            if (!(bh = sb_bread(s, block)))
 527                goto out_no_read;
 528
 529            vdp = (struct iso_volume_descriptor *)bh->b_data;
 530            hdp = (struct hs_volume_descriptor *)bh->b_data;
 531            
 532            /* Due to the overlapping physical location of the descriptors, 
 533             * ISO CDs can match hdp->id==HS_STANDARD_ID as well. To ensure 
 534             * proper identification in this case, we first check for ISO.
 535             */
 536            if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
 537                if (isonum_711 (vdp->type) == ISO_VD_END)
 538                    break;
 539                if (isonum_711 (vdp->type) == ISO_VD_PRIMARY) {
 540                    if (pri == NULL) {
 541                        pri = (struct iso_primary_descriptor *)vdp;
 542                        /* Save the buffer in case we need it ... */
 543                        pri_bh = bh;
 544                        bh = NULL;
 545                    }
 546                }
 547#ifdef CONFIG_JOLIET
 548                else if (isonum_711 (vdp->type) == ISO_VD_SUPPLEMENTARY) {
 549                    sec = (struct iso_supplementary_descriptor *)vdp;
 550                    if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) {
 551                        if (opt.joliet == 'y') {
 552                            if (sec->escape[2] == 0x40) {
 553                                joliet_level = 1;
 554                            } else if (sec->escape[2] == 0x43) {
 555                                joliet_level = 2;
 556                            } else if (sec->escape[2] == 0x45) {
 557                                joliet_level = 3;
 558                            }
 559                            printk(KERN_DEBUG"ISO 9660 Extensions: Microsoft Joliet Level %d\n",
 560                                   joliet_level);
 561                        }
 562                        goto root_found;
 563                    } else {
 564                        /* Unknown supplementary volume descriptor */
 565                        sec = NULL;
 566                    }
 567                }
 568#endif
 569            } else {
 570                if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
 571                    if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
 572                        goto out_freebh;
 573                
 574                    s->u.isofs_sb.s_high_sierra = 1;
 575                    high_sierra = 1;
 576                    opt.rock = 'n';
 577                    h_pri = (struct hs_primary_descriptor *)vdp;
 578                    goto root_found;
 579                }
 580            }
 581
 582            /* Just skip any volume descriptors we don't recognize */
 583
 584            brelse(bh);
 585            bh = NULL;
 586        }
 587        /*
 588         * If we fall through, either no volume descriptor was found,
 589         * or else we passed a primary descriptor looking for others.
 590         */
 591        if (!pri)
 592                goto out_unknown_format;
 593        brelse(bh);
 594        bh = pri_bh;
 595        pri_bh = NULL;
 596
 597root_found:
 598
 599        if (joliet_level && (pri == NULL || opt.rock == 'n')) {
 600            /* This is the case of Joliet with the norock mount flag.
 601             * A disc with both Joliet and Rock Ridge is handled later
 602             */
 603            pri = (struct iso_primary_descriptor *) sec;
 604        }
 605
 606        if(high_sierra){
 607          rootp = (struct iso_directory_record *) h_pri->root_directory_record;
 608          s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size);
 609          s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size);
 610          s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size);
 611        } else {
 612          if (!pri)
 613            goto out_freebh;
 614          rootp = (struct iso_directory_record *) pri->root_directory_record;
 615          s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size);
 616          s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
 617          s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
 618        }
 619
 620        s->u.isofs_sb.s_ninodes = 0; /* No way to figure this out easily */
 621
 622        orig_zonesize = s -> u.isofs_sb.s_log_zone_size;
 623        /*
 624         * If the zone size is smaller than the hardware sector size,
 625         * this is a fatal error.  This would occur if the disc drive
 626         * had sectors that were 2048 bytes, but the filesystem had
 627         * blocks that were 512 bytes (which should only very rarely
 628         * happen.)
 629         */
 630        if(blocksize != 0 && orig_zonesize < blocksize)
 631                goto out_bad_size;
 632
 633        /* RDE: convert log zone size to bit shift */
 634        switch (s -> u.isofs_sb.s_log_zone_size)
 635          { case  512: s -> u.isofs_sb.s_log_zone_size =  9; break;
 636            case 1024: s -> u.isofs_sb.s_log_zone_size = 10; break;
 637            case 2048: s -> u.isofs_sb.s_log_zone_size = 11; break;
 638
 639            default:
 640                goto out_bad_zone_size;
 641          }
 642
 643        s->s_magic = ISOFS_SUPER_MAGIC;
 644
 645        /* The CDROM is read-only, has no nodes (devices) on it, and since
 646           all of the files appear to be owned by root, we really do not want
 647           to allow suid.  (suid or devices will not show up unless we have
 648           Rock Ridge extensions) */
 649
 650        s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
 651
 652        /* Set this for reference. Its not currently used except on write
 653           which we don't have .. */
 654           
 655        /* RDE: data zone now byte offset! */
 656
 657        first_data_zone = ((isonum_733 (rootp->extent) +
 658                          isonum_711 (rootp->ext_attr_length))
 659                         << s -> u.isofs_sb.s_log_zone_size);
 660        s->u.isofs_sb.s_firstdatazone = first_data_zone;
 661#ifndef BEQUIET
 662        printk(KERN_DEBUG "Max size:%ld   Log zone size:%ld\n",
 663               s->u.isofs_sb.s_max_size,
 664               1UL << s->u.isofs_sb.s_log_zone_size);
 665        printk(KERN_DEBUG "First datazone:%ld   Root inode number:%ld\n",
 666               s->u.isofs_sb.s_firstdatazone >> s -> u.isofs_sb.s_log_zone_size,
 667               s->u.isofs_sb.s_firstdatazone);
 668        if(high_sierra)
 669                printk(KERN_DEBUG "Disc in High Sierra format.\n");
 670#endif
 671
 672        /*
 673         * If the Joliet level is set, we _may_ decide to use the
 674         * secondary descriptor, but can't be sure until after we
 675         * read the root inode. But before reading the root inode
 676         * we may need to change the device blocksize, and would
 677         * rather release the old buffer first. So, we cache the
 678         * first_data_zone value from the secondary descriptor.
 679         */
 680        if (joliet_level) {
 681                pri = (struct iso_primary_descriptor *) sec;
 682                rootp = (struct iso_directory_record *)
 683                        pri->root_directory_record;
 684                first_data_zone = ((isonum_733 (rootp->extent) +
 685                                isonum_711 (rootp->ext_attr_length))
 686                                 << s -> u.isofs_sb.s_log_zone_size);
 687        }
 688
 689        /*
 690         * We're all done using the volume descriptor, and may need
 691         * to change the device blocksize, so release the buffer now.
 692         */
 693        brelse(pri_bh);
 694        brelse(bh);
 695
 696        /*
 697         * Force the blocksize to 512 for 512 byte sectors.  The file
 698         * read primitives really get it wrong in a bad way if we don't
 699         * do this.
 700         *
 701         * Note - we should never be setting the blocksize to something
 702         * less than the hardware sector size for the device.  If we
 703         * do, we would end up having to read larger buffers and split
 704         * out portions to satisfy requests.
 705         *
 706         * Note2- the idea here is that we want to deal with the optimal
 707         * zonesize in the filesystem.  If we have it set to something less,
 708         * then we have horrible problems with trying to piece together
 709         * bits of adjacent blocks in order to properly read directory
 710         * entries.  By forcing the blocksize in this way, we ensure
 711         * that we will never be required to do this.
 712         */
 713        if ( orig_zonesize != opt.blocksize ) {
 714                set_blocksize(dev, orig_zonesize);
 715#ifndef BEQUIET
 716                printk(KERN_DEBUG 
 717                        "ISOFS: Forcing new log zone size:%d\n", orig_zonesize);
 718#endif
 719        }
 720        s->s_blocksize = orig_zonesize;
 721        s->s_blocksize_bits = s -> u.isofs_sb.s_log_zone_size;
 722
 723        s->u.isofs_sb.s_nls_iocharset = NULL;
 724
 725#ifdef CONFIG_JOLIET
 726        if (joliet_level && opt.utf8 == 0) {
 727                char * p = opt.iocharset ? opt.iocharset : "iso8859-1";
 728                s->u.isofs_sb.s_nls_iocharset = load_nls(p);
 729                if (! s->u.isofs_sb.s_nls_iocharset) {
 730                        /* Fail only if explicit charset specified */
 731                        if (opt.iocharset)
 732                                goto out_unlock;
 733                        s->u.isofs_sb.s_nls_iocharset = load_nls_default();
 734                }
 735        }
 736#endif
 737        s->s_op = &isofs_sops;
 738        s->u.isofs_sb.s_mapping = opt.map;
 739        s->u.isofs_sb.s_rock = (opt.rock == 'y' ? 2 : 0);
 740        s->u.isofs_sb.s_rock_offset = -1; /* initial offset, will guess until SP is found*/
 741        s->u.isofs_sb.s_cruft = opt.cruft;
 742        s->u.isofs_sb.s_unhide = opt.unhide;
 743        s->u.isofs_sb.s_uid = opt.uid;
 744        s->u.isofs_sb.s_gid = opt.gid;
 745        s->u.isofs_sb.s_utf8 = opt.utf8;
 746        s->u.isofs_sb.s_nocompress = opt.nocompress;
 747        /*
 748         * It would be incredibly stupid to allow people to mark every file
 749         * on the disk as suid, so we merely allow them to set the default
 750         * permissions.
 751         */
 752        s->u.isofs_sb.s_mode = opt.mode & 0777;
 753
 754        /*
 755         * Read the root inode, which _may_ result in changing
 756         * the s_rock flag. Once we have the final s_rock value,
 757         * we then decide whether to use the Joliet descriptor.
 758         */
 759        inode = iget(s, s->u.isofs_sb.s_firstdatazone);
 760
 761        /*
 762         * If this disk has both Rock Ridge and Joliet on it, then we
 763         * want to use Rock Ridge by default.  This can be overridden
 764         * by using the norock mount option.  There is still one other
 765         * possibility that is not taken into account: a Rock Ridge
 766         * CD with Unicode names.  Until someone sees such a beast, it
 767         * will not be supported.
 768         */
 769        if (s->u.isofs_sb.s_rock == 1) {
 770                joliet_level = 0;
 771        } else if (joliet_level) {
 772                s->u.isofs_sb.s_rock = 0;
 773                if (s->u.isofs_sb.s_firstdatazone != first_data_zone) {
 774                        s->u.isofs_sb.s_firstdatazone = first_data_zone;
 775                        printk(KERN_DEBUG 
 776                                "ISOFS: changing to secondary root\n");
 777                        iput(inode);
 778                        inode = iget(s, s->u.isofs_sb.s_firstdatazone);
 779                }
 780        }
 781
 782        if (opt.check == 'u') {
 783                /* Only Joliet is case insensitive by default */
 784                if (joliet_level) opt.check = 'r';
 785                else opt.check = 's';
 786        }
 787        s->u.isofs_sb.s_joliet_level = joliet_level;
 788
 789        /* check the root inode */
 790        if (!inode)
 791                goto out_no_root;
 792        if (!inode->i_op)
 793                goto out_bad_root;
 794        /* get the root dentry */
 795        s->s_root = d_alloc_root(inode);
 796        if (!(s->s_root))
 797                goto out_no_root;
 798
 799        table = 0;
 800        if (joliet_level) table += 2;
 801        if (opt.check == 'r') table++;
 802        s->s_root->d_op = &isofs_dentry_ops[table];
 803
 804        return s;
 805
 806        /*
 807         * Display error messages and free resources.
 808         */
 809out_bad_root:
 810        printk(KERN_WARNING "isofs_read_super: root inode not initialized\n");
 811        goto out_iput;
 812out_no_root:
 813        printk(KERN_WARNING "isofs_read_super: get root inode failed\n");
 814out_iput:
 815        iput(inode);
 816#ifdef CONFIG_JOLIET
 817        if (s->u.isofs_sb.s_nls_iocharset)
 818                unload_nls(s->u.isofs_sb.s_nls_iocharset);
 819#endif
 820        goto out_unlock;
 821out_no_read:
 822        printk(KERN_WARNING "isofs_read_super: "
 823                "bread failed, dev=%s, iso_blknum=%d, block=%d\n",
 824                kdevname(dev), iso_blknum, block);
 825        goto out_unlock;
 826out_bad_zone_size:
 827        printk(KERN_WARNING "Bad logical zone size %ld\n",
 828                s->u.isofs_sb.s_log_zone_size);
 829        goto out_freebh;
 830out_bad_size:
 831        printk(KERN_WARNING "Logical zone size(%d) < hardware blocksize(%u)\n",
 832                orig_zonesize, blocksize);
 833        goto out_freebh;
 834out_unknown_format:
 835        if (!silent)
 836                printk(KERN_WARNING "Unable to identify CD-ROM format.\n");
 837
 838out_freebh:
 839        brelse(bh);
 840out_unlock:
 841        return NULL;
 842}
 843
 844static int isofs_statfs (struct super_block *sb, struct statfs *buf)
 845{
 846        buf->f_type = ISOFS_SUPER_MAGIC;
 847        buf->f_bsize = sb->s_blocksize;
 848        buf->f_blocks = (sb->u.isofs_sb.s_nzones
 849                  << (sb->u.isofs_sb.s_log_zone_size - sb->s_blocksize_bits));
 850        buf->f_bfree = 0;
 851        buf->f_bavail = 0;
 852        buf->f_files = sb->u.isofs_sb.s_ninodes;
 853        buf->f_ffree = 0;
 854        buf->f_namelen = NAME_MAX;
 855        return 0;
 856}
 857
 858/*
 859 * Get a set of blocks; filling in buffer_heads if already allocated
 860 * or getblk() if they are not.  Returns the number of blocks inserted
 861 * (0 == error.)
 862 */
 863int isofs_get_blocks(struct inode *inode, long iblock,
 864                     struct buffer_head **bh_result, unsigned long nblocks)
 865{
 866        unsigned long b_off;
 867        unsigned offset, sect_size;
 868        unsigned int firstext;
 869        unsigned long nextino;
 870        int section, rv;
 871
 872        lock_kernel();
 873
 874        rv = 0;
 875        if (iblock < 0) {
 876                printk("isofs_get_blocks: block < 0\n");
 877                goto abort;
 878        }
 879
 880        b_off = iblock;
 881        
 882        offset    = 0;
 883        firstext  = inode->u.isofs_i.i_first_extent;
 884        sect_size = inode->u.isofs_i.i_section_size >> ISOFS_BUFFER_BITS(inode);
 885        nextino   = inode->u.isofs_i.i_next_section_ino;
 886        section   = 0;
 887
 888        while ( nblocks ) {
 889                /* If we are *way* beyond the end of the file, print a message.
 890                 * Access beyond the end of the file up to the next page boundary
 891                 * is normal, however because of the way the page cache works.
 892                 * In this case, we just return 0 so that we can properly fill
 893                 * the page with useless information without generating any
 894                 * I/O errors.
 895                 */
 896                if (b_off > ((inode->i_size + PAGE_CACHE_SIZE - 1) >> ISOFS_BUFFER_BITS(inode))) {
 897                        printk("isofs_get_blocks: block >= EOF (%ld, %ld)\n",
 898                               iblock, (unsigned long) inode->i_size);
 899                        goto abort;
 900                }
 901                
 902                if (nextino) {
 903                        while (b_off >= (offset + sect_size)) {
 904                                struct inode *ninode;
 905                                
 906                                offset += sect_size;
 907                                if (nextino == 0)
 908                                        goto abort;
 909                                ninode = iget(inode->i_sb, nextino);
 910                                if (!ninode)
 911                                        goto abort;
 912                                firstext  = ninode->u.isofs_i.i_first_extent;
 913                                sect_size = ninode->u.isofs_i.i_section_size;
 914                                nextino   = ninode->u.isofs_i.i_next_section_ino;
 915                                iput(ninode);
 916                                
 917                                if (++section > 100) {
 918                                        printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n");
 919                                        printk("isofs_get_blocks: ino=%lu block=%ld firstext=%u sect_size=%u nextino=%lu\n",
 920                                               inode->i_ino, iblock, firstext, (unsigned) sect_size, nextino);
 921                                        goto abort;
 922                                }
 923                        }
 924                }
 925                
 926                if ( *bh_result ) {
 927                        (*bh_result)->b_dev      = inode->i_dev;
 928                        (*bh_result)->b_blocknr  = firstext + b_off - offset;
 929                        (*bh_result)->b_state   |= (1UL << BH_Mapped);
 930                } else {
 931                        *bh_result = sb_getblk(inode->i_sb, firstext+b_off-offset);
 932                        if ( !*bh_result )
 933                                goto abort;
 934                }
 935                bh_result++;    /* Next buffer head */
 936                b_off++;        /* Next buffer offset */
 937                nblocks--;
 938                rv++;
 939        }
 940
 941
 942abort:
 943        unlock_kernel();
 944        return rv;
 945}
 946
 947/*
 948 * Used by the standard interfaces.
 949 */
 950static int isofs_get_block(struct inode *inode, long iblock,
 951                    struct buffer_head *bh_result, int create)
 952{
 953        if ( create ) {
 954                printk("isofs_get_block: Kernel tries to allocate a block\n");
 955                return -EROFS;
 956        }
 957
 958        return isofs_get_blocks(inode, iblock, &bh_result, 1) ? 0 : -EIO;
 959}
 960
 961static int isofs_bmap(struct inode *inode, int block)
 962{
 963        struct buffer_head dummy;
 964        int error;
 965
 966        dummy.b_state = 0;
 967        dummy.b_blocknr = -1000;
 968        error = isofs_get_block(inode, block, &dummy, 0);
 969        if (!error)
 970                return dummy.b_blocknr;
 971        return 0;
 972}
 973
 974struct buffer_head *isofs_bread(struct inode *inode, unsigned int block)
 975{
 976        unsigned int blknr = isofs_bmap(inode, block);
 977        if (!blknr)
 978                return NULL;
 979        return sb_bread(inode->i_sb, blknr);
 980}
 981
 982static int isofs_readpage(struct file *file, struct page *page)
 983{
 984        return block_read_full_page(page,isofs_get_block);
 985}
 986
 987static int _isofs_bmap(struct address_space *mapping, long block)
 988{
 989        return generic_block_bmap(mapping,block,isofs_get_block);
 990}
 991
 992static struct address_space_operations isofs_aops = {
 993        readpage: isofs_readpage,
 994        sync_page: block_sync_page,
 995        bmap: _isofs_bmap
 996};
 997
 998static inline void test_and_set_uid(uid_t *p, uid_t value)
 999{
1000        if(value) {
1001                *p = value;
1002        }
1003}
1004
1005static inline void test_and_set_gid(gid_t *p, gid_t value)
1006{
1007        if(value) {
1008                *p = value;
1009        }
1010}
1011
1012static int isofs_read_level3_size(struct inode * inode)
1013{
1014        unsigned long f_pos = inode->i_ino;
1015        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
1016        int high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
1017        struct buffer_head * bh = NULL;
1018        unsigned long block, offset;
1019        int i = 0;
1020        int more_entries = 0;
1021        struct iso_directory_record * tmpde = NULL;
1022
1023        inode->i_size = 0;
1024        inode->u.isofs_i.i_next_section_ino = 0;
1025
1026        block = f_pos >> ISOFS_BUFFER_BITS(inode);
1027        offset = f_pos & (bufsize-1);
1028
1029        do {
1030                struct iso_directory_record * de;
1031                unsigned int de_len;
1032
1033                if (!bh) {
1034                        bh = sb_bread(inode->i_sb, block);
1035                        if (!bh)
1036                                goto out_noread;
1037                }
1038                de = (struct iso_directory_record *) (bh->b_data + offset);
1039                de_len = *(unsigned char *) de;
1040
1041                if (de_len == 0) {
1042                        brelse(bh);
1043                        bh = NULL;
1044                        f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
1045                        block = f_pos >> ISOFS_BUFFER_BITS(inode);
1046                        offset = 0;
1047                        continue;
1048                }
1049
1050                offset += de_len;
1051
1052                /* Make sure we have a full directory entry */
1053                if (offset >= bufsize) {
1054                        int slop = bufsize - offset + de_len;
1055                        if (!tmpde) {
1056                                tmpde = kmalloc(256, GFP_KERNEL);
1057                                if (!tmpde)
1058                                        goto out_nomem;
1059                        }
1060                        memcpy(tmpde, de, slop);
1061                        offset &= bufsize - 1;
1062                        block++;
1063                        brelse(bh);
1064                        bh = NULL;
1065                        if (offset) {
1066                                bh = sb_bread(inode->i_sb, block);
1067                                if (!bh)
1068                                        goto out_noread;
1069                                memcpy((void *) tmpde + slop, bh->b_data, offset);
1070                        }
1071                        de = tmpde;
1072                }
1073
1074                inode->i_size += isonum_733(de->size);
1075                if (i == 1)
1076                        inode->u.isofs_i.i_next_section_ino = f_pos;
1077
1078                more_entries = de->flags[-high_sierra] & 0x80;
1079
1080                f_pos += de_len;
1081                i++;
1082                if(i > 100)
1083                        goto out_toomany;
1084        } while(more_entries);
1085out:
1086        if (tmpde)
1087                kfree(tmpde);
1088        if (bh)
1089                brelse(bh);
1090        return 0;
1091
1092out_nomem:
1093        if (bh)
1094                brelse(bh);
1095        return -ENOMEM;
1096
1097out_noread:
1098        printk(KERN_INFO "ISOFS: unable to read i-node block %lu\n", block);
1099        if (tmpde)
1100                kfree(tmpde);
1101        return -EIO;
1102
1103out_toomany:
1104        printk(KERN_INFO "isofs_read_level3_size: "
1105                "More than 100 file sections ?!?, aborting...\n"
1106                "isofs_read_level3_size: inode=%lu ino=%lu\n",
1107                inode->i_ino, f_pos);
1108        goto out;
1109}
1110
1111static void isofs_read_inode(struct inode * inode)
1112{
1113        struct super_block *sb = inode->i_sb;
1114        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
1115        int block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);
1116        int high_sierra = sb->u.isofs_sb.s_high_sierra;
1117        struct buffer_head * bh = NULL;
1118        struct iso_directory_record * de;
1119        struct iso_directory_record * tmpde = NULL;
1120        unsigned int de_len;
1121        unsigned long offset;
1122        int volume_seq_no, i;
1123
1124        bh = sb_bread(inode->i_sb, block);
1125        if (!bh)
1126                goto out_badread;
1127
1128        offset = (inode->i_ino & (bufsize - 1));
1129        de = (struct iso_directory_record *) (bh->b_data + offset);
1130        de_len = *(unsigned char *) de;
1131
1132        if (offset + de_len > bufsize) {
1133                int frag1 = bufsize - offset;
1134
1135                tmpde = kmalloc(de_len, GFP_KERNEL);
1136                if (tmpde == NULL) {
1137                        printk(KERN_INFO "isofs_read_inode: out of memory\n");
1138                        goto fail;
1139                }
1140                memcpy(tmpde, bh->b_data + offset, frag1);
1141                brelse(bh);
1142                bh = sb_bread(inode->i_sb, ++block);
1143                if (!bh)
1144                        goto out_badread;
1145                memcpy((char *)tmpde+frag1, bh->b_data, de_len - frag1);
1146                de = tmpde;
1147        }
1148
1149        /* Assume it is a normal-format file unless told otherwise */
1150        inode->u.isofs_i.i_file_format = isofs_file_normal;
1151
1152        if (de->flags[-high_sierra] & 2) {
1153                inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
1154                inode->i_nlink = 1; /* Set to 1.  We know there are 2, but
1155                                       the find utility tries to optimize
1156                                       if it is 2, and it screws up.  It is
1157                                       easier to give 1 which tells find to
1158                                       do it the hard way. */
1159        } else {
1160                /* Everybody gets to read the file. */
1161                inode->i_mode = inode->i_sb->u.isofs_sb.s_mode;
1162                inode->i_nlink = 1;
1163                inode->i_mode |= S_IFREG;
1164                /* If there are no periods in the name,
1165                 * then set the execute permission bit
1166                 */
1167                for(i=0; i< de->name_len[0]; i++)
1168                        if(de->name[i]=='.' || de->name[i]==';')
1169                                break;
1170                if(i == de->name_len[0] || de->name[i] == ';')
1171                        inode->i_mode |= S_IXUGO; /* execute permission */
1172        }
1173        inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
1174        inode->i_gid = inode->i_sb->u.isofs_sb.s_gid;
1175        inode->i_blocks = inode->i_blksize = 0;
1176
1177
1178        inode->u.isofs_i.i_section_size = isonum_733 (de->size);
1179        if(de->flags[-high_sierra] & 0x80) {
1180                if(isofs_read_level3_size(inode)) goto fail;
1181        } else {
1182                inode->i_size = isonum_733 (de->size);
1183        }
1184
1185        /*
1186         * Some dipshit decided to store some other bit of information
1187         * in the high byte of the file length.  Truncate in case
1188         * this CDROM was mounted with the cruft option.
1189         */
1190
1191        if (inode->i_sb->u.isofs_sb.s_cruft == 'y')
1192                inode->i_size &= 0x00ffffff;
1193
1194        if (de->interleave[0]) {
1195                printk("Interleaved files not (yet) supported.\n");
1196                inode->i_size = 0;
1197        }
1198
1199        /* I have no idea what file_unit_size is used for, so
1200           we will flag it for now */
1201        if (de->file_unit_size[0] != 0) {
1202                printk("File unit size != 0 for ISO file (%ld).\n",
1203                       inode->i_ino);
1204        }
1205
1206        /* I have no idea what other flag bits are used for, so
1207           we will flag it for now */
1208#ifdef DEBUG
1209        if((de->flags[-high_sierra] & ~2)!= 0){
1210                printk("Unusual flag settings for ISO file (%ld %x).\n",
1211                       inode->i_ino, de->flags[-high_sierra]);
1212        }
1213#endif
1214
1215        inode->i_mtime = inode->i_atime = inode->i_ctime =
1216                iso_date(de->date, high_sierra);
1217
1218        inode->u.isofs_i.i_first_extent = (isonum_733 (de->extent) +
1219                                           isonum_711 (de->ext_attr_length));
1220
1221        /* Set the number of blocks for stat() - should be done before RR */
1222        inode->i_blksize = PAGE_CACHE_SIZE; /* For stat() only */
1223        inode->i_blocks  = (inode->i_size + 511) >> 9;
1224
1225        /*
1226         * Now test for possible Rock Ridge extensions which will override
1227         * some of these numbers in the inode structure.
1228         */
1229
1230        if (!high_sierra) {
1231                parse_rock_ridge_inode(de, inode);
1232                /* if we want uid/gid set, override the rock ridge setting */
1233                test_and_set_uid(&inode->i_uid, inode->i_sb->u.isofs_sb.s_uid);
1234                test_and_set_gid(&inode->i_gid, inode->i_sb->u.isofs_sb.s_gid);
1235        }
1236
1237        /* get the volume sequence number */
1238        volume_seq_no = isonum_723 (de->volume_sequence_number) ;
1239
1240        /* Install the inode operations vector */
1241        if (S_ISREG(inode->i_mode)) {
1242                inode->i_fop = &generic_ro_fops;
1243                switch ( inode->u.isofs_i.i_file_format ) {
1244#ifdef CONFIG_ZISOFS
1245                case isofs_file_compressed:
1246                        inode->i_data.a_ops = &zisofs_aops;
1247                        break;
1248#endif
1249                default:
1250                        inode->i_data.a_ops = &isofs_aops;
1251                        break;
1252                }
1253        } else if (S_ISDIR(inode->i_mode)) {
1254                inode->i_op = &isofs_dir_inode_operations;
1255                inode->i_fop = &isofs_dir_operations;
1256        } else if (S_ISLNK(inode->i_mode)) {
1257                inode->i_op = &page_symlink_inode_operations;
1258                inode->i_data.a_ops = &isofs_symlink_aops;
1259        } else
1260                /* XXX - parse_rock_ridge_inode() had already set i_rdev. */
1261                init_special_inode(inode, inode->i_mode,
1262                                   kdev_t_to_nr(inode->i_rdev));
1263 out:
1264        if (tmpde)
1265                kfree(tmpde);
1266        if (bh)
1267                brelse(bh);
1268        return;
1269
1270 out_badread:
1271        printk(KERN_WARNING "ISOFS: unable to read i-node block\n");
1272 fail:
1273        make_bad_inode(inode);
1274        goto out;
1275}
1276
1277#ifdef LEAK_CHECK
1278#undef malloc
1279#undef free_s
1280#undef sb_bread
1281#undef brelse
1282
1283void * leak_check_malloc(unsigned int size){
1284  void * tmp;
1285  check_malloc++;
1286  tmp = kmalloc(size, GFP_KERNEL);
1287  return tmp;
1288}
1289
1290void leak_check_free_s(void * obj, int size){
1291  check_malloc--;
1292  return kfree(obj);
1293}
1294
1295struct buffer_head * leak_check_bread(struct super_block *sb, int block){
1296  check_bread++;
1297  return sb_bread(sb, block);
1298}
1299
1300void leak_check_brelse(struct buffer_head * bh){
1301  check_bread--;
1302  return brelse(bh);
1303}
1304
1305#endif
1306
1307static DECLARE_FSTYPE_DEV(iso9660_fs_type, "iso9660", isofs_read_super);
1308
1309static int __init init_iso9660_fs(void)
1310{
1311#ifdef CONFIG_ZISOFS
1312        int err;
1313
1314        err = zisofs_init();
1315        if ( err )
1316                return err;
1317#endif
1318        return register_filesystem(&iso9660_fs_type);
1319}
1320
1321static void __exit exit_iso9660_fs(void)
1322{
1323        unregister_filesystem(&iso9660_fs_type);
1324#ifdef CONFIG_ZISOFS
1325        zisofs_cleanup();
1326#endif
1327}
1328
1329EXPORT_NO_SYMBOLS;
1330
1331module_init(init_iso9660_fs)
1332module_exit(exit_iso9660_fs)
1333MODULE_LICENSE("GPL");
1334
1335
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.