Bug Summary

File:src/usr.sbin/makefs/cd9660.c
Warning:line 1423, column 13
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name cd9660.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/makefs/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/makefs -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/makefs/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/makefs/cd9660.c
1/* $OpenBSD: cd9660.c,v 1.23 2022/01/11 05:34:32 jsg Exp $ */
2/* $NetBSD: cd9660.c,v 1.53 2016/11/25 23:02:44 christos 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/*
36 * Copyright (c) 2001 Wasabi Systems, Inc.
37 * All rights reserved.
38 *
39 * Written by Luke Mewburn for Wasabi Systems, Inc.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. All advertising materials mentioning features or use of this software
50 * must display the following acknowledgement:
51 * This product includes software developed for the NetBSD Project by
52 * Wasabi Systems, Inc.
53 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
54 * or promote products derived from this software without specific prior
55 * written permission.
56 *
57 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
59 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
60 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
61 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
62 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
63 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
64 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
65 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
66 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
67 * POSSIBILITY OF SUCH DAMAGE.
68 */
69/*
70 * Copyright (c) 1982, 1986, 1989, 1993
71 * The Regents of the University of California. All rights reserved.
72 *
73 * Redistribution and use in source and binary forms, with or without
74 * modification, are permitted provided that the following conditions
75 * are met:
76 * 1. Redistributions of source code must retain the above copyright
77 * notice, this list of conditions and the following disclaimer.
78 * 2. Redistributions in binary form must reproduce the above copyright
79 * notice, this list of conditions and the following disclaimer in the
80 * documentation and/or other materials provided with the distribution.
81 * 3. Neither the name of the University nor the names of its contributors
82 * may be used to endorse or promote products derived from this software
83 * without specific prior written permission.
84 *
85 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
86 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
87 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
88 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
89 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
90 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
91 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
92 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
93 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
94 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
95 * SUCH DAMAGE.
96 *
97 */
98
99#include <sys/queue.h>
100
101#include <string.h>
102#include <ctype.h>
103#include <inttypes.h>
104#include <limits.h>
105
106#include "makefs.h"
107#include "cd9660.h"
108#include "cd9660/iso9660_rrip.h"
109
110/*
111 * Global variables
112 */
113
114static void cd9660_finalize_PVD(iso9660_disk *);
115static cd9660node *cd9660_allocate_cd9660node(void);
116static void cd9660_set_defaults(iso9660_disk *);
117static int cd9660_arguments_set_string(const char *, const char *, size_t,
118 char, char *);
119static void cd9660_populate_iso_dir_record(
120 struct _iso_directory_record_cd9660 *, u_char, u_char, u_char,
121 const char *);
122static void cd9660_setup_root_node(iso9660_disk *);
123static int cd9660_setup_volume_descriptors(iso9660_disk *);
124#if 0
125static int cd9660_fill_extended_attribute_record(cd9660node *);
126#endif
127static void cd9660_sort_nodes(cd9660node *);
128static int cd9660_translate_node_common(iso9660_disk *, cd9660node *);
129static int cd9660_translate_node(iso9660_disk *, fsnode *, cd9660node *);
130static int cd9660_compare_filename(const char *, const char *);
131static void cd9660_sorted_child_insert(cd9660node *, cd9660node *);
132static int cd9660_handle_collisions(iso9660_disk *, cd9660node *, int);
133static cd9660node *cd9660_rename_filename(iso9660_disk *, cd9660node *, int,
134 int);
135static void cd9660_copy_filenames(iso9660_disk *, cd9660node *);
136static void cd9660_sorting_nodes(cd9660node *);
137static int cd9660_count_collisions(cd9660node *);
138static cd9660node *cd9660_rrip_move_directory(iso9660_disk *, cd9660node *);
139static int cd9660_add_dot_records(iso9660_disk *, cd9660node *);
140
141static void cd9660_convert_structure(iso9660_disk *, fsnode *, cd9660node *, int,
142 int *, int *);
143static void cd9660_free_structure(cd9660node *);
144static int cd9660_generate_path_table(iso9660_disk *);
145static int cd9660_level1_convert_filename(iso9660_disk *, const char *, char *,
146 size_t, int);
147static int cd9660_level2_convert_filename(iso9660_disk *, const char *, char *,
148 size_t, int);
149static int cd9660_convert_filename(iso9660_disk *, const char *, char *, size_t, int);
150static void cd9660_populate_dot_records(iso9660_disk *, cd9660node *);
151static int64_t cd9660_compute_offsets(iso9660_disk *, cd9660node *, int64_t);
152#if 0
153static int cd9660_copy_stat_info(cd9660node *, cd9660node *, int);
154#endif
155static cd9660node *cd9660_create_virtual_entry(iso9660_disk *, const char *,
156 cd9660node *, int, int);
157static cd9660node *cd9660_create_file(iso9660_disk *, const char *,
158 cd9660node *, cd9660node *);
159static cd9660node *cd9660_create_directory(iso9660_disk *, const char *,
160 cd9660node *, cd9660node *);
161static cd9660node *cd9660_create_special_directory(iso9660_disk *, u_char,
162 cd9660node *);
163static int cd9660_add_generic_bootimage(iso9660_disk *, const char *);
164
165
166/*
167 * Allocate and initialize a cd9660node
168 * @returns struct cd9660node * Pointer to new node, or NULL on error
169 */
170static cd9660node *
171cd9660_allocate_cd9660node(void)
172{
173 cd9660node *temp = ecalloc(1, sizeof(*temp));
174 TAILQ_INIT(&temp->cn_children)do { (&temp->cn_children)->tqh_first = ((void *)0);
(&temp->cn_children)->tqh_last = &(&temp->
cn_children)->tqh_first; } while (0)
;
175 temp->parent = temp->dot_record = temp->dot_dot_record = NULL((void *)0);
176 temp->ptnext = temp->ptprev = temp->ptlast = NULL((void *)0);
177 temp->node = NULL((void *)0);
178 temp->isoDirRecord = NULL((void *)0);
179 temp->isoExtAttributes = NULL((void *)0);
180 temp->rr_real_parent = temp->rr_relocated = NULL((void *)0);
181 temp->su_tail_data = NULL((void *)0);
182 return temp;
183}
184
185int cd9660_defaults_set = 0;
186
187/**
188* Set default values for cd9660 extension to makefs
189*/
190static void
191cd9660_set_defaults(iso9660_disk *diskStructure)
192{
193 /*Fix the sector size for now, though the spec allows for other sizes*/
194 diskStructure->sectorSize = 2048;
195
196 /* Set up defaults in our own structure */
197 diskStructure->isoLevel = 2;
198
199 diskStructure->rock_ridge_enabled = 0;
200 diskStructure->rock_ridge_renamed_dir_name = 0;
201 diskStructure->rock_ridge_move_count = 0;
202 diskStructure->rr_moved_dir = 0;
203
204 diskStructure->include_padding_areas = 1;
205
206 /* Spec breaking functionality */
207 diskStructure->allow_deep_trees =
208 diskStructure->allow_multidot =
209 diskStructure->omit_trailing_period = 0;
210
211 /* Make sure the PVD is clear */
212 memset(&diskStructure->primaryDescriptor, 0, 2048);
213
214 memset(diskStructure->primaryDescriptor.publisher_id, 0x20,128);
215 memset(diskStructure->primaryDescriptor.preparer_id, 0x20,128);
216 memset(diskStructure->primaryDescriptor.application_id, 0x20,128);
217 memset(diskStructure->primaryDescriptor.copyright_file_id, 0x20,37);
218 memset(diskStructure->primaryDescriptor.abstract_file_id, 0x20,37);
219 memset(diskStructure->primaryDescriptor.bibliographic_file_id, 0x20,37);
220
221 strlcpy(diskStructure->primaryDescriptor.system_id,"NetBSD", sizeof(diskStructure->primaryDescriptor.system_id));
222
223 cd9660_defaults_set = 1;
224
225 /* Boot support: Initially disabled */
226 diskStructure->has_generic_bootimage = 0;
227 diskStructure->generic_bootimage = NULL((void *)0);
228
229 /*memset(diskStructure->boot_descriptor, 0, 2048);*/
230
231 diskStructure->is_bootable = 0;
232 TAILQ_INIT(&diskStructure->boot_images)do { (&diskStructure->boot_images)->tqh_first = ((void
*)0); (&diskStructure->boot_images)->tqh_last = &
(&diskStructure->boot_images)->tqh_first; } while (
0)
;
233 LIST_INIT(&diskStructure->boot_entries)do { ((&diskStructure->boot_entries)->lh_first) = (
(void *)0); } while (0)
;
234}
235
236void
237cd9660_prep_opts(fsinfo_t *fsopts)
238{
239 iso9660_disk *diskStructure = ecalloc(1, sizeof(*diskStructure));
240
241#define OPT_STR(name){ name, ((void *)0), OPT_STRBUF, 0, 0 } \
242 { name, NULL((void *)0), OPT_STRBUF, 0, 0 }
243
244#define OPT_NUM(name, field, min, max){ name, &diskStructure->field, sizeof(diskStructure->
field) == 8 ? OPT_INT64 : (sizeof(diskStructure->field) ==
4 ? OPT_INT32 : (sizeof(diskStructure->field) == 2 ? OPT_INT16
: OPT_INT8)), min, max }
\
245 { name, &diskStructure->field, \
246 sizeof(diskStructure->field) == 8 ? OPT_INT64 : \
247 (sizeof(diskStructure->field) == 4 ? OPT_INT32 : \
248 (sizeof(diskStructure->field) == 2 ? OPT_INT16 : OPT_INT8)), \
249 min, max }
250
251#define OPT_BOOL(name, field){ name, &diskStructure->field, OPT_BOOL } \
252 { name, &diskStructure->field, OPT_BOOL }
253
254 const option_t cd9660_options[] = {
255 OPT_BOOL("allow-deep-trees", allow_deep_trees){ "allow-deep-trees", &diskStructure->allow_deep_trees
, OPT_BOOL }
,
256 OPT_BOOL("allow-multidot", allow_multidot){ "allow-multidot", &diskStructure->allow_multidot, OPT_BOOL
}
,
257 OPT_STR("applicationid"){ "applicationid", ((void *)0), OPT_STRBUF, 0, 0 },
258 OPT_STR("boot-load-segment"){ "boot-load-segment", ((void *)0), OPT_STRBUF, 0, 0 },
259 OPT_STR("bootimage"){ "bootimage", ((void *)0), OPT_STRBUF, 0, 0 },
260 OPT_STR("generic-bootimage"){ "generic-bootimage", ((void *)0), OPT_STRBUF, 0, 0 },
261 OPT_STR("hard-disk-boot"){ "hard-disk-boot", ((void *)0), OPT_STRBUF, 0, 0 },
262 OPT_NUM("isolevel", isoLevel, 1, 3){ "isolevel", &diskStructure->isoLevel, sizeof(diskStructure
->isoLevel) == 8 ? OPT_INT64 : (sizeof(diskStructure->isoLevel
) == 4 ? OPT_INT32 : (sizeof(diskStructure->isoLevel) == 2
? OPT_INT16 : OPT_INT8)), 1, 3 }
,
263 OPT_STR("label"){ "label", ((void *)0), OPT_STRBUF, 0, 0 },
264 OPT_STR("no-boot"){ "no-boot", ((void *)0), OPT_STRBUF, 0, 0 },
265 OPT_STR("no-emul-boot"){ "no-emul-boot", ((void *)0), OPT_STRBUF, 0, 0 },
266 OPT_BOOL("no-trailing-padding", include_padding_areas){ "no-trailing-padding", &diskStructure->include_padding_areas
, OPT_BOOL }
,
267 OPT_BOOL("omit-trailing-period", omit_trailing_period){ "omit-trailing-period", &diskStructure->omit_trailing_period
, OPT_BOOL }
,
268 OPT_STR("preparer"){ "preparer", ((void *)0), OPT_STRBUF, 0, 0 },
269 OPT_STR("publisher"){ "publisher", ((void *)0), OPT_STRBUF, 0, 0 },
270 OPT_BOOL("rockridge", rock_ridge_enabled){ "rockridge", &diskStructure->rock_ridge_enabled, OPT_BOOL
}
,
271 OPT_STR("volumeid"){ "volumeid", ((void *)0), OPT_STRBUF, 0, 0 },
272 { .name = NULL((void *)0) }
273 };
274
275 fsopts->fs_specific = diskStructure;
276 fsopts->fs_options = copy_opts(cd9660_options);
277
278 cd9660_set_defaults(diskStructure);
279}
280
281void
282cd9660_cleanup_opts(fsinfo_t *fsopts)
283{
284 free(fsopts->fs_specific);
285 free(fsopts->fs_options);
286}
287
288static int
289cd9660_arguments_set_string(const char *val, const char *fieldtitle,
290 size_t length, char testmode, char * dest)
291{
292 size_t len;
293 int test;
294
295 if (val == NULL((void *)0))
296 warnx("error: '%s' requires a string argument", fieldtitle);
297 else if ((len = strlen(val)) <= length) {
298 if (testmode == 'd')
299 test = cd9660_valid_d_chars(val);
300 else
301 test = cd9660_valid_a_chars(val);
302 if (test) {
303 memcpy(dest, val, len);
304 if (test == 2)
305 cd9660_uppercase_characters(dest, len);
306 return 1;
307 } else
308 warnx("error: '%s' must be composed of %c-characters",
309 fieldtitle, testmode);
310 } else
311 warnx("error: '%s' must be at most 32 characters long",
312 fieldtitle);
313 return 0;
314}
315
316/*
317 * Command-line parsing function
318 */
319
320int
321cd9660_parse_opts(const char *option, fsinfo_t *fsopts)
322{
323 int rv, i;
324 iso9660_disk *diskStructure = fsopts->fs_specific;
325 option_t *cd9660_options = fsopts->fs_options;
326 char buf[1024];
327 const char *name;
328
329 assert(option != NULL)((option != ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/cd9660.c"
, 329, __func__, "option != NULL"))
;
330
331 i = set_option(cd9660_options, option, buf, sizeof(buf));
332 if (i == -1)
333 return 0;
334
335 if (cd9660_options[i].name == NULL((void *)0))
336 abort();
337
338
339 name = cd9660_options[i].name;
340
341 if (strcmp(name, "applicationid") == 0) {
342 rv = cd9660_arguments_set_string(buf, name, 128, 'a',
343 diskStructure->primaryDescriptor.application_id);
344 } else if (strcmp(name, "boot-load-segment") == 0) {
345 if (buf[0] == '\0') {
346 warnx("Option `%s' doesn't contain a value",
347 name);
348 rv = 0;
349 } else {
350 cd9660_eltorito_add_boot_option(diskStructure,
351 name, buf);
352 rv = 1;
353 }
354 } else if (strcmp(name, "bootimage") == 0) {
355 if (buf[0] == '\0') {
356 warnx("The Boot Image parameter requires a valid boot"
357 " information string");
358 rv = 0;
359 } else
360 rv = cd9660_add_boot_disk(diskStructure, buf);
361 } else if (strcmp(name, "generic-bootimage") == 0) {
362 if (buf[0] == '\0') {
363 warnx("The Generic Boot Image parameter requires a"
364 " valid boot information string");
365 rv = 0;
366 } else
367 rv = cd9660_add_generic_bootimage(diskStructure, buf);
368 } else if (strcmp(name, "label") == 0) {
369 rv = cd9660_arguments_set_string(buf, name, 32, 'd',
370 diskStructure->primaryDescriptor.volume_id);
371 } else if (strcmp(name, "preparer") == 0) {
372 rv = cd9660_arguments_set_string(buf, name, 128, 'a',
373 diskStructure->primaryDescriptor.preparer_id);
374 } else if (strcmp(name, "publisher") == 0) {
375 rv = cd9660_arguments_set_string(buf, name, 128, 'a',
376 diskStructure->primaryDescriptor.publisher_id);
377 } else if (strcmp(name, "volumeid") == 0) {
378 rv = cd9660_arguments_set_string(buf, name, 128, 'a',
379 diskStructure->primaryDescriptor.volume_set_id);
380 } else if (strcmp(name, "hard-disk-boot") == 0 ||
381 strcmp(name, "no-boot") == 0 ||
382 strcmp(name, "no-emul-boot") == 0) {
383 /* RRIP */
384 cd9660_eltorito_add_boot_option(diskStructure, name, 0);
385 rv = 1;
386 } else
387 rv = 1;
388
389 return rv;
390}
391
392/*
393 * Main function for cd9660_makefs
394 * Builds the ISO image file
395 * @param const char *image The image filename to create
396 * @param const char *dir The directory that is being read
397 * @param struct fsnode *root The root node of the filesystem tree
398 * @param struct fsinfo_t *fsopts Any options
399 */
400void
401cd9660_makefs(const char *image, const char *dir, fsnode *root,
402 fsinfo_t *fsopts)
403{
404 int64_t startoffset;
405 int ret, numDirectories;
406 uint64_t pathTableSectors;
407 int64_t firstAvailableSector;
408 int64_t totalSpace;
409 int error;
410 cd9660node *real_root;
411 iso9660_disk *diskStructure = fsopts->fs_specific;
412
413 if (diskStructure->isoLevel < 2 &&
1
Assuming field 'isoLevel' is >= 2
414 diskStructure->allow_multidot)
415 errx(1, "allow-multidot requires iso level of 2");
416
417 assert(image != NULL)((image != ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/cd9660.c"
, 417, __func__, "image != NULL"))
;
2
Assuming 'image' is not equal to null
3
'?' condition is true
418 assert(dir != NULL)((dir != ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/cd9660.c"
, 418, __func__, "dir != NULL"))
;
4
Assuming 'dir' is not equal to null
5
'?' condition is true
419 assert(root != NULL)((root != ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/cd9660.c"
, 419, __func__, "root != NULL"))
;
6
Assuming 'root' is not equal to null
7
'?' condition is true
420
421 /* Set up some constants. Later, these will be defined with options */
422
423 /* Counter needed for path tables */
424 numDirectories = 0;
425
426 /* Convert tree to our own format */
427 /* Actually, we now need to add the REAL root node, at level 0 */
428
429 real_root = cd9660_allocate_cd9660node();
430 real_root->isoDirRecord = emalloc(sizeof(*real_root->isoDirRecord));
431 /* Leave filename blank for root */
432 memset(real_root->isoDirRecord->name, 0,
433 ISO_FILENAME_MAXLENGTH_WITH_PADDING37);
434
435 real_root->level = 0;
436 diskStructure->rootNode = real_root;
437 real_root->type = CD9660_TYPE_DIR0x02;
438 error = 0;
439 real_root->node = root;
440 cd9660_convert_structure(diskStructure, root, real_root, 1,
441 &numDirectories, &error);
442
443 if (TAILQ_EMPTY(&real_root->cn_children)(((&real_root->cn_children)->tqh_first) == ((void *
)0))
) {
8
Assuming field 'tqh_first' is not equal to null
9
Taking false branch
444 errx(1, "%s: converted directory is empty. "
445 "Tree conversion failed", __func__);
446 } else if (error
9.1
'error' is equal to 0
!= 0) {
10
Taking false branch
447 errx(1, "%s: tree conversion failed", __func__);
448 }
449
450 /* Add the dot and dot dot records */
451 cd9660_add_dot_records(diskStructure, real_root);
452
453 cd9660_setup_root_node(diskStructure);
454
455 /* Rock ridge / SUSP init pass */
456 if (diskStructure->rock_ridge_enabled) {
11
Assuming field 'rock_ridge_enabled' is 0
12
Taking false branch
457 cd9660_susp_initialize(diskStructure, diskStructure->rootNode,
458 diskStructure->rootNode, NULL((void *)0));
459 }
460
461 /* Build path table structure */
462 diskStructure->pathTableLength = cd9660_generate_path_table(
13
Calling 'cd9660_generate_path_table'
463 diskStructure);
464
465 pathTableSectors = CD9660_BLOCKS(diskStructure->sectorSize,((((diskStructure->pathTableLength)) + (((diskStructure->
sectorSize)) - 1)) / ((diskStructure->sectorSize)))
466 diskStructure->pathTableLength)((((diskStructure->pathTableLength)) + (((diskStructure->
sectorSize)) - 1)) / ((diskStructure->sectorSize)))
;
467
468 firstAvailableSector = cd9660_setup_volume_descriptors(diskStructure);
469 if (diskStructure->is_bootable) {
470 firstAvailableSector = cd9660_setup_boot(diskStructure,
471 firstAvailableSector);
472 if (firstAvailableSector < 0)
473 errx(1, "setup_boot failed");
474 }
475 /* LE first, then BE */
476 diskStructure->primaryLittleEndianTableSector = firstAvailableSector;
477 diskStructure->primaryBigEndianTableSector =
478 diskStructure->primaryLittleEndianTableSector + pathTableSectors;
479
480 /* Set the secondary ones to -1, not going to use them for now */
481 diskStructure->secondaryBigEndianTableSector = -1;
482 diskStructure->secondaryLittleEndianTableSector = -1;
483
484 diskStructure->dataFirstSector =
485 diskStructure->primaryBigEndianTableSector + pathTableSectors;
486
487 startoffset = diskStructure->sectorSize*diskStructure->dataFirstSector;
488
489 totalSpace = cd9660_compute_offsets(diskStructure, real_root, startoffset);
490
491 diskStructure->totalSectors = diskStructure->dataFirstSector +
492 CD9660_BLOCKS(diskStructure->sectorSize, totalSpace)((((totalSpace)) + (((diskStructure->sectorSize)) - 1)) / (
(diskStructure->sectorSize)))
;
493
494 /* Disabled until pass 1 is done */
495 if (diskStructure->rock_ridge_enabled) {
496 diskStructure->susp_continuation_area_start_sector =
497 diskStructure->totalSectors;
498 diskStructure->totalSectors +=
499 CD9660_BLOCKS(diskStructure->sectorSize,((((diskStructure->susp_continuation_area_size)) + (((diskStructure
->sectorSize)) - 1)) / ((diskStructure->sectorSize)))
500 diskStructure->susp_continuation_area_size)((((diskStructure->susp_continuation_area_size)) + (((diskStructure
->sectorSize)) - 1)) / ((diskStructure->sectorSize)))
;
501 cd9660_susp_finalize(diskStructure, diskStructure->rootNode);
502 }
503
504
505 cd9660_finalize_PVD(diskStructure);
506
507 /* Add padding sectors, just for testing purposes right now */
508 /* diskStructure->totalSectors+=150; */
509
510 /*
511 * Add padding sectors at the end
512 * TODO: Clean this up and separate padding
513 */
514 if (diskStructure->include_padding_areas)
515 diskStructure->totalSectors += 150;
516
517 ret = cd9660_write_image(diskStructure, image);
518
519 /* Clean up data structures */
520 cd9660_free_structure(real_root);
521
522 if (ret == 0) /* cd9660_write_image() failed */
523 exit(1);
524}
525
526/* Generic function pointer - implement later */
527typedef int (*cd9660node_func)(cd9660node *);
528
529static void
530cd9660_finalize_PVD(iso9660_disk *diskStructure)
531{
532 time_t tstamp = Tflag ? stampts : time(NULL((void *)0));
533
534 /* root should be a fixed size of 34 bytes since it has no name */
535 memcpy(diskStructure->primaryDescriptor.root_directory_record,
536 diskStructure->rootNode->dot_record->isoDirRecord, 34);
537
538 /* In RRIP, this might be longer than 34 */
539 diskStructure->primaryDescriptor.root_directory_record[0] = 34;
540
541 /* Set up all the important numbers in the PVD */
542 cd9660_bothendian_dword(diskStructure->totalSectors,
543 (unsigned char *)diskStructure->primaryDescriptor.volume_space_size);
544 cd9660_bothendian_word(1,
545 (unsigned char *)diskStructure->primaryDescriptor.volume_set_size);
546 cd9660_bothendian_word(1,
547 (unsigned char *)
548 diskStructure->primaryDescriptor.volume_sequence_number);
549 cd9660_bothendian_word(diskStructure->sectorSize,
550 (unsigned char *)
551 diskStructure->primaryDescriptor.logical_block_size);
552 cd9660_bothendian_dword(diskStructure->pathTableLength,
553 (unsigned char *)diskStructure->primaryDescriptor.path_table_size);
554
555 cd9660_731(diskStructure->primaryLittleEndianTableSector,
556 (u_char *)diskStructure->primaryDescriptor.type_l_path_table);
557 cd9660_732(diskStructure->primaryBigEndianTableSector,
558 (u_char *)diskStructure->primaryDescriptor.type_m_path_table);
559
560 diskStructure->primaryDescriptor.file_structure_version[0] = 1;
561
562 /* Pad all strings with spaces instead of nulls */
563 cd9660_pad_string_spaces(diskStructure->primaryDescriptor.volume_id, 32);
564 cd9660_pad_string_spaces(diskStructure->primaryDescriptor.system_id, 32);
565 cd9660_pad_string_spaces(diskStructure->primaryDescriptor.volume_set_id,
566 128);
567 cd9660_pad_string_spaces(diskStructure->primaryDescriptor.publisher_id,
568 128);
569 cd9660_pad_string_spaces(diskStructure->primaryDescriptor.preparer_id,
570 128);
571 cd9660_pad_string_spaces(diskStructure->primaryDescriptor.application_id,
572 128);
573 cd9660_pad_string_spaces(
574 diskStructure->primaryDescriptor.copyright_file_id, 37);
575 cd9660_pad_string_spaces(
576 diskStructure->primaryDescriptor.abstract_file_id, 37);
577 cd9660_pad_string_spaces(
578 diskStructure->primaryDescriptor.bibliographic_file_id, 37);
579
580 /* Setup dates */
581 cd9660_time_8426(
582 (unsigned char *)diskStructure->primaryDescriptor.creation_date,
583 tstamp);
584 cd9660_time_8426(
585 (unsigned char *)diskStructure->primaryDescriptor.modification_date,
586 tstamp);
587
588#if 0
589 cd9660_set_date(diskStructure->primaryDescriptor.expiration_date,
590 tstamp);
591#endif
592 memset(diskStructure->primaryDescriptor.expiration_date, '0' ,16);
593 diskStructure->primaryDescriptor.expiration_date[16] = 0;
594
595 cd9660_time_8426(
596 (unsigned char *)diskStructure->primaryDescriptor.effective_date,
597 tstamp);
598}
599
600static void
601cd9660_populate_iso_dir_record(struct _iso_directory_record_cd9660 *record,
602 u_char ext_attr_length, u_char flags,
603 u_char name_len, const char * name)
604{
605 record->ext_attr_length[0] = ext_attr_length;
606 record->flags[0] = ISO_FLAG_CLEAR0x00 | flags;
607 record->file_unit_size[0] = 0;
608 record->interleave[0] = 0;
609 cd9660_bothendian_word(1, record->volume_sequence_number);
610 record->name_len[0] = name_len;
611 memset(record->name, '\0', sizeof (record->name));
612 memcpy(record->name, name, name_len);
613 record->length[0] = 33 + name_len;
614
615 /* Todo : better rounding */
616 record->length[0] += (record->length[0] & 1) ? 1 : 0;
617}
618
619static void
620cd9660_setup_root_node(iso9660_disk *diskStructure)
621{
622 cd9660_populate_iso_dir_record(diskStructure->rootNode->isoDirRecord,
623 0, ISO_FLAG_DIRECTORY0x02, 1, "\0");
624
625}
626
627/*********** SUPPORT FUNCTIONS ***********/
628static int
629cd9660_setup_volume_descriptors(iso9660_disk *diskStructure)
630{
631 /* Boot volume descriptor should come second */
632 int sector = 16;
633 /* For now, a fixed 2 : PVD and terminator */
634 volume_descriptor *temp, *t;
635
636 /* Set up the PVD */
637 temp = emalloc(sizeof(*temp));
638 temp->volumeDescriptorData =
639 (unsigned char *)&diskStructure->primaryDescriptor;
640 temp->volumeDescriptorData[0] = ISO_VOLUME_DESCRIPTOR_PVD1;
641 temp->volumeDescriptorData[6] = 1;
642 temp->sector = sector;
643 memcpy(temp->volumeDescriptorData + 1,
644 ISO_VOLUME_DESCRIPTOR_STANDARD_ID"CD001", 5);
645 diskStructure->firstVolumeDescriptor = temp;
646
647 sector++;
648 /* Set up boot support if enabled. BVD must reside in sector 17 */
649 if (diskStructure->is_bootable) {
650 t = emalloc(sizeof(*t));
651 t->volumeDescriptorData = ecalloc(1, 2048);
652 temp->next = t;
653 temp = t;
654 t->sector = 17;
655 cd9660_setup_boot_volume_descriptor(diskStructure, t);
656 sector++;
657 }
658
659 /* Set up the terminator */
660 t = emalloc(sizeof(*t));
661 t->volumeDescriptorData = ecalloc(1, 2048);
662 temp->next = t;
663 t->volumeDescriptorData[0] = ISO_VOLUME_DESCRIPTOR_TERMINATOR255;
664 t->next = 0;
665 t->volumeDescriptorData[6] = 1;
666 t->sector = sector;
667 memcpy(t->volumeDescriptorData + 1,
668 ISO_VOLUME_DESCRIPTOR_STANDARD_ID"CD001", 5);
669
670 sector++;
671 return sector;
672}
673
674#if 0
675/*
676 * Populate EAR at some point. Not required, but is used by NetBSD's
677 * cd9660 support
678 */
679static int
680cd9660_fill_extended_attribute_record(cd9660node *node)
681{
682 node->isoExtAttributes = emalloc(sizeof(*node->isoExtAttributes));
683 return 1;
684}
685#endif
686
687static int
688cd9660_translate_node_common(iso9660_disk *diskStructure, cd9660node *newnode)
689{
690 time_t tstamp = Tflag ? stampts : time(NULL((void *)0));
691 u_char flag;
692 char temp[ISO_FILENAME_MAXLENGTH_WITH_PADDING37];
693
694 /* Now populate the isoDirRecord structure */
695 memset(temp, 0, ISO_FILENAME_MAXLENGTH_WITH_PADDING37);
696
697 (void)cd9660_convert_filename(diskStructure, newnode->node->name,
698 temp, sizeof temp, !(S_ISDIR(newnode->node->type)((newnode->node->type & 0170000) == 0040000)));
699
700 flag = ISO_FLAG_CLEAR0x00;
701 if (S_ISDIR(newnode->node->type)((newnode->node->type & 0170000) == 0040000))
702 flag |= ISO_FLAG_DIRECTORY0x02;
703
704 cd9660_populate_iso_dir_record(newnode->isoDirRecord, 0,
705 flag, strlen(temp), temp);
706
707 /* Set the various dates */
708
709 /* If we want to use the current date and time */
710
711 cd9660_time_915(newnode->isoDirRecord->date, tstamp);
712
713 cd9660_bothendian_dword(newnode->fileDataLength,
714 newnode->isoDirRecord->size);
715 /* If the file is a link, we want to set the size to 0 */
716 if (S_ISLNK(newnode->node->type)((newnode->node->type & 0170000) == 0120000))
717 newnode->fileDataLength = 0;
718
719 return 1;
720}
721
722/*
723 * Translate fsnode to cd9660node
724 * Translate filenames and other metadata, including dates, sizes,
725 * permissions, etc
726 * @param struct fsnode * The node generated by makefs
727 * @param struct cd9660node * The intermediate node to be written to
728 * @returns int 0 on failure, 1 on success
729 */
730static int
731cd9660_translate_node(iso9660_disk *diskStructure, fsnode *node,
732 cd9660node *newnode)
733{
734 if (node == NULL((void *)0))
735 return 0;
736
737 newnode->isoDirRecord = emalloc(sizeof(*newnode->isoDirRecord));
738 /* Set the node pointer */
739 newnode->node = node;
740
741 /* Set the size */
742 if (!(S_ISDIR(node->type)((node->type & 0170000) == 0040000)))
743 newnode->fileDataLength = node->inode->st.st_size;
744
745 if (cd9660_translate_node_common(diskStructure, newnode) == 0)
746 return 0;
747
748 /* Finally, overwrite some of the values that are set by default */
749 cd9660_time_915(newnode->isoDirRecord->date,
750 Tflag ? stampts : node->inode->st.st_mtimest_mtim.tv_sec);
751
752 return 1;
753}
754
755/*
756 * Compares two ISO filenames
757 * @param const char * The first file name
758 * @param const char * The second file name
759 * @returns : -1 if first is less than second, 0 if they are the same, 1 if
760 * the second is greater than the first
761 */
762static int
763cd9660_compare_filename(const char *first, const char *second)
764{
765 /*
766 * This can be made more optimal once it has been tested
767 * (the extra character, for example, is for testing)
768 */
769
770 int p1 = 0;
771 int p2 = 0;
772 char c1, c2;
773 /* First, on the filename */
774
775 while (p1 < ISO_FILENAME_MAXLENGTH_BEFORE_VERSION30-1
776 && p2 < ISO_FILENAME_MAXLENGTH_BEFORE_VERSION30-1) {
777 c1 = first[p1];
778 c2 = second[p2];
779 if (c1 == '.' && c2 =='.')
780 break;
781 else if (c1 == '.') {
782 p2++;
783 c1 = ' ';
784 } else if (c2 == '.') {
785 p1++;
786 c2 = ' ';
787 } else {
788 p1++;
789 p2++;
790 }
791
792 if (c1 < c2)
793 return -1;
794 else if (c1 > c2) {
795 return 1;
796 }
797 }
798
799 if (first[p1] == '.' && second[p2] == '.') {
800 p1++;
801 p2++;
802 while (p1 < ISO_FILENAME_MAXLENGTH_BEFORE_VERSION30 - 1
803 && p2 < ISO_FILENAME_MAXLENGTH_BEFORE_VERSION30 - 1) {
804 c1 = first[p1];
805 c2 = second[p2];
806 if (c1 == ';' && c2 == ';')
807 break;
808 else if (c1 == ';') {
809 p2++;
810 c1 = ' ';
811 } else if (c2 == ';') {
812 p1++;
813 c2 = ' ';
814 } else {
815 p1++;
816 p2++;
817 }
818
819 if (c1 < c2)
820 return -1;
821 else if (c1 > c2)
822 return 1;
823 }
824 }
825 return 0;
826}
827
828/*
829 * Insert a node into list with ISO sorting rules
830 * @param cd9660node * The head node of the list
831 * @param cd9660node * The node to be inserted
832 */
833static void
834cd9660_sorted_child_insert(cd9660node *parent, cd9660node *cn_new)
835{
836 int compare;
837 cd9660node *cn;
838 struct cd9660_children_head *head = &parent->cn_children;
839
840 /* TODO: Optimize? */
841 cn_new->parent = parent;
842
843 /*
844 * first will either be 0, the . or the ..
845 * if . or .., this means no other entry may be written before first
846 * if 0, the new node may be inserted at the head
847 */
848
849 TAILQ_FOREACH(cn, head, cn_next_child)for((cn) = ((head)->tqh_first); (cn) != ((void *)0); (cn) =
((cn)->cn_next_child.tqe_next))
{
850 /*
851 * Dont insert a node twice -
852 * that would cause an infinite loop
853 */
854 if (cn_new == cn)
855 return;
856
857 compare = cd9660_compare_filename(cn_new->isoDirRecord->name,
858 cn->isoDirRecord->name);
859
860 if (compare == 0)
861 compare = cd9660_compare_filename(cn_new->node->name,
862 cn->node->name);
863
864 if (compare < 0)
865 break;
866 }
867 if (cn == NULL((void *)0))
868 TAILQ_INSERT_TAIL(head, cn_new, cn_next_child)do { (cn_new)->cn_next_child.tqe_next = ((void *)0); (cn_new
)->cn_next_child.tqe_prev = (head)->tqh_last; *(head)->
tqh_last = (cn_new); (head)->tqh_last = &(cn_new)->
cn_next_child.tqe_next; } while (0)
;
869 else
870 TAILQ_INSERT_BEFORE(cn, cn_new, cn_next_child)do { (cn_new)->cn_next_child.tqe_prev = (cn)->cn_next_child
.tqe_prev; (cn_new)->cn_next_child.tqe_next = (cn); *(cn)->
cn_next_child.tqe_prev = (cn_new); (cn)->cn_next_child.tqe_prev
= &(cn_new)->cn_next_child.tqe_next; } while (0)
;
871}
872
873/*
874 * Called After cd9660_sorted_child_insert
875 * handles file collisions by suffixing each filename with ~n
876 * where n represents the files respective place in the ordering
877 */
878static int
879cd9660_handle_collisions(iso9660_disk *diskStructure, cd9660node *colliding,
880 int past)
881{
882 cd9660node *iter, *next, *prev;
883 int skip;
884 int delete_chars = 0;
885 int temp_past = past;
886 int temp_skip;
887 int flag = 0;
888 cd9660node *end_of_range;
889
890 for (iter = TAILQ_FIRST(&colliding->cn_children)((&colliding->cn_children)->tqh_first);
891 iter != NULL((void *)0) && (next = TAILQ_NEXT(iter, cn_next_child)((iter)->cn_next_child.tqe_next)) != NULL((void *)0);) {
892 if (strcmp(iter->isoDirRecord->name,
893 next->isoDirRecord->name) != 0) {
894 iter = TAILQ_NEXT(iter, cn_next_child)((iter)->cn_next_child.tqe_next);
895 continue;
896 }
897 flag = 1;
898 temp_skip = skip = cd9660_count_collisions(iter);
899 end_of_range = iter;
900 while (temp_skip > 0) {
901 temp_skip--;
902 end_of_range = TAILQ_NEXT(end_of_range, cn_next_child)((end_of_range)->cn_next_child.tqe_next);
903 }
904 temp_past = past;
905 while (temp_past > 0) {
906 if ((next = TAILQ_NEXT(end_of_range, cn_next_child)((end_of_range)->cn_next_child.tqe_next)) != NULL((void *)0))
907 end_of_range = next;
908 else if ((prev = TAILQ_PREV(iter, cd9660_children_head, cn_next_child)(*(((struct cd9660_children_head *)((iter)->cn_next_child.
tqe_prev))->tqh_last))
) != NULL((void *)0))
909 iter = prev;
910 else
911 delete_chars++;
912 temp_past--;
913 }
914 skip += past;
915 iter = cd9660_rename_filename(diskStructure, iter, skip,
916 delete_chars);
917 }
918 return flag;
919}
920
921
922static cd9660node *
923cd9660_rename_filename(iso9660_disk *diskStructure, cd9660node *iter, int num,
924 int delete_chars)
925{
926 int i = 0;
927 int numbts, dot, semi, digit, digits, temp, powers, multiplier, count;
928 char *naming;
929 int maxlength;
930 char *tmp;
931
932 /* TODO : A LOT of chanes regarding 8.3 filenames */
933 if (diskStructure->isoLevel == 1)
934 maxlength = 8;
935 else if (diskStructure->isoLevel == 2)
936 maxlength = 31;
937 else
938 maxlength = ISO_FILENAME_MAXLENGTH_BEFORE_VERSION30;
939
940 tmp = emalloc(ISO_FILENAME_MAXLENGTH_WITH_PADDING37);
941
942 while (i < num && iter) {
943 powers = 1;
944 count = 0;
945 digits = 1;
946 multiplier = 1;
947 while (((int)(i / powers) ) >= 10) {
948 digits++;
949 powers = powers * 10;
950 }
951
952 naming = iter->o_name;
953
954 /*
955 while ((*naming != '.') && (*naming != ';')) {
956 naming++;
957 count++;
958 }
959 */
960
961 dot = -1;
962 semi = -1;
963 while (count < maxlength) {
964 if (*naming == '.')
965 dot = count;
966 else if (*naming == ';') {
967 semi = count;
968 break;
969 }
970 naming++;
971 count++;
972 }
973
974 if ((count + digits) < maxlength)
975 numbts = count;
976 else
977 numbts = maxlength - (digits);
978 numbts -= delete_chars;
979
980 /* 8.3 rules - keep the extension, add before the dot */
981
982 /*
983 * This code makes a bunch of assumptions.
984 * See if you can spot them all :)
985 */
986
987#if 0
988 if (diskStructure->isoLevel == 1) {
989 numbts = 8 - digits - delete_chars;
990 if (dot < 0) {
991
992 } else {
993 if (dot < 8) {
994 memmove(&tmp[numbts],&tmp[dot],4);
995 }
996 }
997 }
998#else
999 (void)dot;
1000 (void)semi;
1001 (void)multiplier;
1002#endif
1003
1004 /* (copying just the filename before the '.' */
1005 memcpy(tmp, (iter->o_name), numbts);
1006
1007 /* adding the appropriate number following the name */
1008 temp = i;
1009 while (digits > 0) {
1010 digit = (int)(temp / powers);
1011 temp = temp - digit * powers;
1012 snprintf(&tmp[numbts] , ISO_FILENAME_MAXLENGTH_WITH_PADDING37 - numbts, "%d", digit);
1013 digits--;
1014 numbts++;
1015 powers = powers / 10;
1016 }
1017
1018 while ((*naming != ';') && (numbts < maxlength)) {
1019 tmp[numbts] = (*naming);
1020 naming++;
1021 numbts++;
1022 }
1023
1024 tmp[numbts] = ';';
1025 tmp[numbts+1] = '1';
1026 tmp[numbts+2] = '\0';
1027
1028 /*
1029 * now tmp has exactly the identifier
1030 * we want so we'll copy it back to record
1031 */
1032 memcpy((iter->isoDirRecord->name), tmp, numbts + 3);
1033
1034 iter = TAILQ_NEXT(iter, cn_next_child)((iter)->cn_next_child.tqe_next);
1035 i++;
1036 }
1037
1038 free(tmp);
1039 return iter;
1040}
1041
1042/* Todo: Figure out why these functions are nec. */
1043static void
1044cd9660_copy_filenames(iso9660_disk *diskStructure, cd9660node *node)
1045{
1046 cd9660node *cn;
1047
1048 if (TAILQ_EMPTY(&node->cn_children)(((&node->cn_children)->tqh_first) == ((void *)0)))
1049 return;
1050
1051 if (TAILQ_FIRST(&node->cn_children)((&node->cn_children)->tqh_first)->isoDirRecord == NULL((void *)0)) {
1052 debug_print_tree(diskStructure, diskStructure->rootNode, 0);
1053 exit(1);
1054 }
1055
1056 TAILQ_FOREACH(cn, &node->cn_children, cn_next_child)for((cn) = ((&node->cn_children)->tqh_first); (cn) !=
((void *)0); (cn) = ((cn)->cn_next_child.tqe_next))
{
1057 cd9660_copy_filenames(diskStructure, cn);
1058 memcpy(cn->o_name, cn->isoDirRecord->name,
1059 ISO_FILENAME_MAXLENGTH_WITH_PADDING37);
1060 }
1061}
1062
1063static void
1064cd9660_sorting_nodes(cd9660node *node)
1065{
1066 cd9660node *cn;
1067
1068 TAILQ_FOREACH(cn, &node->cn_children, cn_next_child)for((cn) = ((&node->cn_children)->tqh_first); (cn) !=
((void *)0); (cn) = ((cn)->cn_next_child.tqe_next))
1069 cd9660_sorting_nodes(cn);
1070 cd9660_sort_nodes(node);
1071}
1072
1073/* XXX Bubble sort. */
1074static void
1075cd9660_sort_nodes(cd9660node *node)
1076{
1077 cd9660node *cn, *next;
1078
1079 do {
1080 TAILQ_FOREACH(cn, &node->cn_children, cn_next_child)for((cn) = ((&node->cn_children)->tqh_first); (cn) !=
((void *)0); (cn) = ((cn)->cn_next_child.tqe_next))
{
1081 if ((next = TAILQ_NEXT(cn, cn_next_child)((cn)->cn_next_child.tqe_next)) == NULL((void *)0))
1082 return;
1083 else if (strcmp(next->isoDirRecord->name,
1084 cn->isoDirRecord->name) >= 0)
1085 continue;
1086 TAILQ_REMOVE(&node->cn_children, next, cn_next_child)do { if (((next)->cn_next_child.tqe_next) != ((void *)0)) (
next)->cn_next_child.tqe_next->cn_next_child.tqe_prev =
(next)->cn_next_child.tqe_prev; else (&node->cn_children
)->tqh_last = (next)->cn_next_child.tqe_prev; *(next)->
cn_next_child.tqe_prev = (next)->cn_next_child.tqe_next; ;
; } while (0)
;
1087 TAILQ_INSERT_BEFORE(cn, next, cn_next_child)do { (next)->cn_next_child.tqe_prev = (cn)->cn_next_child
.tqe_prev; (next)->cn_next_child.tqe_next = (cn); *(cn)->
cn_next_child.tqe_prev = (next); (cn)->cn_next_child.tqe_prev
= &(next)->cn_next_child.tqe_next; } while (0)
;
1088 break;
1089 }
1090 } while (cn != NULL((void *)0));
1091}
1092
1093static int
1094cd9660_count_collisions(cd9660node *copy)
1095{
1096 int count = 0;
1097 cd9660node *iter, *next;
1098
1099 for (iter = copy;
1100 (next = TAILQ_NEXT(iter, cn_next_child)((iter)->cn_next_child.tqe_next)) != NULL((void *)0);
1101 iter = next) {
1102 if (cd9660_compare_filename(iter->isoDirRecord->name,
1103 next->isoDirRecord->name) == 0)
1104 count++;
1105 else
1106 return count;
1107 }
1108#if 0
1109 if ((next = TAILQ_NEXT(iter, cn_next_child)((iter)->cn_next_child.tqe_next)) != NULL((void *)0)) {
1110 printf("%s: count is %i \n", __func__, count);
1111 compare = cd9660_compare_filename(iter->isoDirRecord->name,
1112 next->isoDirRecord->name);
1113 if (compare == 0) {
1114 count++;
1115 return cd9660_recurse_on_collision(next, count);
1116 } else
1117 return count;
1118 }
1119#endif
1120 return count;
1121}
1122
1123static cd9660node *
1124cd9660_rrip_move_directory(iso9660_disk *diskStructure, cd9660node *dir)
1125{
1126 char newname[9];
1127 cd9660node *tfile;
1128
1129 /*
1130 * This function needs to:
1131 * 1) Create an empty virtual file in place of the old directory
1132 * 2) Point the virtual file to the new directory
1133 * 3) Point the relocated directory to its old parent
1134 * 4) Move the directory specified by dir into rr_moved_dir,
1135 * and rename it to "diskStructure->rock_ridge_move_count" (as a string)
1136 */
1137
1138 /* First see if the moved directory even exists */
1139 if (diskStructure->rr_moved_dir == NULL((void *)0)) {
1140 diskStructure->rr_moved_dir = cd9660_create_directory(
1141 diskStructure, ISO_RRIP_DEFAULT_MOVE_DIR_NAME"RR_MOVED",
1142 diskStructure->rootNode, dir);
1143 if (diskStructure->rr_moved_dir == NULL((void *)0))
1144 return 0;
1145 cd9660_time_915(diskStructure->rr_moved_dir->isoDirRecord->date,
1146 Tflag ? stampts : start_time.tv_sec);
1147 }
1148
1149 /* Create a file with the same ORIGINAL name */
1150 tfile = cd9660_create_file(diskStructure, dir->node->name, dir->parent,
1151 dir);
1152 if (tfile == NULL((void *)0))
1153 return NULL((void *)0);
1154
1155 diskStructure->rock_ridge_move_count++;
1156 snprintf(newname, sizeof(newname), "%08i",
1157 diskStructure->rock_ridge_move_count);
1158
1159 /* Point to old parent */
1160 dir->rr_real_parent = dir->parent;
1161
1162 /* Place the placeholder file */
1163 if (TAILQ_EMPTY(&dir->rr_real_parent->cn_children)(((&dir->rr_real_parent->cn_children)->tqh_first
) == ((void *)0))
) {
1164 TAILQ_INSERT_HEAD(&dir->rr_real_parent->cn_children, tfile,do { if (((tfile)->cn_next_child.tqe_next = (&dir->
rr_real_parent->cn_children)->tqh_first) != ((void *)0)
) (&dir->rr_real_parent->cn_children)->tqh_first
->cn_next_child.tqe_prev = &(tfile)->cn_next_child.
tqe_next; else (&dir->rr_real_parent->cn_children)->
tqh_last = &(tfile)->cn_next_child.tqe_next; (&dir
->rr_real_parent->cn_children)->tqh_first = (tfile);
(tfile)->cn_next_child.tqe_prev = &(&dir->rr_real_parent
->cn_children)->tqh_first; } while (0)
1165 cn_next_child)do { if (((tfile)->cn_next_child.tqe_next = (&dir->
rr_real_parent->cn_children)->tqh_first) != ((void *)0)
) (&dir->rr_real_parent->cn_children)->tqh_first
->cn_next_child.tqe_prev = &(tfile)->cn_next_child.
tqe_next; else (&dir->rr_real_parent->cn_children)->
tqh_last = &(tfile)->cn_next_child.tqe_next; (&dir
->rr_real_parent->cn_children)->tqh_first = (tfile);
(tfile)->cn_next_child.tqe_prev = &(&dir->rr_real_parent
->cn_children)->tqh_first; } while (0)
;
1166 } else {
1167 cd9660_sorted_child_insert(dir->rr_real_parent, tfile);
1168 }
1169
1170 /* Point to new parent */
1171 dir->parent = diskStructure->rr_moved_dir;
1172
1173 /* Point the file to the moved directory */
1174 tfile->rr_relocated = dir;
1175
1176 /* Actually move the directory */
1177 cd9660_sorted_child_insert(diskStructure->rr_moved_dir, dir);
1178
1179 /* TODO: Inherit permissions / ownership (basically the entire inode) */
1180
1181 /* Set the new name */
1182 memset(dir->isoDirRecord->name, 0, ISO_FILENAME_MAXLENGTH_WITH_PADDING37);
1183 strncpy(dir->isoDirRecord->name, newname, 8);
1184 dir->isoDirRecord->length[0] = 34 + 8;
1185 dir->isoDirRecord->name_len[0] = 8;
1186
1187 return dir;
1188}
1189
1190static int
1191cd9660_add_dot_records(iso9660_disk *diskStructure, cd9660node *root)
1192{
1193 struct cd9660_children_head *head = &root->cn_children;
1194 cd9660node *cn;
1195
1196 TAILQ_FOREACH(cn, head, cn_next_child)for((cn) = ((head)->tqh_first); (cn) != ((void *)0); (cn) =
((cn)->cn_next_child.tqe_next))
{
1197 if ((cn->type & CD9660_TYPE_DIR0x02) == 0)
1198 continue;
1199 /* Recursion first */
1200 cd9660_add_dot_records(diskStructure, cn);
1201 }
1202 cd9660_create_special_directory(diskStructure, CD9660_TYPE_DOT0x04, root);
1203 cd9660_create_special_directory(diskStructure, CD9660_TYPE_DOTDOT0x08,
1204 root);
1205 return 1;
1206}
1207
1208/*
1209 * Convert node to cd9660 structure
1210 * This function is designed to be called recursively on the root node of
1211 * the filesystem
1212 * Lots of recursion going on here, want to make sure it is efficient
1213 * @param struct fsnode * The root node to be converted
1214 * @param struct cd9660* The parent node (should not be NULL)
1215 * @param int Current directory depth
1216 * @param int* Running count of the number of directories that are being created
1217 */
1218static void
1219cd9660_convert_structure(iso9660_disk *diskStructure, fsnode *root,
1220 cd9660node *parent_node, int level, int *numDirectories, int *error)
1221{
1222 fsnode *iterator = root;
1223 cd9660node *this_node;
1224 int working_level;
1225 int add;
1226 int flag = 0;
1227 int counter = 0;
1228
1229 /*
1230 * Newer, more efficient method, reduces recursion depth
1231 */
1232 if (root == NULL((void *)0)) {
1233 warnx("%s: root is null", __func__);
1234 return;
1235 }
1236
1237 /* Test for an empty directory - makefs still gives us the . record */
1238 if ((S_ISDIR(root->type)((root->type & 0170000) == 0040000)) && (root->name[0] == '.')
1239 && (root->name[1] == '\0')) {
1240 root = root->next;
1241 if (root == NULL((void *)0))
1242 return;
1243 }
1244 if ((this_node = cd9660_allocate_cd9660node()) == NULL((void *)0)) {
1245 CD9660_MEM_ALLOC_ERROR(__func__)err(1, "%s, %s l. %d", __func__, "/usr/src/usr.sbin/makefs/cd9660.c"
, 1245)
;
1246 }
1247
1248 /*
1249 * To reduce the number of recursive calls, we will iterate over
1250 * the next pointers to the right.
1251 */
1252 while (iterator != NULL((void *)0)) {
1253 add = 1;
1254 /*
1255 * Increment the directory count if this is a directory
1256 * Ignore "." entries. We will generate them later
1257 */
1258 if (!S_ISDIR(iterator->type)((iterator->type & 0170000) == 0040000) ||
1259 strcmp(iterator->name, ".") != 0) {
1260
1261 /* Translate the node, including its filename */
1262 this_node->parent = parent_node;
1263 cd9660_translate_node(diskStructure, iterator,
1264 this_node);
1265 this_node->level = level;
1266
1267 if (S_ISDIR(iterator->type)((iterator->type & 0170000) == 0040000)) {
1268 (*numDirectories)++;
1269 this_node->type = CD9660_TYPE_DIR0x02;
1270 working_level = level + 1;
1271
1272 /*
1273 * If at level 8, directory would be at 8
1274 * and have children at 9 which is not
1275 * allowed as per ISO spec
1276 */
1277 if (level == 8) {
1278 if ((!diskStructure->allow_deep_trees) &&
1279 (!diskStructure->rock_ridge_enabled)) {
1280 warnx("error: found entry "
1281 "with depth greater "
1282 "than 8.");
1283 (*error) = 1;
1284 return;
1285 } else if (diskStructure->
1286 rock_ridge_enabled) {
1287 working_level = 3;
1288 /*
1289 * Moved directory is actually
1290 * at level 2.
1291 */
1292 this_node->level =
1293 working_level - 1;
1294 if (cd9660_rrip_move_directory(
1295 diskStructure,
1296 this_node) == 0) {
1297 warnx("Failure in "
1298 "cd9660_rrip_"
1299 "move_directory"
1300 );
1301 (*error) = 1;
1302 return;
1303 }
1304 add = 0;
1305 }
1306 }
1307
1308 /* Do the recursive call on the children */
1309 if (iterator->child != 0) {
1310 cd9660_convert_structure(diskStructure,
1311 iterator->child, this_node,
1312 working_level,
1313 numDirectories, error);
1314
1315 if ((*error) == 1) {
1316 warnx("%s: Error on recursive "
1317 "call", __func__);
1318 return;
1319 }
1320 }
1321
1322 } else {
1323 /* Only directories should have children */
1324 assert(iterator->child == NULL)((iterator->child == ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/cd9660.c"
, 1324, __func__, "iterator->child == NULL"))
;
1325
1326 this_node->type = CD9660_TYPE_FILE0x01;
1327 }
1328
1329 /*
1330 * Finally, do a sorted insert
1331 */
1332 if (add) {
1333 cd9660_sorted_child_insert(
1334 parent_node, this_node);
1335 }
1336
1337 /*Allocate new temp_node */
1338 if (iterator->next != 0) {
1339 this_node = cd9660_allocate_cd9660node();
1340 if (this_node == NULL((void *)0))
1341 CD9660_MEM_ALLOC_ERROR(__func__)err(1, "%s, %s l. %d", __func__, "/usr/src/usr.sbin/makefs/cd9660.c"
, 1341)
;
1342 }
1343 }
1344 iterator = iterator->next;
1345 }
1346
1347 /* cd9660_handle_collisions(first_node); */
1348
1349 /* TODO: need cleanup */
1350 cd9660_copy_filenames(diskStructure, parent_node);
1351
1352 do {
1353 flag = cd9660_handle_collisions(diskStructure, parent_node,
1354 counter);
1355 counter++;
1356 cd9660_sorting_nodes(parent_node);
1357 } while ((flag == 1) && (counter < 100));
1358}
1359
1360/*
1361 * Clean up the cd9660node tree
1362 * This is designed to be called recursively on the root node
1363 * @param struct cd9660node *root The node to free
1364 * @returns void
1365 */
1366static void
1367cd9660_free_structure(cd9660node *root)
1368{
1369 cd9660node *cn;
1370
1371 while ((cn = TAILQ_FIRST(&root->cn_children)((&root->cn_children)->tqh_first)) != NULL((void *)0)) {
1372 TAILQ_REMOVE(&root->cn_children, cn, cn_next_child)do { if (((cn)->cn_next_child.tqe_next) != ((void *)0)) (cn
)->cn_next_child.tqe_next->cn_next_child.tqe_prev = (cn
)->cn_next_child.tqe_prev; else (&root->cn_children
)->tqh_last = (cn)->cn_next_child.tqe_prev; *(cn)->cn_next_child
.tqe_prev = (cn)->cn_next_child.tqe_next; ; ; } while (0)
;
1373 cd9660_free_structure(cn);
1374 }
1375 free(root);
1376}
1377
1378/*
1379 * Be a little more memory conservative:
1380 * instead of having the TAILQ_ENTRY as part of the cd9660node,
1381 * just create a temporary structure
1382 */
1383struct ptq_entry
1384{
1385 TAILQ_ENTRY(ptq_entry)struct { struct ptq_entry *tqe_next; struct ptq_entry **tqe_prev
; }
ptq;
1386 cd9660node *node;
1387} *n;
1388
1389#define PTQUEUE_NEW(n,s,r,t){ n = emalloc(sizeof(struct s)); if (n == ((void *)0)) return
r; n->node = t;}
{\
1390 n = emalloc(sizeof(struct s)); \
1391 if (n == NULL((void *)0)) \
1392 return r; \
1393 n->node = t;\
1394}
1395
1396/*
1397 * Generate the path tables
1398 * The specific implementation of this function is left as an exercise to the
1399 * programmer. It could be done recursively. Make sure you read how the path
1400 * table has to be laid out, it has levels.
1401 * @param struct iso9660_disk *disk The disk image
1402 * @returns int The number of built path tables (between 1 and 4), 0 on failure
1403 */
1404static int
1405cd9660_generate_path_table(iso9660_disk *diskStructure)
1406{
1407 cd9660node *cn, *dirNode = diskStructure->rootNode;
1408 cd9660node *last = dirNode;
1409 int pathTableSize = 0; /* computed as we go */
1410 int counter = 1; /* root gets a count of 0 */
1411
1412 TAILQ_HEAD(cd9660_pt_head, ptq_entry)struct cd9660_pt_head { struct ptq_entry *tqh_first; struct ptq_entry
**tqh_last; }
pt_head;
1413 TAILQ_INIT(&pt_head)do { (&pt_head)->tqh_first = ((void *)0); (&pt_head
)->tqh_last = &(&pt_head)->tqh_first; } while (
0)
;
14
Loop condition is false. Exiting loop
1414
1415 PTQUEUE_NEW(n, ptq_entry, -1, diskStructure->rootNode){ n = emalloc(sizeof(struct ptq_entry)); if (n == ((void *)0)
) return -1; n->node = diskStructure->rootNode;}
;
15
Assuming 'n' is not equal to null
16
Taking false branch
1416
1417 /* Push the root node */
1418 TAILQ_INSERT_HEAD(&pt_head, n, ptq)do { if (((n)->ptq.tqe_next = (&pt_head)->tqh_first
) != ((void *)0)) (&pt_head)->tqh_first->ptq.tqe_prev
= &(n)->ptq.tqe_next; else (&pt_head)->tqh_last
= &(n)->ptq.tqe_next; (&pt_head)->tqh_first = (
n); (n)->ptq.tqe_prev = &(&pt_head)->tqh_first;
} while (0)
;
17
Taking false branch
18
Loop condition is false. Exiting loop
1419
1420 /* Breadth-first traversal of file structure */
1421 while (pt_head.tqh_first
18.1
Field 'tqh_first' is not equal to null
38.1
Field 'tqh_first' is not equal to null
!= 0
) {
19
Loop condition is true. Entering loop body
27
Assuming field 'tqh_first' is not equal to null
28
Loop condition is true. Entering loop body
39
Loop condition is true. Entering loop body
1422 n = pt_head.tqh_first;
1423 dirNode = n->node;
40
Use of memory after it is freed
1424 TAILQ_REMOVE(&pt_head, pt_head.tqh_first, ptq)do { if (((pt_head.tqh_first)->ptq.tqe_next) != ((void *)0
)) (pt_head.tqh_first)->ptq.tqe_next->ptq.tqe_prev = (pt_head
.tqh_first)->ptq.tqe_prev; else (&pt_head)->tqh_last
= (pt_head.tqh_first)->ptq.tqe_prev; *(pt_head.tqh_first)
->ptq.tqe_prev = (pt_head.tqh_first)->ptq.tqe_next; ; ;
} while (0)
;
20
Taking false branch
21
Loop condition is false. Exiting loop
29
Assuming field 'tqe_next' is equal to null
30
Taking false branch
31
Loop condition is false. Exiting loop
1425 free(n);
32
Memory is released
1426
1427 /* Update the size */
1428 pathTableSize += ISO_PATHTABLE_ENTRY_BASESIZE8
1429 + dirNode->isoDirRecord->name_len[0]+
1430 (dirNode->isoDirRecord->name_len[0] % 2 == 0 ? 0 : 1);
22
Assuming the condition is false
23
'?' condition is false
33
Assuming the condition is true
34
'?' condition is true
1431 /* includes the padding bit */
1432
1433 dirNode->ptnumber=counter;
1434 if (dirNode
23.1
'dirNode' is equal to 'last'
!= last
) {
24
Taking false branch
35
Assuming 'dirNode' is equal to 'last'
36
Taking false branch
1435 last->ptnext = dirNode;
1436 dirNode->ptprev = last;
1437 }
1438 last = dirNode;
1439
1440 /* Push children onto queue */
1441 TAILQ_FOREACH(cn, &dirNode->cn_children, cn_next_child)for((cn) = ((&dirNode->cn_children)->tqh_first); (cn
) != ((void *)0); (cn) = ((cn)->cn_next_child.tqe_next))
{
25
Assuming 'cn' is equal to null
26
Loop condition is false. Execution continues on line 1455
37
Assuming 'cn' is equal to null
38
Loop condition is false. Execution continues on line 1455
1442 /*
1443 * Dont add the DOT and DOTDOT types to the path
1444 * table.
1445 */
1446 if ((cn->type != CD9660_TYPE_DOT0x04)
1447 && (cn->type != CD9660_TYPE_DOTDOT0x08)) {
1448
1449 if (S_ISDIR(cn->node->type)((cn->node->type & 0170000) == 0040000)) {
1450 PTQUEUE_NEW(n, ptq_entry, -1, cn){ n = emalloc(sizeof(struct ptq_entry)); if (n == ((void *)0)
) return -1; n->node = cn;}
;
1451 TAILQ_INSERT_TAIL(&pt_head, n, ptq)do { (n)->ptq.tqe_next = ((void *)0); (n)->ptq.tqe_prev
= (&pt_head)->tqh_last; *(&pt_head)->tqh_last =
(n); (&pt_head)->tqh_last = &(n)->ptq.tqe_next
; } while (0)
;
1452 }
1453 }
1454 }
1455 counter++;
1456 }
1457 return pathTableSize;
1458}
1459
1460char *
1461cd9660_compute_full_filename(cd9660node *node)
1462{
1463 static char buf[PATH_MAX1024];
1464 int len;
1465
1466 len = snprintf(buf, PATH_MAX1024, "%s/%s/%s", node->node->root,
1467 node->node->path, node->node->name);
1468 if (len < 0) {
1469 warn(NULL((void *)0));
1470 return NULL((void *)0);
1471 } else if (len >= PATH_MAX1024) {
1472 warnc(ENAMETOOLONG63, NULL((void *)0));
1473 return NULL((void *)0);
1474 }
1475 return buf;
1476}
1477
1478/*
1479 * TODO: These two functions are almost identical.
1480 * Some code cleanup is possible here
1481 *
1482 * XXX bounds checking!
1483 */
1484static int
1485cd9660_level1_convert_filename(iso9660_disk *diskStructure, const char *oldname,
1486 char *newname, size_t newnamelen, int is_file)
1487{
1488 /*
1489 * ISO 9660 : 10.1
1490 * File Name shall not contain more than 8 d or d1 characters
1491 * File Name Extension shall not contain more than 3 d or d1 characters
1492 * Directory Identifier shall not contain more than 8 d or d1 characters
1493 */
1494 int namelen = 0;
1495 int extlen = 0;
1496 int found_ext = 0;
1497 char *orignewname = newname;
1498
1499 while (*oldname != '\0' && extlen < 3) {
1500 /* Handle period first, as it is special */
1501 if (*oldname == '.') {
1502 if (found_ext) {
1503 *newname++ = '_';
1504 extlen ++;
1505 }
1506 else {
1507 *newname++ = '.';
1508 found_ext = 1;
1509 }
1510 } else {
1511 /* Enforce 12.3 / 8 */
1512 if (namelen == 8 && !found_ext)
1513 break;
1514
1515 if (islower((unsigned char)*oldname))
1516 *newname++ = toupper((unsigned char)*oldname);
1517 else if (isupper((unsigned char)*oldname)
1518 || isdigit((unsigned char)*oldname))
1519 *newname++ = *oldname;
1520 else
1521 *newname++ = '_';
1522
1523 if (found_ext)
1524 extlen++;
1525 else
1526 namelen++;
1527 }
1528 oldname++;
1529 }
1530 if (is_file) {
1531 if (!found_ext && !diskStructure->omit_trailing_period)
1532 *newname++ = '.';
1533 /* Add version */
1534 snprintf(newname, newnamelen - (newname - orignewname), ";%i", 1);
1535 }
1536 return namelen + extlen + found_ext;
1537}
1538
1539/* XXX bounds checking! */
1540static int
1541cd9660_level2_convert_filename(iso9660_disk *diskStructure, const char *oldname,
1542 char *newname, size_t newnamelen, int is_file)
1543{
1544 /*
1545 * ISO 9660 : 7.5.1
1546 * File name : 0+ d or d1 characters
1547 * separator 1 (.)
1548 * File name extension : 0+ d or d1 characters
1549 * separator 2 (;)
1550 * File version number (5 characters, 1-32767)
1551 * 1 <= Sum of File name and File name extension <= 30
1552 */
1553 int namelen = 0;
1554 int extlen = 0;
1555 int found_ext = 0;
1556 char *orignewname = newname;
1557
1558 while (*oldname != '\0' && namelen + extlen < 30) {
1559 /* Handle period first, as it is special */
1560 if (*oldname == '.') {
1561 if (found_ext) {
1562 if (diskStructure->allow_multidot) {
1563 *newname++ = '.';
1564 } else {
1565 *newname++ = '_';
1566 }
1567 extlen ++;
1568 }
1569 else {
1570 *newname++ = '.';
1571 found_ext = 1;
1572 }
1573 } else {
1574 if (islower((unsigned char)*oldname))
1575 *newname++ = toupper((unsigned char)*oldname);
1576 else if (isupper((unsigned char)*oldname) ||
1577 isdigit((unsigned char)*oldname))
1578 *newname++ = *oldname;
1579 else if (diskStructure->allow_multidot &&
1580 *oldname == '.') {
1581 *newname++ = '.';
1582 } else {
1583 *newname++ = '_';
1584 }
1585
1586 if (found_ext)
1587 extlen++;
1588 else
1589 namelen++;
1590 }
1591 oldname ++;
1592 }
1593 if (is_file) {
1594 if (!found_ext && !diskStructure->omit_trailing_period)
1595 *newname++ = '.';
1596 /* Add version */
1597 snprintf(newname, newnamelen - (newname - orignewname), ";%i", 1);
1598 }
1599 return namelen + extlen + found_ext;
1600}
1601
1602/*
1603 * Convert a file name to ISO compliant file name
1604 * @param char * oldname The original filename
1605 * @param char ** newname The new file name, in the appropriate character
1606 * set and of appropriate length
1607 * @param int 1 if file, 0 if directory
1608 * @returns int The length of the new string
1609 */
1610static int
1611cd9660_convert_filename(iso9660_disk *diskStructure, const char *oldname,
1612 char *newname, size_t newnamelen, int is_file)
1613{
1614 if (diskStructure->isoLevel == 1)
1615 return cd9660_level1_convert_filename(diskStructure,
1616 oldname, newname, newnamelen, is_file);
1617 else if (diskStructure->isoLevel == 2)
1618 return cd9660_level2_convert_filename(diskStructure,
1619 oldname, newname, newnamelen, is_file);
1620 abort();
1621}
1622
1623int
1624cd9660_compute_record_size(iso9660_disk *diskStructure, cd9660node *node)
1625{
1626 int size = node->isoDirRecord->length[0];
1627
1628 if (diskStructure->rock_ridge_enabled)
1629 size += node->susp_entry_size;
1630 size += node->su_tail_size;
1631 size += size & 1; /* Ensure length of record is even. */
1632 assert(size <= 254)((size <= 254) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/cd9660.c"
, 1632, __func__, "size <= 254"))
;
1633 return size;
1634}
1635
1636static void
1637cd9660_populate_dot_records(iso9660_disk *diskStructure, cd9660node *node)
1638{
1639 node->dot_record->fileDataSector = node->fileDataSector;
1640 memcpy(node->dot_record->isoDirRecord,node->isoDirRecord, 34);
1641 node->dot_record->isoDirRecord->name_len[0] = 1;
1642 node->dot_record->isoDirRecord->name[0] = 0;
1643 node->dot_record->isoDirRecord->name[1] = 0;
1644 node->dot_record->isoDirRecord->length[0] = 34;
1645 node->dot_record->fileRecordSize =
1646 cd9660_compute_record_size(diskStructure, node->dot_record);
1647
1648 if (node == diskStructure->rootNode) {
1649 node->dot_dot_record->fileDataSector = node->fileDataSector;
1650 memcpy(node->dot_dot_record->isoDirRecord,node->isoDirRecord,
1651 34);
1652 } else {
1653 node->dot_dot_record->fileDataSector =
1654 node->parent->fileDataSector;
1655 memcpy(node->dot_dot_record->isoDirRecord,
1656 node->parent->isoDirRecord,34);
1657 }
1658 node->dot_dot_record->isoDirRecord->name_len[0] = 1;
1659 node->dot_dot_record->isoDirRecord->name[0] = 1;
1660 node->dot_dot_record->isoDirRecord->name[1] = 0;
1661 node->dot_dot_record->isoDirRecord->length[0] = 34;
1662 node->dot_dot_record->fileRecordSize =
1663 cd9660_compute_record_size(diskStructure, node->dot_dot_record);
1664}
1665
1666/*
1667 * @param struct cd9660node *node The node
1668 * @param int The offset (in bytes) - SHOULD align to the beginning of a sector
1669 * @returns int The total size of files and directory entries (should be
1670 * a multiple of sector size)
1671*/
1672static int64_t
1673cd9660_compute_offsets(iso9660_disk *diskStructure, cd9660node *node,
1674 int64_t startOffset)
1675{
1676 /*
1677 * This function needs to compute the size of directory records and
1678 * runs, file lengths, and set the appropriate variables both in
1679 * cd9660node and isoDirEntry
1680 */
1681 int64_t used_bytes = 0;
1682 int64_t current_sector_usage = 0;
1683 cd9660node *child;
1684 fsinode *inode;
1685 int64_t r;
1686
1687 assert(node != NULL)((node != ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/cd9660.c"
, 1687, __func__, "node != NULL"))
;
1688
1689
1690 /*
1691 * NOTE : There needs to be some special case detection for
1692 * the "real root" node, since for it, node->node is undefined
1693 */
1694
1695 node->fileDataSector = -1;
1696
1697 if (node->type & CD9660_TYPE_DIR0x02) {
1698 node->fileRecordSize = cd9660_compute_record_size(
1699 diskStructure, node);
1700 /*Set what sector this directory starts in*/
1701 node->fileDataSector =
1702 CD9660_BLOCKS(diskStructure->sectorSize,startOffset)((((startOffset)) + (((diskStructure->sectorSize)) - 1)) /
((diskStructure->sectorSize)))
;
1703
1704 cd9660_bothendian_dword(node->fileDataSector,
1705 node->isoDirRecord->extent);
1706
1707 /*
1708 * First loop over children, need to know the size of
1709 * their directory records
1710 */
1711 node->fileSectorsUsed = 1;
1712 TAILQ_FOREACH(child, &node->cn_children, cn_next_child)for((child) = ((&node->cn_children)->tqh_first); (child
) != ((void *)0); (child) = ((child)->cn_next_child.tqe_next
))
{
1713 node->fileDataLength +=
1714 cd9660_compute_record_size(diskStructure, child);
1715 if ((cd9660_compute_record_size(diskStructure, child) +
1716 current_sector_usage) >=
1717 diskStructure->sectorSize) {
1718 current_sector_usage = 0;
1719 node->fileSectorsUsed++;
1720 }
1721
1722 current_sector_usage +=
1723 cd9660_compute_record_size(diskStructure, child);
1724 }
1725
1726 cd9660_bothendian_dword(node->fileSectorsUsed *
1727 diskStructure->sectorSize,node->isoDirRecord->size);
1728
1729 /*
1730 * This should point to the sector after the directory
1731 * record (or, the first byte in that sector)
1732 */
1733 used_bytes += node->fileSectorsUsed * diskStructure->sectorSize;
1734
1735 for (child = TAILQ_NEXT(node->dot_dot_record, cn_next_child)((node->dot_dot_record)->cn_next_child.tqe_next);
1736 child != NULL((void *)0); child = TAILQ_NEXT(child, cn_next_child)((child)->cn_next_child.tqe_next)) {
1737 /* Directories need recursive call */
1738 if (S_ISDIR(child->node->type)((child->node->type & 0170000) == 0040000)) {
1739 r = cd9660_compute_offsets(diskStructure, child,
1740 used_bytes + startOffset);
1741
1742 if (r != -1)
1743 used_bytes += r;
1744 else
1745 return -1;
1746 }
1747 }
1748
1749 /* Explicitly set the . and .. records */
1750 cd9660_populate_dot_records(diskStructure, node);
1751
1752 /* Finally, do another iteration to write the file data*/
1753 for (child = TAILQ_NEXT(node->dot_dot_record, cn_next_child)((node->dot_dot_record)->cn_next_child.tqe_next);
1754 child != NULL((void *)0);
1755 child = TAILQ_NEXT(child, cn_next_child)((child)->cn_next_child.tqe_next)) {
1756 /* Files need extent set */
1757 if (S_ISDIR(child->node->type)((child->node->type & 0170000) == 0040000))
1758 continue;
1759 child->fileRecordSize =
1760 cd9660_compute_record_size(diskStructure, child);
1761
1762 child->fileSectorsUsed =
1763 CD9660_BLOCKS(diskStructure->sectorSize,((((child->fileDataLength)) + (((diskStructure->sectorSize
)) - 1)) / ((diskStructure->sectorSize)))
1764 child->fileDataLength)((((child->fileDataLength)) + (((diskStructure->sectorSize
)) - 1)) / ((diskStructure->sectorSize)))
;
1765
1766 inode = child->node->inode;
1767 if ((inode->flags & FI_ALLOCATED) == 0) {
1768 inode->ino =
1769 CD9660_BLOCKS(diskStructure->sectorSize,((((used_bytes + startOffset)) + (((diskStructure->sectorSize
)) - 1)) / ((diskStructure->sectorSize)))
1770 used_bytes + startOffset)((((used_bytes + startOffset)) + (((diskStructure->sectorSize
)) - 1)) / ((diskStructure->sectorSize)))
;
1771 inode->flags |= FI_ALLOCATED;
1772 used_bytes += child->fileSectorsUsed *
1773 diskStructure->sectorSize;
1774 } else {
1775 INODE_WARNX(("%s: already allocated inode %d "
1776 "data sectors at %" PRIu32, __func__,
1777 (int)inode->st.st_ino, inode->ino));
1778 }
1779 child->fileDataSector = inode->ino;
1780 cd9660_bothendian_dword(child->fileDataSector,
1781 child->isoDirRecord->extent);
1782 }
1783 }
1784
1785 return used_bytes;
1786}
1787
1788#if 0
1789/* Might get rid of this func */
1790static int
1791cd9660_copy_stat_info(cd9660node *from, cd9660node *to, int file)
1792{
1793 to->node->inode->st.st_dev = 0;
1794 to->node->inode->st.st_ino = 0;
1795 to->node->inode->st.st_size = 0;
1796 to->node->inode->st.st_blksize = from->node->inode->st.st_blksize;
1797 to->node->inode->st.st_atimest_atim.tv_sec = from->node->inode->st.st_atimest_atim.tv_sec;
1798 to->node->inode->st.st_mtimest_mtim.tv_sec = from->node->inode->st.st_mtimest_mtim.tv_sec;
1799 to->node->inode->st.st_ctimest_ctim.tv_sec = from->node->inode->st.st_ctimest_ctim.tv_sec;
1800 to->node->inode->st.st_uid = from->node->inode->st.st_uid;
1801 to->node->inode->st.st_gid = from->node->inode->st.st_gid;
1802 to->node->inode->st.st_mode = from->node->inode->st.st_mode;
1803 /* Clear out type */
1804 to->node->inode->st.st_mode = to->node->inode->st.st_mode & ~(S_IFMT0170000);
1805 if (file)
1806 to->node->inode->st.st_mode |= S_IFREG0100000;
1807 else
1808 to->node->inode->st.st_mode |= S_IFDIR0040000;
1809 return 1;
1810}
1811#endif
1812
1813static cd9660node *
1814cd9660_create_virtual_entry(iso9660_disk *diskStructure, const char *name,
1815 cd9660node *parent, int file, int insert)
1816{
1817 cd9660node *temp;
1818 fsnode * tfsnode;
1819
1820 assert(parent != NULL)((parent != ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/cd9660.c"
, 1820, __func__, "parent != NULL"))
;
1821
1822 temp = cd9660_allocate_cd9660node();
1823 if (temp == NULL((void *)0))
1824 return NULL((void *)0);
1825
1826 tfsnode = emalloc(sizeof(*tfsnode));
1827 tfsnode->name = estrdup(name);
1828 temp->isoDirRecord = emalloc(sizeof(*temp->isoDirRecord));
1829
1830 cd9660_convert_filename(diskStructure, tfsnode->name,
1831 temp->isoDirRecord->name, sizeof temp->isoDirRecord->name, file);
1832
1833 temp->node = tfsnode;
1834 temp->parent = parent;
1835
1836 if (insert) {
1837 if (temp->parent != NULL((void *)0)) {
1838 temp->level = temp->parent->level + 1;
1839 if (!TAILQ_EMPTY(&temp->parent->cn_children)(((&temp->parent->cn_children)->tqh_first) == ((
void *)0))
)
1840 cd9660_sorted_child_insert(temp->parent, temp);
1841 else
1842 TAILQ_INSERT_HEAD(&temp->parent->cn_children,do { if (((temp)->cn_next_child.tqe_next = (&temp->
parent->cn_children)->tqh_first) != ((void *)0)) (&
temp->parent->cn_children)->tqh_first->cn_next_child
.tqe_prev = &(temp)->cn_next_child.tqe_next; else (&
temp->parent->cn_children)->tqh_last = &(temp)->
cn_next_child.tqe_next; (&temp->parent->cn_children
)->tqh_first = (temp); (temp)->cn_next_child.tqe_prev =
&(&temp->parent->cn_children)->tqh_first; }
while (0)
1843 temp, cn_next_child)do { if (((temp)->cn_next_child.tqe_next = (&temp->
parent->cn_children)->tqh_first) != ((void *)0)) (&
temp->parent->cn_children)->tqh_first->cn_next_child
.tqe_prev = &(temp)->cn_next_child.tqe_next; else (&
temp->parent->cn_children)->tqh_last = &(temp)->
cn_next_child.tqe_next; (&temp->parent->cn_children
)->tqh_first = (temp); (temp)->cn_next_child.tqe_prev =
&(&temp->parent->cn_children)->tqh_first; }
while (0)
;
1844 }
1845 }
1846
1847 if (parent->node != NULL((void *)0)) {
1848 tfsnode->type = parent->node->type;
1849 }
1850
1851 /* Clear out file type bits */
1852 tfsnode->type &= ~(S_IFMT0170000);
1853 if (file)
1854 tfsnode->type |= S_IFREG0100000;
1855 else
1856 tfsnode->type |= S_IFDIR0040000;
1857
1858 /* Indicate that there is no spec entry (inode) */
1859 tfsnode->flags &= ~(FSNODE_F_HASSPEC0x01);
1860#if 0
1861 cd9660_copy_stat_info(parent, temp, file);
1862#endif
1863 return temp;
1864}
1865
1866static cd9660node *
1867cd9660_create_file(iso9660_disk *diskStructure, const char *name,
1868 cd9660node *parent, cd9660node *me)
1869{
1870 cd9660node *temp;
1871
1872 temp = cd9660_create_virtual_entry(diskStructure, name, parent, 1, 1);
1873 if (temp == NULL((void *)0))
1874 return NULL((void *)0);
1875
1876 temp->fileDataLength = 0;
1877
1878 temp->type = CD9660_TYPE_FILE0x01 | CD9660_TYPE_VIRTUAL0x80;
1879
1880 temp->node->inode = ecalloc(1, sizeof(*temp->node->inode));
1881 *temp->node->inode = *me->node->inode;
1882
1883 if (cd9660_translate_node_common(diskStructure, temp) == 0)
1884 return NULL((void *)0);
1885 return temp;
1886}
1887
1888/*
1889 * Create a new directory which does not exist on disk
1890 * @param const char * name The name to assign to the directory
1891 * @param const char * parent Pointer to the parent directory
1892 * @returns cd9660node * Pointer to the new directory
1893 */
1894static cd9660node *
1895cd9660_create_directory(iso9660_disk *diskStructure, const char *name,
1896 cd9660node *parent, cd9660node *me)
1897{
1898 cd9660node *temp;
1899
1900 temp = cd9660_create_virtual_entry(diskStructure, name, parent, 0, 1);
1901 if (temp == NULL((void *)0))
1902 return NULL((void *)0);
1903 temp->node->type |= S_IFDIR0040000;
1904
1905 temp->type = CD9660_TYPE_DIR0x02 | CD9660_TYPE_VIRTUAL0x80;
1906
1907 temp->node->inode = ecalloc(1, sizeof(*temp->node->inode));
1908 *temp->node->inode = *me->node->inode;
1909
1910 if (cd9660_translate_node_common(diskStructure, temp) == 0)
1911 return NULL((void *)0);
1912 return temp;
1913}
1914
1915static cd9660node *
1916cd9660_create_special_directory(iso9660_disk *diskStructure, u_char type,
1917 cd9660node *parent)
1918{
1919 cd9660node *temp, *first;
1920 char na[2];
1921
1922 assert(parent != NULL)((parent != ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/cd9660.c"
, 1922, __func__, "parent != NULL"))
;
1923
1924 if (type == CD9660_TYPE_DOT0x04)
1925 na[0] = 0;
1926 else if (type == CD9660_TYPE_DOTDOT0x08)
1927 na[0] = 1;
1928 else
1929 return 0;
1930
1931 na[1] = 0;
1932 if ((temp = cd9660_create_virtual_entry(diskStructure, na, parent,
1933 0, 0)) == NULL((void *)0))
1934 return NULL((void *)0);
1935
1936 temp->parent = parent;
1937 temp->type = type;
1938 temp->isoDirRecord->length[0] = 34;
1939 /* Dot record is always first */
1940 if (type == CD9660_TYPE_DOT0x04) {
1941 parent->dot_record = temp;
1942 TAILQ_INSERT_HEAD(&parent->cn_children, temp, cn_next_child)do { if (((temp)->cn_next_child.tqe_next = (&parent->
cn_children)->tqh_first) != ((void *)0)) (&parent->
cn_children)->tqh_first->cn_next_child.tqe_prev = &
(temp)->cn_next_child.tqe_next; else (&parent->cn_children
)->tqh_last = &(temp)->cn_next_child.tqe_next; (&
parent->cn_children)->tqh_first = (temp); (temp)->cn_next_child
.tqe_prev = &(&parent->cn_children)->tqh_first;
} while (0)
;
1943 /* DotDot should be second */
1944 } else if (type == CD9660_TYPE_DOTDOT0x08) {
1945 parent->dot_dot_record = temp;
1946 /*
1947 * If the first child is the dot record, insert
1948 * this second. Otherwise, insert it at the head.
1949 */
1950 if ((first = TAILQ_FIRST(&parent->cn_children)((&parent->cn_children)->tqh_first)) == NULL((void *)0) ||
1951 (first->type & CD9660_TYPE_DOT0x04) == 0) {
1952 TAILQ_INSERT_HEAD(&parent->cn_children, temp,do { if (((temp)->cn_next_child.tqe_next = (&parent->
cn_children)->tqh_first) != ((void *)0)) (&parent->
cn_children)->tqh_first->cn_next_child.tqe_prev = &
(temp)->cn_next_child.tqe_next; else (&parent->cn_children
)->tqh_last = &(temp)->cn_next_child.tqe_next; (&
parent->cn_children)->tqh_first = (temp); (temp)->cn_next_child
.tqe_prev = &(&parent->cn_children)->tqh_first;
} while (0)
1953 cn_next_child)do { if (((temp)->cn_next_child.tqe_next = (&parent->
cn_children)->tqh_first) != ((void *)0)) (&parent->
cn_children)->tqh_first->cn_next_child.tqe_prev = &
(temp)->cn_next_child.tqe_next; else (&parent->cn_children
)->tqh_last = &(temp)->cn_next_child.tqe_next; (&
parent->cn_children)->tqh_first = (temp); (temp)->cn_next_child
.tqe_prev = &(&parent->cn_children)->tqh_first;
} while (0)
;
1954 } else {
1955 TAILQ_INSERT_AFTER(&parent->cn_children, first, temp,do { if (((temp)->cn_next_child.tqe_next = (first)->cn_next_child
.tqe_next) != ((void *)0)) (temp)->cn_next_child.tqe_next->
cn_next_child.tqe_prev = &(temp)->cn_next_child.tqe_next
; else (&parent->cn_children)->tqh_last = &(temp
)->cn_next_child.tqe_next; (first)->cn_next_child.tqe_next
= (temp); (temp)->cn_next_child.tqe_prev = &(first)->
cn_next_child.tqe_next; } while (0)
1956 cn_next_child)do { if (((temp)->cn_next_child.tqe_next = (first)->cn_next_child
.tqe_next) != ((void *)0)) (temp)->cn_next_child.tqe_next->
cn_next_child.tqe_prev = &(temp)->cn_next_child.tqe_next
; else (&parent->cn_children)->tqh_last = &(temp
)->cn_next_child.tqe_next; (first)->cn_next_child.tqe_next
= (temp); (temp)->cn_next_child.tqe_prev = &(first)->
cn_next_child.tqe_next; } while (0)
;
1957 }
1958 }
1959
1960 return temp;
1961}
1962
1963static int
1964cd9660_add_generic_bootimage(iso9660_disk *diskStructure, const char *bootimage)
1965{
1966 struct stat stbuf;
1967
1968 assert(bootimage != NULL)((bootimage != ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/cd9660.c"
, 1968, __func__, "bootimage != NULL"))
;
1969
1970 if (*bootimage == '\0') {
1971 warnx("Error: Boot image must be a filename");
1972 return 0;
1973 }
1974
1975 diskStructure->generic_bootimage = estrdup(bootimage);
1976
1977 if (unveil(diskStructure->generic_bootimage, "r") == -1)
1978 err(1, "unveil %s", diskStructure->generic_bootimage);
1979 /* Get information about the file */
1980 if (lstat(diskStructure->generic_bootimage, &stbuf) == -1)
1981 err(1, "%s: lstat(\"%s\")", __func__,
1982 diskStructure->generic_bootimage);
1983
1984 if (stbuf.st_size > 32768) {
1985 warnx("Error: Boot image must be no greater than 32768 bytes");
1986 return 0;
1987 }
1988
1989 diskStructure->has_generic_bootimage = 1;
1990 return 1;
1991}