CTC++ Coverage Report - Execution Profile    #938/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: fs/isofs/inode.c
Instrumentation mode: function-decision-multicondition
TER: 2 % ( 8/486)

Start/ End/    
True False - Line Source

  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  *   2004  Paul Serice - Inode Support pushed out from 4GB to 128GB
  11  *   2004  Paul Serice - NFS Export Operations
  12  */
  13 
  14 #include <linux/config.h>
  15 #include <linux/init.h>
  16 #include <linux/module.h>
  17 
  18 #include <linux/slab.h>
  19 #include <linux/nls.h>
  20 #include <linux/ctype.h>
  21 #include <linux/smp_lock.h>
  22 #include <linux/statfs.h>
  23 #include <linux/cdrom.h>
  24 #include <linux/parser.h>
  25 
  26 #include "isofs.h"
  27 #include "zisofs.h"
  28 
  29 #define BEQUIET
  30 
  31 static int isofs_hashi(struct dentry *parent, struct qstr *qstr);
  32 static int isofs_hash(struct dentry *parent, struct qstr *qstr);
  33 static int isofs_dentry_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
  34 static int isofs_dentry_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
  35 
  36 #ifdef CONFIG_JOLIET
  37 static int isofs_hashi_ms(struct dentry *parent, struct qstr *qstr);
  38 static int isofs_hash_ms(struct dentry *parent, struct qstr *qstr);
  39 static int isofs_dentry_cmpi_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);
  40 static int isofs_dentry_cmp_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);
  41 #endif
  42 
 
- 43 static void isofs_put_super(struct super_block *sb)
  44 {
  45    struct isofs_sb_info *sbi = ISOFS_SB(sb);
  46 #ifdef CONFIG_JOLIET
- 47    if (sbi->s_nls_iocharset) {
  48       unload_nls(sbi->s_nls_iocharset);
  49       sbi->s_nls_iocharset = NULL;
  50    }
  51 #endif
  52 
  53    kfree(sbi);
  54    sb->s_fs_info = NULL;
 - 55    return;
  56 }
  57 
  58 static void isofs_read_inode(struct inode *);
  59 static int isofs_statfs (struct super_block *, struct kstatfs *);
  60 
  61 static kmem_cache_t *isofs_inode_cachep;
  62 
 
- 63 static struct inode *isofs_alloc_inode(struct super_block *sb)
  64 {
  65    struct iso_inode_info *ei;
  66    ei = kmem_cache_alloc(isofs_inode_cachep, SLAB_KERNEL);
- 67    if (!ei)
 - 68       return NULL;
 - 69    return &ei->vfs_inode;
  70 }
  71 
 
- 72 static void isofs_destroy_inode(struct inode *inode)
  73 {
  74    kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode));
  75 }
  76 
 
- 77 static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
  78 {
  79    struct iso_inode_info *ei = foo;
  80 
  81    if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
- 82        SLAB_CTOR_CONSTRUCTOR)
  83       inode_init_once(&ei->vfs_inode);
  84 }
  85  
 
  86 static int init_inodecache(void)
  87 {
  88    isofs_inode_cachep = kmem_cache_create("isofs_inode_cache",
  89                     sizeof(struct iso_inode_info),
  90                     0, SLAB_RECLAIM_ACCOUNT,
  91                     init_once, NULL);
- 92    if (isofs_inode_cachep == NULL)
 - 93       return -ENOMEM;
   94    return 0;
  95 }
  96 
 
- 97 static void destroy_inodecache(void)
  98 {
- 99    if (kmem_cache_destroy(isofs_inode_cachep))
  100       printk(KERN_INFO "iso_inode_cache: not all structures were "
  101                "freed\n");
  102 }
  103 
 
