1 1.14 andvar /* $NetBSD: udf_core.c,v 1.14 2024/02/05 21:46:05 andvar 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.14 andvar __RCSID("$NetBSD: udf_core.c,v 1.14 2024/02/05 21:46:05 andvar 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.14 andvar if (tz & 0x0800) /* sign extension */ 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.5 reinoud lvd->lv_fsd_loc.loc.part_num = udf_rw16(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.12 andvar /* if we are already 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.12 andvar /* apparently 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.4 reinoud if (udf_rw32(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.4 reinoud if (udf_rw32(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.11 andvar * Always use strategy type 4 unless on WORM which 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.7 reinoud fe->perm = udf_rw32(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.11 andvar * Always use strategy type 4 unless on WORM which 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.7 reinoud efe->perm = udf_rw32(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.6 reinoud vatlvext->unique_id_chk = 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.8 reinoud fe->logblks_rec = udf_rw64(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.8 reinoud efe->logblks_rec = udf_rw64(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.9 reinoud fe->logblks_rec = udf_rw64(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.13 andvar * mmc_discinfo and mmc_trackinfo readers modified from original 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.10 reinoud int32_t wsects; 3786 1.1 reinoud uint64_t present, all_present = -1; 3787 1.1 reinoud uint64_t rpos, wpos; 3788 1.1 reinoud static int t = 0; 3789 1.1 reinoud 3790 1.1 reinoud if (write_queuelen == 0) 3791 1.1 reinoud return 0; 3792 1.1 reinoud 3793 1.1 reinoud if (blockingnr < 64) 3794 1.1 reinoud all_present = ((uint64_t) 1 << blockingnr) -1; 3795 1.1 reinoud linesize = blockingnr * context.sector_size; 3796 1.1 reinoud linebuf = calloc(1, linesize); 3797 1.1 reinoud assert(linebuf); 3798 1.1 reinoud 3799 1.1 reinoud /* fill in blanks if needed */ 3800 1.1 reinoud if (complete && (context.write_strategy != UDF_WRITE_SEQUENTIAL)) { 3801 1.1 reinoud TAILQ_FOREACH(packet, &write_queue, next) { 3802 1.1 reinoud present = packet->present; 3803 1.1 reinoud if (present != all_present) { 3804 1.1 reinoud printf("%c", "\\|/-"[t++ % 4]); fflush(stdout);fflush(stderr); 3805 1.1 reinoud //printf("%16lu : readin %08lx\n", packet->start_sectornr, packet->present ^ all_present); 3806 1.1 reinoud rpos = (uint64_t) packet->start_sectornr * context.sector_size; 3807 1.1 reinoud ret = pread(dev_fd, linebuf, linesize, rpos); 3808 1.1 reinoud if (ret == -1) { 3809 1.1 reinoud printf("\b"); 3810 1.1 reinoud warn("error reading in blanks, " 3811 1.1 reinoud "could indicate bad disc"); 3812 1.1 reinoud printf(" "); 3813 1.1 reinoud } 3814 1.1 reinoud for (int i = 0; i < blockingnr; i++) { 3815 1.1 reinoud //printf("present %08lx, testing bit %08lx, value %08lx\n", present, ((uint64_t) 1 << i), (present & ((uint64_t) 1 << i))); 3816 1.1 reinoud if ((present & ((uint64_t) 1 << i)) > 0) 3817 1.1 reinoud continue; 3818 1.1 reinoud //printf("NOT PRESENT\n"); 3819 1.1 reinoud offset = i * context.sector_size; 3820 1.1 reinoud memcpy(packet->packet_data + offset, 3821 1.1 reinoud linebuf + offset, 3822 1.1 reinoud context.sector_size); 3823 1.1 reinoud packet->present |= ((uint64_t) 1<<i); 3824 1.1 reinoud } 3825 1.1 reinoud printf("\b"); 3826 1.1 reinoud } 3827 1.1 reinoud assert(packet->present == all_present); 3828 1.1 reinoud } 3829 1.1 reinoud } 3830 1.1 reinoud 3831 1.1 reinoud /* writeout */ 3832 1.1 reinoud TAILQ_FOREACH(packet, &write_queue, next) { 3833 1.1 reinoud if (complete || (packet->present == all_present)) { 3834 1.1 reinoud printf("%c", "\\|/-"[t++ % 4]); fflush(stdout);fflush(stderr); 3835 1.1 reinoud //printf("write %lu + %d\n", packet->start_sectornr, linesize / context.sector_size); 3836 1.10 reinoud 3837 1.10 reinoud /* don't write past last possible lba */ 3838 1.10 reinoud wsects = (mmc_discinfo.last_possible_lba + 1 - packet->start_sectornr); 3839 1.10 reinoud assert(wsects >= 0); 3840 1.10 reinoud wsects = MIN(wsects, blockingnr); 3841 1.10 reinoud 3842 1.1 reinoud wpos = (uint64_t) packet->start_sectornr * context.sector_size; 3843 1.10 reinoud ret = pwrite(dev_fd, 3844 1.10 reinoud packet->packet_data, 3845 1.10 reinoud wsects * context.sector_size, 3846 1.10 reinoud wpos); 3847 1.1 reinoud printf("\b"); 3848 1.1 reinoud if (ret == -1) 3849 1.1 reinoud warn("error writing packet, " 3850 1.1 reinoud "could indicate bad disc"); 3851 1.1 reinoud } 3852 1.1 reinoud } 3853 1.1 reinoud 3854 1.1 reinoud /* removing completed packets */ 3855 1.1 reinoud TAILQ_FOREACH_SAFE(packet, &write_queue, next, next_packet) { 3856 1.1 reinoud if (complete || (packet->present == all_present)) { 3857 1.1 reinoud TAILQ_REMOVE(&write_queue, packet, next); 3858 1.1 reinoud free(packet->packet_data); 3859 1.1 reinoud free(packet); 3860 1.1 reinoud write_queuelen--; 3861 1.1 reinoud } 3862 1.1 reinoud } 3863 1.1 reinoud if (complete) { 3864 1.1 reinoud assert(TAILQ_EMPTY(&write_queue)); 3865 1.1 reinoud write_queuelen = 0; 3866 1.1 reinoud } 3867 1.1 reinoud 3868 1.1 reinoud free(linebuf); 3869 1.1 reinoud return 0; 3870 1.1 reinoud } 3871 1.1 reinoud 3872 1.1 reinoud 3873 1.1 reinoud /* --------------------------------------------------------------------- */ 3874 1.1 reinoud 3875 1.1 reinoud /* simplified version of kernel routine */ 3876 1.1 reinoud int 3877 1.1 reinoud udf_translate_vtop(uint32_t lb_num, uint16_t vpart, 3878 1.1 reinoud uint32_t *lb_numres, uint32_t *extres) 3879 1.1 reinoud { 3880 1.1 reinoud struct part_desc *pdesc; 3881 1.1 reinoud struct spare_map_entry *sme; 3882 1.1 reinoud struct short_ad *short_ad; 3883 1.1 reinoud struct extfile_entry *efe; 3884 1.1 reinoud uint32_t ext, len, lb_rel, lb_packet, vat_off; 3885 1.1 reinoud uint32_t start_lb, lb_offset, end_lb_offset; 3886 1.1 reinoud uint32_t udf_rw32_lbmap; 3887 1.1 reinoud uint32_t flags; 3888 1.1 reinoud uint8_t *vat_pos, *data_pos; 3889 1.1 reinoud int dscr_size, l_ea, l_ad, icbflags, addr_type; 3890 1.1 reinoud int rel, part; 3891 1.1 reinoud 3892 1.1 reinoud if (vpart > UDF_VTOP_RAWPART) 3893 1.1 reinoud return EINVAL; 3894 1.1 reinoud 3895 1.1 reinoud ext = INT_MAX; 3896 1.1 reinoud translate_again: 3897 1.1 reinoud part = context.vtop[vpart]; 3898 1.1 reinoud pdesc = context.partitions[part]; 3899 1.1 reinoud 3900 1.1 reinoud switch (context.vtop_tp[vpart]) { 3901 1.1 reinoud case UDF_VTOP_TYPE_RAW : 3902 1.1 reinoud /* 1:1 to the end of the device */ 3903 1.1 reinoud *lb_numres = lb_num; 3904 1.1 reinoud *extres = MIN(ext, INT_MAX); 3905 1.1 reinoud return 0; 3906 1.1 reinoud case UDF_VTOP_TYPE_PHYS : 3907 1.1 reinoud /* transform into its disc logical block */ 3908 1.1 reinoud if (lb_num > udf_rw32(pdesc->part_len)) 3909 1.1 reinoud return EINVAL; 3910 1.1 reinoud *lb_numres = lb_num + udf_rw32(pdesc->start_loc); 3911 1.1 reinoud 3912 1.1 reinoud /* extent from here to the end of the partition */ 3913 1.1 reinoud *extres = MIN(ext, udf_rw32(pdesc->part_len) - lb_num); 3914 1.1 reinoud if (*extres == 0) 3915 1.1 reinoud return EINVAL; 3916 1.1 reinoud return 0; 3917 1.1 reinoud case UDF_VTOP_TYPE_VIRT : 3918 1.1 reinoud /* only maps one logical block, lookup in VAT */ 3919 1.1 reinoud if (lb_num * 4 >= context.vat_size) 3920 1.1 reinoud return EINVAL; 3921 1.1 reinoud vat_off = context.vat_start + lb_num * 4; 3922 1.1 reinoud vat_pos = context.vat_contents + vat_off; 3923 1.1 reinoud udf_rw32_lbmap = *((uint32_t *) vat_pos); 3924 1.1 reinoud 3925 1.1 reinoud if (vat_off >= context.vat_size) /* XXX > or >= ? */ 3926 1.1 reinoud return EINVAL; 3927 1.1 reinoud lb_num = udf_rw32(udf_rw32_lbmap); 3928 1.1 reinoud 3929 1.1 reinoud /* transform into its disc logical block */ 3930 1.1 reinoud if (lb_num > udf_rw32(pdesc->part_len)) 3931 1.1 reinoud return EINVAL; 3932 1.1 reinoud *lb_numres = lb_num + udf_rw32(pdesc->start_loc); 3933 1.1 reinoud 3934 1.1 reinoud /* just one logical block */ 3935 1.1 reinoud *extres = 1; 3936 1.1 reinoud return 0; 3937 1.1 reinoud case UDF_VTOP_TYPE_SPAREABLE : 3938 1.1 reinoud /* check if the packet containing the lb_num is remapped */ 3939 1.1 reinoud lb_packet = lb_num / layout.spareable_blockingnr; 3940 1.1 reinoud lb_rel = lb_num % layout.spareable_blockingnr; 3941 1.1 reinoud 3942 1.1 reinoud for (rel = 0; rel < udf_rw16(context.sparing_table->rt_l); rel++) { 3943 1.1 reinoud sme = &context.sparing_table->entries[rel]; 3944 1.1 reinoud if (lb_packet == udf_rw32(sme->org)) { 3945 1.1 reinoud /* NOTE maps to absolute disc logical block! */ 3946 1.1 reinoud *lb_numres = udf_rw32(sme->map) + lb_rel; 3947 1.1 reinoud *extres = layout.spareable_blockingnr - lb_rel; 3948 1.1 reinoud return 0; 3949 1.1 reinoud } 3950 1.1 reinoud } 3951 1.1 reinoud 3952 1.1 reinoud /* transform into its disc logical block */ 3953 1.1 reinoud if (lb_num > udf_rw32(pdesc->part_len)) 3954 1.1 reinoud return EINVAL; 3955 1.1 reinoud *lb_numres = lb_num + udf_rw32(pdesc->start_loc); 3956 1.1 reinoud 3957 1.1 reinoud /* rest of block */ 3958 1.1 reinoud *extres = MIN(ext, layout.spareable_blockingnr - lb_rel); 3959 1.1 reinoud return 0; 3960 1.1 reinoud case UDF_VTOP_TYPE_META : 3961 1.1 reinoud /* we have to look into the file's allocation descriptors */ 3962 1.1 reinoud 3963 1.1 reinoud /* get first overlapping extent */ 3964 1.1 reinoud efe = context.meta_file; 3965 1.1 reinoud dscr_size = sizeof(struct extfile_entry) - 1; 3966 1.1 reinoud l_ea = udf_rw32(efe->l_ea); 3967 1.1 reinoud l_ad = udf_rw32(efe->l_ad); 3968 1.1 reinoud 3969 1.1 reinoud icbflags = udf_rw16(efe->icbtag.flags); 3970 1.1 reinoud addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 3971 1.1 reinoud if (addr_type != UDF_ICB_SHORT_ALLOC) { 3972 1.1 reinoud warnx("specification violation: metafile not using" 3973 1.1 reinoud "short allocs"); 3974 1.1 reinoud return EINVAL; 3975 1.1 reinoud } 3976 1.1 reinoud 3977 1.1 reinoud data_pos = (uint8_t *) context.meta_file + dscr_size + l_ea; 3978 1.1 reinoud short_ad = (struct short_ad *) data_pos; 3979 1.1 reinoud lb_offset = 0; 3980 1.1 reinoud while (l_ad > 0) { 3981 1.1 reinoud len = udf_rw32(short_ad->len); 3982 1.1 reinoud start_lb = udf_rw32(short_ad->lb_num); 3983 1.1 reinoud flags = UDF_EXT_FLAGS(len); 3984 1.1 reinoud len = UDF_EXT_LEN(len); 3985 1.1 reinoud if (flags == UDF_EXT_REDIRECT) { 3986 1.1 reinoud warnx("implementation limit: no support for " 3987 1.1 reinoud "extent redirection in metadata file"); 3988 1.1 reinoud return EINVAL; 3989 1.1 reinoud } 3990 1.1 reinoud end_lb_offset = lb_offset + len / context.sector_size; 3991 1.1 reinoud /* overlap? */ 3992 1.1 reinoud if (end_lb_offset > lb_num) 3993 1.1 reinoud break; 3994 1.1 reinoud short_ad++; 3995 1.1 reinoud lb_offset = end_lb_offset; 3996 1.1 reinoud l_ad -= sizeof(struct short_ad); 3997 1.1 reinoud } 3998 1.1 reinoud if (l_ad <= 0) { 3999 1.1 reinoud warnx("looking up outside metadata partition!"); 4000 1.1 reinoud return EINVAL; 4001 1.1 reinoud } 4002 1.1 reinoud lb_num = start_lb + (lb_num - lb_offset); 4003 1.1 reinoud vpart = part; 4004 1.1 reinoud ext = end_lb_offset - lb_num; 4005 1.1 reinoud /* 4006 1.1 reinoud * vpart and lb_num are updated, translate again since we 4007 1.1 reinoud * might be mapped on spareable media 4008 1.1 reinoud */ 4009 1.1 reinoud goto translate_again; 4010 1.1 reinoud default: 4011 1.1 reinoud printf("UDF vtop translation scheme %d unimplemented yet\n", 4012 1.1 reinoud context.vtop_tp[vpart]); 4013 1.1 reinoud } 4014 1.1 reinoud 4015 1.1 reinoud return EINVAL; 4016 1.1 reinoud } 4017 1.1 reinoud 4018 1.1 reinoud /* --------------------------------------------------------------------- */ 4019 1.1 reinoud 4020 1.1 reinoud int 4021 1.1 reinoud udf_read_phys(void *blob, uint32_t location, uint32_t sects) 4022 1.1 reinoud { 4023 1.1 reinoud uint32_t phys, cnt; 4024 1.1 reinoud uint8_t *bpos; 4025 1.1 reinoud int error; 4026 1.1 reinoud 4027 1.1 reinoud for (cnt = 0; cnt < sects; cnt++) { 4028 1.1 reinoud bpos = (uint8_t *) blob; 4029 1.1 reinoud bpos += context.sector_size * cnt; 4030 1.1 reinoud 4031 1.1 reinoud phys = location + cnt; 4032 1.1 reinoud error = udf_read_sector(bpos, phys); 4033 1.1 reinoud if (error) 4034 1.1 reinoud return error; 4035 1.1 reinoud } 4036 1.1 reinoud return 0; 4037 1.1 reinoud } 4038 1.1 reinoud 4039 1.1 reinoud 4040 1.1 reinoud int 4041 1.1 reinoud udf_write_phys(void *blob, uint32_t location, uint32_t sects) 4042 1.1 reinoud { 4043 1.1 reinoud uint32_t phys, cnt; 4044 1.1 reinoud uint8_t *bpos; 4045 1.1 reinoud int error; 4046 1.1 reinoud 4047 1.1 reinoud for (cnt = 0; cnt < sects; cnt++) { 4048 1.1 reinoud bpos = (uint8_t *) blob; 4049 1.1 reinoud bpos += context.sector_size * cnt; 4050 1.1 reinoud 4051 1.1 reinoud phys = location + cnt; 4052 1.1 reinoud error = udf_write_sector(bpos, phys); 4053 1.1 reinoud if (error) 4054 1.1 reinoud return error; 4055 1.1 reinoud } 4056 1.1 reinoud return 0; 4057 1.1 reinoud } 4058 1.1 reinoud 4059 1.1 reinoud 4060 1.1 reinoud int 4061 1.1 reinoud udf_read_virt(void *blob, uint32_t location, uint16_t vpart, 4062 1.1 reinoud uint32_t sectors) 4063 1.1 reinoud { 4064 1.1 reinoud uint32_t phys, ext; 4065 1.1 reinoud uint8_t *data; 4066 1.1 reinoud int error; 4067 1.1 reinoud 4068 1.1 reinoud /* determine physical location */ 4069 1.1 reinoud data = (uint8_t *) blob; 4070 1.1 reinoud while (sectors) { 4071 1.1 reinoud if (udf_translate_vtop(location, vpart, &phys, &ext)) { 4072 1.1 reinoud // warnx("internal error: bad translation"); 4073 1.1 reinoud return EINVAL; 4074 1.1 reinoud } 4075 1.1 reinoud ext = MIN(sectors, ext); 4076 1.1 reinoud error = udf_read_phys(data, phys, ext); 4077 1.1 reinoud if (error) 4078 1.1 reinoud return error; 4079 1.1 reinoud location += ext; 4080 1.1 reinoud data += ext * context.sector_size; 4081 1.1 reinoud sectors -= ext; 4082 1.1 reinoud } 4083 1.1 reinoud return 0; 4084 1.1 reinoud } 4085 1.1 reinoud 4086 1.1 reinoud 4087 1.1 reinoud int 4088 1.1 reinoud udf_write_virt(void *blob, uint32_t location, uint16_t vpart, 4089 1.1 reinoud uint32_t sectors) 4090 1.1 reinoud { 4091 1.1 reinoud uint32_t phys, ext, alloc_pos; 4092 1.1 reinoud uint8_t *data; 4093 1.1 reinoud int error; 4094 1.1 reinoud 4095 1.1 reinoud /* determine physical location */ 4096 1.1 reinoud if (context.vtop_tp[vpart] == UDF_VTOP_TYPE_VIRT) { 4097 1.1 reinoud assert(sectors == 1); 4098 1.1 reinoud alloc_pos = context.alloc_pos[context.data_part]; 4099 1.1 reinoud udf_vat_update(location, alloc_pos); 4100 1.1 reinoud udf_translate_vtop(alloc_pos, context.vtop[vpart], &phys, &ext); 4101 1.1 reinoud context.alloc_pos[context.data_part]++; 4102 1.1 reinoud return udf_write_phys(blob, phys, sectors); 4103 1.1 reinoud } 4104 1.1 reinoud 4105 1.1 reinoud data = (uint8_t *) blob; 4106 1.1 reinoud while (sectors) { 4107 1.1 reinoud if (udf_translate_vtop(location, vpart, &phys, &ext)) { 4108 1.1 reinoud warnx("internal error: bad translation"); 4109 1.1 reinoud return EINVAL; 4110 1.1 reinoud } 4111 1.1 reinoud ext = MIN(sectors, ext); 4112 1.1 reinoud error = udf_write_phys(data, phys, ext); 4113 1.1 reinoud if (error) 4114 1.1 reinoud return error; 4115 1.1 reinoud location += ext; 4116 1.1 reinoud data += ext * context.sector_size; 4117 1.1 reinoud sectors -= ext; 4118 1.1 reinoud } 4119 1.1 reinoud return 0; 4120 1.1 reinoud } 4121 1.1 reinoud 4122 1.1 reinoud 4123 1.1 reinoud int 4124 1.1 reinoud udf_read_dscr_phys(uint32_t sector, union dscrptr **dstp) 4125 1.1 reinoud { 4126 1.1 reinoud union dscrptr *dst, *new_dst; 4127 1.1 reinoud uint8_t *pos; 4128 1.1 reinoud uint32_t sectors, dscrlen, sector_size; 4129 1.1 reinoud int error; 4130 1.1 reinoud 4131 1.1 reinoud sector_size = context.sector_size; 4132 1.1 reinoud 4133 1.1 reinoud *dstp = dst = NULL; 4134 1.1 reinoud dscrlen = sector_size; 4135 1.1 reinoud 4136 1.1 reinoud /* read initial piece */ 4137 1.1 reinoud dst = malloc(sector_size); 4138 1.1 reinoud assert(dst); 4139 1.1 reinoud error = udf_read_sector(dst, sector); 4140 1.1 reinoud // if (error) 4141 1.1 reinoud // warn("read error"); 4142 1.1 reinoud 4143 1.1 reinoud if (!error) { 4144 1.1 reinoud /* check if its an empty block */ 4145 1.1 reinoud if (is_zero(dst, sector_size)) { 4146 1.1 reinoud /* return no error but with no dscrptr */ 4147 1.1 reinoud /* dispose first block */ 4148 1.1 reinoud free(dst); 4149 1.1 reinoud return 0; 4150 1.1 reinoud } 4151 1.1 reinoud /* check if its a valid tag */ 4152 1.1 reinoud error = udf_check_tag(dst); 4153 1.1 reinoud if (error) { 4154 1.1 reinoud free(dst); 4155 1.1 reinoud return 0; 4156 1.1 reinoud } 4157 1.1 reinoud /* calculate descriptor size */ 4158 1.1 reinoud dscrlen = udf_tagsize(dst, sector_size); 4159 1.1 reinoud } 4160 1.1 reinoud 4161 1.1 reinoud if (!error && (dscrlen > sector_size)) { 4162 1.1 reinoud /* read the rest of descriptor */ 4163 1.1 reinoud 4164 1.1 reinoud new_dst = realloc(dst, dscrlen); 4165 1.1 reinoud if (new_dst == NULL) { 4166 1.1 reinoud free(dst); 4167 1.1 reinoud return ENOMEM; 4168 1.1 reinoud } 4169 1.1 reinoud dst = new_dst; 4170 1.1 reinoud 4171 1.1 reinoud sectors = dscrlen / sector_size; 4172 1.1 reinoud pos = (uint8_t *) dst + sector_size; 4173 1.1 reinoud error = udf_read_phys(pos, sector + 1, sectors-1); 4174 1.1 reinoud if (error) 4175 1.1 reinoud warnx("read error"); 4176 1.1 reinoud } 4177 1.1 reinoud if (!error) 4178 1.1 reinoud error = udf_check_tag_payload(dst, dscrlen); 4179 1.1 reinoud if (error && dst) { 4180 1.1 reinoud free(dst); 4181 1.1 reinoud dst = NULL; 4182 1.1 reinoud } 4183 1.1 reinoud *dstp = dst; 4184 1.1 reinoud 4185 1.1 reinoud return error; 4186 1.1 reinoud } 4187 1.1 reinoud 4188 1.1 reinoud 4189 1.1 reinoud int 4190 1.1 reinoud udf_write_dscr_phys(union dscrptr *dscr, uint32_t location, 4191 1.1 reinoud uint32_t sectors) 4192 1.1 reinoud { 4193 1.1 reinoud dscr->tag.tag_loc = udf_rw32(location); 4194 1.1 reinoud (void) udf_validate_tag_and_crc_sums(dscr); 4195 1.1 reinoud 4196 1.1 reinoud assert(sectors == udf_tagsize(dscr, context.sector_size) / context.sector_size); 4197 1.1 reinoud return udf_write_phys(dscr, location, sectors); 4198 1.1 reinoud } 4199 1.1 reinoud 4200 1.1 reinoud 4201 1.1 reinoud int 4202 1.1 reinoud udf_read_dscr_virt(uint32_t sector, uint16_t vpart, union dscrptr **dstp) 4203 1.1 reinoud { 4204 1.1 reinoud union dscrptr *dst, *new_dst; 4205 1.1 reinoud uint8_t *pos; 4206 1.1 reinoud uint32_t sectors, dscrlen, sector_size; 4207 1.1 reinoud int error; 4208 1.1 reinoud 4209 1.1 reinoud sector_size = context.sector_size; 4210 1.1 reinoud 4211 1.1 reinoud *dstp = dst = NULL; 4212 1.1 reinoud dscrlen = sector_size; 4213 1.1 reinoud 4214 1.1 reinoud /* read initial piece */ 4215 1.1 reinoud dst = calloc(1, sector_size); 4216 1.1 reinoud assert(dst); 4217 1.1 reinoud error = udf_read_virt(dst, sector, vpart, 1); 4218 1.1 reinoud if (error) 4219 1.1 reinoud return error; 4220 1.1 reinoud 4221 1.1 reinoud if (!error) { 4222 1.1 reinoud /* check if its a valid tag */ 4223 1.1 reinoud error = udf_check_tag(dst); 4224 1.1 reinoud if (error) { 4225 1.1 reinoud /* check if its an empty block */ 4226 1.1 reinoud if (is_zero(dst, sector_size)) { 4227 1.1 reinoud /* return no error but with no dscrptr */ 4228 1.1 reinoud /* dispose first block */ 4229 1.1 reinoud free(dst); 4230 1.1 reinoud return 0; 4231 1.1 reinoud } 4232 1.1 reinoud } 4233 1.1 reinoud /* calculate descriptor size */ 4234 1.1 reinoud dscrlen = udf_tagsize(dst, sector_size); 4235 1.1 reinoud } 4236 1.1 reinoud 4237 1.1 reinoud if (!error && (dscrlen > sector_size)) { 4238 1.1 reinoud /* read the rest of descriptor */ 4239 1.1 reinoud 4240 1.1 reinoud new_dst = realloc(dst, dscrlen); 4241 1.1 reinoud if (new_dst == NULL) { 4242 1.1 reinoud free(dst); 4243 1.1 reinoud return ENOMEM; 4244 1.1 reinoud } 4245 1.1 reinoud dst = new_dst; 4246 1.1 reinoud 4247 1.1 reinoud sectors = dscrlen / sector_size; 4248 1.1 reinoud pos = (uint8_t *) dst + sector_size; 4249 1.1 reinoud error = udf_read_virt(pos, sector + 1, vpart, sectors-1); 4250 1.1 reinoud if (error) 4251 1.1 reinoud warn("read error"); 4252 1.1 reinoud } 4253 1.1 reinoud if (!error) 4254 1.1 reinoud error = udf_check_tag_payload(dst, dscrlen); 4255 1.1 reinoud if (error && dst) { 4256 1.1 reinoud free(dst); 4257 1.1 reinoud dst = NULL; 4258 1.1 reinoud } 4259 1.1 reinoud *dstp = dst; 4260 1.1 reinoud 4261 1.1 reinoud return error; 4262 1.1 reinoud } 4263 1.1 reinoud 4264 1.1 reinoud 4265 1.1 reinoud int 4266 1.1 reinoud udf_write_dscr_virt(union dscrptr *dscr, uint32_t location, uint16_t vpart, 4267 1.1 reinoud uint32_t sectors) 4268 1.1 reinoud { 4269 1.1 reinoud struct file_entry *fe; 4270 1.1 reinoud struct extfile_entry *efe; 4271 1.1 reinoud struct extattrhdr_desc *extattrhdr; 4272 1.1 reinoud 4273 1.1 reinoud extattrhdr = NULL; 4274 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) { 4275 1.1 reinoud fe = (struct file_entry *) dscr; 4276 1.1 reinoud if (udf_rw32(fe->l_ea) > 0) 4277 1.1 reinoud extattrhdr = (struct extattrhdr_desc *) fe->data; 4278 1.1 reinoud } 4279 1.1 reinoud if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) { 4280 1.1 reinoud efe = (struct extfile_entry *) dscr; 4281 1.1 reinoud if (udf_rw32(efe->l_ea) > 0) 4282 1.1 reinoud extattrhdr = (struct extattrhdr_desc *) efe->data; 4283 1.1 reinoud } 4284 1.1 reinoud if (extattrhdr) { 4285 1.1 reinoud extattrhdr->tag.tag_loc = udf_rw32(location); 4286 1.1 reinoud udf_validate_tag_and_crc_sums((union dscrptr *) extattrhdr); 4287 1.1 reinoud } 4288 1.1 reinoud 4289 1.1 reinoud dscr->tag.tag_loc = udf_rw32(location); 4290 1.1 reinoud udf_validate_tag_and_crc_sums(dscr); 4291 1.1 reinoud 4292 1.1 reinoud assert(sectors >= (udf_tagsize(dscr, context.sector_size) / context.sector_size)); 4293 1.1 reinoud return udf_write_virt(dscr, location, vpart, sectors); 4294 1.1 reinoud } 4295 1.1 reinoud 4296 1.1 reinoud 4297 1.1 reinoud int 4298 1.1 reinoud is_zero(void *blob, int size) { 4299 1.1 reinoud uint8_t *p = blob; 4300 1.1 reinoud for (int i = 0; i < size; i++, p++) 4301 1.1 reinoud if (*p) 4302 1.1 reinoud return 0; 4303 1.1 reinoud return 1; 4304 1.1 reinoud } 4305 1.1 reinoud 4306 1.1 reinoud /* --------------------------------------------------------------------- */ 4307 1.1 reinoud 4308 1.1 reinoud static void 4309 1.1 reinoud udf_partition_alloc(int nblk, int vpart, struct long_ad *pos) 4310 1.1 reinoud { 4311 1.1 reinoud memset(pos, 0, sizeof(*pos)); 4312 1.1 reinoud pos->len = udf_rw32(nblk * context.sector_size); 4313 1.1 reinoud pos->loc.lb_num = udf_rw32(context.alloc_pos[vpart]); 4314 1.1 reinoud pos->loc.part_num = udf_rw16(vpart); 4315 1.1 reinoud 4316 1.1 reinoud udf_mark_allocated(context.alloc_pos[vpart], vpart, nblk); 4317 1.1 reinoud context.alloc_pos[vpart] += nblk; 4318 1.1 reinoud } 4319 1.1 reinoud 4320 1.1 reinoud 4321 1.1 reinoud void 4322 1.1 reinoud udf_metadata_alloc(int nblk, struct long_ad *pos) 4323 1.1 reinoud { 4324 1.1 reinoud udf_partition_alloc(nblk, context.metadata_part, pos); 4325 1.1 reinoud } 4326 1.1 reinoud 4327 1.1 reinoud 4328 1.1 reinoud void 4329 1.1 reinoud udf_data_alloc(int nblk, struct long_ad *pos) 4330 1.1 reinoud { 4331 1.1 reinoud udf_partition_alloc(nblk, context.data_part, pos); 4332 1.1 reinoud } 4333 1.1 reinoud 4334 1.1 reinoud 4335 1.1 reinoud void 4336 1.1 reinoud udf_fids_alloc(int nblk, struct long_ad *pos) 4337 1.1 reinoud { 4338 1.1 reinoud udf_partition_alloc(nblk, context.fids_part, pos); 4339 1.1 reinoud } 4340 1.1 reinoud 4341 1.1 reinoud 4342 1.1 reinoud /* --------------------------------------------------------------------- */ 4343 1.1 reinoud 4344 1.1 reinoud /* 4345 1.1 reinoud * udf_derive_format derives the format_flags from the disc's mmc_discinfo. 4346 1.1 reinoud * The resulting flags uniquely define a disc format. Note there are at least 4347 1.1 reinoud * 7 distinct format types defined in UDF. 4348 1.1 reinoud */ 4349 1.1 reinoud 4350 1.1 reinoud #define UDF_VERSION(a) \ 4351 1.1 reinoud (((a) == 0x102) || ((a) == 0x150) || ((a) == 0x200) || \ 4352 1.1 reinoud ((a) == 0x201) || ((a) == 0x250) || ((a) == 0x260)) 4353 1.1 reinoud 4354 1.1 reinoud int 4355 1.1 reinoud udf_derive_format(int req_enable, int req_disable) 4356 1.1 reinoud { 4357 1.1 reinoud int format_flags; 4358 1.1 reinoud int media_accesstype; 4359 1.1 reinoud 4360 1.1 reinoud /* disc writability, formatted, appendable */ 4361 1.1 reinoud if ((mmc_discinfo.mmc_cur & MMC_CAP_RECORDABLE) == 0) { 4362 1.1 reinoud warnx("can't newfs readonly device"); 4363 1.1 reinoud return EROFS; 4364 1.1 reinoud } 4365 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) { 4366 1.1 reinoud /* sequentials need sessions appended */ 4367 1.1 reinoud if (mmc_discinfo.disc_state == MMC_STATE_CLOSED) { 4368 1.1 reinoud warnx("can't append session to a closed disc"); 4369 1.1 reinoud return EROFS; 4370 1.1 reinoud } 4371 1.1 reinoud if ((mmc_discinfo.disc_state != MMC_STATE_EMPTY) && 4372 1.1 reinoud !context.create_new_session) { 4373 1.1 reinoud warnx("disc not empty! Use -F to force " 4374 1.1 reinoud "initialisation"); 4375 1.1 reinoud return EROFS; 4376 1.1 reinoud } 4377 1.1 reinoud } else { 4378 1.1 reinoud /* check if disc (being) formatted or has been started on */ 4379 1.1 reinoud if (mmc_discinfo.disc_state == MMC_STATE_EMPTY) { 4380 1.1 reinoud warnx("disc is not formatted"); 4381 1.1 reinoud return EROFS; 4382 1.1 reinoud } 4383 1.1 reinoud } 4384 1.1 reinoud 4385 1.1 reinoud /* determine UDF format */ 4386 1.1 reinoud format_flags = 0; 4387 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_REWRITABLE) { 4388 1.1 reinoud /* all rewritable media */ 4389 1.1 reinoud format_flags |= FORMAT_REWRITABLE; 4390 1.1 reinoud if (context.min_udf >= 0x0250) { 4391 1.1 reinoud /* standard dictates meta as default */ 4392 1.1 reinoud format_flags |= FORMAT_META; 4393 1.1 reinoud } 4394 1.1 reinoud 4395 1.1 reinoud if ((mmc_discinfo.mmc_cur & MMC_CAP_HW_DEFECTFREE) == 0) { 4396 1.1 reinoud /* spareables for defect management */ 4397 1.1 reinoud if (context.min_udf >= 0x150) 4398 1.1 reinoud format_flags |= FORMAT_SPAREABLE; 4399 1.1 reinoud } 4400 1.1 reinoud } else { 4401 1.1 reinoud /* all once recordable media */ 4402 1.1 reinoud format_flags |= FORMAT_WRITEONCE; 4403 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) { 4404 1.1 reinoud format_flags |= FORMAT_SEQUENTIAL; 4405 1.1 reinoud 4406 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE) { 4407 1.1 reinoud /* logical overwritable */ 4408 1.1 reinoud format_flags |= FORMAT_LOW; 4409 1.1 reinoud } else { 4410 1.1 reinoud /* have to use VAT for overwriting */ 4411 1.1 reinoud format_flags |= FORMAT_VAT; 4412 1.1 reinoud } 4413 1.1 reinoud } else { 4414 1.1 reinoud /* rare WORM devices, but BluRay has one, strat4096 */ 4415 1.1 reinoud format_flags |= FORMAT_WORM; 4416 1.1 reinoud } 4417 1.1 reinoud } 4418 1.1 reinoud 4419 1.1 reinoud /* enable/disable requests */ 4420 1.1 reinoud if (req_disable & FORMAT_META) { 4421 1.1 reinoud format_flags &= ~(FORMAT_META | FORMAT_LOW); 4422 1.1 reinoud req_disable &= ~FORMAT_META; 4423 1.1 reinoud } 4424 1.1 reinoud if ((format_flags & FORMAT_VAT) & UDF_512_TRACK) 4425 1.1 reinoud format_flags |= FORMAT_TRACK512; 4426 1.1 reinoud 4427 1.1 reinoud if (req_enable & FORMAT_READONLY) { 4428 1.1 reinoud format_flags |= FORMAT_READONLY; 4429 1.1 reinoud } 4430 1.1 reinoud 4431 1.1 reinoud /* determine partition/media access type */ 4432 1.1 reinoud media_accesstype = UDF_ACCESSTYPE_NOT_SPECIFIED; 4433 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_REWRITABLE) { 4434 1.1 reinoud media_accesstype = UDF_ACCESSTYPE_OVERWRITABLE; 4435 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_ERASABLE) 4436 1.1 reinoud media_accesstype = UDF_ACCESSTYPE_REWRITEABLE; 4437 1.1 reinoud } else { 4438 1.1 reinoud /* all once recordable media */ 4439 1.1 reinoud media_accesstype = UDF_ACCESSTYPE_WRITE_ONCE; 4440 1.1 reinoud } 4441 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE) 4442 1.1 reinoud media_accesstype = UDF_ACCESSTYPE_PSEUDO_OVERWITE; 4443 1.1 reinoud 4444 1.1 reinoud /* patch up media accesstype */ 4445 1.1 reinoud if (req_enable & FORMAT_READONLY) { 4446 1.1 reinoud /* better now */ 4447 1.1 reinoud media_accesstype = UDF_ACCESSTYPE_READ_ONLY; 4448 1.1 reinoud } 4449 1.1 reinoud 4450 1.1 reinoud /* adjust minimum version limits */ 4451 1.1 reinoud if (format_flags & FORMAT_VAT) 4452 1.1 reinoud context.min_udf = MAX(context.min_udf, 0x0150); 4453 1.1 reinoud if (format_flags & FORMAT_SPAREABLE) 4454 1.1 reinoud context.min_udf = MAX(context.min_udf, 0x0150); 4455 1.1 reinoud if (format_flags & FORMAT_META) 4456 1.1 reinoud context.min_udf = MAX(context.min_udf, 0x0250); 4457 1.1 reinoud if (format_flags & FORMAT_LOW) 4458 1.1 reinoud context.min_udf = MAX(context.min_udf, 0x0260); 4459 1.1 reinoud 4460 1.1 reinoud /* adjust maximum version limits not to tease or break things */ 4461 1.1 reinoud if (!(format_flags & (FORMAT_META | FORMAT_LOW | FORMAT_VAT)) && 4462 1.1 reinoud (context.max_udf > 0x200)) 4463 1.1 reinoud context.max_udf = 0x201; 4464 1.1 reinoud 4465 1.1 reinoud if ((format_flags & (FORMAT_VAT | FORMAT_SPAREABLE)) == 0) 4466 1.1 reinoud if (context.max_udf <= 0x150) 4467 1.1 reinoud context.min_udf = 0x102; 4468 1.1 reinoud 4469 1.1 reinoud /* limit Ecma 167 descriptor if possible/needed */ 4470 1.1 reinoud context.dscrver = 3; 4471 1.1 reinoud if ((context.min_udf < 0x200) || (context.max_udf < 0x200)) { 4472 1.1 reinoud context.dscrver = 2; 4473 1.1 reinoud context.max_udf = 0x150; /* last version < 0x200 */ 4474 1.1 reinoud } 4475 1.1 reinoud 4476 1.1 reinoud /* is it possible ? */ 4477 1.1 reinoud if (context.min_udf > context.max_udf) { 4478 1.1 reinoud warnx("initialisation prohibited by specified maximum " 4479 1.1 reinoud "UDF version 0x%04x. Minimum version required 0x%04x", 4480 1.1 reinoud context.max_udf, context.min_udf); 4481 1.1 reinoud return EPERM; 4482 1.1 reinoud } 4483 1.1 reinoud 4484 1.1 reinoud if (!UDF_VERSION(context.min_udf) || !UDF_VERSION(context.max_udf)) { 4485 1.1 reinoud warnx("internal error, invalid min/max udf versionsi in %s", 4486 1.1 reinoud __func__); 4487 1.1 reinoud return EPERM; 4488 1.1 reinoud } 4489 1.1 reinoud context.format_flags = format_flags; 4490 1.1 reinoud context.media_accesstype = media_accesstype; 4491 1.1 reinoud 4492 1.1 reinoud return 0; 4493 1.1 reinoud } 4494 1.1 reinoud 4495 1.1 reinoud #undef UDF_VERSION 4496 1.1 reinoud 4497 1.1 reinoud 4498 1.1 reinoud /* --------------------------------------------------------------------- */ 4499 1.1 reinoud 4500 1.1 reinoud int 4501 1.1 reinoud udf_proces_names(void) 4502 1.1 reinoud { 4503 1.1 reinoud struct timeval time_of_day; 4504 1.1 reinoud uint32_t primary_nr; 4505 1.1 reinoud uint64_t volset_nr; 4506 1.1 reinoud 4507 1.1 reinoud if (context.logvol_name == NULL) 4508 1.1 reinoud context.logvol_name = strdup("anonymous"); 4509 1.1 reinoud if (context.primary_name == NULL) { 4510 1.1 reinoud if (mmc_discinfo.disc_flags & MMC_DFLAGS_DISCIDVALID) { 4511 1.1 reinoud primary_nr = mmc_discinfo.disc_id; 4512 1.1 reinoud } else { 4513 1.1 reinoud primary_nr = (uint32_t) random(); 4514 1.1 reinoud } 4515 1.1 reinoud context.primary_name = calloc(32, 1); 4516 1.1 reinoud sprintf(context.primary_name, "%08"PRIx32, primary_nr); 4517 1.1 reinoud } 4518 1.1 reinoud if (context.volset_name == NULL) { 4519 1.1 reinoud if (mmc_discinfo.disc_flags & MMC_DFLAGS_BARCODEVALID) { 4520 1.1 reinoud volset_nr = mmc_discinfo.disc_barcode; 4521 1.1 reinoud } else { 4522 1.1 reinoud (void)gettimeofday(&time_of_day, NULL); 4523 1.1 reinoud volset_nr = (uint64_t) random(); 4524 1.1 reinoud volset_nr |= ((uint64_t) time_of_day.tv_sec) << 32; 4525 1.1 reinoud } 4526 1.1 reinoud context.volset_name = calloc(128,1); 4527 1.1 reinoud sprintf(context.volset_name, "%016"PRIx64, volset_nr); 4528 1.1 reinoud } 4529 1.1 reinoud if (context.fileset_name == NULL) 4530 1.1 reinoud context.fileset_name = strdup("anonymous"); 4531 1.1 reinoud 4532 1.1 reinoud /* check passed/created identifiers */ 4533 1.1 reinoud if (strlen(context.logvol_name) > 128) { 4534 1.1 reinoud warnx("logical volume name too long"); 4535 1.1 reinoud return EINVAL; 4536 1.1 reinoud } 4537 1.1 reinoud if (strlen(context.primary_name) > 32) { 4538 1.1 reinoud warnx("primary volume name too long"); 4539 1.1 reinoud return EINVAL; 4540 1.1 reinoud } 4541 1.1 reinoud if (strlen(context.volset_name) > 128) { 4542 1.1 reinoud warnx("volume set name too long"); 4543 1.1 reinoud return EINVAL; 4544 1.1 reinoud } 4545 1.1 reinoud if (strlen(context.fileset_name) > 32) { 4546 1.1 reinoud warnx("fileset name too long"); 4547 1.1 reinoud return EINVAL; 4548 1.1 reinoud } 4549 1.1 reinoud 4550 1.1 reinoud /* signal all OK */ 4551 1.1 reinoud return 0; 4552 1.1 reinoud } 4553 1.1 reinoud 4554 1.1 reinoud /* --------------------------------------------------------------------- */ 4555 1.1 reinoud 4556 1.1 reinoud int 4557 1.1 reinoud udf_write_iso9660_vrs(void) 4558 1.1 reinoud { 4559 1.1 reinoud struct vrs_desc *iso9660_vrs_desc; 4560 1.1 reinoud uint32_t pos; 4561 1.1 reinoud int error, cnt, dpos; 4562 1.1 reinoud 4563 1.1 reinoud /* create ISO/Ecma-167 identification descriptors */ 4564 1.1 reinoud if ((iso9660_vrs_desc = calloc(1, context.sector_size)) == NULL) 4565 1.1 reinoud return ENOMEM; 4566 1.1 reinoud 4567 1.1 reinoud /* 4568 1.1 reinoud * All UDF formats should have their ISO/Ecma-167 descriptors written 4569 1.1 reinoud * except when not possible due to track reservation in the case of 4570 1.1 reinoud * VAT 4571 1.1 reinoud */ 4572 1.1 reinoud if ((context.format_flags & FORMAT_TRACK512) == 0) { 4573 1.1 reinoud dpos = (2048 + context.sector_size - 1) / context.sector_size; 4574 1.1 reinoud 4575 1.1 reinoud /* wipe at least 6 times 2048 byte `sectors' */ 4576 1.1 reinoud for (cnt = 0; cnt < 6 *dpos; cnt++) { 4577 1.1 reinoud pos = layout.iso9660_vrs + cnt; 4578 1.1 reinoud if ((error = udf_write_sector(iso9660_vrs_desc, pos))) { 4579 1.1 reinoud free(iso9660_vrs_desc); 4580 1.1 reinoud return error; 4581 1.1 reinoud } 4582 1.1 reinoud } 4583 1.1 reinoud 4584 1.1 reinoud /* common VRS fields in all written out ISO descriptors */ 4585 1.1 reinoud iso9660_vrs_desc->struct_type = 0; 4586 1.1 reinoud iso9660_vrs_desc->version = 1; 4587 1.1 reinoud pos = layout.iso9660_vrs; 4588 1.1 reinoud 4589 1.1 reinoud /* BEA01, NSR[23], TEA01 */ 4590 1.1 reinoud memcpy(iso9660_vrs_desc->identifier, "BEA01", 5); 4591 1.1 reinoud if ((error = udf_write_sector(iso9660_vrs_desc, pos))) { 4592 1.1 reinoud free(iso9660_vrs_desc); 4593 1.1 reinoud return error; 4594 1.1 reinoud } 4595 1.1 reinoud pos += dpos; 4596 1.1 reinoud 4597 1.1 reinoud if (context.dscrver == 2) 4598 1.1 reinoud memcpy(iso9660_vrs_desc->identifier, "NSR02", 5); 4599 1.1 reinoud else 4600 1.1 reinoud memcpy(iso9660_vrs_desc->identifier, "NSR03", 5); 4601 1.1 reinoud ; 4602 1.1 reinoud if ((error = udf_write_sector(iso9660_vrs_desc, pos))) { 4603 1.1 reinoud free(iso9660_vrs_desc); 4604 1.1 reinoud return error; 4605 1.1 reinoud } 4606 1.1 reinoud pos += dpos; 4607 1.1 reinoud 4608 1.1 reinoud memcpy(iso9660_vrs_desc->identifier, "TEA01", 5); 4609 1.1 reinoud if ((error = udf_write_sector(iso9660_vrs_desc, pos))) { 4610 1.1 reinoud free(iso9660_vrs_desc); 4611 1.1 reinoud return error; 4612 1.1 reinoud } 4613 1.1 reinoud } 4614 1.1 reinoud 4615 1.1 reinoud free(iso9660_vrs_desc); 4616 1.1 reinoud /* return success */ 4617 1.1 reinoud return 0; 4618 1.1 reinoud } 4619 1.1 reinoud 4620 1.1 reinoud 4621 1.1 reinoud /* --------------------------------------------------------------------- */ 4622 1.1 reinoud 4623 1.1 reinoud int 4624 1.1 reinoud udf_get_blockingnr(struct mmc_trackinfo *ti) 4625 1.1 reinoud { 4626 1.1 reinoud int blockingnr; 4627 1.1 reinoud 4628 1.1 reinoud /* determine blockingnr */ 4629 1.1 reinoud blockingnr = ti->packet_size; 4630 1.1 reinoud if (blockingnr <= 1) { 4631 1.1 reinoud /* paranoia on blockingnr */ 4632 1.1 reinoud switch (mmc_discinfo.mmc_profile) { 4633 1.1 reinoud case 0x01 : /* DISC */ 4634 1.1 reinoud blockingnr = 64; 4635 1.1 reinoud break; 4636 1.1 reinoud case 0x08 : /* CDROM */ 4637 1.1 reinoud case 0x09 : /* CD-R */ 4638 1.1 reinoud case 0x0a : /* CD-RW */ 4639 1.1 reinoud blockingnr = 32; /* UDF requirement */ 4640 1.1 reinoud break; 4641 1.1 reinoud case 0x10 : /* DVDROM */ 4642 1.1 reinoud case 0x11 : /* DVD-R (DL) */ 4643 1.1 reinoud case 0x12 : /* DVD-RAM */ 4644 1.1 reinoud case 0x1b : /* DVD+R */ 4645 1.1 reinoud case 0x2b : /* DVD+R Dual layer */ 4646 1.1 reinoud case 0x13 : /* DVD-RW restricted overwrite */ 4647 1.1 reinoud case 0x14 : /* DVD-RW sequential */ 4648 1.1 reinoud case 0x1a : /* DVD+RW */ 4649 1.1 reinoud blockingnr = 16; /* SCSI definition */ 4650 1.1 reinoud break; 4651 1.1 reinoud case 0x40 : /* BDROM */ 4652 1.1 reinoud case 0x41 : /* BD-R Sequential recording (SRM) */ 4653 1.1 reinoud case 0x42 : /* BD-R Random recording (RRM) */ 4654 1.1 reinoud case 0x43 : /* BD-RE */ 4655 1.1 reinoud case 0x51 : /* HD DVD-R */ 4656 1.1 reinoud case 0x52 : /* HD DVD-RW */ 4657 1.1 reinoud blockingnr = 32; /* SCSI definition */ 4658 1.1 reinoud break; 4659 1.1 reinoud default: 4660 1.1 reinoud break; 4661 1.1 reinoud } 4662 1.1 reinoud } 4663 1.1 reinoud return blockingnr; 4664 1.1 reinoud } 4665 1.1 reinoud 4666 1.1 reinoud 4667 1.1 reinoud int 4668 1.1 reinoud udf_spareable_blocks(void) 4669 1.1 reinoud { 4670 1.1 reinoud if (mmc_discinfo.mmc_class == MMC_CLASS_CD) { 4671 1.1 reinoud /* not too much for CD-RW, still 20MiB */ 4672 1.1 reinoud return 32; 4673 1.1 reinoud } else { 4674 1.1 reinoud /* take a value for DVD*RW mainly, BD is `defect free' */ 4675 1.1 reinoud return 512; 4676 1.1 reinoud } 4677 1.1 reinoud } 4678 1.1 reinoud 4679 1.1 reinoud 4680 1.1 reinoud int 4681 1.1 reinoud udf_spareable_blockingnr(void) 4682 1.1 reinoud { 4683 1.1 reinoud struct mmc_trackinfo ti; 4684 1.1 reinoud int spareable_blockingnr; 4685 1.1 reinoud int error; 4686 1.1 reinoud 4687 1.1 reinoud /* determine span/size */ 4688 1.1 reinoud ti.tracknr = mmc_discinfo.first_track_last_session; 4689 1.1 reinoud error = udf_update_trackinfo(&ti); 4690 1.1 reinoud spareable_blockingnr = udf_get_blockingnr(&ti); 4691 1.1 reinoud if (error) 4692 1.1 reinoud spareable_blockingnr = 32; 4693 1.1 reinoud 4694 1.1 reinoud /* 4695 1.1 reinoud * Note that for (bug) compatibility with version UDF 2.00 4696 1.1 reinoud * (fixed in 2.01 and higher) the blocking size needs to be 32 4697 1.1 reinoud * sectors otherwise the drive's blockingnr. 4698 1.1 reinoud */ 4699 1.1 reinoud if (context.min_udf <= 0x200) 4700 1.1 reinoud spareable_blockingnr = 32; 4701 1.1 reinoud return spareable_blockingnr; 4702 1.1 reinoud } 4703 1.1 reinoud 4704 1.1 reinoud 4705 1.1 reinoud /* 4706 1.1 reinoud * Main function that creates and writes out disc contents based on the 4707 1.1 reinoud * format_flags's that uniquely define the type of disc to create. 4708 1.1 reinoud */ 4709 1.1 reinoud 4710 1.1 reinoud int 4711 1.1 reinoud udf_do_newfs_prefix(void) 4712 1.1 reinoud { 4713 1.1 reinoud union dscrptr *zero_dscr; 4714 1.1 reinoud union dscrptr *dscr; 4715 1.1 reinoud struct mmc_trackinfo ti; 4716 1.1 reinoud uint32_t blockingnr; 4717 1.1 reinoud uint32_t cnt, loc, len; 4718 1.1 reinoud int sectcopy; 4719 1.1 reinoud int error, integrity_type; 4720 1.1 reinoud int data_part, metadata_part; 4721 1.1 reinoud int format_flags; 4722 1.1 reinoud 4723 1.1 reinoud /* init */ 4724 1.1 reinoud format_flags = context.format_flags; 4725 1.1 reinoud 4726 1.1 reinoud /* determine span/size */ 4727 1.1 reinoud ti.tracknr = mmc_discinfo.first_track_last_session; 4728 1.1 reinoud error = udf_update_trackinfo(&ti); 4729 1.1 reinoud if (error) 4730 1.1 reinoud return error; 4731 1.1 reinoud 4732 1.1 reinoud if (mmc_discinfo.sector_size > context.sector_size) { 4733 1.1 reinoud warnx("impossible to format: " 4734 1.1 reinoud "sector size %d too small for media sector size %d", 4735 1.1 reinoud context.sector_size, mmc_discinfo.sector_size); 4736 1.1 reinoud return EIO; 4737 1.1 reinoud } 4738 1.1 reinoud 4739 1.1 reinoud /* determine blockingnr */ 4740 1.1 reinoud blockingnr = udf_get_blockingnr(&ti); 4741 1.1 reinoud if (blockingnr <= 0) { 4742 1.1 reinoud warnx("can't fixup blockingnumber for device " 4743 1.1 reinoud "type %d", mmc_discinfo.mmc_profile); 4744 1.1 reinoud warnx("device is not returning valid blocking" 4745 1.1 reinoud " number and media type is unknown"); 4746 1.1 reinoud return EINVAL; 4747 1.1 reinoud } 4748 1.1 reinoud 4749 1.1 reinoud wrtrack_skew = 0; 4750 1.1 reinoud if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) 4751 1.1 reinoud wrtrack_skew = ti.next_writable % blockingnr; 4752 1.1 reinoud 4753 1.1 reinoud /* get layout */ 4754 1.1 reinoud error = udf_calculate_disc_layout(context.min_udf, 4755 1.1 reinoud ti.track_start, mmc_discinfo.last_possible_lba, 4756 1.1 reinoud context.sector_size, blockingnr); 4757 1.1 reinoud 4758 1.1 reinoud /* cache partition for we need it often */ 4759 1.1 reinoud data_part = context.data_part; 4760 1.1 reinoud metadata_part = context.metadata_part; 4761 1.1 reinoud 4762 1.1 reinoud /* Create sparing table descriptor if applicable */ 4763 1.1 reinoud if (format_flags & FORMAT_SPAREABLE) { 4764 1.1 reinoud if ((error = udf_create_sparing_tabled())) 4765 1.1 reinoud return error; 4766 1.1 reinoud 4767 1.1 reinoud if (context.check_surface) { 4768 1.1 reinoud if ((error = udf_surface_check())) 4769 1.1 reinoud return error; 4770 1.1 reinoud } 4771 1.1 reinoud } 4772 1.1 reinoud 4773 1.1 reinoud /* Create a generic terminator descriptor (later reused) */ 4774 1.1 reinoud terminator_dscr = calloc(1, context.sector_size); 4775 1.1 reinoud if (terminator_dscr == NULL) 4776 1.1 reinoud return ENOMEM; 4777 1.1 reinoud udf_create_terminator(terminator_dscr, 0); 4778 1.1 reinoud 4779 1.2 riastrad /* 4780 1.1 reinoud * Create the two Volume Descriptor Sets (VDS) each containing the 4781 1.1 reinoud * following descriptors : primary volume, partition space, 4782 1.1 reinoud * unallocated space, logical volume, implementation use and the 4783 1.1 reinoud * terminator 4784 1.1 reinoud */ 4785 1.1 reinoud 4786 1.1 reinoud /* start of volume recognition sequence building */ 4787 1.1 reinoud context.vds_seq = 0; 4788 1.1 reinoud 4789 1.1 reinoud /* Create primary volume descriptor */ 4790 1.1 reinoud if ((error = udf_create_primaryd())) 4791 1.1 reinoud return error; 4792 1.1 reinoud 4793 1.1 reinoud /* Create partition descriptor */ 4794 1.1 reinoud if ((error = udf_create_partitiond(context.data_part))) 4795 1.1 reinoud return error; 4796 1.1 reinoud 4797 1.1 reinoud /* Create unallocated space descriptor */ 4798 1.1 reinoud if ((error = udf_create_unalloc_spaced())) 4799 1.1 reinoud return error; 4800 1.1 reinoud 4801 1.1 reinoud /* Create logical volume descriptor */ 4802 1.1 reinoud if ((error = udf_create_logical_dscr())) 4803 1.1 reinoud return error; 4804 1.1 reinoud 4805 1.1 reinoud /* Create implementation use descriptor */ 4806 1.1 reinoud /* TODO input of fields 1,2,3 and passing them */ 4807 1.1 reinoud if ((error = udf_create_impvold(NULL, NULL, NULL))) 4808 1.1 reinoud return error; 4809 1.1 reinoud 4810 1.1 reinoud /* Create anchors */ 4811 1.1 reinoud for (cnt = 0; cnt < 3; cnt++) { 4812 1.1 reinoud if ((error = udf_create_anchor(cnt))) { 4813 1.1 reinoud return error; 4814 1.1 reinoud } 4815 1.1 reinoud } 4816 1.1 reinoud 4817 1.1 reinoud /* 4818 1.1 reinoud * Write out what we've created so far. 4819 1.1 reinoud * 4820 1.1 reinoud * Start with wipeout of VRS1 upto start of partition. This allows 4821 1.2 riastrad * formatting for sequentials with the track reservation and it 4822 1.1 reinoud * cleans old rubbish on rewritables. For sequentials without the 4823 1.1 reinoud * track reservation all is wiped from track start. 4824 1.1 reinoud */ 4825 1.1 reinoud if ((zero_dscr = calloc(1, context.sector_size)) == NULL) 4826 1.1 reinoud return ENOMEM; 4827 1.1 reinoud 4828 1.1 reinoud loc = (format_flags & FORMAT_TRACK512) ? layout.vds1 : ti.track_start; 4829 1.1 reinoud for (; loc < layout.part_start_lba; loc++) { 4830 1.1 reinoud if ((error = udf_write_sector(zero_dscr, loc))) { 4831 1.1 reinoud free(zero_dscr); 4832 1.1 reinoud return error; 4833 1.1 reinoud } 4834 1.1 reinoud } 4835 1.1 reinoud free(zero_dscr); 4836 1.1 reinoud 4837 1.1 reinoud /* writeout iso9660 vrs */ 4838 1.1 reinoud if ((error = udf_write_iso9660_vrs())) 4839 1.1 reinoud return error; 4840 1.1 reinoud 4841 1.1 reinoud /* Writeout anchors */ 4842 1.1 reinoud for (cnt = 0; cnt < 3; cnt++) { 4843 1.1 reinoud dscr = (union dscrptr *) context.anchors[cnt]; 4844 1.1 reinoud loc = layout.anchors[cnt]; 4845 1.1 reinoud if ((error = udf_write_dscr_phys(dscr, loc, 1))) { 4846 1.1 reinoud err(1, "ERR!"); 4847 1.1 reinoud return error; 4848 1.1 reinoud } 4849 1.1 reinoud 4850 1.1 reinoud /* sequential media has only one anchor */ 4851 1.1 reinoud if (format_flags & FORMAT_SEQUENTIAL) 4852 1.1 reinoud break; 4853 1.1 reinoud } 4854 1.1 reinoud 4855 1.1 reinoud /* write out main and secondary VRS */ 4856 1.1 reinoud for (sectcopy = 1; sectcopy <= 2; sectcopy++) { 4857 1.1 reinoud loc = (sectcopy == 1) ? layout.vds1 : layout.vds2; 4858 1.1 reinoud 4859 1.1 reinoud /* primary volume descriptor */ 4860 1.1 reinoud dscr = (union dscrptr *) context.primary_vol; 4861 1.1 reinoud error = udf_write_dscr_phys(dscr, loc, 1); 4862 1.1 reinoud if (error) 4863 1.1 reinoud return error; 4864 1.1 reinoud loc++; 4865 1.1 reinoud 4866 1.1 reinoud /* partition descriptor(s) */ 4867 1.1 reinoud for (cnt = 0; cnt < UDF_PARTITIONS; cnt++) { 4868 1.1 reinoud dscr = (union dscrptr *) context.partitions[cnt]; 4869 1.1 reinoud if (dscr) { 4870 1.1 reinoud error = udf_write_dscr_phys(dscr, loc, 1); 4871 1.1 reinoud if (error) 4872 1.1 reinoud return error; 4873 1.1 reinoud loc++; 4874 1.1 reinoud } 4875 1.1 reinoud } 4876 1.1 reinoud 4877 1.1 reinoud /* unallocated space descriptor */ 4878 1.1 reinoud dscr = (union dscrptr *) context.unallocated; 4879 1.1 reinoud error = udf_write_dscr_phys(dscr, loc, 1); 4880 1.1 reinoud if (error) 4881 1.1 reinoud return error; 4882 1.1 reinoud loc++; 4883 1.1 reinoud 4884 1.1 reinoud /* logical volume descriptor */ 4885 1.1 reinoud dscr = (union dscrptr *) context.logical_vol; 4886 1.1 reinoud error = udf_write_dscr_phys(dscr, loc, 1); 4887 1.1 reinoud if (error) 4888 1.1 reinoud return error; 4889 1.1 reinoud loc++; 4890 1.1 reinoud 4891 1.1 reinoud /* implementation use descriptor */ 4892 1.1 reinoud dscr = (union dscrptr *) context.implementation; 4893 1.1 reinoud error = udf_write_dscr_phys(dscr, loc, 1); 4894 1.1 reinoud if (error) 4895 1.1 reinoud return error; 4896 1.1 reinoud loc++; 4897 1.1 reinoud 4898 1.1 reinoud /* terminator descriptor */ 4899 1.1 reinoud error = udf_write_dscr_phys(terminator_dscr, loc, 1); 4900 1.1 reinoud if (error) 4901 1.1 reinoud return error; 4902 1.1 reinoud loc++; 4903 1.1 reinoud } 4904 1.1 reinoud 4905 1.1 reinoud /* writeout the two spareable table descriptors (if needed) */ 4906 1.1 reinoud if (format_flags & FORMAT_SPAREABLE) { 4907 1.1 reinoud for (sectcopy = 1; sectcopy <= 2; sectcopy++) { 4908 1.1 reinoud loc = (sectcopy == 1) ? layout.spt_1 : layout.spt_2; 4909 1.1 reinoud dscr = (union dscrptr *) context.sparing_table; 4910 1.1 reinoud len = udf_tagsize(dscr, context.sector_size) / 4911 1.1 reinoud context.sector_size; 4912 1.1 reinoud 4913 1.1 reinoud /* writeout */ 4914 1.1 reinoud error = udf_write_dscr_phys(dscr, loc, len); 4915 1.1 reinoud if (error) 4916 1.1 reinoud return error; 4917 1.1 reinoud } 4918 1.1 reinoud } 4919 1.1 reinoud 4920 1.1 reinoud /* 4921 1.1 reinoud * Create unallocated space bitmap descriptor. Sequential recorded 4922 1.1 reinoud * media report their own free/used space; no free/used space tables 4923 1.1 reinoud * should be recorded for these. 4924 1.1 reinoud */ 4925 1.1 reinoud if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) { 4926 1.1 reinoud error = udf_create_space_bitmap( 4927 1.1 reinoud layout.alloc_bitmap_dscr_size, 4928 1.1 reinoud layout.part_size_lba, 4929 1.1 reinoud &context.part_unalloc_bits[data_part]); 4930 1.1 reinoud if (error) 4931 1.1 reinoud return error; 4932 1.1 reinoud /* TODO: freed space bitmap if applicable */ 4933 1.1 reinoud 4934 1.1 reinoud /* mark space allocated for the unallocated space bitmap */ 4935 1.1 reinoud udf_mark_allocated(layout.unalloc_space, data_part, 4936 1.1 reinoud layout.alloc_bitmap_dscr_size); 4937 1.1 reinoud } 4938 1.1 reinoud 4939 1.1 reinoud /* 4940 1.1 reinoud * Create metadata partition file entries and allocate and init their 4941 1.1 reinoud * space and free space maps. 4942 1.1 reinoud */ 4943 1.1 reinoud if (format_flags & FORMAT_META) { 4944 1.1 reinoud error = udf_create_meta_files(); 4945 1.1 reinoud if (error) 4946 1.1 reinoud return error; 4947 1.1 reinoud 4948 1.1 reinoud /* mark space allocated for meta partition and its bitmap */ 4949 1.1 reinoud udf_mark_allocated(layout.meta_file, data_part, 1); 4950 1.1 reinoud udf_mark_allocated(layout.meta_mirror, data_part, 1); 4951 1.1 reinoud udf_mark_allocated(layout.meta_part_start_lba, data_part, 4952 1.1 reinoud layout.meta_part_size_lba); 4953 1.1 reinoud 4954 1.1 reinoud if (context.meta_bitmap) { 4955 1.1 reinoud /* metadata bitmap creation and accounting */ 4956 1.1 reinoud error = udf_create_space_bitmap( 4957 1.1 reinoud layout.meta_bitmap_dscr_size, 4958 1.1 reinoud layout.meta_part_size_lba, 4959 1.1 reinoud &context.part_unalloc_bits[metadata_part]); 4960 1.1 reinoud if (error) 4961 1.1 reinoud return error; 4962 1.2 riastrad 4963 1.1 reinoud udf_mark_allocated(layout.meta_bitmap, data_part, 1); 4964 1.1 reinoud /* mark space allocated for the unallocated space bitmap */ 4965 1.1 reinoud udf_mark_allocated(layout.meta_bitmap_space, 4966 1.1 reinoud data_part, 4967 1.1 reinoud layout.meta_bitmap_dscr_size); 4968 1.1 reinoud } 4969 1.1 reinoud } 4970 1.1 reinoud 4971 1.1 reinoud /* create logical volume integrity descriptor */ 4972 1.1 reinoud context.num_files = 0; 4973 1.1 reinoud context.num_directories = 0; 4974 1.1 reinoud integrity_type = UDF_INTEGRITY_OPEN; 4975 1.1 reinoud if ((error = udf_create_lvintd(integrity_type))) 4976 1.1 reinoud return error; 4977 1.1 reinoud 4978 1.1 reinoud /* writeout initial open integrity sequence + terminator */ 4979 1.1 reinoud loc = layout.lvis; 4980 1.1 reinoud dscr = (union dscrptr *) context.logvol_integrity; 4981 1.1 reinoud error = udf_write_dscr_phys(dscr, loc, 1); 4982 1.1 reinoud if (error) 4983 1.1 reinoud return error; 4984 1.1 reinoud loc++; 4985 1.1 reinoud error = udf_write_dscr_phys(terminator_dscr, loc, 1); 4986 1.1 reinoud if (error) 4987 1.1 reinoud return error; 4988 1.1 reinoud 4989 1.1 reinoud /* create VAT if needed */ 4990 1.1 reinoud if (format_flags & FORMAT_VAT) { 4991 1.1 reinoud context.vat_allocated = context.sector_size; 4992 1.1 reinoud context.vat_contents = malloc(context.vat_allocated); 4993 1.1 reinoud assert(context.vat_contents); 4994 1.1 reinoud 4995 1.1 reinoud udf_prepend_VAT_file(); 4996 1.1 reinoud } 4997 1.1 reinoud 4998 1.1 reinoud /* create FSD and writeout */ 4999 1.1 reinoud if ((error = udf_create_fsd())) 5000 1.1 reinoud return error; 5001 1.1 reinoud udf_mark_allocated(layout.fsd, metadata_part, 1); 5002 1.1 reinoud 5003 1.1 reinoud dscr = (union dscrptr *) context.fileset_desc; 5004 1.1 reinoud error = udf_write_dscr_virt(dscr, layout.fsd, metadata_part, 1); 5005 1.1 reinoud 5006 1.1 reinoud return error; 5007 1.1 reinoud } 5008 1.1 reinoud 5009 1.1 reinoud 5010 1.1 reinoud /* specific routine for newfs to create empty rootdirectory */ 5011 1.1 reinoud int 5012 1.1 reinoud udf_do_rootdir(void) 5013 1.1 reinoud { 5014 1.1 reinoud union dscrptr *root_dscr; 5015 1.1 reinoud int error; 5016 1.1 reinoud 5017 1.1 reinoud /* create root directory and write out */ 5018 1.1 reinoud assert(context.unique_id == 0x10); 5019 1.1 reinoud context.unique_id = 0; 5020 1.1 reinoud if ((error = udf_create_new_rootdir(&root_dscr))) 5021 1.1 reinoud return error; 5022 1.1 reinoud udf_mark_allocated(layout.rootdir, context.metadata_part, 1); 5023 1.1 reinoud 5024 1.1 reinoud error = udf_write_dscr_virt(root_dscr, 5025 1.1 reinoud layout.rootdir, context.metadata_part, 1); 5026 1.1 reinoud 5027 1.1 reinoud free(root_dscr); 5028 1.1 reinoud 5029 1.1 reinoud return error; 5030 1.1 reinoud } 5031 1.1 reinoud 5032 1.1 reinoud 5033 1.1 reinoud int 5034 1.1 reinoud udf_do_newfs_postfix(void) 5035 1.1 reinoud { 5036 1.1 reinoud union dscrptr *dscr; 5037 1.1 reinoud uint32_t loc, len; 5038 1.1 reinoud int data_part, metadata_part; 5039 1.1 reinoud int format_flags = context.format_flags; 5040 1.1 reinoud int error; 5041 1.1 reinoud 5042 1.1 reinoud /* cache partition for we need it often */ 5043 1.1 reinoud data_part = context.data_part; 5044 1.1 reinoud metadata_part = context.metadata_part; 5045 1.1 reinoud 5046 1.1 reinoud if ((format_flags & FORMAT_SEQUENTIAL) == 0) { 5047 1.1 reinoud /* update lvint and mark it closed */ 5048 1.1 reinoud udf_update_lvintd(UDF_INTEGRITY_CLOSED); 5049 1.1 reinoud 5050 1.1 reinoud /* overwrite initial terminator */ 5051 1.1 reinoud loc = layout.lvis+1; 5052 1.1 reinoud dscr = (union dscrptr *) context.logvol_integrity; 5053 1.1 reinoud error = udf_write_dscr_phys(dscr, loc, 1); 5054 1.1 reinoud if (error) 5055 1.1 reinoud return error; 5056 1.1 reinoud loc++; 5057 1.1 reinoud 5058 1.1 reinoud /* mark end of integrity descriptor sequence again */ 5059 1.1 reinoud error = udf_write_dscr_phys(terminator_dscr, loc, 1); 5060 1.1 reinoud if (error) 5061 1.1 reinoud return error; 5062 1.1 reinoud } 5063 1.1 reinoud 5064 1.1 reinoud /* write out unallocated space bitmap on non sequential media */ 5065 1.1 reinoud if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) { 5066 1.1 reinoud /* writeout unallocated space bitmap */ 5067 1.1 reinoud loc = layout.unalloc_space; 5068 1.1 reinoud dscr = (union dscrptr *) (context.part_unalloc_bits[data_part]); 5069 1.1 reinoud len = layout.alloc_bitmap_dscr_size; 5070 1.1 reinoud error = udf_write_dscr_virt(dscr, loc, data_part, len); 5071 1.1 reinoud if (error) 5072 1.1 reinoud return error; 5073 1.1 reinoud } 5074 1.1 reinoud 5075 1.1 reinoud if (format_flags & FORMAT_META) { 5076 1.1 reinoud loc = layout.meta_file; 5077 1.1 reinoud dscr = (union dscrptr *) context.meta_file; 5078 1.1 reinoud error = udf_write_dscr_virt(dscr, loc, data_part, 1); 5079 1.1 reinoud if (error) 5080 1.1 reinoud return error; 5081 1.2 riastrad 5082 1.1 reinoud loc = layout.meta_mirror; 5083 1.1 reinoud dscr = (union dscrptr *) context.meta_mirror; 5084 1.1 reinoud error = udf_write_dscr_virt(dscr, loc, data_part, 1); 5085 1.1 reinoud if (error) 5086 1.1 reinoud return error; 5087 1.1 reinoud 5088 1.1 reinoud if (context.meta_bitmap) { 5089 1.1 reinoud loc = layout.meta_bitmap; 5090 1.1 reinoud dscr = (union dscrptr *) context.meta_bitmap; 5091 1.1 reinoud error = udf_write_dscr_virt(dscr, loc, data_part, 1); 5092 1.1 reinoud if (error) 5093 1.1 reinoud return error; 5094 1.1 reinoud 5095 1.1 reinoud /* writeout unallocated space bitmap */ 5096 1.1 reinoud loc = layout.meta_bitmap_space; 5097 1.1 reinoud dscr = (union dscrptr *) 5098 1.1 reinoud (context.part_unalloc_bits[metadata_part]); 5099 1.1 reinoud len = layout.meta_bitmap_dscr_size; 5100 1.1 reinoud error = udf_write_dscr_virt(dscr, loc, data_part, len); 5101 1.1 reinoud if (error) 5102 1.1 reinoud return error; 5103 1.1 reinoud } 5104 1.1 reinoud } 5105 1.1 reinoud 5106 1.1 reinoud /* create and writeout a VAT */ 5107 1.1 reinoud if (format_flags & FORMAT_VAT) 5108 1.1 reinoud udf_writeout_VAT(); 5109 1.1 reinoud 5110 1.1 reinoud /* done */ 5111 1.1 reinoud return 0; 5112 1.1 reinoud } 5113