GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/makefs/cd9660/iso9660_rrip.c Lines: 0 338 0.0 %
Date: 2017-11-07 Branches: 0 189 0.0 %

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