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

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

Generated by: LCOV version 1.10