iso9660_rrip.c revision 1.1 1 /* $NetBSD: iso9660_rrip.c,v 1.1 2005/08/13 01:53:01 fvdl Exp $ */
2
3 /*
4 * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
5 * Perez-Rathke and Ram Vedam. All rights reserved.
6 *
7 * This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
8 * Alan Perez-Rathke and Ram Vedam.
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions 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
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN
21 * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN
25 * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 * USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 * OF SUCH DAMAGE.
33 */
34 /* This will hold all the function definitions
35 * defined in iso9660_rrip.h
36 */
37
38 #include "makefs.h"
39 #include "cd9660.h"
40 #include "iso9660_rrip.h"
41 #include <sys/queue.h>
42 #include <stdio.h>
43
44 #include <sys/cdefs.h>
45 #if defined(__RCSID) && !defined(__lint)
46 __RCSID("$NetBSD: iso9660_rrip.c,v 1.1 2005/08/13 01:53:01 fvdl Exp $");
47 #endif /* !__lint */
48
49 static int cd9660_susp_handle_continuation(cd9660node *);
50 static int cd9660_susp_handle_continuation_common(cd9660node *, int);
51 static struct ISO_SUSP_ATTRIBUTES *cd9660_get_last_attribute(cd9660node *);
52
53 int
54 cd9660_susp_initialize(cd9660node *node)
55 {
56 cd9660node *temp;
57 int r;
58
59 temp = node;
60
61 /* Make sure the node is not NULL. If it is, there are major problems */
62 assert(node != NULL);
63
64 while (temp != NULL) {
65 if (!(temp->type & CD9660_TYPE_DOT) &&
66 !(temp->type & CD9660_TYPE_DOTDOT))
67 LIST_INIT(&(temp->head));
68 if (temp->dot_record != 0)
69 LIST_INIT(&(temp->dot_record->head));
70 if (temp->dot_dot_record != 0)
71 LIST_INIT(&(temp->dot_dot_record->head));
72
73 /* SUSP specific entries here */
74 if ((r = cd9660_susp_initialize_node(temp)) < 0)
75 return r;
76
77 /* currently called cd9660node_rrip_init_links */
78 if ((r = cd9660_rrip_initialize_node(temp)) < 0)
79 return r;
80
81 /*
82 * See if we need a CE record, and set all of the
83 * associated counters.
84 *
85 * This should be called after all extensions. After
86 * this is called, no new records should be added.
87 */
88 if ((r = cd9660_susp_handle_continuation(temp)) < 0)
89 return r;
90
91 /* Recurse on child entries */
92 if (temp->child != NULL) {
93 if ((r = cd9660_susp_initialize(temp->child)) < 0)
94 return 0;
95 }
96 temp = temp->next;
97 }
98 return 1;
99 }
100
101 int
102 cd9660_susp_finalize(cd9660node *node)
103 {
104 cd9660node *temp;
105 int r;
106
107 assert(node != NULL);
108
109 if (node == diskStructure.rootNode)
110 diskStructure.susp_continuation_area_current_free = 0;
111
112 temp = node;
113 while (temp != NULL) {
114
115 if ((r = cd9660_susp_finalize_node(temp)) < 0)
116 return r;
117 if ((r = cd9660_rrip_finalize_node(temp)) < 0)
118 return r;
119
120 if (temp->child != NULL) {
121 if ((r = cd9660_susp_finalize(temp->child)) < 0)
122 return r;
123 }
124 temp = temp->next;
125 }
126 return 1;
127 }
128
129 /*
130 * If we really wanted to speed things up, we could have some sort of
131 * lookup table on the SUSP entry type that calls a functor. Or, we could
132 * combine the functions. These functions are kept separate to allow
133 * easier addition of other extensions.
134
135 * For the sake of simplicity and clarity, we won't be doing that for now.
136 */
137
138 /*
139 * SUSP needs to update the following types:
140 * CE (continuation area)
141 */
142 int
143 cd9660_susp_finalize_node(cd9660node *node)
144 {
145 struct ISO_SUSP_ATTRIBUTES *t;
146
147 /* Handle CE counters */
148 if (node->susp_entry_ce_length > 0) {
149 node->susp_entry_ce_start =
150 diskStructure.susp_continuation_area_current_free;
151 diskStructure.susp_continuation_area_current_free +=
152 node->susp_entry_ce_length;
153 }
154
155 for (t = node->head.lh_first; t != NULL; t = t->rr_ll.le_next) {
156 if (t->susp_type == SUSP_TYPE_SUSP &&
157 t->entry_type == SUSP_ENTRY_SUSP_CE) {
158 cd9660_bothendian_dword(
159 diskStructure.
160 susp_continuation_area_start_sector,
161 t->attr.su_entry.CE.ca_sector);
162
163 cd9660_bothendian_dword(
164 diskStructure.
165 susp_continuation_area_start_sector,
166 t->attr.su_entry.CE.ca_sector);
167 cd9660_bothendian_dword(node->susp_entry_ce_start,
168 t->attr.su_entry.CE.offset);
169 cd9660_bothendian_dword(node->susp_entry_ce_length,
170 t->attr.su_entry.CE.length);
171 }
172 }
173
174 return 0;
175 }
176
177 int
178 cd9660_rrip_finalize_node(cd9660node *node)
179 {
180 struct ISO_SUSP_ATTRIBUTES *t;
181
182 for (t = node->head.lh_first; t != NULL; t = t->rr_ll.le_next) {
183 if (t->susp_type == SUSP_TYPE_RRIP) {
184 switch (t->entry_type) {
185 case SUSP_ENTRY_RRIP_CL:
186 /* Look at rr_relocated*/
187 if (node->rr_relocated == NULL)
188 return -1;
189 cd9660_bothendian_dword(
190 node->rr_relocated->fileDataSector,
191 (unsigned char *)
192 t->attr.rr_entry.CL.dir_loc);
193 break;
194 case SUSP_ENTRY_RRIP_PL:
195 /* Look at rr_real_parent */
196 if (node->rr_real_parent == NULL)
197 return -1;
198 cd9660_bothendian_dword(
199 node->rr_real_parent->fileDataSector,
200 (unsigned char *)
201 t->attr.rr_entry.PL.dir_loc);
202 break;
203 }
204 }
205 }
206 return 0;
207 }
208
209 static int
210 cd9660_susp_handle_continuation_common(cd9660node *node, int space)
211 {
212 int working;
213 struct ISO_SUSP_ATTRIBUTES *temp, *last = NULL, *CE;
214 int susp_used, ca_used;
215
216 working = 254 - space;
217 /* printf("There are %i bytes to work with\n",working); */
218
219 susp_used = 0;
220 ca_used = 0;
221 for (temp = node->head.lh_first; (temp != NULL) && (working >= 0);
222 temp = temp->rr_ll.le_next) {
223 /*
224 * printf("SUSP Entry found, length is %i\n",
225 * CD9660_SUSP_ENTRY_SIZE(temp));
226 */
227 working -= CD9660_SUSP_ENTRY_SIZE(temp);
228 if (working >= 28) {
229 last = temp;
230 susp_used += CD9660_SUSP_ENTRY_SIZE(temp);
231 }
232 }
233
234 /* A CE entry is needed */
235 if (working <= 0) {
236 CE = cd9660node_susp_create_node(SUSP_TYPE_SUSP,
237 SUSP_ENTRY_SUSP_CE, "CE", SUSP_LOC_ENTRY);
238 cd9660_susp_ce(CE, node);
239 /* This will automatically insert at the appropriate location */
240 cd9660node_susp_add_entry(node, last, CE, 0);
241 susp_used += 28;
242
243 /* Count how much CA data is necessary */
244 for (temp = CE->rr_ll.le_next; temp != NULL;
245 temp = temp->rr_ll.le_next) {
246 ca_used += CD9660_SUSP_ENTRY_SIZE(temp);
247 }
248 }
249
250 node->susp_entry_size = susp_used;
251 node->susp_entry_ce_length = ca_used;
252
253 diskStructure.susp_continuation_area_size += ca_used;
254 return 1;
255 }
256
257 /* See if a continuation entry is needed for each of the different types */
258 static int
259 cd9660_susp_handle_continuation(cd9660node *node)
260 {
261 assert (node != NULL);
262
263 /* Entry */
264 if (cd9660_susp_handle_continuation_common(
265 node,(int)(node->isoDirRecord->length[0])) < 0)
266 return 0;
267
268 return 1;
269 }
270
271 struct ISO_SUSP_ATTRIBUTES*
272 cd9660node_susp_add_entry(cd9660node *node, struct ISO_SUSP_ATTRIBUTES *prev,
273 struct ISO_SUSP_ATTRIBUTES *current, int at_head)
274 {
275 if (at_head || prev == NULL)
276 LIST_INSERT_HEAD(&(node->head), current, rr_ll);
277 else {
278 LIST_INSERT_AFTER(prev, current, rr_ll);
279 prev = current;
280 }
281
282 return current;
283 }
284
285 int
286 cd9660_susp_initialize_node(cd9660node *node)
287 {
288 struct ISO_SUSP_ATTRIBUTES *temp;
289
290 /*
291 * Requirements/notes:
292 * CE: is added for us where needed
293 * ST: not sure if it is even required, but if so, should be
294 * handled by the CE code
295 * PD: isnt needed (though might be added for testing)
296 * SP: is stored ONLY on the . record of the root directory
297 * ES: not sure
298 */
299
300 /* Check for root directory, add SP and ER if needed. */
301 if (node->type & CD9660_TYPE_DOT) {
302 if (node->parent == diskStructure.rootNode) {
303 temp = cd9660node_susp_create_node(SUSP_TYPE_SUSP,
304 SUSP_ENTRY_SUSP_SP, "SP", SUSP_LOC_DOT);
305 cd9660_susp_sp(temp, node);
306
307 /* Should be first entry. */
308 temp = cd9660node_susp_add_entry(node, NULL, temp, 1);
309 }
310 }
311 return 1;
312 }
313
314 /*
315 * XXXfvdl use a TAILQ.
316 */
317 static struct ISO_SUSP_ATTRIBUTES *
318 cd9660_get_last_attribute(cd9660node *node)
319 {
320 struct ISO_SUSP_ATTRIBUTES *t;
321
322 assert(node != NULL);
323
324 t = node->head.lh_first;
325 if (t == NULL)
326 return NULL;
327 if (t->rr_ll.le_next == NULL)
328 return t;
329 for (; t->rr_ll.le_next != NULL; t = t->rr_ll.le_next) ;
330 return t;
331 }
332
333 int
334 cd9660_rrip_initialize_node(cd9660node *node)
335 {
336 struct ISO_SUSP_ATTRIBUTES *current = NULL;
337 struct ISO_SUSP_ATTRIBUTES *prev = NULL;
338
339 assert(node != NULL);
340
341 if (node->type & CD9660_TYPE_DOT) {
342 /*
343 * Handle ER - should be the only entry to appear on
344 * a "." record
345 */
346 if (node->parent == diskStructure.rootNode) {
347 cd9660_susp_ER (cd9660_get_last_attribute(node),
348 node, 1, SUSP_RRIP_ER_EXT_ID,
349 SUSP_RRIP_ER_EXT_DES, SUSP_RRIP_ER_EXT_SRC);
350 }
351 } else if (node->type & CD9660_TYPE_DOTDOT) {
352
353 } else {
354 if (node != NULL)
355 prev = cd9660_get_last_attribute(node);
356 /*
357 * Inode dependent values - this may change,
358 * but for now virtual files and directories do
359 * not have an inode structure
360 */
361
362 if ((node->node != NULL) && (node->node->inode != NULL)) {
363 /* PX - POSIX attributes */
364 current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
365 SUSP_ENTRY_RRIP_PX, "PX", SUSP_LOC_ENTRY);
366 cd9660node_rrip_px(current, node->node);
367
368 prev = cd9660node_susp_add_entry(node, prev,
369 current, 0);
370
371 /* TF - timestamp */
372 current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
373 SUSP_ENTRY_RRIP_TF, "TF", SUSP_LOC_ENTRY);
374 cd9660node_rrip_tf(current, node->node);
375 prev = cd9660node_susp_add_entry(node, prev,
376 current, 0);
377
378 /* SL - Symbolic link */
379 /* ?????????? Dan - why is this here? */
380 if (((node->child) == NULL) &&
381 (node->node->inode != NULL) &&
382 (S_ISLNK(node->node->inode->st.st_mode))) {
383 current =
384 cd9660node_susp_create_node(SUSP_TYPE_RRIP,
385 SUSP_ENTRY_RRIP_SL, "SL",
386 SUSP_LOC_ENTRY);
387 prev = cd9660_createSL(prev, node);
388
389 }
390
391 /* PN - device number */
392 if ((node->node->inode != NULL) &&
393 ((S_ISCHR(node->node->inode->st.st_mode) ||
394 (S_ISBLK(node->node->inode->st.st_mode))))) {
395 current =
396 cd9660node_susp_create_node(SUSP_TYPE_RRIP,
397 SUSP_ENTRY_RRIP_PN, "PN",
398 SUSP_LOC_ENTRY);
399 cd9660node_rrip_pn(current, node->node);
400 prev = cd9660node_susp_add_entry(node, prev,
401 current, 0);
402 }
403 }
404 /*
405 * Not every node needs a NM set - only if the name is
406 * actually different. IE: If a file is TEST -> TEST,
407 * no NM. test -> TEST, need a NM
408 *
409 * The rr_moved_dir needs to be assigned a NM record as well.
410 */
411 if (node == diskStructure.rr_moved_dir) {
412 cd9660_rrip_add_NM(cd9660_get_last_attribute(node),node,
413 RRIP_DEFAULT_MOVE_DIR_NAME);
414 }
415 else if ((node->node != NULL) &&
416 ((strlen(node->node->name) !=
417 (int)node->isoDirRecord->name_len[0]) ||
418 (memcmp(node->node->name,node->isoDirRecord->name,
419 (int) node->isoDirRecord->name_len[0]) != 0))) {
420 cd9660_rrip_NM(cd9660_get_last_attribute(node), node);
421 }
422
423
424
425 /* Rock ridge directory relocation code here. */
426
427 /* First handle the CL for the placeholder file. */
428 if (node->rr_relocated != NULL) {
429 current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
430 SUSP_ENTRY_RRIP_CL, "CL", SUSP_LOC_ENTRY);
431 cd9660_rrip_CL(current, node);
432 prev = cd9660node_susp_add_entry(node, prev,
433 current, 0);
434 }
435
436 /* Handle RE*/
437 if (node->rr_real_parent != NULL) {
438 current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
439 SUSP_ENTRY_RRIP_RE, "RE", SUSP_LOC_ENTRY);
440 cd9660_rrip_RE(current,node);
441 prev = cd9660node_susp_add_entry(node, prev,
442 current, 0);
443
444 /* Handle PL */
445 current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
446 SUSP_ENTRY_RRIP_PL, "PL", SUSP_LOC_DOTDOT);
447 cd9660_rrip_PL(current,node->dot_dot_record);
448 cd9660node_susp_add_entry(node->dot_dot_record,
449 cd9660_get_last_attribute(node->dot_dot_record),
450 current,0);
451 }
452 }
453 return 1;
454 }
455
456 struct ISO_SUSP_ATTRIBUTES*
457 cd9660node_susp_create_node(int susp_type, int entry_type, const char *type_id,
458 int write_loc)
459 {
460 struct ISO_SUSP_ATTRIBUTES* temp;
461
462 if ((temp = malloc(sizeof(struct ISO_SUSP_ATTRIBUTES))) == NULL) {
463 CD9660_MEM_ALLOC_ERROR("cd9660node_susp_create_node");
464 exit(1);
465 }
466
467 temp->susp_type = susp_type;
468 temp->entry_type = entry_type;
469 /* Phase this out */
470 temp->type_of[0] = type_id[0];
471 temp->type_of[1] = type_id[1];
472 temp->write_location = write_loc;
473
474 /*
475 * Since the first four bytes is common, lets go ahead and
476 * set the type identifier, since we are passing that to this
477 * function anyhow.
478 */
479 temp->attr.su_entry.SP.h.type[0] = type_id[0];
480 temp->attr.su_entry.SP.h.type[1] = type_id[1];
481 return temp;
482 }
483
484 int
485 cd9660_rrip_PL(struct ISO_SUSP_ATTRIBUTES*p, cd9660node *node)
486 {
487 p->attr.rr_entry.PL.h.length[0] = 12;
488 p->attr.rr_entry.PL.h.version[0] = 1;
489 return 1;
490 }
491
492 int
493 cd9660_rrip_CL(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *node)
494 {
495 p->attr.rr_entry.CL.h.length[0] = 12;
496 p->attr.rr_entry.CL.h.version[0] = 1;
497 return 1;
498 }
499
500 int
501 cd9660_rrip_RE(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *node)
502 {
503 p->attr.rr_entry.RE.h.length[0] = 0;
504 p->attr.rr_entry.RE.h.version[0] = 1;
505 return 1;
506 }
507
508 struct ISO_SUSP_ATTRIBUTES *
509 cd9660_createSL(struct ISO_SUSP_ATTRIBUTES *prev, cd9660node *node)
510 {
511 struct ISO_SUSP_ATTRIBUTES* current;
512 struct ISO_SUSP_ATTRIBUTES* temp;
513 int path_count, dir_count, done, i, j, dir_copied;
514 char temp_cr[255];
515 char temp_sl[255]; /* used in copying continuation entry*/
516 char* sl_ptr;
517
518 sl_ptr = node->node->symlink;
519
520 done = 0;
521 path_count = 0;
522 dir_count = 0;
523 dir_copied = 0;
524 temp = prev;
525 current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
526 SUSP_ENTRY_RRIP_SL, "SL", SUSP_LOC_ENTRY);
527
528 current->attr.rr_entry.SL.h.version[0] = 1;
529 current->attr.rr_entry.SL.flags[0] = SL_FLAGS_NONE;
530
531 if (*sl_ptr == '/') {
532 temp_cr[0] = SL_FLAGS_ROOT;
533 temp_cr[1] = 0;
534 memcpy(current->attr.rr_entry.SL.component + path_count,
535 temp_cr, 2);
536 path_count += 2;
537 sl_ptr++;
538 }
539
540 for (i = 0; i < (dir_count + 2); i++)
541 temp_cr[i] = '\0';
542
543 while (!done) {
544 while ((*sl_ptr != '/') && (*sl_ptr != '\0')) {
545 dir_copied = 1;
546 if (*sl_ptr == '.') {
547 if ((*(sl_ptr + 1) == '/') || (*(sl_ptr + 1)
548 == '\0')) {
549 temp_cr[0] = SL_FLAGS_CURRENT;
550 sl_ptr++;
551 } else if(*(sl_ptr + 1) == '.') {
552 if ((*(sl_ptr + 2) == '/') ||
553 (*(sl_ptr + 2) == '\0')) {
554 temp_cr[0] = SL_FLAGS_PARENT;
555 sl_ptr += 2;
556 }
557 } else {
558 temp_cr[dir_count+2] = *sl_ptr;
559 sl_ptr++;
560 dir_count++;
561 }
562 } else {
563 temp_cr[dir_count + 2] = *sl_ptr;
564 sl_ptr++;
565 dir_count++;
566 }
567 }
568
569 if ((path_count + dir_count) >= 249) {
570 current->attr.rr_entry.SL.flags[0] |= SL_FLAGS_CONTINUE;
571
572 j = 0;
573
574 if (path_count <= 249) {
575 while(j != (249 - path_count)) {
576 temp_sl[j] = temp_cr[j];
577 j++;
578 }
579 temp_sl[0] = SL_FLAGS_CONTINUE;
580 temp_sl[1] = j - 2;
581 memcpy(
582 current->attr.rr_entry.SL.component +
583 path_count,
584 temp_sl, j);
585 }
586
587 path_count += j;
588 current->attr.rr_entry.SL.h.length[0] = path_count + 5;
589 temp = cd9660node_susp_add_entry(node, temp,
590 current, 0);
591 current= cd9660node_susp_create_node(SUSP_TYPE_RRIP,
592 SUSP_ENTRY_RRIP_SL, "SL", SUSP_LOC_ENTRY);
593 current->attr.rr_entry.SL.h.version[0] = 1;
594 current->attr.rr_entry.SL.flags[0] = SL_FLAGS_NONE;
595
596 path_count = 0;
597
598 if (dir_count > 2) {
599 while (j != dir_count + 2) {
600 current->attr.rr_entry.SL.component[
601 path_count + 2] = temp_cr[j];
602 j++;
603 path_count++;
604 }
605 current->attr.rr_entry.SL.component[1]
606 = path_count;
607 path_count+= 2;
608 } else {
609 while(j != dir_count) {
610 current->attr.rr_entry.SL.component[
611 path_count+2] = temp_cr[j];
612 j++;
613 path_count++;
614 }
615 }
616 } else {
617 if (dir_copied == 1) {
618 temp_cr[1] = dir_count;
619 memcpy(current->attr.rr_entry.SL.component +
620 path_count,
621 temp_cr, dir_count + 2);
622 path_count += dir_count + 2;
623 }
624 }
625
626 if (*sl_ptr == '\0') {
627 done = 1;
628 current->attr.rr_entry.SL.h.length[0] = path_count + 5;
629 temp = cd9660node_susp_add_entry(node, temp,
630 current, 0);
631 } else {
632 sl_ptr++;
633 dir_count = 0;
634 dir_copied = 0;
635 for(i = 0; i < 255; i++) {
636 temp_cr[i] = '\0';
637 }
638 }
639 }
640
641 return temp;
642 }
643
644 int
645 cd9660node_rrip_px(struct ISO_SUSP_ATTRIBUTES *v, fsnode *pxinfo)
646 {
647 v->attr.rr_entry.PX.h.length[0] = 36;
648 v->attr.rr_entry.PX.h.version[0] = 1;
649 cd9660_bothendian_dword(pxinfo->inode->st.st_mode,
650 v->attr.rr_entry.PX.mode);
651 cd9660_bothendian_dword(pxinfo->inode->st.st_nlink,
652 v->attr.rr_entry.PX.links);
653 cd9660_bothendian_dword(pxinfo->inode->st.st_uid,
654 v->attr.rr_entry.PX.uid);
655 cd9660_bothendian_dword(pxinfo->inode->st.st_gid,
656 v->attr.rr_entry.PX.gid);
657
658 /* Ignoring the serial number for now */
659 return 1;
660 }
661
662 int
663 cd9660node_rrip_pn(struct ISO_SUSP_ATTRIBUTES *pn_field, fsnode *fnode)
664 {
665 pn_field->attr.rr_entry.PN.h.length[0] = 20;
666 pn_field->attr.rr_entry.PN.h.version[0] = 1;
667
668 if (sizeof (fnode->inode->st.st_dev) > 32)
669 cd9660_bothendian_dword((uint64_t)fnode->inode->st.st_dev >> 32,
670 pn_field->attr.rr_entry.PN.high);
671 else
672 cd9660_bothendian_dword(0, pn_field->attr.rr_entry.PN.high);
673
674 cd9660_bothendian_dword(fnode->inode->st.st_dev & 0xffffffff,
675 pn_field->attr.rr_entry.PN.low);
676 return 1;
677 }
678
679 #if 0
680 int
681 cd9660node_rrip_nm(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *file_node)
682 {
683 int nm_length = strlen(file_node->isoDirRecord->name) + 5;
684 p->attr.rr_entry.NM.h.type[0] = 'N';
685 p->attr.rr_entry.NM.h.type[1] = 'M';
686 sprintf(p->attr.rr_entry.NM.altname, "%s", file_node->isoDirRecord->name);
687 p->attr.rr_entry.NM.h.length[0] = (unsigned char)nm_length;
688 p->attr.rr_entry.NM.h.version[0] = (unsigned char)1;
689 p->attr.rr_entry.NM.flags[0] = (unsigned char) NM_PARENT;
690 return 1;
691 }
692 #endif
693
694 int
695 cd9660node_rrip_tf(struct ISO_SUSP_ATTRIBUTES *p, fsnode *_node)
696 {
697 p->attr.rr_entry.TF.flags[0] = TF_MODIFY | TF_ACCESS | TF_ATTRIBUTES;
698 p->attr.rr_entry.TF.h.length[0] = 4;
699 p->attr.rr_entry.TF.h.version[0] = 1;
700
701 /*
702 * Need to add creation time, backup time,
703 * expiration time, and effective time.
704 */
705
706 cd9660_time_915(p->attr.rr_entry.TF.timestamp,
707 _node->inode->st.st_atime);
708 p->attr.rr_entry.TF.h.length[0] += 7;
709
710 cd9660_time_915(p->attr.rr_entry.TF.timestamp + 7,
711 _node->inode->st.st_mtime);
712 p->attr.rr_entry.TF.h.length[0] += 7;
713
714 cd9660_time_915(p->attr.rr_entry.TF.timestamp + 14,
715 _node->inode->st.st_ctime);
716 p->attr.rr_entry.TF.h.length[0] += 7;
717 return 1;
718 }
719
720 int
721 cd9660_susp_sp(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *spinfo)
722 {
723 p->attr.su_entry.SP.h.length[0] = 7;
724 p->attr.su_entry.SP.h.version[0] = 1;
725 p->attr.su_entry.SP.check[0] = 0xBE;
726 p->attr.su_entry.SP.check[1] = 0xEF;
727 p->attr.su_entry.SP.len_skp[0] = 0;
728 return 1;
729 }
730
731 int
732 cd9660_susp_st(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *stinfo)
733 {
734 p->attr.su_entry.ST.h.type[0] = 'S';
735 p->attr.su_entry.ST.h.type[1] = 'T';
736 p->attr.su_entry.ST.h.length[0] = 4;
737 p->attr.su_entry.ST.h.version[0] = 1;
738 return 1;
739 }
740
741 int
742 cd9660_susp_ce(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *spinfo)
743 {
744 p->attr.su_entry.CE.h.length[0] = 28;
745 p->attr.su_entry.CE.h.version[0] = 1;
746 /* Other attributes dont matter right now, will be updated later */
747 return 1;
748 }
749
750 int
751 cd9660_susp_pd(struct ISO_SUSP_ATTRIBUTES *p, int length)
752 {
753 return 1;
754 }
755
756 struct ISO_SUSP_ATTRIBUTES*
757 cd9660_rrip_add_NM(struct ISO_SUSP_ATTRIBUTES *add_after, cd9660node *node,
758 const char *name)
759 {
760 int working,len;
761 const char *p;
762 struct ISO_SUSP_ATTRIBUTES *r,*temp;
763
764 /*
765 * Each NM record has 254 byes to work with. This means that
766 * the name data itself only has 249 bytes to work with. So, a
767 * name with 251 characters would require two nm records.
768 */
769 p = name;
770 temp = add_after;
771 working = 1;
772 while (working) {
773 r = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
774 SUSP_ENTRY_RRIP_NM, "NM", SUSP_LOC_ENTRY);
775 r->attr.rr_entry.NM.h.version[0] = 1;
776 r->attr.rr_entry.NM.flags[0] = RRIP_NM_FLAGS_NONE;
777 len = strlen(p);
778
779 if (len > 249) {
780 len = 249;
781 r->attr.rr_entry.NM.flags[0] = RRIP_NM_FLAGS_CONTINUE;
782 } else {
783 working = 0;
784 }
785 memcpy(r->attr.rr_entry.NM.altname, p, len);
786 r->attr.rr_entry.NM.h.length[0] = 5 + len;
787
788 temp = cd9660node_susp_add_entry(node, temp, r, 0);
789
790 p += len;
791 }
792
793 return temp;
794 }
795
796 struct ISO_SUSP_ATTRIBUTES*
797 cd9660_rrip_NM(struct ISO_SUSP_ATTRIBUTES *add_after, cd9660node *node)
798 {
799 return cd9660_rrip_add_NM(add_after, node, node->node->name);
800 }
801
802 struct ISO_SUSP_ATTRIBUTES*
803 cd9660_susp_ER(struct ISO_SUSP_ATTRIBUTES *add_after, cd9660node *node,
804 u_char ext_version, const char* ext_id, const char* ext_des,
805 const char* ext_src)
806 {
807 int l;
808 struct ISO_SUSP_ATTRIBUTES *r;
809
810 r = cd9660node_susp_create_node(SUSP_TYPE_SUSP,
811 SUSP_ENTRY_SUSP_ER, "ER", SUSP_LOC_DOT);
812
813 /* Fixed data is 8 bytes */
814 r->attr.su_entry.ER.h.length[0] = 8;
815 r->attr.su_entry.ER.h.version[0] = 1;
816
817 r->attr.su_entry.ER.len_id[0] = (u_char)strlen(ext_id);
818 r->attr.su_entry.ER.len_des[0] = (u_char)strlen(ext_des);
819 r->attr.su_entry.ER.len_src[0] = (u_char)strlen(ext_src);
820
821 l = r->attr.su_entry.ER.len_id[0] +
822 r->attr.su_entry.ER.len_src[0] +
823 r->attr.su_entry.ER.len_des[0];
824
825 /* Everything must fit. */
826 assert(l + r->attr.su_entry.ER.h.length[0] <= 254);
827
828 r->attr.su_entry.ER.h.length[0] += (u_char)l;
829
830
831 r->attr.su_entry.ER.ext_ver[0] = ext_version;
832 memcpy(r->attr.su_entry.ER.ext_data, ext_id,
833 (int)r->attr.su_entry.ER.len_id[0]);
834 l = (int) r->attr.su_entry.ER.len_id[0];
835 memcpy(r->attr.su_entry.ER.ext_data + l,ext_des,
836 (int)r->attr.su_entry.ER.len_des[0]);
837
838 l += (int)r->attr.su_entry.ER.len_des[0];
839 memcpy(r->attr.su_entry.ER.ext_data + l,ext_src,
840 (int)r->attr.su_entry.ER.len_src[0]);
841
842 return cd9660node_susp_add_entry(node, add_after, r, 0);
843 }
844
845 struct ISO_SUSP_ATTRIBUTES*
846 cd9660_susp_ES(struct ISO_SUSP_ATTRIBUTES *last, cd9660node *node)
847 {
848 return NULL;
849 }
850