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