cd9660_rrip.c revision 131526
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 131526 2004-07-03 16:56:45Z phk $"); 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> 471541Srgrimes 481541Srgrimes#include <isofs/cd9660/iso.h> 491541Srgrimes#include <isofs/cd9660/cd9660_node.h> 501541Srgrimes#include <isofs/cd9660/cd9660_rrip.h> 511541Srgrimes#include <isofs/cd9660/iso_rrip.h> 521541Srgrimes 5392765Salfredtypedef int rrt_func_t(void *, ISO_RRIP_ANALYZE *ana); 5412597Sbde 5512597Sbdetypedef struct { 5612597Sbde char type[2]; 5712597Sbde rrt_func_t *func; 5892765Salfred void (*func2)(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana); 5912597Sbde int result; 6012597Sbde} RRIP_TABLE; 6112597Sbde 6292765Salfredstatic int cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, ISO_RRIP_ANALYZE *ana); 6392765Salfredstatic int cd9660_rrip_attr(ISO_RRIP_ATTR *p, ISO_RRIP_ANALYZE *ana); 6492765Salfredstatic int cd9660_rrip_cont(ISO_RRIP_CONT *p, ISO_RRIP_ANALYZE *ana); 6592765Salfredstatic void cd9660_rrip_defattr(struct iso_directory_record *isodir, 6693075Sbde ISO_RRIP_ANALYZE *ana); 6792765Salfredstatic void cd9660_rrip_defname(struct iso_directory_record *isodir, 6893075Sbde ISO_RRIP_ANALYZE *ana); 6992765Salfredstatic void cd9660_rrip_deftstamp(struct iso_directory_record *isodir, 7093075Sbde ISO_RRIP_ANALYZE *ana); 7192765Salfredstatic int cd9660_rrip_device(ISO_RRIP_DEVICE *p, ISO_RRIP_ANALYZE *ana); 7292765Salfredstatic int cd9660_rrip_extref(ISO_RRIP_EXTREF *p, ISO_RRIP_ANALYZE *ana); 7392765Salfredstatic int cd9660_rrip_idflag(ISO_RRIP_IDFLAG *p, ISO_RRIP_ANALYZE *ana); 7492765Salfredstatic int cd9660_rrip_loop(struct iso_directory_record *isodir, 7593075Sbde ISO_RRIP_ANALYZE *ana, RRIP_TABLE *table); 7692765Salfredstatic int cd9660_rrip_pclink(ISO_RRIP_CLINK *p, ISO_RRIP_ANALYZE *ana); 7792765Salfredstatic int cd9660_rrip_reldir(ISO_RRIP_RELDIR *p, ISO_RRIP_ANALYZE *ana); 7892765Salfredstatic int cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana); 7992765Salfredstatic int cd9660_rrip_stop(ISO_SUSP_HEADER *p, ISO_RRIP_ANALYZE *ana); 8092765Salfredstatic int cd9660_rrip_tstamp(ISO_RRIP_TSTAMP *p, ISO_RRIP_ANALYZE *ana); 8112597Sbde 821541Srgrimes/* 831541Srgrimes * POSIX file attribute 841541Srgrimes */ 851541Srgrimesstatic int 861541Srgrimescd9660_rrip_attr(p,ana) 871541Srgrimes ISO_RRIP_ATTR *p; 881541Srgrimes ISO_RRIP_ANALYZE *ana; 891541Srgrimes{ 9022521Sdyson ana->inop->inode.iso_mode = isonum_733(p->mode); 9122521Sdyson ana->inop->inode.iso_uid = isonum_733(p->uid); 9222521Sdyson ana->inop->inode.iso_gid = isonum_733(p->gid); 9322521Sdyson ana->inop->inode.iso_links = isonum_733(p->links); 941541Srgrimes ana->fields &= ~ISO_SUSP_ATTR; 951541Srgrimes return ISO_SUSP_ATTR; 961541Srgrimes} 971541Srgrimes 981541Srgrimesstatic void 991541Srgrimescd9660_rrip_defattr(isodir,ana) 1001541Srgrimes struct iso_directory_record *isodir; 1011541Srgrimes ISO_RRIP_ANALYZE *ana; 1021541Srgrimes{ 1031541Srgrimes /* But this is a required field! */ 1041541Srgrimes printf("RRIP without PX field?\n"); 1055651Sjoerg cd9660_defattr(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 1061541Srgrimes} 1071541Srgrimes 1081541Srgrimes/* 1091541Srgrimes * Symbolic Links 1101541Srgrimes */ 1111541Srgrimesstatic int 1121541Srgrimescd9660_rrip_slink(p,ana) 1135651Sjoerg ISO_RRIP_SLINK *p; 1141541Srgrimes ISO_RRIP_ANALYZE *ana; 1151541Srgrimes{ 116131526Sphk ISO_RRIP_SLINK_COMPONENT *pcomp; 117131526Sphk ISO_RRIP_SLINK_COMPONENT *pcompe; 1181541Srgrimes int len, wlen, cont; 1191541Srgrimes char *outbuf, *inbuf; 1208876Srgrimes 1211541Srgrimes pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component; 1221541Srgrimes pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length)); 1231541Srgrimes len = *ana->outlen; 1241541Srgrimes outbuf = ana->outbuf; 1251541Srgrimes cont = ana->cont; 1268876Srgrimes 1271541Srgrimes /* 1281541Srgrimes * Gathering a Symbolic name from each component with path 1291541Srgrimes */ 1301541Srgrimes for (; 1311541Srgrimes pcomp < pcompe; 1321541Srgrimes pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ 1331541Srgrimes + isonum_711(pcomp->clen))) { 1348876Srgrimes 1351541Srgrimes if (!cont) { 1361541Srgrimes if (len < ana->maxlen) { 1371541Srgrimes len++; 1381541Srgrimes *outbuf++ = '/'; 1391541Srgrimes } 1401541Srgrimes } 1411541Srgrimes cont = 0; 1428876Srgrimes 1431541Srgrimes inbuf = ".."; 1441541Srgrimes wlen = 0; 1458876Srgrimes 1461541Srgrimes switch (*pcomp->cflag) { 1478876Srgrimes 1481541Srgrimes case ISO_SUSP_CFLAG_CURRENT: 1491541Srgrimes /* Inserting Current */ 1501541Srgrimes wlen = 1; 1511541Srgrimes break; 1528876Srgrimes 1531541Srgrimes case ISO_SUSP_CFLAG_PARENT: 1541541Srgrimes /* Inserting Parent */ 1551541Srgrimes wlen = 2; 1561541Srgrimes break; 1578876Srgrimes 1581541Srgrimes case ISO_SUSP_CFLAG_ROOT: 1591541Srgrimes /* Inserting slash for ROOT */ 1601541Srgrimes /* start over from beginning(?) */ 1611541Srgrimes outbuf -= len; 1621541Srgrimes len = 0; 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: 1751541Srgrimes /* Inserting hostname i.e. "kurt.tools.de" */ 1761541Srgrimes inbuf = hostname; 17712287Sphk wlen = strlen(hostname); 1781541Srgrimes break; 1798876Srgrimes 1801541Srgrimes case ISO_SUSP_CFLAG_CONTINUE: 1811541Srgrimes cont = 1; 182102412Scharnier /* FALLTHROUGH */ 1831541Srgrimes case 0: 1841541Srgrimes /* Inserting component */ 1851541Srgrimes wlen = isonum_711(pcomp->clen); 1861541Srgrimes inbuf = pcomp->name; 1871541Srgrimes break; 1881541Srgrimes default: 1891541Srgrimes printf("RRIP with incorrect flags?"); 1901541Srgrimes wlen = ana->maxlen + 1; 1911541Srgrimes break; 1921541Srgrimes } 1938876Srgrimes 1941541Srgrimes if (len + wlen > ana->maxlen) { 1951541Srgrimes /* indicate error to caller */ 1961541Srgrimes ana->cont = 1; 1971541Srgrimes ana->fields = 0; 1981541Srgrimes ana->outbuf -= *ana->outlen; 1991541Srgrimes *ana->outlen = 0; 2001541Srgrimes return 0; 2011541Srgrimes } 2028876Srgrimes 2031541Srgrimes bcopy(inbuf,outbuf,wlen); 2041541Srgrimes outbuf += wlen; 2051541Srgrimes len += wlen; 2068876Srgrimes 2071541Srgrimes } 2081541Srgrimes ana->outbuf = outbuf; 2091541Srgrimes *ana->outlen = len; 2101541Srgrimes ana->cont = cont; 2118876Srgrimes 2121541Srgrimes if (!isonum_711(p->flags)) { 2131541Srgrimes ana->fields &= ~ISO_SUSP_SLINK; 2141541Srgrimes return ISO_SUSP_SLINK; 2151541Srgrimes } 2161541Srgrimes return 0; 2171541Srgrimes} 2181541Srgrimes 2191541Srgrimes/* 2201541Srgrimes * Alternate name 2211541Srgrimes */ 2221541Srgrimesstatic int 2231541Srgrimescd9660_rrip_altname(p,ana) 2241541Srgrimes ISO_RRIP_ALTNAME *p; 2251541Srgrimes ISO_RRIP_ANALYZE *ana; 2261541Srgrimes{ 2271541Srgrimes char *inbuf; 2281541Srgrimes int wlen; 2291541Srgrimes int cont; 2308876Srgrimes 2311541Srgrimes inbuf = ".."; 2321541Srgrimes wlen = 0; 2331541Srgrimes cont = 0; 2348876Srgrimes 2351541Srgrimes switch (*p->flags) { 2361541Srgrimes case ISO_SUSP_CFLAG_CURRENT: 2371541Srgrimes /* Inserting Current */ 2381541Srgrimes wlen = 1; 2391541Srgrimes break; 2408876Srgrimes 2411541Srgrimes case ISO_SUSP_CFLAG_PARENT: 2421541Srgrimes /* Inserting Parent */ 2431541Srgrimes wlen = 2; 2441541Srgrimes break; 2458876Srgrimes 2461541Srgrimes case ISO_SUSP_CFLAG_HOST: 2471541Srgrimes /* Inserting hostname i.e. "kurt.tools.de" */ 2481541Srgrimes inbuf = hostname; 24912287Sphk wlen = strlen(hostname); 2501541Srgrimes break; 2518876Srgrimes 2521541Srgrimes case ISO_SUSP_CFLAG_CONTINUE: 2531541Srgrimes cont = 1; 254102412Scharnier /* FALLTHROUGH */ 2551541Srgrimes case 0: 2561541Srgrimes /* Inserting component */ 2571541Srgrimes wlen = isonum_711(p->h.length) - 5; 2581541Srgrimes inbuf = (char *)p + 5; 2591541Srgrimes break; 2608876Srgrimes 2611541Srgrimes default: 2621541Srgrimes printf("RRIP with incorrect NM flags?\n"); 2631541Srgrimes wlen = ana->maxlen + 1; 2641541Srgrimes break; 2651541Srgrimes } 2668876Srgrimes 2671541Srgrimes if ((*ana->outlen += wlen) > ana->maxlen) { 2681541Srgrimes /* treat as no name field */ 2691541Srgrimes ana->fields &= ~ISO_SUSP_ALTNAME; 2701541Srgrimes ana->outbuf -= *ana->outlen - wlen; 2711541Srgrimes *ana->outlen = 0; 2721541Srgrimes return 0; 2731541Srgrimes } 2748876Srgrimes 2751541Srgrimes bcopy(inbuf,ana->outbuf,wlen); 2761541Srgrimes ana->outbuf += wlen; 2778876Srgrimes 2781541Srgrimes if (!cont) { 2791541Srgrimes ana->fields &= ~ISO_SUSP_ALTNAME; 2801541Srgrimes return ISO_SUSP_ALTNAME; 2811541Srgrimes } 2821541Srgrimes return 0; 2831541Srgrimes} 2841541Srgrimes 2851541Srgrimesstatic void 2861541Srgrimescd9660_rrip_defname(isodir,ana) 2871541Srgrimes struct iso_directory_record *isodir; 2881541Srgrimes ISO_RRIP_ANALYZE *ana; 2891541Srgrimes{ 29045773Sdcs isofntrans(isodir->name,isonum_711(isodir->name_len), 29145773Sdcs ana->outbuf,ana->outlen, 292120492Sfjoe 1,isonum_711(isodir->flags)&4, ana->imp->joliet_level, 293120492Sfjoe ana->imp->im_flags, ana->imp->im_d2l); 29445773Sdcs switch (*ana->outbuf) { 2951541Srgrimes default: 2961541Srgrimes break; 2971541Srgrimes case 1: 2981541Srgrimes *ana->outlen = 2; 299102412Scharnier /* FALLTHROUGH */ 30045773Sdcs case 0: 30145773Sdcs /* outlen is 1 already */ 30245773Sdcs strcpy(ana->outbuf,".."); 3031541Srgrimes break; 3041541Srgrimes } 3051541Srgrimes} 3061541Srgrimes 3071541Srgrimes/* 3081541Srgrimes * Parent or Child Link 3091541Srgrimes */ 3101541Srgrimesstatic int 3111541Srgrimescd9660_rrip_pclink(p,ana) 3125651Sjoerg ISO_RRIP_CLINK *p; 3131541Srgrimes ISO_RRIP_ANALYZE *ana; 3141541Srgrimes{ 3151541Srgrimes *ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift; 3161541Srgrimes ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK); 3171541Srgrimes return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK; 3181541Srgrimes} 3191541Srgrimes 3201541Srgrimes/* 3211541Srgrimes * Relocated directory 3221541Srgrimes */ 3231541Srgrimesstatic int 3241541Srgrimescd9660_rrip_reldir(p,ana) 3255651Sjoerg ISO_RRIP_RELDIR *p; 3261541Srgrimes ISO_RRIP_ANALYZE *ana; 3271541Srgrimes{ 3281541Srgrimes /* special hack to make caller aware of RE field */ 3291541Srgrimes *ana->outlen = 0; 3301541Srgrimes ana->fields = 0; 3311541Srgrimes return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 3321541Srgrimes} 3331541Srgrimes 3341541Srgrimesstatic int 3351541Srgrimescd9660_rrip_tstamp(p,ana) 3361541Srgrimes ISO_RRIP_TSTAMP *p; 3371541Srgrimes ISO_RRIP_ANALYZE *ana; 3381541Srgrimes{ 33922521Sdyson u_char *ptime; 340131526Sphk 3411541Srgrimes ptime = p->time; 3428876Srgrimes 3431541Srgrimes /* Check a format of time stamp (7bytes/17bytes) */ 3441541Srgrimes if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) { 3451541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 3461541Srgrimes ptime += 7; 3478876Srgrimes 3481541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 3495651Sjoerg cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime, 3505651Sjoerg ISO_FTYPE_RRIP); 3511541Srgrimes ptime += 7; 3521541Srgrimes } else 3532806Sbde bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 354131526Sphk 3551541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 3565651Sjoerg cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime, 3575651Sjoerg ISO_FTYPE_RRIP); 3581541Srgrimes ptime += 7; 3591541Srgrimes } else 3601541Srgrimes ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 3618876Srgrimes 3621541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 3635651Sjoerg cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime, 3645651Sjoerg ISO_FTYPE_RRIP); 3651541Srgrimes else 3661541Srgrimes ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 3678876Srgrimes 3681541Srgrimes } else { 3691541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 3701541Srgrimes ptime += 17; 3718876Srgrimes 3721541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 3731541Srgrimes cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime); 3741541Srgrimes ptime += 17; 3751541Srgrimes } else 3762806Sbde bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 377131526Sphk 3781541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 3791541Srgrimes cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime); 3801541Srgrimes ptime += 17; 3811541Srgrimes } else 3821541Srgrimes ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 3838876Srgrimes 3841541Srgrimes if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 3851541Srgrimes cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime); 3861541Srgrimes else 3871541Srgrimes ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 3888876Srgrimes 3891541Srgrimes } 3901541Srgrimes ana->fields &= ~ISO_SUSP_TSTAMP; 3911541Srgrimes return ISO_SUSP_TSTAMP; 3921541Srgrimes} 3931541Srgrimes 3941541Srgrimesstatic void 3951541Srgrimescd9660_rrip_deftstamp(isodir,ana) 3961541Srgrimes struct iso_directory_record *isodir; 3971541Srgrimes ISO_RRIP_ANALYZE *ana; 3981541Srgrimes{ 3995651Sjoerg cd9660_deftstamp(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 4001541Srgrimes} 4011541Srgrimes 4021541Srgrimes/* 4031541Srgrimes * POSIX device modes 4041541Srgrimes */ 4051541Srgrimesstatic int 4061541Srgrimescd9660_rrip_device(p,ana) 4071541Srgrimes ISO_RRIP_DEVICE *p; 4081541Srgrimes ISO_RRIP_ANALYZE *ana; 4091541Srgrimes{ 41022521Sdyson u_int high, low; 411131526Sphk 41222521Sdyson high = isonum_733(p->dev_t_high); 41322521Sdyson low = isonum_733(p->dev_t_low); 414131526Sphk 41522521Sdyson if (high == 0) 416130640Sphk ana->inop->inode.iso_rdev = makedev(umajor(low), uminor(low)); 41722521Sdyson else 418130640Sphk ana->inop->inode.iso_rdev = makedev(high, uminor(low)); 4191541Srgrimes ana->fields &= ~ISO_SUSP_DEVICE; 4201541Srgrimes return ISO_SUSP_DEVICE; 4211541Srgrimes} 4221541Srgrimes 4231541Srgrimes/* 4241541Srgrimes * Flag indicating 4251541Srgrimes */ 4261541Srgrimesstatic int 4271541Srgrimescd9660_rrip_idflag(p,ana) 4281541Srgrimes ISO_RRIP_IDFLAG *p; 4291541Srgrimes ISO_RRIP_ANALYZE *ana; 4301541Srgrimes{ 4311541Srgrimes ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */ 4321541Srgrimes /* special handling of RE field */ 4331541Srgrimes if (ana->fields&ISO_SUSP_RELDIR) 43412597Sbde return cd9660_rrip_reldir(/* XXX */ (ISO_RRIP_RELDIR *)p,ana); 4358876Srgrimes 4361541Srgrimes return ISO_SUSP_IDFLAG; 4371541Srgrimes} 4381541Srgrimes 4391541Srgrimes/* 4401541Srgrimes * Continuation pointer 4411541Srgrimes */ 4421541Srgrimesstatic int 4431541Srgrimescd9660_rrip_cont(p,ana) 4441541Srgrimes ISO_RRIP_CONT *p; 4451541Srgrimes ISO_RRIP_ANALYZE *ana; 4461541Srgrimes{ 4471541Srgrimes ana->iso_ce_blk = isonum_733(p->location); 4481541Srgrimes ana->iso_ce_off = isonum_733(p->offset); 4491541Srgrimes ana->iso_ce_len = isonum_733(p->length); 4501541Srgrimes return ISO_SUSP_CONT; 4511541Srgrimes} 4521541Srgrimes 4531541Srgrimes/* 4541541Srgrimes * System Use end 4551541Srgrimes */ 4561541Srgrimesstatic int 4571541Srgrimescd9660_rrip_stop(p,ana) 4581541Srgrimes ISO_SUSP_HEADER *p; 4591541Srgrimes ISO_RRIP_ANALYZE *ana; 4601541Srgrimes{ 4611541Srgrimes return ISO_SUSP_STOP; 4621541Srgrimes} 4631541Srgrimes 4641541Srgrimes/* 4651541Srgrimes * Extension reference 4661541Srgrimes */ 4671541Srgrimesstatic int 4681541Srgrimescd9660_rrip_extref(p,ana) 4691541Srgrimes ISO_RRIP_EXTREF *p; 4701541Srgrimes ISO_RRIP_ANALYZE *ana; 4711541Srgrimes{ 4721541Srgrimes if (isonum_711(p->len_id) != 10 4731541Srgrimes || bcmp((char *)p + 8,"RRIP_1991A",10) 4741541Srgrimes || isonum_711(p->version) != 1) 4751541Srgrimes return 0; 4761541Srgrimes ana->fields &= ~ISO_SUSP_EXTREF; 4771541Srgrimes return ISO_SUSP_EXTREF; 4781541Srgrimes} 4791541Srgrimes 4801541Srgrimesstatic int 4811541Srgrimescd9660_rrip_loop(isodir,ana,table) 4821541Srgrimes struct iso_directory_record *isodir; 4831541Srgrimes ISO_RRIP_ANALYZE *ana; 4841541Srgrimes RRIP_TABLE *table; 4851541Srgrimes{ 486131526Sphk RRIP_TABLE *ptable; 487131526Sphk ISO_SUSP_HEADER *phead; 488131526Sphk ISO_SUSP_HEADER *pend; 4891541Srgrimes struct buf *bp = NULL; 4901541Srgrimes char *pwhead; 491120492Sfjoe u_short c; 4921541Srgrimes int result; 4938876Srgrimes 4941541Srgrimes /* 4951541Srgrimes * Note: If name length is odd, 4965651Sjoerg * it will be padding 1 byte after the name 4971541Srgrimes */ 4981541Srgrimes pwhead = isodir->name + isonum_711(isodir->name_len); 4991541Srgrimes if (!(isonum_711(isodir->name_len)&1)) 5001541Srgrimes pwhead++; 501120492Sfjoe isochar(isodir->name, pwhead, ana->imp->joliet_level, &c, NULL, 502120492Sfjoe ana->imp->im_flags, ana->imp->im_d2l); 5038876Srgrimes 5041541Srgrimes /* If it's not the '.' entry of the root dir obey SP field */ 50545773Sdcs if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent) 5061541Srgrimes pwhead += ana->imp->rr_skip; 5071541Srgrimes else 5081541Srgrimes pwhead += ana->imp->rr_skip0; 5098876Srgrimes 5101541Srgrimes phead = (ISO_SUSP_HEADER *)pwhead; 5111541Srgrimes pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length)); 5128876Srgrimes 5131541Srgrimes result = 0; 5141541Srgrimes while (1) { 5151541Srgrimes ana->iso_ce_len = 0; 5161541Srgrimes /* 5171541Srgrimes * Note: "pend" should be more than one SUSP header 5188876Srgrimes */ 5191541Srgrimes while (pend >= phead + 1) { 5201541Srgrimes if (isonum_711(phead->version) == 1) { 5211541Srgrimes for (ptable = table; ptable->func; ptable++) { 5221541Srgrimes if (*phead->type == *ptable->type 5231541Srgrimes && phead->type[1] == ptable->type[1]) { 5241541Srgrimes result |= ptable->func(phead,ana); 5251541Srgrimes break; 5261541Srgrimes } 5271541Srgrimes } 5281541Srgrimes if (!ana->fields) 5291541Srgrimes break; 5301541Srgrimes } 53122521Sdyson if (result&ISO_SUSP_STOP) { 53222521Sdyson result &= ~ISO_SUSP_STOP; 53322521Sdyson break; 53422521Sdyson } 53522521Sdyson /* plausibility check */ 53622521Sdyson if (isonum_711(phead->length) < sizeof(*phead)) 53722521Sdyson break; 5381541Srgrimes /* 5391541Srgrimes * move to next SUSP 5401541Srgrimes * Hopefully this works with newer versions, too 5411541Srgrimes */ 5421541Srgrimes phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length)); 5431541Srgrimes } 544131526Sphk 54522521Sdyson if (ana->fields && ana->iso_ce_len) { 5461541Srgrimes if (ana->iso_ce_blk >= ana->imp->volume_space_size 5471541Srgrimes || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size 5481541Srgrimes || bread(ana->imp->im_devvp, 54922521Sdyson ana->iso_ce_blk << 55022521Sdyson (ana->imp->im_bshift - DEV_BSHIFT), 55122521Sdyson ana->imp->logical_block_size, NOCRED, &bp)) 5521541Srgrimes /* what to do now? */ 5531541Srgrimes break; 55422521Sdyson phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off); 5551541Srgrimes pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len); 5561541Srgrimes } else 5571541Srgrimes break; 5581541Srgrimes } 5591541Srgrimes if (bp) 5601541Srgrimes brelse(bp); 5611541Srgrimes /* 5621541Srgrimes * If we don't find the Basic SUSP stuffs, just set default value 56322521Sdyson * (attribute/time stamp) 5641541Srgrimes */ 5651541Srgrimes for (ptable = table; ptable->func2; ptable++) 5661541Srgrimes if (!(ptable->result&result)) 5671541Srgrimes ptable->func2(isodir,ana); 5688876Srgrimes 5691541Srgrimes return result; 5701541Srgrimes} 5711541Srgrimes 57212597Sbde/* 57322521Sdyson * Get Attributes. 57422521Sdyson */ 57522521Sdyson/* 57612597Sbde * XXX the casts are bogus but will do for now. 57712597Sbde */ 57812597Sbde#define BC (rrt_func_t *) 5791541Srgrimesstatic RRIP_TABLE rrip_table_analyze[] = { 58012597Sbde { "PX", BC cd9660_rrip_attr, cd9660_rrip_defattr, ISO_SUSP_ATTR }, 58112597Sbde { "TF", BC cd9660_rrip_tstamp, cd9660_rrip_deftstamp, ISO_SUSP_TSTAMP }, 58212597Sbde { "PN", BC cd9660_rrip_device, 0, ISO_SUSP_DEVICE }, 58312597Sbde { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 58412597Sbde { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 58512597Sbde { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 5861541Srgrimes { "", 0, 0, 0 } 5871541Srgrimes}; 5881541Srgrimes 5891541Srgrimesint 5901541Srgrimescd9660_rrip_analyze(isodir,inop,imp) 5911541Srgrimes struct iso_directory_record *isodir; 5921541Srgrimes struct iso_node *inop; 5931541Srgrimes struct iso_mnt *imp; 5941541Srgrimes{ 5951541Srgrimes ISO_RRIP_ANALYZE analyze; 5968876Srgrimes 5971541Srgrimes analyze.inop = inop; 5981541Srgrimes analyze.imp = imp; 5991541Srgrimes analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE; 6008876Srgrimes 6011541Srgrimes return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze); 6021541Srgrimes} 6031541Srgrimes 604131526Sphk/* 60522521Sdyson * Get Alternate Name. 6061541Srgrimes */ 6071541Srgrimesstatic RRIP_TABLE rrip_table_getname[] = { 60812597Sbde { "NM", BC cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME }, 60912597Sbde { "CL", BC cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 61012597Sbde { "PL", BC cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 61112597Sbde { "RE", BC cd9660_rrip_reldir, 0, ISO_SUSP_RELDIR }, 61212597Sbde { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 61312597Sbde { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 61412597Sbde { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 6151541Srgrimes { "", 0, 0, 0 } 6161541Srgrimes}; 6171541Srgrimes 6181541Srgrimesint 6191541Srgrimescd9660_rrip_getname(isodir,outbuf,outlen,inump,imp) 6201541Srgrimes struct iso_directory_record *isodir; 6211541Srgrimes char *outbuf; 6221541Srgrimes u_short *outlen; 6231541Srgrimes ino_t *inump; 6241541Srgrimes struct iso_mnt *imp; 6251541Srgrimes{ 6261541Srgrimes ISO_RRIP_ANALYZE analyze; 6271541Srgrimes RRIP_TABLE *tab; 628120492Sfjoe u_short c; 6298876Srgrimes 6301541Srgrimes analyze.outbuf = outbuf; 6311541Srgrimes analyze.outlen = outlen; 6321541Srgrimes analyze.maxlen = NAME_MAX; 6331541Srgrimes analyze.inump = inump; 6341541Srgrimes analyze.imp = imp; 6351541Srgrimes analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 6361541Srgrimes *outlen = 0; 6378876Srgrimes 63845773Sdcs isochar(isodir->name, isodir->name + isonum_711(isodir->name_len), 639120492Sfjoe imp->joliet_level, &c, NULL, imp->im_flags, imp->im_d2l); 6401541Srgrimes tab = rrip_table_getname; 64145773Sdcs if (c == 0 || c == 1) { 6421541Srgrimes cd9660_rrip_defname(isodir,&analyze); 6438876Srgrimes 6441541Srgrimes analyze.fields &= ~ISO_SUSP_ALTNAME; 6451541Srgrimes tab++; 6461541Srgrimes } 6478876Srgrimes 6481541Srgrimes return cd9660_rrip_loop(isodir,&analyze,tab); 6491541Srgrimes} 6501541Srgrimes 651131526Sphk/* 65222521Sdyson * Get Symbolic Link. 6531541Srgrimes */ 6541541Srgrimesstatic RRIP_TABLE rrip_table_getsymname[] = { 65512597Sbde { "SL", BC cd9660_rrip_slink, 0, ISO_SUSP_SLINK }, 65612597Sbde { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 65712597Sbde { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 65812597Sbde { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 6591541Srgrimes { "", 0, 0, 0 } 6601541Srgrimes}; 6611541Srgrimes 6621541Srgrimesint 6631541Srgrimescd9660_rrip_getsymname(isodir,outbuf,outlen,imp) 6641541Srgrimes struct iso_directory_record *isodir; 6651541Srgrimes char *outbuf; 6661541Srgrimes u_short *outlen; 6671541Srgrimes struct iso_mnt *imp; 6681541Srgrimes{ 6691541Srgrimes ISO_RRIP_ANALYZE analyze; 6708876Srgrimes 6711541Srgrimes analyze.outbuf = outbuf; 6721541Srgrimes analyze.outlen = outlen; 6731541Srgrimes *outlen = 0; 6741541Srgrimes analyze.maxlen = MAXPATHLEN; 6751541Srgrimes analyze.cont = 1; /* don't start with a slash */ 6761541Srgrimes analyze.imp = imp; 6771541Srgrimes analyze.fields = ISO_SUSP_SLINK; 6788876Srgrimes 6791541Srgrimes return (cd9660_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK); 6801541Srgrimes} 6811541Srgrimes 6821541Srgrimesstatic RRIP_TABLE rrip_table_extref[] = { 68312597Sbde { "ER", BC cd9660_rrip_extref, 0, ISO_SUSP_EXTREF }, 68412597Sbde { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 68512597Sbde { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 6861541Srgrimes { "", 0, 0, 0 } 6871541Srgrimes}; 6881541Srgrimes 6891541Srgrimes/* 6901541Srgrimes * Check for Rock Ridge Extension and return offset of its fields. 69122521Sdyson * Note: We insist on the ER field. 6921541Srgrimes */ 6931541Srgrimesint 6941541Srgrimescd9660_rrip_offset(isodir,imp) 6951541Srgrimes struct iso_directory_record *isodir; 6961541Srgrimes struct iso_mnt *imp; 6971541Srgrimes{ 6981541Srgrimes ISO_RRIP_OFFSET *p; 6991541Srgrimes ISO_RRIP_ANALYZE analyze; 7008876Srgrimes 7011541Srgrimes imp->rr_skip0 = 0; 7021541Srgrimes p = (ISO_RRIP_OFFSET *)(isodir->name + 1); 7031541Srgrimes if (bcmp(p,"SP\7\1\276\357",6)) { 7041541Srgrimes /* Maybe, it's a CDROM XA disc? */ 7051541Srgrimes imp->rr_skip0 = 15; 7061541Srgrimes p = (ISO_RRIP_OFFSET *)((char *)p + 15); 7071541Srgrimes if (bcmp(p,"SP\7\1\276\357",6)) 7081541Srgrimes return -1; 7091541Srgrimes } 7108876Srgrimes 7111541Srgrimes analyze.imp = imp; 7121541Srgrimes analyze.fields = ISO_SUSP_EXTREF; 7131541Srgrimes if (!(cd9660_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF)) 7141541Srgrimes return -1; 7158876Srgrimes 7161541Srgrimes return isonum_711(p->skip); 7171541Srgrimes} 718