1 /* $NetBSD: iso9660_rrip.c,v 1.7 2009/01/10 11:04:36 he 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>
44 #include <sys/cdefs.h>
45 #if defined(__RCSID) && !defined(__lint)
46 __RCSID("$NetBSD: iso9660_rrip.c,v 1.7 2009/01/10 11:04:36 he Exp $");
49 static void cd9660_rrip_initialize_inode(cd9660node
*);
50 static int cd9660_susp_handle_continuation(cd9660node
*);
51 static int cd9660_susp_handle_continuation_common(cd9660node
*, int);
54 cd9660_susp_initialize(cd9660node
*node
, cd9660node
*parent
,
55 cd9660node
*grandparent
)
60 /* Make sure the node is not NULL. If it is, there are major problems */
63 if (!(node
->type
& CD9660_TYPE_DOT
) &&
64 !(node
->type
& CD9660_TYPE_DOTDOT
))
65 TAILQ_INIT(&(node
->head
));
66 if (node
->dot_record
!= 0)
67 TAILQ_INIT(&(node
->dot_record
->head
));
68 if (node
->dot_dot_record
!= 0)
69 TAILQ_INIT(&(node
->dot_dot_record
->head
));
71 /* SUSP specific entries here */
72 if ((r
= cd9660_susp_initialize_node(node
)) < 0)
75 /* currently called cd9660node_rrip_init_links */
76 r
= cd9660_rrip_initialize_node(node
, parent
, grandparent
);
81 * See if we need a CE record, and set all of the
82 * associated counters.
84 * This should be called after all extensions. After
85 * this is called, no new records should be added.
87 if ((r
= cd9660_susp_handle_continuation(node
)) < 0)
90 /* Recurse on children. */
91 TAILQ_FOREACH(cn
, &node
->cn_children
, cn_next_child
) {
92 if ((r
= cd9660_susp_initialize(cn
, node
, parent
)) < 0)
99 cd9660_susp_finalize(cd9660node
*node
)
104 assert(node
!= NULL
);
106 if (node
== diskStructure
.rootNode
)
107 diskStructure
.susp_continuation_area_current_free
= 0;
109 if ((r
= cd9660_susp_finalize_node(node
)) < 0)
111 if ((r
= cd9660_rrip_finalize_node(node
)) < 0)
114 TAILQ_FOREACH(temp
, &node
->cn_children
, cn_next_child
) {
115 if ((r
= cd9660_susp_finalize(temp
)) < 0)
122 * If we really wanted to speed things up, we could have some sort of
123 * lookup table on the SUSP entry type that calls a functor. Or, we could
124 * combine the functions. These functions are kept separate to allow
125 * easier addition of other extensions.
127 * For the sake of simplicity and clarity, we won't be doing that for now.
131 * SUSP needs to update the following types:
132 * CE (continuation area)
135 cd9660_susp_finalize_node(cd9660node
*node
)
137 struct ISO_SUSP_ATTRIBUTES
*t
;
139 /* Handle CE counters */
140 if (node
->susp_entry_ce_length
> 0) {
141 node
->susp_entry_ce_start
=
142 diskStructure
.susp_continuation_area_current_free
;
143 diskStructure
.susp_continuation_area_current_free
+=
144 node
->susp_entry_ce_length
;
147 TAILQ_FOREACH(t
, &node
->head
, rr_ll
) {
148 if (t
->susp_type
!= SUSP_TYPE_SUSP
||
149 t
->entry_type
!= SUSP_ENTRY_SUSP_CE
)
151 cd9660_bothendian_dword(
153 susp_continuation_area_start_sector
,
154 t
->attr
.su_entry
.CE
.ca_sector
);
156 cd9660_bothendian_dword(
158 susp_continuation_area_start_sector
,
159 t
->attr
.su_entry
.CE
.ca_sector
);
160 cd9660_bothendian_dword(node
->susp_entry_ce_start
,
161 t
->attr
.su_entry
.CE
.offset
);
162 cd9660_bothendian_dword(node
->susp_entry_ce_length
,
163 t
->attr
.su_entry
.CE
.length
);
169 cd9660_rrip_finalize_node(cd9660node
*node
)
171 struct ISO_SUSP_ATTRIBUTES
*t
;
173 TAILQ_FOREACH(t
, &node
->head
, rr_ll
) {
174 if (t
->susp_type
!= SUSP_TYPE_RRIP
)
176 switch (t
->entry_type
) {
177 case SUSP_ENTRY_RRIP_CL
:
178 /* Look at rr_relocated*/
179 if (node
->rr_relocated
== NULL
)
181 cd9660_bothendian_dword(
182 node
->rr_relocated
->fileDataSector
,
184 t
->attr
.rr_entry
.CL
.dir_loc
);
186 case SUSP_ENTRY_RRIP_PL
:
187 /* Look at rr_real_parent */
188 if (node
->rr_real_parent
== NULL
)
190 cd9660_bothendian_dword(
191 node
->rr_real_parent
->fileDataSector
,
193 t
->attr
.rr_entry
.PL
.dir_loc
);
201 cd9660_susp_handle_continuation_common(cd9660node
*node
, int space
)
203 int ca_used
, susp_used
, susp_used_pre_ce
, working
;
204 struct ISO_SUSP_ATTRIBUTES
*temp
, *pre_ce
, *last
, *CE
, *ST
;
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); */
213 susp_used_pre_ce
= susp_used
= 0;
215 TAILQ_FOREACH(temp
, &node
->head
, rr_ll
) {
219 * printf("SUSP Entry found, length is %i\n",
220 * CD9660_SUSP_ENTRY_SIZE(temp));
222 working
-= CD9660_SUSP_ENTRY_SIZE(temp
);
225 susp_used
+= CD9660_SUSP_ENTRY_SIZE(temp
);
229 * Remember the last entry after which we
230 * could insert a "CE" entry.
233 susp_used_pre_ce
= susp_used
;
237 /* A CE entry is needed */
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 */
244 TAILQ_INSERT_AFTER(&node
->head
, pre_ce
, CE
, rr_ll
);
246 TAILQ_INSERT_HEAD(&node
->head
, CE
, rr_ll
);
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
);
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
);
262 TAILQ_INSERT_AFTER(&node
->head
, last
, ST
, rr_ll
);
264 TAILQ_INSERT_HEAD(&node
->head
, ST
, rr_ll
);
269 last
->last_in_suf
= 1;
271 node
->susp_entry_size
= susp_used
;
272 node
->susp_entry_ce_length
= ca_used
;
274 diskStructure
.susp_continuation_area_size
+= ca_used
;
278 /* See if a continuation entry is needed for each of the different types */
280 cd9660_susp_handle_continuation(cd9660node
*node
)
282 assert (node
!= NULL
);
285 if (cd9660_susp_handle_continuation_common(
286 node
,(int)(node
->isoDirRecord
->length
[0])) < 0)
293 cd9660_susp_initialize_node(cd9660node
*node
)
295 struct ISO_SUSP_ATTRIBUTES
*temp
;
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
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
);
314 /* Should be first entry. */
315 TAILQ_INSERT_HEAD(&node
->head
, temp
, rr_ll
);
322 cd9660_rrip_initialize_inode(cd9660node
*node
)
324 struct ISO_SUSP_ATTRIBUTES
*attr
;
327 * Inode dependent values - this may change,
328 * but for now virtual files and directories do
329 * not have an inode structure
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
);
338 TAILQ_INSERT_TAIL(&node
->head
, attr
, rr_ll
);
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
);
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
);
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
)))) {
358 cd9660node_susp_create_node(SUSP_TYPE_RRIP
,
359 SUSP_ENTRY_RRIP_PN
, "PN",
361 cd9660node_rrip_pn(attr
, node
->node
);
362 TAILQ_INSERT_TAIL(&node
->head
, attr
, rr_ll
);
368 cd9660_rrip_initialize_node(cd9660node
*node
, cd9660node
*parent
,
369 cd9660node
*grandparent
)
371 struct ISO_SUSP_ATTRIBUTES
*current
= NULL
;
373 assert(node
!= NULL
);
375 if (node
->type
& CD9660_TYPE_DOT
) {
377 * Handle ER - should be the only entry to appear on
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
);
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
);
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
);
402 cd9660_rrip_initialize_inode(node
);
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
409 * The rr_moved_dir needs to be assigned a NM record as well.
411 if (node
== diskStructure
.rr_moved_dir
) {
412 cd9660_rrip_add_NM(node
, RRIP_DEFAULT_MOVE_DIR_NAME
);
414 else if ((node
->node
!= NULL
) &&
415 ((strlen(node
->node
->name
) !=
416 (int)node
->isoDirRecord
->name_len
[0]) ||
417 (memcmp(node
->node
->name
,node
->isoDirRecord
->name
,
418 (int) node
->isoDirRecord
->name_len
[0]) != 0))) {
419 cd9660_rrip_NM(node
);
424 /* Rock ridge directory relocation code here. */
426 /* First handle the CL for the placeholder file. */
427 if (node
->rr_relocated
!= NULL
) {
428 current
= cd9660node_susp_create_node(SUSP_TYPE_RRIP
,
429 SUSP_ENTRY_RRIP_CL
, "CL", SUSP_LOC_ENTRY
);
430 cd9660_rrip_CL(current
, node
);
431 TAILQ_INSERT_TAIL(&node
->head
, current
, rr_ll
);
435 if (node
->rr_real_parent
!= NULL
) {
436 current
= cd9660node_susp_create_node(SUSP_TYPE_RRIP
,
437 SUSP_ENTRY_RRIP_RE
, "RE", SUSP_LOC_ENTRY
);
438 cd9660_rrip_RE(current
,node
);
439 TAILQ_INSERT_TAIL(&node
->head
, current
, rr_ll
);
442 current
= cd9660node_susp_create_node(SUSP_TYPE_RRIP
,
443 SUSP_ENTRY_RRIP_PL
, "PL", SUSP_LOC_DOTDOT
);
444 cd9660_rrip_PL(current
,node
->dot_dot_record
);
445 TAILQ_INSERT_TAIL(&node
->dot_dot_record
->head
, current
,
447 TAILQ_INSERT_TAIL(&node
->head
, current
, rr_ll
);
453 struct ISO_SUSP_ATTRIBUTES
*
454 cd9660node_susp_create_node(int susp_type
, int entry_type
, const char *type_id
,
457 struct ISO_SUSP_ATTRIBUTES
* temp
;
459 if ((temp
= malloc(sizeof(struct ISO_SUSP_ATTRIBUTES
))) == NULL
) {
460 CD9660_MEM_ALLOC_ERROR("cd9660node_susp_create_node");
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] = 0;
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_dev
) > 32)
661 cd9660_bothendian_dword((uint64_t)fnode
->inode
->st
.st_dev
>> 32,
662 pn_field
->attr
.rr_entry
.PN
.high
);
664 cd9660_bothendian_dword(0, pn_field
->attr
.rr_entry
.PN
.high
);
666 cd9660_bothendian_dword(fnode
->inode
->st
.st_dev
& 0xffffffff,
667 pn_field
->attr
.rr_entry
.PN
.low
);
673 cd9660node_rrip_nm(struct ISO_SUSP_ATTRIBUTES
*p
, cd9660node
*file_node
)
675 int nm_length
= strlen(file_node
->isoDirRecord
->name
) + 5;
676 p
->attr
.rr_entry
.NM
.h
.type
[0] = 'N';
677 p
->attr
.rr_entry
.NM
.h
.type
[1] = 'M';
678 sprintf(p
->attr
.rr_entry
.NM
.altname
, "%s", file_node
->isoDirRecord
->name
);
679 p
->attr
.rr_entry
.NM
.h
.length
[0] = (unsigned char)nm_length
;
680 p
->attr
.rr_entry
.NM
.h
.version
[0] = (unsigned char)1;
681 p
->attr
.rr_entry
.NM
.flags
[0] = (unsigned char) NM_PARENT
;
687 cd9660node_rrip_tf(struct ISO_SUSP_ATTRIBUTES
*p
, fsnode
*_node
)
689 p
->attr
.rr_entry
.TF
.flags
[0] = TF_MODIFY
| TF_ACCESS
| TF_ATTRIBUTES
;
690 p
->attr
.rr_entry
.TF
.h
.length
[0] = 4;
691 p
->attr
.rr_entry
.TF
.h
.version
[0] = 1;
694 * Need to add creation time, backup time,
695 * expiration time, and effective time.
698 cd9660_time_915(p
->attr
.rr_entry
.TF
.timestamp
,
699 _node
->inode
->st
.st_atime
);
700 p
->attr
.rr_entry
.TF
.h
.length
[0] += 7;
702 cd9660_time_915(p
->attr
.rr_entry
.TF
.timestamp
+ 7,
703 _node
->inode
->st
.st_mtime
);
704 p
->attr
.rr_entry
.TF
.h
.length
[0] += 7;
706 cd9660_time_915(p
->attr
.rr_entry
.TF
.timestamp
+ 14,
707 _node
->inode
->st
.st_ctime
);
708 p
->attr
.rr_entry
.TF
.h
.length
[0] += 7;
713 cd9660_susp_sp(struct ISO_SUSP_ATTRIBUTES
*p
, cd9660node
*spinfo __unused
)
715 p
->attr
.su_entry
.SP
.h
.length
[0] = 7;
716 p
->attr
.su_entry
.SP
.h
.version
[0] = 1;
717 p
->attr
.su_entry
.SP
.check
[0] = 0xBE;
718 p
->attr
.su_entry
.SP
.check
[1] = 0xEF;
719 p
->attr
.su_entry
.SP
.len_skp
[0] = 0;
724 cd9660_susp_st(struct ISO_SUSP_ATTRIBUTES
*p
, cd9660node
*stinfo __unused
)
726 p
->attr
.su_entry
.ST
.h
.type
[0] = 'S';
727 p
->attr
.su_entry
.ST
.h
.type
[1] = 'T';
728 p
->attr
.su_entry
.ST
.h
.length
[0] = 4;
729 p
->attr
.su_entry
.ST
.h
.version
[0] = 1;
734 cd9660_susp_ce(struct ISO_SUSP_ATTRIBUTES
*p
, cd9660node
*spinfo __unused
)
736 p
->attr
.su_entry
.CE
.h
.length
[0] = 28;
737 p
->attr
.su_entry
.CE
.h
.version
[0] = 1;
738 /* Other attributes dont matter right now, will be updated later */
743 cd9660_susp_pd(struct ISO_SUSP_ATTRIBUTES
*p __unused
, int length __unused
)
749 cd9660_rrip_add_NM(cd9660node
*node
, const char *name
)
753 struct ISO_SUSP_ATTRIBUTES
*r
;
756 * Each NM record has 254 byes to work with. This means that
757 * the name data itself only has 249 bytes to work with. So, a
758 * name with 251 characters would require two nm records.
763 r
= cd9660node_susp_create_node(SUSP_TYPE_RRIP
,
764 SUSP_ENTRY_RRIP_NM
, "NM", SUSP_LOC_ENTRY
);
765 r
->attr
.rr_entry
.NM
.h
.version
[0] = 1;
766 r
->attr
.rr_entry
.NM
.flags
[0] = RRIP_NM_FLAGS_NONE
;
771 r
->attr
.rr_entry
.NM
.flags
[0] = RRIP_NM_FLAGS_CONTINUE
;
775 memcpy(r
->attr
.rr_entry
.NM
.altname
, p
, len
);
776 r
->attr
.rr_entry
.NM
.h
.length
[0] = 5 + len
;
778 TAILQ_INSERT_TAIL(&node
->head
, r
, rr_ll
);
785 cd9660_rrip_NM(cd9660node
*node
)
787 cd9660_rrip_add_NM(node
, node
->node
->name
);
790 struct ISO_SUSP_ATTRIBUTES
*
791 cd9660_susp_ER(cd9660node
*node
,
792 u_char ext_version
, const char* ext_id
, const char* ext_des
,
796 struct ISO_SUSP_ATTRIBUTES
*r
;
798 r
= cd9660node_susp_create_node(SUSP_TYPE_SUSP
,
799 SUSP_ENTRY_SUSP_ER
, "ER", SUSP_LOC_DOT
);
801 /* Fixed data is 8 bytes */
802 r
->attr
.su_entry
.ER
.h
.length
[0] = 8;
803 r
->attr
.su_entry
.ER
.h
.version
[0] = 1;
805 r
->attr
.su_entry
.ER
.len_id
[0] = (u_char
)strlen(ext_id
);
806 r
->attr
.su_entry
.ER
.len_des
[0] = (u_char
)strlen(ext_des
);
807 r
->attr
.su_entry
.ER
.len_src
[0] = (u_char
)strlen(ext_src
);
809 l
= r
->attr
.su_entry
.ER
.len_id
[0] +
810 r
->attr
.su_entry
.ER
.len_src
[0] +
811 r
->attr
.su_entry
.ER
.len_des
[0];
813 /* Everything must fit. */
814 assert(l
+ r
->attr
.su_entry
.ER
.h
.length
[0] <= 254);
816 r
->attr
.su_entry
.ER
.h
.length
[0] += (u_char
)l
;
819 r
->attr
.su_entry
.ER
.ext_ver
[0] = ext_version
;
820 memcpy(r
->attr
.su_entry
.ER
.ext_data
, ext_id
,
821 (int)r
->attr
.su_entry
.ER
.len_id
[0]);
822 l
= (int) r
->attr
.su_entry
.ER
.len_id
[0];
823 memcpy(r
->attr
.su_entry
.ER
.ext_data
+ l
,ext_des
,
824 (int)r
->attr
.su_entry
.ER
.len_des
[0]);
826 l
+= (int)r
->attr
.su_entry
.ER
.len_des
[0];
827 memcpy(r
->attr
.su_entry
.ER
.ext_data
+ l
,ext_src
,
828 (int)r
->attr
.su_entry
.ER
.len_src
[0]);
830 TAILQ_INSERT_TAIL(&node
->head
, r
, rr_ll
);
834 struct ISO_SUSP_ATTRIBUTES
*
835 cd9660_susp_ES(struct ISO_SUSP_ATTRIBUTES
*last __unused
, cd9660node
*node __unused
)