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