cd9660_rrip.c revision 8876
11541Srgrimes/*- 21541Srgrimes * Copyright (c) 1993, 1994 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * This code is derived from software contributed to Berkeley 61541Srgrimes * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 71541Srgrimes * Support code is derived from software contributed to Berkeley 81541Srgrimes * by Atsushi Murai (amurai@spec.co.jp). 91541Srgrimes * 101541Srgrimes * Redistribution and use in source and binary forms, with or without 111541Srgrimes * modification, are permitted provided that the following conditions 121541Srgrimes * are met: 131541Srgrimes * 1. Redistributions of source code must retain the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer. 151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161541Srgrimes * notice, this list of conditions and the following disclaimer in the 171541Srgrimes * documentation and/or other materials provided with the distribution. 181541Srgrimes * 3. All advertising materials mentioning features or use of this software 191541Srgrimes * must display the following acknowledgement: 201541Srgrimes * This product includes software developed by the University of 211541Srgrimes * California, Berkeley and its contributors. 221541Srgrimes * 4. Neither the name of the University nor the names of its contributors 231541Srgrimes * may be used to endorse or promote products derived from this software 241541Srgrimes * without specific prior written permission. 251541Srgrimes * 261541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 271541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 281541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 291541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 301541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 311541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 321541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 331541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 341541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 351541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 361541Srgrimes * SUCH DAMAGE. 371541Srgrimes * 381541Srgrimes * @(#)cd9660_rrip.c 8.2 (Berkeley) 1/23/94 398876Srgrimes * $Id: cd9660_rrip.c,v 1.6 1995/01/16 17:03:26 joerg Exp $ 401541Srgrimes */ 411541Srgrimes 421541Srgrimes#include <sys/param.h> 432806Sbde#include <sys/systm.h> 441541Srgrimes#include <sys/namei.h> 451541Srgrimes#include <sys/buf.h> 461541Srgrimes#include <sys/file.h> 471541Srgrimes#include <sys/vnode.h> 481541Srgrimes#include <sys/mount.h> 491541Srgrimes#include <sys/kernel.h> 501541Srgrimes#include <sys/stat.h> 511541Srgrimes#include <sys/types.h> 521541Srgrimes 531541Srgrimes#include <sys/time.h> 541541Srgrimes 551541Srgrimes#include <isofs/cd9660/iso.h> 561541Srgrimes#include <isofs/cd9660/cd9660_node.h> 571541Srgrimes#include <isofs/cd9660/cd9660_rrip.h> 581541Srgrimes#include <isofs/cd9660/iso_rrip.h> 591541Srgrimes 601541Srgrimes/* 611541Srgrimes * POSIX file attribute 621541Srgrimes */ 631541Srgrimesstatic int 641541Srgrimescd9660_rrip_attr(p,ana) 651541Srgrimes ISO_RRIP_ATTR *p; 661541Srgrimes ISO_RRIP_ANALYZE *ana; 671541Srgrimes{ 681541Srgrimes ana->inop->inode.iso_mode = isonum_731(p->mode_l); 691541Srgrimes ana->inop->inode.iso_uid = (uid_t)isonum_731(p->uid_l); 701541Srgrimes ana->inop->inode.iso_gid = (gid_t)isonum_731(p->gid_l); 711541Srgrimes ana->inop->inode.iso_links = isonum_731(p->links_l); 721541Srgrimes ana->fields &= ~ISO_SUSP_ATTR; 731541Srgrimes return ISO_SUSP_ATTR; 741541Srgrimes} 751541Srgrimes 761541Srgrimesstatic void 771541Srgrimescd9660_rrip_defattr(isodir,ana) 781541Srgrimes struct iso_directory_record *isodir; 791541Srgrimes ISO_RRIP_ANALYZE *ana; 801541Srgrimes{ 811541Srgrimes /* But this is a required field! */ 821541Srgrimes printf("RRIP without PX field?\n"); 835651Sjoerg cd9660_defattr(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 841541Srgrimes} 851541Srgrimes 861541Srgrimes/* 871541Srgrimes * Symbolic Links 881541Srgrimes */ 891541Srgrimesstatic int 901541Srgrimescd9660_rrip_slink(p,ana) 915651Sjoerg ISO_RRIP_SLINK *p; 921541Srgrimes ISO_RRIP_ANALYZE *ana; 931541Srgrimes{ 941541Srgrimes register ISO_RRIP_SLINK_COMPONENT *pcomp; 951541Srgrimes register ISO_RRIP_SLINK_COMPONENT *pcompe; 961541Srgrimes int len, wlen, cont; 971541Srgrimes char *outbuf, *inbuf; 988876Srgrimes 991541Srgrimes pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component; 1001541Srgrimes pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length)); 1011541Srgrimes len = *ana->outlen; 1021541Srgrimes outbuf = ana->outbuf; 1031541Srgrimes cont = ana->cont; 1048876Srgrimes 1051541Srgrimes /* 1061541Srgrimes * Gathering a Symbolic name from each component with path 1071541Srgrimes */ 1081541Srgrimes for (; 1091541Srgrimes pcomp < pcompe; 1101541Srgrimes pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ 1111541Srgrimes + isonum_711(pcomp->clen))) { 1128876Srgrimes 1131541Srgrimes if (!cont) { 1141541Srgrimes if (len < ana->maxlen) { 1151541Srgrimes len++; 1161541Srgrimes *outbuf++ = '/'; 1171541Srgrimes } 1181541Srgrimes } 1191541Srgrimes cont = 0; 1208876Srgrimes 1211541Srgrimes inbuf = ".."; 1221541Srgrimes wlen = 0; 1238876Srgrimes 1241541Srgrimes switch (*pcomp->cflag) { 1258876Srgrimes 1261541Srgrimes case ISO_SUSP_CFLAG_CURRENT: 1271541Srgrimes /* Inserting Current */ 1281541Srgrimes wlen = 1; 1291541Srgrimes break; 1308876Srgrimes 1311541Srgrimes case ISO_SUSP_CFLAG_PARENT: 1321541Srgrimes /* Inserting Parent */ 1331541Srgrimes wlen = 2; 1341541Srgrimes break; 1358876Srgrimes 1361541Srgrimes case ISO_SUSP_CFLAG_ROOT: 1371541Srgrimes /* Inserting slash for ROOT */ 1381541Srgrimes /* start over from beginning(?) */ 1391541Srgrimes outbuf -= len; 1401541Srgrimes len = 0; 1411541Srgrimes break; 1428876Srgrimes 1431541Srgrimes case ISO_SUSP_CFLAG_VOLROOT: 1441541Srgrimes /* Inserting a mount point i.e. "/cdrom" */ 1451541Srgrimes /* same as above */ 1461541Srgrimes outbuf -= len; 1471541Srgrimes len = 0; 1481541Srgrimes inbuf = ana->imp->im_mountp->mnt_stat.f_mntonname; 1491541Srgrimes wlen = strlen(inbuf); 1501541Srgrimes break; 1518876Srgrimes 1521541Srgrimes case ISO_SUSP_CFLAG_HOST: 1531541Srgrimes /* Inserting hostname i.e. "kurt.tools.de" */ 1541541Srgrimes inbuf = hostname; 1551541Srgrimes wlen = hostnamelen; 1561541Srgrimes break; 1578876Srgrimes 1581541Srgrimes case ISO_SUSP_CFLAG_CONTINUE: 1591541Srgrimes cont = 1; 1601541Srgrimes /* fall thru */ 1611541Srgrimes case 0: 1621541Srgrimes /* Inserting component */ 1631541Srgrimes wlen = isonum_711(pcomp->clen); 1641541Srgrimes inbuf = pcomp->name; 1651541Srgrimes break; 1661541Srgrimes default: 1671541Srgrimes printf("RRIP with incorrect flags?"); 1681541Srgrimes wlen = ana->maxlen + 1; 1691541Srgrimes break; 1701541Srgrimes } 1718876Srgrimes 1721541Srgrimes if (len + wlen > ana->maxlen) { 1731541Srgrimes /* indicate error to caller */ 1741541Srgrimes ana->cont = 1; 1751541Srgrimes ana->fields = 0; 1761541Srgrimes ana->outbuf -= *ana->outlen; 1771541Srgrimes *ana->outlen = 0; 1781541Srgrimes return 0; 1791541Srgrimes } 1808876Srgrimes 1811541Srgrimes bcopy(inbuf,outbuf,wlen); 1821541Srgrimes outbuf += wlen; 1831541Srgrimes len += wlen; 1848876Srgrimes 1851541Srgrimes } 1861541Srgrimes ana->outbuf = outbuf; 1871541Srgrimes *ana->outlen = len; 1881541Srgrimes ana->cont = cont; 1898876Srgrimes 1901541Srgrimes if (!isonum_711(p->flags)) { 1911541Srgrimes ana->fields &= ~ISO_SUSP_SLINK; 1921541Srgrimes return ISO_SUSP_SLINK; 1931541Srgrimes } 1941541Srgrimes return 0; 1951541Srgrimes} 1961541Srgrimes 1971541Srgrimes/* 1981541Srgrimes * Alternate name 1991541Srgrimes */ 2001541Srgrimesstatic int 2011541Srgrimescd9660_rrip_altname(p,ana) 2021541Srgrimes ISO_RRIP_ALTNAME *p; 2031541Srgrimes ISO_RRIP_ANALYZE *ana; 2041541Srgrimes{ 2051541Srgrimes char *inbuf; 2061541Srgrimes int wlen; 2071541Srgrimes int cont; 2088876Srgrimes 2091541Srgrimes inbuf = ".."; 2101541Srgrimes wlen = 0; 2111541Srgrimes cont = 0; 2128876Srgrimes 2131541Srgrimes switch (*p->flags) { 2141541Srgrimes case ISO_SUSP_CFLAG_CURRENT: 2151541Srgrimes /* Inserting Current */ 2161541Srgrimes wlen = 1; 2171541Srgrimes break; 2188876Srgrimes 2191541Srgrimes case ISO_SUSP_CFLAG_PARENT: 2201541Srgrimes /* Inserting Parent */ 2211541Srgrimes wlen = 2; 2221541Srgrimes break; 2238876Srgrimes 2241541Srgrimes case ISO_SUSP_CFLAG_HOST: 2251541Srgrimes /* Inserting hostname i.e. "kurt.tools.de" */ 2261541Srgrimes inbuf = hostname; 2271541Srgrimes wlen = hostnamelen; 2281541Srgrimes break; 2298876Srgrimes 2301541Srgrimes case ISO_SUSP_CFLAG_CONTINUE: 2311541Srgrimes cont = 1; 2321541Srgrimes /* fall thru */ 2331541Srgrimes case 0: 2341541Srgrimes /* Inserting component */ 2351541Srgrimes wlen = isonum_711(p->h.length) - 5; 2361541Srgrimes inbuf = (char *)p + 5; 2371541Srgrimes break; 2388876Srgrimes 2391541Srgrimes default: 2401541Srgrimes printf("RRIP with incorrect NM flags?\n"); 2411541Srgrimes wlen = ana->maxlen + 1; 2421541Srgrimes break; 2431541Srgrimes } 2448876Srgrimes 2451541Srgrimes if ((*ana->outlen += wlen) > ana->maxlen) { 2461541Srgrimes /* treat as no name field */ 2471541Srgrimes ana->fields &= ~ISO_SUSP_ALTNAME; 2481541Srgrimes ana->outbuf -= *ana->outlen - wlen; 2491541Srgrimes *ana->outlen = 0; 2501541Srgrimes return 0; 2511541Srgrimes } 2528876Srgrimes 2531541Srgrimes bcopy(inbuf,ana->outbuf,wlen); 2541541Srgrimes ana->outbuf += wlen; 2558876Srgrimes 2561541Srgrimes if (!cont) { 2571541Srgrimes ana->fields &= ~ISO_SUSP_ALTNAME; 2581541Srgrimes return ISO_SUSP_ALTNAME; 2591541Srgrimes } 2601541Srgrimes return 0; 2611541Srgrimes} 2621541Srgrimes 2631541Srgrimesstatic void 2641541Srgrimescd9660_rrip_defname(isodir,ana) 2651541Srgrimes struct iso_directory_record *isodir; 2661541Srgrimes ISO_RRIP_ANALYZE *ana; 2671541Srgrimes{ 2681541Srgrimes strcpy(ana->outbuf,".."); 2691541Srgrimes switch (*isodir->name) { 2701541Srgrimes default: 2711541Srgrimes isofntrans(isodir->name,isonum_711(isodir->name_len), 2721541Srgrimes ana->outbuf,ana->outlen, 2731541Srgrimes 1,isonum_711(isodir->flags)&4); 2741541Srgrimes break; 2751541Srgrimes case 0: 2761541Srgrimes *ana->outlen = 1; 2771541Srgrimes break; 2781541Srgrimes case 1: 2791541Srgrimes *ana->outlen = 2; 2801541Srgrimes break; 2811541Srgrimes } 2821541Srgrimes} 2831541Srgrimes 2841541Srgrimes/* 2851541Srgrimes * Parent or Child Link 2861541Srgrimes */ 2871541Srgrimesstatic int 2881541Srgrimescd9660_rrip_pclink(p,ana) 2895651Sjoerg ISO_RRIP_CLINK *p; 2901541Srgrimes ISO_RRIP_ANALYZE *ana; 2911541Srgrimes{ 2921541Srgrimes *ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift; 2931541Srgrimes ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK); 2941541Srgrimes return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK; 2951541Srgrimes} 2961541Srgrimes 2971541Srgrimes/* 2981541Srgrimes * Relocated directory 2991541Srgrimes */ 3001541Srgrimesstatic int 3011541Srgrimescd9660_rrip_reldir(p,ana) 3025651Sjoerg ISO_RRIP_RELDIR *p; 3031541Srgrimes ISO_RRIP_ANALYZE *ana; 3041541Srgrimes{ 3051541Srgrimes /* special hack to make caller aware of RE field */ 3061541Srgrimes *ana->outlen = 0; 3071541Srgrimes ana->fields = 0; 3081541Srgrimes return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 3091541Srgrimes} 3101541Srgrimes 3111541Srgrimesstatic int 3121541Srgrimescd9660_rrip_tstamp(p,ana) 3131541Srgrimes ISO_RRIP_TSTAMP *p; 3141541Srgrimes ISO_RRIP_ANALYZE *ana; 3151541Srgrimes{ 3161541Srgrimes unsigned char *ptime; 3178876Srgrimes 3181541Srgrimes ptime = p->time; 3198876Srgrimes 3201541Srgrimes /* Check a format of time stamp (7bytes/17bytes) */ 3211541Srgrimes if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) { 3221541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 3231541Srgrimes ptime += 7; 3248876Srgrimes 3251541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 3265651Sjoerg cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime, 3275651Sjoerg ISO_FTYPE_RRIP); 3281541Srgrimes ptime += 7; 3291541Srgrimes } else 3302806Sbde bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 3318876Srgrimes 3321541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 3335651Sjoerg cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime, 3345651Sjoerg ISO_FTYPE_RRIP); 3351541Srgrimes ptime += 7; 3361541Srgrimes } else 3371541Srgrimes ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 3388876Srgrimes 3391541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 3405651Sjoerg cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime, 3415651Sjoerg ISO_FTYPE_RRIP); 3421541Srgrimes else 3431541Srgrimes ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 3448876Srgrimes 3451541Srgrimes } else { 3461541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 3471541Srgrimes ptime += 17; 3488876Srgrimes 3491541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 3501541Srgrimes cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime); 3511541Srgrimes ptime += 17; 3521541Srgrimes } else 3532806Sbde bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 3548876Srgrimes 3551541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 3561541Srgrimes cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime); 3571541Srgrimes ptime += 17; 3581541Srgrimes } else 3591541Srgrimes ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 3608876Srgrimes 3611541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 3621541Srgrimes cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime); 3631541Srgrimes else 3641541Srgrimes ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 3658876Srgrimes 3661541Srgrimes } 3671541Srgrimes ana->fields &= ~ISO_SUSP_TSTAMP; 3681541Srgrimes return ISO_SUSP_TSTAMP; 3691541Srgrimes} 3701541Srgrimes 3711541Srgrimesstatic void 3721541Srgrimescd9660_rrip_deftstamp(isodir,ana) 3731541Srgrimes struct iso_directory_record *isodir; 3741541Srgrimes ISO_RRIP_ANALYZE *ana; 3751541Srgrimes{ 3765651Sjoerg cd9660_deftstamp(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 3771541Srgrimes} 3781541Srgrimes 3791541Srgrimes/* 3801541Srgrimes * POSIX device modes 3811541Srgrimes */ 3821541Srgrimesstatic int 3831541Srgrimescd9660_rrip_device(p,ana) 3841541Srgrimes ISO_RRIP_DEVICE *p; 3851541Srgrimes ISO_RRIP_ANALYZE *ana; 3861541Srgrimes{ 3871541Srgrimes unsigned high, low; 3888876Srgrimes 3891541Srgrimes high = isonum_733(p->dev_t_high_l); 3901541Srgrimes low = isonum_733(p->dev_t_low_l); 3918876Srgrimes 3921541Srgrimes if ( high == 0 ) { 3931541Srgrimes ana->inop->inode.iso_rdev = makedev( major(low), minor(low) ); 3941541Srgrimes } else { 3951541Srgrimes ana->inop->inode.iso_rdev = makedev( high, minor(low) ); 3961541Srgrimes } 3971541Srgrimes ana->fields &= ~ISO_SUSP_DEVICE; 3981541Srgrimes return ISO_SUSP_DEVICE; 3991541Srgrimes} 4001541Srgrimes 4011541Srgrimes/* 4021541Srgrimes * Flag indicating 4031541Srgrimes */ 4041541Srgrimesstatic int 4051541Srgrimescd9660_rrip_idflag(p,ana) 4061541Srgrimes ISO_RRIP_IDFLAG *p; 4071541Srgrimes ISO_RRIP_ANALYZE *ana; 4081541Srgrimes{ 4091541Srgrimes ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */ 4101541Srgrimes /* special handling of RE field */ 4111541Srgrimes if (ana->fields&ISO_SUSP_RELDIR) 4121541Srgrimes return cd9660_rrip_reldir(p,ana); 4138876Srgrimes 4141541Srgrimes return ISO_SUSP_IDFLAG; 4151541Srgrimes} 4161541Srgrimes 4171541Srgrimes/* 4181541Srgrimes * Continuation pointer 4191541Srgrimes */ 4201541Srgrimesstatic int 4211541Srgrimescd9660_rrip_cont(p,ana) 4221541Srgrimes ISO_RRIP_CONT *p; 4231541Srgrimes ISO_RRIP_ANALYZE *ana; 4241541Srgrimes{ 4251541Srgrimes ana->iso_ce_blk = isonum_733(p->location); 4261541Srgrimes ana->iso_ce_off = isonum_733(p->offset); 4271541Srgrimes ana->iso_ce_len = isonum_733(p->length); 4281541Srgrimes return ISO_SUSP_CONT; 4291541Srgrimes} 4301541Srgrimes 4311541Srgrimes/* 4321541Srgrimes * System Use end 4331541Srgrimes */ 4341541Srgrimesstatic int 4351541Srgrimescd9660_rrip_stop(p,ana) 4361541Srgrimes ISO_SUSP_HEADER *p; 4371541Srgrimes ISO_RRIP_ANALYZE *ana; 4381541Srgrimes{ 4391541Srgrimes /* stop analyzing */ 4401541Srgrimes ana->fields = 0; 4411541Srgrimes return ISO_SUSP_STOP; 4421541Srgrimes} 4431541Srgrimes 4441541Srgrimes/* 4451541Srgrimes * Extension reference 4461541Srgrimes */ 4471541Srgrimesstatic int 4481541Srgrimescd9660_rrip_extref(p,ana) 4491541Srgrimes ISO_RRIP_EXTREF *p; 4501541Srgrimes ISO_RRIP_ANALYZE *ana; 4511541Srgrimes{ 4521541Srgrimes if (isonum_711(p->len_id) != 10 4531541Srgrimes || bcmp((char *)p + 8,"RRIP_1991A",10) 4541541Srgrimes || isonum_711(p->version) != 1) 4551541Srgrimes return 0; 4561541Srgrimes ana->fields &= ~ISO_SUSP_EXTREF; 4571541Srgrimes return ISO_SUSP_EXTREF; 4581541Srgrimes} 4591541Srgrimes 4601541Srgrimestypedef struct { 4611541Srgrimes char type[2]; 4621541Srgrimes int (*func)(); 4631541Srgrimes void (*func2)(); 4641541Srgrimes int result; 4651541Srgrimes} RRIP_TABLE; 4661541Srgrimes 4671541Srgrimesstatic int 4681541Srgrimescd9660_rrip_loop(isodir,ana,table) 4691541Srgrimes struct iso_directory_record *isodir; 4701541Srgrimes ISO_RRIP_ANALYZE *ana; 4711541Srgrimes RRIP_TABLE *table; 4721541Srgrimes{ 4731541Srgrimes register RRIP_TABLE *ptable; 4741541Srgrimes register ISO_SUSP_HEADER *phead; 4751541Srgrimes register ISO_SUSP_HEADER *pend; 4761541Srgrimes struct buf *bp = NULL; 4771541Srgrimes char *pwhead; 4781541Srgrimes int result; 4798876Srgrimes 4801541Srgrimes /* 4811541Srgrimes * Note: If name length is odd, 4825651Sjoerg * it will be padding 1 byte after the name 4831541Srgrimes */ 4841541Srgrimes pwhead = isodir->name + isonum_711(isodir->name_len); 4851541Srgrimes if (!(isonum_711(isodir->name_len)&1)) 4861541Srgrimes pwhead++; 4878876Srgrimes 4881541Srgrimes /* If it's not the '.' entry of the root dir obey SP field */ 4891541Srgrimes if (*isodir->name != 0 4901541Srgrimes || isonum_733(isodir->extent) != ana->imp->root_extent) 4911541Srgrimes pwhead += ana->imp->rr_skip; 4921541Srgrimes else 4931541Srgrimes pwhead += ana->imp->rr_skip0; 4948876Srgrimes 4951541Srgrimes phead = (ISO_SUSP_HEADER *)pwhead; 4961541Srgrimes pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length)); 4978876Srgrimes 4981541Srgrimes result = 0; 4991541Srgrimes while (1) { 5001541Srgrimes ana->iso_ce_len = 0; 5011541Srgrimes /* 5021541Srgrimes * Note: "pend" should be more than one SUSP header 5038876Srgrimes */ 5041541Srgrimes while (pend >= phead + 1) { 5051541Srgrimes if (isonum_711(phead->version) == 1) { 5061541Srgrimes for (ptable = table; ptable->func; ptable++) { 5071541Srgrimes if (*phead->type == *ptable->type 5081541Srgrimes && phead->type[1] == ptable->type[1]) { 5091541Srgrimes result |= ptable->func(phead,ana); 5101541Srgrimes break; 5111541Srgrimes } 5121541Srgrimes } 5131541Srgrimes if (!ana->fields) 5141541Srgrimes break; 5151541Srgrimes } 5161541Srgrimes /* 5171541Srgrimes * move to next SUSP 5181541Srgrimes * Hopefully this works with newer versions, too 5191541Srgrimes */ 5201541Srgrimes phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length)); 5211541Srgrimes } 5228876Srgrimes 5231541Srgrimes if ( ana->fields && ana->iso_ce_len ) { 5241541Srgrimes if (ana->iso_ce_blk >= ana->imp->volume_space_size 5251541Srgrimes || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size 5261541Srgrimes || bread(ana->imp->im_devvp, 5272604Sdfr iso_lblktodaddr(ana->imp, ana->iso_ce_blk), 5281541Srgrimes ana->imp->logical_block_size,NOCRED,&bp)) 5291541Srgrimes /* what to do now? */ 5301541Srgrimes break; 5311541Srgrimes phead = (ISO_SUSP_HEADER *)(bp->b_un.b_addr + ana->iso_ce_off); 5321541Srgrimes pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len); 5331541Srgrimes } else 5341541Srgrimes break; 5351541Srgrimes } 5361541Srgrimes if (bp) 5371541Srgrimes brelse(bp); 5381541Srgrimes /* 5391541Srgrimes * If we don't find the Basic SUSP stuffs, just set default value 5401541Srgrimes * ( attribute/time stamp ) 5411541Srgrimes */ 5421541Srgrimes for (ptable = table; ptable->func2; ptable++) 5431541Srgrimes if (!(ptable->result&result)) 5441541Srgrimes ptable->func2(isodir,ana); 5458876Srgrimes 5461541Srgrimes return result; 5471541Srgrimes} 5481541Srgrimes 5491541Srgrimesstatic RRIP_TABLE rrip_table_analyze[] = { 5501541Srgrimes { "PX", cd9660_rrip_attr, cd9660_rrip_defattr, ISO_SUSP_ATTR }, 5511541Srgrimes { "TF", cd9660_rrip_tstamp, cd9660_rrip_deftstamp, ISO_SUSP_TSTAMP }, 5521541Srgrimes { "PN", cd9660_rrip_device, 0, ISO_SUSP_DEVICE }, 5531541Srgrimes { "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 5541541Srgrimes { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 5551541Srgrimes { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 5561541Srgrimes { "", 0, 0, 0 } 5571541Srgrimes}; 5581541Srgrimes 5591541Srgrimesint 5601541Srgrimescd9660_rrip_analyze(isodir,inop,imp) 5611541Srgrimes struct iso_directory_record *isodir; 5621541Srgrimes struct iso_node *inop; 5631541Srgrimes struct iso_mnt *imp; 5641541Srgrimes{ 5651541Srgrimes ISO_RRIP_ANALYZE analyze; 5668876Srgrimes 5671541Srgrimes analyze.inop = inop; 5681541Srgrimes analyze.imp = imp; 5691541Srgrimes analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE; 5708876Srgrimes 5711541Srgrimes return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze); 5721541Srgrimes} 5731541Srgrimes 5748876Srgrimes/* 5758876Srgrimes * Get Alternate Name from 'AL' record 5768876Srgrimes * If either no AL record or 0 length, 5771541Srgrimes * it will be return the translated ISO9660 name, 5781541Srgrimes */ 5791541Srgrimesstatic RRIP_TABLE rrip_table_getname[] = { 5801541Srgrimes { "NM", cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME }, 5811541Srgrimes { "CL", cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 5821541Srgrimes { "PL", cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 5831541Srgrimes { "RE", cd9660_rrip_reldir, 0, ISO_SUSP_RELDIR }, 5841541Srgrimes { "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 5851541Srgrimes { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 5861541Srgrimes { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 5871541Srgrimes { "", 0, 0, 0 } 5881541Srgrimes}; 5891541Srgrimes 5901541Srgrimesint 5911541Srgrimescd9660_rrip_getname(isodir,outbuf,outlen,inump,imp) 5921541Srgrimes struct iso_directory_record *isodir; 5931541Srgrimes char *outbuf; 5941541Srgrimes u_short *outlen; 5951541Srgrimes ino_t *inump; 5961541Srgrimes struct iso_mnt *imp; 5971541Srgrimes{ 5981541Srgrimes ISO_RRIP_ANALYZE analyze; 5991541Srgrimes RRIP_TABLE *tab; 6008876Srgrimes 6011541Srgrimes analyze.outbuf = outbuf; 6021541Srgrimes analyze.outlen = outlen; 6031541Srgrimes analyze.maxlen = NAME_MAX; 6041541Srgrimes analyze.inump = inump; 6051541Srgrimes analyze.imp = imp; 6061541Srgrimes analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 6071541Srgrimes *outlen = 0; 6088876Srgrimes 6091541Srgrimes tab = rrip_table_getname; 6101541Srgrimes if (*isodir->name == 0 6111541Srgrimes || *isodir->name == 1) { 6121541Srgrimes cd9660_rrip_defname(isodir,&analyze); 6138876Srgrimes 6141541Srgrimes analyze.fields &= ~ISO_SUSP_ALTNAME; 6151541Srgrimes tab++; 6161541Srgrimes } 6178876Srgrimes 6181541Srgrimes return cd9660_rrip_loop(isodir,&analyze,tab); 6191541Srgrimes} 6201541Srgrimes 6218876Srgrimes/* 6228876Srgrimes * Get Symbolic Name from 'SL' record 6231541Srgrimes * 6241541Srgrimes * Note: isodir should contains SL record! 6251541Srgrimes */ 6261541Srgrimesstatic RRIP_TABLE rrip_table_getsymname[] = { 6271541Srgrimes { "SL", cd9660_rrip_slink, 0, ISO_SUSP_SLINK }, 6281541Srgrimes { "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 6291541Srgrimes { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 6301541Srgrimes { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 6311541Srgrimes { "", 0, 0, 0 } 6321541Srgrimes}; 6331541Srgrimes 6341541Srgrimesint 6351541Srgrimescd9660_rrip_getsymname(isodir,outbuf,outlen,imp) 6361541Srgrimes struct iso_directory_record *isodir; 6371541Srgrimes char *outbuf; 6381541Srgrimes u_short *outlen; 6391541Srgrimes struct iso_mnt *imp; 6401541Srgrimes{ 6411541Srgrimes ISO_RRIP_ANALYZE analyze; 6428876Srgrimes 6431541Srgrimes analyze.outbuf = outbuf; 6441541Srgrimes analyze.outlen = outlen; 6451541Srgrimes *outlen = 0; 6461541Srgrimes analyze.maxlen = MAXPATHLEN; 6471541Srgrimes analyze.cont = 1; /* don't start with a slash */ 6481541Srgrimes analyze.imp = imp; 6491541Srgrimes analyze.fields = ISO_SUSP_SLINK; 6508876Srgrimes 6511541Srgrimes return (cd9660_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK); 6521541Srgrimes} 6531541Srgrimes 6541541Srgrimesstatic RRIP_TABLE rrip_table_extref[] = { 6551541Srgrimes { "ER", cd9660_rrip_extref, 0, ISO_SUSP_EXTREF }, 6561541Srgrimes { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 6571541Srgrimes { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 6581541Srgrimes { "", 0, 0, 0 } 6591541Srgrimes}; 6601541Srgrimes 6611541Srgrimes/* 6621541Srgrimes * Check for Rock Ridge Extension and return offset of its fields. 6631541Srgrimes * Note: We require the ER field. 6641541Srgrimes */ 6651541Srgrimesint 6661541Srgrimescd9660_rrip_offset(isodir,imp) 6671541Srgrimes struct iso_directory_record *isodir; 6681541Srgrimes struct iso_mnt *imp; 6691541Srgrimes{ 6701541Srgrimes ISO_RRIP_OFFSET *p; 6711541Srgrimes ISO_RRIP_ANALYZE analyze; 6728876Srgrimes 6731541Srgrimes imp->rr_skip0 = 0; 6741541Srgrimes p = (ISO_RRIP_OFFSET *)(isodir->name + 1); 6751541Srgrimes if (bcmp(p,"SP\7\1\276\357",6)) { 6761541Srgrimes /* Maybe, it's a CDROM XA disc? */ 6771541Srgrimes imp->rr_skip0 = 15; 6781541Srgrimes p = (ISO_RRIP_OFFSET *)((char *)p + 15); 6791541Srgrimes if (bcmp(p,"SP\7\1\276\357",6)) 6801541Srgrimes return -1; 6811541Srgrimes } 6828876Srgrimes 6831541Srgrimes analyze.imp = imp; 6841541Srgrimes analyze.fields = ISO_SUSP_EXTREF; 6851541Srgrimes if (!(cd9660_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF)) 6861541Srgrimes return -1; 6878876Srgrimes 6881541Srgrimes return isonum_711(p->skip); 6891541Srgrimes} 690