/* *Wethinkthere'sarecordoftype`sig'atrs->chr.Parsethesignature *andmakesurethatthere'sreallyroomforarecordofthattype.
*/ staticint rock_check_overflow(struct rock_state *rs, int sig)
{ int len;
switch (sig) { case SIG('S', 'P'):
len = sizeof(struct SU_SP_s); break; case SIG('C', 'E'):
len = sizeof(struct SU_CE_s); break; case SIG('E', 'R'):
len = sizeof(struct SU_ER_s); break; case SIG('R', 'R'):
len = sizeof(struct RR_RR_s); break; case SIG('P', 'X'):
len = sizeof(struct RR_PX_s); break; case SIG('P', 'N'):
len = sizeof(struct RR_PN_s); break; case SIG('S', 'L'):
len = sizeof(struct RR_SL_s); break; case SIG('N', 'M'):
len = sizeof(struct RR_NM_s); break; case SIG('C', 'L'):
len = sizeof(struct RR_CL_s); break; case SIG('P', 'L'):
len = sizeof(struct RR_PL_s); break; case SIG('T', 'F'):
len = sizeof(struct RR_TF_s); break; case SIG('Z', 'F'):
len = sizeof(struct RR_ZF_s); break; default:
len = 0; break;
}
len += offsetof(struct rock_ridge, u); if (len > rs->len) {
printk(KERN_NOTICE "rock: directory entry would overflow " "storage\n");
printk(KERN_NOTICE "rock: sig=0x%02x, size=%d, remaining=%d\n",
sig, len, rs->len); return -EIO;
} return0;
}
/* *returnlengthofnamefield;0:notfound,-1:tobeignored
*/ int get_rock_ridge_filename(struct iso_directory_record *de, char *retname, struct inode *inode)
{ struct rock_state rs; struct rock_ridge *rr; int sig; int retnamlen = 0; int truncate = 0; int ret = 0; char *p; int len;
if (!ISOFS_SB(inode->i_sb)->s_rock) return0;
*retname = 0;
while (rs.len > 2) { /* There may be one byte for padding somewhere */
rr = (struct rock_ridge *)rs.chr; /* *Ignorerockridgeinfoifrr->lenisoutofrange,but *don'treturn-EIObecausethatwouldmakethefile *invisible.
*/ if (rr->len < 3) goto out; /* Something got screwed up here */
sig = isonum_721(rs.chr); if (rock_check_overflow(&rs, sig)) goto eio;
rs.chr += rr->len;
rs.len -= rr->len; /* *Asabove,justignoretherockridgeinfoifrr->len *isbogus.
*/ if (rs.len < 0) goto out; /* Something got screwed up here */
switch (sig) { case SIG('R', 'R'): if ((rr->u.RR.flags[0] & RR_NM) == 0) goto out; break; case SIG('S', 'P'): if (check_sp(rr, inode)) goto out; break; case SIG('C', 'E'):
rs.cont_extent = isonum_733(rr->u.CE.extent);
rs.cont_offset = isonum_733(rr->u.CE.offset);
rs.cont_size = isonum_733(rr->u.CE.size); break; case SIG('N', 'M'): if (truncate) break; if (rr->len < 5) break; /* *Iftheflagsare2or4,thisindicates'.'or'..'. *Wedon'twanttodoanythingwiththis,becauseit *screwsupthecodethatcallsus.Wedon'treally *careanyways,sincewecanjustusethenon-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;
}
len = rr->len - 5; if (retnamlen + len >= 254) {
truncate = 1; break;
}
p = memchr(rr->u.NM.name, '\0', len); if (unlikely(p))
len = p - rr->u.NM.name;
memcpy(retname + retnamlen, rr->u.NM.name, len);
retnamlen += len;
retname[retnamlen] = '\0'; break; case SIG('R', 'E'):
kfree(rs.buffer); return -1; default: break;
}
}
ret = rock_continue(&rs); if (ret == 0) goto repeat; if (ret == 1) return retnamlen; /* If 0, this file did not have a NM field */
out:
kfree(rs.buffer); return ret;
eio:
ret = -EIO; goto out;
}
#define RR_REGARD_XA 1 #define RR_RELOC_DE 2
staticint
parse_rock_ridge_inode_internal(struct iso_directory_record *de, struct inode *inode, int flags)
{ int symlink_len = 0; int cnt, sig; unsignedint reloc_block; struct inode *reloc; struct rock_ridge *rr; int rootflag; struct rock_state rs; int ret = 0;
repeat: while (rs.len > 2) { /* There may be one byte for padding somewhere */
rr = (struct rock_ridge *)rs.chr; /* *Ignorerockridgeinfoifrr->lenisoutofrange,but *don'treturn-EIObecausethatwouldmakethefile *invisible.
*/ if (rr->len < 3) goto out; /* Something got screwed up here */
sig = isonum_721(rs.chr); if (rock_check_overflow(&rs, sig)) goto eio;
rs.chr += rr->len;
rs.len -= rr->len; /* *Asabove,justignoretherockridgeinfoifrr->len *isbogus.
*/ if (rs.len < 0) goto out; /* Something got screwed up here */
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; #endif case SIG('S', 'P'): if (check_sp(rr, inode)) goto out; break; case SIG('C', 'E'):
rs.cont_extent = isonum_733(rr->u.CE.extent);
rs.cont_offset = isonum_733(rr->u.CE.offset);
rs.cont_size = isonum_733(rr->u.CE.size); break; case SIG('E', 'R'): /* Invalid length of ER tag id? */ if (rr->u.ER.len_id + offsetof(struct rock_ridge, u.ER.data) > rr->len) goto out;
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(KERN_CONT "%c", rr->u.ER.data[p]);
}
printk(KERN_CONT "\n"); break; case SIG('P', 'X'):
inode->i_mode = isonum_733(rr->u.PX.mode);
set_nlink(inode, isonum_733(rr->u.PX.n_links));
i_uid_write(inode, isonum_733(rr->u.PX.uid));
i_gid_write(inode, 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); /* *TheRockRidgestandardspecifiesthatif *sizeof(dev_t)<=4,thenthehighfieldis *unused,andthedevicenumberiscompletely *storedinthelowfield.Somewritersmay *ignorethissubtlety, *andasaresultwetesttoseeiftheentire *devicenumberis *storedinthelowfield,andusethat.
*/ 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'): { int flags, size, slen;
int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode, int relocated)
{ int flags = relocated ? RR_RELOC_DE : 0; int result = parse_rock_ridge_inode_internal(de, inode, flags);
repeat: while (rs.len > 2) { /* There may be one byte for padding somewhere */
rr = (struct rock_ridge *)rs.chr; if (rr->len < 3) goto out; /* Something got screwed up here */
sig = isonum_721(rs.chr); if (rock_check_overflow(&rs, sig)) goto out;
rs.chr += rr->len;
rs.len -= rr->len; if (rs.len < 0) goto out; /* corrupted isofs */
switch (sig) { case SIG('R', 'R'): if ((rr->u.RR.flags[0] & RR_SL) == 0) goto out; break; case SIG('S', 'P'): if (check_sp(rr, inode)) goto out; break; case SIG('S', 'L'):
rpnt = get_symlink_chunk(rpnt, rr,
link + (PAGE_SIZE - 1)); if (rpnt == NULL) goto out; break; case SIG('C', 'E'): /* This tells is if there is a continuation record */
rs.cont_extent = isonum_733(rr->u.CE.extent);
rs.cont_offset = isonum_733(rr->u.CE.offset);
rs.cont_size = isonum_733(rr->u.CE.size); break; default: break;
}
}
ret = rock_continue(&rs); if (ret == 0) goto repeat; if (ret < 0) goto fail;
if (rpnt == link) goto fail;
brelse(bh);
*rpnt = '\0';
ret = 0;
end:
folio_end_read(folio, ret == 0); return ret;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.