165789Smckusick /*- 265789Smckusick * Copyright (c) 1993, 1994 365789Smckusick * The Regents of the University of California. All rights reserved. 465789Smckusick * 565789Smckusick * This code is derived from software contributed to Berkeley 665789Smckusick * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 765789Smckusick * Support code is derived from software contributed to Berkeley 865789Smckusick * by Atsushi Murai (amurai@spec.co.jp). 965789Smckusick * 1065789Smckusick * %sccs.include.redist.c% 1165789Smckusick * 12*65855Smckusick * @(#)cd9660_rrip.c 8.2 (Berkeley) 01/23/94 1365789Smckusick */ 1465789Smckusick 1565789Smckusick #include <sys/param.h> 1665789Smckusick #include <sys/namei.h> 1765789Smckusick #include <sys/buf.h> 1865789Smckusick #include <sys/file.h> 1965789Smckusick #include <sys/vnode.h> 2065789Smckusick #include <sys/mount.h> 2165789Smckusick #include <sys/kernel.h> 2265789Smckusick #include <sys/stat.h> 2365789Smckusick #include <sys/types.h> 2465789Smckusick 2565789Smckusick #include <sys/time.h> 2665789Smckusick 2765789Smckusick #include <isofs/cd9660/iso.h> 28*65855Smckusick #include <isofs/cd9660/cd9660_node.h> 29*65855Smckusick #include <isofs/cd9660/cd9660_rrip.h> 3065789Smckusick #include <isofs/cd9660/iso_rrip.h> 3165789Smckusick 3265789Smckusick /* 3365789Smckusick * POSIX file attribute 3465789Smckusick */ 3565789Smckusick static int 36*65855Smckusick cd9660_rrip_attr(p,ana) 3765789Smckusick ISO_RRIP_ATTR *p; 3865789Smckusick ISO_RRIP_ANALYZE *ana; 3965789Smckusick { 4065789Smckusick ana->inop->inode.iso_mode = isonum_731(p->mode_l); 4165789Smckusick ana->inop->inode.iso_uid = (uid_t)isonum_731(p->uid_l); 4265789Smckusick ana->inop->inode.iso_gid = (gid_t)isonum_731(p->gid_l); 4365789Smckusick ana->inop->inode.iso_links = isonum_731(p->links_l); 4465789Smckusick ana->fields &= ~ISO_SUSP_ATTR; 4565789Smckusick return ISO_SUSP_ATTR; 4665789Smckusick } 4765789Smckusick 4865789Smckusick static void 49*65855Smckusick cd9660_rrip_defattr(isodir,ana) 5065789Smckusick struct iso_directory_record *isodir; 5165789Smckusick ISO_RRIP_ANALYZE *ana; 5265789Smckusick { 5365789Smckusick /* But this is a required field! */ 5465789Smckusick printf("RRIP without PX field?\n"); 55*65855Smckusick cd9660_defattr(isodir,ana->inop,NULL); 5665789Smckusick } 5765789Smckusick 5865789Smckusick /* 5965789Smckusick * Symbolic Links 6065789Smckusick */ 6165789Smckusick static int 62*65855Smckusick cd9660_rrip_slink(p,ana) 6365789Smckusick ISO_RRIP_SLINK *p; 6465789Smckusick ISO_RRIP_ANALYZE *ana; 6565789Smckusick { 6665789Smckusick register ISO_RRIP_SLINK_COMPONENT *pcomp; 6765789Smckusick register ISO_RRIP_SLINK_COMPONENT *pcompe; 6865789Smckusick int len, wlen, cont; 6965789Smckusick char *outbuf, *inbuf; 7065789Smckusick 7165789Smckusick pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component; 7265789Smckusick pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length)); 7365789Smckusick len = *ana->outlen; 7465789Smckusick outbuf = ana->outbuf; 7565789Smckusick cont = ana->cont; 7665789Smckusick 7765789Smckusick /* 7865789Smckusick * Gathering a Symbolic name from each component with path 7965789Smckusick */ 8065789Smckusick for (; 8165789Smckusick pcomp < pcompe; 8265789Smckusick pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ 8365789Smckusick + isonum_711(pcomp->clen))) { 8465789Smckusick 8565789Smckusick if (!cont) { 8665789Smckusick if (len < ana->maxlen) { 8765789Smckusick len++; 8865789Smckusick *outbuf++ = '/'; 8965789Smckusick } 9065789Smckusick } 9165789Smckusick cont = 0; 9265789Smckusick 9365789Smckusick inbuf = ".."; 9465789Smckusick wlen = 0; 9565789Smckusick 9665789Smckusick switch (*pcomp->cflag) { 9765789Smckusick 9865789Smckusick case ISO_SUSP_CFLAG_CURRENT: 9965789Smckusick /* Inserting Current */ 10065789Smckusick wlen = 1; 10165789Smckusick break; 10265789Smckusick 10365789Smckusick case ISO_SUSP_CFLAG_PARENT: 10465789Smckusick /* Inserting Parent */ 10565789Smckusick wlen = 2; 10665789Smckusick break; 10765789Smckusick 10865789Smckusick case ISO_SUSP_CFLAG_ROOT: 10965789Smckusick /* Inserting slash for ROOT */ 11065789Smckusick /* start over from beginning(?) */ 11165789Smckusick outbuf -= len; 11265789Smckusick len = 0; 11365789Smckusick break; 11465789Smckusick 11565789Smckusick case ISO_SUSP_CFLAG_VOLROOT: 11665789Smckusick /* Inserting a mount point i.e. "/cdrom" */ 11765789Smckusick /* same as above */ 11865789Smckusick outbuf -= len; 11965789Smckusick len = 0; 12065789Smckusick inbuf = ana->imp->im_mountp->mnt_stat.f_mntonname; 12165789Smckusick wlen = strlen(inbuf); 12265789Smckusick break; 12365789Smckusick 12465789Smckusick case ISO_SUSP_CFLAG_HOST: 12565789Smckusick /* Inserting hostname i.e. "kurt.tools.de" */ 12665789Smckusick inbuf = hostname; 12765789Smckusick wlen = hostnamelen; 12865789Smckusick break; 12965789Smckusick 13065789Smckusick case ISO_SUSP_CFLAG_CONTINUE: 13165789Smckusick cont = 1; 13265789Smckusick /* fall thru */ 13365789Smckusick case 0: 13465789Smckusick /* Inserting component */ 13565789Smckusick wlen = isonum_711(pcomp->clen); 13665789Smckusick inbuf = pcomp->name; 13765789Smckusick break; 13865789Smckusick default: 13965789Smckusick printf("RRIP with incorrect flags?"); 14065789Smckusick wlen = ana->maxlen + 1; 14165789Smckusick break; 14265789Smckusick } 14365789Smckusick 14465789Smckusick if (len + wlen > ana->maxlen) { 14565789Smckusick /* indicate error to caller */ 14665789Smckusick ana->cont = 1; 14765789Smckusick ana->fields = 0; 14865789Smckusick ana->outbuf -= *ana->outlen; 14965789Smckusick *ana->outlen = 0; 15065789Smckusick return 0; 15165789Smckusick } 15265789Smckusick 15365789Smckusick bcopy(inbuf,outbuf,wlen); 15465789Smckusick outbuf += wlen; 15565789Smckusick len += wlen; 15665789Smckusick 15765789Smckusick } 15865789Smckusick ana->outbuf = outbuf; 15965789Smckusick *ana->outlen = len; 16065789Smckusick ana->cont = cont; 16165789Smckusick 16265789Smckusick if (!isonum_711(p->flags)) { 16365789Smckusick ana->fields &= ~ISO_SUSP_SLINK; 16465789Smckusick return ISO_SUSP_SLINK; 16565789Smckusick } 16665789Smckusick return 0; 16765789Smckusick } 16865789Smckusick 16965789Smckusick /* 17065789Smckusick * Alternate name 17165789Smckusick */ 17265789Smckusick static int 173*65855Smckusick cd9660_rrip_altname(p,ana) 17465789Smckusick ISO_RRIP_ALTNAME *p; 17565789Smckusick ISO_RRIP_ANALYZE *ana; 17665789Smckusick { 17765789Smckusick char *inbuf; 17865789Smckusick int wlen; 17965789Smckusick int cont; 18065789Smckusick 18165789Smckusick inbuf = ".."; 18265789Smckusick wlen = 0; 18365789Smckusick cont = 0; 18465789Smckusick 18565789Smckusick switch (*p->flags) { 18665789Smckusick case ISO_SUSP_CFLAG_CURRENT: 18765789Smckusick /* Inserting Current */ 18865789Smckusick wlen = 1; 18965789Smckusick break; 19065789Smckusick 19165789Smckusick case ISO_SUSP_CFLAG_PARENT: 19265789Smckusick /* Inserting Parent */ 19365789Smckusick wlen = 2; 19465789Smckusick break; 19565789Smckusick 19665789Smckusick case ISO_SUSP_CFLAG_HOST: 19765789Smckusick /* Inserting hostname i.e. "kurt.tools.de" */ 19865789Smckusick inbuf = hostname; 19965789Smckusick wlen = hostnamelen; 20065789Smckusick break; 20165789Smckusick 20265789Smckusick case ISO_SUSP_CFLAG_CONTINUE: 20365789Smckusick cont = 1; 20465789Smckusick /* fall thru */ 20565789Smckusick case 0: 20665789Smckusick /* Inserting component */ 20765789Smckusick wlen = isonum_711(p->h.length) - 5; 20865789Smckusick inbuf = (char *)p + 5; 20965789Smckusick break; 21065789Smckusick 21165789Smckusick default: 21265789Smckusick printf("RRIP with incorrect NM flags?\n"); 21365789Smckusick wlen = ana->maxlen + 1; 21465789Smckusick break; 21565789Smckusick } 21665789Smckusick 21765789Smckusick if ((*ana->outlen += wlen) > ana->maxlen) { 21865789Smckusick /* treat as no name field */ 21965789Smckusick ana->fields &= ~ISO_SUSP_ALTNAME; 22065789Smckusick ana->outbuf -= *ana->outlen - wlen; 22165789Smckusick *ana->outlen = 0; 22265789Smckusick return 0; 22365789Smckusick } 22465789Smckusick 22565789Smckusick bcopy(inbuf,ana->outbuf,wlen); 22665789Smckusick ana->outbuf += wlen; 22765789Smckusick 22865789Smckusick if (!cont) { 22965789Smckusick ana->fields &= ~ISO_SUSP_ALTNAME; 23065789Smckusick return ISO_SUSP_ALTNAME; 23165789Smckusick } 23265789Smckusick return 0; 23365789Smckusick } 23465789Smckusick 23565789Smckusick static void 236*65855Smckusick cd9660_rrip_defname(isodir,ana) 23765789Smckusick struct iso_directory_record *isodir; 23865789Smckusick ISO_RRIP_ANALYZE *ana; 23965789Smckusick { 24065789Smckusick strcpy(ana->outbuf,".."); 24165789Smckusick switch (*isodir->name) { 24265789Smckusick default: 24365789Smckusick isofntrans(isodir->name,isonum_711(isodir->name_len), 24465789Smckusick ana->outbuf,ana->outlen, 24565789Smckusick 1,isonum_711(isodir->flags)&4); 24665789Smckusick break; 24765789Smckusick case 0: 24865789Smckusick *ana->outlen = 1; 24965789Smckusick break; 25065789Smckusick case 1: 25165789Smckusick *ana->outlen = 2; 25265789Smckusick break; 25365789Smckusick } 25465789Smckusick } 25565789Smckusick 25665789Smckusick /* 25765789Smckusick * Parent or Child Link 25865789Smckusick */ 25965789Smckusick static int 260*65855Smckusick cd9660_rrip_pclink(p,ana) 26165789Smckusick ISO_RRIP_CLINK *p; 26265789Smckusick ISO_RRIP_ANALYZE *ana; 26365789Smckusick { 26465789Smckusick *ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift; 26565789Smckusick ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK); 26665789Smckusick return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK; 26765789Smckusick } 26865789Smckusick 26965789Smckusick /* 27065789Smckusick * Relocated directory 27165789Smckusick */ 27265789Smckusick static int 273*65855Smckusick cd9660_rrip_reldir(p,ana) 27465789Smckusick ISO_RRIP_RELDIR *p; 27565789Smckusick ISO_RRIP_ANALYZE *ana; 27665789Smckusick { 27765789Smckusick /* special hack to make caller aware of RE field */ 27865789Smckusick *ana->outlen = 0; 27965789Smckusick ana->fields = 0; 28065789Smckusick return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 28165789Smckusick } 28265789Smckusick 28365789Smckusick static int 284*65855Smckusick cd9660_rrip_tstamp(p,ana) 28565789Smckusick ISO_RRIP_TSTAMP *p; 28665789Smckusick ISO_RRIP_ANALYZE *ana; 28765789Smckusick { 28865789Smckusick unsigned char *ptime; 28965789Smckusick 29065789Smckusick ptime = p->time; 29165789Smckusick 29265789Smckusick /* Check a format of time stamp (7bytes/17bytes) */ 29365789Smckusick if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) { 29465789Smckusick if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 29565789Smckusick ptime += 7; 29665789Smckusick 29765789Smckusick if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 298*65855Smckusick cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime); 29965789Smckusick ptime += 7; 30065789Smckusick } else 30165789Smckusick bzero(&ana->inop->inode.iso_mtime,sizeof(struct timeval)); 30265789Smckusick 30365789Smckusick if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 304*65855Smckusick cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime); 30565789Smckusick ptime += 7; 30665789Smckusick } else 30765789Smckusick ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 30865789Smckusick 30965789Smckusick if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 310*65855Smckusick cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime); 31165789Smckusick else 31265789Smckusick ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 31365789Smckusick 31465789Smckusick } else { 31565789Smckusick if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 31665789Smckusick ptime += 17; 31765789Smckusick 31865789Smckusick if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 319*65855Smckusick cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime); 32065789Smckusick ptime += 17; 32165789Smckusick } else 32265789Smckusick bzero(&ana->inop->inode.iso_mtime,sizeof(struct timeval)); 32365789Smckusick 32465789Smckusick if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 325*65855Smckusick cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime); 32665789Smckusick ptime += 17; 32765789Smckusick } else 32865789Smckusick ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 32965789Smckusick 33065789Smckusick if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 331*65855Smckusick cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime); 33265789Smckusick else 33365789Smckusick ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 33465789Smckusick 33565789Smckusick } 33665789Smckusick ana->fields &= ~ISO_SUSP_TSTAMP; 33765789Smckusick return ISO_SUSP_TSTAMP; 33865789Smckusick } 33965789Smckusick 34065789Smckusick static void 341*65855Smckusick cd9660_rrip_deftstamp(isodir,ana) 34265789Smckusick struct iso_directory_record *isodir; 34365789Smckusick ISO_RRIP_ANALYZE *ana; 34465789Smckusick { 345*65855Smckusick cd9660_deftstamp(isodir,ana->inop,NULL); 34665789Smckusick } 34765789Smckusick 34865789Smckusick /* 34965789Smckusick * POSIX device modes 35065789Smckusick */ 35165789Smckusick static int 352*65855Smckusick cd9660_rrip_device(p,ana) 35365789Smckusick ISO_RRIP_DEVICE *p; 35465789Smckusick ISO_RRIP_ANALYZE *ana; 35565789Smckusick { 35665789Smckusick unsigned high, low; 35765789Smckusick 35865789Smckusick high = isonum_733(p->dev_t_high_l); 35965789Smckusick low = isonum_733(p->dev_t_low_l); 36065789Smckusick 36165789Smckusick if ( high == 0 ) { 36265789Smckusick ana->inop->inode.iso_rdev = makedev( major(low), minor(low) ); 36365789Smckusick } else { 36465789Smckusick ana->inop->inode.iso_rdev = makedev( high, minor(low) ); 36565789Smckusick } 36665789Smckusick ana->fields &= ~ISO_SUSP_DEVICE; 36765789Smckusick return ISO_SUSP_DEVICE; 36865789Smckusick } 36965789Smckusick 37065789Smckusick /* 37165789Smckusick * Flag indicating 37265789Smckusick */ 37365789Smckusick static int 374*65855Smckusick cd9660_rrip_idflag(p,ana) 37565789Smckusick ISO_RRIP_IDFLAG *p; 37665789Smckusick ISO_RRIP_ANALYZE *ana; 37765789Smckusick { 37865789Smckusick ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */ 37965789Smckusick /* special handling of RE field */ 38065789Smckusick if (ana->fields&ISO_SUSP_RELDIR) 381*65855Smckusick return cd9660_rrip_reldir(p,ana); 38265789Smckusick 38365789Smckusick return ISO_SUSP_IDFLAG; 38465789Smckusick } 38565789Smckusick 38665789Smckusick /* 38765789Smckusick * Continuation pointer 38865789Smckusick */ 38965789Smckusick static int 390*65855Smckusick cd9660_rrip_cont(p,ana) 39165789Smckusick ISO_RRIP_CONT *p; 39265789Smckusick ISO_RRIP_ANALYZE *ana; 39365789Smckusick { 39465789Smckusick ana->iso_ce_blk = isonum_733(p->location); 39565789Smckusick ana->iso_ce_off = isonum_733(p->offset); 39665789Smckusick ana->iso_ce_len = isonum_733(p->length); 39765789Smckusick return ISO_SUSP_CONT; 39865789Smckusick } 39965789Smckusick 40065789Smckusick /* 40165789Smckusick * System Use end 40265789Smckusick */ 40365789Smckusick static int 404*65855Smckusick cd9660_rrip_stop(p,ana) 40565789Smckusick ISO_SUSP_HEADER *p; 40665789Smckusick ISO_RRIP_ANALYZE *ana; 40765789Smckusick { 40865789Smckusick /* stop analyzing */ 40965789Smckusick ana->fields = 0; 41065789Smckusick return ISO_SUSP_STOP; 41165789Smckusick } 41265789Smckusick 41365789Smckusick /* 41465789Smckusick * Extension reference 41565789Smckusick */ 41665789Smckusick static int 417*65855Smckusick cd9660_rrip_extref(p,ana) 41865789Smckusick ISO_RRIP_EXTREF *p; 41965789Smckusick ISO_RRIP_ANALYZE *ana; 42065789Smckusick { 42165789Smckusick if (isonum_711(p->len_id) != 10 42265789Smckusick || bcmp((char *)p + 8,"RRIP_1991A",10) 42365789Smckusick || isonum_711(p->version) != 1) 42465789Smckusick return 0; 42565789Smckusick ana->fields &= ~ISO_SUSP_EXTREF; 42665789Smckusick return ISO_SUSP_EXTREF; 42765789Smckusick } 42865789Smckusick 42965789Smckusick typedef struct { 43065789Smckusick char type[2]; 43165789Smckusick int (*func)(); 43265789Smckusick void (*func2)(); 43365789Smckusick int result; 43465789Smckusick } RRIP_TABLE; 43565789Smckusick 43665789Smckusick static int 437*65855Smckusick cd9660_rrip_loop(isodir,ana,table) 43865789Smckusick struct iso_directory_record *isodir; 43965789Smckusick ISO_RRIP_ANALYZE *ana; 44065789Smckusick RRIP_TABLE *table; 44165789Smckusick { 44265789Smckusick register RRIP_TABLE *ptable; 44365789Smckusick register ISO_SUSP_HEADER *phead; 44465789Smckusick register ISO_SUSP_HEADER *pend; 44565789Smckusick struct buf *bp = NULL; 44665789Smckusick int i; 44765789Smckusick char *pwhead; 44865789Smckusick int result; 44965789Smckusick 45065789Smckusick /* 45165789Smckusick * Note: If name length is odd, 45265789Smckusick * it will be padding 1 byte after the name 45365789Smckusick */ 45465789Smckusick pwhead = isodir->name + isonum_711(isodir->name_len); 45565789Smckusick if (!(isonum_711(isodir->name_len)&1)) 45665789Smckusick pwhead++; 45765789Smckusick 45865789Smckusick /* If it's not the '.' entry of the root dir obey SP field */ 45965789Smckusick if (*isodir->name != 0 46065789Smckusick || isonum_733(isodir->extent) != ana->imp->root_extent) 46165789Smckusick pwhead += ana->imp->rr_skip; 46265789Smckusick else 46365789Smckusick pwhead += ana->imp->rr_skip0; 46465789Smckusick 46565789Smckusick phead = (ISO_SUSP_HEADER *)pwhead; 46665789Smckusick pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length)); 46765789Smckusick 46865789Smckusick result = 0; 46965789Smckusick while (1) { 47065789Smckusick ana->iso_ce_len = 0; 47165789Smckusick /* 47265789Smckusick * Note: "pend" should be more than one SUSP header 47365789Smckusick */ 47465789Smckusick while (pend >= phead + 1) { 47565789Smckusick if (isonum_711(phead->version) == 1) { 47665789Smckusick for (ptable = table; ptable->func; ptable++) { 47765789Smckusick if (*phead->type == *ptable->type 47865789Smckusick && phead->type[1] == ptable->type[1]) { 47965789Smckusick result |= ptable->func(phead,ana); 48065789Smckusick break; 48165789Smckusick } 48265789Smckusick } 48365789Smckusick if (!ana->fields) 48465789Smckusick break; 48565789Smckusick } 48665789Smckusick /* 48765789Smckusick * move to next SUSP 48865789Smckusick * Hopefully this works with newer versions, too 48965789Smckusick */ 49065789Smckusick phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length)); 49165789Smckusick } 49265789Smckusick 49365789Smckusick if ( ana->fields && ana->iso_ce_len ) { 49465789Smckusick if (ana->iso_ce_blk >= ana->imp->volume_space_size 49565789Smckusick || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size 49665789Smckusick || bread(ana->imp->im_devvp, 49765789Smckusick ana->iso_ce_blk * ana->imp->logical_block_size / DEV_BSIZE, 49865789Smckusick ana->imp->logical_block_size,NOCRED,&bp)) 49965789Smckusick /* what to do now? */ 50065789Smckusick break; 50165789Smckusick phead = (ISO_SUSP_HEADER *)(bp->b_un.b_addr + ana->iso_ce_off); 50265789Smckusick pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len); 50365789Smckusick } else 50465789Smckusick break; 50565789Smckusick } 50665789Smckusick if (bp) 50765789Smckusick brelse(bp); 50865789Smckusick /* 50965789Smckusick * If we don't find the Basic SUSP stuffs, just set default value 51065789Smckusick * ( attribute/time stamp ) 51165789Smckusick */ 51265789Smckusick for (ptable = table; ptable->func2; ptable++) 51365789Smckusick if (!(ptable->result&result)) 51465789Smckusick ptable->func2(isodir,ana); 51565789Smckusick 51665789Smckusick return result; 51765789Smckusick } 51865789Smckusick 51965789Smckusick static RRIP_TABLE rrip_table_analyze[] = { 520*65855Smckusick { "PX", cd9660_rrip_attr, cd9660_rrip_defattr, ISO_SUSP_ATTR }, 521*65855Smckusick { "TF", cd9660_rrip_tstamp, cd9660_rrip_deftstamp, ISO_SUSP_TSTAMP }, 522*65855Smckusick { "PN", cd9660_rrip_device, 0, ISO_SUSP_DEVICE }, 523*65855Smckusick { "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 524*65855Smckusick { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 525*65855Smckusick { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 52665789Smckusick { "", 0, 0, 0 } 52765789Smckusick }; 52865789Smckusick 52965789Smckusick int 530*65855Smckusick cd9660_rrip_analyze(isodir,inop,imp) 53165789Smckusick struct iso_directory_record *isodir; 53265789Smckusick struct iso_node *inop; 53365789Smckusick struct iso_mnt *imp; 53465789Smckusick { 53565789Smckusick ISO_RRIP_ANALYZE analyze; 53665789Smckusick 53765789Smckusick analyze.inop = inop; 53865789Smckusick analyze.imp = imp; 53965789Smckusick analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE; 54065789Smckusick 541*65855Smckusick return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze); 54265789Smckusick } 54365789Smckusick 54465789Smckusick /* 54565789Smckusick * Get Alternate Name from 'AL' record 54665789Smckusick * If either no AL record or 0 length, 54765789Smckusick * it will be return the translated ISO9660 name, 54865789Smckusick */ 54965789Smckusick static RRIP_TABLE rrip_table_getname[] = { 550*65855Smckusick { "NM", cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME }, 551*65855Smckusick { "CL", cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 552*65855Smckusick { "PL", cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 553*65855Smckusick { "RE", cd9660_rrip_reldir, 0, ISO_SUSP_RELDIR }, 554*65855Smckusick { "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 555*65855Smckusick { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 556*65855Smckusick { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 55765789Smckusick { "", 0, 0, 0 } 55865789Smckusick }; 55965789Smckusick 56065789Smckusick int 561*65855Smckusick cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp) 56265789Smckusick struct iso_directory_record *isodir; 56365789Smckusick char *outbuf; 56465789Smckusick u_short *outlen; 56565789Smckusick ino_t *inump; 56665789Smckusick struct iso_mnt *imp; 56765789Smckusick { 56865789Smckusick ISO_RRIP_ANALYZE analyze; 56965789Smckusick RRIP_TABLE *tab; 57065789Smckusick 57165789Smckusick analyze.outbuf = outbuf; 57265789Smckusick analyze.outlen = outlen; 57365789Smckusick analyze.maxlen = NAME_MAX; 57465789Smckusick analyze.inump = inump; 57565789Smckusick analyze.imp = imp; 57665789Smckusick analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 57765789Smckusick *outlen = 0; 57865789Smckusick 57965789Smckusick tab = rrip_table_getname; 58065789Smckusick if (*isodir->name == 0 58165789Smckusick || *isodir->name == 1) { 582*65855Smckusick cd9660_rrip_defname(isodir,&analyze); 58365789Smckusick 58465789Smckusick analyze.fields &= ~ISO_SUSP_ALTNAME; 58565789Smckusick tab++; 58665789Smckusick } 58765789Smckusick 588*65855Smckusick return cd9660_rrip_loop(isodir,&analyze,tab); 58965789Smckusick } 59065789Smckusick 59165789Smckusick /* 59265789Smckusick * Get Symbolic Name from 'SL' record 59365789Smckusick * 59465789Smckusick * Note: isodir should contains SL record! 59565789Smckusick */ 59665789Smckusick static RRIP_TABLE rrip_table_getsymname[] = { 597*65855Smckusick { "SL", cd9660_rrip_slink, 0, ISO_SUSP_SLINK }, 598*65855Smckusick { "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 599*65855Smckusick { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 600*65855Smckusick { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 60165789Smckusick { "", 0, 0, 0 } 60265789Smckusick }; 60365789Smckusick 60465789Smckusick int 605*65855Smckusick cd9660_rrip_getsymname(isodir,outbuf,outlen,imp) 60665789Smckusick struct iso_directory_record *isodir; 60765789Smckusick char *outbuf; 60865789Smckusick u_short *outlen; 60965789Smckusick struct iso_mnt *imp; 61065789Smckusick { 61165789Smckusick ISO_RRIP_ANALYZE analyze; 61265789Smckusick 61365789Smckusick analyze.outbuf = outbuf; 61465789Smckusick analyze.outlen = outlen; 61565789Smckusick *outlen = 0; 61665789Smckusick analyze.maxlen = MAXPATHLEN; 61765789Smckusick analyze.cont = 1; /* don't start with a slash */ 61865789Smckusick analyze.imp = imp; 61965789Smckusick analyze.fields = ISO_SUSP_SLINK; 62065789Smckusick 621*65855Smckusick return (cd9660_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK); 62265789Smckusick } 62365789Smckusick 62465789Smckusick static RRIP_TABLE rrip_table_extref[] = { 625*65855Smckusick { "ER", cd9660_rrip_extref, 0, ISO_SUSP_EXTREF }, 626*65855Smckusick { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 627*65855Smckusick { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 62865789Smckusick { "", 0, 0, 0 } 62965789Smckusick }; 63065789Smckusick 63165789Smckusick /* 63265789Smckusick * Check for Rock Ridge Extension and return offset of its fields. 63365789Smckusick * Note: We require the ER field. 63465789Smckusick */ 63565789Smckusick int 636*65855Smckusick cd9660_rrip_offset(isodir,imp) 63765789Smckusick struct iso_directory_record *isodir; 63865789Smckusick struct iso_mnt *imp; 63965789Smckusick { 64065789Smckusick ISO_RRIP_OFFSET *p; 64165789Smckusick ISO_RRIP_ANALYZE analyze; 64265789Smckusick 64365789Smckusick imp->rr_skip0 = 0; 64465789Smckusick p = (ISO_RRIP_OFFSET *)(isodir->name + 1); 64565789Smckusick if (bcmp(p,"SP\7\1\276\357",6)) { 64665789Smckusick /* Maybe, it's a CDROM XA disc? */ 64765789Smckusick imp->rr_skip0 = 15; 64865789Smckusick p = (ISO_RRIP_OFFSET *)((char *)p + 15); 64965789Smckusick if (bcmp(p,"SP\7\1\276\357",6)) 65065789Smckusick return -1; 65165789Smckusick } 65265789Smckusick 65365789Smckusick analyze.imp = imp; 65465789Smckusick analyze.fields = ISO_SUSP_EXTREF; 655*65855Smckusick if (!(cd9660_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF)) 65665789Smckusick return -1; 65765789Smckusick 65865789Smckusick return isonum_711(p->skip); 65965789Smckusick } 660