- 104 static int isofs_remount(struct super_block *sb, int *flags, char *data)
  105 {
  106    /* we probably want a lot more here */
  107    *flags |= MS_RDONLY;
 - 108    return 0;
  109 }
  110 
  111 static struct super_operations isofs_sops = {
  112    .alloc_inode   = isofs_alloc_inode,
  113    .destroy_inode   = isofs_destroy_inode,
  114    .read_inode   = isofs_read_inode,
  115    .put_super   = isofs_put_super,
  116    .statfs      = isofs_statfs,
  117    .remount_fs   = isofs_remount,
  118 };
  119 
  120 
  121 static struct dentry_operations isofs_dentry_ops[] = {
  122    {
  123       .d_hash      = isofs_hash,
  124       .d_compare   = isofs_dentry_cmp,
  125    },
  126    {
  127       .d_hash      = isofs_hashi,
  128       .d_compare   = isofs_dentry_cmpi,
  129    },
  130 #ifdef CONFIG_JOLIET
  131    {
  132       .d_hash      = isofs_hash_ms,
  133       .d_compare   = isofs_dentry_cmp_ms,
  134    },
  135    {
  136       .d_hash      = isofs_hashi_ms,
  137       .d_compare   = isofs_dentry_cmpi_ms,
  138    },
  139 #endif
  140 };
  141 
  142 struct iso9660_options{
  143    char map;
  144    char rock;
  145    char joliet;
  146    char cruft;
  147    char hide;
  148    char showassoc;
  149    char nocompress;
  150    unsigned char check;
  151    unsigned int blocksize;
  152    mode_t mode;
  153    gid_t gid;
  154    uid_t uid;
  155    char *iocharset;
  156    unsigned char utf8;
  157         /* LVE */
  158         s32 session;
  159         s32 sbsector;
  160 };
  161 
  162 /*
  163  * Compute the hash for the isofs name corresponding to the dentry.
  164  */
  165 static int
 
- 166 isofs_hash_common(struct dentry *dentry, struct qstr *qstr, int ms)
  167 {
  168    const char *name;
  169    int len;
  170 
  171    len = qstr->len;
  172    name = qstr->name;
- 173    if (ms) {
- 174       while (len && name[len-1] == '.')
 - 174     T && T
 - 174     T && F
 - 174     F && _
  175          len--;
  176    }
  177 
  178    qstr->hash = full_name_hash(name, len);
  179 
 - 180    return 0;
  181 }
  182 
  183 /*
  184  * Compute the hash for the isofs name corresponding to the dentry.
  185  */
  186 static int
 
- 187 isofs_hashi_common(struct dentry *dentry, struct qstr *qstr, int ms)
  188 {
  189    const char *name;
  190    int len;
  191    char c;
  192    unsigned long hash;
  193 
  194    len = qstr->len;
  195    name = qstr->name;
- 196    if (ms) {
- 197       while (len && name[len-1] == '.')
 - 197     T && T
 - 197     T && F
 - 197     F && _
  198          len--;
  199    }
  200 
  201    hash = init_name_hash();
- 202    while (len--) {
  203       c = tolower(*name++);
  204       hash = partial_name_hash(tolower(c), hash);
  205    }
  206    qstr->hash = end_name_hash(hash);
  207 
 - 208    return 0;
  209 }
  210 
  211 /*
  212  * Case insensitive compare of two isofs names.
  213  */
 
- 214 static int isofs_dentry_cmpi_common(struct dentry *dentry, struct qstr *a,
  215             struct qstr *b, int ms)
  216 {
  217    int alen, blen;
  218 
  219    /* A filename cannot end in '.' or we treat it like it has none */
  220    alen = a->len;
  221    blen = b->len;
- 222    if (ms) {
- 223       while (alen && a->name[alen-1] == '.')
 - 223     T && T
 - 223     T && F
 - 223     F && _
  224          alen--;
- 225       while (blen && b->name[blen-1] == '.')
 - 225     T && T
 - 225     T && F
 - 225     F && _
  226          blen--;
  227    }
- 228    if (alen == blen) {
- 229       if (strnicmp(a->name, b->name, alen) == 0)
 - 230          return 0;
  231    }
 - 232    return 1;
  233 }
  234 
  235 /*
  236  * Case sensitive compare of two isofs names.
  237  */
 
- 238 static int isofs_dentry_cmp_common(struct dentry *dentry, struct qstr *a,
  239                struct qstr *b, int ms)
  240 {
  241    int alen, blen;
  242 
  243    /* A filename cannot end in '.' or we treat it like it has none */
  244    alen = a->len;
  245    blen = b->len;
- 246    if (ms) {
- 247       while (alen && a->name[alen-1] == '.')
 - 247     T && T
 - 247     T && F
 - 247     F && _
  248          alen--;
- 249       while (blen && b->name[blen-1] == '.')
 - 249     T && T
 - 249     T && F
 - 249     F && _
  250          blen--;
  251    }
- 252    if (alen == blen) {
- 253       if (strncmp(a->name, b->name, alen) == 0)
 - 254          return 0;
  255    }
 - 256    return 1;
  257 }
  258 
  259 static int
 
- 260 isofs_hash(struct dentry *dentry, struct qstr *qstr)
  261 {
 - 262    return isofs_hash_common(dentry, qstr, 0);
  263 }
  264 
  265 static int
 
- 266 isofs_hashi(struct dentry *dentry, struct qstr *qstr)
  267 {
 - 268    return isofs_hashi_common(dentry, qstr, 0);
  269 }
  270 
  271 static int
 
