LCOV - code coverage report
Current view: top level - fs/isofs - rock.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 417 0.0 %
Date: 2022-03-28 16:04:14 Functions: 0 6 0.0 %
Branches: 0 222 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  *  linux/fs/isofs/rock.c
       4                 :            :  *
       5                 :            :  *  (C) 1992, 1993  Eric Youngdale
       6                 :            :  *
       7                 :            :  *  Rock Ridge Extensions to iso9660
       8                 :            :  */
       9                 :            : 
      10                 :            : #include <linux/slab.h>
      11                 :            : #include <linux/pagemap.h>
      12                 :            : 
      13                 :            : #include "isofs.h"
      14                 :            : #include "rock.h"
      15                 :            : 
      16                 :            : /*
      17                 :            :  * These functions are designed to read the system areas of a directory record
      18                 :            :  * and extract relevant information.  There are different functions provided
      19                 :            :  * depending upon what information we need at the time.  One function fills
      20                 :            :  * out an inode structure, a second one extracts a filename, a third one
      21                 :            :  * returns a symbolic link name, and a fourth one returns the extent number
      22                 :            :  * for the file.
      23                 :            :  */
      24                 :            : 
      25                 :            : #define SIG(A,B) ((A) | ((B) << 8))       /* isonum_721() */
      26                 :            : 
      27                 :            : struct rock_state {
      28                 :            :         void *buffer;
      29                 :            :         unsigned char *chr;
      30                 :            :         int len;
      31                 :            :         int cont_size;
      32                 :            :         int cont_extent;
      33                 :            :         int cont_offset;
      34                 :            :         int cont_loops;
      35                 :            :         struct inode *inode;
      36                 :            : };
      37                 :            : 
      38                 :            : /*
      39                 :            :  * This is a way of ensuring that we have something in the system
      40                 :            :  * use fields that is compatible with Rock Ridge.  Return zero on success.
      41                 :            :  */
      42                 :            : 
      43                 :          0 : static int check_sp(struct rock_ridge *rr, struct inode *inode)
      44                 :            : {
      45                 :          0 :         if (rr->u.SP.magic[0] != 0xbe)
      46                 :            :                 return -1;
      47   [ #  #  #  #  :          0 :         if (rr->u.SP.magic[1] != 0xef)
                   #  # ]
      48                 :            :                 return -1;
      49                 :          0 :         ISOFS_SB(inode->i_sb)->s_rock_offset = rr->u.SP.skip;
      50                 :          0 :         return 0;
      51                 :            : }
      52                 :            : 
      53                 :            : static void setup_rock_ridge(struct iso_directory_record *de,
      54                 :            :                         struct inode *inode, struct rock_state *rs)
      55                 :            : {
      56                 :            :         rs->len = sizeof(struct iso_directory_record) + de->name_len[0];
      57                 :            :         if (rs->len & 1)
      58                 :            :                 (rs->len)++;
      59                 :            :         rs->chr = (unsigned char *)de + rs->len;
      60                 :            :         rs->len = *((unsigned char *)de) - rs->len;
      61                 :            :         if (rs->len < 0)
      62                 :            :                 rs->len = 0;
      63                 :            : 
      64                 :            :         if (ISOFS_SB(inode->i_sb)->s_rock_offset != -1) {
      65                 :            :                 rs->len -= ISOFS_SB(inode->i_sb)->s_rock_offset;
      66                 :            :                 rs->chr += ISOFS_SB(inode->i_sb)->s_rock_offset;
      67                 :            :                 if (rs->len < 0)
      68                 :            :                         rs->len = 0;
      69                 :            :         }
      70                 :            : }
      71                 :            : 
      72                 :          0 : static void init_rock_state(struct rock_state *rs, struct inode *inode)
      73                 :            : {
      74                 :          0 :         memset(rs, 0, sizeof(*rs));
      75                 :          0 :         rs->inode = inode;
      76                 :            : }
      77                 :            : 
      78                 :            : /* Maximum number of Rock Ridge continuation entries */
      79                 :            : #define RR_MAX_CE_ENTRIES 32
      80                 :            : 
      81                 :            : /*
      82                 :            :  * Returns 0 if the caller should continue scanning, 1 if the scan must end
      83                 :            :  * and -ve on error.
      84                 :            :  */
      85                 :          0 : static int rock_continue(struct rock_state *rs)
      86                 :            : {
      87                 :          0 :         int ret = 1;
      88                 :          0 :         int blocksize = 1 << rs->inode->i_blkbits;
      89                 :          0 :         const int min_de_size = offsetof(struct rock_ridge, u);
      90                 :            : 
      91                 :          0 :         kfree(rs->buffer);
      92                 :          0 :         rs->buffer = NULL;
      93                 :            : 
      94         [ #  # ]:          0 :         if ((unsigned)rs->cont_offset > blocksize - min_de_size ||
      95         [ #  # ]:          0 :             (unsigned)rs->cont_size > blocksize ||
      96         [ #  # ]:          0 :             (unsigned)(rs->cont_offset + rs->cont_size) > blocksize) {
      97                 :          0 :                 printk(KERN_NOTICE "rock: corrupted directory entry. "
      98                 :            :                         "extent=%d, offset=%d, size=%d\n",
      99                 :            :                         rs->cont_extent, rs->cont_offset, rs->cont_size);
     100                 :          0 :                 ret = -EIO;
     101                 :          0 :                 goto out;
     102                 :            :         }
     103                 :            : 
     104         [ #  # ]:          0 :         if (rs->cont_extent) {
     105                 :          0 :                 struct buffer_head *bh;
     106                 :            : 
     107         [ #  # ]:          0 :                 rs->buffer = kmalloc(rs->cont_size, GFP_KERNEL);
     108         [ #  # ]:          0 :                 if (!rs->buffer) {
     109                 :          0 :                         ret = -ENOMEM;
     110                 :          0 :                         goto out;
     111                 :            :                 }
     112                 :          0 :                 ret = -EIO;
     113         [ #  # ]:          0 :                 if (++rs->cont_loops >= RR_MAX_CE_ENTRIES)
     114                 :          0 :                         goto out;
     115                 :          0 :                 bh = sb_bread(rs->inode->i_sb, rs->cont_extent);
     116         [ #  # ]:          0 :                 if (bh) {
     117                 :          0 :                         memcpy(rs->buffer, bh->b_data + rs->cont_offset,
     118                 :          0 :                                         rs->cont_size);
     119                 :          0 :                         put_bh(bh);
     120                 :          0 :                         rs->chr = rs->buffer;
     121                 :          0 :                         rs->len = rs->cont_size;
     122                 :          0 :                         rs->cont_extent = 0;
     123                 :          0 :                         rs->cont_size = 0;
     124                 :          0 :                         rs->cont_offset = 0;
     125                 :          0 :                         return 0;
     126                 :            :                 }
     127                 :          0 :                 printk("Unable to read rock-ridge attributes\n");
     128                 :            :         }
     129                 :          0 : out:
     130                 :          0 :         kfree(rs->buffer);
     131                 :          0 :         rs->buffer = NULL;
     132                 :          0 :         return ret;
     133                 :            : }
     134                 :            : 
     135                 :            : /*
     136                 :            :  * We think there's a record of type `sig' at rs->chr.  Parse the signature
     137                 :            :  * and make sure that there's really room for a record of that type.
     138                 :            :  */
     139                 :            : static int rock_check_overflow(struct rock_state *rs, int sig)
     140                 :            : {
     141                 :            :         int len;
     142                 :            : 
     143                 :            :         switch (sig) {
     144                 :            :         case SIG('S', 'P'):
     145                 :            :                 len = sizeof(struct SU_SP_s);
     146                 :            :                 break;
     147                 :            :         case SIG('C', 'E'):
     148                 :            :                 len = sizeof(struct SU_CE_s);
     149                 :            :                 break;
     150                 :            :         case SIG('E', 'R'):
     151                 :            :                 len = sizeof(struct SU_ER_s);
     152                 :            :                 break;
     153                 :            :         case SIG('R', 'R'):
     154                 :            :                 len = sizeof(struct RR_RR_s);
     155                 :            :                 break;
     156                 :            :         case SIG('P', 'X'):
     157                 :            :                 len = sizeof(struct RR_PX_s);
     158                 :            :                 break;
     159                 :            :         case SIG('P', 'N'):
     160                 :            :                 len = sizeof(struct RR_PN_s);
     161                 :            :                 break;
     162                 :            :         case SIG('S', 'L'):
     163                 :            :                 len = sizeof(struct RR_SL_s);
     164                 :            :                 break;
     165                 :            :         case SIG('N', 'M'):
     166                 :            :                 len = sizeof(struct RR_NM_s);
     167                 :            :                 break;
     168                 :            :         case SIG('C', 'L'):
     169                 :            :                 len = sizeof(struct RR_CL_s);
     170                 :            :                 break;
     171                 :            :         case SIG('P', 'L'):
     172                 :            :                 len = sizeof(struct RR_PL_s);
     173                 :            :                 break;
     174                 :            :         case SIG('T', 'F'):
     175                 :            :                 len = sizeof(struct RR_TF_s);
     176                 :            :                 break;
     177                 :            :         case SIG('Z', 'F'):
     178                 :            :                 len = sizeof(struct RR_ZF_s);
     179                 :            :                 break;
     180                 :            :         default:
     181                 :            :                 len = 0;
     182                 :            :                 break;
     183                 :            :         }
     184                 :            :         len += offsetof(struct rock_ridge, u);
     185                 :            :         if (len > rs->len) {
     186                 :            :                 printk(KERN_NOTICE "rock: directory entry would overflow "
     187                 :            :                                 "storage\n");
     188                 :            :                 printk(KERN_NOTICE "rock: sig=0x%02x, size=%d, remaining=%d\n",
     189                 :            :                                 sig, len, rs->len);
     190                 :            :                 return -EIO;
     191                 :            :         }
     192                 :            :         return 0;
     193                 :            : }
     194                 :            : 
     195                 :            : /*
     196                 :            :  * return length of name field; 0: not found, -1: to be ignored
     197                 :            :  */
     198                 :          0 : int get_rock_ridge_filename(struct iso_directory_record *de,
     199                 :            :                             char *retname, struct inode *inode)
     200                 :            : {
     201                 :          0 :         struct rock_state rs;
     202                 :          0 :         struct rock_ridge *rr;
     203                 :          0 :         int sig;
     204                 :          0 :         int retnamlen = 0;
     205                 :          0 :         int truncate = 0;
     206                 :          0 :         int ret = 0;
     207                 :          0 :         char *p;
     208                 :          0 :         int len;
     209                 :            : 
     210         [ #  # ]:          0 :         if (!ISOFS_SB(inode->i_sb)->s_rock)
     211                 :            :                 return 0;
     212                 :          0 :         *retname = 0;
     213                 :            : 
     214                 :          0 :         init_rock_state(&rs, inode);
     215                 :          0 :         setup_rock_ridge(de, inode, &rs);
     216                 :            : repeat:
     217                 :            : 
     218         [ #  # ]:          0 :         while (rs.len > 2) { /* There may be one byte for padding somewhere */
     219                 :          0 :                 rr = (struct rock_ridge *)rs.chr;
     220                 :            :                 /*
     221                 :            :                  * Ignore rock ridge info if rr->len is out of range, but
     222                 :            :                  * don't return -EIO because that would make the file
     223                 :            :                  * invisible.
     224                 :            :                  */
     225         [ #  # ]:          0 :                 if (rr->len < 3)
     226                 :          0 :                         goto out;       /* Something got screwed up here */
     227                 :          0 :                 sig = isonum_721(rs.chr);
     228         [ #  # ]:          0 :                 if (rock_check_overflow(&rs, sig))
     229                 :          0 :                         goto eio;
     230                 :          0 :                 rs.chr += rr->len;
     231                 :          0 :                 rs.len -= rr->len;
     232                 :            :                 /*
     233                 :            :                  * As above, just ignore the rock ridge info if rr->len
     234                 :            :                  * is bogus.
     235                 :            :                  */
     236         [ #  # ]:          0 :                 if (rs.len < 0)
     237                 :          0 :                         goto out;       /* Something got screwed up here */
     238                 :            : 
     239   [ #  #  #  #  :          0 :                 switch (sig) {
                   #  # ]
     240                 :          0 :                 case SIG('R', 'R'):
     241         [ #  # ]:          0 :                         if ((rr->u.RR.flags[0] & RR_NM) == 0)
     242                 :          0 :                                 goto out;
     243                 :            :                         break;
     244                 :          0 :                 case SIG('S', 'P'):
     245         [ #  # ]:          0 :                         if (check_sp(rr, inode))
     246                 :          0 :                                 goto out;
     247                 :            :                         break;
     248                 :          0 :                 case SIG('C', 'E'):
     249                 :          0 :                         rs.cont_extent = isonum_733(rr->u.CE.extent);
     250                 :          0 :                         rs.cont_offset = isonum_733(rr->u.CE.offset);
     251                 :          0 :                         rs.cont_size = isonum_733(rr->u.CE.size);
     252                 :          0 :                         break;
     253                 :          0 :                 case SIG('N', 'M'):
     254         [ #  # ]:          0 :                         if (truncate)
     255                 :            :                                 break;
     256         [ #  # ]:          0 :                         if (rr->len < 5)
     257                 :            :                                 break;
     258                 :            :                         /*
     259                 :            :                          * If the flags are 2 or 4, this indicates '.' or '..'.
     260                 :            :                          * We don't want to do anything with this, because it
     261                 :            :                          * screws up the code that calls us.  We don't really
     262                 :            :                          * care anyways, since we can just use the non-RR
     263                 :            :                          * name.
     264                 :            :                          */
     265         [ #  # ]:          0 :                         if (rr->u.NM.flags & 6)
     266                 :            :                                 break;
     267                 :            : 
     268         [ #  # ]:          0 :                         if (rr->u.NM.flags & ~1) {
     269                 :          0 :                                 printk("Unsupported NM flag settings (%d)\n",
     270                 :            :                                         rr->u.NM.flags);
     271                 :          0 :                                 break;
     272                 :            :                         }
     273                 :          0 :                         len = rr->len - 5;
     274         [ #  # ]:          0 :                         if (retnamlen + len >= 254) {
     275                 :            :                                 truncate = 1;
     276                 :            :                                 break;
     277                 :            :                         }
     278                 :          0 :                         p = memchr(rr->u.NM.name, '\0', len);
     279         [ #  # ]:          0 :                         if (unlikely(p))
     280                 :          0 :                                 len = p - rr->u.NM.name;
     281                 :          0 :                         memcpy(retname + retnamlen, rr->u.NM.name, len);
     282                 :          0 :                         retnamlen += len;
     283                 :          0 :                         retname[retnamlen] = '\0';
     284                 :          0 :                         break;
     285                 :          0 :                 case SIG('R', 'E'):
     286                 :          0 :                         kfree(rs.buffer);
     287                 :          0 :                         return -1;
     288                 :            :                 default:
     289                 :            :                         break;
     290                 :            :                 }
     291                 :          0 :         }
     292                 :          0 :         ret = rock_continue(&rs);
     293         [ #  # ]:          0 :         if (ret == 0)
     294                 :          0 :                 goto repeat;
     295         [ #  # ]:          0 :         if (ret == 1)
     296                 :            :                 return retnamlen; /* If 0, this file did not have a NM field */
     297                 :          0 : out:
     298                 :          0 :         kfree(rs.buffer);
     299                 :          0 :         return ret;
     300                 :            : eio:
     301                 :          0 :         ret = -EIO;
     302                 :          0 :         goto out;
     303                 :            : }
     304                 :            : 
     305                 :            : #define RR_REGARD_XA 1
     306                 :            : #define RR_RELOC_DE 2
     307                 :            : 
     308                 :            : static int
     309                 :          0 : parse_rock_ridge_inode_internal(struct iso_directory_record *de,
     310                 :            :                                 struct inode *inode, int flags)
     311                 :            : {
     312                 :          0 :         int symlink_len = 0;
     313                 :          0 :         int cnt, sig;
     314                 :          0 :         unsigned int reloc_block;
     315                 :          0 :         struct inode *reloc;
     316                 :          0 :         struct rock_ridge *rr;
     317                 :          0 :         int rootflag;
     318                 :          0 :         struct rock_state rs;
     319                 :          0 :         int ret = 0;
     320                 :            : 
     321         [ #  # ]:          0 :         if (!ISOFS_SB(inode->i_sb)->s_rock)
     322                 :            :                 return 0;
     323                 :            : 
     324                 :          0 :         init_rock_state(&rs, inode);
     325                 :          0 :         setup_rock_ridge(de, inode, &rs);
     326         [ #  # ]:          0 :         if (flags & RR_REGARD_XA) {
     327                 :          0 :                 rs.chr += 14;
     328                 :          0 :                 rs.len -= 14;
     329         [ #  # ]:          0 :                 if (rs.len < 0)
     330                 :          0 :                         rs.len = 0;
     331                 :            :         }
     332                 :            : 
     333                 :          0 : repeat:
     334         [ #  # ]:          0 :         while (rs.len > 2) { /* There may be one byte for padding somewhere */
     335                 :          0 :                 rr = (struct rock_ridge *)rs.chr;
     336                 :            :                 /*
     337                 :            :                  * Ignore rock ridge info if rr->len is out of range, but
     338                 :            :                  * don't return -EIO because that would make the file
     339                 :            :                  * invisible.
     340                 :            :                  */
     341         [ #  # ]:          0 :                 if (rr->len < 3)
     342                 :          0 :                         goto out;       /* Something got screwed up here */
     343                 :          0 :                 sig = isonum_721(rs.chr);
     344         [ #  # ]:          0 :                 if (rock_check_overflow(&rs, sig))
     345                 :          0 :                         goto eio;
     346                 :          0 :                 rs.chr += rr->len;
     347                 :          0 :                 rs.len -= rr->len;
     348                 :            :                 /*
     349                 :            :                  * As above, just ignore the rock ridge info if rr->len
     350                 :            :                  * is bogus.
     351                 :            :                  */
     352         [ #  # ]:          0 :                 if (rs.len < 0)
     353                 :          0 :                         goto out;       /* Something got screwed up here */
     354                 :            : 
     355   [ #  #  #  #  :          0 :                 switch (sig) {
          #  #  #  #  #  
                   #  # ]
     356                 :            : #ifndef CONFIG_ZISOFS           /* No flag for SF or ZF */
     357                 :            :                 case SIG('R', 'R'):
     358                 :            :                         if ((rr->u.RR.flags[0] &
     359                 :            :                              (RR_PX | RR_TF | RR_SL | RR_CL)) == 0)
     360                 :            :                                 goto out;
     361                 :            :                         break;
     362                 :            : #endif
     363                 :          0 :                 case SIG('S', 'P'):
     364         [ #  # ]:          0 :                         if (check_sp(rr, inode))
     365                 :          0 :                                 goto out;
     366                 :            :                         break;
     367                 :          0 :                 case SIG('C', 'E'):
     368                 :          0 :                         rs.cont_extent = isonum_733(rr->u.CE.extent);
     369                 :          0 :                         rs.cont_offset = isonum_733(rr->u.CE.offset);
     370                 :          0 :                         rs.cont_size = isonum_733(rr->u.CE.size);
     371                 :          0 :                         break;
     372                 :          0 :                 case SIG('E', 'R'):
     373                 :            :                         /* Invalid length of ER tag id? */
     374         [ #  # ]:          0 :                         if (rr->u.ER.len_id + offsetof(struct rock_ridge, u.ER.data) > rr->len)
     375                 :          0 :                                 goto out;
     376                 :          0 :                         ISOFS_SB(inode->i_sb)->s_rock = 1;
     377                 :          0 :                         printk(KERN_DEBUG "ISO 9660 Extensions: ");
     378                 :            :                         {
     379                 :          0 :                                 int p;
     380         [ #  # ]:          0 :                                 for (p = 0; p < rr->u.ER.len_id; p++)
     381                 :          0 :                                         printk(KERN_CONT "%c", rr->u.ER.data[p]);
     382                 :            :                         }
     383                 :          0 :                         printk(KERN_CONT "\n");
     384                 :          0 :                         break;
     385                 :          0 :                 case SIG('P', 'X'):
     386                 :          0 :                         inode->i_mode = isonum_733(rr->u.PX.mode);
     387                 :          0 :                         set_nlink(inode, isonum_733(rr->u.PX.n_links));
     388                 :          0 :                         i_uid_write(inode, isonum_733(rr->u.PX.uid));
     389                 :          0 :                         i_gid_write(inode, isonum_733(rr->u.PX.gid));
     390                 :            :                         break;
     391                 :          0 :                 case SIG('P', 'N'):
     392                 :            :                         {
     393                 :          0 :                                 int high, low;
     394         [ #  # ]:          0 :                                 high = isonum_733(rr->u.PN.dev_high);
     395                 :          0 :                                 low = isonum_733(rr->u.PN.dev_low);
     396                 :            :                                 /*
     397                 :            :                                  * The Rock Ridge standard specifies that if
     398                 :            :                                  * sizeof(dev_t) <= 4, then the high field is
     399                 :            :                                  * unused, and the device number is completely
     400                 :            :                                  * stored in the low field.  Some writers may
     401                 :            :                                  * ignore this subtlety,
     402                 :            :                                  * and as a result we test to see if the entire
     403                 :            :                                  * device number is
     404                 :            :                                  * stored in the low field, and use that.
     405                 :            :                                  */
     406   [ #  #  #  # ]:          0 :                                 if ((low & ~0xff) && high == 0) {
     407                 :          0 :                                         inode->i_rdev =
     408                 :          0 :                                             MKDEV(low >> 8, low & 0xff);
     409                 :            :                                 } else {
     410                 :          0 :                                         inode->i_rdev =
     411                 :          0 :                                             MKDEV(high, low);
     412                 :            :                                 }
     413                 :            :                         }
     414                 :            :                         break;
     415                 :          0 :                 case SIG('T', 'F'):
     416                 :            :                         /*
     417                 :            :                          * Some RRIP writers incorrectly place ctime in the
     418                 :            :                          * TF_CREATE field. Try to handle this correctly for
     419                 :            :                          * either case.
     420                 :            :                          */
     421                 :            :                         /* Rock ridge never appears on a High Sierra disk */
     422                 :          0 :                         cnt = 0;
     423         [ #  # ]:          0 :                         if (rr->u.TF.flags & TF_CREATE) {
     424                 :          0 :                                 inode->i_ctime.tv_sec =
     425                 :          0 :                                     iso_date(rr->u.TF.times[cnt++].time,
     426                 :            :                                              0);
     427                 :          0 :                                 inode->i_ctime.tv_nsec = 0;
     428                 :            :                         }
     429         [ #  # ]:          0 :                         if (rr->u.TF.flags & TF_MODIFY) {
     430                 :          0 :                                 inode->i_mtime.tv_sec =
     431                 :          0 :                                     iso_date(rr->u.TF.times[cnt++].time,
     432                 :            :                                              0);
     433                 :          0 :                                 inode->i_mtime.tv_nsec = 0;
     434                 :            :                         }
     435         [ #  # ]:          0 :                         if (rr->u.TF.flags & TF_ACCESS) {
     436                 :          0 :                                 inode->i_atime.tv_sec =
     437                 :          0 :                                     iso_date(rr->u.TF.times[cnt++].time,
     438                 :            :                                              0);
     439                 :          0 :                                 inode->i_atime.tv_nsec = 0;
     440                 :            :                         }
     441         [ #  # ]:          0 :                         if (rr->u.TF.flags & TF_ATTRIBUTES) {
     442                 :          0 :                                 inode->i_ctime.tv_sec =
     443                 :          0 :                                     iso_date(rr->u.TF.times[cnt++].time,
     444                 :            :                                              0);
     445                 :          0 :                                 inode->i_ctime.tv_nsec = 0;
     446                 :            :                         }
     447                 :            :                         break;
     448                 :          0 :                 case SIG('S', 'L'):
     449                 :            :                         {
     450                 :          0 :                                 int slen;
     451                 :          0 :                                 struct SL_component *slp;
     452                 :          0 :                                 struct SL_component *oldslp;
     453                 :          0 :                                 slen = rr->len - 5;
     454                 :          0 :                                 slp = &rr->u.SL.link;
     455                 :          0 :                                 inode->i_size = symlink_len;
     456         [ #  # ]:          0 :                                 while (slen > 1) {
     457                 :          0 :                                         rootflag = 0;
     458   [ #  #  #  #  :          0 :                                         switch (slp->flags & ~1) {
                      # ]
     459                 :          0 :                                         case 0:
     460                 :          0 :                                                 inode->i_size +=
     461                 :          0 :                                                     slp->len;
     462                 :          0 :                                                 break;
     463                 :          0 :                                         case 2:
     464                 :          0 :                                                 inode->i_size += 1;
     465                 :          0 :                                                 break;
     466                 :          0 :                                         case 4:
     467                 :          0 :                                                 inode->i_size += 2;
     468                 :          0 :                                                 break;
     469                 :          0 :                                         case 8:
     470                 :          0 :                                                 rootflag = 1;
     471                 :          0 :                                                 inode->i_size += 1;
     472                 :          0 :                                                 break;
     473                 :          0 :                                         default:
     474                 :          0 :                                                 printk("Symlink component flag "
     475                 :            :                                                         "not implemented\n");
     476                 :            :                                         }
     477                 :          0 :                                         slen -= slp->len + 2;
     478                 :          0 :                                         oldslp = slp;
     479                 :          0 :                                         slp = (struct SL_component *)
     480                 :          0 :                                                 (((char *)slp) + slp->len + 2);
     481                 :            : 
     482         [ #  # ]:          0 :                                         if (slen < 2) {
     483         [ #  # ]:          0 :                                                 if (((rr->u.SL.
     484                 :            :                                                       flags & 1) != 0)
     485                 :          0 :                                                     &&
     486         [ #  # ]:          0 :                                                     ((oldslp->
     487                 :            :                                                       flags & 1) == 0))
     488                 :          0 :                                                         inode->i_size +=
     489                 :            :                                                             1;
     490                 :            :                                                 break;
     491                 :            :                                         }
     492                 :            : 
     493                 :            :                                         /*
     494                 :            :                                          * If this component record isn't
     495                 :            :                                          * continued, then append a '/'.
     496                 :            :                                          */
     497         [ #  # ]:          0 :                                         if (!rootflag
     498         [ #  # ]:          0 :                                             && (oldslp->flags & 1) == 0)
     499                 :          0 :                                                 inode->i_size += 1;
     500                 :            :                                 }
     501                 :            :                         }
     502                 :          0 :                         symlink_len = inode->i_size;
     503                 :          0 :                         break;
     504                 :          0 :                 case SIG('R', 'E'):
     505                 :          0 :                         printk(KERN_WARNING "Attempt to read inode for "
     506                 :            :                                         "relocated directory\n");
     507                 :          0 :                         goto out;
     508                 :          0 :                 case SIG('C', 'L'):
     509         [ #  # ]:          0 :                         if (flags & RR_RELOC_DE) {
     510                 :          0 :                                 printk(KERN_ERR
     511                 :            :                                        "ISOFS: Recursive directory relocation "
     512                 :            :                                        "is not supported\n");
     513                 :          0 :                                 goto eio;
     514                 :            :                         }
     515         [ #  # ]:          0 :                         reloc_block = isonum_733(rr->u.CL.location);
     516         [ #  # ]:          0 :                         if (reloc_block == ISOFS_I(inode)->i_iget5_block &&
     517         [ #  # ]:          0 :                             ISOFS_I(inode)->i_iget5_offset == 0) {
     518                 :          0 :                                 printk(KERN_ERR
     519                 :            :                                        "ISOFS: Directory relocation points to "
     520                 :            :                                        "itself\n");
     521                 :          0 :                                 goto eio;
     522                 :            :                         }
     523                 :          0 :                         ISOFS_I(inode)->i_first_extent = reloc_block;
     524                 :          0 :                         reloc = isofs_iget_reloc(inode->i_sb, reloc_block, 0);
     525         [ #  # ]:          0 :                         if (IS_ERR(reloc)) {
     526                 :          0 :                                 ret = PTR_ERR(reloc);
     527                 :          0 :                                 goto out;
     528                 :            :                         }
     529                 :          0 :                         inode->i_mode = reloc->i_mode;
     530                 :          0 :                         set_nlink(inode, reloc->i_nlink);
     531                 :          0 :                         inode->i_uid = reloc->i_uid;
     532                 :          0 :                         inode->i_gid = reloc->i_gid;
     533                 :          0 :                         inode->i_rdev = reloc->i_rdev;
     534                 :          0 :                         inode->i_size = reloc->i_size;
     535                 :          0 :                         inode->i_blocks = reloc->i_blocks;
     536                 :          0 :                         inode->i_atime = reloc->i_atime;
     537                 :          0 :                         inode->i_ctime = reloc->i_ctime;
     538                 :          0 :                         inode->i_mtime = reloc->i_mtime;
     539                 :          0 :                         iput(reloc);
     540                 :          0 :                         break;
     541                 :            : #ifdef CONFIG_ZISOFS
     542                 :          0 :                 case SIG('Z', 'F'): {
     543                 :          0 :                         int algo;
     544                 :            : 
     545         [ #  # ]:          0 :                         if (ISOFS_SB(inode->i_sb)->s_nocompress)
     546                 :            :                                 break;
     547         [ #  # ]:          0 :                         algo = isonum_721(rr->u.ZF.algorithm);
     548         [ #  # ]:          0 :                         if (algo == SIG('p', 'z')) {
     549                 :          0 :                                 int block_shift =
     550         [ #  # ]:          0 :                                         isonum_711(&rr->u.ZF.parms[1]);
     551         [ #  # ]:          0 :                                 if (block_shift > 17) {
     552                 :          0 :                                         printk(KERN_WARNING "isofs: "
     553                 :            :                                                 "Can't handle ZF block "
     554                 :            :                                                 "size of 2^%d\n",
     555                 :            :                                                 block_shift);
     556                 :            :                                 } else {
     557                 :            :                                         /*
     558                 :            :                                          * Note: we don't change
     559                 :            :                                          * i_blocks here
     560                 :            :                                          */
     561                 :          0 :                                         ISOFS_I(inode)->i_file_format =
     562                 :            :                                                 isofs_file_compressed;
     563                 :            :                                         /*
     564                 :            :                                          * Parameters to compression
     565                 :            :                                          * algorithm (header size,
     566                 :            :                                          * block size)
     567                 :            :                                          */
     568                 :          0 :                                         ISOFS_I(inode)->i_format_parm[0] =
     569                 :          0 :                                                 isonum_711(&rr->u.ZF.parms[0]);
     570                 :          0 :                                         ISOFS_I(inode)->i_format_parm[1] =
     571                 :          0 :                                                 isonum_711(&rr->u.ZF.parms[1]);
     572                 :          0 :                                         inode->i_size =
     573                 :          0 :                                             isonum_733(rr->u.ZF.
     574                 :            :                                                        real_size);
     575                 :            :                                 }
     576                 :            :                         } else {
     577                 :          0 :                                 printk(KERN_WARNING
     578                 :            :                                        "isofs: Unknown ZF compression "
     579                 :            :                                                 "algorithm: %c%c\n",
     580                 :          0 :                                        rr->u.ZF.algorithm[0],
     581                 :          0 :                                        rr->u.ZF.algorithm[1]);
     582                 :            :                         }
     583                 :            :                         break;
     584                 :            :                 }
     585                 :            : #endif
     586                 :            :                 default:
     587                 :            :                         break;
     588                 :            :                 }
     589                 :          0 :         }
     590                 :          0 :         ret = rock_continue(&rs);
     591         [ #  # ]:          0 :         if (ret == 0)
     592                 :          0 :                 goto repeat;
     593         [ #  # ]:          0 :         if (ret == 1)
     594                 :          0 :                 ret = 0;
     595                 :          0 : out:
     596                 :          0 :         kfree(rs.buffer);
     597                 :          0 :         return ret;
     598                 :          0 : eio:
     599                 :          0 :         ret = -EIO;
     600                 :          0 :         goto out;
     601                 :            : }
     602                 :            : 
     603                 :          0 : static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
     604                 :            : {
     605                 :          0 :         int slen;
     606                 :          0 :         int rootflag;
     607                 :          0 :         struct SL_component *oldslp;
     608                 :          0 :         struct SL_component *slp;
     609                 :          0 :         slen = rr->len - 5;
     610                 :          0 :         slp = &rr->u.SL.link;
     611         [ #  # ]:          0 :         while (slen > 1) {
     612                 :          0 :                 rootflag = 0;
     613   [ #  #  #  #  :          0 :                 switch (slp->flags & ~1) {
                      # ]
     614                 :          0 :                 case 0:
     615         [ #  # ]:          0 :                         if (slp->len > plimit - rpnt)
     616                 :            :                                 return NULL;
     617                 :          0 :                         memcpy(rpnt, slp->text, slp->len);
     618                 :          0 :                         rpnt += slp->len;
     619                 :          0 :                         break;
     620                 :          0 :                 case 2:
     621         [ #  # ]:          0 :                         if (rpnt >= plimit)
     622                 :            :                                 return NULL;
     623                 :          0 :                         *rpnt++ = '.';
     624                 :          0 :                         break;
     625                 :          0 :                 case 4:
     626         [ #  # ]:          0 :                         if (2 > plimit - rpnt)
     627                 :            :                                 return NULL;
     628                 :          0 :                         *rpnt++ = '.';
     629                 :          0 :                         *rpnt++ = '.';
     630                 :          0 :                         break;
     631                 :          0 :                 case 8:
     632         [ #  # ]:          0 :                         if (rpnt >= plimit)
     633                 :            :                                 return NULL;
     634                 :          0 :                         rootflag = 1;
     635                 :          0 :                         *rpnt++ = '/';
     636                 :          0 :                         break;
     637                 :          0 :                 default:
     638                 :          0 :                         printk("Symlink component flag not implemented (%d)\n",
     639                 :            :                                slp->flags);
     640                 :            :                 }
     641                 :          0 :                 slen -= slp->len + 2;
     642                 :          0 :                 oldslp = slp;
     643                 :          0 :                 slp = (struct SL_component *)((char *)slp + slp->len + 2);
     644                 :            : 
     645         [ #  # ]:          0 :                 if (slen < 2) {
     646                 :            :                         /*
     647                 :            :                          * If there is another SL record, and this component
     648                 :            :                          * record isn't continued, then add a slash.
     649                 :            :                          */
     650   [ #  #  #  # ]:          0 :                         if ((!rootflag) && (rr->u.SL.flags & 1) &&
     651         [ #  # ]:          0 :                             !(oldslp->flags & 1)) {
     652         [ #  # ]:          0 :                                 if (rpnt >= plimit)
     653                 :            :                                         return NULL;
     654                 :          0 :                                 *rpnt++ = '/';
     655                 :            :                         }
     656                 :            :                         break;
     657                 :            :                 }
     658                 :            : 
     659                 :            :                 /*
     660                 :            :                  * If this component record isn't continued, then append a '/'.
     661                 :            :                  */
     662   [ #  #  #  # ]:          0 :                 if (!rootflag && !(oldslp->flags & 1)) {
     663         [ #  # ]:          0 :                         if (rpnt >= plimit)
     664                 :            :                                 return NULL;
     665                 :          0 :                         *rpnt++ = '/';
     666                 :            :                 }
     667                 :            :         }
     668                 :            :         return rpnt;
     669                 :            : }
     670                 :            : 
     671                 :          0 : int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode,
     672                 :            :                            int relocated)
     673                 :            : {
     674         [ #  # ]:          0 :         int flags = relocated ? RR_RELOC_DE : 0;
     675                 :          0 :         int result = parse_rock_ridge_inode_internal(de, inode, flags);
     676                 :            : 
     677                 :            :         /*
     678                 :            :          * if rockridge flag was reset and we didn't look for attributes
     679                 :            :          * behind eventual XA attributes, have a look there
     680                 :            :          */
     681         [ #  # ]:          0 :         if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1)
     682         [ #  # ]:          0 :             && (ISOFS_SB(inode->i_sb)->s_rock == 2)) {
     683                 :          0 :                 result = parse_rock_ridge_inode_internal(de, inode,
     684                 :            :                                                          flags | RR_REGARD_XA);
     685                 :            :         }
     686                 :          0 :         return result;
     687                 :            : }
     688                 :            : 
     689                 :            : /*
     690                 :            :  * readpage() for symlinks: reads symlink contents into the page and either
     691                 :            :  * makes it uptodate and returns 0 or returns error (-EIO)
     692                 :            :  */
     693                 :          0 : static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
     694                 :            : {
     695                 :          0 :         struct inode *inode = page->mapping->host;
     696         [ #  # ]:          0 :         struct iso_inode_info *ei = ISOFS_I(inode);
     697         [ #  # ]:          0 :         struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
     698         [ #  # ]:          0 :         char *link = page_address(page);
     699                 :          0 :         unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
     700                 :          0 :         struct buffer_head *bh;
     701                 :          0 :         char *rpnt = link;
     702                 :          0 :         unsigned char *pnt;
     703                 :          0 :         struct iso_directory_record *raw_de;
     704                 :          0 :         unsigned long block, offset;
     705                 :          0 :         int sig;
     706                 :          0 :         struct rock_ridge *rr;
     707                 :          0 :         struct rock_state rs;
     708                 :          0 :         int ret;
     709                 :            : 
     710         [ #  # ]:          0 :         if (!sbi->s_rock)
     711                 :          0 :                 goto error;
     712                 :            : 
     713                 :          0 :         init_rock_state(&rs, inode);
     714                 :          0 :         block = ei->i_iget5_block;
     715                 :          0 :         bh = sb_bread(inode->i_sb, block);
     716         [ #  # ]:          0 :         if (!bh)
     717                 :          0 :                 goto out_noread;
     718                 :            : 
     719                 :          0 :         offset = ei->i_iget5_offset;
     720                 :          0 :         pnt = (unsigned char *)bh->b_data + offset;
     721                 :            : 
     722                 :          0 :         raw_de = (struct iso_directory_record *)pnt;
     723                 :            : 
     724                 :            :         /*
     725                 :            :          * If we go past the end of the buffer, there is some sort of error.
     726                 :            :          */
     727         [ #  # ]:          0 :         if (offset + *pnt > bufsize)
     728                 :          0 :                 goto out_bad_span;
     729                 :            : 
     730                 :            :         /*
     731                 :            :          * Now test for possible Rock Ridge extensions which will override
     732                 :            :          * some of these numbers in the inode structure.
     733                 :            :          */
     734                 :            : 
     735                 :          0 :         setup_rock_ridge(raw_de, inode, &rs);
     736                 :            : 
     737                 :            : repeat:
     738         [ #  # ]:          0 :         while (rs.len > 2) { /* There may be one byte for padding somewhere */
     739                 :          0 :                 rr = (struct rock_ridge *)rs.chr;
     740         [ #  # ]:          0 :                 if (rr->len < 3)
     741                 :          0 :                         goto out;       /* Something got screwed up here */
     742                 :          0 :                 sig = isonum_721(rs.chr);
     743         [ #  # ]:          0 :                 if (rock_check_overflow(&rs, sig))
     744                 :          0 :                         goto out;
     745                 :          0 :                 rs.chr += rr->len;
     746                 :          0 :                 rs.len -= rr->len;
     747         [ #  # ]:          0 :                 if (rs.len < 0)
     748                 :          0 :                         goto out;       /* corrupted isofs */
     749                 :            : 
     750   [ #  #  #  #  :          0 :                 switch (sig) {
                      # ]
     751                 :          0 :                 case SIG('R', 'R'):
     752         [ #  # ]:          0 :                         if ((rr->u.RR.flags[0] & RR_SL) == 0)
     753                 :          0 :                                 goto out;
     754                 :            :                         break;
     755                 :          0 :                 case SIG('S', 'P'):
     756         [ #  # ]:          0 :                         if (check_sp(rr, inode))
     757                 :          0 :                                 goto out;
     758                 :            :                         break;
     759                 :          0 :                 case SIG('S', 'L'):
     760                 :          0 :                         rpnt = get_symlink_chunk(rpnt, rr,
     761                 :            :                                                  link + (PAGE_SIZE - 1));
     762         [ #  # ]:          0 :                         if (rpnt == NULL)
     763                 :          0 :                                 goto out;
     764                 :            :                         break;
     765                 :          0 :                 case SIG('C', 'E'):
     766                 :            :                         /* This tells is if there is a continuation record */
     767                 :          0 :                         rs.cont_extent = isonum_733(rr->u.CE.extent);
     768                 :          0 :                         rs.cont_offset = isonum_733(rr->u.CE.offset);
     769                 :          0 :                         rs.cont_size = isonum_733(rr->u.CE.size);
     770                 :            :                 default:
     771                 :            :                         break;
     772                 :            :                 }
     773                 :            :         }
     774                 :          0 :         ret = rock_continue(&rs);
     775         [ #  # ]:          0 :         if (ret == 0)
     776                 :          0 :                 goto repeat;
     777         [ #  # ]:          0 :         if (ret < 0)
     778                 :          0 :                 goto fail;
     779                 :            : 
     780         [ #  # ]:          0 :         if (rpnt == link)
     781                 :          0 :                 goto fail;
     782                 :          0 :         brelse(bh);
     783                 :          0 :         *rpnt = '\0';
     784                 :          0 :         SetPageUptodate(page);
     785                 :          0 :         unlock_page(page);
     786                 :          0 :         return 0;
     787                 :            : 
     788                 :            :         /* error exit from macro */
     789                 :          0 : out:
     790                 :          0 :         kfree(rs.buffer);
     791                 :          0 :         goto fail;
     792                 :            : out_noread:
     793                 :          0 :         printk("unable to read i-node block");
     794                 :          0 :         goto fail;
     795                 :            : out_bad_span:
     796                 :          0 :         printk("symlink spans iso9660 blocks\n");
     797                 :          0 : fail:
     798         [ #  # ]:          0 :         brelse(bh);
     799                 :          0 : error:
     800         [ #  # ]:          0 :         SetPageError(page);
     801                 :          0 :         unlock_page(page);
     802                 :          0 :         return -EIO;
     803                 :            : }
     804                 :            : 
     805                 :            : const struct address_space_operations isofs_symlink_aops = {
     806                 :            :         .readpage = rock_ridge_symlink_readpage
     807                 :            : };

Generated by: LCOV version 1.14