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