LCOV - code coverage report
Current view: top level - fs/isofs - dir.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 135 0.0 %
Date: 2022-04-01 14:35:51 Functions: 0 4 0.0 %
Branches: 0 106 0.0 %

           Branch data     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 :                         return -EIO;
     156                 :            :                 }
     157                 :            : 
     158         [ #  # ]:          0 :                 if (first_de) {
     159         [ #  # ]:          0 :                         isofs_normalize_block_and_offset(de,
     160                 :            :                                                         &block_saved,
     161                 :            :                                                         &offset_saved);
     162                 :          0 :                         inode_number = isofs_get_ino(block_saved,
     163                 :            :                                                         offset_saved, bufbits);
     164                 :            :                 }
     165                 :            : 
     166         [ #  # ]:          0 :                 if (de->flags[-sbi->s_high_sierra] & 0x80) {
     167                 :          0 :                         first_de = 0;
     168                 :          0 :                         ctx->pos += de_len;
     169                 :          0 :                         continue;
     170                 :            :                 }
     171                 :          0 :                 first_de = 1;
     172                 :            : 
     173                 :            :                 /* Handle the case of the '.' directory */
     174   [ #  #  #  # ]:          0 :                 if (de->name_len[0] == 1 && de->name[0] == 0) {
     175         [ #  # ]:          0 :                         if (!dir_emit_dot(file, ctx))
     176                 :            :                                 break;
     177                 :          0 :                         ctx->pos += de_len;
     178                 :          0 :                         continue;
     179                 :            :                 }
     180                 :            : 
     181                 :          0 :                 len = 0;
     182                 :            : 
     183                 :            :                 /* Handle the case of the '..' directory */
     184   [ #  #  #  # ]:          0 :                 if (de->name_len[0] == 1 && de->name[0] == 1) {
     185         [ #  # ]:          0 :                         if (!dir_emit_dotdot(file, ctx))
     186                 :            :                                 break;
     187                 :          0 :                         ctx->pos += de_len;
     188                 :          0 :                         continue;
     189                 :            :                 }
     190                 :            : 
     191                 :            :                 /* Handle everything else.  Do name translation if there
     192                 :            :                    is no Rock Ridge NM field. */
     193                 :            : 
     194                 :            :                 /*
     195                 :            :                  * Do not report hidden files if so instructed, or associated
     196                 :            :                  * files unless instructed to do so
     197                 :            :                  */
     198   [ #  #  #  #  :          0 :                 if ((sbi->s_hide && (de->flags[-sbi->s_high_sierra] & 1)) ||
                   #  # ]
     199         [ #  # ]:          0 :                     (!sbi->s_showassoc &&
     200                 :            :                                 (de->flags[-sbi->s_high_sierra] & 4))) {
     201                 :          0 :                         ctx->pos += de_len;
     202                 :          0 :                         continue;
     203                 :            :                 }
     204                 :            : 
     205                 :          0 :                 map = 1;
     206         [ #  # ]:          0 :                 if (sbi->s_rock) {
     207                 :          0 :                         len = get_rock_ridge_filename(de, tmpname, inode);
     208         [ #  # ]:          0 :                         if (len != 0) {         /* may be -1 */
     209                 :          0 :                                 p = tmpname;
     210                 :          0 :                                 map = 0;
     211                 :            :                         }
     212                 :            :                 }
     213         [ #  # ]:          0 :                 if (map) {
     214                 :            : #ifdef CONFIG_JOLIET
     215         [ #  # ]:          0 :                         if (sbi->s_joliet_level) {
     216                 :          0 :                                 len = get_joliet_filename(de, tmpname, inode);
     217                 :          0 :                                 p = tmpname;
     218                 :            :                         } else
     219                 :            : #endif
     220         [ #  # ]:          0 :                         if (sbi->s_mapping == 'a') {
     221                 :          0 :                                 len = get_acorn_filename(de, tmpname, inode);
     222                 :          0 :                                 p = tmpname;
     223                 :            :                         } else
     224         [ #  # ]:          0 :                         if (sbi->s_mapping == 'n') {
     225                 :          0 :                                 len = isofs_name_translate(de, tmpname, inode);
     226                 :          0 :                                 p = tmpname;
     227                 :            :                         } else {
     228                 :          0 :                                 p = de->name;
     229                 :          0 :                                 len = de->name_len[0];
     230                 :            :                         }
     231                 :            :                 }
     232         [ #  # ]:          0 :                 if (len > 0) {
     233         [ #  # ]:          0 :                         if (!dir_emit(ctx, p, len, inode_number, DT_UNKNOWN))
     234                 :            :                                 break;
     235                 :            :                 }
     236                 :          0 :                 ctx->pos += de_len;
     237                 :            : 
     238                 :          0 :                 continue;
     239                 :            :         }
     240         [ #  # ]:          0 :         if (bh)
     241                 :          0 :                 brelse(bh);
     242                 :            :         return 0;
     243                 :            : }
     244                 :            : 
     245                 :            : /*
     246                 :            :  * Handle allocation of temporary space for name translation and
     247                 :            :  * handling split directory entries.. The real work is done by
     248                 :            :  * "do_isofs_readdir()".
     249                 :            :  */
     250                 :          0 : static int isofs_readdir(struct file *file, struct dir_context *ctx)
     251                 :            : {
     252                 :          0 :         int result;
     253                 :          0 :         char *tmpname;
     254                 :          0 :         struct iso_directory_record *tmpde;
     255                 :          0 :         struct inode *inode = file_inode(file);
     256                 :            : 
     257                 :          0 :         tmpname = (char *)__get_free_page(GFP_KERNEL);
     258         [ #  # ]:          0 :         if (tmpname == NULL)
     259                 :            :                 return -ENOMEM;
     260                 :            : 
     261                 :          0 :         tmpde = (struct iso_directory_record *) (tmpname+1024);
     262                 :            : 
     263                 :          0 :         result = do_isofs_readdir(inode, file, ctx, tmpname, tmpde);
     264                 :            : 
     265                 :          0 :         free_page((unsigned long) tmpname);
     266                 :          0 :         return result;
     267                 :            : }
     268                 :            : 
     269                 :            : const struct file_operations isofs_dir_operations =
     270                 :            : {
     271                 :            :         .llseek = generic_file_llseek,
     272                 :            :         .read = generic_read_dir,
     273                 :            :         .iterate_shared = isofs_readdir,
     274                 :            : };
     275                 :            : 
     276                 :            : /*
     277                 :            :  * directories can handle most operations...
     278                 :            :  */
     279                 :            : const struct inode_operations isofs_dir_inode_operations =
     280                 :            : {
     281                 :            :         .lookup = isofs_lookup,
     282                 :            : };
     283                 :            : 
     284                 :            : 

Generated by: LCOV version 1.14