1 1.177 andvar /* $NetBSD: udf_subr.c,v 1.177 2025/03/28 19:34:35 andvar Exp $ */ 2 1.1 reinoud 3 1.1 reinoud /* 4 1.45 reinoud * Copyright (c) 2006, 2008 Reinoud Zandijk 5 1.1 reinoud * All rights reserved. 6 1.152 skrll * 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.152 skrll * 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.152 skrll * 27 1.1 reinoud */ 28 1.1 reinoud 29 1.1 reinoud 30 1.1 reinoud #include <sys/cdefs.h> 31 1.1 reinoud #ifndef lint 32 1.177 andvar __KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.177 2025/03/28 19:34:35 andvar Exp $"); 33 1.1 reinoud #endif /* not lint */ 34 1.1 reinoud 35 1.1 reinoud 36 1.1 reinoud #if defined(_KERNEL_OPT) 37 1.1 reinoud #include "opt_compat_netbsd.h" 38 1.1 reinoud #endif 39 1.1 reinoud 40 1.1 reinoud #include <sys/param.h> 41 1.1 reinoud #include <sys/systm.h> 42 1.1 reinoud #include <sys/sysctl.h> 43 1.1 reinoud #include <sys/namei.h> 44 1.1 reinoud #include <sys/proc.h> 45 1.1 reinoud #include <sys/kernel.h> 46 1.1 reinoud #include <sys/vnode.h> 47 1.1 reinoud #include <miscfs/genfs/genfs_node.h> 48 1.1 reinoud #include <sys/mount.h> 49 1.1 reinoud #include <sys/buf.h> 50 1.1 reinoud #include <sys/file.h> 51 1.1 reinoud #include <sys/device.h> 52 1.1 reinoud #include <sys/disklabel.h> 53 1.1 reinoud #include <sys/ioctl.h> 54 1.1 reinoud #include <sys/malloc.h> 55 1.1 reinoud #include <sys/dirent.h> 56 1.1 reinoud #include <sys/stat.h> 57 1.1 reinoud #include <sys/conf.h> 58 1.8 christos #include <sys/kauth.h> 59 1.48 reinoud #include <fs/unicode.h> 60 1.30 reinoud #include <dev/clock_subr.h> 61 1.1 reinoud 62 1.1 reinoud #include <fs/udf/ecma167-udf.h> 63 1.1 reinoud #include <fs/udf/udf_mount.h> 64 1.73 reinoud #include <sys/dirhash.h> 65 1.1 reinoud 66 1.1 reinoud #include "udf.h" 67 1.1 reinoud #include "udf_subr.h" 68 1.1 reinoud #include "udf_bswap.h" 69 1.1 reinoud 70 1.1 reinoud 71 1.45 reinoud #define VTOI(vnode) ((struct udf_node *) (vnode)->v_data) 72 1.45 reinoud 73 1.45 reinoud #define UDF_SET_SYSTEMFILE(vp) \ 74 1.45 reinoud /* XXXAD Is the vnode locked? */ \ 75 1.45 reinoud (vp)->v_vflag |= VV_SYSTEM; \ 76 1.109 reinoud vref((vp)); \ 77 1.109 reinoud vput((vp)); \ 78 1.1 reinoud 79 1.45 reinoud extern int syncer_maxdelay; /* maximum delay time */ 80 1.45 reinoud extern int (**udf_vnodeop_p)(void *); 81 1.1 reinoud 82 1.45 reinoud /* --------------------------------------------------------------------- */ 83 1.1 reinoud 84 1.45 reinoud //#ifdef DEBUG 85 1.45 reinoud #if 1 86 1.1 reinoud 87 1.1 reinoud #if 0 88 1.45 reinoud static void 89 1.45 reinoud udf_dumpblob(boid *blob, uint32_t dlen) 90 1.1 reinoud { 91 1.45 reinoud int i, j; 92 1.1 reinoud 93 1.1 reinoud printf("blob = %p\n", blob); 94 1.1 reinoud printf("dump of %d bytes\n", dlen); 95 1.1 reinoud 96 1.1 reinoud for (i = 0; i < dlen; i+ = 16) { 97 1.1 reinoud printf("%04x ", i); 98 1.1 reinoud for (j = 0; j < 16; j++) { 99 1.1 reinoud if (i+j < dlen) { 100 1.1 reinoud printf("%02x ", blob[i+j]); 101 1.1 reinoud } else { 102 1.1 reinoud printf(" "); 103 1.9 christos } 104 1.9 christos } 105 1.1 reinoud for (j = 0; j < 16; j++) { 106 1.1 reinoud if (i+j < dlen) { 107 1.1 reinoud if (blob[i+j]>32 && blob[i+j]! = 127) { 108 1.1 reinoud printf("%c", blob[i+j]); 109 1.1 reinoud } else { 110 1.1 reinoud printf("."); 111 1.9 christos } 112 1.9 christos } 113 1.9 christos } 114 1.1 reinoud printf("\n"); 115 1.9 christos } 116 1.1 reinoud printf("\n"); 117 1.45 reinoud Debugger(); 118 1.9 christos } 119 1.1 reinoud #endif 120 1.1 reinoud 121 1.1 reinoud static void 122 1.1 reinoud udf_dump_discinfo(struct udf_mount *ump) 123 1.1 reinoud { 124 1.1 reinoud char bits[128]; 125 1.1 reinoud struct mmc_discinfo *di = &ump->discinfo; 126 1.1 reinoud 127 1.1 reinoud if ((udf_verbose & UDF_DEBUG_VOLUMES) == 0) 128 1.1 reinoud return; 129 1.1 reinoud 130 1.1 reinoud printf("Device/media info :\n"); 131 1.1 reinoud printf("\tMMC profile 0x%02x\n", di->mmc_profile); 132 1.1 reinoud printf("\tderived class %d\n", di->mmc_class); 133 1.1 reinoud printf("\tsector size %d\n", di->sector_size); 134 1.1 reinoud printf("\tdisc state %d\n", di->disc_state); 135 1.1 reinoud printf("\tlast ses state %d\n", di->last_session_state); 136 1.1 reinoud printf("\tbg format state %d\n", di->bg_format_state); 137 1.1 reinoud printf("\tfrst track %d\n", di->first_track); 138 1.1 reinoud printf("\tfst on last ses %d\n", di->first_track_last_session); 139 1.1 reinoud printf("\tlst on last ses %d\n", di->last_track_last_session); 140 1.1 reinoud printf("\tlink block penalty %d\n", di->link_block_penalty); 141 1.80 christos snprintb(bits, sizeof(bits), MMC_DFLAGS_FLAGBITS, di->disc_flags); 142 1.1 reinoud printf("\tdisc flags %s\n", bits); 143 1.1 reinoud printf("\tdisc id %x\n", di->disc_id); 144 1.1 reinoud printf("\tdisc barcode %"PRIx64"\n", di->disc_barcode); 145 1.1 reinoud 146 1.1 reinoud printf("\tnum sessions %d\n", di->num_sessions); 147 1.1 reinoud printf("\tnum tracks %d\n", di->num_tracks); 148 1.1 reinoud 149 1.80 christos snprintb(bits, sizeof(bits), MMC_CAP_FLAGBITS, di->mmc_cur); 150 1.1 reinoud printf("\tcapabilities cur %s\n", bits); 151 1.80 christos snprintb(bits, sizeof(bits), MMC_CAP_FLAGBITS, di->mmc_cap); 152 1.1 reinoud printf("\tcapabilities cap %s\n", bits); 153 1.1 reinoud } 154 1.85 reinoud 155 1.85 reinoud static void 156 1.85 reinoud udf_dump_trackinfo(struct mmc_trackinfo *trackinfo) 157 1.85 reinoud { 158 1.85 reinoud char bits[128]; 159 1.85 reinoud 160 1.85 reinoud if ((udf_verbose & UDF_DEBUG_VOLUMES) == 0) 161 1.85 reinoud return; 162 1.85 reinoud 163 1.85 reinoud printf("Trackinfo for track %d:\n", trackinfo->tracknr); 164 1.85 reinoud printf("\tsessionnr %d\n", trackinfo->sessionnr); 165 1.85 reinoud printf("\ttrack mode %d\n", trackinfo->track_mode); 166 1.85 reinoud printf("\tdata mode %d\n", trackinfo->data_mode); 167 1.85 reinoud snprintb(bits, sizeof(bits), MMC_TRACKINFO_FLAGBITS, trackinfo->flags); 168 1.85 reinoud printf("\tflags %s\n", bits); 169 1.85 reinoud 170 1.85 reinoud printf("\ttrack start %d\n", trackinfo->track_start); 171 1.85 reinoud printf("\tnext_writable %d\n", trackinfo->next_writable); 172 1.85 reinoud printf("\tfree_blocks %d\n", trackinfo->free_blocks); 173 1.85 reinoud printf("\tpacket_size %d\n", trackinfo->packet_size); 174 1.85 reinoud printf("\ttrack size %d\n", trackinfo->track_size); 175 1.85 reinoud printf("\tlast recorded block %d\n", trackinfo->last_recorded); 176 1.85 reinoud } 177 1.85 reinoud 178 1.1 reinoud #else 179 1.1 reinoud #define udf_dump_discinfo(a); 180 1.85 reinoud #define udf_dump_trackinfo(a); 181 1.1 reinoud #endif 182 1.1 reinoud 183 1.45 reinoud 184 1.45 reinoud /* --------------------------------------------------------------------- */ 185 1.45 reinoud 186 1.1 reinoud /* not called often */ 187 1.1 reinoud int 188 1.1 reinoud udf_update_discinfo(struct udf_mount *ump) 189 1.1 reinoud { 190 1.1 reinoud struct vnode *devvp = ump->devvp; 191 1.118 christos uint64_t psize; 192 1.118 christos unsigned secsize; 193 1.1 reinoud struct mmc_discinfo *di; 194 1.1 reinoud int error; 195 1.1 reinoud 196 1.1 reinoud DPRINTF(VOLUMES, ("read/update disc info\n")); 197 1.1 reinoud di = &ump->discinfo; 198 1.1 reinoud memset(di, 0, sizeof(struct mmc_discinfo)); 199 1.1 reinoud 200 1.1 reinoud /* check if we're on a MMC capable device, i.e. CD/DVD */ 201 1.41 pooka error = VOP_IOCTL(devvp, MMCGETDISCINFO, di, FKIOCTL, NOCRED); 202 1.1 reinoud if (error == 0) { 203 1.1 reinoud udf_dump_discinfo(ump); 204 1.1 reinoud return 0; 205 1.9 christos } 206 1.1 reinoud 207 1.1 reinoud /* disc partition support */ 208 1.118 christos error = getdisksize(devvp, &psize, &secsize); 209 1.1 reinoud if (error) 210 1.118 christos return error; 211 1.1 reinoud 212 1.1 reinoud /* set up a disc info profile for partitions */ 213 1.1 reinoud di->mmc_profile = 0x01; /* disc type */ 214 1.1 reinoud di->mmc_class = MMC_CLASS_DISC; 215 1.1 reinoud di->disc_state = MMC_STATE_CLOSED; 216 1.1 reinoud di->last_session_state = MMC_STATE_CLOSED; 217 1.1 reinoud di->bg_format_state = MMC_BGFSTATE_COMPLETED; 218 1.1 reinoud di->link_block_penalty = 0; 219 1.1 reinoud 220 1.1 reinoud di->mmc_cur = MMC_CAP_RECORDABLE | MMC_CAP_REWRITABLE | 221 1.4 reinoud MMC_CAP_ZEROLINKBLK | MMC_CAP_HW_DEFECTFREE; 222 1.1 reinoud di->mmc_cap = di->mmc_cur; 223 1.1 reinoud di->disc_flags = MMC_DFLAGS_UNRESTRICTED; 224 1.1 reinoud 225 1.1 reinoud /* TODO problem with last_possible_lba on resizable VND; request */ 226 1.118 christos di->last_possible_lba = psize; 227 1.118 christos di->sector_size = secsize; 228 1.1 reinoud 229 1.1 reinoud di->num_sessions = 1; 230 1.1 reinoud di->num_tracks = 1; 231 1.1 reinoud 232 1.1 reinoud di->first_track = 1; 233 1.1 reinoud di->first_track_last_session = di->last_track_last_session = 1; 234 1.1 reinoud 235 1.1 reinoud udf_dump_discinfo(ump); 236 1.1 reinoud return 0; 237 1.1 reinoud } 238 1.1 reinoud 239 1.1 reinoud 240 1.1 reinoud int 241 1.1 reinoud udf_update_trackinfo(struct udf_mount *ump, struct mmc_trackinfo *ti) 242 1.1 reinoud { 243 1.1 reinoud struct vnode *devvp = ump->devvp; 244 1.1 reinoud struct mmc_discinfo *di = &ump->discinfo; 245 1.1 reinoud int error, class; 246 1.1 reinoud 247 1.1 reinoud DPRINTF(VOLUMES, ("read track info\n")); 248 1.1 reinoud 249 1.1 reinoud class = di->mmc_class; 250 1.1 reinoud if (class != MMC_CLASS_DISC) { 251 1.1 reinoud /* tracknr specified in struct ti */ 252 1.41 pooka error = VOP_IOCTL(devvp, MMCGETTRACKINFO, ti, FKIOCTL, NOCRED); 253 1.1 reinoud return error; 254 1.9 christos } 255 1.1 reinoud 256 1.1 reinoud /* disc partition support */ 257 1.1 reinoud if (ti->tracknr != 1) 258 1.1 reinoud return EIO; 259 1.1 reinoud 260 1.1 reinoud /* create fake ti (TODO check for resized vnds) */ 261 1.1 reinoud ti->sessionnr = 1; 262 1.1 reinoud 263 1.1 reinoud ti->track_mode = 0; /* XXX */ 264 1.1 reinoud ti->data_mode = 0; /* XXX */ 265 1.1 reinoud ti->flags = MMC_TRACKINFO_LRA_VALID | MMC_TRACKINFO_NWA_VALID; 266 1.1 reinoud 267 1.1 reinoud ti->track_start = 0; 268 1.1 reinoud ti->packet_size = 1; 269 1.1 reinoud 270 1.1 reinoud /* TODO support for resizable vnd */ 271 1.1 reinoud ti->track_size = di->last_possible_lba; 272 1.1 reinoud ti->next_writable = di->last_possible_lba; 273 1.1 reinoud ti->last_recorded = ti->next_writable; 274 1.1 reinoud ti->free_blocks = 0; 275 1.1 reinoud 276 1.1 reinoud return 0; 277 1.1 reinoud } 278 1.1 reinoud 279 1.1 reinoud 280 1.45 reinoud int 281 1.45 reinoud udf_setup_writeparams(struct udf_mount *ump) 282 1.1 reinoud { 283 1.45 reinoud struct mmc_writeparams mmc_writeparams; 284 1.45 reinoud int error; 285 1.45 reinoud 286 1.45 reinoud if (ump->discinfo.mmc_class == MMC_CLASS_DISC) 287 1.45 reinoud return 0; 288 1.45 reinoud 289 1.45 reinoud /* 290 1.45 reinoud * only CD burning normally needs setting up, but other disc types 291 1.45 reinoud * might need other settings to be made. The MMC framework will set up 292 1.155 andvar * the necessary recording parameters according to the disc 293 1.45 reinoud * characteristics read in. Modifications can be made in the discinfo 294 1.45 reinoud * structure passed to change the nature of the disc. 295 1.45 reinoud */ 296 1.45 reinoud 297 1.45 reinoud memset(&mmc_writeparams, 0, sizeof(struct mmc_writeparams)); 298 1.45 reinoud mmc_writeparams.mmc_class = ump->discinfo.mmc_class; 299 1.45 reinoud mmc_writeparams.mmc_cur = ump->discinfo.mmc_cur; 300 1.45 reinoud 301 1.45 reinoud /* 302 1.45 reinoud * UDF dictates first track to determine track mode for the whole 303 1.45 reinoud * disc. [UDF 1.50/6.10.1.1, UDF 1.50/6.10.2.1] 304 1.45 reinoud * To prevent problems with a `reserved' track in front we start with 305 1.45 reinoud * the 2nd track and if that is not valid, go for the 1st. 306 1.45 reinoud */ 307 1.45 reinoud mmc_writeparams.tracknr = 2; 308 1.45 reinoud mmc_writeparams.data_mode = MMC_DATAMODE_DEFAULT; /* XA disc */ 309 1.45 reinoud mmc_writeparams.track_mode = MMC_TRACKMODE_DEFAULT; /* data */ 310 1.45 reinoud 311 1.45 reinoud error = VOP_IOCTL(ump->devvp, MMCSETUPWRITEPARAMS, &mmc_writeparams, 312 1.45 reinoud FKIOCTL, NOCRED); 313 1.45 reinoud if (error) { 314 1.45 reinoud mmc_writeparams.tracknr = 1; 315 1.45 reinoud error = VOP_IOCTL(ump->devvp, MMCSETUPWRITEPARAMS, 316 1.45 reinoud &mmc_writeparams, FKIOCTL, NOCRED); 317 1.45 reinoud } 318 1.45 reinoud return error; 319 1.45 reinoud } 320 1.45 reinoud 321 1.45 reinoud 322 1.138 reinoud void 323 1.138 reinoud udf_mmc_synchronise_caches(struct udf_mount *ump) 324 1.45 reinoud { 325 1.45 reinoud struct mmc_op mmc_op; 326 1.45 reinoud 327 1.138 reinoud DPRINTF(CALL, ("udf_mcc_synchronise_caches()\n")); 328 1.45 reinoud 329 1.45 reinoud if (ump->vfs_mountp->mnt_flag & MNT_RDONLY) 330 1.138 reinoud return; 331 1.45 reinoud 332 1.45 reinoud /* discs are done now */ 333 1.45 reinoud if (ump->discinfo.mmc_class == MMC_CLASS_DISC) 334 1.138 reinoud return; 335 1.45 reinoud 336 1.87 cegger memset(&mmc_op, 0, sizeof(struct mmc_op)); 337 1.45 reinoud mmc_op.operation = MMC_OP_SYNCHRONISECACHE; 338 1.45 reinoud 339 1.45 reinoud /* ignore return code */ 340 1.45 reinoud (void) VOP_IOCTL(ump->devvp, MMCOP, &mmc_op, FKIOCTL, NOCRED); 341 1.45 reinoud } 342 1.45 reinoud 343 1.45 reinoud /* --------------------------------------------------------------------- */ 344 1.45 reinoud 345 1.45 reinoud /* track/session searching for mounting */ 346 1.45 reinoud int 347 1.45 reinoud udf_search_tracks(struct udf_mount *ump, struct udf_args *args, 348 1.45 reinoud int *first_tracknr, int *last_tracknr) 349 1.45 reinoud { 350 1.45 reinoud struct mmc_trackinfo trackinfo; 351 1.45 reinoud uint32_t tracknr, start_track, num_tracks; 352 1.1 reinoud int error; 353 1.1 reinoud 354 1.1 reinoud /* if negative, sessionnr is relative to last session */ 355 1.1 reinoud if (args->sessionnr < 0) { 356 1.1 reinoud args->sessionnr += ump->discinfo.num_sessions; 357 1.9 christos } 358 1.1 reinoud 359 1.1 reinoud /* sanity */ 360 1.45 reinoud if (args->sessionnr < 0) 361 1.45 reinoud args->sessionnr = 0; 362 1.1 reinoud if (args->sessionnr > ump->discinfo.num_sessions) 363 1.1 reinoud args->sessionnr = ump->discinfo.num_sessions; 364 1.1 reinoud 365 1.1 reinoud /* search the tracks for this session, zero session nr indicates last */ 366 1.42 reinoud if (args->sessionnr == 0) 367 1.1 reinoud args->sessionnr = ump->discinfo.num_sessions; 368 1.42 reinoud if (ump->discinfo.last_session_state == MMC_STATE_EMPTY) 369 1.42 reinoud args->sessionnr--; 370 1.42 reinoud 371 1.45 reinoud /* sanity again */ 372 1.45 reinoud if (args->sessionnr < 0) 373 1.45 reinoud args->sessionnr = 0; 374 1.1 reinoud 375 1.1 reinoud /* search the first and last track of the specified session */ 376 1.1 reinoud num_tracks = ump->discinfo.num_tracks; 377 1.1 reinoud start_track = ump->discinfo.first_track; 378 1.1 reinoud 379 1.1 reinoud /* search for first track of this session */ 380 1.1 reinoud for (tracknr = start_track; tracknr <= num_tracks; tracknr++) { 381 1.1 reinoud /* get track info */ 382 1.1 reinoud trackinfo.tracknr = tracknr; 383 1.1 reinoud error = udf_update_trackinfo(ump, &trackinfo); 384 1.1 reinoud if (error) 385 1.1 reinoud return error; 386 1.1 reinoud 387 1.1 reinoud if (trackinfo.sessionnr == args->sessionnr) 388 1.1 reinoud break; 389 1.1 reinoud } 390 1.1 reinoud *first_tracknr = tracknr; 391 1.1 reinoud 392 1.1 reinoud /* search for last track of this session */ 393 1.1 reinoud for (;tracknr <= num_tracks; tracknr++) { 394 1.1 reinoud /* get track info */ 395 1.1 reinoud trackinfo.tracknr = tracknr; 396 1.1 reinoud error = udf_update_trackinfo(ump, &trackinfo); 397 1.1 reinoud if (error || (trackinfo.sessionnr != args->sessionnr)) { 398 1.1 reinoud tracknr--; 399 1.1 reinoud break; 400 1.9 christos } 401 1.9 christos } 402 1.1 reinoud if (tracknr > num_tracks) 403 1.1 reinoud tracknr--; 404 1.1 reinoud 405 1.1 reinoud *last_tracknr = tracknr; 406 1.1 reinoud 407 1.45 reinoud if (*last_tracknr < *first_tracknr) { 408 1.45 reinoud printf( "udf_search_tracks: sanity check on drive+disc failed, " 409 1.45 reinoud "drive returned garbage\n"); 410 1.45 reinoud return EINVAL; 411 1.45 reinoud } 412 1.45 reinoud 413 1.1 reinoud assert(*last_tracknr >= *first_tracknr); 414 1.1 reinoud return 0; 415 1.1 reinoud } 416 1.1 reinoud 417 1.1 reinoud 418 1.45 reinoud /* 419 1.45 reinoud * NOTE: this is the only routine in this file that directly peeks into the 420 1.45 reinoud * metadata file but since its at a larval state of the mount it can't hurt. 421 1.45 reinoud * 422 1.45 reinoud * XXX candidate for udf_allocation.c 423 1.45 reinoud * XXX clean me up!, change to new node reading code. 424 1.45 reinoud */ 425 1.45 reinoud 426 1.45 reinoud static void 427 1.45 reinoud udf_check_track_metadata_overlap(struct udf_mount *ump, 428 1.45 reinoud struct mmc_trackinfo *trackinfo) 429 1.1 reinoud { 430 1.45 reinoud struct part_desc *part; 431 1.45 reinoud struct file_entry *fe; 432 1.45 reinoud struct extfile_entry *efe; 433 1.45 reinoud struct short_ad *s_ad; 434 1.45 reinoud struct long_ad *l_ad; 435 1.45 reinoud uint32_t track_start, track_end; 436 1.45 reinoud uint32_t phys_part_start, phys_part_end, part_start, part_end; 437 1.45 reinoud uint32_t sector_size, len, alloclen, plb_num; 438 1.45 reinoud uint8_t *pos; 439 1.121 christos int addr_type, icblen, icbflags; 440 1.1 reinoud 441 1.45 reinoud /* get our track extents */ 442 1.45 reinoud track_start = trackinfo->track_start; 443 1.45 reinoud track_end = track_start + trackinfo->track_size; 444 1.45 reinoud 445 1.45 reinoud /* get our base partition extent */ 446 1.71 reinoud KASSERT(ump->node_part == ump->fids_part); 447 1.112 reinoud part = ump->partitions[ump->vtop[ump->node_part]]; 448 1.45 reinoud phys_part_start = udf_rw32(part->start_loc); 449 1.45 reinoud phys_part_end = phys_part_start + udf_rw32(part->part_len); 450 1.1 reinoud 451 1.45 reinoud /* no use if its outside the physical partition */ 452 1.45 reinoud if ((phys_part_start >= track_end) || (phys_part_end < track_start)) 453 1.45 reinoud return; 454 1.1 reinoud 455 1.45 reinoud /* 456 1.45 reinoud * now follow all extents in the fe/efe to see if they refer to this 457 1.45 reinoud * track 458 1.45 reinoud */ 459 1.1 reinoud 460 1.45 reinoud sector_size = ump->discinfo.sector_size; 461 1.1 reinoud 462 1.45 reinoud /* XXX should we claim exclusive access to the metafile ? */ 463 1.45 reinoud /* TODO: move to new node read code */ 464 1.45 reinoud fe = ump->metadata_node->fe; 465 1.45 reinoud efe = ump->metadata_node->efe; 466 1.45 reinoud if (fe) { 467 1.45 reinoud alloclen = udf_rw32(fe->l_ad); 468 1.45 reinoud pos = &fe->data[0] + udf_rw32(fe->l_ea); 469 1.45 reinoud icbflags = udf_rw16(fe->icbtag.flags); 470 1.45 reinoud } else { 471 1.45 reinoud assert(efe); 472 1.45 reinoud alloclen = udf_rw32(efe->l_ad); 473 1.45 reinoud pos = &efe->data[0] + udf_rw32(efe->l_ea); 474 1.45 reinoud icbflags = udf_rw16(efe->icbtag.flags); 475 1.9 christos } 476 1.45 reinoud addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 477 1.45 reinoud 478 1.45 reinoud while (alloclen) { 479 1.45 reinoud if (addr_type == UDF_ICB_SHORT_ALLOC) { 480 1.45 reinoud icblen = sizeof(struct short_ad); 481 1.45 reinoud s_ad = (struct short_ad *) pos; 482 1.45 reinoud len = udf_rw32(s_ad->len); 483 1.45 reinoud plb_num = udf_rw32(s_ad->lb_num); 484 1.45 reinoud } else { 485 1.45 reinoud /* should not be present, but why not */ 486 1.45 reinoud icblen = sizeof(struct long_ad); 487 1.45 reinoud l_ad = (struct long_ad *) pos; 488 1.45 reinoud len = udf_rw32(l_ad->len); 489 1.45 reinoud plb_num = udf_rw32(l_ad->loc.lb_num); 490 1.45 reinoud /* pvpart_num = udf_rw16(l_ad->loc.part_num); */ 491 1.45 reinoud } 492 1.45 reinoud /* process extent */ 493 1.45 reinoud len = UDF_EXT_LEN(len); 494 1.1 reinoud 495 1.45 reinoud part_start = phys_part_start + plb_num; 496 1.45 reinoud part_end = part_start + (len / sector_size); 497 1.1 reinoud 498 1.45 reinoud if ((part_start >= track_start) && (part_end <= track_end)) { 499 1.45 reinoud /* extent is enclosed within this track */ 500 1.45 reinoud ump->metadata_track = *trackinfo; 501 1.45 reinoud return; 502 1.45 reinoud } 503 1.1 reinoud 504 1.45 reinoud pos += icblen; 505 1.45 reinoud alloclen -= icblen; 506 1.9 christos } 507 1.45 reinoud } 508 1.45 reinoud 509 1.1 reinoud 510 1.45 reinoud int 511 1.45 reinoud udf_search_writing_tracks(struct udf_mount *ump) 512 1.45 reinoud { 513 1.82 reinoud struct vnode *devvp = ump->devvp; 514 1.45 reinoud struct mmc_trackinfo trackinfo; 515 1.85 reinoud struct mmc_op mmc_op; 516 1.45 reinoud struct part_desc *part; 517 1.45 reinoud uint32_t tracknr, start_track, num_tracks; 518 1.45 reinoud uint32_t track_start, track_end, part_start, part_end; 519 1.71 reinoud int node_alloc, error; 520 1.1 reinoud 521 1.45 reinoud /* 522 1.45 reinoud * in the CD/(HD)DVD/BD recordable device model a few tracks within 523 1.45 reinoud * the last session might be open but in the UDF device model at most 524 1.45 reinoud * three tracks can be open: a reserved track for delayed ISO VRS 525 1.45 reinoud * writing, a data track and a metadata track. We search here for the 526 1.45 reinoud * data track and the metadata track. Note that the reserved track is 527 1.45 reinoud * troublesome but can be detected by its small size of < 512 sectors. 528 1.45 reinoud */ 529 1.1 reinoud 530 1.85 reinoud /* update discinfo since it might have changed */ 531 1.85 reinoud error = udf_update_discinfo(ump); 532 1.85 reinoud if (error) 533 1.85 reinoud return error; 534 1.85 reinoud 535 1.45 reinoud num_tracks = ump->discinfo.num_tracks; 536 1.45 reinoud start_track = ump->discinfo.first_track; 537 1.1 reinoud 538 1.45 reinoud /* fetch info on first and possibly only track */ 539 1.45 reinoud trackinfo.tracknr = start_track; 540 1.45 reinoud error = udf_update_trackinfo(ump, &trackinfo); 541 1.45 reinoud if (error) 542 1.45 reinoud return error; 543 1.13 reinoud 544 1.45 reinoud /* copy results to our mount point */ 545 1.45 reinoud ump->data_track = trackinfo; 546 1.45 reinoud ump->metadata_track = trackinfo; 547 1.1 reinoud 548 1.45 reinoud /* if not sequential, we're done */ 549 1.45 reinoud if (num_tracks == 1) 550 1.45 reinoud return 0; 551 1.1 reinoud 552 1.45 reinoud for (tracknr = start_track;tracknr <= num_tracks; tracknr++) { 553 1.45 reinoud /* get track info */ 554 1.45 reinoud trackinfo.tracknr = tracknr; 555 1.45 reinoud error = udf_update_trackinfo(ump, &trackinfo); 556 1.45 reinoud if (error) 557 1.45 reinoud return error; 558 1.1 reinoud 559 1.82 reinoud /* 560 1.82 reinoud * If this track is marked damaged, ask for repair. This is an 561 1.82 reinoud * optional command, so ignore its error but report warning. 562 1.82 reinoud */ 563 1.82 reinoud if (trackinfo.flags & MMC_TRACKINFO_DAMAGED) { 564 1.85 reinoud memset(&mmc_op, 0, sizeof(mmc_op)); 565 1.85 reinoud mmc_op.operation = MMC_OP_REPAIRTRACK; 566 1.85 reinoud mmc_op.mmc_profile = ump->discinfo.mmc_profile; 567 1.85 reinoud mmc_op.tracknr = tracknr; 568 1.85 reinoud error = VOP_IOCTL(devvp, MMCOP, &mmc_op, FKIOCTL, NOCRED); 569 1.82 reinoud if (error) 570 1.82 reinoud (void)printf("Drive can't explicitly repair " 571 1.82 reinoud "damaged track %d, but it might " 572 1.82 reinoud "autorepair\n", tracknr); 573 1.82 reinoud 574 1.82 reinoud /* reget track info */ 575 1.82 reinoud error = udf_update_trackinfo(ump, &trackinfo); 576 1.82 reinoud if (error) 577 1.82 reinoud return error; 578 1.82 reinoud } 579 1.45 reinoud if ((trackinfo.flags & MMC_TRACKINFO_NWA_VALID) == 0) 580 1.45 reinoud continue; 581 1.85 reinoud 582 1.45 reinoud track_start = trackinfo.track_start; 583 1.45 reinoud track_end = track_start + trackinfo.track_size; 584 1.1 reinoud 585 1.45 reinoud /* check for overlap on data partition */ 586 1.45 reinoud part = ump->partitions[ump->data_part]; 587 1.45 reinoud part_start = udf_rw32(part->start_loc); 588 1.45 reinoud part_end = part_start + udf_rw32(part->part_len); 589 1.45 reinoud if ((part_start < track_end) && (part_end > track_start)) { 590 1.45 reinoud ump->data_track = trackinfo; 591 1.45 reinoud /* TODO check if UDF partition data_part is writable */ 592 1.45 reinoud } 593 1.45 reinoud 594 1.45 reinoud /* check for overlap on metadata partition */ 595 1.71 reinoud node_alloc = ump->vtop_alloc[ump->node_part]; 596 1.71 reinoud if ((node_alloc == UDF_ALLOC_METASEQUENTIAL) || 597 1.71 reinoud (node_alloc == UDF_ALLOC_METABITMAP)) { 598 1.45 reinoud udf_check_track_metadata_overlap(ump, &trackinfo); 599 1.45 reinoud } else { 600 1.45 reinoud ump->metadata_track = trackinfo; 601 1.9 christos } 602 1.45 reinoud } 603 1.1 reinoud 604 1.45 reinoud if ((ump->data_track.flags & MMC_TRACKINFO_NWA_VALID) == 0) 605 1.45 reinoud return EROFS; 606 1.1 reinoud 607 1.45 reinoud if ((ump->metadata_track.flags & MMC_TRACKINFO_NWA_VALID) == 0) 608 1.45 reinoud return EROFS; 609 1.1 reinoud 610 1.1 reinoud return 0; 611 1.1 reinoud } 612 1.1 reinoud 613 1.1 reinoud /* --------------------------------------------------------------------- */ 614 1.1 reinoud 615 1.45 reinoud /* 616 1.45 reinoud * Check if the blob starts with a good UDF tag. Tags are protected by a 617 1.162 reinoud * checksum over the header except one byte at position 4 that is the checksum 618 1.45 reinoud * itself. 619 1.45 reinoud */ 620 1.45 reinoud 621 1.45 reinoud int 622 1.45 reinoud udf_check_tag(void *blob) 623 1.1 reinoud { 624 1.45 reinoud struct desc_tag *tag = blob; 625 1.45 reinoud uint8_t *pos, sum, cnt; 626 1.1 reinoud 627 1.45 reinoud /* check TAG header checksum */ 628 1.45 reinoud pos = (uint8_t *) tag; 629 1.45 reinoud sum = 0; 630 1.45 reinoud 631 1.45 reinoud for(cnt = 0; cnt < 16; cnt++) { 632 1.45 reinoud if (cnt != 4) 633 1.45 reinoud sum += *pos; 634 1.45 reinoud pos++; 635 1.45 reinoud } 636 1.45 reinoud if (sum != tag->cksum) { 637 1.45 reinoud /* bad tag header checksum; this is not a valid tag */ 638 1.45 reinoud return EINVAL; 639 1.45 reinoud } 640 1.45 reinoud 641 1.45 reinoud return 0; 642 1.45 reinoud } 643 1.45 reinoud 644 1.45 reinoud 645 1.45 reinoud /* 646 1.45 reinoud * check tag payload will check descriptor CRC as specified. 647 1.45 reinoud * If the descriptor is too long, it will return EIO otherwise EINVAL. 648 1.45 reinoud */ 649 1.1 reinoud 650 1.45 reinoud int 651 1.45 reinoud udf_check_tag_payload(void *blob, uint32_t max_length) 652 1.45 reinoud { 653 1.45 reinoud struct desc_tag *tag = blob; 654 1.45 reinoud uint16_t crc, crc_len; 655 1.1 reinoud 656 1.45 reinoud crc_len = udf_rw16(tag->desc_crc_len); 657 1.1 reinoud 658 1.45 reinoud /* check payload CRC if applicable */ 659 1.45 reinoud if (crc_len == 0) 660 1.45 reinoud return 0; 661 1.1 reinoud 662 1.45 reinoud if (crc_len > max_length) 663 1.45 reinoud return EIO; 664 1.1 reinoud 665 1.45 reinoud crc = udf_cksum(((uint8_t *) tag) + UDF_DESC_TAG_LENGTH, crc_len); 666 1.45 reinoud if (crc != udf_rw16(tag->desc_crc)) { 667 1.45 reinoud /* bad payload CRC; this is a broken tag */ 668 1.45 reinoud return EINVAL; 669 1.9 christos } 670 1.1 reinoud 671 1.45 reinoud return 0; 672 1.1 reinoud } 673 1.1 reinoud 674 1.1 reinoud 675 1.45 reinoud void 676 1.45 reinoud udf_validate_tag_sum(void *blob) 677 1.1 reinoud { 678 1.45 reinoud struct desc_tag *tag = blob; 679 1.45 reinoud uint8_t *pos, sum, cnt; 680 1.1 reinoud 681 1.45 reinoud /* calculate TAG header checksum */ 682 1.45 reinoud pos = (uint8_t *) tag; 683 1.45 reinoud sum = 0; 684 1.1 reinoud 685 1.45 reinoud for(cnt = 0; cnt < 16; cnt++) { 686 1.45 reinoud if (cnt != 4) sum += *pos; 687 1.45 reinoud pos++; 688 1.45 reinoud } 689 1.45 reinoud tag->cksum = sum; /* 8 bit */ 690 1.45 reinoud } 691 1.1 reinoud 692 1.1 reinoud 693 1.45 reinoud /* assumes sector number of descriptor to be saved already present */ 694 1.45 reinoud void 695 1.45 reinoud udf_validate_tag_and_crc_sums(void *blob) 696 1.45 reinoud { 697 1.45 reinoud struct desc_tag *tag = blob; 698 1.45 reinoud uint8_t *btag = (uint8_t *) tag; 699 1.45 reinoud uint16_t crc, crc_len; 700 1.1 reinoud 701 1.45 reinoud crc_len = udf_rw16(tag->desc_crc_len); 702 1.1 reinoud 703 1.45 reinoud /* check payload CRC if applicable */ 704 1.45 reinoud if (crc_len > 0) { 705 1.45 reinoud crc = udf_cksum(btag + UDF_DESC_TAG_LENGTH, crc_len); 706 1.45 reinoud tag->desc_crc = udf_rw16(crc); 707 1.9 christos } 708 1.1 reinoud 709 1.45 reinoud /* calculate TAG header checksum */ 710 1.45 reinoud udf_validate_tag_sum(blob); 711 1.1 reinoud } 712 1.1 reinoud 713 1.1 reinoud /* --------------------------------------------------------------------- */ 714 1.1 reinoud 715 1.1 reinoud /* 716 1.45 reinoud * XXX note the different semantics from udfclient: for FIDs it still rounds 717 1.45 reinoud * up to sectors. Use udf_fidsize() for a correct length. 718 1.1 reinoud */ 719 1.1 reinoud 720 1.45 reinoud int 721 1.45 reinoud udf_tagsize(union dscrptr *dscr, uint32_t lb_size) 722 1.1 reinoud { 723 1.45 reinoud uint32_t size, tag_id, num_lb, elmsz; 724 1.1 reinoud 725 1.45 reinoud tag_id = udf_rw16(dscr->tag.id); 726 1.1 reinoud 727 1.45 reinoud switch (tag_id) { 728 1.45 reinoud case TAGID_LOGVOL : 729 1.45 reinoud size = sizeof(struct logvol_desc) - 1; 730 1.45 reinoud size += udf_rw32(dscr->lvd.mt_l); 731 1.45 reinoud break; 732 1.45 reinoud case TAGID_UNALLOC_SPACE : 733 1.45 reinoud elmsz = sizeof(struct extent_ad); 734 1.45 reinoud size = sizeof(struct unalloc_sp_desc) - elmsz; 735 1.45 reinoud size += udf_rw32(dscr->usd.alloc_desc_num) * elmsz; 736 1.45 reinoud break; 737 1.45 reinoud case TAGID_FID : 738 1.45 reinoud size = UDF_FID_SIZE + dscr->fid.l_fi + udf_rw16(dscr->fid.l_iu); 739 1.45 reinoud size = (size + 3) & ~3; 740 1.45 reinoud break; 741 1.45 reinoud case TAGID_LOGVOL_INTEGRITY : 742 1.45 reinoud size = sizeof(struct logvol_int_desc) - sizeof(uint32_t); 743 1.45 reinoud size += udf_rw32(dscr->lvid.l_iu); 744 1.45 reinoud size += (2 * udf_rw32(dscr->lvid.num_part) * sizeof(uint32_t)); 745 1.45 reinoud break; 746 1.45 reinoud case TAGID_SPACE_BITMAP : 747 1.45 reinoud size = sizeof(struct space_bitmap_desc) - 1; 748 1.45 reinoud size += udf_rw32(dscr->sbd.num_bytes); 749 1.45 reinoud break; 750 1.45 reinoud case TAGID_SPARING_TABLE : 751 1.45 reinoud elmsz = sizeof(struct spare_map_entry); 752 1.45 reinoud size = sizeof(struct udf_sparing_table) - elmsz; 753 1.45 reinoud size += udf_rw16(dscr->spt.rt_l) * elmsz; 754 1.45 reinoud break; 755 1.45 reinoud case TAGID_FENTRY : 756 1.45 reinoud size = sizeof(struct file_entry); 757 1.45 reinoud size += udf_rw32(dscr->fe.l_ea) + udf_rw32(dscr->fe.l_ad)-1; 758 1.45 reinoud break; 759 1.45 reinoud case TAGID_EXTFENTRY : 760 1.45 reinoud size = sizeof(struct extfile_entry); 761 1.45 reinoud size += udf_rw32(dscr->efe.l_ea) + udf_rw32(dscr->efe.l_ad)-1; 762 1.45 reinoud break; 763 1.45 reinoud case TAGID_FSD : 764 1.45 reinoud size = sizeof(struct fileset_desc); 765 1.45 reinoud break; 766 1.45 reinoud default : 767 1.45 reinoud size = sizeof(union dscrptr); 768 1.45 reinoud break; 769 1.45 reinoud } 770 1.1 reinoud 771 1.70 reinoud if ((size == 0) || (lb_size == 0)) 772 1.70 reinoud return 0; 773 1.70 reinoud 774 1.70 reinoud if (lb_size == 1) 775 1.70 reinoud return size; 776 1.1 reinoud 777 1.45 reinoud /* round up in sectors */ 778 1.45 reinoud num_lb = (size + lb_size -1) / lb_size; 779 1.45 reinoud return num_lb * lb_size; 780 1.45 reinoud } 781 1.1 reinoud 782 1.1 reinoud 783 1.45 reinoud int 784 1.45 reinoud udf_fidsize(struct fileid_desc *fid) 785 1.45 reinoud { 786 1.45 reinoud uint32_t size; 787 1.3 reinoud 788 1.45 reinoud if (udf_rw16(fid->tag.id) != TAGID_FID) 789 1.45 reinoud panic("got udf_fidsize on non FID\n"); 790 1.1 reinoud 791 1.45 reinoud size = UDF_FID_SIZE + fid->l_fi + udf_rw16(fid->l_iu); 792 1.45 reinoud size = (size + 3) & ~3; 793 1.1 reinoud 794 1.45 reinoud return size; 795 1.1 reinoud } 796 1.1 reinoud 797 1.1 reinoud /* --------------------------------------------------------------------- */ 798 1.1 reinoud 799 1.45 reinoud void 800 1.45 reinoud udf_lock_node(struct udf_node *udf_node, int flag, char const *fname, const int lineno) 801 1.45 reinoud { 802 1.45 reinoud int ret; 803 1.45 reinoud 804 1.45 reinoud mutex_enter(&udf_node->node_mutex); 805 1.45 reinoud /* wait until free */ 806 1.45 reinoud while (udf_node->i_flags & IN_LOCKED) { 807 1.45 reinoud ret = cv_timedwait(&udf_node->node_lock, &udf_node->node_mutex, hz/8); 808 1.45 reinoud /* TODO check if we should return error; abort */ 809 1.45 reinoud if (ret == EWOULDBLOCK) { 810 1.45 reinoud DPRINTF(LOCKING, ( "udf_lock_node: udf_node %p would block " 811 1.45 reinoud "wanted at %s:%d, previously locked at %s:%d\n", 812 1.152 skrll udf_node, fname, lineno, 813 1.45 reinoud udf_node->lock_fname, udf_node->lock_lineno)); 814 1.45 reinoud } 815 1.45 reinoud } 816 1.45 reinoud /* grab */ 817 1.45 reinoud udf_node->i_flags |= IN_LOCKED | flag; 818 1.45 reinoud /* debug */ 819 1.45 reinoud udf_node->lock_fname = fname; 820 1.45 reinoud udf_node->lock_lineno = lineno; 821 1.45 reinoud 822 1.45 reinoud mutex_exit(&udf_node->node_mutex); 823 1.45 reinoud } 824 1.45 reinoud 825 1.1 reinoud 826 1.45 reinoud void 827 1.45 reinoud udf_unlock_node(struct udf_node *udf_node, int flag) 828 1.22 christos { 829 1.45 reinoud mutex_enter(&udf_node->node_mutex); 830 1.45 reinoud udf_node->i_flags &= ~(IN_LOCKED | flag); 831 1.45 reinoud cv_broadcast(&udf_node->node_lock); 832 1.45 reinoud mutex_exit(&udf_node->node_mutex); 833 1.45 reinoud } 834 1.1 reinoud 835 1.1 reinoud 836 1.45 reinoud /* --------------------------------------------------------------------- */ 837 1.1 reinoud 838 1.45 reinoud static int 839 1.45 reinoud udf_read_anchor(struct udf_mount *ump, uint32_t sector, struct anchor_vdp **dst) 840 1.45 reinoud { 841 1.45 reinoud int error; 842 1.45 reinoud 843 1.45 reinoud error = udf_read_phys_dscr(ump, sector, M_UDFVOLD, 844 1.45 reinoud (union dscrptr **) dst); 845 1.45 reinoud if (!error) { 846 1.45 reinoud /* blank terminator blocks are not allowed here */ 847 1.45 reinoud if (*dst == NULL) 848 1.45 reinoud return ENOENT; 849 1.45 reinoud if (udf_rw16((*dst)->tag.id) != TAGID_ANCHOR) { 850 1.45 reinoud error = ENOENT; 851 1.45 reinoud free(*dst, M_UDFVOLD); 852 1.45 reinoud *dst = NULL; 853 1.45 reinoud DPRINTF(VOLUMES, ("Not an anchor\n")); 854 1.45 reinoud } 855 1.45 reinoud } 856 1.45 reinoud 857 1.45 reinoud return error; 858 1.45 reinoud } 859 1.45 reinoud 860 1.45 reinoud 861 1.45 reinoud int 862 1.45 reinoud udf_read_anchors(struct udf_mount *ump) 863 1.45 reinoud { 864 1.45 reinoud struct udf_args *args = &ump->mount_args; 865 1.45 reinoud struct mmc_trackinfo first_track; 866 1.45 reinoud struct mmc_trackinfo second_track; 867 1.45 reinoud struct mmc_trackinfo last_track; 868 1.45 reinoud struct anchor_vdp **anchorsp; 869 1.45 reinoud uint32_t track_start; 870 1.45 reinoud uint32_t track_end; 871 1.45 reinoud uint32_t positions[4]; 872 1.45 reinoud int first_tracknr, last_tracknr; 873 1.45 reinoud int error, anch, ok, first_anchor; 874 1.45 reinoud 875 1.45 reinoud /* search the first and last track of the specified session */ 876 1.45 reinoud error = udf_search_tracks(ump, args, &first_tracknr, &last_tracknr); 877 1.45 reinoud if (!error) { 878 1.45 reinoud first_track.tracknr = first_tracknr; 879 1.45 reinoud error = udf_update_trackinfo(ump, &first_track); 880 1.45 reinoud } 881 1.45 reinoud if (!error) { 882 1.45 reinoud last_track.tracknr = last_tracknr; 883 1.45 reinoud error = udf_update_trackinfo(ump, &last_track); 884 1.45 reinoud } 885 1.45 reinoud if ((!error) && (first_tracknr != last_tracknr)) { 886 1.45 reinoud second_track.tracknr = first_tracknr+1; 887 1.45 reinoud error = udf_update_trackinfo(ump, &second_track); 888 1.45 reinoud } 889 1.45 reinoud if (error) { 890 1.45 reinoud printf("UDF mount: reading disc geometry failed\n"); 891 1.45 reinoud return 0; 892 1.45 reinoud } 893 1.45 reinoud 894 1.45 reinoud track_start = first_track.track_start; 895 1.1 reinoud 896 1.45 reinoud /* `end' is not as straitforward as start. */ 897 1.45 reinoud track_end = last_track.track_start 898 1.45 reinoud + last_track.track_size - last_track.free_blocks - 1; 899 1.1 reinoud 900 1.45 reinoud if (ump->discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) { 901 1.45 reinoud /* end of track is not straitforward here */ 902 1.45 reinoud if (last_track.flags & MMC_TRACKINFO_LRA_VALID) 903 1.45 reinoud track_end = last_track.last_recorded; 904 1.45 reinoud else if (last_track.flags & MMC_TRACKINFO_NWA_VALID) 905 1.45 reinoud track_end = last_track.next_writable 906 1.45 reinoud - ump->discinfo.link_block_penalty; 907 1.9 christos } 908 1.1 reinoud 909 1.45 reinoud /* its no use reading a blank track */ 910 1.45 reinoud first_anchor = 0; 911 1.45 reinoud if (first_track.flags & MMC_TRACKINFO_BLANK) 912 1.45 reinoud first_anchor = 1; 913 1.45 reinoud 914 1.45 reinoud /* get our packet size */ 915 1.45 reinoud ump->packet_size = first_track.packet_size; 916 1.45 reinoud if (first_track.flags & MMC_TRACKINFO_BLANK) 917 1.45 reinoud ump->packet_size = second_track.packet_size; 918 1.45 reinoud 919 1.45 reinoud if (ump->packet_size <= 1) { 920 1.45 reinoud /* take max, but not bigger than 64 */ 921 1.45 reinoud ump->packet_size = MAXPHYS / ump->discinfo.sector_size; 922 1.45 reinoud ump->packet_size = MIN(ump->packet_size, 64); 923 1.9 christos } 924 1.45 reinoud KASSERT(ump->packet_size >= 1); 925 1.1 reinoud 926 1.45 reinoud /* read anchors start+256, start+512, end-256, end */ 927 1.45 reinoud positions[0] = track_start+256; 928 1.45 reinoud positions[1] = track_end-256; 929 1.45 reinoud positions[2] = track_end; 930 1.45 reinoud positions[3] = track_start+512; /* [UDF 2.60/6.11.2] */ 931 1.151 skrll /* XXX shouldn't +512 be preferred over +256 for compat with Roxio CD */ 932 1.1 reinoud 933 1.45 reinoud ok = 0; 934 1.45 reinoud anchorsp = ump->anchors; 935 1.45 reinoud for (anch = first_anchor; anch < 4; anch++) { 936 1.45 reinoud DPRINTF(VOLUMES, ("Read anchor %d at sector %d\n", anch, 937 1.45 reinoud positions[anch])); 938 1.45 reinoud error = udf_read_anchor(ump, positions[anch], anchorsp); 939 1.45 reinoud if (!error) { 940 1.45 reinoud anchorsp++; 941 1.45 reinoud ok++; 942 1.45 reinoud } 943 1.45 reinoud } 944 1.1 reinoud 945 1.45 reinoud /* VATs are only recorded on sequential media, but initialise */ 946 1.45 reinoud ump->first_possible_vat_location = track_start + 2; 947 1.137 reinoud ump->last_possible_vat_location = track_end; 948 1.1 reinoud 949 1.45 reinoud return ok; 950 1.45 reinoud } 951 1.1 reinoud 952 1.45 reinoud /* --------------------------------------------------------------------- */ 953 1.1 reinoud 954 1.95 reinoud int 955 1.95 reinoud udf_get_c_type(struct udf_node *udf_node) 956 1.95 reinoud { 957 1.95 reinoud int isdir, what; 958 1.95 reinoud 959 1.95 reinoud isdir = (udf_node->vnode->v_type == VDIR); 960 1.95 reinoud what = isdir ? UDF_C_FIDS : UDF_C_USERDATA; 961 1.95 reinoud 962 1.95 reinoud if (udf_node->ump) 963 1.95 reinoud if (udf_node == udf_node->ump->metadatabitmap_node) 964 1.95 reinoud what = UDF_C_METADATA_SBM; 965 1.95 reinoud 966 1.95 reinoud return what; 967 1.95 reinoud } 968 1.95 reinoud 969 1.95 reinoud 970 1.95 reinoud int 971 1.95 reinoud udf_get_record_vpart(struct udf_mount *ump, int udf_c_type) 972 1.95 reinoud { 973 1.95 reinoud int vpart_num; 974 1.95 reinoud 975 1.95 reinoud vpart_num = ump->data_part; 976 1.95 reinoud if (udf_c_type == UDF_C_NODE) 977 1.95 reinoud vpart_num = ump->node_part; 978 1.95 reinoud if (udf_c_type == UDF_C_FIDS) 979 1.95 reinoud vpart_num = ump->fids_part; 980 1.95 reinoud 981 1.95 reinoud return vpart_num; 982 1.95 reinoud } 983 1.95 reinoud 984 1.111 reinoud 985 1.152 skrll /* 986 1.111 reinoud * BUGALERT: some rogue implementations use random physical partition 987 1.111 reinoud * numbers to break other implementations so lookup the number. 988 1.111 reinoud */ 989 1.111 reinoud 990 1.111 reinoud static uint16_t 991 1.111 reinoud udf_find_raw_phys(struct udf_mount *ump, uint16_t raw_phys_part) 992 1.111 reinoud { 993 1.111 reinoud struct part_desc *part; 994 1.111 reinoud uint16_t phys_part; 995 1.111 reinoud 996 1.111 reinoud for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 997 1.111 reinoud part = ump->partitions[phys_part]; 998 1.111 reinoud if (part == NULL) 999 1.111 reinoud break; 1000 1.111 reinoud if (udf_rw16(part->part_num) == raw_phys_part) 1001 1.111 reinoud break; 1002 1.111 reinoud } 1003 1.111 reinoud return phys_part; 1004 1.111 reinoud } 1005 1.111 reinoud 1006 1.95 reinoud /* --------------------------------------------------------------------- */ 1007 1.95 reinoud 1008 1.45 reinoud /* we dont try to be smart; we just record the parts */ 1009 1.45 reinoud #define UDF_UPDATE_DSCR(name, dscr) \ 1010 1.45 reinoud if (name) \ 1011 1.45 reinoud free(name, M_UDFVOLD); \ 1012 1.45 reinoud name = dscr; 1013 1.1 reinoud 1014 1.45 reinoud static int 1015 1.45 reinoud udf_process_vds_descriptor(struct udf_mount *ump, union dscrptr *dscr) 1016 1.45 reinoud { 1017 1.45 reinoud uint16_t phys_part, raw_phys_part; 1018 1.1 reinoud 1019 1.45 reinoud DPRINTF(VOLUMES, ("\tprocessing VDS descr %d\n", 1020 1.45 reinoud udf_rw16(dscr->tag.id))); 1021 1.45 reinoud switch (udf_rw16(dscr->tag.id)) { 1022 1.45 reinoud case TAGID_PRI_VOL : /* primary partition */ 1023 1.45 reinoud UDF_UPDATE_DSCR(ump->primary_vol, &dscr->pvd); 1024 1.45 reinoud break; 1025 1.45 reinoud case TAGID_LOGVOL : /* logical volume */ 1026 1.45 reinoud UDF_UPDATE_DSCR(ump->logical_vol, &dscr->lvd); 1027 1.45 reinoud break; 1028 1.45 reinoud case TAGID_UNALLOC_SPACE : /* unallocated space */ 1029 1.45 reinoud UDF_UPDATE_DSCR(ump->unallocated, &dscr->usd); 1030 1.45 reinoud break; 1031 1.45 reinoud case TAGID_IMP_VOL : /* implementation */ 1032 1.45 reinoud /* XXX do we care about multiple impl. descr ? */ 1033 1.45 reinoud UDF_UPDATE_DSCR(ump->implementation, &dscr->ivd); 1034 1.45 reinoud break; 1035 1.45 reinoud case TAGID_PARTITION : /* physical partition */ 1036 1.45 reinoud /* not much use if its not allocated */ 1037 1.45 reinoud if ((udf_rw16(dscr->pd.flags) & UDF_PART_FLAG_ALLOCATED) == 0) { 1038 1.45 reinoud free(dscr, M_UDFVOLD); 1039 1.1 reinoud break; 1040 1.9 christos } 1041 1.1 reinoud 1042 1.33 reinoud /* 1043 1.33 reinoud * BUGALERT: some rogue implementations use random physical 1044 1.100 mbalmer * partition numbers to break other implementations so lookup 1045 1.33 reinoud * the number. 1046 1.33 reinoud */ 1047 1.45 reinoud raw_phys_part = udf_rw16(dscr->pd.part_num); 1048 1.111 reinoud phys_part = udf_find_raw_phys(ump, raw_phys_part); 1049 1.111 reinoud 1050 1.45 reinoud if (phys_part == UDF_PARTITIONS) { 1051 1.45 reinoud free(dscr, M_UDFVOLD); 1052 1.1 reinoud return EINVAL; 1053 1.45 reinoud } 1054 1.1 reinoud 1055 1.45 reinoud UDF_UPDATE_DSCR(ump->partitions[phys_part], &dscr->pd); 1056 1.45 reinoud break; 1057 1.45 reinoud case TAGID_VOL : /* volume space extender; rare */ 1058 1.45 reinoud DPRINTF(VOLUMES, ("VDS extender ignored\n")); 1059 1.45 reinoud free(dscr, M_UDFVOLD); 1060 1.45 reinoud break; 1061 1.45 reinoud default : 1062 1.45 reinoud DPRINTF(VOLUMES, ("Unhandled VDS type %d\n", 1063 1.45 reinoud udf_rw16(dscr->tag.id))); 1064 1.45 reinoud free(dscr, M_UDFVOLD); 1065 1.9 christos } 1066 1.1 reinoud 1067 1.45 reinoud return 0; 1068 1.45 reinoud } 1069 1.45 reinoud #undef UDF_UPDATE_DSCR 1070 1.1 reinoud 1071 1.45 reinoud /* --------------------------------------------------------------------- */ 1072 1.1 reinoud 1073 1.45 reinoud static int 1074 1.45 reinoud udf_read_vds_extent(struct udf_mount *ump, uint32_t loc, uint32_t len) 1075 1.45 reinoud { 1076 1.45 reinoud union dscrptr *dscr; 1077 1.45 reinoud uint32_t sector_size, dscr_size; 1078 1.45 reinoud int error; 1079 1.1 reinoud 1080 1.45 reinoud sector_size = ump->discinfo.sector_size; 1081 1.1 reinoud 1082 1.45 reinoud /* loc is sectornr, len is in bytes */ 1083 1.45 reinoud error = EIO; 1084 1.45 reinoud while (len) { 1085 1.45 reinoud error = udf_read_phys_dscr(ump, loc, M_UDFVOLD, &dscr); 1086 1.45 reinoud if (error) 1087 1.45 reinoud return error; 1088 1.45 reinoud 1089 1.45 reinoud /* blank block is a terminator */ 1090 1.45 reinoud if (dscr == NULL) 1091 1.45 reinoud return 0; 1092 1.45 reinoud 1093 1.45 reinoud /* TERM descriptor is a terminator */ 1094 1.45 reinoud if (udf_rw16(dscr->tag.id) == TAGID_TERM) { 1095 1.45 reinoud free(dscr, M_UDFVOLD); 1096 1.45 reinoud return 0; 1097 1.45 reinoud } 1098 1.45 reinoud 1099 1.45 reinoud /* process all others */ 1100 1.45 reinoud dscr_size = udf_tagsize(dscr, sector_size); 1101 1.45 reinoud error = udf_process_vds_descriptor(ump, dscr); 1102 1.45 reinoud if (error) { 1103 1.45 reinoud free(dscr, M_UDFVOLD); 1104 1.45 reinoud break; 1105 1.45 reinoud } 1106 1.45 reinoud assert((dscr_size % sector_size) == 0); 1107 1.45 reinoud 1108 1.45 reinoud len -= dscr_size; 1109 1.45 reinoud loc += dscr_size / sector_size; 1110 1.45 reinoud } 1111 1.45 reinoud 1112 1.45 reinoud return error; 1113 1.45 reinoud } 1114 1.45 reinoud 1115 1.45 reinoud 1116 1.45 reinoud int 1117 1.45 reinoud udf_read_vds_space(struct udf_mount *ump) 1118 1.45 reinoud { 1119 1.45 reinoud /* struct udf_args *args = &ump->mount_args; */ 1120 1.45 reinoud struct anchor_vdp *anchor, *anchor2; 1121 1.45 reinoud size_t size; 1122 1.45 reinoud uint32_t main_loc, main_len; 1123 1.45 reinoud uint32_t reserve_loc, reserve_len; 1124 1.45 reinoud int error; 1125 1.45 reinoud 1126 1.45 reinoud /* 1127 1.45 reinoud * read in VDS space provided by the anchors; if one descriptor read 1128 1.45 reinoud * fails, try the mirror sector. 1129 1.45 reinoud * 1130 1.45 reinoud * check if 2nd anchor is different from 1st; if so, go for 2nd. This 1131 1.45 reinoud * avoids the `compatibility features' of DirectCD that may confuse 1132 1.45 reinoud * stuff completely. 1133 1.45 reinoud */ 1134 1.45 reinoud 1135 1.45 reinoud anchor = ump->anchors[0]; 1136 1.45 reinoud anchor2 = ump->anchors[1]; 1137 1.45 reinoud assert(anchor); 1138 1.45 reinoud 1139 1.45 reinoud if (anchor2) { 1140 1.45 reinoud size = sizeof(struct extent_ad); 1141 1.45 reinoud if (memcmp(&anchor->main_vds_ex, &anchor2->main_vds_ex, size)) 1142 1.45 reinoud anchor = anchor2; 1143 1.45 reinoud /* reserve is specified to be a literal copy of main */ 1144 1.45 reinoud } 1145 1.45 reinoud 1146 1.45 reinoud main_loc = udf_rw32(anchor->main_vds_ex.loc); 1147 1.45 reinoud main_len = udf_rw32(anchor->main_vds_ex.len); 1148 1.45 reinoud 1149 1.45 reinoud reserve_loc = udf_rw32(anchor->reserve_vds_ex.loc); 1150 1.45 reinoud reserve_len = udf_rw32(anchor->reserve_vds_ex.len); 1151 1.45 reinoud 1152 1.45 reinoud error = udf_read_vds_extent(ump, main_loc, main_len); 1153 1.45 reinoud if (error) { 1154 1.45 reinoud printf("UDF mount: reading in reserve VDS extent\n"); 1155 1.45 reinoud error = udf_read_vds_extent(ump, reserve_loc, reserve_len); 1156 1.45 reinoud } 1157 1.45 reinoud 1158 1.45 reinoud return error; 1159 1.45 reinoud } 1160 1.45 reinoud 1161 1.45 reinoud /* --------------------------------------------------------------------- */ 1162 1.45 reinoud 1163 1.45 reinoud /* 1164 1.45 reinoud * Read in the logical volume integrity sequence pointed to by our logical 1165 1.45 reinoud * volume descriptor. Its a sequence that can be extended using fields in the 1166 1.45 reinoud * integrity descriptor itself. On sequential media only one is found, on 1167 1.45 reinoud * rewritable media a sequence of descriptors can be found as a form of 1168 1.45 reinoud * history keeping and on non sequential write-once media the chain is vital 1169 1.45 reinoud * to allow more and more descriptors to be written. The last descriptor 1170 1.45 reinoud * written in an extent needs to claim space for a new extent. 1171 1.45 reinoud */ 1172 1.45 reinoud 1173 1.45 reinoud static int 1174 1.45 reinoud udf_retrieve_lvint(struct udf_mount *ump) 1175 1.45 reinoud { 1176 1.45 reinoud union dscrptr *dscr; 1177 1.45 reinoud struct logvol_int_desc *lvint; 1178 1.45 reinoud struct udf_lvintq *trace; 1179 1.45 reinoud uint32_t lb_size, lbnum, len; 1180 1.45 reinoud int dscr_type, error, trace_len; 1181 1.45 reinoud 1182 1.45 reinoud lb_size = udf_rw32(ump->logical_vol->lb_size); 1183 1.45 reinoud len = udf_rw32(ump->logical_vol->integrity_seq_loc.len); 1184 1.45 reinoud lbnum = udf_rw32(ump->logical_vol->integrity_seq_loc.loc); 1185 1.45 reinoud 1186 1.45 reinoud /* clean trace */ 1187 1.45 reinoud memset(ump->lvint_trace, 0, 1188 1.45 reinoud UDF_LVDINT_SEGMENTS * sizeof(struct udf_lvintq)); 1189 1.45 reinoud 1190 1.45 reinoud trace_len = 0; 1191 1.45 reinoud trace = ump->lvint_trace; 1192 1.45 reinoud trace->start = lbnum; 1193 1.45 reinoud trace->end = lbnum + len/lb_size; 1194 1.45 reinoud trace->pos = 0; 1195 1.45 reinoud trace->wpos = 0; 1196 1.45 reinoud 1197 1.45 reinoud lvint = NULL; 1198 1.45 reinoud dscr = NULL; 1199 1.45 reinoud error = 0; 1200 1.45 reinoud while (len) { 1201 1.45 reinoud trace->pos = lbnum - trace->start; 1202 1.45 reinoud trace->wpos = trace->pos + 1; 1203 1.45 reinoud 1204 1.45 reinoud /* read in our integrity descriptor */ 1205 1.45 reinoud error = udf_read_phys_dscr(ump, lbnum, M_UDFVOLD, &dscr); 1206 1.45 reinoud if (!error) { 1207 1.45 reinoud if (dscr == NULL) { 1208 1.45 reinoud trace->wpos = trace->pos; 1209 1.45 reinoud break; /* empty terminates */ 1210 1.45 reinoud } 1211 1.45 reinoud dscr_type = udf_rw16(dscr->tag.id); 1212 1.45 reinoud if (dscr_type == TAGID_TERM) { 1213 1.45 reinoud trace->wpos = trace->pos; 1214 1.45 reinoud break; /* clean terminator */ 1215 1.45 reinoud } 1216 1.45 reinoud if (dscr_type != TAGID_LOGVOL_INTEGRITY) { 1217 1.45 reinoud /* fatal... corrupt disc */ 1218 1.45 reinoud error = ENOENT; 1219 1.45 reinoud break; 1220 1.45 reinoud } 1221 1.45 reinoud if (lvint) 1222 1.45 reinoud free(lvint, M_UDFVOLD); 1223 1.45 reinoud lvint = &dscr->lvid; 1224 1.45 reinoud dscr = NULL; 1225 1.45 reinoud } /* else hope for the best... maybe the next is ok */ 1226 1.45 reinoud 1227 1.45 reinoud DPRINTFIF(VOLUMES, lvint, ("logvol integrity read, state %s\n", 1228 1.45 reinoud udf_rw32(lvint->integrity_type) ? "CLOSED" : "OPEN")); 1229 1.45 reinoud 1230 1.45 reinoud /* proceed sequential */ 1231 1.45 reinoud lbnum += 1; 1232 1.45 reinoud len -= lb_size; 1233 1.45 reinoud 1234 1.45 reinoud /* are we linking to a new piece? */ 1235 1.45 reinoud if (dscr && lvint->next_extent.len) { 1236 1.142 reinoud len = udf_rw32(lvint->next_extent.len); 1237 1.45 reinoud lbnum = udf_rw32(lvint->next_extent.loc); 1238 1.45 reinoud 1239 1.45 reinoud if (trace_len >= UDF_LVDINT_SEGMENTS-1) { 1240 1.45 reinoud /* IEK! segment link full... */ 1241 1.45 reinoud DPRINTF(VOLUMES, ("lvdint segments full\n")); 1242 1.45 reinoud error = EINVAL; 1243 1.45 reinoud } else { 1244 1.45 reinoud trace++; 1245 1.45 reinoud trace_len++; 1246 1.45 reinoud 1247 1.45 reinoud trace->start = lbnum; 1248 1.45 reinoud trace->end = lbnum + len/lb_size; 1249 1.45 reinoud trace->pos = 0; 1250 1.45 reinoud trace->wpos = 0; 1251 1.45 reinoud } 1252 1.45 reinoud } 1253 1.45 reinoud } 1254 1.45 reinoud 1255 1.45 reinoud /* clean up the mess, esp. when there is an error */ 1256 1.45 reinoud if (dscr) 1257 1.45 reinoud free(dscr, M_UDFVOLD); 1258 1.45 reinoud 1259 1.45 reinoud if (error && lvint) { 1260 1.45 reinoud free(lvint, M_UDFVOLD); 1261 1.45 reinoud lvint = NULL; 1262 1.45 reinoud } 1263 1.45 reinoud 1264 1.45 reinoud if (!lvint) 1265 1.45 reinoud error = ENOENT; 1266 1.45 reinoud 1267 1.45 reinoud ump->logvol_integrity = lvint; 1268 1.45 reinoud return error; 1269 1.45 reinoud } 1270 1.45 reinoud 1271 1.45 reinoud 1272 1.45 reinoud static int 1273 1.45 reinoud udf_loose_lvint_history(struct udf_mount *ump) 1274 1.45 reinoud { 1275 1.45 reinoud union dscrptr **bufs, *dscr, *last_dscr; 1276 1.45 reinoud struct udf_lvintq *trace, *in_trace, *out_trace; 1277 1.45 reinoud struct logvol_int_desc *lvint; 1278 1.45 reinoud uint32_t in_ext, in_pos, in_len; 1279 1.45 reinoud uint32_t out_ext, out_wpos, out_len; 1280 1.121 christos uint32_t lb_num; 1281 1.45 reinoud uint32_t len, start; 1282 1.142 reinoud int ext, sumext, extlen, cnt, cpy_len, dscr_type; 1283 1.45 reinoud int losing; 1284 1.45 reinoud int error; 1285 1.45 reinoud 1286 1.45 reinoud DPRINTF(VOLUMES, ("need to lose some lvint history\n")); 1287 1.45 reinoud 1288 1.45 reinoud /* search smallest extent */ 1289 1.45 reinoud trace = &ump->lvint_trace[0]; 1290 1.142 reinoud sumext = trace->end - trace->start; 1291 1.45 reinoud for (ext = 1; ext < UDF_LVDINT_SEGMENTS; ext++) { 1292 1.45 reinoud trace = &ump->lvint_trace[ext]; 1293 1.45 reinoud extlen = trace->end - trace->start; 1294 1.45 reinoud if (extlen == 0) 1295 1.45 reinoud break; 1296 1.142 reinoud sumext += extlen; 1297 1.45 reinoud } 1298 1.142 reinoud 1299 1.142 reinoud /* just one element? its not legal but be bug compatible */ 1300 1.142 reinoud if (sumext == 1) { 1301 1.142 reinoud /* overwrite the only entry */ 1302 1.142 reinoud DPRINTF(VOLUMES, ("\tLinux bugcompat overwriting sole entry\n")); 1303 1.142 reinoud trace = &ump->lvint_trace[0]; 1304 1.142 reinoud trace->wpos = 0; 1305 1.142 reinoud return 0; 1306 1.142 reinoud } 1307 1.142 reinoud 1308 1.142 reinoud losing = MIN(sumext, UDF_LVINT_LOSSAGE); 1309 1.142 reinoud 1310 1.142 reinoud /* no sense wiping too much */ 1311 1.142 reinoud if (sumext == UDF_LVINT_LOSSAGE) 1312 1.142 reinoud losing = UDF_LVINT_LOSSAGE/2; 1313 1.45 reinoud 1314 1.45 reinoud DPRINTF(VOLUMES, ("\tlosing %d entries\n", losing)); 1315 1.45 reinoud 1316 1.45 reinoud /* get buffer for pieces */ 1317 1.45 reinoud bufs = malloc(UDF_LVDINT_SEGMENTS * sizeof(void *), M_TEMP, M_WAITOK); 1318 1.45 reinoud 1319 1.45 reinoud in_ext = 0; 1320 1.45 reinoud in_pos = losing; 1321 1.45 reinoud in_trace = &ump->lvint_trace[in_ext]; 1322 1.45 reinoud in_len = in_trace->end - in_trace->start; 1323 1.45 reinoud out_ext = 0; 1324 1.45 reinoud out_wpos = 0; 1325 1.45 reinoud out_trace = &ump->lvint_trace[out_ext]; 1326 1.45 reinoud out_len = out_trace->end - out_trace->start; 1327 1.45 reinoud 1328 1.45 reinoud last_dscr = NULL; 1329 1.45 reinoud for(;;) { 1330 1.45 reinoud out_trace->pos = out_wpos; 1331 1.45 reinoud out_trace->wpos = out_trace->pos; 1332 1.45 reinoud if (in_pos >= in_len) { 1333 1.45 reinoud in_ext++; 1334 1.45 reinoud in_pos = 0; 1335 1.45 reinoud in_trace = &ump->lvint_trace[in_ext]; 1336 1.45 reinoud in_len = in_trace->end - in_trace->start; 1337 1.45 reinoud } 1338 1.45 reinoud if (out_wpos >= out_len) { 1339 1.45 reinoud out_ext++; 1340 1.45 reinoud out_wpos = 0; 1341 1.45 reinoud out_trace = &ump->lvint_trace[out_ext]; 1342 1.45 reinoud out_len = out_trace->end - out_trace->start; 1343 1.45 reinoud } 1344 1.45 reinoud /* copy overlap contents */ 1345 1.45 reinoud cpy_len = MIN(in_len - in_pos, out_len - out_wpos); 1346 1.45 reinoud cpy_len = MIN(cpy_len, in_len - in_trace->pos); 1347 1.45 reinoud if (cpy_len == 0) 1348 1.45 reinoud break; 1349 1.45 reinoud 1350 1.45 reinoud /* copy */ 1351 1.45 reinoud DPRINTF(VOLUMES, ("\treading %d lvid descriptors\n", cpy_len)); 1352 1.45 reinoud for (cnt = 0; cnt < cpy_len; cnt++) { 1353 1.45 reinoud /* read in our integrity descriptor */ 1354 1.45 reinoud lb_num = in_trace->start + in_pos + cnt; 1355 1.45 reinoud error = udf_read_phys_dscr(ump, lb_num, M_UDFVOLD, 1356 1.45 reinoud &dscr); 1357 1.45 reinoud if (error) { 1358 1.45 reinoud /* copy last one */ 1359 1.45 reinoud dscr = last_dscr; 1360 1.45 reinoud } 1361 1.45 reinoud bufs[cnt] = dscr; 1362 1.45 reinoud if (!error) { 1363 1.45 reinoud if (dscr == NULL) { 1364 1.45 reinoud out_trace->pos = out_wpos + cnt; 1365 1.45 reinoud out_trace->wpos = out_trace->pos; 1366 1.45 reinoud break; /* empty terminates */ 1367 1.45 reinoud } 1368 1.45 reinoud dscr_type = udf_rw16(dscr->tag.id); 1369 1.45 reinoud if (dscr_type == TAGID_TERM) { 1370 1.45 reinoud out_trace->pos = out_wpos + cnt; 1371 1.45 reinoud out_trace->wpos = out_trace->pos; 1372 1.45 reinoud break; /* clean terminator */ 1373 1.45 reinoud } 1374 1.45 reinoud if (dscr_type != TAGID_LOGVOL_INTEGRITY) { 1375 1.45 reinoud panic( "UDF integrity sequence " 1376 1.45 reinoud "corrupted while mounted!\n"); 1377 1.45 reinoud } 1378 1.45 reinoud last_dscr = dscr; 1379 1.45 reinoud } 1380 1.45 reinoud } 1381 1.45 reinoud 1382 1.45 reinoud /* patch up if first entry was on error */ 1383 1.45 reinoud if (bufs[0] == NULL) { 1384 1.45 reinoud for (cnt = 0; cnt < cpy_len; cnt++) 1385 1.45 reinoud if (bufs[cnt] != NULL) 1386 1.45 reinoud break; 1387 1.45 reinoud last_dscr = bufs[cnt]; 1388 1.45 reinoud for (; cnt > 0; cnt--) { 1389 1.45 reinoud bufs[cnt] = last_dscr; 1390 1.45 reinoud } 1391 1.45 reinoud } 1392 1.45 reinoud 1393 1.45 reinoud /* glue + write out */ 1394 1.45 reinoud DPRINTF(VOLUMES, ("\twriting %d lvid descriptors\n", cpy_len)); 1395 1.45 reinoud for (cnt = 0; cnt < cpy_len; cnt++) { 1396 1.45 reinoud lb_num = out_trace->start + out_wpos + cnt; 1397 1.45 reinoud lvint = &bufs[cnt]->lvid; 1398 1.45 reinoud 1399 1.45 reinoud /* set continuation */ 1400 1.45 reinoud len = 0; 1401 1.45 reinoud start = 0; 1402 1.45 reinoud if (out_wpos + cnt == out_len) { 1403 1.45 reinoud /* get continuation */ 1404 1.45 reinoud trace = &ump->lvint_trace[out_ext+1]; 1405 1.45 reinoud len = trace->end - trace->start; 1406 1.45 reinoud start = trace->start; 1407 1.45 reinoud } 1408 1.45 reinoud lvint->next_extent.len = udf_rw32(len); 1409 1.45 reinoud lvint->next_extent.loc = udf_rw32(start); 1410 1.45 reinoud 1411 1.45 reinoud lb_num = trace->start + trace->wpos; 1412 1.45 reinoud error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR, 1413 1.45 reinoud bufs[cnt], lb_num, lb_num); 1414 1.45 reinoud DPRINTFIF(VOLUMES, error, 1415 1.45 reinoud ("error writing lvint lb_num\n")); 1416 1.45 reinoud } 1417 1.45 reinoud 1418 1.45 reinoud /* free non repeating descriptors */ 1419 1.45 reinoud last_dscr = NULL; 1420 1.45 reinoud for (cnt = 0; cnt < cpy_len; cnt++) { 1421 1.45 reinoud if (bufs[cnt] != last_dscr) 1422 1.45 reinoud free(bufs[cnt], M_UDFVOLD); 1423 1.45 reinoud last_dscr = bufs[cnt]; 1424 1.45 reinoud } 1425 1.45 reinoud 1426 1.45 reinoud /* advance */ 1427 1.45 reinoud in_pos += cpy_len; 1428 1.45 reinoud out_wpos += cpy_len; 1429 1.45 reinoud } 1430 1.45 reinoud 1431 1.45 reinoud free(bufs, M_TEMP); 1432 1.45 reinoud 1433 1.45 reinoud return 0; 1434 1.45 reinoud } 1435 1.45 reinoud 1436 1.45 reinoud 1437 1.45 reinoud static int 1438 1.45 reinoud udf_writeout_lvint(struct udf_mount *ump, int lvflag) 1439 1.45 reinoud { 1440 1.45 reinoud struct udf_lvintq *trace; 1441 1.45 reinoud struct timeval now_v; 1442 1.45 reinoud struct timespec now_s; 1443 1.45 reinoud uint32_t sector; 1444 1.45 reinoud int logvol_integrity; 1445 1.45 reinoud int space, error; 1446 1.45 reinoud 1447 1.45 reinoud DPRINTF(VOLUMES, ("writing out logvol integrity descriptor\n")); 1448 1.45 reinoud 1449 1.45 reinoud /* get free space in last chunk */ 1450 1.45 reinoud trace = ump->lvint_trace; 1451 1.45 reinoud while (trace->wpos > (trace->end - trace->start)) { 1452 1.45 reinoud DPRINTF(VOLUMES, ("skip : start = %d, end = %d, pos = %d, " 1453 1.45 reinoud "wpos = %d\n", trace->start, trace->end, 1454 1.45 reinoud trace->pos, trace->wpos)); 1455 1.45 reinoud trace++; 1456 1.45 reinoud } 1457 1.45 reinoud 1458 1.45 reinoud /* check if there is space to append */ 1459 1.45 reinoud space = (trace->end - trace->start) - trace->wpos; 1460 1.45 reinoud DPRINTF(VOLUMES, ("write start = %d, end = %d, pos = %d, wpos = %d, " 1461 1.45 reinoud "space = %d\n", trace->start, trace->end, trace->pos, 1462 1.45 reinoud trace->wpos, space)); 1463 1.45 reinoud 1464 1.45 reinoud /* get state */ 1465 1.45 reinoud logvol_integrity = udf_rw32(ump->logvol_integrity->integrity_type); 1466 1.45 reinoud if (logvol_integrity == UDF_INTEGRITY_CLOSED) { 1467 1.45 reinoud if ((space < 3) && (lvflag & UDF_APPENDONLY_LVINT)) { 1468 1.45 reinoud /* TODO extent LVINT space if possible */ 1469 1.45 reinoud return EROFS; 1470 1.45 reinoud } 1471 1.45 reinoud } 1472 1.45 reinoud 1473 1.45 reinoud if (space < 1) { 1474 1.45 reinoud if (lvflag & UDF_APPENDONLY_LVINT) 1475 1.45 reinoud return EROFS; 1476 1.142 reinoud 1477 1.45 reinoud /* loose history by re-writing extents */ 1478 1.45 reinoud error = udf_loose_lvint_history(ump); 1479 1.45 reinoud if (error) 1480 1.45 reinoud return error; 1481 1.142 reinoud 1482 1.142 reinoud trace = ump->lvint_trace; 1483 1.142 reinoud while (trace->wpos > (trace->end - trace->start)) 1484 1.142 reinoud trace++; 1485 1.142 reinoud space = (trace->end - trace->start) - trace->wpos; 1486 1.142 reinoud DPRINTF(VOLUMES, ("new try: write start = %d, end = %d, " 1487 1.142 reinoud "pos = %d, wpos = %d, " 1488 1.142 reinoud "space = %d\n", trace->start, trace->end, 1489 1.142 reinoud trace->pos, trace->wpos, space)); 1490 1.45 reinoud } 1491 1.45 reinoud 1492 1.45 reinoud /* update our integrity descriptor to identify us and timestamp it */ 1493 1.45 reinoud DPRINTF(VOLUMES, ("updating integrity descriptor\n")); 1494 1.45 reinoud microtime(&now_v); 1495 1.45 reinoud TIMEVAL_TO_TIMESPEC(&now_v, &now_s); 1496 1.45 reinoud udf_timespec_to_timestamp(&now_s, &ump->logvol_integrity->time); 1497 1.45 reinoud udf_set_regid(&ump->logvol_info->impl_id, IMPL_NAME); 1498 1.45 reinoud udf_add_impl_regid(ump, &ump->logvol_info->impl_id); 1499 1.45 reinoud 1500 1.45 reinoud /* writeout integrity descriptor */ 1501 1.45 reinoud sector = trace->start + trace->wpos; 1502 1.45 reinoud error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR, 1503 1.45 reinoud (union dscrptr *) ump->logvol_integrity, 1504 1.45 reinoud sector, sector); 1505 1.45 reinoud DPRINTF(VOLUMES, ("writeout lvint : error = %d\n", error)); 1506 1.45 reinoud if (error) 1507 1.45 reinoud return error; 1508 1.45 reinoud 1509 1.45 reinoud /* advance write position */ 1510 1.45 reinoud trace->wpos++; space--; 1511 1.45 reinoud if (space >= 1) { 1512 1.45 reinoud /* append terminator */ 1513 1.45 reinoud sector = trace->start + trace->wpos; 1514 1.45 reinoud error = udf_write_terminator(ump, sector); 1515 1.45 reinoud 1516 1.45 reinoud DPRINTF(VOLUMES, ("write terminator : error = %d\n", error)); 1517 1.45 reinoud } 1518 1.45 reinoud 1519 1.45 reinoud space = (trace->end - trace->start) - trace->wpos; 1520 1.45 reinoud DPRINTF(VOLUMES, ("write start = %d, end = %d, pos = %d, wpos = %d, " 1521 1.45 reinoud "space = %d\n", trace->start, trace->end, trace->pos, 1522 1.45 reinoud trace->wpos, space)); 1523 1.45 reinoud DPRINTF(VOLUMES, ("finished writing out logvol integrity descriptor " 1524 1.158 andvar "successfully\n")); 1525 1.45 reinoud 1526 1.45 reinoud return error; 1527 1.45 reinoud } 1528 1.45 reinoud 1529 1.45 reinoud /* --------------------------------------------------------------------- */ 1530 1.45 reinoud 1531 1.45 reinoud static int 1532 1.68 reinoud udf_read_physical_partition_spacetables(struct udf_mount *ump) 1533 1.45 reinoud { 1534 1.45 reinoud union dscrptr *dscr; 1535 1.45 reinoud /* struct udf_args *args = &ump->mount_args; */ 1536 1.45 reinoud struct part_desc *partd; 1537 1.45 reinoud struct part_hdr_desc *parthdr; 1538 1.45 reinoud struct udf_bitmap *bitmap; 1539 1.45 reinoud uint32_t phys_part; 1540 1.45 reinoud uint32_t lb_num, len; 1541 1.45 reinoud int error, dscr_type; 1542 1.45 reinoud 1543 1.45 reinoud /* unallocated space map */ 1544 1.45 reinoud for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 1545 1.45 reinoud partd = ump->partitions[phys_part]; 1546 1.45 reinoud if (partd == NULL) 1547 1.45 reinoud continue; 1548 1.45 reinoud parthdr = &partd->_impl_use.part_hdr; 1549 1.45 reinoud 1550 1.45 reinoud lb_num = udf_rw32(partd->start_loc); 1551 1.45 reinoud lb_num += udf_rw32(parthdr->unalloc_space_bitmap.lb_num); 1552 1.45 reinoud len = udf_rw32(parthdr->unalloc_space_bitmap.len); 1553 1.45 reinoud if (len == 0) 1554 1.45 reinoud continue; 1555 1.45 reinoud 1556 1.45 reinoud DPRINTF(VOLUMES, ("Read unalloc. space bitmap %d\n", lb_num)); 1557 1.45 reinoud error = udf_read_phys_dscr(ump, lb_num, M_UDFVOLD, &dscr); 1558 1.45 reinoud if (!error && dscr) { 1559 1.45 reinoud /* analyse */ 1560 1.45 reinoud dscr_type = udf_rw16(dscr->tag.id); 1561 1.45 reinoud if (dscr_type == TAGID_SPACE_BITMAP) { 1562 1.45 reinoud DPRINTF(VOLUMES, ("Accepting space bitmap\n")); 1563 1.45 reinoud ump->part_unalloc_dscr[phys_part] = &dscr->sbd; 1564 1.45 reinoud 1565 1.45 reinoud /* fill in ump->part_unalloc_bits */ 1566 1.45 reinoud bitmap = &ump->part_unalloc_bits[phys_part]; 1567 1.45 reinoud bitmap->blob = (uint8_t *) dscr; 1568 1.45 reinoud bitmap->bits = dscr->sbd.data; 1569 1.45 reinoud bitmap->max_offset = udf_rw32(dscr->sbd.num_bits); 1570 1.45 reinoud bitmap->pages = NULL; /* TODO */ 1571 1.45 reinoud bitmap->data_pos = 0; 1572 1.45 reinoud bitmap->metadata_pos = 0; 1573 1.45 reinoud } else { 1574 1.45 reinoud free(dscr, M_UDFVOLD); 1575 1.45 reinoud 1576 1.45 reinoud printf( "UDF mount: error reading unallocated " 1577 1.45 reinoud "space bitmap\n"); 1578 1.45 reinoud return EROFS; 1579 1.45 reinoud } 1580 1.45 reinoud } else { 1581 1.45 reinoud /* blank not allowed */ 1582 1.45 reinoud printf("UDF mount: blank unallocated space bitmap\n"); 1583 1.45 reinoud return EROFS; 1584 1.45 reinoud } 1585 1.45 reinoud } 1586 1.45 reinoud 1587 1.45 reinoud /* unallocated space table (not supported) */ 1588 1.45 reinoud for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 1589 1.45 reinoud partd = ump->partitions[phys_part]; 1590 1.45 reinoud if (partd == NULL) 1591 1.45 reinoud continue; 1592 1.45 reinoud parthdr = &partd->_impl_use.part_hdr; 1593 1.152 skrll 1594 1.45 reinoud len = udf_rw32(parthdr->unalloc_space_table.len); 1595 1.45 reinoud if (len) { 1596 1.45 reinoud printf("UDF mount: space tables not supported\n"); 1597 1.45 reinoud return EROFS; 1598 1.45 reinoud } 1599 1.45 reinoud } 1600 1.45 reinoud 1601 1.45 reinoud /* freed space map */ 1602 1.45 reinoud for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 1603 1.45 reinoud partd = ump->partitions[phys_part]; 1604 1.45 reinoud if (partd == NULL) 1605 1.45 reinoud continue; 1606 1.45 reinoud parthdr = &partd->_impl_use.part_hdr; 1607 1.45 reinoud 1608 1.45 reinoud /* freed space map */ 1609 1.45 reinoud lb_num = udf_rw32(partd->start_loc); 1610 1.45 reinoud lb_num += udf_rw32(parthdr->freed_space_bitmap.lb_num); 1611 1.45 reinoud len = udf_rw32(parthdr->freed_space_bitmap.len); 1612 1.45 reinoud if (len == 0) 1613 1.45 reinoud continue; 1614 1.45 reinoud 1615 1.45 reinoud DPRINTF(VOLUMES, ("Read unalloc. space bitmap %d\n", lb_num)); 1616 1.45 reinoud error = udf_read_phys_dscr(ump, lb_num, M_UDFVOLD, &dscr); 1617 1.45 reinoud if (!error && dscr) { 1618 1.45 reinoud /* analyse */ 1619 1.45 reinoud dscr_type = udf_rw16(dscr->tag.id); 1620 1.45 reinoud if (dscr_type == TAGID_SPACE_BITMAP) { 1621 1.45 reinoud DPRINTF(VOLUMES, ("Accepting space bitmap\n")); 1622 1.45 reinoud ump->part_freed_dscr[phys_part] = &dscr->sbd; 1623 1.45 reinoud 1624 1.45 reinoud /* fill in ump->part_freed_bits */ 1625 1.45 reinoud bitmap = &ump->part_unalloc_bits[phys_part]; 1626 1.45 reinoud bitmap->blob = (uint8_t *) dscr; 1627 1.45 reinoud bitmap->bits = dscr->sbd.data; 1628 1.45 reinoud bitmap->max_offset = udf_rw32(dscr->sbd.num_bits); 1629 1.45 reinoud bitmap->pages = NULL; /* TODO */ 1630 1.45 reinoud bitmap->data_pos = 0; 1631 1.45 reinoud bitmap->metadata_pos = 0; 1632 1.45 reinoud } else { 1633 1.45 reinoud free(dscr, M_UDFVOLD); 1634 1.45 reinoud 1635 1.45 reinoud printf( "UDF mount: error reading freed " 1636 1.45 reinoud "space bitmap\n"); 1637 1.45 reinoud return EROFS; 1638 1.45 reinoud } 1639 1.45 reinoud } else { 1640 1.45 reinoud /* blank not allowed */ 1641 1.45 reinoud printf("UDF mount: blank freed space bitmap\n"); 1642 1.45 reinoud return EROFS; 1643 1.45 reinoud } 1644 1.45 reinoud } 1645 1.45 reinoud 1646 1.45 reinoud /* freed space table (not supported) */ 1647 1.45 reinoud for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 1648 1.45 reinoud partd = ump->partitions[phys_part]; 1649 1.45 reinoud if (partd == NULL) 1650 1.45 reinoud continue; 1651 1.45 reinoud parthdr = &partd->_impl_use.part_hdr; 1652 1.152 skrll 1653 1.45 reinoud len = udf_rw32(parthdr->freed_space_table.len); 1654 1.45 reinoud if (len) { 1655 1.45 reinoud printf("UDF mount: space tables not supported\n"); 1656 1.45 reinoud return EROFS; 1657 1.45 reinoud } 1658 1.45 reinoud } 1659 1.45 reinoud 1660 1.45 reinoud return 0; 1661 1.45 reinoud } 1662 1.45 reinoud 1663 1.45 reinoud 1664 1.45 reinoud /* TODO implement async writeout */ 1665 1.45 reinoud int 1666 1.68 reinoud udf_write_physical_partition_spacetables(struct udf_mount *ump, int waitfor) 1667 1.45 reinoud { 1668 1.45 reinoud union dscrptr *dscr; 1669 1.45 reinoud /* struct udf_args *args = &ump->mount_args; */ 1670 1.45 reinoud struct part_desc *partd; 1671 1.45 reinoud struct part_hdr_desc *parthdr; 1672 1.45 reinoud uint32_t phys_part; 1673 1.45 reinoud uint32_t lb_num, len, ptov; 1674 1.45 reinoud int error_all, error; 1675 1.45 reinoud 1676 1.45 reinoud error_all = 0; 1677 1.45 reinoud /* unallocated space map */ 1678 1.45 reinoud for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 1679 1.45 reinoud partd = ump->partitions[phys_part]; 1680 1.45 reinoud if (partd == NULL) 1681 1.45 reinoud continue; 1682 1.45 reinoud parthdr = &partd->_impl_use.part_hdr; 1683 1.45 reinoud 1684 1.45 reinoud ptov = udf_rw32(partd->start_loc); 1685 1.45 reinoud lb_num = udf_rw32(parthdr->unalloc_space_bitmap.lb_num); 1686 1.45 reinoud len = udf_rw32(parthdr->unalloc_space_bitmap.len); 1687 1.45 reinoud if (len == 0) 1688 1.45 reinoud continue; 1689 1.45 reinoud 1690 1.45 reinoud DPRINTF(VOLUMES, ("Write unalloc. space bitmap %d\n", 1691 1.45 reinoud lb_num + ptov)); 1692 1.45 reinoud dscr = (union dscrptr *) ump->part_unalloc_dscr[phys_part]; 1693 1.142 reinoud 1694 1.142 reinoud /* force a sane minimum for descriptors CRC length */ 1695 1.142 reinoud /* see UDF 2.3.1.2 and 2.3.8.1 */ 1696 1.142 reinoud KASSERT(udf_rw16(dscr->sbd.tag.id) == TAGID_SPACE_BITMAP); 1697 1.142 reinoud if (udf_rw16(dscr->sbd.tag.desc_crc_len) == 0) 1698 1.142 reinoud dscr->sbd.tag.desc_crc_len = udf_rw16(8); 1699 1.142 reinoud 1700 1.142 reinoud /* write out space bitmap */ 1701 1.45 reinoud error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR, 1702 1.45 reinoud (union dscrptr *) dscr, 1703 1.45 reinoud ptov + lb_num, lb_num); 1704 1.45 reinoud if (error) { 1705 1.45 reinoud DPRINTF(VOLUMES, ("\tfailed!! (error %d)\n", error)); 1706 1.45 reinoud error_all = error; 1707 1.45 reinoud } 1708 1.45 reinoud } 1709 1.45 reinoud 1710 1.45 reinoud /* freed space map */ 1711 1.45 reinoud for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 1712 1.45 reinoud partd = ump->partitions[phys_part]; 1713 1.45 reinoud if (partd == NULL) 1714 1.45 reinoud continue; 1715 1.45 reinoud parthdr = &partd->_impl_use.part_hdr; 1716 1.45 reinoud 1717 1.45 reinoud /* freed space map */ 1718 1.45 reinoud ptov = udf_rw32(partd->start_loc); 1719 1.45 reinoud lb_num = udf_rw32(parthdr->freed_space_bitmap.lb_num); 1720 1.45 reinoud len = udf_rw32(parthdr->freed_space_bitmap.len); 1721 1.45 reinoud if (len == 0) 1722 1.45 reinoud continue; 1723 1.45 reinoud 1724 1.45 reinoud DPRINTF(VOLUMES, ("Write freed space bitmap %d\n", 1725 1.45 reinoud lb_num + ptov)); 1726 1.45 reinoud dscr = (union dscrptr *) ump->part_freed_dscr[phys_part]; 1727 1.142 reinoud 1728 1.142 reinoud /* force a sane minimum for descriptors CRC length */ 1729 1.142 reinoud /* see UDF 2.3.1.2 and 2.3.8.1 */ 1730 1.142 reinoud KASSERT(udf_rw16(dscr->sbd.tag.id) == TAGID_SPACE_BITMAP); 1731 1.142 reinoud if (udf_rw16(dscr->sbd.tag.desc_crc_len) == 0) 1732 1.142 reinoud dscr->sbd.tag.desc_crc_len = udf_rw16(8); 1733 1.142 reinoud 1734 1.142 reinoud /* write out space bitmap */ 1735 1.45 reinoud error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR, 1736 1.45 reinoud (union dscrptr *) dscr, 1737 1.45 reinoud ptov + lb_num, lb_num); 1738 1.45 reinoud if (error) { 1739 1.45 reinoud DPRINTF(VOLUMES, ("\tfailed!! (error %d)\n", error)); 1740 1.45 reinoud error_all = error; 1741 1.45 reinoud } 1742 1.45 reinoud } 1743 1.45 reinoud 1744 1.45 reinoud return error_all; 1745 1.45 reinoud } 1746 1.45 reinoud 1747 1.70 reinoud 1748 1.70 reinoud static int 1749 1.70 reinoud udf_read_metadata_partition_spacetable(struct udf_mount *ump) 1750 1.70 reinoud { 1751 1.70 reinoud struct udf_node *bitmap_node; 1752 1.70 reinoud union dscrptr *dscr; 1753 1.70 reinoud struct udf_bitmap *bitmap; 1754 1.70 reinoud uint64_t inflen; 1755 1.70 reinoud int error, dscr_type; 1756 1.70 reinoud 1757 1.70 reinoud bitmap_node = ump->metadatabitmap_node; 1758 1.70 reinoud 1759 1.70 reinoud /* only read in when metadata bitmap node is read in */ 1760 1.70 reinoud if (bitmap_node == NULL) 1761 1.70 reinoud return 0; 1762 1.70 reinoud 1763 1.70 reinoud if (bitmap_node->fe) { 1764 1.70 reinoud inflen = udf_rw64(bitmap_node->fe->inf_len); 1765 1.70 reinoud } else { 1766 1.70 reinoud KASSERT(bitmap_node->efe); 1767 1.70 reinoud inflen = udf_rw64(bitmap_node->efe->inf_len); 1768 1.70 reinoud } 1769 1.70 reinoud 1770 1.70 reinoud DPRINTF(VOLUMES, ("Reading metadata space bitmap for " 1771 1.70 reinoud "%"PRIu64" bytes\n", inflen)); 1772 1.70 reinoud 1773 1.70 reinoud /* allocate space for bitmap */ 1774 1.144 jdolecek dscr = malloc(inflen, M_UDFVOLD, M_WAITOK); 1775 1.70 reinoud if (!dscr) 1776 1.70 reinoud return ENOMEM; 1777 1.70 reinoud 1778 1.70 reinoud /* set vnode type to regular file or we can't read from it! */ 1779 1.70 reinoud bitmap_node->vnode->v_type = VREG; 1780 1.70 reinoud 1781 1.70 reinoud /* read in complete metadata bitmap file */ 1782 1.70 reinoud error = vn_rdwr(UIO_READ, bitmap_node->vnode, 1783 1.70 reinoud dscr, 1784 1.70 reinoud inflen, 0, 1785 1.70 reinoud UIO_SYSSPACE, 1786 1.109 reinoud IO_SYNC | IO_ALTSEMANTICS, FSCRED, 1787 1.70 reinoud NULL, NULL); 1788 1.70 reinoud if (error) { 1789 1.70 reinoud DPRINTF(VOLUMES, ("Error reading metadata space bitmap\n")); 1790 1.70 reinoud goto errorout; 1791 1.70 reinoud } 1792 1.70 reinoud 1793 1.70 reinoud /* analyse */ 1794 1.70 reinoud dscr_type = udf_rw16(dscr->tag.id); 1795 1.70 reinoud if (dscr_type == TAGID_SPACE_BITMAP) { 1796 1.70 reinoud DPRINTF(VOLUMES, ("Accepting metadata space bitmap\n")); 1797 1.70 reinoud ump->metadata_unalloc_dscr = &dscr->sbd; 1798 1.70 reinoud 1799 1.70 reinoud /* fill in bitmap bits */ 1800 1.70 reinoud bitmap = &ump->metadata_unalloc_bits; 1801 1.70 reinoud bitmap->blob = (uint8_t *) dscr; 1802 1.70 reinoud bitmap->bits = dscr->sbd.data; 1803 1.70 reinoud bitmap->max_offset = udf_rw32(dscr->sbd.num_bits); 1804 1.70 reinoud bitmap->pages = NULL; /* TODO */ 1805 1.70 reinoud bitmap->data_pos = 0; 1806 1.70 reinoud bitmap->metadata_pos = 0; 1807 1.70 reinoud } else { 1808 1.70 reinoud DPRINTF(VOLUMES, ("No valid bitmap found!\n")); 1809 1.70 reinoud goto errorout; 1810 1.70 reinoud } 1811 1.70 reinoud 1812 1.70 reinoud return 0; 1813 1.70 reinoud 1814 1.70 reinoud errorout: 1815 1.70 reinoud free(dscr, M_UDFVOLD); 1816 1.70 reinoud printf( "UDF mount: error reading unallocated " 1817 1.70 reinoud "space bitmap for metadata partition\n"); 1818 1.70 reinoud return EROFS; 1819 1.70 reinoud } 1820 1.70 reinoud 1821 1.70 reinoud 1822 1.70 reinoud int 1823 1.70 reinoud udf_write_metadata_partition_spacetable(struct udf_mount *ump, int waitfor) 1824 1.70 reinoud { 1825 1.70 reinoud struct udf_node *bitmap_node; 1826 1.70 reinoud union dscrptr *dscr; 1827 1.121 christos uint64_t new_inflen; 1828 1.70 reinoud int dummy, error; 1829 1.70 reinoud 1830 1.70 reinoud bitmap_node = ump->metadatabitmap_node; 1831 1.70 reinoud 1832 1.70 reinoud /* only write out when metadata bitmap node is known */ 1833 1.70 reinoud if (bitmap_node == NULL) 1834 1.70 reinoud return 0; 1835 1.70 reinoud 1836 1.121 christos if (!bitmap_node->fe) { 1837 1.70 reinoud KASSERT(bitmap_node->efe); 1838 1.70 reinoud } 1839 1.70 reinoud 1840 1.70 reinoud /* reduce length to zero */ 1841 1.70 reinoud dscr = (union dscrptr *) ump->metadata_unalloc_dscr; 1842 1.70 reinoud new_inflen = udf_tagsize(dscr, 1); 1843 1.70 reinoud 1844 1.125 reinoud DPRINTF(VOLUMES, ("Resize and write out metadata space bitmap " 1845 1.125 reinoud " for %"PRIu64" bytes\n", new_inflen)); 1846 1.70 reinoud 1847 1.71 reinoud error = udf_resize_node(bitmap_node, new_inflen, &dummy); 1848 1.70 reinoud if (error) 1849 1.70 reinoud printf("Error resizing metadata space bitmap\n"); 1850 1.70 reinoud 1851 1.70 reinoud error = vn_rdwr(UIO_WRITE, bitmap_node->vnode, 1852 1.70 reinoud dscr, 1853 1.70 reinoud new_inflen, 0, 1854 1.70 reinoud UIO_SYSSPACE, 1855 1.109 reinoud IO_ALTSEMANTICS, FSCRED, 1856 1.70 reinoud NULL, NULL); 1857 1.70 reinoud 1858 1.70 reinoud bitmap_node->i_flags |= IN_MODIFIED; 1859 1.119 chs error = vflushbuf(bitmap_node->vnode, FSYNC_WAIT); 1860 1.114 hannken if (error == 0) 1861 1.114 hannken error = VOP_FSYNC(bitmap_node->vnode, 1862 1.114 hannken FSCRED, FSYNC_WAIT, 0, 0); 1863 1.70 reinoud 1864 1.70 reinoud if (error) 1865 1.70 reinoud printf( "Error writing out metadata partition unalloced " 1866 1.70 reinoud "space bitmap!\n"); 1867 1.70 reinoud 1868 1.70 reinoud return error; 1869 1.70 reinoud } 1870 1.70 reinoud 1871 1.70 reinoud 1872 1.70 reinoud /* --------------------------------------------------------------------- */ 1873 1.70 reinoud 1874 1.45 reinoud /* 1875 1.45 reinoud * Checks if ump's vds information is correct and complete 1876 1.45 reinoud */ 1877 1.45 reinoud 1878 1.45 reinoud int 1879 1.45 reinoud udf_process_vds(struct udf_mount *ump) { 1880 1.45 reinoud union udf_pmap *mapping; 1881 1.45 reinoud /* struct udf_args *args = &ump->mount_args; */ 1882 1.45 reinoud struct logvol_int_desc *lvint; 1883 1.45 reinoud struct udf_logvol_info *lvinfo; 1884 1.121 christos uint32_t n_pm; 1885 1.45 reinoud uint8_t *pmap_pos; 1886 1.45 reinoud char *domain_name, *map_name; 1887 1.45 reinoud const char *check_name; 1888 1.45 reinoud char bits[128]; 1889 1.45 reinoud int pmap_stype, pmap_size; 1890 1.71 reinoud int pmap_type, log_part, phys_part, raw_phys_part, maps_on; 1891 1.45 reinoud int n_phys, n_virt, n_spar, n_meta; 1892 1.121 christos int len; 1893 1.45 reinoud 1894 1.45 reinoud if (ump == NULL) 1895 1.45 reinoud return ENOENT; 1896 1.45 reinoud 1897 1.45 reinoud /* we need at least an anchor (trivial, but for safety) */ 1898 1.45 reinoud if (ump->anchors[0] == NULL) 1899 1.45 reinoud return EINVAL; 1900 1.45 reinoud 1901 1.45 reinoud /* we need at least one primary and one logical volume descriptor */ 1902 1.45 reinoud if ((ump->primary_vol == NULL) || (ump->logical_vol) == NULL) 1903 1.45 reinoud return EINVAL; 1904 1.45 reinoud 1905 1.45 reinoud /* we need at least one partition descriptor */ 1906 1.45 reinoud if (ump->partitions[0] == NULL) 1907 1.45 reinoud return EINVAL; 1908 1.45 reinoud 1909 1.45 reinoud /* check logical volume sector size verses device sector size */ 1910 1.45 reinoud if (udf_rw32(ump->logical_vol->lb_size) != ump->discinfo.sector_size) { 1911 1.45 reinoud printf("UDF mount: format violation, lb_size != sector size\n"); 1912 1.45 reinoud return EINVAL; 1913 1.45 reinoud } 1914 1.45 reinoud 1915 1.45 reinoud /* check domain name */ 1916 1.45 reinoud domain_name = ump->logical_vol->domain_id.id; 1917 1.45 reinoud if (strncmp(domain_name, "*OSTA UDF Compliant", 20)) { 1918 1.45 reinoud printf("mount_udf: disc not OSTA UDF Compliant, aborting\n"); 1919 1.45 reinoud return EINVAL; 1920 1.45 reinoud } 1921 1.45 reinoud 1922 1.45 reinoud /* retrieve logical volume integrity sequence */ 1923 1.121 christos (void)udf_retrieve_lvint(ump); 1924 1.45 reinoud 1925 1.45 reinoud /* 1926 1.45 reinoud * We need at least one logvol integrity descriptor recorded. Note 1927 1.45 reinoud * that its OK to have an open logical volume integrity here. The VAT 1928 1.45 reinoud * will close/update the integrity. 1929 1.45 reinoud */ 1930 1.45 reinoud if (ump->logvol_integrity == NULL) 1931 1.45 reinoud return EINVAL; 1932 1.45 reinoud 1933 1.45 reinoud /* process derived structures */ 1934 1.45 reinoud n_pm = udf_rw32(ump->logical_vol->n_pm); /* num partmaps */ 1935 1.45 reinoud lvint = ump->logvol_integrity; 1936 1.45 reinoud lvinfo = (struct udf_logvol_info *) (&lvint->tables[2 * n_pm]); 1937 1.45 reinoud ump->logvol_info = lvinfo; 1938 1.45 reinoud 1939 1.45 reinoud /* TODO check udf versions? */ 1940 1.45 reinoud 1941 1.45 reinoud /* 1942 1.45 reinoud * check logvol mappings: effective virt->log partmap translation 1943 1.45 reinoud * check and recording of the mapping results. Saves expensive 1944 1.45 reinoud * strncmp() in tight places. 1945 1.45 reinoud */ 1946 1.45 reinoud DPRINTF(VOLUMES, ("checking logvol mappings\n")); 1947 1.45 reinoud n_pm = udf_rw32(ump->logical_vol->n_pm); /* num partmaps */ 1948 1.45 reinoud pmap_pos = ump->logical_vol->maps; 1949 1.45 reinoud 1950 1.45 reinoud if (n_pm > UDF_PMAPS) { 1951 1.45 reinoud printf("UDF mount: too many mappings\n"); 1952 1.45 reinoud return EINVAL; 1953 1.45 reinoud } 1954 1.45 reinoud 1955 1.71 reinoud /* count types and set partition numbers */ 1956 1.71 reinoud ump->data_part = ump->node_part = ump->fids_part = 0; 1957 1.45 reinoud n_phys = n_virt = n_spar = n_meta = 0; 1958 1.45 reinoud for (log_part = 0; log_part < n_pm; log_part++) { 1959 1.45 reinoud mapping = (union udf_pmap *) pmap_pos; 1960 1.45 reinoud pmap_stype = pmap_pos[0]; 1961 1.45 reinoud pmap_size = pmap_pos[1]; 1962 1.45 reinoud switch (pmap_stype) { 1963 1.45 reinoud case 1: /* physical mapping */ 1964 1.45 reinoud /* volseq = udf_rw16(mapping->pm1.vol_seq_num); */ 1965 1.45 reinoud raw_phys_part = udf_rw16(mapping->pm1.part_num); 1966 1.45 reinoud pmap_type = UDF_VTOP_TYPE_PHYS; 1967 1.45 reinoud n_phys++; 1968 1.71 reinoud ump->data_part = log_part; 1969 1.71 reinoud ump->node_part = log_part; 1970 1.71 reinoud ump->fids_part = log_part; 1971 1.45 reinoud break; 1972 1.45 reinoud case 2: /* virtual/sparable/meta mapping */ 1973 1.45 reinoud map_name = mapping->pm2.part_id.id; 1974 1.45 reinoud /* volseq = udf_rw16(mapping->pm2.vol_seq_num); */ 1975 1.45 reinoud raw_phys_part = udf_rw16(mapping->pm2.part_num); 1976 1.45 reinoud pmap_type = UDF_VTOP_TYPE_UNKNOWN; 1977 1.45 reinoud len = UDF_REGID_ID_SIZE; 1978 1.45 reinoud 1979 1.45 reinoud check_name = "*UDF Virtual Partition"; 1980 1.45 reinoud if (strncmp(map_name, check_name, len) == 0) { 1981 1.45 reinoud pmap_type = UDF_VTOP_TYPE_VIRT; 1982 1.45 reinoud n_virt++; 1983 1.71 reinoud ump->node_part = log_part; 1984 1.45 reinoud break; 1985 1.45 reinoud } 1986 1.45 reinoud check_name = "*UDF Sparable Partition"; 1987 1.45 reinoud if (strncmp(map_name, check_name, len) == 0) { 1988 1.45 reinoud pmap_type = UDF_VTOP_TYPE_SPARABLE; 1989 1.45 reinoud n_spar++; 1990 1.71 reinoud ump->data_part = log_part; 1991 1.71 reinoud ump->node_part = log_part; 1992 1.71 reinoud ump->fids_part = log_part; 1993 1.45 reinoud break; 1994 1.45 reinoud } 1995 1.45 reinoud check_name = "*UDF Metadata Partition"; 1996 1.45 reinoud if (strncmp(map_name, check_name, len) == 0) { 1997 1.45 reinoud pmap_type = UDF_VTOP_TYPE_META; 1998 1.45 reinoud n_meta++; 1999 1.71 reinoud ump->node_part = log_part; 2000 1.71 reinoud ump->fids_part = log_part; 2001 1.45 reinoud break; 2002 1.45 reinoud } 2003 1.45 reinoud break; 2004 1.45 reinoud default: 2005 1.45 reinoud return EINVAL; 2006 1.45 reinoud } 2007 1.45 reinoud 2008 1.45 reinoud /* 2009 1.45 reinoud * BUGALERT: some rogue implementations use random physical 2010 1.100 mbalmer * partition numbers to break other implementations so lookup 2011 1.45 reinoud * the number. 2012 1.45 reinoud */ 2013 1.111 reinoud phys_part = udf_find_raw_phys(ump, raw_phys_part); 2014 1.45 reinoud 2015 1.45 reinoud DPRINTF(VOLUMES, ("\t%d -> %d(%d) type %d\n", log_part, 2016 1.45 reinoud raw_phys_part, phys_part, pmap_type)); 2017 1.152 skrll 2018 1.45 reinoud if (phys_part == UDF_PARTITIONS) 2019 1.45 reinoud return EINVAL; 2020 1.45 reinoud if (pmap_type == UDF_VTOP_TYPE_UNKNOWN) 2021 1.45 reinoud return EINVAL; 2022 1.45 reinoud 2023 1.45 reinoud ump->vtop [log_part] = phys_part; 2024 1.45 reinoud ump->vtop_tp[log_part] = pmap_type; 2025 1.45 reinoud 2026 1.45 reinoud pmap_pos += pmap_size; 2027 1.45 reinoud } 2028 1.45 reinoud /* not winning the beauty contest */ 2029 1.45 reinoud ump->vtop_tp[UDF_VTOP_RAWPART] = UDF_VTOP_TYPE_RAW; 2030 1.45 reinoud 2031 1.45 reinoud /* test some basic UDF assertions/requirements */ 2032 1.45 reinoud if ((n_virt > 1) || (n_spar > 1) || (n_meta > 1)) 2033 1.45 reinoud return EINVAL; 2034 1.45 reinoud 2035 1.45 reinoud if (n_virt) { 2036 1.45 reinoud if ((n_phys == 0) || n_spar || n_meta) 2037 1.45 reinoud return EINVAL; 2038 1.45 reinoud } 2039 1.45 reinoud if (n_spar + n_phys == 0) 2040 1.45 reinoud return EINVAL; 2041 1.45 reinoud 2042 1.71 reinoud /* select allocation type for each logical partition */ 2043 1.71 reinoud for (log_part = 0; log_part < n_pm; log_part++) { 2044 1.71 reinoud maps_on = ump->vtop[log_part]; 2045 1.71 reinoud switch (ump->vtop_tp[log_part]) { 2046 1.71 reinoud case UDF_VTOP_TYPE_PHYS : 2047 1.71 reinoud assert(maps_on == log_part); 2048 1.71 reinoud ump->vtop_alloc[log_part] = UDF_ALLOC_SPACEMAP; 2049 1.71 reinoud break; 2050 1.71 reinoud case UDF_VTOP_TYPE_VIRT : 2051 1.71 reinoud ump->vtop_alloc[log_part] = UDF_ALLOC_VAT; 2052 1.71 reinoud ump->vtop_alloc[maps_on] = UDF_ALLOC_SEQUENTIAL; 2053 1.71 reinoud break; 2054 1.71 reinoud case UDF_VTOP_TYPE_SPARABLE : 2055 1.71 reinoud assert(maps_on == log_part); 2056 1.71 reinoud ump->vtop_alloc[log_part] = UDF_ALLOC_SPACEMAP; 2057 1.71 reinoud break; 2058 1.71 reinoud case UDF_VTOP_TYPE_META : 2059 1.71 reinoud ump->vtop_alloc[log_part] = UDF_ALLOC_METABITMAP; 2060 1.71 reinoud if (ump->discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE) { 2061 1.71 reinoud /* special case for UDF 2.60 */ 2062 1.71 reinoud ump->vtop_alloc[log_part] = UDF_ALLOC_METASEQUENTIAL; 2063 1.71 reinoud ump->vtop_alloc[maps_on] = UDF_ALLOC_SEQUENTIAL; 2064 1.71 reinoud } 2065 1.71 reinoud break; 2066 1.71 reinoud default: 2067 1.159 msaitoh panic("bad allocation type in udf's ump->vtop\n"); 2068 1.45 reinoud } 2069 1.45 reinoud } 2070 1.45 reinoud 2071 1.45 reinoud /* determine logical volume open/closure actions */ 2072 1.45 reinoud if (n_virt) { 2073 1.45 reinoud ump->lvopen = 0; 2074 1.85 reinoud if (ump->discinfo.last_session_state == MMC_STATE_EMPTY) 2075 1.45 reinoud ump->lvopen |= UDF_OPEN_SESSION ; 2076 1.45 reinoud ump->lvclose = UDF_WRITE_VAT; 2077 1.45 reinoud if (ump->mount_args.udfmflags & UDFMNT_CLOSESESSION) 2078 1.45 reinoud ump->lvclose |= UDF_CLOSE_SESSION; 2079 1.45 reinoud } else { 2080 1.45 reinoud /* `normal' rewritable or non sequential media */ 2081 1.45 reinoud ump->lvopen = UDF_WRITE_LVINT; 2082 1.45 reinoud ump->lvclose = UDF_WRITE_LVINT; 2083 1.45 reinoud if ((ump->discinfo.mmc_cur & MMC_CAP_REWRITABLE) == 0) 2084 1.113 reinoud ump->lvopen |= UDF_APPENDONLY_LVINT; 2085 1.113 reinoud if ((ump->discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE)) 2086 1.113 reinoud ump->lvopen &= ~UDF_APPENDONLY_LVINT; 2087 1.45 reinoud } 2088 1.45 reinoud 2089 1.45 reinoud /* 2090 1.176 andvar * Determine scheduler error behaviour. For virtual partitions, update 2091 1.45 reinoud * the trackinfo; for sparable partitions replace a whole block on the 2092 1.154 andvar * sparable table. Always requeue. 2093 1.45 reinoud */ 2094 1.45 reinoud ump->lvreadwrite = 0; 2095 1.45 reinoud if (n_virt) 2096 1.45 reinoud ump->lvreadwrite = UDF_UPDATE_TRACKINFO; 2097 1.45 reinoud if (n_spar) 2098 1.45 reinoud ump->lvreadwrite = UDF_REMAP_BLOCK; 2099 1.45 reinoud 2100 1.45 reinoud /* 2101 1.176 andvar * Select our scheduler 2102 1.45 reinoud */ 2103 1.45 reinoud ump->strategy = &udf_strat_rmw; 2104 1.45 reinoud if (n_virt || (ump->discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE)) 2105 1.45 reinoud ump->strategy = &udf_strat_sequential; 2106 1.45 reinoud if ((ump->discinfo.mmc_class == MMC_CLASS_DISC) || 2107 1.45 reinoud (ump->discinfo.mmc_class == MMC_CLASS_UNKN)) 2108 1.45 reinoud ump->strategy = &udf_strat_direct; 2109 1.45 reinoud if (n_spar) 2110 1.45 reinoud ump->strategy = &udf_strat_rmw; 2111 1.45 reinoud 2112 1.75 reinoud #if 0 2113 1.176 andvar /* read-only access won't benefit from the other schedulers */ 2114 1.75 reinoud if (ump->vfs_mountp->mnt_flag & MNT_RDONLY) 2115 1.75 reinoud ump->strategy = &udf_strat_direct; 2116 1.75 reinoud #endif 2117 1.75 reinoud 2118 1.45 reinoud /* print results */ 2119 1.71 reinoud DPRINTF(VOLUMES, ("\tdata partition %d\n", ump->data_part)); 2120 1.71 reinoud DPRINTF(VOLUMES, ("\t\talloc scheme %d\n", ump->vtop_alloc[ump->data_part])); 2121 1.71 reinoud DPRINTF(VOLUMES, ("\tnode partition %d\n", ump->node_part)); 2122 1.71 reinoud DPRINTF(VOLUMES, ("\t\talloc scheme %d\n", ump->vtop_alloc[ump->node_part])); 2123 1.71 reinoud DPRINTF(VOLUMES, ("\tfids partition %d\n", ump->fids_part)); 2124 1.71 reinoud DPRINTF(VOLUMES, ("\t\talloc scheme %d\n", ump->vtop_alloc[ump->fids_part])); 2125 1.45 reinoud 2126 1.80 christos snprintb(bits, sizeof(bits), UDFLOGVOL_BITS, ump->lvopen); 2127 1.45 reinoud DPRINTF(VOLUMES, ("\tactions on logvol open %s\n", bits)); 2128 1.80 christos snprintb(bits, sizeof(bits), UDFLOGVOL_BITS, ump->lvclose); 2129 1.45 reinoud DPRINTF(VOLUMES, ("\tactions on logvol close %s\n", bits)); 2130 1.80 christos snprintb(bits, sizeof(bits), UDFONERROR_BITS, ump->lvreadwrite); 2131 1.45 reinoud DPRINTF(VOLUMES, ("\tactions on logvol errors %s\n", bits)); 2132 1.45 reinoud 2133 1.176 andvar DPRINTF(VOLUMES, ("\tselected scheduler `%s`\n", 2134 1.45 reinoud (ump->strategy == &udf_strat_direct) ? "Direct" : 2135 1.45 reinoud (ump->strategy == &udf_strat_sequential) ? "Sequential" : 2136 1.45 reinoud (ump->strategy == &udf_strat_rmw) ? "RMW" : "UNKNOWN!")); 2137 1.45 reinoud 2138 1.45 reinoud /* signal its OK for now */ 2139 1.45 reinoud return 0; 2140 1.45 reinoud } 2141 1.45 reinoud 2142 1.45 reinoud /* --------------------------------------------------------------------- */ 2143 1.45 reinoud 2144 1.45 reinoud /* 2145 1.45 reinoud * Update logical volume name in all structures that keep a record of it. We 2146 1.45 reinoud * use memmove since each of them might be specified as a source. 2147 1.45 reinoud * 2148 1.45 reinoud * Note that it doesn't update the VAT structure! 2149 1.45 reinoud */ 2150 1.45 reinoud 2151 1.45 reinoud static void 2152 1.45 reinoud udf_update_logvolname(struct udf_mount *ump, char *logvol_id) 2153 1.45 reinoud { 2154 1.45 reinoud struct logvol_desc *lvd = NULL; 2155 1.45 reinoud struct fileset_desc *fsd = NULL; 2156 1.45 reinoud struct udf_lv_info *lvi = NULL; 2157 1.45 reinoud 2158 1.45 reinoud DPRINTF(VOLUMES, ("Updating logical volume name\n")); 2159 1.45 reinoud lvd = ump->logical_vol; 2160 1.45 reinoud fsd = ump->fileset_desc; 2161 1.45 reinoud if (ump->implementation) 2162 1.45 reinoud lvi = &ump->implementation->_impl_use.lv_info; 2163 1.45 reinoud 2164 1.171 andvar /* logvol's id might be specified as original so use memmove here */ 2165 1.45 reinoud memmove(lvd->logvol_id, logvol_id, 128); 2166 1.45 reinoud if (fsd) 2167 1.45 reinoud memmove(fsd->logvol_id, logvol_id, 128); 2168 1.45 reinoud if (lvi) 2169 1.45 reinoud memmove(lvi->logvol_id, logvol_id, 128); 2170 1.45 reinoud } 2171 1.45 reinoud 2172 1.45 reinoud /* --------------------------------------------------------------------- */ 2173 1.45 reinoud 2174 1.55 reinoud void 2175 1.51 reinoud udf_inittag(struct udf_mount *ump, struct desc_tag *tag, int tagid, 2176 1.51 reinoud uint32_t sector) 2177 1.51 reinoud { 2178 1.51 reinoud assert(ump->logical_vol); 2179 1.51 reinoud 2180 1.51 reinoud tag->id = udf_rw16(tagid); 2181 1.51 reinoud tag->descriptor_ver = ump->logical_vol->tag.descriptor_ver; 2182 1.51 reinoud tag->cksum = 0; 2183 1.51 reinoud tag->reserved = 0; 2184 1.51 reinoud tag->serial_num = ump->logical_vol->tag.serial_num; 2185 1.51 reinoud tag->tag_loc = udf_rw32(sector); 2186 1.51 reinoud } 2187 1.51 reinoud 2188 1.51 reinoud 2189 1.51 reinoud uint64_t 2190 1.51 reinoud udf_advance_uniqueid(struct udf_mount *ump) 2191 1.51 reinoud { 2192 1.51 reinoud uint64_t unique_id; 2193 1.51 reinoud 2194 1.51 reinoud mutex_enter(&ump->logvol_mutex); 2195 1.51 reinoud unique_id = udf_rw64(ump->logvol_integrity->lvint_next_unique_id); 2196 1.51 reinoud if (unique_id < 0x10) 2197 1.51 reinoud unique_id = 0x10; 2198 1.51 reinoud ump->logvol_integrity->lvint_next_unique_id = udf_rw64(unique_id + 1); 2199 1.51 reinoud mutex_exit(&ump->logvol_mutex); 2200 1.51 reinoud 2201 1.51 reinoud return unique_id; 2202 1.51 reinoud } 2203 1.51 reinoud 2204 1.51 reinoud 2205 1.51 reinoud static void 2206 1.51 reinoud udf_adjust_filecount(struct udf_node *udf_node, int sign) 2207 1.51 reinoud { 2208 1.51 reinoud struct udf_mount *ump = udf_node->ump; 2209 1.51 reinoud uint32_t num_dirs, num_files; 2210 1.51 reinoud int udf_file_type; 2211 1.51 reinoud 2212 1.51 reinoud /* get file type */ 2213 1.51 reinoud if (udf_node->fe) { 2214 1.51 reinoud udf_file_type = udf_node->fe->icbtag.file_type; 2215 1.51 reinoud } else { 2216 1.51 reinoud udf_file_type = udf_node->efe->icbtag.file_type; 2217 1.51 reinoud } 2218 1.51 reinoud 2219 1.51 reinoud /* adjust file count */ 2220 1.51 reinoud mutex_enter(&ump->allocate_mutex); 2221 1.51 reinoud if (udf_file_type == UDF_ICB_FILETYPE_DIRECTORY) { 2222 1.51 reinoud num_dirs = udf_rw32(ump->logvol_info->num_directories); 2223 1.51 reinoud ump->logvol_info->num_directories = 2224 1.51 reinoud udf_rw32((num_dirs + sign)); 2225 1.51 reinoud } else { 2226 1.51 reinoud num_files = udf_rw32(ump->logvol_info->num_files); 2227 1.51 reinoud ump->logvol_info->num_files = 2228 1.51 reinoud udf_rw32((num_files + sign)); 2229 1.51 reinoud } 2230 1.51 reinoud mutex_exit(&ump->allocate_mutex); 2231 1.51 reinoud } 2232 1.51 reinoud 2233 1.51 reinoud 2234 1.51 reinoud void 2235 1.51 reinoud udf_osta_charset(struct charspec *charspec) 2236 1.51 reinoud { 2237 1.87 cegger memset(charspec, 0, sizeof(struct charspec)); 2238 1.51 reinoud charspec->type = 0; 2239 1.51 reinoud strcpy((char *) charspec->inf, "OSTA Compressed Unicode"); 2240 1.51 reinoud } 2241 1.51 reinoud 2242 1.51 reinoud 2243 1.51 reinoud /* first call udf_set_regid and then the suffix */ 2244 1.51 reinoud void 2245 1.51 reinoud udf_set_regid(struct regid *regid, char const *name) 2246 1.51 reinoud { 2247 1.87 cegger memset(regid, 0, sizeof(struct regid)); 2248 1.51 reinoud regid->flags = 0; /* not dirty and not protected */ 2249 1.51 reinoud strcpy((char *) regid->id, name); 2250 1.51 reinoud } 2251 1.51 reinoud 2252 1.51 reinoud 2253 1.51 reinoud void 2254 1.51 reinoud udf_add_domain_regid(struct udf_mount *ump, struct regid *regid) 2255 1.51 reinoud { 2256 1.51 reinoud uint16_t *ver; 2257 1.51 reinoud 2258 1.51 reinoud ver = (uint16_t *) regid->id_suffix; 2259 1.51 reinoud *ver = ump->logvol_info->min_udf_readver; 2260 1.51 reinoud } 2261 1.51 reinoud 2262 1.51 reinoud 2263 1.51 reinoud void 2264 1.51 reinoud udf_add_udf_regid(struct udf_mount *ump, struct regid *regid) 2265 1.51 reinoud { 2266 1.51 reinoud uint16_t *ver; 2267 1.51 reinoud 2268 1.51 reinoud ver = (uint16_t *) regid->id_suffix; 2269 1.51 reinoud *ver = ump->logvol_info->min_udf_readver; 2270 1.51 reinoud 2271 1.51 reinoud regid->id_suffix[2] = 4; /* unix */ 2272 1.51 reinoud regid->id_suffix[3] = 8; /* NetBSD */ 2273 1.51 reinoud } 2274 1.51 reinoud 2275 1.51 reinoud 2276 1.51 reinoud void 2277 1.51 reinoud udf_add_impl_regid(struct udf_mount *ump, struct regid *regid) 2278 1.51 reinoud { 2279 1.51 reinoud regid->id_suffix[0] = 4; /* unix */ 2280 1.51 reinoud regid->id_suffix[1] = 8; /* NetBSD */ 2281 1.51 reinoud } 2282 1.51 reinoud 2283 1.51 reinoud 2284 1.51 reinoud void 2285 1.51 reinoud udf_add_app_regid(struct udf_mount *ump, struct regid *regid) 2286 1.51 reinoud { 2287 1.51 reinoud regid->id_suffix[0] = APP_VERSION_MAIN; 2288 1.51 reinoud regid->id_suffix[1] = APP_VERSION_SUB; 2289 1.51 reinoud } 2290 1.51 reinoud 2291 1.51 reinoud static int 2292 1.51 reinoud udf_create_parentfid(struct udf_mount *ump, struct fileid_desc *fid, 2293 1.51 reinoud struct long_ad *parent, uint64_t unique_id) 2294 1.51 reinoud { 2295 1.51 reinoud /* the size of an empty FID is 38 but needs to be a multiple of 4 */ 2296 1.51 reinoud int fidsize = 40; 2297 1.51 reinoud 2298 1.51 reinoud udf_inittag(ump, &fid->tag, TAGID_FID, udf_rw32(parent->loc.lb_num)); 2299 1.51 reinoud fid->file_version_num = udf_rw16(1); /* UDF 2.3.4.1 */ 2300 1.51 reinoud fid->file_char = UDF_FILE_CHAR_DIR | UDF_FILE_CHAR_PAR; 2301 1.51 reinoud fid->icb = *parent; 2302 1.51 reinoud fid->icb.longad_uniqueid = udf_rw32((uint32_t) unique_id); 2303 1.88 reinoud fid->tag.desc_crc_len = udf_rw16(fidsize - UDF_DESC_TAG_LENGTH); 2304 1.51 reinoud (void) udf_validate_tag_and_crc_sums((union dscrptr *) fid); 2305 1.51 reinoud 2306 1.51 reinoud return fidsize; 2307 1.51 reinoud } 2308 1.51 reinoud 2309 1.51 reinoud /* --------------------------------------------------------------------- */ 2310 1.51 reinoud 2311 1.45 reinoud /* 2312 1.51 reinoud * Extended attribute support. UDF knows of 3 places for extended attributes: 2313 1.45 reinoud * 2314 1.51 reinoud * (a) inside the file's (e)fe in the length of the extended attribute area 2315 1.51 reinoud * before the allocation descriptors/filedata 2316 1.45 reinoud * 2317 1.152 skrll * (b) in a file referenced by (e)fe->ext_attr_icb and 2318 1.45 reinoud * 2319 1.45 reinoud * (c) in the e(fe)'s associated stream directory that can hold various 2320 1.45 reinoud * sub-files. In the stream directory a few fixed named subfiles are reserved 2321 1.45 reinoud * for NT/Unix ACL's and OS/2 attributes. 2322 1.152 skrll * 2323 1.154 andvar * NOTE: Extended attributes are read randomly but always written 2324 1.154 andvar * *atomically*. For ACL's this interface is probably different but not known 2325 1.45 reinoud * to me yet. 2326 1.51 reinoud * 2327 1.154 andvar * Order of extended attributes in a space: 2328 1.51 reinoud * ECMA 167 EAs 2329 1.51 reinoud * Non block aligned Implementation Use EAs 2330 1.51 reinoud * Block aligned Implementation Use EAs 2331 1.51 reinoud * Application Use EAs 2332 1.45 reinoud */ 2333 1.45 reinoud 2334 1.45 reinoud static int 2335 1.45 reinoud udf_impl_extattr_check(struct impl_extattr_entry *implext) 2336 1.45 reinoud { 2337 1.45 reinoud uint16_t *spos; 2338 1.45 reinoud 2339 1.45 reinoud if (strncmp(implext->imp_id.id, "*UDF", 4) == 0) { 2340 1.45 reinoud /* checksum valid? */ 2341 1.45 reinoud DPRINTF(EXTATTR, ("checking UDF impl. attr checksum\n")); 2342 1.45 reinoud spos = (uint16_t *) implext->data; 2343 1.45 reinoud if (udf_rw16(*spos) != udf_ea_cksum((uint8_t *) implext)) 2344 1.45 reinoud return EINVAL; 2345 1.45 reinoud } 2346 1.45 reinoud return 0; 2347 1.45 reinoud } 2348 1.45 reinoud 2349 1.45 reinoud static void 2350 1.45 reinoud udf_calc_impl_extattr_checksum(struct impl_extattr_entry *implext) 2351 1.45 reinoud { 2352 1.45 reinoud uint16_t *spos; 2353 1.45 reinoud 2354 1.45 reinoud if (strncmp(implext->imp_id.id, "*UDF", 4) == 0) { 2355 1.45 reinoud /* set checksum */ 2356 1.45 reinoud spos = (uint16_t *) implext->data; 2357 1.45 reinoud *spos = udf_rw16(udf_ea_cksum((uint8_t *) implext)); 2358 1.45 reinoud } 2359 1.45 reinoud } 2360 1.45 reinoud 2361 1.45 reinoud 2362 1.45 reinoud int 2363 1.45 reinoud udf_extattr_search_intern(struct udf_node *node, 2364 1.45 reinoud uint32_t sattr, char const *sattrname, 2365 1.45 reinoud uint32_t *offsetp, uint32_t *lengthp) 2366 1.45 reinoud { 2367 1.45 reinoud struct extattrhdr_desc *eahdr; 2368 1.45 reinoud struct extattr_entry *attrhdr; 2369 1.45 reinoud struct impl_extattr_entry *implext; 2370 1.45 reinoud uint32_t offset, a_l, sector_size; 2371 1.45 reinoud int32_t l_ea; 2372 1.45 reinoud uint8_t *pos; 2373 1.45 reinoud int error; 2374 1.45 reinoud 2375 1.45 reinoud /* get mountpoint */ 2376 1.45 reinoud sector_size = node->ump->discinfo.sector_size; 2377 1.45 reinoud 2378 1.45 reinoud /* get information from fe/efe */ 2379 1.45 reinoud if (node->fe) { 2380 1.45 reinoud l_ea = udf_rw32(node->fe->l_ea); 2381 1.45 reinoud eahdr = (struct extattrhdr_desc *) node->fe->data; 2382 1.45 reinoud } else { 2383 1.45 reinoud assert(node->efe); 2384 1.45 reinoud l_ea = udf_rw32(node->efe->l_ea); 2385 1.45 reinoud eahdr = (struct extattrhdr_desc *) node->efe->data; 2386 1.45 reinoud } 2387 1.45 reinoud 2388 1.45 reinoud /* something recorded here? */ 2389 1.45 reinoud if (l_ea == 0) 2390 1.45 reinoud return ENOENT; 2391 1.45 reinoud 2392 1.45 reinoud /* check extended attribute tag; what to do if it fails? */ 2393 1.45 reinoud error = udf_check_tag(eahdr); 2394 1.45 reinoud if (error) 2395 1.45 reinoud return EINVAL; 2396 1.45 reinoud if (udf_rw16(eahdr->tag.id) != TAGID_EXTATTR_HDR) 2397 1.45 reinoud return EINVAL; 2398 1.45 reinoud error = udf_check_tag_payload(eahdr, sizeof(struct extattrhdr_desc)); 2399 1.45 reinoud if (error) 2400 1.45 reinoud return EINVAL; 2401 1.45 reinoud 2402 1.45 reinoud DPRINTF(EXTATTR, ("Found %d bytes of extended attributes\n", l_ea)); 2403 1.45 reinoud 2404 1.45 reinoud /* looking for Ecma-167 attributes? */ 2405 1.45 reinoud offset = sizeof(struct extattrhdr_desc); 2406 1.45 reinoud 2407 1.163 msaitoh /* looking for either implementation use or application use */ 2408 1.45 reinoud if (sattr == 2048) { /* [4/48.10.8] */ 2409 1.45 reinoud offset = udf_rw32(eahdr->impl_attr_loc); 2410 1.45 reinoud if (offset == UDF_IMPL_ATTR_LOC_NOT_PRESENT) 2411 1.45 reinoud return ENOENT; 2412 1.45 reinoud } 2413 1.45 reinoud if (sattr == 65536) { /* [4/48.10.9] */ 2414 1.45 reinoud offset = udf_rw32(eahdr->appl_attr_loc); 2415 1.45 reinoud if (offset == UDF_APPL_ATTR_LOC_NOT_PRESENT) 2416 1.45 reinoud return ENOENT; 2417 1.45 reinoud } 2418 1.45 reinoud 2419 1.45 reinoud /* paranoia check offset and l_ea */ 2420 1.45 reinoud if (l_ea + offset >= sector_size - sizeof(struct extattr_entry)) 2421 1.45 reinoud return EINVAL; 2422 1.45 reinoud 2423 1.45 reinoud DPRINTF(EXTATTR, ("Starting at offset %d\n", offset)); 2424 1.45 reinoud 2425 1.45 reinoud /* find our extended attribute */ 2426 1.45 reinoud l_ea -= offset; 2427 1.45 reinoud pos = (uint8_t *) eahdr + offset; 2428 1.45 reinoud 2429 1.45 reinoud while (l_ea >= sizeof(struct extattr_entry)) { 2430 1.45 reinoud DPRINTF(EXTATTR, ("%d extended attr bytes left\n", l_ea)); 2431 1.45 reinoud attrhdr = (struct extattr_entry *) pos; 2432 1.45 reinoud implext = (struct impl_extattr_entry *) pos; 2433 1.45 reinoud 2434 1.45 reinoud /* get complete attribute length and check for roque values */ 2435 1.45 reinoud a_l = udf_rw32(attrhdr->a_l); 2436 1.45 reinoud DPRINTF(EXTATTR, ("attribute %d:%d, len %d/%d\n", 2437 1.45 reinoud udf_rw32(attrhdr->type), 2438 1.45 reinoud attrhdr->subtype, a_l, l_ea)); 2439 1.45 reinoud if ((a_l == 0) || (a_l > l_ea)) 2440 1.45 reinoud return EINVAL; 2441 1.45 reinoud 2442 1.169 reinoud if (udf_rw32(attrhdr->type) != sattr) 2443 1.45 reinoud goto next_attribute; 2444 1.45 reinoud 2445 1.45 reinoud /* we might have found it! */ 2446 1.169 reinoud if (udf_rw32(attrhdr->type) < 2048) { /* Ecma-167 attribute */ 2447 1.45 reinoud *offsetp = offset; 2448 1.45 reinoud *lengthp = a_l; 2449 1.45 reinoud return 0; /* success */ 2450 1.45 reinoud } 2451 1.45 reinoud 2452 1.45 reinoud /* 2453 1.45 reinoud * Implementation use and application use extended attributes 2454 1.45 reinoud * have a name to identify. They share the same structure only 2455 1.45 reinoud * UDF implementation use extended attributes have a checksum 2456 1.45 reinoud * we need to check 2457 1.45 reinoud */ 2458 1.45 reinoud 2459 1.45 reinoud DPRINTF(EXTATTR, ("named attribute %s\n", implext->imp_id.id)); 2460 1.45 reinoud if (strcmp(implext->imp_id.id, sattrname) == 0) { 2461 1.45 reinoud /* we have found our appl/implementation attribute */ 2462 1.45 reinoud *offsetp = offset; 2463 1.45 reinoud *lengthp = a_l; 2464 1.45 reinoud return 0; /* success */ 2465 1.45 reinoud } 2466 1.45 reinoud 2467 1.45 reinoud next_attribute: 2468 1.45 reinoud /* next attribute */ 2469 1.45 reinoud pos += a_l; 2470 1.45 reinoud l_ea -= a_l; 2471 1.45 reinoud offset += a_l; 2472 1.45 reinoud } 2473 1.45 reinoud /* not found */ 2474 1.45 reinoud return ENOENT; 2475 1.45 reinoud } 2476 1.45 reinoud 2477 1.45 reinoud 2478 1.51 reinoud static void 2479 1.51 reinoud udf_extattr_insert_internal(struct udf_mount *ump, union dscrptr *dscr, 2480 1.51 reinoud struct extattr_entry *extattr) 2481 1.51 reinoud { 2482 1.51 reinoud struct file_entry *fe; 2483 1.51 reinoud struct extfile_entry *efe; 2484 1.51 reinoud struct extattrhdr_desc *extattrhdr; 2485 1.51 reinoud struct impl_extattr_entry *implext; 2486 1.51 reinoud uint32_t impl_attr_loc, appl_attr_loc, l_ea, a_l, exthdr_len; 2487 1.51 reinoud uint32_t *l_eap, l_ad; 2488 1.51 reinoud uint16_t *spos; 2489 1.51 reinoud uint8_t *bpos, *data; 2490 1.51 reinoud 2491 1.51 reinoud if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) { 2492 1.51 reinoud fe = &dscr->fe; 2493 1.51 reinoud data = fe->data; 2494 1.51 reinoud l_eap = &fe->l_ea; 2495 1.51 reinoud l_ad = udf_rw32(fe->l_ad); 2496 1.51 reinoud } else if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) { 2497 1.51 reinoud efe = &dscr->efe; 2498 1.51 reinoud data = efe->data; 2499 1.51 reinoud l_eap = &efe->l_ea; 2500 1.51 reinoud l_ad = udf_rw32(efe->l_ad); 2501 1.51 reinoud } else { 2502 1.51 reinoud panic("Bad tag passed to udf_extattr_insert_internal"); 2503 1.51 reinoud } 2504 1.51 reinoud 2505 1.51 reinoud /* can't append already written to file descriptors yet */ 2506 1.51 reinoud assert(l_ad == 0); 2507 1.124 christos __USE(l_ad); 2508 1.51 reinoud 2509 1.51 reinoud /* should have a header! */ 2510 1.51 reinoud extattrhdr = (struct extattrhdr_desc *) data; 2511 1.51 reinoud l_ea = udf_rw32(*l_eap); 2512 1.51 reinoud if (l_ea == 0) { 2513 1.51 reinoud /* create empty extended attribute header */ 2514 1.51 reinoud exthdr_len = sizeof(struct extattrhdr_desc); 2515 1.51 reinoud 2516 1.51 reinoud udf_inittag(ump, &extattrhdr->tag, TAGID_EXTATTR_HDR, 2517 1.51 reinoud /* loc */ 0); 2518 1.51 reinoud extattrhdr->impl_attr_loc = udf_rw32(exthdr_len); 2519 1.51 reinoud extattrhdr->appl_attr_loc = udf_rw32(exthdr_len); 2520 1.51 reinoud extattrhdr->tag.desc_crc_len = udf_rw16(8); 2521 1.51 reinoud 2522 1.51 reinoud /* record extended attribute header length */ 2523 1.51 reinoud l_ea = exthdr_len; 2524 1.51 reinoud *l_eap = udf_rw32(l_ea); 2525 1.51 reinoud } 2526 1.51 reinoud 2527 1.51 reinoud /* extract locations */ 2528 1.51 reinoud impl_attr_loc = udf_rw32(extattrhdr->impl_attr_loc); 2529 1.51 reinoud appl_attr_loc = udf_rw32(extattrhdr->appl_attr_loc); 2530 1.51 reinoud if (impl_attr_loc == UDF_IMPL_ATTR_LOC_NOT_PRESENT) 2531 1.51 reinoud impl_attr_loc = l_ea; 2532 1.51 reinoud if (appl_attr_loc == UDF_IMPL_ATTR_LOC_NOT_PRESENT) 2533 1.51 reinoud appl_attr_loc = l_ea; 2534 1.51 reinoud 2535 1.51 reinoud /* Ecma 167 EAs */ 2536 1.51 reinoud if (udf_rw32(extattr->type) < 2048) { 2537 1.51 reinoud assert(impl_attr_loc == l_ea); 2538 1.51 reinoud assert(appl_attr_loc == l_ea); 2539 1.51 reinoud } 2540 1.51 reinoud 2541 1.51 reinoud /* implementation use extended attributes */ 2542 1.51 reinoud if (udf_rw32(extattr->type) == 2048) { 2543 1.51 reinoud assert(appl_attr_loc == l_ea); 2544 1.51 reinoud 2545 1.51 reinoud /* calculate and write extended attribute header checksum */ 2546 1.51 reinoud implext = (struct impl_extattr_entry *) extattr; 2547 1.51 reinoud assert(udf_rw32(implext->iu_l) == 4); /* [UDF 3.3.4.5] */ 2548 1.51 reinoud spos = (uint16_t *) implext->data; 2549 1.51 reinoud *spos = udf_rw16(udf_ea_cksum((uint8_t *) implext)); 2550 1.51 reinoud } 2551 1.51 reinoud 2552 1.51 reinoud /* application use extended attributes */ 2553 1.51 reinoud assert(udf_rw32(extattr->type) != 65536); 2554 1.51 reinoud assert(appl_attr_loc == l_ea); 2555 1.51 reinoud 2556 1.51 reinoud /* append the attribute at the end of the current space */ 2557 1.51 reinoud bpos = data + udf_rw32(*l_eap); 2558 1.51 reinoud a_l = udf_rw32(extattr->a_l); 2559 1.51 reinoud 2560 1.51 reinoud /* update impl. attribute locations */ 2561 1.51 reinoud if (udf_rw32(extattr->type) < 2048) { 2562 1.51 reinoud impl_attr_loc = l_ea + a_l; 2563 1.51 reinoud appl_attr_loc = l_ea + a_l; 2564 1.51 reinoud } 2565 1.51 reinoud if (udf_rw32(extattr->type) == 2048) { 2566 1.51 reinoud appl_attr_loc = l_ea + a_l; 2567 1.51 reinoud } 2568 1.51 reinoud 2569 1.51 reinoud /* copy and advance */ 2570 1.51 reinoud memcpy(bpos, extattr, a_l); 2571 1.51 reinoud l_ea += a_l; 2572 1.51 reinoud *l_eap = udf_rw32(l_ea); 2573 1.51 reinoud 2574 1.51 reinoud /* do the `dance` again backwards */ 2575 1.51 reinoud if (udf_rw16(ump->logical_vol->tag.descriptor_ver) != 2) { 2576 1.51 reinoud if (impl_attr_loc == l_ea) 2577 1.51 reinoud impl_attr_loc = UDF_IMPL_ATTR_LOC_NOT_PRESENT; 2578 1.51 reinoud if (appl_attr_loc == l_ea) 2579 1.51 reinoud appl_attr_loc = UDF_APPL_ATTR_LOC_NOT_PRESENT; 2580 1.51 reinoud } 2581 1.51 reinoud 2582 1.51 reinoud /* store offsets */ 2583 1.51 reinoud extattrhdr->impl_attr_loc = udf_rw32(impl_attr_loc); 2584 1.51 reinoud extattrhdr->appl_attr_loc = udf_rw32(appl_attr_loc); 2585 1.51 reinoud } 2586 1.51 reinoud 2587 1.45 reinoud 2588 1.45 reinoud /* --------------------------------------------------------------------- */ 2589 1.45 reinoud 2590 1.152 skrll static int 2591 1.45 reinoud udf_update_lvid_from_vat_extattr(struct udf_node *vat_node) 2592 1.45 reinoud { 2593 1.45 reinoud struct udf_mount *ump; 2594 1.45 reinoud struct udf_logvol_info *lvinfo; 2595 1.45 reinoud struct impl_extattr_entry *implext; 2596 1.45 reinoud struct vatlvext_extattr_entry lvext; 2597 1.45 reinoud const char *extstr = "*UDF VAT LVExtension"; 2598 1.45 reinoud uint64_t vat_uniqueid; 2599 1.45 reinoud uint32_t offset, a_l; 2600 1.45 reinoud uint8_t *ea_start, *lvextpos; 2601 1.45 reinoud int error; 2602 1.45 reinoud 2603 1.45 reinoud /* get mountpoint and lvinfo */ 2604 1.45 reinoud ump = vat_node->ump; 2605 1.45 reinoud lvinfo = ump->logvol_info; 2606 1.45 reinoud 2607 1.45 reinoud /* get information from fe/efe */ 2608 1.45 reinoud if (vat_node->fe) { 2609 1.45 reinoud vat_uniqueid = udf_rw64(vat_node->fe->unique_id); 2610 1.45 reinoud ea_start = vat_node->fe->data; 2611 1.45 reinoud } else { 2612 1.45 reinoud vat_uniqueid = udf_rw64(vat_node->efe->unique_id); 2613 1.45 reinoud ea_start = vat_node->efe->data; 2614 1.45 reinoud } 2615 1.45 reinoud 2616 1.45 reinoud error = udf_extattr_search_intern(vat_node, 2048, extstr, &offset, &a_l); 2617 1.45 reinoud if (error) 2618 1.45 reinoud return error; 2619 1.45 reinoud 2620 1.45 reinoud implext = (struct impl_extattr_entry *) (ea_start + offset); 2621 1.45 reinoud error = udf_impl_extattr_check(implext); 2622 1.45 reinoud if (error) 2623 1.45 reinoud return error; 2624 1.45 reinoud 2625 1.45 reinoud /* paranoia */ 2626 1.143 reinoud if (a_l != sizeof(*implext) -2 + udf_rw32(implext->iu_l) + sizeof(lvext)) { 2627 1.45 reinoud DPRINTF(VOLUMES, ("VAT LVExtension size doesn't compute\n")); 2628 1.45 reinoud return EINVAL; 2629 1.45 reinoud } 2630 1.45 reinoud 2631 1.45 reinoud /* 2632 1.45 reinoud * we have found our "VAT LVExtension attribute. BUT due to a 2633 1.45 reinoud * bug in the specification it might not be word aligned so 2634 1.45 reinoud * copy first to avoid panics on some machines (!!) 2635 1.45 reinoud */ 2636 1.45 reinoud DPRINTF(VOLUMES, ("Found VAT LVExtension attr\n")); 2637 1.45 reinoud lvextpos = implext->data + udf_rw32(implext->iu_l); 2638 1.45 reinoud memcpy(&lvext, lvextpos, sizeof(lvext)); 2639 1.45 reinoud 2640 1.45 reinoud /* check if it was updated the last time */ 2641 1.45 reinoud if (udf_rw64(lvext.unique_id_chk) == vat_uniqueid) { 2642 1.45 reinoud lvinfo->num_files = lvext.num_files; 2643 1.45 reinoud lvinfo->num_directories = lvext.num_directories; 2644 1.45 reinoud udf_update_logvolname(ump, lvext.logvol_id); 2645 1.45 reinoud } else { 2646 1.45 reinoud DPRINTF(VOLUMES, ("VAT LVExtension out of date\n")); 2647 1.45 reinoud /* replace VAT LVExt by free space EA */ 2648 1.45 reinoud memset(implext->imp_id.id, 0, UDF_REGID_ID_SIZE); 2649 1.45 reinoud strcpy(implext->imp_id.id, "*UDF FreeEASpace"); 2650 1.45 reinoud udf_calc_impl_extattr_checksum(implext); 2651 1.45 reinoud } 2652 1.45 reinoud 2653 1.45 reinoud return 0; 2654 1.45 reinoud } 2655 1.45 reinoud 2656 1.45 reinoud 2657 1.152 skrll static int 2658 1.45 reinoud udf_update_vat_extattr_from_lvid(struct udf_node *vat_node) 2659 1.45 reinoud { 2660 1.45 reinoud struct udf_mount *ump; 2661 1.45 reinoud struct udf_logvol_info *lvinfo; 2662 1.45 reinoud struct impl_extattr_entry *implext; 2663 1.45 reinoud struct vatlvext_extattr_entry lvext; 2664 1.45 reinoud const char *extstr = "*UDF VAT LVExtension"; 2665 1.45 reinoud uint64_t vat_uniqueid; 2666 1.45 reinoud uint32_t offset, a_l; 2667 1.153 mrg uint8_t *ea_start; 2668 1.153 mrg uintptr_t lvextpos; 2669 1.45 reinoud int error; 2670 1.45 reinoud 2671 1.45 reinoud /* get mountpoint and lvinfo */ 2672 1.45 reinoud ump = vat_node->ump; 2673 1.45 reinoud lvinfo = ump->logvol_info; 2674 1.45 reinoud 2675 1.45 reinoud /* get information from fe/efe */ 2676 1.45 reinoud if (vat_node->fe) { 2677 1.45 reinoud vat_uniqueid = udf_rw64(vat_node->fe->unique_id); 2678 1.45 reinoud ea_start = vat_node->fe->data; 2679 1.45 reinoud } else { 2680 1.45 reinoud vat_uniqueid = udf_rw64(vat_node->efe->unique_id); 2681 1.45 reinoud ea_start = vat_node->efe->data; 2682 1.45 reinoud } 2683 1.45 reinoud 2684 1.45 reinoud error = udf_extattr_search_intern(vat_node, 2048, extstr, &offset, &a_l); 2685 1.45 reinoud if (error) 2686 1.45 reinoud return error; 2687 1.45 reinoud /* found, it existed */ 2688 1.45 reinoud 2689 1.45 reinoud /* paranoia */ 2690 1.45 reinoud implext = (struct impl_extattr_entry *) (ea_start + offset); 2691 1.45 reinoud error = udf_impl_extattr_check(implext); 2692 1.45 reinoud if (error) { 2693 1.45 reinoud DPRINTF(VOLUMES, ("VAT LVExtension bad on update\n")); 2694 1.45 reinoud return error; 2695 1.45 reinoud } 2696 1.45 reinoud /* it is correct */ 2697 1.45 reinoud 2698 1.45 reinoud /* 2699 1.45 reinoud * we have found our "VAT LVExtension attribute. BUT due to a 2700 1.45 reinoud * bug in the specification it might not be word aligned so 2701 1.45 reinoud * copy first to avoid panics on some machines (!!) 2702 1.45 reinoud */ 2703 1.45 reinoud DPRINTF(VOLUMES, ("Updating VAT LVExtension attr\n")); 2704 1.153 mrg lvextpos = (uintptr_t)implext->data + udf_rw32(implext->iu_l); 2705 1.45 reinoud 2706 1.45 reinoud lvext.unique_id_chk = vat_uniqueid; 2707 1.45 reinoud lvext.num_files = lvinfo->num_files; 2708 1.45 reinoud lvext.num_directories = lvinfo->num_directories; 2709 1.45 reinoud memmove(lvext.logvol_id, ump->logical_vol->logvol_id, 128); 2710 1.45 reinoud 2711 1.153 mrg memcpy((void *)lvextpos, &lvext, sizeof(lvext)); 2712 1.45 reinoud 2713 1.45 reinoud return 0; 2714 1.45 reinoud } 2715 1.45 reinoud 2716 1.45 reinoud /* --------------------------------------------------------------------- */ 2717 1.45 reinoud 2718 1.45 reinoud int 2719 1.45 reinoud udf_vat_read(struct udf_node *vat_node, uint8_t *blob, int size, uint32_t offset) 2720 1.45 reinoud { 2721 1.45 reinoud struct udf_mount *ump = vat_node->ump; 2722 1.45 reinoud 2723 1.45 reinoud if (offset + size > ump->vat_offset + ump->vat_entries * 4) 2724 1.45 reinoud return EINVAL; 2725 1.45 reinoud 2726 1.45 reinoud memcpy(blob, ump->vat_table + offset, size); 2727 1.45 reinoud return 0; 2728 1.45 reinoud } 2729 1.45 reinoud 2730 1.45 reinoud int 2731 1.45 reinoud udf_vat_write(struct udf_node *vat_node, uint8_t *blob, int size, uint32_t offset) 2732 1.45 reinoud { 2733 1.45 reinoud struct udf_mount *ump = vat_node->ump; 2734 1.45 reinoud uint32_t offset_high; 2735 1.45 reinoud uint8_t *new_vat_table; 2736 1.45 reinoud 2737 1.45 reinoud /* extent VAT allocation if needed */ 2738 1.45 reinoud offset_high = offset + size; 2739 1.45 reinoud if (offset_high >= ump->vat_table_alloc_len) { 2740 1.45 reinoud /* realloc */ 2741 1.45 reinoud new_vat_table = realloc(ump->vat_table, 2742 1.45 reinoud ump->vat_table_alloc_len + UDF_VAT_CHUNKSIZE, 2743 1.144 jdolecek M_UDFVOLD, M_WAITOK); 2744 1.45 reinoud if (!new_vat_table) { 2745 1.45 reinoud printf("udf_vat_write: can't extent VAT, out of mem\n"); 2746 1.45 reinoud return ENOMEM; 2747 1.45 reinoud } 2748 1.45 reinoud ump->vat_table = new_vat_table; 2749 1.45 reinoud ump->vat_table_alloc_len += UDF_VAT_CHUNKSIZE; 2750 1.45 reinoud } 2751 1.45 reinoud ump->vat_table_len = MAX(ump->vat_table_len, offset_high); 2752 1.45 reinoud 2753 1.45 reinoud memcpy(ump->vat_table + offset, blob, size); 2754 1.45 reinoud return 0; 2755 1.45 reinoud } 2756 1.45 reinoud 2757 1.45 reinoud /* --------------------------------------------------------------------- */ 2758 1.45 reinoud 2759 1.45 reinoud /* TODO support previous VAT location writeout */ 2760 1.45 reinoud static int 2761 1.45 reinoud udf_update_vat_descriptor(struct udf_mount *ump) 2762 1.45 reinoud { 2763 1.45 reinoud struct udf_node *vat_node = ump->vat_node; 2764 1.45 reinoud struct udf_logvol_info *lvinfo = ump->logvol_info; 2765 1.45 reinoud struct icb_tag *icbtag; 2766 1.45 reinoud struct udf_oldvat_tail *oldvat_tl; 2767 1.45 reinoud struct udf_vat *vat; 2768 1.161 reinoud struct regid *regid; 2769 1.45 reinoud uint64_t unique_id; 2770 1.45 reinoud uint32_t lb_size; 2771 1.45 reinoud uint8_t *raw_vat; 2772 1.161 reinoud int vat_length, impl_use_len, filetype, error; 2773 1.45 reinoud 2774 1.45 reinoud KASSERT(vat_node); 2775 1.45 reinoud KASSERT(lvinfo); 2776 1.45 reinoud lb_size = udf_rw32(ump->logical_vol->lb_size); 2777 1.45 reinoud 2778 1.45 reinoud /* get our new unique_id */ 2779 1.45 reinoud unique_id = udf_advance_uniqueid(ump); 2780 1.45 reinoud 2781 1.45 reinoud /* get information from fe/efe */ 2782 1.45 reinoud if (vat_node->fe) { 2783 1.45 reinoud icbtag = &vat_node->fe->icbtag; 2784 1.45 reinoud vat_node->fe->unique_id = udf_rw64(unique_id); 2785 1.45 reinoud } else { 2786 1.45 reinoud icbtag = &vat_node->efe->icbtag; 2787 1.45 reinoud vat_node->efe->unique_id = udf_rw64(unique_id); 2788 1.45 reinoud } 2789 1.45 reinoud 2790 1.45 reinoud /* Check icb filetype! it has to be 0 or UDF_ICB_FILETYPE_VAT */ 2791 1.45 reinoud filetype = icbtag->file_type; 2792 1.45 reinoud KASSERT((filetype == 0) || (filetype == UDF_ICB_FILETYPE_VAT)); 2793 1.45 reinoud 2794 1.45 reinoud /* allocate piece to process head or tail of VAT file */ 2795 1.45 reinoud raw_vat = malloc(lb_size, M_TEMP, M_WAITOK); 2796 1.45 reinoud 2797 1.45 reinoud if (filetype == 0) { 2798 1.45 reinoud /* 2799 1.45 reinoud * Update "*UDF VAT LVExtension" extended attribute from the 2800 1.45 reinoud * lvint if present. 2801 1.45 reinoud */ 2802 1.45 reinoud udf_update_vat_extattr_from_lvid(vat_node); 2803 1.45 reinoud 2804 1.45 reinoud /* setup identifying regid */ 2805 1.45 reinoud oldvat_tl = (struct udf_oldvat_tail *) raw_vat; 2806 1.45 reinoud memset(oldvat_tl, 0, sizeof(struct udf_oldvat_tail)); 2807 1.45 reinoud 2808 1.45 reinoud udf_set_regid(&oldvat_tl->id, "*UDF Virtual Alloc Tbl"); 2809 1.45 reinoud udf_add_udf_regid(ump, &oldvat_tl->id); 2810 1.45 reinoud oldvat_tl->prev_vat = udf_rw32(0xffffffff); 2811 1.45 reinoud 2812 1.45 reinoud /* write out new tail of virtual allocation table file */ 2813 1.45 reinoud error = udf_vat_write(vat_node, raw_vat, 2814 1.45 reinoud sizeof(struct udf_oldvat_tail), ump->vat_entries * 4); 2815 1.45 reinoud } else { 2816 1.45 reinoud /* compose the VAT2 header */ 2817 1.161 reinoud vat_length = sizeof(struct udf_vat); 2818 1.45 reinoud vat = (struct udf_vat *) raw_vat; 2819 1.45 reinoud 2820 1.161 reinoud error = udf_vat_read(vat_node, raw_vat, vat_length, 0); 2821 1.161 reinoud if (error) 2822 1.161 reinoud goto errout; 2823 1.161 reinoud 2824 1.161 reinoud impl_use_len = udf_rw16(vat->impl_use_len); 2825 1.161 reinoud vat_length += impl_use_len; 2826 1.161 reinoud 2827 1.161 reinoud error = udf_vat_read(vat_node, raw_vat, vat_length, 0); 2828 1.161 reinoud if (error) 2829 1.161 reinoud goto errout; 2830 1.161 reinoud 2831 1.45 reinoud memmove(vat->logvol_id, ump->logical_vol->logvol_id, 128); 2832 1.45 reinoud vat->prev_vat = udf_rw32(0xffffffff); 2833 1.45 reinoud vat->num_files = lvinfo->num_files; 2834 1.45 reinoud vat->num_directories = lvinfo->num_directories; 2835 1.45 reinoud vat->min_udf_readver = lvinfo->min_udf_readver; 2836 1.45 reinoud vat->min_udf_writever = lvinfo->min_udf_writever; 2837 1.45 reinoud vat->max_udf_writever = lvinfo->max_udf_writever; 2838 1.45 reinoud 2839 1.161 reinoud if (impl_use_len >= sizeof(struct regid)) { 2840 1.161 reinoud /* insert our implementation identification */ 2841 1.161 reinoud memset(vat->data, 0, impl_use_len); 2842 1.161 reinoud regid = (struct regid *) vat->data; 2843 1.161 reinoud udf_set_regid(regid, IMPL_NAME); 2844 1.161 reinoud udf_add_app_regid(ump, regid); 2845 1.161 reinoud } else { 2846 1.161 reinoud if (impl_use_len) 2847 1.161 reinoud memset(vat->data, 0, impl_use_len); 2848 1.161 reinoud vat->impl_use_len = 0; 2849 1.161 reinoud } 2850 1.161 reinoud error = udf_vat_write(vat_node, raw_vat, vat_length, 0); 2851 1.45 reinoud } 2852 1.161 reinoud errout: 2853 1.45 reinoud free(raw_vat, M_TEMP); 2854 1.45 reinoud 2855 1.45 reinoud return error; /* success! */ 2856 1.45 reinoud } 2857 1.45 reinoud 2858 1.45 reinoud 2859 1.45 reinoud int 2860 1.45 reinoud udf_writeout_vat(struct udf_mount *ump) 2861 1.45 reinoud { 2862 1.45 reinoud struct udf_node *vat_node = ump->vat_node; 2863 1.45 reinoud int error; 2864 1.45 reinoud 2865 1.45 reinoud KASSERT(vat_node); 2866 1.45 reinoud 2867 1.45 reinoud DPRINTF(CALL, ("udf_writeout_vat\n")); 2868 1.45 reinoud 2869 1.95 reinoud // mutex_enter(&ump->allocate_mutex); 2870 1.45 reinoud udf_update_vat_descriptor(ump); 2871 1.45 reinoud 2872 1.45 reinoud /* write out the VAT contents ; TODO intelligent writing */ 2873 1.45 reinoud error = vn_rdwr(UIO_WRITE, vat_node->vnode, 2874 1.45 reinoud ump->vat_table, ump->vat_table_len, 0, 2875 1.109 reinoud UIO_SYSSPACE, 0, FSCRED, NULL, NULL); 2876 1.45 reinoud if (error) { 2877 1.45 reinoud printf("udf_writeout_vat: failed to write out VAT contents\n"); 2878 1.45 reinoud goto out; 2879 1.45 reinoud } 2880 1.45 reinoud 2881 1.95 reinoud // mutex_exit(&ump->allocate_mutex); 2882 1.45 reinoud 2883 1.119 chs error = vflushbuf(ump->vat_node->vnode, FSYNC_WAIT); 2884 1.114 hannken if (error) 2885 1.114 hannken goto out; 2886 1.45 reinoud error = VOP_FSYNC(ump->vat_node->vnode, 2887 1.45 reinoud FSCRED, FSYNC_WAIT, 0, 0); 2888 1.45 reinoud if (error) 2889 1.45 reinoud printf("udf_writeout_vat: error writing VAT node!\n"); 2890 1.45 reinoud out: 2891 1.45 reinoud return error; 2892 1.45 reinoud } 2893 1.45 reinoud 2894 1.45 reinoud /* --------------------------------------------------------------------- */ 2895 1.45 reinoud 2896 1.45 reinoud /* 2897 1.45 reinoud * Read in relevant pieces of VAT file and check if its indeed a VAT file 2898 1.45 reinoud * descriptor. If OK, read in complete VAT file. 2899 1.45 reinoud */ 2900 1.45 reinoud 2901 1.45 reinoud static int 2902 1.45 reinoud udf_check_for_vat(struct udf_node *vat_node) 2903 1.45 reinoud { 2904 1.45 reinoud struct udf_mount *ump; 2905 1.45 reinoud struct icb_tag *icbtag; 2906 1.45 reinoud struct timestamp *mtime; 2907 1.45 reinoud struct udf_vat *vat; 2908 1.45 reinoud struct udf_oldvat_tail *oldvat_tl; 2909 1.45 reinoud struct udf_logvol_info *lvinfo; 2910 1.45 reinoud uint64_t unique_id; 2911 1.45 reinoud uint32_t vat_length; 2912 1.45 reinoud uint32_t vat_offset, vat_entries, vat_table_alloc_len; 2913 1.45 reinoud uint32_t sector_size; 2914 1.45 reinoud uint32_t *raw_vat; 2915 1.45 reinoud uint8_t *vat_table; 2916 1.45 reinoud char *regid_name; 2917 1.45 reinoud int filetype; 2918 1.45 reinoud int error; 2919 1.45 reinoud 2920 1.45 reinoud /* vat_length is really 64 bits though impossible */ 2921 1.45 reinoud 2922 1.45 reinoud DPRINTF(VOLUMES, ("Checking for VAT\n")); 2923 1.45 reinoud if (!vat_node) 2924 1.45 reinoud return ENOENT; 2925 1.45 reinoud 2926 1.45 reinoud /* get mount info */ 2927 1.45 reinoud ump = vat_node->ump; 2928 1.45 reinoud sector_size = udf_rw32(ump->logical_vol->lb_size); 2929 1.45 reinoud 2930 1.45 reinoud /* check assertions */ 2931 1.45 reinoud assert(vat_node->fe || vat_node->efe); 2932 1.45 reinoud assert(ump->logvol_integrity); 2933 1.45 reinoud 2934 1.45 reinoud /* set vnode type to regular file or we can't read from it! */ 2935 1.45 reinoud vat_node->vnode->v_type = VREG; 2936 1.45 reinoud 2937 1.45 reinoud /* get information from fe/efe */ 2938 1.45 reinoud if (vat_node->fe) { 2939 1.45 reinoud vat_length = udf_rw64(vat_node->fe->inf_len); 2940 1.45 reinoud icbtag = &vat_node->fe->icbtag; 2941 1.45 reinoud mtime = &vat_node->fe->mtime; 2942 1.45 reinoud unique_id = udf_rw64(vat_node->fe->unique_id); 2943 1.45 reinoud } else { 2944 1.45 reinoud vat_length = udf_rw64(vat_node->efe->inf_len); 2945 1.45 reinoud icbtag = &vat_node->efe->icbtag; 2946 1.45 reinoud mtime = &vat_node->efe->mtime; 2947 1.45 reinoud unique_id = udf_rw64(vat_node->efe->unique_id); 2948 1.45 reinoud } 2949 1.45 reinoud 2950 1.45 reinoud /* Check icb filetype! it has to be 0 or UDF_ICB_FILETYPE_VAT */ 2951 1.45 reinoud filetype = icbtag->file_type; 2952 1.45 reinoud if ((filetype != 0) && (filetype != UDF_ICB_FILETYPE_VAT)) 2953 1.45 reinoud return ENOENT; 2954 1.45 reinoud 2955 1.45 reinoud DPRINTF(VOLUMES, ("\tPossible VAT length %d\n", vat_length)); 2956 1.45 reinoud 2957 1.45 reinoud vat_table_alloc_len = 2958 1.45 reinoud ((vat_length + UDF_VAT_CHUNKSIZE-1) / UDF_VAT_CHUNKSIZE) 2959 1.45 reinoud * UDF_VAT_CHUNKSIZE; 2960 1.45 reinoud 2961 1.144 jdolecek vat_table = malloc(vat_table_alloc_len, M_UDFVOLD, M_WAITOK); 2962 1.45 reinoud if (vat_table == NULL) { 2963 1.45 reinoud printf("allocation of %d bytes failed for VAT\n", 2964 1.45 reinoud vat_table_alloc_len); 2965 1.45 reinoud return ENOMEM; 2966 1.45 reinoud } 2967 1.45 reinoud 2968 1.45 reinoud /* allocate piece to read in head or tail of VAT file */ 2969 1.45 reinoud raw_vat = malloc(sector_size, M_TEMP, M_WAITOK); 2970 1.45 reinoud 2971 1.45 reinoud /* 2972 1.45 reinoud * check contents of the file if its the old 1.50 VAT table format. 2973 1.45 reinoud * Its notoriously broken and allthough some implementations support an 2974 1.157 andvar * extension as defined in the UDF 1.50 errata document, its doubtful 2975 1.45 reinoud * to be useable since a lot of implementations don't maintain it. 2976 1.45 reinoud */ 2977 1.45 reinoud lvinfo = ump->logvol_info; 2978 1.45 reinoud 2979 1.45 reinoud if (filetype == 0) { 2980 1.45 reinoud /* definition */ 2981 1.45 reinoud vat_offset = 0; 2982 1.45 reinoud vat_entries = (vat_length-36)/4; 2983 1.45 reinoud 2984 1.45 reinoud /* read in tail of virtual allocation table file */ 2985 1.45 reinoud error = vn_rdwr(UIO_READ, vat_node->vnode, 2986 1.45 reinoud (uint8_t *) raw_vat, 2987 1.45 reinoud sizeof(struct udf_oldvat_tail), 2988 1.45 reinoud vat_entries * 4, 2989 1.45 reinoud UIO_SYSSPACE, IO_SYNC | IO_NODELOCKED, FSCRED, 2990 1.45 reinoud NULL, NULL); 2991 1.45 reinoud if (error) 2992 1.45 reinoud goto out; 2993 1.45 reinoud 2994 1.45 reinoud /* check 1.50 VAT */ 2995 1.45 reinoud oldvat_tl = (struct udf_oldvat_tail *) raw_vat; 2996 1.45 reinoud regid_name = (char *) oldvat_tl->id.id; 2997 1.45 reinoud error = strncmp(regid_name, "*UDF Virtual Alloc Tbl", 22); 2998 1.45 reinoud if (error) { 2999 1.45 reinoud DPRINTF(VOLUMES, ("VAT format 1.50 rejected\n")); 3000 1.45 reinoud error = ENOENT; 3001 1.45 reinoud goto out; 3002 1.45 reinoud } 3003 1.45 reinoud 3004 1.45 reinoud /* 3005 1.45 reinoud * update LVID from "*UDF VAT LVExtension" extended attribute 3006 1.45 reinoud * if present. 3007 1.45 reinoud */ 3008 1.45 reinoud udf_update_lvid_from_vat_extattr(vat_node); 3009 1.45 reinoud } else { 3010 1.45 reinoud /* read in head of virtual allocation table file */ 3011 1.45 reinoud error = vn_rdwr(UIO_READ, vat_node->vnode, 3012 1.45 reinoud (uint8_t *) raw_vat, 3013 1.45 reinoud sizeof(struct udf_vat), 0, 3014 1.45 reinoud UIO_SYSSPACE, IO_SYNC | IO_NODELOCKED, FSCRED, 3015 1.45 reinoud NULL, NULL); 3016 1.45 reinoud if (error) 3017 1.45 reinoud goto out; 3018 1.45 reinoud 3019 1.45 reinoud /* definition */ 3020 1.45 reinoud vat = (struct udf_vat *) raw_vat; 3021 1.161 reinoud vat_offset = udf_rw16(vat->header_len); 3022 1.45 reinoud vat_entries = (vat_length - vat_offset)/4; 3023 1.45 reinoud 3024 1.45 reinoud assert(lvinfo); 3025 1.45 reinoud lvinfo->num_files = vat->num_files; 3026 1.45 reinoud lvinfo->num_directories = vat->num_directories; 3027 1.45 reinoud lvinfo->min_udf_readver = vat->min_udf_readver; 3028 1.45 reinoud lvinfo->min_udf_writever = vat->min_udf_writever; 3029 1.45 reinoud lvinfo->max_udf_writever = vat->max_udf_writever; 3030 1.152 skrll 3031 1.45 reinoud udf_update_logvolname(ump, vat->logvol_id); 3032 1.45 reinoud } 3033 1.45 reinoud 3034 1.45 reinoud /* read in complete VAT file */ 3035 1.45 reinoud error = vn_rdwr(UIO_READ, vat_node->vnode, 3036 1.45 reinoud vat_table, 3037 1.45 reinoud vat_length, 0, 3038 1.45 reinoud UIO_SYSSPACE, IO_SYNC | IO_NODELOCKED, FSCRED, 3039 1.45 reinoud NULL, NULL); 3040 1.45 reinoud if (error) 3041 1.45 reinoud printf("read in of complete VAT file failed (error %d)\n", 3042 1.45 reinoud error); 3043 1.45 reinoud if (error) 3044 1.45 reinoud goto out; 3045 1.45 reinoud 3046 1.45 reinoud DPRINTF(VOLUMES, ("VAT format accepted, marking it closed\n")); 3047 1.90 reinoud ump->logvol_integrity->lvint_next_unique_id = udf_rw64(unique_id); 3048 1.45 reinoud ump->logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_CLOSED); 3049 1.45 reinoud ump->logvol_integrity->time = *mtime; 3050 1.45 reinoud 3051 1.137 reinoud /* if we're updating, free old allocated space */ 3052 1.137 reinoud if (ump->vat_table) 3053 1.137 reinoud free(ump->vat_table, M_UDFVOLD); 3054 1.137 reinoud 3055 1.45 reinoud ump->vat_table_len = vat_length; 3056 1.45 reinoud ump->vat_table_alloc_len = vat_table_alloc_len; 3057 1.45 reinoud ump->vat_table = vat_table; 3058 1.45 reinoud ump->vat_offset = vat_offset; 3059 1.45 reinoud ump->vat_entries = vat_entries; 3060 1.45 reinoud ump->vat_last_free_lb = 0; /* start at beginning */ 3061 1.45 reinoud 3062 1.45 reinoud out: 3063 1.45 reinoud if (error) { 3064 1.45 reinoud if (vat_table) 3065 1.45 reinoud free(vat_table, M_UDFVOLD); 3066 1.45 reinoud } 3067 1.45 reinoud free(raw_vat, M_TEMP); 3068 1.45 reinoud 3069 1.45 reinoud return error; 3070 1.45 reinoud } 3071 1.45 reinoud 3072 1.45 reinoud /* --------------------------------------------------------------------- */ 3073 1.45 reinoud 3074 1.45 reinoud static int 3075 1.45 reinoud udf_search_vat(struct udf_mount *ump, union udf_pmap *mapping) 3076 1.45 reinoud { 3077 1.137 reinoud struct udf_node *vat_node, *accepted_vat_node; 3078 1.45 reinoud struct long_ad icb_loc; 3079 1.137 reinoud uint32_t early_vat_loc, late_vat_loc, vat_loc; 3080 1.45 reinoud int error; 3081 1.45 reinoud 3082 1.45 reinoud /* mapping info not needed */ 3083 1.45 reinoud mapping = mapping; 3084 1.45 reinoud 3085 1.137 reinoud DPRINTF(VOLUMES, ("Searching VAT\n")); 3086 1.152 skrll 3087 1.137 reinoud /* 3088 1.137 reinoud * Start reading forward in blocks from the first possible vat 3089 1.137 reinoud * location. If not found in this block, start again a bit before 3090 1.137 reinoud * until we get a hit. 3091 1.137 reinoud */ 3092 1.137 reinoud late_vat_loc = ump->last_possible_vat_location; 3093 1.137 reinoud early_vat_loc = MAX(late_vat_loc - 64, ump->first_possible_vat_location); 3094 1.152 skrll 3095 1.137 reinoud DPRINTF(VOLUMES, ("\tfull range %d to %d\n", early_vat_loc, late_vat_loc)); 3096 1.137 reinoud accepted_vat_node = NULL; 3097 1.137 reinoud do { 3098 1.137 reinoud vat_loc = early_vat_loc; 3099 1.137 reinoud DPRINTF(VOLUMES, ("\tchecking range %d to %d\n", 3100 1.137 reinoud early_vat_loc, late_vat_loc)); 3101 1.137 reinoud do { 3102 1.137 reinoud DPRINTF(VOLUMES, ("\t\tChecking for VAT at sector %d\n", 3103 1.137 reinoud vat_loc)); 3104 1.137 reinoud icb_loc.loc.part_num = udf_rw16(UDF_VTOP_RAWPART); 3105 1.137 reinoud icb_loc.loc.lb_num = udf_rw32(vat_loc); 3106 1.45 reinoud 3107 1.148 ad error = udf_get_node(ump, &icb_loc, &vat_node, 3108 1.148 ad LK_EXCLUSIVE); 3109 1.137 reinoud if (!error) { 3110 1.137 reinoud error = udf_check_for_vat(vat_node); 3111 1.137 reinoud vat_node->i_flags = 0; /* reset access */ 3112 1.137 reinoud } 3113 1.137 reinoud if (!error) { 3114 1.137 reinoud DPRINTFIF(VOLUMES, !error, 3115 1.137 reinoud ("VAT candidate accepted at %d\n", 3116 1.137 reinoud vat_loc)); 3117 1.137 reinoud if (accepted_vat_node) 3118 1.137 reinoud vput(accepted_vat_node->vnode); 3119 1.137 reinoud accepted_vat_node = vat_node; 3120 1.137 reinoud accepted_vat_node->i_flags |= IN_NO_DELETE; 3121 1.137 reinoud vat_node = NULL; 3122 1.137 reinoud } 3123 1.137 reinoud if (vat_node) 3124 1.137 reinoud vput(vat_node->vnode); 3125 1.137 reinoud vat_loc++; /* walk forward */ 3126 1.160 reinoud } while (vat_loc <= late_vat_loc); 3127 1.137 reinoud if (accepted_vat_node) 3128 1.137 reinoud break; 3129 1.137 reinoud 3130 1.137 reinoud early_vat_loc = MAX(early_vat_loc - 64, ump->first_possible_vat_location); 3131 1.137 reinoud late_vat_loc = MIN(early_vat_loc + 64, ump->last_possible_vat_location); 3132 1.137 reinoud } while (late_vat_loc > ump->first_possible_vat_location); 3133 1.137 reinoud 3134 1.137 reinoud /* keep our last accepted VAT node around */ 3135 1.137 reinoud if (accepted_vat_node) { 3136 1.137 reinoud /* revert no delete flag again to avoid potential side effects */ 3137 1.137 reinoud accepted_vat_node->i_flags &= ~IN_NO_DELETE; 3138 1.45 reinoud 3139 1.137 reinoud UDF_SET_SYSTEMFILE(accepted_vat_node->vnode); 3140 1.137 reinoud ump->vat_node = accepted_vat_node; 3141 1.137 reinoud return 0; 3142 1.45 reinoud } 3143 1.45 reinoud 3144 1.45 reinoud return error; 3145 1.45 reinoud } 3146 1.45 reinoud 3147 1.45 reinoud /* --------------------------------------------------------------------- */ 3148 1.45 reinoud 3149 1.45 reinoud static int 3150 1.45 reinoud udf_read_sparables(struct udf_mount *ump, union udf_pmap *mapping) 3151 1.45 reinoud { 3152 1.45 reinoud union dscrptr *dscr; 3153 1.45 reinoud struct part_map_spare *pms = &mapping->pms; 3154 1.45 reinoud uint32_t lb_num; 3155 1.45 reinoud int spar, error; 3156 1.45 reinoud 3157 1.45 reinoud /* 3158 1.45 reinoud * The partition mapping passed on to us specifies the information we 3159 1.45 reinoud * need to locate and initialise the sparable partition mapping 3160 1.45 reinoud * information we need. 3161 1.45 reinoud */ 3162 1.45 reinoud 3163 1.45 reinoud DPRINTF(VOLUMES, ("Read sparable table\n")); 3164 1.45 reinoud ump->sparable_packet_size = udf_rw16(pms->packet_len); 3165 1.45 reinoud KASSERT(ump->sparable_packet_size >= ump->packet_size); /* XXX */ 3166 1.45 reinoud 3167 1.45 reinoud for (spar = 0; spar < pms->n_st; spar++) { 3168 1.45 reinoud lb_num = pms->st_loc[spar]; 3169 1.45 reinoud DPRINTF(VOLUMES, ("Checking for sparing table %d\n", lb_num)); 3170 1.45 reinoud error = udf_read_phys_dscr(ump, lb_num, M_UDFVOLD, &dscr); 3171 1.45 reinoud if (!error && dscr) { 3172 1.45 reinoud if (udf_rw16(dscr->tag.id) == TAGID_SPARING_TABLE) { 3173 1.45 reinoud if (ump->sparing_table) 3174 1.45 reinoud free(ump->sparing_table, M_UDFVOLD); 3175 1.45 reinoud ump->sparing_table = &dscr->spt; 3176 1.45 reinoud dscr = NULL; 3177 1.45 reinoud DPRINTF(VOLUMES, 3178 1.45 reinoud ("Sparing table accepted (%d entries)\n", 3179 1.45 reinoud udf_rw16(ump->sparing_table->rt_l))); 3180 1.45 reinoud break; /* we're done */ 3181 1.45 reinoud } 3182 1.45 reinoud } 3183 1.45 reinoud if (dscr) 3184 1.45 reinoud free(dscr, M_UDFVOLD); 3185 1.45 reinoud } 3186 1.45 reinoud 3187 1.45 reinoud if (ump->sparing_table) 3188 1.45 reinoud return 0; 3189 1.45 reinoud 3190 1.45 reinoud return ENOENT; 3191 1.45 reinoud } 3192 1.45 reinoud 3193 1.45 reinoud /* --------------------------------------------------------------------- */ 3194 1.45 reinoud 3195 1.45 reinoud static int 3196 1.45 reinoud udf_read_metadata_nodes(struct udf_mount *ump, union udf_pmap *mapping) 3197 1.45 reinoud { 3198 1.45 reinoud struct part_map_meta *pmm = &mapping->pmm; 3199 1.45 reinoud struct long_ad icb_loc; 3200 1.45 reinoud struct vnode *vp; 3201 1.111 reinoud uint16_t raw_phys_part, phys_part; 3202 1.45 reinoud int error; 3203 1.45 reinoud 3204 1.111 reinoud /* 3205 1.111 reinoud * BUGALERT: some rogue implementations use random physical 3206 1.111 reinoud * partition numbers to break other implementations so lookup 3207 1.111 reinoud * the number. 3208 1.111 reinoud */ 3209 1.111 reinoud 3210 1.102 reinoud /* extract our allocation parameters set up on format */ 3211 1.103 reinoud ump->metadata_alloc_unit_size = udf_rw32(mapping->pmm.alloc_unit_size); 3212 1.103 reinoud ump->metadata_alignment_unit_size = udf_rw16(mapping->pmm.alignment_unit_size); 3213 1.103 reinoud ump->metadata_flags = mapping->pmm.flags; 3214 1.102 reinoud 3215 1.45 reinoud DPRINTF(VOLUMES, ("Reading in Metadata files\n")); 3216 1.111 reinoud raw_phys_part = udf_rw16(pmm->part_num); 3217 1.111 reinoud phys_part = udf_find_raw_phys(ump, raw_phys_part); 3218 1.111 reinoud 3219 1.111 reinoud icb_loc.loc.part_num = udf_rw16(phys_part); 3220 1.111 reinoud 3221 1.111 reinoud DPRINTF(VOLUMES, ("Metadata file\n")); 3222 1.45 reinoud icb_loc.loc.lb_num = pmm->meta_file_lbn; 3223 1.148 ad error = udf_get_node(ump, &icb_loc, &ump->metadata_node, 3224 1.148 ad LK_EXCLUSIVE); 3225 1.45 reinoud if (ump->metadata_node) { 3226 1.45 reinoud vp = ump->metadata_node->vnode; 3227 1.45 reinoud UDF_SET_SYSTEMFILE(vp); 3228 1.45 reinoud } 3229 1.45 reinoud 3230 1.45 reinoud icb_loc.loc.lb_num = pmm->meta_mirror_file_lbn; 3231 1.45 reinoud if (icb_loc.loc.lb_num != -1) { 3232 1.45 reinoud DPRINTF(VOLUMES, ("Metadata copy file\n")); 3233 1.148 ad error = udf_get_node(ump, &icb_loc, &ump->metadatamirror_node, 3234 1.148 ad LK_EXCLUSIVE); 3235 1.45 reinoud if (ump->metadatamirror_node) { 3236 1.45 reinoud vp = ump->metadatamirror_node->vnode; 3237 1.45 reinoud UDF_SET_SYSTEMFILE(vp); 3238 1.45 reinoud } 3239 1.45 reinoud } 3240 1.45 reinoud 3241 1.45 reinoud icb_loc.loc.lb_num = pmm->meta_bitmap_file_lbn; 3242 1.45 reinoud if (icb_loc.loc.lb_num != -1) { 3243 1.45 reinoud DPRINTF(VOLUMES, ("Metadata bitmap file\n")); 3244 1.148 ad error = udf_get_node(ump, &icb_loc, &ump->metadatabitmap_node, 3245 1.148 ad LK_EXCLUSIVE); 3246 1.45 reinoud if (ump->metadatabitmap_node) { 3247 1.45 reinoud vp = ump->metadatabitmap_node->vnode; 3248 1.45 reinoud UDF_SET_SYSTEMFILE(vp); 3249 1.45 reinoud } 3250 1.45 reinoud } 3251 1.45 reinoud 3252 1.45 reinoud /* if we're mounting read-only we relax the requirements */ 3253 1.45 reinoud if (ump->vfs_mountp->mnt_flag & MNT_RDONLY) { 3254 1.45 reinoud error = EFAULT; 3255 1.45 reinoud if (ump->metadata_node) 3256 1.45 reinoud error = 0; 3257 1.45 reinoud if ((ump->metadata_node == NULL) && (ump->metadatamirror_node)) { 3258 1.45 reinoud printf( "udf mount: Metadata file not readable, " 3259 1.45 reinoud "substituting Metadata copy file\n"); 3260 1.45 reinoud ump->metadata_node = ump->metadatamirror_node; 3261 1.45 reinoud ump->metadatamirror_node = NULL; 3262 1.45 reinoud error = 0; 3263 1.45 reinoud } 3264 1.45 reinoud } else { 3265 1.45 reinoud /* mounting read/write */ 3266 1.70 reinoud /* XXX DISABLED! metadata writing is not working yet XXX */ 3267 1.71 reinoud if (error) 3268 1.53 reinoud error = EROFS; 3269 1.45 reinoud } 3270 1.45 reinoud DPRINTFIF(VOLUMES, error, ("udf mount: failed to read " 3271 1.45 reinoud "metadata files\n")); 3272 1.45 reinoud return error; 3273 1.45 reinoud } 3274 1.45 reinoud 3275 1.45 reinoud /* --------------------------------------------------------------------- */ 3276 1.45 reinoud 3277 1.45 reinoud int 3278 1.45 reinoud udf_read_vds_tables(struct udf_mount *ump) 3279 1.45 reinoud { 3280 1.45 reinoud union udf_pmap *mapping; 3281 1.45 reinoud /* struct udf_args *args = &ump->mount_args; */ 3282 1.121 christos uint32_t n_pm; 3283 1.45 reinoud uint32_t log_part; 3284 1.45 reinoud uint8_t *pmap_pos; 3285 1.45 reinoud int pmap_size; 3286 1.45 reinoud int error; 3287 1.45 reinoud 3288 1.69 reinoud /* Iterate (again) over the part mappings for locations */ 3289 1.45 reinoud n_pm = udf_rw32(ump->logical_vol->n_pm); /* num partmaps */ 3290 1.45 reinoud pmap_pos = ump->logical_vol->maps; 3291 1.45 reinoud 3292 1.45 reinoud for (log_part = 0; log_part < n_pm; log_part++) { 3293 1.45 reinoud mapping = (union udf_pmap *) pmap_pos; 3294 1.45 reinoud switch (ump->vtop_tp[log_part]) { 3295 1.45 reinoud case UDF_VTOP_TYPE_PHYS : 3296 1.45 reinoud /* nothing */ 3297 1.45 reinoud break; 3298 1.45 reinoud case UDF_VTOP_TYPE_VIRT : 3299 1.45 reinoud /* search and load VAT */ 3300 1.45 reinoud error = udf_search_vat(ump, mapping); 3301 1.45 reinoud if (error) 3302 1.45 reinoud return ENOENT; 3303 1.45 reinoud break; 3304 1.45 reinoud case UDF_VTOP_TYPE_SPARABLE : 3305 1.45 reinoud /* load one of the sparable tables */ 3306 1.45 reinoud error = udf_read_sparables(ump, mapping); 3307 1.45 reinoud if (error) 3308 1.45 reinoud return ENOENT; 3309 1.45 reinoud break; 3310 1.45 reinoud case UDF_VTOP_TYPE_META : 3311 1.45 reinoud /* load the associated file descriptors */ 3312 1.45 reinoud error = udf_read_metadata_nodes(ump, mapping); 3313 1.45 reinoud if (error) 3314 1.45 reinoud return ENOENT; 3315 1.45 reinoud break; 3316 1.45 reinoud default: 3317 1.45 reinoud break; 3318 1.45 reinoud } 3319 1.45 reinoud pmap_size = pmap_pos[1]; 3320 1.45 reinoud pmap_pos += pmap_size; 3321 1.45 reinoud } 3322 1.45 reinoud 3323 1.70 reinoud /* read in and check unallocated and free space info if writing */ 3324 1.70 reinoud if ((ump->vfs_mountp->mnt_flag & MNT_RDONLY) == 0) { 3325 1.70 reinoud error = udf_read_physical_partition_spacetables(ump); 3326 1.70 reinoud if (error) 3327 1.70 reinoud return error; 3328 1.70 reinoud 3329 1.100 mbalmer /* also read in metadata partition spacebitmap if defined */ 3330 1.70 reinoud error = udf_read_metadata_partition_spacetable(ump); 3331 1.70 reinoud return error; 3332 1.70 reinoud } 3333 1.70 reinoud 3334 1.45 reinoud return 0; 3335 1.45 reinoud } 3336 1.45 reinoud 3337 1.45 reinoud /* --------------------------------------------------------------------- */ 3338 1.45 reinoud 3339 1.45 reinoud int 3340 1.45 reinoud udf_read_rootdirs(struct udf_mount *ump) 3341 1.45 reinoud { 3342 1.45 reinoud union dscrptr *dscr; 3343 1.45 reinoud /* struct udf_args *args = &ump->mount_args; */ 3344 1.45 reinoud struct udf_node *rootdir_node, *streamdir_node; 3345 1.45 reinoud struct long_ad fsd_loc, *dir_loc; 3346 1.45 reinoud uint32_t lb_num, dummy; 3347 1.45 reinoud uint32_t fsd_len; 3348 1.45 reinoud int dscr_type; 3349 1.45 reinoud int error; 3350 1.45 reinoud 3351 1.45 reinoud /* TODO implement FSD reading in separate function like integrity? */ 3352 1.45 reinoud /* get fileset descriptor sequence */ 3353 1.45 reinoud fsd_loc = ump->logical_vol->lv_fsd_loc; 3354 1.45 reinoud fsd_len = udf_rw32(fsd_loc.len); 3355 1.45 reinoud 3356 1.45 reinoud dscr = NULL; 3357 1.45 reinoud error = 0; 3358 1.45 reinoud while (fsd_len || error) { 3359 1.45 reinoud DPRINTF(VOLUMES, ("fsd_len = %d\n", fsd_len)); 3360 1.45 reinoud /* translate fsd_loc to lb_num */ 3361 1.45 reinoud error = udf_translate_vtop(ump, &fsd_loc, &lb_num, &dummy); 3362 1.45 reinoud if (error) 3363 1.45 reinoud break; 3364 1.45 reinoud DPRINTF(VOLUMES, ("Reading FSD at lb %d\n", lb_num)); 3365 1.45 reinoud error = udf_read_phys_dscr(ump, lb_num, M_UDFVOLD, &dscr); 3366 1.45 reinoud /* end markers */ 3367 1.45 reinoud if (error || (dscr == NULL)) 3368 1.45 reinoud break; 3369 1.45 reinoud 3370 1.45 reinoud /* analyse */ 3371 1.45 reinoud dscr_type = udf_rw16(dscr->tag.id); 3372 1.45 reinoud if (dscr_type == TAGID_TERM) 3373 1.45 reinoud break; 3374 1.45 reinoud if (dscr_type != TAGID_FSD) { 3375 1.45 reinoud free(dscr, M_UDFVOLD); 3376 1.45 reinoud return ENOENT; 3377 1.45 reinoud } 3378 1.45 reinoud 3379 1.45 reinoud /* 3380 1.45 reinoud * TODO check for multiple fileset descriptors; its only 3381 1.45 reinoud * picking the last now. Also check for FSD 3382 1.45 reinoud * correctness/interpretability 3383 1.45 reinoud */ 3384 1.45 reinoud 3385 1.45 reinoud /* update */ 3386 1.45 reinoud if (ump->fileset_desc) { 3387 1.45 reinoud free(ump->fileset_desc, M_UDFVOLD); 3388 1.45 reinoud } 3389 1.45 reinoud ump->fileset_desc = &dscr->fsd; 3390 1.45 reinoud dscr = NULL; 3391 1.45 reinoud 3392 1.45 reinoud /* continue to the next fsd */ 3393 1.45 reinoud fsd_len -= ump->discinfo.sector_size; 3394 1.45 reinoud fsd_loc.loc.lb_num = udf_rw32(udf_rw32(fsd_loc.loc.lb_num)+1); 3395 1.45 reinoud 3396 1.45 reinoud /* follow up to fsd->next_ex (long_ad) if its not null */ 3397 1.45 reinoud if (udf_rw32(ump->fileset_desc->next_ex.len)) { 3398 1.45 reinoud DPRINTF(VOLUMES, ("follow up FSD extent\n")); 3399 1.45 reinoud fsd_loc = ump->fileset_desc->next_ex; 3400 1.45 reinoud fsd_len = udf_rw32(ump->fileset_desc->next_ex.len); 3401 1.45 reinoud } 3402 1.45 reinoud } 3403 1.45 reinoud if (dscr) 3404 1.45 reinoud free(dscr, M_UDFVOLD); 3405 1.45 reinoud 3406 1.45 reinoud /* there has to be one */ 3407 1.45 reinoud if (ump->fileset_desc == NULL) 3408 1.45 reinoud return ENOENT; 3409 1.45 reinoud 3410 1.45 reinoud DPRINTF(VOLUMES, ("FSD read in fine\n")); 3411 1.45 reinoud DPRINTF(VOLUMES, ("Updating fsd logical volume id\n")); 3412 1.45 reinoud udf_update_logvolname(ump, ump->logical_vol->logvol_id); 3413 1.45 reinoud 3414 1.45 reinoud /* 3415 1.45 reinoud * Now the FSD is known, read in the rootdirectory and if one exists, 3416 1.45 reinoud * the system stream dir. Some files in the system streamdir are not 3417 1.45 reinoud * wanted in this implementation since they are not maintained. If 3418 1.45 reinoud * writing is enabled we'll delete these files if they exist. 3419 1.45 reinoud */ 3420 1.45 reinoud 3421 1.45 reinoud rootdir_node = streamdir_node = NULL; 3422 1.45 reinoud dir_loc = NULL; 3423 1.45 reinoud 3424 1.45 reinoud /* try to read in the rootdir */ 3425 1.45 reinoud dir_loc = &ump->fileset_desc->rootdir_icb; 3426 1.148 ad error = udf_get_node(ump, dir_loc, &rootdir_node, LK_EXCLUSIVE); 3427 1.45 reinoud if (error) 3428 1.45 reinoud return ENOENT; 3429 1.45 reinoud 3430 1.166 andvar /* apparently it reads in fine */ 3431 1.45 reinoud 3432 1.45 reinoud /* 3433 1.45 reinoud * Try the system stream directory; not very likely in the ones we 3434 1.45 reinoud * test, but for completeness. 3435 1.45 reinoud */ 3436 1.45 reinoud dir_loc = &ump->fileset_desc->streamdir_icb; 3437 1.45 reinoud if (udf_rw32(dir_loc->len)) { 3438 1.45 reinoud printf("udf_read_rootdirs: streamdir defined "); 3439 1.148 ad error = udf_get_node(ump, dir_loc, &streamdir_node, 3440 1.148 ad LK_EXCLUSIVE); 3441 1.45 reinoud if (error) { 3442 1.45 reinoud printf("but error in streamdir reading\n"); 3443 1.1 reinoud } else { 3444 1.45 reinoud printf("but ignored\n"); 3445 1.45 reinoud /* 3446 1.45 reinoud * TODO process streamdir `baddies' i.e. files we dont 3447 1.45 reinoud * want if R/W 3448 1.45 reinoud */ 3449 1.45 reinoud } 3450 1.45 reinoud } 3451 1.45 reinoud 3452 1.45 reinoud DPRINTF(VOLUMES, ("Rootdir(s) read in fine\n")); 3453 1.45 reinoud 3454 1.45 reinoud /* release the vnodes again; they'll be auto-recycled later */ 3455 1.45 reinoud if (streamdir_node) { 3456 1.45 reinoud vput(streamdir_node->vnode); 3457 1.45 reinoud } 3458 1.45 reinoud if (rootdir_node) { 3459 1.45 reinoud vput(rootdir_node->vnode); 3460 1.45 reinoud } 3461 1.45 reinoud 3462 1.45 reinoud return 0; 3463 1.45 reinoud } 3464 1.45 reinoud 3465 1.45 reinoud /* --------------------------------------------------------------------- */ 3466 1.45 reinoud 3467 1.45 reinoud /* To make absolutely sure we are NOT returning zero, add one :) */ 3468 1.45 reinoud 3469 1.45 reinoud long 3470 1.98 reinoud udf_get_node_id(const struct long_ad *icbptr) 3471 1.45 reinoud { 3472 1.45 reinoud /* ought to be enough since each mountpoint has its own chain */ 3473 1.45 reinoud return udf_rw32(icbptr->loc.lb_num) + 1; 3474 1.45 reinoud } 3475 1.45 reinoud 3476 1.45 reinoud 3477 1.96 reinoud int 3478 1.98 reinoud udf_compare_icb(const struct long_ad *a, const struct long_ad *b) 3479 1.96 reinoud { 3480 1.98 reinoud if (udf_rw16(a->loc.part_num) < udf_rw16(b->loc.part_num)) 3481 1.98 reinoud return -1; 3482 1.98 reinoud if (udf_rw16(a->loc.part_num) > udf_rw16(b->loc.part_num)) 3483 1.98 reinoud return 1; 3484 1.98 reinoud 3485 1.98 reinoud if (udf_rw32(a->loc.lb_num) < udf_rw32(b->loc.lb_num)) 3486 1.98 reinoud return -1; 3487 1.98 reinoud if (udf_rw32(a->loc.lb_num) > udf_rw32(b->loc.lb_num)) 3488 1.98 reinoud return 1; 3489 1.98 reinoud 3490 1.98 reinoud return 0; 3491 1.96 reinoud } 3492 1.96 reinoud 3493 1.96 reinoud 3494 1.98 reinoud static int 3495 1.108 rmind udf_compare_rbnodes(void *ctx, const void *a, const void *b) 3496 1.45 reinoud { 3497 1.108 rmind const struct udf_node *a_node = a; 3498 1.108 rmind const struct udf_node *b_node = b; 3499 1.98 reinoud 3500 1.98 reinoud return udf_compare_icb(&a_node->loc, &b_node->loc); 3501 1.98 reinoud } 3502 1.45 reinoud 3503 1.45 reinoud 3504 1.98 reinoud static int 3505 1.108 rmind udf_compare_rbnode_icb(void *ctx, const void *a, const void *key) 3506 1.98 reinoud { 3507 1.108 rmind const struct udf_node *a_node = a; 3508 1.98 reinoud const struct long_ad * const icb = key; 3509 1.45 reinoud 3510 1.98 reinoud return udf_compare_icb(&a_node->loc, icb); 3511 1.45 reinoud } 3512 1.45 reinoud 3513 1.45 reinoud 3514 1.108 rmind static const rb_tree_ops_t udf_node_rbtree_ops = { 3515 1.98 reinoud .rbto_compare_nodes = udf_compare_rbnodes, 3516 1.108 rmind .rbto_compare_key = udf_compare_rbnode_icb, 3517 1.108 rmind .rbto_node_offset = offsetof(struct udf_node, rbnode), 3518 1.108 rmind .rbto_context = NULL 3519 1.98 reinoud }; 3520 1.98 reinoud 3521 1.98 reinoud 3522 1.98 reinoud void 3523 1.98 reinoud udf_init_nodes_tree(struct udf_mount *ump) 3524 1.45 reinoud { 3525 1.108 rmind 3526 1.98 reinoud rb_tree_init(&ump->udf_node_tree, &udf_node_rbtree_ops); 3527 1.98 reinoud } 3528 1.45 reinoud 3529 1.45 reinoud 3530 1.45 reinoud /* --------------------------------------------------------------------- */ 3531 1.45 reinoud 3532 1.85 reinoud static int 3533 1.85 reinoud udf_validate_session_start(struct udf_mount *ump) 3534 1.85 reinoud { 3535 1.85 reinoud struct mmc_trackinfo trackinfo; 3536 1.85 reinoud struct vrs_desc *vrs; 3537 1.85 reinoud uint32_t tracknr, sessionnr, sector, sector_size; 3538 1.85 reinoud uint32_t iso9660_vrs, write_track_start; 3539 1.85 reinoud uint8_t *buffer, *blank, *pos; 3540 1.85 reinoud int blks, max_sectors, vrs_len; 3541 1.85 reinoud int error; 3542 1.85 reinoud 3543 1.85 reinoud /* disc appendable? */ 3544 1.85 reinoud if (ump->discinfo.disc_state == MMC_STATE_FULL) 3545 1.85 reinoud return EROFS; 3546 1.85 reinoud 3547 1.85 reinoud /* already written here? if so, there should be an ISO VDS */ 3548 1.85 reinoud if (ump->discinfo.last_session_state == MMC_STATE_INCOMPLETE) 3549 1.85 reinoud return 0; 3550 1.85 reinoud 3551 1.85 reinoud /* 3552 1.85 reinoud * Check if the first track of the session is blank and if so, copy or 3553 1.85 reinoud * create a dummy ISO descriptor so the disc is valid again. 3554 1.85 reinoud */ 3555 1.85 reinoud 3556 1.85 reinoud tracknr = ump->discinfo.first_track_last_session; 3557 1.85 reinoud memset(&trackinfo, 0, sizeof(struct mmc_trackinfo)); 3558 1.85 reinoud trackinfo.tracknr = tracknr; 3559 1.85 reinoud error = udf_update_trackinfo(ump, &trackinfo); 3560 1.85 reinoud if (error) 3561 1.85 reinoud return error; 3562 1.85 reinoud 3563 1.85 reinoud udf_dump_trackinfo(&trackinfo); 3564 1.85 reinoud KASSERT(trackinfo.flags & (MMC_TRACKINFO_BLANK | MMC_TRACKINFO_RESERVED)); 3565 1.85 reinoud KASSERT(trackinfo.sessionnr > 1); 3566 1.85 reinoud 3567 1.85 reinoud KASSERT(trackinfo.flags & MMC_TRACKINFO_NWA_VALID); 3568 1.85 reinoud write_track_start = trackinfo.next_writable; 3569 1.85 reinoud 3570 1.85 reinoud /* we have to copy the ISO VRS from a former session */ 3571 1.85 reinoud DPRINTF(VOLUMES, ("validate_session_start: " 3572 1.85 reinoud "blank or reserved track, copying VRS\n")); 3573 1.85 reinoud 3574 1.85 reinoud /* sessionnr should be the session we're mounting */ 3575 1.85 reinoud sessionnr = ump->mount_args.sessionnr; 3576 1.85 reinoud 3577 1.85 reinoud /* start at the first track */ 3578 1.85 reinoud tracknr = ump->discinfo.first_track; 3579 1.85 reinoud while (tracknr <= ump->discinfo.num_tracks) { 3580 1.85 reinoud trackinfo.tracknr = tracknr; 3581 1.85 reinoud error = udf_update_trackinfo(ump, &trackinfo); 3582 1.85 reinoud if (error) { 3583 1.85 reinoud DPRINTF(VOLUMES, ("failed to get trackinfo; aborting\n")); 3584 1.85 reinoud return error; 3585 1.85 reinoud } 3586 1.85 reinoud if (trackinfo.sessionnr == sessionnr) 3587 1.85 reinoud break; 3588 1.85 reinoud tracknr++; 3589 1.85 reinoud } 3590 1.85 reinoud if (trackinfo.sessionnr != sessionnr) { 3591 1.85 reinoud DPRINTF(VOLUMES, ("failed to get trackinfo; aborting\n")); 3592 1.85 reinoud return ENOENT; 3593 1.85 reinoud } 3594 1.85 reinoud 3595 1.85 reinoud DPRINTF(VOLUMES, ("found possible former ISO VRS at\n")); 3596 1.85 reinoud udf_dump_trackinfo(&trackinfo); 3597 1.85 reinoud 3598 1.85 reinoud /* 3599 1.85 reinoud * location of iso9660 vrs is defined as first sector AFTER 32kb, 3600 1.85 reinoud * minimum ISO `sector size' 2048 3601 1.85 reinoud */ 3602 1.85 reinoud sector_size = ump->discinfo.sector_size; 3603 1.85 reinoud iso9660_vrs = ((32*1024 + sector_size - 1) / sector_size) 3604 1.85 reinoud + trackinfo.track_start; 3605 1.85 reinoud 3606 1.85 reinoud buffer = malloc(UDF_ISO_VRS_SIZE, M_TEMP, M_WAITOK); 3607 1.85 reinoud max_sectors = UDF_ISO_VRS_SIZE / sector_size; 3608 1.85 reinoud blks = MAX(1, 2048 / sector_size); 3609 1.85 reinoud 3610 1.85 reinoud error = 0; 3611 1.85 reinoud for (sector = 0; sector < max_sectors; sector += blks) { 3612 1.85 reinoud pos = buffer + sector * sector_size; 3613 1.85 reinoud error = udf_read_phys_sectors(ump, UDF_C_DSCR, pos, 3614 1.85 reinoud iso9660_vrs + sector, blks); 3615 1.85 reinoud if (error) 3616 1.85 reinoud break; 3617 1.85 reinoud /* check this ISO descriptor */ 3618 1.85 reinoud vrs = (struct vrs_desc *) pos; 3619 1.85 reinoud DPRINTF(VOLUMES, ("got VRS id `%4s`\n", vrs->identifier)); 3620 1.85 reinoud if (strncmp(vrs->identifier, VRS_CD001, 5) == 0) 3621 1.85 reinoud continue; 3622 1.85 reinoud if (strncmp(vrs->identifier, VRS_CDW02, 5) == 0) 3623 1.85 reinoud continue; 3624 1.85 reinoud if (strncmp(vrs->identifier, VRS_BEA01, 5) == 0) 3625 1.85 reinoud continue; 3626 1.85 reinoud if (strncmp(vrs->identifier, VRS_NSR02, 5) == 0) 3627 1.85 reinoud continue; 3628 1.85 reinoud if (strncmp(vrs->identifier, VRS_NSR03, 5) == 0) 3629 1.85 reinoud continue; 3630 1.85 reinoud if (strncmp(vrs->identifier, VRS_TEA01, 5) == 0) 3631 1.85 reinoud break; 3632 1.85 reinoud /* now what? for now, end of sequence */ 3633 1.85 reinoud break; 3634 1.85 reinoud } 3635 1.85 reinoud vrs_len = sector + blks; 3636 1.85 reinoud if (error) { 3637 1.85 reinoud DPRINTF(VOLUMES, ("error reading old ISO VRS\n")); 3638 1.85 reinoud DPRINTF(VOLUMES, ("creating minimal ISO VRS\n")); 3639 1.85 reinoud 3640 1.85 reinoud memset(buffer, 0, UDF_ISO_VRS_SIZE); 3641 1.85 reinoud 3642 1.85 reinoud vrs = (struct vrs_desc *) (buffer); 3643 1.85 reinoud vrs->struct_type = 0; 3644 1.85 reinoud vrs->version = 1; 3645 1.85 reinoud memcpy(vrs->identifier,VRS_BEA01, 5); 3646 1.85 reinoud 3647 1.85 reinoud vrs = (struct vrs_desc *) (buffer + 2048); 3648 1.85 reinoud vrs->struct_type = 0; 3649 1.85 reinoud vrs->version = 1; 3650 1.90 reinoud if (udf_rw16(ump->logical_vol->tag.descriptor_ver) == 2) { 3651 1.85 reinoud memcpy(vrs->identifier,VRS_NSR02, 5); 3652 1.85 reinoud } else { 3653 1.85 reinoud memcpy(vrs->identifier,VRS_NSR03, 5); 3654 1.85 reinoud } 3655 1.85 reinoud 3656 1.85 reinoud vrs = (struct vrs_desc *) (buffer + 4096); 3657 1.85 reinoud vrs->struct_type = 0; 3658 1.85 reinoud vrs->version = 1; 3659 1.85 reinoud memcpy(vrs->identifier, VRS_TEA01, 5); 3660 1.85 reinoud 3661 1.85 reinoud vrs_len = 3*blks; 3662 1.85 reinoud } 3663 1.85 reinoud 3664 1.85 reinoud DPRINTF(VOLUMES, ("Got VRS of %d sectors long\n", vrs_len)); 3665 1.85 reinoud 3666 1.85 reinoud /* 3667 1.85 reinoud * location of iso9660 vrs is defined as first sector AFTER 32kb, 3668 1.85 reinoud * minimum ISO `sector size' 2048 3669 1.85 reinoud */ 3670 1.85 reinoud sector_size = ump->discinfo.sector_size; 3671 1.85 reinoud iso9660_vrs = ((32*1024 + sector_size - 1) / sector_size) 3672 1.85 reinoud + write_track_start; 3673 1.85 reinoud 3674 1.85 reinoud /* write out 32 kb */ 3675 1.85 reinoud blank = malloc(sector_size, M_TEMP, M_WAITOK); 3676 1.85 reinoud memset(blank, 0, sector_size); 3677 1.85 reinoud error = 0; 3678 1.85 reinoud for (sector = write_track_start; sector < iso9660_vrs; sector ++) { 3679 1.85 reinoud error = udf_write_phys_sectors(ump, UDF_C_ABSOLUTE, 3680 1.85 reinoud blank, sector, 1); 3681 1.85 reinoud if (error) 3682 1.85 reinoud break; 3683 1.85 reinoud } 3684 1.85 reinoud if (!error) { 3685 1.85 reinoud /* write out our ISO VRS */ 3686 1.85 reinoud KASSERT(sector == iso9660_vrs); 3687 1.85 reinoud error = udf_write_phys_sectors(ump, UDF_C_ABSOLUTE, buffer, 3688 1.85 reinoud sector, vrs_len); 3689 1.85 reinoud sector += vrs_len; 3690 1.85 reinoud } 3691 1.85 reinoud if (!error) { 3692 1.85 reinoud /* fill upto the first anchor at S+256 */ 3693 1.85 reinoud for (; sector < write_track_start+256; sector++) { 3694 1.85 reinoud error = udf_write_phys_sectors(ump, UDF_C_ABSOLUTE, 3695 1.85 reinoud blank, sector, 1); 3696 1.85 reinoud if (error) 3697 1.85 reinoud break; 3698 1.85 reinoud } 3699 1.85 reinoud } 3700 1.85 reinoud if (!error) { 3701 1.85 reinoud /* write out anchor; write at ABSOLUTE place! */ 3702 1.85 reinoud error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_ABSOLUTE, 3703 1.85 reinoud (union dscrptr *) ump->anchors[0], sector, sector); 3704 1.85 reinoud if (error) 3705 1.85 reinoud printf("writeout of anchor failed!\n"); 3706 1.85 reinoud } 3707 1.85 reinoud 3708 1.85 reinoud free(blank, M_TEMP); 3709 1.85 reinoud free(buffer, M_TEMP); 3710 1.85 reinoud 3711 1.85 reinoud if (error) 3712 1.85 reinoud printf("udf_open_session: error writing iso vrs! : " 3713 1.85 reinoud "leaving disc in compromised state!\n"); 3714 1.85 reinoud 3715 1.85 reinoud /* synchronise device caches */ 3716 1.85 reinoud (void) udf_synchronise_caches(ump); 3717 1.85 reinoud 3718 1.85 reinoud return error; 3719 1.85 reinoud } 3720 1.85 reinoud 3721 1.85 reinoud 3722 1.45 reinoud int 3723 1.45 reinoud udf_open_logvol(struct udf_mount *ump) 3724 1.45 reinoud { 3725 1.45 reinoud int logvol_integrity; 3726 1.45 reinoud int error; 3727 1.45 reinoud 3728 1.45 reinoud /* already/still open? */ 3729 1.45 reinoud logvol_integrity = udf_rw32(ump->logvol_integrity->integrity_type); 3730 1.45 reinoud if (logvol_integrity == UDF_INTEGRITY_OPEN) 3731 1.45 reinoud return 0; 3732 1.45 reinoud 3733 1.45 reinoud /* can we open it ? */ 3734 1.45 reinoud if (ump->vfs_mountp->mnt_flag & MNT_RDONLY) 3735 1.45 reinoud return EROFS; 3736 1.45 reinoud 3737 1.45 reinoud /* setup write parameters */ 3738 1.45 reinoud DPRINTF(VOLUMES, ("Setting up write parameters\n")); 3739 1.45 reinoud if ((error = udf_setup_writeparams(ump)) != 0) 3740 1.45 reinoud return error; 3741 1.45 reinoud 3742 1.45 reinoud /* determine data and metadata tracks (most likely same) */ 3743 1.45 reinoud error = udf_search_writing_tracks(ump); 3744 1.45 reinoud if (error) { 3745 1.45 reinoud /* most likely lack of space */ 3746 1.45 reinoud printf("udf_open_logvol: error searching writing tracks\n"); 3747 1.45 reinoud return EROFS; 3748 1.45 reinoud } 3749 1.45 reinoud 3750 1.45 reinoud /* writeout/update lvint on disc or only in memory */ 3751 1.45 reinoud DPRINTF(VOLUMES, ("Opening logical volume\n")); 3752 1.45 reinoud if (ump->lvopen & UDF_OPEN_SESSION) { 3753 1.85 reinoud /* TODO optional track reservation opening */ 3754 1.85 reinoud error = udf_validate_session_start(ump); 3755 1.85 reinoud if (error) 3756 1.85 reinoud return error; 3757 1.45 reinoud 3758 1.45 reinoud /* determine data and metadata tracks again */ 3759 1.45 reinoud error = udf_search_writing_tracks(ump); 3760 1.137 reinoud 3761 1.137 reinoud if (ump->lvclose & UDF_WRITE_VAT) { 3762 1.137 reinoud /* 3763 1.137 reinoud * we writeout the VAT to get a self-sustained session 3764 1.137 reinoud * for fsck 3765 1.137 reinoud */ 3766 1.137 reinoud DPRINTF(VOLUMES, ("lvclose & UDF_WRITE_VAT\n")); 3767 1.137 reinoud 3768 1.137 reinoud /* write out the VAT data and all its descriptors */ 3769 1.137 reinoud DPRINTF(VOLUMES, ("writeout vat_node\n")); 3770 1.137 reinoud udf_writeout_vat(ump); 3771 1.137 reinoud 3772 1.138 reinoud /* force everything to be synchronized on the device */ 3773 1.138 reinoud (void) udf_synchronise_caches(ump); 3774 1.137 reinoud } 3775 1.45 reinoud } 3776 1.45 reinoud 3777 1.45 reinoud /* mark it open */ 3778 1.45 reinoud ump->logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_OPEN); 3779 1.45 reinoud 3780 1.45 reinoud /* do we need to write it out? */ 3781 1.45 reinoud if (ump->lvopen & UDF_WRITE_LVINT) { 3782 1.45 reinoud error = udf_writeout_lvint(ump, ump->lvopen); 3783 1.45 reinoud /* if we couldn't write it mark it closed again */ 3784 1.45 reinoud if (error) { 3785 1.45 reinoud ump->logvol_integrity->integrity_type = 3786 1.45 reinoud udf_rw32(UDF_INTEGRITY_CLOSED); 3787 1.45 reinoud return error; 3788 1.45 reinoud } 3789 1.45 reinoud } 3790 1.45 reinoud 3791 1.45 reinoud return 0; 3792 1.45 reinoud } 3793 1.45 reinoud 3794 1.45 reinoud 3795 1.45 reinoud int 3796 1.45 reinoud udf_close_logvol(struct udf_mount *ump, int mntflags) 3797 1.45 reinoud { 3798 1.85 reinoud struct vnode *devvp = ump->devvp; 3799 1.85 reinoud struct mmc_op mmc_op; 3800 1.167 reinoud uint32_t phys; 3801 1.45 reinoud int logvol_integrity; 3802 1.70 reinoud int error = 0, error1 = 0, error2 = 0; 3803 1.85 reinoud int tracknr; 3804 1.167 reinoud int nvats, n, relblk, wrtrack_skew, nok; 3805 1.45 reinoud 3806 1.45 reinoud /* already/still closed? */ 3807 1.45 reinoud logvol_integrity = udf_rw32(ump->logvol_integrity->integrity_type); 3808 1.45 reinoud if (logvol_integrity == UDF_INTEGRITY_CLOSED) 3809 1.45 reinoud return 0; 3810 1.45 reinoud 3811 1.45 reinoud /* writeout/update lvint or write out VAT */ 3812 1.85 reinoud DPRINTF(VOLUMES, ("udf_close_logvol: closing logical volume\n")); 3813 1.85 reinoud #ifdef DIAGNOSTIC 3814 1.85 reinoud if (ump->lvclose & UDF_CLOSE_SESSION) 3815 1.85 reinoud KASSERT(ump->lvclose & UDF_WRITE_VAT); 3816 1.85 reinoud #endif 3817 1.85 reinoud 3818 1.45 reinoud if (ump->lvclose & UDF_WRITE_VAT) { 3819 1.45 reinoud DPRINTF(VOLUMES, ("lvclose & UDF_WRITE_VAT\n")); 3820 1.45 reinoud 3821 1.85 reinoud /* write out the VAT data and all its descriptors */ 3822 1.45 reinoud DPRINTF(VOLUMES, ("writeout vat_node\n")); 3823 1.71 reinoud udf_writeout_vat(ump); 3824 1.85 reinoud 3825 1.167 reinoud /* 3826 1.167 reinoud * For bug-compatibility with Windows, the last VAT sector 3827 1.167 reinoud * must be a multiple of 16/32 from the start of the track. 3828 1.167 reinoud * To allow for scratches, write out at least a 32 pieces. 3829 1.167 reinoud */ 3830 1.167 reinoud phys = ump->data_track.track_start; 3831 1.167 reinoud wrtrack_skew = phys % 32; 3832 1.167 reinoud 3833 1.167 reinoud phys = ump->data_track.next_writable; 3834 1.167 reinoud relblk = phys % 32; 3835 1.167 reinoud nvats = 32 + 32 - (relblk - wrtrack_skew); 3836 1.85 reinoud 3837 1.85 reinoud #if notyet 3838 1.85 reinoud /* 3839 1.85 reinoud * TODO calculate the available space and if the disc is 3840 1.165 andvar * almost full, write out till end-256-1 with banks, write 3841 1.85 reinoud * AVDP and fill up with VATs, then close session and close 3842 1.85 reinoud * disc. 3843 1.85 reinoud */ 3844 1.85 reinoud if (ump->lvclose & UDF_FINALISE_DISC) { 3845 1.85 reinoud error = udf_write_phys_dscr_sync(ump, NULL, 3846 1.85 reinoud UDF_C_FLOAT_DSCR, 3847 1.85 reinoud (union dscrptr *) ump->anchors[0], 3848 1.85 reinoud 0, 0); 3849 1.85 reinoud if (error) 3850 1.85 reinoud printf("writeout of anchor failed!\n"); 3851 1.85 reinoud 3852 1.85 reinoud /* pad space with VAT ICBs */ 3853 1.85 reinoud nvats = 256; 3854 1.85 reinoud } 3855 1.85 reinoud #endif 3856 1.85 reinoud 3857 1.85 reinoud /* write out a number of VAT nodes */ 3858 1.85 reinoud nok = 0; 3859 1.85 reinoud for (n = 0; n < nvats; n++) { 3860 1.85 reinoud /* will now only write last FE/EFE */ 3861 1.45 reinoud ump->vat_node->i_flags |= IN_MODIFIED; 3862 1.45 reinoud error = VOP_FSYNC(ump->vat_node->vnode, 3863 1.45 reinoud FSCRED, FSYNC_WAIT, 0, 0); 3864 1.85 reinoud if (!error) 3865 1.85 reinoud nok++; 3866 1.85 reinoud } 3867 1.138 reinoud /* force everything to be synchronized on the device */ 3868 1.138 reinoud (void) udf_synchronise_caches(ump); 3869 1.138 reinoud 3870 1.85 reinoud if (nok < 14) { 3871 1.85 reinoud /* arbitrary; but at least one or two CD frames */ 3872 1.85 reinoud printf("writeout of at least 14 VATs failed\n"); 3873 1.85 reinoud return error; 3874 1.85 reinoud } 3875 1.85 reinoud } 3876 1.85 reinoud 3877 1.85 reinoud /* NOTE the disc is in a (minimal) valid state now; no erroring out */ 3878 1.85 reinoud 3879 1.85 reinoud /* finish closing of session */ 3880 1.85 reinoud if (ump->lvclose & UDF_CLOSE_SESSION) { 3881 1.138 reinoud DPRINTF(VOLUMES, ("udf_close_logvol: closing session " 3882 1.138 reinoud "as requested\n")); 3883 1.85 reinoud error = udf_validate_session_start(ump); 3884 1.85 reinoud if (error) 3885 1.85 reinoud return error; 3886 1.85 reinoud 3887 1.99 reinoud (void) udf_synchronise_caches(ump); 3888 1.99 reinoud 3889 1.85 reinoud /* close all associated tracks */ 3890 1.85 reinoud tracknr = ump->discinfo.first_track_last_session; 3891 1.85 reinoud error = 0; 3892 1.85 reinoud while (tracknr <= ump->discinfo.last_track_last_session) { 3893 1.85 reinoud DPRINTF(VOLUMES, ("\tclosing possible open " 3894 1.85 reinoud "track %d\n", tracknr)); 3895 1.85 reinoud memset(&mmc_op, 0, sizeof(mmc_op)); 3896 1.85 reinoud mmc_op.operation = MMC_OP_CLOSETRACK; 3897 1.85 reinoud mmc_op.mmc_profile = ump->discinfo.mmc_profile; 3898 1.85 reinoud mmc_op.tracknr = tracknr; 3899 1.85 reinoud error = VOP_IOCTL(devvp, MMCOP, &mmc_op, 3900 1.85 reinoud FKIOCTL, NOCRED); 3901 1.85 reinoud if (error) 3902 1.85 reinoud printf("udf_close_logvol: closing of " 3903 1.85 reinoud "track %d failed\n", tracknr); 3904 1.85 reinoud tracknr ++; 3905 1.85 reinoud } 3906 1.85 reinoud if (!error) { 3907 1.85 reinoud DPRINTF(VOLUMES, ("closing session\n")); 3908 1.85 reinoud memset(&mmc_op, 0, sizeof(mmc_op)); 3909 1.85 reinoud mmc_op.operation = MMC_OP_CLOSESESSION; 3910 1.85 reinoud mmc_op.mmc_profile = ump->discinfo.mmc_profile; 3911 1.85 reinoud mmc_op.sessionnr = ump->discinfo.num_sessions; 3912 1.85 reinoud error = VOP_IOCTL(devvp, MMCOP, &mmc_op, 3913 1.85 reinoud FKIOCTL, NOCRED); 3914 1.85 reinoud if (error) 3915 1.85 reinoud printf("udf_close_logvol: closing of session" 3916 1.85 reinoud "failed\n"); 3917 1.45 reinoud } 3918 1.85 reinoud if (!error) 3919 1.85 reinoud ump->lvopen |= UDF_OPEN_SESSION; 3920 1.45 reinoud if (error) { 3921 1.85 reinoud printf("udf_close_logvol: leaving disc as it is\n"); 3922 1.85 reinoud ump->lvclose &= ~UDF_FINALISE_DISC; 3923 1.45 reinoud } 3924 1.45 reinoud } 3925 1.45 reinoud 3926 1.85 reinoud if (ump->lvclose & UDF_FINALISE_DISC) { 3927 1.85 reinoud memset(&mmc_op, 0, sizeof(mmc_op)); 3928 1.85 reinoud mmc_op.operation = MMC_OP_FINALISEDISC; 3929 1.85 reinoud mmc_op.mmc_profile = ump->discinfo.mmc_profile; 3930 1.85 reinoud mmc_op.sessionnr = ump->discinfo.num_sessions; 3931 1.85 reinoud error = VOP_IOCTL(devvp, MMCOP, &mmc_op, 3932 1.85 reinoud FKIOCTL, NOCRED); 3933 1.85 reinoud if (error) 3934 1.85 reinoud printf("udf_close_logvol: finalising disc" 3935 1.85 reinoud "failed\n"); 3936 1.85 reinoud } 3937 1.85 reinoud 3938 1.85 reinoud /* write out partition bitmaps if requested */ 3939 1.45 reinoud if (ump->lvclose & UDF_WRITE_PART_BITMAPS) { 3940 1.70 reinoud /* sync writeout metadata spacetable if existing */ 3941 1.70 reinoud error1 = udf_write_metadata_partition_spacetable(ump, true); 3942 1.70 reinoud if (error1) 3943 1.70 reinoud printf( "udf_close_logvol: writeout of metadata space " 3944 1.70 reinoud "bitmap failed\n"); 3945 1.70 reinoud 3946 1.68 reinoud /* sync writeout partition spacetables */ 3947 1.70 reinoud error2 = udf_write_physical_partition_spacetables(ump, true); 3948 1.70 reinoud if (error2) 3949 1.45 reinoud printf( "udf_close_logvol: writeout of space tables " 3950 1.45 reinoud "failed\n"); 3951 1.70 reinoud 3952 1.70 reinoud if (error1 || error2) 3953 1.70 reinoud return (error1 | error2); 3954 1.70 reinoud 3955 1.45 reinoud ump->lvclose &= ~UDF_WRITE_PART_BITMAPS; 3956 1.45 reinoud } 3957 1.45 reinoud 3958 1.104 reinoud /* write out metadata partition nodes if requested */ 3959 1.104 reinoud if (ump->lvclose & UDF_WRITE_METAPART_NODES) { 3960 1.104 reinoud /* sync writeout metadata descriptor node */ 3961 1.104 reinoud error1 = udf_writeout_node(ump->metadata_node, FSYNC_WAIT); 3962 1.104 reinoud if (error1) 3963 1.104 reinoud printf( "udf_close_logvol: writeout of metadata partition " 3964 1.104 reinoud "node failed\n"); 3965 1.104 reinoud 3966 1.104 reinoud /* duplicate metadata partition descriptor if needed */ 3967 1.104 reinoud udf_synchronise_metadatamirror_node(ump); 3968 1.104 reinoud 3969 1.104 reinoud /* sync writeout metadatamirror descriptor node */ 3970 1.104 reinoud error2 = udf_writeout_node(ump->metadatamirror_node, FSYNC_WAIT); 3971 1.104 reinoud if (error2) 3972 1.104 reinoud printf( "udf_close_logvol: writeout of metadata partition " 3973 1.104 reinoud "mirror node failed\n"); 3974 1.104 reinoud 3975 1.104 reinoud if (error1 || error2) 3976 1.104 reinoud return (error1 | error2); 3977 1.104 reinoud 3978 1.104 reinoud ump->lvclose &= ~UDF_WRITE_METAPART_NODES; 3979 1.104 reinoud } 3980 1.104 reinoud 3981 1.45 reinoud /* mark it closed */ 3982 1.45 reinoud ump->logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_CLOSED); 3983 1.45 reinoud 3984 1.85 reinoud /* do we need to write out the logical volume integrity? */ 3985 1.45 reinoud if (ump->lvclose & UDF_WRITE_LVINT) 3986 1.45 reinoud error = udf_writeout_lvint(ump, ump->lvopen); 3987 1.45 reinoud if (error) { 3988 1.45 reinoud /* HELP now what? mark it open again for now */ 3989 1.45 reinoud ump->logvol_integrity->integrity_type = 3990 1.45 reinoud udf_rw32(UDF_INTEGRITY_OPEN); 3991 1.45 reinoud return error; 3992 1.9 christos } 3993 1.1 reinoud 3994 1.45 reinoud (void) udf_synchronise_caches(ump); 3995 1.1 reinoud 3996 1.1 reinoud return 0; 3997 1.1 reinoud } 3998 1.1 reinoud 3999 1.1 reinoud /* --------------------------------------------------------------------- */ 4000 1.1 reinoud 4001 1.1 reinoud /* 4002 1.45 reinoud * Genfs interfacing 4003 1.45 reinoud * 4004 1.45 reinoud * static const struct genfs_ops udf_genfsops = { 4005 1.45 reinoud * .gop_size = genfs_size, 4006 1.45 reinoud * size of transfers 4007 1.45 reinoud * .gop_alloc = udf_gop_alloc, 4008 1.45 reinoud * allocate len bytes at offset 4009 1.45 reinoud * .gop_write = genfs_gop_write, 4010 1.45 reinoud * putpages interface code 4011 1.45 reinoud * .gop_markupdate = udf_gop_markupdate, 4012 1.45 reinoud * set update/modify flags etc. 4013 1.45 reinoud * } 4014 1.45 reinoud */ 4015 1.45 reinoud 4016 1.45 reinoud /* 4017 1.45 reinoud * Genfs interface. These four functions are the only ones defined though not 4018 1.45 reinoud * documented... great.... 4019 1.1 reinoud */ 4020 1.1 reinoud 4021 1.45 reinoud /* 4022 1.95 reinoud * Called for allocating an extent of the file either by VOP_WRITE() or by 4023 1.95 reinoud * genfs filling up gaps. 4024 1.45 reinoud */ 4025 1.1 reinoud static int 4026 1.45 reinoud udf_gop_alloc(struct vnode *vp, off_t off, 4027 1.45 reinoud off_t len, int flags, kauth_cred_t cred) 4028 1.45 reinoud { 4029 1.45 reinoud struct udf_node *udf_node = VTOI(vp); 4030 1.45 reinoud struct udf_mount *ump = udf_node->ump; 4031 1.95 reinoud uint64_t lb_start, lb_end; 4032 1.45 reinoud uint32_t lb_size, num_lb; 4033 1.95 reinoud int udf_c_type, vpart_num, can_fail; 4034 1.95 reinoud int error; 4035 1.95 reinoud 4036 1.95 reinoud DPRINTF(ALLOC, ("udf_gop_alloc called for offset %"PRIu64" for %"PRIu64" bytes, %s\n", 4037 1.95 reinoud off, len, flags? "SYNC":"NONE")); 4038 1.95 reinoud 4039 1.95 reinoud /* 4040 1.95 reinoud * request the pages of our vnode and see how many pages will need to 4041 1.95 reinoud * be allocated and reserve that space 4042 1.95 reinoud */ 4043 1.95 reinoud lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); 4044 1.95 reinoud lb_start = off / lb_size; 4045 1.95 reinoud lb_end = (off + len + lb_size -1) / lb_size; 4046 1.95 reinoud num_lb = lb_end - lb_start; 4047 1.95 reinoud 4048 1.95 reinoud udf_c_type = udf_get_c_type(udf_node); 4049 1.95 reinoud vpart_num = udf_get_record_vpart(ump, udf_c_type); 4050 1.95 reinoud 4051 1.95 reinoud /* all requests can fail */ 4052 1.95 reinoud can_fail = true; 4053 1.95 reinoud 4054 1.95 reinoud /* fid's (directories) can't fail */ 4055 1.95 reinoud if (udf_c_type == UDF_C_FIDS) 4056 1.95 reinoud can_fail = false; 4057 1.95 reinoud 4058 1.95 reinoud /* system files can't fail */ 4059 1.95 reinoud if (vp->v_vflag & VV_SYSTEM) 4060 1.95 reinoud can_fail = false; 4061 1.95 reinoud 4062 1.95 reinoud error = udf_reserve_space(ump, udf_node, udf_c_type, 4063 1.95 reinoud vpart_num, num_lb, can_fail); 4064 1.45 reinoud 4065 1.95 reinoud DPRINTF(ALLOC, ("\tlb_start %"PRIu64", lb_end %"PRIu64", num_lb %d\n", 4066 1.95 reinoud lb_start, lb_end, num_lb)); 4067 1.45 reinoud 4068 1.95 reinoud return error; 4069 1.45 reinoud } 4070 1.45 reinoud 4071 1.45 reinoud 4072 1.45 reinoud /* 4073 1.45 reinoud * callback from genfs to update our flags 4074 1.45 reinoud */ 4075 1.45 reinoud static void 4076 1.45 reinoud udf_gop_markupdate(struct vnode *vp, int flags) 4077 1.45 reinoud { 4078 1.45 reinoud struct udf_node *udf_node = VTOI(vp); 4079 1.45 reinoud u_long mask = 0; 4080 1.45 reinoud 4081 1.45 reinoud if ((flags & GOP_UPDATE_ACCESSED) != 0) { 4082 1.45 reinoud mask = IN_ACCESS; 4083 1.45 reinoud } 4084 1.45 reinoud if ((flags & GOP_UPDATE_MODIFIED) != 0) { 4085 1.45 reinoud if (vp->v_type == VREG) { 4086 1.45 reinoud mask |= IN_CHANGE | IN_UPDATE; 4087 1.45 reinoud } else { 4088 1.45 reinoud mask |= IN_MODIFY; 4089 1.45 reinoud } 4090 1.45 reinoud } 4091 1.45 reinoud if (mask) { 4092 1.45 reinoud udf_node->i_flags |= mask; 4093 1.45 reinoud } 4094 1.45 reinoud } 4095 1.45 reinoud 4096 1.45 reinoud 4097 1.45 reinoud static const struct genfs_ops udf_genfsops = { 4098 1.45 reinoud .gop_size = genfs_size, 4099 1.45 reinoud .gop_alloc = udf_gop_alloc, 4100 1.45 reinoud .gop_write = genfs_gop_write_rwmap, 4101 1.45 reinoud .gop_markupdate = udf_gop_markupdate, 4102 1.140 chs .gop_putrange = genfs_gop_putrange, 4103 1.45 reinoud }; 4104 1.45 reinoud 4105 1.45 reinoud 4106 1.45 reinoud /* --------------------------------------------------------------------- */ 4107 1.45 reinoud 4108 1.45 reinoud int 4109 1.45 reinoud udf_write_terminator(struct udf_mount *ump, uint32_t sector) 4110 1.1 reinoud { 4111 1.45 reinoud union dscrptr *dscr; 4112 1.1 reinoud int error; 4113 1.1 reinoud 4114 1.83 cegger dscr = malloc(ump->discinfo.sector_size, M_TEMP, M_WAITOK|M_ZERO); 4115 1.45 reinoud udf_inittag(ump, &dscr->tag, TAGID_TERM, sector); 4116 1.45 reinoud 4117 1.45 reinoud /* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */ 4118 1.45 reinoud dscr->tag.desc_crc_len = udf_rw16(512-UDF_DESC_TAG_LENGTH); 4119 1.45 reinoud (void) udf_validate_tag_and_crc_sums(dscr); 4120 1.45 reinoud 4121 1.45 reinoud error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR, 4122 1.45 reinoud dscr, sector, sector); 4123 1.45 reinoud 4124 1.45 reinoud free(dscr, M_TEMP); 4125 1.45 reinoud 4126 1.45 reinoud return error; 4127 1.45 reinoud } 4128 1.45 reinoud 4129 1.45 reinoud 4130 1.45 reinoud /* --------------------------------------------------------------------- */ 4131 1.45 reinoud 4132 1.45 reinoud /* UDF<->unix converters */ 4133 1.45 reinoud 4134 1.45 reinoud /* --------------------------------------------------------------------- */ 4135 1.45 reinoud 4136 1.45 reinoud static mode_t 4137 1.45 reinoud udf_perm_to_unix_mode(uint32_t perm) 4138 1.45 reinoud { 4139 1.45 reinoud mode_t mode; 4140 1.45 reinoud 4141 1.45 reinoud mode = ((perm & UDF_FENTRY_PERM_USER_MASK) ); 4142 1.45 reinoud mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK ) >> 2); 4143 1.45 reinoud mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4); 4144 1.45 reinoud 4145 1.45 reinoud return mode; 4146 1.45 reinoud } 4147 1.45 reinoud 4148 1.45 reinoud /* --------------------------------------------------------------------- */ 4149 1.45 reinoud 4150 1.45 reinoud static uint32_t 4151 1.45 reinoud unix_mode_to_udf_perm(mode_t mode) 4152 1.45 reinoud { 4153 1.45 reinoud uint32_t perm; 4154 1.152 skrll 4155 1.45 reinoud perm = ((mode & S_IRWXO) ); 4156 1.45 reinoud perm |= ((mode & S_IRWXG) << 2); 4157 1.45 reinoud perm |= ((mode & S_IRWXU) << 4); 4158 1.45 reinoud perm |= ((mode & S_IWOTH) << 3); 4159 1.45 reinoud perm |= ((mode & S_IWGRP) << 5); 4160 1.45 reinoud perm |= ((mode & S_IWUSR) << 7); 4161 1.45 reinoud 4162 1.45 reinoud return perm; 4163 1.45 reinoud } 4164 1.45 reinoud 4165 1.45 reinoud /* --------------------------------------------------------------------- */ 4166 1.45 reinoud 4167 1.45 reinoud static uint32_t 4168 1.45 reinoud udf_icb_to_unix_filetype(uint32_t icbftype) 4169 1.45 reinoud { 4170 1.45 reinoud switch (icbftype) { 4171 1.45 reinoud case UDF_ICB_FILETYPE_DIRECTORY : 4172 1.45 reinoud case UDF_ICB_FILETYPE_STREAMDIR : 4173 1.45 reinoud return S_IFDIR; 4174 1.45 reinoud case UDF_ICB_FILETYPE_FIFO : 4175 1.45 reinoud return S_IFIFO; 4176 1.45 reinoud case UDF_ICB_FILETYPE_CHARDEVICE : 4177 1.45 reinoud return S_IFCHR; 4178 1.45 reinoud case UDF_ICB_FILETYPE_BLOCKDEVICE : 4179 1.45 reinoud return S_IFBLK; 4180 1.45 reinoud case UDF_ICB_FILETYPE_RANDOMACCESS : 4181 1.45 reinoud case UDF_ICB_FILETYPE_REALTIME : 4182 1.45 reinoud return S_IFREG; 4183 1.45 reinoud case UDF_ICB_FILETYPE_SYMLINK : 4184 1.45 reinoud return S_IFLNK; 4185 1.45 reinoud case UDF_ICB_FILETYPE_SOCKET : 4186 1.45 reinoud return S_IFSOCK; 4187 1.45 reinoud } 4188 1.45 reinoud /* no idea what this is */ 4189 1.45 reinoud return 0; 4190 1.45 reinoud } 4191 1.1 reinoud 4192 1.45 reinoud /* --------------------------------------------------------------------- */ 4193 1.1 reinoud 4194 1.45 reinoud void 4195 1.48 reinoud udf_to_unix_name(char *result, int result_len, char *id, int len, 4196 1.48 reinoud struct charspec *chsp) 4197 1.45 reinoud { 4198 1.45 reinoud uint16_t *raw_name, *unix_name; 4199 1.45 reinoud uint16_t *inchp, ch; 4200 1.45 reinoud uint8_t *outchp; 4201 1.45 reinoud const char *osta_id = "OSTA Compressed Unicode"; 4202 1.48 reinoud int ucode_chars, nice_uchars, is_osta_typ0, nout; 4203 1.1 reinoud 4204 1.45 reinoud raw_name = malloc(2048 * sizeof(uint16_t), M_UDFTEMP, M_WAITOK); 4205 1.45 reinoud unix_name = raw_name + 1024; /* split space in half */ 4206 1.45 reinoud assert(sizeof(char) == sizeof(uint8_t)); 4207 1.45 reinoud outchp = (uint8_t *) result; 4208 1.1 reinoud 4209 1.45 reinoud is_osta_typ0 = (chsp->type == 0); 4210 1.45 reinoud is_osta_typ0 &= (strcmp((char *) chsp->inf, osta_id) == 0); 4211 1.45 reinoud if (is_osta_typ0) { 4212 1.48 reinoud /* TODO clean up */ 4213 1.45 reinoud *raw_name = *unix_name = 0; 4214 1.45 reinoud ucode_chars = udf_UncompressUnicode(len, (uint8_t *) id, raw_name); 4215 1.45 reinoud ucode_chars = MIN(ucode_chars, UnicodeLength((unicode_t *) raw_name)); 4216 1.45 reinoud nice_uchars = UDFTransName(unix_name, raw_name, ucode_chars); 4217 1.48 reinoud /* output UTF8 */ 4218 1.45 reinoud for (inchp = unix_name; nice_uchars>0; inchp++, nice_uchars--) { 4219 1.45 reinoud ch = *inchp; 4220 1.48 reinoud nout = wput_utf8(outchp, result_len, ch); 4221 1.48 reinoud outchp += nout; result_len -= nout; 4222 1.45 reinoud if (!ch) break; 4223 1.45 reinoud } 4224 1.45 reinoud *outchp++ = 0; 4225 1.1 reinoud } else { 4226 1.45 reinoud /* assume 8bit char length byte latin-1 */ 4227 1.45 reinoud assert(*id == 8); 4228 1.117 christos assert(strlen((char *) (id+1)) <= NAME_MAX); 4229 1.45 reinoud strncpy((char *) result, (char *) (id+1), strlen((char *) (id+1))); 4230 1.9 christos } 4231 1.45 reinoud free(raw_name, M_UDFTEMP); 4232 1.45 reinoud } 4233 1.45 reinoud 4234 1.45 reinoud /* --------------------------------------------------------------------- */ 4235 1.1 reinoud 4236 1.45 reinoud void 4237 1.45 reinoud unix_to_udf_name(char *result, uint8_t *result_len, char const *name, int name_len, 4238 1.45 reinoud struct charspec *chsp) 4239 1.45 reinoud { 4240 1.45 reinoud uint16_t *raw_name; 4241 1.45 reinoud uint16_t *outchp; 4242 1.45 reinoud const char *inchp; 4243 1.45 reinoud const char *osta_id = "OSTA Compressed Unicode"; 4244 1.49 christos int udf_chars, is_osta_typ0, bits; 4245 1.49 christos size_t cnt; 4246 1.1 reinoud 4247 1.45 reinoud /* allocate temporary unicode-16 buffer */ 4248 1.45 reinoud raw_name = malloc(1024, M_UDFTEMP, M_WAITOK); 4249 1.1 reinoud 4250 1.48 reinoud /* convert utf8 to unicode-16 */ 4251 1.45 reinoud *raw_name = 0; 4252 1.45 reinoud inchp = name; 4253 1.45 reinoud outchp = raw_name; 4254 1.48 reinoud bits = 8; 4255 1.48 reinoud for (cnt = name_len, udf_chars = 0; cnt;) { 4256 1.48 reinoud *outchp = wget_utf8(&inchp, &cnt); 4257 1.48 reinoud if (*outchp > 0xff) 4258 1.48 reinoud bits=16; 4259 1.48 reinoud outchp++; 4260 1.48 reinoud udf_chars++; 4261 1.45 reinoud } 4262 1.48 reinoud /* null terminate just in case */ 4263 1.48 reinoud *outchp++ = 0; 4264 1.1 reinoud 4265 1.45 reinoud is_osta_typ0 = (chsp->type == 0); 4266 1.45 reinoud is_osta_typ0 &= (strcmp((char *) chsp->inf, osta_id) == 0); 4267 1.45 reinoud if (is_osta_typ0) { 4268 1.48 reinoud udf_chars = udf_CompressUnicode(udf_chars, bits, 4269 1.45 reinoud (unicode_t *) raw_name, 4270 1.45 reinoud (byte *) result); 4271 1.45 reinoud } else { 4272 1.48 reinoud printf("unix to udf name: no CHSP0 ?\n"); 4273 1.45 reinoud /* XXX assume 8bit char length byte latin-1 */ 4274 1.45 reinoud *result++ = 8; udf_chars = 1; 4275 1.45 reinoud strncpy(result, name + 1, name_len); 4276 1.45 reinoud udf_chars += name_len; 4277 1.9 christos } 4278 1.45 reinoud *result_len = udf_chars; 4279 1.45 reinoud free(raw_name, M_UDFTEMP); 4280 1.45 reinoud } 4281 1.45 reinoud 4282 1.45 reinoud /* --------------------------------------------------------------------- */ 4283 1.45 reinoud 4284 1.45 reinoud void 4285 1.45 reinoud udf_timestamp_to_timespec(struct udf_mount *ump, 4286 1.45 reinoud struct timestamp *timestamp, 4287 1.45 reinoud struct timespec *timespec) 4288 1.45 reinoud { 4289 1.45 reinoud struct clock_ymdhms ymdhms; 4290 1.45 reinoud uint32_t usecs, secs, nsecs; 4291 1.45 reinoud uint16_t tz; 4292 1.45 reinoud 4293 1.45 reinoud /* fill in ymdhms structure from timestamp */ 4294 1.45 reinoud memset(&ymdhms, 0, sizeof(ymdhms)); 4295 1.45 reinoud ymdhms.dt_year = udf_rw16(timestamp->year); 4296 1.45 reinoud ymdhms.dt_mon = timestamp->month; 4297 1.45 reinoud ymdhms.dt_day = timestamp->day; 4298 1.45 reinoud ymdhms.dt_wday = 0; /* ? */ 4299 1.45 reinoud ymdhms.dt_hour = timestamp->hour; 4300 1.45 reinoud ymdhms.dt_min = timestamp->minute; 4301 1.45 reinoud ymdhms.dt_sec = timestamp->second; 4302 1.45 reinoud 4303 1.45 reinoud secs = clock_ymdhms_to_secs(&ymdhms); 4304 1.45 reinoud usecs = timestamp->usec + 4305 1.45 reinoud 100*timestamp->hund_usec + 10000*timestamp->centisec; 4306 1.45 reinoud nsecs = usecs * 1000; 4307 1.1 reinoud 4308 1.1 reinoud /* 4309 1.45 reinoud * Calculate the time zone. The timezone is 12 bit signed 2's 4310 1.45 reinoud * compliment, so we gotta do some extra magic to handle it right. 4311 1.1 reinoud */ 4312 1.45 reinoud tz = udf_rw16(timestamp->type_tz); 4313 1.45 reinoud tz &= 0x0fff; /* only lower 12 bits are significant */ 4314 1.157 andvar if (tz & 0x0800) /* sign extension */ 4315 1.45 reinoud tz |= 0xf000; 4316 1.1 reinoud 4317 1.45 reinoud /* TODO check timezone conversion */ 4318 1.45 reinoud /* check if we are specified a timezone to convert */ 4319 1.45 reinoud if (udf_rw16(timestamp->type_tz) & 0x1000) { 4320 1.45 reinoud if ((int16_t) tz != -2047) 4321 1.45 reinoud secs -= (int16_t) tz * 60; 4322 1.1 reinoud } else { 4323 1.45 reinoud secs -= ump->mount_args.gmtoff; 4324 1.45 reinoud } 4325 1.1 reinoud 4326 1.45 reinoud timespec->tv_sec = secs; 4327 1.45 reinoud timespec->tv_nsec = nsecs; 4328 1.45 reinoud } 4329 1.1 reinoud 4330 1.1 reinoud 4331 1.45 reinoud void 4332 1.45 reinoud udf_timespec_to_timestamp(struct timespec *timespec, struct timestamp *timestamp) 4333 1.45 reinoud { 4334 1.45 reinoud struct clock_ymdhms ymdhms; 4335 1.45 reinoud uint32_t husec, usec, csec; 4336 1.1 reinoud 4337 1.45 reinoud (void) clock_secs_to_ymdhms(timespec->tv_sec, &ymdhms); 4338 1.1 reinoud 4339 1.58 reinoud usec = timespec->tv_nsec / 1000; 4340 1.58 reinoud husec = usec / 100; 4341 1.58 reinoud usec -= husec * 100; /* only 0-99 in usec */ 4342 1.58 reinoud csec = husec / 100; /* only 0-99 in csec */ 4343 1.58 reinoud husec -= csec * 100; /* only 0-99 in husec */ 4344 1.45 reinoud 4345 1.45 reinoud /* set method 1 for CUT/GMT */ 4346 1.45 reinoud timestamp->type_tz = udf_rw16((1<<12) + 0); 4347 1.45 reinoud timestamp->year = udf_rw16(ymdhms.dt_year); 4348 1.45 reinoud timestamp->month = ymdhms.dt_mon; 4349 1.45 reinoud timestamp->day = ymdhms.dt_day; 4350 1.45 reinoud timestamp->hour = ymdhms.dt_hour; 4351 1.45 reinoud timestamp->minute = ymdhms.dt_min; 4352 1.45 reinoud timestamp->second = ymdhms.dt_sec; 4353 1.45 reinoud timestamp->centisec = csec; 4354 1.45 reinoud timestamp->hund_usec = husec; 4355 1.45 reinoud timestamp->usec = usec; 4356 1.1 reinoud } 4357 1.1 reinoud 4358 1.1 reinoud /* --------------------------------------------------------------------- */ 4359 1.1 reinoud 4360 1.45 reinoud /* 4361 1.45 reinoud * Attribute and filetypes converters with get/set pairs 4362 1.45 reinoud */ 4363 1.45 reinoud 4364 1.45 reinoud uint32_t 4365 1.45 reinoud udf_getaccessmode(struct udf_node *udf_node) 4366 1.1 reinoud { 4367 1.101 mbalmer struct file_entry *fe = udf_node->fe; 4368 1.45 reinoud struct extfile_entry *efe = udf_node->efe; 4369 1.45 reinoud uint32_t udf_perm, icbftype; 4370 1.45 reinoud uint32_t mode, ftype; 4371 1.45 reinoud uint16_t icbflags; 4372 1.1 reinoud 4373 1.45 reinoud UDF_LOCK_NODE(udf_node, 0); 4374 1.45 reinoud if (fe) { 4375 1.45 reinoud udf_perm = udf_rw32(fe->perm); 4376 1.45 reinoud icbftype = fe->icbtag.file_type; 4377 1.45 reinoud icbflags = udf_rw16(fe->icbtag.flags); 4378 1.45 reinoud } else { 4379 1.45 reinoud assert(udf_node->efe); 4380 1.45 reinoud udf_perm = udf_rw32(efe->perm); 4381 1.45 reinoud icbftype = efe->icbtag.file_type; 4382 1.45 reinoud icbflags = udf_rw16(efe->icbtag.flags); 4383 1.45 reinoud } 4384 1.1 reinoud 4385 1.45 reinoud mode = udf_perm_to_unix_mode(udf_perm); 4386 1.45 reinoud ftype = udf_icb_to_unix_filetype(icbftype); 4387 1.1 reinoud 4388 1.45 reinoud /* set suid, sgid, sticky from flags in fe/efe */ 4389 1.45 reinoud if (icbflags & UDF_ICB_TAG_FLAGS_SETUID) 4390 1.45 reinoud mode |= S_ISUID; 4391 1.45 reinoud if (icbflags & UDF_ICB_TAG_FLAGS_SETGID) 4392 1.45 reinoud mode |= S_ISGID; 4393 1.45 reinoud if (icbflags & UDF_ICB_TAG_FLAGS_STICKY) 4394 1.45 reinoud mode |= S_ISVTX; 4395 1.1 reinoud 4396 1.45 reinoud UDF_UNLOCK_NODE(udf_node, 0); 4397 1.1 reinoud 4398 1.45 reinoud return mode | ftype; 4399 1.1 reinoud } 4400 1.1 reinoud 4401 1.1 reinoud 4402 1.45 reinoud void 4403 1.45 reinoud udf_setaccessmode(struct udf_node *udf_node, mode_t mode) 4404 1.1 reinoud { 4405 1.45 reinoud struct file_entry *fe = udf_node->fe; 4406 1.45 reinoud struct extfile_entry *efe = udf_node->efe; 4407 1.45 reinoud uint32_t udf_perm; 4408 1.45 reinoud uint16_t icbflags; 4409 1.45 reinoud 4410 1.45 reinoud UDF_LOCK_NODE(udf_node, 0); 4411 1.45 reinoud udf_perm = unix_mode_to_udf_perm(mode & ALLPERMS); 4412 1.45 reinoud if (fe) { 4413 1.45 reinoud icbflags = udf_rw16(fe->icbtag.flags); 4414 1.45 reinoud } else { 4415 1.45 reinoud icbflags = udf_rw16(efe->icbtag.flags); 4416 1.45 reinoud } 4417 1.1 reinoud 4418 1.45 reinoud icbflags &= ~UDF_ICB_TAG_FLAGS_SETUID; 4419 1.45 reinoud icbflags &= ~UDF_ICB_TAG_FLAGS_SETGID; 4420 1.45 reinoud icbflags &= ~UDF_ICB_TAG_FLAGS_STICKY; 4421 1.45 reinoud if (mode & S_ISUID) 4422 1.45 reinoud icbflags |= UDF_ICB_TAG_FLAGS_SETUID; 4423 1.45 reinoud if (mode & S_ISGID) 4424 1.45 reinoud icbflags |= UDF_ICB_TAG_FLAGS_SETGID; 4425 1.45 reinoud if (mode & S_ISVTX) 4426 1.45 reinoud icbflags |= UDF_ICB_TAG_FLAGS_STICKY; 4427 1.1 reinoud 4428 1.45 reinoud if (fe) { 4429 1.45 reinoud fe->perm = udf_rw32(udf_perm); 4430 1.45 reinoud fe->icbtag.flags = udf_rw16(icbflags); 4431 1.45 reinoud } else { 4432 1.45 reinoud efe->perm = udf_rw32(udf_perm); 4433 1.45 reinoud efe->icbtag.flags = udf_rw16(icbflags); 4434 1.9 christos } 4435 1.1 reinoud 4436 1.45 reinoud UDF_UNLOCK_NODE(udf_node, 0); 4437 1.1 reinoud } 4438 1.1 reinoud 4439 1.1 reinoud 4440 1.45 reinoud void 4441 1.45 reinoud udf_getownership(struct udf_node *udf_node, uid_t *uidp, gid_t *gidp) 4442 1.26 reinoud { 4443 1.45 reinoud struct udf_mount *ump = udf_node->ump; 4444 1.45 reinoud struct file_entry *fe = udf_node->fe; 4445 1.45 reinoud struct extfile_entry *efe = udf_node->efe; 4446 1.45 reinoud uid_t uid; 4447 1.45 reinoud gid_t gid; 4448 1.26 reinoud 4449 1.45 reinoud UDF_LOCK_NODE(udf_node, 0); 4450 1.45 reinoud if (fe) { 4451 1.45 reinoud uid = (uid_t)udf_rw32(fe->uid); 4452 1.45 reinoud gid = (gid_t)udf_rw32(fe->gid); 4453 1.45 reinoud } else { 4454 1.45 reinoud assert(udf_node->efe); 4455 1.45 reinoud uid = (uid_t)udf_rw32(efe->uid); 4456 1.45 reinoud gid = (gid_t)udf_rw32(efe->gid); 4457 1.45 reinoud } 4458 1.152 skrll 4459 1.45 reinoud /* do the uid/gid translation game */ 4460 1.76 reinoud if (uid == (uid_t) -1) 4461 1.45 reinoud uid = ump->mount_args.anon_uid; 4462 1.76 reinoud if (gid == (gid_t) -1) 4463 1.45 reinoud gid = ump->mount_args.anon_gid; 4464 1.76 reinoud 4465 1.45 reinoud *uidp = uid; 4466 1.45 reinoud *gidp = gid; 4467 1.45 reinoud 4468 1.45 reinoud UDF_UNLOCK_NODE(udf_node, 0); 4469 1.45 reinoud } 4470 1.26 reinoud 4471 1.26 reinoud 4472 1.45 reinoud void 4473 1.45 reinoud udf_setownership(struct udf_node *udf_node, uid_t uid, gid_t gid) 4474 1.45 reinoud { 4475 1.45 reinoud struct udf_mount *ump = udf_node->ump; 4476 1.45 reinoud struct file_entry *fe = udf_node->fe; 4477 1.45 reinoud struct extfile_entry *efe = udf_node->efe; 4478 1.45 reinoud uid_t nobody_uid; 4479 1.45 reinoud gid_t nobody_gid; 4480 1.45 reinoud 4481 1.45 reinoud UDF_LOCK_NODE(udf_node, 0); 4482 1.45 reinoud 4483 1.45 reinoud /* do the uid/gid translation game */ 4484 1.45 reinoud nobody_uid = ump->mount_args.nobody_uid; 4485 1.45 reinoud nobody_gid = ump->mount_args.nobody_gid; 4486 1.76 reinoud if (uid == nobody_uid) 4487 1.45 reinoud uid = (uid_t) -1; 4488 1.76 reinoud if (gid == nobody_gid) 4489 1.45 reinoud gid = (gid_t) -1; 4490 1.26 reinoud 4491 1.45 reinoud if (fe) { 4492 1.45 reinoud fe->uid = udf_rw32((uint32_t) uid); 4493 1.45 reinoud fe->gid = udf_rw32((uint32_t) gid); 4494 1.26 reinoud } else { 4495 1.45 reinoud efe->uid = udf_rw32((uint32_t) uid); 4496 1.45 reinoud efe->gid = udf_rw32((uint32_t) gid); 4497 1.26 reinoud } 4498 1.45 reinoud 4499 1.45 reinoud UDF_UNLOCK_NODE(udf_node, 0); 4500 1.26 reinoud } 4501 1.45 reinoud 4502 1.26 reinoud 4503 1.26 reinoud /* --------------------------------------------------------------------- */ 4504 1.26 reinoud 4505 1.59 reinoud 4506 1.120 reinoud int 4507 1.120 reinoud udf_dirhash_fill(struct udf_node *dir_node) 4508 1.1 reinoud { 4509 1.59 reinoud struct vnode *dvp = dir_node->vnode; 4510 1.73 reinoud struct dirhash *dirh; 4511 1.45 reinoud struct file_entry *fe = dir_node->fe; 4512 1.45 reinoud struct extfile_entry *efe = dir_node->efe; 4513 1.45 reinoud struct fileid_desc *fid; 4514 1.45 reinoud struct dirent *dirent; 4515 1.59 reinoud uint64_t file_size, pre_diroffset, diroffset; 4516 1.45 reinoud uint32_t lb_size; 4517 1.59 reinoud int error; 4518 1.59 reinoud 4519 1.66 reinoud /* make sure we have a dirhash to work on */ 4520 1.66 reinoud dirh = dir_node->dir_hash; 4521 1.66 reinoud KASSERT(dirh); 4522 1.66 reinoud KASSERT(dirh->refcnt > 0); 4523 1.66 reinoud 4524 1.73 reinoud if (dirh->flags & DIRH_BROKEN) 4525 1.59 reinoud return EIO; 4526 1.73 reinoud if (dirh->flags & DIRH_COMPLETE) 4527 1.59 reinoud return 0; 4528 1.59 reinoud 4529 1.66 reinoud /* make sure we have a clean dirhash to add to */ 4530 1.73 reinoud dirhash_purge_entries(dirh); 4531 1.45 reinoud 4532 1.45 reinoud /* get directory filesize */ 4533 1.45 reinoud if (fe) { 4534 1.45 reinoud file_size = udf_rw64(fe->inf_len); 4535 1.45 reinoud } else { 4536 1.45 reinoud assert(efe); 4537 1.45 reinoud file_size = udf_rw64(efe->inf_len); 4538 1.45 reinoud } 4539 1.45 reinoud 4540 1.45 reinoud /* allocate temporary space for fid */ 4541 1.45 reinoud lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size); 4542 1.45 reinoud fid = malloc(lb_size, M_UDFTEMP, M_WAITOK); 4543 1.1 reinoud 4544 1.59 reinoud /* allocate temporary space for dirent */ 4545 1.59 reinoud dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK); 4546 1.59 reinoud 4547 1.59 reinoud error = 0; 4548 1.59 reinoud diroffset = 0; 4549 1.59 reinoud while (diroffset < file_size) { 4550 1.59 reinoud /* transfer a new fid/dirent */ 4551 1.59 reinoud pre_diroffset = diroffset; 4552 1.59 reinoud error = udf_read_fid_stream(dvp, &diroffset, fid, dirent); 4553 1.59 reinoud if (error) { 4554 1.59 reinoud /* TODO what to do? continue but not add? */ 4555 1.73 reinoud dirh->flags |= DIRH_BROKEN; 4556 1.73 reinoud dirhash_purge_entries(dirh); 4557 1.59 reinoud break; 4558 1.59 reinoud } 4559 1.1 reinoud 4560 1.59 reinoud if ((fid->file_char & UDF_FILE_CHAR_DEL)) { 4561 1.59 reinoud /* register deleted extent for reuse */ 4562 1.73 reinoud dirhash_enter_freed(dirh, pre_diroffset, 4563 1.59 reinoud udf_fidsize(fid)); 4564 1.59 reinoud } else { 4565 1.59 reinoud /* append to the dirhash */ 4566 1.73 reinoud dirhash_enter(dirh, dirent, pre_diroffset, 4567 1.59 reinoud udf_fidsize(fid), 0); 4568 1.59 reinoud } 4569 1.9 christos } 4570 1.73 reinoud dirh->flags |= DIRH_COMPLETE; 4571 1.59 reinoud 4572 1.59 reinoud free(fid, M_UDFTEMP); 4573 1.59 reinoud free(dirent, M_UDFTEMP); 4574 1.59 reinoud 4575 1.59 reinoud return error; 4576 1.59 reinoud } 4577 1.59 reinoud 4578 1.59 reinoud 4579 1.59 reinoud /* --------------------------------------------------------------------- */ 4580 1.59 reinoud 4581 1.59 reinoud /* 4582 1.59 reinoud * Directory read and manipulation functions. 4583 1.59 reinoud * 4584 1.59 reinoud */ 4585 1.59 reinoud 4586 1.152 skrll int 4587 1.59 reinoud udf_lookup_name_in_dir(struct vnode *vp, const char *name, int namelen, 4588 1.59 reinoud struct long_ad *icb_loc, int *found) 4589 1.59 reinoud { 4590 1.59 reinoud struct udf_node *dir_node = VTOI(vp); 4591 1.73 reinoud struct dirhash *dirh; 4592 1.73 reinoud struct dirhash_entry *dirh_ep; 4593 1.59 reinoud struct fileid_desc *fid; 4594 1.136 reinoud struct dirent *dirent, *s_dirent; 4595 1.136 reinoud struct charspec osta_charspec; 4596 1.59 reinoud uint64_t diroffset; 4597 1.59 reinoud uint32_t lb_size; 4598 1.59 reinoud int hit, error; 4599 1.59 reinoud 4600 1.59 reinoud /* set default return */ 4601 1.59 reinoud *found = 0; 4602 1.59 reinoud 4603 1.66 reinoud /* get our dirhash and make sure its read in */ 4604 1.73 reinoud dirhash_get(&dir_node->dir_hash); 4605 1.120 reinoud error = udf_dirhash_fill(dir_node); 4606 1.66 reinoud if (error) { 4607 1.73 reinoud dirhash_put(dir_node->dir_hash); 4608 1.59 reinoud return error; 4609 1.66 reinoud } 4610 1.73 reinoud dirh = dir_node->dir_hash; 4611 1.1 reinoud 4612 1.59 reinoud /* allocate temporary space for fid */ 4613 1.136 reinoud lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size); 4614 1.136 reinoud fid = malloc(lb_size, M_UDFTEMP, M_WAITOK); 4615 1.136 reinoud dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK); 4616 1.136 reinoud s_dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK); 4617 1.59 reinoud 4618 1.59 reinoud DPRINTF(DIRHASH, ("dirhash_lookup looking for `%*.*s`\n", 4619 1.59 reinoud namelen, namelen, name)); 4620 1.1 reinoud 4621 1.136 reinoud /* convert given unix name to canonical unix name */ 4622 1.136 reinoud udf_osta_charset(&osta_charspec); 4623 1.136 reinoud unix_to_udf_name((char *) fid->data, &fid->l_fi, 4624 1.136 reinoud name, namelen, &osta_charspec); 4625 1.136 reinoud udf_to_unix_name(s_dirent->d_name, NAME_MAX, 4626 1.136 reinoud (char *) fid->data, fid->l_fi, 4627 1.136 reinoud &osta_charspec); 4628 1.136 reinoud s_dirent->d_namlen = strlen(s_dirent->d_name); 4629 1.136 reinoud 4630 1.59 reinoud /* search our dirhash hits */ 4631 1.59 reinoud memset(icb_loc, 0, sizeof(*icb_loc)); 4632 1.59 reinoud dirh_ep = NULL; 4633 1.59 reinoud for (;;) { 4634 1.136 reinoud hit = dirhash_lookup(dirh, s_dirent->d_name, s_dirent->d_namlen, &dirh_ep); 4635 1.59 reinoud /* if no hit, abort the search */ 4636 1.59 reinoud if (!hit) 4637 1.59 reinoud break; 4638 1.1 reinoud 4639 1.59 reinoud /* check this hit */ 4640 1.59 reinoud diroffset = dirh_ep->offset; 4641 1.1 reinoud 4642 1.45 reinoud /* transfer a new fid/dirent */ 4643 1.45 reinoud error = udf_read_fid_stream(vp, &diroffset, fid, dirent); 4644 1.1 reinoud if (error) 4645 1.1 reinoud break; 4646 1.1 reinoud 4647 1.59 reinoud DPRINTF(DIRHASH, ("dirhash_lookup\tchecking `%*.*s`\n", 4648 1.59 reinoud dirent->d_namlen, dirent->d_namlen, dirent->d_name)); 4649 1.1 reinoud 4650 1.59 reinoud /* see if its our entry */ 4651 1.136 reinoud if (strncmp(dirent->d_name, s_dirent->d_name, s_dirent->d_namlen) == 0) { 4652 1.59 reinoud *found = 1; 4653 1.59 reinoud *icb_loc = fid->icb; 4654 1.45 reinoud break; 4655 1.9 christos } 4656 1.45 reinoud } 4657 1.45 reinoud free(fid, M_UDFTEMP); 4658 1.45 reinoud free(dirent, M_UDFTEMP); 4659 1.136 reinoud free(s_dirent, M_UDFTEMP); 4660 1.1 reinoud 4661 1.73 reinoud dirhash_put(dir_node->dir_hash); 4662 1.66 reinoud 4663 1.59 reinoud return error; 4664 1.45 reinoud } 4665 1.1 reinoud 4666 1.45 reinoud /* --------------------------------------------------------------------- */ 4667 1.1 reinoud 4668 1.45 reinoud static int 4669 1.45 reinoud udf_create_new_fe(struct udf_mount *ump, struct file_entry *fe, int file_type, 4670 1.45 reinoud struct long_ad *node_icb, struct long_ad *parent_icb, 4671 1.45 reinoud uint64_t parent_unique_id) 4672 1.45 reinoud { 4673 1.45 reinoud struct timespec now; 4674 1.45 reinoud struct icb_tag *icb; 4675 1.51 reinoud struct filetimes_extattr_entry *ft_extattr; 4676 1.45 reinoud uint64_t unique_id; 4677 1.45 reinoud uint32_t fidsize, lb_num; 4678 1.51 reinoud uint8_t *bpos; 4679 1.51 reinoud int crclen, attrlen; 4680 1.45 reinoud 4681 1.45 reinoud lb_num = udf_rw32(node_icb->loc.lb_num); 4682 1.45 reinoud udf_inittag(ump, &fe->tag, TAGID_FENTRY, lb_num); 4683 1.45 reinoud icb = &fe->icbtag; 4684 1.1 reinoud 4685 1.1 reinoud /* 4686 1.170 andvar * Always use strategy type 4 unless on WORM which we don't support 4687 1.45 reinoud * (yet). Fill in defaults and set for internal allocation of data. 4688 1.1 reinoud */ 4689 1.45 reinoud icb->strat_type = udf_rw16(4); 4690 1.45 reinoud icb->max_num_entries = udf_rw16(1); 4691 1.45 reinoud icb->file_type = file_type; /* 8 bit */ 4692 1.45 reinoud icb->flags = udf_rw16(UDF_ICB_INTERN_ALLOC); 4693 1.45 reinoud 4694 1.45 reinoud fe->perm = udf_rw32(0x7fff); /* all is allowed */ 4695 1.45 reinoud fe->link_cnt = udf_rw16(0); /* explicit setting */ 4696 1.1 reinoud 4697 1.45 reinoud fe->ckpoint = udf_rw32(1); /* user supplied file version */ 4698 1.45 reinoud 4699 1.45 reinoud vfs_timestamp(&now); 4700 1.45 reinoud udf_timespec_to_timestamp(&now, &fe->atime); 4701 1.45 reinoud udf_timespec_to_timestamp(&now, &fe->attrtime); 4702 1.45 reinoud udf_timespec_to_timestamp(&now, &fe->mtime); 4703 1.1 reinoud 4704 1.45 reinoud udf_set_regid(&fe->imp_id, IMPL_NAME); 4705 1.45 reinoud udf_add_impl_regid(ump, &fe->imp_id); 4706 1.1 reinoud 4707 1.45 reinoud unique_id = udf_advance_uniqueid(ump); 4708 1.45 reinoud fe->unique_id = udf_rw64(unique_id); 4709 1.51 reinoud fe->l_ea = udf_rw32(0); 4710 1.51 reinoud 4711 1.51 reinoud /* create extended attribute to record our creation time */ 4712 1.51 reinoud attrlen = UDF_FILETIMES_ATTR_SIZE(1); 4713 1.51 reinoud ft_extattr = malloc(attrlen, M_UDFTEMP, M_WAITOK); 4714 1.51 reinoud memset(ft_extattr, 0, attrlen); 4715 1.51 reinoud ft_extattr->hdr.type = udf_rw32(UDF_FILETIMES_ATTR_NO); 4716 1.51 reinoud ft_extattr->hdr.subtype = 1; /* [4/48.10.5] */ 4717 1.51 reinoud ft_extattr->hdr.a_l = udf_rw32(UDF_FILETIMES_ATTR_SIZE(1)); 4718 1.51 reinoud ft_extattr->d_l = udf_rw32(UDF_TIMESTAMP_SIZE); /* one item */ 4719 1.51 reinoud ft_extattr->existence = UDF_FILETIMES_FILE_CREATION; 4720 1.51 reinoud udf_timespec_to_timestamp(&now, &ft_extattr->times[0]); 4721 1.51 reinoud 4722 1.51 reinoud udf_extattr_insert_internal(ump, (union dscrptr *) fe, 4723 1.51 reinoud (struct extattr_entry *) ft_extattr); 4724 1.51 reinoud free(ft_extattr, M_UDFTEMP); 4725 1.1 reinoud 4726 1.51 reinoud /* if its a directory, create '..' */ 4727 1.51 reinoud bpos = (uint8_t *) fe->data + udf_rw32(fe->l_ea); 4728 1.45 reinoud fidsize = 0; 4729 1.45 reinoud if (file_type == UDF_ICB_FILETYPE_DIRECTORY) { 4730 1.45 reinoud fidsize = udf_create_parentfid(ump, 4731 1.51 reinoud (struct fileid_desc *) bpos, parent_icb, 4732 1.45 reinoud parent_unique_id); 4733 1.9 christos } 4734 1.1 reinoud 4735 1.45 reinoud /* record fidlength information */ 4736 1.45 reinoud fe->inf_len = udf_rw64(fidsize); 4737 1.45 reinoud fe->l_ad = udf_rw32(fidsize); 4738 1.45 reinoud fe->logblks_rec = udf_rw64(0); /* intern */ 4739 1.45 reinoud 4740 1.45 reinoud crclen = sizeof(struct file_entry) - 1 - UDF_DESC_TAG_LENGTH; 4741 1.51 reinoud crclen += udf_rw32(fe->l_ea) + fidsize; 4742 1.45 reinoud fe->tag.desc_crc_len = udf_rw16(crclen); 4743 1.1 reinoud 4744 1.45 reinoud (void) udf_validate_tag_and_crc_sums((union dscrptr *) fe); 4745 1.1 reinoud 4746 1.45 reinoud return fidsize; 4747 1.1 reinoud } 4748 1.1 reinoud 4749 1.1 reinoud /* --------------------------------------------------------------------- */ 4750 1.1 reinoud 4751 1.45 reinoud static int 4752 1.45 reinoud udf_create_new_efe(struct udf_mount *ump, struct extfile_entry *efe, 4753 1.45 reinoud int file_type, struct long_ad *node_icb, struct long_ad *parent_icb, 4754 1.45 reinoud uint64_t parent_unique_id) 4755 1.45 reinoud { 4756 1.45 reinoud struct timespec now; 4757 1.45 reinoud struct icb_tag *icb; 4758 1.45 reinoud uint64_t unique_id; 4759 1.45 reinoud uint32_t fidsize, lb_num; 4760 1.51 reinoud uint8_t *bpos; 4761 1.45 reinoud int crclen; 4762 1.45 reinoud 4763 1.45 reinoud lb_num = udf_rw32(node_icb->loc.lb_num); 4764 1.45 reinoud udf_inittag(ump, &efe->tag, TAGID_EXTFENTRY, lb_num); 4765 1.45 reinoud icb = &efe->icbtag; 4766 1.45 reinoud 4767 1.45 reinoud /* 4768 1.170 andvar * Always use strategy type 4 unless on WORM which we don't support 4769 1.45 reinoud * (yet). Fill in defaults and set for internal allocation of data. 4770 1.45 reinoud */ 4771 1.45 reinoud icb->strat_type = udf_rw16(4); 4772 1.45 reinoud icb->max_num_entries = udf_rw16(1); 4773 1.45 reinoud icb->file_type = file_type; /* 8 bit */ 4774 1.45 reinoud icb->flags = udf_rw16(UDF_ICB_INTERN_ALLOC); 4775 1.1 reinoud 4776 1.45 reinoud efe->perm = udf_rw32(0x7fff); /* all is allowed */ 4777 1.45 reinoud efe->link_cnt = udf_rw16(0); /* explicit setting */ 4778 1.1 reinoud 4779 1.45 reinoud efe->ckpoint = udf_rw32(1); /* user supplied file version */ 4780 1.1 reinoud 4781 1.45 reinoud vfs_timestamp(&now); 4782 1.45 reinoud udf_timespec_to_timestamp(&now, &efe->ctime); 4783 1.45 reinoud udf_timespec_to_timestamp(&now, &efe->atime); 4784 1.45 reinoud udf_timespec_to_timestamp(&now, &efe->attrtime); 4785 1.45 reinoud udf_timespec_to_timestamp(&now, &efe->mtime); 4786 1.26 reinoud 4787 1.45 reinoud udf_set_regid(&efe->imp_id, IMPL_NAME); 4788 1.45 reinoud udf_add_impl_regid(ump, &efe->imp_id); 4789 1.1 reinoud 4790 1.45 reinoud unique_id = udf_advance_uniqueid(ump); 4791 1.45 reinoud efe->unique_id = udf_rw64(unique_id); 4792 1.51 reinoud efe->l_ea = udf_rw32(0); 4793 1.1 reinoud 4794 1.51 reinoud /* if its a directory, create '..' */ 4795 1.51 reinoud bpos = (uint8_t *) efe->data + udf_rw32(efe->l_ea); 4796 1.45 reinoud fidsize = 0; 4797 1.45 reinoud if (file_type == UDF_ICB_FILETYPE_DIRECTORY) { 4798 1.45 reinoud fidsize = udf_create_parentfid(ump, 4799 1.51 reinoud (struct fileid_desc *) bpos, parent_icb, 4800 1.45 reinoud parent_unique_id); 4801 1.45 reinoud } 4802 1.1 reinoud 4803 1.45 reinoud /* record fidlength information */ 4804 1.45 reinoud efe->obj_size = udf_rw64(fidsize); 4805 1.45 reinoud efe->inf_len = udf_rw64(fidsize); 4806 1.45 reinoud efe->l_ad = udf_rw32(fidsize); 4807 1.45 reinoud efe->logblks_rec = udf_rw64(0); /* intern */ 4808 1.1 reinoud 4809 1.45 reinoud crclen = sizeof(struct extfile_entry) - 1 - UDF_DESC_TAG_LENGTH; 4810 1.51 reinoud crclen += udf_rw32(efe->l_ea) + fidsize; 4811 1.45 reinoud efe->tag.desc_crc_len = udf_rw16(crclen); 4812 1.1 reinoud 4813 1.45 reinoud (void) udf_validate_tag_and_crc_sums((union dscrptr *) efe); 4814 1.1 reinoud 4815 1.45 reinoud return fidsize; 4816 1.1 reinoud } 4817 1.1 reinoud 4818 1.1 reinoud /* --------------------------------------------------------------------- */ 4819 1.1 reinoud 4820 1.45 reinoud int 4821 1.45 reinoud udf_dir_detach(struct udf_mount *ump, struct udf_node *dir_node, 4822 1.45 reinoud struct udf_node *udf_node, struct componentname *cnp) 4823 1.1 reinoud { 4824 1.59 reinoud struct vnode *dvp = dir_node->vnode; 4825 1.73 reinoud struct dirhash *dirh; 4826 1.73 reinoud struct dirhash_entry *dirh_ep; 4827 1.45 reinoud struct file_entry *fe = dir_node->fe; 4828 1.45 reinoud struct fileid_desc *fid; 4829 1.136 reinoud struct dirent *dirent, *s_dirent; 4830 1.136 reinoud struct charspec osta_charspec; 4831 1.121 christos uint64_t diroffset; 4832 1.45 reinoud uint32_t lb_size, fidsize; 4833 1.45 reinoud int found, error; 4834 1.59 reinoud int hit, refcnt; 4835 1.1 reinoud 4836 1.66 reinoud /* get our dirhash and make sure its read in */ 4837 1.73 reinoud dirhash_get(&dir_node->dir_hash); 4838 1.120 reinoud error = udf_dirhash_fill(dir_node); 4839 1.66 reinoud if (error) { 4840 1.73 reinoud dirhash_put(dir_node->dir_hash); 4841 1.66 reinoud return error; 4842 1.66 reinoud } 4843 1.73 reinoud dirh = dir_node->dir_hash; 4844 1.66 reinoud 4845 1.45 reinoud /* get directory filesize */ 4846 1.121 christos if (!fe) { 4847 1.122 riz assert(dir_node->efe); 4848 1.45 reinoud } 4849 1.1 reinoud 4850 1.136 reinoud /* allocate temporary space for fid and dirents */ 4851 1.136 reinoud lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size); 4852 1.136 reinoud fid = malloc(lb_size, M_UDFTEMP, M_WAITOK); 4853 1.136 reinoud dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK); 4854 1.136 reinoud s_dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK); 4855 1.136 reinoud 4856 1.136 reinoud /* convert given unix name to canonical unix name */ 4857 1.136 reinoud udf_osta_charset(&osta_charspec); 4858 1.136 reinoud unix_to_udf_name((char *) fid->data, &fid->l_fi, 4859 1.136 reinoud cnp->cn_nameptr, cnp->cn_namelen, &osta_charspec); 4860 1.136 reinoud udf_to_unix_name(s_dirent->d_name, NAME_MAX, 4861 1.136 reinoud (char *) fid->data, fid->l_fi, 4862 1.136 reinoud &osta_charspec); 4863 1.136 reinoud s_dirent->d_namlen = strlen(s_dirent->d_name); 4864 1.1 reinoud 4865 1.59 reinoud /* search our dirhash hits */ 4866 1.45 reinoud found = 0; 4867 1.59 reinoud dirh_ep = NULL; 4868 1.59 reinoud for (;;) { 4869 1.136 reinoud hit = dirhash_lookup(dirh, s_dirent->d_name, s_dirent->d_namlen, &dirh_ep); 4870 1.59 reinoud /* if no hit, abort the search */ 4871 1.59 reinoud if (!hit) 4872 1.59 reinoud break; 4873 1.1 reinoud 4874 1.59 reinoud /* check this hit */ 4875 1.59 reinoud diroffset = dirh_ep->offset; 4876 1.1 reinoud 4877 1.45 reinoud /* transfer a new fid/dirent */ 4878 1.59 reinoud error = udf_read_fid_stream(dvp, &diroffset, fid, dirent); 4879 1.45 reinoud if (error) 4880 1.45 reinoud break; 4881 1.1 reinoud 4882 1.59 reinoud /* see if its our entry */ 4883 1.136 reinoud KASSERT(dirent->d_namlen == s_dirent->d_namlen); 4884 1.136 reinoud if (strncmp(dirent->d_name, s_dirent->d_name, s_dirent->d_namlen) == 0) { 4885 1.59 reinoud found = 1; 4886 1.45 reinoud break; 4887 1.45 reinoud } 4888 1.45 reinoud } 4889 1.59 reinoud 4890 1.59 reinoud if (!found) 4891 1.59 reinoud error = ENOENT; 4892 1.59 reinoud if (error) 4893 1.59 reinoud goto error_out; 4894 1.1 reinoud 4895 1.45 reinoud /* mark deleted */ 4896 1.45 reinoud fid->file_char |= UDF_FILE_CHAR_DEL; 4897 1.45 reinoud #ifdef UDF_COMPLETE_DELETE 4898 1.45 reinoud memset(&fid->icb, 0, sizeof(fid->icb)); 4899 1.45 reinoud #endif 4900 1.45 reinoud (void) udf_validate_tag_and_crc_sums((union dscrptr *) fid); 4901 1.1 reinoud 4902 1.59 reinoud /* get size of fid and compensate for the read_fid_stream advance */ 4903 1.45 reinoud fidsize = udf_fidsize(fid); 4904 1.45 reinoud diroffset -= fidsize; 4905 1.45 reinoud 4906 1.45 reinoud /* write out */ 4907 1.45 reinoud error = vn_rdwr(UIO_WRITE, dir_node->vnode, 4908 1.152 skrll fid, fidsize, diroffset, 4909 1.45 reinoud UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, 4910 1.45 reinoud FSCRED, NULL, NULL); 4911 1.59 reinoud if (error) 4912 1.59 reinoud goto error_out; 4913 1.59 reinoud 4914 1.59 reinoud /* get reference count of attached node */ 4915 1.59 reinoud if (udf_node->fe) { 4916 1.59 reinoud refcnt = udf_rw16(udf_node->fe->link_cnt); 4917 1.59 reinoud } else { 4918 1.59 reinoud KASSERT(udf_node->efe); 4919 1.59 reinoud refcnt = udf_rw16(udf_node->efe->link_cnt); 4920 1.59 reinoud } 4921 1.45 reinoud #ifdef UDF_COMPLETE_DELETE 4922 1.175 andvar /* subtract reference counter in attached node */ 4923 1.59 reinoud refcnt -= 1; 4924 1.59 reinoud if (udf_node->fe) { 4925 1.59 reinoud udf_node->fe->link_cnt = udf_rw16(refcnt); 4926 1.59 reinoud } else { 4927 1.59 reinoud udf_node->efe->link_cnt = udf_rw16(refcnt); 4928 1.59 reinoud } 4929 1.59 reinoud 4930 1.59 reinoud /* prevent writeout when refcnt == 0 */ 4931 1.59 reinoud if (refcnt == 0) 4932 1.59 reinoud udf_node->i_flags |= IN_DELETED; 4933 1.59 reinoud 4934 1.59 reinoud if (fid->file_char & UDF_FILE_CHAR_DIR) { 4935 1.59 reinoud int drefcnt; 4936 1.59 reinoud 4937 1.175 andvar /* subtract reference counter in directory node */ 4938 1.59 reinoud /* note subtract 2 (?) for its was also backreferenced */ 4939 1.59 reinoud if (dir_node->fe) { 4940 1.59 reinoud drefcnt = udf_rw16(dir_node->fe->link_cnt); 4941 1.59 reinoud drefcnt -= 1; 4942 1.59 reinoud dir_node->fe->link_cnt = udf_rw16(drefcnt); 4943 1.45 reinoud } else { 4944 1.59 reinoud KASSERT(dir_node->efe); 4945 1.59 reinoud drefcnt = udf_rw16(dir_node->efe->link_cnt); 4946 1.59 reinoud drefcnt -= 1; 4947 1.59 reinoud dir_node->efe->link_cnt = udf_rw16(drefcnt); 4948 1.45 reinoud } 4949 1.59 reinoud } 4950 1.1 reinoud 4951 1.59 reinoud udf_node->i_flags |= IN_MODIFIED; 4952 1.59 reinoud dir_node->i_flags |= IN_MODIFIED; 4953 1.45 reinoud #endif 4954 1.59 reinoud /* if it is/was a hardlink adjust the file count */ 4955 1.59 reinoud if (refcnt > 0) 4956 1.59 reinoud udf_adjust_filecount(udf_node, -1); 4957 1.59 reinoud 4958 1.59 reinoud /* remove from the dirhash */ 4959 1.73 reinoud dirhash_remove(dirh, dirent, diroffset, 4960 1.59 reinoud udf_fidsize(fid)); 4961 1.1 reinoud 4962 1.59 reinoud error_out: 4963 1.45 reinoud free(fid, M_UDFTEMP); 4964 1.45 reinoud free(dirent, M_UDFTEMP); 4965 1.136 reinoud free(s_dirent, M_UDFTEMP); 4966 1.1 reinoud 4967 1.73 reinoud dirhash_put(dir_node->dir_hash); 4968 1.66 reinoud 4969 1.45 reinoud return error; 4970 1.1 reinoud } 4971 1.1 reinoud 4972 1.1 reinoud /* --------------------------------------------------------------------- */ 4973 1.1 reinoud 4974 1.94 reinoud int 4975 1.94 reinoud udf_dir_update_rootentry(struct udf_mount *ump, struct udf_node *dir_node, 4976 1.94 reinoud struct udf_node *new_parent_node) 4977 1.94 reinoud { 4978 1.94 reinoud struct vnode *dvp = dir_node->vnode; 4979 1.94 reinoud struct dirhash *dirh; 4980 1.94 reinoud struct dirhash_entry *dirh_ep; 4981 1.94 reinoud struct file_entry *fe; 4982 1.94 reinoud struct extfile_entry *efe; 4983 1.94 reinoud struct fileid_desc *fid; 4984 1.94 reinoud struct dirent *dirent; 4985 1.121 christos uint64_t diroffset; 4986 1.94 reinoud uint64_t new_parent_unique_id; 4987 1.94 reinoud uint32_t lb_size, fidsize; 4988 1.94 reinoud int found, error; 4989 1.94 reinoud char const *name = ".."; 4990 1.94 reinoud int namelen = 2; 4991 1.94 reinoud int hit; 4992 1.94 reinoud 4993 1.94 reinoud /* get our dirhash and make sure its read in */ 4994 1.94 reinoud dirhash_get(&dir_node->dir_hash); 4995 1.120 reinoud error = udf_dirhash_fill(dir_node); 4996 1.94 reinoud if (error) { 4997 1.94 reinoud dirhash_put(dir_node->dir_hash); 4998 1.94 reinoud return error; 4999 1.94 reinoud } 5000 1.94 reinoud dirh = dir_node->dir_hash; 5001 1.94 reinoud 5002 1.94 reinoud /* get new parent's unique ID */ 5003 1.94 reinoud fe = new_parent_node->fe; 5004 1.94 reinoud efe = new_parent_node->efe; 5005 1.94 reinoud if (fe) { 5006 1.94 reinoud new_parent_unique_id = udf_rw64(fe->unique_id); 5007 1.94 reinoud } else { 5008 1.94 reinoud assert(efe); 5009 1.94 reinoud new_parent_unique_id = udf_rw64(efe->unique_id); 5010 1.94 reinoud } 5011 1.94 reinoud 5012 1.94 reinoud /* get directory filesize */ 5013 1.94 reinoud fe = dir_node->fe; 5014 1.94 reinoud efe = dir_node->efe; 5015 1.121 christos if (!fe) { 5016 1.94 reinoud assert(efe); 5017 1.94 reinoud } 5018 1.94 reinoud 5019 1.94 reinoud /* allocate temporary space for fid */ 5020 1.94 reinoud lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size); 5021 1.94 reinoud fid = malloc(lb_size, M_UDFTEMP, M_WAITOK); 5022 1.94 reinoud dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK); 5023 1.94 reinoud 5024 1.94 reinoud /* 5025 1.94 reinoud * NOTE the standard does not dictate the FID entry '..' should be 5026 1.94 reinoud * first, though in practice it will most likely be. 5027 1.94 reinoud */ 5028 1.94 reinoud 5029 1.94 reinoud /* search our dirhash hits */ 5030 1.94 reinoud found = 0; 5031 1.94 reinoud dirh_ep = NULL; 5032 1.94 reinoud for (;;) { 5033 1.94 reinoud hit = dirhash_lookup(dirh, name, namelen, &dirh_ep); 5034 1.94 reinoud /* if no hit, abort the search */ 5035 1.94 reinoud if (!hit) 5036 1.94 reinoud break; 5037 1.94 reinoud 5038 1.94 reinoud /* check this hit */ 5039 1.94 reinoud diroffset = dirh_ep->offset; 5040 1.94 reinoud 5041 1.94 reinoud /* transfer a new fid/dirent */ 5042 1.94 reinoud error = udf_read_fid_stream(dvp, &diroffset, fid, dirent); 5043 1.94 reinoud if (error) 5044 1.94 reinoud break; 5045 1.94 reinoud 5046 1.94 reinoud /* see if its our entry */ 5047 1.94 reinoud KASSERT(dirent->d_namlen == namelen); 5048 1.94 reinoud if (strncmp(dirent->d_name, name, namelen) == 0) { 5049 1.94 reinoud found = 1; 5050 1.94 reinoud break; 5051 1.94 reinoud } 5052 1.94 reinoud } 5053 1.94 reinoud 5054 1.94 reinoud if (!found) 5055 1.94 reinoud error = ENOENT; 5056 1.94 reinoud if (error) 5057 1.94 reinoud goto error_out; 5058 1.94 reinoud 5059 1.94 reinoud /* update our ICB to the new parent, hit of lower 32 bits of uniqueid */ 5060 1.94 reinoud fid->icb = new_parent_node->write_loc; 5061 1.94 reinoud fid->icb.longad_uniqueid = udf_rw32(new_parent_unique_id); 5062 1.94 reinoud 5063 1.94 reinoud (void) udf_validate_tag_and_crc_sums((union dscrptr *) fid); 5064 1.94 reinoud 5065 1.94 reinoud /* get size of fid and compensate for the read_fid_stream advance */ 5066 1.94 reinoud fidsize = udf_fidsize(fid); 5067 1.94 reinoud diroffset -= fidsize; 5068 1.94 reinoud 5069 1.94 reinoud /* write out */ 5070 1.94 reinoud error = vn_rdwr(UIO_WRITE, dir_node->vnode, 5071 1.152 skrll fid, fidsize, diroffset, 5072 1.94 reinoud UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, 5073 1.94 reinoud FSCRED, NULL, NULL); 5074 1.94 reinoud 5075 1.94 reinoud /* nothing to be done in the dirhash */ 5076 1.94 reinoud 5077 1.94 reinoud error_out: 5078 1.94 reinoud free(fid, M_UDFTEMP); 5079 1.94 reinoud free(dirent, M_UDFTEMP); 5080 1.94 reinoud 5081 1.94 reinoud dirhash_put(dir_node->dir_hash); 5082 1.94 reinoud 5083 1.94 reinoud return error; 5084 1.94 reinoud } 5085 1.94 reinoud 5086 1.94 reinoud /* --------------------------------------------------------------------- */ 5087 1.94 reinoud 5088 1.45 reinoud /* 5089 1.45 reinoud * We are not allowed to split the fid tag itself over an logical block so 5090 1.45 reinoud * check the space remaining in the logical block. 5091 1.45 reinoud * 5092 1.45 reinoud * We try to select the smallest candidate for recycling or when none is 5093 1.45 reinoud * found, append a new one at the end of the directory. 5094 1.45 reinoud */ 5095 1.45 reinoud 5096 1.1 reinoud int 5097 1.45 reinoud udf_dir_attach(struct udf_mount *ump, struct udf_node *dir_node, 5098 1.45 reinoud struct udf_node *udf_node, struct vattr *vap, struct componentname *cnp) 5099 1.1 reinoud { 5100 1.45 reinoud struct vnode *dvp = dir_node->vnode; 5101 1.73 reinoud struct dirhash *dirh; 5102 1.73 reinoud struct dirhash_entry *dirh_ep; 5103 1.45 reinoud struct fileid_desc *fid; 5104 1.45 reinoud struct icb_tag *icbtag; 5105 1.45 reinoud struct charspec osta_charspec; 5106 1.45 reinoud struct dirent dirent; 5107 1.74 reinoud uint64_t unique_id, dir_size; 5108 1.45 reinoud uint64_t fid_pos, end_fid_pos, chosen_fid_pos; 5109 1.45 reinoud uint32_t chosen_size, chosen_size_diff; 5110 1.45 reinoud int lb_size, lb_rest, fidsize, this_fidsize, size_diff; 5111 1.59 reinoud int file_char, refcnt, icbflags, addr_type, hit, error; 5112 1.45 reinoud 5113 1.66 reinoud /* get our dirhash and make sure its read in */ 5114 1.73 reinoud dirhash_get(&dir_node->dir_hash); 5115 1.120 reinoud error = udf_dirhash_fill(dir_node); 5116 1.66 reinoud if (error) { 5117 1.73 reinoud dirhash_put(dir_node->dir_hash); 5118 1.66 reinoud return error; 5119 1.66 reinoud } 5120 1.73 reinoud dirh = dir_node->dir_hash; 5121 1.66 reinoud 5122 1.66 reinoud /* get info */ 5123 1.45 reinoud lb_size = udf_rw32(ump->logical_vol->lb_size); 5124 1.45 reinoud udf_osta_charset(&osta_charspec); 5125 1.45 reinoud 5126 1.45 reinoud if (dir_node->fe) { 5127 1.45 reinoud dir_size = udf_rw64(dir_node->fe->inf_len); 5128 1.59 reinoud icbtag = &dir_node->fe->icbtag; 5129 1.45 reinoud } else { 5130 1.45 reinoud dir_size = udf_rw64(dir_node->efe->inf_len); 5131 1.59 reinoud icbtag = &dir_node->efe->icbtag; 5132 1.45 reinoud } 5133 1.1 reinoud 5134 1.45 reinoud icbflags = udf_rw16(icbtag->flags); 5135 1.45 reinoud addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 5136 1.1 reinoud 5137 1.45 reinoud if (udf_node->fe) { 5138 1.45 reinoud unique_id = udf_rw64(udf_node->fe->unique_id); 5139 1.59 reinoud refcnt = udf_rw16(udf_node->fe->link_cnt); 5140 1.45 reinoud } else { 5141 1.45 reinoud unique_id = udf_rw64(udf_node->efe->unique_id); 5142 1.59 reinoud refcnt = udf_rw16(udf_node->efe->link_cnt); 5143 1.45 reinoud } 5144 1.1 reinoud 5145 1.45 reinoud if (refcnt > 0) { 5146 1.45 reinoud unique_id = udf_advance_uniqueid(ump); 5147 1.45 reinoud udf_adjust_filecount(udf_node, 1); 5148 1.9 christos } 5149 1.1 reinoud 5150 1.45 reinoud /* determine file characteristics */ 5151 1.45 reinoud file_char = 0; /* visible non deleted file and not stream metadata */ 5152 1.45 reinoud if (vap->va_type == VDIR) 5153 1.45 reinoud file_char = UDF_FILE_CHAR_DIR; 5154 1.45 reinoud 5155 1.45 reinoud /* malloc scrap buffer */ 5156 1.83 cegger fid = malloc(lb_size, M_TEMP, M_WAITOK|M_ZERO); 5157 1.45 reinoud 5158 1.45 reinoud /* calculate _minimum_ fid size */ 5159 1.45 reinoud unix_to_udf_name((char *) fid->data, &fid->l_fi, 5160 1.45 reinoud cnp->cn_nameptr, cnp->cn_namelen, &osta_charspec); 5161 1.45 reinoud fidsize = UDF_FID_SIZE + fid->l_fi; 5162 1.45 reinoud fidsize = (fidsize + 3) & ~3; /* multiple of 4 */ 5163 1.1 reinoud 5164 1.45 reinoud /* find position that will fit the FID */ 5165 1.59 reinoud chosen_fid_pos = dir_size; 5166 1.45 reinoud chosen_size = 0; 5167 1.45 reinoud chosen_size_diff = UINT_MAX; 5168 1.1 reinoud 5169 1.59 reinoud /* shut up gcc */ 5170 1.59 reinoud dirent.d_namlen = 0; 5171 1.59 reinoud 5172 1.59 reinoud /* search our dirhash hits */ 5173 1.59 reinoud error = 0; 5174 1.59 reinoud dirh_ep = NULL; 5175 1.45 reinoud for (;;) { 5176 1.73 reinoud hit = dirhash_lookup_freed(dirh, fidsize, &dirh_ep); 5177 1.59 reinoud /* if no hit, abort the search */ 5178 1.59 reinoud if (!hit) 5179 1.45 reinoud break; 5180 1.1 reinoud 5181 1.59 reinoud /* check this hit for size */ 5182 1.73 reinoud this_fidsize = dirh_ep->entry_size; 5183 1.1 reinoud 5184 1.59 reinoud /* check this hit */ 5185 1.59 reinoud fid_pos = dirh_ep->offset; 5186 1.59 reinoud end_fid_pos = fid_pos + this_fidsize; 5187 1.59 reinoud size_diff = this_fidsize - fidsize; 5188 1.59 reinoud lb_rest = lb_size - (end_fid_pos % lb_size); 5189 1.45 reinoud 5190 1.45 reinoud #ifndef UDF_COMPLETE_DELETE 5191 1.59 reinoud /* transfer a new fid/dirent */ 5192 1.59 reinoud error = udf_read_fid_stream(vp, &fid_pos, fid, dirent); 5193 1.59 reinoud if (error) 5194 1.59 reinoud goto error_out; 5195 1.59 reinoud 5196 1.59 reinoud /* only reuse entries that are wiped */ 5197 1.59 reinoud /* check if the len + loc are marked zero */ 5198 1.88 reinoud if (udf_rw32(fid->icb.len) != 0) 5199 1.59 reinoud continue; 5200 1.59 reinoud if (udf_rw32(fid->icb.loc.lb_num) != 0) 5201 1.59 reinoud continue; 5202 1.88 reinoud if (udf_rw16(fid->icb.loc.part_num) != 0) 5203 1.59 reinoud continue; 5204 1.59 reinoud #endif /* UDF_COMPLETE_DELETE */ 5205 1.59 reinoud 5206 1.59 reinoud /* select if not splitting the tag and its smaller */ 5207 1.59 reinoud if ((size_diff >= 0) && 5208 1.59 reinoud (size_diff < chosen_size_diff) && 5209 1.59 reinoud (lb_rest >= sizeof(struct desc_tag))) 5210 1.59 reinoud { 5211 1.59 reinoud /* UDF 2.3.4.2+3 specifies rules for iu size */ 5212 1.59 reinoud if ((size_diff == 0) || (size_diff >= 32)) { 5213 1.59 reinoud chosen_fid_pos = fid_pos; 5214 1.59 reinoud chosen_size = this_fidsize; 5215 1.59 reinoud chosen_size_diff = size_diff; 5216 1.45 reinoud } 5217 1.45 reinoud } 5218 1.59 reinoud } 5219 1.1 reinoud 5220 1.1 reinoud 5221 1.45 reinoud /* extend directory if no other candidate found */ 5222 1.45 reinoud if (chosen_size == 0) { 5223 1.45 reinoud chosen_fid_pos = dir_size; 5224 1.45 reinoud chosen_size = fidsize; 5225 1.45 reinoud chosen_size_diff = 0; 5226 1.1 reinoud 5227 1.45 reinoud /* special case UDF 2.00+ 2.3.4.4, no splitting up fid tag */ 5228 1.45 reinoud if (addr_type == UDF_ICB_INTERN_ALLOC) { 5229 1.45 reinoud /* pre-grow directory to see if we're to switch */ 5230 1.45 reinoud udf_grow_node(dir_node, dir_size + chosen_size); 5231 1.1 reinoud 5232 1.45 reinoud icbflags = udf_rw16(icbtag->flags); 5233 1.45 reinoud addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 5234 1.45 reinoud } 5235 1.1 reinoud 5236 1.156 andvar /* make sure the next fid desc_tag won't be split */ 5237 1.45 reinoud if (addr_type != UDF_ICB_INTERN_ALLOC) { 5238 1.45 reinoud end_fid_pos = chosen_fid_pos + chosen_size; 5239 1.45 reinoud lb_rest = lb_size - (end_fid_pos % lb_size); 5240 1.1 reinoud 5241 1.45 reinoud /* pad with implementation use regid if needed */ 5242 1.45 reinoud if (lb_rest < sizeof(struct desc_tag)) 5243 1.45 reinoud chosen_size += 32; 5244 1.45 reinoud } 5245 1.1 reinoud } 5246 1.45 reinoud chosen_size_diff = chosen_size - fidsize; 5247 1.45 reinoud 5248 1.45 reinoud /* populate the FID */ 5249 1.45 reinoud memset(fid, 0, lb_size); 5250 1.45 reinoud udf_inittag(ump, &fid->tag, TAGID_FID, 0); 5251 1.45 reinoud fid->file_version_num = udf_rw16(1); /* UDF 2.3.4.1 */ 5252 1.45 reinoud fid->file_char = file_char; 5253 1.45 reinoud fid->icb = udf_node->loc; 5254 1.45 reinoud fid->icb.longad_uniqueid = udf_rw32((uint32_t) unique_id); 5255 1.45 reinoud fid->l_iu = udf_rw16(0); 5256 1.45 reinoud 5257 1.45 reinoud if (chosen_size > fidsize) { 5258 1.45 reinoud /* insert implementation-use regid to space it correctly */ 5259 1.45 reinoud fid->l_iu = udf_rw16(chosen_size_diff); 5260 1.45 reinoud 5261 1.45 reinoud /* set implementation use */ 5262 1.45 reinoud udf_set_regid((struct regid *) fid->data, IMPL_NAME); 5263 1.45 reinoud udf_add_impl_regid(ump, (struct regid *) fid->data); 5264 1.45 reinoud } 5265 1.45 reinoud 5266 1.45 reinoud /* fill in name */ 5267 1.45 reinoud unix_to_udf_name((char *) fid->data + udf_rw16(fid->l_iu), 5268 1.45 reinoud &fid->l_fi, cnp->cn_nameptr, cnp->cn_namelen, &osta_charspec); 5269 1.45 reinoud 5270 1.88 reinoud fid->tag.desc_crc_len = udf_rw16(chosen_size - UDF_DESC_TAG_LENGTH); 5271 1.45 reinoud (void) udf_validate_tag_and_crc_sums((union dscrptr *) fid); 5272 1.45 reinoud 5273 1.45 reinoud /* writeout FID/update parent directory */ 5274 1.45 reinoud error = vn_rdwr(UIO_WRITE, dvp, 5275 1.152 skrll fid, chosen_size, chosen_fid_pos, 5276 1.45 reinoud UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, 5277 1.45 reinoud FSCRED, NULL, NULL); 5278 1.45 reinoud 5279 1.59 reinoud if (error) 5280 1.59 reinoud goto error_out; 5281 1.45 reinoud 5282 1.45 reinoud /* add reference counter in attached node */ 5283 1.45 reinoud if (udf_node->fe) { 5284 1.45 reinoud refcnt = udf_rw16(udf_node->fe->link_cnt); 5285 1.45 reinoud udf_node->fe->link_cnt = udf_rw16(refcnt+1); 5286 1.45 reinoud } else { 5287 1.45 reinoud KASSERT(udf_node->efe); 5288 1.45 reinoud refcnt = udf_rw16(udf_node->efe->link_cnt); 5289 1.45 reinoud udf_node->efe->link_cnt = udf_rw16(refcnt+1); 5290 1.45 reinoud } 5291 1.45 reinoud 5292 1.45 reinoud /* mark not deleted if it was... just in case, but do warn */ 5293 1.45 reinoud if (udf_node->i_flags & IN_DELETED) { 5294 1.45 reinoud printf("udf: warning, marking a file undeleted\n"); 5295 1.45 reinoud udf_node->i_flags &= ~IN_DELETED; 5296 1.45 reinoud } 5297 1.45 reinoud 5298 1.45 reinoud if (file_char & UDF_FILE_CHAR_DIR) { 5299 1.45 reinoud /* add reference counter in directory node for '..' */ 5300 1.45 reinoud if (dir_node->fe) { 5301 1.45 reinoud refcnt = udf_rw16(dir_node->fe->link_cnt); 5302 1.45 reinoud refcnt++; 5303 1.45 reinoud dir_node->fe->link_cnt = udf_rw16(refcnt); 5304 1.45 reinoud } else { 5305 1.45 reinoud KASSERT(dir_node->efe); 5306 1.45 reinoud refcnt = udf_rw16(dir_node->efe->link_cnt); 5307 1.45 reinoud refcnt++; 5308 1.45 reinoud dir_node->efe->link_cnt = udf_rw16(refcnt); 5309 1.45 reinoud } 5310 1.1 reinoud } 5311 1.1 reinoud 5312 1.59 reinoud /* append to the dirhash */ 5313 1.110 reinoud /* NOTE do not use dirent anymore or it won't match later! */ 5314 1.117 christos udf_to_unix_name(dirent.d_name, NAME_MAX, 5315 1.110 reinoud (char *) fid->data + udf_rw16(fid->l_iu), fid->l_fi, &osta_charspec); 5316 1.110 reinoud dirent.d_namlen = strlen(dirent.d_name); 5317 1.73 reinoud dirhash_enter(dirh, &dirent, chosen_fid_pos, 5318 1.59 reinoud udf_fidsize(fid), 1); 5319 1.45 reinoud 5320 1.59 reinoud /* note updates */ 5321 1.45 reinoud udf_node->i_flags |= IN_CHANGE | IN_MODIFY; /* | IN_CREATE? */ 5322 1.45 reinoud /* VN_KNOTE(udf_node, ...) */ 5323 1.50 reinoud udf_update(udf_node->vnode, NULL, NULL, NULL, 0); 5324 1.45 reinoud 5325 1.59 reinoud error_out: 5326 1.45 reinoud free(fid, M_TEMP); 5327 1.1 reinoud 5328 1.73 reinoud dirhash_put(dir_node->dir_hash); 5329 1.66 reinoud 5330 1.59 reinoud return error; 5331 1.45 reinoud } 5332 1.1 reinoud 5333 1.1 reinoud /* --------------------------------------------------------------------- */ 5334 1.1 reinoud 5335 1.1 reinoud /* 5336 1.45 reinoud * Each node can have an attached streamdir node though not recursively. These 5337 1.45 reinoud * are otherwise known as named substreams/named extended attributes that have 5338 1.45 reinoud * no size limitations. 5339 1.1 reinoud * 5340 1.1 reinoud * `Normal' extended attributes are indicated with a number and are recorded 5341 1.1 reinoud * in either the fe/efe descriptor itself for small descriptors or recorded in 5342 1.45 reinoud * the attached extended attribute file. Since these spaces can get 5343 1.45 reinoud * fragmented, care ought to be taken. 5344 1.45 reinoud * 5345 1.45 reinoud * Since the size of the space reserved for allocation descriptors is limited, 5346 1.45 reinoud * there is a mechanim provided for extending this space; this is done by a 5347 1.174 andvar * special extent to allow shrinking of the allocations without breaking the 5348 1.45 reinoud * linkage to the allocation extent descriptor. 5349 1.1 reinoud */ 5350 1.1 reinoud 5351 1.1 reinoud int 5352 1.129 hannken udf_loadvnode(struct mount *mp, struct vnode *vp, 5353 1.129 hannken const void *key, size_t key_len, const void **new_key) 5354 1.1 reinoud { 5355 1.45 reinoud union dscrptr *dscr; 5356 1.129 hannken struct udf_mount *ump; 5357 1.45 reinoud struct udf_node *udf_node; 5358 1.129 hannken struct long_ad node_icb_loc, icb_loc, next_icb_loc, last_fe_icb_loc; 5359 1.1 reinoud uint64_t file_size; 5360 1.1 reinoud uint32_t lb_size, sector, dummy; 5361 1.1 reinoud int udf_file_type, dscr_type, strat, strat4096, needs_indirect; 5362 1.45 reinoud int slot, eof, error; 5363 1.126 reinoud int num_indir_followed = 0; 5364 1.1 reinoud 5365 1.129 hannken DPRINTF(NODE, ("udf_loadvnode called\n")); 5366 1.129 hannken udf_node = NULL; 5367 1.129 hannken ump = VFSTOUDF(mp); 5368 1.129 hannken 5369 1.129 hannken KASSERT(key_len == sizeof(node_icb_loc.loc)); 5370 1.129 hannken memset(&node_icb_loc, 0, sizeof(node_icb_loc)); 5371 1.129 hannken node_icb_loc.len = ump->logical_vol->lb_size; 5372 1.129 hannken memcpy(&node_icb_loc.loc, key, key_len); 5373 1.1 reinoud 5374 1.45 reinoud /* garbage check: translate udf_node_icb_loc to sectornr */ 5375 1.129 hannken error = udf_translate_vtop(ump, &node_icb_loc, §or, &dummy); 5376 1.1 reinoud if (error) { 5377 1.111 reinoud DPRINTF(NODE, ("\tcan't translate icb address!\n")); 5378 1.1 reinoud /* no use, this will fail anyway */ 5379 1.1 reinoud return EINVAL; 5380 1.9 christos } 5381 1.1 reinoud 5382 1.45 reinoud /* build udf_node (do initialise!) */ 5383 1.45 reinoud udf_node = pool_get(&udf_node_pool, PR_WAITOK); 5384 1.45 reinoud memset(udf_node, 0, sizeof(struct udf_node)); 5385 1.1 reinoud 5386 1.129 hannken vp->v_tag = VT_UDF; 5387 1.129 hannken vp->v_op = udf_vnodeop_p; 5388 1.129 hannken vp->v_data = udf_node; 5389 1.1 reinoud 5390 1.1 reinoud /* initialise crosslinks, note location of fe/efe for hashing */ 5391 1.45 reinoud udf_node->ump = ump; 5392 1.129 hannken udf_node->vnode = vp; 5393 1.129 hannken udf_node->loc = node_icb_loc; 5394 1.45 reinoud udf_node->lockf = 0; 5395 1.45 reinoud mutex_init(&udf_node->node_mutex, MUTEX_DEFAULT, IPL_NONE); 5396 1.45 reinoud cv_init(&udf_node->node_lock, "udf_nlk"); 5397 1.129 hannken genfs_node_init(vp, &udf_genfsops); /* inititise genfs */ 5398 1.45 reinoud udf_node->outstanding_bufs = 0; 5399 1.45 reinoud udf_node->outstanding_nodedscr = 0; 5400 1.95 reinoud udf_node->uncommitted_lbs = 0; 5401 1.1 reinoud 5402 1.81 reinoud /* check if we're fetching the root */ 5403 1.81 reinoud if (ump->fileset_desc) 5404 1.81 reinoud if (memcmp(&udf_node->loc, &ump->fileset_desc->rootdir_icb, 5405 1.81 reinoud sizeof(struct long_ad)) == 0) 5406 1.129 hannken vp->v_vflag |= VV_ROOT; 5407 1.79 reinoud 5408 1.129 hannken icb_loc = node_icb_loc; 5409 1.1 reinoud needs_indirect = 0; 5410 1.1 reinoud strat4096 = 0; 5411 1.1 reinoud udf_file_type = UDF_ICB_FILETYPE_UNKNOWN; 5412 1.1 reinoud file_size = 0; 5413 1.1 reinoud lb_size = udf_rw32(ump->logical_vol->lb_size); 5414 1.1 reinoud 5415 1.45 reinoud DPRINTF(NODE, ("\tstart reading descriptors\n")); 5416 1.1 reinoud do { 5417 1.1 reinoud /* try to read in fe/efe */ 5418 1.45 reinoud error = udf_read_logvol_dscr(ump, &icb_loc, &dscr); 5419 1.1 reinoud 5420 1.1 reinoud /* blank sector marks end of sequence, check this */ 5421 1.45 reinoud if ((dscr == NULL) && (!strat4096)) 5422 1.1 reinoud error = ENOENT; 5423 1.1 reinoud 5424 1.1 reinoud /* break if read error or blank sector */ 5425 1.45 reinoud if (error || (dscr == NULL)) 5426 1.1 reinoud break; 5427 1.1 reinoud 5428 1.1 reinoud /* process descriptor based on the descriptor type */ 5429 1.45 reinoud dscr_type = udf_rw16(dscr->tag.id); 5430 1.45 reinoud DPRINTF(NODE, ("\tread descriptor %d\n", dscr_type)); 5431 1.1 reinoud 5432 1.1 reinoud /* if dealing with an indirect entry, follow the link */ 5433 1.45 reinoud if (dscr_type == TAGID_INDIRECTENTRY) { 5434 1.1 reinoud needs_indirect = 0; 5435 1.127 reinoud next_icb_loc = dscr->inde.indirect_icb; 5436 1.45 reinoud udf_free_logvol_dscr(ump, &icb_loc, dscr); 5437 1.127 reinoud icb_loc = next_icb_loc; 5438 1.126 reinoud if (++num_indir_followed > UDF_MAX_INDIRS_FOLLOW) { 5439 1.126 reinoud error = EMLINK; 5440 1.126 reinoud break; 5441 1.126 reinoud } 5442 1.1 reinoud continue; 5443 1.9 christos } 5444 1.1 reinoud 5445 1.1 reinoud /* only file entries and extended file entries allowed here */ 5446 1.1 reinoud if ((dscr_type != TAGID_FENTRY) && 5447 1.1 reinoud (dscr_type != TAGID_EXTFENTRY)) { 5448 1.45 reinoud udf_free_logvol_dscr(ump, &icb_loc, dscr); 5449 1.1 reinoud error = ENOENT; 5450 1.1 reinoud break; 5451 1.9 christos } 5452 1.1 reinoud 5453 1.45 reinoud KASSERT(udf_tagsize(dscr, lb_size) == lb_size); 5454 1.1 reinoud 5455 1.45 reinoud /* choose this one */ 5456 1.45 reinoud last_fe_icb_loc = icb_loc; 5457 1.152 skrll 5458 1.1 reinoud /* record and process/update (ext)fentry */ 5459 1.1 reinoud if (dscr_type == TAGID_FENTRY) { 5460 1.45 reinoud if (udf_node->fe) 5461 1.45 reinoud udf_free_logvol_dscr(ump, &last_fe_icb_loc, 5462 1.45 reinoud udf_node->fe); 5463 1.45 reinoud udf_node->fe = &dscr->fe; 5464 1.45 reinoud strat = udf_rw16(udf_node->fe->icbtag.strat_type); 5465 1.45 reinoud udf_file_type = udf_node->fe->icbtag.file_type; 5466 1.45 reinoud file_size = udf_rw64(udf_node->fe->inf_len); 5467 1.1 reinoud } else { 5468 1.45 reinoud if (udf_node->efe) 5469 1.45 reinoud udf_free_logvol_dscr(ump, &last_fe_icb_loc, 5470 1.45 reinoud udf_node->efe); 5471 1.45 reinoud udf_node->efe = &dscr->efe; 5472 1.45 reinoud strat = udf_rw16(udf_node->efe->icbtag.strat_type); 5473 1.45 reinoud udf_file_type = udf_node->efe->icbtag.file_type; 5474 1.45 reinoud file_size = udf_rw64(udf_node->efe->inf_len); 5475 1.9 christos } 5476 1.1 reinoud 5477 1.1 reinoud /* check recording strategy (structure) */ 5478 1.1 reinoud 5479 1.1 reinoud /* 5480 1.1 reinoud * Strategy 4096 is a daisy linked chain terminating with an 5481 1.1 reinoud * unrecorded sector or a TERM descriptor. The next 5482 1.1 reinoud * descriptor is to be found in the sector that follows the 5483 1.1 reinoud * current sector. 5484 1.1 reinoud */ 5485 1.1 reinoud if (strat == 4096) { 5486 1.1 reinoud strat4096 = 1; 5487 1.1 reinoud needs_indirect = 1; 5488 1.1 reinoud 5489 1.1 reinoud icb_loc.loc.lb_num = udf_rw32(icb_loc.loc.lb_num) + 1; 5490 1.9 christos } 5491 1.1 reinoud 5492 1.1 reinoud /* 5493 1.1 reinoud * Strategy 4 is the normal strategy and terminates, but if 5494 1.1 reinoud * we're in strategy 4096, we can't have strategy 4 mixed in 5495 1.1 reinoud */ 5496 1.1 reinoud 5497 1.1 reinoud if (strat == 4) { 5498 1.1 reinoud if (strat4096) { 5499 1.1 reinoud error = EINVAL; 5500 1.1 reinoud break; 5501 1.9 christos } 5502 1.1 reinoud break; /* done */ 5503 1.9 christos } 5504 1.1 reinoud } while (!error); 5505 1.1 reinoud 5506 1.45 reinoud /* first round of cleanup code */ 5507 1.1 reinoud if (error) { 5508 1.45 reinoud DPRINTF(NODE, ("\tnode fe/efe failed!\n")); 5509 1.1 reinoud /* recycle udf_node */ 5510 1.45 reinoud udf_dispose_node(udf_node); 5511 1.1 reinoud 5512 1.1 reinoud return EINVAL; /* error code ok? */ 5513 1.9 christos } 5514 1.45 reinoud DPRINTF(NODE, ("\tnode fe/efe read in fine\n")); 5515 1.1 reinoud 5516 1.177 andvar /* assert no references to dscr anymore beyond this point */ 5517 1.45 reinoud assert((udf_node->fe) || (udf_node->efe)); 5518 1.1 reinoud dscr = NULL; 5519 1.1 reinoud 5520 1.1 reinoud /* 5521 1.45 reinoud * Remember where to record an updated version of the descriptor. If 5522 1.1 reinoud * there is a sequence of indirect entries, icb_loc will have been 5523 1.172 andvar * updated. It's the write discipline to allocate new space and to make 5524 1.1 reinoud * sure the chain is maintained. 5525 1.1 reinoud * 5526 1.1 reinoud * `needs_indirect' flags if the next location is to be filled with 5527 1.164 andvar * an indirect entry. 5528 1.1 reinoud */ 5529 1.45 reinoud udf_node->write_loc = icb_loc; 5530 1.45 reinoud udf_node->needs_indirect = needs_indirect; 5531 1.45 reinoud 5532 1.45 reinoud /* 5533 1.173 gutterid * Go through all allocations extents of this descriptor and when 5534 1.45 reinoud * encountering a redirect read in the allocation extension. These are 5535 1.45 reinoud * daisy-chained. 5536 1.45 reinoud */ 5537 1.45 reinoud UDF_LOCK_NODE(udf_node, 0); 5538 1.45 reinoud udf_node->num_extensions = 0; 5539 1.45 reinoud 5540 1.45 reinoud error = 0; 5541 1.45 reinoud slot = 0; 5542 1.45 reinoud for (;;) { 5543 1.45 reinoud udf_get_adslot(udf_node, slot, &icb_loc, &eof); 5544 1.52 reinoud DPRINTF(ADWLK, ("slot %d, eof = %d, flags = %d, len = %d, " 5545 1.52 reinoud "lb_num = %d, part = %d\n", slot, eof, 5546 1.52 reinoud UDF_EXT_FLAGS(udf_rw32(icb_loc.len)), 5547 1.52 reinoud UDF_EXT_LEN(udf_rw32(icb_loc.len)), 5548 1.52 reinoud udf_rw32(icb_loc.loc.lb_num), 5549 1.52 reinoud udf_rw16(icb_loc.loc.part_num))); 5550 1.45 reinoud if (eof) 5551 1.45 reinoud break; 5552 1.52 reinoud slot++; 5553 1.45 reinoud 5554 1.52 reinoud if (UDF_EXT_FLAGS(udf_rw32(icb_loc.len)) != UDF_EXT_REDIRECT) 5555 1.45 reinoud continue; 5556 1.45 reinoud 5557 1.45 reinoud DPRINTF(NODE, ("\tgot redirect extent\n")); 5558 1.45 reinoud if (udf_node->num_extensions >= UDF_MAX_ALLOC_EXTENTS) { 5559 1.45 reinoud DPRINTF(ALLOC, ("udf_get_node: implementation limit, " 5560 1.45 reinoud "too many allocation extensions on " 5561 1.45 reinoud "udf_node\n")); 5562 1.45 reinoud error = EINVAL; 5563 1.45 reinoud break; 5564 1.45 reinoud } 5565 1.45 reinoud 5566 1.45 reinoud /* length can only be *one* lb : UDF 2.50/2.3.7.1 */ 5567 1.52 reinoud if (UDF_EXT_LEN(udf_rw32(icb_loc.len)) != lb_size) { 5568 1.45 reinoud DPRINTF(ALLOC, ("udf_get_node: bad allocation " 5569 1.45 reinoud "extension size in udf_node\n")); 5570 1.45 reinoud error = EINVAL; 5571 1.45 reinoud break; 5572 1.45 reinoud } 5573 1.45 reinoud 5574 1.52 reinoud DPRINTF(NODE, ("read allocation extent at lb_num %d\n", 5575 1.52 reinoud UDF_EXT_LEN(udf_rw32(icb_loc.loc.lb_num)))); 5576 1.45 reinoud /* load in allocation extent */ 5577 1.45 reinoud error = udf_read_logvol_dscr(ump, &icb_loc, &dscr); 5578 1.45 reinoud if (error || (dscr == NULL)) 5579 1.45 reinoud break; 5580 1.45 reinoud 5581 1.45 reinoud /* process read-in descriptor */ 5582 1.45 reinoud dscr_type = udf_rw16(dscr->tag.id); 5583 1.45 reinoud 5584 1.45 reinoud if (dscr_type != TAGID_ALLOCEXTENT) { 5585 1.45 reinoud udf_free_logvol_dscr(ump, &icb_loc, dscr); 5586 1.45 reinoud error = ENOENT; 5587 1.45 reinoud break; 5588 1.45 reinoud } 5589 1.45 reinoud 5590 1.45 reinoud DPRINTF(NODE, ("\trecording redirect extent\n")); 5591 1.45 reinoud udf_node->ext[udf_node->num_extensions] = &dscr->aee; 5592 1.45 reinoud udf_node->ext_loc[udf_node->num_extensions] = icb_loc; 5593 1.45 reinoud 5594 1.45 reinoud udf_node->num_extensions++; 5595 1.45 reinoud 5596 1.45 reinoud } /* while */ 5597 1.45 reinoud UDF_UNLOCK_NODE(udf_node, 0); 5598 1.45 reinoud 5599 1.45 reinoud /* second round of cleanup code */ 5600 1.45 reinoud if (error) { 5601 1.45 reinoud /* recycle udf_node */ 5602 1.45 reinoud udf_dispose_node(udf_node); 5603 1.45 reinoud 5604 1.45 reinoud return EINVAL; /* error code ok? */ 5605 1.45 reinoud } 5606 1.45 reinoud 5607 1.45 reinoud DPRINTF(NODE, ("\tnode read in fine\n")); 5608 1.1 reinoud 5609 1.1 reinoud /* 5610 1.1 reinoud * Translate UDF filetypes into vnode types. 5611 1.1 reinoud * 5612 1.1 reinoud * Systemfiles like the meta main and mirror files are not treated as 5613 1.1 reinoud * normal files, so we type them as having no type. UDF dictates that 5614 1.1 reinoud * they are not allowed to be visible. 5615 1.1 reinoud */ 5616 1.1 reinoud 5617 1.45 reinoud switch (udf_file_type) { 5618 1.45 reinoud case UDF_ICB_FILETYPE_DIRECTORY : 5619 1.45 reinoud case UDF_ICB_FILETYPE_STREAMDIR : 5620 1.129 hannken vp->v_type = VDIR; 5621 1.45 reinoud break; 5622 1.45 reinoud case UDF_ICB_FILETYPE_BLOCKDEVICE : 5623 1.129 hannken vp->v_type = VBLK; 5624 1.45 reinoud break; 5625 1.45 reinoud case UDF_ICB_FILETYPE_CHARDEVICE : 5626 1.129 hannken vp->v_type = VCHR; 5627 1.45 reinoud break; 5628 1.45 reinoud case UDF_ICB_FILETYPE_SOCKET : 5629 1.129 hannken vp->v_type = VSOCK; 5630 1.45 reinoud break; 5631 1.45 reinoud case UDF_ICB_FILETYPE_FIFO : 5632 1.129 hannken vp->v_type = VFIFO; 5633 1.45 reinoud break; 5634 1.45 reinoud case UDF_ICB_FILETYPE_SYMLINK : 5635 1.129 hannken vp->v_type = VLNK; 5636 1.45 reinoud break; 5637 1.45 reinoud case UDF_ICB_FILETYPE_VAT : 5638 1.45 reinoud case UDF_ICB_FILETYPE_META_MAIN : 5639 1.45 reinoud case UDF_ICB_FILETYPE_META_MIRROR : 5640 1.129 hannken vp->v_type = VNON; 5641 1.45 reinoud break; 5642 1.45 reinoud case UDF_ICB_FILETYPE_RANDOMACCESS : 5643 1.45 reinoud case UDF_ICB_FILETYPE_REALTIME : 5644 1.129 hannken vp->v_type = VREG; 5645 1.45 reinoud break; 5646 1.45 reinoud default: 5647 1.45 reinoud /* YIKES, something else */ 5648 1.129 hannken vp->v_type = VNON; 5649 1.45 reinoud } 5650 1.45 reinoud 5651 1.1 reinoud /* TODO specfs, fifofs etc etc. vnops setting */ 5652 1.45 reinoud 5653 1.45 reinoud /* don't forget to set vnode's v_size */ 5654 1.129 hannken uvm_vnp_setsize(vp, file_size); 5655 1.45 reinoud 5656 1.45 reinoud /* TODO ext attr and streamdir udf_nodes */ 5657 1.45 reinoud 5658 1.129 hannken *new_key = &udf_node->loc.loc; 5659 1.45 reinoud 5660 1.45 reinoud return 0; 5661 1.45 reinoud } 5662 1.45 reinoud 5663 1.129 hannken int 5664 1.129 hannken udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc, 5665 1.148 ad struct udf_node **udf_noderes, int lktype) 5666 1.129 hannken { 5667 1.129 hannken int error; 5668 1.129 hannken struct vnode *vp; 5669 1.129 hannken 5670 1.137 reinoud *udf_noderes = NULL; 5671 1.137 reinoud 5672 1.129 hannken error = vcache_get(ump->vfs_mountp, &node_icb_loc->loc, 5673 1.129 hannken sizeof(node_icb_loc->loc), &vp); 5674 1.129 hannken if (error) 5675 1.129 hannken return error; 5676 1.150 hannken error = vn_lock(vp, lktype); 5677 1.129 hannken if (error) { 5678 1.129 hannken vrele(vp); 5679 1.129 hannken return error; 5680 1.129 hannken } 5681 1.129 hannken *udf_noderes = VTOI(vp); 5682 1.129 hannken return 0; 5683 1.129 hannken } 5684 1.129 hannken 5685 1.45 reinoud /* --------------------------------------------------------------------- */ 5686 1.45 reinoud 5687 1.45 reinoud int 5688 1.45 reinoud udf_writeout_node(struct udf_node *udf_node, int waitfor) 5689 1.45 reinoud { 5690 1.45 reinoud union dscrptr *dscr; 5691 1.45 reinoud struct long_ad *loc; 5692 1.91 reinoud int extnr, error; 5693 1.45 reinoud 5694 1.45 reinoud DPRINTF(NODE, ("udf_writeout_node called\n")); 5695 1.45 reinoud 5696 1.45 reinoud KASSERT(udf_node->outstanding_bufs == 0); 5697 1.45 reinoud KASSERT(udf_node->outstanding_nodedscr == 0); 5698 1.45 reinoud 5699 1.45 reinoud KASSERT(LIST_EMPTY(&udf_node->vnode->v_dirtyblkhd)); 5700 1.45 reinoud 5701 1.45 reinoud if (udf_node->i_flags & IN_DELETED) { 5702 1.45 reinoud DPRINTF(NODE, ("\tnode deleted; not writing out\n")); 5703 1.95 reinoud udf_cleanup_reservation(udf_node); 5704 1.45 reinoud return 0; 5705 1.45 reinoud } 5706 1.45 reinoud 5707 1.93 reinoud /* lock node; unlocked in callback */ 5708 1.91 reinoud UDF_LOCK_NODE(udf_node, 0); 5709 1.55 reinoud 5710 1.95 reinoud /* remove pending reservations, we're written out */ 5711 1.95 reinoud udf_cleanup_reservation(udf_node); 5712 1.95 reinoud 5713 1.55 reinoud /* at least one descriptor writeout */ 5714 1.55 reinoud udf_node->outstanding_nodedscr = 1; 5715 1.55 reinoud 5716 1.45 reinoud /* we're going to write out the descriptor so clear the flags */ 5717 1.45 reinoud udf_node->i_flags &= ~(IN_MODIFIED | IN_ACCESSED); 5718 1.45 reinoud 5719 1.55 reinoud /* if we were rebuild, write out the allocation extents */ 5720 1.55 reinoud if (udf_node->i_flags & IN_NODE_REBUILD) { 5721 1.71 reinoud /* mark outstanding node descriptors and issue them */ 5722 1.55 reinoud udf_node->outstanding_nodedscr += udf_node->num_extensions; 5723 1.55 reinoud for (extnr = 0; extnr < udf_node->num_extensions; extnr++) { 5724 1.55 reinoud loc = &udf_node->ext_loc[extnr]; 5725 1.55 reinoud dscr = (union dscrptr *) udf_node->ext[extnr]; 5726 1.55 reinoud error = udf_write_logvol_dscr(udf_node, dscr, loc, 0); 5727 1.55 reinoud if (error) 5728 1.55 reinoud return error; 5729 1.55 reinoud } 5730 1.55 reinoud /* mark allocation extents written out */ 5731 1.55 reinoud udf_node->i_flags &= ~(IN_NODE_REBUILD); 5732 1.55 reinoud } 5733 1.55 reinoud 5734 1.45 reinoud if (udf_node->fe) { 5735 1.71 reinoud KASSERT(udf_node->efe == NULL); 5736 1.45 reinoud dscr = (union dscrptr *) udf_node->fe; 5737 1.45 reinoud } else { 5738 1.45 reinoud KASSERT(udf_node->efe); 5739 1.71 reinoud KASSERT(udf_node->fe == NULL); 5740 1.45 reinoud dscr = (union dscrptr *) udf_node->efe; 5741 1.45 reinoud } 5742 1.45 reinoud KASSERT(dscr); 5743 1.45 reinoud 5744 1.45 reinoud loc = &udf_node->write_loc; 5745 1.45 reinoud error = udf_write_logvol_dscr(udf_node, dscr, loc, waitfor); 5746 1.95 reinoud 5747 1.45 reinoud return error; 5748 1.45 reinoud } 5749 1.45 reinoud 5750 1.45 reinoud /* --------------------------------------------------------------------- */ 5751 1.45 reinoud 5752 1.45 reinoud int 5753 1.45 reinoud udf_dispose_node(struct udf_node *udf_node) 5754 1.45 reinoud { 5755 1.45 reinoud struct vnode *vp; 5756 1.52 reinoud int extnr; 5757 1.45 reinoud 5758 1.45 reinoud DPRINTF(NODE, ("udf_dispose_node called on node %p\n", udf_node)); 5759 1.45 reinoud if (!udf_node) { 5760 1.45 reinoud DPRINTF(NODE, ("UDF: Dispose node on node NULL, ignoring\n")); 5761 1.45 reinoud return 0; 5762 1.45 reinoud } 5763 1.45 reinoud 5764 1.45 reinoud vp = udf_node->vnode; 5765 1.45 reinoud #ifdef DIAGNOSTIC 5766 1.45 reinoud if (vp->v_numoutput) 5767 1.45 reinoud panic("disposing UDF node with pending I/O's, udf_node = %p, " 5768 1.45 reinoud "v_numoutput = %d", udf_node, vp->v_numoutput); 5769 1.45 reinoud #endif 5770 1.45 reinoud 5771 1.95 reinoud udf_cleanup_reservation(udf_node); 5772 1.45 reinoud 5773 1.45 reinoud /* TODO extended attributes and streamdir */ 5774 1.45 reinoud 5775 1.59 reinoud /* remove dirhash if present */ 5776 1.73 reinoud dirhash_purge(&udf_node->dir_hash); 5777 1.59 reinoud 5778 1.45 reinoud /* destroy our lock */ 5779 1.45 reinoud mutex_destroy(&udf_node->node_mutex); 5780 1.45 reinoud cv_destroy(&udf_node->node_lock); 5781 1.45 reinoud 5782 1.45 reinoud /* dissociate our udf_node from the vnode */ 5783 1.45 reinoud genfs_node_destroy(udf_node->vnode); 5784 1.132 hannken mutex_enter(vp->v_interlock); 5785 1.45 reinoud vp->v_data = NULL; 5786 1.132 hannken mutex_exit(vp->v_interlock); 5787 1.45 reinoud 5788 1.45 reinoud /* free associated memory and the node itself */ 5789 1.52 reinoud for (extnr = 0; extnr < udf_node->num_extensions; extnr++) { 5790 1.52 reinoud udf_free_logvol_dscr(udf_node->ump, &udf_node->ext_loc[extnr], 5791 1.52 reinoud udf_node->ext[extnr]); 5792 1.52 reinoud udf_node->ext[extnr] = (void *) 0xdeadcccc; 5793 1.52 reinoud } 5794 1.52 reinoud 5795 1.45 reinoud if (udf_node->fe) 5796 1.52 reinoud udf_free_logvol_dscr(udf_node->ump, &udf_node->loc, 5797 1.52 reinoud udf_node->fe); 5798 1.45 reinoud if (udf_node->efe) 5799 1.52 reinoud udf_free_logvol_dscr(udf_node->ump, &udf_node->loc, 5800 1.52 reinoud udf_node->efe); 5801 1.45 reinoud 5802 1.45 reinoud udf_node->fe = (void *) 0xdeadaaaa; 5803 1.45 reinoud udf_node->efe = (void *) 0xdeadbbbb; 5804 1.45 reinoud udf_node->ump = (void *) 0xdeadbeef; 5805 1.45 reinoud pool_put(&udf_node_pool, udf_node); 5806 1.45 reinoud 5807 1.45 reinoud return 0; 5808 1.45 reinoud } 5809 1.45 reinoud 5810 1.45 reinoud 5811 1.45 reinoud 5812 1.45 reinoud /* 5813 1.129 hannken * create a new node using the specified dvp, vap and cnp. 5814 1.129 hannken * This allows special files to be created. Use with care. 5815 1.45 reinoud */ 5816 1.45 reinoud 5817 1.129 hannken int 5818 1.129 hannken udf_newvnode(struct mount *mp, struct vnode *dvp, struct vnode *vp, 5819 1.145 hannken struct vattr *vap, kauth_cred_t cred, void *extra, 5820 1.129 hannken size_t *key_len, const void **new_key) 5821 1.45 reinoud { 5822 1.45 reinoud union dscrptr *dscr; 5823 1.101 mbalmer struct udf_node *dir_node = VTOI(dvp); 5824 1.45 reinoud struct udf_node *udf_node; 5825 1.45 reinoud struct udf_mount *ump = dir_node->ump; 5826 1.45 reinoud struct long_ad node_icb_loc; 5827 1.45 reinoud uint64_t parent_unique_id; 5828 1.70 reinoud uint64_t lmapping; 5829 1.45 reinoud uint32_t lb_size, lb_num; 5830 1.45 reinoud uint16_t vpart_num; 5831 1.56 reinoud uid_t uid; 5832 1.56 reinoud gid_t gid, parent_gid; 5833 1.129 hannken int (**vnodeops)(void *); 5834 1.129 hannken int udf_file_type, fid_size, error; 5835 1.129 hannken 5836 1.129 hannken vnodeops = udf_vnodeop_p; 5837 1.129 hannken udf_file_type = UDF_ICB_FILETYPE_RANDOMACCESS; 5838 1.129 hannken 5839 1.129 hannken switch (vap->va_type) { 5840 1.129 hannken case VREG : 5841 1.129 hannken udf_file_type = UDF_ICB_FILETYPE_RANDOMACCESS; 5842 1.129 hannken break; 5843 1.129 hannken case VDIR : 5844 1.129 hannken udf_file_type = UDF_ICB_FILETYPE_DIRECTORY; 5845 1.129 hannken break; 5846 1.129 hannken case VLNK : 5847 1.129 hannken udf_file_type = UDF_ICB_FILETYPE_SYMLINK; 5848 1.129 hannken break; 5849 1.129 hannken case VBLK : 5850 1.129 hannken udf_file_type = UDF_ICB_FILETYPE_BLOCKDEVICE; 5851 1.129 hannken /* specfs */ 5852 1.129 hannken return ENOTSUP; 5853 1.129 hannken break; 5854 1.129 hannken case VCHR : 5855 1.129 hannken udf_file_type = UDF_ICB_FILETYPE_CHARDEVICE; 5856 1.129 hannken /* specfs */ 5857 1.129 hannken return ENOTSUP; 5858 1.129 hannken break; 5859 1.129 hannken case VFIFO : 5860 1.129 hannken udf_file_type = UDF_ICB_FILETYPE_FIFO; 5861 1.129 hannken /* fifofs */ 5862 1.129 hannken return ENOTSUP; 5863 1.129 hannken break; 5864 1.129 hannken case VSOCK : 5865 1.129 hannken udf_file_type = UDF_ICB_FILETYPE_SOCKET; 5866 1.129 hannken return ENOTSUP; 5867 1.129 hannken break; 5868 1.129 hannken case VNON : 5869 1.129 hannken case VBAD : 5870 1.129 hannken default : 5871 1.129 hannken /* nothing; can we even create these? */ 5872 1.129 hannken return EINVAL; 5873 1.129 hannken } 5874 1.45 reinoud 5875 1.45 reinoud lb_size = udf_rw32(ump->logical_vol->lb_size); 5876 1.45 reinoud 5877 1.95 reinoud /* reserve space for one logical block */ 5878 1.71 reinoud vpart_num = ump->node_part; 5879 1.95 reinoud error = udf_reserve_space(ump, NULL, UDF_C_NODE, 5880 1.95 reinoud vpart_num, 1, /* can_fail */ true); 5881 1.95 reinoud if (error) 5882 1.129 hannken return error; 5883 1.95 reinoud 5884 1.95 reinoud /* allocate node */ 5885 1.95 reinoud error = udf_allocate_space(ump, NULL, UDF_C_NODE, 5886 1.95 reinoud vpart_num, 1, &lmapping); 5887 1.129 hannken if (error) { 5888 1.129 hannken udf_do_unreserve_space(ump, NULL, vpart_num, 1); 5889 1.129 hannken return error; 5890 1.129 hannken } 5891 1.129 hannken 5892 1.45 reinoud lb_num = lmapping; 5893 1.1 reinoud 5894 1.45 reinoud /* initialise pointer to location */ 5895 1.45 reinoud memset(&node_icb_loc, 0, sizeof(struct long_ad)); 5896 1.89 reinoud node_icb_loc.len = udf_rw32(lb_size); 5897 1.45 reinoud node_icb_loc.loc.lb_num = udf_rw32(lb_num); 5898 1.45 reinoud node_icb_loc.loc.part_num = udf_rw16(vpart_num); 5899 1.45 reinoud 5900 1.45 reinoud /* build udf_node (do initialise!) */ 5901 1.45 reinoud udf_node = pool_get(&udf_node_pool, PR_WAITOK); 5902 1.45 reinoud memset(udf_node, 0, sizeof(struct udf_node)); 5903 1.45 reinoud 5904 1.45 reinoud /* initialise crosslinks, note location of fe/efe for hashing */ 5905 1.45 reinoud /* bugalert: synchronise with udf_get_node() */ 5906 1.45 reinoud udf_node->ump = ump; 5907 1.129 hannken udf_node->vnode = vp; 5908 1.129 hannken vp->v_data = udf_node; 5909 1.45 reinoud udf_node->loc = node_icb_loc; 5910 1.45 reinoud udf_node->write_loc = node_icb_loc; 5911 1.45 reinoud udf_node->lockf = 0; 5912 1.45 reinoud mutex_init(&udf_node->node_mutex, MUTEX_DEFAULT, IPL_NONE); 5913 1.45 reinoud cv_init(&udf_node->node_lock, "udf_nlk"); 5914 1.45 reinoud udf_node->outstanding_bufs = 0; 5915 1.45 reinoud udf_node->outstanding_nodedscr = 0; 5916 1.95 reinoud udf_node->uncommitted_lbs = 0; 5917 1.45 reinoud 5918 1.129 hannken vp->v_tag = VT_UDF; 5919 1.129 hannken vp->v_op = vnodeops; 5920 1.129 hannken 5921 1.1 reinoud /* initialise genfs */ 5922 1.129 hannken genfs_node_init(vp, &udf_genfsops); 5923 1.1 reinoud 5924 1.168 andvar /* get parent's unique ID for referring '..' if its a directory */ 5925 1.45 reinoud if (dir_node->fe) { 5926 1.45 reinoud parent_unique_id = udf_rw64(dir_node->fe->unique_id); 5927 1.56 reinoud parent_gid = (gid_t) udf_rw32(dir_node->fe->gid); 5928 1.45 reinoud } else { 5929 1.45 reinoud parent_unique_id = udf_rw64(dir_node->efe->unique_id); 5930 1.56 reinoud parent_gid = (gid_t) udf_rw32(dir_node->efe->gid); 5931 1.45 reinoud } 5932 1.1 reinoud 5933 1.45 reinoud /* get descriptor */ 5934 1.45 reinoud udf_create_logvol_dscr(ump, udf_node, &node_icb_loc, &dscr); 5935 1.1 reinoud 5936 1.45 reinoud /* choose a fe or an efe for it */ 5937 1.90 reinoud if (udf_rw16(ump->logical_vol->tag.descriptor_ver) == 2) { 5938 1.45 reinoud udf_node->fe = &dscr->fe; 5939 1.45 reinoud fid_size = udf_create_new_fe(ump, udf_node->fe, 5940 1.45 reinoud udf_file_type, &udf_node->loc, 5941 1.45 reinoud &dir_node->loc, parent_unique_id); 5942 1.45 reinoud /* TODO add extended attribute for creation time */ 5943 1.45 reinoud } else { 5944 1.45 reinoud udf_node->efe = &dscr->efe; 5945 1.45 reinoud fid_size = udf_create_new_efe(ump, udf_node->efe, 5946 1.45 reinoud udf_file_type, &udf_node->loc, 5947 1.45 reinoud &dir_node->loc, parent_unique_id); 5948 1.45 reinoud } 5949 1.45 reinoud KASSERT(dscr->tag.tag_loc == udf_node->loc.loc.lb_num); 5950 1.1 reinoud 5951 1.45 reinoud /* update vnode's size and type */ 5952 1.129 hannken vp->v_type = vap->va_type; 5953 1.129 hannken uvm_vnp_setsize(vp, fid_size); 5954 1.1 reinoud 5955 1.45 reinoud /* set access mode */ 5956 1.45 reinoud udf_setaccessmode(udf_node, vap->va_mode); 5957 1.1 reinoud 5958 1.45 reinoud /* set ownership */ 5959 1.129 hannken uid = kauth_cred_geteuid(cred); 5960 1.56 reinoud gid = parent_gid; 5961 1.56 reinoud udf_setownership(udf_node, uid, gid); 5962 1.1 reinoud 5963 1.141 maya *key_len = sizeof(udf_node->loc.loc); 5964 1.129 hannken *new_key = &udf_node->loc.loc; 5965 1.129 hannken 5966 1.129 hannken return 0; 5967 1.129 hannken } 5968 1.129 hannken 5969 1.129 hannken 5970 1.129 hannken int 5971 1.129 hannken udf_create_node(struct vnode *dvp, struct vnode **vpp, struct vattr *vap, 5972 1.129 hannken struct componentname *cnp) 5973 1.129 hannken { 5974 1.129 hannken struct udf_node *udf_node, *dir_node = VTOI(dvp); 5975 1.129 hannken struct udf_mount *ump = dir_node->ump; 5976 1.129 hannken int error; 5977 1.129 hannken 5978 1.145 hannken error = vcache_new(dvp->v_mount, dvp, vap, cnp->cn_cred, NULL, vpp); 5979 1.129 hannken if (error) 5980 1.129 hannken return error; 5981 1.129 hannken 5982 1.129 hannken udf_node = VTOI(*vpp); 5983 1.45 reinoud error = udf_dir_attach(ump, dir_node, udf_node, vap, cnp); 5984 1.45 reinoud if (error) { 5985 1.129 hannken struct long_ad *node_icb_loc = &udf_node->loc; 5986 1.129 hannken uint32_t lb_num = udf_rw32(node_icb_loc->loc.lb_num); 5987 1.129 hannken uint16_t vpart_num = udf_rw16(node_icb_loc->loc.part_num); 5988 1.129 hannken 5989 1.45 reinoud /* free disc allocation for node */ 5990 1.45 reinoud udf_free_allocated_space(ump, lb_num, vpart_num, 1); 5991 1.1 reinoud 5992 1.45 reinoud /* recycle udf_node */ 5993 1.45 reinoud udf_dispose_node(udf_node); 5994 1.129 hannken vrele(*vpp); 5995 1.1 reinoud 5996 1.45 reinoud *vpp = NULL; 5997 1.45 reinoud return error; 5998 1.45 reinoud } 5999 1.1 reinoud 6000 1.45 reinoud /* adjust file count */ 6001 1.45 reinoud udf_adjust_filecount(udf_node, 1); 6002 1.1 reinoud 6003 1.147 christos cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags); 6004 1.45 reinoud return 0; 6005 1.1 reinoud } 6006 1.1 reinoud 6007 1.1 reinoud /* --------------------------------------------------------------------- */ 6008 1.1 reinoud 6009 1.45 reinoud static void 6010 1.45 reinoud udf_free_descriptor_space(struct udf_node *udf_node, struct long_ad *loc, void *mem) 6011 1.45 reinoud { 6012 1.45 reinoud struct udf_mount *ump = udf_node->ump; 6013 1.45 reinoud uint32_t lb_size, lb_num, len, num_lb; 6014 1.45 reinoud uint16_t vpart_num; 6015 1.45 reinoud 6016 1.45 reinoud /* is there really one? */ 6017 1.45 reinoud if (mem == NULL) 6018 1.45 reinoud return; 6019 1.1 reinoud 6020 1.45 reinoud /* got a descriptor here */ 6021 1.55 reinoud len = UDF_EXT_LEN(udf_rw32(loc->len)); 6022 1.45 reinoud lb_num = udf_rw32(loc->loc.lb_num); 6023 1.45 reinoud vpart_num = udf_rw16(loc->loc.part_num); 6024 1.1 reinoud 6025 1.45 reinoud lb_size = udf_rw32(ump->logical_vol->lb_size); 6026 1.45 reinoud num_lb = (len + lb_size -1) / lb_size; 6027 1.1 reinoud 6028 1.45 reinoud udf_free_allocated_space(ump, lb_num, vpart_num, num_lb); 6029 1.1 reinoud } 6030 1.1 reinoud 6031 1.1 reinoud void 6032 1.45 reinoud udf_delete_node(struct udf_node *udf_node) 6033 1.1 reinoud { 6034 1.45 reinoud void *dscr; 6035 1.45 reinoud struct long_ad *loc; 6036 1.45 reinoud int extnr, lvint, dummy; 6037 1.45 reinoud 6038 1.137 reinoud if (udf_node->i_flags & IN_NO_DELETE) 6039 1.137 reinoud return; 6040 1.137 reinoud 6041 1.45 reinoud /* paranoia check on integrity; should be open!; we could panic */ 6042 1.45 reinoud lvint = udf_rw32(udf_node->ump->logvol_integrity->integrity_type); 6043 1.45 reinoud if (lvint == UDF_INTEGRITY_CLOSED) 6044 1.45 reinoud printf("\tIntegrity was CLOSED!\n"); 6045 1.45 reinoud 6046 1.45 reinoud /* whatever the node type, change its size to zero */ 6047 1.45 reinoud (void) udf_resize_node(udf_node, 0, &dummy); 6048 1.1 reinoud 6049 1.45 reinoud /* force it to be `clean'; no use writing it out */ 6050 1.45 reinoud udf_node->i_flags &= ~(IN_MODIFIED | IN_ACCESSED | IN_ACCESS | 6051 1.45 reinoud IN_CHANGE | IN_UPDATE | IN_MODIFY); 6052 1.1 reinoud 6053 1.45 reinoud /* adjust file count */ 6054 1.45 reinoud udf_adjust_filecount(udf_node, -1); 6055 1.1 reinoud 6056 1.1 reinoud /* 6057 1.45 reinoud * Free its allocated descriptors; memory will be released when 6058 1.45 reinoud * vop_reclaim() is called. 6059 1.1 reinoud */ 6060 1.45 reinoud loc = &udf_node->loc; 6061 1.45 reinoud 6062 1.45 reinoud dscr = udf_node->fe; 6063 1.45 reinoud udf_free_descriptor_space(udf_node, loc, dscr); 6064 1.45 reinoud dscr = udf_node->efe; 6065 1.45 reinoud udf_free_descriptor_space(udf_node, loc, dscr); 6066 1.1 reinoud 6067 1.45 reinoud for (extnr = 0; extnr < UDF_MAX_ALLOC_EXTENTS; extnr++) { 6068 1.45 reinoud dscr = udf_node->ext[extnr]; 6069 1.45 reinoud loc = &udf_node->ext_loc[extnr]; 6070 1.45 reinoud udf_free_descriptor_space(udf_node, loc, dscr); 6071 1.9 christos } 6072 1.1 reinoud } 6073 1.1 reinoud 6074 1.1 reinoud /* --------------------------------------------------------------------- */ 6075 1.1 reinoud 6076 1.45 reinoud /* set new filesize; node but be LOCKED on entry and is locked on exit */ 6077 1.45 reinoud int 6078 1.45 reinoud udf_resize_node(struct udf_node *udf_node, uint64_t new_size, int *extended) 6079 1.1 reinoud { 6080 1.45 reinoud struct file_entry *fe = udf_node->fe; 6081 1.45 reinoud struct extfile_entry *efe = udf_node->efe; 6082 1.45 reinoud uint64_t file_size; 6083 1.45 reinoud int error; 6084 1.1 reinoud 6085 1.45 reinoud if (fe) { 6086 1.45 reinoud file_size = udf_rw64(fe->inf_len); 6087 1.1 reinoud } else { 6088 1.1 reinoud assert(udf_node->efe); 6089 1.45 reinoud file_size = udf_rw64(efe->inf_len); 6090 1.9 christos } 6091 1.1 reinoud 6092 1.45 reinoud DPRINTF(ATTR, ("\tchanging file length from %"PRIu64" to %"PRIu64"\n", 6093 1.45 reinoud file_size, new_size)); 6094 1.45 reinoud 6095 1.45 reinoud /* if not changing, we're done */ 6096 1.45 reinoud if (file_size == new_size) 6097 1.45 reinoud return 0; 6098 1.1 reinoud 6099 1.45 reinoud *extended = (new_size > file_size); 6100 1.45 reinoud if (*extended) { 6101 1.45 reinoud error = udf_grow_node(udf_node, new_size); 6102 1.45 reinoud } else { 6103 1.45 reinoud error = udf_shrink_node(udf_node, new_size); 6104 1.45 reinoud } 6105 1.1 reinoud 6106 1.45 reinoud return error; 6107 1.1 reinoud } 6108 1.1 reinoud 6109 1.45 reinoud 6110 1.1 reinoud /* --------------------------------------------------------------------- */ 6111 1.1 reinoud 6112 1.45 reinoud void 6113 1.45 reinoud udf_itimes(struct udf_node *udf_node, struct timespec *acc, 6114 1.50 reinoud struct timespec *mod, struct timespec *birth) 6115 1.1 reinoud { 6116 1.45 reinoud struct timespec now; 6117 1.1 reinoud struct file_entry *fe; 6118 1.1 reinoud struct extfile_entry *efe; 6119 1.51 reinoud struct filetimes_extattr_entry *ft_extattr; 6120 1.50 reinoud struct timestamp *atime, *mtime, *attrtime, *ctime; 6121 1.50 reinoud struct timestamp fe_ctime; 6122 1.50 reinoud struct timespec cur_birth; 6123 1.51 reinoud uint32_t offset, a_l; 6124 1.51 reinoud uint8_t *filedata; 6125 1.51 reinoud int error; 6126 1.45 reinoud 6127 1.45 reinoud /* protect against rogue values */ 6128 1.45 reinoud if (!udf_node) 6129 1.45 reinoud return; 6130 1.45 reinoud 6131 1.45 reinoud fe = udf_node->fe; 6132 1.45 reinoud efe = udf_node->efe; 6133 1.45 reinoud 6134 1.45 reinoud if (!(udf_node->i_flags & (IN_ACCESS|IN_CHANGE|IN_UPDATE|IN_MODIFY))) 6135 1.45 reinoud return; 6136 1.1 reinoud 6137 1.45 reinoud /* get descriptor information */ 6138 1.45 reinoud if (fe) { 6139 1.45 reinoud atime = &fe->atime; 6140 1.45 reinoud mtime = &fe->mtime; 6141 1.45 reinoud attrtime = &fe->attrtime; 6142 1.51 reinoud filedata = fe->data; 6143 1.51 reinoud 6144 1.51 reinoud /* initial save dummy setting */ 6145 1.50 reinoud ctime = &fe_ctime; 6146 1.51 reinoud 6147 1.51 reinoud /* check our extended attribute if present */ 6148 1.51 reinoud error = udf_extattr_search_intern(udf_node, 6149 1.51 reinoud UDF_FILETIMES_ATTR_NO, "", &offset, &a_l); 6150 1.51 reinoud if (!error) { 6151 1.51 reinoud ft_extattr = (struct filetimes_extattr_entry *) 6152 1.51 reinoud (filedata + offset); 6153 1.51 reinoud if (ft_extattr->existence & UDF_FILETIMES_FILE_CREATION) 6154 1.51 reinoud ctime = &ft_extattr->times[0]; 6155 1.51 reinoud } 6156 1.51 reinoud /* TODO create the extended attribute if not found ? */ 6157 1.1 reinoud } else { 6158 1.45 reinoud assert(udf_node->efe); 6159 1.45 reinoud atime = &efe->atime; 6160 1.45 reinoud mtime = &efe->mtime; 6161 1.45 reinoud attrtime = &efe->attrtime; 6162 1.50 reinoud ctime = &efe->ctime; 6163 1.45 reinoud } 6164 1.45 reinoud 6165 1.45 reinoud vfs_timestamp(&now); 6166 1.45 reinoud 6167 1.45 reinoud /* set access time */ 6168 1.45 reinoud if (udf_node->i_flags & IN_ACCESS) { 6169 1.45 reinoud if (acc == NULL) 6170 1.45 reinoud acc = &now; 6171 1.45 reinoud udf_timespec_to_timestamp(acc, atime); 6172 1.45 reinoud } 6173 1.45 reinoud 6174 1.45 reinoud /* set modification time */ 6175 1.45 reinoud if (udf_node->i_flags & (IN_UPDATE | IN_MODIFY)) { 6176 1.45 reinoud if (mod == NULL) 6177 1.45 reinoud mod = &now; 6178 1.45 reinoud udf_timespec_to_timestamp(mod, mtime); 6179 1.50 reinoud 6180 1.50 reinoud /* ensure birthtime is older than set modification! */ 6181 1.50 reinoud udf_timestamp_to_timespec(udf_node->ump, ctime, &cur_birth); 6182 1.50 reinoud if ((cur_birth.tv_sec > mod->tv_sec) || 6183 1.50 reinoud ((cur_birth.tv_sec == mod->tv_sec) && 6184 1.50 reinoud (cur_birth.tv_nsec > mod->tv_nsec))) { 6185 1.50 reinoud udf_timespec_to_timestamp(mod, ctime); 6186 1.50 reinoud } 6187 1.45 reinoud } 6188 1.45 reinoud 6189 1.50 reinoud /* update birthtime if specified */ 6190 1.116 mbalmer /* XXX we assume here that given birthtime is older than mod */ 6191 1.51 reinoud if (birth && (birth->tv_sec != VNOVAL)) { 6192 1.50 reinoud udf_timespec_to_timestamp(birth, ctime); 6193 1.51 reinoud } 6194 1.50 reinoud 6195 1.45 reinoud /* set change time */ 6196 1.50 reinoud if (udf_node->i_flags & (IN_CHANGE | IN_MODIFY)) 6197 1.50 reinoud udf_timespec_to_timestamp(&now, attrtime); 6198 1.1 reinoud 6199 1.45 reinoud /* notify updates to the node itself */ 6200 1.45 reinoud if (udf_node->i_flags & (IN_ACCESS | IN_MODIFY)) 6201 1.45 reinoud udf_node->i_flags |= IN_ACCESSED; 6202 1.45 reinoud if (udf_node->i_flags & (IN_UPDATE | IN_CHANGE)) 6203 1.45 reinoud udf_node->i_flags |= IN_MODIFIED; 6204 1.45 reinoud 6205 1.45 reinoud /* clear modification flags */ 6206 1.45 reinoud udf_node->i_flags &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY); 6207 1.45 reinoud } 6208 1.45 reinoud 6209 1.45 reinoud /* --------------------------------------------------------------------- */ 6210 1.1 reinoud 6211 1.45 reinoud int 6212 1.45 reinoud udf_update(struct vnode *vp, struct timespec *acc, 6213 1.50 reinoud struct timespec *mod, struct timespec *birth, int updflags) 6214 1.45 reinoud { 6215 1.71 reinoud union dscrptr *dscrptr; 6216 1.45 reinoud struct udf_node *udf_node = VTOI(vp); 6217 1.45 reinoud struct udf_mount *ump = udf_node->ump; 6218 1.45 reinoud struct regid *impl_id; 6219 1.45 reinoud int mnt_async = (vp->v_mount->mnt_flag & MNT_ASYNC); 6220 1.45 reinoud int waitfor, flags; 6221 1.31 reinoud 6222 1.45 reinoud #ifdef DEBUG 6223 1.45 reinoud char bits[128]; 6224 1.50 reinoud DPRINTF(CALL, ("udf_update(node, %p, %p, %p, %d)\n", acc, mod, birth, 6225 1.50 reinoud updflags)); 6226 1.80 christos snprintb(bits, sizeof(bits), IN_FLAGBITS, udf_node->i_flags); 6227 1.45 reinoud DPRINTF(CALL, ("\tnode flags %s\n", bits)); 6228 1.45 reinoud DPRINTF(CALL, ("\t\tmnt_async = %d\n", mnt_async)); 6229 1.45 reinoud #endif 6230 1.31 reinoud 6231 1.45 reinoud /* set our times */ 6232 1.51 reinoud udf_itimes(udf_node, acc, mod, birth); 6233 1.37 rumble 6234 1.45 reinoud /* set our implementation id */ 6235 1.45 reinoud if (udf_node->fe) { 6236 1.71 reinoud dscrptr = (union dscrptr *) udf_node->fe; 6237 1.45 reinoud impl_id = &udf_node->fe->imp_id; 6238 1.45 reinoud } else { 6239 1.71 reinoud dscrptr = (union dscrptr *) udf_node->efe; 6240 1.45 reinoud impl_id = &udf_node->efe->imp_id; 6241 1.45 reinoud } 6242 1.71 reinoud 6243 1.71 reinoud /* set our ID */ 6244 1.45 reinoud udf_set_regid(impl_id, IMPL_NAME); 6245 1.45 reinoud udf_add_impl_regid(ump, impl_id); 6246 1.18 reinoud 6247 1.71 reinoud /* update our crc! on RMW we are not allowed to change a thing */ 6248 1.71 reinoud udf_validate_tag_and_crc_sums(dscrptr); 6249 1.71 reinoud 6250 1.45 reinoud /* if called when mounted readonly, never write back */ 6251 1.45 reinoud if (vp->v_mount->mnt_flag & MNT_RDONLY) 6252 1.45 reinoud return 0; 6253 1.1 reinoud 6254 1.45 reinoud /* check if the node is dirty 'enough'*/ 6255 1.45 reinoud if (updflags & UPDATE_CLOSE) { 6256 1.45 reinoud flags = udf_node->i_flags & (IN_MODIFIED | IN_ACCESSED); 6257 1.45 reinoud } else { 6258 1.45 reinoud flags = udf_node->i_flags & IN_MODIFIED; 6259 1.45 reinoud } 6260 1.45 reinoud if (flags == 0) 6261 1.45 reinoud return 0; 6262 1.19 reinoud 6263 1.45 reinoud /* determine if we need to write sync or async */ 6264 1.45 reinoud waitfor = 0; 6265 1.45 reinoud if ((flags & IN_MODIFIED) && (mnt_async == 0)) { 6266 1.45 reinoud /* sync mounted */ 6267 1.45 reinoud waitfor = updflags & UPDATE_WAIT; 6268 1.45 reinoud if (updflags & UPDATE_DIROP) 6269 1.45 reinoud waitfor |= UPDATE_WAIT; 6270 1.9 christos } 6271 1.45 reinoud if (waitfor) 6272 1.45 reinoud return VOP_FSYNC(vp, FSCRED, FSYNC_WAIT, 0,0); 6273 1.1 reinoud 6274 1.45 reinoud return 0; 6275 1.1 reinoud } 6276 1.1 reinoud 6277 1.45 reinoud 6278 1.1 reinoud /* --------------------------------------------------------------------- */ 6279 1.1 reinoud 6280 1.59 reinoud 6281 1.1 reinoud /* 6282 1.1 reinoud * Read one fid and process it into a dirent and advance to the next (*fid) 6283 1.1 reinoud * has to be allocated a logical block in size, (*dirent) struct dirent length 6284 1.1 reinoud */ 6285 1.1 reinoud 6286 1.1 reinoud int 6287 1.1 reinoud udf_read_fid_stream(struct vnode *vp, uint64_t *offset, 6288 1.97 reinoud struct fileid_desc *fid, struct dirent *dirent) 6289 1.1 reinoud { 6290 1.1 reinoud struct udf_node *dir_node = VTOI(vp); 6291 1.1 reinoud struct udf_mount *ump = dir_node->ump; 6292 1.45 reinoud struct file_entry *fe = dir_node->fe; 6293 1.45 reinoud struct extfile_entry *efe = dir_node->efe; 6294 1.45 reinoud uint32_t fid_size, lb_size; 6295 1.1 reinoud uint64_t file_size; 6296 1.1 reinoud char *fid_name; 6297 1.1 reinoud int enough, error; 6298 1.1 reinoud 6299 1.1 reinoud assert(fid); 6300 1.1 reinoud assert(dirent); 6301 1.1 reinoud assert(dir_node); 6302 1.1 reinoud assert(offset); 6303 1.1 reinoud assert(*offset != 1); 6304 1.1 reinoud 6305 1.45 reinoud DPRINTF(FIDS, ("read_fid_stream called at offset %"PRIu64"\n", *offset)); 6306 1.1 reinoud /* check if we're past the end of the directory */ 6307 1.45 reinoud if (fe) { 6308 1.1 reinoud file_size = udf_rw64(fe->inf_len); 6309 1.1 reinoud } else { 6310 1.1 reinoud assert(dir_node->efe); 6311 1.1 reinoud file_size = udf_rw64(efe->inf_len); 6312 1.9 christos } 6313 1.1 reinoud if (*offset >= file_size) 6314 1.1 reinoud return EINVAL; 6315 1.1 reinoud 6316 1.1 reinoud /* get maximum length of FID descriptor */ 6317 1.1 reinoud lb_size = udf_rw32(ump->logical_vol->lb_size); 6318 1.1 reinoud 6319 1.1 reinoud /* initialise return values */ 6320 1.45 reinoud fid_size = 0; 6321 1.1 reinoud memset(dirent, 0, sizeof(struct dirent)); 6322 1.1 reinoud memset(fid, 0, lb_size); 6323 1.1 reinoud 6324 1.45 reinoud enough = (file_size - (*offset) >= UDF_FID_SIZE); 6325 1.45 reinoud if (!enough) { 6326 1.45 reinoud /* short dir ... */ 6327 1.45 reinoud return EIO; 6328 1.45 reinoud } 6329 1.1 reinoud 6330 1.45 reinoud error = vn_rdwr(UIO_READ, vp, 6331 1.45 reinoud fid, MIN(file_size - (*offset), lb_size), *offset, 6332 1.45 reinoud UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, FSCRED, 6333 1.45 reinoud NULL, NULL); 6334 1.1 reinoud if (error) 6335 1.1 reinoud return error; 6336 1.1 reinoud 6337 1.45 reinoud DPRINTF(FIDS, ("\tfid piece read in fine\n")); 6338 1.1 reinoud /* 6339 1.1 reinoud * Check if we got a whole descriptor. 6340 1.45 reinoud * TODO Try to `resync' directory stream when something is very wrong. 6341 1.1 reinoud */ 6342 1.1 reinoud 6343 1.1 reinoud /* check if our FID header is OK */ 6344 1.1 reinoud error = udf_check_tag(fid); 6345 1.45 reinoud if (error) { 6346 1.45 reinoud goto brokendir; 6347 1.9 christos } 6348 1.45 reinoud DPRINTF(FIDS, ("\ttag check ok\n")); 6349 1.1 reinoud 6350 1.45 reinoud if (udf_rw16(fid->tag.id) != TAGID_FID) { 6351 1.45 reinoud error = EIO; 6352 1.45 reinoud goto brokendir; 6353 1.9 christos } 6354 1.45 reinoud DPRINTF(FIDS, ("\ttag checked ok: got TAGID_FID\n")); 6355 1.1 reinoud 6356 1.45 reinoud /* check for length */ 6357 1.45 reinoud fid_size = udf_fidsize(fid); 6358 1.45 reinoud enough = (file_size - (*offset) >= fid_size); 6359 1.1 reinoud if (!enough) { 6360 1.45 reinoud error = EIO; 6361 1.45 reinoud goto brokendir; 6362 1.9 christos } 6363 1.45 reinoud DPRINTF(FIDS, ("\tthe complete fid is read in\n")); 6364 1.1 reinoud 6365 1.1 reinoud /* check FID contents */ 6366 1.45 reinoud error = udf_check_tag_payload((union dscrptr *) fid, lb_size); 6367 1.45 reinoud brokendir: 6368 1.1 reinoud if (error) { 6369 1.1 reinoud /* note that is sometimes a bit quick to report */ 6370 1.84 pooka printf("UDF: BROKEN DIRECTORY ENTRY\n"); 6371 1.1 reinoud /* RESYNC? */ 6372 1.1 reinoud /* TODO: use udf_resync_fid_stream */ 6373 1.1 reinoud return EIO; 6374 1.9 christos } 6375 1.45 reinoud DPRINTF(FIDS, ("\tpayload checked ok\n")); 6376 1.1 reinoud 6377 1.1 reinoud /* we got a whole and valid descriptor! */ 6378 1.45 reinoud DPRINTF(FIDS, ("\tinterpret FID\n")); 6379 1.1 reinoud 6380 1.1 reinoud /* create resulting dirent structure */ 6381 1.1 reinoud fid_name = (char *) fid->data + udf_rw16(fid->l_iu); 6382 1.117 christos udf_to_unix_name(dirent->d_name, NAME_MAX, 6383 1.1 reinoud fid_name, fid->l_fi, &ump->logical_vol->desc_charset); 6384 1.1 reinoud 6385 1.1 reinoud /* '..' has no name, so provide one */ 6386 1.1 reinoud if (fid->file_char & UDF_FILE_CHAR_PAR) 6387 1.1 reinoud strcpy(dirent->d_name, ".."); 6388 1.1 reinoud 6389 1.98 reinoud dirent->d_fileno = udf_get_node_id(&fid->icb); /* inode hash XXX */ 6390 1.1 reinoud dirent->d_namlen = strlen(dirent->d_name); 6391 1.1 reinoud dirent->d_reclen = _DIRENT_SIZE(dirent); 6392 1.1 reinoud 6393 1.1 reinoud /* 6394 1.1 reinoud * Note that its not worth trying to go for the filetypes now... its 6395 1.1 reinoud * too expensive too 6396 1.1 reinoud */ 6397 1.1 reinoud dirent->d_type = DT_UNKNOWN; 6398 1.1 reinoud 6399 1.1 reinoud /* initial guess for filetype we can make */ 6400 1.1 reinoud if (fid->file_char & UDF_FILE_CHAR_DIR) 6401 1.1 reinoud dirent->d_type = DT_DIR; 6402 1.1 reinoud 6403 1.1 reinoud /* advance */ 6404 1.45 reinoud *offset += fid_size; 6405 1.1 reinoud 6406 1.1 reinoud return error; 6407 1.1 reinoud } 6408 1.1 reinoud 6409 1.45 reinoud 6410 1.45 reinoud /* --------------------------------------------------------------------- */ 6411 1.45 reinoud 6412 1.45 reinoud static void 6413 1.132 hannken udf_sync_pass(struct udf_mount *ump, kauth_cred_t cred, int pass, int *ndirty) 6414 1.45 reinoud { 6415 1.45 reinoud struct udf_node *udf_node, *n_udf_node; 6416 1.45 reinoud struct vnode *vp; 6417 1.45 reinoud int vdirty, error; 6418 1.45 reinoud 6419 1.132 hannken KASSERT(mutex_owned(&ump->sync_lock)); 6420 1.45 reinoud 6421 1.45 reinoud DPRINTF(SYNC, ("sync_pass %d\n", pass)); 6422 1.108 rmind udf_node = RB_TREE_MIN(&ump->udf_node_tree); 6423 1.45 reinoud for (;udf_node; udf_node = n_udf_node) { 6424 1.45 reinoud DPRINTF(SYNC, (".")); 6425 1.45 reinoud 6426 1.45 reinoud vp = udf_node->vnode; 6427 1.45 reinoud 6428 1.108 rmind n_udf_node = rb_tree_iterate(&ump->udf_node_tree, 6429 1.108 rmind udf_node, RB_DIR_RIGHT); 6430 1.98 reinoud 6431 1.130 riastrad error = vn_lock(vp, LK_EXCLUSIVE | LK_NOWAIT); 6432 1.130 riastrad if (error) { 6433 1.130 riastrad KASSERT(error == EBUSY); 6434 1.130 riastrad *ndirty += 1; 6435 1.130 riastrad continue; 6436 1.130 riastrad } 6437 1.45 reinoud 6438 1.45 reinoud switch (pass) { 6439 1.45 reinoud case 1: 6440 1.45 reinoud VOP_FSYNC(vp, cred, 0 | FSYNC_DATAONLY,0,0); 6441 1.45 reinoud break; 6442 1.45 reinoud case 2: 6443 1.45 reinoud vdirty = vp->v_numoutput; 6444 1.45 reinoud if (vp->v_tag == VT_UDF) 6445 1.45 reinoud vdirty += udf_node->outstanding_bufs + 6446 1.45 reinoud udf_node->outstanding_nodedscr; 6447 1.45 reinoud if (vdirty == 0) 6448 1.45 reinoud VOP_FSYNC(vp, cred, 0,0,0); 6449 1.45 reinoud *ndirty += vdirty; 6450 1.45 reinoud break; 6451 1.45 reinoud case 3: 6452 1.45 reinoud vdirty = vp->v_numoutput; 6453 1.45 reinoud if (vp->v_tag == VT_UDF) 6454 1.45 reinoud vdirty += udf_node->outstanding_bufs + 6455 1.45 reinoud udf_node->outstanding_nodedscr; 6456 1.45 reinoud *ndirty += vdirty; 6457 1.45 reinoud break; 6458 1.45 reinoud } 6459 1.45 reinoud 6460 1.132 hannken VOP_UNLOCK(vp); 6461 1.45 reinoud } 6462 1.45 reinoud DPRINTF(SYNC, ("END sync_pass %d\n", pass)); 6463 1.45 reinoud } 6464 1.45 reinoud 6465 1.45 reinoud 6466 1.132 hannken static bool 6467 1.132 hannken udf_sync_selector(void *cl, struct vnode *vp) 6468 1.132 hannken { 6469 1.139 riastrad struct udf_node *udf_node; 6470 1.139 riastrad 6471 1.139 riastrad KASSERT(mutex_owned(vp->v_interlock)); 6472 1.139 riastrad 6473 1.139 riastrad udf_node = VTOI(vp); 6474 1.132 hannken 6475 1.132 hannken if (vp->v_vflag & VV_SYSTEM) 6476 1.132 hannken return false; 6477 1.132 hannken if (vp->v_type == VNON) 6478 1.132 hannken return false; 6479 1.132 hannken if (udf_node == NULL) 6480 1.132 hannken return false; 6481 1.132 hannken if ((udf_node->i_flags & (IN_ACCESSED | IN_UPDATE | IN_MODIFIED)) == 0) 6482 1.132 hannken return false; 6483 1.149 ad if (LIST_EMPTY(&vp->v_dirtyblkhd) && (vp->v_iflag & VI_ONWORKLST) == 0) 6484 1.132 hannken return false; 6485 1.132 hannken 6486 1.132 hannken return true; 6487 1.132 hannken } 6488 1.132 hannken 6489 1.45 reinoud void 6490 1.45 reinoud udf_do_sync(struct udf_mount *ump, kauth_cred_t cred, int waitfor) 6491 1.45 reinoud { 6492 1.132 hannken struct vnode_iterator *marker; 6493 1.132 hannken struct vnode *vp; 6494 1.132 hannken struct udf_node *udf_node, *udf_next_node; 6495 1.45 reinoud int dummy, ndirty; 6496 1.45 reinoud 6497 1.132 hannken if (waitfor == MNT_LAZY) 6498 1.132 hannken return; 6499 1.132 hannken 6500 1.132 hannken mutex_enter(&ump->sync_lock); 6501 1.132 hannken 6502 1.132 hannken /* Fill the rbtree with nodes to sync. */ 6503 1.132 hannken vfs_vnode_iterator_init(ump->vfs_mountp, &marker); 6504 1.132 hannken while ((vp = vfs_vnode_iterator_next(marker, 6505 1.132 hannken udf_sync_selector, NULL)) != NULL) { 6506 1.132 hannken udf_node = VTOI(vp); 6507 1.132 hannken udf_node->i_flags |= IN_SYNCED; 6508 1.132 hannken rb_tree_insert_node(&ump->udf_node_tree, udf_node); 6509 1.132 hannken } 6510 1.132 hannken vfs_vnode_iterator_destroy(marker); 6511 1.132 hannken 6512 1.45 reinoud dummy = 0; 6513 1.45 reinoud DPRINTF(CALL, ("issue VOP_FSYNC(DATA only) on all nodes\n")); 6514 1.45 reinoud DPRINTF(SYNC, ("issue VOP_FSYNC(DATA only) on all nodes\n")); 6515 1.132 hannken udf_sync_pass(ump, cred, 1, &dummy); 6516 1.45 reinoud 6517 1.45 reinoud DPRINTF(CALL, ("issue VOP_FSYNC(COMPLETE) on all finished nodes\n")); 6518 1.45 reinoud DPRINTF(SYNC, ("issue VOP_FSYNC(COMPLETE) on all finished nodes\n")); 6519 1.132 hannken udf_sync_pass(ump, cred, 2, &dummy); 6520 1.45 reinoud 6521 1.45 reinoud if (waitfor == MNT_WAIT) { 6522 1.132 hannken recount: 6523 1.45 reinoud ndirty = ump->devvp->v_numoutput; 6524 1.77 reinoud DPRINTF(SYNC, ("counting pending blocks: on devvp %d\n", 6525 1.45 reinoud ndirty)); 6526 1.132 hannken udf_sync_pass(ump, cred, 3, &ndirty); 6527 1.77 reinoud DPRINTF(SYNC, ("counted num dirty pending blocks %d\n", 6528 1.45 reinoud ndirty)); 6529 1.152 skrll 6530 1.45 reinoud if (ndirty) { 6531 1.45 reinoud /* 1/4 second wait */ 6532 1.131 hannken kpause("udfsync2", false, hz/4, NULL); 6533 1.45 reinoud goto recount; 6534 1.45 reinoud } 6535 1.45 reinoud } 6536 1.45 reinoud 6537 1.132 hannken /* Clean the rbtree. */ 6538 1.132 hannken for (udf_node = RB_TREE_MIN(&ump->udf_node_tree); 6539 1.132 hannken udf_node; udf_node = udf_next_node) { 6540 1.132 hannken udf_next_node = rb_tree_iterate(&ump->udf_node_tree, 6541 1.132 hannken udf_node, RB_DIR_RIGHT); 6542 1.132 hannken rb_tree_remove_node(&ump->udf_node_tree, udf_node); 6543 1.132 hannken udf_node->i_flags &= ~IN_SYNCED; 6544 1.132 hannken vrele(udf_node->vnode); 6545 1.132 hannken } 6546 1.132 hannken 6547 1.132 hannken mutex_exit(&ump->sync_lock); 6548 1.45 reinoud } 6549 1.45 reinoud 6550 1.1 reinoud /* --------------------------------------------------------------------- */ 6551 1.1 reinoud 6552 1.1 reinoud /* 6553 1.45 reinoud * Read and write file extent in/from the buffer. 6554 1.45 reinoud * 6555 1.146 msaitoh * The splitup of the extent into separate request-buffers is to minimise 6556 1.45 reinoud * copying around as much as possible. 6557 1.45 reinoud * 6558 1.1 reinoud * block based file reading and writing 6559 1.1 reinoud */ 6560 1.1 reinoud 6561 1.1 reinoud static int 6562 1.1 reinoud udf_read_internal(struct udf_node *node, uint8_t *blob) 6563 1.1 reinoud { 6564 1.1 reinoud struct udf_mount *ump; 6565 1.45 reinoud struct file_entry *fe = node->fe; 6566 1.45 reinoud struct extfile_entry *efe = node->efe; 6567 1.1 reinoud uint64_t inflen; 6568 1.1 reinoud uint32_t sector_size; 6569 1.135 dholland uint8_t *srcpos; 6570 1.1 reinoud int icbflags, addr_type; 6571 1.1 reinoud 6572 1.1 reinoud /* get extent and do some paranoia checks */ 6573 1.1 reinoud ump = node->ump; 6574 1.1 reinoud sector_size = ump->discinfo.sector_size; 6575 1.1 reinoud 6576 1.135 dholland /* 6577 1.135 dholland * XXX there should be real bounds-checking logic here, 6578 1.135 dholland * in case ->l_ea or ->inf_len contains nonsense. 6579 1.135 dholland */ 6580 1.135 dholland 6581 1.1 reinoud if (fe) { 6582 1.1 reinoud inflen = udf_rw64(fe->inf_len); 6583 1.135 dholland srcpos = &fe->data[0] + udf_rw32(fe->l_ea); 6584 1.1 reinoud icbflags = udf_rw16(fe->icbtag.flags); 6585 1.45 reinoud } else { 6586 1.45 reinoud assert(node->efe); 6587 1.1 reinoud inflen = udf_rw64(efe->inf_len); 6588 1.135 dholland srcpos = &efe->data[0] + udf_rw32(efe->l_ea); 6589 1.1 reinoud icbflags = udf_rw16(efe->icbtag.flags); 6590 1.9 christos } 6591 1.1 reinoud addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 6592 1.1 reinoud 6593 1.1 reinoud assert(addr_type == UDF_ICB_INTERN_ALLOC); 6594 1.124 christos __USE(addr_type); 6595 1.1 reinoud assert(inflen < sector_size); 6596 1.1 reinoud 6597 1.1 reinoud /* copy out info */ 6598 1.135 dholland memcpy(blob, srcpos, inflen); 6599 1.134 christos memset(&blob[inflen], 0, sector_size - inflen); 6600 1.1 reinoud 6601 1.1 reinoud return 0; 6602 1.1 reinoud } 6603 1.1 reinoud 6604 1.1 reinoud 6605 1.45 reinoud static int 6606 1.45 reinoud udf_write_internal(struct udf_node *node, uint8_t *blob) 6607 1.1 reinoud { 6608 1.45 reinoud struct udf_mount *ump; 6609 1.45 reinoud struct file_entry *fe = node->fe; 6610 1.45 reinoud struct extfile_entry *efe = node->efe; 6611 1.45 reinoud uint64_t inflen; 6612 1.1 reinoud uint32_t sector_size; 6613 1.45 reinoud uint8_t *pos; 6614 1.45 reinoud int icbflags, addr_type; 6615 1.45 reinoud 6616 1.45 reinoud /* get extent and do some paranoia checks */ 6617 1.45 reinoud ump = node->ump; 6618 1.45 reinoud sector_size = ump->discinfo.sector_size; 6619 1.1 reinoud 6620 1.45 reinoud if (fe) { 6621 1.45 reinoud inflen = udf_rw64(fe->inf_len); 6622 1.45 reinoud pos = &fe->data[0] + udf_rw32(fe->l_ea); 6623 1.45 reinoud icbflags = udf_rw16(fe->icbtag.flags); 6624 1.45 reinoud } else { 6625 1.45 reinoud assert(node->efe); 6626 1.45 reinoud inflen = udf_rw64(efe->inf_len); 6627 1.45 reinoud pos = &efe->data[0] + udf_rw32(efe->l_ea); 6628 1.45 reinoud icbflags = udf_rw16(efe->icbtag.flags); 6629 1.45 reinoud } 6630 1.45 reinoud addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 6631 1.1 reinoud 6632 1.45 reinoud assert(addr_type == UDF_ICB_INTERN_ALLOC); 6633 1.124 christos __USE(addr_type); 6634 1.45 reinoud assert(inflen < sector_size); 6635 1.124 christos __USE(sector_size); 6636 1.1 reinoud 6637 1.45 reinoud /* copy in blob */ 6638 1.45 reinoud /* memset(pos, 0, inflen); */ 6639 1.45 reinoud memcpy(pos, blob, inflen); 6640 1.1 reinoud 6641 1.45 reinoud return 0; 6642 1.1 reinoud } 6643 1.1 reinoud 6644 1.1 reinoud 6645 1.1 reinoud void 6646 1.45 reinoud udf_read_filebuf(struct udf_node *udf_node, struct buf *buf) 6647 1.1 reinoud { 6648 1.1 reinoud struct buf *nestbuf; 6649 1.45 reinoud struct udf_mount *ump = udf_node->ump; 6650 1.10 christos uint64_t *mapping; 6651 1.1 reinoud uint64_t run_start; 6652 1.1 reinoud uint32_t sector_size; 6653 1.1 reinoud uint32_t buf_offset, sector, rbuflen, rblk; 6654 1.45 reinoud uint32_t from, lblkno; 6655 1.45 reinoud uint32_t sectors; 6656 1.1 reinoud uint8_t *buf_pos; 6657 1.95 reinoud int error, run_length, what; 6658 1.1 reinoud 6659 1.45 reinoud sector_size = udf_node->ump->discinfo.sector_size; 6660 1.1 reinoud 6661 1.1 reinoud from = buf->b_blkno; 6662 1.1 reinoud sectors = buf->b_bcount / sector_size; 6663 1.1 reinoud 6664 1.95 reinoud what = udf_get_c_type(udf_node); 6665 1.45 reinoud 6666 1.1 reinoud /* assure we have enough translation slots */ 6667 1.45 reinoud KASSERT(buf->b_bcount / sector_size <= UDF_MAX_MAPPINGS); 6668 1.45 reinoud KASSERT(MAXPHYS / sector_size <= UDF_MAX_MAPPINGS); 6669 1.1 reinoud 6670 1.45 reinoud if (sectors > UDF_MAX_MAPPINGS) { 6671 1.1 reinoud printf("udf_read_filebuf: implementation limit on bufsize\n"); 6672 1.1 reinoud buf->b_error = EIO; 6673 1.1 reinoud biodone(buf); 6674 1.1 reinoud return; 6675 1.9 christos } 6676 1.1 reinoud 6677 1.45 reinoud mapping = malloc(sizeof(*mapping) * UDF_MAX_MAPPINGS, M_TEMP, M_WAITOK); 6678 1.10 christos 6679 1.1 reinoud error = 0; 6680 1.1 reinoud DPRINTF(READ, ("\ttranslate %d-%d\n", from, sectors)); 6681 1.45 reinoud error = udf_translate_file_extent(udf_node, from, sectors, mapping); 6682 1.1 reinoud if (error) { 6683 1.1 reinoud buf->b_error = error; 6684 1.1 reinoud biodone(buf); 6685 1.10 christos goto out; 6686 1.9 christos } 6687 1.1 reinoud DPRINTF(READ, ("\ttranslate extent went OK\n")); 6688 1.1 reinoud 6689 1.45 reinoud /* pre-check if its an internal */ 6690 1.1 reinoud if (*mapping == UDF_TRANS_INTERN) { 6691 1.45 reinoud error = udf_read_internal(udf_node, (uint8_t *) buf->b_data); 6692 1.45 reinoud if (error) 6693 1.1 reinoud buf->b_error = error; 6694 1.1 reinoud biodone(buf); 6695 1.10 christos goto out; 6696 1.9 christos } 6697 1.1 reinoud DPRINTF(READ, ("\tnot intern\n")); 6698 1.1 reinoud 6699 1.45 reinoud #ifdef DEBUG 6700 1.45 reinoud if (udf_verbose & UDF_DEBUG_TRANSLATE) { 6701 1.45 reinoud printf("Returned translation table:\n"); 6702 1.45 reinoud for (sector = 0; sector < sectors; sector++) { 6703 1.45 reinoud printf("%d : %"PRIu64"\n", sector, mapping[sector]); 6704 1.45 reinoud } 6705 1.45 reinoud } 6706 1.45 reinoud #endif 6707 1.45 reinoud 6708 1.176 andvar /* request read-in of data from disc scheduler */ 6709 1.1 reinoud buf->b_resid = buf->b_bcount; 6710 1.1 reinoud for (sector = 0; sector < sectors; sector++) { 6711 1.1 reinoud buf_offset = sector * sector_size; 6712 1.1 reinoud buf_pos = (uint8_t *) buf->b_data + buf_offset; 6713 1.1 reinoud DPRINTF(READ, ("\tprocessing rel sector %d\n", sector)); 6714 1.1 reinoud 6715 1.45 reinoud /* check if its zero or unmapped to stop reading */ 6716 1.1 reinoud switch (mapping[sector]) { 6717 1.1 reinoud case UDF_TRANS_UNMAPPED: 6718 1.1 reinoud case UDF_TRANS_ZERO: 6719 1.45 reinoud /* copy zero sector TODO runlength like below */ 6720 1.1 reinoud memset(buf_pos, 0, sector_size); 6721 1.1 reinoud DPRINTF(READ, ("\treturning zero sector\n")); 6722 1.1 reinoud nestiobuf_done(buf, sector_size, 0); 6723 1.1 reinoud break; 6724 1.1 reinoud default : 6725 1.1 reinoud DPRINTF(READ, ("\tread sector " 6726 1.1 reinoud "%"PRIu64"\n", mapping[sector])); 6727 1.1 reinoud 6728 1.45 reinoud lblkno = from + sector; 6729 1.1 reinoud run_start = mapping[sector]; 6730 1.1 reinoud run_length = 1; 6731 1.1 reinoud while (sector < sectors-1) { 6732 1.1 reinoud if (mapping[sector+1] != mapping[sector]+1) 6733 1.1 reinoud break; 6734 1.1 reinoud run_length++; 6735 1.1 reinoud sector++; 6736 1.9 christos } 6737 1.1 reinoud 6738 1.1 reinoud /* 6739 1.1 reinoud * nest an iobuf and mark it for async reading. Since 6740 1.1 reinoud * we're using nested buffers, they can't be cached by 6741 1.1 reinoud * design. 6742 1.1 reinoud */ 6743 1.1 reinoud rbuflen = run_length * sector_size; 6744 1.1 reinoud rblk = run_start * (sector_size/DEV_BSIZE); 6745 1.1 reinoud 6746 1.44 ad nestbuf = getiobuf(NULL, true); 6747 1.1 reinoud nestiobuf_setup(buf, nestbuf, buf_offset, rbuflen); 6748 1.1 reinoud /* nestbuf is B_ASYNC */ 6749 1.1 reinoud 6750 1.45 reinoud /* identify this nestbuf */ 6751 1.45 reinoud nestbuf->b_lblkno = lblkno; 6752 1.45 reinoud assert(nestbuf->b_vp == udf_node->vnode); 6753 1.45 reinoud 6754 1.176 andvar /* CD schedules on raw blkno */ 6755 1.45 reinoud nestbuf->b_blkno = rblk; 6756 1.45 reinoud nestbuf->b_proc = NULL; 6757 1.45 reinoud nestbuf->b_rawblkno = rblk; 6758 1.45 reinoud nestbuf->b_udf_c_type = what; 6759 1.45 reinoud 6760 1.45 reinoud udf_discstrat_queuebuf(ump, nestbuf); 6761 1.9 christos } 6762 1.9 christos } 6763 1.10 christos out: 6764 1.45 reinoud /* if we're synchronously reading, wait for the completion */ 6765 1.45 reinoud if ((buf->b_flags & B_ASYNC) == 0) 6766 1.45 reinoud biowait(buf); 6767 1.45 reinoud 6768 1.1 reinoud DPRINTF(READ, ("\tend of read_filebuf\n")); 6769 1.45 reinoud free(mapping, M_TEMP); 6770 1.10 christos return; 6771 1.1 reinoud } 6772 1.1 reinoud 6773 1.1 reinoud 6774 1.45 reinoud void 6775 1.45 reinoud udf_write_filebuf(struct udf_node *udf_node, struct buf *buf) 6776 1.45 reinoud { 6777 1.45 reinoud struct buf *nestbuf; 6778 1.45 reinoud struct udf_mount *ump = udf_node->ump; 6779 1.45 reinoud uint64_t *mapping; 6780 1.45 reinoud uint64_t run_start; 6781 1.45 reinoud uint32_t lb_size; 6782 1.45 reinoud uint32_t buf_offset, lb_num, rbuflen, rblk; 6783 1.45 reinoud uint32_t from, lblkno; 6784 1.45 reinoud uint32_t num_lb; 6785 1.95 reinoud int error, run_length, what, s; 6786 1.45 reinoud 6787 1.45 reinoud lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); 6788 1.45 reinoud 6789 1.45 reinoud from = buf->b_blkno; 6790 1.45 reinoud num_lb = buf->b_bcount / lb_size; 6791 1.1 reinoud 6792 1.95 reinoud what = udf_get_c_type(udf_node); 6793 1.70 reinoud 6794 1.45 reinoud /* assure we have enough translation slots */ 6795 1.45 reinoud KASSERT(buf->b_bcount / lb_size <= UDF_MAX_MAPPINGS); 6796 1.45 reinoud KASSERT(MAXPHYS / lb_size <= UDF_MAX_MAPPINGS); 6797 1.1 reinoud 6798 1.45 reinoud if (num_lb > UDF_MAX_MAPPINGS) { 6799 1.45 reinoud printf("udf_write_filebuf: implementation limit on bufsize\n"); 6800 1.45 reinoud buf->b_error = EIO; 6801 1.45 reinoud biodone(buf); 6802 1.45 reinoud return; 6803 1.45 reinoud } 6804 1.1 reinoud 6805 1.45 reinoud mapping = malloc(sizeof(*mapping) * UDF_MAX_MAPPINGS, M_TEMP, M_WAITOK); 6806 1.1 reinoud 6807 1.45 reinoud error = 0; 6808 1.45 reinoud DPRINTF(WRITE, ("\ttranslate %d-%d\n", from, num_lb)); 6809 1.45 reinoud error = udf_translate_file_extent(udf_node, from, num_lb, mapping); 6810 1.45 reinoud if (error) { 6811 1.45 reinoud buf->b_error = error; 6812 1.45 reinoud biodone(buf); 6813 1.45 reinoud goto out; 6814 1.9 christos } 6815 1.45 reinoud DPRINTF(WRITE, ("\ttranslate extent went OK\n")); 6816 1.45 reinoud 6817 1.45 reinoud /* if its internally mapped, we can write it in the descriptor itself */ 6818 1.45 reinoud if (*mapping == UDF_TRANS_INTERN) { 6819 1.45 reinoud /* TODO paranoia check if we ARE going to have enough space */ 6820 1.45 reinoud error = udf_write_internal(udf_node, (uint8_t *) buf->b_data); 6821 1.45 reinoud if (error) 6822 1.45 reinoud buf->b_error = error; 6823 1.45 reinoud biodone(buf); 6824 1.45 reinoud goto out; 6825 1.9 christos } 6826 1.45 reinoud DPRINTF(WRITE, ("\tnot intern\n")); 6827 1.45 reinoud 6828 1.176 andvar /* request write out of data to disc scheduler */ 6829 1.45 reinoud buf->b_resid = buf->b_bcount; 6830 1.45 reinoud for (lb_num = 0; lb_num < num_lb; lb_num++) { 6831 1.45 reinoud buf_offset = lb_num * lb_size; 6832 1.45 reinoud DPRINTF(WRITE, ("\tprocessing rel lb_num %d\n", lb_num)); 6833 1.45 reinoud 6834 1.45 reinoud /* 6835 1.45 reinoud * Mappings are not that important here. Just before we write 6836 1.45 reinoud * the lb_num we late-allocate them when needed and update the 6837 1.45 reinoud * mapping in the udf_node. 6838 1.45 reinoud */ 6839 1.45 reinoud 6840 1.45 reinoud /* XXX why not ignore the mapping altogether ? */ 6841 1.45 reinoud DPRINTF(WRITE, ("\twrite lb_num " 6842 1.45 reinoud "%"PRIu64, mapping[lb_num])); 6843 1.45 reinoud 6844 1.45 reinoud lblkno = from + lb_num; 6845 1.45 reinoud run_start = mapping[lb_num]; 6846 1.45 reinoud run_length = 1; 6847 1.45 reinoud while (lb_num < num_lb-1) { 6848 1.45 reinoud if (mapping[lb_num+1] != mapping[lb_num]+1) 6849 1.45 reinoud if (mapping[lb_num+1] != mapping[lb_num]) 6850 1.45 reinoud break; 6851 1.45 reinoud run_length++; 6852 1.45 reinoud lb_num++; 6853 1.45 reinoud } 6854 1.45 reinoud DPRINTF(WRITE, ("+ %d\n", run_length)); 6855 1.1 reinoud 6856 1.45 reinoud /* nest an iobuf on the master buffer for the extent */ 6857 1.45 reinoud rbuflen = run_length * lb_size; 6858 1.45 reinoud rblk = run_start * (lb_size/DEV_BSIZE); 6859 1.1 reinoud 6860 1.45 reinoud nestbuf = getiobuf(NULL, true); 6861 1.45 reinoud nestiobuf_setup(buf, nestbuf, buf_offset, rbuflen); 6862 1.45 reinoud /* nestbuf is B_ASYNC */ 6863 1.45 reinoud 6864 1.45 reinoud /* identify this nestbuf */ 6865 1.45 reinoud nestbuf->b_lblkno = lblkno; 6866 1.45 reinoud KASSERT(nestbuf->b_vp == udf_node->vnode); 6867 1.45 reinoud 6868 1.176 andvar /* CD schedules on raw blkno */ 6869 1.45 reinoud nestbuf->b_blkno = rblk; 6870 1.45 reinoud nestbuf->b_proc = NULL; 6871 1.45 reinoud nestbuf->b_rawblkno = rblk; 6872 1.45 reinoud nestbuf->b_udf_c_type = what; 6873 1.45 reinoud 6874 1.45 reinoud /* increment our outstanding bufs counter */ 6875 1.45 reinoud s = splbio(); 6876 1.45 reinoud udf_node->outstanding_bufs++; 6877 1.45 reinoud splx(s); 6878 1.1 reinoud 6879 1.45 reinoud udf_discstrat_queuebuf(ump, nestbuf); 6880 1.9 christos } 6881 1.45 reinoud out: 6882 1.45 reinoud /* if we're synchronously writing, wait for the completion */ 6883 1.45 reinoud if ((buf->b_flags & B_ASYNC) == 0) 6884 1.45 reinoud biowait(buf); 6885 1.45 reinoud 6886 1.45 reinoud DPRINTF(WRITE, ("\tend of write_filebuf\n")); 6887 1.45 reinoud free(mapping, M_TEMP); 6888 1.45 reinoud return; 6889 1.1 reinoud } 6890 1.1 reinoud 6891 1.1 reinoud /* --------------------------------------------------------------------- */ 6892