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