/*! Get @return length of name field; 0: not found, -1: to be ignored */ int get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir, /*out*/ char * psz_name, /*in/out*/ iso9660_stat_t *p_stat) { int len; unsigned char *chr; int symlink_len = 0; CONTINUE_DECLS; int i_namelen = 0; int truncate=0; if (!p_stat || nope == p_stat->rr.b3_rock) return 0; *psz_name = 0; SETUP_ROCK_RIDGE(p_iso9660_dir, chr, len); /*repeat:*/ { iso_extension_record_t * rr; int sig; int rootflag; while (len > 1){ /* There may be one byte for padding somewhere */ rr = (iso_extension_record_t *) chr; if (rr->len == 0) goto out; /* Something got screwed up here */ sig = *chr+(*(chr+1) << 8); chr += rr->len; len -= rr->len; switch(sig){ case SIG('S','P'): CHECK_SP(goto out); break; case SIG('C','E'): { iso711_t i_fname = from_711(p_iso9660_dir->filename.len); if ('\0' == p_iso9660_dir->filename.str[1] && 1 == i_fname) break; if ('\1' == p_iso9660_dir->filename.str[1] && 1 == i_fname) break; } CHECK_CE; break; case SIG('E','R'): p_stat->rr.b3_rock = yep; cdio_debug("ISO 9660 Extensions: "); { int p; for(p=0;p<rr->u.ER.len_id;p++) cdio_debug("%c",rr->u.ER.data[p]); } break; case SIG('N','M'): /* Alternate name */ p_stat->rr.b3_rock = yep; if (truncate) break; if (rr->u.NM.flags & ISO_ROCK_NM_PARENT) { i_namelen = sizeof(".."); strncat(psz_name, "..", i_namelen); } else if (rr->u.NM.flags & ISO_ROCK_NM_CURRENT) { i_namelen = sizeof("."); strncat(psz_name, ".", i_namelen); break; } if (rr->u.NM.flags & ~1) { cdio_info("Unsupported NM flag settings (%d)",rr->u.NM.flags); break; } if((strlen(psz_name) + rr->len - 5) >= 254) { truncate = 1; break; } strncat(psz_name, rr->u.NM.name, rr->len - 5); i_namelen += rr->len - 5; break; case SIG('P','X'): /* POSIX file attributes */ p_stat->rr.st_mode = from_733(rr->u.PX.st_mode); p_stat->rr.st_nlinks = from_733(rr->u.PX.st_nlinks); p_stat->rr.st_uid = from_733(rr->u.PX.st_uid); p_stat->rr.st_gid = from_733(rr->u.PX.st_gid); p_stat->rr.b3_rock = yep; break; case SIG('S','L'): { /* Symbolic link */ uint8_t slen; iso_rock_sl_part_t * p_sl; iso_rock_sl_part_t * p_oldsl; slen = rr->len - 5; p_sl = &rr->u.SL.link; p_stat->rr.i_symlink = symlink_len; while (slen > 1){ rootflag = 0; switch(p_sl->flags &~1){ case 0: realloc_symlink(p_stat, p_sl->len); memcpy(&(p_stat->rr.psz_symlink[p_stat->rr.i_symlink]), p_sl->text, p_sl->len); p_stat->rr.i_symlink += p_sl->len; break; case 4: realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.'; /* continue into next case. */ case 2: realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.'; break; case 8: rootflag = 1; realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/'; break; default: cdio_warn("Symlink component flag not implemented"); } slen -= p_sl->len + 2; p_oldsl = p_sl; p_sl = (iso_rock_sl_part_t *) (((char *) p_sl) + p_sl->len + 2); if (slen < 2) { if (((rr->u.SL.flags & 1) != 0) && ((p_oldsl->flags & 1) == 0)) p_stat->rr.i_symlink += 1; break; } /* * If this component record isn't continued, then append a '/'. */ if (!rootflag && (p_oldsl->flags & 1) == 0) { realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/'; } } } symlink_len = p_stat->rr.i_symlink; realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[symlink_len]='\0'; break; case SIG('R','E'): free(buffer); return -1; case SIG('T','F'): /* Time stamp(s) for a file */ { int cnt = 0; add_time(ISO_ROCK_TF_CREATE, create); add_time(ISO_ROCK_TF_MODIFY, modify); add_time(ISO_ROCK_TF_ACCESS, access); add_time(ISO_ROCK_TF_ATTRIBUTES, attributes); add_time(ISO_ROCK_TF_BACKUP, backup); add_time(ISO_ROCK_TF_EXPIRATION, expiration); add_time(ISO_ROCK_TF_EFFECTIVE, effective); p_stat->rr.b3_rock = yep; break; } default: break; } } } free(buffer); return i_namelen; /* If 0, this file did not have a NM field */ out: free(buffer); return 0; }
static int parse_rock_ridge_stat_internal(iso9660_dir_t *p_iso9660_dir, iso9660_stat_t *p_stat, int regard_xa) { int len; unsigned char * chr; int symlink_len = 0; CONTINUE_DECLS; if (nope == p_stat->rr.b3_rock) return 0; SETUP_ROCK_RIDGE(p_iso9660_dir, chr, len); if (regard_xa) { chr+=14; len-=14; if (len<0) len=0; } /* repeat:*/ { int sig; iso_extension_record_t * rr; int rootflag; while (len > 1){ /* There may be one byte for padding somewhere */ rr = (iso_extension_record_t *) chr; if (rr->len == 0) goto out; /* Something got screwed up here */ sig = from_721(*chr); chr += rr->len; len -= rr->len; switch(sig){ case SIG('S','P'): CHECK_SP(goto out); break; case SIG('C','E'): CHECK_CE; break; case SIG('E','R'): p_stat->rr.b3_rock = yep; cdio_debug("ISO 9660 Extensions: "); { int p; for(p=0;p<rr->u.ER.len_id;p++) cdio_debug("%c",rr->u.ER.data[p]); } break; case SIG('P','X'): p_stat->rr.st_mode = from_733(rr->u.PX.st_mode); p_stat->rr.st_nlinks = from_733(rr->u.PX.st_nlinks); p_stat->rr.st_uid = from_733(rr->u.PX.st_uid); p_stat->rr.st_gid = from_733(rr->u.PX.st_gid); break; case SIG('P','N'): /* Device major,minor number */ { int32_t high, low; high = from_733(rr->u.PN.dev_high); low = from_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) { p_stat->rr.i_rdev = CDIO_MKDEV(low >> 8, low & 0xff); } else { p_stat->rr.i_rdev = CDIO_MKDEV(high, low); } } break; case SIG('T','F'): /* Time stamp(s) for a file */ { int cnt = 0; add_time(ISO_ROCK_TF_CREATE, create); add_time(ISO_ROCK_TF_MODIFY, modify); add_time(ISO_ROCK_TF_ACCESS, access); add_time(ISO_ROCK_TF_ATTRIBUTES, attributes); add_time(ISO_ROCK_TF_BACKUP, backup); add_time(ISO_ROCK_TF_EXPIRATION, expiration); add_time(ISO_ROCK_TF_EFFECTIVE, effective); p_stat->rr.b3_rock = yep; break; } case SIG('S','L'): { /* Symbolic link */ uint8_t slen; iso_rock_sl_part_t * p_sl; iso_rock_sl_part_t * p_oldsl; slen = rr->len - 5; p_sl = &rr->u.SL.link; p_stat->rr.i_symlink = symlink_len; while (slen > 1){ rootflag = 0; switch(p_sl->flags &~1){ case 0: realloc_symlink(p_stat, p_sl->len); memcpy(&(p_stat->rr.psz_symlink[p_stat->rr.i_symlink]), p_sl->text, p_sl->len); p_stat->rr.i_symlink += p_sl->len; break; case 4: realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.'; /* continue into next case. */ case 2: realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.'; break; case 8: rootflag = 1; realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/'; p_stat->rr.i_symlink++; break; default: cdio_warn("Symlink component flag not implemented"); } slen -= p_sl->len + 2; p_oldsl = p_sl; p_sl = (iso_rock_sl_part_t *) (((char *) p_sl) + p_sl->len + 2); if (slen < 2) { if (((rr->u.SL.flags & 1) != 0) && ((p_oldsl->flags & 1) == 0)) p_stat->rr.i_symlink += 1; break; } /* * If this component record isn't continued, then append a '/'. */ if (!rootflag && (p_oldsl->flags & 1) == 0) { realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/'; } } } symlink_len = p_stat->rr.i_symlink; realloc_symlink(p_stat, 1); p_stat->rr.psz_symlink[symlink_len]='\0'; break; case SIG('R','E'): cdio_warn("Attempt to read p_stat for relocated directory"); goto out; #ifdef FINISHED case SIG('C','L'): { iso9660_stat_t * reloc; ISOFS_I(p_stat)->i_first_extent = from_733(rr->u.CL.location); reloc = isofs_iget(p_stat->rr.i_sb, p_stat->rr.i_first_extent, 0); if (!reloc) goto out; p_stat->rr.st_mode = reloc->st_mode; p_stat->rr.st_nlinks = reloc->st_nlinks; p_stat->rr.st_uid = reloc->st_uid; p_stat->rr.st_gid = reloc->st_gid; p_stat->rr.i_rdev = reloc->i_rdev; p_stat->rr.i_symlink = reloc->i_symlink; p_stat->rr.i_blocks = reloc->i_blocks; p_stat->rr.i_atime = reloc->i_atime; p_stat->rr.i_ctime = reloc->i_ctime; p_stat->rr.i_mtime = reloc->i_mtime; iput(reloc); } break; #endif default: break; } }
int find_rock_ridge_relocation(struct iso_directory_record * de, struct inode * inode) { int flag; int len; int retval; unsigned char * chr; CONTINUE_DECLS; flag = 0; /* If this is a '..' then we are looking for the parent, otherwise we are looking for the child */ if (de->name[0]==1 && de->name_len[0]==1) flag = 1; /* Return value if we do not find appropriate record. */ retval = isonum_733 (de->extent); if (!inode->i_sb->u.isofs_sb.s_rock) return retval; SETUP_ROCK_RIDGE(de, chr, len); repeat: { int rrflag, sig; struct rock_ridge * rr; while (len > 1){ /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *) chr; if (rr->len == 0) goto out; /* Something got screwed up here */ sig = isonum_721(chr); chr += rr->len; len -= rr->len; switch(sig){ case SIG('R','R'): rrflag = rr->u.RR.flags[0]; if (flag && !(rrflag & RR_PL)) goto out; if (!flag && !(rrflag & RR_CL)) goto out; break; case SIG('S','P'): CHECK_SP(goto out); break; case SIG('C','L'): if (flag == 0) { retval = isonum_733(rr->u.CL.location); goto out; } break; case SIG('P','L'): if (flag != 0) { retval = isonum_733(rr->u.PL.location); goto out; } break; case SIG('C','E'): CHECK_CE; /* This tells is if there is a continuation record */ break; default: break; } } } MAYBE_CONTINUE(repeat, inode); return retval; out: if(buffer) kfree(buffer); return retval; }
int parse_rock_ridge_inode_internal(struct iso_directory_record * de, struct inode * inode,int regard_xa){ int len; unsigned char * chr; int symlink_len = 0; CONTINUE_DECLS; if (!inode->i_sb->u.isofs_sb.s_rock) return 0; SETUP_ROCK_RIDGE(de, chr, len); if (regard_xa) { chr+=14; len-=14; if (len<0) len=0; }; repeat: { int cnt, sig; struct inode * reloc; struct rock_ridge * rr; int rootflag; while (len > 1){ /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *) chr; if (rr->len == 0) goto out; /* Something got screwed up here */ sig = isonum_721(chr); chr += rr->len; len -= rr->len; 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'): CHECK_SP(goto out); break; case SIG('C','E'): CHECK_CE; break; case SIG('E','R'): inode->i_sb->u.isofs_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); } } 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 = iso_date(rr->u.TF.times[cnt++].time, 0); if(rr->u.TF.flags & TF_MODIFY) inode->i_mtime = iso_date(rr->u.TF.times[cnt++].time, 0); if(rr->u.TF.flags & TF_ACCESS) inode->i_atime = iso_date(rr->u.TF.times[cnt++].time, 0); if(rr->u.TF.flags & TF_ATTRIBUTES) inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 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"); } 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; } } 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'): inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location); reloc = iget(inode->i_sb, (inode->u.isofs_i.i_first_extent << inode -> i_sb -> u.isofs_sb.s_log_zone_size)); 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; #ifdef CONFIG_ZISOFS case SIG('Z','F'): if ( !inode->i_sb->u.isofs_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 */ inode->u.isofs_i.i_file_format = isofs_file_compressed; /* Parameters to compression algorithm (header size, block size) */ inode->u.isofs_i.i_format_parm[0] = isonum_711(&rr->u.ZF.parms[0]); inode->u.isofs_i.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; } }
/* return length of name field; 0: not found, -1: to be ignored */ int get_rock_ridge_filename(struct iso_directory_record * de, char * retname, struct inode * inode) { int len; unsigned char * chr; CONTINUE_DECLS; int retnamlen = 0, truncate=0; if (!inode->i_sb->u.isofs_sb.s_rock) return 0; *retname = 0; SETUP_ROCK_RIDGE(de, chr, len); repeat: { struct rock_ridge * rr; int sig; while (len > 1){ /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *) chr; if (rr->len == 0) goto out; /* Something got screwed up here */ sig = isonum_721(chr); chr += rr->len; len -= rr->len; 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; /* * 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; break; case SIG('R','E'): if (buffer) kfree(buffer); return -1; default: break; } } } MAYBE_CONTINUE(repeat,inode); return retnamlen; /* If 0, this file did not have a NM field */ out: if(buffer) kfree(buffer); return 0; }
int parse_rock_ridge_inode(struct iso_directory_record * de, struct inode * inode){ int len; unsigned char * chr; int symlink_len = 0; CONTINUE_DECLS; if (!inode->i_sb->u.isofs_sb.s_rock) return 0; SETUP_ROCK_RIDGE(de, chr, len); repeat: { int cnt, sig; struct inode * reloc; struct rock_ridge * rr; int rootflag; while (len > 1){ /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *) chr; if (rr->len == 0) goto out; /* Something got screwed up here */ sig = (chr[0] << 8) + chr[1]; chr += rr->len; len -= rr->len; switch(sig){ case SIG('R','R'): if((rr->u.RR.flags[0] & (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out; break; case SIG('S','P'): CHECK_SP(goto out); break; case SIG('C','E'): CHECK_CE; break; case SIG('E','R'): inode->i_sb->u.isofs_sb.s_rock = 1; printk(KERN_DEBUG"ISO9660 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); } }; break; case SIG('T','F'): { struct stamp *times = (struct stamp *) &(rr->u.TF.__times); /* 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 = iso_date(times[cnt++].time, 0); if(rr->u.TF.flags & TF_MODIFY) inode->i_mtime = iso_date(times[cnt++].time, 0); if(rr->u.TF.flags & TF_ACCESS) inode->i_atime = iso_date(times[cnt++].time, 0); if(rr->u.TF.flags & TF_ATTRIBUTES) inode->i_ctime = iso_date(times[cnt++].time, 0); break; } case SIG('S','L'): {int slen; struct SL_component * slp; struct SL_component * oldslp; slen = rr->len - 5; slp = (struct SL_component *)&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"); }; 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; } } symlink_len = inode->i_size; break; case SIG('R','E'): printk("Attempt to read inode for relocated directory\n"); goto out; case SIG('C','L'): #ifdef DEBUG printk("RR CL (%x)\n",inode->i_ino); #endif inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location) << inode -> i_sb -> u.isofs_sb.s_log_zone_size; reloc = iget(inode->i_sb, inode->u.isofs_i.i_first_extent); 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_atime = reloc->i_atime; inode->i_ctime = reloc->i_ctime; inode->i_mtime = reloc->i_mtime; iput(reloc); break; default: break; } };
int get_rock_ridge_filename(struct iso_directory_record * de, char * retname, struct inode * inode) { int len; unsigned char * chr; CONTINUE_DECLS; int retnamlen = 0, truncate=0; if (!inode->i_sb->u.isofs_sb.s_rock) return 0; *retname = 0; retnamlen = 0; SETUP_ROCK_RIDGE(de, chr, len); repeat: { struct rock_ridge * rr; int sig; while (len > 1){ /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *) chr; if (rr->len == 0) goto out; /* Something got screwed up here */ sig = (chr[0] << 8) + chr[1]; chr += rr->len; len -= rr->len; 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; 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; break; case SIG('R','E'): #ifdef DEBUG printk("RR: RE (%x)\n", inode->i_ino); #endif if (buffer) kfree(buffer); return -1; default: break; } }; } MAYBE_CONTINUE(repeat,inode); return retnamlen; /* If 0, this file did not have a NM field */ out: if(buffer) kfree(buffer); return 0; }