1 /** $MirOS: src/sys/isofs/cd9660/cd9660_rrip.c,v 1.2 2008/11/01 00:21:32 tg Exp $ */
2 /* $OpenBSD: cd9660_rrip.c,v 1.8 2003/06/02 23:28:05 millert Exp $ */
3 /* $NetBSD: cd9660_rrip.c,v 1.17 1997/01/24 00:27:32 cgd Exp $ */
4
5 /*-
6 * Copyright (c) 1993, 1994
7 * The Regents of the University of California. All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley
10 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
11 * Support code is derived from software contributed to Berkeley
12 * by Atsushi Murai (amurai@spec.co.jp).
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)cd9660_rrip.c 8.6 (Berkeley) 12/5/94
39 */
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/namei.h>
44 #include <sys/buf.h>
45 #include <sys/file.h>
46 #include <sys/vnode.h>
47 #include <sys/mount.h>
48 #include <sys/kernel.h>
49 #include <sys/stat.h>
50 #include <sys/types.h>
51
52 #include <sys/time.h>
53
54 #include <isofs/cd9660/iso.h>
55 #include <isofs/cd9660/cd9660_extern.h>
56 #include <isofs/cd9660/cd9660_node.h>
57 #include <isofs/cd9660/cd9660_rrip.h>
58 #include <isofs/cd9660/iso_rrip.h>
59
60 typedef struct {
61 char type[2];
62 int (*func)(void *, ISO_RRIP_ANALYZE *);
63 void (*func2)(void *, ISO_RRIP_ANALYZE *);
64 int result;
65 } RRIP_TABLE;
66
67 static int cd9660_rrip_attr(void *, ISO_RRIP_ANALYZE *);
68 static void cd9660_rrip_defattr(void *, ISO_RRIP_ANALYZE *);
69 static int cd9660_rrip_slink(void *, ISO_RRIP_ANALYZE *);
70 static int cd9660_rrip_altname(void *, ISO_RRIP_ANALYZE *);
71 static void cd9660_rrip_defname(void *, ISO_RRIP_ANALYZE *);
72 static int cd9660_rrip_pclink(void *, ISO_RRIP_ANALYZE *);
73 static int cd9660_rrip_reldir(void *, ISO_RRIP_ANALYZE *);
74 static int cd9660_rrip_tstamp(void *, ISO_RRIP_ANALYZE *);
75 static void cd9660_rrip_deftstamp(void *, ISO_RRIP_ANALYZE *);
76 static int cd9660_rrip_device(void *, ISO_RRIP_ANALYZE *);
77 static int cd9660_rrip_idflag(void *, ISO_RRIP_ANALYZE *);
78 static int cd9660_rrip_cont(void *, ISO_RRIP_ANALYZE *);
79 static int cd9660_rrip_stop(void *, ISO_RRIP_ANALYZE *);
80 static int cd9660_rrip_extref(void *, ISO_RRIP_ANALYZE *);
81 static int cd9660_rrip_loop(struct iso_directory_record *,
82 ISO_RRIP_ANALYZE *, RRIP_TABLE *);
83 /*
84 * POSIX file attribute
85 */
86 static int
cd9660_rrip_attr(v,ana)87 cd9660_rrip_attr(v, ana)
88 void *v;
89 ISO_RRIP_ANALYZE *ana;
90 {
91 ISO_RRIP_ATTR *p = v;
92
93 ana->inop->inode.iso_mode = isonum_733(p->mode);
94 ana->inop->inode.iso_uid = isonum_733(p->uid);
95 ana->inop->inode.iso_gid = isonum_733(p->gid);
96 ana->inop->inode.iso_links = isonum_733(p->links);
97 ana->fields &= ~ISO_SUSP_ATTR;
98 return (ISO_SUSP_ATTR);
99 }
100
101 static void
cd9660_rrip_defattr(v,ana)102 cd9660_rrip_defattr(v, ana)
103 void *v;
104 ISO_RRIP_ANALYZE *ana;
105 {
106 struct iso_directory_record *isodir = v;
107
108 /* But this is a required field! */
109 printf("RRIP without PX field?\n");
110 cd9660_defattr(isodir, ana->inop, NULL);
111 }
112
113 /*
114 * Symbolic Links
115 */
116 static int
cd9660_rrip_slink(v,ana)117 cd9660_rrip_slink(v, ana)
118 void *v;
119 ISO_RRIP_ANALYZE *ana;
120 {
121 ISO_RRIP_SLINK *p = v;
122 register ISO_RRIP_SLINK_COMPONENT *pcomp;
123 register ISO_RRIP_SLINK_COMPONENT *pcompe;
124 int len, wlen, cont;
125 char *outbuf, *inbuf;
126
127 pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component;
128 pcompe =
129 (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length));
130 len = *ana->outlen;
131 outbuf = ana->outbuf;
132 cont = ana->cont;
133
134 /*
135 * Gathering a Symbolic name from each component with path
136 */
137 for (; pcomp < pcompe;
138 pcomp = (ISO_RRIP_SLINK_COMPONENT *)
139 ((char *)pcomp + ISO_RRIP_SLSIZ + isonum_711(pcomp->clen))) {
140
141 if (!cont) {
142 if (len < ana->maxlen) {
143 len++;
144 *outbuf++ = '/';
145 }
146 }
147 cont = 0;
148
149 inbuf = "..";
150 wlen = 0;
151
152 switch (*pcomp->cflag) {
153
154 case ISO_SUSP_CFLAG_CURRENT:
155 /* Inserting Current */
156 wlen = 1;
157 break;
158
159 case ISO_SUSP_CFLAG_PARENT:
160 /* Inserting Parent */
161 wlen = 2;
162 break;
163
164 case ISO_SUSP_CFLAG_ROOT:
165 /* Inserting slash for ROOT */
166 /* start over from beginning(?) */
167 outbuf -= len;
168 len = 0;
169 break;
170
171 case ISO_SUSP_CFLAG_VOLROOT:
172 /* Inserting a mount point i.e. "/cdrom" */
173 /* same as above */
174 outbuf -= len;
175 len = 0;
176 inbuf = ana->imp->im_mountp->mnt_stat.f_mntonname;
177 wlen = strlen(inbuf);
178 break;
179
180 case ISO_SUSP_CFLAG_HOST:
181 /* Inserting hostname i.e. "kurt.tools.de" */
182 inbuf = hostname;
183 wlen = hostnamelen;
184 break;
185
186 case ISO_SUSP_CFLAG_CONTINUE:
187 cont = 1;
188 /* fall thru */
189 case 0:
190 /* Inserting component */
191 wlen = isonum_711(pcomp->clen);
192 inbuf = pcomp->name;
193 break;
194 default:
195 printf("RRIP with incorrect flags?");
196 wlen = ana->maxlen + 1;
197 break;
198 }
199
200 if (len + wlen > ana->maxlen) {
201 /* indicate error to caller */
202 ana->cont = 1;
203 ana->fields = 0;
204 ana->outbuf -= *ana->outlen;
205 *ana->outlen = 0;
206 return (0);
207 }
208
209 bcopy(inbuf, outbuf, wlen);
210 outbuf += wlen;
211 len += wlen;
212 }
213 ana->outbuf = outbuf;
214 *ana->outlen = len;
215 ana->cont = cont;
216
217 if (!isonum_711(p->flags)) {
218 ana->fields &= ~ISO_SUSP_SLINK;
219 return (ISO_SUSP_SLINK);
220 }
221 return (0);
222 }
223
224 /*
225 * Alternate name
226 */
227 static int
cd9660_rrip_altname(v,ana)228 cd9660_rrip_altname(v, ana)
229 void *v;
230 ISO_RRIP_ANALYZE *ana;
231 {
232 ISO_RRIP_ALTNAME *p = v;
233 char *inbuf;
234 int wlen;
235 int cont;
236
237 inbuf = "..";
238 wlen = 0;
239 cont = 0;
240
241 switch (*p->flags) {
242 case ISO_SUSP_CFLAG_CURRENT:
243 /* Inserting Current */
244 wlen = 1;
245 break;
246
247 case ISO_SUSP_CFLAG_PARENT:
248 /* Inserting Parent */
249 wlen = 2;
250 break;
251
252 case ISO_SUSP_CFLAG_HOST:
253 /* Inserting hostname i.e. "kurt.tools.de" */
254 inbuf = hostname;
255 wlen = hostnamelen;
256 break;
257
258 case ISO_SUSP_CFLAG_CONTINUE:
259 cont = 1;
260 /* fall thru */
261 case 0:
262 /* Inserting component */
263 wlen = isonum_711(p->h.length) - 5;
264 inbuf = (char *)p + 5;
265 break;
266
267 default:
268 printf("RRIP with incorrect NM flags?\n");
269 wlen = ana->maxlen + 1;
270 break;
271 }
272
273 if ((*ana->outlen += wlen) > ana->maxlen) {
274 /* treat as no name field */
275 ana->fields &= ~ISO_SUSP_ALTNAME;
276 ana->outbuf -= *ana->outlen - wlen;
277 *ana->outlen = 0;
278 return (0);
279 }
280
281 bcopy(inbuf, ana->outbuf, wlen);
282 ana->outbuf += wlen;
283
284 if (!cont) {
285 ana->fields &= ~ISO_SUSP_ALTNAME;
286 return (ISO_SUSP_ALTNAME);
287 }
288 return (0);
289 }
290
291 static void
cd9660_rrip_defname(v,ana)292 cd9660_rrip_defname(v, ana)
293 void *v;
294 ISO_RRIP_ANALYZE *ana;
295 {
296 struct iso_directory_record *isodir = v;
297
298 strlcpy(ana->outbuf, "..", ana->maxlen - *ana->outlen);
299 switch (*isodir->name) {
300 default:
301 isofntrans(isodir->name, isonum_711(isodir->name_len),
302 ana->outbuf, ana->outlen, 1,
303 isonum_711(isodir->flags) & 4, ana->imp->joliet_level);
304 break;
305 case 0:
306 *ana->outlen = 1;
307 break;
308 case 1:
309 *ana->outlen = 2;
310 break;
311 }
312 }
313
314 /*
315 * Parent or Child Link
316 */
317 static int
cd9660_rrip_pclink(v,ana)318 cd9660_rrip_pclink(v, ana)
319 void *v;
320 ISO_RRIP_ANALYZE *ana;
321 {
322 ISO_RRIP_CLINK *p = v;
323
324 *ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift;
325 ana->fields &= ~(ISO_SUSP_CLINK | ISO_SUSP_PLINK);
326 return (*p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK);
327 }
328
329 /*
330 * Relocated directory
331 */
332 /*ARGSUSED*/
333 static int
cd9660_rrip_reldir(v,ana)334 cd9660_rrip_reldir(v, ana)
335 void *v;
336 ISO_RRIP_ANALYZE *ana;
337 {
338 /* special hack to make caller aware of RE field */
339 *ana->outlen = 0;
340 ana->fields = 0;
341 return (ISO_SUSP_RELDIR | ISO_SUSP_ALTNAME | ISO_SUSP_CLINK |
342 ISO_SUSP_PLINK);
343 }
344
345 static int
cd9660_rrip_tstamp(v,ana)346 cd9660_rrip_tstamp(v, ana)
347 void *v;
348 ISO_RRIP_ANALYZE *ana;
349 {
350 ISO_RRIP_TSTAMP *p = v;
351 u_char *ptime;
352
353 ptime = p->time;
354
355 /* Check a format of time stamp (7bytes/17bytes) */
356 if (!(*p->flags & ISO_SUSP_TSTAMP_FORM17)) {
357 if (*p->flags & ISO_SUSP_TSTAMP_CREAT)
358 ptime += 7;
359
360 if (*p->flags & ISO_SUSP_TSTAMP_MODIFY) {
361 cd9660_tstamp_conv7(ptime,
362 &ana->inop->inode.iso_mtime);
363 ptime += 7;
364 } else
365 bzero(&ana->inop->inode.iso_mtime,
366 sizeof(struct timespec));
367
368 if (*p->flags & ISO_SUSP_TSTAMP_ACCESS) {
369 cd9660_tstamp_conv7(ptime,
370 &ana->inop->inode.iso_atime);
371 ptime += 7;
372 } else
373 ana->inop->inode.iso_atime =
374 ana->inop->inode.iso_mtime;
375
376 if (*p->flags & ISO_SUSP_TSTAMP_ATTR)
377 cd9660_tstamp_conv7(ptime,
378 &ana->inop->inode.iso_ctime);
379 else
380 ana->inop->inode.iso_ctime =
381 ana->inop->inode.iso_mtime;
382
383 } else {
384 if (*p->flags & ISO_SUSP_TSTAMP_CREAT)
385 ptime += 17;
386
387 if (*p->flags & ISO_SUSP_TSTAMP_MODIFY) {
388 cd9660_tstamp_conv17(ptime,
389 &ana->inop->inode.iso_mtime);
390 ptime += 17;
391 } else
392 bzero(&ana->inop->inode.iso_mtime,
393 sizeof(struct timespec));
394
395 if (*p->flags & ISO_SUSP_TSTAMP_ACCESS) {
396 cd9660_tstamp_conv17(ptime,
397 &ana->inop->inode.iso_atime);
398 ptime += 17;
399 } else
400 ana->inop->inode.iso_atime =
401 ana->inop->inode.iso_mtime;
402
403 if (*p->flags & ISO_SUSP_TSTAMP_ATTR)
404 cd9660_tstamp_conv17(ptime,
405 &ana->inop->inode.iso_ctime);
406 else
407 ana->inop->inode.iso_ctime =
408 ana->inop->inode.iso_mtime;
409
410 }
411 ana->fields &= ~ISO_SUSP_TSTAMP;
412 return (ISO_SUSP_TSTAMP);
413 }
414
415 static void
cd9660_rrip_deftstamp(v,ana)416 cd9660_rrip_deftstamp(v, ana)
417 void *v;
418 ISO_RRIP_ANALYZE *ana;
419 {
420 struct iso_directory_record *isodir = v;
421
422 cd9660_deftstamp(isodir, ana->inop, NULL);
423 }
424
425 /*
426 * POSIX device modes
427 */
428 static int
cd9660_rrip_device(v,ana)429 cd9660_rrip_device(v, ana)
430 void *v;
431 ISO_RRIP_ANALYZE *ana;
432 {
433 ISO_RRIP_DEVICE *p = v;
434 u_int high, low;
435 uint64_t tdev;
436
437 high = isonum_733(p->dev_t_high);
438 low = isonum_733(p->dev_t_low);
439
440 tdev = (uint32_t)high;
441 tdev <<= 32;
442 tdev |= (uint32_t)low;
443 ana->inop->inode.iso_rdev = (dev_t)tdev;
444
445 ana->fields &= ~ISO_SUSP_DEVICE;
446 return (ISO_SUSP_DEVICE);
447 }
448
449 /*
450 * Flag indicating
451 */
452 static int
cd9660_rrip_idflag(v,ana)453 cd9660_rrip_idflag(v, ana)
454 void *v;
455 ISO_RRIP_ANALYZE *ana;
456 {
457 ISO_RRIP_IDFLAG *p = v;
458
459 /* don't touch high bits */
460 ana->fields &= isonum_711(p->flags) | ~0xff;
461 /* special handling of RE field */
462 if (ana->fields & ISO_SUSP_RELDIR)
463 return (cd9660_rrip_reldir(p, ana));
464
465 return (ISO_SUSP_IDFLAG);
466 }
467
468 /*
469 * Continuation pointer
470 */
471 static int
cd9660_rrip_cont(v,ana)472 cd9660_rrip_cont(v, ana)
473 void *v;
474 ISO_RRIP_ANALYZE *ana;
475 {
476 ISO_RRIP_CONT *p = v;
477
478 ana->iso_ce_blk = isonum_733(p->location);
479 ana->iso_ce_off = isonum_733(p->offset);
480 ana->iso_ce_len = isonum_733(p->length);
481 return (ISO_SUSP_CONT);
482 }
483
484 /*
485 * System Use end
486 */
487 static int
cd9660_rrip_stop(v,ana)488 cd9660_rrip_stop(v, ana)
489 void *v;
490 ISO_RRIP_ANALYZE *ana;
491 {
492 return (ISO_SUSP_STOP);
493 }
494
495 /*
496 * Extension reference
497 */
498 static int
cd9660_rrip_extref(v,ana)499 cd9660_rrip_extref(v, ana)
500 void *v;
501 ISO_RRIP_ANALYZE *ana;
502 {
503 ISO_RRIP_EXTREF *p = v;
504
505 if (isonum_711(p->version) != 1)
506 return (0);
507 if (isonum_711(p->len_id) != 9 &&
508 isonum_711(p->len_id) != 10)
509 return (0);
510 if (isonum_711(p->len_id) == 9 &&
511 bcmp((char *)p + 8, "IEEE_1282", 9))
512 return (0);
513 if (isonum_711(p->len_id) == 10 &&
514 bcmp((char *)p + 8, "IEEE_P1282", 10) &&
515 bcmp((char *)p + 8, "RRIP_1991A", 10))
516 return (0);
517 ana->fields &= ~ISO_SUSP_EXTREF;
518 return (ISO_SUSP_EXTREF);
519 }
520
521
522 static int
cd9660_rrip_loop(isodir,ana,table)523 cd9660_rrip_loop(isodir, ana, table)
524 struct iso_directory_record *isodir;
525 ISO_RRIP_ANALYZE *ana;
526 RRIP_TABLE *table;
527 {
528 register RRIP_TABLE *ptable;
529 register ISO_SUSP_HEADER *phead;
530 register ISO_SUSP_HEADER *pend;
531 struct buf *bp = NULL;
532 char *pwhead;
533 u_char c;
534 int result;
535
536 /*
537 * Note: If name length is odd,
538 * it will be padded by 1 byte after the name
539 */
540 pwhead = isodir->name + isonum_711(isodir->name_len);
541 if (!(isonum_711(isodir->name_len) & 1))
542 pwhead++;
543 isochar(isodir->name, pwhead, ana->imp->joliet_level, &c);
544
545 /* If it's not the '.' entry of the root dir obey SP field */
546 if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent)
547 pwhead += ana->imp->rr_skip;
548 else
549 pwhead += ana->imp->rr_skip0;
550
551 phead = (ISO_SUSP_HEADER *)pwhead;
552 pend =
553 (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length));
554
555 result = 0;
556 while (1) {
557 ana->iso_ce_len = 0;
558 /*
559 * Note: "pend" should be more than one SUSP header
560 */
561 while (pend >= phead + 1) {
562 if (isonum_711(phead->version) == 1) {
563 for (ptable = table; ptable->func; ptable++) {
564 if (*phead->type == *ptable->type &&
565 phead->type[1] == ptable->type[1])
566 {
567 result |=
568 ptable->func(phead, ana);
569 break;
570 }
571 }
572 if (!ana->fields)
573 break;
574 }
575 if (result & ISO_SUSP_STOP) {
576 result &= ~ISO_SUSP_STOP;
577 break;
578 }
579 /* plausibility check */
580 if (isonum_711(phead->length) < sizeof(*phead))
581 break;
582 /*
583 * move to next SUSP
584 * Hopefully this works with newer versions, too
585 */
586 phead = (ISO_SUSP_HEADER *)
587 ((char *)phead + isonum_711(phead->length));
588 }
589
590 if (ana->fields && ana->iso_ce_len) {
591 if (ana->iso_ce_blk >= ana->imp->volume_space_size ||
592 ana->iso_ce_off + ana->iso_ce_len >
593 ana->imp->logical_block_size ||
594 bread(ana->imp->im_devvp, ana->iso_ce_blk <<
595 (ana->imp->im_bshift - DEV_BSHIFT),
596 ana->imp->logical_block_size, NOCRED, &bp))
597 /* what to do now? */
598 break;
599 phead =
600 (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off);
601 pend = (ISO_SUSP_HEADER *)
602 ((char *)phead + ana->iso_ce_len);
603 } else
604 break;
605 }
606 if (bp)
607 brelse(bp);
608 /*
609 * If we don't find the Basic SUSP stuffs, just set default value
610 * (attribute/time stamp)
611 */
612 for (ptable = table; ptable->func2; ptable++)
613 if (!(ptable->result & result))
614 ptable->func2(isodir, ana);
615
616 return (result);
617 }
618
619 /*
620 * Get Attributes.
621 */
622 static RRIP_TABLE rrip_table_analyze[] = {
623 { "PX", cd9660_rrip_attr, cd9660_rrip_defattr,
624 ISO_SUSP_ATTR },
625 { "TF", cd9660_rrip_tstamp, cd9660_rrip_deftstamp,
626 ISO_SUSP_TSTAMP },
627 { "PN", cd9660_rrip_device, 0,
628 ISO_SUSP_DEVICE },
629 { "RR", cd9660_rrip_idflag, 0,
630 ISO_SUSP_IDFLAG },
631 { "CE", cd9660_rrip_cont, 0,
632 ISO_SUSP_CONT },
633 { "ST", cd9660_rrip_stop, 0,
634 ISO_SUSP_STOP },
635 { "", 0, 0,
636 0 }
637 };
638
639 int
cd9660_rrip_analyze(isodir,inop,imp)640 cd9660_rrip_analyze(isodir, inop, imp)
641 struct iso_directory_record *isodir;
642 struct iso_node *inop;
643 struct iso_mnt *imp;
644 {
645 ISO_RRIP_ANALYZE analyze;
646
647 analyze.inop = inop;
648 analyze.imp = imp;
649 analyze.fields = ISO_SUSP_ATTR | ISO_SUSP_TSTAMP | ISO_SUSP_DEVICE;
650
651 return (cd9660_rrip_loop(isodir, &analyze, rrip_table_analyze));
652 }
653
654 /*
655 * Get Alternate Name.
656 */
657 static RRIP_TABLE rrip_table_getname[] = {
658 { "NM", cd9660_rrip_altname, cd9660_rrip_defname,
659 ISO_SUSP_ALTNAME },
660 { "CL", cd9660_rrip_pclink, 0,
661 ISO_SUSP_CLINK|ISO_SUSP_PLINK },
662 { "PL", cd9660_rrip_pclink, 0,
663 ISO_SUSP_CLINK|ISO_SUSP_PLINK },
664 { "RE", cd9660_rrip_reldir, 0,
665 ISO_SUSP_RELDIR },
666 { "RR", cd9660_rrip_idflag, 0,
667 ISO_SUSP_IDFLAG },
668 { "CE", cd9660_rrip_cont, 0,
669 ISO_SUSP_CONT },
670 { "ST", cd9660_rrip_stop, 0,
671 ISO_SUSP_STOP },
672 { "", 0, 0,
673 0 }
674 };
675
676 int
cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)677 cd9660_rrip_getname(isodir, outbuf, outlen, inump, imp)
678 struct iso_directory_record *isodir;
679 char *outbuf;
680 u_short *outlen;
681 ino_t *inump;
682 struct iso_mnt *imp;
683 {
684 ISO_RRIP_ANALYZE analyze;
685 RRIP_TABLE *tab;
686 u_char c;
687
688 analyze.outbuf = outbuf;
689 analyze.outlen = outlen;
690 analyze.maxlen = NAME_MAX;
691 analyze.inump = inump;
692 analyze.imp = imp;
693 analyze.fields = ISO_SUSP_ALTNAME | ISO_SUSP_RELDIR | ISO_SUSP_CLINK |
694 ISO_SUSP_PLINK;
695 *outlen = 0;
696
697 isochar(isodir->name, isodir->name + isonum_711(isodir->name_len),
698 imp->joliet_level, &c);
699 tab = rrip_table_getname;
700 if (c == 0 || c == 1) {
701 cd9660_rrip_defname(isodir, &analyze);
702
703 analyze.fields &= ~ISO_SUSP_ALTNAME;
704 tab++;
705 }
706
707 return (cd9660_rrip_loop(isodir, &analyze, tab));
708 }
709
710 /*
711 * Get Symbolic Link.
712 */
713 static RRIP_TABLE rrip_table_getsymname[] = {
714 { "SL", cd9660_rrip_slink, 0, ISO_SUSP_SLINK },
715 { "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG },
716 { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT },
717 { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP },
718 { "", 0, 0, 0 }
719 };
720
721 int
cd9660_rrip_getsymname(isodir,outbuf,outlen,imp)722 cd9660_rrip_getsymname(isodir, outbuf, outlen, imp)
723 struct iso_directory_record *isodir;
724 char *outbuf;
725 u_short *outlen;
726 struct iso_mnt *imp;
727 {
728 ISO_RRIP_ANALYZE analyze;
729
730 analyze.outbuf = outbuf;
731 analyze.outlen = outlen;
732 *outlen = 0;
733 analyze.maxlen = MAXPATHLEN;
734 analyze.cont = 1; /* don't start with a slash */
735 analyze.imp = imp;
736 analyze.fields = ISO_SUSP_SLINK;
737
738 return (cd9660_rrip_loop(isodir, &analyze, rrip_table_getsymname) &
739 ISO_SUSP_SLINK);
740 }
741
742 static RRIP_TABLE rrip_table_extref[] = {
743 { "ER", cd9660_rrip_extref, 0, ISO_SUSP_EXTREF },
744 { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT },
745 { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP },
746 { "", 0, 0, 0 }
747 };
748
749 /*
750 * Check for Rock Ridge Extension and return offset of its fields.
751 * Note: We insist on the ER field.
752 */
753 int
cd9660_rrip_offset(isodir,imp)754 cd9660_rrip_offset(isodir, imp)
755 struct iso_directory_record *isodir;
756 struct iso_mnt *imp;
757 {
758 ISO_RRIP_OFFSET *p;
759 ISO_RRIP_ANALYZE analyze;
760
761 imp->rr_skip0 = 0;
762 p = (ISO_RRIP_OFFSET *)(isodir->name + 1);
763 if (bcmp(p, "SP\7\1\276\357", 6)) {
764 /* Maybe, it's a CDROM XA disc? */
765 imp->rr_skip0 = 15;
766 p = (ISO_RRIP_OFFSET *)((char *)p + 15);
767 if (bcmp(p, "SP\7\1\276\357", 6))
768 return (-1);
769 }
770
771 analyze.imp = imp;
772 analyze.fields = ISO_SUSP_EXTREF;
773 if (!(cd9660_rrip_loop(isodir, &analyze, rrip_table_extref) &
774 ISO_SUSP_EXTREF))
775 return (-1);
776
777 return (isonum_711(p->skip));
778 }
779