diff options
-rw-r--r-- | fs/isofs/rock.c | 571 |
1 files changed, 285 insertions, 286 deletions
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index bbc348f0189..e981c040a49 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c @@ -90,82 +90,78 @@ int get_rock_ridge_filename(struct iso_directory_record *de, int len; unsigned char *chr; CONTINUE_DECLS; - int retnamlen = 0, truncate = 0; + struct rock_ridge *rr; + int sig; + int retnamlen = 0; + int truncate = 0; if (!ISOFS_SB(inode->i_sb)->s_rock) return 0; *retname = 0; SETUP_ROCK_RIDGE(de, chr, len); - repeat: - { - struct rock_ridge *rr; - int sig; - - while (len > 2) { /* There may be one byte for padding somewhere */ - rr = (struct rock_ridge *)chr; - if (rr->len < 3) - goto out; /* Something got screwed up here */ - sig = isonum_721(chr); - chr += rr->len; - len -= rr->len; - if (len < 0) - goto out; /* corrupted isofs */ - - switch (sig) { - case SIG('R', 'R'): - if ((rr->u.RR.flags[0] & RR_NM) == 0) - goto out; +repeat: + + while (len > 2) { /* There may be one byte for padding somewhere */ + rr = (struct rock_ridge *)chr; + if (rr->len < 3) + goto out; /* Something got screwed up here */ + sig = isonum_721(chr); + chr += rr->len; + len -= rr->len; + if (len < 0) + goto out; /* corrupted isofs */ + + switch (sig) { + case SIG('R', 'R'): + if ((rr->u.RR.flags[0] & RR_NM) == 0) + goto out; + break; + case SIG('S', 'P'): + CHECK_SP(goto out); + break; + case SIG('C', 'E'): + CHECK_CE; + break; + case SIG('N', 'M'): + if (truncate) break; - case SIG('S', 'P'): - CHECK_SP(goto out); + if (rr->len < 5) break; - case SIG('C', 'E'): - CHECK_CE; + /* + * If the flags are 2 or 4, this indicates '.' or '..'. + * We don't want to do anything with this, because it + * screws up the code that calls us. We don't really + * care anyways, since we can just use the non-RR + * name. + */ + if (rr->u.NM.flags & 6) break; - case SIG('N', 'M'): - if (truncate) - break; - if (rr->len < 5) - break; - /* - * If the flags are 2 or 4, this indicates '.' or '..'. - * We don't want to do anything with this, because it - * screws up the code that calls us. We don't really - * care anyways, since we can just use the non-RR - * name. - */ - if (rr->u.NM.flags & 6) { - break; - } - if (rr->u.NM.flags & ~1) { - printk - ("Unsupported NM flag settings (%d)\n", - rr->u.NM.flags); - break; - } - if ((strlen(retname) + rr->len - 5) >= 254) { - truncate = 1; - break; - } - strncat(retname, rr->u.NM.name, rr->len - 5); - retnamlen += rr->len - 5; + if (rr->u.NM.flags & ~1) { + printk("Unsupported NM flag settings (%d)\n", + rr->u.NM.flags); break; - case SIG('R', 'E'): - if (buffer) - kfree(buffer); - return -1; - default: + } + if ((strlen(retname) + rr->len - 5) >= 254) { + truncate = 1; break; } + strncat(retname, rr->u.NM.name, rr->len - 5); + retnamlen += rr->len - 5; + break; + case SIG('R', 'E'): + if (buffer) + kfree(buffer); + return -1; + default: + break; } } MAYBE_CONTINUE(repeat, inode); - if (buffer) - kfree(buffer); + kfree(buffer); return retnamlen; /* If 0, this file did not have a NM field */ - out: +out: if (buffer) kfree(buffer); return 0; @@ -178,6 +174,11 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de, int len; unsigned char *chr; int symlink_len = 0; + int cnt, sig; + struct inode *reloc; + struct rock_ridge *rr; + int rootflag; + CONTINUE_DECLS; if (!ISOFS_SB(inode->i_sb)->s_rock) @@ -191,238 +192,237 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de, len = 0; } - repeat: - { - int cnt, sig; - struct inode *reloc; - struct rock_ridge *rr; - int rootflag; - - while (len > 2) { /* There may be one byte for padding somewhere */ - rr = (struct rock_ridge *)chr; - if (rr->len < 3) - goto out; /* Something got screwed up here */ - sig = isonum_721(chr); - chr += rr->len; - len -= rr->len; - if (len < 0) - goto out; /* corrupted isofs */ - - switch (sig) { +repeat: + while (len > 2) { /* There may be one byte for padding somewhere */ + rr = (struct rock_ridge *)chr; + if (rr->len < 3) + goto out; /* Something got screwed up here */ + sig = isonum_721(chr); + chr += rr->len; + len -= rr->len; + if (len < 0) + goto out; /* corrupted isofs */ + + switch (sig) { #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */ - case SIG('R', 'R'): - if ((rr->u.RR.flags[0] & - (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) - goto out; - break; + case SIG('R', 'R'): + if ((rr->u.RR.flags[0] & + (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) + goto out; + break; #endif - case SIG('S', 'P'): - CHECK_SP(goto out); - break; - case SIG('C', 'E'): - CHECK_CE; - break; - case SIG('E', 'R'): - ISOFS_SB(inode->i_sb)->s_rock = 1; - printk(KERN_DEBUG "ISO 9660 Extensions: "); - { - int p; - for (p = 0; p < rr->u.ER.len_id; p++) - printk("%c", rr->u.ER.data[p]); + case SIG('S', 'P'): + CHECK_SP(goto out); + break; + case SIG('C', 'E'): + CHECK_CE; + break; + case SIG('E', 'R'): + ISOFS_SB(inode->i_sb)->s_rock = 1; + printk(KERN_DEBUG "ISO 9660 Extensions: "); + { + int p; + for (p = 0; p < rr->u.ER.len_id; p++) + printk("%c", rr->u.ER.data[p]); + } + printk("\n"); + break; + case SIG('P', 'X'): + inode->i_mode = isonum_733(rr->u.PX.mode); + inode->i_nlink = isonum_733(rr->u.PX.n_links); + inode->i_uid = isonum_733(rr->u.PX.uid); + inode->i_gid = isonum_733(rr->u.PX.gid); + break; + case SIG('P', 'N'): + { + int high, low; + high = isonum_733(rr->u.PN.dev_high); + low = isonum_733(rr->u.PN.dev_low); + /* + * The Rock Ridge standard specifies that if + * sizeof(dev_t) <= 4, then the high field is + * unused, and the device number is completely + * stored in the low field. Some writers may + * ignore this subtlety, + * and as a result we test to see if the entire + * device number is + * stored in the low field, and use that. + */ + if ((low & ~0xff) && high == 0) { + inode->i_rdev = + MKDEV(low >> 8, low & 0xff); + } else { + inode->i_rdev = + MKDEV(high, low); } - printk("\n"); - break; - case SIG('P', 'X'): - inode->i_mode = isonum_733(rr->u.PX.mode); - inode->i_nlink = isonum_733(rr->u.PX.n_links); - inode->i_uid = isonum_733(rr->u.PX.uid); - inode->i_gid = isonum_733(rr->u.PX.gid); - break; - case SIG('P', 'N'): - { - int high, low; - high = isonum_733(rr->u.PN.dev_high); - low = isonum_733(rr->u.PN.dev_low); - /* - * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4, - * then the high field is unused, and the device number is completely - * stored in the low field. Some writers may ignore this subtlety, - * and as a result we test to see if the entire device number is - * stored in the low field, and use that. - */ - if ((low & ~0xff) && high == 0) { - inode->i_rdev = - MKDEV(low >> 8, low & 0xff); - } else { - inode->i_rdev = - MKDEV(high, low); + } + break; + case SIG('T', 'F'): + /* + * Some RRIP writers incorrectly place ctime in the + * TF_CREATE field. Try to handle this correctly for + * either case. + */ + /* Rock ridge never appears on a High Sierra disk */ + cnt = 0; + if (rr->u.TF.flags & TF_CREATE) { + inode->i_ctime.tv_sec = + iso_date(rr->u.TF.times[cnt++].time, + 0); + inode->i_ctime.tv_nsec = 0; + } + if (rr->u.TF.flags & TF_MODIFY) { + inode->i_mtime.tv_sec = + iso_date(rr->u.TF.times[cnt++].time, + 0); + inode->i_mtime.tv_nsec = 0; + } + if (rr->u.TF.flags & TF_ACCESS) { + inode->i_atime.tv_sec = + iso_date(rr->u.TF.times[cnt++].time, + 0); + inode->i_atime.tv_nsec = 0; + } + if (rr->u.TF.flags & TF_ATTRIBUTES) { + inode->i_ctime.tv_sec = + iso_date(rr->u.TF.times[cnt++].time, + 0); + inode->i_ctime.tv_nsec = 0; + } + break; + case SIG('S', 'L'): + { + int slen; + struct SL_component *slp; + struct SL_component *oldslp; + slen = rr->len - 5; + slp = &rr->u.SL.link; + inode->i_size = symlink_len; + while (slen > 1) { + rootflag = 0; + switch (slp->flags & ~1) { + case 0: + inode->i_size += + slp->len; + break; + case 2: + inode->i_size += 1; + break; + case 4: + inode->i_size += 2; + break; + case 8: + rootflag = 1; + inode->i_size += 1; + break; + default: + printk("Symlink component flag " + "not implemented\n"); } - } - break; - case SIG('T', 'F'): - /* Some RRIP writers incorrectly place ctime in the TF_CREATE field. - Try to handle this correctly for either case. */ - cnt = 0; /* Rock ridge never appears on a High Sierra disk */ - if (rr->u.TF.flags & TF_CREATE) { - inode->i_ctime.tv_sec = - iso_date(rr->u.TF.times[cnt++].time, - 0); - inode->i_ctime.tv_nsec = 0; - } - if (rr->u.TF.flags & TF_MODIFY) { - inode->i_mtime.tv_sec = - iso_date(rr->u.TF.times[cnt++].time, - 0); - inode->i_mtime.tv_nsec = 0; - } - if (rr->u.TF.flags & TF_ACCESS) { - inode->i_atime.tv_sec = - iso_date(rr->u.TF.times[cnt++].time, - 0); - inode->i_atime.tv_nsec = 0; - } - if (rr->u.TF.flags & TF_ATTRIBUTES) { - inode->i_ctime.tv_sec = - iso_date(rr->u.TF.times[cnt++].time, - 0); - inode->i_ctime.tv_nsec = 0; - } - break; - case SIG('S', 'L'): - { - int slen; - struct SL_component *slp; - struct SL_component *oldslp; - slen = rr->len - 5; - slp = &rr->u.SL.link; - inode->i_size = symlink_len; - while (slen > 1) { - rootflag = 0; - switch (slp->flags & ~1) { - case 0: + slen -= slp->len + 2; + oldslp = slp; + slp = (struct SL_component *) + (((char *)slp) + slp->len + 2); + + if (slen < 2) { + if (((rr->u.SL. + flags & 1) != 0) + && + ((oldslp-> + flags & 1) == 0)) inode->i_size += - slp->len; - break; - case 2: - inode->i_size += 1; - break; - case 4: - inode->i_size += 2; - break; - case 8: - rootflag = 1; - inode->i_size += 1; - break; - default: - printk - ("Symlink component flag not implemented\n"); - } - slen -= slp->len + 2; - oldslp = slp; - slp = - (struct SL_component - *)(((char *)slp) + - slp->len + 2); - - if (slen < 2) { - if (((rr->u.SL. - flags & 1) != 0) - && - ((oldslp-> - flags & 1) == 0)) - inode->i_size += - 1; - break; - } - - /* - * If this component record isn't continued, then append a '/'. - */ - if (!rootflag - && (oldslp->flags & 1) == 0) - inode->i_size += 1; + 1; + break; } + + /* + * If this component record isn't + * continued, then append a '/'. + */ + if (!rootflag + && (oldslp->flags & 1) == 0) + inode->i_size += 1; } - symlink_len = inode->i_size; - break; - case SIG('R', 'E'): - printk(KERN_WARNING - "Attempt to read inode for relocated directory\n"); + } + symlink_len = inode->i_size; + break; + case SIG('R', 'E'): + printk(KERN_WARNING "Attempt to read inode for " + "relocated directory\n"); + goto out; + case SIG('C', 'L'): + ISOFS_I(inode)->i_first_extent = + isonum_733(rr->u.CL.location); + reloc = + isofs_iget(inode->i_sb, + ISOFS_I(inode)->i_first_extent, + 0); + if (!reloc) goto out; - case SIG('C', 'L'): - ISOFS_I(inode)->i_first_extent = - isonum_733(rr->u.CL.location); - reloc = - isofs_iget(inode->i_sb, - ISOFS_I(inode)->i_first_extent, - 0); - if (!reloc) - goto out; - inode->i_mode = reloc->i_mode; - inode->i_nlink = reloc->i_nlink; - inode->i_uid = reloc->i_uid; - inode->i_gid = reloc->i_gid; - inode->i_rdev = reloc->i_rdev; - inode->i_size = reloc->i_size; - inode->i_blocks = reloc->i_blocks; - inode->i_atime = reloc->i_atime; - inode->i_ctime = reloc->i_ctime; - inode->i_mtime = reloc->i_mtime; - iput(reloc); - break; + inode->i_mode = reloc->i_mode; + inode->i_nlink = reloc->i_nlink; + inode->i_uid = reloc->i_uid; + inode->i_gid = reloc->i_gid; + inode->i_rdev = reloc->i_rdev; + inode->i_size = reloc->i_size; + inode->i_blocks = reloc->i_blocks; + inode->i_atime = reloc->i_atime; + inode->i_ctime = reloc->i_ctime; + inode->i_mtime = reloc->i_mtime; + iput(reloc); + break; #ifdef CONFIG_ZISOFS - case SIG('Z', 'F'): - if (!ISOFS_SB(inode->i_sb)->s_nocompress) { - int algo; - algo = isonum_721(rr->u.ZF.algorithm); - if (algo == SIG('p', 'z')) { - int block_shift = - isonum_711(&rr->u.ZF. - parms[1]); - if (block_shift < - PAGE_CACHE_SHIFT - || block_shift > 17) { - printk(KERN_WARNING - "isofs: Can't handle ZF block size of 2^%d\n", - block_shift); - } else { - /* Note: we don't change i_blocks here */ - ISOFS_I(inode)-> - i_file_format = - isofs_file_compressed; - /* Parameters to compression algorithm (header size, block size) */ - ISOFS_I(inode)-> - i_format_parm[0] = - isonum_711(&rr->u. - ZF. - parms - [0]); - ISOFS_I(inode)-> - i_format_parm[1] = - isonum_711(&rr->u. - ZF. - parms - [1]); - inode->i_size = - isonum_733(rr->u.ZF. - real_size); - } - } else { - printk(KERN_WARNING - "isofs: Unknown ZF compression algorithm: %c%c\n", - rr->u.ZF.algorithm[0], - rr->u.ZF.algorithm[1]); - } - } - break; -#endif - default: + case SIG('Z', 'F'): { + int algo; + + if (ISOFS_SB(inode->i_sb)->s_nocompress) break; + algo = isonum_721(rr->u.ZF.algorithm); + if (algo == SIG('p', 'z')) { + int block_shift = + isonum_711(&rr->u.ZF.parms[1]); + if (block_shift < PAGE_CACHE_SHIFT + || block_shift > 17) { + printk(KERN_WARNING "isofs: " + "Can't handle ZF block " + "size of 2^%d\n", + block_shift); + } else { + /* + * Note: we don't change + * i_blocks here + */ + ISOFS_I(inode)->i_file_format = + isofs_file_compressed; + /* + * Parameters to compression + * algorithm (header size, + * block size) + */ + ISOFS_I(inode)->i_format_parm[0] = + isonum_711(&rr->u.ZF.parms[0]); + ISOFS_I(inode)->i_format_parm[1] = + isonum_711(&rr->u.ZF.parms[1]); + inode->i_size = + isonum_733(rr->u.ZF. + real_size); + } + } else { + printk(KERN_WARNING + "isofs: Unknown ZF compression " + "algorithm: %c%c\n", + rr->u.ZF.algorithm[0], + rr->u.ZF.algorithm[1]); } + break; + } +#endif + default: + break; } } MAYBE_CONTINUE(repeat, inode); - out: +out: if (buffer) kfree(buffer); return 0; @@ -553,8 +553,8 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page) SETUP_ROCK_RIDGE(raw_inode, chr, len); - repeat: - while (len > 2) { /* There may be one byte for padding somewhere */ +repeat: + while (len > 2) { /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *)chr; if (rr->len < 3) goto out; /* Something got screwed up here */ @@ -586,8 +586,7 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page) } } MAYBE_CONTINUE(repeat, inode); - if (buffer) - kfree(buffer); + kfree(buffer); if (rpnt == link) goto fail; @@ -600,19 +599,19 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page) return 0; /* error exit from macro */ - out: +out: if (buffer) kfree(buffer); goto fail; - out_noread: +out_noread: printk("unable to read i-node block"); goto fail; - out_bad_span: +out_bad_span: printk("symlink spans iso9660 blocks\n"); - fail: +fail: brelse(bh); unlock_kernel(); - error: +error: SetPageError(page); kunmap(page); unlock_page(page); |