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

          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           0 : static void setup_rock_ridge(struct iso_directory_record *de,
      54             :                         struct inode *inode, struct rock_state *rs)
      55             : {
      56           0 :         rs->len = sizeof(struct iso_directory_record) + de->name_len[0];
      57           0 :         if (rs->len & 1)
      58           0 :                 (rs->len)++;
      59           0 :         rs->chr = (unsigned char *)de + rs->len;
      60           0 :         rs->len = *((unsigned char *)de) - rs->len;
      61           0 :         if (rs->len < 0)
      62           0 :                 rs->len = 0;
      63             : 
      64           0 :         if (ISOFS_SB(inode->i_sb)->s_rock_offset != -1) {
      65           0 :                 rs->len -= ISOFS_SB(inode->i_sb)->s_rock_offset;
      66           0 :                 rs->chr += ISOFS_SB(inode->i_sb)->s_rock_offset;
      67           0 :                 if (rs->len < 0)
      68           0 :                         rs->len = 0;
      69             :         }
      70           0 : }
      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           0 : static int rock_check_overflow(struct rock_state *rs, int sig)
     140             : {
     141           0 :         int len;
     142             : 
     143           0 :         switch (sig) {
     144             :         case SIG('S', 'P'):
     145             :                 len = sizeof(struct SU_SP_s);
     146             :                 break;
     147           0 :         case SIG('C', 'E'):
     148           0 :                 len = sizeof(struct SU_CE_s);
     149           0 :                 break;
     150           0 :         case SIG('E', 'R'):
     151           0 :                 len = sizeof(struct SU_ER_s);
     152           0 :                 break;
     153           0 :         case SIG('R', 'R'):
     154           0 :                 len = sizeof(struct RR_RR_s);
     155           0 :                 break;
     156           0 :         case SIG('P', 'X'):
     157           0 :                 len = sizeof(struct RR_PX_s);
     158           0 :                 break;
     159           0 :         case SIG('P', 'N'):
     160           0 :                 len = sizeof(struct RR_PN_s);
     161           0 :                 break;
     162             :         case SIG('S', 'L'):
     163             :                 len = sizeof(struct RR_SL_s);
     164             :                 break;
     165           0 :         case SIG('N', 'M'):
     166           0 :                 len = sizeof(struct RR_NM_s);
     167           0 :                 break;
     168           0 :         case SIG('C', 'L'):
     169           0 :                 len = sizeof(struct RR_CL_s);
     170           0 :                 break;
     171           0 :         case SIG('P', 'L'):
     172           0 :                 len = sizeof(struct RR_PL_s);
     173           0 :                 break;
     174           0 :         case SIG('T', 'F'):
     175           0 :                 len = sizeof(struct RR_TF_s);
     176           0 :                 break;
     177           0 :         case SIG('Z', 'F'):
     178           0 :                 len = sizeof(struct RR_ZF_s);
     179           0 :                 break;
     180           0 :         default:
     181           0 :                 len = 0;
     182           0 :                 break;
     183             :         }
     184           0 :         len += offsetof(struct rock_ridge, u);
     185           0 :         if (len > rs->len) {
     186           0 :                 printk(KERN_NOTICE "rock: directory entry would overflow "
     187             :                                 "storage\n");
     188           0 :                 printk(KERN_NOTICE "rock: sig=0x%02x, size=%d, remaining=%d\n",
     189             :                                 sig, len, rs->len);
     190           0 :                 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             :                 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           0 : 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           0 :                 case SIG('R', 'R'):
     358           0 :                         if ((rr->u.RR.flags[0] &
     359             :                              (RR_PX | RR_TF | RR_SL | RR_CL)) == 0)
     360           0 :                                 goto out;
     361             :                         break;
     362             : #endif
     363             :                 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             :                 case SIG('Z', 'F'): {
     543             :                         int algo;
     544             : 
     545             :                         if (ISOFS_SB(inode->i_sb)->s_nocompress)
     546             :                                 break;
     547             :                         algo = isonum_721(rr->u.ZF.algorithm);
     548             :                         if (algo == SIG('p', 'z')) {
     549             :                                 int block_shift =
     550             :                                         isonum_711(&rr->u.ZF.parms[1]);
     551             :                                 if (block_shift > 17) {
     552             :                                         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             :                                         ISOFS_I(inode)->i_file_format =
     562             :                                                 isofs_file_compressed;
     563             :                                         /*
     564             :                                          * Parameters to compression
     565             :                                          * algorithm (header size,
     566             :                                          * block size)
     567             :                                          */
     568             :                                         ISOFS_I(inode)->i_format_parm[0] =
     569             :                                                 isonum_711(&rr->u.ZF.parms[0]);
     570             :                                         ISOFS_I(inode)->i_format_parm[1] =
     571             :                                                 isonum_711(&rr->u.ZF.parms[1]);
     572             :                                         inode->i_size =
     573             :                                             isonum_733(rr->u.ZF.
     574             :                                                        real_size);
     575             :                                 }
     576             :                         } else {
     577             :                                 printk(KERN_WARNING
     578             :                                        "isofs: Unknown ZF compression "
     579             :                                                 "algorithm: %c%c\n",
     580             :                                        rr->u.ZF.algorithm[0],
     581             :                                        rr->u.ZF.algorithm[1]);
     582             :                         }
     583             :                         break;
     584             :                 }
     585             : #endif
     586             :                 default:
     587             :                         break;
     588             :                 }
     589             :         }
     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             :                 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           0 : out_noread:
     793           0 :         printk("unable to read i-node block");
     794           0 :         goto fail;
     795           0 : 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