cd9660_rrip.c revision 92765
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 * 3822521Sdyson * @(#)cd9660_rrip.c 8.6 (Berkeley) 12/5/94 3950477Speter * $FreeBSD: head/sys/fs/cd9660/cd9660_rrip.c 92765 2002-03-20 07:51:46Z alfred $ 401541Srgrimes */ 411541Srgrimes 421541Srgrimes#include <sys/param.h> 432806Sbde#include <sys/systm.h> 4460041Sphk#include <sys/bio.h> 451541Srgrimes#include <sys/buf.h> 461541Srgrimes#include <sys/vnode.h> 471541Srgrimes#include <sys/mount.h> 481541Srgrimes#include <sys/kernel.h> 491541Srgrimes 501541Srgrimes#include <isofs/cd9660/iso.h> 511541Srgrimes#include <isofs/cd9660/cd9660_node.h> 521541Srgrimes#include <isofs/cd9660/cd9660_rrip.h> 531541Srgrimes#include <isofs/cd9660/iso_rrip.h> 541541Srgrimes 5592765Salfredtypedef int rrt_func_t(void *, ISO_RRIP_ANALYZE *ana); 5612597Sbde 5712597Sbdetypedef struct { 5812597Sbde char type[2]; 5912597Sbde rrt_func_t *func; 6092765Salfred void (*func2)(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana); 6112597Sbde int result; 6212597Sbde} RRIP_TABLE; 6312597Sbde 6492765Salfredstatic int cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, ISO_RRIP_ANALYZE *ana); 6592765Salfredstatic int cd9660_rrip_attr(ISO_RRIP_ATTR *p, ISO_RRIP_ANALYZE *ana); 6692765Salfredstatic int cd9660_rrip_cont(ISO_RRIP_CONT *p, ISO_RRIP_ANALYZE *ana); 6792765Salfredstatic void cd9660_rrip_defattr(struct iso_directory_record *isodir, 6892765Salfred ISO_RRIP_ANALYZE *ana); 6992765Salfredstatic void cd9660_rrip_defname(struct iso_directory_record *isodir, 7092765Salfred ISO_RRIP_ANALYZE *ana); 7192765Salfredstatic void cd9660_rrip_deftstamp(struct iso_directory_record *isodir, 7292765Salfred ISO_RRIP_ANALYZE *ana); 7392765Salfredstatic int cd9660_rrip_device(ISO_RRIP_DEVICE *p, ISO_RRIP_ANALYZE *ana); 7492765Salfredstatic int cd9660_rrip_extref(ISO_RRIP_EXTREF *p, ISO_RRIP_ANALYZE *ana); 7592765Salfredstatic int cd9660_rrip_idflag(ISO_RRIP_IDFLAG *p, ISO_RRIP_ANALYZE *ana); 7692765Salfredstatic int cd9660_rrip_loop(struct iso_directory_record *isodir, 7712597Sbde ISO_RRIP_ANALYZE *ana, 7892765Salfred RRIP_TABLE *table); 7992765Salfredstatic int cd9660_rrip_pclink(ISO_RRIP_CLINK *p, ISO_RRIP_ANALYZE *ana); 8092765Salfredstatic int cd9660_rrip_reldir(ISO_RRIP_RELDIR *p, ISO_RRIP_ANALYZE *ana); 8192765Salfredstatic int cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana); 8292765Salfredstatic int cd9660_rrip_stop(ISO_SUSP_HEADER *p, ISO_RRIP_ANALYZE *ana); 8392765Salfredstatic int cd9660_rrip_tstamp(ISO_RRIP_TSTAMP *p, ISO_RRIP_ANALYZE *ana); 8412597Sbde 851541Srgrimes/* 861541Srgrimes * POSIX file attribute 871541Srgrimes */ 881541Srgrimesstatic int 891541Srgrimescd9660_rrip_attr(p,ana) 901541Srgrimes ISO_RRIP_ATTR *p; 911541Srgrimes ISO_RRIP_ANALYZE *ana; 921541Srgrimes{ 9322521Sdyson ana->inop->inode.iso_mode = isonum_733(p->mode); 9422521Sdyson ana->inop->inode.iso_uid = isonum_733(p->uid); 9522521Sdyson ana->inop->inode.iso_gid = isonum_733(p->gid); 9622521Sdyson ana->inop->inode.iso_links = isonum_733(p->links); 971541Srgrimes ana->fields &= ~ISO_SUSP_ATTR; 981541Srgrimes return ISO_SUSP_ATTR; 991541Srgrimes} 1001541Srgrimes 1011541Srgrimesstatic void 1021541Srgrimescd9660_rrip_defattr(isodir,ana) 1031541Srgrimes struct iso_directory_record *isodir; 1041541Srgrimes ISO_RRIP_ANALYZE *ana; 1051541Srgrimes{ 1061541Srgrimes /* But this is a required field! */ 1071541Srgrimes printf("RRIP without PX field?\n"); 1085651Sjoerg cd9660_defattr(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 1091541Srgrimes} 1101541Srgrimes 1111541Srgrimes/* 1121541Srgrimes * Symbolic Links 1131541Srgrimes */ 1141541Srgrimesstatic int 1151541Srgrimescd9660_rrip_slink(p,ana) 1165651Sjoerg ISO_RRIP_SLINK *p; 1171541Srgrimes ISO_RRIP_ANALYZE *ana; 1181541Srgrimes{ 1191541Srgrimes register ISO_RRIP_SLINK_COMPONENT *pcomp; 1201541Srgrimes register ISO_RRIP_SLINK_COMPONENT *pcompe; 1211541Srgrimes int len, wlen, cont; 1221541Srgrimes char *outbuf, *inbuf; 1238876Srgrimes 1241541Srgrimes pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component; 1251541Srgrimes pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length)); 1261541Srgrimes len = *ana->outlen; 1271541Srgrimes outbuf = ana->outbuf; 1281541Srgrimes cont = ana->cont; 1298876Srgrimes 1301541Srgrimes /* 1311541Srgrimes * Gathering a Symbolic name from each component with path 1321541Srgrimes */ 1331541Srgrimes for (; 1341541Srgrimes pcomp < pcompe; 1351541Srgrimes pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ 1361541Srgrimes + isonum_711(pcomp->clen))) { 1378876Srgrimes 1381541Srgrimes if (!cont) { 1391541Srgrimes if (len < ana->maxlen) { 1401541Srgrimes len++; 1411541Srgrimes *outbuf++ = '/'; 1421541Srgrimes } 1431541Srgrimes } 1441541Srgrimes cont = 0; 1458876Srgrimes 1461541Srgrimes inbuf = ".."; 1471541Srgrimes wlen = 0; 1488876Srgrimes 1491541Srgrimes switch (*pcomp->cflag) { 1508876Srgrimes 1511541Srgrimes case ISO_SUSP_CFLAG_CURRENT: 1521541Srgrimes /* Inserting Current */ 1531541Srgrimes wlen = 1; 1541541Srgrimes break; 1558876Srgrimes 1561541Srgrimes case ISO_SUSP_CFLAG_PARENT: 1571541Srgrimes /* Inserting Parent */ 1581541Srgrimes wlen = 2; 1591541Srgrimes break; 1608876Srgrimes 1611541Srgrimes case ISO_SUSP_CFLAG_ROOT: 1621541Srgrimes /* Inserting slash for ROOT */ 1631541Srgrimes /* start over from beginning(?) */ 1641541Srgrimes outbuf -= len; 1651541Srgrimes len = 0; 1661541Srgrimes break; 1678876Srgrimes 1681541Srgrimes case ISO_SUSP_CFLAG_VOLROOT: 1691541Srgrimes /* Inserting a mount point i.e. "/cdrom" */ 1701541Srgrimes /* same as above */ 1711541Srgrimes outbuf -= len; 1721541Srgrimes len = 0; 1731541Srgrimes inbuf = ana->imp->im_mountp->mnt_stat.f_mntonname; 1741541Srgrimes wlen = strlen(inbuf); 1751541Srgrimes break; 1768876Srgrimes 1771541Srgrimes case ISO_SUSP_CFLAG_HOST: 1781541Srgrimes /* Inserting hostname i.e. "kurt.tools.de" */ 1791541Srgrimes inbuf = hostname; 18012287Sphk wlen = strlen(hostname); 1811541Srgrimes break; 1828876Srgrimes 1831541Srgrimes case ISO_SUSP_CFLAG_CONTINUE: 1841541Srgrimes cont = 1; 1851541Srgrimes /* fall thru */ 1861541Srgrimes case 0: 1871541Srgrimes /* Inserting component */ 1881541Srgrimes wlen = isonum_711(pcomp->clen); 1891541Srgrimes inbuf = pcomp->name; 1901541Srgrimes break; 1911541Srgrimes default: 1921541Srgrimes printf("RRIP with incorrect flags?"); 1931541Srgrimes wlen = ana->maxlen + 1; 1941541Srgrimes break; 1951541Srgrimes } 1968876Srgrimes 1971541Srgrimes if (len + wlen > ana->maxlen) { 1981541Srgrimes /* indicate error to caller */ 1991541Srgrimes ana->cont = 1; 2001541Srgrimes ana->fields = 0; 2011541Srgrimes ana->outbuf -= *ana->outlen; 2021541Srgrimes *ana->outlen = 0; 2031541Srgrimes return 0; 2041541Srgrimes } 2058876Srgrimes 2061541Srgrimes bcopy(inbuf,outbuf,wlen); 2071541Srgrimes outbuf += wlen; 2081541Srgrimes len += wlen; 2098876Srgrimes 2101541Srgrimes } 2111541Srgrimes ana->outbuf = outbuf; 2121541Srgrimes *ana->outlen = len; 2131541Srgrimes ana->cont = cont; 2148876Srgrimes 2151541Srgrimes if (!isonum_711(p->flags)) { 2161541Srgrimes ana->fields &= ~ISO_SUSP_SLINK; 2171541Srgrimes return ISO_SUSP_SLINK; 2181541Srgrimes } 2191541Srgrimes return 0; 2201541Srgrimes} 2211541Srgrimes 2221541Srgrimes/* 2231541Srgrimes * Alternate name 2241541Srgrimes */ 2251541Srgrimesstatic int 2261541Srgrimescd9660_rrip_altname(p,ana) 2271541Srgrimes ISO_RRIP_ALTNAME *p; 2281541Srgrimes ISO_RRIP_ANALYZE *ana; 2291541Srgrimes{ 2301541Srgrimes char *inbuf; 2311541Srgrimes int wlen; 2321541Srgrimes int cont; 2338876Srgrimes 2341541Srgrimes inbuf = ".."; 2351541Srgrimes wlen = 0; 2361541Srgrimes cont = 0; 2378876Srgrimes 2381541Srgrimes switch (*p->flags) { 2391541Srgrimes case ISO_SUSP_CFLAG_CURRENT: 2401541Srgrimes /* Inserting Current */ 2411541Srgrimes wlen = 1; 2421541Srgrimes break; 2438876Srgrimes 2441541Srgrimes case ISO_SUSP_CFLAG_PARENT: 2451541Srgrimes /* Inserting Parent */ 2461541Srgrimes wlen = 2; 2471541Srgrimes break; 2488876Srgrimes 2491541Srgrimes case ISO_SUSP_CFLAG_HOST: 2501541Srgrimes /* Inserting hostname i.e. "kurt.tools.de" */ 2511541Srgrimes inbuf = hostname; 25212287Sphk wlen = strlen(hostname); 2531541Srgrimes break; 2548876Srgrimes 2551541Srgrimes case ISO_SUSP_CFLAG_CONTINUE: 2561541Srgrimes cont = 1; 2571541Srgrimes /* fall thru */ 2581541Srgrimes case 0: 2591541Srgrimes /* Inserting component */ 2601541Srgrimes wlen = isonum_711(p->h.length) - 5; 2611541Srgrimes inbuf = (char *)p + 5; 2621541Srgrimes break; 2638876Srgrimes 2641541Srgrimes default: 2651541Srgrimes printf("RRIP with incorrect NM flags?\n"); 2661541Srgrimes wlen = ana->maxlen + 1; 2671541Srgrimes break; 2681541Srgrimes } 2698876Srgrimes 2701541Srgrimes if ((*ana->outlen += wlen) > ana->maxlen) { 2711541Srgrimes /* treat as no name field */ 2721541Srgrimes ana->fields &= ~ISO_SUSP_ALTNAME; 2731541Srgrimes ana->outbuf -= *ana->outlen - wlen; 2741541Srgrimes *ana->outlen = 0; 2751541Srgrimes return 0; 2761541Srgrimes } 2778876Srgrimes 2781541Srgrimes bcopy(inbuf,ana->outbuf,wlen); 2791541Srgrimes ana->outbuf += wlen; 2808876Srgrimes 2811541Srgrimes if (!cont) { 2821541Srgrimes ana->fields &= ~ISO_SUSP_ALTNAME; 2831541Srgrimes return ISO_SUSP_ALTNAME; 2841541Srgrimes } 2851541Srgrimes return 0; 2861541Srgrimes} 2871541Srgrimes 2881541Srgrimesstatic void 2891541Srgrimescd9660_rrip_defname(isodir,ana) 2901541Srgrimes struct iso_directory_record *isodir; 2911541Srgrimes ISO_RRIP_ANALYZE *ana; 2921541Srgrimes{ 29345773Sdcs isofntrans(isodir->name,isonum_711(isodir->name_len), 29445773Sdcs ana->outbuf,ana->outlen, 29545773Sdcs 1,isonum_711(isodir->flags)&4, ana->imp->joliet_level); 29645773Sdcs switch (*ana->outbuf) { 2971541Srgrimes default: 2981541Srgrimes break; 2991541Srgrimes case 1: 3001541Srgrimes *ana->outlen = 2; 30145773Sdcs /* FALL THROUGH */ 30245773Sdcs case 0: 30345773Sdcs /* outlen is 1 already */ 30445773Sdcs strcpy(ana->outbuf,".."); 3051541Srgrimes break; 3061541Srgrimes } 3071541Srgrimes} 3081541Srgrimes 3091541Srgrimes/* 3101541Srgrimes * Parent or Child Link 3111541Srgrimes */ 3121541Srgrimesstatic int 3131541Srgrimescd9660_rrip_pclink(p,ana) 3145651Sjoerg ISO_RRIP_CLINK *p; 3151541Srgrimes ISO_RRIP_ANALYZE *ana; 3161541Srgrimes{ 3171541Srgrimes *ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift; 3181541Srgrimes ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK); 3191541Srgrimes return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK; 3201541Srgrimes} 3211541Srgrimes 3221541Srgrimes/* 3231541Srgrimes * Relocated directory 3241541Srgrimes */ 3251541Srgrimesstatic int 3261541Srgrimescd9660_rrip_reldir(p,ana) 3275651Sjoerg ISO_RRIP_RELDIR *p; 3281541Srgrimes ISO_RRIP_ANALYZE *ana; 3291541Srgrimes{ 3301541Srgrimes /* special hack to make caller aware of RE field */ 3311541Srgrimes *ana->outlen = 0; 3321541Srgrimes ana->fields = 0; 3331541Srgrimes return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 3341541Srgrimes} 3351541Srgrimes 3361541Srgrimesstatic int 3371541Srgrimescd9660_rrip_tstamp(p,ana) 3381541Srgrimes ISO_RRIP_TSTAMP *p; 3391541Srgrimes ISO_RRIP_ANALYZE *ana; 3401541Srgrimes{ 34122521Sdyson u_char *ptime; 34222521Sdyson 3431541Srgrimes ptime = p->time; 3448876Srgrimes 3451541Srgrimes /* Check a format of time stamp (7bytes/17bytes) */ 3461541Srgrimes if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) { 3471541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 3481541Srgrimes ptime += 7; 3498876Srgrimes 3501541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 3515651Sjoerg cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime, 3525651Sjoerg ISO_FTYPE_RRIP); 3531541Srgrimes ptime += 7; 3541541Srgrimes } else 3552806Sbde bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 35622521Sdyson 3571541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 3585651Sjoerg cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime, 3595651Sjoerg ISO_FTYPE_RRIP); 3601541Srgrimes ptime += 7; 3611541Srgrimes } else 3621541Srgrimes ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 3638876Srgrimes 3641541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 3655651Sjoerg cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime, 3665651Sjoerg ISO_FTYPE_RRIP); 3671541Srgrimes else 3681541Srgrimes ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 3698876Srgrimes 3701541Srgrimes } else { 3711541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 3721541Srgrimes ptime += 17; 3738876Srgrimes 3741541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 3751541Srgrimes cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime); 3761541Srgrimes ptime += 17; 3771541Srgrimes } else 3782806Sbde bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 37922521Sdyson 3801541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 3811541Srgrimes cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime); 3821541Srgrimes ptime += 17; 3831541Srgrimes } else 3841541Srgrimes ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 3858876Srgrimes 3861541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 3871541Srgrimes cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime); 3881541Srgrimes else 3891541Srgrimes ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 3908876Srgrimes 3911541Srgrimes } 3921541Srgrimes ana->fields &= ~ISO_SUSP_TSTAMP; 3931541Srgrimes return ISO_SUSP_TSTAMP; 3941541Srgrimes} 3951541Srgrimes 3961541Srgrimesstatic void 3971541Srgrimescd9660_rrip_deftstamp(isodir,ana) 3981541Srgrimes struct iso_directory_record *isodir; 3991541Srgrimes ISO_RRIP_ANALYZE *ana; 4001541Srgrimes{ 4015651Sjoerg cd9660_deftstamp(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 4021541Srgrimes} 4031541Srgrimes 4041541Srgrimes/* 4051541Srgrimes * POSIX device modes 4061541Srgrimes */ 4071541Srgrimesstatic int 4081541Srgrimescd9660_rrip_device(p,ana) 4091541Srgrimes ISO_RRIP_DEVICE *p; 4101541Srgrimes ISO_RRIP_ANALYZE *ana; 4111541Srgrimes{ 41222521Sdyson u_int high, low; 41322521Sdyson 41422521Sdyson high = isonum_733(p->dev_t_high); 41522521Sdyson low = isonum_733(p->dev_t_low); 41622521Sdyson 41722521Sdyson if (high == 0) 41848859Sphk ana->inop->inode.iso_rdev = makeudev(umajor(low), uminor(low)); 41922521Sdyson else 42048859Sphk ana->inop->inode.iso_rdev = makeudev(high, uminor(low)); 4211541Srgrimes ana->fields &= ~ISO_SUSP_DEVICE; 4221541Srgrimes return ISO_SUSP_DEVICE; 4231541Srgrimes} 4241541Srgrimes 4251541Srgrimes/* 4261541Srgrimes * Flag indicating 4271541Srgrimes */ 4281541Srgrimesstatic int 4291541Srgrimescd9660_rrip_idflag(p,ana) 4301541Srgrimes ISO_RRIP_IDFLAG *p; 4311541Srgrimes ISO_RRIP_ANALYZE *ana; 4321541Srgrimes{ 4331541Srgrimes ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */ 4341541Srgrimes /* special handling of RE field */ 4351541Srgrimes if (ana->fields&ISO_SUSP_RELDIR) 43612597Sbde return cd9660_rrip_reldir(/* XXX */ (ISO_RRIP_RELDIR *)p,ana); 4378876Srgrimes 4381541Srgrimes return ISO_SUSP_IDFLAG; 4391541Srgrimes} 4401541Srgrimes 4411541Srgrimes/* 4421541Srgrimes * Continuation pointer 4431541Srgrimes */ 4441541Srgrimesstatic int 4451541Srgrimescd9660_rrip_cont(p,ana) 4461541Srgrimes ISO_RRIP_CONT *p; 4471541Srgrimes ISO_RRIP_ANALYZE *ana; 4481541Srgrimes{ 4491541Srgrimes ana->iso_ce_blk = isonum_733(p->location); 4501541Srgrimes ana->iso_ce_off = isonum_733(p->offset); 4511541Srgrimes ana->iso_ce_len = isonum_733(p->length); 4521541Srgrimes return ISO_SUSP_CONT; 4531541Srgrimes} 4541541Srgrimes 4551541Srgrimes/* 4561541Srgrimes * System Use end 4571541Srgrimes */ 4581541Srgrimesstatic int 4591541Srgrimescd9660_rrip_stop(p,ana) 4601541Srgrimes ISO_SUSP_HEADER *p; 4611541Srgrimes ISO_RRIP_ANALYZE *ana; 4621541Srgrimes{ 4631541Srgrimes return ISO_SUSP_STOP; 4641541Srgrimes} 4651541Srgrimes 4661541Srgrimes/* 4671541Srgrimes * Extension reference 4681541Srgrimes */ 4691541Srgrimesstatic int 4701541Srgrimescd9660_rrip_extref(p,ana) 4711541Srgrimes ISO_RRIP_EXTREF *p; 4721541Srgrimes ISO_RRIP_ANALYZE *ana; 4731541Srgrimes{ 4741541Srgrimes if (isonum_711(p->len_id) != 10 4751541Srgrimes || bcmp((char *)p + 8,"RRIP_1991A",10) 4761541Srgrimes || isonum_711(p->version) != 1) 4771541Srgrimes return 0; 4781541Srgrimes ana->fields &= ~ISO_SUSP_EXTREF; 4791541Srgrimes return ISO_SUSP_EXTREF; 4801541Srgrimes} 4811541Srgrimes 4821541Srgrimesstatic int 4831541Srgrimescd9660_rrip_loop(isodir,ana,table) 4841541Srgrimes struct iso_directory_record *isodir; 4851541Srgrimes ISO_RRIP_ANALYZE *ana; 4861541Srgrimes RRIP_TABLE *table; 4871541Srgrimes{ 4881541Srgrimes register RRIP_TABLE *ptable; 4891541Srgrimes register ISO_SUSP_HEADER *phead; 4901541Srgrimes register ISO_SUSP_HEADER *pend; 4911541Srgrimes struct buf *bp = NULL; 4921541Srgrimes char *pwhead; 49345773Sdcs u_char c; 4941541Srgrimes int result; 4958876Srgrimes 4961541Srgrimes /* 4971541Srgrimes * Note: If name length is odd, 4985651Sjoerg * it will be padding 1 byte after the name 4991541Srgrimes */ 5001541Srgrimes pwhead = isodir->name + isonum_711(isodir->name_len); 5011541Srgrimes if (!(isonum_711(isodir->name_len)&1)) 5021541Srgrimes pwhead++; 50345773Sdcs isochar(isodir->name, pwhead, ana->imp->joliet_level, &c); 5048876Srgrimes 5051541Srgrimes /* If it's not the '.' entry of the root dir obey SP field */ 50645773Sdcs if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent) 5071541Srgrimes pwhead += ana->imp->rr_skip; 5081541Srgrimes else 5091541Srgrimes pwhead += ana->imp->rr_skip0; 5108876Srgrimes 5111541Srgrimes phead = (ISO_SUSP_HEADER *)pwhead; 5121541Srgrimes pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length)); 5138876Srgrimes 5141541Srgrimes result = 0; 5151541Srgrimes while (1) { 5161541Srgrimes ana->iso_ce_len = 0; 5171541Srgrimes /* 5181541Srgrimes * Note: "pend" should be more than one SUSP header 5198876Srgrimes */ 5201541Srgrimes while (pend >= phead + 1) { 5211541Srgrimes if (isonum_711(phead->version) == 1) { 5221541Srgrimes for (ptable = table; ptable->func; ptable++) { 5231541Srgrimes if (*phead->type == *ptable->type 5241541Srgrimes && phead->type[1] == ptable->type[1]) { 5251541Srgrimes result |= ptable->func(phead,ana); 5261541Srgrimes break; 5271541Srgrimes } 5281541Srgrimes } 5291541Srgrimes if (!ana->fields) 5301541Srgrimes break; 5311541Srgrimes } 53222521Sdyson if (result&ISO_SUSP_STOP) { 53322521Sdyson result &= ~ISO_SUSP_STOP; 53422521Sdyson break; 53522521Sdyson } 53622521Sdyson /* plausibility check */ 53722521Sdyson if (isonum_711(phead->length) < sizeof(*phead)) 53822521Sdyson break; 5391541Srgrimes /* 5401541Srgrimes * move to next SUSP 5411541Srgrimes * Hopefully this works with newer versions, too 5421541Srgrimes */ 5431541Srgrimes phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length)); 5441541Srgrimes } 54522521Sdyson 54622521Sdyson if (ana->fields && ana->iso_ce_len) { 5471541Srgrimes if (ana->iso_ce_blk >= ana->imp->volume_space_size 5481541Srgrimes || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size 5491541Srgrimes || bread(ana->imp->im_devvp, 55022521Sdyson ana->iso_ce_blk << 55122521Sdyson (ana->imp->im_bshift - DEV_BSHIFT), 55222521Sdyson ana->imp->logical_block_size, NOCRED, &bp)) 5531541Srgrimes /* what to do now? */ 5541541Srgrimes break; 55522521Sdyson phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off); 5561541Srgrimes pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len); 5571541Srgrimes } else 5581541Srgrimes break; 5591541Srgrimes } 5601541Srgrimes if (bp) 5611541Srgrimes brelse(bp); 5621541Srgrimes /* 5631541Srgrimes * If we don't find the Basic SUSP stuffs, just set default value 56422521Sdyson * (attribute/time stamp) 5651541Srgrimes */ 5661541Srgrimes for (ptable = table; ptable->func2; ptable++) 5671541Srgrimes if (!(ptable->result&result)) 5681541Srgrimes ptable->func2(isodir,ana); 5698876Srgrimes 5701541Srgrimes return result; 5711541Srgrimes} 5721541Srgrimes 57312597Sbde/* 57422521Sdyson * Get Attributes. 57522521Sdyson */ 57622521Sdyson/* 57712597Sbde * XXX the casts are bogus but will do for now. 57812597Sbde */ 57912597Sbde#define BC (rrt_func_t *) 5801541Srgrimesstatic RRIP_TABLE rrip_table_analyze[] = { 58112597Sbde { "PX", BC cd9660_rrip_attr, cd9660_rrip_defattr, ISO_SUSP_ATTR }, 58212597Sbde { "TF", BC cd9660_rrip_tstamp, cd9660_rrip_deftstamp, ISO_SUSP_TSTAMP }, 58312597Sbde { "PN", BC cd9660_rrip_device, 0, ISO_SUSP_DEVICE }, 58412597Sbde { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 58512597Sbde { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 58612597Sbde { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 5871541Srgrimes { "", 0, 0, 0 } 5881541Srgrimes}; 5891541Srgrimes 5901541Srgrimesint 5911541Srgrimescd9660_rrip_analyze(isodir,inop,imp) 5921541Srgrimes struct iso_directory_record *isodir; 5931541Srgrimes struct iso_node *inop; 5941541Srgrimes struct iso_mnt *imp; 5951541Srgrimes{ 5961541Srgrimes ISO_RRIP_ANALYZE analyze; 5978876Srgrimes 5981541Srgrimes analyze.inop = inop; 5991541Srgrimes analyze.imp = imp; 6001541Srgrimes analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE; 6018876Srgrimes 6021541Srgrimes return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze); 6031541Srgrimes} 6041541Srgrimes 60522521Sdyson/* 60622521Sdyson * Get Alternate Name. 6071541Srgrimes */ 6081541Srgrimesstatic RRIP_TABLE rrip_table_getname[] = { 60912597Sbde { "NM", BC cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME }, 61012597Sbde { "CL", BC cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 61112597Sbde { "PL", BC cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 61212597Sbde { "RE", BC cd9660_rrip_reldir, 0, ISO_SUSP_RELDIR }, 61312597Sbde { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 61412597Sbde { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 61512597Sbde { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 6161541Srgrimes { "", 0, 0, 0 } 6171541Srgrimes}; 6181541Srgrimes 6191541Srgrimesint 6201541Srgrimescd9660_rrip_getname(isodir,outbuf,outlen,inump,imp) 6211541Srgrimes struct iso_directory_record *isodir; 6221541Srgrimes char *outbuf; 6231541Srgrimes u_short *outlen; 6241541Srgrimes ino_t *inump; 6251541Srgrimes struct iso_mnt *imp; 6261541Srgrimes{ 6271541Srgrimes ISO_RRIP_ANALYZE analyze; 6281541Srgrimes RRIP_TABLE *tab; 62945773Sdcs u_char c; 6308876Srgrimes 6311541Srgrimes analyze.outbuf = outbuf; 6321541Srgrimes analyze.outlen = outlen; 6331541Srgrimes analyze.maxlen = NAME_MAX; 6341541Srgrimes analyze.inump = inump; 6351541Srgrimes analyze.imp = imp; 6361541Srgrimes analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 6371541Srgrimes *outlen = 0; 6388876Srgrimes 63945773Sdcs isochar(isodir->name, isodir->name + isonum_711(isodir->name_len), 64045773Sdcs imp->joliet_level, &c); 6411541Srgrimes tab = rrip_table_getname; 64245773Sdcs if (c == 0 || c == 1) { 6431541Srgrimes cd9660_rrip_defname(isodir,&analyze); 6448876Srgrimes 6451541Srgrimes analyze.fields &= ~ISO_SUSP_ALTNAME; 6461541Srgrimes tab++; 6471541Srgrimes } 6488876Srgrimes 6491541Srgrimes return cd9660_rrip_loop(isodir,&analyze,tab); 6501541Srgrimes} 6511541Srgrimes 65222521Sdyson/* 65322521Sdyson * Get Symbolic Link. 6541541Srgrimes */ 6551541Srgrimesstatic RRIP_TABLE rrip_table_getsymname[] = { 65612597Sbde { "SL", BC cd9660_rrip_slink, 0, ISO_SUSP_SLINK }, 65712597Sbde { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 65812597Sbde { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 65912597Sbde { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 6601541Srgrimes { "", 0, 0, 0 } 6611541Srgrimes}; 6621541Srgrimes 6631541Srgrimesint 6641541Srgrimescd9660_rrip_getsymname(isodir,outbuf,outlen,imp) 6651541Srgrimes struct iso_directory_record *isodir; 6661541Srgrimes char *outbuf; 6671541Srgrimes u_short *outlen; 6681541Srgrimes struct iso_mnt *imp; 6691541Srgrimes{ 6701541Srgrimes ISO_RRIP_ANALYZE analyze; 6718876Srgrimes 6721541Srgrimes analyze.outbuf = outbuf; 6731541Srgrimes analyze.outlen = outlen; 6741541Srgrimes *outlen = 0; 6751541Srgrimes analyze.maxlen = MAXPATHLEN; 6761541Srgrimes analyze.cont = 1; /* don't start with a slash */ 6771541Srgrimes analyze.imp = imp; 6781541Srgrimes analyze.fields = ISO_SUSP_SLINK; 6798876Srgrimes 6801541Srgrimes return (cd9660_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK); 6811541Srgrimes} 6821541Srgrimes 6831541Srgrimesstatic RRIP_TABLE rrip_table_extref[] = { 68412597Sbde { "ER", BC cd9660_rrip_extref, 0, ISO_SUSP_EXTREF }, 68512597Sbde { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 68612597Sbde { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 6871541Srgrimes { "", 0, 0, 0 } 6881541Srgrimes}; 6891541Srgrimes 6901541Srgrimes/* 6911541Srgrimes * Check for Rock Ridge Extension and return offset of its fields. 69222521Sdyson * Note: We insist on the ER field. 6931541Srgrimes */ 6941541Srgrimesint 6951541Srgrimescd9660_rrip_offset(isodir,imp) 6961541Srgrimes struct iso_directory_record *isodir; 6971541Srgrimes struct iso_mnt *imp; 6981541Srgrimes{ 6991541Srgrimes ISO_RRIP_OFFSET *p; 7001541Srgrimes ISO_RRIP_ANALYZE analyze; 7018876Srgrimes 7021541Srgrimes imp->rr_skip0 = 0; 7031541Srgrimes p = (ISO_RRIP_OFFSET *)(isodir->name + 1); 7041541Srgrimes if (bcmp(p,"SP\7\1\276\357",6)) { 7051541Srgrimes /* Maybe, it's a CDROM XA disc? */ 7061541Srgrimes imp->rr_skip0 = 15; 7071541Srgrimes p = (ISO_RRIP_OFFSET *)((char *)p + 15); 7081541Srgrimes if (bcmp(p,"SP\7\1\276\357",6)) 7091541Srgrimes return -1; 7101541Srgrimes } 7118876Srgrimes 7121541Srgrimes analyze.imp = imp; 7131541Srgrimes analyze.fields = ISO_SUSP_EXTREF; 7141541Srgrimes if (!(cd9660_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF)) 7151541Srgrimes return -1; 7168876Srgrimes 7171541Srgrimes return isonum_711(p->skip); 7181541Srgrimes} 719