- 272 isofs_dentry_cmp(struct dentry *dentry,struct qstr *a,struct qstr *b)
  273 {
 - 274    return isofs_dentry_cmp_common(dentry, a, b, 0);
  275 }
  276 
  277 static int
 
- 278 isofs_dentry_cmpi(struct dentry *dentry,struct qstr *a,struct qstr *b)
  279 {
 - 280    return isofs_dentry_cmpi_common(dentry, a, b, 0);
  281 }
  282 
  283 #ifdef CONFIG_JOLIET
  284 static int
 
- 285 isofs_hash_ms(struct dentry *dentry, struct qstr *qstr)
  286 {
 - 287    return isofs_hash_common(dentry, qstr, 1);
  288 }
  289 
  290 static int
 
- 291 isofs_hashi_ms(struct dentry *dentry, struct qstr *qstr)
  292 {
 - 293    return isofs_hashi_common(dentry, qstr, 1);
  294 }
  295 
  296 static int
 
- 297 isofs_dentry_cmp_ms(struct dentry *dentry,struct qstr *a,struct qstr *b)
  298 {
 - 299    return isofs_dentry_cmp_common(dentry, a, b, 1);
  300 }
  301 
  302 static int
 
- 303 isofs_dentry_cmpi_ms(struct dentry *dentry,struct qstr *a,struct qstr *b)
  304 {
 - 305    return isofs_dentry_cmpi_common(dentry, a, b, 1);
  306 }
  307 #endif
  308 
  309 enum {
  310    Opt_block, Opt_check_r, Opt_check_s, Opt_cruft, Opt_gid, Opt_ignore,
  311    Opt_iocharset, Opt_map_a, Opt_map_n, Opt_map_o, Opt_mode, Opt_nojoliet,
  312    Opt_norock, Opt_sb, Opt_session, Opt_uid, Opt_unhide, Opt_utf8, Opt_err,
  313    Opt_nocompress, Opt_hide, Opt_showassoc,
  314 };
  315 
  316 static match_table_t tokens = {
  317    {Opt_norock, "norock"},
  318    {Opt_nojoliet, "nojoliet"},
  319    {Opt_unhide, "unhide"},
  320    {Opt_hide, "hide"},
  321    {Opt_showassoc, "showassoc"},
  322    {Opt_cruft, "cruft"},
  323    {Opt_utf8, "utf8"},
  324    {Opt_iocharset, "iocharset=%s"},
  325    {Opt_map_a, "map=acorn"},
  326    {Opt_map_a, "map=a"},
  327    {Opt_map_n, "map=normal"},
  328    {Opt_map_n, "map=n"},
  329    {Opt_map_o, "map=off"},
  330    {Opt_map_o, "map=o"},
  331    {Opt_session, "session=%u"},
  332    {Opt_sb, "sbsector=%u"},
  333    {Opt_check_r, "check=relaxed"},
  334    {Opt_check_r, "check=r"},
  335    {Opt_check_s, "check=strict"},
  336    {Opt_check_s, "check=s"},
  337    {Opt_uid, "uid=%u"},
  338    {Opt_gid, "gid=%u"},
  339    {Opt_mode, "mode=%u"},
  340    {Opt_block, "block=%u"},
  341    {Opt_ignore, "conv=binary"},
  342    {Opt_ignore, "conv=b"},
  343    {Opt_ignore, "conv=text"},
  344    {Opt_ignore, "conv=t"},
  345    {Opt_ignore, "conv=mtext"},
  346    {Opt_ignore, "conv=m"},
  347    {Opt_ignore, "conv=auto"},
  348    {Opt_ignore, "conv=a"},
  349    {Opt_nocompress, "nocompress"},
  350    {Opt_err, NULL}
  351 };
  352 
 
