LCOV - code coverage report
Current view: top level - lkbce/fs/isofs - namei.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 114 114 100.0 %
Date: 2017-01-25 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :  *  linux/fs/isofs/namei.c
       3             :  *
       4             :  *  (C) 1992  Eric Youngdale Modified for ISO 9660 filesystem.
       5             :  *
       6             :  *  (C) 1991  Linus Torvalds - minix filesystem
       7             :  */
       8             : 
       9             : #include <linux/smp_lock.h>
      10             : #include "isofs.h"
      11             : 
      12             : /*
      13             :  * ok, we cannot use strncmp, as the name is not in our data space.
      14             :  * Thus we'll have to use isofs_match. No big problem. Match also makes
      15             :  * some sanity tests.
      16             :  */
      17             : static int
      18             : isofs_cmp(struct dentry *dentry, const char *compare, int dlen)
      19             : {
      20           8 :         struct qstr qstr;
      21           8 : 
      22          16 :         if (!compare)
      23           8 :                 return 1;
      24             : 
      25             :         /* check special "." and ".." files */
      26          16 :         if (dlen == 1) {
      27             :                 /* "." */
      28          16 :                 if (compare[0] == 0) {
      29          16 :                         if (!dentry->d_name.len)
      30           8 :                                 return 0;
      31           8 :                         compare = ".";
      32          16 :                 } else if (compare[0] == 1) {
      33           8 :                         compare = "..";
      34           8 :                         dlen = 2;
      35             :                 }
      36             :         }
      37             : 
      38           8 :         qstr.name = compare;
      39           8 :         qstr.len = dlen;
      40          48 :         return dentry->d_op->d_compare(dentry, &dentry->d_name, &qstr);
      41             : }
      42             : 
      43             : /*
      44             :  *      isofs_find_entry()
      45             :  *
      46             :  * finds an entry in the specified directory with the wanted name. It
      47             :  * returns the inode number of the found entry, or 0 on error.
      48             :  */
      49             : static unsigned long
      50             : isofs_find_entry(struct inode *dir, struct dentry *dentry,
      51             :         unsigned long *block_rv, unsigned long *offset_rv,
      52             :         char *tmpname, struct iso_directory_record *tmpde)
      53             : {
      54           2 :         unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);
      55           2 :         unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
      56           1 :         unsigned long block, f_pos, offset, block_saved, offset_saved;
      57           2 :         struct buffer_head *bh = NULL;
      58           4 :         struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
      59           1 : 
      60           5 :         if (!ISOFS_I(dir)->i_first_extent)
      61           2 :                 return 0;
      62           1 : 
      63           2 :         f_pos = 0;
      64           2 :         offset = 0;
      65           2 :         block = 0;
      66           1 : 
      67           5 :         while (f_pos < dir->i_size) {
      68           2 :                 struct iso_directory_record *de;
      69           2 :                 int de_len, match, i, dlen;
      70           1 :                 char *dpnt;
      71           1 : 
      72           3 :                 if (!bh) {
      73           3 :                         bh = isofs_bread(dir, block);
      74           2 :                         if (!bh)
      75           1 :                                 return 0;
      76             :                 }
      77             : 
      78           2 :                 de = (struct iso_directory_record *) (bh->b_data + offset);
      79             : 
      80           2 :                 de_len = *(unsigned char *) de;
      81           4 :                 if (!de_len) {
      82           4 :                         brelse(bh);
      83           1 :                         bh = NULL;
      84           1 :                         f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
      85           1 :                         block = f_pos >> bufbits;
      86           1 :                         offset = 0;
      87           1 :                         continue;
      88             :                 }
      89             : 
      90           2 :                 block_saved = bh->b_blocknr;
      91           2 :                 offset_saved = offset;
      92           2 :                 offset += de_len;
      93           2 :                 f_pos += de_len;
      94             : 
      95             :                 /* Make sure we have a full directory entry */
      96           4 :                 if (offset >= bufsize) {
      97           2 :                         int slop = bufsize - offset + de_len;
      98           2 :                         memcpy(tmpde, de, slop);
      99           2 :                         offset &= bufsize - 1;
     100           2 :                         block++;
     101           4 :                         brelse(bh);
     102           1 :                         bh = NULL;
     103           2 :                         if (offset) {
     104           3 :                                 bh = isofs_bread(dir, block);
     105           2 :                                 if (!bh)
     106           1 :                                         return 0;
     107           2 :                                 memcpy((void *) tmpde + slop, bh->b_data, offset);
     108             :                         }
     109           2 :                         de = tmpde;
     110             :                 }
     111             : 
     112           4 :                 dlen = de->name_len[0];
     113           4 :                 dpnt = de->name;
     114             :                 /* Basic sanity check, whether name doesn't exceed dir entry */
     115           8 :                 if (de_len < dlen + sizeof(struct iso_directory_record)) {
     116           4 :                         printk(KERN_NOTICE "iso9660: Corrupted directory entry"
     117             :                                " in block %lu of inode %lu\n", block,
     118             :                                dir->i_ino);
     119           4 :                         return 0;
     120             :                 }
     121             : 
     122          35 :                 if (sbi->s_rock &&
     123             :                     ((i = get_rock_ridge_filename(de, tmpname, dir)))) {
     124           1 :                         dlen = i;       /* possibly -1 */
     125           5 :                         dpnt = tmpname;
     126             : #ifdef CONFIG_JOLIET
     127          15 :                 } else if (sbi->s_joliet_level) {
     128          10 :                         dlen = get_joliet_filename(de, tmpname, dir);
     129           1 :                         dpnt = tmpname;
     130             : #endif
     131          15 :                 } else if (sbi->s_mapping == 'a') {
     132          10 :                         dlen = get_acorn_filename(de, tmpname, dir);
     133           1 :                         dpnt = tmpname;
     134          15 :                 } else if (sbi->s_mapping == 'n') {
     135          10 :                         dlen = isofs_name_translate(de, tmpname, dir);
     136           1 :                         dpnt = tmpname;
     137             :                 }
     138             : 
     139             :                 /*
     140             :                  * Skip hidden or associated files unless hide or showassoc,
     141             :                  * respectively, is set
     142             :                  */
     143           8 :                 match = 0;
     144          96 :                 if (dlen > 0 &&
     145             :                         (!sbi->s_hide ||
     146             :                                 (!(de->flags[-sbi->s_high_sierra] & 1))) &&
     147             :                         (sbi->s_showassoc ||
     148             :                                 (!(de->flags[-sbi->s_high_sierra] & 4)))) {
     149          17 :                         match = (isofs_cmp(dentry, dpnt, dlen) == 0);
     150             :                 }
     151          18 :                 if (match) {
     152          27 :                         isofs_normalize_block_and_offset(de,
     153             :                                                          &block_saved,
     154             :                                                          &offset_saved);
     155           1 :                         *block_rv = block_saved;
     156           1 :                         *offset_rv = offset_saved;
     157           2 :                         brelse(bh);
     158           1 :                         return 1;
     159             :                 }
     160             :         }
     161           2 :         brelse(bh);
     162          10 :         return 0;
     163             : }
     164             : 
     165             : struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
     166             : {
     167           1 :         int found;
     168           2 :         unsigned long uninitialized_var(block);
     169           2 :         unsigned long uninitialized_var(offset);
     170           1 :         struct inode *inode;
     171           1 :         struct page *page;
     172           1 : 
     173           2 :         dentry->d_op = dir->i_sb->s_root->d_op;
     174           1 : 
     175           3 :         page = alloc_page(GFP_USER);
     176           3 :         if (!page)
     177           4 :                 return ERR_PTR(-ENOMEM);
     178           1 : 
     179           1 :         lock_kernel();
     180          13 :         found = isofs_find_entry(dir, dentry,
     181             :                                 &block, &offset,
     182             :                                 page_address(page),
     183             :                                 1024 + page_address(page));
     184           1 :         __free_page(page);
     185             : 
     186           1 :         inode = NULL;
     187           2 :         if (found) {
     188           6 :                 inode = isofs_iget(dir->i_sb, block, offset);
     189           4 :                 if (IS_ERR(inode)) {
     190           1 :                         unlock_kernel();
     191           3 :                         return ERR_CAST(inode);
     192             :                 }
     193             :         }
     194           2 :         unlock_kernel();
     195           4 :         return d_splice_alias(inode, dentry);
     196             : }

Generated by: LCOV version 1.10