LCOV - code coverage report
Current view: top level - fs/isofs - dir.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 0 136 0.0 %
Date: 2021-04-22 12:43:58 Functions: 0 4 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  *  linux/fs/isofs/dir.c
       4             :  *
       5             :  *  (C) 1992, 1993, 1994  Eric Youngdale Modified for ISO 9660 filesystem.
       6             :  *
       7             :  *  (C) 1991  Linus Torvalds - minix filesystem
       8             :  *
       9             :  *  Steve Beynon                       : Missing last directory entries fixed
      10             :  *  (stephen@askone.demon.co.uk)      : 21st June 1996
      11             :  *
      12             :  *  isofs directory handling functions
      13             :  */
      14             : #include <linux/gfp.h>
      15             : #include "isofs.h"
      16             : 
      17           0 : int isofs_name_translate(struct iso_directory_record *de, char *new, struct inode *inode)
      18             : {
      19           0 :         char * old = de->name;
      20           0 :         int len = de->name_len[0];
      21           0 :         int i;
      22             : 
      23           0 :         for (i = 0; i < len; i++) {
      24           0 :                 unsigned char c = old[i];
      25           0 :                 if (!c)
      26             :                         break;
      27             : 
      28           0 :                 if (c >= 'A' && c <= 'Z')
      29           0 :                         c |= 0x20;      /* lower case */
      30             : 
      31             :                 /* Drop trailing '.;1' (ISO 9660:1988 7.5.1 requires period) */
      32           0 :                 if (c == '.' && i == len - 3 && old[i + 1] == ';' && old[i + 2] == '1')
      33             :                         break;
      34             : 
      35             :                 /* Drop trailing ';1' */
      36           0 :                 if (c == ';' && i == len - 2 && old[i + 1] == '1')
      37             :                         break;
      38             : 
      39             :                 /* Convert remaining ';' to '.' */
      40             :                 /* Also '/' to '.' (broken Acorn-generated ISO9660 images) */
      41           0 :                 if (c == ';' || c == '/')
      42           0 :                         c = '.';
      43             : 
      44           0 :                 new[i] = c;
      45             :         }
      46           0 :         return i;
      47             : }
      48             : 
      49             : /* Acorn extensions written by Matthew Wilcox <willy@infradead.org> 1998 */
      50           0 : int get_acorn_filename(struct iso_directory_record *de,
      51             :                             char *retname, struct inode *inode)
      52             : {
      53           0 :         int std;
      54           0 :         unsigned char *chr;
      55           0 :         int retnamlen = isofs_name_translate(de, retname, inode);
      56             : 
      57           0 :         if (retnamlen == 0)
      58             :                 return 0;
      59           0 :         std = sizeof(struct iso_directory_record) + de->name_len[0];
      60           0 :         if (std & 1)
      61           0 :                 std++;
      62           0 :         if (de->length[0] - std != 32)
      63             :                 return retnamlen;
      64           0 :         chr = ((unsigned char *) de) + std;
      65           0 :         if (strncmp(chr, "ARCHIMEDES", 10))
      66             :                 return retnamlen;
      67           0 :         if ((*retname == '_') && ((chr[19] & 1) == 1))
      68           0 :                 *retname = '!';
      69           0 :         if (((de->flags[0] & 2) == 0) && (chr[13] == 0xff)
      70           0 :                 && ((chr[12] & 0xf0) == 0xf0)) {
      71           0 :                 retname[retnamlen] = ',';
      72           0 :                 sprintf(retname+retnamlen+1, "%3.3x",
      73           0 :                         ((chr[12] & 0xf) << 8) | chr[11]);
      74           0 :                 retnamlen += 4;
      75             :         }
      76             :         return retnamlen;
      77             : }
      78             : 
      79             : /*
      80             :  * This should _really_ be cleaned up some day..
      81             :  */
      82           0 : static int do_isofs_readdir(struct inode *inode, struct file *file,
      83             :                 struct dir_context *ctx,
      84             :                 char *tmpname, struct iso_directory_record *tmpde)
      85             : {
      86           0 :         unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
      87           0 :         unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
      88           0 :         unsigned long block, offset, block_saved, offset_saved;
      89           0 :         unsigned long inode_number = 0; /* Quiet GCC */
      90           0 :         struct buffer_head *bh = NULL;
      91           0 :         int len;
      92           0 :         int map;
      93           0 :         int first_de = 1;
      94           0 :         char *p = NULL;         /* Quiet GCC */
      95           0 :         struct iso_directory_record *de;
      96           0 :         struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
      97             : 
      98           0 :         offset = ctx->pos & (bufsize - 1);
      99           0 :         block = ctx->pos >> bufbits;
     100             : 
     101           0 :         while (ctx->pos < inode->i_size) {
     102           0 :                 int de_len;
     103             : 
     104           0 :                 if (!bh) {
     105           0 :                         bh = isofs_bread(inode, block);
     106           0 :                         if (!bh)
     107             :                                 return 0;
     108             :                 }
     109             : 
     110           0 :                 de = (struct iso_directory_record *) (bh->b_data + offset);
     111             : 
     112           0 :                 de_len = *(unsigned char *)de;
     113             : 
     114             :                 /*
     115             :                  * If the length byte is zero, we should move on to the next
     116             :                  * CDROM sector.  If we are at the end of the directory, we
     117             :                  * kick out of the while loop.
     118             :                  */
     119             : 
     120           0 :                 if (de_len == 0) {
     121           0 :                         brelse(bh);
     122           0 :                         bh = NULL;
     123           0 :                         ctx->pos = (ctx->pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
     124           0 :                         block = ctx->pos >> bufbits;
     125           0 :                         offset = 0;
     126           0 :                         continue;
     127             :                 }
     128             : 
     129           0 :                 block_saved = block;
     130           0 :                 offset_saved = offset;
     131           0 :                 offset += de_len;
     132             : 
     133             :                 /* Make sure we have a full directory entry */
     134           0 :                 if (offset >= bufsize) {
     135           0 :                         int slop = bufsize - offset + de_len;
     136           0 :                         memcpy(tmpde, de, slop);
     137           0 :                         offset &= bufsize - 1;
     138           0 :                         block++;
     139           0 :                         brelse(bh);
     140           0 :                         bh = NULL;
     141           0 :                         if (offset) {
     142           0 :                                 bh = isofs_bread(inode, block);
     143           0 :                                 if (!bh)
     144             :                                         return 0;
     145           0 :                                 memcpy((void *) tmpde + slop, bh->b_data, offset);
     146             :                         }
     147             :                         de = tmpde;
     148             :                 }
     149             :                 /* Basic sanity check, whether name doesn't exceed dir entry */
     150           0 :                 if (de_len < de->name_len[0] +
     151             :                                         sizeof(struct iso_directory_record)) {
     152           0 :                         printk(KERN_NOTICE "iso9660: Corrupted directory entry"
     153             :                                " in block %lu of inode %lu\n", block,
     154             :                                inode->i_ino);
     155           0 :                         brelse(bh);
     156           0 :                         return -EIO;
     157             :                 }
     158             : 
     159           0 :                 if (first_de) {
     160           0 :                         isofs_normalize_block_and_offset(de,
     161             :                                                         &block_saved,
     162             :                                                         &offset_saved);
     163           0 :                         inode_number = isofs_get_ino(block_saved,
     164             :                                                         offset_saved, bufbits);
     165             :                 }
     166             : 
     167           0 :                 if (de->flags[-sbi->s_high_sierra] & 0x80) {
     168           0 :                         first_de = 0;
     169           0 :                         ctx->pos += de_len;
     170           0 :                         continue;
     171             :                 }
     172           0 :                 first_de = 1;
     173             : 
     174             :                 /* Handle the case of the '.' directory */
     175           0 :                 if (de->name_len[0] == 1 && de->name[0] == 0) {
     176           0 :                         if (!dir_emit_dot(file, ctx))
     177             :                                 break;
     178           0 :                         ctx->pos += de_len;
     179           0 :                         continue;
     180             :                 }
     181             : 
     182           0 :                 len = 0;
     183             : 
     184             :                 /* Handle the case of the '..' directory */
     185           0 :                 if (de->name_len[0] == 1 && de->name[0] == 1) {
     186           0 :                         if (!dir_emit_dotdot(file, ctx))
     187             :                                 break;
     188           0 :                         ctx->pos += de_len;
     189           0 :                         continue;
     190             :                 }
     191             : 
     192             :                 /* Handle everything else.  Do name translation if there
     193             :                    is no Rock Ridge NM field. */
     194             : 
     195             :                 /*
     196             :                  * Do not report hidden files if so instructed, or associated
     197             :                  * files unless instructed to do so
     198             :                  */
     199           0 :                 if ((sbi->s_hide && (de->flags[-sbi->s_high_sierra] & 1)) ||
     200           0 :                     (!sbi->s_showassoc &&
     201             :                                 (de->flags[-sbi->s_high_sierra] & 4))) {
     202           0 :                         ctx->pos += de_len;
     203           0 :                         continue;
     204             :                 }
     205             : 
     206           0 :                 map = 1;
     207           0 :                 if (sbi->s_rock) {
     208           0 :                         len = get_rock_ridge_filename(de, tmpname, inode);
     209           0 :                         if (len != 0) {         /* may be -1 */
     210           0 :                                 p = tmpname;
     211           0 :                                 map = 0;
     212             :                         }
     213             :                 }
     214           0 :                 if (map) {
     215             : #ifdef CONFIG_JOLIET
     216           0 :                         if (sbi->s_joliet_level) {
     217           0 :                                 len = get_joliet_filename(de, tmpname, inode);
     218           0 :                                 p = tmpname;
     219             :                         } else
     220             : #endif
     221           0 :                         if (sbi->s_mapping == 'a') {
     222           0 :                                 len = get_acorn_filename(de, tmpname, inode);
     223           0 :                                 p = tmpname;
     224             :                         } else
     225           0 :                         if (sbi->s_mapping == 'n') {
     226           0 :                                 len = isofs_name_translate(de, tmpname, inode);
     227           0 :                                 p = tmpname;
     228             :                         } else {
     229           0 :                                 p = de->name;
     230           0 :                                 len = de->name_len[0];
     231             :                         }
     232             :                 }
     233           0 :                 if (len > 0) {
     234           0 :                         if (!dir_emit(ctx, p, len, inode_number, DT_UNKNOWN))
     235             :                                 break;
     236             :                 }
     237           0 :                 ctx->pos += de_len;
     238             : 
     239           0 :                 continue;
     240             :         }
     241           0 :         if (bh)
     242           0 :                 brelse(bh);
     243             :         return 0;
     244             : }
     245             : 
     246             : /*
     247             :  * Handle allocation of temporary space for name translation and
     248             :  * handling split directory entries.. The real work is done by
     249             :  * "do_isofs_readdir()".
     250             :  */
     251           0 : static int isofs_readdir(struct file *file, struct dir_context *ctx)
     252             : {
     253           0 :         int result;
     254           0 :         char *tmpname;
     255           0 :         struct iso_directory_record *tmpde;
     256           0 :         struct inode *inode = file_inode(file);
     257             : 
     258           0 :         tmpname = (char *)__get_free_page(GFP_KERNEL);
     259           0 :         if (tmpname == NULL)
     260             :                 return -ENOMEM;
     261             : 
     262           0 :         tmpde = (struct iso_directory_record *) (tmpname+1024);
     263             : 
     264           0 :         result = do_isofs_readdir(inode, file, ctx, tmpname, tmpde);
     265             : 
     266           0 :         free_page((unsigned long) tmpname);
     267           0 :         return result;
     268             : }
     269             : 
     270             : const struct file_operations isofs_dir_operations =
     271             : {
     272             :         .llseek = generic_file_llseek,
     273             :         .read = generic_read_dir,
     274             :         .iterate_shared = isofs_readdir,
     275             : };
     276             : 
     277             : /*
     278             :  * directories can handle most operations...
     279             :  */
     280             : const struct inode_operations isofs_dir_inode_operations =
     281             : {
     282             :         .lookup = isofs_lookup,
     283             : };
     284             : 
     285             : 

Generated by: LCOV version 1.14