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