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