1 /* $NetBSD: iso9660_rrip.c,v 1.14 2014/05/30 13:14:47 martin Exp $ */
4 * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
5 * Perez-Rathke and Ram Vedam. All rights reserved.
7 * This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
8 * Alan Perez-Rathke and Ram Vedam.
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
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.
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
34 /* This will hold all the function definitions
35 * defined in iso9660_rrip.h
40 #include "iso9660_rrip.h"
41 #include <sys/queue.h>
45 #include <sys/cdefs.h>
46 #if defined(__RCSID) && !defined(__lint)
47 __RCSID("$NetBSD: iso9660_rrip.c,v 1.14 2014/05/30 13:14:47 martin Exp $");
50 static void cd9660_rrip_initialize_inode(cd9660node
*);
51 static int cd9660_susp_handle_continuation(iso9660_disk
*, cd9660node
*);
52 static int cd9660_susp_handle_continuation_common(iso9660_disk
*, cd9660node
*,
56 cd9660_susp_initialize(iso9660_disk
*diskStructure
, cd9660node
*node
,
57 cd9660node
*parent
, cd9660node
*grandparent
)
62 /* Make sure the node is not NULL. If it is, there are major problems */
65 if (!(node
->type
& CD9660_TYPE_DOT
) &&
66 !(node
->type
& CD9660_TYPE_DOTDOT
))
67 TAILQ_INIT(&(node
->head
));
68 if (node
->dot_record
!= 0)
69 TAILQ_INIT(&(node
->dot_record
->head
));
70 if (node
->dot_dot_record
!= 0)
71 TAILQ_INIT(&(node
->dot_dot_record
->head
));
73 /* SUSP specific entries here */
74 if ((r
= cd9660_susp_initialize_node(diskStructure
, node
)) < 0)
77 /* currently called cd9660node_rrip_init_links */
78 r
= cd9660_rrip_initialize_node(diskStructure
, node
, parent
, grandparent
);
83 * See if we need a CE record, and set all of the
84 * associated counters.
86 * This should be called after all extensions. After
87 * this is called, no new records should be added.
89 if ((r
= cd9660_susp_handle_continuation(diskStructure
, node
)) < 0)
92 /* Recurse on children. */
93 TAILQ_FOREACH(cn
, &node
->cn_children
, cn_next_child
) {
94 if ((r
= cd9660_susp_initialize(diskStructure
, cn
, node
, parent
)) < 0)
101 cd9660_susp_finalize(iso9660_disk
*diskStructure
, cd9660node
*node
)
106 assert(node
!= NULL
);
108 if (node
== diskStructure
->rootNode
)
109 diskStructure
->susp_continuation_area_current_free
= 0;
111 if ((r
= cd9660_susp_finalize_node(diskStructure
, node
)) < 0)
113 if ((r
= cd9660_rrip_finalize_node(diskStructure
, node
)) < 0)
116 TAILQ_FOREACH(temp
, &node
->cn_children
, cn_next_child
) {
117 if ((r
= cd9660_susp_finalize(diskStructure
, temp
)) < 0)
124 * If we really wanted to speed things up, we could have some sort of
125 * lookup table on the SUSP entry type that calls a functor. Or, we could
126 * combine the functions. These functions are kept separate to allow
127 * easier addition of other extensions.
129 * For the sake of simplicity and clarity, we won't be doing that for now.
133 * SUSP needs to update the following types:
134 * CE (continuation area)
137 cd9660_susp_finalize_node(iso9660_disk
*diskStructure
, cd9660node
*node
)
139 struct ISO_SUSP_ATTRIBUTES
*t
;
141 /* Handle CE counters */
142 if (node
->susp_entry_ce_length
> 0) {
143 node
->susp_entry_ce_start
=
144 diskStructure
->susp_continuation_area_current_free
;
145 diskStructure
->susp_continuation_area_current_free
+=
146 node
->susp_entry_ce_length
;
149 TAILQ_FOREACH(t
, &node
->head
, rr_ll
) {
150 if (t
->susp_type
!= SUSP_TYPE_SUSP
||
151 t
->entry_type
!= SUSP_ENTRY_SUSP_CE
)
153 cd9660_bothendian_dword(
155 susp_continuation_area_start_sector
,
156 t
->attr
.su_entry
.CE
.ca_sector
);
158 cd9660_bothendian_dword(
160 susp_continuation_area_start_sector
,
161 t
->attr
.su_entry
.CE
.ca_sector
);
162 cd9660_bothendian_dword(node
->susp_entry_ce_start
,
163 t
->attr
.su_entry
.CE
.offset
);
164 cd9660_bothendian_dword(node
->susp_entry_ce_length
,
165 t
->attr
.su_entry
.CE
.length
);
171 cd9660_rrip_finalize_node(iso9660_disk
*diskStructure __unused
,
174 struct ISO_SUSP_ATTRIBUTES
*t
;
176 TAILQ_FOREACH(t
, &node
->head
, rr_ll
) {
177 if (t
->susp_type
!= SUSP_TYPE_RRIP
)
179 switch (t
->entry_type
) {
180 case SUSP_ENTRY_RRIP_CL
:
181 /* Look at rr_relocated*/
182 if (node
->rr_relocated
== NULL
)
184 cd9660_bothendian_dword(
185 node
->rr_relocated
->fileDataSector
,
187 t
->attr
.rr_entry
.CL
.dir_loc
);
189 case SUSP_ENTRY_RRIP_PL
:
190 /* Look at rr_real_parent */
191 if (node
->parent
== NULL
||
192 node
->parent
->rr_real_parent
== NULL
)
194 cd9660_bothendian_dword(
195 node
->parent
->rr_real_parent
->fileDataSector
,
197 t
->attr
.rr_entry
.PL
.dir_loc
);
205 cd9660_susp_handle_continuation_common(iso9660_disk
*diskStructure
,
206 cd9660node
*node
, int space
)
208 int ca_used
, susp_used
, susp_used_pre_ce
, working
;
209 struct ISO_SUSP_ATTRIBUTES
*temp
, *pre_ce
, *last
, *CE
, *ST
;
211 pre_ce
= last
= NULL
;
212 working
= 254 - space
;
213 if (node
->su_tail_size
> 0)
214 /* Allow 4 bytes for "ST" record. */
215 working
-= node
->su_tail_size
+ 4;
216 /* printf("There are %i bytes to work with\n",working); */
218 susp_used_pre_ce
= susp_used
= 0;
220 TAILQ_FOREACH(temp
, &node
->head
, rr_ll
) {
224 * printf("SUSP Entry found, length is %i\n",
225 * CD9660_SUSP_ENTRY_SIZE(temp));
227 working
-= CD9660_SUSP_ENTRY_SIZE(temp
);
230 susp_used
+= CD9660_SUSP_ENTRY_SIZE(temp
);
234 * Remember the last entry after which we
235 * could insert a "CE" entry.
238 susp_used_pre_ce
= susp_used
;
242 /* A CE entry is needed */
244 CE
= cd9660node_susp_create_node(SUSP_TYPE_SUSP
,
245 SUSP_ENTRY_SUSP_CE
, "CE", SUSP_LOC_ENTRY
);
246 cd9660_susp_ce(CE
, node
);
247 /* This will automatically insert at the appropriate location */
249 TAILQ_INSERT_AFTER(&node
->head
, pre_ce
, CE
, rr_ll
);
251 TAILQ_INSERT_HEAD(&node
->head
, CE
, rr_ll
);
253 susp_used
= susp_used_pre_ce
+ 28;
254 /* Count how much CA data is necessary */
255 for (temp
= TAILQ_NEXT(last
, rr_ll
); temp
!= NULL
;
256 temp
= TAILQ_NEXT(temp
, rr_ll
)) {
257 ca_used
+= CD9660_SUSP_ENTRY_SIZE(temp
);
261 /* An ST entry is needed */
262 if (node
->su_tail_size
> 0) {
263 ST
= cd9660node_susp_create_node(SUSP_TYPE_SUSP
,
264 SUSP_ENTRY_SUSP_ST
, "ST", SUSP_LOC_ENTRY
);
265 cd9660_susp_st(ST
, node
);
267 TAILQ_INSERT_AFTER(&node
->head
, last
, ST
, rr_ll
);
269 TAILQ_INSERT_HEAD(&node
->head
, ST
, rr_ll
);
274 last
->last_in_suf
= 1;
276 node
->susp_entry_size
= susp_used
;
277 node
->susp_entry_ce_length
= ca_used
;
279 diskStructure
->susp_continuation_area_size
+= ca_used
;
283 /* See if a continuation entry is needed for each of the different types */
285 cd9660_susp_handle_continuation(iso9660_disk
*diskStructure
, cd9660node
*node
)
287 assert (node
!= NULL
);
290 if (cd9660_susp_handle_continuation_common(diskStructure
,
291 node
,(int)(node
->isoDirRecord
->length
[0])) < 0)
298 cd9660_susp_initialize_node(iso9660_disk
*diskStructure
, cd9660node
*node
)
300 struct ISO_SUSP_ATTRIBUTES
*temp
;
303 * Requirements/notes:
304 * CE: is added for us where needed
305 * ST: not sure if it is even required, but if so, should be
306 * handled by the CE code
307 * PD: isnt needed (though might be added for testing)
308 * SP: is stored ONLY on the . record of the root directory
312 /* Check for root directory, add SP and ER if needed. */
313 if (node
->type
& CD9660_TYPE_DOT
) {
314 if (node
->parent
== diskStructure
->rootNode
) {
315 temp
= cd9660node_susp_create_node(SUSP_TYPE_SUSP
,
316 SUSP_ENTRY_SUSP_SP
, "SP", SUSP_LOC_DOT
);
317 cd9660_susp_sp(temp
, node
);
319 /* Should be first entry. */
320 TAILQ_INSERT_HEAD(&node
->head
, temp
, rr_ll
);
327 cd9660_rrip_initialize_inode(cd9660node
*node
)
329 struct ISO_SUSP_ATTRIBUTES
*attr
;
332 * Inode dependent values - this may change,
333 * but for now virtual files and directories do
334 * not have an inode structure
337 if ((node
->node
!= NULL
) && (node
->node
->inode
!= NULL
)) {
338 /* PX - POSIX attributes */
339 attr
= cd9660node_susp_create_node(SUSP_TYPE_RRIP
,
340 SUSP_ENTRY_RRIP_PX
, "PX", SUSP_LOC_ENTRY
);
341 cd9660node_rrip_px(attr
, node
->node
);
343 TAILQ_INSERT_TAIL(&node
->head
, attr
, rr_ll
);
346 attr
= cd9660node_susp_create_node(SUSP_TYPE_RRIP
,
347 SUSP_ENTRY_RRIP_TF
, "TF", SUSP_LOC_ENTRY
);
348 cd9660node_rrip_tf(attr
, node
->node
);
349 TAILQ_INSERT_TAIL(&node
->head
, attr
, rr_ll
);
351 /* SL - Symbolic link */
352 /* ?????????? Dan - why is this here? */
353 if (TAILQ_EMPTY(&node
->cn_children
) &&
354 node
->node
->inode
!= NULL
&&
355 S_ISLNK(node
->node
->inode
->st
.st_mode
))
356 cd9660_createSL(node
);
358 /* PN - device number */
359 if (node
->node
->inode
!= NULL
&&
360 ((S_ISCHR(node
->node
->inode
->st
.st_mode
) ||
361 S_ISBLK(node
->node
->inode
->st
.st_mode
)))) {
363 cd9660node_susp_create_node(SUSP_TYPE_RRIP
,
364 SUSP_ENTRY_RRIP_PN
, "PN",
366 cd9660node_rrip_pn(attr
, node
->node
);
367 TAILQ_INSERT_TAIL(&node
->head
, attr
, rr_ll
);
373 cd9660_rrip_initialize_node(iso9660_disk
*diskStructure
, cd9660node
*node
,
374 cd9660node
*parent
, cd9660node
*grandparent
)
376 struct ISO_SUSP_ATTRIBUTES
*current
= NULL
;
378 assert(node
!= NULL
);
380 if (node
->type
& CD9660_TYPE_DOT
) {
382 * Handle ER - should be the only entry to appear on
385 if (node
->parent
== diskStructure
->rootNode
) {
386 cd9660_susp_ER(node
, 1, SUSP_RRIP_ER_EXT_ID
,
387 SUSP_RRIP_ER_EXT_DES
, SUSP_RRIP_ER_EXT_SRC
);
389 if (parent
!= NULL
&& parent
->node
!= NULL
&&
390 parent
->node
->inode
!= NULL
) {
391 /* PX - POSIX attributes */
392 current
= cd9660node_susp_create_node(SUSP_TYPE_RRIP
,
393 SUSP_ENTRY_RRIP_PX
, "PX", SUSP_LOC_ENTRY
);
394 cd9660node_rrip_px(current
, parent
->node
);
395 TAILQ_INSERT_TAIL(&node
->head
, current
, rr_ll
);
397 } else if (node
->type
& CD9660_TYPE_DOTDOT
) {
398 if (grandparent
!= NULL
&& grandparent
->node
!= NULL
&&
399 grandparent
->node
->inode
!= NULL
) {
400 /* PX - POSIX attributes */
401 current
= cd9660node_susp_create_node(SUSP_TYPE_RRIP
,
402 SUSP_ENTRY_RRIP_PX
, "PX", SUSP_LOC_ENTRY
);
403 cd9660node_rrip_px(current
, grandparent
->node
);
404 TAILQ_INSERT_TAIL(&node
->head
, current
, rr_ll
);
407 if (parent
!= NULL
&& parent
->rr_real_parent
!= NULL
) {
408 current
= cd9660node_susp_create_node(SUSP_TYPE_RRIP
,
409 SUSP_ENTRY_RRIP_PL
, "PL", SUSP_LOC_DOTDOT
);
410 cd9660_rrip_PL(current
,node
);
411 TAILQ_INSERT_TAIL(&node
->head
, current
, rr_ll
);
414 cd9660_rrip_initialize_inode(node
);
417 * Not every node needs a NM set - only if the name is
418 * actually different. IE: If a file is TEST -> TEST,
419 * no NM. test -> TEST, need a NM
421 * The rr_moved_dir needs to be assigned a NM record as well.
423 if (node
== diskStructure
->rr_moved_dir
) {
424 cd9660_rrip_add_NM(node
, RRIP_DEFAULT_MOVE_DIR_NAME
);
426 else if ((node
->node
!= NULL
) &&
427 ((strlen(node
->node
->name
) !=
428 (uint8_t)node
->isoDirRecord
->name_len
[0]) ||
429 (memcmp(node
->node
->name
,node
->isoDirRecord
->name
,
430 (uint8_t)node
->isoDirRecord
->name_len
[0]) != 0))) {
431 cd9660_rrip_NM(node
);
436 /* Rock ridge directory relocation code here. */
438 /* First handle the CL for the placeholder file. */
439 if (node
->rr_relocated
!= NULL
) {
440 current
= cd9660node_susp_create_node(SUSP_TYPE_RRIP
,
441 SUSP_ENTRY_RRIP_CL
, "CL", SUSP_LOC_ENTRY
);
442 cd9660_rrip_CL(current
, node
);
443 TAILQ_INSERT_TAIL(&node
->head
, current
, rr_ll
);
447 if (node
->rr_real_parent
!= NULL
) {
448 current
= cd9660node_susp_create_node(SUSP_TYPE_RRIP
,
449 SUSP_ENTRY_RRIP_RE
, "RE", SUSP_LOC_ENTRY
);
450 cd9660_rrip_RE(current
,node
);
451 TAILQ_INSERT_TAIL(&node
->head
, current
, rr_ll
);
457 struct ISO_SUSP_ATTRIBUTES
*
458 cd9660node_susp_create_node(int susp_type
, int entry_type
, const char *type_id
,
461 struct ISO_SUSP_ATTRIBUTES
* temp
;
463 temp
= emalloc(sizeof(*temp
));
464 temp
->susp_type
= susp_type
;
465 temp
->entry_type
= entry_type
;
466 temp
->last_in_suf
= 0;
468 temp
->type_of
[0] = type_id
[0];
469 temp
->type_of
[1] = type_id
[1];
470 temp
->write_location
= write_loc
;
473 * Since the first four bytes is common, lets go ahead and
474 * set the type identifier, since we are passing that to this
477 temp
->attr
.su_entry
.SP
.h
.type
[0] = type_id
[0];
478 temp
->attr
.su_entry
.SP
.h
.type
[1] = type_id
[1];
483 cd9660_rrip_PL(struct ISO_SUSP_ATTRIBUTES
* p
, cd9660node
*node __unused
)
485 p
->attr
.rr_entry
.PL
.h
.length
[0] = 12;
486 p
->attr
.rr_entry
.PL
.h
.version
[0] = 1;
491 cd9660_rrip_CL(struct ISO_SUSP_ATTRIBUTES
*p
, cd9660node
*node __unused
)
493 p
->attr
.rr_entry
.CL
.h
.length
[0] = 12;
494 p
->attr
.rr_entry
.CL
.h
.version
[0] = 1;
499 cd9660_rrip_RE(struct ISO_SUSP_ATTRIBUTES
*p
, cd9660node
*node __unused
)
501 p
->attr
.rr_entry
.RE
.h
.length
[0] = 4;
502 p
->attr
.rr_entry
.RE
.h
.version
[0] = 1;
507 cd9660_createSL(cd9660node
*node
)
509 struct ISO_SUSP_ATTRIBUTES
* current
;
510 int path_count
, dir_count
, done
, i
, j
, dir_copied
;
512 char temp_sl
[255]; /* used in copying continuation entry*/
515 sl_ptr
= node
->node
->symlink
;
521 current
= cd9660node_susp_create_node(SUSP_TYPE_RRIP
,
522 SUSP_ENTRY_RRIP_SL
, "SL", SUSP_LOC_ENTRY
);
524 current
->attr
.rr_entry
.SL
.h
.version
[0] = 1;
525 current
->attr
.rr_entry
.SL
.flags
[0] = SL_FLAGS_NONE
;
527 if (*sl_ptr
== '/') {
528 temp_cr
[0] = SL_FLAGS_ROOT
;
530 memcpy(current
->attr
.rr_entry
.SL
.component
+ path_count
,
536 for (i
= 0; i
< (dir_count
+ 2); i
++)
540 while ((*sl_ptr
!= '/') && (*sl_ptr
!= '\0')) {
542 if (*sl_ptr
== '.') {
543 if ((*(sl_ptr
+ 1) == '/') || (*(sl_ptr
+ 1)
545 temp_cr
[0] = SL_FLAGS_CURRENT
;
547 } else if(*(sl_ptr
+ 1) == '.') {
548 if ((*(sl_ptr
+ 2) == '/') ||
549 (*(sl_ptr
+ 2) == '\0')) {
550 temp_cr
[0] = SL_FLAGS_PARENT
;
554 temp_cr
[dir_count
+2] = *sl_ptr
;
559 temp_cr
[dir_count
+ 2] = *sl_ptr
;
565 if ((path_count
+ dir_count
) >= 249) {
566 current
->attr
.rr_entry
.SL
.flags
[0] |= SL_FLAGS_CONTINUE
;
570 if (path_count
<= 249) {
571 while(j
!= (249 - path_count
)) {
572 temp_sl
[j
] = temp_cr
[j
];
575 temp_sl
[0] = SL_FLAGS_CONTINUE
;
578 current
->attr
.rr_entry
.SL
.component
+
584 current
->attr
.rr_entry
.SL
.h
.length
[0] = path_count
+ 5;
585 TAILQ_INSERT_TAIL(&node
->head
, current
, rr_ll
);
586 current
= cd9660node_susp_create_node(SUSP_TYPE_RRIP
,
587 SUSP_ENTRY_RRIP_SL
, "SL", SUSP_LOC_ENTRY
);
588 current
->attr
.rr_entry
.SL
.h
.version
[0] = 1;
589 current
->attr
.rr_entry
.SL
.flags
[0] = SL_FLAGS_NONE
;
594 while (j
!= dir_count
+ 2) {
595 current
->attr
.rr_entry
.SL
.component
[
596 path_count
+ 2] = temp_cr
[j
];
600 current
->attr
.rr_entry
.SL
.component
[1]
604 while(j
!= dir_count
) {
605 current
->attr
.rr_entry
.SL
.component
[
606 path_count
+2] = temp_cr
[j
];
612 if (dir_copied
== 1) {
613 temp_cr
[1] = dir_count
;
614 memcpy(current
->attr
.rr_entry
.SL
.component
+
616 temp_cr
, dir_count
+ 2);
617 path_count
+= dir_count
+ 2;
621 if (*sl_ptr
== '\0') {
623 current
->attr
.rr_entry
.SL
.h
.length
[0] = path_count
+ 5;
624 TAILQ_INSERT_TAIL(&node
->head
, current
, rr_ll
);
629 for(i
= 0; i
< 255; i
++) {
637 cd9660node_rrip_px(struct ISO_SUSP_ATTRIBUTES
*v
, fsnode
*pxinfo
)
639 v
->attr
.rr_entry
.PX
.h
.length
[0] = 36;
640 v
->attr
.rr_entry
.PX
.h
.version
[0] = 1;
641 cd9660_bothendian_dword(pxinfo
->inode
->st
.st_mode
,
642 v
->attr
.rr_entry
.PX
.mode
);
643 cd9660_bothendian_dword(pxinfo
->inode
->st
.st_nlink
,
644 v
->attr
.rr_entry
.PX
.links
);
645 cd9660_bothendian_dword(pxinfo
->inode
->st
.st_uid
,
646 v
->attr
.rr_entry
.PX
.uid
);
647 cd9660_bothendian_dword(pxinfo
->inode
->st
.st_gid
,
648 v
->attr
.rr_entry
.PX
.gid
);
650 /* Ignoring the serial number for now */
655 cd9660node_rrip_pn(struct ISO_SUSP_ATTRIBUTES
*pn_field
, fsnode
*fnode
)
657 pn_field
->attr
.rr_entry
.PN
.h
.length
[0] = 20;
658 pn_field
->attr
.rr_entry
.PN
.h
.version
[0] = 1;
660 if (sizeof (fnode
->inode
->st
.st_rdev
) > 4)
661 cd9660_bothendian_dword(
662 (uint64_t)fnode
->inode
->st
.st_rdev
>> 32,
663 pn_field
->attr
.rr_entry
.PN
.high
);
665 cd9660_bothendian_dword(0, pn_field
->attr
.rr_entry
.PN
.high
);
667 cd9660_bothendian_dword(fnode
->inode
->st
.st_rdev
& 0xffffffff,
668 pn_field
->attr
.rr_entry
.PN
.low
);
674 cd9660node_rrip_nm(struct ISO_SUSP_ATTRIBUTES
*p
, cd9660node
*file_node
)
676 int nm_length
= strlen(file_node
->isoDirRecord
->name
) + 5;
677 p
->attr
.rr_entry
.NM
.h
.type
[0] = 'N';
678 p
->attr
.rr_entry
.NM
.h
.type
[1] = 'M';
679 sprintf(p
->attr
.rr_entry
.NM
.altname
, "%s", file_node
->isoDirRecord
->name
);
680 p
->attr
.rr_entry
.NM
.h
.length
[0] = (unsigned char)nm_length
;
681 p
->attr
.rr_entry
.NM
.h
.version
[0] = (unsigned char)1;
682 p
->attr
.rr_entry
.NM
.flags
[0] = (unsigned char) NM_PARENT
;
688 cd9660node_rrip_tf(struct ISO_SUSP_ATTRIBUTES
*p
, fsnode
*_node
)
690 p
->attr
.rr_entry
.TF
.flags
[0] = TF_MODIFY
| TF_ACCESS
| TF_ATTRIBUTES
;
691 p
->attr
.rr_entry
.TF
.h
.length
[0] = 5;
692 p
->attr
.rr_entry
.TF
.h
.version
[0] = 1;
695 * Need to add creation time, backup time,
696 * expiration time, and effective time.
699 cd9660_time_915(p
->attr
.rr_entry
.TF
.timestamp
,
700 _node
->inode
->st
.st_atime
);
701 p
->attr
.rr_entry
.TF
.h
.length
[0] += 7;
703 cd9660_time_915(p
->attr
.rr_entry
.TF
.timestamp
+ 7,
704 _node
->inode
->st
.st_mtime
);
705 p
->attr
.rr_entry
.TF
.h
.length
[0] += 7;
707 cd9660_time_915(p
->attr
.rr_entry
.TF
.timestamp
+ 14,
708 _node
->inode
->st
.st_ctime
);
709 p
->attr
.rr_entry
.TF
.h
.length
[0] += 7;
714 cd9660_susp_sp(struct ISO_SUSP_ATTRIBUTES
*p
, cd9660node
*spinfo __unused
)
716 p
->attr
.su_entry
.SP
.h
.length
[0] = 7;
717 p
->attr
.su_entry
.SP
.h
.version
[0] = 1;
718 p
->attr
.su_entry
.SP
.check
[0] = 0xBE;
719 p
->attr
.su_entry
.SP
.check
[1] = 0xEF;
720 p
->attr
.su_entry
.SP
.len_skp
[0] = 0;
725 cd9660_susp_st(struct ISO_SUSP_ATTRIBUTES
*p
, cd9660node
*stinfo __unused
)
727 p
->attr
.su_entry
.ST
.h
.type
[0] = 'S';
728 p
->attr
.su_entry
.ST
.h
.type
[1] = 'T';
729 p
->attr
.su_entry
.ST
.h
.length
[0] = 4;
730 p
->attr
.su_entry
.ST
.h
.version
[0] = 1;
735 cd9660_susp_ce(struct ISO_SUSP_ATTRIBUTES
*p
, cd9660node
*spinfo __unused
)
737 p
->attr
.su_entry
.CE
.h
.length
[0] = 28;
738 p
->attr
.su_entry
.CE
.h
.version
[0] = 1;
739 /* Other attributes dont matter right now, will be updated later */
744 cd9660_susp_pd(struct ISO_SUSP_ATTRIBUTES
*p __unused
, int length __unused
)
750 cd9660_rrip_add_NM(cd9660node
*node
, const char *name
)
754 struct ISO_SUSP_ATTRIBUTES
*r
;
757 * Each NM record has 254 byes to work with. This means that
758 * the name data itself only has 249 bytes to work with. So, a
759 * name with 251 characters would require two nm records.
764 r
= cd9660node_susp_create_node(SUSP_TYPE_RRIP
,
765 SUSP_ENTRY_RRIP_NM
, "NM", SUSP_LOC_ENTRY
);
766 r
->attr
.rr_entry
.NM
.h
.version
[0] = 1;
767 r
->attr
.rr_entry
.NM
.flags
[0] = RRIP_NM_FLAGS_NONE
;
772 r
->attr
.rr_entry
.NM
.flags
[0] = RRIP_NM_FLAGS_CONTINUE
;
776 memcpy(r
->attr
.rr_entry
.NM
.altname
, p
, len
);
777 r
->attr
.rr_entry
.NM
.h
.length
[0] = 5 + len
;
779 TAILQ_INSERT_TAIL(&node
->head
, r
, rr_ll
);
786 cd9660_rrip_NM(cd9660node
*node
)
788 cd9660_rrip_add_NM(node
, node
->node
->name
);
791 struct ISO_SUSP_ATTRIBUTES
*
792 cd9660_susp_ER(cd9660node
*node
,
793 u_char ext_version
, const char* ext_id
, const char* ext_des
,
797 struct ISO_SUSP_ATTRIBUTES
*r
;
799 r
= cd9660node_susp_create_node(SUSP_TYPE_SUSP
,
800 SUSP_ENTRY_SUSP_ER
, "ER", SUSP_LOC_DOT
);
802 /* Fixed data is 8 bytes */
803 r
->attr
.su_entry
.ER
.h
.length
[0] = 8;
804 r
->attr
.su_entry
.ER
.h
.version
[0] = 1;
806 r
->attr
.su_entry
.ER
.len_id
[0] = (u_char
)strlen(ext_id
);
807 r
->attr
.su_entry
.ER
.len_des
[0] = (u_char
)strlen(ext_des
);
808 r
->attr
.su_entry
.ER
.len_src
[0] = (u_char
)strlen(ext_src
);
810 l
= r
->attr
.su_entry
.ER
.len_id
[0] +
811 r
->attr
.su_entry
.ER
.len_src
[0] +
812 r
->attr
.su_entry
.ER
.len_des
[0];
814 /* Everything must fit. */
815 assert(l
+ r
->attr
.su_entry
.ER
.h
.length
[0] <= 254);
817 r
->attr
.su_entry
.ER
.h
.length
[0] += (u_char
)l
;
820 r
->attr
.su_entry
.ER
.ext_ver
[0] = ext_version
;
821 memcpy(r
->attr
.su_entry
.ER
.ext_data
, ext_id
,
822 (int)r
->attr
.su_entry
.ER
.len_id
[0]);
823 l
= (int) r
->attr
.su_entry
.ER
.len_id
[0];
824 memcpy(r
->attr
.su_entry
.ER
.ext_data
+ l
,ext_des
,
825 (int)r
->attr
.su_entry
.ER
.len_des
[0]);
827 l
+= (int)r
->attr
.su_entry
.ER
.len_des
[0];
828 memcpy(r
->attr
.su_entry
.ER
.ext_data
+ l
,ext_src
,
829 (int)r
->attr
.su_entry
.ER
.len_src
[0]);
831 TAILQ_INSERT_TAIL(&node
->head
, r
, rr_ll
);
835 struct ISO_SUSP_ATTRIBUTES
*
836 cd9660_susp_ES(struct ISO_SUSP_ATTRIBUTES
*last __unused
, cd9660node
*node __unused
)