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