Home | History | Annotate | Line # | Download | only in cd9660
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