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