cd9660_rrip.c revision 187830
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 * 4. Neither the name of the University nor the names of its contributors 191541Srgrimes * may be used to endorse or promote products derived from this software 201541Srgrimes * without specific prior written permission. 211541Srgrimes * 221541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 231541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 241541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 251541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 261541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 271541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 281541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 291541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 301541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 311541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 321541Srgrimes * SUCH DAMAGE. 331541Srgrimes * 3422521Sdyson * @(#)cd9660_rrip.c 8.6 (Berkeley) 12/5/94 351541Srgrimes */ 361541Srgrimes 37116181Sobrien#include <sys/cdefs.h> 38116181Sobrien__FBSDID("$FreeBSD: head/sys/fs/cd9660/cd9660_rrip.c 187830 2009-01-28 17:57:16Z ed $"); 39116181Sobrien 401541Srgrimes#include <sys/param.h> 412806Sbde#include <sys/systm.h> 4260041Sphk#include <sys/bio.h> 431541Srgrimes#include <sys/buf.h> 441541Srgrimes#include <sys/vnode.h> 451541Srgrimes#include <sys/mount.h> 461541Srgrimes#include <sys/kernel.h> 47181803Sbz#include <sys/vimage.h> 481541Srgrimes 49166639Srodrigc#include <fs/cd9660/iso.h> 50166639Srodrigc#include <fs/cd9660/cd9660_node.h> 51166639Srodrigc#include <fs/cd9660/cd9660_rrip.h> 52166639Srodrigc#include <fs/cd9660/iso_rrip.h> 531541Srgrimes 5492765Salfredtypedef int rrt_func_t(void *, ISO_RRIP_ANALYZE *ana); 5512597Sbde 5612597Sbdetypedef struct { 5712597Sbde char type[2]; 5812597Sbde rrt_func_t *func; 5992765Salfred void (*func2)(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana); 6012597Sbde int result; 6112597Sbde} RRIP_TABLE; 6212597Sbde 6392765Salfredstatic int cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, ISO_RRIP_ANALYZE *ana); 6492765Salfredstatic int cd9660_rrip_attr(ISO_RRIP_ATTR *p, ISO_RRIP_ANALYZE *ana); 6592765Salfredstatic int cd9660_rrip_cont(ISO_RRIP_CONT *p, ISO_RRIP_ANALYZE *ana); 6692765Salfredstatic void cd9660_rrip_defattr(struct iso_directory_record *isodir, 6793075Sbde ISO_RRIP_ANALYZE *ana); 6892765Salfredstatic void cd9660_rrip_defname(struct iso_directory_record *isodir, 6993075Sbde ISO_RRIP_ANALYZE *ana); 7092765Salfredstatic void cd9660_rrip_deftstamp(struct iso_directory_record *isodir, 7193075Sbde ISO_RRIP_ANALYZE *ana); 7292765Salfredstatic int cd9660_rrip_device(ISO_RRIP_DEVICE *p, ISO_RRIP_ANALYZE *ana); 7392765Salfredstatic int cd9660_rrip_extref(ISO_RRIP_EXTREF *p, ISO_RRIP_ANALYZE *ana); 7492765Salfredstatic int cd9660_rrip_idflag(ISO_RRIP_IDFLAG *p, ISO_RRIP_ANALYZE *ana); 7592765Salfredstatic int cd9660_rrip_loop(struct iso_directory_record *isodir, 7693075Sbde ISO_RRIP_ANALYZE *ana, RRIP_TABLE *table); 7792765Salfredstatic int cd9660_rrip_pclink(ISO_RRIP_CLINK *p, ISO_RRIP_ANALYZE *ana); 7892765Salfredstatic int cd9660_rrip_reldir(ISO_RRIP_RELDIR *p, ISO_RRIP_ANALYZE *ana); 7992765Salfredstatic int cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana); 8092765Salfredstatic int cd9660_rrip_stop(ISO_SUSP_HEADER *p, ISO_RRIP_ANALYZE *ana); 8192765Salfredstatic int cd9660_rrip_tstamp(ISO_RRIP_TSTAMP *p, ISO_RRIP_ANALYZE *ana); 8212597Sbde 831541Srgrimes/* 841541Srgrimes * POSIX file attribute 851541Srgrimes */ 861541Srgrimesstatic int 871541Srgrimescd9660_rrip_attr(p,ana) 881541Srgrimes ISO_RRIP_ATTR *p; 891541Srgrimes ISO_RRIP_ANALYZE *ana; 901541Srgrimes{ 9122521Sdyson ana->inop->inode.iso_mode = isonum_733(p->mode); 9222521Sdyson ana->inop->inode.iso_uid = isonum_733(p->uid); 9322521Sdyson ana->inop->inode.iso_gid = isonum_733(p->gid); 9422521Sdyson ana->inop->inode.iso_links = isonum_733(p->links); 951541Srgrimes ana->fields &= ~ISO_SUSP_ATTR; 961541Srgrimes return ISO_SUSP_ATTR; 971541Srgrimes} 981541Srgrimes 991541Srgrimesstatic void 1001541Srgrimescd9660_rrip_defattr(isodir,ana) 1011541Srgrimes struct iso_directory_record *isodir; 1021541Srgrimes ISO_RRIP_ANALYZE *ana; 1031541Srgrimes{ 1041541Srgrimes /* But this is a required field! */ 1051541Srgrimes printf("RRIP without PX field?\n"); 1065651Sjoerg cd9660_defattr(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 1071541Srgrimes} 1081541Srgrimes 1091541Srgrimes/* 1101541Srgrimes * Symbolic Links 1111541Srgrimes */ 1121541Srgrimesstatic int 1131541Srgrimescd9660_rrip_slink(p,ana) 1145651Sjoerg ISO_RRIP_SLINK *p; 1151541Srgrimes ISO_RRIP_ANALYZE *ana; 1161541Srgrimes{ 117183550Szec INIT_VPROCG(TD_TO_VPROCG(curthread)); 118131526Sphk ISO_RRIP_SLINK_COMPONENT *pcomp; 119131526Sphk ISO_RRIP_SLINK_COMPONENT *pcompe; 1201541Srgrimes int len, wlen, cont; 1211541Srgrimes char *outbuf, *inbuf; 1228876Srgrimes 1231541Srgrimes pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component; 1241541Srgrimes pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length)); 1251541Srgrimes len = *ana->outlen; 1261541Srgrimes outbuf = ana->outbuf; 1271541Srgrimes cont = ana->cont; 1288876Srgrimes 1291541Srgrimes /* 1301541Srgrimes * Gathering a Symbolic name from each component with path 1311541Srgrimes */ 1321541Srgrimes for (; 1331541Srgrimes pcomp < pcompe; 1341541Srgrimes pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ 1351541Srgrimes + isonum_711(pcomp->clen))) { 1368876Srgrimes 1371541Srgrimes if (!cont) { 1381541Srgrimes if (len < ana->maxlen) { 1391541Srgrimes len++; 1401541Srgrimes *outbuf++ = '/'; 1411541Srgrimes } 1421541Srgrimes } 1431541Srgrimes cont = 0; 1448876Srgrimes 1451541Srgrimes inbuf = ".."; 1461541Srgrimes wlen = 0; 1478876Srgrimes 1481541Srgrimes switch (*pcomp->cflag) { 1498876Srgrimes 1501541Srgrimes case ISO_SUSP_CFLAG_CURRENT: 1511541Srgrimes /* Inserting Current */ 1521541Srgrimes wlen = 1; 1531541Srgrimes break; 1548876Srgrimes 1551541Srgrimes case ISO_SUSP_CFLAG_PARENT: 1561541Srgrimes /* Inserting Parent */ 1571541Srgrimes wlen = 2; 1581541Srgrimes break; 1598876Srgrimes 1601541Srgrimes case ISO_SUSP_CFLAG_ROOT: 1611541Srgrimes /* Inserting slash for ROOT */ 162156693Sjoerg /* Double slash, nothing really to do here. */ 1631541Srgrimes break; 1648876Srgrimes 1651541Srgrimes case ISO_SUSP_CFLAG_VOLROOT: 1661541Srgrimes /* Inserting a mount point i.e. "/cdrom" */ 1671541Srgrimes /* same as above */ 1681541Srgrimes outbuf -= len; 1691541Srgrimes len = 0; 1701541Srgrimes inbuf = ana->imp->im_mountp->mnt_stat.f_mntonname; 1711541Srgrimes wlen = strlen(inbuf); 1721541Srgrimes break; 1738876Srgrimes 1741541Srgrimes case ISO_SUSP_CFLAG_HOST: 175180291Srwatson /* XXXRW: locking. */ 1761541Srgrimes /* Inserting hostname i.e. "kurt.tools.de" */ 177181803Sbz inbuf = V_hostname; 178181803Sbz wlen = strlen(V_hostname); 1791541Srgrimes break; 1808876Srgrimes 1811541Srgrimes case ISO_SUSP_CFLAG_CONTINUE: 1821541Srgrimes cont = 1; 183102412Scharnier /* FALLTHROUGH */ 1841541Srgrimes case 0: 1851541Srgrimes /* Inserting component */ 1861541Srgrimes wlen = isonum_711(pcomp->clen); 1871541Srgrimes inbuf = pcomp->name; 1881541Srgrimes break; 1891541Srgrimes default: 1901541Srgrimes printf("RRIP with incorrect flags?"); 1911541Srgrimes wlen = ana->maxlen + 1; 1921541Srgrimes break; 1931541Srgrimes } 1948876Srgrimes 1951541Srgrimes if (len + wlen > ana->maxlen) { 1961541Srgrimes /* indicate error to caller */ 1971541Srgrimes ana->cont = 1; 1981541Srgrimes ana->fields = 0; 1991541Srgrimes ana->outbuf -= *ana->outlen; 2001541Srgrimes *ana->outlen = 0; 2011541Srgrimes return 0; 2021541Srgrimes } 2038876Srgrimes 2041541Srgrimes bcopy(inbuf,outbuf,wlen); 2051541Srgrimes outbuf += wlen; 2061541Srgrimes len += wlen; 2078876Srgrimes 2081541Srgrimes } 2091541Srgrimes ana->outbuf = outbuf; 2101541Srgrimes *ana->outlen = len; 2111541Srgrimes ana->cont = cont; 2128876Srgrimes 2131541Srgrimes if (!isonum_711(p->flags)) { 2141541Srgrimes ana->fields &= ~ISO_SUSP_SLINK; 2151541Srgrimes return ISO_SUSP_SLINK; 2161541Srgrimes } 2171541Srgrimes return 0; 2181541Srgrimes} 2191541Srgrimes 2201541Srgrimes/* 2211541Srgrimes * Alternate name 2221541Srgrimes */ 2231541Srgrimesstatic int 2241541Srgrimescd9660_rrip_altname(p,ana) 2251541Srgrimes ISO_RRIP_ALTNAME *p; 2261541Srgrimes ISO_RRIP_ANALYZE *ana; 2271541Srgrimes{ 228183550Szec INIT_VPROCG(TD_TO_VPROCG(curthread)); 2291541Srgrimes char *inbuf; 2301541Srgrimes int wlen; 2311541Srgrimes int cont; 2328876Srgrimes 2331541Srgrimes inbuf = ".."; 2341541Srgrimes wlen = 0; 2351541Srgrimes cont = 0; 2368876Srgrimes 2371541Srgrimes switch (*p->flags) { 2381541Srgrimes case ISO_SUSP_CFLAG_CURRENT: 2391541Srgrimes /* Inserting Current */ 2401541Srgrimes wlen = 1; 2411541Srgrimes break; 2428876Srgrimes 2431541Srgrimes case ISO_SUSP_CFLAG_PARENT: 2441541Srgrimes /* Inserting Parent */ 2451541Srgrimes wlen = 2; 2461541Srgrimes break; 2478876Srgrimes 2481541Srgrimes case ISO_SUSP_CFLAG_HOST: 249180291Srwatson /* XXXRW: locking. */ 2501541Srgrimes /* Inserting hostname i.e. "kurt.tools.de" */ 251181803Sbz inbuf = V_hostname; 252181803Sbz wlen = strlen(V_hostname); 2531541Srgrimes break; 2548876Srgrimes 2551541Srgrimes case ISO_SUSP_CFLAG_CONTINUE: 2561541Srgrimes cont = 1; 257102412Scharnier /* FALLTHROUGH */ 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, 295120492Sfjoe 1,isonum_711(isodir->flags)&4, ana->imp->joliet_level, 296120492Sfjoe ana->imp->im_flags, ana->imp->im_d2l); 29745773Sdcs switch (*ana->outbuf) { 2981541Srgrimes default: 2991541Srgrimes break; 3001541Srgrimes case 1: 3011541Srgrimes *ana->outlen = 2; 302102412Scharnier /* FALLTHROUGH */ 30345773Sdcs case 0: 30445773Sdcs /* outlen is 1 already */ 30545773Sdcs strcpy(ana->outbuf,".."); 3061541Srgrimes break; 3071541Srgrimes } 3081541Srgrimes} 3091541Srgrimes 3101541Srgrimes/* 3111541Srgrimes * Parent or Child Link 3121541Srgrimes */ 3131541Srgrimesstatic int 3141541Srgrimescd9660_rrip_pclink(p,ana) 3155651Sjoerg ISO_RRIP_CLINK *p; 3161541Srgrimes ISO_RRIP_ANALYZE *ana; 3171541Srgrimes{ 3181541Srgrimes *ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift; 3191541Srgrimes ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK); 3201541Srgrimes return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK; 3211541Srgrimes} 3221541Srgrimes 3231541Srgrimes/* 3241541Srgrimes * Relocated directory 3251541Srgrimes */ 3261541Srgrimesstatic int 3271541Srgrimescd9660_rrip_reldir(p,ana) 3285651Sjoerg ISO_RRIP_RELDIR *p; 3291541Srgrimes ISO_RRIP_ANALYZE *ana; 3301541Srgrimes{ 3311541Srgrimes /* special hack to make caller aware of RE field */ 3321541Srgrimes *ana->outlen = 0; 3331541Srgrimes ana->fields = 0; 3341541Srgrimes return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 3351541Srgrimes} 3361541Srgrimes 3371541Srgrimesstatic int 3381541Srgrimescd9660_rrip_tstamp(p,ana) 3391541Srgrimes ISO_RRIP_TSTAMP *p; 3401541Srgrimes ISO_RRIP_ANALYZE *ana; 3411541Srgrimes{ 34222521Sdyson u_char *ptime; 343131526Sphk 3441541Srgrimes ptime = p->time; 3458876Srgrimes 3461541Srgrimes /* Check a format of time stamp (7bytes/17bytes) */ 3471541Srgrimes if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) { 3481541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 3491541Srgrimes ptime += 7; 3508876Srgrimes 3511541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 3525651Sjoerg cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime, 3535651Sjoerg ISO_FTYPE_RRIP); 3541541Srgrimes ptime += 7; 3551541Srgrimes } else 3562806Sbde bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 357131526Sphk 3581541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 3595651Sjoerg cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime, 3605651Sjoerg ISO_FTYPE_RRIP); 3611541Srgrimes ptime += 7; 3621541Srgrimes } else 3631541Srgrimes ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 3648876Srgrimes 3651541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 3665651Sjoerg cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime, 3675651Sjoerg ISO_FTYPE_RRIP); 3681541Srgrimes else 3691541Srgrimes ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 3708876Srgrimes 3711541Srgrimes } else { 3721541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 3731541Srgrimes ptime += 17; 3748876Srgrimes 3751541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 3761541Srgrimes cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime); 3771541Srgrimes ptime += 17; 3781541Srgrimes } else 3792806Sbde bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 380131526Sphk 3811541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 3821541Srgrimes cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime); 3831541Srgrimes ptime += 17; 3841541Srgrimes } else 3851541Srgrimes ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 3868876Srgrimes 3871541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 3881541Srgrimes cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime); 3891541Srgrimes else 3901541Srgrimes ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 3918876Srgrimes 3921541Srgrimes } 3931541Srgrimes ana->fields &= ~ISO_SUSP_TSTAMP; 3941541Srgrimes return ISO_SUSP_TSTAMP; 3951541Srgrimes} 3961541Srgrimes 3971541Srgrimesstatic void 3981541Srgrimescd9660_rrip_deftstamp(isodir,ana) 3991541Srgrimes struct iso_directory_record *isodir; 4001541Srgrimes ISO_RRIP_ANALYZE *ana; 4011541Srgrimes{ 4025651Sjoerg cd9660_deftstamp(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 4031541Srgrimes} 4041541Srgrimes 4051541Srgrimes/* 4061541Srgrimes * POSIX device modes 4071541Srgrimes */ 4081541Srgrimesstatic int 4091541Srgrimescd9660_rrip_device(p,ana) 4101541Srgrimes ISO_RRIP_DEVICE *p; 4111541Srgrimes ISO_RRIP_ANALYZE *ana; 4121541Srgrimes{ 41322521Sdyson u_int high, low; 414131526Sphk 41522521Sdyson high = isonum_733(p->dev_t_high); 41622521Sdyson low = isonum_733(p->dev_t_low); 417131526Sphk 41822521Sdyson if (high == 0) 419187830Sed ana->inop->inode.iso_rdev = makedev(major(low), minor(low)); 42022521Sdyson else 421187830Sed ana->inop->inode.iso_rdev = makedev(high, minor(low)); 4221541Srgrimes ana->fields &= ~ISO_SUSP_DEVICE; 4231541Srgrimes return ISO_SUSP_DEVICE; 4241541Srgrimes} 4251541Srgrimes 4261541Srgrimes/* 4271541Srgrimes * Flag indicating 4281541Srgrimes */ 4291541Srgrimesstatic int 4301541Srgrimescd9660_rrip_idflag(p,ana) 4311541Srgrimes ISO_RRIP_IDFLAG *p; 4321541Srgrimes ISO_RRIP_ANALYZE *ana; 4331541Srgrimes{ 4341541Srgrimes ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */ 4351541Srgrimes /* special handling of RE field */ 4361541Srgrimes if (ana->fields&ISO_SUSP_RELDIR) 43712597Sbde return cd9660_rrip_reldir(/* XXX */ (ISO_RRIP_RELDIR *)p,ana); 4388876Srgrimes 4391541Srgrimes return ISO_SUSP_IDFLAG; 4401541Srgrimes} 4411541Srgrimes 4421541Srgrimes/* 4431541Srgrimes * Continuation pointer 4441541Srgrimes */ 4451541Srgrimesstatic int 4461541Srgrimescd9660_rrip_cont(p,ana) 4471541Srgrimes ISO_RRIP_CONT *p; 4481541Srgrimes ISO_RRIP_ANALYZE *ana; 4491541Srgrimes{ 4501541Srgrimes ana->iso_ce_blk = isonum_733(p->location); 4511541Srgrimes ana->iso_ce_off = isonum_733(p->offset); 4521541Srgrimes ana->iso_ce_len = isonum_733(p->length); 4531541Srgrimes return ISO_SUSP_CONT; 4541541Srgrimes} 4551541Srgrimes 4561541Srgrimes/* 4571541Srgrimes * System Use end 4581541Srgrimes */ 4591541Srgrimesstatic int 4601541Srgrimescd9660_rrip_stop(p,ana) 4611541Srgrimes ISO_SUSP_HEADER *p; 4621541Srgrimes ISO_RRIP_ANALYZE *ana; 4631541Srgrimes{ 4641541Srgrimes return ISO_SUSP_STOP; 4651541Srgrimes} 4661541Srgrimes 4671541Srgrimes/* 4681541Srgrimes * Extension reference 4691541Srgrimes */ 4701541Srgrimesstatic int 4711541Srgrimescd9660_rrip_extref(p,ana) 4721541Srgrimes ISO_RRIP_EXTREF *p; 4731541Srgrimes ISO_RRIP_ANALYZE *ana; 4741541Srgrimes{ 475185334Slulf if ( ! ((isonum_711(p->len_id) == 10 476185334Slulf && bcmp((char *)p + 8,"RRIP_1991A",10) == 0) 477185334Slulf || (isonum_711(p->len_id) == 10 478185334Slulf && bcmp((char *)p + 8,"IEEE_P1282",10) == 0) 479185334Slulf || (isonum_711(p->len_id) == 9 480185334Slulf && bcmp((char *)p + 8,"IEEE_1282", 9) == 0)) 4811541Srgrimes || isonum_711(p->version) != 1) 4821541Srgrimes return 0; 4831541Srgrimes ana->fields &= ~ISO_SUSP_EXTREF; 4841541Srgrimes return ISO_SUSP_EXTREF; 4851541Srgrimes} 4861541Srgrimes 4871541Srgrimesstatic int 4881541Srgrimescd9660_rrip_loop(isodir,ana,table) 4891541Srgrimes struct iso_directory_record *isodir; 4901541Srgrimes ISO_RRIP_ANALYZE *ana; 4911541Srgrimes RRIP_TABLE *table; 4921541Srgrimes{ 493131526Sphk RRIP_TABLE *ptable; 494131526Sphk ISO_SUSP_HEADER *phead; 495131526Sphk ISO_SUSP_HEADER *pend; 4961541Srgrimes struct buf *bp = NULL; 4971541Srgrimes char *pwhead; 498120492Sfjoe u_short c; 4991541Srgrimes int result; 5008876Srgrimes 5011541Srgrimes /* 5021541Srgrimes * Note: If name length is odd, 5035651Sjoerg * it will be padding 1 byte after the name 5041541Srgrimes */ 5051541Srgrimes pwhead = isodir->name + isonum_711(isodir->name_len); 5061541Srgrimes if (!(isonum_711(isodir->name_len)&1)) 5071541Srgrimes pwhead++; 508120492Sfjoe isochar(isodir->name, pwhead, ana->imp->joliet_level, &c, NULL, 509120492Sfjoe ana->imp->im_flags, ana->imp->im_d2l); 5108876Srgrimes 5111541Srgrimes /* If it's not the '.' entry of the root dir obey SP field */ 51245773Sdcs if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent) 5131541Srgrimes pwhead += ana->imp->rr_skip; 5141541Srgrimes else 5151541Srgrimes pwhead += ana->imp->rr_skip0; 5168876Srgrimes 5171541Srgrimes phead = (ISO_SUSP_HEADER *)pwhead; 5181541Srgrimes pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length)); 5198876Srgrimes 5201541Srgrimes result = 0; 5211541Srgrimes while (1) { 5221541Srgrimes ana->iso_ce_len = 0; 5231541Srgrimes /* 5241541Srgrimes * Note: "pend" should be more than one SUSP header 5258876Srgrimes */ 5261541Srgrimes while (pend >= phead + 1) { 5271541Srgrimes if (isonum_711(phead->version) == 1) { 5281541Srgrimes for (ptable = table; ptable->func; ptable++) { 5291541Srgrimes if (*phead->type == *ptable->type 5301541Srgrimes && phead->type[1] == ptable->type[1]) { 5311541Srgrimes result |= ptable->func(phead,ana); 5321541Srgrimes break; 5331541Srgrimes } 5341541Srgrimes } 5351541Srgrimes if (!ana->fields) 5361541Srgrimes break; 5371541Srgrimes } 53822521Sdyson if (result&ISO_SUSP_STOP) { 53922521Sdyson result &= ~ISO_SUSP_STOP; 54022521Sdyson break; 54122521Sdyson } 54222521Sdyson /* plausibility check */ 54322521Sdyson if (isonum_711(phead->length) < sizeof(*phead)) 54422521Sdyson break; 5451541Srgrimes /* 5461541Srgrimes * move to next SUSP 5471541Srgrimes * Hopefully this works with newer versions, too 5481541Srgrimes */ 5491541Srgrimes phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length)); 5501541Srgrimes } 551131526Sphk 55222521Sdyson if (ana->fields && ana->iso_ce_len) { 5531541Srgrimes if (ana->iso_ce_blk >= ana->imp->volume_space_size 5541541Srgrimes || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size 5551541Srgrimes || bread(ana->imp->im_devvp, 55622521Sdyson ana->iso_ce_blk << 55722521Sdyson (ana->imp->im_bshift - DEV_BSHIFT), 55822521Sdyson ana->imp->logical_block_size, NOCRED, &bp)) 5591541Srgrimes /* what to do now? */ 5601541Srgrimes break; 56122521Sdyson phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off); 5621541Srgrimes pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len); 5631541Srgrimes } else 5641541Srgrimes break; 5651541Srgrimes } 5661541Srgrimes if (bp) 5671541Srgrimes brelse(bp); 5681541Srgrimes /* 5691541Srgrimes * If we don't find the Basic SUSP stuffs, just set default value 57022521Sdyson * (attribute/time stamp) 5711541Srgrimes */ 5721541Srgrimes for (ptable = table; ptable->func2; ptable++) 5731541Srgrimes if (!(ptable->result&result)) 5741541Srgrimes ptable->func2(isodir,ana); 5758876Srgrimes 5761541Srgrimes return result; 5771541Srgrimes} 5781541Srgrimes 57912597Sbde/* 58022521Sdyson * Get Attributes. 58122521Sdyson */ 58222521Sdyson/* 58312597Sbde * XXX the casts are bogus but will do for now. 58412597Sbde */ 58512597Sbde#define BC (rrt_func_t *) 5861541Srgrimesstatic RRIP_TABLE rrip_table_analyze[] = { 58712597Sbde { "PX", BC cd9660_rrip_attr, cd9660_rrip_defattr, ISO_SUSP_ATTR }, 58812597Sbde { "TF", BC cd9660_rrip_tstamp, cd9660_rrip_deftstamp, ISO_SUSP_TSTAMP }, 58912597Sbde { "PN", BC cd9660_rrip_device, 0, ISO_SUSP_DEVICE }, 59012597Sbde { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 59112597Sbde { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 59212597Sbde { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 5931541Srgrimes { "", 0, 0, 0 } 5941541Srgrimes}; 5951541Srgrimes 5961541Srgrimesint 5971541Srgrimescd9660_rrip_analyze(isodir,inop,imp) 5981541Srgrimes struct iso_directory_record *isodir; 5991541Srgrimes struct iso_node *inop; 6001541Srgrimes struct iso_mnt *imp; 6011541Srgrimes{ 6021541Srgrimes ISO_RRIP_ANALYZE analyze; 6038876Srgrimes 6041541Srgrimes analyze.inop = inop; 6051541Srgrimes analyze.imp = imp; 6061541Srgrimes analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE; 6078876Srgrimes 6081541Srgrimes return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze); 6091541Srgrimes} 6101541Srgrimes 611131526Sphk/* 61222521Sdyson * Get Alternate Name. 6131541Srgrimes */ 6141541Srgrimesstatic RRIP_TABLE rrip_table_getname[] = { 61512597Sbde { "NM", BC cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME }, 61612597Sbde { "CL", BC cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 61712597Sbde { "PL", BC cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 61812597Sbde { "RE", BC cd9660_rrip_reldir, 0, ISO_SUSP_RELDIR }, 61912597Sbde { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 62012597Sbde { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 62112597Sbde { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 6221541Srgrimes { "", 0, 0, 0 } 6231541Srgrimes}; 6241541Srgrimes 6251541Srgrimesint 6261541Srgrimescd9660_rrip_getname(isodir,outbuf,outlen,inump,imp) 6271541Srgrimes struct iso_directory_record *isodir; 6281541Srgrimes char *outbuf; 6291541Srgrimes u_short *outlen; 6301541Srgrimes ino_t *inump; 6311541Srgrimes struct iso_mnt *imp; 6321541Srgrimes{ 6331541Srgrimes ISO_RRIP_ANALYZE analyze; 6341541Srgrimes RRIP_TABLE *tab; 635120492Sfjoe u_short c; 6368876Srgrimes 6371541Srgrimes analyze.outbuf = outbuf; 6381541Srgrimes analyze.outlen = outlen; 6391541Srgrimes analyze.maxlen = NAME_MAX; 6401541Srgrimes analyze.inump = inump; 6411541Srgrimes analyze.imp = imp; 6421541Srgrimes analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 6431541Srgrimes *outlen = 0; 6448876Srgrimes 64545773Sdcs isochar(isodir->name, isodir->name + isonum_711(isodir->name_len), 646120492Sfjoe imp->joliet_level, &c, NULL, imp->im_flags, imp->im_d2l); 6471541Srgrimes tab = rrip_table_getname; 64845773Sdcs if (c == 0 || c == 1) { 6491541Srgrimes cd9660_rrip_defname(isodir,&analyze); 6508876Srgrimes 6511541Srgrimes analyze.fields &= ~ISO_SUSP_ALTNAME; 6521541Srgrimes tab++; 6531541Srgrimes } 6548876Srgrimes 6551541Srgrimes return cd9660_rrip_loop(isodir,&analyze,tab); 6561541Srgrimes} 6571541Srgrimes 658131526Sphk/* 65922521Sdyson * Get Symbolic Link. 6601541Srgrimes */ 6611541Srgrimesstatic RRIP_TABLE rrip_table_getsymname[] = { 66212597Sbde { "SL", BC cd9660_rrip_slink, 0, ISO_SUSP_SLINK }, 66312597Sbde { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 66412597Sbde { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 66512597Sbde { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 6661541Srgrimes { "", 0, 0, 0 } 6671541Srgrimes}; 6681541Srgrimes 6691541Srgrimesint 6701541Srgrimescd9660_rrip_getsymname(isodir,outbuf,outlen,imp) 6711541Srgrimes struct iso_directory_record *isodir; 6721541Srgrimes char *outbuf; 6731541Srgrimes u_short *outlen; 6741541Srgrimes struct iso_mnt *imp; 6751541Srgrimes{ 6761541Srgrimes ISO_RRIP_ANALYZE analyze; 6778876Srgrimes 6781541Srgrimes analyze.outbuf = outbuf; 6791541Srgrimes analyze.outlen = outlen; 6801541Srgrimes *outlen = 0; 6811541Srgrimes analyze.maxlen = MAXPATHLEN; 6821541Srgrimes analyze.cont = 1; /* don't start with a slash */ 6831541Srgrimes analyze.imp = imp; 6841541Srgrimes analyze.fields = ISO_SUSP_SLINK; 6858876Srgrimes 6861541Srgrimes return (cd9660_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK); 6871541Srgrimes} 6881541Srgrimes 6891541Srgrimesstatic RRIP_TABLE rrip_table_extref[] = { 69012597Sbde { "ER", BC cd9660_rrip_extref, 0, ISO_SUSP_EXTREF }, 69112597Sbde { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 69212597Sbde { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 6931541Srgrimes { "", 0, 0, 0 } 6941541Srgrimes}; 6951541Srgrimes 6961541Srgrimes/* 6971541Srgrimes * Check for Rock Ridge Extension and return offset of its fields. 69822521Sdyson * Note: We insist on the ER field. 6991541Srgrimes */ 7001541Srgrimesint 7011541Srgrimescd9660_rrip_offset(isodir,imp) 7021541Srgrimes struct iso_directory_record *isodir; 7031541Srgrimes struct iso_mnt *imp; 7041541Srgrimes{ 7051541Srgrimes ISO_RRIP_OFFSET *p; 7061541Srgrimes ISO_RRIP_ANALYZE analyze; 7078876Srgrimes 7081541Srgrimes imp->rr_skip0 = 0; 7091541Srgrimes p = (ISO_RRIP_OFFSET *)(isodir->name + 1); 7101541Srgrimes if (bcmp(p,"SP\7\1\276\357",6)) { 7111541Srgrimes /* Maybe, it's a CDROM XA disc? */ 7121541Srgrimes imp->rr_skip0 = 15; 7131541Srgrimes p = (ISO_RRIP_OFFSET *)((char *)p + 15); 7141541Srgrimes if (bcmp(p,"SP\7\1\276\357",6)) 7151541Srgrimes return -1; 7161541Srgrimes } 7178876Srgrimes 7181541Srgrimes analyze.imp = imp; 7191541Srgrimes analyze.fields = ISO_SUSP_EXTREF; 7201541Srgrimes if (!(cd9660_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF)) 7211541Srgrimes return -1; 7228876Srgrimes 7231541Srgrimes return isonum_711(p->skip); 7241541Srgrimes} 725