- 353 static int parse_options(char *options, struct iso9660_options *popt)
  354 {
  355    char *p;
  356    int option;
  357 
  358    popt->map = 'n';
  359    popt->rock = 'y';
  360    popt->joliet = 'y';
  361    popt->cruft = 'n';
  362    popt->hide = 'n';
  363    popt->showassoc = 'n';
  364    popt->check = 'u';      /* unset */
  365    popt->nocompress = 0;
  366    popt->blocksize = 1024;
  367    popt->mode = S_IRUGO | S_IXUGO; /* r-x for all.  The disc could
  368                   be shared with DOS machines so
  369                   virtually anything could be
  370                   a valid executable. */
  371    popt->gid = 0;
  372    popt->uid = 0;
  373    popt->iocharset = NULL;
  374    popt->utf8 = 0;
  375    popt->session=-1;
  376    popt->sbsector=-1;
- 377    if (!options)
 - 378       return 1;
  379 
- 380    while ((p = strsep(&options, ",")) != NULL) {
  381       int token;
  382       substring_t args[MAX_OPT_ARGS];
  383       unsigned n;
  384 
- 385       if (!*p)
 - 386          continue;
  387 
  388       token = match_token(p, tokens, args);
    389       switch (token) {
 - 390       case Opt_norock:
  391          popt->rock = 'n';
 - 392          break;
 - 393       case Opt_nojoliet:
  394          popt->joliet = 'n';
 - 395          break;
 - 396       case Opt_hide:
  397          popt->hide = 'y';
 - 398          break;
 - 399       case Opt_unhide:
 - 400       case Opt_showassoc:
  401          popt->showassoc = 'y';
 - 402          break;
 - 403       case Opt_cruft:
  404          popt->cruft = 'y';
 - 405          break;
 - 406       case Opt_utf8:
  407          popt->utf8 = 1;
 - 408          break;
  409 #ifdef CONFIG_JOLIET
 - 410       case Opt_iocharset:
  411          popt->iocharset = match_strdup(&args[0]);
 - 412          break;
  413 #endif
 - 414       case Opt_map_a:
  415          popt->map = 'a';
 - 416          break;
 - 417       case Opt_map_o:
  418          popt->map = 'o';
 - 419          break;
 - 420       case Opt_map_n:
  421          popt->map = 'n';
 - 422          break;
 - 423       case Opt_session:
- 424          if (match_int(&args[0], &option))
 - 425             return 0;
  426          n = option;
- 427          if (n > 99)
 - 428             return 0;
  429          popt->session = n + 1;
 - 430          break;
 - 431       case Opt_sb:
- 432          if (match_int(&args[0], &option))
 - 433             return 0;
  434          popt->sbsector = option;
 - 435          break;
 - 436       case Opt_check_r:
  437          popt->check = 'r';
 - 438          break;
 - 439       case Opt_check_s:
  440          popt->check = 's';
 - 441          break;
 - 442       case Opt_ignore:
 - 443          break;
 - 444       case Opt_uid:
- 445          if (match_int(&args[0], &option))
 - 446             return 0;
  447          popt->uid = option;
 - 448          break;
 - 449       case Opt_gid:
- 450          if (match_int(&args[0], &option))
 - 451             return 0;
  452          popt->gid = option;
 - 453          break;
 - 454       case Opt_mode:
- 455          if (match_int(&args[0], &option))
 - 456             return 0;
  457          popt->mode = option;
 - 458          break;
 - 459       case Opt_block:
- 460          if (match_int(&args[0], &option))
 - 461             return 0;
  462          n = option;
- 463          if (n != 512 && n != 1024 && n != 2048)
 - 463       T && T && T
 - 463       T && T && F
 - 463       T && F && _
 - 463       F && _ && _
 - 464             return 0;
  465          popt->blocksize = n;
 - 466          break;
 - 467       case Opt_nocompress:
  468          popt->nocompress = 1;
 - 469          break;
 - 470       default:
 - 471          return 0;
  472       }
  473    }
 - 474    return 1;
  475 }
  476 
  477 /*
  478  * look if the driver can tell the multi session redirection value
  479  *
  480  * don't change this if you don't know what you do, please!
  481  * Multisession is legal only with XA disks.
  482  * A non-XA disk with more than one volume descriptor may do it right, but
  483  * usually is written in a nowhere standardized "multi-partition" manner.
  484  * Multisession uses absolute addressing (solely the first frame of the whole
  485  * track is #0), multi-partition uses relative addressing (each first frame of
  486  * each track is #0), and a track is not a session.
  487  *
  488  * A broken CDwriter software or drive firmware does not set new standards,
  489  * at least not if conflicting with the existing ones.
  490  *
  491  * emoenke@gwdg.de
  492  */
  493 #define WE_OBEY_THE_WRITTEN_STANDARDS 1
  494 
 
- 495 static unsigned int isofs_get_last_session(struct super_block *sb, s32 session)
  496 {
  497    struct cdrom_multisession ms_info;
  498    unsigned int vol_desc_start;
  499    struct block_device *bdev = sb->s_bdev;
  500    int i;
  501 
  502    vol_desc_start=0;
  503    ms_info.addr_format=CDROM_LBA;
- 504    if(session >= 0 && session <= 99) {
 - 504   T && T
 - 504   T && F
 - 504   F && _
  505       struct cdrom_tocentry Te;
  506       Te.cdte_track=session;