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*68049Smckusick * @(#)cd9660_rrip.c 8.6 (Berkeley) 12/05/94
1365789Smckusick */
1465789Smckusick
1565789Smckusick #include <sys/param.h>
16*68049Smckusick #include <sys/systm.h>
1765789Smckusick #include <sys/namei.h>
1865789Smckusick #include <sys/buf.h>
1965789Smckusick #include <sys/file.h>
2065789Smckusick #include <sys/vnode.h>
2165789Smckusick #include <sys/mount.h>
2265789Smckusick #include <sys/kernel.h>
2365789Smckusick #include <sys/stat.h>
2465789Smckusick #include <sys/types.h>
2565789Smckusick
2665789Smckusick #include <sys/time.h>
2765789Smckusick
2865789Smckusick #include <isofs/cd9660/iso.h>
2965855Smckusick #include <isofs/cd9660/cd9660_node.h>
3065855Smckusick #include <isofs/cd9660/cd9660_rrip.h>
3165789Smckusick #include <isofs/cd9660/iso_rrip.h>
3265789Smckusick
3365789Smckusick /*
3465789Smckusick * POSIX file attribute
3565789Smckusick */
3665789Smckusick static int
cd9660_rrip_attr(p,ana)3765855Smckusick cd9660_rrip_attr(p,ana)
3865789Smckusick ISO_RRIP_ATTR *p;
3965789Smckusick ISO_RRIP_ANALYZE *ana;
4065789Smckusick {
41*68049Smckusick ana->inop->inode.iso_mode = isonum_733(p->mode);
42*68049Smckusick ana->inop->inode.iso_uid = isonum_733(p->uid);
43*68049Smckusick ana->inop->inode.iso_gid = isonum_733(p->gid);
44*68049Smckusick ana->inop->inode.iso_links = isonum_733(p->links);
4565789Smckusick ana->fields &= ~ISO_SUSP_ATTR;
4665789Smckusick return ISO_SUSP_ATTR;
4765789Smckusick }
4865789Smckusick
4965789Smckusick static void
cd9660_rrip_defattr(isodir,ana)5065855Smckusick cd9660_rrip_defattr(isodir,ana)
5165789Smckusick struct iso_directory_record *isodir;
5265789Smckusick ISO_RRIP_ANALYZE *ana;
5365789Smckusick {
5465789Smckusick /* But this is a required field! */
5565789Smckusick printf("RRIP without PX field?\n");
5665855Smckusick cd9660_defattr(isodir,ana->inop,NULL);
5765789Smckusick }
5865789Smckusick
5965789Smckusick /*
6065789Smckusick * Symbolic Links
6165789Smckusick */
6265789Smckusick static int
cd9660_rrip_slink(p,ana)6365855Smckusick cd9660_rrip_slink(p,ana)
6465789Smckusick ISO_RRIP_SLINK *p;
6565789Smckusick ISO_RRIP_ANALYZE *ana;
6665789Smckusick {
6765789Smckusick register ISO_RRIP_SLINK_COMPONENT *pcomp;
6865789Smckusick register ISO_RRIP_SLINK_COMPONENT *pcompe;
6965789Smckusick int len, wlen, cont;
7065789Smckusick char *outbuf, *inbuf;
7165789Smckusick
7265789Smckusick pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component;
7365789Smckusick pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length));
7465789Smckusick len = *ana->outlen;
7565789Smckusick outbuf = ana->outbuf;
7665789Smckusick cont = ana->cont;
7765789Smckusick
7865789Smckusick /*
7965789Smckusick * Gathering a Symbolic name from each component with path
8065789Smckusick */
8165789Smckusick for (;
8265789Smckusick pcomp < pcompe;
8365789Smckusick pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ
8465789Smckusick + isonum_711(pcomp->clen))) {
8565789Smckusick
8665789Smckusick if (!cont) {
8765789Smckusick if (len < ana->maxlen) {
8865789Smckusick len++;
8965789Smckusick *outbuf++ = '/';
9065789Smckusick }
9165789Smckusick }
9265789Smckusick cont = 0;
9365789Smckusick
9465789Smckusick inbuf = "..";
9565789Smckusick wlen = 0;
9665789Smckusick
9765789Smckusick switch (*pcomp->cflag) {
9865789Smckusick
9965789Smckusick case ISO_SUSP_CFLAG_CURRENT:
10065789Smckusick /* Inserting Current */
10165789Smckusick wlen = 1;
10265789Smckusick break;
10365789Smckusick
10465789Smckusick case ISO_SUSP_CFLAG_PARENT:
10565789Smckusick /* Inserting Parent */
10665789Smckusick wlen = 2;
10765789Smckusick break;
10865789Smckusick
10965789Smckusick case ISO_SUSP_CFLAG_ROOT:
11065789Smckusick /* Inserting slash for ROOT */
11165789Smckusick /* start over from beginning(?) */
11265789Smckusick outbuf -= len;
11365789Smckusick len = 0;
11465789Smckusick break;
11565789Smckusick
11665789Smckusick case ISO_SUSP_CFLAG_VOLROOT:
11765789Smckusick /* Inserting a mount point i.e. "/cdrom" */
11865789Smckusick /* same as above */
11965789Smckusick outbuf -= len;
12065789Smckusick len = 0;
12165789Smckusick inbuf = ana->imp->im_mountp->mnt_stat.f_mntonname;
12265789Smckusick wlen = strlen(inbuf);
12365789Smckusick break;
12465789Smckusick
12565789Smckusick case ISO_SUSP_CFLAG_HOST:
12665789Smckusick /* Inserting hostname i.e. "kurt.tools.de" */
12765789Smckusick inbuf = hostname;
12865789Smckusick wlen = hostnamelen;
12965789Smckusick break;
13065789Smckusick
13165789Smckusick case ISO_SUSP_CFLAG_CONTINUE:
13265789Smckusick cont = 1;
13365789Smckusick /* fall thru */
13465789Smckusick case 0:
13565789Smckusick /* Inserting component */
13665789Smckusick wlen = isonum_711(pcomp->clen);
13765789Smckusick inbuf = pcomp->name;
13865789Smckusick break;
13965789Smckusick default:
14065789Smckusick printf("RRIP with incorrect flags?");
14165789Smckusick wlen = ana->maxlen + 1;
14265789Smckusick break;
14365789Smckusick }
14465789Smckusick
14565789Smckusick if (len + wlen > ana->maxlen) {
14665789Smckusick /* indicate error to caller */
14765789Smckusick ana->cont = 1;
14865789Smckusick ana->fields = 0;
14965789Smckusick ana->outbuf -= *ana->outlen;
15065789Smckusick *ana->outlen = 0;
15165789Smckusick return 0;
15265789Smckusick }
15365789Smckusick
15465789Smckusick bcopy(inbuf,outbuf,wlen);
15565789Smckusick outbuf += wlen;
15665789Smckusick len += wlen;
15765789Smckusick
15865789Smckusick }
15965789Smckusick ana->outbuf = outbuf;
16065789Smckusick *ana->outlen = len;
16165789Smckusick ana->cont = cont;
16265789Smckusick
16365789Smckusick if (!isonum_711(p->flags)) {
16465789Smckusick ana->fields &= ~ISO_SUSP_SLINK;
16565789Smckusick return ISO_SUSP_SLINK;
16665789Smckusick }
16765789Smckusick return 0;
16865789Smckusick }
16965789Smckusick
17065789Smckusick /*
17165789Smckusick * Alternate name
17265789Smckusick */
17365789Smckusick static int
cd9660_rrip_altname(p,ana)17465855Smckusick cd9660_rrip_altname(p,ana)
17565789Smckusick ISO_RRIP_ALTNAME *p;
17665789Smckusick ISO_RRIP_ANALYZE *ana;
17765789Smckusick {
17865789Smckusick char *inbuf;
17965789Smckusick int wlen;
18065789Smckusick int cont;
18165789Smckusick
18265789Smckusick inbuf = "..";
18365789Smckusick wlen = 0;
18465789Smckusick cont = 0;
18565789Smckusick
18665789Smckusick switch (*p->flags) {
18765789Smckusick case ISO_SUSP_CFLAG_CURRENT:
18865789Smckusick /* Inserting Current */
18965789Smckusick wlen = 1;
19065789Smckusick break;
19165789Smckusick
19265789Smckusick case ISO_SUSP_CFLAG_PARENT:
19365789Smckusick /* Inserting Parent */
19465789Smckusick wlen = 2;
19565789Smckusick break;
19665789Smckusick
19765789Smckusick case ISO_SUSP_CFLAG_HOST:
19865789Smckusick /* Inserting hostname i.e. "kurt.tools.de" */
19965789Smckusick inbuf = hostname;
20065789Smckusick wlen = hostnamelen;
20165789Smckusick break;
20265789Smckusick
20365789Smckusick case ISO_SUSP_CFLAG_CONTINUE:
20465789Smckusick cont = 1;
20565789Smckusick /* fall thru */
20665789Smckusick case 0:
20765789Smckusick /* Inserting component */
20865789Smckusick wlen = isonum_711(p->h.length) - 5;
20965789Smckusick inbuf = (char *)p + 5;
21065789Smckusick break;
21165789Smckusick
21265789Smckusick default:
21365789Smckusick printf("RRIP with incorrect NM flags?\n");
21465789Smckusick wlen = ana->maxlen + 1;
21565789Smckusick break;
21665789Smckusick }
21765789Smckusick
21865789Smckusick if ((*ana->outlen += wlen) > ana->maxlen) {
21965789Smckusick /* treat as no name field */
22065789Smckusick ana->fields &= ~ISO_SUSP_ALTNAME;
22165789Smckusick ana->outbuf -= *ana->outlen - wlen;
22265789Smckusick *ana->outlen = 0;
22365789Smckusick return 0;
22465789Smckusick }
22565789Smckusick
22665789Smckusick bcopy(inbuf,ana->outbuf,wlen);
22765789Smckusick ana->outbuf += wlen;
22865789Smckusick
22965789Smckusick if (!cont) {
23065789Smckusick ana->fields &= ~ISO_SUSP_ALTNAME;
23165789Smckusick return ISO_SUSP_ALTNAME;
23265789Smckusick }
23365789Smckusick return 0;
23465789Smckusick }
23565789Smckusick
23665789Smckusick static void
cd9660_rrip_defname(isodir,ana)23765855Smckusick cd9660_rrip_defname(isodir,ana)
23865789Smckusick struct iso_directory_record *isodir;
23965789Smckusick ISO_RRIP_ANALYZE *ana;
24065789Smckusick {
24165789Smckusick strcpy(ana->outbuf,"..");
24265789Smckusick switch (*isodir->name) {
24365789Smckusick default:
24465789Smckusick isofntrans(isodir->name,isonum_711(isodir->name_len),
24565789Smckusick ana->outbuf,ana->outlen,
24665789Smckusick 1,isonum_711(isodir->flags)&4);
24765789Smckusick break;
24865789Smckusick case 0:
24965789Smckusick *ana->outlen = 1;
25065789Smckusick break;
25165789Smckusick case 1:
25265789Smckusick *ana->outlen = 2;
25365789Smckusick break;
25465789Smckusick }
25565789Smckusick }
25665789Smckusick
25765789Smckusick /*
25865789Smckusick * Parent or Child Link
25965789Smckusick */
26065789Smckusick static int
cd9660_rrip_pclink(p,ana)26165855Smckusick cd9660_rrip_pclink(p,ana)
26265789Smckusick ISO_RRIP_CLINK *p;
26365789Smckusick ISO_RRIP_ANALYZE *ana;
26465789Smckusick {
26565789Smckusick *ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift;
26665789Smckusick ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK);
26765789Smckusick return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK;
26865789Smckusick }
26965789Smckusick
27065789Smckusick /*
27165789Smckusick * Relocated directory
27265789Smckusick */
27365789Smckusick static int
cd9660_rrip_reldir(p,ana)27465855Smckusick cd9660_rrip_reldir(p,ana)
27565789Smckusick ISO_RRIP_RELDIR *p;
27665789Smckusick ISO_RRIP_ANALYZE *ana;
27765789Smckusick {
27865789Smckusick /* special hack to make caller aware of RE field */
27965789Smckusick *ana->outlen = 0;
28065789Smckusick ana->fields = 0;
28165789Smckusick return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
28265789Smckusick }
28365789Smckusick
28465789Smckusick static int
cd9660_rrip_tstamp(p,ana)28565855Smckusick cd9660_rrip_tstamp(p,ana)
28665789Smckusick ISO_RRIP_TSTAMP *p;
28765789Smckusick ISO_RRIP_ANALYZE *ana;
28865789Smckusick {
289*68049Smckusick u_char *ptime;
29065789Smckusick
29165789Smckusick ptime = p->time;
29265789Smckusick
29365789Smckusick /* Check a format of time stamp (7bytes/17bytes) */
29465789Smckusick if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) {
29565789Smckusick if (*p->flags&ISO_SUSP_TSTAMP_CREAT)
29665789Smckusick ptime += 7;
29765789Smckusick
29865789Smckusick if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) {
29965855Smckusick cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime);
30065789Smckusick ptime += 7;
30165789Smckusick } else
302*68049Smckusick bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec));
30365789Smckusick
30465789Smckusick if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
30565855Smckusick cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime);
30665789Smckusick ptime += 7;
30765789Smckusick } else
30865789Smckusick ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime;
30965789Smckusick
31065789Smckusick if (*p->flags&ISO_SUSP_TSTAMP_ATTR)
31165855Smckusick cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime);
31265789Smckusick else
31365789Smckusick ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime;
31465789Smckusick
31565789Smckusick } else {
31665789Smckusick if (*p->flags&ISO_SUSP_TSTAMP_CREAT)
31765789Smckusick ptime += 17;
31865789Smckusick
31965789Smckusick if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) {
32065855Smckusick cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime);
32165789Smckusick ptime += 17;
32265789Smckusick } else
323*68049Smckusick bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec));
32465789Smckusick
32565789Smckusick if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
32665855Smckusick cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime);
32765789Smckusick ptime += 17;
32865789Smckusick } else
32965789Smckusick ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime;
33065789Smckusick
33165789Smckusick if (*p->flags&ISO_SUSP_TSTAMP_ATTR)
33265855Smckusick cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime);
33365789Smckusick else
33465789Smckusick ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime;
33565789Smckusick
33665789Smckusick }
33765789Smckusick ana->fields &= ~ISO_SUSP_TSTAMP;
33865789Smckusick return ISO_SUSP_TSTAMP;
33965789Smckusick }
34065789Smckusick
34165789Smckusick static void
cd9660_rrip_deftstamp(isodir,ana)34265855Smckusick cd9660_rrip_deftstamp(isodir,ana)
34365789Smckusick struct iso_directory_record *isodir;
34465789Smckusick ISO_RRIP_ANALYZE *ana;
34565789Smckusick {
34665855Smckusick cd9660_deftstamp(isodir,ana->inop,NULL);
34765789Smckusick }
34865789Smckusick
34965789Smckusick /*
35065789Smckusick * POSIX device modes
35165789Smckusick */
35265789Smckusick static int
cd9660_rrip_device(p,ana)35365855Smckusick cd9660_rrip_device(p,ana)
35465789Smckusick ISO_RRIP_DEVICE *p;
35565789Smckusick ISO_RRIP_ANALYZE *ana;
35665789Smckusick {
357*68049Smckusick u_int high, low;
35865789Smckusick
359*68049Smckusick high = isonum_733(p->dev_t_high);
360*68049Smckusick low = isonum_733(p->dev_t_low);
36165789Smckusick
36267377Smkm if (high == 0)
36367377Smkm ana->inop->inode.iso_rdev = makedev(major(low), minor(low));
36467377Smkm else
36567377Smkm ana->inop->inode.iso_rdev = makedev(high, minor(low));
36665789Smckusick ana->fields &= ~ISO_SUSP_DEVICE;
36765789Smckusick return ISO_SUSP_DEVICE;
36865789Smckusick }
36965789Smckusick
37065789Smckusick /*
37165789Smckusick * Flag indicating
37265789Smckusick */
37365789Smckusick static int
cd9660_rrip_idflag(p,ana)37465855Smckusick 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)
38165855Smckusick return cd9660_rrip_reldir(p,ana);
38265789Smckusick
38365789Smckusick return ISO_SUSP_IDFLAG;
38465789Smckusick }
38565789Smckusick
38665789Smckusick /*
38765789Smckusick * Continuation pointer
38865789Smckusick */
38965789Smckusick static int
cd9660_rrip_cont(p,ana)39065855Smckusick 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
cd9660_rrip_stop(p,ana)40465855Smckusick cd9660_rrip_stop(p,ana)
40565789Smckusick ISO_SUSP_HEADER *p;
40665789Smckusick ISO_RRIP_ANALYZE *ana;
40765789Smckusick {
40865789Smckusick return ISO_SUSP_STOP;
40965789Smckusick }
41065789Smckusick
41165789Smckusick /*
41265789Smckusick * Extension reference
41365789Smckusick */
41465789Smckusick static int
cd9660_rrip_extref(p,ana)41565855Smckusick cd9660_rrip_extref(p,ana)
41665789Smckusick ISO_RRIP_EXTREF *p;
41765789Smckusick ISO_RRIP_ANALYZE *ana;
41865789Smckusick {
41965789Smckusick if (isonum_711(p->len_id) != 10
42065789Smckusick || bcmp((char *)p + 8,"RRIP_1991A",10)
42165789Smckusick || isonum_711(p->version) != 1)
42265789Smckusick return 0;
42365789Smckusick ana->fields &= ~ISO_SUSP_EXTREF;
42465789Smckusick return ISO_SUSP_EXTREF;
42565789Smckusick }
42665789Smckusick
42765789Smckusick typedef struct {
42865789Smckusick char type[2];
42965789Smckusick int (*func)();
43065789Smckusick void (*func2)();
43165789Smckusick int result;
43265789Smckusick } RRIP_TABLE;
43365789Smckusick
43465789Smckusick static int
cd9660_rrip_loop(isodir,ana,table)43565855Smckusick cd9660_rrip_loop(isodir,ana,table)
43665789Smckusick struct iso_directory_record *isodir;
43765789Smckusick ISO_RRIP_ANALYZE *ana;
43865789Smckusick RRIP_TABLE *table;
43965789Smckusick {
44065789Smckusick register RRIP_TABLE *ptable;
44165789Smckusick register ISO_SUSP_HEADER *phead;
44265789Smckusick register ISO_SUSP_HEADER *pend;
44365789Smckusick struct buf *bp = NULL;
44465789Smckusick int i;
44565789Smckusick char *pwhead;
44665789Smckusick int result;
44765789Smckusick
44865789Smckusick /*
44965789Smckusick * Note: If name length is odd,
45065789Smckusick * it will be padding 1 byte after the name
45165789Smckusick */
45265789Smckusick pwhead = isodir->name + isonum_711(isodir->name_len);
45365789Smckusick if (!(isonum_711(isodir->name_len)&1))
45465789Smckusick pwhead++;
45565789Smckusick
45665789Smckusick /* If it's not the '.' entry of the root dir obey SP field */
45765789Smckusick if (*isodir->name != 0
45865789Smckusick || isonum_733(isodir->extent) != ana->imp->root_extent)
45965789Smckusick pwhead += ana->imp->rr_skip;
46065789Smckusick else
46165789Smckusick pwhead += ana->imp->rr_skip0;
46265789Smckusick
46365789Smckusick phead = (ISO_SUSP_HEADER *)pwhead;
46465789Smckusick pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length));
46565789Smckusick
46665789Smckusick result = 0;
46765789Smckusick while (1) {
46865789Smckusick ana->iso_ce_len = 0;
46965789Smckusick /*
47065789Smckusick * Note: "pend" should be more than one SUSP header
47165789Smckusick */
47265789Smckusick while (pend >= phead + 1) {
47365789Smckusick if (isonum_711(phead->version) == 1) {
47465789Smckusick for (ptable = table; ptable->func; ptable++) {
47565789Smckusick if (*phead->type == *ptable->type
47665789Smckusick && phead->type[1] == ptable->type[1]) {
47765789Smckusick result |= ptable->func(phead,ana);
47865789Smckusick break;
47965789Smckusick }
48065789Smckusick }
48165789Smckusick if (!ana->fields)
48265789Smckusick break;
48365789Smckusick }
48467377Smkm if (result&ISO_SUSP_STOP) {
48567377Smkm result &= ~ISO_SUSP_STOP;
48667377Smkm break;
48767377Smkm }
48867377Smkm /* plausibility check */
48967377Smkm if (isonum_711(phead->length) < sizeof(*phead))
49067377Smkm break;
49165789Smckusick /*
49265789Smckusick * move to next SUSP
49365789Smckusick * Hopefully this works with newer versions, too
49465789Smckusick */
49565789Smckusick phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length));
49665789Smckusick }
49765789Smckusick
49867377Smkm if (ana->fields && ana->iso_ce_len) {
49965789Smckusick if (ana->iso_ce_blk >= ana->imp->volume_space_size
50065789Smckusick || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size
50165789Smckusick || bread(ana->imp->im_devvp,
502*68049Smckusick ana->iso_ce_blk <<
503*68049Smckusick (ana->imp->im_bshift - DEV_BSHIFT),
504*68049Smckusick ana->imp->logical_block_size, NOCRED, &bp))
50565789Smckusick /* what to do now? */
50665789Smckusick break;
507*68049Smckusick phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off);
50865789Smckusick pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len);
50965789Smckusick } else
51065789Smckusick break;
51165789Smckusick }
51265789Smckusick if (bp)
51365789Smckusick brelse(bp);
51465789Smckusick /*
51565789Smckusick * If we don't find the Basic SUSP stuffs, just set default value
51667377Smkm * (attribute/time stamp)
51765789Smckusick */
51865789Smckusick for (ptable = table; ptable->func2; ptable++)
51965789Smckusick if (!(ptable->result&result))
52065789Smckusick ptable->func2(isodir,ana);
52165789Smckusick
52265789Smckusick return result;
52365789Smckusick }
52465789Smckusick
52567377Smkm /*
52667377Smkm * Get Attributes.
52767377Smkm */
52865789Smckusick static RRIP_TABLE rrip_table_analyze[] = {
52965855Smckusick { "PX", cd9660_rrip_attr, cd9660_rrip_defattr, ISO_SUSP_ATTR },
53065855Smckusick { "TF", cd9660_rrip_tstamp, cd9660_rrip_deftstamp, ISO_SUSP_TSTAMP },
53165855Smckusick { "PN", cd9660_rrip_device, 0, ISO_SUSP_DEVICE },
53265855Smckusick { "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG },
53365855Smckusick { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT },
53465855Smckusick { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP },
53565789Smckusick { "", 0, 0, 0 }
53665789Smckusick };
53765789Smckusick
53865789Smckusick int
cd9660_rrip_analyze(isodir,inop,imp)53965855Smckusick cd9660_rrip_analyze(isodir,inop,imp)
54065789Smckusick struct iso_directory_record *isodir;
54165789Smckusick struct iso_node *inop;
54265789Smckusick struct iso_mnt *imp;
54365789Smckusick {
54465789Smckusick ISO_RRIP_ANALYZE analyze;
54565789Smckusick
54665789Smckusick analyze.inop = inop;
54765789Smckusick analyze.imp = imp;
54865789Smckusick analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE;
54965789Smckusick
55065855Smckusick return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze);
55165789Smckusick }
55265789Smckusick
55365789Smckusick /*
55467377Smkm * Get Alternate Name.
55565789Smckusick */
55665789Smckusick static RRIP_TABLE rrip_table_getname[] = {
55765855Smckusick { "NM", cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME },
55865855Smckusick { "CL", cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK },
55965855Smckusick { "PL", cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK },
56065855Smckusick { "RE", cd9660_rrip_reldir, 0, ISO_SUSP_RELDIR },
56165855Smckusick { "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG },
56265855Smckusick { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT },
56365855Smckusick { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP },
56465789Smckusick { "", 0, 0, 0 }
56565789Smckusick };
56665789Smckusick
56765789Smckusick int
cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)56865855Smckusick cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)
56965789Smckusick struct iso_directory_record *isodir;
57065789Smckusick char *outbuf;
57165789Smckusick u_short *outlen;
57265789Smckusick ino_t *inump;
57365789Smckusick struct iso_mnt *imp;
57465789Smckusick {
57565789Smckusick ISO_RRIP_ANALYZE analyze;
57665789Smckusick RRIP_TABLE *tab;
57765789Smckusick
57865789Smckusick analyze.outbuf = outbuf;
57965789Smckusick analyze.outlen = outlen;
58065789Smckusick analyze.maxlen = NAME_MAX;
58165789Smckusick analyze.inump = inump;
58265789Smckusick analyze.imp = imp;
58365789Smckusick analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
58465789Smckusick *outlen = 0;
58565789Smckusick
58665789Smckusick tab = rrip_table_getname;
58765789Smckusick if (*isodir->name == 0
58865789Smckusick || *isodir->name == 1) {
58965855Smckusick cd9660_rrip_defname(isodir,&analyze);
59065789Smckusick
59165789Smckusick analyze.fields &= ~ISO_SUSP_ALTNAME;
59265789Smckusick tab++;
59365789Smckusick }
59465789Smckusick
59565855Smckusick return cd9660_rrip_loop(isodir,&analyze,tab);
59665789Smckusick }
59765789Smckusick
59865789Smckusick /*
59967377Smkm * Get Symbolic Link.
60065789Smckusick */
60165789Smckusick static RRIP_TABLE rrip_table_getsymname[] = {
60265855Smckusick { "SL", cd9660_rrip_slink, 0, ISO_SUSP_SLINK },
60365855Smckusick { "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG },
60465855Smckusick { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT },
60565855Smckusick { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP },
60665789Smckusick { "", 0, 0, 0 }
60765789Smckusick };
60865789Smckusick
60965789Smckusick int
cd9660_rrip_getsymname(isodir,outbuf,outlen,imp)61065855Smckusick cd9660_rrip_getsymname(isodir,outbuf,outlen,imp)
61165789Smckusick struct iso_directory_record *isodir;
61265789Smckusick char *outbuf;
61365789Smckusick u_short *outlen;
61465789Smckusick struct iso_mnt *imp;
61565789Smckusick {
61665789Smckusick ISO_RRIP_ANALYZE analyze;
61765789Smckusick
61865789Smckusick analyze.outbuf = outbuf;
61967699Smckusick analyze.outlen = outlen;
62065789Smckusick *outlen = 0;
62165789Smckusick analyze.maxlen = MAXPATHLEN;
62265789Smckusick analyze.cont = 1; /* don't start with a slash */
62365789Smckusick analyze.imp = imp;
62465789Smckusick analyze.fields = ISO_SUSP_SLINK;
62565789Smckusick
62665855Smckusick return (cd9660_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK);
62765789Smckusick }
62865789Smckusick
62965789Smckusick static RRIP_TABLE rrip_table_extref[] = {
63065855Smckusick { "ER", cd9660_rrip_extref, 0, ISO_SUSP_EXTREF },
63165855Smckusick { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT },
63265855Smckusick { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP },
63365789Smckusick { "", 0, 0, 0 }
63465789Smckusick };
63565789Smckusick
63665789Smckusick /*
63765789Smckusick * Check for Rock Ridge Extension and return offset of its fields.
63867377Smkm * Note: We insist on the ER field.
63965789Smckusick */
64065789Smckusick int
cd9660_rrip_offset(isodir,imp)64165855Smckusick cd9660_rrip_offset(isodir,imp)
64265789Smckusick struct iso_directory_record *isodir;
64365789Smckusick struct iso_mnt *imp;
64465789Smckusick {
64565789Smckusick ISO_RRIP_OFFSET *p;
64665789Smckusick ISO_RRIP_ANALYZE analyze;
64765789Smckusick
64865789Smckusick imp->rr_skip0 = 0;
64965789Smckusick p = (ISO_RRIP_OFFSET *)(isodir->name + 1);
65065789Smckusick if (bcmp(p,"SP\7\1\276\357",6)) {
65165789Smckusick /* Maybe, it's a CDROM XA disc? */
65265789Smckusick imp->rr_skip0 = 15;
65365789Smckusick p = (ISO_RRIP_OFFSET *)((char *)p + 15);
65465789Smckusick if (bcmp(p,"SP\7\1\276\357",6))
65565789Smckusick return -1;
65665789Smckusick }
65765789Smckusick
65865789Smckusick analyze.imp = imp;
65965789Smckusick analyze.fields = ISO_SUSP_EXTREF;
66065855Smckusick if (!(cd9660_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF))
66165789Smckusick return -1;
66265789Smckusick
66365789Smckusick return isonum_711(p->skip);
66465789Smckusick }
665