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