udf_core.c revision 1.3 1 1.3 reinoud /* $NetBSD: udf_core.c,v 1.3 2022/04/22 20:56:46 reinoud Exp $ */
2 1.1 reinoud
3 1.1 reinoud /*
4 1.1 reinoud * Copyright (c) 2006, 2008, 2021, 2022 Reinoud Zandijk
5 1.1 reinoud * All rights reserved.
6 1.2 riastrad *
7 1.1 reinoud * Redistribution and use in source and binary forms, with or without
8 1.1 reinoud * modification, are permitted provided that the following conditions
9 1.1 reinoud * are met:
10 1.1 reinoud * 1. Redistributions of source code must retain the above copyright
11 1.1 reinoud * notice, this list of conditions and the following disclaimer.
12 1.1 reinoud * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 reinoud * notice, this list of conditions and the following disclaimer in the
14 1.1 reinoud * documentation and/or other materials provided with the distribution.
15 1.2 riastrad *
16 1.1 reinoud * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.1 reinoud * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.1 reinoud * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.1 reinoud * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.1 reinoud * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 1.1 reinoud * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 1.1 reinoud * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 1.1 reinoud * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 1.1 reinoud * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 1.1 reinoud * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 1.2 riastrad *
27 1.1 reinoud */
28 1.1 reinoud #if HAVE_NBTOOL_CONFIG_H
29 1.1 reinoud #include "nbtool_config.h"
30 1.1 reinoud #endif
31 1.1 reinoud
32 1.1 reinoud #include <sys/cdefs.h>
33 1.3 reinoud __RCSID("$NetBSD: udf_core.c,v 1.3 2022/04/22 20:56:46 reinoud Exp $");
34 1.1 reinoud
35 1.1 reinoud #include <stdio.h>
36 1.1 reinoud #include <stdlib.h>
37 1.1 reinoud #include <stddef.h>
38 1.1 reinoud #include <string.h>
39 1.1 reinoud #include <strings.h>
40 1.1 reinoud #include <unistd.h>
41 1.1 reinoud #include <errno.h>
42 1.1 reinoud #include <time.h>
43 1.1 reinoud #include <assert.h>
44 1.1 reinoud #include <err.h>
45 1.1 reinoud #include <fcntl.h>
46 1.1 reinoud #include <util.h>
47 1.1 reinoud #include <sys/types.h>
48 1.1 reinoud #include <sys/param.h>
49 1.1 reinoud #include <sys/ioctl.h>
50 1.1 reinoud #include <sys/queue.h>
51 1.1 reinoud #include "newfs_udf.h"
52 1.1 reinoud #include "unicode.h"
53 1.1 reinoud #include "udf_core.h"
54 1.1 reinoud
55 1.1 reinoud
56 1.1 reinoud /* disk partition support */
57 1.1 reinoud #if !HAVE_NBTOOL_CONFIG_H
58 1.1 reinoud #include "../fsck/partutil.h"
59 1.1 reinoud #include "../fsck/partutil.c"
60 1.1 reinoud #endif
61 1.1 reinoud
62 1.1 reinoud
63 1.1 reinoud /* queue for temporary storage of sectors to be written out */
64 1.1 reinoud struct wrpacket {
65 1.1 reinoud uint64_t start_sectornr;
66 1.1 reinoud uint8_t *packet_data;
67 1.1 reinoud uint64_t present;
68 1.1 reinoud TAILQ_ENTRY(wrpacket) next;
69 1.1 reinoud };
70 1.1 reinoud
71 1.1 reinoud
72 1.1 reinoud /* global variables describing disc and format requests */
73 1.1 reinoud struct udf_create_context context;
74 1.1 reinoud struct udf_disclayout layout;
75 1.1 reinoud
76 1.1 reinoud
77 1.1 reinoud int dev_fd_rdonly; /* device: open readonly! */
78 1.1 reinoud int dev_fd; /* device: file descriptor */
79 1.1 reinoud struct stat dev_fd_stat; /* device: last stat info */
80 1.1 reinoud char *dev_name; /* device: name */
81 1.1 reinoud int emul_mmc_profile; /* for files */
82 1.1 reinoud int emul_packetsize; /* for discs and files */
83 1.1 reinoud int emul_sectorsize; /* for files */
84 1.1 reinoud off_t emul_size; /* for files */
85 1.1 reinoud
86 1.1 reinoud struct mmc_discinfo mmc_discinfo; /* device: disc info */
87 1.1 reinoud union dscrptr *terminator_dscr; /* generic terminator descriptor*/
88 1.1 reinoud
89 1.1 reinoud
90 1.1 reinoud /* write queue and track blocking skew */
91 1.1 reinoud TAILQ_HEAD(wrpacket_list, wrpacket) write_queue;
92 1.1 reinoud int write_queuelen;
93 1.1 reinoud int write_queue_suspend;
94 1.1 reinoud uint32_t wrtrack_skew; /* offset for writing sector0 */
95 1.1 reinoud
96 1.1 reinoud static void udf_init_writequeue(int write_strategy);
97 1.1 reinoud static int udf_writeout_writequeue(bool complete);
98 1.1 reinoud
99 1.1 reinoud /*
100 1.1 reinoud * NOTE that there is some overlap between this code and the udf kernel fs.
101 1.1 reinoud * This is intentionally though it might better be factored out one day.
102 1.1 reinoud */
103 1.1 reinoud
104 1.1 reinoud void
105 1.1 reinoud udf_init_create_context(void)
106 1.1 reinoud {
107 1.1 reinoud /* clear */
108 1.1 reinoud memset(&context, 0, sizeof(struct udf_create_context));
109 1.1 reinoud
110 1.1 reinoud /* fill with defaults currently known */
111 1.1 reinoud context.dscrver = 3;
112 1.1 reinoud context.min_udf = 0x0102;
113 1.1 reinoud context.max_udf = 0x0250;
114 1.1 reinoud context.serialnum = 1; /* default */
115 1.1 reinoud
116 1.1 reinoud context.gmtoff = 0;
117 1.1 reinoud context.meta_perc = UDF_META_PERC;
118 1.1 reinoud context.check_surface = 0;
119 1.1 reinoud context.create_new_session = 0;
120 1.1 reinoud
121 1.1 reinoud context.sector_size = 512; /* minimum for UDF */
122 1.1 reinoud context.media_accesstype = UDF_ACCESSTYPE_NOT_SPECIFIED;
123 1.1 reinoud context.format_flags = FORMAT_INVALID;
124 1.1 reinoud context.write_strategy = UDF_WRITE_PACKET;
125 1.1 reinoud
126 1.1 reinoud context.logvol_name = NULL;
127 1.1 reinoud context.primary_name = NULL;
128 1.1 reinoud context.volset_name = NULL;
129 1.1 reinoud context.fileset_name = NULL;
130 1.1 reinoud
131 1.1 reinoud /* most basic identification */
132 1.1 reinoud context.app_name = "*NetBSD";
133 1.1 reinoud context.app_version_main = 0;
134 1.1 reinoud context.app_version_sub = 0;
135 1.1 reinoud context.impl_name = "*NetBSD";
136 1.1 reinoud
137 1.1 reinoud context.vds_seq = 0; /* first one starts with zero */
138 1.1 reinoud
139 1.1 reinoud /* Minimum value of 16 : UDF 3.2.1.1, 3.3.3.4. */
140 1.1 reinoud context.unique_id = 0x10;
141 1.1 reinoud
142 1.1 reinoud context.num_files = 0;
143 1.1 reinoud context.num_directories = 0;
144 1.1 reinoud
145 1.1 reinoud context.data_part = 0;
146 1.1 reinoud context.metadata_part = 0;
147 1.1 reinoud }
148 1.1 reinoud
149 1.1 reinoud
150 1.1 reinoud /* version can be specified as 0xabc or a.bc */
151 1.1 reinoud static int
152 1.1 reinoud parse_udfversion(const char *pos, uint32_t *version) {
153 1.1 reinoud int hex = 0;
154 1.1 reinoud char c1, c2, c3, c4;
155 1.1 reinoud
156 1.1 reinoud *version = 0;
157 1.1 reinoud if (*pos == '0') {
158 1.1 reinoud pos++;
159 1.1 reinoud /* expect hex format */
160 1.1 reinoud hex = 1;
161 1.1 reinoud if (*pos++ != 'x')
162 1.1 reinoud return 1;
163 1.1 reinoud }
164 1.1 reinoud
165 1.1 reinoud c1 = *pos++;
166 1.1 reinoud if (c1 < '0' || c1 > '9')
167 1.1 reinoud return 1;
168 1.1 reinoud c1 -= '0';
169 1.1 reinoud
170 1.1 reinoud c2 = *pos++;
171 1.1 reinoud if (!hex) {
172 1.1 reinoud if (c2 != '.')
173 1.1 reinoud return 1;
174 1.1 reinoud c2 = *pos++;
175 1.1 reinoud }
176 1.1 reinoud if (c2 < '0' || c2 > '9')
177 1.1 reinoud return 1;
178 1.1 reinoud c2 -= '0';
179 1.1 reinoud
180 1.1 reinoud c3 = *pos++;
181 1.1 reinoud if (c3 < '0' || c3 > '9')
182 1.1 reinoud return 1;
183 1.1 reinoud c3 -= '0';
184 1.1 reinoud
185 1.1 reinoud c4 = *pos++;
186 1.1 reinoud if (c4 != 0)
187 1.1 reinoud return 1;
188 1.1 reinoud
189 1.1 reinoud *version = c1 * 0x100 + c2 * 0x10 + c3;
190 1.1 reinoud return 0;
191 1.1 reinoud }
192 1.1 reinoud
193 1.1 reinoud
194 1.1 reinoud /*
195 1.1 reinoud * Parse a given string for an udf version.
196 1.1 reinoud * May exit.
197 1.1 reinoud */
198 1.1 reinoud int
199 1.1 reinoud a_udf_version(const char *s, const char *id_type)
200 1.1 reinoud {
201 1.1 reinoud uint32_t version;
202 1.1 reinoud
203 1.1 reinoud if (parse_udfversion(s, &version))
204 1.1 reinoud errx(1, "unknown %s version %s; specify as hex or float", id_type, s);
205 1.1 reinoud switch (version) {
206 1.1 reinoud case 0x102:
207 1.1 reinoud case 0x150:
208 1.1 reinoud case 0x200:
209 1.1 reinoud case 0x201:
210 1.1 reinoud case 0x250:
211 1.1 reinoud break;
212 1.1 reinoud case 0x260:
213 1.1 reinoud /* we don't support this one */
214 1.1 reinoud errx(1, "UDF version 0x260 is not supported");
215 1.1 reinoud break;
216 1.1 reinoud default:
217 1.1 reinoud errx(1, "unknown %s version %s, choose from "
218 1.1 reinoud "0x102, 0x150, 0x200, 0x201, 0x250",
219 1.1 reinoud id_type, s);
220 1.1 reinoud }
221 1.1 reinoud return version;
222 1.1 reinoud }
223 1.1 reinoud
224 1.1 reinoud
225 1.1 reinoud static uint32_t
226 1.1 reinoud udf_space_bitmap_len(uint32_t part_size)
227 1.1 reinoud {
228 1.1 reinoud return sizeof(struct space_bitmap_desc)-1 +
229 1.1 reinoud part_size/8;
230 1.1 reinoud }
231 1.1 reinoud
232 1.1 reinoud
233 1.1 reinoud uint32_t
234 1.1 reinoud udf_bytes_to_sectors(uint64_t bytes)
235 1.1 reinoud {
236 1.1 reinoud uint32_t sector_size = context.sector_size;
237 1.1 reinoud return (bytes + sector_size -1) / sector_size;
238 1.1 reinoud }
239 1.1 reinoud
240 1.1 reinoud
241 1.1 reinoud void
242 1.1 reinoud udf_dump_layout(void) {
243 1.1 reinoud #ifdef DEBUG
244 1.1 reinoud int format_flags = context.format_flags;
245 1.1 reinoud int sector_size = context.sector_size;
246 1.1 reinoud
247 1.1 reinoud printf("Summary so far\n");
248 1.1 reinoud printf("\tiso9660_vrs\t\t%d\n", layout.iso9660_vrs);
249 1.1 reinoud printf("\tanchor0\t\t\t%d\n", layout.anchors[0]);
250 1.1 reinoud printf("\tanchor1\t\t\t%d\n", layout.anchors[1]);
251 1.1 reinoud printf("\tanchor2\t\t\t%d\n", layout.anchors[2]);
252 1.1 reinoud printf("\tvds1_size\t\t%d\n", layout.vds1_size);
253 1.1 reinoud printf("\tvds2_size\t\t%d\n", layout.vds2_size);
254 1.1 reinoud printf("\tvds1\t\t\t%d\n", layout.vds1);
255 1.1 reinoud printf("\tvds2\t\t\t%d\n", layout.vds2);
256 1.1 reinoud printf("\tlvis_size\t\t%d\n", layout.lvis_size);
257 1.1 reinoud printf("\tlvis\t\t\t%d\n", layout.lvis);
258 1.1 reinoud if (format_flags & FORMAT_SPAREABLE) {
259 1.1 reinoud printf("\tspareable size\t\t%d\n", layout.spareable_area_size);
260 1.1 reinoud printf("\tspareable\t\t%d\n", layout.spareable_area);
261 1.1 reinoud }
262 1.1 reinoud printf("\tpartition start lba\t%d\n", layout.part_start_lba);
263 1.1 reinoud printf("\tpartition size\t\t%ld KiB, %ld MiB\n",
264 1.1 reinoud ((uint64_t) layout.part_size_lba * sector_size) / 1024,
265 1.1 reinoud ((uint64_t) layout.part_size_lba * sector_size) / (1024*1024));
266 1.1 reinoud if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
267 1.1 reinoud printf("\tpart bitmap start\t%d\n", layout.unalloc_space);
268 1.1 reinoud printf("\t\tfor %d lba\n", layout.alloc_bitmap_dscr_size);
269 1.1 reinoud }
270 1.1 reinoud if (format_flags & FORMAT_META) {
271 1.1 reinoud printf("\tmeta blockingnr\t\t%d\n", layout.meta_blockingnr);
272 1.1 reinoud printf("\tmeta alignment\t\t%d\n", layout.meta_alignment);
273 1.1 reinoud printf("\tmeta size\t\t%ld KiB, %ld MiB\n",
274 1.1 reinoud ((uint64_t) layout.meta_part_size_lba * sector_size) / 1024,
275 1.1 reinoud ((uint64_t) layout.meta_part_size_lba * sector_size) / (1024*1024));
276 1.1 reinoud printf("\tmeta file\t\t%d\n", layout.meta_file);
277 1.1 reinoud printf("\tmeta mirror\t\t%d\n", layout.meta_mirror);
278 1.1 reinoud printf("\tmeta bitmap\t\t%d\n", layout.meta_bitmap);
279 1.1 reinoud printf("\tmeta bitmap start\t%d\n", layout.meta_bitmap_space);
280 1.1 reinoud printf("\t\tfor %d lba\n", layout.meta_bitmap_dscr_size);
281 1.1 reinoud printf("\tmeta space start\t%d\n", layout.meta_part_start_lba);
282 1.1 reinoud printf("\t\tfor %d lba\n", layout.meta_part_size_lba);
283 1.1 reinoud }
284 1.1 reinoud printf("\n");
285 1.1 reinoud #endif
286 1.1 reinoud }
287 1.1 reinoud
288 1.1 reinoud
289 1.1 reinoud int
290 1.1 reinoud udf_calculate_disc_layout(int min_udf,
291 1.1 reinoud uint32_t first_lba, uint32_t last_lba,
292 1.1 reinoud uint32_t sector_size, uint32_t blockingnr)
293 1.1 reinoud {
294 1.1 reinoud uint64_t kbsize, bytes;
295 1.1 reinoud uint32_t spareable_blockingnr;
296 1.1 reinoud uint32_t align_blockingnr;
297 1.1 reinoud uint32_t pos, mpos;
298 1.1 reinoud int format_flags = context.format_flags;
299 1.1 reinoud
300 1.1 reinoud /* clear */
301 1.1 reinoud memset(&layout, 0, sizeof(layout));
302 1.1 reinoud
303 1.1 reinoud /* fill with parameters */
304 1.1 reinoud layout.wrtrack_skew = wrtrack_skew;
305 1.1 reinoud layout.first_lba = first_lba;
306 1.1 reinoud layout.last_lba = last_lba;
307 1.1 reinoud layout.blockingnr = blockingnr;
308 1.1 reinoud layout.spareable_blocks = udf_spareable_blocks();
309 1.1 reinoud
310 1.1 reinoud /* start disc layouting */
311 1.1 reinoud
312 1.1 reinoud /*
313 1.1 reinoud * location of iso9660 vrs is defined as first sector AFTER 32kb,
314 1.1 reinoud * minimum `sector size' 2048
315 1.1 reinoud */
316 1.1 reinoud layout.iso9660_vrs = ((32*1024 + sector_size - 1) / sector_size)
317 1.1 reinoud + first_lba;
318 1.1 reinoud
319 1.1 reinoud /* anchor starts at specified offset in sectors */
320 1.1 reinoud layout.anchors[0] = first_lba + 256;
321 1.1 reinoud if (format_flags & FORMAT_TRACK512)
322 1.1 reinoud layout.anchors[0] = first_lba + 512;
323 1.1 reinoud layout.anchors[1] = last_lba - 256;
324 1.1 reinoud layout.anchors[2] = last_lba;
325 1.1 reinoud
326 1.1 reinoud /* update workable space */
327 1.1 reinoud first_lba = layout.anchors[0] + blockingnr;
328 1.1 reinoud last_lba = layout.anchors[1] - 1;
329 1.1 reinoud
330 1.1 reinoud /* XXX rest of anchor packet can be added to unallocated space descr */
331 1.1 reinoud
332 1.1 reinoud /* reserve space for VRS and VRS copy and associated tables */
333 1.1 reinoud layout.vds1_size = MAX(16, blockingnr); /* UDF 2.2.3.1+2 */
334 1.1 reinoud layout.vds1 = first_lba;
335 1.1 reinoud first_lba += layout.vds1_size; /* next packet */
336 1.1 reinoud
337 1.1 reinoud layout.vds2_size = layout.vds1_size;
338 1.1 reinoud if (format_flags & FORMAT_SEQUENTIAL) {
339 1.1 reinoud /* for sequential, append them ASAP */
340 1.1 reinoud layout.vds2 = first_lba;
341 1.1 reinoud first_lba += layout.vds2_size;
342 1.1 reinoud } else {
343 1.1 reinoud layout.vds2 = layout.anchors[1] +1 - layout.vds2_size;
344 1.1 reinoud last_lba = layout.vds2 - 1;
345 1.1 reinoud }
346 1.1 reinoud
347 1.1 reinoud /*
348 1.1 reinoud * Reserve space for logvol integrity sequence, at least 8192 bytes
349 1.1 reinoud * for overwritable and rewritable media UDF 2.2.4.6, ECMA 3/10.6.12.
350 1.1 reinoud */
351 1.1 reinoud layout.lvis_size = MAX(8192.0/sector_size, 2 * blockingnr);
352 1.1 reinoud if (layout.lvis_size * sector_size < 8192)
353 1.1 reinoud layout.lvis_size++;
354 1.1 reinoud if (format_flags & FORMAT_VAT)
355 1.1 reinoud layout.lvis_size = 2;
356 1.1 reinoud if (format_flags & FORMAT_WORM)
357 1.1 reinoud layout.lvis_size = 64 * blockingnr;
358 1.1 reinoud
359 1.1 reinoud /* TODO skip bad blocks in LVID sequence */
360 1.1 reinoud layout.lvis = first_lba;
361 1.1 reinoud first_lba += layout.lvis_size;
362 1.1 reinoud
363 1.1 reinoud /* initial guess of UDF partition size */
364 1.1 reinoud layout.part_start_lba = first_lba;
365 1.1 reinoud layout.part_size_lba = last_lba - layout.part_start_lba;
366 1.1 reinoud
367 1.1 reinoud /* all non sequential media needs an unallocated space bitmap */
368 1.1 reinoud layout.alloc_bitmap_dscr_size = 0;
369 1.1 reinoud if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) {
370 1.1 reinoud bytes = udf_space_bitmap_len(layout.part_size_lba);
371 1.1 reinoud layout.alloc_bitmap_dscr_size = udf_bytes_to_sectors(bytes);
372 1.1 reinoud
373 1.1 reinoud /* XXX freed space map when applicable */
374 1.1 reinoud }
375 1.1 reinoud
376 1.1 reinoud spareable_blockingnr = udf_spareable_blockingnr();
377 1.1 reinoud align_blockingnr = blockingnr;
378 1.1 reinoud
379 1.1 reinoud if (format_flags & (FORMAT_SPAREABLE | FORMAT_META))
380 1.1 reinoud align_blockingnr = spareable_blockingnr;
381 1.1 reinoud
382 1.1 reinoud layout.align_blockingnr = align_blockingnr;
383 1.1 reinoud layout.spareable_blockingnr = spareable_blockingnr;
384 1.1 reinoud
385 1.1 reinoud /*
386 1.1 reinoud * Align partition LBA space to blocking granularity. Not strictly
387 1.1 reinoud * necessary for non spareables but safer for the VRS data since it is
388 1.1 reinoud * updated sporadically
389 1.1 reinoud */
390 1.1 reinoud
391 1.1 reinoud #ifdef DEBUG
392 1.1 reinoud printf("Lost %lu slack sectors at start\n", UDF_ROUNDUP(
393 1.1 reinoud first_lba, align_blockingnr) -
394 1.1 reinoud first_lba);
395 1.1 reinoud printf("Lost %lu slack sectors at end\n",
396 1.1 reinoud last_lba - UDF_ROUNDDOWN(
397 1.1 reinoud last_lba, align_blockingnr));
398 1.1 reinoud #endif
399 1.1 reinoud
400 1.1 reinoud first_lba = UDF_ROUNDUP(first_lba, align_blockingnr);
401 1.1 reinoud last_lba = UDF_ROUNDDOWN(last_lba, align_blockingnr);
402 1.1 reinoud
403 1.1 reinoud if ((format_flags & FORMAT_SPAREABLE) == 0)
404 1.1 reinoud layout.spareable_blocks = 0;
405 1.1 reinoud
406 1.1 reinoud if (format_flags & FORMAT_SPAREABLE) {
407 1.1 reinoud layout.spareable_area_size =
408 1.1 reinoud layout.spareable_blocks * spareable_blockingnr;
409 1.1 reinoud
410 1.1 reinoud /* a sparing table descriptor is a whole blockingnr sectors */
411 1.1 reinoud layout.sparing_table_dscr_lbas = spareable_blockingnr;
412 1.1 reinoud
413 1.1 reinoud /* place the descriptors at the start and end of the area */
414 1.1 reinoud layout.spt_1 = first_lba;
415 1.1 reinoud first_lba += layout.sparing_table_dscr_lbas;
416 1.1 reinoud
417 1.1 reinoud layout.spt_2 = last_lba - layout.sparing_table_dscr_lbas;
418 1.1 reinoud last_lba -= layout.sparing_table_dscr_lbas;
419 1.1 reinoud
420 1.1 reinoud /* allocate spareable section */
421 1.1 reinoud layout.spareable_area = first_lba;
422 1.1 reinoud first_lba += layout.spareable_area_size;
423 1.1 reinoud }
424 1.1 reinoud
425 1.1 reinoud /* update guess of UDF partition size */
426 1.1 reinoud layout.part_start_lba = first_lba;
427 1.1 reinoud layout.part_size_lba = last_lba - layout.part_start_lba;
428 1.1 reinoud
429 1.1 reinoud /* determine partition selection for data and metadata */
430 1.1 reinoud context.data_part = 0;
431 1.1 reinoud context.metadata_part = context.data_part;
432 1.1 reinoud if ((format_flags & FORMAT_VAT) || (format_flags & FORMAT_META))
433 1.1 reinoud context.metadata_part = context.data_part + 1;
434 1.1 reinoud context.fids_part = context.metadata_part;
435 1.1 reinoud if (format_flags & FORMAT_VAT)
436 1.1 reinoud context.fids_part = context.data_part;
437 1.1 reinoud
438 1.1 reinoud /*
439 1.1 reinoud * Pick fixed logical space sector numbers for main FSD, rootdir and
440 1.1 reinoud * unallocated space. The reason for this pre-allocation is that they
441 1.1 reinoud * are referenced in the volume descriptor sequence and hence can't be
442 1.1 reinoud * allocated later.
443 1.1 reinoud */
444 1.1 reinoud pos = 0;
445 1.1 reinoud layout.unalloc_space = pos;
446 1.1 reinoud pos += layout.alloc_bitmap_dscr_size;
447 1.1 reinoud
448 1.1 reinoud /* claim metadata descriptors and partition space [UDF 2.2.10] */
449 1.1 reinoud if (format_flags & FORMAT_META) {
450 1.1 reinoud /* note: all in backing partition space */
451 1.1 reinoud layout.meta_file = pos++;
452 1.1 reinoud layout.meta_bitmap = 0xffffffff;
453 1.1 reinoud if (!(context.format_flags & FORMAT_READONLY))
454 1.1 reinoud layout.meta_bitmap = pos++;
455 1.1 reinoud layout.meta_mirror = layout.part_size_lba-1;
456 1.1 reinoud layout.meta_alignment = MAX(blockingnr, spareable_blockingnr);
457 1.1 reinoud layout.meta_blockingnr = MAX(layout.meta_alignment, 32);
458 1.1 reinoud
459 1.1 reinoud /* calculate our partition length and store in sectors */
460 1.1 reinoud layout.meta_part_size_lba = layout.part_size_lba *
461 1.1 reinoud ((float) context.meta_perc / 100.0);
462 1.1 reinoud layout.meta_part_size_lba = MAX(layout.meta_part_size_lba, 32);
463 1.1 reinoud layout.meta_part_size_lba =
464 1.1 reinoud UDF_ROUNDDOWN(layout.meta_part_size_lba, layout.meta_blockingnr);
465 1.1 reinoud
466 1.1 reinoud if (!(context.format_flags & FORMAT_READONLY)) {
467 1.1 reinoud /* metadata partition free space bitmap */
468 1.1 reinoud bytes = udf_space_bitmap_len(layout.meta_part_size_lba);
469 1.1 reinoud layout.meta_bitmap_dscr_size = udf_bytes_to_sectors(bytes);
470 1.1 reinoud
471 1.1 reinoud layout.meta_bitmap_space = pos;
472 1.1 reinoud pos += layout.meta_bitmap_dscr_size;
473 1.1 reinoud }
474 1.1 reinoud
475 1.1 reinoud layout.meta_part_start_lba = UDF_ROUNDUP(pos, layout.meta_alignment);
476 1.1 reinoud pos = layout.meta_part_start_lba + layout.meta_part_size_lba;
477 1.1 reinoud }
478 1.1 reinoud
479 1.1 reinoud if (context.metadata_part == context.data_part) {
480 1.1 reinoud mpos = pos;
481 1.1 reinoud layout.fsd = mpos; mpos += 1;
482 1.1 reinoud layout.rootdir = mpos;
483 1.1 reinoud pos = mpos;
484 1.1 reinoud } else {
485 1.1 reinoud mpos = 0;
486 1.1 reinoud layout.fsd = mpos; mpos += 1;
487 1.1 reinoud layout.rootdir = mpos;
488 1.1 reinoud }
489 1.1 reinoud
490 1.1 reinoud /* pos and mpos now refer to the rootdir block */
491 1.1 reinoud context.alloc_pos[context.data_part] = pos;
492 1.1 reinoud context.alloc_pos[context.metadata_part] = mpos;
493 1.1 reinoud
494 1.1 reinoud udf_dump_layout();
495 1.1 reinoud
496 1.1 reinoud kbsize = (uint64_t) last_lba * sector_size;
497 1.1 reinoud printf("Total space on this medium approx. "
498 1.1 reinoud "%"PRIu64" KiB, %"PRIu64" MiB\n",
499 1.1 reinoud kbsize/1024, kbsize/(1024*1024));
500 1.1 reinoud kbsize = (uint64_t)(layout.part_size_lba - layout.alloc_bitmap_dscr_size
501 1.1 reinoud - layout.meta_bitmap_dscr_size) * sector_size;
502 1.1 reinoud printf("Recordable free space on this volume approx. "
503 1.1 reinoud "%"PRIu64" KiB, %"PRIu64" MiB\n\n",
504 1.1 reinoud kbsize/1024, kbsize/(1024*1024));
505 1.1 reinoud
506 1.1 reinoud return 0;
507 1.1 reinoud }
508 1.1 reinoud
509 1.1 reinoud
510 1.1 reinoud /*
511 1.1 reinoud * Check if the blob starts with a good UDF tag. Tags are protected by a
512 1.1 reinoud * checksum over the header, except one byte at position 4 that is the
513 1.1 reinoud * checksum itself.
514 1.1 reinoud */
515 1.1 reinoud int
516 1.1 reinoud udf_check_tag(void *blob)
517 1.1 reinoud {
518 1.1 reinoud struct desc_tag *tag = blob;
519 1.1 reinoud uint8_t *pos, sum, cnt;
520 1.1 reinoud
521 1.1 reinoud /* check TAG header checksum */
522 1.1 reinoud pos = (uint8_t *) tag;
523 1.1 reinoud sum = 0;
524 1.1 reinoud
525 1.1 reinoud for(cnt = 0; cnt < 16; cnt++) {
526 1.1 reinoud if (cnt != 4)
527 1.1 reinoud sum += *pos;
528 1.1 reinoud pos++;
529 1.1 reinoud }
530 1.1 reinoud if (sum != tag->cksum) {
531 1.1 reinoud /* bad tag header checksum; this is not a valid tag */
532 1.1 reinoud return EINVAL;
533 1.1 reinoud }
534 1.1 reinoud
535 1.1 reinoud return 0;
536 1.1 reinoud }
537 1.1 reinoud
538 1.1 reinoud
539 1.1 reinoud /*
540 1.1 reinoud * check tag payload will check descriptor CRC as specified.
541 1.1 reinoud * If the descriptor is too long, it will return EIO otherwise EINVAL.
542 1.1 reinoud */
543 1.1 reinoud int
544 1.1 reinoud udf_check_tag_payload(void *blob, uint32_t max_length)
545 1.1 reinoud {
546 1.1 reinoud struct desc_tag *tag = blob;
547 1.1 reinoud uint16_t crc, crc_len;
548 1.1 reinoud
549 1.1 reinoud crc_len = udf_rw16(tag->desc_crc_len);
550 1.1 reinoud
551 1.1 reinoud /* check payload CRC if applicable */
552 1.1 reinoud if (crc_len == 0)
553 1.1 reinoud return 0;
554 1.1 reinoud
555 1.1 reinoud if (crc_len > max_length)
556 1.1 reinoud return EIO;
557 1.1 reinoud
558 1.1 reinoud crc = udf_cksum(((uint8_t *) tag) + UDF_DESC_TAG_LENGTH, crc_len);
559 1.1 reinoud if (crc != udf_rw16(tag->desc_crc)) {
560 1.1 reinoud /* bad payload CRC; this is a broken tag */
561 1.1 reinoud return EINVAL;
562 1.1 reinoud }
563 1.1 reinoud
564 1.1 reinoud return 0;
565 1.1 reinoud }
566 1.1 reinoud
567 1.1 reinoud
568 1.1 reinoud int
569 1.1 reinoud udf_check_tag_and_location(void *blob, uint32_t location)
570 1.1 reinoud {
571 1.1 reinoud struct desc_tag *tag = blob;
572 1.1 reinoud
573 1.1 reinoud if (udf_check_tag(blob))
574 1.1 reinoud return 1;
575 1.1 reinoud if (udf_rw32(tag->tag_loc) != location)
576 1.1 reinoud return 1;
577 1.1 reinoud return 0;
578 1.1 reinoud }
579 1.1 reinoud
580 1.1 reinoud
581 1.1 reinoud int
582 1.1 reinoud udf_validate_tag_sum(union dscrptr *dscr)
583 1.1 reinoud {
584 1.1 reinoud struct desc_tag *tag = &dscr->tag;
585 1.1 reinoud uint8_t *pos, sum, cnt;
586 1.1 reinoud
587 1.1 reinoud /* calculate TAG header checksum */
588 1.1 reinoud pos = (uint8_t *) tag;
589 1.1 reinoud sum = 0;
590 1.1 reinoud
591 1.1 reinoud for (cnt = 0; cnt < 16; cnt++) {
592 1.1 reinoud if (cnt != 4) sum += *pos;
593 1.1 reinoud pos++;
594 1.1 reinoud };
595 1.1 reinoud tag->cksum = sum; /* 8 bit */
596 1.1 reinoud
597 1.1 reinoud return 0;
598 1.1 reinoud }
599 1.1 reinoud
600 1.1 reinoud
601 1.1 reinoud /* assumes sector number of descriptor to be already present */
602 1.1 reinoud int
603 1.1 reinoud udf_validate_tag_and_crc_sums(union dscrptr *dscr)
604 1.1 reinoud {
605 1.1 reinoud struct desc_tag *tag = &dscr->tag;
606 1.1 reinoud uint16_t crc;
607 1.1 reinoud
608 1.1 reinoud /* check payload CRC if applicable */
609 1.1 reinoud if (udf_rw16(tag->desc_crc_len) > 0) {
610 1.1 reinoud crc = udf_cksum(((uint8_t *) tag) + UDF_DESC_TAG_LENGTH,
611 1.1 reinoud udf_rw16(tag->desc_crc_len));
612 1.1 reinoud tag->desc_crc = udf_rw16(crc);
613 1.1 reinoud };
614 1.1 reinoud
615 1.1 reinoud /* calculate TAG header checksum */
616 1.1 reinoud return udf_validate_tag_sum(dscr);
617 1.1 reinoud }
618 1.1 reinoud
619 1.1 reinoud
620 1.1 reinoud void
621 1.1 reinoud udf_inittag(struct desc_tag *tag, int tagid, uint32_t loc)
622 1.1 reinoud {
623 1.1 reinoud tag->id = udf_rw16(tagid);
624 1.1 reinoud tag->descriptor_ver = udf_rw16(context.dscrver);
625 1.1 reinoud tag->cksum = 0;
626 1.1 reinoud tag->reserved = 0;
627 1.1 reinoud tag->serial_num = udf_rw16(context.serialnum);
628 1.1 reinoud tag->tag_loc = udf_rw32(loc);
629 1.1 reinoud }
630 1.1 reinoud
631 1.1 reinoud
632 1.1 reinoud int
633 1.1 reinoud udf_create_anchor(int num)
634 1.1 reinoud {
635 1.1 reinoud struct anchor_vdp *avdp;
636 1.1 reinoud uint32_t vds1_extent_len = layout.vds1_size * context.sector_size;
637 1.1 reinoud uint32_t vds2_extent_len = layout.vds2_size * context.sector_size;
638 1.1 reinoud
639 1.1 reinoud avdp = context.anchors[num];
640 1.1 reinoud if (!avdp)
641 1.1 reinoud if ((avdp = calloc(1, context.sector_size)) == NULL)
642 1.1 reinoud return ENOMEM;
643 1.1 reinoud
644 1.1 reinoud udf_inittag(&avdp->tag, TAGID_ANCHOR, layout.anchors[num]);
645 1.1 reinoud
646 1.1 reinoud avdp->main_vds_ex.loc = udf_rw32(layout.vds1);
647 1.1 reinoud avdp->main_vds_ex.len = udf_rw32(vds1_extent_len);
648 1.1 reinoud
649 1.1 reinoud avdp->reserve_vds_ex.loc = udf_rw32(layout.vds2);
650 1.1 reinoud avdp->reserve_vds_ex.len = udf_rw32(vds2_extent_len);
651 1.1 reinoud
652 1.1 reinoud /* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */
653 1.1 reinoud avdp->tag.desc_crc_len = udf_rw16(512-UDF_DESC_TAG_LENGTH);
654 1.1 reinoud
655 1.1 reinoud context.anchors[num] = avdp;
656 1.1 reinoud return 0;
657 1.1 reinoud }
658 1.1 reinoud
659 1.1 reinoud
660 1.1 reinoud void
661 1.1 reinoud udf_create_terminator(union dscrptr *dscr, uint32_t loc)
662 1.1 reinoud {
663 1.1 reinoud memset(dscr, 0, context.sector_size);
664 1.1 reinoud udf_inittag(&dscr->tag, TAGID_TERM, loc);
665 1.1 reinoud
666 1.1 reinoud /* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */
667 1.1 reinoud dscr->tag.desc_crc_len = udf_rw16(512-UDF_DESC_TAG_LENGTH);
668 1.1 reinoud }
669 1.1 reinoud
670 1.1 reinoud
671 1.1 reinoud void
672 1.1 reinoud udf_osta_charset(struct charspec *charspec)
673 1.1 reinoud {
674 1.1 reinoud memset(charspec, 0, sizeof(*charspec));
675 1.1 reinoud charspec->type = 0;
676 1.1 reinoud strcpy((char *) charspec->inf, "OSTA Compressed Unicode");
677 1.1 reinoud }
678 1.1 reinoud
679 1.1 reinoud
680 1.1 reinoud /* ---- shared from kernel's udf_subr.c, slightly modified ---- */
681 1.1 reinoud void
682 1.1 reinoud udf_to_unix_name(char *result, int result_len, char *id, int len,
683 1.1 reinoud struct charspec *chsp)
684 1.1 reinoud {
685 1.1 reinoud uint16_t *raw_name, *unix_name;
686 1.1 reinoud uint16_t *inchp, ch;
687 1.1 reinoud char *outchp;
688 1.1 reinoud const char *osta_id = "OSTA Compressed Unicode";
689 1.1 reinoud int ucode_chars, nice_uchars, is_osta_typ0, nout;
690 1.1 reinoud
691 1.1 reinoud raw_name = malloc(2048 * sizeof(uint16_t));
692 1.1 reinoud assert(raw_name);
693 1.1 reinoud
694 1.1 reinoud unix_name = raw_name + 1024; /* split space in half */
695 1.1 reinoud assert(sizeof(char) == sizeof(uint8_t));
696 1.1 reinoud outchp = result;
697 1.1 reinoud
698 1.1 reinoud is_osta_typ0 = (chsp->type == 0);
699 1.1 reinoud is_osta_typ0 &= (strcmp((char *) chsp->inf, osta_id) == 0);
700 1.1 reinoud if (is_osta_typ0) {
701 1.1 reinoud /* TODO clean up */
702 1.1 reinoud *raw_name = *unix_name = 0;
703 1.1 reinoud ucode_chars = udf_UncompressUnicode(len, (uint8_t *) id, raw_name);
704 1.1 reinoud ucode_chars = MIN(ucode_chars, UnicodeLength((unicode_t *) raw_name));
705 1.1 reinoud nice_uchars = UDFTransName(unix_name, raw_name, ucode_chars);
706 1.1 reinoud /* output UTF8 */
707 1.1 reinoud for (inchp = unix_name; nice_uchars>0; inchp++, nice_uchars--) {
708 1.1 reinoud ch = *inchp;
709 1.1 reinoud nout = wput_utf8(outchp, result_len, ch);
710 1.1 reinoud outchp += nout; result_len -= nout;
711 1.1 reinoud if (!ch) break;
712 1.1 reinoud }
713 1.1 reinoud *outchp++ = 0;
714 1.1 reinoud } else {
715 1.1 reinoud /* assume 8bit char length byte latin-1 */
716 1.1 reinoud assert(*id == 8);
717 1.1 reinoud assert(strlen((char *) (id+1)) <= NAME_MAX);
718 1.1 reinoud memcpy((char *) result, (char *) (id+1), strlen((char *) (id+1)));
719 1.1 reinoud }
720 1.1 reinoud free(raw_name);
721 1.1 reinoud }
722 1.1 reinoud
723 1.1 reinoud
724 1.1 reinoud void
725 1.1 reinoud unix_to_udf_name(char *result, uint8_t *result_len, char const *name, int name_len,
726 1.1 reinoud struct charspec *chsp)
727 1.1 reinoud {
728 1.1 reinoud uint16_t *raw_name;
729 1.1 reinoud uint16_t *outchp;
730 1.1 reinoud const char *inchp;
731 1.1 reinoud const char *osta_id = "OSTA Compressed Unicode";
732 1.1 reinoud int udf_chars, is_osta_typ0, bits;
733 1.1 reinoud size_t cnt;
734 1.1 reinoud
735 1.1 reinoud /* allocate temporary unicode-16 buffer */
736 1.1 reinoud raw_name = malloc(1024);
737 1.1 reinoud assert(raw_name);
738 1.1 reinoud
739 1.1 reinoud /* convert utf8 to unicode-16 */
740 1.1 reinoud *raw_name = 0;
741 1.1 reinoud inchp = name;
742 1.1 reinoud outchp = raw_name;
743 1.1 reinoud bits = 8;
744 1.1 reinoud for (cnt = name_len, udf_chars = 0; cnt;) {
745 1.1 reinoud *outchp = wget_utf8(&inchp, &cnt);
746 1.1 reinoud if (*outchp > 0xff)
747 1.1 reinoud bits=16;
748 1.1 reinoud outchp++;
749 1.1 reinoud udf_chars++;
750 1.1 reinoud }
751 1.1 reinoud /* null terminate just in case */
752 1.1 reinoud *outchp++ = 0;
753 1.1 reinoud
754 1.1 reinoud is_osta_typ0 = (chsp->type == 0);
755 1.1 reinoud is_osta_typ0 &= (strcmp((char *) chsp->inf, osta_id) == 0);
756 1.1 reinoud if (is_osta_typ0) {
757 1.1 reinoud udf_chars = udf_CompressUnicode(udf_chars, bits,
758 1.1 reinoud (unicode_t *) raw_name,
759 1.1 reinoud (byte *) result);
760 1.1 reinoud } else {
761 1.1 reinoud printf("unix to udf name: no CHSP0 ?\n");
762 1.1 reinoud /* XXX assume 8bit char length byte latin-1 */
763 1.1 reinoud *result++ = 8; udf_chars = 1;
764 1.1 reinoud strncpy(result, name + 1, name_len);
765 1.1 reinoud udf_chars += name_len;
766 1.1 reinoud }
767 1.1 reinoud *result_len = udf_chars;
768 1.1 reinoud free(raw_name);
769 1.1 reinoud }
770 1.1 reinoud
771 1.1 reinoud
772 1.1 reinoud /* first call udf_set_regid and then the suffix */
773 1.1 reinoud void
774 1.1 reinoud udf_set_regid(struct regid *regid, char const *name)
775 1.1 reinoud {
776 1.1 reinoud memset(regid, 0, sizeof(*regid));
777 1.1 reinoud regid->flags = 0; /* not dirty and not protected */
778 1.1 reinoud strcpy((char *) regid->id, name);
779 1.1 reinoud }
780 1.1 reinoud
781 1.1 reinoud
782 1.1 reinoud void
783 1.1 reinoud udf_add_domain_regid(struct regid *regid)
784 1.1 reinoud {
785 1.1 reinoud uint16_t *ver;
786 1.1 reinoud
787 1.1 reinoud ver = (uint16_t *) regid->id_suffix;
788 1.1 reinoud *ver = udf_rw16(context.min_udf);
789 1.1 reinoud }
790 1.1 reinoud
791 1.1 reinoud
792 1.1 reinoud void
793 1.1 reinoud udf_add_udf_regid(struct regid *regid)
794 1.1 reinoud {
795 1.1 reinoud uint16_t *ver;
796 1.1 reinoud
797 1.1 reinoud ver = (uint16_t *) regid->id_suffix;
798 1.1 reinoud *ver = udf_rw16(context.min_udf);
799 1.1 reinoud
800 1.1 reinoud regid->id_suffix[2] = 4; /* unix */
801 1.1 reinoud regid->id_suffix[3] = 8; /* NetBSD */
802 1.1 reinoud }
803 1.1 reinoud
804 1.1 reinoud
805 1.1 reinoud void
806 1.1 reinoud udf_add_impl_regid(struct regid *regid)
807 1.1 reinoud {
808 1.1 reinoud regid->id_suffix[0] = 4; /* unix */
809 1.1 reinoud regid->id_suffix[1] = 8; /* NetBSD */
810 1.1 reinoud }
811 1.1 reinoud
812 1.1 reinoud
813 1.1 reinoud void
814 1.1 reinoud udf_add_app_regid(struct regid *regid)
815 1.1 reinoud {
816 1.1 reinoud regid->id_suffix[0] = context.app_version_main;
817 1.1 reinoud regid->id_suffix[1] = context.app_version_sub;
818 1.1 reinoud }
819 1.1 reinoud
820 1.1 reinoud
821 1.2 riastrad /*
822 1.1 reinoud * Timestamp to timespec conversion code is taken with small modifications
823 1.1 reinoud * from FreeBSD /sys/fs/udf by Scott Long <scottl (at) freebsd.org>
824 1.1 reinoud */
825 1.1 reinoud
826 1.1 reinoud static int mon_lens[2][12] = {
827 1.1 reinoud {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
828 1.1 reinoud {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
829 1.1 reinoud };
830 1.1 reinoud
831 1.1 reinoud
832 1.1 reinoud static int
833 1.1 reinoud udf_isaleapyear(int year)
834 1.2 riastrad {
835 1.1 reinoud int i;
836 1.2 riastrad
837 1.1 reinoud i = (year % 4) ? 0 : 1;
838 1.1 reinoud i &= (year % 100) ? 1 : 0;
839 1.1 reinoud i |= (year % 400) ? 0 : 1;
840 1.2 riastrad
841 1.1 reinoud return i;
842 1.1 reinoud }
843 1.1 reinoud
844 1.1 reinoud
845 1.1 reinoud void
846 1.1 reinoud udf_timestamp_to_timespec(struct timestamp *timestamp, struct timespec *timespec)
847 1.1 reinoud {
848 1.1 reinoud uint32_t usecs, secs, nsecs;
849 1.1 reinoud uint16_t tz;
850 1.1 reinoud int i, lpyear, daysinyear, year;
851 1.1 reinoud
852 1.1 reinoud timespec->tv_sec = secs = 0;
853 1.1 reinoud timespec->tv_nsec = nsecs = 0;
854 1.1 reinoud
855 1.1 reinoud /*
856 1.1 reinoud * DirectCD seems to like using bogus year values.
857 1.1 reinoud * Distrust time->month especially, since it will be used for an array
858 1.1 reinoud * index.
859 1.1 reinoud */
860 1.1 reinoud year = udf_rw16(timestamp->year);
861 1.1 reinoud if ((year < 1970) || (timestamp->month > 12)) {
862 1.1 reinoud return;
863 1.1 reinoud }
864 1.2 riastrad
865 1.1 reinoud /* Calculate the time and day */
866 1.1 reinoud usecs = timestamp->usec + 100*timestamp->hund_usec + 10000*timestamp->centisec;
867 1.1 reinoud nsecs = usecs * 1000;
868 1.2 riastrad secs = timestamp->second;
869 1.1 reinoud secs += timestamp->minute * 60;
870 1.1 reinoud secs += timestamp->hour * 3600;
871 1.1 reinoud secs += (timestamp->day-1) * 3600 * 24; /* day : 1-31 */
872 1.2 riastrad
873 1.1 reinoud /* Calclulate the month */
874 1.1 reinoud lpyear = udf_isaleapyear(year);
875 1.1 reinoud for (i = 1; i < timestamp->month; i++)
876 1.1 reinoud secs += mon_lens[lpyear][i-1] * 3600 * 24; /* month: 1-12 */
877 1.2 riastrad
878 1.2 riastrad for (i = 1970; i < year; i++) {
879 1.1 reinoud daysinyear = udf_isaleapyear(i) + 365 ;
880 1.1 reinoud secs += daysinyear * 3600 * 24;
881 1.1 reinoud }
882 1.1 reinoud
883 1.1 reinoud /*
884 1.1 reinoud * Calculate the time zone. The timezone is 12 bit signed 2's
885 1.1 reinoud * compliment, so we gotta do some extra magic to handle it right.
886 1.1 reinoud */
887 1.1 reinoud tz = udf_rw16(timestamp->type_tz);
888 1.1 reinoud tz &= 0x0fff; /* only lower 12 bits are significant */
889 1.1 reinoud if (tz & 0x0800) /* sign extention */
890 1.1 reinoud tz |= 0xf000;
891 1.1 reinoud
892 1.1 reinoud /* TODO check timezone conversion */
893 1.1 reinoud #if 1
894 1.1 reinoud /* check if we are specified a timezone to convert */
895 1.1 reinoud if (udf_rw16(timestamp->type_tz) & 0x1000)
896 1.1 reinoud if ((int16_t) tz != -2047)
897 1.1 reinoud secs -= (int16_t) tz * 60;
898 1.1 reinoud #endif
899 1.1 reinoud timespec->tv_sec = secs;
900 1.1 reinoud timespec->tv_nsec = nsecs;
901 1.1 reinoud }
902 1.1 reinoud
903 1.1 reinoud
904 1.1 reinoud /*
905 1.1 reinoud * Fill in timestamp structure based on clock_gettime(). Time is reported back
906 1.1 reinoud * as a time_t accompanied with a nano second field.
907 1.1 reinoud *
908 1.1 reinoud * The husec, usec and csec could be relaxed in type.
909 1.1 reinoud */
910 1.1 reinoud void
911 1.1 reinoud udf_timespec_to_timestamp(struct timespec *timespec, struct timestamp *timestamp)
912 1.1 reinoud {
913 1.1 reinoud struct tm tm;
914 1.1 reinoud uint64_t husec, usec, csec;
915 1.1 reinoud
916 1.1 reinoud memset(timestamp, 0, sizeof(*timestamp));
917 1.1 reinoud gmtime_r(×pec->tv_sec, &tm);
918 1.1 reinoud
919 1.1 reinoud /*
920 1.1 reinoud * Time type and time zone : see ECMA 1/7.3, UDF 2., 2.1.4.1, 3.1.1.
921 1.1 reinoud *
922 1.1 reinoud * Lower 12 bits are two complement signed timezone offset if bit 12
923 1.1 reinoud * (method 1) is clear. Otherwise if bit 12 is set, specify timezone
924 1.1 reinoud * offset to -2047 i.e. unsigned `zero'
925 1.1 reinoud */
926 1.1 reinoud
927 1.1 reinoud /* set method 1 for CUT/GMT */
928 1.1 reinoud timestamp->type_tz = udf_rw16((1<<12) + 0);
929 1.1 reinoud timestamp->year = udf_rw16(tm.tm_year + 1900);
930 1.1 reinoud timestamp->month = tm.tm_mon + 1; /* `tm' uses 0..11 for months */
931 1.1 reinoud timestamp->day = tm.tm_mday;
932 1.1 reinoud timestamp->hour = tm.tm_hour;
933 1.1 reinoud timestamp->minute = tm.tm_min;
934 1.1 reinoud timestamp->second = tm.tm_sec;
935 1.1 reinoud
936 1.1 reinoud usec = (timespec->tv_nsec + 500) / 1000; /* round */
937 1.1 reinoud husec = usec / 100;
938 1.1 reinoud usec -= husec * 100; /* only 0-99 in usec */
939 1.1 reinoud csec = husec / 100; /* only 0-99 in csec */
940 1.1 reinoud husec -= csec * 100; /* only 0-99 in husec */
941 1.1 reinoud
942 1.1 reinoud /* in rare cases there is overflow in csec */
943 1.1 reinoud csec = MIN(99, csec);
944 1.1 reinoud husec = MIN(99, husec);
945 1.1 reinoud usec = MIN(99, usec);
946 1.1 reinoud
947 1.1 reinoud timestamp->centisec = csec;
948 1.1 reinoud timestamp->hund_usec = husec;
949 1.1 reinoud timestamp->usec = usec;
950 1.1 reinoud }
951 1.1 reinoud
952 1.1 reinoud
953 1.1 reinoud static void
954 1.1 reinoud udf_set_timestamp(struct timestamp *timestamp, time_t value)
955 1.1 reinoud {
956 1.1 reinoud struct timespec t;
957 1.1 reinoud
958 1.1 reinoud memset(&t, 0, sizeof(struct timespec));
959 1.1 reinoud t.tv_sec = value;
960 1.1 reinoud t.tv_nsec = 0;
961 1.1 reinoud udf_timespec_to_timestamp(&t, timestamp);
962 1.1 reinoud }
963 1.1 reinoud
964 1.1 reinoud
965 1.1 reinoud static uint32_t
966 1.1 reinoud unix_mode_to_udf_perm(mode_t mode)
967 1.1 reinoud {
968 1.1 reinoud uint32_t perm;
969 1.2 riastrad
970 1.1 reinoud perm = ((mode & S_IRWXO) );
971 1.1 reinoud perm |= ((mode & S_IRWXG) << 2);
972 1.1 reinoud perm |= ((mode & S_IRWXU) << 4);
973 1.1 reinoud perm |= ((mode & S_IWOTH) << 3);
974 1.1 reinoud perm |= ((mode & S_IWGRP) << 5);
975 1.1 reinoud perm |= ((mode & S_IWUSR) << 7);
976 1.1 reinoud
977 1.1 reinoud return perm;
978 1.1 reinoud }
979 1.1 reinoud
980 1.1 reinoud /* end of copied code */
981 1.1 reinoud
982 1.1 reinoud
983 1.1 reinoud void
984 1.1 reinoud udf_encode_osta_id(char *osta_id, uint16_t len, char *text)
985 1.1 reinoud {
986 1.1 reinoud struct charspec osta_charspec;
987 1.1 reinoud uint8_t result_len;
988 1.1 reinoud
989 1.1 reinoud memset(osta_id, 0, len);
990 1.1 reinoud if (!text || (strlen(text) == 0)) return;
991 1.1 reinoud
992 1.1 reinoud udf_osta_charset(&osta_charspec);
993 1.1 reinoud unix_to_udf_name(osta_id, &result_len, text, strlen(text),
994 1.1 reinoud &osta_charspec);
995 1.1 reinoud
996 1.1 reinoud /* Ecma 167/7.2.13 states that length is recorded in the last byte */
997 1.1 reinoud osta_id[len-1] = strlen(text)+1;
998 1.1 reinoud }
999 1.1 reinoud
1000 1.1 reinoud
1001 1.1 reinoud void
1002 1.1 reinoud udf_set_timestamp_now(struct timestamp *timestamp)
1003 1.1 reinoud {
1004 1.1 reinoud struct timespec now;
1005 1.1 reinoud
1006 1.1 reinoud #ifdef CLOCK_REALTIME
1007 1.1 reinoud (void)clock_gettime(CLOCK_REALTIME, &now);
1008 1.1 reinoud #else
1009 1.1 reinoud struct timeval time_of_day;
1010 1.1 reinoud
1011 1.1 reinoud (void)gettimeofday(&time_of_day, NULL);
1012 1.1 reinoud now.tv_sec = time_of_day.tv_sec;
1013 1.1 reinoud now.tv_nsec = time_of_day.tv_usec * 1000;
1014 1.1 reinoud #endif
1015 1.1 reinoud udf_timespec_to_timestamp(&now, timestamp);
1016 1.1 reinoud }
1017 1.1 reinoud
1018 1.1 reinoud
1019 1.1 reinoud int
1020 1.1 reinoud udf_create_primaryd(void)
1021 1.1 reinoud {
1022 1.1 reinoud struct pri_vol_desc *pri;
1023 1.1 reinoud uint16_t crclen;
1024 1.1 reinoud
1025 1.1 reinoud pri = calloc(1, context.sector_size);
1026 1.1 reinoud if (pri == NULL)
1027 1.1 reinoud return ENOMEM;
1028 1.1 reinoud
1029 1.1 reinoud memset(pri, 0, context.sector_size);
1030 1.1 reinoud udf_inittag(&pri->tag, TAGID_PRI_VOL, /* loc */ 0);
1031 1.1 reinoud pri->seq_num = udf_rw32(context.vds_seq); context.vds_seq++;
1032 1.1 reinoud
1033 1.1 reinoud pri->pvd_num = udf_rw32(0); /* default serial */
1034 1.1 reinoud udf_encode_osta_id(pri->vol_id, 32, context.primary_name);
1035 1.1 reinoud
1036 1.1 reinoud /* set defaults for single disc volumes as UDF prescribes */
1037 1.1 reinoud pri->vds_num = udf_rw16(1);
1038 1.1 reinoud pri->max_vol_seq = udf_rw16(1);
1039 1.1 reinoud pri->ichg_lvl = udf_rw16(2);
1040 1.1 reinoud pri->max_ichg_lvl = udf_rw16(3);
1041 1.1 reinoud pri->flags = udf_rw16(0);
1042 1.1 reinoud
1043 1.1 reinoud pri->charset_list = udf_rw32(1); /* only CS0 */
1044 1.1 reinoud pri->max_charset_list = udf_rw32(1); /* only CS0 */
1045 1.1 reinoud
1046 1.1 reinoud udf_encode_osta_id(pri->volset_id, 128, context.volset_name);
1047 1.1 reinoud udf_osta_charset(&pri->desc_charset);
1048 1.1 reinoud udf_osta_charset(&pri->explanatory_charset);
1049 1.1 reinoud
1050 1.1 reinoud udf_set_regid(&pri->app_id, context.app_name);
1051 1.1 reinoud udf_add_app_regid(&pri->app_id);
1052 1.1 reinoud
1053 1.1 reinoud udf_set_regid(&pri->imp_id, context.impl_name);
1054 1.1 reinoud udf_add_impl_regid(&pri->imp_id);
1055 1.1 reinoud
1056 1.1 reinoud udf_set_timestamp_now(&pri->time);
1057 1.1 reinoud
1058 1.1 reinoud crclen = sizeof(struct pri_vol_desc) - UDF_DESC_TAG_LENGTH;
1059 1.1 reinoud pri->tag.desc_crc_len = udf_rw16(crclen);
1060 1.1 reinoud
1061 1.1 reinoud context.primary_vol = pri;
1062 1.1 reinoud
1063 1.1 reinoud return 0;
1064 1.1 reinoud }
1065 1.1 reinoud
1066 1.1 reinoud
1067 1.1 reinoud /*
1068 1.1 reinoud * BUGALERT: some rogue implementations use random physical partition
1069 1.1 reinoud * numbers to break other implementations so lookup the number.
1070 1.1 reinoud */
1071 1.1 reinoud
1072 1.1 reinoud uint16_t
1073 1.1 reinoud udf_find_raw_phys(uint16_t raw_phys_part)
1074 1.1 reinoud {
1075 1.1 reinoud struct part_desc *part;
1076 1.1 reinoud uint16_t phys_part;
1077 1.1 reinoud
1078 1.1 reinoud for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) {
1079 1.1 reinoud part = context.partitions[phys_part];
1080 1.1 reinoud if (part == NULL)
1081 1.1 reinoud break;
1082 1.1 reinoud if (udf_rw16(part->part_num) == raw_phys_part)
1083 1.1 reinoud break;
1084 1.1 reinoud }
1085 1.1 reinoud return phys_part;
1086 1.1 reinoud }
1087 1.1 reinoud
1088 1.1 reinoud
1089 1.1 reinoud /* XXX no support for unallocated or freed space tables yet (!) */
1090 1.1 reinoud int
1091 1.1 reinoud udf_create_partitiond(int part_num)
1092 1.1 reinoud {
1093 1.1 reinoud struct part_desc *pd;
1094 1.1 reinoud struct part_hdr_desc *phd;
1095 1.1 reinoud uint32_t sector_size, bitmap_bytes;
1096 1.1 reinoud uint16_t crclen;
1097 1.1 reinoud int part_accesstype = context.media_accesstype;
1098 1.1 reinoud
1099 1.1 reinoud sector_size = context.sector_size;
1100 1.1 reinoud bitmap_bytes = layout.alloc_bitmap_dscr_size * sector_size;
1101 1.1 reinoud
1102 1.1 reinoud if (context.partitions[part_num])
1103 1.1 reinoud errx(1, "internal error, partition %d already defined in %s",
1104 1.1 reinoud part_num, __func__);
1105 1.1 reinoud
1106 1.1 reinoud pd = calloc(1, context.sector_size);
1107 1.1 reinoud if (pd == NULL)
1108 1.1 reinoud return ENOMEM;
1109 1.1 reinoud phd = &pd->_impl_use.part_hdr;
1110 1.1 reinoud
1111 1.1 reinoud udf_inittag(&pd->tag, TAGID_PARTITION, /* loc */ 0);
1112 1.1 reinoud pd->seq_num = udf_rw32(context.vds_seq); context.vds_seq++;
1113 1.1 reinoud
1114 1.1 reinoud pd->flags = udf_rw16(1); /* allocated */
1115 1.1 reinoud pd->part_num = udf_rw16(part_num); /* only one physical partition */
1116 1.1 reinoud
1117 1.1 reinoud if (context.dscrver == 2) {
1118 1.1 reinoud udf_set_regid(&pd->contents, "+NSR02");
1119 1.1 reinoud } else {
1120 1.1 reinoud udf_set_regid(&pd->contents, "+NSR03");
1121 1.1 reinoud }
1122 1.1 reinoud udf_add_app_regid(&pd->contents);
1123 1.1 reinoud
1124 1.1 reinoud phd->unalloc_space_bitmap.len = udf_rw32(bitmap_bytes);
1125 1.1 reinoud phd->unalloc_space_bitmap.lb_num = udf_rw32(layout.unalloc_space);
1126 1.1 reinoud
1127 1.1 reinoud if (layout.freed_space) {
1128 1.1 reinoud phd->freed_space_bitmap.len = udf_rw32(bitmap_bytes);
1129 1.1 reinoud phd->freed_space_bitmap.lb_num = udf_rw32(layout.freed_space);
1130 1.1 reinoud }
1131 1.1 reinoud
1132 1.1 reinoud pd->access_type = udf_rw32(part_accesstype);
1133 1.1 reinoud pd->start_loc = udf_rw32(layout.part_start_lba);
1134 1.1 reinoud pd->part_len = udf_rw32(layout.part_size_lba);
1135 1.1 reinoud
1136 1.1 reinoud udf_set_regid(&pd->imp_id, context.impl_name);
1137 1.1 reinoud udf_add_impl_regid(&pd->imp_id);
1138 1.1 reinoud
1139 1.1 reinoud crclen = sizeof(struct part_desc) - UDF_DESC_TAG_LENGTH;
1140 1.1 reinoud pd->tag.desc_crc_len = udf_rw16(crclen);
1141 1.1 reinoud
1142 1.1 reinoud context.partitions[part_num] = pd;
1143 1.1 reinoud
1144 1.1 reinoud return 0;
1145 1.1 reinoud }
1146 1.1 reinoud
1147 1.1 reinoud
1148 1.1 reinoud int
1149 1.1 reinoud udf_create_unalloc_spaced(void)
1150 1.1 reinoud {
1151 1.1 reinoud struct unalloc_sp_desc *usd;
1152 1.1 reinoud uint16_t crclen;
1153 1.1 reinoud
1154 1.1 reinoud usd = calloc(1, context.sector_size);
1155 1.1 reinoud if (usd == NULL)
1156 1.1 reinoud return ENOMEM;
1157 1.1 reinoud
1158 1.1 reinoud udf_inittag(&usd->tag, TAGID_UNALLOC_SPACE, /* loc */ 0);
1159 1.1 reinoud usd->seq_num = udf_rw32(context.vds_seq); context.vds_seq++;
1160 1.1 reinoud
1161 1.1 reinoud /* no default entries */
1162 1.1 reinoud usd->alloc_desc_num = udf_rw32(0); /* no entries */
1163 1.1 reinoud
1164 1.1 reinoud crclen = sizeof(struct unalloc_sp_desc) - sizeof(struct extent_ad);
1165 1.1 reinoud crclen -= UDF_DESC_TAG_LENGTH;
1166 1.1 reinoud usd->tag.desc_crc_len = udf_rw16(crclen);
1167 1.1 reinoud
1168 1.1 reinoud context.unallocated = usd;
1169 1.1 reinoud
1170 1.1 reinoud return 0;
1171 1.1 reinoud }
1172 1.1 reinoud
1173 1.1 reinoud
1174 1.1 reinoud static int
1175 1.1 reinoud udf_create_base_logical_dscr(void)
1176 1.1 reinoud {
1177 1.1 reinoud struct logvol_desc *lvd;
1178 1.1 reinoud uint32_t sector_size;
1179 1.1 reinoud uint16_t crclen;
1180 1.1 reinoud
1181 1.1 reinoud sector_size = context.sector_size;
1182 1.1 reinoud
1183 1.1 reinoud lvd = calloc(1, sector_size);
1184 1.1 reinoud if (lvd == NULL)
1185 1.1 reinoud return ENOMEM;
1186 1.1 reinoud
1187 1.1 reinoud udf_inittag(&lvd->tag, TAGID_LOGVOL, /* loc */ 0);
1188 1.1 reinoud lvd->seq_num = udf_rw32(context.vds_seq); context.vds_seq++;
1189 1.1 reinoud
1190 1.1 reinoud udf_osta_charset(&lvd->desc_charset);
1191 1.1 reinoud udf_encode_osta_id(lvd->logvol_id, 128, context.logvol_name);
1192 1.1 reinoud lvd->lb_size = udf_rw32(sector_size);
1193 1.1 reinoud
1194 1.1 reinoud udf_set_regid(&lvd->domain_id, "*OSTA UDF Compliant");
1195 1.1 reinoud udf_add_domain_regid(&lvd->domain_id);
1196 1.1 reinoud
1197 1.1 reinoud /* no partition mappings/entries yet */
1198 1.1 reinoud lvd->mt_l = udf_rw32(0);
1199 1.1 reinoud lvd->n_pm = udf_rw32(0);
1200 1.1 reinoud
1201 1.1 reinoud udf_set_regid(&lvd->imp_id, context.impl_name);
1202 1.1 reinoud udf_add_impl_regid(&lvd->imp_id);
1203 1.1 reinoud
1204 1.1 reinoud lvd->integrity_seq_loc.loc = udf_rw32(layout.lvis);
1205 1.1 reinoud lvd->integrity_seq_loc.len = udf_rw32(layout.lvis_size * sector_size);
1206 1.1 reinoud
1207 1.1 reinoud /* just one fsd for now */
1208 1.1 reinoud lvd->lv_fsd_loc.len = udf_rw32(sector_size);
1209 1.1 reinoud lvd->lv_fsd_loc.loc.part_num = udf_rw32(context.metadata_part);
1210 1.1 reinoud lvd->lv_fsd_loc.loc.lb_num = udf_rw32(layout.fsd);
1211 1.1 reinoud
1212 1.1 reinoud crclen = sizeof(struct logvol_desc) - 1 - UDF_DESC_TAG_LENGTH;
1213 1.1 reinoud lvd->tag.desc_crc_len = udf_rw16(crclen);
1214 1.1 reinoud
1215 1.1 reinoud context.logical_vol = lvd;
1216 1.1 reinoud context.vtop_tp[UDF_VTOP_RAWPART] = UDF_VTOP_TYPE_RAW;
1217 1.1 reinoud
1218 1.1 reinoud return 0;
1219 1.1 reinoud }
1220 1.1 reinoud
1221 1.1 reinoud
1222 1.2 riastrad static void
1223 1.1 reinoud udf_add_logvol_part_physical(uint16_t phys_part)
1224 1.1 reinoud {
1225 1.1 reinoud struct logvol_desc *logvol = context.logical_vol;
1226 1.1 reinoud union udf_pmap *pmap;
1227 1.1 reinoud uint8_t *pmap_pos;
1228 1.1 reinoud uint16_t crclen;
1229 1.1 reinoud uint32_t pmap1_size, log_part;
1230 1.1 reinoud
1231 1.1 reinoud log_part = udf_rw32(logvol->n_pm);
1232 1.1 reinoud pmap_pos = logvol->maps + udf_rw32(logvol->mt_l);
1233 1.1 reinoud pmap1_size = sizeof(struct part_map_1);
1234 1.1 reinoud
1235 1.1 reinoud pmap = (union udf_pmap *) pmap_pos;
1236 1.1 reinoud pmap->pm1.type = 1;
1237 1.1 reinoud pmap->pm1.len = sizeof(struct part_map_1);
1238 1.1 reinoud pmap->pm1.vol_seq_num = udf_rw16(1); /* no multi-volume */
1239 1.1 reinoud pmap->pm1.part_num = udf_rw16(phys_part);
1240 1.1 reinoud
1241 1.1 reinoud context.vtop [log_part] = phys_part;
1242 1.1 reinoud context.vtop_tp [log_part] = UDF_VTOP_TYPE_PHYS;
1243 1.1 reinoud context.part_size[log_part] = layout.part_size_lba;
1244 1.1 reinoud context.part_free[log_part] = layout.part_size_lba;
1245 1.1 reinoud
1246 1.1 reinoud /* increment number of partitions and length */
1247 1.1 reinoud logvol->n_pm = udf_rw32(log_part + 1);
1248 1.1 reinoud logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmap1_size);
1249 1.1 reinoud
1250 1.1 reinoud crclen = udf_rw16(logvol->tag.desc_crc_len) + pmap1_size;
1251 1.1 reinoud logvol->tag.desc_crc_len = udf_rw16(crclen);
1252 1.1 reinoud }
1253 1.1 reinoud
1254 1.1 reinoud
1255 1.1 reinoud static void
1256 1.1 reinoud udf_add_logvol_part_virtual(uint16_t phys_part)
1257 1.1 reinoud {
1258 1.1 reinoud union udf_pmap *pmap;
1259 1.1 reinoud struct logvol_desc *logvol = context.logical_vol;
1260 1.1 reinoud uint8_t *pmap_pos;
1261 1.1 reinoud uint16_t crclen;
1262 1.1 reinoud uint32_t pmapv_size, log_part;
1263 1.1 reinoud
1264 1.1 reinoud log_part = udf_rw32(logvol->n_pm);
1265 1.1 reinoud pmap_pos = logvol->maps + udf_rw32(logvol->mt_l);
1266 1.1 reinoud pmapv_size = sizeof(struct part_map_2);
1267 1.1 reinoud
1268 1.1 reinoud pmap = (union udf_pmap *) pmap_pos;
1269 1.1 reinoud pmap->pmv.type = 2;
1270 1.1 reinoud pmap->pmv.len = pmapv_size;
1271 1.1 reinoud
1272 1.1 reinoud udf_set_regid(&pmap->pmv.id, "*UDF Virtual Partition");
1273 1.1 reinoud udf_add_udf_regid(&pmap->pmv.id);
1274 1.1 reinoud
1275 1.1 reinoud pmap->pmv.vol_seq_num = udf_rw16(1); /* no multi-volume */
1276 1.1 reinoud pmap->pmv.part_num = udf_rw16(phys_part);
1277 1.1 reinoud
1278 1.1 reinoud context.vtop [log_part] = phys_part;
1279 1.1 reinoud context.vtop_tp [log_part] = UDF_VTOP_TYPE_VIRT;
1280 1.1 reinoud context.part_size[log_part] = 0xffffffff;
1281 1.1 reinoud context.part_free[log_part] = 0xffffffff;
1282 1.1 reinoud
1283 1.1 reinoud /* increment number of partitions and length */
1284 1.1 reinoud logvol->n_pm = udf_rw32(log_part + 1);
1285 1.1 reinoud logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmapv_size);
1286 1.1 reinoud
1287 1.1 reinoud crclen = udf_rw16(logvol->tag.desc_crc_len) + pmapv_size;
1288 1.1 reinoud logvol->tag.desc_crc_len = udf_rw16(crclen);
1289 1.1 reinoud }
1290 1.1 reinoud
1291 1.1 reinoud
1292 1.1 reinoud /* sparing table size is in bytes */
1293 1.1 reinoud static void
1294 1.1 reinoud udf_add_logvol_part_spareable(uint16_t phys_part)
1295 1.1 reinoud {
1296 1.1 reinoud union udf_pmap *pmap;
1297 1.1 reinoud struct logvol_desc *logvol = context.logical_vol;
1298 1.1 reinoud uint32_t *st_pos, spareable_bytes, pmaps_size;
1299 1.1 reinoud uint8_t *pmap_pos, num;
1300 1.1 reinoud uint16_t crclen;
1301 1.1 reinoud uint32_t log_part;
1302 1.1 reinoud
1303 1.1 reinoud log_part = udf_rw32(logvol->n_pm);
1304 1.1 reinoud pmap_pos = logvol->maps + udf_rw32(logvol->mt_l);
1305 1.1 reinoud pmaps_size = sizeof(struct part_map_2);
1306 1.1 reinoud spareable_bytes = layout.spareable_area_size * context.sector_size;
1307 1.1 reinoud
1308 1.1 reinoud pmap = (union udf_pmap *) pmap_pos;
1309 1.1 reinoud pmap->pms.type = 2;
1310 1.1 reinoud pmap->pms.len = pmaps_size;
1311 1.1 reinoud
1312 1.1 reinoud udf_set_regid(&pmap->pmv.id, "*UDF Sparable Partition");
1313 1.1 reinoud udf_add_udf_regid(&pmap->pmv.id);
1314 1.1 reinoud
1315 1.1 reinoud pmap->pms.vol_seq_num = udf_rw16(1); /* no multi-volume */
1316 1.1 reinoud pmap->pms.part_num = udf_rw16(phys_part);
1317 1.1 reinoud
1318 1.1 reinoud pmap->pms.packet_len = udf_rw16(layout.spareable_blockingnr);
1319 1.1 reinoud pmap->pms.st_size = udf_rw32(spareable_bytes);
1320 1.1 reinoud
1321 1.1 reinoud /* enter spare tables */
1322 1.1 reinoud st_pos = &pmap->pms.st_loc[0];
1323 1.1 reinoud *st_pos++ = udf_rw32(layout.spt_1);
1324 1.1 reinoud *st_pos++ = udf_rw32(layout.spt_2);
1325 1.1 reinoud
1326 1.1 reinoud num = 2;
1327 1.1 reinoud if (layout.spt_2 == 0) num--;
1328 1.1 reinoud if (layout.spt_1 == 0) num--;
1329 1.1 reinoud pmap->pms.n_st = num; /* 8 bit */
1330 1.1 reinoud
1331 1.1 reinoud context.vtop [log_part] = phys_part;
1332 1.1 reinoud context.vtop_tp [log_part] = UDF_VTOP_TYPE_SPAREABLE;
1333 1.1 reinoud context.part_size[log_part] = layout.part_size_lba;
1334 1.1 reinoud context.part_free[log_part] = layout.part_size_lba;
1335 1.1 reinoud
1336 1.1 reinoud /* increment number of partitions and length */
1337 1.1 reinoud logvol->n_pm = udf_rw32(log_part + 1);
1338 1.1 reinoud logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmaps_size);
1339 1.1 reinoud
1340 1.1 reinoud crclen = udf_rw16(logvol->tag.desc_crc_len) + pmaps_size;
1341 1.1 reinoud logvol->tag.desc_crc_len = udf_rw16(crclen);
1342 1.1 reinoud }
1343 1.1 reinoud
1344 1.1 reinoud
1345 1.1 reinoud int
1346 1.1 reinoud udf_create_sparing_tabled(void)
1347 1.1 reinoud {
1348 1.1 reinoud struct udf_sparing_table *spt;
1349 1.1 reinoud struct spare_map_entry *sme;
1350 1.1 reinoud uint32_t loc, cnt;
1351 1.1 reinoud uint32_t crclen; /* XXX: should be 16; need to detect overflow */
1352 1.1 reinoud
1353 1.1 reinoud spt = calloc(context.sector_size, layout.sparing_table_dscr_lbas);
1354 1.1 reinoud if (spt == NULL)
1355 1.1 reinoud return ENOMEM;
1356 1.1 reinoud
1357 1.1 reinoud /* a sparing table descriptor is a whole spareable_blockingnr sectors */
1358 1.1 reinoud udf_inittag(&spt->tag, TAGID_SPARING_TABLE, /* loc */ 0);
1359 1.1 reinoud
1360 1.1 reinoud udf_set_regid(&spt->id, "*UDF Sparing Table");
1361 1.1 reinoud udf_add_udf_regid(&spt->id);
1362 1.1 reinoud
1363 1.1 reinoud spt->rt_l = udf_rw16(layout.spareable_blocks);
1364 1.1 reinoud spt->seq_num = udf_rw32(0); /* first generation */
1365 1.1 reinoud
1366 1.1 reinoud for (cnt = 0; cnt < layout.spareable_blocks; cnt++) {
1367 1.1 reinoud sme = &spt->entries[cnt];
1368 1.1 reinoud loc = layout.spareable_area + cnt * layout.spareable_blockingnr;
1369 1.1 reinoud sme->org = udf_rw32(0xffffffff); /* open for reloc */
1370 1.1 reinoud sme->map = udf_rw32(loc);
1371 1.1 reinoud }
1372 1.1 reinoud
1373 1.1 reinoud /* calculate crc len for actual size */
1374 1.1 reinoud crclen = sizeof(struct udf_sparing_table) - UDF_DESC_TAG_LENGTH;
1375 1.1 reinoud crclen += (layout.spareable_blocks-1) * sizeof(struct spare_map_entry);
1376 1.1 reinoud
1377 1.1 reinoud assert(crclen <= UINT16_MAX);
1378 1.1 reinoud spt->tag.desc_crc_len = udf_rw16((uint16_t)crclen);
1379 1.1 reinoud
1380 1.1 reinoud context.sparing_table = spt;
1381 1.1 reinoud
1382 1.1 reinoud return 0;
1383 1.1 reinoud }
1384 1.1 reinoud
1385 1.1 reinoud
1386 1.1 reinoud static void
1387 1.1 reinoud udf_add_logvol_part_meta(uint16_t phys_part)
1388 1.1 reinoud {
1389 1.1 reinoud union udf_pmap *pmap;
1390 1.1 reinoud struct logvol_desc *logvol = context.logical_vol;
1391 1.1 reinoud uint8_t *pmap_pos;
1392 1.1 reinoud uint32_t pmapv_size, log_part;
1393 1.1 reinoud uint16_t crclen;
1394 1.1 reinoud
1395 1.1 reinoud log_part = udf_rw32(logvol->n_pm);
1396 1.1 reinoud pmap_pos = logvol->maps + udf_rw32(logvol->mt_l);
1397 1.1 reinoud pmapv_size = sizeof(struct part_map_2);
1398 1.1 reinoud
1399 1.1 reinoud pmap = (union udf_pmap *) pmap_pos;
1400 1.1 reinoud pmap->pmm.type = 2;
1401 1.1 reinoud pmap->pmm.len = pmapv_size;
1402 1.1 reinoud
1403 1.1 reinoud udf_set_regid(&pmap->pmm.id, "*UDF Metadata Partition");
1404 1.1 reinoud udf_add_udf_regid(&pmap->pmm.id);
1405 1.1 reinoud
1406 1.1 reinoud pmap->pmm.vol_seq_num = udf_rw16(1); /* no multi-volume */
1407 1.1 reinoud pmap->pmm.part_num = udf_rw16(phys_part);
1408 1.1 reinoud
1409 1.1 reinoud /* fill in meta data file(s) and alloc/alignment unit sizes */
1410 1.1 reinoud pmap->pmm.meta_file_lbn = udf_rw32(layout.meta_file);
1411 1.1 reinoud pmap->pmm.meta_mirror_file_lbn = udf_rw32(layout.meta_mirror);
1412 1.1 reinoud pmap->pmm.meta_bitmap_file_lbn = udf_rw32(layout.meta_bitmap);
1413 1.1 reinoud pmap->pmm.alloc_unit_size = udf_rw32(layout.meta_blockingnr);
1414 1.1 reinoud pmap->pmm.alignment_unit_size = udf_rw16(layout.meta_alignment);
1415 1.1 reinoud pmap->pmm.flags = 0; /* METADATA_DUPLICATED */
1416 1.1 reinoud
1417 1.1 reinoud context.vtop [log_part] = phys_part;
1418 1.1 reinoud context.vtop_tp [log_part] = UDF_VTOP_TYPE_META;
1419 1.1 reinoud context.part_size[log_part] = layout.meta_part_size_lba;
1420 1.1 reinoud context.part_free[log_part] = layout.meta_part_size_lba;
1421 1.1 reinoud
1422 1.1 reinoud /* increment number of partitions and length */
1423 1.1 reinoud logvol->n_pm = udf_rw32(log_part + 1);
1424 1.1 reinoud logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmapv_size);
1425 1.1 reinoud
1426 1.1 reinoud crclen = udf_rw16(logvol->tag.desc_crc_len) + pmapv_size;
1427 1.1 reinoud logvol->tag.desc_crc_len = udf_rw16(crclen);
1428 1.1 reinoud }
1429 1.1 reinoud
1430 1.1 reinoud
1431 1.1 reinoud int
1432 1.1 reinoud udf_create_logical_dscr(void)
1433 1.1 reinoud {
1434 1.1 reinoud int error;
1435 1.1 reinoud
1436 1.1 reinoud if ((error = udf_create_base_logical_dscr()))
1437 1.1 reinoud return error;
1438 1.1 reinoud
1439 1.1 reinoud /* we pass data_part for there might be a read-only part one day */
1440 1.1 reinoud if (context.format_flags & FORMAT_SPAREABLE) {
1441 1.1 reinoud /* spareable partition mapping has no physical mapping */
1442 1.1 reinoud udf_add_logvol_part_spareable(context.data_part);
1443 1.1 reinoud } else {
1444 1.1 reinoud udf_add_logvol_part_physical(context.data_part);
1445 1.1 reinoud }
1446 1.1 reinoud
1447 1.1 reinoud if (context.format_flags & FORMAT_VAT) {
1448 1.1 reinoud /* add VAT virtual mapping; reflects on datapart */
1449 1.1 reinoud udf_add_logvol_part_virtual(context.data_part);
1450 1.1 reinoud }
1451 1.1 reinoud if (context.format_flags & FORMAT_META) {
1452 1.1 reinoud /* add META data mapping; reflects on datapart */
1453 1.1 reinoud udf_add_logvol_part_meta(context.data_part);
1454 1.1 reinoud }
1455 1.1 reinoud
1456 1.1 reinoud return 0;
1457 1.1 reinoud }
1458 1.1 reinoud
1459 1.1 reinoud
1460 1.1 reinoud int
1461 1.1 reinoud udf_create_impvold(char *field1, char *field2, char *field3)
1462 1.1 reinoud {
1463 1.1 reinoud struct impvol_desc *ivd;
1464 1.1 reinoud struct udf_lv_info *lvi;
1465 1.1 reinoud uint16_t crclen;
1466 1.1 reinoud
1467 1.1 reinoud ivd = calloc(1, context.sector_size);
1468 1.1 reinoud if (ivd == NULL)
1469 1.1 reinoud return ENOMEM;
1470 1.1 reinoud lvi = &ivd->_impl_use.lv_info;
1471 1.1 reinoud
1472 1.1 reinoud udf_inittag(&ivd->tag, TAGID_IMP_VOL, /* loc */ 0);
1473 1.1 reinoud ivd->seq_num = udf_rw32(context.vds_seq); context.vds_seq++;
1474 1.1 reinoud
1475 1.1 reinoud udf_set_regid(&ivd->impl_id, "*UDF LV Info");
1476 1.1 reinoud udf_add_udf_regid(&ivd->impl_id);
1477 1.1 reinoud
1478 1.1 reinoud /* fill in UDF specific part */
1479 1.1 reinoud udf_osta_charset(&lvi->lvi_charset);
1480 1.1 reinoud udf_encode_osta_id(lvi->logvol_id, 128, context.logvol_name);
1481 1.1 reinoud
1482 1.1 reinoud udf_encode_osta_id(lvi->lvinfo1, 36, field1);
1483 1.1 reinoud udf_encode_osta_id(lvi->lvinfo2, 36, field2);
1484 1.1 reinoud udf_encode_osta_id(lvi->lvinfo3, 36, field3);
1485 1.1 reinoud
1486 1.1 reinoud udf_set_regid(&lvi->impl_id, context.impl_name);
1487 1.1 reinoud udf_add_impl_regid(&lvi->impl_id);
1488 1.1 reinoud
1489 1.1 reinoud crclen = sizeof(struct impvol_desc) - UDF_DESC_TAG_LENGTH;
1490 1.1 reinoud ivd->tag.desc_crc_len = udf_rw16(crclen);
1491 1.1 reinoud
1492 1.1 reinoud context.implementation = ivd;
1493 1.1 reinoud
1494 1.1 reinoud return 0;
1495 1.1 reinoud }
1496 1.1 reinoud
1497 1.1 reinoud
1498 1.1 reinoud /* XXX might need to be sanitised a bit */
1499 1.1 reinoud void
1500 1.1 reinoud udf_update_lvintd(int type)
1501 1.1 reinoud {
1502 1.1 reinoud struct logvol_int_desc *lvid;
1503 1.1 reinoud struct udf_logvol_info *lvinfo;
1504 1.1 reinoud struct logvol_desc *logvol;
1505 1.1 reinoud uint32_t *pos;
1506 1.1 reinoud uint32_t cnt, num_partmappings;
1507 1.1 reinoud uint32_t crclen; /* XXX: should be 16; need to detect overflow */
1508 1.1 reinoud
1509 1.1 reinoud lvid = context.logvol_integrity;
1510 1.1 reinoud logvol = context.logical_vol;
1511 1.1 reinoud assert(lvid);
1512 1.1 reinoud assert(logvol);
1513 1.1 reinoud
1514 1.1 reinoud lvid->integrity_type = udf_rw32(type);
1515 1.1 reinoud udf_set_timestamp_now(&lvid->time);
1516 1.1 reinoud
1517 1.1 reinoud /* initialise lvinfo just in case its not set yet */
1518 1.1 reinoud num_partmappings = udf_rw32(logvol->n_pm);
1519 1.1 reinoud assert(num_partmappings > 0);
1520 1.1 reinoud
1521 1.1 reinoud lvinfo = (struct udf_logvol_info *)
1522 1.1 reinoud (lvid->tables + num_partmappings * 2);
1523 1.1 reinoud context.logvol_info = lvinfo;
1524 1.1 reinoud
1525 1.1 reinoud udf_set_regid(&lvinfo->impl_id, context.impl_name);
1526 1.1 reinoud udf_add_impl_regid(&lvinfo->impl_id);
1527 1.1 reinoud
1528 1.1 reinoud if (type == UDF_INTEGRITY_CLOSED) {
1529 1.1 reinoud lvinfo->num_files = udf_rw32(context.num_files);
1530 1.1 reinoud lvinfo->num_directories = udf_rw32(context.num_directories);
1531 1.1 reinoud
1532 1.1 reinoud lvid->lvint_next_unique_id = udf_rw64(context.unique_id);
1533 1.1 reinoud }
1534 1.1 reinoud
1535 1.1 reinoud /* sane enough? */
1536 1.1 reinoud if (udf_rw16(lvinfo->min_udf_readver) < context.min_udf)
1537 1.1 reinoud lvinfo->min_udf_readver = udf_rw16(context.min_udf);
1538 1.1 reinoud if (udf_rw16(lvinfo->min_udf_writever) < context.min_udf)
1539 1.1 reinoud lvinfo->min_udf_writever = udf_rw16(context.min_udf);
1540 1.1 reinoud if (udf_rw16(lvinfo->max_udf_writever) < context.max_udf)
1541 1.1 reinoud lvinfo->max_udf_writever = udf_rw16(context.max_udf);
1542 1.1 reinoud
1543 1.1 reinoud lvid->num_part = udf_rw32(num_partmappings);
1544 1.1 reinoud
1545 1.1 reinoud pos = &lvid->tables[0];
1546 1.1 reinoud for (cnt = 0; cnt < num_partmappings; cnt++) {
1547 1.1 reinoud *pos++ = udf_rw32(context.part_free[cnt]);
1548 1.1 reinoud }
1549 1.1 reinoud for (cnt = 0; cnt < num_partmappings; cnt++) {
1550 1.1 reinoud *pos++ = udf_rw32(context.part_size[cnt]);
1551 1.1 reinoud }
1552 1.1 reinoud
1553 1.1 reinoud crclen = sizeof(struct logvol_int_desc) -4 -UDF_DESC_TAG_LENGTH +
1554 1.1 reinoud udf_rw32(lvid->l_iu);
1555 1.1 reinoud crclen += num_partmappings * 2 * 4;
1556 1.1 reinoud
1557 1.1 reinoud assert(crclen <= UINT16_MAX);
1558 1.1 reinoud if (lvid->tag.desc_crc_len == 0)
1559 1.1 reinoud lvid->tag.desc_crc_len = udf_rw16(crclen);
1560 1.1 reinoud
1561 1.1 reinoud context.logvol_info = lvinfo;
1562 1.1 reinoud }
1563 1.1 reinoud
1564 1.1 reinoud
1565 1.1 reinoud int
1566 1.1 reinoud udf_create_lvintd(int type)
1567 1.1 reinoud {
1568 1.1 reinoud struct logvol_int_desc *lvid;
1569 1.1 reinoud int l_iu;
1570 1.1 reinoud
1571 1.1 reinoud lvid = calloc(1, context.sector_size);
1572 1.1 reinoud if (lvid == NULL)
1573 1.1 reinoud return ENOMEM;
1574 1.1 reinoud
1575 1.1 reinoud udf_inittag(&lvid->tag, TAGID_LOGVOL_INTEGRITY, /* loc */ 0);
1576 1.1 reinoud context.logvol_integrity = lvid;
1577 1.1 reinoud
1578 1.1 reinoud /* only set for standard UDF info, no extra impl. use needed */
1579 1.1 reinoud l_iu = sizeof(struct udf_logvol_info);
1580 1.1 reinoud lvid->l_iu = udf_rw32(l_iu);
1581 1.1 reinoud
1582 1.1 reinoud udf_update_lvintd(type);
1583 1.1 reinoud
1584 1.1 reinoud return 0;
1585 1.1 reinoud }
1586 1.1 reinoud
1587 1.1 reinoud
1588 1.1 reinoud int
1589 1.1 reinoud udf_create_fsd(void)
1590 1.1 reinoud {
1591 1.1 reinoud struct fileset_desc *fsd;
1592 1.1 reinoud uint16_t crclen;
1593 1.1 reinoud
1594 1.1 reinoud fsd = calloc(1, context.sector_size);
1595 1.1 reinoud if (fsd == NULL)
1596 1.1 reinoud return ENOMEM;
1597 1.1 reinoud
1598 1.1 reinoud udf_inittag(&fsd->tag, TAGID_FSD, /* loc */ 0);
1599 1.1 reinoud
1600 1.1 reinoud udf_set_timestamp_now(&fsd->time);
1601 1.1 reinoud fsd->ichg_lvl = udf_rw16(3); /* UDF 2.3.2.1 */
1602 1.1 reinoud fsd->max_ichg_lvl = udf_rw16(3); /* UDF 2.3.2.2 */
1603 1.1 reinoud
1604 1.1 reinoud fsd->charset_list = udf_rw32(1); /* only CS0 */
1605 1.1 reinoud fsd->max_charset_list = udf_rw32(1); /* only CS0 */
1606 1.1 reinoud
1607 1.1 reinoud fsd->fileset_num = udf_rw32(0); /* only one fsd */
1608 1.1 reinoud fsd->fileset_desc_num = udf_rw32(0); /* original */
1609 1.1 reinoud
1610 1.1 reinoud udf_osta_charset(&fsd->logvol_id_charset);
1611 1.1 reinoud udf_encode_osta_id(fsd->logvol_id, 128, context.logvol_name);
1612 1.1 reinoud
1613 1.1 reinoud udf_osta_charset(&fsd->fileset_charset);
1614 1.1 reinoud udf_encode_osta_id(fsd->fileset_id, 32, context.fileset_name);
1615 1.1 reinoud
1616 1.1 reinoud /* copyright file and abstract file names obmitted */
1617 1.1 reinoud
1618 1.1 reinoud fsd->rootdir_icb.len = udf_rw32(context.sector_size);
1619 1.1 reinoud fsd->rootdir_icb.loc.lb_num = udf_rw32(layout.rootdir);
1620 1.1 reinoud fsd->rootdir_icb.loc.part_num = udf_rw16(context.metadata_part);
1621 1.1 reinoud
1622 1.1 reinoud udf_set_regid(&fsd->domain_id, "*OSTA UDF Compliant");
1623 1.1 reinoud udf_add_domain_regid(&fsd->domain_id);
1624 1.1 reinoud
1625 1.1 reinoud /* next_ex stays zero */
1626 1.1 reinoud /* no system streamdirs yet */
1627 1.1 reinoud
1628 1.1 reinoud crclen = sizeof(struct fileset_desc) - UDF_DESC_TAG_LENGTH;
1629 1.1 reinoud fsd->tag.desc_crc_len = udf_rw16(crclen);
1630 1.1 reinoud
1631 1.1 reinoud context.fileset_desc = fsd;
1632 1.1 reinoud
1633 1.1 reinoud return 0;
1634 1.1 reinoud }
1635 1.1 reinoud
1636 1.1 reinoud
1637 1.1 reinoud int
1638 1.1 reinoud udf_create_space_bitmap(uint32_t dscr_size, uint32_t part_size_lba,
1639 1.1 reinoud struct space_bitmap_desc **sbdp)
1640 1.1 reinoud {
1641 1.1 reinoud struct space_bitmap_desc *sbd;
1642 1.1 reinoud uint32_t cnt;
1643 1.1 reinoud uint16_t crclen;
1644 1.1 reinoud
1645 1.1 reinoud *sbdp = NULL;
1646 1.1 reinoud sbd = calloc(context.sector_size, dscr_size);
1647 1.1 reinoud if (sbd == NULL)
1648 1.1 reinoud return ENOMEM;
1649 1.1 reinoud
1650 1.1 reinoud udf_inittag(&sbd->tag, TAGID_SPACE_BITMAP, /* loc */ 0);
1651 1.1 reinoud
1652 1.1 reinoud sbd->num_bits = udf_rw32(part_size_lba);
1653 1.1 reinoud sbd->num_bytes = udf_rw32((part_size_lba + 7)/8);
1654 1.1 reinoud
1655 1.1 reinoud /* fill space with 0xff to indicate free */
1656 1.1 reinoud for (cnt = 0; cnt < udf_rw32(sbd->num_bytes); cnt++)
1657 1.1 reinoud sbd->data[cnt] = 0xff;
1658 1.1 reinoud
1659 1.1 reinoud /* set crc to only cover the header (UDF 2.3.1.2, 2.3.8.1) */
1660 1.1 reinoud crclen = sizeof(struct space_bitmap_desc) -1 - UDF_DESC_TAG_LENGTH;
1661 1.1 reinoud sbd->tag.desc_crc_len = udf_rw16(crclen);
1662 1.1 reinoud
1663 1.1 reinoud *sbdp = sbd;
1664 1.1 reinoud return 0;
1665 1.1 reinoud }
1666 1.1 reinoud
1667 1.1 reinoud /* --------------------------------------------------------------------- */
1668 1.1 reinoud
1669 1.2 riastrad int
1670 1.1 reinoud udf_register_bad_block(uint32_t location)
1671 1.1 reinoud {
1672 1.1 reinoud struct udf_sparing_table *spt;
1673 1.1 reinoud struct spare_map_entry *sme, *free_sme;
1674 1.1 reinoud uint32_t cnt;
1675 1.1 reinoud
1676 1.1 reinoud spt = context.sparing_table;
1677 1.1 reinoud if (spt == NULL)
1678 1.1 reinoud errx(1, "internal error, adding bad block to "
1679 1.1 reinoud "non spareable in %s", __func__);
1680 1.1 reinoud
1681 1.1 reinoud /* find us a free spare map entry */
1682 1.1 reinoud free_sme = NULL;
1683 1.1 reinoud for (cnt = 0; cnt < layout.spareable_blocks; cnt++) {
1684 1.1 reinoud sme = &spt->entries[cnt];
1685 1.1 reinoud /* if we are allready in it, bail out */
1686 1.1 reinoud if (udf_rw32(sme->org) == location)
1687 1.1 reinoud return 0;
1688 1.1 reinoud if (udf_rw32(sme->org) == 0xffffffff) {
1689 1.1 reinoud free_sme = sme;
1690 1.1 reinoud break;
1691 1.1 reinoud }
1692 1.1 reinoud }
1693 1.1 reinoud if (free_sme == NULL) {
1694 1.1 reinoud warnx("disc relocation blocks full; disc too damaged");
1695 1.1 reinoud return EINVAL;
1696 1.1 reinoud }
1697 1.1 reinoud free_sme->org = udf_rw32(location);
1698 1.1 reinoud
1699 1.1 reinoud return 0;
1700 1.1 reinoud }
1701 1.1 reinoud
1702 1.1 reinoud
1703 1.1 reinoud void
1704 1.1 reinoud udf_mark_allocated(uint32_t start_lb, int partnr, uint32_t blocks)
1705 1.1 reinoud {
1706 1.1 reinoud union dscrptr *dscr;
1707 1.1 reinoud uint8_t *bpos;
1708 1.1 reinoud uint32_t cnt, bit;
1709 1.1 reinoud
1710 1.1 reinoud /* account for space used on underlying partition */
1711 1.1 reinoud #ifdef DEBUG
1712 1.1 reinoud printf("mark allocated : partnr %d, start_lb %d for %d blocks\n",
1713 1.1 reinoud partnr, start_lb, blocks);
1714 1.1 reinoud #endif
1715 1.1 reinoud
1716 1.1 reinoud switch (context.vtop_tp[partnr]) {
1717 1.1 reinoud case UDF_VTOP_TYPE_VIRT:
1718 1.1 reinoud /* nothing */
1719 1.1 reinoud break;
1720 1.1 reinoud case UDF_VTOP_TYPE_PHYS:
1721 1.1 reinoud case UDF_VTOP_TYPE_SPAREABLE:
1722 1.1 reinoud case UDF_VTOP_TYPE_META:
1723 1.1 reinoud if (context.part_unalloc_bits[context.vtop[partnr]] == NULL) {
1724 1.1 reinoud context.part_free[partnr] = 0;
1725 1.1 reinoud break;
1726 1.1 reinoud }
1727 1.1 reinoud #ifdef DEBUG
1728 1.1 reinoud printf("marking %d+%d as used\n", start_lb, blocks);
1729 1.1 reinoud #endif
1730 1.1 reinoud dscr = (union dscrptr *) (context.part_unalloc_bits[partnr]);
1731 1.1 reinoud for (cnt = start_lb; cnt < start_lb + blocks; cnt++) {
1732 1.1 reinoud bpos = &dscr->sbd.data[cnt / 8];
1733 1.1 reinoud bit = cnt % 8;
1734 1.1 reinoud /* only account for bits marked free */
1735 1.1 reinoud if ((*bpos & (1 << bit)))
1736 1.1 reinoud context.part_free[partnr] -= 1;
1737 1.1 reinoud *bpos &= ~(1<< bit);
1738 1.1 reinoud }
1739 1.1 reinoud break;
1740 1.1 reinoud default:
1741 1.1 reinoud errx(1, "internal error: bad mapping type %d in %s",
1742 1.1 reinoud context.vtop_tp[partnr], __func__);
1743 1.1 reinoud }
1744 1.1 reinoud }
1745 1.1 reinoud
1746 1.1 reinoud
1747 1.1 reinoud void
1748 1.1 reinoud udf_advance_uniqueid(void)
1749 1.1 reinoud {
1750 1.1 reinoud /* Minimum value of 16 : UDF 3.2.1.1, 3.3.3.4. */
1751 1.1 reinoud context.unique_id++;
1752 1.1 reinoud if (context.unique_id < 0x10)
1753 1.1 reinoud context.unique_id = 0x10;
1754 1.1 reinoud }
1755 1.1 reinoud
1756 1.1 reinoud /* --------------------------------------------------------------------- */
1757 1.1 reinoud
1758 1.1 reinoud /* XXX implement the using of the results */
1759 1.1 reinoud int
1760 1.1 reinoud udf_surface_check(void)
1761 1.1 reinoud {
1762 1.1 reinoud uint32_t loc, block_bytes;
1763 1.1 reinoud uint32_t sector_size, blockingnr, bpos;
1764 1.1 reinoud uint8_t *buffer;
1765 1.1 reinoud int error, num_errors;
1766 1.1 reinoud
1767 1.1 reinoud if (mmc_discinfo.mmc_class == MMC_CLASS_DISC)
1768 1.1 reinoud return 0;
1769 1.1 reinoud
1770 1.1 reinoud sector_size = context.sector_size;
1771 1.1 reinoud blockingnr = layout.blockingnr;
1772 1.1 reinoud
1773 1.1 reinoud block_bytes = layout.blockingnr * sector_size;
1774 1.1 reinoud if ((buffer = malloc(block_bytes)) == NULL)
1775 1.1 reinoud return ENOMEM;
1776 1.1 reinoud
1777 1.1 reinoud /* set all one to not kill Flash memory? */
1778 1.1 reinoud for (bpos = 0; bpos < block_bytes; bpos++)
1779 1.1 reinoud buffer[bpos] = 0x00;
1780 1.1 reinoud
1781 1.1 reinoud printf("\nChecking disc surface : phase 1 - writing\n");
1782 1.1 reinoud num_errors = 0;
1783 1.1 reinoud loc = layout.first_lba;
1784 1.1 reinoud while (loc <= layout.last_lba) {
1785 1.1 reinoud /* write blockingnr sectors */
1786 1.1 reinoud error = pwrite(dev_fd, buffer, block_bytes,
1787 1.1 reinoud (uint64_t) loc*sector_size);
1788 1.1 reinoud printf(" %08d + %d (%02d %%)\r", loc, blockingnr,
1789 1.1 reinoud (int)((100.0 * loc)/layout.last_lba));
1790 1.1 reinoud fflush(stdout);
1791 1.1 reinoud if (error == -1) {
1792 1.1 reinoud /* block is bad */
1793 1.1 reinoud printf("BAD block at %08d + %d \n",
1794 1.1 reinoud loc, layout.blockingnr);
1795 1.1 reinoud if ((error = udf_register_bad_block(loc))) {
1796 1.1 reinoud free(buffer);
1797 1.1 reinoud return error;
1798 1.1 reinoud }
1799 1.1 reinoud num_errors ++;
1800 1.1 reinoud }
1801 1.1 reinoud loc += layout.blockingnr;
1802 1.1 reinoud }
1803 1.1 reinoud
1804 1.1 reinoud printf("\nChecking disc surface : phase 2 - reading\n");
1805 1.1 reinoud num_errors = 0;
1806 1.1 reinoud loc = layout.first_lba;
1807 1.1 reinoud while (loc <= layout.last_lba) {
1808 1.1 reinoud /* read blockingnr sectors */
1809 1.1 reinoud error = pread(dev_fd, buffer, block_bytes, loc*sector_size);
1810 1.1 reinoud printf(" %08d + %d (%02d %%)\r", loc, blockingnr,
1811 1.1 reinoud (int)((100.0 * loc)/layout.last_lba));
1812 1.1 reinoud fflush(stdout);
1813 1.1 reinoud if (error == -1) {
1814 1.1 reinoud /* block is bad */
1815 1.1 reinoud printf("BAD block at %08d + %d \n",
1816 1.1 reinoud loc, layout.blockingnr);
1817 1.1 reinoud if ((error = udf_register_bad_block(loc))) {
1818 1.1 reinoud free(buffer);
1819 1.1 reinoud return error;
1820 1.1 reinoud }
1821 1.1 reinoud num_errors ++;
1822 1.1 reinoud }
1823 1.1 reinoud loc += layout.blockingnr;
1824 1.1 reinoud }
1825 1.1 reinoud printf("Scan complete : %d bad blocks found\n", num_errors);
1826 1.1 reinoud free(buffer);
1827 1.1 reinoud
1828 1.1 reinoud return 0;
1829 1.1 reinoud }
1830 1.1 reinoud
1831 1.1 reinoud /* --------------------------------------------------------------------- */
1832 1.1 reinoud
1833 1.1 reinoud #define UDF_SYMLINKBUFLEN (64*1024) /* picked */
1834 1.1 reinoud int
1835 1.1 reinoud udf_encode_symlink(uint8_t **pathbufp, uint32_t *pathlenp, char *target)
1836 1.1 reinoud {
1837 1.1 reinoud struct charspec osta_charspec;
1838 1.1 reinoud struct pathcomp pathcomp;
1839 1.1 reinoud char *pathbuf, *pathpos, *compnamepos;
1840 1.1 reinoud // char *mntonname;
1841 1.1 reinoud // int mntonnamelen;
1842 1.1 reinoud int pathlen, len, compnamelen;
1843 1.1 reinoud int error;
1844 1.1 reinoud
1845 1.1 reinoud /* process `target' to an UDF structure */
1846 1.1 reinoud pathbuf = malloc(UDF_SYMLINKBUFLEN);
1847 1.1 reinoud assert(pathbuf);
1848 1.1 reinoud
1849 1.1 reinoud *pathbufp = NULL;
1850 1.1 reinoud *pathlenp = 0;
1851 1.1 reinoud
1852 1.1 reinoud pathpos = pathbuf;
1853 1.1 reinoud pathlen = 0;
1854 1.1 reinoud udf_osta_charset(&osta_charspec);
1855 1.1 reinoud
1856 1.1 reinoud if (*target == '/') {
1857 1.1 reinoud /* symlink starts from the root */
1858 1.1 reinoud len = UDF_PATH_COMP_SIZE;
1859 1.1 reinoud memset(&pathcomp, 0, len);
1860 1.1 reinoud pathcomp.type = UDF_PATH_COMP_ROOT;
1861 1.1 reinoud
1862 1.1 reinoud #if 0
1863 1.1 reinoud /* XXX how to check for in makefs? */
1864 1.1 reinoud /* check if its mount-point relative! */
1865 1.1 reinoud mntonname = udf_node->ump->vfs_mountp->mnt_stat.f_mntonname;
1866 1.1 reinoud mntonnamelen = strlen(mntonname);
1867 1.1 reinoud if (strlen(target) >= mntonnamelen) {
1868 1.1 reinoud if (strncmp(target, mntonname, mntonnamelen) == 0) {
1869 1.1 reinoud pathcomp.type = UDF_PATH_COMP_MOUNTROOT;
1870 1.1 reinoud target += mntonnamelen;
1871 1.1 reinoud }
1872 1.1 reinoud } else {
1873 1.1 reinoud target++;
1874 1.1 reinoud }
1875 1.1 reinoud #else
1876 1.1 reinoud target++;
1877 1.1 reinoud #endif
1878 1.1 reinoud
1879 1.1 reinoud memcpy(pathpos, &pathcomp, len);
1880 1.1 reinoud pathpos += len;
1881 1.1 reinoud pathlen += len;
1882 1.1 reinoud }
1883 1.1 reinoud
1884 1.1 reinoud error = 0;
1885 1.1 reinoud while (*target) {
1886 1.1 reinoud /* ignore multiple '/' */
1887 1.1 reinoud while (*target == '/') {
1888 1.1 reinoud target++;
1889 1.1 reinoud }
1890 1.1 reinoud if (!*target)
1891 1.1 reinoud break;
1892 1.1 reinoud
1893 1.1 reinoud /* extract component name */
1894 1.1 reinoud compnamelen = 0;
1895 1.1 reinoud compnamepos = target;
1896 1.1 reinoud while ((*target) && (*target != '/')) {
1897 1.1 reinoud target++;
1898 1.1 reinoud compnamelen++;
1899 1.1 reinoud }
1900 1.1 reinoud
1901 1.1 reinoud /* just trunc if too long ?? (security issue) */
1902 1.1 reinoud if (compnamelen >= 127) {
1903 1.1 reinoud error = ENAMETOOLONG;
1904 1.1 reinoud break;
1905 1.1 reinoud }
1906 1.1 reinoud
1907 1.1 reinoud /* convert unix name to UDF name */
1908 1.1 reinoud len = sizeof(struct pathcomp);
1909 1.1 reinoud memset(&pathcomp, 0, len);
1910 1.1 reinoud pathcomp.type = UDF_PATH_COMP_NAME;
1911 1.1 reinoud len = UDF_PATH_COMP_SIZE;
1912 1.1 reinoud
1913 1.1 reinoud if ((compnamelen == 2) && (strncmp(compnamepos, "..", 2) == 0))
1914 1.1 reinoud pathcomp.type = UDF_PATH_COMP_PARENTDIR;
1915 1.1 reinoud if ((compnamelen == 1) && (*compnamepos == '.'))
1916 1.1 reinoud pathcomp.type = UDF_PATH_COMP_CURDIR;
1917 1.1 reinoud
1918 1.1 reinoud if (pathcomp.type == UDF_PATH_COMP_NAME) {
1919 1.1 reinoud unix_to_udf_name(
1920 1.1 reinoud (char *) &pathcomp.ident, &pathcomp.l_ci,
1921 1.1 reinoud compnamepos, compnamelen,
1922 1.1 reinoud &osta_charspec);
1923 1.1 reinoud len = UDF_PATH_COMP_SIZE + pathcomp.l_ci;
1924 1.1 reinoud }
1925 1.1 reinoud
1926 1.1 reinoud if (pathlen + len >= UDF_SYMLINKBUFLEN) {
1927 1.1 reinoud error = ENAMETOOLONG;
1928 1.1 reinoud break;
1929 1.1 reinoud }
1930 1.1 reinoud
1931 1.1 reinoud memcpy(pathpos, &pathcomp, len);
1932 1.1 reinoud pathpos += len;
1933 1.1 reinoud pathlen += len;
1934 1.1 reinoud }
1935 1.1 reinoud
1936 1.1 reinoud if (error) {
1937 1.1 reinoud /* aparently too big */
1938 1.1 reinoud free(pathbuf);
1939 1.1 reinoud return error;
1940 1.1 reinoud }
1941 1.1 reinoud
1942 1.1 reinoud /* return status of symlink contents writeout */
1943 1.1 reinoud *pathbufp = (uint8_t *) pathbuf;
1944 1.1 reinoud *pathlenp = pathlen;
1945 1.1 reinoud
1946 1.1 reinoud return 0;
1947 1.1 reinoud
1948 1.1 reinoud }
1949 1.1 reinoud #undef UDF_SYMLINKBUFLEN
1950 1.1 reinoud
1951 1.1 reinoud
1952 1.1 reinoud /*
1953 1.1 reinoud * XXX note the different semantics from udfclient: for FIDs it still rounds
1954 1.1 reinoud * up to sectors. Use udf_fidsize() for a correct length.
1955 1.1 reinoud */
1956 1.1 reinoud uint32_t
1957 1.1 reinoud udf_tagsize(union dscrptr *dscr, uint32_t lb_size)
1958 1.1 reinoud {
1959 1.1 reinoud uint32_t size, tag_id, num_lb, elmsz;
1960 1.1 reinoud
1961 1.1 reinoud tag_id = udf_rw16(dscr->tag.id);
1962 1.1 reinoud
1963 1.1 reinoud switch (tag_id) {
1964 1.1 reinoud case TAGID_LOGVOL :
1965 1.1 reinoud size = sizeof(struct logvol_desc) - 1;
1966 1.1 reinoud size += udf_rw32(dscr->lvd.mt_l);
1967 1.1 reinoud break;
1968 1.1 reinoud case TAGID_UNALLOC_SPACE :
1969 1.1 reinoud elmsz = sizeof(struct extent_ad);
1970 1.1 reinoud size = sizeof(struct unalloc_sp_desc) - elmsz;
1971 1.1 reinoud size += udf_rw32(dscr->usd.alloc_desc_num) * elmsz;
1972 1.1 reinoud break;
1973 1.1 reinoud case TAGID_FID :
1974 1.1 reinoud size = UDF_FID_SIZE + dscr->fid.l_fi + udf_rw16(dscr->fid.l_iu);
1975 1.1 reinoud size = (size + 3) & ~3;
1976 1.1 reinoud break;
1977 1.1 reinoud case TAGID_LOGVOL_INTEGRITY :
1978 1.1 reinoud size = sizeof(struct logvol_int_desc) - sizeof(uint32_t);
1979 1.1 reinoud size += udf_rw32(dscr->lvid.l_iu);
1980 1.1 reinoud size += (2 * udf_rw32(dscr->lvid.num_part) * sizeof(uint32_t));
1981 1.1 reinoud break;
1982 1.1 reinoud case TAGID_SPACE_BITMAP :
1983 1.1 reinoud size = sizeof(struct space_bitmap_desc) - 1;
1984 1.1 reinoud size += udf_rw32(dscr->sbd.num_bytes);
1985 1.1 reinoud break;
1986 1.1 reinoud case TAGID_SPARING_TABLE :
1987 1.1 reinoud elmsz = sizeof(struct spare_map_entry);
1988 1.1 reinoud size = sizeof(struct udf_sparing_table) - elmsz;
1989 1.1 reinoud size += udf_rw16(dscr->spt.rt_l) * elmsz;
1990 1.1 reinoud break;
1991 1.1 reinoud case TAGID_FENTRY :
1992 1.1 reinoud size = sizeof(struct file_entry);
1993 1.1 reinoud size += udf_rw32(dscr->fe.l_ea) + udf_rw32(dscr->fe.l_ad)-1;
1994 1.1 reinoud break;
1995 1.1 reinoud case TAGID_EXTFENTRY :
1996 1.1 reinoud size = sizeof(struct extfile_entry);
1997 1.1 reinoud size += udf_rw32(dscr->efe.l_ea) + udf_rw32(dscr->efe.l_ad)-1;
1998 1.1 reinoud break;
1999 1.1 reinoud case TAGID_FSD :
2000 1.1 reinoud size = sizeof(struct fileset_desc);
2001 1.1 reinoud break;
2002 1.1 reinoud default :
2003 1.1 reinoud size = sizeof(union dscrptr);
2004 1.1 reinoud break;
2005 1.1 reinoud }
2006 1.1 reinoud
2007 1.1 reinoud if ((size == 0) || (lb_size == 0))
2008 1.1 reinoud return 0;
2009 1.1 reinoud
2010 1.1 reinoud if (lb_size == 1)
2011 1.1 reinoud return size;
2012 1.1 reinoud
2013 1.1 reinoud /* round up in sectors */
2014 1.1 reinoud num_lb = (size + lb_size -1) / lb_size;
2015 1.1 reinoud return num_lb * lb_size;
2016 1.1 reinoud }
2017 1.1 reinoud
2018 1.1 reinoud
2019 1.1 reinoud int
2020 1.1 reinoud udf_fidsize(struct fileid_desc *fid)
2021 1.1 reinoud {
2022 1.1 reinoud uint32_t size;
2023 1.1 reinoud
2024 1.1 reinoud if (udf_rw16(fid->tag.id) != TAGID_FID)
2025 1.1 reinoud errx(1, "internal error, bad tag in %s", __func__);
2026 1.1 reinoud
2027 1.3 reinoud size = UDF_FID_SIZE + fid->l_fi + udf_rw16(fid->l_iu);
2028 1.1 reinoud size = (size + 3) & ~3;
2029 1.1 reinoud
2030 1.1 reinoud return size;
2031 1.1 reinoud }
2032 1.1 reinoud
2033 1.1 reinoud
2034 1.1 reinoud int
2035 1.1 reinoud udf_create_parentfid(struct fileid_desc *fid, struct long_ad *parent)
2036 1.1 reinoud {
2037 1.1 reinoud /* the size of an empty FID is 38 but needs to be a multiple of 4 */
2038 1.1 reinoud int fidsize = 40;
2039 1.1 reinoud
2040 1.1 reinoud udf_inittag(&fid->tag, TAGID_FID, udf_rw32(parent->loc.lb_num));
2041 1.1 reinoud fid->file_version_num = udf_rw16(1); /* UDF 2.3.4.1 */
2042 1.1 reinoud fid->file_char = UDF_FILE_CHAR_DIR | UDF_FILE_CHAR_PAR;
2043 1.1 reinoud fid->icb = *parent;
2044 1.1 reinoud fid->icb.longad_uniqueid = parent->longad_uniqueid;
2045 1.1 reinoud fid->tag.desc_crc_len = udf_rw16(fidsize - UDF_DESC_TAG_LENGTH);
2046 1.1 reinoud
2047 1.1 reinoud /* we have to do the fid here explicitly for simplicity */
2048 1.1 reinoud udf_validate_tag_and_crc_sums((union dscrptr *) fid);
2049 1.1 reinoud
2050 1.1 reinoud return fidsize;
2051 1.1 reinoud }
2052 1.1 reinoud
2053 1.1 reinoud
2054 1.1 reinoud void
2055 1.1 reinoud udf_create_fid(uint32_t diroff, struct fileid_desc *fid, char *name,
2056 1.1 reinoud int file_char, struct long_ad *ref)
2057 1.1 reinoud {
2058 1.1 reinoud struct charspec osta_charspec;
2059 1.1 reinoud uint32_t endfid;
2060 1.1 reinoud uint32_t fidsize, lb_rest;
2061 1.1 reinoud
2062 1.1 reinoud memset(fid, 0, sizeof(*fid));
2063 1.1 reinoud udf_inittag(&fid->tag, TAGID_FID, udf_rw32(ref->loc.lb_num));
2064 1.1 reinoud fid->file_version_num = udf_rw16(1); /* UDF 2.3.4.1 */
2065 1.1 reinoud fid->file_char = file_char;
2066 1.1 reinoud fid->l_iu = udf_rw16(0);
2067 1.1 reinoud fid->icb = *ref;
2068 1.1 reinoud fid->icb.longad_uniqueid = ref->longad_uniqueid;
2069 1.1 reinoud
2070 1.1 reinoud udf_osta_charset(&osta_charspec);
2071 1.1 reinoud unix_to_udf_name((char *) fid->data, &fid->l_fi, name, strlen(name),
2072 1.1 reinoud &osta_charspec);
2073 1.1 reinoud
2074 1.1 reinoud /*
2075 1.1 reinoud * OK, tricky part: we need to pad so the next descriptor header won't
2076 1.1 reinoud * cross the sector boundary
2077 1.1 reinoud */
2078 1.1 reinoud endfid = diroff + udf_fidsize(fid);
2079 1.1 reinoud lb_rest = context.sector_size - (endfid % context.sector_size);
2080 1.1 reinoud if (lb_rest < sizeof(struct desc_tag)) {
2081 1.1 reinoud /* add at least 32 */
2082 1.1 reinoud fid->l_iu = udf_rw16(32);
2083 1.1 reinoud udf_set_regid((struct regid *) fid->data, context.impl_name);
2084 1.1 reinoud udf_add_impl_regid((struct regid *) fid->data);
2085 1.1 reinoud
2086 1.1 reinoud unix_to_udf_name((char *) fid->data + udf_rw16(fid->l_iu),
2087 1.1 reinoud &fid->l_fi, name, strlen(name), &osta_charspec);
2088 1.1 reinoud }
2089 1.1 reinoud
2090 1.1 reinoud fidsize = udf_fidsize(fid);
2091 1.1 reinoud fid->tag.desc_crc_len = udf_rw16(fidsize - UDF_DESC_TAG_LENGTH);
2092 1.1 reinoud
2093 1.1 reinoud /* make sure the header sums stays correct */
2094 1.1 reinoud udf_validate_tag_and_crc_sums((union dscrptr *)fid);
2095 1.1 reinoud }
2096 1.1 reinoud
2097 1.1 reinoud
2098 1.1 reinoud static void
2099 1.1 reinoud udf_append_parentfid(union dscrptr *dscr, struct long_ad *parent_icb)
2100 1.1 reinoud {
2101 1.1 reinoud struct file_entry *fe;
2102 1.1 reinoud struct extfile_entry *efe;
2103 1.1 reinoud struct fileid_desc *fid;
2104 1.1 reinoud uint32_t l_ea;
2105 1.1 reinoud uint32_t fidsize, crclen;
2106 1.1 reinoud uint8_t *bpos, *data;
2107 1.1 reinoud
2108 1.1 reinoud fe = NULL;
2109 1.1 reinoud efe = NULL;
2110 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
2111 1.1 reinoud fe = &dscr->fe;
2112 1.1 reinoud data = fe->data;
2113 1.1 reinoud l_ea = udf_rw32(fe->l_ea);
2114 1.1 reinoud } else if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
2115 1.1 reinoud efe = &dscr->efe;
2116 1.1 reinoud data = efe->data;
2117 1.1 reinoud l_ea = udf_rw32(efe->l_ea);
2118 1.1 reinoud } else {
2119 1.1 reinoud errx(1, "internal error, bad tag in %s", __func__);
2120 1.1 reinoud }
2121 1.1 reinoud
2122 1.1 reinoud /* create '..' */
2123 1.1 reinoud bpos = data + l_ea;
2124 1.1 reinoud fid = (struct fileid_desc *) bpos;
2125 1.1 reinoud fidsize = udf_create_parentfid(fid, parent_icb);
2126 1.1 reinoud
2127 1.1 reinoud /* record fidlength information */
2128 1.1 reinoud if (fe) {
2129 1.1 reinoud fe->inf_len = udf_rw64(fidsize);
2130 1.1 reinoud fe->l_ad = udf_rw32(fidsize);
2131 1.1 reinoud fe->logblks_rec = udf_rw64(0); /* intern */
2132 1.1 reinoud crclen = sizeof(struct file_entry);
2133 1.1 reinoud } else {
2134 1.1 reinoud efe->inf_len = udf_rw64(fidsize);
2135 1.1 reinoud efe->obj_size = udf_rw64(fidsize);
2136 1.1 reinoud efe->l_ad = udf_rw32(fidsize);
2137 1.1 reinoud efe->logblks_rec = udf_rw64(0); /* intern */
2138 1.1 reinoud crclen = sizeof(struct extfile_entry);
2139 1.1 reinoud }
2140 1.1 reinoud crclen -= 1 + UDF_DESC_TAG_LENGTH;
2141 1.1 reinoud crclen += l_ea + fidsize;
2142 1.1 reinoud dscr->tag.desc_crc_len = udf_rw16(crclen);
2143 1.1 reinoud
2144 1.1 reinoud /* make sure the header sums stays correct */
2145 1.1 reinoud udf_validate_tag_and_crc_sums(dscr);
2146 1.1 reinoud }
2147 1.1 reinoud
2148 1.1 reinoud /* --------------------------------------------------------------------- */
2149 1.1 reinoud
2150 1.1 reinoud /*
2151 1.1 reinoud * Extended attribute support. UDF knows of 3 places for extended attributes:
2152 1.1 reinoud *
2153 1.1 reinoud * (a) inside the file's (e)fe in the length of the extended attribute area
2154 1.1 reinoud * before the allocation descriptors/filedata
2155 1.1 reinoud *
2156 1.1 reinoud * (b) in a file referenced by (e)fe->ext_attr_icb and
2157 1.1 reinoud *
2158 1.1 reinoud * (c) in the e(fe)'s associated stream directory that can hold various
2159 1.1 reinoud * sub-files. In the stream directory a few fixed named subfiles are reserved
2160 1.1 reinoud * for NT/Unix ACL's and OS/2 attributes.
2161 1.1 reinoud *
2162 1.1 reinoud * NOTE: Extended attributes are read randomly but always written
2163 1.1 reinoud * *atomically*. For ACL's this interface is probably different but not known
2164 1.1 reinoud * to me yet.
2165 1.1 reinoud *
2166 1.1 reinoud * Order of extended attributes in a space:
2167 1.1 reinoud * ECMA 167 EAs
2168 1.1 reinoud * Non block aligned Implementation Use EAs
2169 1.1 reinoud * Block aligned Implementation Use EAs
2170 1.1 reinoud * Application Use EAs
2171 1.1 reinoud */
2172 1.1 reinoud
2173 1.1 reinoud int
2174 1.1 reinoud udf_impl_extattr_check(struct impl_extattr_entry *implext)
2175 1.1 reinoud {
2176 1.1 reinoud uint16_t *spos;
2177 1.1 reinoud
2178 1.1 reinoud if (strncmp((char *) implext->imp_id.id, "*UDF", 4) == 0) {
2179 1.1 reinoud /* checksum valid? */
2180 1.1 reinoud spos = (uint16_t *) implext->data;
2181 1.1 reinoud if (udf_rw16(*spos) != udf_ea_cksum((uint8_t *) implext))
2182 1.1 reinoud return EINVAL;
2183 1.1 reinoud }
2184 1.1 reinoud return 0;
2185 1.1 reinoud }
2186 1.1 reinoud
2187 1.1 reinoud void
2188 1.1 reinoud udf_calc_impl_extattr_checksum(struct impl_extattr_entry *implext)
2189 1.1 reinoud {
2190 1.1 reinoud uint16_t *spos;
2191 1.1 reinoud
2192 1.1 reinoud if (strncmp((char *) implext->imp_id.id, "*UDF", 4) == 0) {
2193 1.1 reinoud /* set checksum */
2194 1.1 reinoud spos = (uint16_t *) implext->data;
2195 1.1 reinoud *spos = udf_rw16(udf_ea_cksum((uint8_t *) implext));
2196 1.1 reinoud }
2197 1.1 reinoud }
2198 1.1 reinoud
2199 1.1 reinoud
2200 1.1 reinoud int
2201 1.1 reinoud udf_extattr_search_intern(union dscrptr *dscr,
2202 1.1 reinoud uint32_t sattr, char const *sattrname,
2203 1.1 reinoud uint32_t *offsetp, uint32_t *lengthp)
2204 1.1 reinoud {
2205 1.1 reinoud struct extattrhdr_desc *eahdr;
2206 1.1 reinoud struct extattr_entry *attrhdr;
2207 1.1 reinoud struct impl_extattr_entry *implext;
2208 1.1 reinoud uint32_t offset, a_l, sector_size;
2209 1.1 reinoud uint32_t l_ea;
2210 1.1 reinoud uint8_t *pos;
2211 1.1 reinoud int tag_id, error;
2212 1.1 reinoud
2213 1.1 reinoud sector_size = context.sector_size;
2214 1.1 reinoud
2215 1.1 reinoud /* get information from fe/efe */
2216 1.1 reinoud tag_id = udf_rw16(dscr->tag.id);
2217 1.1 reinoud if (tag_id == TAGID_FENTRY) {
2218 1.1 reinoud l_ea = udf_rw32(dscr->fe.l_ea);
2219 1.1 reinoud eahdr = (struct extattrhdr_desc *) dscr->fe.data;
2220 1.1 reinoud } else {
2221 1.1 reinoud assert(tag_id == TAGID_EXTFENTRY);
2222 1.1 reinoud l_ea = udf_rw32(dscr->efe.l_ea);
2223 1.1 reinoud eahdr = (struct extattrhdr_desc *) dscr->efe.data;
2224 1.1 reinoud }
2225 1.1 reinoud
2226 1.1 reinoud /* something recorded here? */
2227 1.1 reinoud if (l_ea == 0)
2228 1.1 reinoud return ENOENT;
2229 1.1 reinoud
2230 1.1 reinoud /* check extended attribute tag; what to do if it fails? */
2231 1.1 reinoud error = udf_check_tag(eahdr);
2232 1.1 reinoud if (error)
2233 1.1 reinoud return EINVAL;
2234 1.1 reinoud if (udf_rw16(eahdr->tag.id) != TAGID_EXTATTR_HDR)
2235 1.1 reinoud return EINVAL;
2236 1.1 reinoud error = udf_check_tag_payload(eahdr, sizeof(struct extattrhdr_desc));
2237 1.1 reinoud if (error)
2238 1.1 reinoud return EINVAL;
2239 1.1 reinoud
2240 1.1 reinoud /* looking for Ecma-167 attributes? */
2241 1.1 reinoud offset = sizeof(struct extattrhdr_desc);
2242 1.1 reinoud
2243 1.1 reinoud /* looking for either implementation use or application use */
2244 1.1 reinoud if (sattr == 2048) { /* [4/48.10.8] */
2245 1.1 reinoud offset = udf_rw32(eahdr->impl_attr_loc);
2246 1.1 reinoud if (offset == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
2247 1.1 reinoud return ENOENT;
2248 1.1 reinoud }
2249 1.1 reinoud if (sattr == 65536) { /* [4/48.10.9] */
2250 1.1 reinoud offset = udf_rw32(eahdr->appl_attr_loc);
2251 1.1 reinoud if (offset == UDF_APPL_ATTR_LOC_NOT_PRESENT)
2252 1.1 reinoud return ENOENT;
2253 1.1 reinoud }
2254 1.1 reinoud
2255 1.1 reinoud /* paranoia check offset and l_ea */
2256 1.1 reinoud if (l_ea + offset >= sector_size - sizeof(struct extattr_entry))
2257 1.1 reinoud return EINVAL;
2258 1.1 reinoud
2259 1.1 reinoud /* find our extended attribute */
2260 1.1 reinoud l_ea -= offset;
2261 1.1 reinoud pos = (uint8_t *) eahdr + offset;
2262 1.1 reinoud
2263 1.1 reinoud while (l_ea >= sizeof(struct extattr_entry)) {
2264 1.1 reinoud attrhdr = (struct extattr_entry *) pos;
2265 1.1 reinoud implext = (struct impl_extattr_entry *) pos;
2266 1.1 reinoud
2267 1.1 reinoud /* get complete attribute length and check for roque values */
2268 1.1 reinoud a_l = udf_rw32(attrhdr->a_l);
2269 1.1 reinoud if ((a_l == 0) || (a_l > l_ea))
2270 1.1 reinoud return EINVAL;
2271 1.1 reinoud
2272 1.1 reinoud if (attrhdr->type != sattr)
2273 1.1 reinoud goto next_attribute;
2274 1.1 reinoud
2275 1.1 reinoud /* we might have found it! */
2276 1.1 reinoud if (attrhdr->type < 2048) { /* Ecma-167 attribute */
2277 1.1 reinoud *offsetp = offset;
2278 1.1 reinoud *lengthp = a_l;
2279 1.1 reinoud return 0; /* success */
2280 1.1 reinoud }
2281 1.1 reinoud
2282 1.1 reinoud /*
2283 1.1 reinoud * Implementation use and application use extended attributes
2284 1.1 reinoud * have a name to identify. They share the same structure only
2285 1.1 reinoud * UDF implementation use extended attributes have a checksum
2286 1.1 reinoud * we need to check
2287 1.1 reinoud */
2288 1.1 reinoud
2289 1.1 reinoud if (strcmp((char *) implext->imp_id.id, sattrname) == 0) {
2290 1.1 reinoud /* we have found our appl/implementation attribute */
2291 1.1 reinoud *offsetp = offset;
2292 1.1 reinoud *lengthp = a_l;
2293 1.1 reinoud return 0; /* success */
2294 1.1 reinoud }
2295 1.1 reinoud
2296 1.1 reinoud next_attribute:
2297 1.1 reinoud /* next attribute */
2298 1.1 reinoud pos += a_l;
2299 1.1 reinoud l_ea -= a_l;
2300 1.1 reinoud offset += a_l;
2301 1.1 reinoud }
2302 1.1 reinoud /* not found */
2303 1.1 reinoud return ENOENT;
2304 1.1 reinoud }
2305 1.1 reinoud
2306 1.1 reinoud
2307 1.1 reinoud static void
2308 1.1 reinoud udf_extattr_insert_internal(union dscrptr *dscr, struct extattr_entry *extattr)
2309 1.1 reinoud {
2310 1.1 reinoud struct file_entry *fe;
2311 1.1 reinoud struct extfile_entry *efe;
2312 1.1 reinoud struct extattrhdr_desc *extattrhdr;
2313 1.1 reinoud struct impl_extattr_entry *implext;
2314 1.1 reinoud uint32_t impl_attr_loc, appl_attr_loc, l_ea, l_ad, a_l;
2315 1.1 reinoud uint16_t *spos;
2316 1.1 reinoud uint8_t *bpos, *data;
2317 1.1 reinoud void *l_eap;
2318 1.1 reinoud
2319 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
2320 1.1 reinoud fe = &dscr->fe;
2321 1.1 reinoud data = fe->data;
2322 1.1 reinoud l_eap = &fe->l_ea;
2323 1.1 reinoud l_ad = udf_rw32(fe->l_ad);
2324 1.1 reinoud } else if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
2325 1.1 reinoud efe = &dscr->efe;
2326 1.1 reinoud data = efe->data;
2327 1.1 reinoud l_eap = &efe->l_ea;
2328 1.1 reinoud l_ad = udf_rw32(efe->l_ad);
2329 1.1 reinoud } else {
2330 1.1 reinoud errx(1, "internal error, bad tag in %s", __func__);
2331 1.1 reinoud }
2332 1.1 reinoud
2333 1.1 reinoud /* should have a header! */
2334 1.1 reinoud extattrhdr = (struct extattrhdr_desc *) data;
2335 1.1 reinoud memcpy(&l_ea, l_eap, sizeof(l_ea));
2336 1.1 reinoud l_ea = udf_rw32(l_ea);
2337 1.1 reinoud if (l_ea == 0) {
2338 1.1 reinoud uint32_t exthdr_len;
2339 1.1 reinoud assert(l_ad == 0);
2340 1.1 reinoud /* create empty extended attribute header */
2341 1.1 reinoud l_ea = sizeof(struct extattrhdr_desc);
2342 1.1 reinoud exthdr_len = udf_rw32(l_ea);
2343 1.1 reinoud
2344 1.1 reinoud udf_inittag(&extattrhdr->tag, TAGID_EXTATTR_HDR, /* loc */ 0);
2345 1.1 reinoud extattrhdr->impl_attr_loc = exthdr_len;
2346 1.1 reinoud extattrhdr->appl_attr_loc = exthdr_len;
2347 1.1 reinoud extattrhdr->tag.desc_crc_len = udf_rw16(8);
2348 1.1 reinoud
2349 1.1 reinoud /* record extended attribute header length */
2350 1.1 reinoud memcpy(l_eap, &exthdr_len, sizeof(exthdr_len));
2351 1.1 reinoud }
2352 1.1 reinoud
2353 1.1 reinoud /* extract locations */
2354 1.1 reinoud impl_attr_loc = udf_rw32(extattrhdr->impl_attr_loc);
2355 1.1 reinoud appl_attr_loc = udf_rw32(extattrhdr->appl_attr_loc);
2356 1.1 reinoud if (impl_attr_loc == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
2357 1.1 reinoud impl_attr_loc = l_ea;
2358 1.1 reinoud if (appl_attr_loc == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
2359 1.1 reinoud appl_attr_loc = l_ea;
2360 1.1 reinoud
2361 1.1 reinoud /* Ecma 167 EAs */
2362 1.1 reinoud if (udf_rw32(extattr->type) < 2048) {
2363 1.1 reinoud assert(impl_attr_loc == l_ea);
2364 1.1 reinoud assert(appl_attr_loc == l_ea);
2365 1.1 reinoud }
2366 1.1 reinoud
2367 1.1 reinoud /* implementation use extended attributes */
2368 1.1 reinoud if (udf_rw32(extattr->type) == 2048) {
2369 1.1 reinoud assert(appl_attr_loc == l_ea);
2370 1.1 reinoud
2371 1.1 reinoud /* calculate and write extended attribute header checksum */
2372 1.1 reinoud implext = (struct impl_extattr_entry *) extattr;
2373 1.1 reinoud assert(udf_rw32(implext->iu_l) == 4); /* [UDF 3.3.4.5] */
2374 1.1 reinoud spos = (uint16_t *) implext->data;
2375 1.1 reinoud *spos = udf_rw16(udf_ea_cksum((uint8_t *) implext));
2376 1.1 reinoud }
2377 1.1 reinoud
2378 1.1 reinoud /* application use extended attributes */
2379 1.1 reinoud assert(udf_rw32(extattr->type) != 65536);
2380 1.1 reinoud assert(appl_attr_loc == l_ea);
2381 1.1 reinoud
2382 1.1 reinoud /* append the attribute at the end of the current space */
2383 1.1 reinoud bpos = data + l_ea;
2384 1.1 reinoud a_l = udf_rw32(extattr->a_l);
2385 1.1 reinoud
2386 1.1 reinoud /* update impl. attribute locations */
2387 1.1 reinoud if (udf_rw32(extattr->type) < 2048) {
2388 1.1 reinoud impl_attr_loc = l_ea + a_l;
2389 1.1 reinoud appl_attr_loc = l_ea + a_l;
2390 1.1 reinoud }
2391 1.1 reinoud if (udf_rw32(extattr->type) == 2048) {
2392 1.1 reinoud appl_attr_loc = l_ea + a_l;
2393 1.1 reinoud }
2394 1.1 reinoud
2395 1.1 reinoud /* copy and advance */
2396 1.1 reinoud memcpy(bpos, extattr, a_l);
2397 1.1 reinoud l_ea += a_l;
2398 1.1 reinoud l_ea = udf_rw32(l_ea);
2399 1.1 reinoud memcpy(l_eap, &l_ea, sizeof(l_ea));
2400 1.1 reinoud
2401 1.1 reinoud /* do the `dance` again backwards */
2402 1.1 reinoud if (context.dscrver != 2) {
2403 1.1 reinoud if (impl_attr_loc == l_ea)
2404 1.1 reinoud impl_attr_loc = UDF_IMPL_ATTR_LOC_NOT_PRESENT;
2405 1.1 reinoud if (appl_attr_loc == l_ea)
2406 1.1 reinoud appl_attr_loc = UDF_APPL_ATTR_LOC_NOT_PRESENT;
2407 1.1 reinoud }
2408 1.1 reinoud
2409 1.1 reinoud /* store offsets */
2410 1.1 reinoud extattrhdr->impl_attr_loc = udf_rw32(impl_attr_loc);
2411 1.1 reinoud extattrhdr->appl_attr_loc = udf_rw32(appl_attr_loc);
2412 1.1 reinoud
2413 1.1 reinoud /* make sure the header sums stays correct */
2414 1.1 reinoud udf_validate_tag_and_crc_sums((union dscrptr *) extattrhdr);
2415 1.1 reinoud }
2416 1.1 reinoud
2417 1.1 reinoud /* --------------------------------------------------------------------- */
2418 1.1 reinoud
2419 1.1 reinoud int
2420 1.1 reinoud udf_create_new_fe(struct file_entry **fep, int file_type, struct stat *st)
2421 1.1 reinoud {
2422 1.1 reinoud struct file_entry *fe;
2423 1.1 reinoud struct icb_tag *icb;
2424 1.1 reinoud struct timestamp birthtime;
2425 1.1 reinoud struct filetimes_extattr_entry *ft_extattr;
2426 1.1 reinoud uint32_t crclen; /* XXX: should be 16; need to detect overflow */
2427 1.1 reinoud uint16_t icbflags;
2428 1.1 reinoud
2429 1.1 reinoud *fep = NULL;
2430 1.1 reinoud fe = calloc(1, context.sector_size);
2431 1.1 reinoud if (fe == NULL)
2432 1.1 reinoud return ENOMEM;
2433 1.1 reinoud
2434 1.1 reinoud udf_inittag(&fe->tag, TAGID_FENTRY, /* loc */ 0);
2435 1.1 reinoud icb = &fe->icbtag;
2436 1.1 reinoud
2437 1.1 reinoud /*
2438 1.1 reinoud * Always use strategy type 4 unless on WORM wich we don't support
2439 1.1 reinoud * (yet). Fill in defaults and set for internal allocation of data.
2440 1.1 reinoud */
2441 1.1 reinoud icb->strat_type = udf_rw16(4);
2442 1.1 reinoud icb->max_num_entries = udf_rw16(1);
2443 1.1 reinoud icb->file_type = file_type; /* 8 bit */
2444 1.1 reinoud icb->flags = udf_rw16(UDF_ICB_INTERN_ALLOC);
2445 1.1 reinoud
2446 1.1 reinoud fe->perm = udf_rw32(0x7fff); /* all is allowed */
2447 1.1 reinoud fe->link_cnt = udf_rw16(0); /* explicit setting */
2448 1.1 reinoud
2449 1.1 reinoud fe->ckpoint = udf_rw32(1); /* user supplied file version */
2450 1.1 reinoud
2451 1.1 reinoud udf_set_timestamp_now(&birthtime);
2452 1.1 reinoud udf_set_timestamp_now(&fe->atime);
2453 1.1 reinoud udf_set_timestamp_now(&fe->attrtime);
2454 1.1 reinoud udf_set_timestamp_now(&fe->mtime);
2455 1.1 reinoud
2456 1.1 reinoud /* set attributes */
2457 1.1 reinoud if (st) {
2458 1.1 reinoud #if !HAVE_NBTOOL_CONFIG_H
2459 1.1 reinoud udf_set_timestamp(&birthtime, st->st_birthtime);
2460 1.1 reinoud #else
2461 1.1 reinoud udf_set_timestamp(&birthtime, 0);
2462 1.1 reinoud #endif
2463 1.1 reinoud udf_set_timestamp(&fe->atime, st->st_atime);
2464 1.1 reinoud udf_set_timestamp(&fe->attrtime, st->st_ctime);
2465 1.1 reinoud udf_set_timestamp(&fe->mtime, st->st_mtime);
2466 1.1 reinoud fe->uid = udf_rw32(st->st_uid);
2467 1.1 reinoud fe->gid = udf_rw32(st->st_gid);
2468 1.1 reinoud
2469 1.1 reinoud fe->perm = unix_mode_to_udf_perm(st->st_mode);
2470 1.1 reinoud
2471 1.1 reinoud icbflags = udf_rw16(fe->icbtag.flags);
2472 1.1 reinoud icbflags &= ~UDF_ICB_TAG_FLAGS_SETUID;
2473 1.1 reinoud icbflags &= ~UDF_ICB_TAG_FLAGS_SETGID;
2474 1.1 reinoud icbflags &= ~UDF_ICB_TAG_FLAGS_STICKY;
2475 1.1 reinoud if (st->st_mode & S_ISUID)
2476 1.1 reinoud icbflags |= UDF_ICB_TAG_FLAGS_SETUID;
2477 1.1 reinoud if (st->st_mode & S_ISGID)
2478 1.1 reinoud icbflags |= UDF_ICB_TAG_FLAGS_SETGID;
2479 1.1 reinoud if (st->st_mode & S_ISVTX)
2480 1.1 reinoud icbflags |= UDF_ICB_TAG_FLAGS_STICKY;
2481 1.1 reinoud fe->icbtag.flags = udf_rw16(icbflags);
2482 1.1 reinoud }
2483 1.1 reinoud
2484 1.1 reinoud udf_set_regid(&fe->imp_id, context.impl_name);
2485 1.1 reinoud udf_add_impl_regid(&fe->imp_id);
2486 1.1 reinoud fe->unique_id = udf_rw64(context.unique_id);
2487 1.1 reinoud udf_advance_uniqueid();
2488 1.1 reinoud
2489 1.1 reinoud fe->l_ea = udf_rw32(0);
2490 1.1 reinoud
2491 1.1 reinoud /* create extended attribute to record our creation time */
2492 1.1 reinoud ft_extattr = calloc(1, UDF_FILETIMES_ATTR_SIZE(1));
2493 1.1 reinoud ft_extattr->hdr.type = udf_rw32(UDF_FILETIMES_ATTR_NO);
2494 1.1 reinoud ft_extattr->hdr.subtype = 1; /* [4/48.10.5] */
2495 1.1 reinoud ft_extattr->hdr.a_l = udf_rw32(UDF_FILETIMES_ATTR_SIZE(1));
2496 1.1 reinoud ft_extattr->d_l = udf_rw32(UDF_TIMESTAMP_SIZE); /* one item */
2497 1.1 reinoud ft_extattr->existence = UDF_FILETIMES_FILE_CREATION;
2498 1.1 reinoud ft_extattr->times[0] = birthtime;
2499 1.1 reinoud
2500 1.1 reinoud udf_extattr_insert_internal((union dscrptr *) fe,
2501 1.1 reinoud (struct extattr_entry *) ft_extattr);
2502 1.1 reinoud free(ft_extattr);
2503 1.1 reinoud
2504 1.1 reinoud /* record fidlength information */
2505 1.1 reinoud fe->inf_len = udf_rw64(0);
2506 1.1 reinoud fe->l_ad = udf_rw32(0);
2507 1.1 reinoud fe->logblks_rec = udf_rw64(0); /* intern */
2508 1.1 reinoud
2509 1.1 reinoud crclen = sizeof(struct file_entry) - 1 - UDF_DESC_TAG_LENGTH;
2510 1.1 reinoud crclen += udf_rw32(fe->l_ea);
2511 1.1 reinoud
2512 1.1 reinoud /* make sure the header sums stays correct */
2513 1.1 reinoud fe->tag.desc_crc_len = udf_rw16(crclen);
2514 1.1 reinoud udf_validate_tag_and_crc_sums((union dscrptr *) fe);
2515 1.1 reinoud
2516 1.1 reinoud *fep = fe;
2517 1.1 reinoud return 0;
2518 1.1 reinoud }
2519 1.1 reinoud
2520 1.1 reinoud
2521 1.1 reinoud int
2522 1.1 reinoud udf_create_new_efe(struct extfile_entry **efep, int file_type, struct stat *st)
2523 1.1 reinoud {
2524 1.1 reinoud struct extfile_entry *efe;
2525 1.1 reinoud struct icb_tag *icb;
2526 1.1 reinoud uint32_t crclen; /* XXX: should be 16; need to detect overflow */
2527 1.1 reinoud uint16_t icbflags;
2528 1.1 reinoud
2529 1.1 reinoud *efep = NULL;
2530 1.1 reinoud efe = calloc(1, context.sector_size);
2531 1.1 reinoud if (efe == NULL)
2532 1.1 reinoud return ENOMEM;
2533 1.1 reinoud
2534 1.1 reinoud udf_inittag(&efe->tag, TAGID_EXTFENTRY, /* loc */ 0);
2535 1.1 reinoud icb = &efe->icbtag;
2536 1.1 reinoud
2537 1.1 reinoud /*
2538 1.1 reinoud * Always use strategy type 4 unless on WORM wich we don't support
2539 1.1 reinoud * (yet). Fill in defaults and set for internal allocation of data.
2540 1.1 reinoud */
2541 1.1 reinoud icb->strat_type = udf_rw16(4);
2542 1.1 reinoud icb->max_num_entries = udf_rw16(1);
2543 1.1 reinoud icb->file_type = file_type; /* 8 bit */
2544 1.1 reinoud icb->flags = udf_rw16(UDF_ICB_INTERN_ALLOC);
2545 1.1 reinoud
2546 1.1 reinoud efe->perm = udf_rw32(0x7fff); /* all is allowed */
2547 1.1 reinoud efe->link_cnt = udf_rw16(0); /* explicit setting */
2548 1.1 reinoud
2549 1.1 reinoud efe->ckpoint = udf_rw32(1); /* user supplied file version */
2550 1.1 reinoud
2551 1.1 reinoud udf_set_timestamp_now(&efe->ctime);
2552 1.1 reinoud udf_set_timestamp_now(&efe->atime);
2553 1.1 reinoud udf_set_timestamp_now(&efe->attrtime);
2554 1.1 reinoud udf_set_timestamp_now(&efe->mtime);
2555 1.1 reinoud
2556 1.1 reinoud /* set attributes */
2557 1.1 reinoud if (st) {
2558 1.1 reinoud #if !HAVE_NBTOOL_CONFIG_H
2559 1.1 reinoud udf_set_timestamp(&efe->ctime, st->st_birthtime);
2560 1.1 reinoud #else
2561 1.1 reinoud udf_set_timestamp(&efe->ctime, 0);
2562 1.1 reinoud #endif
2563 1.1 reinoud udf_set_timestamp(&efe->atime, st->st_atime);
2564 1.1 reinoud udf_set_timestamp(&efe->attrtime, st->st_ctime);
2565 1.1 reinoud udf_set_timestamp(&efe->mtime, st->st_mtime);
2566 1.1 reinoud efe->uid = udf_rw32(st->st_uid);
2567 1.1 reinoud efe->gid = udf_rw32(st->st_gid);
2568 1.1 reinoud
2569 1.1 reinoud efe->perm = unix_mode_to_udf_perm(st->st_mode);
2570 1.1 reinoud
2571 1.1 reinoud icbflags = udf_rw16(efe->icbtag.flags);
2572 1.1 reinoud icbflags &= ~UDF_ICB_TAG_FLAGS_SETUID;
2573 1.1 reinoud icbflags &= ~UDF_ICB_TAG_FLAGS_SETGID;
2574 1.1 reinoud icbflags &= ~UDF_ICB_TAG_FLAGS_STICKY;
2575 1.1 reinoud if (st->st_mode & S_ISUID)
2576 1.1 reinoud icbflags |= UDF_ICB_TAG_FLAGS_SETUID;
2577 1.1 reinoud if (st->st_mode & S_ISGID)
2578 1.1 reinoud icbflags |= UDF_ICB_TAG_FLAGS_SETGID;
2579 1.1 reinoud if (st->st_mode & S_ISVTX)
2580 1.1 reinoud icbflags |= UDF_ICB_TAG_FLAGS_STICKY;
2581 1.1 reinoud efe->icbtag.flags = udf_rw16(icbflags);
2582 1.1 reinoud }
2583 1.1 reinoud
2584 1.1 reinoud udf_set_regid(&efe->imp_id, context.impl_name);
2585 1.1 reinoud udf_add_impl_regid(&efe->imp_id);
2586 1.1 reinoud
2587 1.1 reinoud efe->unique_id = udf_rw64(context.unique_id);
2588 1.1 reinoud udf_advance_uniqueid();
2589 1.1 reinoud
2590 1.1 reinoud /* record fidlength information */
2591 1.1 reinoud efe->inf_len = udf_rw64(0);
2592 1.1 reinoud efe->obj_size = udf_rw64(0);
2593 1.1 reinoud efe->l_ad = udf_rw32(0);
2594 1.1 reinoud efe->logblks_rec = udf_rw64(0);
2595 1.1 reinoud
2596 1.1 reinoud crclen = sizeof(struct extfile_entry) - 1 - UDF_DESC_TAG_LENGTH;
2597 1.1 reinoud
2598 1.1 reinoud /* make sure the header sums stays correct */
2599 1.1 reinoud efe->tag.desc_crc_len = udf_rw16(crclen);
2600 1.1 reinoud udf_validate_tag_and_crc_sums((union dscrptr *) efe);
2601 1.1 reinoud
2602 1.1 reinoud *efep = efe;
2603 1.1 reinoud return 0;
2604 1.1 reinoud }
2605 1.1 reinoud
2606 1.1 reinoud /* --------------------------------------------------------------------- */
2607 1.1 reinoud
2608 1.1 reinoud /* for METADATA file appending only */
2609 1.1 reinoud static void
2610 1.1 reinoud udf_append_meta_mapping_part_to_efe(struct extfile_entry *efe,
2611 1.1 reinoud struct short_ad *mapping)
2612 1.1 reinoud {
2613 1.1 reinoud struct icb_tag *icb;
2614 1.1 reinoud uint64_t inf_len, obj_size, logblks_rec;
2615 1.1 reinoud uint32_t l_ad, l_ea;
2616 1.1 reinoud uint16_t crclen;
2617 1.1 reinoud uintptr_t bpos;
2618 1.1 reinoud
2619 1.1 reinoud inf_len = udf_rw64(efe->inf_len);
2620 1.1 reinoud obj_size = udf_rw64(efe->obj_size);
2621 1.1 reinoud logblks_rec = udf_rw64(efe->logblks_rec);
2622 1.1 reinoud l_ad = udf_rw32(efe->l_ad);
2623 1.1 reinoud l_ea = udf_rw32(efe->l_ea);
2624 1.1 reinoud crclen = udf_rw16(efe->tag.desc_crc_len);
2625 1.1 reinoud icb = &efe->icbtag;
2626 1.1 reinoud
2627 1.1 reinoud /* set our allocation to shorts if not already done */
2628 1.1 reinoud icb->flags = udf_rw16(UDF_ICB_SHORT_ALLOC);
2629 1.1 reinoud
2630 1.1 reinoud /* append short_ad */
2631 1.1 reinoud bpos = (uintptr_t)efe->data + l_ea + l_ad;
2632 1.1 reinoud memcpy((void *)bpos, mapping, sizeof(struct short_ad));
2633 1.1 reinoud
2634 1.1 reinoud l_ad += sizeof(struct short_ad);
2635 1.1 reinoud crclen += sizeof(struct short_ad);
2636 1.1 reinoud inf_len += UDF_EXT_LEN(udf_rw32(mapping->len));
2637 1.1 reinoud obj_size += UDF_EXT_LEN(udf_rw32(mapping->len));
2638 1.1 reinoud logblks_rec = UDF_ROUNDUP(inf_len, context.sector_size) /
2639 1.1 reinoud context.sector_size;
2640 1.1 reinoud
2641 1.1 reinoud efe->l_ad = udf_rw32(l_ad);
2642 1.1 reinoud efe->inf_len = udf_rw64(inf_len);
2643 1.1 reinoud efe->obj_size = udf_rw64(obj_size);
2644 1.1 reinoud efe->logblks_rec = udf_rw64(logblks_rec);
2645 1.1 reinoud efe->tag.desc_crc_len = udf_rw16(crclen);
2646 1.1 reinoud }
2647 1.1 reinoud
2648 1.1 reinoud
2649 1.1 reinoud /* for METADATA file appending only */
2650 1.1 reinoud static void
2651 1.1 reinoud udf_append_meta_mapping_to_efe(struct extfile_entry *efe,
2652 1.1 reinoud uint16_t partnr, uint32_t lb_num,
2653 1.1 reinoud uint64_t len)
2654 1.1 reinoud {
2655 1.1 reinoud struct short_ad mapping;
2656 1.1 reinoud uint64_t max_len, part_len;
2657 1.1 reinoud
2658 1.1 reinoud /* calculate max length meta allocation sizes */
2659 1.1 reinoud max_len = UDF_EXT_MAXLEN / context.sector_size; /* in sectors */
2660 1.1 reinoud max_len = (max_len / layout.meta_blockingnr) * layout.meta_blockingnr;
2661 1.1 reinoud max_len = max_len * context.sector_size;
2662 1.1 reinoud
2663 1.1 reinoud memset(&mapping, 0, sizeof(mapping));
2664 1.1 reinoud while (len) {
2665 1.1 reinoud part_len = MIN(len, max_len);
2666 1.1 reinoud mapping.lb_num = udf_rw32(lb_num);
2667 1.1 reinoud mapping.len = udf_rw32(part_len);
2668 1.1 reinoud
2669 1.1 reinoud udf_append_meta_mapping_part_to_efe(efe, &mapping);
2670 1.1 reinoud
2671 1.1 reinoud lb_num += part_len / context.sector_size;
2672 1.1 reinoud len -= part_len;
2673 1.1 reinoud }
2674 1.1 reinoud }
2675 1.1 reinoud
2676 1.1 reinoud
2677 1.1 reinoud int
2678 1.1 reinoud udf_create_meta_files(void)
2679 1.1 reinoud {
2680 1.1 reinoud struct extfile_entry *efe;
2681 1.1 reinoud struct long_ad meta_icb;
2682 1.1 reinoud uint64_t bytes;
2683 1.1 reinoud uint32_t sector_size;
2684 1.1 reinoud int filetype, error;
2685 1.1 reinoud
2686 1.1 reinoud sector_size = context.sector_size;
2687 1.1 reinoud
2688 1.1 reinoud memset(&meta_icb, 0, sizeof(meta_icb));
2689 1.1 reinoud meta_icb.len = udf_rw32(sector_size);
2690 1.1 reinoud meta_icb.loc.part_num = udf_rw16(context.data_part);
2691 1.1 reinoud
2692 1.1 reinoud /* create metadata file */
2693 1.1 reinoud meta_icb.loc.lb_num = udf_rw32(layout.meta_file);
2694 1.1 reinoud filetype = UDF_ICB_FILETYPE_META_MAIN;
2695 1.1 reinoud error = udf_create_new_efe(&efe, filetype, NULL);
2696 1.1 reinoud if (error)
2697 1.1 reinoud return error;
2698 1.1 reinoud context.meta_file = efe;
2699 1.1 reinoud context.meta_file->unique_id = udf_rw64(0);
2700 1.1 reinoud
2701 1.1 reinoud /* create metadata mirror file */
2702 1.1 reinoud meta_icb.loc.lb_num = udf_rw32(layout.meta_mirror);
2703 1.1 reinoud filetype = UDF_ICB_FILETYPE_META_MIRROR;
2704 1.1 reinoud error = udf_create_new_efe(&efe, filetype, NULL);
2705 1.1 reinoud if (error)
2706 1.1 reinoud return error;
2707 1.1 reinoud context.meta_mirror = efe;
2708 1.1 reinoud context.meta_mirror->unique_id = udf_rw64(0);
2709 1.1 reinoud
2710 1.1 reinoud if (!(context.format_flags & FORMAT_READONLY)) {
2711 1.1 reinoud /* create metadata bitmap file */
2712 1.1 reinoud meta_icb.loc.lb_num = udf_rw32(layout.meta_bitmap);
2713 1.1 reinoud filetype = UDF_ICB_FILETYPE_META_BITMAP;
2714 1.1 reinoud error = udf_create_new_efe(&efe, filetype, NULL);
2715 1.1 reinoud if (error)
2716 1.1 reinoud return error;
2717 1.1 reinoud context.meta_bitmap = efe;
2718 1.1 reinoud context.meta_bitmap->unique_id = udf_rw64(0);
2719 1.1 reinoud }
2720 1.1 reinoud
2721 1.1 reinoud /* restart unique id */
2722 1.1 reinoud context.unique_id = 0x10;
2723 1.1 reinoud
2724 1.1 reinoud /* XXX no support for metadata mirroring yet */
2725 1.1 reinoud /* insert extents */
2726 1.1 reinoud efe = context.meta_file;
2727 1.1 reinoud udf_append_meta_mapping_to_efe(efe, context.data_part,
2728 1.1 reinoud layout.meta_part_start_lba,
2729 1.1 reinoud (uint64_t) layout.meta_part_size_lba * sector_size);
2730 1.1 reinoud
2731 1.1 reinoud efe = context.meta_mirror;
2732 1.1 reinoud udf_append_meta_mapping_to_efe(efe, context.data_part,
2733 1.1 reinoud layout.meta_part_start_lba,
2734 1.1 reinoud (uint64_t) layout.meta_part_size_lba * sector_size);
2735 1.1 reinoud
2736 1.1 reinoud if (context.meta_bitmap) {
2737 1.1 reinoud efe = context.meta_bitmap;
2738 1.1 reinoud bytes = udf_space_bitmap_len(layout.meta_part_size_lba);
2739 1.1 reinoud udf_append_meta_mapping_to_efe(efe, context.data_part,
2740 1.1 reinoud layout.meta_bitmap_space, bytes);
2741 1.1 reinoud }
2742 1.1 reinoud
2743 1.1 reinoud return 0;
2744 1.1 reinoud }
2745 1.1 reinoud
2746 1.1 reinoud
2747 1.1 reinoud /* --------------------------------------------------------------------- */
2748 1.1 reinoud
2749 1.1 reinoud int
2750 1.1 reinoud udf_create_new_rootdir(union dscrptr **dscr)
2751 1.1 reinoud {
2752 1.1 reinoud struct file_entry *fe;
2753 1.1 reinoud struct extfile_entry *efe;
2754 1.1 reinoud struct long_ad root_icb;
2755 1.1 reinoud int filetype, error;
2756 1.1 reinoud
2757 1.1 reinoud memset(&root_icb, 0, sizeof(root_icb));
2758 1.1 reinoud root_icb.len = udf_rw32(context.sector_size);
2759 1.1 reinoud root_icb.loc.lb_num = udf_rw32(layout.rootdir);
2760 1.1 reinoud root_icb.loc.part_num = udf_rw16(context.metadata_part);
2761 1.1 reinoud
2762 1.1 reinoud filetype = UDF_ICB_FILETYPE_DIRECTORY;
2763 1.1 reinoud if (context.dscrver == 2) {
2764 1.1 reinoud error = udf_create_new_fe(&fe, filetype, NULL);
2765 1.1 reinoud *dscr = (union dscrptr *) fe;
2766 1.1 reinoud } else {
2767 1.1 reinoud error = udf_create_new_efe(&efe, filetype, NULL);
2768 1.1 reinoud *dscr = (union dscrptr *) efe;
2769 1.1 reinoud }
2770 1.1 reinoud if (error)
2771 1.1 reinoud return error;
2772 1.1 reinoud
2773 1.1 reinoud /* append '..' */
2774 1.1 reinoud udf_append_parentfid(*dscr, &root_icb);
2775 1.1 reinoud
2776 1.1 reinoud /* rootdir has explicit only one link on creation; '..' is no link */
2777 1.1 reinoud if (context.dscrver == 2) {
2778 1.1 reinoud fe->link_cnt = udf_rw16(1);
2779 1.1 reinoud } else {
2780 1.1 reinoud efe->link_cnt = udf_rw16(1);
2781 1.1 reinoud }
2782 1.1 reinoud
2783 1.1 reinoud context.num_directories++;
2784 1.1 reinoud assert(context.num_directories == 1);
2785 1.1 reinoud
2786 1.1 reinoud return 0;
2787 1.1 reinoud }
2788 1.1 reinoud
2789 1.1 reinoud
2790 1.1 reinoud void
2791 1.1 reinoud udf_prepend_VAT_file(void)
2792 1.1 reinoud {
2793 1.1 reinoud /* old style VAT has no prepend */
2794 1.1 reinoud if (context.dscrver == 2) {
2795 1.1 reinoud context.vat_start = 0;
2796 1.1 reinoud context.vat_size = 0;
2797 1.1 reinoud return;
2798 1.1 reinoud }
2799 1.1 reinoud
2800 1.1 reinoud context.vat_start = offsetof(struct udf_vat, data);
2801 1.1 reinoud context.vat_size = offsetof(struct udf_vat, data);
2802 1.1 reinoud }
2803 1.1 reinoud
2804 1.1 reinoud
2805 1.1 reinoud void
2806 1.1 reinoud udf_vat_update(uint32_t virt, uint32_t phys)
2807 1.1 reinoud {
2808 1.1 reinoud uint32_t *vatpos;
2809 1.1 reinoud uint32_t new_size;
2810 1.1 reinoud
2811 1.1 reinoud if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
2812 1.1 reinoud return;
2813 1.2 riastrad
2814 1.1 reinoud new_size = MAX(context.vat_size,
2815 1.1 reinoud (context.vat_start + (virt+1)*sizeof(uint32_t)));
2816 1.1 reinoud
2817 1.1 reinoud if (new_size > context.vat_allocated) {
2818 1.2 riastrad context.vat_allocated =
2819 1.1 reinoud UDF_ROUNDUP(new_size, context.sector_size);
2820 1.1 reinoud context.vat_contents = realloc(context.vat_contents,
2821 1.1 reinoud context.vat_allocated);
2822 1.1 reinoud assert(context.vat_contents);
2823 1.1 reinoud /* XXX could also report error */
2824 1.1 reinoud }
2825 1.1 reinoud vatpos = (uint32_t *) (context.vat_contents + context.vat_start);
2826 1.1 reinoud vatpos[virt] = udf_rw32(phys);
2827 1.1 reinoud
2828 1.1 reinoud context.vat_size = MAX(context.vat_size,
2829 1.1 reinoud (context.vat_start + (virt+1)*sizeof(uint32_t)));
2830 1.1 reinoud }
2831 1.1 reinoud
2832 1.1 reinoud
2833 1.1 reinoud int
2834 1.1 reinoud udf_append_VAT_file(void)
2835 1.1 reinoud {
2836 1.1 reinoud struct udf_oldvat_tail *oldvat_tail;
2837 1.1 reinoud struct udf_vat *vathdr;
2838 1.1 reinoud int32_t len_diff;
2839 1.1 reinoud
2840 1.1 reinoud /* new style VAT has VAT LVInt analog in front */
2841 1.1 reinoud if (context.dscrver == 3) {
2842 1.1 reinoud /* set up VATv2 descriptor */
2843 1.1 reinoud vathdr = (struct udf_vat *) context.vat_contents;
2844 1.1 reinoud vathdr->header_len = udf_rw16(sizeof(struct udf_vat) - 1);
2845 1.1 reinoud vathdr->impl_use_len = udf_rw16(0);
2846 1.1 reinoud memcpy(vathdr->logvol_id, context.logical_vol->logvol_id, 128);
2847 1.1 reinoud vathdr->prev_vat = udf_rw32(UDF_NO_PREV_VAT);
2848 1.1 reinoud vathdr->num_files = udf_rw32(context.num_files);
2849 1.1 reinoud vathdr->num_directories = udf_rw32(context.num_directories);
2850 1.1 reinoud
2851 1.1 reinoud vathdr->min_udf_readver = udf_rw16(context.min_udf);
2852 1.1 reinoud vathdr->min_udf_writever = udf_rw16(context.min_udf);
2853 1.1 reinoud vathdr->max_udf_writever = udf_rw16(context.max_udf);
2854 1.1 reinoud
2855 1.1 reinoud return 0;
2856 1.1 reinoud }
2857 1.1 reinoud
2858 1.1 reinoud /* old style VAT has identifier appended */
2859 1.1 reinoud
2860 1.1 reinoud /* append "*UDF Virtual Alloc Tbl" id and prev. VAT location */
2861 1.1 reinoud len_diff = context.vat_allocated - context.vat_size;
2862 1.1 reinoud assert(len_diff >= 0);
2863 1.1 reinoud if (len_diff < (int32_t) sizeof(struct udf_oldvat_tail)) {
2864 1.1 reinoud context.vat_allocated += context.sector_size;
2865 1.1 reinoud context.vat_contents = realloc(context.vat_contents,
2866 1.1 reinoud context.vat_allocated);
2867 1.1 reinoud assert(context.vat_contents);
2868 1.1 reinoud /* XXX could also report error */
2869 1.1 reinoud }
2870 1.1 reinoud
2871 1.1 reinoud oldvat_tail = (struct udf_oldvat_tail *) (context.vat_contents +
2872 1.1 reinoud context.vat_size);
2873 1.1 reinoud
2874 1.1 reinoud udf_set_regid(&oldvat_tail->id, "*UDF Virtual Alloc Tbl");
2875 1.1 reinoud udf_add_udf_regid(&oldvat_tail->id);
2876 1.1 reinoud oldvat_tail->prev_vat = udf_rw32(UDF_NO_PREV_VAT);
2877 1.1 reinoud
2878 1.1 reinoud context.vat_size += sizeof(struct udf_oldvat_tail);
2879 1.1 reinoud
2880 1.1 reinoud return 0;
2881 1.1 reinoud }
2882 1.1 reinoud
2883 1.1 reinoud
2884 1.1 reinoud int
2885 1.1 reinoud udf_create_VAT(union dscrptr **vat_dscr, struct long_ad *vatdata_loc)
2886 1.1 reinoud {
2887 1.1 reinoud struct impl_extattr_entry *implext;
2888 1.1 reinoud struct vatlvext_extattr_entry *vatlvext;
2889 1.1 reinoud struct long_ad *allocpos;
2890 1.1 reinoud uint8_t *bpos, *extattr;
2891 1.1 reinoud uint32_t ea_len, inf_len, vat_len, blks;
2892 1.1 reinoud int filetype;
2893 1.1 reinoud int error;
2894 1.1 reinoud
2895 1.1 reinoud assert((layout.rootdir < 2) && (layout.fsd < 2));
2896 1.1 reinoud
2897 1.1 reinoud if (context.dscrver == 2) {
2898 1.1 reinoud struct file_entry *fe;
2899 1.1 reinoud
2900 1.1 reinoud /* old style VAT */
2901 1.1 reinoud filetype = UDF_ICB_FILETYPE_UNKNOWN;
2902 1.1 reinoud error = udf_create_new_fe(&fe, filetype, NULL);
2903 1.1 reinoud if (error)
2904 1.1 reinoud return error;
2905 1.1 reinoud
2906 1.1 reinoud /* append VAT LVExtension attribute */
2907 1.1 reinoud ea_len = sizeof(struct impl_extattr_entry) - 2 + 4 +
2908 1.1 reinoud sizeof(struct vatlvext_extattr_entry);
2909 1.1 reinoud
2910 1.1 reinoud extattr = calloc(1, ea_len);
2911 1.1 reinoud
2912 1.1 reinoud implext = (struct impl_extattr_entry *) extattr;
2913 1.1 reinoud implext->hdr.type = udf_rw32(2048); /* [4/48.10.8] */
2914 1.1 reinoud implext->hdr.subtype = 1; /* [4/48.10.8.2] */
2915 1.1 reinoud implext->hdr.a_l = udf_rw32(ea_len); /* VAT LVext EA size */
2916 1.1 reinoud /* use 4 bytes of imp use for UDF checksum [UDF 3.3.4.5] */
2917 1.1 reinoud implext->iu_l = udf_rw32(4);
2918 1.1 reinoud udf_set_regid(&implext->imp_id, "*UDF VAT LVExtension");
2919 1.1 reinoud udf_add_udf_regid(&implext->imp_id);
2920 1.1 reinoud
2921 1.1 reinoud /* VAT LVExtension data follows UDF IU space */
2922 1.1 reinoud bpos = ((uint8_t *) implext->data) + 4;
2923 1.1 reinoud vatlvext = (struct vatlvext_extattr_entry *) bpos;
2924 1.1 reinoud
2925 1.1 reinoud vatlvext->unique_id_chk = udf_rw64(fe->unique_id);
2926 1.1 reinoud vatlvext->num_files = udf_rw32(context.num_files);
2927 1.1 reinoud vatlvext->num_directories = udf_rw32(context.num_directories);
2928 1.1 reinoud memcpy(vatlvext->logvol_id, context.logical_vol->logvol_id,128);
2929 1.1 reinoud
2930 1.1 reinoud udf_extattr_insert_internal((union dscrptr *) fe,
2931 1.1 reinoud (struct extattr_entry *) extattr);
2932 1.1 reinoud
2933 1.1 reinoud free(extattr);
2934 1.1 reinoud
2935 1.1 reinoud fe->icbtag.flags = udf_rw16(UDF_ICB_LONG_ALLOC);
2936 1.1 reinoud
2937 1.1 reinoud allocpos = (struct long_ad *) (fe->data + udf_rw32(fe->l_ea));
2938 1.1 reinoud *allocpos = *vatdata_loc;
2939 1.1 reinoud
2940 1.1 reinoud /* set length */
2941 1.1 reinoud inf_len = context.vat_size;
2942 1.1 reinoud fe->inf_len = udf_rw64(inf_len);
2943 1.1 reinoud allocpos->len = udf_rw32(inf_len);
2944 1.1 reinoud fe->l_ad = udf_rw32(sizeof(struct long_ad));
2945 1.1 reinoud blks = UDF_ROUNDUP(inf_len, context.sector_size) /
2946 1.1 reinoud context.sector_size;
2947 1.1 reinoud fe->logblks_rec = udf_rw32(blks);
2948 1.1 reinoud
2949 1.1 reinoud /* update vat descriptor's CRC length */
2950 1.1 reinoud vat_len = sizeof(struct file_entry) - 1 - UDF_DESC_TAG_LENGTH;
2951 1.1 reinoud vat_len += udf_rw32(fe->l_ad) + udf_rw32(fe->l_ea);
2952 1.1 reinoud fe->tag.desc_crc_len = udf_rw16(vat_len);
2953 1.1 reinoud
2954 1.1 reinoud *vat_dscr = (union dscrptr *) fe;
2955 1.1 reinoud } else {
2956 1.1 reinoud /* the choice is between an EFE or an FE as VAT */
2957 1.1 reinoud #if 1
2958 1.1 reinoud struct extfile_entry *efe;
2959 1.1 reinoud
2960 1.1 reinoud /* new style VAT on FE */
2961 1.1 reinoud filetype = UDF_ICB_FILETYPE_VAT;
2962 1.1 reinoud error = udf_create_new_efe(&efe, filetype, NULL);
2963 1.1 reinoud if (error)
2964 1.1 reinoud return error;
2965 1.1 reinoud
2966 1.1 reinoud efe->icbtag.flags = udf_rw16(UDF_ICB_LONG_ALLOC);
2967 1.1 reinoud
2968 1.1 reinoud allocpos = (struct long_ad *) efe->data;
2969 1.1 reinoud *allocpos = *vatdata_loc;
2970 1.1 reinoud
2971 1.1 reinoud /* set length */
2972 1.1 reinoud inf_len = context.vat_size;
2973 1.1 reinoud efe->inf_len = udf_rw64(inf_len);
2974 1.1 reinoud allocpos->len = udf_rw32(inf_len);
2975 1.1 reinoud efe->obj_size = udf_rw64(inf_len);
2976 1.1 reinoud efe->l_ad = udf_rw32(sizeof(struct long_ad));
2977 1.1 reinoud blks = UDF_ROUNDUP(inf_len, context.sector_size) /
2978 1.1 reinoud context.sector_size;
2979 1.1 reinoud efe->logblks_rec = udf_rw32(blks);
2980 1.1 reinoud
2981 1.1 reinoud vat_len = sizeof(struct extfile_entry)-1 - UDF_DESC_TAG_LENGTH;
2982 1.1 reinoud vat_len += udf_rw32(efe->l_ad);
2983 1.1 reinoud efe->tag.desc_crc_len = udf_rw16(vat_len);
2984 1.1 reinoud
2985 1.1 reinoud *vat_dscr = (union dscrptr *) efe;
2986 1.1 reinoud #else
2987 1.1 reinoud struct file_entry *fe;
2988 1.1 reinoud uint32_t l_ea;
2989 1.1 reinoud
2990 1.1 reinoud /* new style VAT on EFE */
2991 1.1 reinoud filetype = UDF_ICB_FILETYPE_VAT;
2992 1.1 reinoud error = udf_create_new_fe(&fe, filetype, NULL);
2993 1.1 reinoud if (error)
2994 1.1 reinoud return error;
2995 1.1 reinoud
2996 1.1 reinoud fe->icbtag.flags = udf_rw16(UDF_ICB_LONG_ALLOC);
2997 1.1 reinoud
2998 1.1 reinoud l_ea = udf_rw32(fe->l_ea);
2999 1.1 reinoud allocpos = (struct long_ad *) (fe->data + l_ea);
3000 1.1 reinoud *allocpos = *vatdata_loc;
3001 1.1 reinoud
3002 1.1 reinoud /* set length */
3003 1.1 reinoud inf_len = context.vat_size;
3004 1.1 reinoud fe->inf_len = udf_rw64(inf_len);
3005 1.1 reinoud allocpos->len = udf_rw32(inf_len);
3006 1.1 reinoud fe->l_ad = udf_rw32(sizeof(struct long_ad));
3007 1.1 reinoud blks = UDF_ROUNDUP(inf_len, context.sector_size) /
3008 1.1 reinoud context.sector_size;
3009 1.1 reinoud fe->logblks_rec = udf_rw32(blks);
3010 1.1 reinoud
3011 1.1 reinoud vat_len = sizeof(struct file_entry)-1 - UDF_DESC_TAG_LENGTH;
3012 1.1 reinoud vat_len += udf_rw32(fe->l_ad) + udf_rw32(fe->l_ea);
3013 1.1 reinoud fe->tag.desc_crc_len = udf_rw16(vat_len);
3014 1.1 reinoud
3015 1.1 reinoud *vat_dscr = (union dscrptr *) fe;
3016 1.1 reinoud #endif
3017 1.1 reinoud }
3018 1.2 riastrad
3019 1.1 reinoud return 0;
3020 1.1 reinoud }
3021 1.1 reinoud
3022 1.1 reinoud
3023 1.1 reinoud int
3024 1.1 reinoud udf_writeout_VAT(void)
3025 1.1 reinoud {
3026 1.1 reinoud union dscrptr *vat_dscr;
3027 1.1 reinoud struct long_ad vatdata;
3028 1.1 reinoud uint32_t loc, phys, ext, sects;
3029 1.1 reinoud int rel_block, rest_block, error;
3030 1.1 reinoud
3031 1.1 reinoud vat_dscr = NULL;
3032 1.1 reinoud /* update lvint to reflect the newest values (no writeout) */
3033 1.1 reinoud udf_update_lvintd(UDF_INTEGRITY_CLOSED);
3034 1.1 reinoud
3035 1.1 reinoud error = udf_append_VAT_file();
3036 1.1 reinoud if (error)
3037 1.1 reinoud return error;
3038 1.1 reinoud
3039 1.1 reinoud /* write out VAT data */
3040 1.1 reinoud sects = UDF_ROUNDUP(context.vat_size, context.sector_size) /
3041 1.1 reinoud context.sector_size;
3042 1.1 reinoud layout.vat = context.alloc_pos[context.data_part];
3043 1.1 reinoud udf_data_alloc(sects, &vatdata);
3044 1.1 reinoud //printf("layout.vat %d\n", layout.vat + udf_rw32(context.partitions[context.data_part]->start_loc));
3045 1.1 reinoud
3046 1.1 reinoud loc = udf_rw32(vatdata.loc.lb_num);
3047 1.1 reinoud udf_translate_vtop(loc, context.data_part, &phys, &ext);
3048 1.1 reinoud
3049 1.1 reinoud error = udf_write_phys(context.vat_contents, phys, sects);
3050 1.1 reinoud if (error)
3051 1.1 reinoud return error;
3052 1.1 reinoud loc += sects;
3053 1.1 reinoud
3054 1.1 reinoud /* create new VAT descriptor */
3055 1.1 reinoud error = udf_create_VAT(&vat_dscr, &vatdata);
3056 1.1 reinoud if (error)
3057 1.1 reinoud return error;
3058 1.1 reinoud
3059 1.1 reinoud //printf("VAT data at %d\n", vatdata.loc.lb_num);
3060 1.1 reinoud //printf("VAT itself at %d\n", loc + udf_rw32(context.partitions[context.data_part]->start_loc));
3061 1.1 reinoud
3062 1.1 reinoud /* at least one */
3063 1.1 reinoud error = udf_write_dscr_virt(vat_dscr, loc, context.data_part, 1);
3064 1.1 reinoud loc++;
3065 1.1 reinoud
3066 1.1 reinoud error = udf_translate_vtop(loc, context.data_part, &phys, &ext);
3067 1.1 reinoud assert(!error);
3068 1.1 reinoud
3069 1.1 reinoud rel_block = phys - (UDF_ROUNDDOWN(phys, layout.blockingnr) + wrtrack_skew);
3070 1.1 reinoud rest_block = layout.blockingnr - rel_block;
3071 1.1 reinoud
3072 1.1 reinoud for (int i = 0; i < rest_block; i++) {
3073 1.1 reinoud error = udf_write_dscr_virt(vat_dscr, loc, context.data_part, 1);
3074 1.1 reinoud loc++;
3075 1.1 reinoud }
3076 1.1 reinoud free(vat_dscr);
3077 1.1 reinoud
3078 1.1 reinoud return error;
3079 1.1 reinoud }
3080 1.1 reinoud
3081 1.1 reinoud
3082 1.1 reinoud /* --------------------------------------------------------------------- */
3083 1.1 reinoud /*
3084 1.1 reinoud * mmc_discinfo and mmc_trackinfo readers modified from origional in udf main
3085 1.1 reinoud * code in sys/fs/udf/
3086 1.1 reinoud */
3087 1.1 reinoud
3088 1.1 reinoud void
3089 1.1 reinoud udf_dump_discinfo(struct mmc_discinfo *di)
3090 1.1 reinoud {
3091 1.1 reinoud #ifdef DEBUG
3092 1.1 reinoud char bits[128];
3093 1.1 reinoud
3094 1.1 reinoud printf("Device/media info :\n");
3095 1.1 reinoud printf("\tMMC profile 0x%02x\n", di->mmc_profile);
3096 1.1 reinoud printf("\tderived class %d\n", di->mmc_class);
3097 1.1 reinoud printf("\tsector size %d\n", di->sector_size);
3098 1.1 reinoud printf("\tdisc state %d\n", di->disc_state);
3099 1.1 reinoud printf("\tlast ses state %d\n", di->last_session_state);
3100 1.1 reinoud printf("\tbg format state %d\n", di->bg_format_state);
3101 1.1 reinoud printf("\tfrst track %d\n", di->first_track);
3102 1.1 reinoud printf("\tfst on last ses %d\n", di->first_track_last_session);
3103 1.1 reinoud printf("\tlst on last ses %d\n", di->last_track_last_session);
3104 1.1 reinoud printf("\tlink block penalty %d\n", di->link_block_penalty);
3105 1.1 reinoud snprintb(bits, sizeof(bits), MMC_DFLAGS_FLAGBITS, (uint64_t) di->disc_flags);
3106 1.1 reinoud printf("\tdisc flags %s\n", bits);
3107 1.1 reinoud printf("\tdisc id %x\n", di->disc_id);
3108 1.1 reinoud printf("\tdisc barcode %"PRIx64"\n", di->disc_barcode);
3109 1.1 reinoud
3110 1.1 reinoud printf("\tnum sessions %d\n", di->num_sessions);
3111 1.1 reinoud printf("\tnum tracks %d\n", di->num_tracks);
3112 1.1 reinoud
3113 1.1 reinoud snprintb(bits, sizeof(bits), MMC_CAP_FLAGBITS, di->mmc_cur);
3114 1.1 reinoud printf("\tcapabilities cur %s\n", bits);
3115 1.1 reinoud snprintb(bits, sizeof(bits), MMC_CAP_FLAGBITS, di->mmc_cap);
3116 1.1 reinoud printf("\tcapabilities cap %s\n", bits);
3117 1.1 reinoud printf("\n");
3118 1.1 reinoud printf("\tlast_possible_lba %d\n", di->last_possible_lba);
3119 1.1 reinoud printf("\n");
3120 1.1 reinoud #endif
3121 1.1 reinoud }
3122 1.1 reinoud
3123 1.1 reinoud
3124 1.1 reinoud void
3125 1.1 reinoud udf_synchronise_caches(void)
3126 1.1 reinoud {
3127 1.1 reinoud #if !HAVE_NBTOOL_CONFIG_H
3128 1.1 reinoud struct mmc_op mmc_op;
3129 1.1 reinoud
3130 1.1 reinoud bzero(&mmc_op, sizeof(struct mmc_op));
3131 1.1 reinoud mmc_op.operation = MMC_OP_SYNCHRONISECACHE;
3132 1.1 reinoud
3133 1.1 reinoud /* this device might not know this ioct, so just be ignorant */
3134 1.1 reinoud (void) ioctl(dev_fd, MMCOP, &mmc_op);
3135 1.1 reinoud #endif
3136 1.1 reinoud }
3137 1.1 reinoud
3138 1.1 reinoud
3139 1.1 reinoud /*
3140 1.1 reinoud * General Idea:
3141 1.1 reinoud *
3142 1.1 reinoud * stat the dev_fd
3143 1.1 reinoud *
3144 1.1 reinoud * If a S_ISREG(), we emulate using the emul_* settings.
3145 1.1 reinoud *
3146 1.1 reinoud * If its a device :
3147 1.1 reinoud * try the MMCGETDISCINFO ioctl() and be done.
3148 1.1 reinoud *
3149 1.1 reinoud * If that fails, its a regular disc and set the type to disc media.
3150 1.1 reinoud *
3151 1.1 reinoud */
3152 1.1 reinoud
3153 1.1 reinoud
3154 1.1 reinoud int
3155 1.1 reinoud udf_update_discinfo(void)
3156 1.1 reinoud {
3157 1.1 reinoud off_t size, last_sector, secsize;
3158 1.1 reinoud int error;
3159 1.1 reinoud
3160 1.1 reinoud memset(&mmc_discinfo, 0, sizeof(struct mmc_discinfo));
3161 1.1 reinoud
3162 1.1 reinoud #if !HAVE_NBTOOL_CONFIG_H
3163 1.1 reinoud /* check if we're on a MMC capable device, i.e. CD/DVD */
3164 1.1 reinoud error = ioctl(dev_fd, MMCGETDISCINFO, &mmc_discinfo);
3165 1.1 reinoud if (error == 0) {
3166 1.1 reinoud if ((emul_mmc_profile != -1) &&
3167 1.1 reinoud (emul_mmc_profile != mmc_discinfo.mmc_profile)) {
3168 1.1 reinoud errno = EINVAL;
3169 1.1 reinoud perror("media and specified disc type mismatch");
3170 1.1 reinoud return errno;
3171 1.1 reinoud }
3172 1.1 reinoud emul_size = 0;
3173 1.1 reinoud return 0;
3174 1.1 reinoud }
3175 1.1 reinoud #endif
3176 1.1 reinoud
3177 1.1 reinoud if (S_ISREG(dev_fd_stat.st_mode)) {
3178 1.1 reinoud /* file support; we pick the minimum sector size allowed */
3179 1.1 reinoud if (emul_mmc_profile < 0)
3180 1.1 reinoud emul_mmc_profile = 0x01;
3181 1.1 reinoud if (emul_size == 0)
3182 1.1 reinoud emul_size = dev_fd_stat.st_size;
3183 1.1 reinoud size = emul_size;
3184 1.1 reinoud secsize = emul_sectorsize;
3185 1.1 reinoud last_sector = (size / secsize) - 1;
3186 1.1 reinoud if (ftruncate(dev_fd, size)) {
3187 1.1 reinoud perror("can't resize file");
3188 1.1 reinoud return EXIT_FAILURE;
3189 1.1 reinoud }
3190 1.1 reinoud } else {
3191 1.1 reinoud #if !HAVE_NBTOOL_CONFIG_H
3192 1.1 reinoud struct disk_geom geo;
3193 1.1 reinoud struct dkwedge_info dkw;
3194 1.1 reinoud
3195 1.1 reinoud /* sanity */
3196 1.1 reinoud if (emul_mmc_profile <= 0)
3197 1.1 reinoud emul_mmc_profile = 0x01;
3198 1.1 reinoud if (emul_mmc_profile != 0x01) {
3199 1.1 reinoud warnx("format incompatible with disc partition");
3200 1.2 riastrad return EXIT_FAILURE;
3201 1.1 reinoud }
3202 1.1 reinoud
3203 1.1 reinoud /* get our disc info */
3204 1.1 reinoud error = getdiskinfo(dev_name, dev_fd, NULL, &geo, &dkw);
3205 1.1 reinoud if (error) {
3206 1.1 reinoud warn("retrieving disc info failed");
3207 1.1 reinoud return EXIT_FAILURE;
3208 1.1 reinoud }
3209 1.1 reinoud secsize = emul_sectorsize;
3210 1.1 reinoud last_sector = (dkw.dkw_size - 1) * geo.dg_secsize / secsize;
3211 1.1 reinoud #else
3212 1.1 reinoud warnx("disk partitions only usable outside tools");
3213 1.1 reinoud return EIO;
3214 1.1 reinoud #endif
3215 1.1 reinoud }
3216 1.1 reinoud
3217 1.1 reinoud /* commons */
3218 1.1 reinoud mmc_discinfo.mmc_profile = emul_mmc_profile;
3219 1.1 reinoud mmc_discinfo.disc_state = MMC_STATE_CLOSED;
3220 1.1 reinoud mmc_discinfo.last_session_state = MMC_STATE_CLOSED;
3221 1.1 reinoud mmc_discinfo.bg_format_state = MMC_BGFSTATE_COMPLETED;
3222 1.1 reinoud mmc_discinfo.link_block_penalty = 0;
3223 1.1 reinoud
3224 1.1 reinoud mmc_discinfo.disc_flags = MMC_DFLAGS_UNRESTRICTED;
3225 1.1 reinoud
3226 1.1 reinoud mmc_discinfo.last_possible_lba = last_sector;
3227 1.1 reinoud mmc_discinfo.sector_size = secsize;
3228 1.1 reinoud
3229 1.1 reinoud mmc_discinfo.num_sessions = 1;
3230 1.1 reinoud mmc_discinfo.num_tracks = 1;
3231 1.1 reinoud
3232 1.1 reinoud mmc_discinfo.first_track = 1;
3233 1.1 reinoud mmc_discinfo.first_track_last_session = mmc_discinfo.last_track_last_session = 1;
3234 1.1 reinoud
3235 1.1 reinoud mmc_discinfo.mmc_cur = MMC_CAP_RECORDABLE | MMC_CAP_ZEROLINKBLK;
3236 1.1 reinoud switch (emul_mmc_profile) {
3237 1.1 reinoud case 0x00: /* unknown, treat as CDROM */
3238 1.1 reinoud case 0x08: /* CDROM */
3239 1.1 reinoud case 0x10: /* DVDROM */
3240 1.1 reinoud case 0x40: /* BDROM */
3241 1.1 reinoud /* FALLTHROUGH */
3242 1.1 reinoud case 0x01: /* disc */
3243 1.1 reinoud /* set up a disc info profile for partitions/files */
3244 1.1 reinoud mmc_discinfo.mmc_class = MMC_CLASS_DISC;
3245 1.1 reinoud mmc_discinfo.mmc_cur |= MMC_CAP_REWRITABLE | MMC_CAP_HW_DEFECTFREE;
3246 1.1 reinoud break;
3247 1.1 reinoud case 0x09: /* CD-R */
3248 1.1 reinoud mmc_discinfo.mmc_class = MMC_CLASS_CD;
3249 1.1 reinoud mmc_discinfo.mmc_cur |= MMC_CAP_SEQUENTIAL;
3250 1.1 reinoud mmc_discinfo.disc_state = MMC_STATE_EMPTY;
3251 1.1 reinoud break;
3252 1.1 reinoud case 0x0a: /* CD-RW + CD-MRW (regretably) */
3253 1.1 reinoud mmc_discinfo.mmc_class = MMC_CLASS_CD;
3254 1.1 reinoud mmc_discinfo.mmc_cur |= MMC_CAP_REWRITABLE;
3255 1.1 reinoud break;
3256 1.1 reinoud case 0x13: /* DVD-RW */
3257 1.1 reinoud case 0x1a: /* DVD+RW */
3258 1.1 reinoud mmc_discinfo.mmc_class = MMC_CLASS_DVD;
3259 1.1 reinoud mmc_discinfo.mmc_cur |= MMC_CAP_REWRITABLE;
3260 1.1 reinoud break;
3261 1.1 reinoud case 0x11: /* DVD-R */
3262 1.1 reinoud case 0x14: /* DVD-RW sequential */
3263 1.1 reinoud case 0x1b: /* DVD+R */
3264 1.1 reinoud case 0x2b: /* DVD+R DL */
3265 1.1 reinoud case 0x51: /* HD DVD-R */
3266 1.1 reinoud mmc_discinfo.mmc_class = MMC_CLASS_DVD;
3267 1.1 reinoud mmc_discinfo.mmc_cur |= MMC_CAP_SEQUENTIAL;
3268 1.1 reinoud mmc_discinfo.disc_state = MMC_STATE_EMPTY;
3269 1.1 reinoud break;
3270 1.1 reinoud case 0x41: /* BD-R */
3271 1.1 reinoud mmc_discinfo.mmc_class = MMC_CLASS_BD;
3272 1.1 reinoud mmc_discinfo.mmc_cur |= MMC_CAP_SEQUENTIAL | MMC_CAP_HW_DEFECTFREE;
3273 1.1 reinoud mmc_discinfo.disc_state = MMC_STATE_EMPTY;
3274 1.1 reinoud break;
3275 1.1 reinoud case 0x43: /* BD-RE */
3276 1.1 reinoud mmc_discinfo.mmc_class = MMC_CLASS_BD;
3277 1.1 reinoud mmc_discinfo.mmc_cur |= MMC_CAP_REWRITABLE | MMC_CAP_HW_DEFECTFREE;
3278 1.1 reinoud break;
3279 1.1 reinoud default:
3280 1.1 reinoud errno = EINVAL;
3281 1.1 reinoud perror("unknown or unimplemented device type");
3282 1.1 reinoud return errno;
3283 1.1 reinoud }
3284 1.1 reinoud mmc_discinfo.mmc_cap = mmc_discinfo.mmc_cur;
3285 1.1 reinoud
3286 1.1 reinoud return 0;
3287 1.1 reinoud }
3288 1.1 reinoud
3289 1.1 reinoud
3290 1.1 reinoud int
3291 1.1 reinoud udf_update_trackinfo(struct mmc_trackinfo *ti)
3292 1.1 reinoud {
3293 1.1 reinoud int error, class;
3294 1.1 reinoud
3295 1.1 reinoud #if !HAVE_NBTOOL_CONFIG_H
3296 1.1 reinoud class = mmc_discinfo.mmc_class;
3297 1.1 reinoud if (class != MMC_CLASS_DISC) {
3298 1.1 reinoud /* tracknr specified in struct ti */
3299 1.1 reinoud error = ioctl(dev_fd, MMCGETTRACKINFO, ti);
3300 1.1 reinoud if (!error)
3301 1.1 reinoud return 0;
3302 1.1 reinoud }
3303 1.1 reinoud #endif
3304 1.1 reinoud
3305 1.1 reinoud /* discs partition support */
3306 1.1 reinoud if (ti->tracknr != 1)
3307 1.1 reinoud return EIO;
3308 1.1 reinoud
3309 1.1 reinoud /* create fake ti (TODO check for resized vnds) */
3310 1.1 reinoud ti->sessionnr = 1;
3311 1.1 reinoud
3312 1.1 reinoud ti->track_mode = 0; /* XXX */
3313 1.1 reinoud ti->data_mode = 0; /* XXX */
3314 1.1 reinoud ti->flags = MMC_TRACKINFO_LRA_VALID | MMC_TRACKINFO_NWA_VALID;
3315 1.1 reinoud
3316 1.1 reinoud ti->track_start = 0;
3317 1.1 reinoud ti->packet_size = emul_packetsize;
3318 1.1 reinoud
3319 1.1 reinoud /* TODO support for resizable vnd */
3320 1.1 reinoud ti->track_size = mmc_discinfo.last_possible_lba;
3321 1.1 reinoud ti->next_writable = mmc_discinfo.last_possible_lba + 1; //0;
3322 1.1 reinoud ti->last_recorded = ti->next_writable;
3323 1.1 reinoud ti->free_blocks = 0;
3324 1.1 reinoud
3325 1.1 reinoud return 0;
3326 1.1 reinoud }
3327 1.1 reinoud
3328 1.1 reinoud
3329 1.1 reinoud int
3330 1.1 reinoud udf_opendisc(const char *device, int open_flags)
3331 1.1 reinoud {
3332 1.1 reinoud /* set global variable to the passed name */
3333 1.1 reinoud dev_name = strdup(device);
3334 1.1 reinoud
3335 1.1 reinoud /* open device */
3336 1.1 reinoud if (open_flags & O_RDONLY) {
3337 1.1 reinoud dev_fd_rdonly = 1;
3338 1.1 reinoud if ((dev_fd = open(dev_name, O_RDONLY, 0)) == -1) {
3339 1.1 reinoud warn("device/image not found");
3340 1.1 reinoud return EXIT_FAILURE;
3341 1.1 reinoud }
3342 1.1 reinoud } else {
3343 1.1 reinoud dev_fd_rdonly = 0;
3344 1.1 reinoud if ((dev_fd = open(dev_name, O_RDWR, 0)) == -1) {
3345 1.1 reinoud /* check if we need to create a file */
3346 1.1 reinoud dev_fd = open(dev_name, O_RDONLY, 0);
3347 1.1 reinoud if (dev_fd > 0) {
3348 1.1 reinoud warn("device is there but can't be opened for "
3349 1.1 reinoud "read/write");
3350 1.1 reinoud return EXIT_FAILURE;
3351 1.1 reinoud }
3352 1.1 reinoud if ((open_flags & O_CREAT) == 0) {
3353 1.1 reinoud warnx("device/image not found");
3354 1.1 reinoud return EXIT_FAILURE;
3355 1.1 reinoud }
3356 1.1 reinoud /* need to create a file */
3357 1.1 reinoud dev_fd = open(dev_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
3358 1.1 reinoud if (dev_fd == -1) {
3359 1.1 reinoud warn("can't create image file");
3360 1.1 reinoud return EXIT_FAILURE;
3361 1.1 reinoud }
3362 1.1 reinoud }
3363 1.1 reinoud }
3364 1.1 reinoud
3365 1.1 reinoud /* stat the device/image */
3366 1.1 reinoud if (fstat(dev_fd, &dev_fd_stat) != 0) {
3367 1.1 reinoud warn("can't stat the disc image");
3368 1.1 reinoud return EXIT_FAILURE;
3369 1.1 reinoud }
3370 1.1 reinoud
3371 1.1 reinoud /* sanity check and resizing of file */
3372 1.1 reinoud if (S_ISREG(dev_fd_stat.st_mode)) {
3373 1.1 reinoud if (emul_size == 0)
3374 1.1 reinoud emul_size = dev_fd_stat.st_size;
3375 1.1 reinoud /* sanitise arguments */
3376 1.1 reinoud emul_sectorsize &= ~511;
3377 1.1 reinoud if (emul_size & (emul_sectorsize-1)) {
3378 1.1 reinoud warnx("size of file is not a multiple of sector size, "
3379 1.1 reinoud "shrinking");
3380 1.1 reinoud emul_size -= emul_size & (emul_sectorsize-1);
3381 1.1 reinoud }
3382 1.1 reinoud
3383 1.1 reinoud /* grow the image */
3384 1.1 reinoud if (ftruncate(dev_fd, emul_size)) {
3385 1.1 reinoud warn("can't resize file");
3386 1.1 reinoud return EXIT_FAILURE;
3387 1.1 reinoud }
3388 1.1 reinoud /* restat the device/image */
3389 1.1 reinoud if (fstat(dev_fd, &dev_fd_stat) != 0) {
3390 1.1 reinoud warn("can't re-stat the disc image");
3391 1.1 reinoud return EXIT_FAILURE;
3392 1.1 reinoud }
3393 1.1 reinoud } else {
3394 1.1 reinoud if (!S_ISCHR(dev_fd_stat.st_mode)) {
3395 1.1 reinoud warnx("%s is not a raw device", dev_name);
3396 1.1 reinoud return EXIT_FAILURE;
3397 1.1 reinoud }
3398 1.1 reinoud }
3399 1.1 reinoud
3400 1.1 reinoud /* just in case something went wrong, synchronise the drive's cache */
3401 1.1 reinoud udf_synchronise_caches();
3402 1.1 reinoud if (udf_update_discinfo()) {
3403 1.1 reinoud warnx("update discinfo failed");
3404 1.1 reinoud return EXIT_FAILURE;
3405 1.1 reinoud }
3406 1.1 reinoud
3407 1.1 reinoud /* honour minimum sector size of the device */
3408 1.1 reinoud if (mmc_discinfo.sector_size > context.sector_size)
3409 1.1 reinoud context.sector_size = mmc_discinfo.sector_size;
3410 1.1 reinoud
3411 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL)
3412 1.1 reinoud udf_init_writequeue(UDF_WRITE_SEQUENTIAL);
3413 1.1 reinoud else {
3414 1.1 reinoud udf_init_writequeue(UDF_WRITE_PACKET);
3415 1.1 reinoud }
3416 1.1 reinoud return 0;
3417 1.1 reinoud }
3418 1.1 reinoud
3419 1.1 reinoud
3420 1.1 reinoud void
3421 1.1 reinoud udf_closedisc(void)
3422 1.1 reinoud {
3423 1.1 reinoud if (!write_queue_suspend) {
3424 1.1 reinoud udf_writeout_writequeue(true);
3425 1.1 reinoud assert(write_queuelen == 0);
3426 1.1 reinoud }
3427 1.1 reinoud
3428 1.1 reinoud udf_synchronise_caches();
3429 1.1 reinoud if (dev_fd)
3430 1.1 reinoud close(dev_fd);
3431 1.1 reinoud }
3432 1.1 reinoud
3433 1.1 reinoud /* --------------------------------------------------------------------- */
3434 1.1 reinoud
3435 1.1 reinoud static int
3436 1.1 reinoud udf_setup_writeparams(void)
3437 1.1 reinoud {
3438 1.1 reinoud #if !HAVE_NBTOOL_CONFIG_H
3439 1.1 reinoud struct mmc_writeparams mmc_writeparams;
3440 1.1 reinoud int error;
3441 1.1 reinoud
3442 1.1 reinoud if (mmc_discinfo.mmc_class == MMC_CLASS_DISC)
3443 1.1 reinoud return 0;
3444 1.1 reinoud
3445 1.1 reinoud if (S_ISREG(dev_fd_stat.st_mode))
3446 1.1 reinoud return 0;
3447 1.1 reinoud
3448 1.1 reinoud /*
3449 1.1 reinoud * only CD burning normally needs setting up, but other disc types
3450 1.1 reinoud * might need other settings to be made. The MMC framework will set up
3451 1.1 reinoud * the necessary recording parameters according to the disc
3452 1.1 reinoud * characteristics read in. Modifications can be made in the discinfo
3453 1.1 reinoud * structure passed to change the nature of the disc.
3454 1.1 reinoud */
3455 1.1 reinoud memset(&mmc_writeparams, 0, sizeof(struct mmc_writeparams));
3456 1.1 reinoud mmc_writeparams.mmc_class = mmc_discinfo.mmc_class;
3457 1.1 reinoud mmc_writeparams.mmc_cur = mmc_discinfo.mmc_cur;
3458 1.1 reinoud
3459 1.1 reinoud /*
3460 1.1 reinoud * UDF dictates first track to determine track mode for the whole
3461 1.1 reinoud * disc. [UDF 1.50/6.10.1.1, UDF 1.50/6.10.2.1]
3462 1.1 reinoud * To prevent problems with a `reserved' track in front we start with
3463 1.1 reinoud * the 2nd track and if that is not valid, go for the 1st.
3464 1.1 reinoud */
3465 1.1 reinoud mmc_writeparams.tracknr = 2;
3466 1.1 reinoud mmc_writeparams.data_mode = MMC_DATAMODE_DEFAULT; /* XA disc */
3467 1.1 reinoud mmc_writeparams.track_mode = MMC_TRACKMODE_DEFAULT; /* data */
3468 1.1 reinoud
3469 1.1 reinoud error = ioctl(dev_fd, MMCSETUPWRITEPARAMS, &mmc_writeparams);
3470 1.1 reinoud if (error) {
3471 1.1 reinoud mmc_writeparams.tracknr = 1;
3472 1.1 reinoud error = ioctl(dev_fd, MMCSETUPWRITEPARAMS, &mmc_writeparams);
3473 1.1 reinoud }
3474 1.1 reinoud return error;
3475 1.1 reinoud #else
3476 1.1 reinoud return 0;
3477 1.1 reinoud #endif
3478 1.1 reinoud }
3479 1.1 reinoud
3480 1.1 reinoud
3481 1.1 reinoud /*
3482 1.1 reinoud * On sequential recordable media, we might need to close the last session to
3483 1.1 reinoud * be able to write new anchors/new fs.
3484 1.1 reinoud */
3485 1.1 reinoud static int
3486 1.1 reinoud udf_open_new_session(void)
3487 1.1 reinoud {
3488 1.1 reinoud #if !HAVE_NBTOOL_CONFIG_H
3489 1.1 reinoud struct mmc_trackinfo ti;
3490 1.1 reinoud struct mmc_op op;
3491 1.1 reinoud int tracknr, error;
3492 1.1 reinoud
3493 1.1 reinoud /* if the drive is not sequential, we're done */
3494 1.1 reinoud if ((mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) == 0)
3495 1.1 reinoud return 0;
3496 1.1 reinoud
3497 1.1 reinoud /* close the last session if its still open */
3498 1.1 reinoud if (mmc_discinfo.last_session_state == MMC_STATE_INCOMPLETE) {
3499 1.1 reinoud /*
3500 1.1 reinoud * Leave the disc alone if force format is not set, it will
3501 1.1 reinoud * error out later
3502 1.1 reinoud */
3503 1.1 reinoud if (!context.create_new_session)
3504 1.1 reinoud return 0;
3505 1.1 reinoud
3506 1.1 reinoud // printf("Closing last open session if present\n");
3507 1.1 reinoud /* close all associated tracks */
3508 1.1 reinoud tracknr = mmc_discinfo.first_track_last_session;
3509 1.1 reinoud while (tracknr <= mmc_discinfo.last_track_last_session) {
3510 1.1 reinoud ti.tracknr = tracknr;
3511 1.1 reinoud error = udf_update_trackinfo(&ti);
3512 1.1 reinoud if (error)
3513 1.1 reinoud return error;
3514 1.1 reinoud // printf("\tClosing open track %d\n", tracknr);
3515 1.1 reinoud memset(&op, 0, sizeof(op));
3516 1.1 reinoud op.operation = MMC_OP_CLOSETRACK;
3517 1.1 reinoud op.mmc_profile = mmc_discinfo.mmc_profile;
3518 1.1 reinoud op.tracknr = tracknr;
3519 1.1 reinoud error = ioctl(dev_fd, MMCOP, &op);
3520 1.1 reinoud if (error)
3521 1.1 reinoud return error;
3522 1.1 reinoud tracknr ++;
3523 1.1 reinoud }
3524 1.1 reinoud // printf("Closing session\n");
3525 1.1 reinoud memset(&op, 0, sizeof(op));
3526 1.1 reinoud op.operation = MMC_OP_CLOSESESSION;
3527 1.1 reinoud op.mmc_profile = mmc_discinfo.mmc_profile;
3528 1.1 reinoud op.sessionnr = mmc_discinfo.num_sessions;
3529 1.1 reinoud error = ioctl(dev_fd, MMCOP, &op);
3530 1.1 reinoud if (error)
3531 1.1 reinoud return error;
3532 1.1 reinoud
3533 1.1 reinoud /* update discinfo since it changed by the operations */
3534 1.1 reinoud error = udf_update_discinfo();
3535 1.1 reinoud if (error)
3536 1.1 reinoud return error;
3537 1.1 reinoud }
3538 1.1 reinoud #endif
3539 1.1 reinoud return 0;
3540 1.1 reinoud }
3541 1.1 reinoud
3542 1.1 reinoud
3543 1.1 reinoud /* bit paranoid but tracks may need repair before they can be written to */
3544 1.1 reinoud static void
3545 1.1 reinoud udf_repair_tracks(void)
3546 1.1 reinoud {
3547 1.1 reinoud #if !HAVE_NBTOOL_CONFIG_H
3548 1.1 reinoud struct mmc_trackinfo ti;
3549 1.1 reinoud struct mmc_op op;
3550 1.1 reinoud int tracknr, error;
3551 1.1 reinoud
3552 1.1 reinoud tracknr = mmc_discinfo.first_track_last_session;
3553 1.1 reinoud while (tracknr <= mmc_discinfo.last_track_last_session) {
3554 1.1 reinoud ti.tracknr = tracknr;
3555 1.1 reinoud error = udf_update_trackinfo(&ti);
3556 1.1 reinoud if (error) {
3557 1.1 reinoud warnx("error updating track information for track %d",
3558 1.1 reinoud tracknr);
3559 1.1 reinoud /* resume */
3560 1.1 reinoud tracknr++;
3561 1.1 reinoud continue;
3562 1.1 reinoud }
3563 1.1 reinoud
3564 1.1 reinoud if (ti.flags & MMC_TRACKINFO_DAMAGED) {
3565 1.1 reinoud /*
3566 1.1 reinoud * Need to repair last track before anything can be done.
3567 1.1 reinoud * this is an optional command, so ignore its error but report
3568 1.1 reinoud * warning.
3569 1.1 reinoud */
3570 1.1 reinoud memset(&op, 0, sizeof(op));
3571 1.1 reinoud op.operation = MMC_OP_REPAIRTRACK;
3572 1.1 reinoud op.mmc_profile = mmc_discinfo.mmc_profile;
3573 1.1 reinoud op.tracknr = ti.tracknr;
3574 1.1 reinoud error = ioctl(dev_fd, MMCOP, &op);
3575 1.1 reinoud
3576 1.1 reinoud if (error)
3577 1.1 reinoud warnx("drive notifies it can't explicitly repair "
3578 1.1 reinoud "damaged track, but it might autorepair\n");
3579 1.1 reinoud }
3580 1.1 reinoud tracknr++;
3581 1.1 reinoud }
3582 1.1 reinoud /* tracks (if any) might not be damaged now, operations are ok now */
3583 1.1 reinoud #endif
3584 1.1 reinoud }
3585 1.1 reinoud
3586 1.1 reinoud
3587 1.1 reinoud int
3588 1.1 reinoud udf_prepare_disc(void)
3589 1.1 reinoud {
3590 1.1 reinoud #if !HAVE_NBTOOL_CONFIG_H
3591 1.1 reinoud int error;
3592 1.1 reinoud
3593 1.1 reinoud /* setup write parameters from discinfo */
3594 1.1 reinoud error = udf_setup_writeparams();
3595 1.1 reinoud if (error)
3596 1.1 reinoud return error;
3597 1.1 reinoud
3598 1.1 reinoud udf_repair_tracks();
3599 1.1 reinoud
3600 1.1 reinoud /* open new session if needed */
3601 1.1 reinoud return udf_open_new_session();
3602 1.1 reinoud #endif
3603 1.1 reinoud return 0;
3604 1.1 reinoud }
3605 1.1 reinoud
3606 1.1 reinoud
3607 1.1 reinoud /* --------------------------------------------------------------------- */
3608 1.1 reinoud
3609 1.1 reinoud /*
3610 1.1 reinoud * write queue implementation
3611 1.1 reinoud */
3612 1.1 reinoud
3613 1.1 reinoud void
3614 1.1 reinoud udf_suspend_writing(void)
3615 1.1 reinoud {
3616 1.1 reinoud write_queue_suspend = 1;
3617 1.1 reinoud }
3618 1.1 reinoud
3619 1.1 reinoud
3620 1.1 reinoud void
3621 1.1 reinoud udf_allow_writing(void)
3622 1.1 reinoud {
3623 1.1 reinoud write_queue_suspend = 0;
3624 1.1 reinoud }
3625 1.1 reinoud
3626 1.1 reinoud
3627 1.1 reinoud static void
3628 1.1 reinoud udf_init_writequeue(int write_strategy)
3629 1.1 reinoud {
3630 1.1 reinoud context.write_strategy = write_strategy;
3631 1.1 reinoud write_queue_suspend = 0;
3632 1.1 reinoud
3633 1.1 reinoud /* setup sector writeout queue's */
3634 1.1 reinoud TAILQ_INIT(&write_queue);
3635 1.1 reinoud write_queuelen = 0;
3636 1.1 reinoud }
3637 1.1 reinoud
3638 1.1 reinoud
3639 1.1 reinoud int
3640 1.1 reinoud udf_write_sector(void *sector, uint64_t location)
3641 1.1 reinoud {
3642 1.1 reinoud struct wrpacket *packet, *found_packet;
3643 1.1 reinoud uint64_t rel_loc;
3644 1.1 reinoud uint64_t blockingnr = layout.blockingnr;
3645 1.1 reinoud int error;
3646 1.1 reinoud
3647 1.1 reinoud assert(!dev_fd_rdonly);
3648 1.1 reinoud assert(blockingnr >= 1);
3649 1.1 reinoud assert(blockingnr <= 64);
3650 1.1 reinoud
3651 1.1 reinoud /*
3652 1.1 reinoud * We have a write strategy but in practice packet writing is
3653 1.1 reinoud * preferable for all media types.
3654 1.1 reinoud */
3655 1.1 reinoud
3656 1.1 reinoud again:
3657 1.1 reinoud /* search location */
3658 1.1 reinoud found_packet = NULL;
3659 1.1 reinoud TAILQ_FOREACH_REVERSE(packet, &write_queue, wrpacket_list, next) {
3660 1.1 reinoud if (packet->start_sectornr <= location) {
3661 1.1 reinoud found_packet = packet;
3662 1.1 reinoud break;
3663 1.1 reinoud }
3664 1.1 reinoud }
3665 1.1 reinoud
3666 1.1 reinoud /* are we in a current packet? */
3667 1.1 reinoud if (found_packet) {
3668 1.1 reinoud uint64_t base = found_packet->start_sectornr;
3669 1.1 reinoud if ((location >= base) && (location -base < blockingnr)) {
3670 1.1 reinoud /* fill in existing packet */
3671 1.1 reinoud rel_loc = location - base;
3672 1.1 reinoud memcpy(found_packet->packet_data +
3673 1.1 reinoud rel_loc * context.sector_size,
3674 1.1 reinoud sector, context.sector_size);
3675 1.1 reinoud found_packet->present |= ((uint64_t) 1 << rel_loc);
3676 1.1 reinoud return 0;
3677 1.1 reinoud }
3678 1.1 reinoud }
3679 1.1 reinoud
3680 1.1 reinoud if ((write_queuelen > UDF_MAX_QUEUELEN) && !write_queue_suspend) {
3681 1.1 reinoud /* we purge the queue and reset found_packet! */
3682 1.1 reinoud error = udf_writeout_writequeue(false);
3683 1.1 reinoud if (error)
3684 1.1 reinoud return error;
3685 1.1 reinoud goto again;
3686 1.1 reinoud }
3687 1.1 reinoud
3688 1.1 reinoud /* create new packet */
3689 1.1 reinoud packet = calloc(1, sizeof(struct wrpacket));
3690 1.1 reinoud if (packet == NULL)
3691 1.1 reinoud return errno;
3692 1.1 reinoud packet->packet_data = calloc(1, context.sector_size * blockingnr);
3693 1.1 reinoud if (packet->packet_data == NULL) {
3694 1.1 reinoud free(packet);
3695 1.1 reinoud return errno;
3696 1.1 reinoud }
3697 1.1 reinoud packet->start_sectornr =
3698 1.1 reinoud UDF_ROUNDDOWN(location, blockingnr) + wrtrack_skew;
3699 1.1 reinoud rel_loc = location - packet->start_sectornr;
3700 1.1 reinoud
3701 1.1 reinoud memcpy(packet->packet_data +
3702 1.1 reinoud rel_loc * context.sector_size,
3703 1.1 reinoud sector, context.sector_size);
3704 1.1 reinoud packet->present = ((uint64_t) 1 << rel_loc);
3705 1.1 reinoud
3706 1.1 reinoud if (found_packet) {
3707 1.1 reinoud TAILQ_INSERT_AFTER(&write_queue, found_packet, packet, next);
3708 1.1 reinoud } else {
3709 1.1 reinoud TAILQ_INSERT_HEAD(&write_queue, packet, next);
3710 1.1 reinoud }
3711 1.1 reinoud write_queuelen++;
3712 1.1 reinoud
3713 1.1 reinoud return 0;
3714 1.1 reinoud }
3715 1.1 reinoud
3716 1.1 reinoud
3717 1.1 reinoud int
3718 1.1 reinoud udf_read_sector(void *sector, uint64_t location)
3719 1.1 reinoud {
3720 1.1 reinoud struct wrpacket *packet, *found_packet;
3721 1.1 reinoud ssize_t ret;
3722 1.1 reinoud uint64_t rpos, rel_loc;
3723 1.1 reinoud uint64_t blockingnr = layout.blockingnr;
3724 1.1 reinoud
3725 1.1 reinoud rpos = (uint64_t) location * context.sector_size;
3726 1.1 reinoud
3727 1.1 reinoud /* search location */
3728 1.1 reinoud found_packet = NULL;
3729 1.1 reinoud TAILQ_FOREACH_REVERSE(packet, &write_queue, wrpacket_list, next) {
3730 1.1 reinoud if (packet->start_sectornr <= location) {
3731 1.1 reinoud found_packet = packet;
3732 1.1 reinoud break;
3733 1.1 reinoud }
3734 1.1 reinoud }
3735 1.1 reinoud
3736 1.1 reinoud /* are we in a current packet? */
3737 1.1 reinoud if (found_packet) {
3738 1.1 reinoud uint64_t base = found_packet->start_sectornr;
3739 1.1 reinoud if ((location >= base) && (location -base < blockingnr)) {
3740 1.1 reinoud /* fill in existing packet */
3741 1.1 reinoud rel_loc = location - base;
3742 1.1 reinoud if (found_packet->present & ((uint64_t) 1 << rel_loc)) {
3743 1.1 reinoud memcpy(sector, found_packet->packet_data +
3744 1.1 reinoud rel_loc * context.sector_size,
3745 1.1 reinoud context.sector_size);
3746 1.1 reinoud } else {
3747 1.1 reinoud ret = pread(dev_fd, sector, context.sector_size, rpos);
3748 1.1 reinoud if (ret == -1)
3749 1.1 reinoud return errno;
3750 1.1 reinoud if (ret < (int) context.sector_size)
3751 1.1 reinoud return EIO;
3752 1.1 reinoud memcpy(found_packet->packet_data +
3753 1.1 reinoud rel_loc * context.sector_size,
3754 1.1 reinoud sector, context.sector_size);
3755 1.1 reinoud found_packet->present |= ((uint64_t) 1 << rel_loc);
3756 1.1 reinoud return 0;
3757 1.1 reinoud }
3758 1.1 reinoud }
3759 1.1 reinoud }
3760 1.1 reinoud /* don't create a packet just for we read something */
3761 1.1 reinoud ret = pread(dev_fd, sector, context.sector_size, rpos);
3762 1.1 reinoud if (ret == -1)
3763 1.1 reinoud return errno;
3764 1.1 reinoud if (ret < (int) context.sector_size)
3765 1.1 reinoud return EIO;
3766 1.1 reinoud return 0;
3767 1.1 reinoud }
3768 1.1 reinoud
3769 1.1 reinoud
3770 1.1 reinoud /*
3771 1.1 reinoud * Now all write requests are queued in the TAILQ, write them out to the
3772 1.1 reinoud * disc/file image. Special care needs to be taken for devices that are only
3773 1.1 reinoud * strict overwritable i.e. only in packet size chunks
3774 1.1 reinoud *
3775 1.1 reinoud * XXX support for growing vnd?
3776 1.1 reinoud */
3777 1.1 reinoud
3778 1.1 reinoud static int
3779 1.1 reinoud udf_writeout_writequeue(bool complete)
3780 1.1 reinoud {
3781 1.1 reinoud struct wrpacket *packet, *next_packet;
3782 1.1 reinoud int blockingnr = layout.blockingnr;
3783 1.1 reinoud int linesize, offset, ret;
3784 1.1 reinoud uint8_t *linebuf;
3785 1.1 reinoud uint64_t present, all_present = -1;
3786 1.1 reinoud uint64_t rpos, wpos;
3787 1.1 reinoud static int t = 0;
3788 1.1 reinoud
3789 1.1 reinoud if (write_queuelen == 0)
3790 1.1 reinoud return 0;
3791 1.1 reinoud
3792 1.1 reinoud if (blockingnr < 64)
3793 1.1 reinoud all_present = ((uint64_t) 1 << blockingnr) -1;
3794 1.1 reinoud linesize = blockingnr * context.sector_size;
3795 1.1 reinoud linebuf = calloc(1, linesize);
3796 1.1 reinoud assert(linebuf);
3797 1.1 reinoud
3798 1.1 reinoud /* fill in blanks if needed */
3799 1.1 reinoud if (complete && (context.write_strategy != UDF_WRITE_SEQUENTIAL)) {
3800 1.1 reinoud TAILQ_FOREACH(packet, &write_queue, next) {
3801 1.1 reinoud present = packet->present;
3802 1.1 reinoud if (present != all_present) {
3803 1.1 reinoud printf("%c", "\\|/-"[t++ % 4]); fflush(stdout);fflush(stderr);
3804 1.1 reinoud //printf("%16lu : readin %08lx\n", packet->start_sectornr, packet->present ^ all_present);
3805 1.1 reinoud rpos = (uint64_t) packet->start_sectornr * context.sector_size;
3806 1.1 reinoud ret = pread(dev_fd, linebuf, linesize, rpos);
3807 1.1 reinoud if (ret == -1) {
3808 1.1 reinoud printf("\b");
3809 1.1 reinoud warn("error reading in blanks, "
3810 1.1 reinoud "could indicate bad disc");
3811 1.1 reinoud printf(" ");
3812 1.1 reinoud }
3813 1.1 reinoud for (int i = 0; i < blockingnr; i++) {
3814 1.1 reinoud //printf("present %08lx, testing bit %08lx, value %08lx\n", present, ((uint64_t) 1 << i), (present & ((uint64_t) 1 << i)));
3815 1.1 reinoud if ((present & ((uint64_t) 1 << i)) > 0)
3816 1.1 reinoud continue;
3817 1.1 reinoud //printf("NOT PRESENT\n");
3818 1.1 reinoud offset = i * context.sector_size;
3819 1.1 reinoud memcpy(packet->packet_data + offset,
3820 1.1 reinoud linebuf + offset,
3821 1.1 reinoud context.sector_size);
3822 1.1 reinoud packet->present |= ((uint64_t) 1<<i);
3823 1.1 reinoud }
3824 1.1 reinoud printf("\b");
3825 1.1 reinoud }
3826 1.1 reinoud assert(packet->present == all_present);
3827 1.1 reinoud }
3828 1.1 reinoud }
3829 1.1 reinoud
3830 1.1 reinoud /* writeout */
3831 1.1 reinoud TAILQ_FOREACH(packet, &write_queue, next) {
3832 1.1 reinoud if (complete || (packet->present == all_present)) {
3833 1.1 reinoud printf("%c", "\\|/-"[t++ % 4]); fflush(stdout);fflush(stderr);
3834 1.1 reinoud //printf("write %lu + %d\n", packet->start_sectornr, linesize / context.sector_size);
3835 1.1 reinoud wpos = (uint64_t) packet->start_sectornr * context.sector_size;
3836 1.1 reinoud ret = pwrite(dev_fd, packet->packet_data, linesize, wpos);
3837 1.1 reinoud printf("\b");
3838 1.1 reinoud if (ret == -1)
3839 1.1 reinoud warn("error writing packet, "
3840 1.1 reinoud "could indicate bad disc");
3841 1.1 reinoud }
3842 1.1 reinoud }
3843 1.1 reinoud
3844 1.1 reinoud /* removing completed packets */
3845 1.1 reinoud TAILQ_FOREACH_SAFE(packet, &write_queue, next, next_packet) {
3846 1.1 reinoud if (complete || (packet->present == all_present)) {
3847 1.1 reinoud TAILQ_REMOVE(&write_queue, packet, next);
3848 1.1 reinoud free(packet->packet_data);
3849 1.1 reinoud free(packet);
3850 1.1 reinoud write_queuelen--;
3851 1.1 reinoud }
3852 1.1 reinoud }
3853 1.1 reinoud if (complete) {
3854 1.1 reinoud assert(TAILQ_EMPTY(&write_queue));
3855 1.1 reinoud write_queuelen = 0;
3856 1.1 reinoud }
3857 1.1 reinoud
3858 1.1 reinoud free(linebuf);
3859 1.1 reinoud return 0;
3860 1.1 reinoud }
3861 1.1 reinoud
3862 1.1 reinoud
3863 1.1 reinoud /* --------------------------------------------------------------------- */
3864 1.1 reinoud
3865 1.1 reinoud /* simplified version of kernel routine */
3866 1.1 reinoud int
3867 1.1 reinoud udf_translate_vtop(uint32_t lb_num, uint16_t vpart,
3868 1.1 reinoud uint32_t *lb_numres, uint32_t *extres)
3869 1.1 reinoud {
3870 1.1 reinoud struct part_desc *pdesc;
3871 1.1 reinoud struct spare_map_entry *sme;
3872 1.1 reinoud struct short_ad *short_ad;
3873 1.1 reinoud struct extfile_entry *efe;
3874 1.1 reinoud uint32_t ext, len, lb_rel, lb_packet, vat_off;
3875 1.1 reinoud uint32_t start_lb, lb_offset, end_lb_offset;
3876 1.1 reinoud uint32_t udf_rw32_lbmap;
3877 1.1 reinoud uint32_t flags;
3878 1.1 reinoud uint8_t *vat_pos, *data_pos;
3879 1.1 reinoud int dscr_size, l_ea, l_ad, icbflags, addr_type;
3880 1.1 reinoud int rel, part;
3881 1.1 reinoud
3882 1.1 reinoud if (vpart > UDF_VTOP_RAWPART)
3883 1.1 reinoud return EINVAL;
3884 1.1 reinoud
3885 1.1 reinoud ext = INT_MAX;
3886 1.1 reinoud translate_again:
3887 1.1 reinoud part = context.vtop[vpart];
3888 1.1 reinoud pdesc = context.partitions[part];
3889 1.1 reinoud
3890 1.1 reinoud switch (context.vtop_tp[vpart]) {
3891 1.1 reinoud case UDF_VTOP_TYPE_RAW :
3892 1.1 reinoud /* 1:1 to the end of the device */
3893 1.1 reinoud *lb_numres = lb_num;
3894 1.1 reinoud *extres = MIN(ext, INT_MAX);
3895 1.1 reinoud return 0;
3896 1.1 reinoud case UDF_VTOP_TYPE_PHYS :
3897 1.1 reinoud /* transform into its disc logical block */
3898 1.1 reinoud if (lb_num > udf_rw32(pdesc->part_len))
3899 1.1 reinoud return EINVAL;
3900 1.1 reinoud *lb_numres = lb_num + udf_rw32(pdesc->start_loc);
3901 1.1 reinoud
3902 1.1 reinoud /* extent from here to the end of the partition */
3903 1.1 reinoud *extres = MIN(ext, udf_rw32(pdesc->part_len) - lb_num);
3904 1.1 reinoud if (*extres == 0)
3905 1.1 reinoud return EINVAL;
3906 1.1 reinoud return 0;
3907 1.1 reinoud case UDF_VTOP_TYPE_VIRT :
3908 1.1 reinoud /* only maps one logical block, lookup in VAT */
3909 1.1 reinoud if (lb_num * 4 >= context.vat_size)
3910 1.1 reinoud return EINVAL;
3911 1.1 reinoud vat_off = context.vat_start + lb_num * 4;
3912 1.1 reinoud vat_pos = context.vat_contents + vat_off;
3913 1.1 reinoud udf_rw32_lbmap = *((uint32_t *) vat_pos);
3914 1.1 reinoud
3915 1.1 reinoud if (vat_off >= context.vat_size) /* XXX > or >= ? */
3916 1.1 reinoud return EINVAL;
3917 1.1 reinoud lb_num = udf_rw32(udf_rw32_lbmap);
3918 1.1 reinoud
3919 1.1 reinoud /* transform into its disc logical block */
3920 1.1 reinoud if (lb_num > udf_rw32(pdesc->part_len))
3921 1.1 reinoud return EINVAL;
3922 1.1 reinoud *lb_numres = lb_num + udf_rw32(pdesc->start_loc);
3923 1.1 reinoud
3924 1.1 reinoud /* just one logical block */
3925 1.1 reinoud *extres = 1;
3926 1.1 reinoud return 0;
3927 1.1 reinoud case UDF_VTOP_TYPE_SPAREABLE :
3928 1.1 reinoud /* check if the packet containing the lb_num is remapped */
3929 1.1 reinoud lb_packet = lb_num / layout.spareable_blockingnr;
3930 1.1 reinoud lb_rel = lb_num % layout.spareable_blockingnr;
3931 1.1 reinoud
3932 1.1 reinoud for (rel = 0; rel < udf_rw16(context.sparing_table->rt_l); rel++) {
3933 1.1 reinoud sme = &context.sparing_table->entries[rel];
3934 1.1 reinoud if (lb_packet == udf_rw32(sme->org)) {
3935 1.1 reinoud /* NOTE maps to absolute disc logical block! */
3936 1.1 reinoud *lb_numres = udf_rw32(sme->map) + lb_rel;
3937 1.1 reinoud *extres = layout.spareable_blockingnr - lb_rel;
3938 1.1 reinoud return 0;
3939 1.1 reinoud }
3940 1.1 reinoud }
3941 1.1 reinoud
3942 1.1 reinoud /* transform into its disc logical block */
3943 1.1 reinoud if (lb_num > udf_rw32(pdesc->part_len))
3944 1.1 reinoud return EINVAL;
3945 1.1 reinoud *lb_numres = lb_num + udf_rw32(pdesc->start_loc);
3946 1.1 reinoud
3947 1.1 reinoud /* rest of block */
3948 1.1 reinoud *extres = MIN(ext, layout.spareable_blockingnr - lb_rel);
3949 1.1 reinoud return 0;
3950 1.1 reinoud case UDF_VTOP_TYPE_META :
3951 1.1 reinoud /* we have to look into the file's allocation descriptors */
3952 1.1 reinoud
3953 1.1 reinoud /* get first overlapping extent */
3954 1.1 reinoud efe = context.meta_file;
3955 1.1 reinoud dscr_size = sizeof(struct extfile_entry) - 1;
3956 1.1 reinoud l_ea = udf_rw32(efe->l_ea);
3957 1.1 reinoud l_ad = udf_rw32(efe->l_ad);
3958 1.1 reinoud
3959 1.1 reinoud icbflags = udf_rw16(efe->icbtag.flags);
3960 1.1 reinoud addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
3961 1.1 reinoud if (addr_type != UDF_ICB_SHORT_ALLOC) {
3962 1.1 reinoud warnx("specification violation: metafile not using"
3963 1.1 reinoud "short allocs");
3964 1.1 reinoud return EINVAL;
3965 1.1 reinoud }
3966 1.1 reinoud
3967 1.1 reinoud data_pos = (uint8_t *) context.meta_file + dscr_size + l_ea;
3968 1.1 reinoud short_ad = (struct short_ad *) data_pos;
3969 1.1 reinoud lb_offset = 0;
3970 1.1 reinoud while (l_ad > 0) {
3971 1.1 reinoud len = udf_rw32(short_ad->len);
3972 1.1 reinoud start_lb = udf_rw32(short_ad->lb_num);
3973 1.1 reinoud flags = UDF_EXT_FLAGS(len);
3974 1.1 reinoud len = UDF_EXT_LEN(len);
3975 1.1 reinoud if (flags == UDF_EXT_REDIRECT) {
3976 1.1 reinoud warnx("implementation limit: no support for "
3977 1.1 reinoud "extent redirection in metadata file");
3978 1.1 reinoud return EINVAL;
3979 1.1 reinoud }
3980 1.1 reinoud end_lb_offset = lb_offset + len / context.sector_size;
3981 1.1 reinoud /* overlap? */
3982 1.1 reinoud if (end_lb_offset > lb_num)
3983 1.1 reinoud break;
3984 1.1 reinoud short_ad++;
3985 1.1 reinoud lb_offset = end_lb_offset;
3986 1.1 reinoud l_ad -= sizeof(struct short_ad);
3987 1.1 reinoud }
3988 1.1 reinoud if (l_ad <= 0) {
3989 1.1 reinoud warnx("looking up outside metadata partition!");
3990 1.1 reinoud return EINVAL;
3991 1.1 reinoud }
3992 1.1 reinoud lb_num = start_lb + (lb_num - lb_offset);
3993 1.1 reinoud vpart = part;
3994 1.1 reinoud ext = end_lb_offset - lb_num;
3995 1.1 reinoud /*
3996 1.1 reinoud * vpart and lb_num are updated, translate again since we
3997 1.1 reinoud * might be mapped on spareable media
3998 1.1 reinoud */
3999 1.1 reinoud goto translate_again;
4000 1.1 reinoud default:
4001 1.1 reinoud printf("UDF vtop translation scheme %d unimplemented yet\n",
4002 1.1 reinoud context.vtop_tp[vpart]);
4003 1.1 reinoud }
4004 1.1 reinoud
4005 1.1 reinoud return EINVAL;
4006 1.1 reinoud }
4007 1.1 reinoud
4008 1.1 reinoud /* --------------------------------------------------------------------- */
4009 1.1 reinoud
4010 1.1 reinoud int
4011 1.1 reinoud udf_read_phys(void *blob, uint32_t location, uint32_t sects)
4012 1.1 reinoud {
4013 1.1 reinoud uint32_t phys, cnt;
4014 1.1 reinoud uint8_t *bpos;
4015 1.1 reinoud int error;
4016 1.1 reinoud
4017 1.1 reinoud for (cnt = 0; cnt < sects; cnt++) {
4018 1.1 reinoud bpos = (uint8_t *) blob;
4019 1.1 reinoud bpos += context.sector_size * cnt;
4020 1.1 reinoud
4021 1.1 reinoud phys = location + cnt;
4022 1.1 reinoud error = udf_read_sector(bpos, phys);
4023 1.1 reinoud if (error)
4024 1.1 reinoud return error;
4025 1.1 reinoud }
4026 1.1 reinoud return 0;
4027 1.1 reinoud }
4028 1.1 reinoud
4029 1.1 reinoud
4030 1.1 reinoud int
4031 1.1 reinoud udf_write_phys(void *blob, uint32_t location, uint32_t sects)
4032 1.1 reinoud {
4033 1.1 reinoud uint32_t phys, cnt;
4034 1.1 reinoud uint8_t *bpos;
4035 1.1 reinoud int error;
4036 1.1 reinoud
4037 1.1 reinoud for (cnt = 0; cnt < sects; cnt++) {
4038 1.1 reinoud bpos = (uint8_t *) blob;
4039 1.1 reinoud bpos += context.sector_size * cnt;
4040 1.1 reinoud
4041 1.1 reinoud phys = location + cnt;
4042 1.1 reinoud error = udf_write_sector(bpos, phys);
4043 1.1 reinoud if (error)
4044 1.1 reinoud return error;
4045 1.1 reinoud }
4046 1.1 reinoud return 0;
4047 1.1 reinoud }
4048 1.1 reinoud
4049 1.1 reinoud
4050 1.1 reinoud int
4051 1.1 reinoud udf_read_virt(void *blob, uint32_t location, uint16_t vpart,
4052 1.1 reinoud uint32_t sectors)
4053 1.1 reinoud {
4054 1.1 reinoud uint32_t phys, ext;
4055 1.1 reinoud uint8_t *data;
4056 1.1 reinoud int error;
4057 1.1 reinoud
4058 1.1 reinoud /* determine physical location */
4059 1.1 reinoud data = (uint8_t *) blob;
4060 1.1 reinoud while (sectors) {
4061 1.1 reinoud if (udf_translate_vtop(location, vpart, &phys, &ext)) {
4062 1.1 reinoud // warnx("internal error: bad translation");
4063 1.1 reinoud return EINVAL;
4064 1.1 reinoud }
4065 1.1 reinoud ext = MIN(sectors, ext);
4066 1.1 reinoud error = udf_read_phys(data, phys, ext);
4067 1.1 reinoud if (error)
4068 1.1 reinoud return error;
4069 1.1 reinoud location += ext;
4070 1.1 reinoud data += ext * context.sector_size;
4071 1.1 reinoud sectors -= ext;
4072 1.1 reinoud }
4073 1.1 reinoud return 0;
4074 1.1 reinoud }
4075 1.1 reinoud
4076 1.1 reinoud
4077 1.1 reinoud int
4078 1.1 reinoud udf_write_virt(void *blob, uint32_t location, uint16_t vpart,
4079 1.1 reinoud uint32_t sectors)
4080 1.1 reinoud {
4081 1.1 reinoud uint32_t phys, ext, alloc_pos;
4082 1.1 reinoud uint8_t *data;
4083 1.1 reinoud int error;
4084 1.1 reinoud
4085 1.1 reinoud /* determine physical location */
4086 1.1 reinoud if (context.vtop_tp[vpart] == UDF_VTOP_TYPE_VIRT) {
4087 1.1 reinoud assert(sectors == 1);
4088 1.1 reinoud alloc_pos = context.alloc_pos[context.data_part];
4089 1.1 reinoud udf_vat_update(location, alloc_pos);
4090 1.1 reinoud udf_translate_vtop(alloc_pos, context.vtop[vpart], &phys, &ext);
4091 1.1 reinoud context.alloc_pos[context.data_part]++;
4092 1.1 reinoud return udf_write_phys(blob, phys, sectors);
4093 1.1 reinoud }
4094 1.1 reinoud
4095 1.1 reinoud data = (uint8_t *) blob;
4096 1.1 reinoud while (sectors) {
4097 1.1 reinoud if (udf_translate_vtop(location, vpart, &phys, &ext)) {
4098 1.1 reinoud warnx("internal error: bad translation");
4099 1.1 reinoud return EINVAL;
4100 1.1 reinoud }
4101 1.1 reinoud ext = MIN(sectors, ext);
4102 1.1 reinoud error = udf_write_phys(data, phys, ext);
4103 1.1 reinoud if (error)
4104 1.1 reinoud return error;
4105 1.1 reinoud location += ext;
4106 1.1 reinoud data += ext * context.sector_size;
4107 1.1 reinoud sectors -= ext;
4108 1.1 reinoud }
4109 1.1 reinoud return 0;
4110 1.1 reinoud }
4111 1.1 reinoud
4112 1.1 reinoud
4113 1.1 reinoud int
4114 1.1 reinoud udf_read_dscr_phys(uint32_t sector, union dscrptr **dstp)
4115 1.1 reinoud {
4116 1.1 reinoud union dscrptr *dst, *new_dst;
4117 1.1 reinoud uint8_t *pos;
4118 1.1 reinoud uint32_t sectors, dscrlen, sector_size;
4119 1.1 reinoud int error;
4120 1.1 reinoud
4121 1.1 reinoud sector_size = context.sector_size;
4122 1.1 reinoud
4123 1.1 reinoud *dstp = dst = NULL;
4124 1.1 reinoud dscrlen = sector_size;
4125 1.1 reinoud
4126 1.1 reinoud /* read initial piece */
4127 1.1 reinoud dst = malloc(sector_size);
4128 1.1 reinoud assert(dst);
4129 1.1 reinoud error = udf_read_sector(dst, sector);
4130 1.1 reinoud // if (error)
4131 1.1 reinoud // warn("read error");
4132 1.1 reinoud
4133 1.1 reinoud if (!error) {
4134 1.1 reinoud /* check if its an empty block */
4135 1.1 reinoud if (is_zero(dst, sector_size)) {
4136 1.1 reinoud /* return no error but with no dscrptr */
4137 1.1 reinoud /* dispose first block */
4138 1.1 reinoud free(dst);
4139 1.1 reinoud return 0;
4140 1.1 reinoud }
4141 1.1 reinoud /* check if its a valid tag */
4142 1.1 reinoud error = udf_check_tag(dst);
4143 1.1 reinoud if (error) {
4144 1.1 reinoud free(dst);
4145 1.1 reinoud return 0;
4146 1.1 reinoud }
4147 1.1 reinoud /* calculate descriptor size */
4148 1.1 reinoud dscrlen = udf_tagsize(dst, sector_size);
4149 1.1 reinoud }
4150 1.1 reinoud
4151 1.1 reinoud if (!error && (dscrlen > sector_size)) {
4152 1.1 reinoud /* read the rest of descriptor */
4153 1.1 reinoud
4154 1.1 reinoud new_dst = realloc(dst, dscrlen);
4155 1.1 reinoud if (new_dst == NULL) {
4156 1.1 reinoud free(dst);
4157 1.1 reinoud return ENOMEM;
4158 1.1 reinoud }
4159 1.1 reinoud dst = new_dst;
4160 1.1 reinoud
4161 1.1 reinoud sectors = dscrlen / sector_size;
4162 1.1 reinoud pos = (uint8_t *) dst + sector_size;
4163 1.1 reinoud error = udf_read_phys(pos, sector + 1, sectors-1);
4164 1.1 reinoud if (error)
4165 1.1 reinoud warnx("read error");
4166 1.1 reinoud }
4167 1.1 reinoud if (!error)
4168 1.1 reinoud error = udf_check_tag_payload(dst, dscrlen);
4169 1.1 reinoud if (error && dst) {
4170 1.1 reinoud free(dst);
4171 1.1 reinoud dst = NULL;
4172 1.1 reinoud }
4173 1.1 reinoud *dstp = dst;
4174 1.1 reinoud
4175 1.1 reinoud return error;
4176 1.1 reinoud }
4177 1.1 reinoud
4178 1.1 reinoud
4179 1.1 reinoud int
4180 1.1 reinoud udf_write_dscr_phys(union dscrptr *dscr, uint32_t location,
4181 1.1 reinoud uint32_t sectors)
4182 1.1 reinoud {
4183 1.1 reinoud dscr->tag.tag_loc = udf_rw32(location);
4184 1.1 reinoud (void) udf_validate_tag_and_crc_sums(dscr);
4185 1.1 reinoud
4186 1.1 reinoud assert(sectors == udf_tagsize(dscr, context.sector_size) / context.sector_size);
4187 1.1 reinoud return udf_write_phys(dscr, location, sectors);
4188 1.1 reinoud }
4189 1.1 reinoud
4190 1.1 reinoud
4191 1.1 reinoud int
4192 1.1 reinoud udf_read_dscr_virt(uint32_t sector, uint16_t vpart, union dscrptr **dstp)
4193 1.1 reinoud {
4194 1.1 reinoud union dscrptr *dst, *new_dst;
4195 1.1 reinoud uint8_t *pos;
4196 1.1 reinoud uint32_t sectors, dscrlen, sector_size;
4197 1.1 reinoud int error;
4198 1.1 reinoud
4199 1.1 reinoud sector_size = context.sector_size;
4200 1.1 reinoud
4201 1.1 reinoud *dstp = dst = NULL;
4202 1.1 reinoud dscrlen = sector_size;
4203 1.1 reinoud
4204 1.1 reinoud /* read initial piece */
4205 1.1 reinoud dst = calloc(1, sector_size);
4206 1.1 reinoud assert(dst);
4207 1.1 reinoud error = udf_read_virt(dst, sector, vpart, 1);
4208 1.1 reinoud if (error)
4209 1.1 reinoud return error;
4210 1.1 reinoud
4211 1.1 reinoud if (!error) {
4212 1.1 reinoud /* check if its a valid tag */
4213 1.1 reinoud error = udf_check_tag(dst);
4214 1.1 reinoud if (error) {
4215 1.1 reinoud /* check if its an empty block */
4216 1.1 reinoud if (is_zero(dst, sector_size)) {
4217 1.1 reinoud /* return no error but with no dscrptr */
4218 1.1 reinoud /* dispose first block */
4219 1.1 reinoud free(dst);
4220 1.1 reinoud return 0;
4221 1.1 reinoud }
4222 1.1 reinoud }
4223 1.1 reinoud /* calculate descriptor size */
4224 1.1 reinoud dscrlen = udf_tagsize(dst, sector_size);
4225 1.1 reinoud }
4226 1.1 reinoud
4227 1.1 reinoud if (!error && (dscrlen > sector_size)) {
4228 1.1 reinoud /* read the rest of descriptor */
4229 1.1 reinoud
4230 1.1 reinoud new_dst = realloc(dst, dscrlen);
4231 1.1 reinoud if (new_dst == NULL) {
4232 1.1 reinoud free(dst);
4233 1.1 reinoud return ENOMEM;
4234 1.1 reinoud }
4235 1.1 reinoud dst = new_dst;
4236 1.1 reinoud
4237 1.1 reinoud sectors = dscrlen / sector_size;
4238 1.1 reinoud pos = (uint8_t *) dst + sector_size;
4239 1.1 reinoud error = udf_read_virt(pos, sector + 1, vpart, sectors-1);
4240 1.1 reinoud if (error)
4241 1.1 reinoud warn("read error");
4242 1.1 reinoud }
4243 1.1 reinoud if (!error)
4244 1.1 reinoud error = udf_check_tag_payload(dst, dscrlen);
4245 1.1 reinoud if (error && dst) {
4246 1.1 reinoud free(dst);
4247 1.1 reinoud dst = NULL;
4248 1.1 reinoud }
4249 1.1 reinoud *dstp = dst;
4250 1.1 reinoud
4251 1.1 reinoud return error;
4252 1.1 reinoud }
4253 1.1 reinoud
4254 1.1 reinoud
4255 1.1 reinoud int
4256 1.1 reinoud udf_write_dscr_virt(union dscrptr *dscr, uint32_t location, uint16_t vpart,
4257 1.1 reinoud uint32_t sectors)
4258 1.1 reinoud {
4259 1.1 reinoud struct file_entry *fe;
4260 1.1 reinoud struct extfile_entry *efe;
4261 1.1 reinoud struct extattrhdr_desc *extattrhdr;
4262 1.1 reinoud
4263 1.1 reinoud extattrhdr = NULL;
4264 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
4265 1.1 reinoud fe = (struct file_entry *) dscr;
4266 1.1 reinoud if (udf_rw32(fe->l_ea) > 0)
4267 1.1 reinoud extattrhdr = (struct extattrhdr_desc *) fe->data;
4268 1.1 reinoud }
4269 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
4270 1.1 reinoud efe = (struct extfile_entry *) dscr;
4271 1.1 reinoud if (udf_rw32(efe->l_ea) > 0)
4272 1.1 reinoud extattrhdr = (struct extattrhdr_desc *) efe->data;
4273 1.1 reinoud }
4274 1.1 reinoud if (extattrhdr) {
4275 1.1 reinoud extattrhdr->tag.tag_loc = udf_rw32(location);
4276 1.1 reinoud udf_validate_tag_and_crc_sums((union dscrptr *) extattrhdr);
4277 1.1 reinoud }
4278 1.1 reinoud
4279 1.1 reinoud dscr->tag.tag_loc = udf_rw32(location);
4280 1.1 reinoud udf_validate_tag_and_crc_sums(dscr);
4281 1.1 reinoud
4282 1.1 reinoud assert(sectors >= (udf_tagsize(dscr, context.sector_size) / context.sector_size));
4283 1.1 reinoud return udf_write_virt(dscr, location, vpart, sectors);
4284 1.1 reinoud }
4285 1.1 reinoud
4286 1.1 reinoud
4287 1.1 reinoud int
4288 1.1 reinoud is_zero(void *blob, int size) {
4289 1.1 reinoud uint8_t *p = blob;
4290 1.1 reinoud for (int i = 0; i < size; i++, p++)
4291 1.1 reinoud if (*p)
4292 1.1 reinoud return 0;
4293 1.1 reinoud return 1;
4294 1.1 reinoud }
4295 1.1 reinoud
4296 1.1 reinoud /* --------------------------------------------------------------------- */
4297 1.1 reinoud
4298 1.1 reinoud static void
4299 1.1 reinoud udf_partition_alloc(int nblk, int vpart, struct long_ad *pos)
4300 1.1 reinoud {
4301 1.1 reinoud memset(pos, 0, sizeof(*pos));
4302 1.1 reinoud pos->len = udf_rw32(nblk * context.sector_size);
4303 1.1 reinoud pos->loc.lb_num = udf_rw32(context.alloc_pos[vpart]);
4304 1.1 reinoud pos->loc.part_num = udf_rw16(vpart);
4305 1.1 reinoud
4306 1.1 reinoud udf_mark_allocated(context.alloc_pos[vpart], vpart, nblk);
4307 1.1 reinoud context.alloc_pos[vpart] += nblk;
4308 1.1 reinoud }
4309 1.1 reinoud
4310 1.1 reinoud
4311 1.1 reinoud void
4312 1.1 reinoud udf_metadata_alloc(int nblk, struct long_ad *pos)
4313 1.1 reinoud {
4314 1.1 reinoud udf_partition_alloc(nblk, context.metadata_part, pos);
4315 1.1 reinoud }
4316 1.1 reinoud
4317 1.1 reinoud
4318 1.1 reinoud void
4319 1.1 reinoud udf_data_alloc(int nblk, struct long_ad *pos)
4320 1.1 reinoud {
4321 1.1 reinoud udf_partition_alloc(nblk, context.data_part, pos);
4322 1.1 reinoud }
4323 1.1 reinoud
4324 1.1 reinoud
4325 1.1 reinoud void
4326 1.1 reinoud udf_fids_alloc(int nblk, struct long_ad *pos)
4327 1.1 reinoud {
4328 1.1 reinoud udf_partition_alloc(nblk, context.fids_part, pos);
4329 1.1 reinoud }
4330 1.1 reinoud
4331 1.1 reinoud
4332 1.1 reinoud /* --------------------------------------------------------------------- */
4333 1.1 reinoud
4334 1.1 reinoud /*
4335 1.1 reinoud * udf_derive_format derives the format_flags from the disc's mmc_discinfo.
4336 1.1 reinoud * The resulting flags uniquely define a disc format. Note there are at least
4337 1.1 reinoud * 7 distinct format types defined in UDF.
4338 1.1 reinoud */
4339 1.1 reinoud
4340 1.1 reinoud #define UDF_VERSION(a) \
4341 1.1 reinoud (((a) == 0x102) || ((a) == 0x150) || ((a) == 0x200) || \
4342 1.1 reinoud ((a) == 0x201) || ((a) == 0x250) || ((a) == 0x260))
4343 1.1 reinoud
4344 1.1 reinoud int
4345 1.1 reinoud udf_derive_format(int req_enable, int req_disable)
4346 1.1 reinoud {
4347 1.1 reinoud int format_flags;
4348 1.1 reinoud int media_accesstype;
4349 1.1 reinoud
4350 1.1 reinoud /* disc writability, formatted, appendable */
4351 1.1 reinoud if ((mmc_discinfo.mmc_cur & MMC_CAP_RECORDABLE) == 0) {
4352 1.1 reinoud warnx("can't newfs readonly device");
4353 1.1 reinoud return EROFS;
4354 1.1 reinoud }
4355 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) {
4356 1.1 reinoud /* sequentials need sessions appended */
4357 1.1 reinoud if (mmc_discinfo.disc_state == MMC_STATE_CLOSED) {
4358 1.1 reinoud warnx("can't append session to a closed disc");
4359 1.1 reinoud return EROFS;
4360 1.1 reinoud }
4361 1.1 reinoud if ((mmc_discinfo.disc_state != MMC_STATE_EMPTY) &&
4362 1.1 reinoud !context.create_new_session) {
4363 1.1 reinoud warnx("disc not empty! Use -F to force "
4364 1.1 reinoud "initialisation");
4365 1.1 reinoud return EROFS;
4366 1.1 reinoud }
4367 1.1 reinoud } else {
4368 1.1 reinoud /* check if disc (being) formatted or has been started on */
4369 1.1 reinoud if (mmc_discinfo.disc_state == MMC_STATE_EMPTY) {
4370 1.1 reinoud warnx("disc is not formatted");
4371 1.1 reinoud return EROFS;
4372 1.1 reinoud }
4373 1.1 reinoud }
4374 1.1 reinoud
4375 1.1 reinoud /* determine UDF format */
4376 1.1 reinoud format_flags = 0;
4377 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_REWRITABLE) {
4378 1.1 reinoud /* all rewritable media */
4379 1.1 reinoud format_flags |= FORMAT_REWRITABLE;
4380 1.1 reinoud if (context.min_udf >= 0x0250) {
4381 1.1 reinoud /* standard dictates meta as default */
4382 1.1 reinoud format_flags |= FORMAT_META;
4383 1.1 reinoud }
4384 1.1 reinoud
4385 1.1 reinoud if ((mmc_discinfo.mmc_cur & MMC_CAP_HW_DEFECTFREE) == 0) {
4386 1.1 reinoud /* spareables for defect management */
4387 1.1 reinoud if (context.min_udf >= 0x150)
4388 1.1 reinoud format_flags |= FORMAT_SPAREABLE;
4389 1.1 reinoud }
4390 1.1 reinoud } else {
4391 1.1 reinoud /* all once recordable media */
4392 1.1 reinoud format_flags |= FORMAT_WRITEONCE;
4393 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) {
4394 1.1 reinoud format_flags |= FORMAT_SEQUENTIAL;
4395 1.1 reinoud
4396 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE) {
4397 1.1 reinoud /* logical overwritable */
4398 1.1 reinoud format_flags |= FORMAT_LOW;
4399 1.1 reinoud } else {
4400 1.1 reinoud /* have to use VAT for overwriting */
4401 1.1 reinoud format_flags |= FORMAT_VAT;
4402 1.1 reinoud }
4403 1.1 reinoud } else {
4404 1.1 reinoud /* rare WORM devices, but BluRay has one, strat4096 */
4405 1.1 reinoud format_flags |= FORMAT_WORM;
4406 1.1 reinoud }
4407 1.1 reinoud }
4408 1.1 reinoud
4409 1.1 reinoud /* enable/disable requests */
4410 1.1 reinoud if (req_disable & FORMAT_META) {
4411 1.1 reinoud format_flags &= ~(FORMAT_META | FORMAT_LOW);
4412 1.1 reinoud req_disable &= ~FORMAT_META;
4413 1.1 reinoud }
4414 1.1 reinoud if ((format_flags & FORMAT_VAT) & UDF_512_TRACK)
4415 1.1 reinoud format_flags |= FORMAT_TRACK512;
4416 1.1 reinoud
4417 1.1 reinoud if (req_enable & FORMAT_READONLY) {
4418 1.1 reinoud format_flags |= FORMAT_READONLY;
4419 1.1 reinoud }
4420 1.1 reinoud
4421 1.1 reinoud /* determine partition/media access type */
4422 1.1 reinoud media_accesstype = UDF_ACCESSTYPE_NOT_SPECIFIED;
4423 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_REWRITABLE) {
4424 1.1 reinoud media_accesstype = UDF_ACCESSTYPE_OVERWRITABLE;
4425 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_ERASABLE)
4426 1.1 reinoud media_accesstype = UDF_ACCESSTYPE_REWRITEABLE;
4427 1.1 reinoud } else {
4428 1.1 reinoud /* all once recordable media */
4429 1.1 reinoud media_accesstype = UDF_ACCESSTYPE_WRITE_ONCE;
4430 1.1 reinoud }
4431 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE)
4432 1.1 reinoud media_accesstype = UDF_ACCESSTYPE_PSEUDO_OVERWITE;
4433 1.1 reinoud
4434 1.1 reinoud /* patch up media accesstype */
4435 1.1 reinoud if (req_enable & FORMAT_READONLY) {
4436 1.1 reinoud /* better now */
4437 1.1 reinoud media_accesstype = UDF_ACCESSTYPE_READ_ONLY;
4438 1.1 reinoud }
4439 1.1 reinoud
4440 1.1 reinoud /* adjust minimum version limits */
4441 1.1 reinoud if (format_flags & FORMAT_VAT)
4442 1.1 reinoud context.min_udf = MAX(context.min_udf, 0x0150);
4443 1.1 reinoud if (format_flags & FORMAT_SPAREABLE)
4444 1.1 reinoud context.min_udf = MAX(context.min_udf, 0x0150);
4445 1.1 reinoud if (format_flags & FORMAT_META)
4446 1.1 reinoud context.min_udf = MAX(context.min_udf, 0x0250);
4447 1.1 reinoud if (format_flags & FORMAT_LOW)
4448 1.1 reinoud context.min_udf = MAX(context.min_udf, 0x0260);
4449 1.1 reinoud
4450 1.1 reinoud /* adjust maximum version limits not to tease or break things */
4451 1.1 reinoud if (!(format_flags & (FORMAT_META | FORMAT_LOW | FORMAT_VAT)) &&
4452 1.1 reinoud (context.max_udf > 0x200))
4453 1.1 reinoud context.max_udf = 0x201;
4454 1.1 reinoud
4455 1.1 reinoud if ((format_flags & (FORMAT_VAT | FORMAT_SPAREABLE)) == 0)
4456 1.1 reinoud if (context.max_udf <= 0x150)
4457 1.1 reinoud context.min_udf = 0x102;
4458 1.1 reinoud
4459 1.1 reinoud /* limit Ecma 167 descriptor if possible/needed */
4460 1.1 reinoud context.dscrver = 3;
4461 1.1 reinoud if ((context.min_udf < 0x200) || (context.max_udf < 0x200)) {
4462 1.1 reinoud context.dscrver = 2;
4463 1.1 reinoud context.max_udf = 0x150; /* last version < 0x200 */
4464 1.1 reinoud }
4465 1.1 reinoud
4466 1.1 reinoud /* is it possible ? */
4467 1.1 reinoud if (context.min_udf > context.max_udf) {
4468 1.1 reinoud warnx("initialisation prohibited by specified maximum "
4469 1.1 reinoud "UDF version 0x%04x. Minimum version required 0x%04x",
4470 1.1 reinoud context.max_udf, context.min_udf);
4471 1.1 reinoud return EPERM;
4472 1.1 reinoud }
4473 1.1 reinoud
4474 1.1 reinoud if (!UDF_VERSION(context.min_udf) || !UDF_VERSION(context.max_udf)) {
4475 1.1 reinoud warnx("internal error, invalid min/max udf versionsi in %s",
4476 1.1 reinoud __func__);
4477 1.1 reinoud return EPERM;
4478 1.1 reinoud }
4479 1.1 reinoud context.format_flags = format_flags;
4480 1.1 reinoud context.media_accesstype = media_accesstype;
4481 1.1 reinoud
4482 1.1 reinoud return 0;
4483 1.1 reinoud }
4484 1.1 reinoud
4485 1.1 reinoud #undef UDF_VERSION
4486 1.1 reinoud
4487 1.1 reinoud
4488 1.1 reinoud /* --------------------------------------------------------------------- */
4489 1.1 reinoud
4490 1.1 reinoud int
4491 1.1 reinoud udf_proces_names(void)
4492 1.1 reinoud {
4493 1.1 reinoud struct timeval time_of_day;
4494 1.1 reinoud uint32_t primary_nr;
4495 1.1 reinoud uint64_t volset_nr;
4496 1.1 reinoud
4497 1.1 reinoud if (context.logvol_name == NULL)
4498 1.1 reinoud context.logvol_name = strdup("anonymous");
4499 1.1 reinoud if (context.primary_name == NULL) {
4500 1.1 reinoud if (mmc_discinfo.disc_flags & MMC_DFLAGS_DISCIDVALID) {
4501 1.1 reinoud primary_nr = mmc_discinfo.disc_id;
4502 1.1 reinoud } else {
4503 1.1 reinoud primary_nr = (uint32_t) random();
4504 1.1 reinoud }
4505 1.1 reinoud context.primary_name = calloc(32, 1);
4506 1.1 reinoud sprintf(context.primary_name, "%08"PRIx32, primary_nr);
4507 1.1 reinoud }
4508 1.1 reinoud if (context.volset_name == NULL) {
4509 1.1 reinoud if (mmc_discinfo.disc_flags & MMC_DFLAGS_BARCODEVALID) {
4510 1.1 reinoud volset_nr = mmc_discinfo.disc_barcode;
4511 1.1 reinoud } else {
4512 1.1 reinoud (void)gettimeofday(&time_of_day, NULL);
4513 1.1 reinoud volset_nr = (uint64_t) random();
4514 1.1 reinoud volset_nr |= ((uint64_t) time_of_day.tv_sec) << 32;
4515 1.1 reinoud }
4516 1.1 reinoud context.volset_name = calloc(128,1);
4517 1.1 reinoud sprintf(context.volset_name, "%016"PRIx64, volset_nr);
4518 1.1 reinoud }
4519 1.1 reinoud if (context.fileset_name == NULL)
4520 1.1 reinoud context.fileset_name = strdup("anonymous");
4521 1.1 reinoud
4522 1.1 reinoud /* check passed/created identifiers */
4523 1.1 reinoud if (strlen(context.logvol_name) > 128) {
4524 1.1 reinoud warnx("logical volume name too long");
4525 1.1 reinoud return EINVAL;
4526 1.1 reinoud }
4527 1.1 reinoud if (strlen(context.primary_name) > 32) {
4528 1.1 reinoud warnx("primary volume name too long");
4529 1.1 reinoud return EINVAL;
4530 1.1 reinoud }
4531 1.1 reinoud if (strlen(context.volset_name) > 128) {
4532 1.1 reinoud warnx("volume set name too long");
4533 1.1 reinoud return EINVAL;
4534 1.1 reinoud }
4535 1.1 reinoud if (strlen(context.fileset_name) > 32) {
4536 1.1 reinoud warnx("fileset name too long");
4537 1.1 reinoud return EINVAL;
4538 1.1 reinoud }
4539 1.1 reinoud
4540 1.1 reinoud /* signal all OK */
4541 1.1 reinoud return 0;
4542 1.1 reinoud }
4543 1.1 reinoud
4544 1.1 reinoud /* --------------------------------------------------------------------- */
4545 1.1 reinoud
4546 1.1 reinoud int
4547 1.1 reinoud udf_write_iso9660_vrs(void)
4548 1.1 reinoud {
4549 1.1 reinoud struct vrs_desc *iso9660_vrs_desc;
4550 1.1 reinoud uint32_t pos;
4551 1.1 reinoud int error, cnt, dpos;
4552 1.1 reinoud
4553 1.1 reinoud /* create ISO/Ecma-167 identification descriptors */
4554 1.1 reinoud if ((iso9660_vrs_desc = calloc(1, context.sector_size)) == NULL)
4555 1.1 reinoud return ENOMEM;
4556 1.1 reinoud
4557 1.1 reinoud /*
4558 1.1 reinoud * All UDF formats should have their ISO/Ecma-167 descriptors written
4559 1.1 reinoud * except when not possible due to track reservation in the case of
4560 1.1 reinoud * VAT
4561 1.1 reinoud */
4562 1.1 reinoud if ((context.format_flags & FORMAT_TRACK512) == 0) {
4563 1.1 reinoud dpos = (2048 + context.sector_size - 1) / context.sector_size;
4564 1.1 reinoud
4565 1.1 reinoud /* wipe at least 6 times 2048 byte `sectors' */
4566 1.1 reinoud for (cnt = 0; cnt < 6 *dpos; cnt++) {
4567 1.1 reinoud pos = layout.iso9660_vrs + cnt;
4568 1.1 reinoud if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
4569 1.1 reinoud free(iso9660_vrs_desc);
4570 1.1 reinoud return error;
4571 1.1 reinoud }
4572 1.1 reinoud }
4573 1.1 reinoud
4574 1.1 reinoud /* common VRS fields in all written out ISO descriptors */
4575 1.1 reinoud iso9660_vrs_desc->struct_type = 0;
4576 1.1 reinoud iso9660_vrs_desc->version = 1;
4577 1.1 reinoud pos = layout.iso9660_vrs;
4578 1.1 reinoud
4579 1.1 reinoud /* BEA01, NSR[23], TEA01 */
4580 1.1 reinoud memcpy(iso9660_vrs_desc->identifier, "BEA01", 5);
4581 1.1 reinoud if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
4582 1.1 reinoud free(iso9660_vrs_desc);
4583 1.1 reinoud return error;
4584 1.1 reinoud }
4585 1.1 reinoud pos += dpos;
4586 1.1 reinoud
4587 1.1 reinoud if (context.dscrver == 2)
4588 1.1 reinoud memcpy(iso9660_vrs_desc->identifier, "NSR02", 5);
4589 1.1 reinoud else
4590 1.1 reinoud memcpy(iso9660_vrs_desc->identifier, "NSR03", 5);
4591 1.1 reinoud ;
4592 1.1 reinoud if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
4593 1.1 reinoud free(iso9660_vrs_desc);
4594 1.1 reinoud return error;
4595 1.1 reinoud }
4596 1.1 reinoud pos += dpos;
4597 1.1 reinoud
4598 1.1 reinoud memcpy(iso9660_vrs_desc->identifier, "TEA01", 5);
4599 1.1 reinoud if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
4600 1.1 reinoud free(iso9660_vrs_desc);
4601 1.1 reinoud return error;
4602 1.1 reinoud }
4603 1.1 reinoud }
4604 1.1 reinoud
4605 1.1 reinoud free(iso9660_vrs_desc);
4606 1.1 reinoud /* return success */
4607 1.1 reinoud return 0;
4608 1.1 reinoud }
4609 1.1 reinoud
4610 1.1 reinoud
4611 1.1 reinoud /* --------------------------------------------------------------------- */
4612 1.1 reinoud
4613 1.1 reinoud int
4614 1.1 reinoud udf_get_blockingnr(struct mmc_trackinfo *ti)
4615 1.1 reinoud {
4616 1.1 reinoud int blockingnr;
4617 1.1 reinoud
4618 1.1 reinoud /* determine blockingnr */
4619 1.1 reinoud blockingnr = ti->packet_size;
4620 1.1 reinoud if (blockingnr <= 1) {
4621 1.1 reinoud /* paranoia on blockingnr */
4622 1.1 reinoud switch (mmc_discinfo.mmc_profile) {
4623 1.1 reinoud case 0x01 : /* DISC */
4624 1.1 reinoud blockingnr = 64;
4625 1.1 reinoud break;
4626 1.1 reinoud case 0x08 : /* CDROM */
4627 1.1 reinoud case 0x09 : /* CD-R */
4628 1.1 reinoud case 0x0a : /* CD-RW */
4629 1.1 reinoud blockingnr = 32; /* UDF requirement */
4630 1.1 reinoud break;
4631 1.1 reinoud case 0x10 : /* DVDROM */
4632 1.1 reinoud case 0x11 : /* DVD-R (DL) */
4633 1.1 reinoud case 0x12 : /* DVD-RAM */
4634 1.1 reinoud case 0x1b : /* DVD+R */
4635 1.1 reinoud case 0x2b : /* DVD+R Dual layer */
4636 1.1 reinoud case 0x13 : /* DVD-RW restricted overwrite */
4637 1.1 reinoud case 0x14 : /* DVD-RW sequential */
4638 1.1 reinoud case 0x1a : /* DVD+RW */
4639 1.1 reinoud blockingnr = 16; /* SCSI definition */
4640 1.1 reinoud break;
4641 1.1 reinoud case 0x40 : /* BDROM */
4642 1.1 reinoud case 0x41 : /* BD-R Sequential recording (SRM) */
4643 1.1 reinoud case 0x42 : /* BD-R Random recording (RRM) */
4644 1.1 reinoud case 0x43 : /* BD-RE */
4645 1.1 reinoud case 0x51 : /* HD DVD-R */
4646 1.1 reinoud case 0x52 : /* HD DVD-RW */
4647 1.1 reinoud blockingnr = 32; /* SCSI definition */
4648 1.1 reinoud break;
4649 1.1 reinoud default:
4650 1.1 reinoud break;
4651 1.1 reinoud }
4652 1.1 reinoud }
4653 1.1 reinoud return blockingnr;
4654 1.1 reinoud }
4655 1.1 reinoud
4656 1.1 reinoud
4657 1.1 reinoud int
4658 1.1 reinoud udf_spareable_blocks(void)
4659 1.1 reinoud {
4660 1.1 reinoud if (mmc_discinfo.mmc_class == MMC_CLASS_CD) {
4661 1.1 reinoud /* not too much for CD-RW, still 20MiB */
4662 1.1 reinoud return 32;
4663 1.1 reinoud } else {
4664 1.1 reinoud /* take a value for DVD*RW mainly, BD is `defect free' */
4665 1.1 reinoud return 512;
4666 1.1 reinoud }
4667 1.1 reinoud }
4668 1.1 reinoud
4669 1.1 reinoud
4670 1.1 reinoud int
4671 1.1 reinoud udf_spareable_blockingnr(void)
4672 1.1 reinoud {
4673 1.1 reinoud struct mmc_trackinfo ti;
4674 1.1 reinoud int spareable_blockingnr;
4675 1.1 reinoud int error;
4676 1.1 reinoud
4677 1.1 reinoud /* determine span/size */
4678 1.1 reinoud ti.tracknr = mmc_discinfo.first_track_last_session;
4679 1.1 reinoud error = udf_update_trackinfo(&ti);
4680 1.1 reinoud spareable_blockingnr = udf_get_blockingnr(&ti);
4681 1.1 reinoud if (error)
4682 1.1 reinoud spareable_blockingnr = 32;
4683 1.1 reinoud
4684 1.1 reinoud /*
4685 1.1 reinoud * Note that for (bug) compatibility with version UDF 2.00
4686 1.1 reinoud * (fixed in 2.01 and higher) the blocking size needs to be 32
4687 1.1 reinoud * sectors otherwise the drive's blockingnr.
4688 1.1 reinoud */
4689 1.1 reinoud if (context.min_udf <= 0x200)
4690 1.1 reinoud spareable_blockingnr = 32;
4691 1.1 reinoud return spareable_blockingnr;
4692 1.1 reinoud }
4693 1.1 reinoud
4694 1.1 reinoud
4695 1.1 reinoud /*
4696 1.1 reinoud * Main function that creates and writes out disc contents based on the
4697 1.1 reinoud * format_flags's that uniquely define the type of disc to create.
4698 1.1 reinoud */
4699 1.1 reinoud
4700 1.1 reinoud int
4701 1.1 reinoud udf_do_newfs_prefix(void)
4702 1.1 reinoud {
4703 1.1 reinoud union dscrptr *zero_dscr;
4704 1.1 reinoud union dscrptr *dscr;
4705 1.1 reinoud struct mmc_trackinfo ti;
4706 1.1 reinoud uint32_t blockingnr;
4707 1.1 reinoud uint32_t cnt, loc, len;
4708 1.1 reinoud int sectcopy;
4709 1.1 reinoud int error, integrity_type;
4710 1.1 reinoud int data_part, metadata_part;
4711 1.1 reinoud int format_flags;
4712 1.1 reinoud
4713 1.1 reinoud /* init */
4714 1.1 reinoud format_flags = context.format_flags;
4715 1.1 reinoud
4716 1.1 reinoud /* determine span/size */
4717 1.1 reinoud ti.tracknr = mmc_discinfo.first_track_last_session;
4718 1.1 reinoud error = udf_update_trackinfo(&ti);
4719 1.1 reinoud if (error)
4720 1.1 reinoud return error;
4721 1.1 reinoud
4722 1.1 reinoud if (mmc_discinfo.sector_size > context.sector_size) {
4723 1.1 reinoud warnx("impossible to format: "
4724 1.1 reinoud "sector size %d too small for media sector size %d",
4725 1.1 reinoud context.sector_size, mmc_discinfo.sector_size);
4726 1.1 reinoud return EIO;
4727 1.1 reinoud }
4728 1.1 reinoud
4729 1.1 reinoud /* determine blockingnr */
4730 1.1 reinoud blockingnr = udf_get_blockingnr(&ti);
4731 1.1 reinoud if (blockingnr <= 0) {
4732 1.1 reinoud warnx("can't fixup blockingnumber for device "
4733 1.1 reinoud "type %d", mmc_discinfo.mmc_profile);
4734 1.1 reinoud warnx("device is not returning valid blocking"
4735 1.1 reinoud " number and media type is unknown");
4736 1.1 reinoud return EINVAL;
4737 1.1 reinoud }
4738 1.1 reinoud
4739 1.1 reinoud wrtrack_skew = 0;
4740 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL)
4741 1.1 reinoud wrtrack_skew = ti.next_writable % blockingnr;
4742 1.1 reinoud
4743 1.1 reinoud /* get layout */
4744 1.1 reinoud error = udf_calculate_disc_layout(context.min_udf,
4745 1.1 reinoud ti.track_start, mmc_discinfo.last_possible_lba,
4746 1.1 reinoud context.sector_size, blockingnr);
4747 1.1 reinoud
4748 1.1 reinoud /* cache partition for we need it often */
4749 1.1 reinoud data_part = context.data_part;
4750 1.1 reinoud metadata_part = context.metadata_part;
4751 1.1 reinoud
4752 1.1 reinoud /* Create sparing table descriptor if applicable */
4753 1.1 reinoud if (format_flags & FORMAT_SPAREABLE) {
4754 1.1 reinoud if ((error = udf_create_sparing_tabled()))
4755 1.1 reinoud return error;
4756 1.1 reinoud
4757 1.1 reinoud if (context.check_surface) {
4758 1.1 reinoud if ((error = udf_surface_check()))
4759 1.1 reinoud return error;
4760 1.1 reinoud }
4761 1.1 reinoud }
4762 1.1 reinoud
4763 1.1 reinoud /* Create a generic terminator descriptor (later reused) */
4764 1.1 reinoud terminator_dscr = calloc(1, context.sector_size);
4765 1.1 reinoud if (terminator_dscr == NULL)
4766 1.1 reinoud return ENOMEM;
4767 1.1 reinoud udf_create_terminator(terminator_dscr, 0);
4768 1.1 reinoud
4769 1.2 riastrad /*
4770 1.1 reinoud * Create the two Volume Descriptor Sets (VDS) each containing the
4771 1.1 reinoud * following descriptors : primary volume, partition space,
4772 1.1 reinoud * unallocated space, logical volume, implementation use and the
4773 1.1 reinoud * terminator
4774 1.1 reinoud */
4775 1.1 reinoud
4776 1.1 reinoud /* start of volume recognition sequence building */
4777 1.1 reinoud context.vds_seq = 0;
4778 1.1 reinoud
4779 1.1 reinoud /* Create primary volume descriptor */
4780 1.1 reinoud if ((error = udf_create_primaryd()))
4781 1.1 reinoud return error;
4782 1.1 reinoud
4783 1.1 reinoud /* Create partition descriptor */
4784 1.1 reinoud if ((error = udf_create_partitiond(context.data_part)))
4785 1.1 reinoud return error;
4786 1.1 reinoud
4787 1.1 reinoud /* Create unallocated space descriptor */
4788 1.1 reinoud if ((error = udf_create_unalloc_spaced()))
4789 1.1 reinoud return error;
4790 1.1 reinoud
4791 1.1 reinoud /* Create logical volume descriptor */
4792 1.1 reinoud if ((error = udf_create_logical_dscr()))
4793 1.1 reinoud return error;
4794 1.1 reinoud
4795 1.1 reinoud /* Create implementation use descriptor */
4796 1.1 reinoud /* TODO input of fields 1,2,3 and passing them */
4797 1.1 reinoud if ((error = udf_create_impvold(NULL, NULL, NULL)))
4798 1.1 reinoud return error;
4799 1.1 reinoud
4800 1.1 reinoud /* Create anchors */
4801 1.1 reinoud for (cnt = 0; cnt < 3; cnt++) {
4802 1.1 reinoud if ((error = udf_create_anchor(cnt))) {
4803 1.1 reinoud return error;
4804 1.1 reinoud }
4805 1.1 reinoud }
4806 1.1 reinoud
4807 1.1 reinoud /*
4808 1.1 reinoud * Write out what we've created so far.
4809 1.1 reinoud *
4810 1.1 reinoud * Start with wipeout of VRS1 upto start of partition. This allows
4811 1.2 riastrad * formatting for sequentials with the track reservation and it
4812 1.1 reinoud * cleans old rubbish on rewritables. For sequentials without the
4813 1.1 reinoud * track reservation all is wiped from track start.
4814 1.1 reinoud */
4815 1.1 reinoud if ((zero_dscr = calloc(1, context.sector_size)) == NULL)
4816 1.1 reinoud return ENOMEM;
4817 1.1 reinoud
4818 1.1 reinoud loc = (format_flags & FORMAT_TRACK512) ? layout.vds1 : ti.track_start;
4819 1.1 reinoud for (; loc < layout.part_start_lba; loc++) {
4820 1.1 reinoud if ((error = udf_write_sector(zero_dscr, loc))) {
4821 1.1 reinoud free(zero_dscr);
4822 1.1 reinoud return error;
4823 1.1 reinoud }
4824 1.1 reinoud }
4825 1.1 reinoud free(zero_dscr);
4826 1.1 reinoud
4827 1.1 reinoud /* writeout iso9660 vrs */
4828 1.1 reinoud if ((error = udf_write_iso9660_vrs()))
4829 1.1 reinoud return error;
4830 1.1 reinoud
4831 1.1 reinoud /* Writeout anchors */
4832 1.1 reinoud for (cnt = 0; cnt < 3; cnt++) {
4833 1.1 reinoud dscr = (union dscrptr *) context.anchors[cnt];
4834 1.1 reinoud loc = layout.anchors[cnt];
4835 1.1 reinoud if ((error = udf_write_dscr_phys(dscr, loc, 1))) {
4836 1.1 reinoud err(1, "ERR!");
4837 1.1 reinoud return error;
4838 1.1 reinoud }
4839 1.1 reinoud
4840 1.1 reinoud /* sequential media has only one anchor */
4841 1.1 reinoud if (format_flags & FORMAT_SEQUENTIAL)
4842 1.1 reinoud break;
4843 1.1 reinoud }
4844 1.1 reinoud
4845 1.1 reinoud /* write out main and secondary VRS */
4846 1.1 reinoud for (sectcopy = 1; sectcopy <= 2; sectcopy++) {
4847 1.1 reinoud loc = (sectcopy == 1) ? layout.vds1 : layout.vds2;
4848 1.1 reinoud
4849 1.1 reinoud /* primary volume descriptor */
4850 1.1 reinoud dscr = (union dscrptr *) context.primary_vol;
4851 1.1 reinoud error = udf_write_dscr_phys(dscr, loc, 1);
4852 1.1 reinoud if (error)
4853 1.1 reinoud return error;
4854 1.1 reinoud loc++;
4855 1.1 reinoud
4856 1.1 reinoud /* partition descriptor(s) */
4857 1.1 reinoud for (cnt = 0; cnt < UDF_PARTITIONS; cnt++) {
4858 1.1 reinoud dscr = (union dscrptr *) context.partitions[cnt];
4859 1.1 reinoud if (dscr) {
4860 1.1 reinoud error = udf_write_dscr_phys(dscr, loc, 1);
4861 1.1 reinoud if (error)
4862 1.1 reinoud return error;
4863 1.1 reinoud loc++;
4864 1.1 reinoud }
4865 1.1 reinoud }
4866 1.1 reinoud
4867 1.1 reinoud /* unallocated space descriptor */
4868 1.1 reinoud dscr = (union dscrptr *) context.unallocated;
4869 1.1 reinoud error = udf_write_dscr_phys(dscr, loc, 1);
4870 1.1 reinoud if (error)
4871 1.1 reinoud return error;
4872 1.1 reinoud loc++;
4873 1.1 reinoud
4874 1.1 reinoud /* logical volume descriptor */
4875 1.1 reinoud dscr = (union dscrptr *) context.logical_vol;
4876 1.1 reinoud error = udf_write_dscr_phys(dscr, loc, 1);
4877 1.1 reinoud if (error)
4878 1.1 reinoud return error;
4879 1.1 reinoud loc++;
4880 1.1 reinoud
4881 1.1 reinoud /* implementation use descriptor */
4882 1.1 reinoud dscr = (union dscrptr *) context.implementation;
4883 1.1 reinoud error = udf_write_dscr_phys(dscr, loc, 1);
4884 1.1 reinoud if (error)
4885 1.1 reinoud return error;
4886 1.1 reinoud loc++;
4887 1.1 reinoud
4888 1.1 reinoud /* terminator descriptor */
4889 1.1 reinoud error = udf_write_dscr_phys(terminator_dscr, loc, 1);
4890 1.1 reinoud if (error)
4891 1.1 reinoud return error;
4892 1.1 reinoud loc++;
4893 1.1 reinoud }
4894 1.1 reinoud
4895 1.1 reinoud /* writeout the two spareable table descriptors (if needed) */
4896 1.1 reinoud if (format_flags & FORMAT_SPAREABLE) {
4897 1.1 reinoud for (sectcopy = 1; sectcopy <= 2; sectcopy++) {
4898 1.1 reinoud loc = (sectcopy == 1) ? layout.spt_1 : layout.spt_2;
4899 1.1 reinoud dscr = (union dscrptr *) context.sparing_table;
4900 1.1 reinoud len = udf_tagsize(dscr, context.sector_size) /
4901 1.1 reinoud context.sector_size;
4902 1.1 reinoud
4903 1.1 reinoud /* writeout */
4904 1.1 reinoud error = udf_write_dscr_phys(dscr, loc, len);
4905 1.1 reinoud if (error)
4906 1.1 reinoud return error;
4907 1.1 reinoud }
4908 1.1 reinoud }
4909 1.1 reinoud
4910 1.1 reinoud /*
4911 1.1 reinoud * Create unallocated space bitmap descriptor. Sequential recorded
4912 1.1 reinoud * media report their own free/used space; no free/used space tables
4913 1.1 reinoud * should be recorded for these.
4914 1.1 reinoud */
4915 1.1 reinoud if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) {
4916 1.1 reinoud error = udf_create_space_bitmap(
4917 1.1 reinoud layout.alloc_bitmap_dscr_size,
4918 1.1 reinoud layout.part_size_lba,
4919 1.1 reinoud &context.part_unalloc_bits[data_part]);
4920 1.1 reinoud if (error)
4921 1.1 reinoud return error;
4922 1.1 reinoud /* TODO: freed space bitmap if applicable */
4923 1.1 reinoud
4924 1.1 reinoud /* mark space allocated for the unallocated space bitmap */
4925 1.1 reinoud udf_mark_allocated(layout.unalloc_space, data_part,
4926 1.1 reinoud layout.alloc_bitmap_dscr_size);
4927 1.1 reinoud }
4928 1.1 reinoud
4929 1.1 reinoud /*
4930 1.1 reinoud * Create metadata partition file entries and allocate and init their
4931 1.1 reinoud * space and free space maps.
4932 1.1 reinoud */
4933 1.1 reinoud if (format_flags & FORMAT_META) {
4934 1.1 reinoud error = udf_create_meta_files();
4935 1.1 reinoud if (error)
4936 1.1 reinoud return error;
4937 1.1 reinoud
4938 1.1 reinoud /* mark space allocated for meta partition and its bitmap */
4939 1.1 reinoud udf_mark_allocated(layout.meta_file, data_part, 1);
4940 1.1 reinoud udf_mark_allocated(layout.meta_mirror, data_part, 1);
4941 1.1 reinoud udf_mark_allocated(layout.meta_part_start_lba, data_part,
4942 1.1 reinoud layout.meta_part_size_lba);
4943 1.1 reinoud
4944 1.1 reinoud if (context.meta_bitmap) {
4945 1.1 reinoud /* metadata bitmap creation and accounting */
4946 1.1 reinoud error = udf_create_space_bitmap(
4947 1.1 reinoud layout.meta_bitmap_dscr_size,
4948 1.1 reinoud layout.meta_part_size_lba,
4949 1.1 reinoud &context.part_unalloc_bits[metadata_part]);
4950 1.1 reinoud if (error)
4951 1.1 reinoud return error;
4952 1.2 riastrad
4953 1.1 reinoud udf_mark_allocated(layout.meta_bitmap, data_part, 1);
4954 1.1 reinoud /* mark space allocated for the unallocated space bitmap */
4955 1.1 reinoud udf_mark_allocated(layout.meta_bitmap_space,
4956 1.1 reinoud data_part,
4957 1.1 reinoud layout.meta_bitmap_dscr_size);
4958 1.1 reinoud }
4959 1.1 reinoud }
4960 1.1 reinoud
4961 1.1 reinoud /* create logical volume integrity descriptor */
4962 1.1 reinoud context.num_files = 0;
4963 1.1 reinoud context.num_directories = 0;
4964 1.1 reinoud integrity_type = UDF_INTEGRITY_OPEN;
4965 1.1 reinoud if ((error = udf_create_lvintd(integrity_type)))
4966 1.1 reinoud return error;
4967 1.1 reinoud
4968 1.1 reinoud /* writeout initial open integrity sequence + terminator */
4969 1.1 reinoud loc = layout.lvis;
4970 1.1 reinoud dscr = (union dscrptr *) context.logvol_integrity;
4971 1.1 reinoud error = udf_write_dscr_phys(dscr, loc, 1);
4972 1.1 reinoud if (error)
4973 1.1 reinoud return error;
4974 1.1 reinoud loc++;
4975 1.1 reinoud error = udf_write_dscr_phys(terminator_dscr, loc, 1);
4976 1.1 reinoud if (error)
4977 1.1 reinoud return error;
4978 1.1 reinoud
4979 1.1 reinoud /* create VAT if needed */
4980 1.1 reinoud if (format_flags & FORMAT_VAT) {
4981 1.1 reinoud context.vat_allocated = context.sector_size;
4982 1.1 reinoud context.vat_contents = malloc(context.vat_allocated);
4983 1.1 reinoud assert(context.vat_contents);
4984 1.1 reinoud
4985 1.1 reinoud udf_prepend_VAT_file();
4986 1.1 reinoud }
4987 1.1 reinoud
4988 1.1 reinoud /* create FSD and writeout */
4989 1.1 reinoud if ((error = udf_create_fsd()))
4990 1.1 reinoud return error;
4991 1.1 reinoud udf_mark_allocated(layout.fsd, metadata_part, 1);
4992 1.1 reinoud
4993 1.1 reinoud dscr = (union dscrptr *) context.fileset_desc;
4994 1.1 reinoud error = udf_write_dscr_virt(dscr, layout.fsd, metadata_part, 1);
4995 1.1 reinoud
4996 1.1 reinoud return error;
4997 1.1 reinoud }
4998 1.1 reinoud
4999 1.1 reinoud
5000 1.1 reinoud /* specific routine for newfs to create empty rootdirectory */
5001 1.1 reinoud int
5002 1.1 reinoud udf_do_rootdir(void)
5003 1.1 reinoud {
5004 1.1 reinoud union dscrptr *root_dscr;
5005 1.1 reinoud int error;
5006 1.1 reinoud
5007 1.1 reinoud /* create root directory and write out */
5008 1.1 reinoud assert(context.unique_id == 0x10);
5009 1.1 reinoud context.unique_id = 0;
5010 1.1 reinoud if ((error = udf_create_new_rootdir(&root_dscr)))
5011 1.1 reinoud return error;
5012 1.1 reinoud udf_mark_allocated(layout.rootdir, context.metadata_part, 1);
5013 1.1 reinoud
5014 1.1 reinoud error = udf_write_dscr_virt(root_dscr,
5015 1.1 reinoud layout.rootdir, context.metadata_part, 1);
5016 1.1 reinoud
5017 1.1 reinoud free(root_dscr);
5018 1.1 reinoud
5019 1.1 reinoud return error;
5020 1.1 reinoud }
5021 1.1 reinoud
5022 1.1 reinoud
5023 1.1 reinoud int
5024 1.1 reinoud udf_do_newfs_postfix(void)
5025 1.1 reinoud {
5026 1.1 reinoud union dscrptr *dscr;
5027 1.1 reinoud uint32_t loc, len;
5028 1.1 reinoud int data_part, metadata_part;
5029 1.1 reinoud int format_flags = context.format_flags;
5030 1.1 reinoud int error;
5031 1.1 reinoud
5032 1.1 reinoud /* cache partition for we need it often */
5033 1.1 reinoud data_part = context.data_part;
5034 1.1 reinoud metadata_part = context.metadata_part;
5035 1.1 reinoud
5036 1.1 reinoud if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
5037 1.1 reinoud /* update lvint and mark it closed */
5038 1.1 reinoud udf_update_lvintd(UDF_INTEGRITY_CLOSED);
5039 1.1 reinoud
5040 1.1 reinoud /* overwrite initial terminator */
5041 1.1 reinoud loc = layout.lvis+1;
5042 1.1 reinoud dscr = (union dscrptr *) context.logvol_integrity;
5043 1.1 reinoud error = udf_write_dscr_phys(dscr, loc, 1);
5044 1.1 reinoud if (error)
5045 1.1 reinoud return error;
5046 1.1 reinoud loc++;
5047 1.1 reinoud
5048 1.1 reinoud /* mark end of integrity descriptor sequence again */
5049 1.1 reinoud error = udf_write_dscr_phys(terminator_dscr, loc, 1);
5050 1.1 reinoud if (error)
5051 1.1 reinoud return error;
5052 1.1 reinoud }
5053 1.1 reinoud
5054 1.1 reinoud /* write out unallocated space bitmap on non sequential media */
5055 1.1 reinoud if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) {
5056 1.1 reinoud /* writeout unallocated space bitmap */
5057 1.1 reinoud loc = layout.unalloc_space;
5058 1.1 reinoud dscr = (union dscrptr *) (context.part_unalloc_bits[data_part]);
5059 1.1 reinoud len = layout.alloc_bitmap_dscr_size;
5060 1.1 reinoud error = udf_write_dscr_virt(dscr, loc, data_part, len);
5061 1.1 reinoud if (error)
5062 1.1 reinoud return error;
5063 1.1 reinoud }
5064 1.1 reinoud
5065 1.1 reinoud if (format_flags & FORMAT_META) {
5066 1.1 reinoud loc = layout.meta_file;
5067 1.1 reinoud dscr = (union dscrptr *) context.meta_file;
5068 1.1 reinoud error = udf_write_dscr_virt(dscr, loc, data_part, 1);
5069 1.1 reinoud if (error)
5070 1.1 reinoud return error;
5071 1.2 riastrad
5072 1.1 reinoud loc = layout.meta_mirror;
5073 1.1 reinoud dscr = (union dscrptr *) context.meta_mirror;
5074 1.1 reinoud error = udf_write_dscr_virt(dscr, loc, data_part, 1);
5075 1.1 reinoud if (error)
5076 1.1 reinoud return error;
5077 1.1 reinoud
5078 1.1 reinoud if (context.meta_bitmap) {
5079 1.1 reinoud loc = layout.meta_bitmap;
5080 1.1 reinoud dscr = (union dscrptr *) context.meta_bitmap;
5081 1.1 reinoud error = udf_write_dscr_virt(dscr, loc, data_part, 1);
5082 1.1 reinoud if (error)
5083 1.1 reinoud return error;
5084 1.1 reinoud
5085 1.1 reinoud /* writeout unallocated space bitmap */
5086 1.1 reinoud loc = layout.meta_bitmap_space;
5087 1.1 reinoud dscr = (union dscrptr *)
5088 1.1 reinoud (context.part_unalloc_bits[metadata_part]);
5089 1.1 reinoud len = layout.meta_bitmap_dscr_size;
5090 1.1 reinoud error = udf_write_dscr_virt(dscr, loc, data_part, len);
5091 1.1 reinoud if (error)
5092 1.1 reinoud return error;
5093 1.1 reinoud }
5094 1.1 reinoud }
5095 1.1 reinoud
5096 1.1 reinoud /* create and writeout a VAT */
5097 1.1 reinoud if (format_flags & FORMAT_VAT)
5098 1.1 reinoud udf_writeout_VAT();
5099 1.1 reinoud
5100 1.1 reinoud /* done */
5101 1.1 reinoud return 0;
5102 1.1 reinoud }
5103