cd9660_rrip.c revision 120492
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 391541Srgrimes */ 401541Srgrimes 41116181Sobrien#include <sys/cdefs.h> 42116181Sobrien__FBSDID("$FreeBSD: head/sys/fs/cd9660/cd9660_rrip.c 120492 2003-09-26 20:26:25Z fjoe $"); 43116181Sobrien 441541Srgrimes#include <sys/param.h> 452806Sbde#include <sys/systm.h> 4660041Sphk#include <sys/bio.h> 471541Srgrimes#include <sys/buf.h> 481541Srgrimes#include <sys/vnode.h> 491541Srgrimes#include <sys/mount.h> 501541Srgrimes#include <sys/kernel.h> 511541Srgrimes 521541Srgrimes#include <isofs/cd9660/iso.h> 531541Srgrimes#include <isofs/cd9660/cd9660_node.h> 541541Srgrimes#include <isofs/cd9660/cd9660_rrip.h> 551541Srgrimes#include <isofs/cd9660/iso_rrip.h> 561541Srgrimes 5792765Salfredtypedef int rrt_func_t(void *, ISO_RRIP_ANALYZE *ana); 5812597Sbde 5912597Sbdetypedef struct { 6012597Sbde char type[2]; 6112597Sbde rrt_func_t *func; 6292765Salfred void (*func2)(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana); 6312597Sbde int result; 6412597Sbde} RRIP_TABLE; 6512597Sbde 6692765Salfredstatic int cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, ISO_RRIP_ANALYZE *ana); 6792765Salfredstatic int cd9660_rrip_attr(ISO_RRIP_ATTR *p, ISO_RRIP_ANALYZE *ana); 6892765Salfredstatic int cd9660_rrip_cont(ISO_RRIP_CONT *p, ISO_RRIP_ANALYZE *ana); 6992765Salfredstatic void cd9660_rrip_defattr(struct iso_directory_record *isodir, 7093075Sbde ISO_RRIP_ANALYZE *ana); 7192765Salfredstatic void cd9660_rrip_defname(struct iso_directory_record *isodir, 7293075Sbde ISO_RRIP_ANALYZE *ana); 7392765Salfredstatic void cd9660_rrip_deftstamp(struct iso_directory_record *isodir, 7493075Sbde ISO_RRIP_ANALYZE *ana); 7592765Salfredstatic int cd9660_rrip_device(ISO_RRIP_DEVICE *p, ISO_RRIP_ANALYZE *ana); 7692765Salfredstatic int cd9660_rrip_extref(ISO_RRIP_EXTREF *p, ISO_RRIP_ANALYZE *ana); 7792765Salfredstatic int cd9660_rrip_idflag(ISO_RRIP_IDFLAG *p, ISO_RRIP_ANALYZE *ana); 7892765Salfredstatic int cd9660_rrip_loop(struct iso_directory_record *isodir, 7993075Sbde ISO_RRIP_ANALYZE *ana, RRIP_TABLE *table); 8092765Salfredstatic int cd9660_rrip_pclink(ISO_RRIP_CLINK *p, ISO_RRIP_ANALYZE *ana); 8192765Salfredstatic int cd9660_rrip_reldir(ISO_RRIP_RELDIR *p, ISO_RRIP_ANALYZE *ana); 8292765Salfredstatic int cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana); 8392765Salfredstatic int cd9660_rrip_stop(ISO_SUSP_HEADER *p, ISO_RRIP_ANALYZE *ana); 8492765Salfredstatic int cd9660_rrip_tstamp(ISO_RRIP_TSTAMP *p, ISO_RRIP_ANALYZE *ana); 8512597Sbde 861541Srgrimes/* 871541Srgrimes * POSIX file attribute 881541Srgrimes */ 891541Srgrimesstatic int 901541Srgrimescd9660_rrip_attr(p,ana) 911541Srgrimes ISO_RRIP_ATTR *p; 921541Srgrimes ISO_RRIP_ANALYZE *ana; 931541Srgrimes{ 9422521Sdyson ana->inop->inode.iso_mode = isonum_733(p->mode); 9522521Sdyson ana->inop->inode.iso_uid = isonum_733(p->uid); 9622521Sdyson ana->inop->inode.iso_gid = isonum_733(p->gid); 9722521Sdyson ana->inop->inode.iso_links = isonum_733(p->links); 981541Srgrimes ana->fields &= ~ISO_SUSP_ATTR; 991541Srgrimes return ISO_SUSP_ATTR; 1001541Srgrimes} 1011541Srgrimes 1021541Srgrimesstatic void 1031541Srgrimescd9660_rrip_defattr(isodir,ana) 1041541Srgrimes struct iso_directory_record *isodir; 1051541Srgrimes ISO_RRIP_ANALYZE *ana; 1061541Srgrimes{ 1071541Srgrimes /* But this is a required field! */ 1081541Srgrimes printf("RRIP without PX field?\n"); 1095651Sjoerg cd9660_defattr(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 1101541Srgrimes} 1111541Srgrimes 1121541Srgrimes/* 1131541Srgrimes * Symbolic Links 1141541Srgrimes */ 1151541Srgrimesstatic int 1161541Srgrimescd9660_rrip_slink(p,ana) 1175651Sjoerg ISO_RRIP_SLINK *p; 1181541Srgrimes ISO_RRIP_ANALYZE *ana; 1191541Srgrimes{ 1201541Srgrimes register ISO_RRIP_SLINK_COMPONENT *pcomp; 1211541Srgrimes register ISO_RRIP_SLINK_COMPONENT *pcompe; 1221541Srgrimes int len, wlen, cont; 1231541Srgrimes char *outbuf, *inbuf; 1248876Srgrimes 1251541Srgrimes pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component; 1261541Srgrimes pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length)); 1271541Srgrimes len = *ana->outlen; 1281541Srgrimes outbuf = ana->outbuf; 1291541Srgrimes cont = ana->cont; 1308876Srgrimes 1311541Srgrimes /* 1321541Srgrimes * Gathering a Symbolic name from each component with path 1331541Srgrimes */ 1341541Srgrimes for (; 1351541Srgrimes pcomp < pcompe; 1361541Srgrimes pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ 1371541Srgrimes + isonum_711(pcomp->clen))) { 1388876Srgrimes 1391541Srgrimes if (!cont) { 1401541Srgrimes if (len < ana->maxlen) { 1411541Srgrimes len++; 1421541Srgrimes *outbuf++ = '/'; 1431541Srgrimes } 1441541Srgrimes } 1451541Srgrimes cont = 0; 1468876Srgrimes 1471541Srgrimes inbuf = ".."; 1481541Srgrimes wlen = 0; 1498876Srgrimes 1501541Srgrimes switch (*pcomp->cflag) { 1518876Srgrimes 1521541Srgrimes case ISO_SUSP_CFLAG_CURRENT: 1531541Srgrimes /* Inserting Current */ 1541541Srgrimes wlen = 1; 1551541Srgrimes break; 1568876Srgrimes 1571541Srgrimes case ISO_SUSP_CFLAG_PARENT: 1581541Srgrimes /* Inserting Parent */ 1591541Srgrimes wlen = 2; 1601541Srgrimes break; 1618876Srgrimes 1621541Srgrimes case ISO_SUSP_CFLAG_ROOT: 1631541Srgrimes /* Inserting slash for ROOT */ 1641541Srgrimes /* start over from beginning(?) */ 1651541Srgrimes outbuf -= len; 1661541Srgrimes len = 0; 1671541Srgrimes break; 1688876Srgrimes 1691541Srgrimes case ISO_SUSP_CFLAG_VOLROOT: 1701541Srgrimes /* Inserting a mount point i.e. "/cdrom" */ 1711541Srgrimes /* same as above */ 1721541Srgrimes outbuf -= len; 1731541Srgrimes len = 0; 1741541Srgrimes inbuf = ana->imp->im_mountp->mnt_stat.f_mntonname; 1751541Srgrimes wlen = strlen(inbuf); 1761541Srgrimes break; 1778876Srgrimes 1781541Srgrimes case ISO_SUSP_CFLAG_HOST: 1791541Srgrimes /* Inserting hostname i.e. "kurt.tools.de" */ 1801541Srgrimes inbuf = hostname; 18112287Sphk wlen = strlen(hostname); 1821541Srgrimes break; 1838876Srgrimes 1841541Srgrimes case ISO_SUSP_CFLAG_CONTINUE: 1851541Srgrimes cont = 1; 186102412Scharnier /* FALLTHROUGH */ 1871541Srgrimes case 0: 1881541Srgrimes /* Inserting component */ 1891541Srgrimes wlen = isonum_711(pcomp->clen); 1901541Srgrimes inbuf = pcomp->name; 1911541Srgrimes break; 1921541Srgrimes default: 1931541Srgrimes printf("RRIP with incorrect flags?"); 1941541Srgrimes wlen = ana->maxlen + 1; 1951541Srgrimes break; 1961541Srgrimes } 1978876Srgrimes 1981541Srgrimes if (len + wlen > ana->maxlen) { 1991541Srgrimes /* indicate error to caller */ 2001541Srgrimes ana->cont = 1; 2011541Srgrimes ana->fields = 0; 2021541Srgrimes ana->outbuf -= *ana->outlen; 2031541Srgrimes *ana->outlen = 0; 2041541Srgrimes return 0; 2051541Srgrimes } 2068876Srgrimes 2071541Srgrimes bcopy(inbuf,outbuf,wlen); 2081541Srgrimes outbuf += wlen; 2091541Srgrimes len += wlen; 2108876Srgrimes 2111541Srgrimes } 2121541Srgrimes ana->outbuf = outbuf; 2131541Srgrimes *ana->outlen = len; 2141541Srgrimes ana->cont = cont; 2158876Srgrimes 2161541Srgrimes if (!isonum_711(p->flags)) { 2171541Srgrimes ana->fields &= ~ISO_SUSP_SLINK; 2181541Srgrimes return ISO_SUSP_SLINK; 2191541Srgrimes } 2201541Srgrimes return 0; 2211541Srgrimes} 2221541Srgrimes 2231541Srgrimes/* 2241541Srgrimes * Alternate name 2251541Srgrimes */ 2261541Srgrimesstatic int 2271541Srgrimescd9660_rrip_altname(p,ana) 2281541Srgrimes ISO_RRIP_ALTNAME *p; 2291541Srgrimes ISO_RRIP_ANALYZE *ana; 2301541Srgrimes{ 2311541Srgrimes char *inbuf; 2321541Srgrimes int wlen; 2331541Srgrimes int cont; 2348876Srgrimes 2351541Srgrimes inbuf = ".."; 2361541Srgrimes wlen = 0; 2371541Srgrimes cont = 0; 2388876Srgrimes 2391541Srgrimes switch (*p->flags) { 2401541Srgrimes case ISO_SUSP_CFLAG_CURRENT: 2411541Srgrimes /* Inserting Current */ 2421541Srgrimes wlen = 1; 2431541Srgrimes break; 2448876Srgrimes 2451541Srgrimes case ISO_SUSP_CFLAG_PARENT: 2461541Srgrimes /* Inserting Parent */ 2471541Srgrimes wlen = 2; 2481541Srgrimes break; 2498876Srgrimes 2501541Srgrimes case ISO_SUSP_CFLAG_HOST: 2511541Srgrimes /* Inserting hostname i.e. "kurt.tools.de" */ 2521541Srgrimes inbuf = hostname; 25312287Sphk wlen = strlen(hostname); 2541541Srgrimes break; 2558876Srgrimes 2561541Srgrimes case ISO_SUSP_CFLAG_CONTINUE: 2571541Srgrimes cont = 1; 258102412Scharnier /* FALLTHROUGH */ 2591541Srgrimes case 0: 2601541Srgrimes /* Inserting component */ 2611541Srgrimes wlen = isonum_711(p->h.length) - 5; 2621541Srgrimes inbuf = (char *)p + 5; 2631541Srgrimes break; 2648876Srgrimes 2651541Srgrimes default: 2661541Srgrimes printf("RRIP with incorrect NM flags?\n"); 2671541Srgrimes wlen = ana->maxlen + 1; 2681541Srgrimes break; 2691541Srgrimes } 2708876Srgrimes 2711541Srgrimes if ((*ana->outlen += wlen) > ana->maxlen) { 2721541Srgrimes /* treat as no name field */ 2731541Srgrimes ana->fields &= ~ISO_SUSP_ALTNAME; 2741541Srgrimes ana->outbuf -= *ana->outlen - wlen; 2751541Srgrimes *ana->outlen = 0; 2761541Srgrimes return 0; 2771541Srgrimes } 2788876Srgrimes 2791541Srgrimes bcopy(inbuf,ana->outbuf,wlen); 2801541Srgrimes ana->outbuf += wlen; 2818876Srgrimes 2821541Srgrimes if (!cont) { 2831541Srgrimes ana->fields &= ~ISO_SUSP_ALTNAME; 2841541Srgrimes return ISO_SUSP_ALTNAME; 2851541Srgrimes } 2861541Srgrimes return 0; 2871541Srgrimes} 2881541Srgrimes 2891541Srgrimesstatic void 2901541Srgrimescd9660_rrip_defname(isodir,ana) 2911541Srgrimes struct iso_directory_record *isodir; 2921541Srgrimes ISO_RRIP_ANALYZE *ana; 2931541Srgrimes{ 29445773Sdcs isofntrans(isodir->name,isonum_711(isodir->name_len), 29545773Sdcs ana->outbuf,ana->outlen, 296120492Sfjoe 1,isonum_711(isodir->flags)&4, ana->imp->joliet_level, 297120492Sfjoe ana->imp->im_flags, ana->imp->im_d2l); 29845773Sdcs switch (*ana->outbuf) { 2991541Srgrimes default: 3001541Srgrimes break; 3011541Srgrimes case 1: 3021541Srgrimes *ana->outlen = 2; 303102412Scharnier /* FALLTHROUGH */ 30445773Sdcs case 0: 30545773Sdcs /* outlen is 1 already */ 30645773Sdcs strcpy(ana->outbuf,".."); 3071541Srgrimes break; 3081541Srgrimes } 3091541Srgrimes} 3101541Srgrimes 3111541Srgrimes/* 3121541Srgrimes * Parent or Child Link 3131541Srgrimes */ 3141541Srgrimesstatic int 3151541Srgrimescd9660_rrip_pclink(p,ana) 3165651Sjoerg ISO_RRIP_CLINK *p; 3171541Srgrimes ISO_RRIP_ANALYZE *ana; 3181541Srgrimes{ 3191541Srgrimes *ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift; 3201541Srgrimes ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK); 3211541Srgrimes return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK; 3221541Srgrimes} 3231541Srgrimes 3241541Srgrimes/* 3251541Srgrimes * Relocated directory 3261541Srgrimes */ 3271541Srgrimesstatic int 3281541Srgrimescd9660_rrip_reldir(p,ana) 3295651Sjoerg ISO_RRIP_RELDIR *p; 3301541Srgrimes ISO_RRIP_ANALYZE *ana; 3311541Srgrimes{ 3321541Srgrimes /* special hack to make caller aware of RE field */ 3331541Srgrimes *ana->outlen = 0; 3341541Srgrimes ana->fields = 0; 3351541Srgrimes return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 3361541Srgrimes} 3371541Srgrimes 3381541Srgrimesstatic int 3391541Srgrimescd9660_rrip_tstamp(p,ana) 3401541Srgrimes ISO_RRIP_TSTAMP *p; 3411541Srgrimes ISO_RRIP_ANALYZE *ana; 3421541Srgrimes{ 34322521Sdyson u_char *ptime; 34422521Sdyson 3451541Srgrimes ptime = p->time; 3468876Srgrimes 3471541Srgrimes /* Check a format of time stamp (7bytes/17bytes) */ 3481541Srgrimes if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) { 3491541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 3501541Srgrimes ptime += 7; 3518876Srgrimes 3521541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 3535651Sjoerg cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime, 3545651Sjoerg ISO_FTYPE_RRIP); 3551541Srgrimes ptime += 7; 3561541Srgrimes } else 3572806Sbde bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 35822521Sdyson 3591541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 3605651Sjoerg cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime, 3615651Sjoerg ISO_FTYPE_RRIP); 3621541Srgrimes ptime += 7; 3631541Srgrimes } else 3641541Srgrimes ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 3658876Srgrimes 3661541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 3675651Sjoerg cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime, 3685651Sjoerg ISO_FTYPE_RRIP); 3691541Srgrimes else 3701541Srgrimes ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 3718876Srgrimes 3721541Srgrimes } else { 3731541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 3741541Srgrimes ptime += 17; 3758876Srgrimes 3761541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 3771541Srgrimes cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime); 3781541Srgrimes ptime += 17; 3791541Srgrimes } else 3802806Sbde bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 38122521Sdyson 3821541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 3831541Srgrimes cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime); 3841541Srgrimes ptime += 17; 3851541Srgrimes } else 3861541Srgrimes ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 3878876Srgrimes 3881541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 3891541Srgrimes cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime); 3901541Srgrimes else 3911541Srgrimes ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 3928876Srgrimes 3931541Srgrimes } 3941541Srgrimes ana->fields &= ~ISO_SUSP_TSTAMP; 3951541Srgrimes return ISO_SUSP_TSTAMP; 3961541Srgrimes} 3971541Srgrimes 3981541Srgrimesstatic void 3991541Srgrimescd9660_rrip_deftstamp(isodir,ana) 4001541Srgrimes struct iso_directory_record *isodir; 4011541Srgrimes ISO_RRIP_ANALYZE *ana; 4021541Srgrimes{ 4035651Sjoerg cd9660_deftstamp(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 4041541Srgrimes} 4051541Srgrimes 4061541Srgrimes/* 4071541Srgrimes * POSIX device modes 4081541Srgrimes */ 4091541Srgrimesstatic int 4101541Srgrimescd9660_rrip_device(p,ana) 4111541Srgrimes ISO_RRIP_DEVICE *p; 4121541Srgrimes ISO_RRIP_ANALYZE *ana; 4131541Srgrimes{ 41422521Sdyson u_int high, low; 41522521Sdyson 41622521Sdyson high = isonum_733(p->dev_t_high); 41722521Sdyson low = isonum_733(p->dev_t_low); 41822521Sdyson 41922521Sdyson if (high == 0) 42048859Sphk ana->inop->inode.iso_rdev = makeudev(umajor(low), uminor(low)); 42122521Sdyson else 42248859Sphk ana->inop->inode.iso_rdev = makeudev(high, uminor(low)); 4231541Srgrimes ana->fields &= ~ISO_SUSP_DEVICE; 4241541Srgrimes return ISO_SUSP_DEVICE; 4251541Srgrimes} 4261541Srgrimes 4271541Srgrimes/* 4281541Srgrimes * Flag indicating 4291541Srgrimes */ 4301541Srgrimesstatic int 4311541Srgrimescd9660_rrip_idflag(p,ana) 4321541Srgrimes ISO_RRIP_IDFLAG *p; 4331541Srgrimes ISO_RRIP_ANALYZE *ana; 4341541Srgrimes{ 4351541Srgrimes ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */ 4361541Srgrimes /* special handling of RE field */ 4371541Srgrimes if (ana->fields&ISO_SUSP_RELDIR) 43812597Sbde return cd9660_rrip_reldir(/* XXX */ (ISO_RRIP_RELDIR *)p,ana); 4398876Srgrimes 4401541Srgrimes return ISO_SUSP_IDFLAG; 4411541Srgrimes} 4421541Srgrimes 4431541Srgrimes/* 4441541Srgrimes * Continuation pointer 4451541Srgrimes */ 4461541Srgrimesstatic int 4471541Srgrimescd9660_rrip_cont(p,ana) 4481541Srgrimes ISO_RRIP_CONT *p; 4491541Srgrimes ISO_RRIP_ANALYZE *ana; 4501541Srgrimes{ 4511541Srgrimes ana->iso_ce_blk = isonum_733(p->location); 4521541Srgrimes ana->iso_ce_off = isonum_733(p->offset); 4531541Srgrimes ana->iso_ce_len = isonum_733(p->length); 4541541Srgrimes return ISO_SUSP_CONT; 4551541Srgrimes} 4561541Srgrimes 4571541Srgrimes/* 4581541Srgrimes * System Use end 4591541Srgrimes */ 4601541Srgrimesstatic int 4611541Srgrimescd9660_rrip_stop(p,ana) 4621541Srgrimes ISO_SUSP_HEADER *p; 4631541Srgrimes ISO_RRIP_ANALYZE *ana; 4641541Srgrimes{ 4651541Srgrimes return ISO_SUSP_STOP; 4661541Srgrimes} 4671541Srgrimes 4681541Srgrimes/* 4691541Srgrimes * Extension reference 4701541Srgrimes */ 4711541Srgrimesstatic int 4721541Srgrimescd9660_rrip_extref(p,ana) 4731541Srgrimes ISO_RRIP_EXTREF *p; 4741541Srgrimes ISO_RRIP_ANALYZE *ana; 4751541Srgrimes{ 4761541Srgrimes if (isonum_711(p->len_id) != 10 4771541Srgrimes || bcmp((char *)p + 8,"RRIP_1991A",10) 4781541Srgrimes || isonum_711(p->version) != 1) 4791541Srgrimes return 0; 4801541Srgrimes ana->fields &= ~ISO_SUSP_EXTREF; 4811541Srgrimes return ISO_SUSP_EXTREF; 4821541Srgrimes} 4831541Srgrimes 4841541Srgrimesstatic int 4851541Srgrimescd9660_rrip_loop(isodir,ana,table) 4861541Srgrimes struct iso_directory_record *isodir; 4871541Srgrimes ISO_RRIP_ANALYZE *ana; 4881541Srgrimes RRIP_TABLE *table; 4891541Srgrimes{ 4901541Srgrimes register RRIP_TABLE *ptable; 4911541Srgrimes register ISO_SUSP_HEADER *phead; 4921541Srgrimes register ISO_SUSP_HEADER *pend; 4931541Srgrimes struct buf *bp = NULL; 4941541Srgrimes char *pwhead; 495120492Sfjoe u_short c; 4961541Srgrimes int result; 4978876Srgrimes 4981541Srgrimes /* 4991541Srgrimes * Note: If name length is odd, 5005651Sjoerg * it will be padding 1 byte after the name 5011541Srgrimes */ 5021541Srgrimes pwhead = isodir->name + isonum_711(isodir->name_len); 5031541Srgrimes if (!(isonum_711(isodir->name_len)&1)) 5041541Srgrimes pwhead++; 505120492Sfjoe isochar(isodir->name, pwhead, ana->imp->joliet_level, &c, NULL, 506120492Sfjoe ana->imp->im_flags, ana->imp->im_d2l); 5078876Srgrimes 5081541Srgrimes /* If it's not the '.' entry of the root dir obey SP field */ 50945773Sdcs if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent) 5101541Srgrimes pwhead += ana->imp->rr_skip; 5111541Srgrimes else 5121541Srgrimes pwhead += ana->imp->rr_skip0; 5138876Srgrimes 5141541Srgrimes phead = (ISO_SUSP_HEADER *)pwhead; 5151541Srgrimes pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length)); 5168876Srgrimes 5171541Srgrimes result = 0; 5181541Srgrimes while (1) { 5191541Srgrimes ana->iso_ce_len = 0; 5201541Srgrimes /* 5211541Srgrimes * Note: "pend" should be more than one SUSP header 5228876Srgrimes */ 5231541Srgrimes while (pend >= phead + 1) { 5241541Srgrimes if (isonum_711(phead->version) == 1) { 5251541Srgrimes for (ptable = table; ptable->func; ptable++) { 5261541Srgrimes if (*phead->type == *ptable->type 5271541Srgrimes && phead->type[1] == ptable->type[1]) { 5281541Srgrimes result |= ptable->func(phead,ana); 5291541Srgrimes break; 5301541Srgrimes } 5311541Srgrimes } 5321541Srgrimes if (!ana->fields) 5331541Srgrimes break; 5341541Srgrimes } 53522521Sdyson if (result&ISO_SUSP_STOP) { 53622521Sdyson result &= ~ISO_SUSP_STOP; 53722521Sdyson break; 53822521Sdyson } 53922521Sdyson /* plausibility check */ 54022521Sdyson if (isonum_711(phead->length) < sizeof(*phead)) 54122521Sdyson break; 5421541Srgrimes /* 5431541Srgrimes * move to next SUSP 5441541Srgrimes * Hopefully this works with newer versions, too 5451541Srgrimes */ 5461541Srgrimes phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length)); 5471541Srgrimes } 54822521Sdyson 54922521Sdyson if (ana->fields && ana->iso_ce_len) { 5501541Srgrimes if (ana->iso_ce_blk >= ana->imp->volume_space_size 5511541Srgrimes || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size 5521541Srgrimes || bread(ana->imp->im_devvp, 55322521Sdyson ana->iso_ce_blk << 55422521Sdyson (ana->imp->im_bshift - DEV_BSHIFT), 55522521Sdyson ana->imp->logical_block_size, NOCRED, &bp)) 5561541Srgrimes /* what to do now? */ 5571541Srgrimes break; 55822521Sdyson phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off); 5591541Srgrimes pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len); 5601541Srgrimes } else 5611541Srgrimes break; 5621541Srgrimes } 5631541Srgrimes if (bp) 5641541Srgrimes brelse(bp); 5651541Srgrimes /* 5661541Srgrimes * If we don't find the Basic SUSP stuffs, just set default value 56722521Sdyson * (attribute/time stamp) 5681541Srgrimes */ 5691541Srgrimes for (ptable = table; ptable->func2; ptable++) 5701541Srgrimes if (!(ptable->result&result)) 5711541Srgrimes ptable->func2(isodir,ana); 5728876Srgrimes 5731541Srgrimes return result; 5741541Srgrimes} 5751541Srgrimes 57612597Sbde/* 57722521Sdyson * Get Attributes. 57822521Sdyson */ 57922521Sdyson/* 58012597Sbde * XXX the casts are bogus but will do for now. 58112597Sbde */ 58212597Sbde#define BC (rrt_func_t *) 5831541Srgrimesstatic RRIP_TABLE rrip_table_analyze[] = { 58412597Sbde { "PX", BC cd9660_rrip_attr, cd9660_rrip_defattr, ISO_SUSP_ATTR }, 58512597Sbde { "TF", BC cd9660_rrip_tstamp, cd9660_rrip_deftstamp, ISO_SUSP_TSTAMP }, 58612597Sbde { "PN", BC cd9660_rrip_device, 0, ISO_SUSP_DEVICE }, 58712597Sbde { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 58812597Sbde { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 58912597Sbde { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 5901541Srgrimes { "", 0, 0, 0 } 5911541Srgrimes}; 5921541Srgrimes 5931541Srgrimesint 5941541Srgrimescd9660_rrip_analyze(isodir,inop,imp) 5951541Srgrimes struct iso_directory_record *isodir; 5961541Srgrimes struct iso_node *inop; 5971541Srgrimes struct iso_mnt *imp; 5981541Srgrimes{ 5991541Srgrimes ISO_RRIP_ANALYZE analyze; 6008876Srgrimes 6011541Srgrimes analyze.inop = inop; 6021541Srgrimes analyze.imp = imp; 6031541Srgrimes analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE; 6048876Srgrimes 6051541Srgrimes return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze); 6061541Srgrimes} 6071541Srgrimes 60822521Sdyson/* 60922521Sdyson * Get Alternate Name. 6101541Srgrimes */ 6111541Srgrimesstatic RRIP_TABLE rrip_table_getname[] = { 61212597Sbde { "NM", BC cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME }, 61312597Sbde { "CL", BC cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 61412597Sbde { "PL", BC cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 61512597Sbde { "RE", BC cd9660_rrip_reldir, 0, ISO_SUSP_RELDIR }, 61612597Sbde { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 61712597Sbde { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 61812597Sbde { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 6191541Srgrimes { "", 0, 0, 0 } 6201541Srgrimes}; 6211541Srgrimes 6221541Srgrimesint 6231541Srgrimescd9660_rrip_getname(isodir,outbuf,outlen,inump,imp) 6241541Srgrimes struct iso_directory_record *isodir; 6251541Srgrimes char *outbuf; 6261541Srgrimes u_short *outlen; 6271541Srgrimes ino_t *inump; 6281541Srgrimes struct iso_mnt *imp; 6291541Srgrimes{ 6301541Srgrimes ISO_RRIP_ANALYZE analyze; 6311541Srgrimes RRIP_TABLE *tab; 632120492Sfjoe u_short c; 6338876Srgrimes 6341541Srgrimes analyze.outbuf = outbuf; 6351541Srgrimes analyze.outlen = outlen; 6361541Srgrimes analyze.maxlen = NAME_MAX; 6371541Srgrimes analyze.inump = inump; 6381541Srgrimes analyze.imp = imp; 6391541Srgrimes analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 6401541Srgrimes *outlen = 0; 6418876Srgrimes 64245773Sdcs isochar(isodir->name, isodir->name + isonum_711(isodir->name_len), 643120492Sfjoe imp->joliet_level, &c, NULL, imp->im_flags, imp->im_d2l); 6441541Srgrimes tab = rrip_table_getname; 64545773Sdcs if (c == 0 || c == 1) { 6461541Srgrimes cd9660_rrip_defname(isodir,&analyze); 6478876Srgrimes 6481541Srgrimes analyze.fields &= ~ISO_SUSP_ALTNAME; 6491541Srgrimes tab++; 6501541Srgrimes } 6518876Srgrimes 6521541Srgrimes return cd9660_rrip_loop(isodir,&analyze,tab); 6531541Srgrimes} 6541541Srgrimes 65522521Sdyson/* 65622521Sdyson * Get Symbolic Link. 6571541Srgrimes */ 6581541Srgrimesstatic RRIP_TABLE rrip_table_getsymname[] = { 65912597Sbde { "SL", BC cd9660_rrip_slink, 0, ISO_SUSP_SLINK }, 66012597Sbde { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 66112597Sbde { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 66212597Sbde { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 6631541Srgrimes { "", 0, 0, 0 } 6641541Srgrimes}; 6651541Srgrimes 6661541Srgrimesint 6671541Srgrimescd9660_rrip_getsymname(isodir,outbuf,outlen,imp) 6681541Srgrimes struct iso_directory_record *isodir; 6691541Srgrimes char *outbuf; 6701541Srgrimes u_short *outlen; 6711541Srgrimes struct iso_mnt *imp; 6721541Srgrimes{ 6731541Srgrimes ISO_RRIP_ANALYZE analyze; 6748876Srgrimes 6751541Srgrimes analyze.outbuf = outbuf; 6761541Srgrimes analyze.outlen = outlen; 6771541Srgrimes *outlen = 0; 6781541Srgrimes analyze.maxlen = MAXPATHLEN; 6791541Srgrimes analyze.cont = 1; /* don't start with a slash */ 6801541Srgrimes analyze.imp = imp; 6811541Srgrimes analyze.fields = ISO_SUSP_SLINK; 6828876Srgrimes 6831541Srgrimes return (cd9660_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK); 6841541Srgrimes} 6851541Srgrimes 6861541Srgrimesstatic RRIP_TABLE rrip_table_extref[] = { 68712597Sbde { "ER", BC cd9660_rrip_extref, 0, ISO_SUSP_EXTREF }, 68812597Sbde { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 68912597Sbde { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 6901541Srgrimes { "", 0, 0, 0 } 6911541Srgrimes}; 6921541Srgrimes 6931541Srgrimes/* 6941541Srgrimes * Check for Rock Ridge Extension and return offset of its fields. 69522521Sdyson * Note: We insist on the ER field. 6961541Srgrimes */ 6971541Srgrimesint 6981541Srgrimescd9660_rrip_offset(isodir,imp) 6991541Srgrimes struct iso_directory_record *isodir; 7001541Srgrimes struct iso_mnt *imp; 7011541Srgrimes{ 7021541Srgrimes ISO_RRIP_OFFSET *p; 7031541Srgrimes ISO_RRIP_ANALYZE analyze; 7048876Srgrimes 7051541Srgrimes imp->rr_skip0 = 0; 7061541Srgrimes p = (ISO_RRIP_OFFSET *)(isodir->name + 1); 7071541Srgrimes if (bcmp(p,"SP\7\1\276\357",6)) { 7081541Srgrimes /* Maybe, it's a CDROM XA disc? */ 7091541Srgrimes imp->rr_skip0 = 15; 7101541Srgrimes p = (ISO_RRIP_OFFSET *)((char *)p + 15); 7111541Srgrimes if (bcmp(p,"SP\7\1\276\357",6)) 7121541Srgrimes return -1; 7131541Srgrimes } 7148876Srgrimes 7151541Srgrimes analyze.imp = imp; 7161541Srgrimes analyze.fields = ISO_SUSP_EXTREF; 7171541Srgrimes if (!(cd9660_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF)) 7181541Srgrimes return -1; 7198876Srgrimes 7201541Srgrimes return isonum_711(p->skip); 7211541Srgrimes} 722