main.c revision 1.2 1 /* $NetBSD: main.c,v 1.2 2022/04/06 13:42:39 wiz Exp $ */
2
3 /*
4 * Copyright (c) 2022 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 /*
31 * Note to reader:
32 *
33 * fsck_udf uses the common udf_core.c file with newfs and makefs. It does use
34 * some of the layout structure values but not all.
35 */
36
37
38 #include <sys/cdefs.h>
39 #ifndef lint
40 __RCSID("$NetBSD: main.c,v 1.2 2022/04/06 13:42:39 wiz Exp $");
41 #endif /* not lint */
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <stddef.h>
46 #include <dirent.h>
47 #include <inttypes.h>
48 #include <stdint.h>
49 #include <string.h>
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <unistd.h>
53 #include <util.h>
54 #include <time.h>
55 #include <tzfile.h>
56 #include <math.h>
57 #include <assert.h>
58 #include <err.h>
59
60 #if !HAVE_NBTOOL_CONFIG_H
61 #define _EXPOSE_MMC
62 #include <sys/cdio.h>
63 #else
64 #include "udf/cdio_mmc_structs.h"
65 #endif
66
67 #include <sys/ioctl.h>
68 #include <sys/stat.h>
69 #include <sys/types.h>
70 #include <sys/disklabel.h>
71 #include <sys/dkio.h>
72 #include <sys/param.h>
73 #include <sys/queue.h>
74
75 #include <fs/udf/ecma167-udf.h>
76 #include <fs/udf/udf_mount.h>
77
78 #include "fsutil.h"
79 #include "exitvalues.h"
80 #include "udf_core.h"
81
82 /* Identifying myself */
83 #define IMPL_NAME "*NetBSD fsck_udf 10.0"
84 #define APP_VERSION_MAIN 0
85 #define APP_VERSION_SUB 5
86
87 /* allocation walker actions */
88 #define AD_LOAD_FILE (1<<0)
89 #define AD_SAVE_FILE (1<<1)
90 #define AD_CHECK_FIDS (1<<2)
91 #define AD_ADJUST_FIDS (1<<3)
92 #define AD_GATHER_STATS (1<<4)
93 #define AD_CHECK_USED (1<<5)
94 #define AD_MARK_AS_USED (1<<6)
95 #define AD_FIND_OVERLAP_PAIR (1<<7)
96
97 struct udf_fsck_file_stats {
98 uint64_t inf_len;
99 uint64_t obj_size;
100 uint64_t logblks_rec;
101 };
102
103
104 struct udf_fsck_fid_context {
105 uint64_t fid_offset;
106 uint64_t data_left;
107 };
108
109
110 /* basic node administration for passes */
111 #define FSCK_NODE_FLAG_HARDLINK (1<< 0) /* hardlink, for accounting */
112 #define FSCK_NODE_FLAG_DIRECTORY (1<< 1) /* is a normal directory */
113 #define FSCK_NODE_FLAG_HAS_STREAM_DIR (1<< 2) /* has a stream directory */
114 #define FSCK_NODE_FLAG_STREAM_ENTRY (1<< 3) /* is a stream file */
115 #define FSCK_NODE_FLAG_STREAM_DIR (1<< 4) /* is a stream directory */
116 #define FSCK_NODE_FLAG_OK(f) (((f) >> 5) == 0)
117
118 #define FSCK_NODE_FLAG_KEEP (1<< 5) /* don't discard */
119 #define FSCK_NODE_FLAG_DIRTY (1<< 6) /* descriptor needs writeout */
120 #define FSCK_NODE_FLAG_REPAIRDIR (1<< 7) /* repair bad FID entries */
121 #define FSCK_NODE_FLAG_NEW_UNIQUE_ID (1<< 8) /* repair bad FID entries */
122 #define FSCK_NODE_FLAG_COPY_PARENT_ID (1<< 9) /* repair bad FID entries */
123 #define FSCK_NODE_FLAG_WIPE_STREAM_DIR (1<<10) /* wipe stream directory */
124 #define FSCK_NODE_FLAG_NOTFOUND (1<<11) /* FID pointing to garbage */
125 #define FSCK_NODE_FLAG_PAR_NOT_FOUND (1<<12) /* parent node not found! */
126 #define FSCK_NODE_FLAG_OVERLAP (1<<13) /* node has overlaps */
127
128 #define FSCK_NODE_FLAG_STREAM (FSCK_NODE_FLAG_STREAM_ENTRY | FSCK_NODE_FLAG_STREAM_DIR)
129
130
131 #define HASH_HASHBITS 5
132 #define HASH_HASHSIZE (1 << HASH_HASHBITS)
133 #define HASH_HASHMASK (HASH_HASHSIZE - 1)
134
135 /* fsck node for accounting checks */
136 struct udf_fsck_node {
137 struct udf_fsck_node *parent;
138 char *fname;
139
140 struct long_ad loc;
141 struct long_ad streamdir_loc;
142 int fsck_flags;
143
144 int link_count;
145 int found_link_count;
146 uint64_t unique_id;
147
148 struct udf_fsck_file_stats declared;
149 struct udf_fsck_file_stats found;
150
151 uint8_t *directory; /* directory contents */
152
153 LIST_ENTRY(udf_fsck_node) next_hash;
154 TAILQ_ENTRY(udf_fsck_node) next;
155 };
156 TAILQ_HEAD(udf_fsck_node_list, udf_fsck_node) fs_nodes;
157 LIST_HEAD(udf_fsck_node_hash_list, udf_fsck_node) fs_nodes_hash[HASH_HASHSIZE];
158
159
160 /* fsck used space bitmap conflict list */
161 #define FSCK_OVERLAP_MAIN_NODE (1<<0)
162 #define FSCK_OVERLAP_EXTALLOC (1<<1)
163 #define FSCK_OVERLAP_EXTENT (1<<2)
164
165 struct udf_fsck_overlap {
166 struct udf_fsck_node *node;
167 struct udf_fsck_node *node2;
168
169 struct long_ad loc;
170 struct long_ad loc2;
171
172 int flags;
173 int flags2;
174
175 TAILQ_ENTRY(udf_fsck_overlap) next;
176 };
177 TAILQ_HEAD(udf_fsck_overlap_list, udf_fsck_overlap) fsck_overlaps;
178
179
180 /* backup of old read in free space bitmaps */
181 struct space_bitmap_desc *recorded_part_unalloc_bits[UDF_PARTITIONS];
182 uint32_t recorded_part_free[UDF_PARTITIONS];
183
184 /* shadow VAT build */
185 uint8_t *shadow_vat_contents;
186
187
188 /* options */
189 int alwaysno = 0; /* assume "no" for all questions */
190 int alwaysyes = 0; /* assume "yes" for all questions */
191 int search_older_vat = 0; /* search for older VATs */
192 int force = 0; /* do check even if its marked clean */
193 int preen = 0; /* set when preening, doing automatic small repairs */
194 int rdonly = 0; /* open device/image read-only */
195 int rdonly_flag = 0; /* as passed on command line */
196 int heuristics = 0; /* use heuristics to fix esoteric corruptions */
197 int target_session = 0; /* offset to last session to check */
198
199
200 /* actions to undertake */
201 int undo_opening_session = 0; /* trying to undo opening of last crippled session */
202 int open_integrity = 0; /* should be open the integrity ie close later */
203 int vat_writeout = 0; /* write out the VAT anyway */
204
205
206 /* SIGINFO */
207 static sig_atomic_t print_info = 0; /* request for information on progress */
208
209
210 /* prototypes */
211 static void usage(void) __dead;
212 static int checkfilesys(char *given_dev);
213 static int ask(int def, const char *fmt, ...);
214 static int ask_noauto(int def, const char *fmt, ...);
215
216 static void udf_recursive_keep(struct udf_fsck_node *node);
217 static char *udf_node_path(struct udf_fsck_node *node);
218 static void udf_shadow_VAT_in_use(struct long_ad *loc);
219 static int udf_quick_check_fids(struct udf_fsck_node *node, union dscrptr *dscr);
220
221
222 /* --------------------------------------------------------------------- */
223
224 /* from bin/ls */
225 static void
226 printtime(time_t ftime)
227 {
228 struct timespec clock;
229 const char *longstring;
230 time_t now;
231 int i;
232
233 clock_gettime(CLOCK_REALTIME, &clock);
234 now = clock.tv_sec;
235
236 if ((longstring = ctime(&ftime)) == NULL) {
237 /* 012345678901234567890123 */
238 longstring = "????????????????????????";
239 }
240 for (i = 4; i < 11; ++i)
241 (void)putchar(longstring[i]);
242
243 #define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
244 if (ftime + SIXMONTHS > now && ftime - SIXMONTHS < now)
245 for (i = 11; i < 16; ++i)
246 (void)putchar(longstring[i]);
247 else {
248 (void)putchar(' ');
249 for (i = 20; i < 24; ++i)
250 (void)putchar(longstring[i]);
251 }
252 (void)putchar(' ');
253 }
254
255
256 static void
257 udf_print_timestamp(const char *prefix, struct timestamp *timestamp, const char *suffix)
258 {
259 struct timespec timespec;
260
261 udf_timestamp_to_timespec(timestamp, ×pec);
262 printf("%s", prefix);
263 printtime(timespec.tv_sec);
264 printf("%s", suffix);
265 }
266
267
268 static int
269 udf_compare_mtimes(struct timestamp *t1, struct timestamp *t2)
270 {
271 struct timespec t1_tsp, t2_tsp;
272
273 udf_timestamp_to_timespec(t1, &t1_tsp);
274 udf_timestamp_to_timespec(t2, &t2_tsp);
275
276 if (t1_tsp.tv_sec < t2_tsp.tv_sec)
277 return -1;
278 if (t1_tsp.tv_sec > t2_tsp.tv_sec)
279 return 1;
280 if (t1_tsp.tv_nsec < t2_tsp.tv_nsec)
281 return -1;
282 if (t1_tsp.tv_nsec > t2_tsp.tv_nsec)
283 return 1;
284 return 0;
285 }
286
287 /* --------------------------------------------------------------------- */
288
289 static int
290 udf_calc_node_hash(struct long_ad *icb)
291 {
292 uint32_t lb_num = udf_rw32(icb->loc.lb_num);
293 uint16_t vpart = udf_rw16(icb->loc.part_num);
294
295 return ((uint64_t) (vpart + lb_num * 257)) & HASH_HASHMASK;
296 }
297
298
299 static struct udf_fsck_node *
300 udf_node_lookup(struct long_ad *icb)
301 {
302 struct udf_fsck_node *pos;
303 int entry = udf_calc_node_hash(icb);
304
305 pos = LIST_FIRST(&fs_nodes_hash[entry]);
306 while (pos) {
307 if (pos->loc.loc.part_num == icb->loc.part_num)
308 if (pos->loc.loc.lb_num == icb->loc.lb_num)
309 return pos;
310 pos = LIST_NEXT(pos, next_hash);
311 }
312 return NULL;
313 }
314
315 /* --------------------------------------------------------------------- */
316
317 /* Note: only for VAT media since we don't allocate in bitmap */
318 static void
319 udf_wipe_and_reallocate(union dscrptr *dscrptr, int vpart_num, uint32_t *l_adp)
320 {
321 struct file_entry *fe = &dscrptr->fe;
322 struct extfile_entry *efe = &dscrptr->efe;
323 struct desc_tag *tag = &dscrptr->tag;
324 struct icb_tag *icb;
325 struct long_ad allocated;
326 struct long_ad *long_adp = NULL;
327 struct short_ad *short_adp = NULL;
328 uint64_t inf_len;
329 uint32_t l_ea, l_ad;
330 uint8_t *bpos;
331 int bpos_start, ad_type, id;
332
333 assert(context.format_flags & FORMAT_VAT);
334
335 id = udf_rw16(tag->id);
336 assert(id == TAGID_FENTRY || id == TAGID_EXTFENTRY);
337 if (id == TAGID_FENTRY) {
338 icb = &fe->icbtag;
339 inf_len = udf_rw64(fe->inf_len);
340 l_ea = udf_rw32(fe->l_ea);
341 bpos = (uint8_t *) fe->data + l_ea;
342 bpos_start = offsetof(struct file_entry, data) + l_ea;
343 } else {
344 icb = &efe->icbtag;
345 inf_len = udf_rw64(efe->inf_len);
346 l_ea = udf_rw32(efe->l_ea);
347 bpos = (uint8_t *) efe->data + l_ea;
348 bpos_start = offsetof(struct extfile_entry, data) + l_ea;
349 }
350 /* inf_len should be correct for one slot */
351 assert(inf_len < UDF_EXT_MAXLEN);
352
353 ad_type = udf_rw16(icb->flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
354 if (ad_type == UDF_ICB_INTERN_ALLOC) {
355 /* no action needed */
356 return;
357 }
358
359 assert(vpart_num == context.data_part);
360 udf_data_alloc(udf_bytes_to_sectors(inf_len), &allocated);
361 memset(bpos, 0, context.sector_size - bpos_start);
362 /* create one short_ad or one long_ad */
363 if (ad_type == UDF_ICB_SHORT_ALLOC) {
364 short_adp = (struct short_ad *) bpos;
365 short_adp->len = udf_rw64(inf_len);
366 short_adp->lb_num = allocated.loc.lb_num;
367 l_ad = sizeof(struct short_ad);
368 } else {
369 long_adp = (struct long_ad *) bpos;
370 memcpy(long_adp, &allocated, sizeof(struct long_ad));
371 long_adp->len = udf_rw64(inf_len);
372 l_ad = sizeof(struct long_ad);
373 }
374 if (id == TAGID_FENTRY)
375 fe->l_ad = udf_rw32(l_ad);
376 else
377 efe->l_ad = udf_rw32(l_ad);
378 ;
379 *l_adp = l_ad;
380 }
381
382
383 static void
384 udf_copy_fid_verbatim(struct fileid_desc *sfid, struct fileid_desc *dfid,
385 uint64_t dfpos, uint64_t drest)
386 {
387 uint64_t endfid;
388 uint32_t minlen, lb_rest, fidsize;
389
390 if (udf_rw16(sfid->l_iu) == 0) {
391 memcpy(dfid, sfid, udf_fidsize(sfid));
392 return;
393 }
394
395 /* see if we can reduce its size */
396 minlen = udf_fidsize(sfid) - udf_rw16(sfid->l_iu);
397
398 /*
399 * OK, tricky part: we need to pad so the next descriptor header won't
400 * cross the sector boundary
401 */
402 endfid = dfpos + minlen;
403 lb_rest = context.sector_size - (endfid % context.sector_size);
404
405 memcpy(dfid, sfid, UDF_FID_SIZE);
406 if (lb_rest < sizeof(struct desc_tag)) {
407 /* add at least 32 */
408 dfid->l_iu = udf_rw16(32);
409 udf_set_regid((struct regid *) dfid->data, context.impl_name);
410 udf_add_impl_regid((struct regid *) dfid->data);
411
412 }
413 memcpy( dfid->data + udf_rw16(dfid->l_iu),
414 sfid->data + udf_rw16(sfid->l_iu),
415 minlen - UDF_FID_SIZE);
416
417 fidsize = udf_fidsize(dfid);
418 dfid->tag.desc_crc_len = udf_rw16(fidsize - UDF_DESC_TAG_LENGTH);
419 }
420
421
422 static int
423 udf_rebuild_fid_stream(struct udf_fsck_node *node, int64_t *rest_lenp)
424 {
425 struct fileid_desc *sfid, *dfid;
426 uint64_t inf_len;
427 uint64_t sfpos, dfpos;
428 int64_t srest, drest;
429 // uint32_t sfid_len, dfid_len;
430 uint8_t *directory, *rebuild_dir;
431 // int namelen;
432 int error, streaming, was_streaming, warned, error_in_stream;
433
434 directory = node->directory;
435 inf_len = node->found.inf_len;
436
437 rebuild_dir = calloc(1, inf_len);
438 assert(rebuild_dir);
439
440 sfpos = 0;
441 srest = inf_len;
442
443 dfpos = 0;
444 drest = inf_len;
445
446 error_in_stream = 0;
447 streaming = 1;
448 was_streaming = 1;
449 warned = 0;
450 while (srest > 0) {
451 if (was_streaming & !streaming) {
452 if (!warned) {
453 pwarn("%s : BROKEN directory\n",
454 udf_node_path(node));
455 udf_recursive_keep(node);
456 node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
457 }
458 warned = 1;
459 pwarn("%s : <directory resync>\n",
460 udf_node_path(node));
461 }
462 was_streaming = streaming;
463
464 assert(drest >= UDF_FID_SIZE);
465 sfid = (struct fileid_desc *) (directory + sfpos);
466 dfid = (struct fileid_desc *) (rebuild_dir + dfpos);
467
468 /* check if we can read/salvage the next source fid */
469 if (udf_rw16(sfid->tag.id) != TAGID_FID) {
470 streaming = 0;
471 sfpos += 4;
472 srest -= 4;
473 error_in_stream = 1;
474 continue;
475 }
476 error = udf_check_tag(sfid);
477 if (error) {
478 /* unlikely to be recoverable */
479 streaming = 0;
480 sfpos += 4;
481 srest -= 4;
482 error_in_stream = 1;
483 continue;
484 }
485 error = udf_check_tag_payload(
486 (union dscrptr *) sfid,
487 context.sector_size);
488 if (!error) {
489 streaming = 1;
490 /* all OK, just copy verbatim, shrinking if possible */
491 udf_copy_fid_verbatim(sfid, dfid, dfpos, drest);
492
493 sfpos += udf_fidsize(sfid);
494 srest -= udf_fidsize(sfid);
495
496 dfpos += udf_fidsize(dfid);
497 drest -= udf_fidsize(dfid);
498
499 assert(udf_fidsize(sfid) == udf_fidsize(dfid));
500 continue;
501 }
502
503 /*
504 * The hard part, we need to try to recover of what is
505 * deductible of the bad source fid. The tag itself is OK, but
506 * that doesn't say much; its contents can still be off.
507 */
508
509 /* TODO NOT IMPLEMENTED YET, skip this entry the blunt way */
510 streaming = 0;
511 sfpos += 4;
512 srest -= 4;
513 error_in_stream = 1;
514 }
515
516 /* if we could shrink/fix the node, mark it for repair */
517 if (error_in_stream) {
518 udf_recursive_keep(node);
519 node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
520 }
521
522 if (sfpos != dfpos)
523 printf("%s: could save %ld bytes in directory\n", udf_node_path(node), sfpos - dfpos);
524
525 memset(directory, 0, inf_len);
526 memcpy(directory, rebuild_dir, dfpos);
527
528 free(rebuild_dir);
529
530 *rest_lenp = dfpos;
531 return error_in_stream;
532 }
533
534
535 static int
536 udf_quick_check_fids_piece(uint8_t *piece, uint32_t piece_len,
537 struct udf_fsck_fid_context *fid_context,
538 uint32_t lb_num)
539 {
540 int error;
541 struct fileid_desc *fid;
542 uint32_t location;
543 uint32_t offset, fidsize;
544
545 offset = fid_context->fid_offset % context.sector_size;
546 while (fid_context->data_left && (offset < piece_len)) {
547 fid = (struct fileid_desc *) (piece + offset);
548 if (udf_rw16(fid->tag.id) == TAGID_FID) {
549 error = udf_check_tag_payload(
550 (union dscrptr *) fid,
551 context.sector_size);
552 if (error)
553 return error;
554 } else {
555 return EINVAL;
556 }
557 assert(udf_rw16(fid->tag.id) == TAGID_FID);
558
559 location = lb_num + offset / context.sector_size;
560
561 if (udf_rw32(fid->tag.tag_loc) != location)
562 return EINVAL;
563
564 if (context.dscrver == 2) {
565 /* compression IDs should be preserved in UDF < 2.00 */
566 if (*(fid->data + udf_rw16(fid->l_iu)) > 16)
567 return EINVAL;
568 }
569
570 fidsize = udf_fidsize(fid);
571 offset += fidsize;
572 fid_context->fid_offset += fidsize;
573 fid_context->data_left -= fidsize;
574 }
575
576 return 0;
577 }
578
579
580 static void
581 udf_fids_fixup(uint8_t *piece, uint32_t piece_len,
582 struct udf_fsck_fid_context *fid_context,
583 uint32_t lb_num)
584 {
585 struct fileid_desc *fid;
586 uint32_t location;
587 uint32_t offset, fidsize;
588
589 offset = fid_context->fid_offset % context.sector_size;
590 while (fid_context->data_left && (offset < piece_len)) {
591
592 fid = (struct fileid_desc *) (piece + offset);
593 assert(udf_rw16(fid->tag.id) == TAGID_FID);
594
595 location = lb_num + offset / context.sector_size;
596 fid->tag.tag_loc = udf_rw32(location);
597
598 udf_validate_tag_and_crc_sums((union dscrptr *) fid);
599
600 fidsize = udf_fidsize(fid);
601 offset += fidsize;
602 fid_context->fid_offset += fidsize;
603 fid_context->data_left -= fidsize;
604 }
605 }
606
607
608 /* NOTE returns non 0 for overlap, not an error code */
609 static int
610 udf_check_if_allocated(struct udf_fsck_node *node, int flags,
611 uint32_t start_lb, int partnr, uint32_t piece_len)
612 {
613 union dscrptr *dscr;
614 struct udf_fsck_overlap *new_overlap;
615 uint8_t *bpos;
616 uint32_t cnt, bit;
617 uint32_t blocks = udf_bytes_to_sectors(piece_len);
618 int overlap = 0;
619
620 /* account for space used on underlying partition */
621 #ifdef DEBUG
622 printf("check allocated : node %p, flags %d, partnr %d, start_lb %d for %d blocks\n",
623 node, flags, partnr, start_lb, blocks);
624 #endif
625
626 switch (context.vtop_tp[partnr]) {
627 case UDF_VTOP_TYPE_VIRT:
628 /* nothing */
629 break;
630 case UDF_VTOP_TYPE_PHYS:
631 case UDF_VTOP_TYPE_SPAREABLE:
632 case UDF_VTOP_TYPE_META:
633 if (context.part_unalloc_bits[context.vtop[partnr]] == NULL)
634 break;
635 #ifdef DEBUG
636 printf("checking allocation of %d+%d for being used\n", start_lb, blocks);
637 #endif
638 dscr = (union dscrptr *) (context.part_unalloc_bits[partnr]);
639 for (cnt = start_lb; cnt < start_lb + blocks; cnt++) {
640 bpos = &dscr->sbd.data[cnt / 8];
641 bit = cnt % 8;
642 /* only account for bits marked free */
643 if ((*bpos & (1 << bit)) == 0)
644 overlap++;
645 }
646 if (overlap == 0)
647 break;
648
649 /* overlap */
650 // pwarn("%s allocation OVERLAP found, type %d\n",
651 // udf_node_path(node), flags);
652 udf_recursive_keep(node);
653 node->fsck_flags |= FSCK_NODE_FLAG_OVERLAP;
654
655 new_overlap = calloc(1, sizeof(struct udf_fsck_overlap));
656 assert(new_overlap);
657
658 new_overlap->node = node;
659 new_overlap->node2 = NULL;
660 new_overlap->flags = flags;
661 new_overlap->flags2 = 0;
662 new_overlap->loc.len = udf_rw32(piece_len);
663 new_overlap->loc.loc.lb_num = udf_rw32(start_lb);
664 new_overlap->loc.loc.part_num = udf_rw16(partnr);
665
666 TAILQ_INSERT_TAIL(&fsck_overlaps, new_overlap, next);
667
668 return overlap;
669 break;
670 default:
671 errx(1, "internal error: bad mapping type %d in %s",
672 context.vtop_tp[partnr], __func__);
673 }
674 /* no overlap */
675 return 0;
676 }
677
678
679 /* NOTE returns non 0 for overlap, not an error code */
680 static void
681 udf_check_overlap_pair(struct udf_fsck_node *node, int flags,
682 uint32_t start_lb, int partnr, uint32_t piece_len)
683 {
684 struct udf_fsck_overlap *overlap;
685 uint32_t ostart_lb, opiece_len, oblocks;
686 uint32_t blocks = udf_bytes_to_sectors(piece_len);
687 int opartnr;
688
689 /* account for space used on underlying partition */
690 #ifdef DEBUG
691 printf("check overlap pair : node %p, flags %d, partnr %d, start_lb %d for %d blocks\n",
692 node, flags, partnr, start_lb, blocks);
693 #endif
694
695 switch (context.vtop_tp[partnr]) {
696 case UDF_VTOP_TYPE_VIRT:
697 /* nothing */
698 break;
699 case UDF_VTOP_TYPE_PHYS:
700 case UDF_VTOP_TYPE_SPAREABLE:
701 case UDF_VTOP_TYPE_META:
702 if (context.part_unalloc_bits[context.vtop[partnr]] == NULL)
703 break;
704 #ifdef DEBUG
705 printf("checking overlap of %d+%d for being used\n", start_lb, blocks);
706 #endif
707 /* check all current overlaps with the piece we have here */
708 TAILQ_FOREACH(overlap, &fsck_overlaps, next) {
709 opiece_len = udf_rw32(overlap->loc.len);
710 ostart_lb = udf_rw32(overlap->loc.loc.lb_num);
711 opartnr = udf_rw16(overlap->loc.loc.part_num);
712 oblocks = udf_bytes_to_sectors(opiece_len);
713
714 if (partnr != opartnr)
715 continue;
716 /* piece before overlap? */
717 if (start_lb + blocks < ostart_lb)
718 continue;
719 /* piece after overlap? */
720 if (start_lb > ostart_lb + oblocks)
721 continue;
722
723 /* overlap, mark conflict */
724 overlap->node2 = node;
725 overlap->flags2 = flags;
726 overlap->loc2.len = udf_rw32(piece_len);
727 overlap->loc2.loc.lb_num = udf_rw32(start_lb);
728 overlap->loc2.loc.part_num = udf_rw16(partnr);
729
730 udf_recursive_keep(node);
731 node->fsck_flags |= FSCK_NODE_FLAG_OVERLAP;
732 }
733 return;
734 default:
735 errx(1, "internal error: bad mapping type %d in %s",
736 context.vtop_tp[partnr], __func__);
737 }
738 /* no overlap */
739 return;
740 }
741
742
743
744 static int
745 udf_process_ad(union dscrptr *dscrptr, int action, uint8_t **resultp,
746 int vpart_num, uint64_t fpos,
747 struct short_ad *short_adp, struct long_ad *long_adp, void *process_context)
748 {
749 struct file_entry *fe = &dscrptr->fe;
750 struct extfile_entry *efe = &dscrptr->efe;
751 struct desc_tag *tag = &dscrptr->tag;
752 struct icb_tag *icb;
753 struct udf_fsck_file_stats *stats;
754 uint64_t inf_len;
755 uint32_t l_ea, piece_len, piece_alloc_len, piece_sectors, lb_num, flags;
756 uint32_t dscr_lb_num;
757 uint32_t i;
758 uint8_t *bpos, *piece;
759 int id, ad_type;
760 int error, piece_error, return_error;
761
762 assert(dscrptr);
763 stats = (struct udf_fsck_file_stats *) process_context;
764
765 id = udf_rw16(tag->id);
766 assert(id == TAGID_FENTRY || id == TAGID_EXTFENTRY);
767 if (id == TAGID_FENTRY) {
768 icb = &fe->icbtag;
769 dscr_lb_num = udf_rw32(fe->tag.tag_loc);
770 inf_len = udf_rw64(fe->inf_len);
771 l_ea = udf_rw32(fe->l_ea);
772 bpos = (uint8_t *) fe->data + l_ea;
773 } else {
774 icb = &efe->icbtag;
775 dscr_lb_num = udf_rw32(efe->tag.tag_loc);
776 inf_len = udf_rw64(efe->inf_len);
777 l_ea = udf_rw32(efe->l_ea);
778 bpos = (uint8_t *) efe->data + l_ea;
779 }
780
781 lb_num = 0;
782 piece_len = 0;
783
784 ad_type = udf_rw16(icb->flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
785 if (ad_type == UDF_ICB_INTERN_ALLOC) {
786 piece_len = inf_len;
787 }
788 if (short_adp) {
789 piece_len = udf_rw32(short_adp->len);
790 lb_num = udf_rw32(short_adp->lb_num);
791 }
792 if (long_adp) {
793 piece_len = udf_rw32(long_adp->len);
794 lb_num = udf_rw32(long_adp->loc.lb_num);
795 vpart_num = udf_rw16(long_adp->loc.part_num);
796 }
797 flags = UDF_EXT_FLAGS(piece_len);
798 piece_len = UDF_EXT_LEN(piece_len);
799 piece_alloc_len = UDF_ROUNDUP(piece_len, context.sector_size);
800 piece_sectors = piece_alloc_len / context.sector_size;
801
802 return_error = 0;
803 if (action & AD_GATHER_STATS) {
804 if (ad_type == UDF_ICB_INTERN_ALLOC) {
805 stats->inf_len = piece_len;
806 stats->obj_size = piece_len;
807 stats->logblks_rec = 0;
808 } else if (flags == UDF_EXT_ALLOCATED) {
809 stats->inf_len += piece_len;
810 stats->obj_size += piece_len;
811 stats->logblks_rec += piece_sectors;
812 } else if (flags == UDF_EXT_FREED) {
813 stats->inf_len += piece_len;
814 stats->obj_size += piece_len;
815 stats->logblks_rec += piece_sectors;
816 } else if (flags == UDF_EXT_FREE) {
817 stats->inf_len += piece_len;
818 stats->obj_size += piece_len;
819 }
820 }
821 if (action & AD_LOAD_FILE) {
822 uint32_t alloc_len;
823
824 piece = calloc(1, piece_alloc_len);
825 if (piece == NULL)
826 return errno;
827 if (ad_type == UDF_ICB_INTERN_ALLOC) {
828 memcpy(piece, bpos, piece_len);
829 } else if (flags == 0) {
830 /* not empty */
831 /* read sector by sector reading as much as possible */
832 for (i = 0; i < piece_sectors; i++) {
833 piece_error = udf_read_virt(
834 piece + i * context.sector_size,
835 lb_num + i, vpart_num, 1);
836 if (piece_error)
837 return_error = piece_error;
838 }
839 }
840
841 alloc_len = UDF_ROUNDUP(fpos + piece_len, context.sector_size);
842 error = reallocarr(resultp, 1, alloc_len);
843 if (error) {
844 /* fatal */
845 free(piece);
846 free(*resultp);
847 return errno;
848 }
849
850 memcpy(*resultp + fpos, piece, piece_alloc_len);
851 free(piece);
852 }
853 if (action & AD_ADJUST_FIDS) {
854 piece = *resultp + fpos;
855 if (ad_type == UDF_ICB_INTERN_ALLOC) {
856 udf_fids_fixup(piece, piece_len, process_context,
857 dscr_lb_num);
858 } else if (flags == 0) {
859 udf_fids_fixup(piece, piece_len, process_context,
860 lb_num);
861 }
862 }
863 if (action & AD_CHECK_FIDS) {
864 piece = *resultp + fpos;
865 if (ad_type == UDF_ICB_INTERN_ALLOC) {
866 error = udf_quick_check_fids_piece(piece, piece_len,
867 process_context, dscr_lb_num);
868 } else if (flags == 0) {
869 error = udf_quick_check_fids_piece(piece, piece_len,
870 process_context, lb_num);
871 }
872 if (error)
873 return error;
874 }
875 if (action & AD_SAVE_FILE) {
876 /*
877 * Note: only used for directory contents.
878 */
879 piece = *resultp + fpos;
880 if (ad_type == UDF_ICB_INTERN_ALLOC) {
881 memcpy(bpos, piece, piece_len);
882 /* nothing */
883 } else if (flags == 0) {
884 /* not empty */
885 error = udf_write_virt(
886 piece, lb_num, vpart_num,
887 piece_sectors);
888 if (error) {
889 pwarn("Got error writing piece\n");
890 return error;
891 }
892 } else {
893 /* allocated but not written piece, skip */
894 }
895 }
896 if (action & AD_CHECK_USED) {
897 if (ad_type == UDF_ICB_INTERN_ALLOC) {
898 /* nothing */
899 } else if (flags != UDF_EXT_FREE) {
900 struct udf_fsck_node *node = process_context;
901 (void) udf_check_if_allocated(
902 node,
903 FSCK_OVERLAP_EXTENT,
904 lb_num, vpart_num,
905 piece_len);
906 }
907 }
908 if (action & AD_FIND_OVERLAP_PAIR) {
909 if (ad_type == UDF_ICB_INTERN_ALLOC) {
910 /* nothing */
911 } else if (flags != UDF_EXT_FREE) {
912 struct udf_fsck_node *node = process_context;
913 udf_check_overlap_pair(
914 node,
915 FSCK_OVERLAP_EXTENT,
916 lb_num, vpart_num,
917 piece_len);
918 }
919 }
920 if (action & AD_MARK_AS_USED) {
921 if (ad_type == UDF_ICB_INTERN_ALLOC) {
922 /* nothing */
923 } else if (flags != UDF_EXT_FREE) {
924 udf_mark_allocated(lb_num, vpart_num,
925 udf_bytes_to_sectors(piece_len));
926 }
927 }
928
929 return return_error;
930 }
931
932
933 static int
934 udf_process_file(union dscrptr *dscrptr, int vpart_num, uint8_t **resultp,
935 int action, void *process_context)
936 {
937 struct file_entry *fe = &dscrptr->fe;
938 struct extfile_entry *efe = &dscrptr->efe;
939 struct desc_tag *tag = &dscrptr->tag;
940 struct alloc_ext_entry *ext;
941 struct icb_tag *icb;
942 struct long_ad *long_adp = NULL;
943 struct short_ad *short_adp = NULL;
944 union dscrptr *extdscr = NULL;
945 uint64_t fpos;
946 uint32_t l_ad, l_ea, piece_len, lb_num, flags;
947 uint8_t *bpos;
948 int id, extid, ad_type, ad_len;
949 int error;
950
951 id = udf_rw16(tag->id);
952 assert(id == TAGID_FENTRY || id == TAGID_EXTFENTRY);
953
954 if (action & AD_CHECK_USED) {
955 struct udf_fsck_node *node = process_context;
956 (void) udf_check_if_allocated(
957 node,
958 FSCK_OVERLAP_MAIN_NODE,
959 udf_rw32(node->loc.loc.lb_num),
960 udf_rw16(node->loc.loc.part_num),
961 context.sector_size);
962 /* return error code? */
963 }
964
965 if (action & AD_FIND_OVERLAP_PAIR) {
966 struct udf_fsck_node *node = process_context;
967 udf_check_overlap_pair(
968 node,
969 FSCK_OVERLAP_MAIN_NODE,
970 udf_rw32(node->loc.loc.lb_num),
971 udf_rw16(node->loc.loc.part_num),
972 context.sector_size);
973 /* return error code? */
974 }
975
976 if (action & AD_MARK_AS_USED)
977 udf_mark_allocated(udf_rw32(tag->tag_loc), vpart_num, 1);
978
979 if (id == TAGID_FENTRY) {
980 icb = &fe->icbtag;
981 l_ad = udf_rw32(fe->l_ad);
982 l_ea = udf_rw32(fe->l_ea);
983 bpos = (uint8_t *) fe->data + l_ea;
984 } else {
985 icb = &efe->icbtag;
986 l_ad = udf_rw32(efe->l_ad);
987 l_ea = udf_rw32(efe->l_ea);
988 bpos = (uint8_t *) efe->data + l_ea;
989 }
990
991 ad_type = udf_rw16(icb->flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
992 if (ad_type == UDF_ICB_INTERN_ALLOC) {
993 error = udf_process_ad(dscrptr, action, resultp, -1, 0,
994 NULL, NULL, process_context);
995 return error;
996 }
997 if ((ad_type != UDF_ICB_SHORT_ALLOC) &&
998 (ad_type != UDF_ICB_LONG_ALLOC))
999 return EINVAL;
1000
1001 if (ad_type == UDF_ICB_SHORT_ALLOC)
1002 short_adp = (struct short_ad *) bpos;
1003 else
1004 long_adp = (struct long_ad *) bpos;
1005 ;
1006
1007 if (action & AD_SAVE_FILE) {
1008 /*
1009 * Special case for writeout file/directory on recordable
1010 * media. We write in one go so wipe and (re)allocate the
1011 * entire space.
1012 */
1013 if (context.format_flags & FORMAT_VAT)
1014 udf_wipe_and_reallocate(dscrptr, vpart_num, &l_ad);
1015 }
1016
1017 fpos = 0;
1018 bpos = NULL;
1019 error = 0;
1020 while (l_ad) {
1021 if (ad_type == UDF_ICB_SHORT_ALLOC) {
1022 piece_len = udf_rw32(short_adp->len);
1023 lb_num = udf_rw32(short_adp->lb_num);
1024 ad_len = sizeof(struct short_ad);
1025 } else /* UDF_ICB_LONG_ALLOC */ {
1026 piece_len = udf_rw32(long_adp->len);
1027 lb_num = udf_rw32(long_adp->loc.lb_num);
1028 vpart_num = udf_rw16(long_adp->loc.part_num);
1029 ad_len = sizeof(struct long_ad);
1030 }
1031 flags = UDF_EXT_FLAGS(piece_len);
1032 piece_len = UDF_EXT_LEN(piece_len);
1033
1034 switch (flags) {
1035 default :
1036 error = udf_process_ad(dscrptr, action, resultp,
1037 vpart_num, fpos, short_adp, long_adp,
1038 process_context);
1039 break;
1040 case UDF_EXT_REDIRECT :
1041 if (piece_len != context.sector_size) {
1042 /* should this be an error? */
1043 pwarn("Got extension redirect with wrong size %d\n",
1044 piece_len);
1045 error = EINVAL;
1046 break;
1047 }
1048 free(extdscr);
1049 error = udf_read_dscr_virt(lb_num, vpart_num, &extdscr);
1050 if (error)
1051 break;
1052 /* empty block is terminator */
1053 if (extdscr == NULL)
1054 return 0;
1055 ext = &extdscr->aee;
1056 extid = udf_rw16(ext->tag.id);
1057 if (extid != TAGID_ALLOCEXTENT) {
1058 pwarn("Corruption in allocated extents chain\n");
1059 /* corruption! */
1060 free(extdscr);
1061 errno = EINVAL;
1062 break;
1063 }
1064
1065 if (action & AD_CHECK_USED) {
1066 (void) udf_check_if_allocated(
1067 (struct udf_fsck_node *) process_context,
1068 FSCK_OVERLAP_EXTALLOC,
1069 lb_num,
1070 vpart_num,
1071 context.sector_size);
1072 /* returning error code ? */
1073 }
1074
1075 if (action & AD_FIND_OVERLAP_PAIR) {
1076 struct udf_fsck_node *node = process_context;
1077 udf_check_overlap_pair(
1078 node,
1079 FSCK_OVERLAP_EXTALLOC,
1080 lb_num,
1081 vpart_num,
1082 context.sector_size);
1083 /* return error code? */
1084 }
1085
1086 if (action & AD_MARK_AS_USED)
1087 udf_mark_allocated(
1088 lb_num, vpart_num,
1089 1);
1090 /* TODO check for prev_entry? */
1091 l_ad = ext->l_ad;
1092 bpos = ext->data;
1093 if (ad_type == UDF_ICB_SHORT_ALLOC)
1094 short_adp = (struct short_ad *) bpos;
1095 else
1096 long_adp = (struct long_ad *) bpos;
1097 ;
1098 continue;
1099 }
1100 if (error)
1101 break;
1102
1103 if (long_adp) long_adp++;
1104 if (short_adp) short_adp++;
1105 fpos += piece_len;
1106 bpos += piece_len;
1107 l_ad -= ad_len;
1108 }
1109
1110 return error;
1111 }
1112
1113
1114 static int
1115 udf_readin_file(union dscrptr *dscrptr, int vpart_num, uint8_t **resultp,
1116 struct udf_fsck_file_stats *statsp)
1117 {
1118 struct udf_fsck_file_stats stats;
1119 int error;
1120
1121 bzero(&stats, sizeof(stats));
1122 *resultp = NULL;
1123 error = udf_process_file(dscrptr, vpart_num, resultp,
1124 AD_LOAD_FILE | AD_GATHER_STATS, (void *) &stats);
1125 if (statsp)
1126 *statsp = stats;
1127 return error;
1128 }
1129
1130 /* --------------------------------------------------------------------- */
1131
1132 #define MAX_BSIZE (0x10000)
1133 #define UDF_ISO_VRS_SIZE (32*2048) /* 32 ISO `sectors' */
1134
1135 static void
1136 udf_check_vrs9660(void)
1137 {
1138 struct vrs_desc *vrs;
1139 uint8_t buffer[MAX_BSIZE];
1140 uint64_t rpos;
1141 uint8_t *pos;
1142 int max_sectors, sector, factor;
1143 int ret, ok;
1144
1145 if (context.format_flags & FORMAT_TRACK512)
1146 return;
1147
1148 /*
1149 * location of iso9660 VRS is defined as first sector AFTER 32kb,
1150 * minimum `sector size' 2048
1151 */
1152 layout.iso9660_vrs = ((32*1024 + context.sector_size - 1) /
1153 context.sector_size);
1154 max_sectors = UDF_ISO_VRS_SIZE / 2048;
1155 factor = (2048 + context.sector_size -1) / context.sector_size;
1156
1157 ok = 1;
1158 rpos = (uint64_t) layout.iso9660_vrs * context.sector_size;
1159 ret = pread(dev_fd, buffer, UDF_ISO_VRS_SIZE, rpos);
1160 if (ret == -1) {
1161 pwarn("Error reading in ISO9660 VRS\n");
1162 ok = 0;
1163 }
1164 if (ok && ((uint32_t) ret != UDF_ISO_VRS_SIZE)) {
1165 pwarn("Short read in ISO9660 VRS\n");
1166 ok = 0;
1167 }
1168
1169 if (ok) {
1170 ok = 0;
1171 for (sector = 0; sector < max_sectors; sector++) {
1172 pos = buffer + sector * factor * context.sector_size;
1173 vrs = (struct vrs_desc *) pos;
1174 if (strncmp((const char *) vrs->identifier, VRS_BEA01, 5) == 0)
1175 ok = 1;
1176 if (strncmp((const char *) vrs->identifier, VRS_NSR02, 5) == 0)
1177 ok |= 2;
1178 if (strncmp((const char *) vrs->identifier, VRS_NSR03, 5) == 0)
1179 ok |= 2;
1180 if (strncmp((const char *) vrs->identifier, VRS_TEA01, 5) == 0) {
1181 ok |= 4;
1182 break;
1183 }
1184 }
1185 if (ok != 7)
1186 ok = 0;
1187 }
1188 if (!ok) {
1189 pwarn("Error in ISO 9660 volume recognition sequence\n");
1190 if (context.format_flags & FORMAT_SEQUENTIAL) {
1191 pwarn("ISO 9660 volume recognition sequence can't be repaired "
1192 "on SEQUENTIAL media\n");
1193 } else if (ask(0, "fix ISO 9660 volume recognition sequence")) {
1194 if (!rdonly)
1195 udf_write_iso9660_vrs();
1196 }
1197 }
1198 }
1199
1200
1201 /*
1202 * Read in disc and try to find basic properties like sector size, expected
1203 * UDF versions etc.
1204 */
1205
1206 static int
1207 udf_find_anchor(int anum)
1208 {
1209 uint8_t buffer[MAX_BSIZE];
1210 struct anchor_vdp *avdp = (struct anchor_vdp *) buffer;
1211 uint64_t rpos;
1212 uint32_t location;
1213 int sz_guess, ret;
1214 int error;
1215
1216 location = layout.anchors[anum];
1217
1218 /*
1219 * Search ADVP by reading bigger and bigger sectors NOTE we can't use
1220 * udf_read_phys yet since the sector size is not known yet
1221 */
1222 sz_guess = mmc_discinfo.sector_size; /* assume media is bigger */
1223 for (; sz_guess <= MAX_BSIZE; sz_guess += 512) {
1224 rpos = (uint64_t) location * sz_guess;
1225 ret = pread(dev_fd, buffer, sz_guess, rpos);
1226 if (ret == -1) {
1227 if (errno == ENODEV)
1228 return errno;
1229 } else if (ret != sz_guess) {
1230 /* most likely EOF, ignore */
1231 } else {
1232 error = udf_check_tag_and_location(buffer, location);
1233 if (!error) {
1234 if (udf_rw16(avdp->tag.id) != TAGID_ANCHOR)
1235 continue;
1236 error = udf_check_tag_payload(buffer, sz_guess);
1237 if (!error)
1238 break;
1239 }
1240 }
1241 }
1242 if (sz_guess > MAX_BSIZE)
1243 return -1;
1244
1245 /* special case for disc images */
1246 if (mmc_discinfo.sector_size != (unsigned int) sz_guess) {
1247 emul_sectorsize = sz_guess;
1248 udf_update_discinfo();
1249 }
1250 context.sector_size = sz_guess;
1251 context.dscrver = udf_rw16(avdp->tag.descriptor_ver);
1252
1253 context.anchors[anum] = calloc(1, context.sector_size);
1254 memcpy(context.anchors[anum], avdp, context.sector_size);
1255
1256 context.min_udf = 0x102;
1257 context.max_udf = 0x150;
1258 if (context.dscrver > 2) {
1259 context.min_udf = 0x200;
1260 context.max_udf = 0x260;
1261 }
1262 return 0;
1263 }
1264
1265
1266 static int
1267 udf_get_anchors(void)
1268 {
1269 struct mmc_trackinfo ti;
1270 struct anchor_vdp *avdp;
1271 int need_fixup, error;
1272
1273 memset(&layout, 0, sizeof(layout));
1274 memset(&ti, 0, sizeof(ti));
1275
1276 /* search start */
1277 for (int i = 1; i <= mmc_discinfo.num_tracks; i++) {
1278 ti.tracknr = i;
1279 error = udf_update_trackinfo(&ti);
1280 assert(!error);
1281 if (ti.sessionnr == target_session)
1282 break;
1283 }
1284 /* support for track 512 */
1285 if (ti.flags & MMC_TRACKINFO_BLANK)
1286 context.format_flags |= FORMAT_TRACK512;
1287
1288 assert(!error);
1289 context.first_ti = ti;
1290
1291 /* search end */
1292 for (int i = mmc_discinfo.num_tracks; i > 0; i--) {
1293 ti.tracknr = i;
1294 error = udf_update_trackinfo(&ti);
1295 assert(!error);
1296 if (ti.sessionnr == target_session)
1297 break;
1298 }
1299 context.last_ti = ti;
1300
1301 layout.first_lba = context.first_ti.track_start;
1302 layout.last_lba = mmc_discinfo.last_possible_lba;
1303 layout.blockingnr = udf_get_blockingnr(&ti);
1304
1305 layout.anchors[0] = layout.first_lba + 256;
1306 if (context.format_flags & FORMAT_TRACK512)
1307 layout.anchors[0] = layout.first_lba + 512;
1308 layout.anchors[1] = layout.last_lba - 256;
1309 layout.anchors[2] = layout.last_lba;
1310
1311 need_fixup = 0;
1312 error = udf_find_anchor(0);
1313 if (error == ENODEV) {
1314 pwarn("Drive empty?\n");
1315 return errno;
1316 }
1317 if (error) {
1318 need_fixup = 1;
1319 if (!preen)
1320 pwarn("Anchor ADVP0 can't be found! Searching others\n");
1321 error = udf_find_anchor(2);
1322 if (error) {
1323 if (!preen)
1324 pwarn("Anchor ADVP2 can't be found! Searching ADVP1\n");
1325 /* this may be fidly, but search */
1326 error = udf_find_anchor(1);
1327 if (error) {
1328 if (!preen)
1329 pwarn("No valid anchors found!\n");
1330 /* TODO scan media for VDS? */
1331 return -1;
1332 }
1333 }
1334 }
1335
1336 if (need_fixup) {
1337 if (context.format_flags & FORMAT_SEQUENTIAL) {
1338 pwarn("Missing primary anchor can't be resolved on "
1339 "SEQUENTIAL media\n");
1340 } else if (ask(1, "Fixup missing anchors")) {
1341 pwarn("TODO fixup missing anchors\n");
1342 need_fixup = 0;
1343 }
1344 if (need_fixup)
1345 return -1;
1346 }
1347 if (!preen)
1348 printf("Filesystem sectorsize is %d bytes.\n\n",
1349 context.sector_size);
1350
1351 /* update our last track info since our idea of sector size might have changed */
1352 (void) udf_update_trackinfo(&context.last_ti);
1353
1354 /* sector size is now known */
1355 wrtrack_skew = context.last_ti.next_writable % layout.blockingnr;
1356
1357 avdp = context.anchors[0];
1358 /* extract info from current anchor */
1359 layout.vds1 = udf_rw32(avdp->main_vds_ex.loc);
1360 layout.vds1_size = udf_rw32(avdp->main_vds_ex.len) / context.sector_size;
1361 layout.vds2 = udf_rw32(avdp->reserve_vds_ex.loc);
1362 layout.vds2_size = udf_rw32(avdp->reserve_vds_ex.len) / context.sector_size;
1363
1364 return 0;
1365 }
1366
1367
1368 #define UDF_LVINT_HIST_CHUNK 32
1369 static void
1370 udf_retrieve_lvint(void) {
1371 union dscrptr *dscr;
1372 struct logvol_int_desc *lvint;
1373 struct udf_lvintq *trace;
1374 uint32_t lbnum, len, *pos;
1375 uint8_t *wpos;
1376 int num_partmappings;
1377 int error, cnt, trace_len;
1378 int sector_size = context.sector_size;
1379
1380 len = udf_rw32(context.logical_vol->integrity_seq_loc.len);
1381 lbnum = udf_rw32(context.logical_vol->integrity_seq_loc.loc);
1382 layout.lvis = lbnum;
1383 layout.lvis_size = len / sector_size;
1384
1385 udf_create_lvintd(UDF_INTEGRITY_OPEN);
1386
1387 /* clean trace and history */
1388 memset(context.lvint_trace, 0,
1389 UDF_LVDINT_SEGMENTS * sizeof(struct udf_lvintq));
1390 context.lvint_history_wpos = 0;
1391 context.lvint_history_len = UDF_LVINT_HIST_CHUNK;
1392 context.lvint_history = calloc(UDF_LVINT_HIST_CHUNK, sector_size);
1393
1394 /* record the length on this segment */
1395 context.lvint_history_ondisc_len = (len / sector_size);
1396
1397 trace_len = 0;
1398 trace = context.lvint_trace;
1399 trace->start = lbnum;
1400 trace->end = lbnum + len/sector_size;
1401 trace->pos = 0;
1402 trace->wpos = 0;
1403
1404 dscr = NULL;
1405 error = 0;
1406 while (len) {
1407 trace->pos = lbnum - trace->start;
1408 trace->wpos = trace->pos + 1;
1409
1410 free(dscr);
1411 error = udf_read_dscr_phys(lbnum, &dscr);
1412 /* bad descriptors mean corruption, terminate */
1413 if (error)
1414 break;
1415
1416 /* empty terminates */
1417 if (dscr == NULL) {
1418 trace->wpos = trace->pos;
1419 break;
1420 }
1421
1422 /* we got a valid descriptor */
1423 if (udf_rw16(dscr->tag.id) == TAGID_TERM) {
1424 trace->wpos = trace->pos;
1425 break;
1426 }
1427 /* only logical volume integrity descriptors are valid */
1428 if (udf_rw16(dscr->tag.id) != TAGID_LOGVOL_INTEGRITY) {
1429 error = ENOENT;
1430 break;
1431 }
1432 lvint = &dscr->lvid;
1433
1434 /* see if our history is long enough, with one spare */
1435 if (context.lvint_history_wpos+2 >= context.lvint_history_len) {
1436 int new_len = context.lvint_history_len +
1437 UDF_LVINT_HIST_CHUNK;
1438 if (reallocarr(&context.lvint_history,
1439 new_len, sector_size))
1440 err(FSCK_EXIT_CHECK_FAILED, "can't expand logvol history");
1441 context.lvint_history_len = new_len;
1442 }
1443
1444 /* are we linking to a new piece? */
1445 if (lvint->next_extent.len) {
1446 len = udf_rw32(lvint->next_extent.len);
1447 lbnum = udf_rw32(lvint->next_extent.loc);
1448
1449 if (trace_len >= UDF_LVDINT_SEGMENTS-1) {
1450 /* IEK! segment link full... */
1451 pwarn("implementation limit: logical volume "
1452 "integrity segment list full\n");
1453 error = ENOMEM;
1454 break;
1455 }
1456 trace++;
1457 trace_len++;
1458
1459 trace->start = lbnum;
1460 trace->end = lbnum + len/sector_size;
1461 trace->pos = 0;
1462 trace->wpos = 0;
1463
1464 context.lvint_history_ondisc_len += (len / sector_size);
1465 }
1466
1467 /* record this found lvint; it is one sector long */
1468 wpos = context.lvint_history +
1469 context.lvint_history_wpos * sector_size;
1470 memcpy(wpos, dscr, sector_size);
1471 memcpy(context.logvol_integrity, dscr, sector_size);
1472 context.lvint_history_wpos++;
1473
1474 /* proceed sequential */
1475 lbnum += 1;
1476 len -= sector_size;
1477 }
1478
1479 /* clean up the mess, esp. when there is an error */
1480 free(dscr);
1481
1482 if (error) {
1483 if (!preen)
1484 printf("Error in logical volume integrity sequence\n");
1485 printf("Marking logical volume integrity OPEN\n");
1486 udf_update_lvintd(UDF_INTEGRITY_OPEN);
1487 }
1488
1489 if (udf_rw16(context.logvol_info->min_udf_readver) > context.min_udf)
1490 context.min_udf = udf_rw16(context.logvol_info->min_udf_readver);
1491 if (udf_rw16(context.logvol_info->min_udf_writever) > context.min_udf)
1492 context.min_udf = udf_rw16(context.logvol_info->min_udf_writever);
1493 if (udf_rw16(context.logvol_info->max_udf_writever) < context.max_udf)
1494 context.max_udf = udf_rw16(context.logvol_info->max_udf_writever);
1495
1496 context.unique_id = udf_rw64(context.logvol_integrity->lvint_next_unique_id);
1497
1498 /* fill in current size/free values */
1499 pos = &context.logvol_integrity->tables[0];
1500 num_partmappings = udf_rw32(context.logical_vol->n_pm);
1501 for (cnt = 0; cnt < num_partmappings; cnt++) {
1502 context.part_free[cnt] = udf_rw32(*pos);
1503 pos++;
1504 }
1505 /* leave the partition sizes alone; no idea why they are stated here */
1506 /* TODO sanity check the free space and partition sizes? */
1507
1508 /* XXX FAULT INJECTION POINT XXX */
1509 //udf_update_lvintd(UDF_INTEGRITY_OPEN);
1510
1511 if (!preen) {
1512 int ver;
1513
1514 printf("\n");
1515 ver = udf_rw16(context.logvol_info->min_udf_readver);
1516 printf("Minimum read version v%x.%02x\n", ver/0x100, ver&0xff);
1517 ver = udf_rw16(context.logvol_info->min_udf_writever);
1518 printf("Minimum write version v%x.%02x\n", ver/0x100, ver&0xff);
1519 ver = udf_rw16(context.logvol_info->max_udf_writever);
1520 printf("Maximum write version v%x.%02x\n", ver/0x100, ver&0xff);
1521
1522 printf("\nLast logical volume integrity state is %s.\n",
1523 udf_rw32(context.logvol_integrity->integrity_type) ?
1524 "CLOSED" : "OPEN");
1525 }
1526 }
1527
1528
1529 static int
1530 udf_writeout_lvint(void)
1531 {
1532 union dscrptr *terminator;
1533 struct udf_lvintq *intq, *nintq;
1534 struct logvol_int_desc *lvint;
1535 uint32_t location;
1536 int wpos, num_avail;
1537 int sector_size = context.sector_size;
1538 int integrity_type, error;
1539 int next_present, end_slot, last_segment;
1540
1541 /* only write out when its open */
1542 integrity_type = udf_rw32(context.logvol_integrity->integrity_type);
1543 if (integrity_type == UDF_INTEGRITY_CLOSED)
1544 return 0;
1545
1546 if (!preen)
1547 printf("\n");
1548 if (!ask(1, "Write out modifications"))
1549 return 0;
1550
1551 udf_allow_writing();
1552
1553 /* close logical volume */
1554 udf_update_lvintd(UDF_INTEGRITY_CLOSED);
1555
1556 /* do we need to lose some history? */
1557 if ((context.lvint_history_ondisc_len - context.lvint_history_wpos) < 2) {
1558 uint8_t *src, *dst;
1559 uint32_t size;
1560
1561 dst = context.lvint_history;
1562 src = dst + sector_size;
1563 size = (context.lvint_history_wpos-2) * sector_size;
1564 memmove(dst, src, size);
1565 context.lvint_history_wpos -= 2;
1566 }
1567
1568 /* write out complete trace just in case */
1569 wpos = 0;
1570 location = 0;
1571 for (int i = 0; i < UDF_LVDINT_SEGMENTS; i++) {
1572 intq = &context.lvint_trace[i];
1573 nintq = &context.lvint_trace[i+1];
1574
1575 /* end of line? */
1576 if (intq->start == intq->end)
1577 break;
1578 num_avail = intq->end - intq->start;
1579 location = intq->start;
1580 for (int sector = 0; sector < num_avail; sector++) {
1581 lvint = (struct logvol_int_desc *)
1582 (context.lvint_history + wpos * sector_size);
1583 memset(&lvint->next_extent, 0, sizeof(struct extent_ad));
1584 next_present = (wpos != context.lvint_history_wpos);
1585 end_slot = (sector == num_avail -1);
1586 last_segment = (i == UDF_LVDINT_SEGMENTS-1);
1587 if (end_slot && next_present && !last_segment) {
1588 /* link to next segment */
1589 lvint->next_extent.len = udf_rw32(
1590 sector_size * (nintq->end - nintq->start));
1591 lvint->next_extent.loc = udf_rw32(nintq->start);
1592 }
1593 error = udf_write_dscr_phys((union dscrptr *) lvint, location, 1);
1594 assert(!error);
1595 wpos++;
1596 location++;
1597 if (wpos == context.lvint_history_wpos)
1598 break;
1599 }
1600 }
1601
1602 /* at write pos, write out our integrity */
1603 assert(location);
1604 lvint = context.logvol_integrity;
1605 error = udf_write_dscr_phys((union dscrptr *) lvint, location, 1);
1606 assert(!error);
1607 wpos++;
1608 location++;
1609
1610 /* write out terminator */
1611 terminator = calloc(1, context.sector_size);
1612 assert(terminator);
1613 udf_create_terminator(terminator, 0);
1614
1615 /* same or increasing serial number: ECMA 3/7.2.5, 4/7.2.5, UDF 2.3.1.1. */
1616 terminator->tag.serial_num = lvint->tag.serial_num;
1617
1618 error = udf_write_dscr_phys(terminator, location, 1);
1619 free(terminator);
1620 assert(!error);
1621 wpos++;
1622 location++;
1623
1624 return 0;
1625 }
1626
1627
1628 static int
1629 udf_readin_partitions_free_space(void)
1630 {
1631 union dscrptr *dscr;
1632 struct part_desc *part;
1633 struct part_hdr_desc *phd;
1634 uint32_t bitmap_len, bitmap_lb;
1635 int cnt, tagid, error;
1636
1637 /* XXX freed space bitmap ignored XXX */
1638 error = 0;
1639 for (cnt = 0; cnt < UDF_PARTITIONS; cnt++) {
1640 part = context.partitions[cnt];
1641 if (!part)
1642 continue;
1643
1644 phd = &part->pd_part_hdr;
1645 bitmap_len = udf_rw32(phd->unalloc_space_bitmap.len);
1646 bitmap_lb = udf_rw32(phd->unalloc_space_bitmap.lb_num);
1647
1648 if (bitmap_len == 0) {
1649 error = 0;
1650 continue;
1651 }
1652
1653 if (!preen)
1654 printf("Reading in free space map for partition %d\n", cnt);
1655 error = udf_read_dscr_virt(bitmap_lb, cnt, &dscr);
1656 if (error)
1657 break;
1658 if (!dscr) {
1659 error = ENOENT;
1660 break;
1661 }
1662 tagid = udf_rw16(dscr->tag.id);
1663 if (tagid != TAGID_SPACE_BITMAP) {
1664 pwarn("Unallocated space bitmap expected but got "
1665 "tag %d\n", tagid);
1666 free(dscr);
1667 error = ENOENT;
1668 break;
1669 }
1670 if (udf_tagsize(dscr, context.sector_size) > bitmap_len) {
1671 pwarn("Warning, size of read in bitmap %d is "
1672 "not equal to expected size %d\n",
1673 udf_tagsize(dscr, context.sector_size),
1674 bitmap_len);
1675 }
1676 context.part_unalloc_bits[cnt] = &dscr->sbd;
1677 }
1678
1679 /* special case for metadata partitions */
1680 for (cnt = 0; cnt < UDF_PMAPS; cnt++) {
1681 if (context.vtop_tp[cnt] != UDF_VTOP_TYPE_META)
1682 continue;
1683 /* only if present */
1684 if (layout.meta_bitmap == 0xffffffff)
1685 continue;
1686 if (!preen)
1687 printf("Reading in free space map for partition %d\n", cnt);
1688 error = udf_readin_file(
1689 (union dscrptr *) context.meta_bitmap,
1690 context.vtop[cnt],
1691 (uint8_t **) &context.part_unalloc_bits[cnt],
1692 NULL);
1693 if (error) {
1694 free(context.part_unalloc_bits[cnt]);
1695 context.part_unalloc_bits[cnt] = NULL;
1696 pwarn("implementation limit: metadata bitmap file read error, "
1697 "can't fix this up yet\n");
1698 return error;
1699 }
1700 }
1701 if (!preen)
1702 printf("\n");
1703
1704 return error;
1705 }
1706
1707
1708 /* ------------------------- VAT support ------------------------- */
1709
1710 /*
1711 * Update logical volume name in all structures that keep a record of it. We
1712 * use memmove since each of them might be specified as a source.
1713 *
1714 * Note that it doesn't update the VAT structure!
1715 */
1716
1717 static void
1718 udf_update_logvolname(char *logvol_id)
1719 {
1720 struct logvol_desc *lvd = NULL;
1721 struct fileset_desc *fsd = NULL;
1722 struct udf_lv_info *lvi = NULL;
1723
1724 lvd = context.logical_vol;
1725 fsd = context.fileset_desc;
1726 if (context.implementation)
1727 lvi = &context.implementation->_impl_use.lv_info;
1728
1729 /* logvol's id might be specified as original so use memmove here */
1730 memmove(lvd->logvol_id, logvol_id, 128);
1731 if (fsd)
1732 memmove(fsd->logvol_id, logvol_id, 128);
1733 if (lvi)
1734 memmove(lvi->logvol_id, logvol_id, 128);
1735 }
1736
1737
1738 static struct timestamp *
1739 udf_file_mtime(union dscrptr *dscr)
1740 {
1741 int tag_id = udf_rw16(dscr->tag.id);
1742
1743 assert((tag_id == TAGID_FENTRY) || (tag_id == TAGID_EXTFENTRY));
1744 if (tag_id == TAGID_FENTRY)
1745 return &dscr->fe.mtime;
1746 else
1747 return &dscr->efe.mtime;
1748 ;
1749 }
1750
1751
1752 static void
1753 udf_print_vat_details(union dscrptr *dscr)
1754 {
1755 printf("\n");
1756 udf_print_timestamp("\tFound VAT timestamped at ",
1757 udf_file_mtime(dscr), "\n");
1758 }
1759
1760
1761 static int
1762 udf_check_for_vat(union dscrptr *dscr)
1763 {
1764 struct icb_tag *icbtag;
1765 uint32_t vat_length;
1766 int tag_id, filetype;
1767
1768 tag_id = udf_rw16(dscr->tag.id);
1769
1770 if ((tag_id != TAGID_FENTRY) && (tag_id != TAGID_EXTFENTRY))
1771 return ENOENT;
1772
1773 if (tag_id == TAGID_FENTRY) {
1774 vat_length = udf_rw64(dscr->fe.inf_len);
1775 icbtag = &dscr->fe.icbtag;
1776 } else {
1777 vat_length = udf_rw64(dscr->efe.inf_len);
1778 icbtag = &dscr->efe.icbtag;
1779 }
1780 filetype = icbtag->file_type;
1781 if ((filetype != 0) && (filetype != UDF_ICB_FILETYPE_VAT))
1782 return ENOENT;
1783
1784 /* TODO sanity check vat length */
1785 vat_length = vat_length;
1786
1787 return 0;
1788 }
1789
1790
1791 static int
1792 udf_extract_vat(union dscrptr *dscr, uint8_t **vat_contents)
1793 {
1794 struct udf_fsck_file_stats stats;
1795 struct icb_tag *icbtag;
1796 struct timestamp *mtime;
1797 struct udf_vat *vat;
1798 struct udf_oldvat_tail *oldvat_tl;
1799 struct udf_logvol_info *lvinfo;
1800 struct impl_extattr_entry *implext;
1801 struct vatlvext_extattr_entry lvext;
1802 const char *extstr = "*UDF VAT LVExtension";
1803 uint64_t vat_unique_id;
1804 uint64_t vat_length;
1805 uint32_t vat_entries, vat_offset;
1806 uint32_t offset, a_l;
1807 uint8_t *ea_start, *lvextpos;
1808 char *regid_name;
1809 int tag_id, filetype;
1810 int error;
1811
1812 *vat_contents = NULL;
1813 lvinfo = context.logvol_info;
1814
1815 /* read in VAT contents */
1816 error = udf_readin_file(dscr, context.data_part, vat_contents, &stats);
1817 if (error) {
1818 error = ENOENT;
1819 goto out;
1820 }
1821
1822 /* tag_id already checked */
1823 tag_id = udf_rw16(dscr->tag.id);
1824 if (tag_id == TAGID_FENTRY) {
1825 vat_length = udf_rw64(dscr->fe.inf_len);
1826 icbtag = &dscr->fe.icbtag;
1827 mtime = &dscr->fe.mtime;
1828 vat_unique_id = udf_rw64(dscr->fe.unique_id);
1829 ea_start = dscr->fe.data;
1830 } else {
1831 vat_length = udf_rw64(dscr->efe.inf_len);
1832 icbtag = &dscr->efe.icbtag;
1833 mtime = &dscr->efe.mtime;
1834 vat_unique_id = udf_rw64(dscr->efe.unique_id);
1835 ea_start = dscr->efe.data; /* for completion */
1836 }
1837
1838 if (vat_length > stats.inf_len) {
1839 error = ENOENT;
1840 goto out;
1841 }
1842
1843 /* file type already checked */
1844 filetype = icbtag->file_type;
1845
1846 /* extract info from our VAT data */
1847 if (filetype == 0) {
1848 /* VAT 1.50 format */
1849 /* definition */
1850 vat_offset = 0;
1851 vat_entries = (vat_length-36)/4;
1852 oldvat_tl = (struct udf_oldvat_tail *)
1853 (*vat_contents + vat_entries * 4);
1854 regid_name = (char *) oldvat_tl->id.id;
1855 error = strncmp(regid_name, "*UDF Virtual Alloc Tbl", 22);
1856 if (error) {
1857 pwarn("Possible VAT 1.50 detected without tail\n");
1858 if (ask_noauto(0, "Accept anyway")) {
1859 vat_entries = vat_length/4;
1860 vat_writeout = 1;
1861 error = 0;
1862 goto ok;
1863 }
1864 pwarn("VAT format 1.50 rejected\n");
1865 error = ENOENT;
1866 goto out;
1867 }
1868
1869 /*
1870 * The following VAT extensions are optional and ignored but
1871 * demand a clean VAT write out for sanity.
1872 */
1873 error = udf_extattr_search_intern(dscr, 2048, extstr, &offset, &a_l);
1874 if (error) {
1875 /* VAT LVExtension extended attribute missing */
1876 vat_writeout = 1;
1877 goto ok;
1878 }
1879
1880 implext = (struct impl_extattr_entry *) (ea_start + offset);
1881 error = udf_impl_extattr_check(implext);
1882 if (error) {
1883 /* VAT LVExtension checksum failed */
1884 vat_writeout = 1;
1885 goto ok;
1886 }
1887
1888 /* paranoia */
1889 if (a_l != sizeof(*implext) -2 + udf_rw32(implext->iu_l) + sizeof(lvext)) {
1890 /* VAT LVExtension size doesn't compute */
1891 vat_writeout = 1;
1892 goto ok;
1893 }
1894
1895 /*
1896 * We have found our "VAT LVExtension attribute. BUT due to a
1897 * bug in the specification it might not be word aligned so
1898 * copy first to avoid panics on some machines (!!)
1899 */
1900 lvextpos = implext->data + udf_rw32(implext->iu_l);
1901 memcpy(&lvext, lvextpos, sizeof(lvext));
1902
1903 /* check if it was updated the last time */
1904 if (udf_rw64(lvext.unique_id_chk) == vat_unique_id) {
1905 lvinfo->num_files = lvext.num_files;
1906 lvinfo->num_directories = lvext.num_directories;
1907 udf_update_logvolname(lvext.logvol_id);
1908 } else {
1909 /* VAT LVExtension out of date */
1910 vat_writeout = 1;
1911 }
1912 } else {
1913 /* VAT 2.xy format */
1914 /* definition */
1915 vat = (struct udf_vat *) (*vat_contents);
1916 vat_offset = udf_rw16(vat->header_len);
1917 vat_entries = (vat_length - vat_offset)/4;
1918
1919 if (heuristics) {
1920 if (vat->impl_use_len == 0) {
1921 uint32_t start_val;
1922 start_val = udf_rw32(*((uint32_t *) vat->data));
1923 if (start_val == 0x694d2a00) {
1924 /* "<0>*Mic"osoft Windows */
1925 pwarn("Heuristics found corrupted MS Windows VAT\n");
1926 if (ask(0, "Repair")) {
1927 vat->impl_use_len = udf_rw16(32);
1928 vat->header_len = udf_rw16(udf_rw16(vat->header_len) + 32);
1929 vat_offset += 32;
1930 vat_writeout = 1;
1931 }
1932 }
1933 }
1934 }
1935 assert(lvinfo);
1936 lvinfo->num_files = vat->num_files;
1937 lvinfo->num_directories = vat->num_directories;
1938 lvinfo->min_udf_readver = vat->min_udf_readver;
1939 lvinfo->min_udf_writever = vat->min_udf_writever;
1940 lvinfo->max_udf_writever = vat->max_udf_writever;
1941
1942 udf_update_logvolname(vat->logvol_id);
1943 }
1944
1945 /* XXX FAULT INJECTION POINT XXX */
1946 //vat_writeout = 1;
1947
1948 ok:
1949 /* extra sanity checking */
1950 if (tag_id == TAGID_FENTRY) {
1951 /* nothing checked as yet */
1952 } else {
1953 /*
1954 * The following VAT violations are ignored but demand a clean VAT
1955 * writeout for sanity
1956 */
1957 if (!is_zero(&dscr->efe.streamdir_icb, sizeof(struct long_ad))) {
1958 /* VAT specification violation:
1959 * VAT has no cleared streamdir reference */
1960 vat_writeout = 1;
1961 }
1962 if (!is_zero(&dscr->efe.ex_attr_icb, sizeof(struct long_ad))) {
1963 /* VAT specification violation:
1964 * VAT has no cleared extended attribute reference */
1965 vat_writeout = 1;
1966 }
1967 if (dscr->efe.obj_size != dscr->efe.inf_len) {
1968 /* VAT specification violation:
1969 * VAT has invalid object size */
1970 vat_writeout = 1;
1971 }
1972 }
1973
1974 if (!vat_writeout) {
1975 context.logvol_integrity->lvint_next_unique_id = udf_rw64(vat_unique_id);
1976 context.logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_CLOSED);
1977 context.logvol_integrity->time = *mtime;
1978 }
1979
1980 context.unique_id = vat_unique_id;
1981 context.vat_allocated = UDF_ROUNDUP(vat_length, context.sector_size);
1982 context.vat_contents = *vat_contents;
1983 context.vat_start = vat_offset;
1984 context.vat_size = vat_offset + vat_entries * 4;
1985
1986 out:
1987 if (error) {
1988 free(*vat_contents);
1989 *vat_contents = NULL;
1990 }
1991
1992 return error;
1993 }
1994
1995
1996 #define VAT_BLK 256
1997 static int
1998 udf_search_vat(union udf_pmap *mapping, int log_part)
1999 {
2000 union dscrptr *vat_candidate, *accepted_vat;
2001 struct part_desc *pdesc;
2002 struct mmc_trackinfo *ti, *ti_s;
2003 uint32_t part_start;
2004 uint32_t vat_loc, early_vat_loc, late_vat_loc, accepted_vat_loc;
2005 uint32_t first_possible_vat_location, last_possible_vat_location;
2006 uint8_t *vat_contents, *accepted_vat_contents;
2007 int num_tracks, tracknr, found_a_VAT, valid_loc, error;
2008
2009 /*
2010 * Start reading forward in blocks from the first possible vat
2011 * location. If not found in this block, start again a bit before
2012 * until we get a hit.
2013 */
2014
2015 /* get complete list of all our valid ranges */
2016 ti_s = calloc(mmc_discinfo.num_tracks, sizeof(struct mmc_trackinfo));
2017 for (tracknr = 1; tracknr <= mmc_discinfo.num_tracks; tracknr++) {
2018 ti = &ti_s[tracknr];
2019 ti->tracknr = tracknr;
2020 (void) udf_update_trackinfo(ti);
2021 }
2022
2023 /* derive our very first track number our base partition covers */
2024 pdesc = context.partitions[context.data_part];
2025 part_start = udf_rw32(pdesc->start_loc);
2026 for (int cnt = 0; cnt < UDF_PARTITIONS; cnt++) {
2027 pdesc = context.partitions[cnt];
2028 if (!pdesc)
2029 continue;
2030 part_start = MIN(part_start, udf_rw32(pdesc->start_loc));
2031 }
2032 num_tracks = mmc_discinfo.num_tracks;
2033 for (tracknr = 1, ti = NULL; tracknr <= num_tracks; tracknr++) {
2034 ti = &ti_s[tracknr];
2035 if ((part_start >= ti->track_start) &&
2036 (part_start <= ti->track_start + ti->track_size))
2037 break;
2038 }
2039 context.first_ti_partition = *ti;
2040
2041 first_possible_vat_location = context.first_ti_partition.track_start;
2042 last_possible_vat_location = context.last_ti.track_start +
2043 context.last_ti.track_size -
2044 context.last_ti.free_blocks + 1;
2045
2046 /* initial guess is around 16 sectors back */
2047 late_vat_loc = last_possible_vat_location;
2048 early_vat_loc = MAX(late_vat_loc - 16, first_possible_vat_location);
2049
2050 if (!preen)
2051 printf("Full VAT range search from %d to %d\n",
2052 first_possible_vat_location,
2053 last_possible_vat_location);
2054
2055 vat_writeout = 0;
2056 accepted_vat = NULL;
2057 accepted_vat_contents = NULL;
2058 accepted_vat_loc = 0;
2059 do {
2060 vat_loc = early_vat_loc;
2061 if (!preen) {
2062 printf("\tChecking range %8d to %8d\n",
2063 early_vat_loc, late_vat_loc);
2064 fflush(stdout);
2065 }
2066 found_a_VAT = 0;
2067 while (vat_loc <= late_vat_loc) {
2068 if (print_info) {
2069 pwarn("\nchecking for VAT in sector %8d\n", vat_loc);
2070 print_info = 0;
2071 }
2072 /* check if its in readable range */
2073 valid_loc = 0;
2074 for (tracknr = 1; tracknr <= num_tracks; tracknr++) {
2075 ti = &ti_s[tracknr];
2076 if (!(ti->flags & MMC_TRACKINFO_BLANK) &&
2077 ((vat_loc >= ti->track_start) &&
2078 (vat_loc <= ti->track_start + ti->track_size))) {
2079 valid_loc = 1;
2080 break;
2081 }
2082 }
2083 if (!valid_loc) {
2084 vat_loc++;
2085 continue;
2086 }
2087
2088 error = udf_read_dscr_phys(vat_loc, &vat_candidate);
2089 if (!vat_candidate)
2090 error = ENOENT;
2091 if (!error)
2092 error = udf_check_for_vat(vat_candidate);
2093 if (error) {
2094 vat_loc++; /* walk forward */
2095 continue;
2096 }
2097
2098 if (accepted_vat) {
2099 /* check if newer vat time stamp is the same */
2100 if (udf_compare_mtimes(
2101 udf_file_mtime(vat_candidate),
2102 udf_file_mtime(accepted_vat)
2103 ) == 0) {
2104 free(vat_candidate);
2105 vat_loc++; /* walk forward */
2106 continue;
2107 }
2108 }
2109
2110 /* check if its contents are OK */
2111 error = udf_extract_vat(
2112 vat_candidate, &vat_contents);
2113 if (error) {
2114 /* unlikely */
2115 // pwarn("Unreadable or malformed VAT encountered\n");
2116 free(vat_candidate);
2117 vat_loc++;
2118 continue;
2119 }
2120 /* accept new vat */
2121 free(accepted_vat);
2122 free(accepted_vat_contents);
2123
2124 accepted_vat = vat_candidate;
2125 accepted_vat_contents = vat_contents;
2126 accepted_vat_loc = vat_loc;
2127 vat_candidate = NULL;
2128 vat_contents = NULL;
2129
2130 found_a_VAT = 1;
2131
2132 vat_loc++; /* walk forward */
2133 };
2134
2135 if (found_a_VAT && accepted_vat) {
2136 /* VAT accepted */
2137 if (!preen)
2138 udf_print_vat_details(accepted_vat);
2139 if (vat_writeout)
2140 pwarn("\tVAT accepted but marked dirty\n");
2141 if (!preen && !vat_writeout)
2142 pwarn("\tLogical volume integrity state set to CLOSED\n");
2143 if (!search_older_vat)
2144 break;
2145 if (!ask_noauto(0, "\tSearch older VAT"))
2146 break;
2147 late_vat_loc = accepted_vat_loc - 1;
2148 } else {
2149 late_vat_loc = early_vat_loc - 1;
2150 }
2151 early_vat_loc = first_possible_vat_location;
2152 if (late_vat_loc > VAT_BLK)
2153 early_vat_loc = MAX(early_vat_loc, late_vat_loc - VAT_BLK);
2154 } while (late_vat_loc > first_possible_vat_location);
2155
2156 if (!preen)
2157 printf("\n");
2158
2159 undo_opening_session = 0;
2160
2161 if (!accepted_vat) {
2162 if ((context.last_ti.sessionnr > 1) &&
2163 ask_noauto(0, "Undo opening of last session")) {
2164 undo_opening_session = 1;
2165 pwarn("Undoing opening of last session not implemented!\n");
2166 error = ENOENT;
2167 goto error_out;
2168 } else {
2169 pwarn("No valid VAT found!\n");
2170 error = ENOENT;
2171 goto error_out;
2172 }
2173 }
2174 if (last_possible_vat_location - accepted_vat_loc > 16) {
2175 assert(accepted_vat);
2176 pwarn("Selected VAT is not the latest or not at the end of "
2177 "track.\n");
2178 vat_writeout = 1;
2179 }
2180
2181 /* XXX FAULT INJECTION POINT XXX */
2182 //vat_writeout = 1;
2183 //udf_update_lvintd(UDF_INTEGRITY_OPEN);
2184
2185 return 0;
2186
2187 error_out:
2188 free(accepted_vat);
2189 free(accepted_vat_contents);
2190
2191 return error;
2192 }
2193
2194 /* ------------------------- sparables support ------------------------- */
2195
2196 static int
2197 udf_read_spareables(union udf_pmap *mapping, int log_part)
2198 {
2199 union dscrptr *dscr;
2200 struct part_map_spare *pms = &mapping->pms;
2201 uint32_t lb_num;
2202 int spar, error;
2203
2204 for (spar = 0; spar < pms->n_st; spar++) {
2205 lb_num = pms->st_loc[spar];
2206 error = udf_read_dscr_phys(lb_num, &dscr);
2207 if (error && !preen)
2208 pwarn("Error reading spareable table %d\n", spar);
2209 if (!error && dscr) {
2210 if (udf_rw16(dscr->tag.id) == TAGID_SPARING_TABLE) {
2211 free(context.sparing_table);
2212 context.sparing_table = &dscr->spt;
2213 dscr = NULL;
2214 break; /* we're done */
2215 }
2216 }
2217 free(dscr);
2218 }
2219 if (context.sparing_table == NULL)
2220 return ENOENT;
2221 return 0;
2222 }
2223
2224 /* ------------------------- metadata support ------------------------- */
2225
2226 static bool
2227 udf_metadata_node_supported(void)
2228 {
2229 struct extfile_entry *efe;
2230 struct short_ad *short_ad;
2231 uint32_t len;
2232 uint32_t flags;
2233 uint8_t *data_pos;
2234 int dscr_size, l_ea, l_ad, icbflags, addr_type;
2235
2236 /* we have to look into the file's allocation descriptors */
2237
2238 efe = context.meta_file;
2239 dscr_size = sizeof(struct extfile_entry) - 1;
2240 l_ea = udf_rw32(efe->l_ea);
2241 l_ad = udf_rw32(efe->l_ad);
2242
2243 icbflags = udf_rw16(efe->icbtag.flags);
2244 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
2245 if (addr_type != UDF_ICB_SHORT_ALLOC) {
2246 warnx("specification violation: metafile not using"
2247 "short allocs");
2248 return false;
2249 }
2250
2251 data_pos = (uint8_t *) context.meta_file + dscr_size + l_ea;
2252 short_ad = (struct short_ad *) data_pos;
2253 while (l_ad > 0) {
2254 len = udf_rw32(short_ad->len);
2255 flags = UDF_EXT_FLAGS(len);
2256 if (flags == UDF_EXT_REDIRECT) {
2257 warnx("implementation limit: no support for "
2258 "extent redirections in metadata file");
2259 return false;
2260 }
2261 short_ad++;
2262 l_ad -= sizeof(struct short_ad);
2263 }
2264 /* we passed all of them */
2265 return true;
2266 }
2267
2268
2269 static int
2270 udf_read_metadata_nodes(union udf_pmap *mapping, int log_part)
2271 {
2272 union dscrptr *dscr1, *dscr2, *dscr3;
2273 struct part_map_meta *pmm = &mapping->pmm;
2274 uint16_t raw_phys_part, phys_part;
2275 int tagid, file_type, error;
2276
2277 /*
2278 * BUGALERT: some rogue implementations use random physical
2279 * partition numbers to break other implementations so lookup
2280 * the number.
2281 */
2282
2283 raw_phys_part = udf_rw16(pmm->part_num);
2284 phys_part = udf_find_raw_phys(raw_phys_part);
2285
2286 error = udf_read_dscr_virt(layout.meta_file, phys_part, &dscr1);
2287 if (!error) {
2288 tagid = udf_rw16(dscr1->tag.id);
2289 file_type = dscr1->efe.icbtag.file_type;
2290 if ((tagid != TAGID_EXTFENTRY) ||
2291 (file_type != UDF_ICB_FILETYPE_META_MAIN))
2292 error = ENOENT;
2293 }
2294 if (error) {
2295 pwarn("Bad primary metadata file descriptor\n");
2296 free(dscr1);
2297 dscr1 = NULL;
2298 }
2299
2300 error = udf_read_dscr_virt(layout.meta_mirror, phys_part, &dscr2);
2301 if (!error) {
2302 tagid = udf_rw16(dscr2->tag.id);
2303 file_type = dscr2->efe.icbtag.file_type;
2304 if ((tagid != TAGID_EXTFENTRY) ||
2305 (file_type != UDF_ICB_FILETYPE_META_MIRROR))
2306 error = ENOENT;
2307 }
2308 if (error) {
2309 pwarn("Bad mirror metadata file descriptor\n");
2310 free(dscr2);
2311 dscr2 = NULL;
2312 }
2313
2314 if ((dscr1 == NULL) && (dscr2 == NULL)) {
2315 pwarn("No valid metadata file descriptors found!\n");
2316 return -1;
2317 }
2318
2319 error = 0;
2320 if ((dscr1 == NULL) && dscr2) {
2321 dscr1 = malloc(context.sector_size);
2322 memcpy(dscr1, dscr2, context.sector_size);
2323 dscr1->efe.icbtag.file_type = UDF_ICB_FILETYPE_META_MAIN;
2324 if (ask(1, "Fix up bad primary metadata file descriptor")) {
2325 error = udf_write_dscr_virt(dscr1,
2326 layout.meta_file, phys_part, 1);
2327 }
2328 }
2329 if (dscr1 && (dscr2 == NULL)) {
2330 dscr2 = malloc(context.sector_size);
2331 memcpy(dscr2, dscr1, context.sector_size);
2332 dscr2->efe.icbtag.file_type = UDF_ICB_FILETYPE_META_MIRROR;
2333 if (ask(1, "Fix up bad mirror metadata file descriptor")) {
2334 error = udf_write_dscr_virt(dscr2,
2335 layout.meta_mirror, phys_part, 1);
2336 }
2337 }
2338 if (error)
2339 pwarn("Copying metadata file descriptor failed, "
2340 "trying to continue\n");
2341
2342 context.meta_file = &dscr1->efe;
2343 context.meta_mirror = &dscr2->efe;
2344
2345 dscr3 = NULL;
2346 if (layout.meta_bitmap != 0xffffffff) {
2347 error = udf_read_dscr_virt(layout.meta_bitmap, phys_part, &dscr3);
2348 if (!error) {
2349 tagid = udf_rw16(dscr3->tag.id);
2350 file_type = dscr3->efe.icbtag.file_type;
2351 if ((tagid != TAGID_EXTFENTRY) ||
2352 (file_type != UDF_ICB_FILETYPE_META_BITMAP))
2353 error = ENOENT;
2354 }
2355 if (error) {
2356 pwarn("Bad metadata bitmap file descriptor\n");
2357 free(dscr3);
2358 dscr3 = NULL;
2359 }
2360
2361 if (dscr3 == NULL) {
2362 pwarn("implementation limit: can't repair missing or "
2363 "damaged metadata bitmap descriptor\n");
2364 return -1;
2365 }
2366
2367 context.meta_bitmap = &dscr3->efe;
2368 }
2369
2370 /* TODO early check if meta_file has allocation extent redirections */
2371 if (!udf_metadata_node_supported())
2372 return EINVAL;
2373
2374 return 0;
2375 }
2376
2377 /* ------------------------- VDS readin ------------------------- */
2378
2379 /* checks if the VDS information is correct and complete */
2380 static int
2381 udf_process_vds(void) {
2382 union dscrptr *dscr;
2383 union udf_pmap *mapping;
2384 struct part_desc *pdesc;
2385 struct long_ad fsd_loc;
2386 uint8_t *pmap_pos;
2387 char *domain_name, *map_name;
2388 const char *check_name;
2389 int pmap_stype, pmap_size;
2390 int pmap_type, log_part, phys_part, raw_phys_part; //, maps_on;
2391 int n_pm, n_phys, n_virt, n_spar, n_meta;
2392 int len, error;
2393
2394 /* we need at least an anchor (trivial, but for safety) */
2395 if (context.anchors[0] == NULL) {
2396 pwarn("sanity check: no anchors?\n");
2397 return EINVAL;
2398 }
2399
2400 /* we need at least one primary and one logical volume descriptor */
2401 if ((context.primary_vol == NULL) || (context.logical_vol) == NULL) {
2402 pwarn("sanity check: missing primary or missing logical volume\n");
2403 return EINVAL;
2404 }
2405
2406 /* we need at least one partition descriptor */
2407 if (context.partitions[0] == NULL) {
2408 pwarn("sanity check: missing partition descriptor\n");
2409 return EINVAL;
2410 }
2411
2412 /* check logical volume sector size versus device sector size */
2413 if (udf_rw32(context.logical_vol->lb_size) != context.sector_size) {
2414 pwarn("sanity check: lb_size != sector size\n");
2415 return EINVAL;
2416 }
2417
2418 /* check domain name, should never fail */
2419 domain_name = (char *) context.logical_vol->domain_id.id;
2420 if (strncmp(domain_name, "*OSTA UDF Compliant", 20)) {
2421 pwarn("sanity check: disc not OSTA UDF Compliant, aborting\n");
2422 return EINVAL;
2423 }
2424
2425 /* retrieve logical volume integrity sequence */
2426 udf_retrieve_lvint();
2427
2428 /* check if we support this disc, ie less or equal to 0x250 */
2429 if (udf_rw16(context.logvol_info->min_udf_writever) > 0x250) {
2430 pwarn("implementation limit: minimum write version UDF 2.60 "
2431 "and on are not supported\n");
2432 return EINVAL;
2433 }
2434
2435 /*
2436 * check logvol mappings: effective virt->log partmap translation
2437 * check and recording of the mapping results. Saves expensive
2438 * strncmp() in tight places.
2439 */
2440 n_pm = udf_rw32(context.logical_vol->n_pm); /* num partmaps */
2441 pmap_pos = context.logical_vol->maps;
2442
2443 if (n_pm > UDF_PMAPS) {
2444 pwarn("implementation limit: too many logvol mappings\n");
2445 return EINVAL;
2446 }
2447
2448 /* count types and set partition numbers */
2449 context.data_part = context.metadata_part = context.fids_part = 0;
2450 n_phys = n_virt = n_spar = n_meta = 0;
2451 for (log_part = 0; log_part < n_pm; log_part++) {
2452 mapping = (union udf_pmap *) pmap_pos;
2453 pmap_stype = pmap_pos[0];
2454 pmap_size = pmap_pos[1];
2455 switch (pmap_stype) {
2456 case 1: /* physical mapping */
2457 /* volseq = udf_rw16(mapping->pm1.vol_seq_num); */
2458 raw_phys_part = udf_rw16(mapping->pm1.part_num);
2459 pmap_type = UDF_VTOP_TYPE_PHYS;
2460 n_phys++;
2461 context.data_part = log_part;
2462 context.metadata_part = log_part;
2463 context.fids_part = log_part;
2464 break;
2465 case 2: /* virtual/sparable/meta mapping */
2466 map_name = (char *) mapping->pm2.part_id.id;
2467 /* volseq = udf_rw16(mapping->pm2.vol_seq_num); */
2468 raw_phys_part = udf_rw16(mapping->pm2.part_num);
2469 pmap_type = UDF_VTOP_TYPE_UNKNOWN;
2470 len = UDF_REGID_ID_SIZE;
2471
2472 check_name = "*UDF Virtual Partition";
2473 if (strncmp(map_name, check_name, len) == 0) {
2474 pmap_type = UDF_VTOP_TYPE_VIRT;
2475 n_virt++;
2476 context.metadata_part = log_part;
2477 context.format_flags |= FORMAT_VAT;
2478 break;
2479 }
2480 check_name = "*UDF Sparable Partition";
2481 if (strncmp(map_name, check_name, len) == 0) {
2482 pmap_type = UDF_VTOP_TYPE_SPAREABLE;
2483 n_spar++;
2484 layout.spareable_blockingnr = udf_rw16(mapping->pms.packet_len);
2485
2486 context.data_part = log_part;
2487 context.metadata_part = log_part;
2488 context.fids_part = log_part;
2489 context.format_flags |= FORMAT_SPAREABLE;
2490 break;
2491 }
2492 check_name = "*UDF Metadata Partition";
2493 if (strncmp(map_name, check_name, len) == 0) {
2494 pmap_type = UDF_VTOP_TYPE_META;
2495 n_meta++;
2496 layout.meta_file = udf_rw32(mapping->pmm.meta_file_lbn);
2497 layout.meta_mirror = udf_rw32(mapping->pmm.meta_mirror_file_lbn);
2498 layout.meta_bitmap = udf_rw32(mapping->pmm.meta_bitmap_file_lbn);
2499 layout.meta_blockingnr = udf_rw32(mapping->pmm.alloc_unit_size);
2500 layout.meta_alignment = udf_rw16(mapping->pmm.alignment_unit_size);
2501 /* XXX metadata_flags in mapping->pmm.flags? XXX */
2502
2503 context.metadata_part = log_part;
2504 context.fids_part = log_part;
2505 context.format_flags |= FORMAT_META;
2506 break;
2507 }
2508 break;
2509 default:
2510 return EINVAL;
2511 }
2512
2513 /*
2514 * BUGALERT: some rogue implementations use random physical
2515 * partition numbers to break other implementations so lookup
2516 * the number.
2517 */
2518 phys_part = udf_find_raw_phys(raw_phys_part);
2519
2520 if (phys_part == UDF_PARTITIONS) {
2521 pwarn("implementation limit: too many partitions\n");
2522 return EINVAL;
2523 }
2524 if (pmap_type == UDF_VTOP_TYPE_UNKNOWN) {
2525 pwarn("implementation limit: encountered unknown "
2526 "logvol mapping `%s`!\n", map_name);
2527 return EINVAL;
2528 }
2529
2530 context.vtop [log_part] = phys_part;
2531 context.vtop_tp[log_part] = pmap_type;
2532
2533 pmap_pos += pmap_size;
2534 }
2535 /* not winning the beauty contest */
2536 context.vtop_tp[UDF_VTOP_RAWPART] = UDF_VTOP_TYPE_RAW;
2537
2538 /* test some basic UDF assertions/requirements */
2539 if ((n_virt > 1) || (n_spar > 1) || (n_meta > 1)) {
2540 pwarn("Sanity check: format error, more than one "
2541 "virtual, sparable or meta mapping\n");
2542 return EINVAL;
2543 }
2544
2545 if (n_virt) {
2546 if ((n_phys == 0) || n_spar || n_meta) {
2547 pwarn("Sanity check: format error, no backing for "
2548 "virtual partition\n");
2549 return EINVAL;
2550 }
2551 }
2552 if (n_spar + n_phys == 0) {
2553 pwarn("Sanity check: can't combine a sparable and a "
2554 "physical partition\n");
2555 return EINVAL;
2556 }
2557
2558 /* print format type as derived */
2559 if (!preen) {
2560 char bits[255];
2561 snprintb(bits, sizeof(bits), FORMAT_FLAGBITS, context.format_flags);
2562 printf("Format flags %s\n\n", bits);
2563 }
2564
2565 /* read supporting tables */
2566 pmap_pos = context.logical_vol->maps;
2567 for (log_part = 0; log_part < n_pm; log_part++) {
2568 mapping = (union udf_pmap *) pmap_pos;
2569 pmap_size = pmap_pos[1];
2570 switch (context.vtop_tp[log_part]) {
2571 case UDF_VTOP_TYPE_PHYS :
2572 /* nothing */
2573 break;
2574 case UDF_VTOP_TYPE_VIRT :
2575 /* search and load VAT */
2576 error = udf_search_vat(mapping, log_part);
2577 if (error) {
2578 pwarn("Couldn't find virtual allocation table\n");
2579 return ENOENT;
2580 }
2581 break;
2582 case UDF_VTOP_TYPE_SPAREABLE :
2583 /* load one of the sparable tables */
2584 error = udf_read_spareables(mapping, log_part);
2585 if (error) {
2586 pwarn("Couldn't load sparable blocks tables\n");
2587 return ENOENT;
2588 }
2589 break;
2590 case UDF_VTOP_TYPE_META :
2591 /* load the associated file descriptors */
2592 error = udf_read_metadata_nodes(mapping, log_part);
2593 if (error) {
2594 pwarn("Couldn't read in the metadata descriptors\n");
2595 return ENOENT;
2596 }
2597
2598 /*
2599 * We have to extract the partition size from the meta
2600 * data file length
2601 */
2602 context.part_size[log_part] =
2603 udf_rw32(context.meta_file->inf_len) / context.sector_size;
2604 break;
2605 default:
2606 break;
2607 }
2608 pmap_pos += pmap_size;
2609 }
2610
2611 /*
2612 * Free/unallocated space bitmap readin delayed; the FS might be
2613 * closed already; no need to read in copious amount of data only to
2614 * not use it later.
2615 *
2616 * For now, extract partition sizes in our context
2617 */
2618 for (int cnt = 0; cnt < UDF_PARTITIONS; cnt++) {
2619 pdesc = context.partitions[cnt];
2620 if (!pdesc)
2621 continue;
2622
2623 context.part_size[cnt] = udf_rw32(pdesc->part_len);
2624 context.part_unalloc_bits[cnt] = NULL;
2625 }
2626
2627 /* read file set descriptor */
2628 fsd_loc = context.logical_vol->lv_fsd_loc;
2629 error = udf_read_dscr_virt(
2630 udf_rw32(fsd_loc.loc.lb_num),
2631 udf_rw16(fsd_loc.loc.part_num), &dscr);
2632 if (error) {
2633 pwarn("Couldn't read in file set descriptor\n");
2634 pwarn("implementation limit: can't fix this\n");
2635 return ENOENT;
2636 }
2637 if (udf_rw16(dscr->tag.id) != TAGID_FSD) {
2638 pwarn("Expected fsd at (p %d, lb %d)\n",
2639 udf_rw16(fsd_loc.loc.part_num),
2640 udf_rw32(fsd_loc.loc.lb_num));
2641 pwarn("File set descriptor not pointing to a file set!\n");
2642 return ENOENT;
2643 }
2644 context.fileset_desc = &dscr->fsd;
2645
2646 /* signal its OK for now */
2647 return 0;
2648 }
2649
2650
2651 #define UDF_UPDATE_DSCR(name, dscr) \
2652 if (name) {\
2653 free (name); \
2654 updated = 1; \
2655 } \
2656 name = calloc(1, dscr_size); \
2657 memcpy(name, dscr, dscr_size);
2658
2659 static void
2660 udf_process_vds_descriptor(union dscrptr *dscr, int dscr_size) {
2661 struct pri_vol_desc *pri;
2662 struct logvol_desc *lvd;
2663 uint16_t raw_phys_part, phys_part;
2664 int updated = 0;
2665
2666 switch (udf_rw16(dscr->tag.id)) {
2667 case TAGID_PRI_VOL : /* primary partition */
2668 UDF_UPDATE_DSCR(context.primary_vol, dscr);
2669 pri = context.primary_vol;
2670
2671 context.primary_name = malloc(32);
2672 context.volset_name = malloc(128);
2673
2674 udf_to_unix_name(context.volset_name, 32, pri->volset_id, 32,
2675 &pri->desc_charset);
2676 udf_to_unix_name(context.primary_name, 128, pri->vol_id, 128,
2677 &pri->desc_charset);
2678
2679 if (!preen && !updated) {
2680 pwarn("Volume set `%s`\n", context.volset_name);
2681 pwarn("Primary volume `%s`\n", context.primary_name);
2682 }
2683 break;
2684 case TAGID_LOGVOL : /* logical volume */
2685 UDF_UPDATE_DSCR(context.logical_vol, dscr);
2686 /* could check lvd->domain_id */
2687 lvd = context.logical_vol;
2688 context.logvol_name = malloc(128);
2689
2690 udf_to_unix_name(context.logvol_name, 128, lvd->logvol_id, 128,
2691 &lvd->desc_charset);
2692
2693 if (!preen && !updated)
2694 pwarn("Logical volume `%s`\n", context.logvol_name);
2695 break;
2696 case TAGID_UNALLOC_SPACE : /* unallocated space */
2697 UDF_UPDATE_DSCR(context.unallocated, dscr);
2698 break;
2699 case TAGID_IMP_VOL : /* implementation */
2700 UDF_UPDATE_DSCR(context.implementation, dscr);
2701 break;
2702 case TAGID_PARTITION : /* partition(s) */
2703 /* not much use if its not allocated */
2704 if ((udf_rw16(dscr->pd.flags) & UDF_PART_FLAG_ALLOCATED) == 0) {
2705 pwarn("Ignoring unallocated partition\n");
2706 break;
2707 }
2708 raw_phys_part = udf_rw16(dscr->pd.part_num);
2709 phys_part = udf_find_raw_phys(raw_phys_part);
2710
2711 if (phys_part >= UDF_PARTITIONS) {
2712 pwarn("Too many physical partitions, ignoring\n");
2713 break;
2714 }
2715 UDF_UPDATE_DSCR(context.partitions[phys_part], dscr);
2716 break;
2717 case TAGID_TERM : /* terminator */
2718 break;
2719 case TAGID_VOL : /* volume space ext */
2720 pwarn("Ignoring VDS extender\n");
2721 break;
2722 default :
2723 pwarn("Unknown VDS type %d found, ignored\n",
2724 udf_rw16(dscr->tag.id));
2725 }
2726 }
2727
2728
2729 static void
2730 udf_read_vds_extent(union dscrptr *dscr, int vds_size) {
2731 uint8_t *pos;
2732 int sector_size = context.sector_size;
2733 int dscr_size;
2734
2735 pos = (uint8_t *) dscr;
2736 while (vds_size) {
2737 /* process the descriptor */
2738 dscr = (union dscrptr *) pos;
2739
2740 /* empty block terminates */
2741 if (is_zero(dscr, sector_size))
2742 return;
2743
2744 /* terminator terminates */
2745 if (udf_rw16(dscr->tag.id) == TAGID_TERM)
2746 return;
2747
2748 if (udf_check_tag(dscr))
2749 pwarn("Bad descriptor sum in vds, ignoring\n");
2750
2751 dscr_size = udf_tagsize(dscr, sector_size);
2752 if (udf_check_tag_payload(dscr, dscr_size))
2753 pwarn("Bad descriptor CRC in vds, ignoring\n");
2754
2755 udf_process_vds_descriptor(dscr, dscr_size);
2756
2757 pos += dscr_size;
2758 vds_size -= dscr_size;
2759 }
2760 }
2761
2762
2763 static int
2764 udf_copy_VDS_area(void *destbuf, void *srcbuf)
2765 {
2766 pwarn("TODO implement VDS copy area, signalling success\n");
2767 return 0;
2768 }
2769
2770
2771 /* XXX why two buffers and not just read descritor by descriptor XXX */
2772 static int
2773 udf_check_VDS_areas(void) {
2774 union dscrptr *vds1_buf, *vds2_buf;
2775 int vds1_size, vds2_size;
2776 int error, error1, error2;
2777
2778 vds1_size = layout.vds1_size * context.sector_size;
2779 vds2_size = layout.vds2_size * context.sector_size;
2780 vds1_buf = calloc(1, vds1_size);
2781 vds2_buf = calloc(1, vds2_size);
2782 assert(vds1_buf); assert(vds2_buf);
2783
2784 error1 = udf_read_phys(vds1_buf, layout.vds1, layout.vds1_size);
2785 error2 = udf_read_phys(vds2_buf, layout.vds2, layout.vds2_size);
2786
2787 if (error1 && error2) {
2788 pwarn("Can't read both volume descriptor areas!\n");
2789 return -1;
2790 }
2791
2792 if (!error1) {
2793 /* retrieve data from VDS 1 */
2794 udf_read_vds_extent(vds1_buf, vds1_size);
2795 context.vds_buf = vds1_buf;
2796 context.vds_size = vds1_size;
2797 free(vds2_buf);
2798 }
2799 if (!error2) {
2800 /* retrieve data from VDS 2 */
2801 udf_read_vds_extent(vds2_buf, vds2_size);
2802 context.vds_buf = vds2_buf;
2803 context.vds_size = vds2_size;
2804 free(vds1_buf);
2805 }
2806 /* check if all is correct and complete */
2807 error = udf_process_vds();
2808 if (error)
2809 return error;
2810
2811 /* TODO check if both area's are logically the same */
2812 error = 0;
2813 if (!error1 && error2) {
2814 /* first OK, second faulty */
2815 pwarn("Backup volume descriptor missing or damaged\n");
2816 if (context.format_flags & FORMAT_SEQUENTIAL) {
2817 pwarn("Can't fixup backup volume descriptor on "
2818 "SEQUENTIAL media\n");
2819 } else if (ask(1, "Fixup backup volume descriptor")) {
2820 error = udf_copy_VDS_area(vds2_buf, vds1_buf);
2821 pwarn("\n");
2822 }
2823 }
2824 if (error1 && !error2) {
2825 /* second OK, first faulty */
2826 pwarn("Primary volume descriptor missing or damaged\n");
2827 if (context.format_flags & FORMAT_SEQUENTIAL) {
2828 pwarn("Can't fix up primary volume descriptor on "
2829 "SEQUENTIAL media\n");
2830 } else if (ask(1, "Fix up primary volume descriptor")) {
2831 error = udf_copy_VDS_area(vds1_buf, vds2_buf);
2832 }
2833 }
2834 if (error)
2835 pwarn("copying VDS areas failed!\n");
2836 if (!preen)
2837 printf("\n");
2838
2839 return error;
2840 }
2841
2842 /* --------------------------------------------------------------------- */
2843
2844 static int
2845 udf_prepare_writing(void)
2846 {
2847 union dscrptr *zero_dscr, *dscr;
2848 struct mmc_trackinfo ti;
2849 uint32_t first_lba, loc;
2850 int sector_size = context.sector_size;
2851 int error;
2852
2853 error = udf_prepare_disc();
2854 if (error) {
2855 pwarn("*** Preparing disc for writing failed!\n");
2856 return error;
2857 }
2858
2859 /* if we are not on sequential media, we're done */
2860 if ((mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) == 0)
2861 return 0;
2862 assert(context.format_flags & FORMAT_VAT);
2863
2864 /* if the disc is full, we drop back to read only */
2865 if (mmc_discinfo.disc_state == MMC_STATE_FULL)
2866 rdonly = 1;
2867 if (rdonly)
2868 return 0;
2869
2870 /* check if we need to open the last track */
2871 ti.tracknr = mmc_discinfo.last_track_last_session;
2872 error = udf_update_trackinfo(&ti);
2873 if (error)
2874 return error;
2875 if (!(ti.flags & MMC_TRACKINFO_BLANK) &&
2876 (ti.flags & MMC_TRACKINFO_NWA_VALID)) {
2877 /*
2878 * Not closed; translate next_writable to a position relative to our
2879 * backing partition
2880 */
2881 context.alloc_pos[context.data_part] = ti.next_writable -
2882 udf_rw32(context.partitions[context.data_part]->start_loc);
2883 wrtrack_skew = ti.next_writable % layout.blockingnr;
2884 return 0;
2885 }
2886 assert(ti.flags & MMC_TRACKINFO_NWA_VALID);
2887
2888 /* just in case */
2889 udf_suspend_writing();
2890
2891 /* 'add' a new track */
2892 udf_update_discinfo();
2893 memset(&context.last_ti, 0, sizeof(struct mmc_trackinfo));
2894 context.last_ti.tracknr = mmc_discinfo.first_track_last_session;
2895 (void) udf_update_trackinfo(&context.last_ti);
2896
2897 assert(mmc_discinfo.last_session_state == MMC_STATE_EMPTY);
2898 first_lba = context.last_ti.track_start;
2899 wrtrack_skew = context.last_ti.track_start % layout.blockingnr;
2900
2901 /*
2902 * location of iso9660 vrs is defined as first sector AFTER 32kb,
2903 * minimum `sector size' 2048
2904 */
2905 layout.iso9660_vrs = ((32*1024 + sector_size - 1) / sector_size)
2906 + first_lba;
2907
2908 /* anchor starts at specified offset in sectors */
2909 layout.anchors[0] = first_lba + 256;
2910
2911 /* ready for appending, write preamble, we are using overwrite here! */
2912 if ((zero_dscr = calloc(1, context.sector_size)) == NULL)
2913 return ENOMEM;
2914 loc = first_lba;
2915 for (; loc < first_lba + 256; loc++) {
2916 if ((error = udf_write_sector(zero_dscr, loc))) {
2917 free(zero_dscr);
2918 return error;
2919 }
2920 }
2921 free(zero_dscr);
2922
2923 /* write new ISO9660 volume recognition sequence */
2924 if ((error = udf_write_iso9660_vrs())) {
2925 pwarn("internal error: can't write iso966 VRS in new session!\n");
2926 rdonly = 1;
2927 return error;
2928 }
2929
2930 /* write out our old anchor, VDS spaces will be reused */
2931 assert(context.anchors[0]);
2932 dscr = (union dscrptr *) context.anchors[0];
2933 loc = layout.anchors[0];
2934 if ((error = udf_write_dscr_phys(dscr, loc, 1))) {
2935 pwarn("internal error: can't write anchor in new session!\n");
2936 rdonly = 1;
2937 return error;
2938 }
2939
2940 context.alloc_pos[context.data_part] = first_lba + 257 -
2941 udf_rw32(context.partitions[context.data_part]->start_loc);
2942
2943 return 0;
2944 }
2945
2946
2947 static int
2948 udf_close_volume_vat(void)
2949 {
2950 int integrity_type;
2951
2952 /* only write out when its open */
2953 integrity_type = udf_rw32(context.logvol_integrity->integrity_type);
2954 if (integrity_type == UDF_INTEGRITY_CLOSED)
2955 return 0;
2956
2957 if (!preen)
2958 printf("\n");
2959 if (!ask(1, "Write out modifications"))
2960 return 0;
2961
2962 /* writeout our VAT contents */
2963 udf_allow_writing();
2964 return udf_writeout_VAT();
2965 }
2966
2967
2968 static int
2969 udf_close_volume(void)
2970 {
2971 struct part_desc *part;
2972 struct part_hdr_desc *phd;
2973 struct logvol_int_desc *lvid;
2974 struct udf_logvol_info *lvinfo;
2975 struct logvol_desc *logvol;
2976 uint32_t bitmap_len, bitmap_lb, bitmap_numlb;
2977 int i, equal, error;
2978
2979 lvid = context.logvol_integrity;
2980 logvol = context.logical_vol;
2981 lvinfo = context.logvol_info;
2982 assert(lvid);
2983 assert(logvol);
2984 assert(lvinfo);
2985
2986 /* check our highest unique id */
2987 if (context.unique_id > udf_rw64(lvid->lvint_next_unique_id)) {
2988 pwarn("Last unique id updated from %ld to %ld : FIXED\n",
2989 udf_rw64(lvid->lvint_next_unique_id),
2990 context.unique_id);
2991 open_integrity = 1;
2992 }
2993
2994 /* check file/directory counts */
2995 if (context.num_files != udf_rw32(lvinfo->num_files)) {
2996 pwarn("Number of files corrected from %d to %d : FIXED\n",
2997 udf_rw32(lvinfo->num_files),
2998 context.num_files);
2999 open_integrity = 1;
3000 }
3001 if (context.num_directories != udf_rw32(lvinfo->num_directories)) {
3002 pwarn("Number of directories corrected from %d to %d : FIXED\n",
3003 udf_rw32(lvinfo->num_directories),
3004 context.num_directories);
3005 open_integrity = 1;
3006 }
3007
3008 if (vat_writeout)
3009 open_integrity = 1;
3010
3011 if (open_integrity)
3012 udf_update_lvintd(UDF_INTEGRITY_OPEN);
3013
3014 if (context.format_flags & FORMAT_VAT)
3015 return udf_close_volume_vat();
3016
3017 /* adjust free space accounting! */
3018 for (i = 0; i < UDF_PARTITIONS; i++) {
3019 part = context.partitions[i];
3020 if (!part)
3021 continue;
3022 phd = &part->pd_part_hdr;
3023 bitmap_len = udf_rw32(phd->unalloc_space_bitmap.len);
3024 bitmap_lb = udf_rw32(phd->unalloc_space_bitmap.lb_num);
3025
3026 if (bitmap_len == 0) {
3027 error = 0;
3028 continue;
3029 }
3030
3031 equal = memcmp( recorded_part_unalloc_bits[i],
3032 context.part_unalloc_bits[i],
3033 bitmap_len) == 0;
3034
3035 if (!equal || (context.part_free[i] != recorded_part_free[i])) {
3036 if (!equal)
3037 pwarn("Calculated bitmap for partition %d not equal "
3038 "to recorded one : FIXED\n", i);
3039 pwarn("Free space on partition %d corrected "
3040 "from %d to %d blocks : FIXED\n", i,
3041 recorded_part_free[i],
3042 context.part_free[i]);
3043
3044 /* write out updated free space map */
3045 pwarn("Updating unallocated bitmap for partition\n");
3046 if (!preen)
3047 printf("Writing free space map "
3048 "for partition %d\n", i);
3049 error = 0;
3050 if (context.vtop_tp[i] == UDF_VTOP_TYPE_META) {
3051 if (context.meta_bitmap) {
3052 assert(i == context.metadata_part);
3053 error = udf_process_file(
3054 (union dscrptr *) context.meta_bitmap,
3055 context.data_part,
3056 (uint8_t **) &(context.part_unalloc_bits[i]),
3057 AD_SAVE_FILE, NULL);
3058 }
3059 } else {
3060 bitmap_numlb = udf_bytes_to_sectors(bitmap_len);
3061 error = udf_write_dscr_virt(
3062 (union dscrptr *) context.part_unalloc_bits[i],
3063 bitmap_lb,
3064 i,
3065 bitmap_numlb);
3066 }
3067 if (error)
3068 pwarn("Updating unallocated bitmap failed, "
3069 "continuing\n");
3070 udf_update_lvintd(UDF_INTEGRITY_OPEN);
3071 }
3072 }
3073
3074 /* write out the logical volume integrity sequence */
3075 error = udf_writeout_lvint();
3076
3077 return error;
3078 }
3079
3080 /* --------------------------------------------------------------------- */
3081
3082 /*
3083 * Main part of file system checking.
3084 *
3085 * Walk the entire directory tree and check all link counts and rebuild the
3086 * free space map (if present) on the go.
3087 */
3088
3089 static struct udf_fsck_node *
3090 udf_new_fsck_node(struct udf_fsck_node *parent, struct long_ad *loc, char *fname)
3091 {
3092 struct udf_fsck_node *this;
3093 this = calloc(1, sizeof(struct udf_fsck_node));
3094 if (!this)
3095 return NULL;
3096
3097 this->parent = parent;
3098 this->fname = strdup(fname);
3099 this->loc = *loc;
3100 this->fsck_flags = 0;
3101
3102 this->link_count = 0;
3103 this->found_link_count = 0;
3104
3105 return this;
3106 }
3107
3108
3109 static void
3110 udf_node_path_piece(char *pathname, struct udf_fsck_node *node)
3111 {
3112 if (node->parent) {
3113 udf_node_path_piece(pathname, node->parent);
3114 if (node->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR)
3115 strcat(pathname, "");
3116 else
3117 strcat(pathname, "/");
3118 }
3119 strcat(pathname, node->fname);
3120 }
3121
3122
3123 static char *
3124 udf_node_path(struct udf_fsck_node *node)
3125 {
3126 static char pathname[MAXPATHLEN + 10];
3127
3128 strcpy(pathname, "`");
3129 if (node->parent)
3130 udf_node_path_piece(pathname, node);
3131 else
3132 strcat(pathname, "/");
3133 strcat(pathname, "'");
3134
3135 return pathname;
3136 }
3137
3138
3139 static void
3140 udf_recursive_keep(struct udf_fsck_node *node)
3141 {
3142 while (node->parent) {
3143 node = node->parent;
3144 node->fsck_flags |= FSCK_NODE_FLAG_KEEP;
3145 }
3146 }
3147
3148
3149 static int
3150 udf_quick_check_fids(struct udf_fsck_node *node, union dscrptr *dscr)
3151 {
3152 struct udf_fsck_fid_context fid_context;
3153 int error;
3154
3155 fid_context.fid_offset = 0;
3156 fid_context.data_left = node->found.inf_len;
3157 error = udf_process_file(dscr, context.fids_part,
3158 &node->directory,
3159 AD_CHECK_FIDS,
3160 &fid_context);
3161
3162 return error;
3163 }
3164
3165
3166 /* read descriptor at node's location */
3167 static int
3168 udf_read_node_dscr(struct udf_fsck_node *node, union dscrptr **dscrptr)
3169 {
3170 *dscrptr = NULL;
3171 return udf_read_dscr_virt(
3172 udf_rw32(node->loc.loc.lb_num),
3173 udf_rw16(node->loc.loc.part_num),
3174 dscrptr);
3175 }
3176
3177
3178 static int
3179 udf_extract_node_info(struct udf_fsck_node *node, union dscrptr *dscr,
3180 int be_quiet)
3181 {
3182 struct icb_tag *icb = NULL;
3183 struct file_entry *fe = NULL;
3184 struct extfile_entry *efe = NULL;
3185 int ad_type, error;
3186
3187 if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
3188 fe = (struct file_entry *) dscr;
3189 icb = &fe->icbtag;
3190 node->declared.inf_len = udf_rw64(fe->inf_len);
3191 node->declared.obj_size = udf_rw64(fe->inf_len);
3192 node->declared.logblks_rec = udf_rw64(fe->logblks_rec);
3193 node->link_count = udf_rw16(fe->link_cnt);
3194 node->unique_id = udf_rw64(fe->unique_id);
3195
3196 /* XXX FAULT INJECTION POINT XXX */
3197 //if (fe->unique_id == 33) { return ENOENT;}
3198
3199 }
3200 if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
3201 efe = (struct extfile_entry *) dscr;
3202 icb = &efe->icbtag;
3203 node->declared.inf_len = udf_rw64(efe->inf_len);
3204 node->declared.obj_size = udf_rw64(efe->obj_size);
3205 node->declared.logblks_rec = udf_rw64(efe->logblks_rec);
3206 node->link_count = udf_rw16(efe->link_cnt);
3207 node->unique_id = udf_rw64(efe->unique_id);
3208 node->streamdir_loc = efe->streamdir_icb;
3209 if (node->streamdir_loc.len)
3210 node->fsck_flags |= FSCK_NODE_FLAG_HAS_STREAM_DIR;
3211
3212 /* XXX FAULT INJECTION POINT XXX */
3213 //if (efe->unique_id == 0x891) { return ENOENT;}
3214
3215 }
3216
3217 if (!fe && !efe) {
3218 //printf("NOT REFERENCING AN FE/EFE!\n");
3219 return ENOENT;
3220 }
3221
3222 if (node->unique_id >= context.unique_id)
3223 context.unique_id = node->unique_id+1;
3224
3225 ad_type = udf_rw16(icb->flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
3226 if ((ad_type != UDF_ICB_INTERN_ALLOC) &&
3227 (ad_type != UDF_ICB_SHORT_ALLOC) &&
3228 (ad_type != UDF_ICB_LONG_ALLOC)) {
3229 pwarn("%s : unknown allocation type\n",
3230 udf_node_path(node));
3231 return EINVAL;
3232 }
3233
3234 bzero(&node->found, sizeof(node->found));
3235 error = udf_process_file(dscr, udf_rw16(node->loc.loc.part_num), NULL,
3236 AD_GATHER_STATS, (void *) &node->found);
3237
3238 switch (icb->file_type) {
3239 case UDF_ICB_FILETYPE_RANDOMACCESS :
3240 case UDF_ICB_FILETYPE_BLOCKDEVICE :
3241 case UDF_ICB_FILETYPE_CHARDEVICE :
3242 case UDF_ICB_FILETYPE_FIFO :
3243 case UDF_ICB_FILETYPE_SOCKET :
3244 case UDF_ICB_FILETYPE_SYMLINK :
3245 case UDF_ICB_FILETYPE_REALTIME :
3246 break;
3247 default:
3248 /* unknown or unsupported file type, TODO clearing? */
3249 free(dscr);
3250 pwarn("%s : specification violation, unknown file type %d\n",
3251 udf_node_path(node), icb->file_type);
3252 return ENOENT;
3253 case UDF_ICB_FILETYPE_STREAMDIR :
3254 case UDF_ICB_FILETYPE_DIRECTORY :
3255 /* read in the directory contents */
3256 error = udf_readin_file(dscr, udf_rw16(node->loc.loc.part_num),
3257 &node->directory, NULL);
3258
3259 /* XXX FAULT INJECTION POINT XXX */
3260 //if (dscr->efe.unique_id == 109) node->directory[125] = 0xff;
3261 //if (dscr->efe.unique_id == 310) memset(node->directory+1024, 0, 300);
3262
3263 if (error && !be_quiet) {
3264 pwarn("%s : directory has read errors\n",
3265 udf_node_path(node));
3266 if (ask(0, "Directory could be fixed or cleared. "
3267 "Wipe defective directory")) {
3268 return ENOENT;
3269 }
3270 udf_recursive_keep(node);
3271 node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3272 }
3273 node->fsck_flags |= FSCK_NODE_FLAG_DIRECTORY;
3274 error = udf_quick_check_fids(node, dscr);
3275 if (error) {
3276 if (!(node->fsck_flags & FSCK_NODE_FLAG_REPAIRDIR))
3277 pwarn("%s : directory file entries need repair\n",
3278 udf_node_path(node));
3279 udf_recursive_keep(node);
3280 node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3281 }
3282 }
3283
3284 /* XXX FAULT INJECTION POINT XXX */
3285 //if (fe->unique_id == 0) node->link_count++;
3286 //if (efe->unique_id == 0) node->link_count++;
3287 //if (efe->unique_id == 772) { node->declared.inf_len += 205; node->declared.obj_size -= 0; }
3288
3289 return 0;
3290 }
3291
3292
3293 static void
3294 udf_fixup_lengths_pass1(struct udf_fsck_node *node, union dscrptr *dscr)
3295 {
3296 int64_t diff;
3297
3298 /* file length check */
3299 diff = node->found.inf_len - node->declared.inf_len;
3300 if (diff) {
3301 pwarn("%s : recorded information length incorrect: "
3302 "%lu instead of declared %lu\n",
3303 udf_node_path(node),
3304 node->found.inf_len, node->declared.inf_len);
3305 node->declared.inf_len = node->found.inf_len;
3306 udf_recursive_keep(node);
3307 node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
3308 }
3309
3310 /* recorded logical blocks count check */
3311 diff = node->found.logblks_rec - node->declared.logblks_rec;
3312 if (diff) {
3313 pwarn("%s : logical blocks recorded incorrect: "
3314 "%lu instead of declared %lu, fixing\n",
3315 udf_node_path(node),
3316 node->found.logblks_rec, node->declared.logblks_rec);
3317 node->declared.logblks_rec = node->found.logblks_rec;
3318 udf_recursive_keep(node);
3319 node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
3320 }
3321
3322 /* tally object sizes for streamdirs */
3323 node->found.obj_size = node->found.inf_len;
3324 if (node->fsck_flags & FSCK_NODE_FLAG_STREAM_ENTRY) {
3325 assert(node->parent); /* streamdir itself */
3326 if (node->parent->parent)
3327 node->parent->parent->found.obj_size +=
3328 node->found.inf_len;
3329 }
3330
3331 /* check descriptor CRC length */
3332 if (udf_rw16(dscr->tag.desc_crc_len) !=
3333 udf_tagsize(dscr, 1) - sizeof(struct desc_tag)) {
3334 pwarn("%s : node file descriptor CRC length mismatch; "
3335 "%d declared, %ld expected\n",
3336 udf_node_path(node), udf_rw16(dscr->tag.desc_crc_len),
3337 udf_tagsize(dscr, 1) - sizeof(struct desc_tag));
3338 udf_recursive_keep(node);
3339 node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
3340 }
3341 }
3342
3343
3344 static void
3345 udf_node_pass1_add_entry(struct udf_fsck_node *node,
3346 struct fileid_desc *fid, struct dirent *dirent)
3347 {
3348 struct udf_fsck_node *leaf_node;
3349 int entry;
3350
3351 /* skip deleted FID entries */
3352 if (fid->file_char & UDF_FILE_CHAR_DEL)
3353 return;
3354
3355 if (udf_rw32(fid->icb.loc.lb_num) == 0) {
3356 pwarn("%s : FileID entry `%s` has invalid location\n",
3357 udf_node_path(node), dirent->d_name);
3358 udf_recursive_keep(node);
3359 if (node->parent)
3360 node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3361 return;
3362 }
3363
3364 /* increase parent link count */
3365 if (fid->file_char & UDF_FILE_CHAR_PAR) {
3366 if (node->parent)
3367 node->parent->found_link_count++;
3368 return;
3369 }
3370
3371 /* lookup if we already know this node */
3372 leaf_node = udf_node_lookup(&fid->icb);
3373 if (leaf_node) {
3374 /* got a hard link! */
3375 leaf_node->found_link_count++;
3376 return;
3377 }
3378
3379 /* create new node */
3380 leaf_node = udf_new_fsck_node(
3381 node, &fid->icb, dirent->d_name);
3382 if (node->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR)
3383 leaf_node->fsck_flags |= FSCK_NODE_FLAG_STREAM_ENTRY;
3384
3385 TAILQ_INSERT_TAIL(&fs_nodes, leaf_node, next);
3386 entry = udf_calc_node_hash(&fid->icb);
3387 LIST_INSERT_HEAD(&fs_nodes_hash[entry], leaf_node, next_hash);
3388 }
3389
3390
3391 static void
3392 udf_node_pass1_add_streamdir_entry(struct udf_fsck_node *node)
3393 {
3394 struct udf_fsck_node *leaf_node;
3395 int entry;
3396
3397 /* check for recursion */
3398 if (node->fsck_flags & FSCK_NODE_FLAG_STREAM) {
3399 /* recursive streams are not allowed by spec */
3400 pwarn("%s : specification violation, recursive stream dir\n",
3401 udf_node_path(node));
3402 udf_recursive_keep(node);
3403 node->fsck_flags |= FSCK_NODE_FLAG_WIPE_STREAM_DIR;
3404 return;
3405 }
3406
3407 /* lookup if we already know this node */
3408 leaf_node = udf_node_lookup(&node->streamdir_loc);
3409 if (leaf_node) {
3410 pwarn("%s : specification violation, hardlinked streamdir\n",
3411 udf_node_path(leaf_node));
3412 udf_recursive_keep(node);
3413 node->fsck_flags |= FSCK_NODE_FLAG_WIPE_STREAM_DIR;
3414 return;
3415 }
3416
3417 /* create new node */
3418 leaf_node = udf_new_fsck_node(
3419 node, &node->streamdir_loc, strdup(""));
3420 leaf_node->fsck_flags |= FSCK_NODE_FLAG_STREAM_DIR;
3421
3422 /* streamdirs have link count 0 : ECMA 4/14.9.6 */
3423 leaf_node->found_link_count--;
3424
3425 /* insert in to lists */
3426 TAILQ_INSERT_TAIL(&fs_nodes, leaf_node, next);
3427 entry = udf_calc_node_hash(&node->streamdir_loc);
3428 LIST_INSERT_HEAD(&fs_nodes_hash[entry], leaf_node, next_hash);
3429 }
3430
3431
3432 static int
3433 udf_process_node_pass1(struct udf_fsck_node *node, union dscrptr *dscr)
3434 {
3435 struct fileid_desc *fid;
3436 struct dirent dirent;
3437 struct charspec osta_charspec;
3438 int64_t fpos, new_length, rest_len;
3439 uint32_t fid_len;
3440 uint8_t *bpos;
3441 int isdir;
3442 int error;
3443
3444 isdir = node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY;
3445
3446 /* keep link count */
3447 node->found_link_count++;
3448
3449 if (isdir) {
3450 assert(node->directory);
3451 udf_rebuild_fid_stream(node, &new_length);
3452 node->found.inf_len = new_length;
3453 rest_len = new_length;
3454 }
3455
3456 udf_fixup_lengths_pass1(node, dscr);
3457
3458 /* check UniqueID */
3459 if (node->parent) {
3460 if (node->fsck_flags & FSCK_NODE_FLAG_STREAM) {
3461
3462 /* XXX FAULT INJECTION POINT XXX */
3463 //node->unique_id = 0xdeadbeefcafe;
3464
3465 if (node->unique_id != node->parent->unique_id) {
3466 pwarn("%s : stream file/dir UniqueID mismatch "
3467 "with parent\n",
3468 udf_node_path(node));
3469 /* do the work here prematurely for our siblings */
3470 udf_recursive_keep(node);
3471 node->unique_id = node->parent->unique_id;
3472 node->fsck_flags |= FSCK_NODE_FLAG_COPY_PARENT_ID |
3473 FSCK_NODE_FLAG_DIRTY;
3474 assert(node->parent);
3475 node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3476 }
3477 } else if (node->unique_id < 16) {
3478 pwarn("%s : file has bad UniqueID\n",
3479 udf_node_path(node));
3480 udf_recursive_keep(node);
3481 node->fsck_flags |= FSCK_NODE_FLAG_NEW_UNIQUE_ID;
3482 assert(node->parent);
3483 node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3484 }
3485 } else {
3486 /* rootdir */
3487 if (node->unique_id != 0) {
3488 pwarn("%s : has bad UniqueID, has to be zero\n",
3489 udf_node_path(node));
3490 udf_recursive_keep(node);
3491 node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3492 }
3493 }
3494
3495 /* add streamdir if present */
3496 if (node->fsck_flags & FSCK_NODE_FLAG_HAS_STREAM_DIR)
3497 udf_node_pass1_add_streamdir_entry(node);
3498
3499 /* add all children */
3500 if (isdir) {
3501 node->fsck_flags |= FSCK_NODE_FLAG_PAR_NOT_FOUND;
3502 rest_len = node->found.inf_len;
3503
3504 /* walk through all our FIDs in the directory stream */
3505 bpos = node->directory;
3506 fpos = 0;
3507 while (rest_len > 0) {
3508 fid = (struct fileid_desc *) bpos;
3509 fid_len = udf_fidsize(fid);
3510
3511 /* get printable name */
3512 memset(&dirent, 0, sizeof(dirent));
3513 udf_osta_charset(&osta_charspec);
3514 udf_to_unix_name(dirent.d_name, NAME_MAX,
3515 (char *) fid->data + udf_rw16(fid->l_iu), fid->l_fi,
3516 &osta_charspec);
3517 dirent.d_namlen = strlen(dirent.d_name);
3518
3519 /* '..' has no name, so provide one */
3520 if (fid->file_char & UDF_FILE_CHAR_PAR) {
3521 strcpy(dirent.d_name, "..");
3522 node->fsck_flags &= ~FSCK_NODE_FLAG_PAR_NOT_FOUND;
3523 }
3524
3525 udf_node_pass1_add_entry(node, fid, &dirent);
3526
3527 fpos += fid_len;
3528 bpos += fid_len;
3529 rest_len -= fid_len;
3530 }
3531 }
3532
3533 error = udf_process_file(dscr, udf_rw16(node->loc.loc.part_num), NULL,
3534 AD_CHECK_USED, node);
3535 if (error) {
3536 pwarn("%s : internal error: checking for being allocated shouldn't fail\n",
3537 udf_node_path(node));
3538 return EINVAL;
3539 }
3540 /* file/directory is OK and referenced as its size won't change */
3541 error = udf_process_file(dscr, udf_rw16(node->loc.loc.part_num), NULL,
3542 AD_MARK_AS_USED, NULL);
3543 if (error) {
3544 pwarn("%s : internal error: marking allocated shouldn't fail\n",
3545 udf_node_path(node));
3546 return EINVAL;
3547 }
3548 return 0;
3549 }
3550
3551
3552 static void
3553 udf_node_pass3_repairdir(struct udf_fsck_node *node, union dscrptr *dscr)
3554 {
3555 struct fileid_desc *fid, *last_empty_fid;
3556 struct udf_fsck_node *file_node;
3557 struct udf_fsck_fid_context fid_context;
3558 struct dirent dirent;
3559 struct charspec osta_charspec;
3560 int64_t fpos, rest_len;
3561 uint32_t fid_len;
3562 uint8_t *bpos;
3563 int parent_missing;
3564 int error;
3565
3566 pwarn("%s : fixing up directory\n", udf_node_path(node));
3567 assert(node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY);
3568
3569 rest_len = node->found.inf_len;
3570
3571 udf_osta_charset(&osta_charspec);
3572 bpos = node->directory;
3573 fpos = 0;
3574 parent_missing = (node->fsck_flags & FSCK_NODE_FLAG_PAR_NOT_FOUND)? 1:0;
3575
3576 last_empty_fid = NULL;
3577 while (rest_len > 0) {
3578 fid = (struct fileid_desc *) bpos;
3579 fid_len = udf_fidsize(fid);
3580
3581 /* get printable name */
3582 memset(&dirent, 0, sizeof(dirent));
3583 udf_to_unix_name(dirent.d_name, NAME_MAX,
3584 (char *) fid->data + udf_rw16(fid->l_iu), fid->l_fi,
3585 &osta_charspec);
3586 dirent.d_namlen = strlen(dirent.d_name);
3587
3588 /* '..' has no name, so provide one */
3589 if (fid->file_char & UDF_FILE_CHAR_PAR) {
3590 strcpy(dirent.d_name, "..");
3591 }
3592
3593 /* only look up when not deleted */
3594 file_node = NULL;
3595 if ((fid->file_char & UDF_FILE_CHAR_DEL) == 0)
3596 file_node = udf_node_lookup(&fid->icb);
3597
3598 /* if found */
3599 if (file_node) {
3600 /* delete files which couldn't be found */
3601 if (file_node && (file_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)) {
3602 fid->file_char |= UDF_FILE_CHAR_DEL;
3603 memset(&fid->icb, 0, sizeof(struct long_ad));
3604 }
3605
3606 /* fix up FID UniqueID errors */
3607 if (fid->icb.longad_uniqueid != file_node->unique_id)
3608 fid->icb.longad_uniqueid = udf_rw64(file_node->unique_id);
3609 } else {
3610 /* just mark it deleted if not found */
3611 fid->file_char |= UDF_FILE_CHAR_DEL;
3612 }
3613
3614 if (fid->file_char & UDF_FILE_CHAR_DEL) {
3615 memset(&fid->icb, 0 , sizeof(struct long_ad));
3616 if (context.dscrver == 2) {
3617 uint8_t *cpos;
3618 /* compression IDs are preserved */
3619 cpos = (fid->data + udf_rw16(fid->l_iu));
3620 if (*cpos == 254)
3621 *cpos = 8;
3622 if (*cpos == 255)
3623 *cpos = 16;
3624 }
3625 }
3626
3627 fpos += fid_len;
3628 bpos += fid_len;
3629 rest_len -= fid_len;
3630 assert(rest_len >= 0);
3631 }
3632 if (parent_missing) {
3633 /* this should be valid or we're in LALA land */
3634 assert(last_empty_fid);
3635 pwarn("%s : implementation limit, can't fix up missing parent node yet!\n",
3636 udf_node_path(node));
3637 }
3638
3639 node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
3640
3641 fid_context.fid_offset = 0;
3642 fid_context.data_left = node->found.inf_len;
3643 error = udf_process_file(dscr, context.fids_part,
3644 &node->directory,
3645 AD_ADJUST_FIDS | AD_SAVE_FILE,
3646 &fid_context);
3647 if (error)
3648 pwarn("Failed to write out directory!\n");
3649 }
3650
3651
3652 static void
3653 udf_node_pass3_writeout_update(struct udf_fsck_node *node, union dscrptr *dscr)
3654 {
3655 struct file_entry *fe = NULL;
3656 struct extfile_entry *efe = NULL;
3657 int error;
3658
3659 vat_writeout = 1;
3660 if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
3661 fe = (struct file_entry *) dscr;
3662 fe->inf_len = udf_rw64(node->declared.inf_len);
3663 fe->logblks_rec = udf_rw64(node->declared.logblks_rec);
3664 fe->link_cnt = udf_rw16(node->link_count);
3665 fe->unique_id = udf_rw64(node->unique_id);
3666 }
3667 if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
3668 efe = (struct extfile_entry *) dscr;
3669 efe->inf_len = udf_rw64(node->declared.inf_len);
3670 efe->obj_size = udf_rw64(node->declared.obj_size);
3671 efe->logblks_rec = udf_rw64(node->declared.logblks_rec);
3672 efe->link_cnt = udf_rw16(node->link_count);
3673 efe->unique_id = udf_rw64(node->unique_id);
3674 /* streamdir directly cleared in dscr */
3675 }
3676
3677 /* fixup CRC length (if needed) */
3678 dscr->tag.desc_crc_len = udf_tagsize(dscr, 1) - sizeof(struct desc_tag);
3679
3680 pwarn("%s : updating node\n", udf_node_path(node));
3681 error = udf_write_dscr_virt(dscr, udf_rw32(node->loc.loc.lb_num),
3682 udf_rw16(node->loc.loc.part_num), 1);
3683 udf_shadow_VAT_in_use(&node->loc);
3684 if (error)
3685 pwarn("%s failed\n", __func__);
3686 }
3687
3688
3689 static void
3690 udf_create_new_space_bitmaps_and_reset_freespace(void)
3691 {
3692 struct space_bitmap_desc *sbd, *new_sbd;
3693 struct part_desc *part;
3694 struct part_hdr_desc *phd;
3695 uint32_t bitmap_len, bitmap_lb, bitmap_numlb;
3696 uint32_t cnt;
3697 int i, p, dscr_size;
3698 int error;
3699
3700 /* copy recorded freespace info and clear counters */
3701 for (i = 0; i < UDF_PARTITIONS; i++) {
3702 recorded_part_free[i] = context.part_free[i];
3703 context.part_free[i] = context.part_size[i];
3704 }
3705
3706 /* clone existing bitmaps */
3707 for (i = 0; i < UDF_PARTITIONS; i++) {
3708 sbd = context.part_unalloc_bits[i];
3709 recorded_part_unalloc_bits[i] = sbd;
3710 if (sbd == NULL)
3711 continue;
3712 dscr_size = udf_tagsize((union dscrptr *) sbd,
3713 context.sector_size);
3714 new_sbd = calloc(1, dscr_size);
3715 memcpy(new_sbd, sbd, sizeof(struct space_bitmap_desc)-1);
3716
3717 /* fill space with 0xff to indicate free */
3718 for (cnt = 0; cnt < udf_rw32(sbd->num_bytes); cnt++)
3719 new_sbd->data[cnt] = 0xff;
3720
3721 context.part_unalloc_bits[i] = new_sbd;
3722 }
3723
3724 /* allocate the space bitmaps themselves (normally one) */
3725 for (i = 0; i < UDF_PARTITIONS; i++) {
3726 part = context.partitions[i];
3727 if (!part)
3728 continue;
3729
3730 phd = &part->pd_part_hdr;
3731 bitmap_len = udf_rw32(phd->unalloc_space_bitmap.len);
3732 bitmap_lb = udf_rw32(phd->unalloc_space_bitmap.lb_num);
3733 if (bitmap_len == 0)
3734 continue;
3735
3736 bitmap_numlb = udf_bytes_to_sectors(bitmap_len);
3737 sbd = context.part_unalloc_bits[i];
3738 assert(sbd);
3739
3740 udf_mark_allocated(bitmap_lb, context.vtop[i], bitmap_numlb);
3741 }
3742
3743 /* special case for metadata partition */
3744 if (context.format_flags & FORMAT_META) {
3745 i = context.metadata_part;
3746 p = context.vtop[i];
3747 assert(context.vtop_tp[i] == UDF_VTOP_TYPE_META);
3748 error = udf_process_file((union dscrptr *) context.meta_file,
3749 p, NULL, AD_MARK_AS_USED, NULL);
3750 error = udf_process_file((union dscrptr *) context.meta_mirror,
3751 p, NULL, AD_MARK_AS_USED, NULL);
3752 if (context.meta_bitmap) {
3753 error = udf_process_file(
3754 (union dscrptr *) context.meta_bitmap,
3755 p, NULL, AD_MARK_AS_USED, NULL);
3756 assert(error == 0);
3757 }
3758 }
3759
3760 /* mark fsd allocation ! */
3761 udf_mark_allocated(udf_rw32(context.fileset_desc->tag.tag_loc),
3762 context.metadata_part, 1);
3763 }
3764
3765
3766 static void
3767 udf_shadow_VAT_in_use(struct long_ad *loc)
3768 {
3769 uint32_t i;
3770 uint8_t *vat_pos, *shadow_vat_pos;
3771
3772 if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
3773 return;
3774
3775 i = udf_rw32(loc->loc.lb_num);
3776 vat_pos = context.vat_contents + context.vat_start + i*4;
3777 shadow_vat_pos = shadow_vat_contents + context.vat_start + i*4;
3778 /* keeping endian */
3779 *(uint32_t *) shadow_vat_pos = *(uint32_t *) vat_pos;
3780 }
3781
3782
3783 static void
3784 udf_create_shadow_VAT(void)
3785 {
3786 struct long_ad fsd_loc;
3787 uint32_t vat_entries, i;
3788 uint8_t *vat_pos;
3789
3790 if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
3791 return;
3792
3793 shadow_vat_contents = calloc(1, context.vat_allocated);
3794 assert(shadow_vat_contents);
3795 memcpy(shadow_vat_contents, context.vat_contents, context.vat_size);
3796
3797 vat_entries = (context.vat_size - context.vat_start)/4;
3798 for (i = 0; i < vat_entries; i++) {
3799 vat_pos = shadow_vat_contents + context.vat_start + i*4;
3800 *(uint32_t *) vat_pos = udf_rw32(0xffffffff);
3801 }
3802
3803 /*
3804 * Record our FSD in this shadow VAT since its the only one outside
3805 * the nodes.
3806 */
3807 memset(&fsd_loc, 0, sizeof(struct long_ad));
3808 fsd_loc.loc.lb_num = context.fileset_desc->tag.tag_loc;
3809 udf_shadow_VAT_in_use(&fsd_loc);
3810 }
3811
3812
3813 static void
3814 udf_check_shadow_VAT(void)
3815 {
3816 uint32_t vat_entries, i;
3817 uint8_t *vat_pos, *shadow_vat_pos;
3818 int difference = 0;
3819
3820 if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
3821 return;
3822
3823 vat_entries = (context.vat_size - context.vat_start)/4;
3824 for (i = 0; i < vat_entries; i++) {
3825 vat_pos = context.vat_contents + context.vat_start + i*4;
3826 shadow_vat_pos = shadow_vat_contents + context.vat_start + i*4;
3827 if (*(uint32_t *) vat_pos != *(uint32_t *) shadow_vat_pos) {
3828 difference++;
3829 }
3830 }
3831 memcpy(context.vat_contents, shadow_vat_contents, context.vat_size);
3832 if (difference) {
3833 if (!preen)
3834 printf("\t\t");
3835 pwarn("%d unused VAT entries cleaned\n", difference);
3836 vat_writeout = 1;
3837 }
3838 }
3839
3840
3841 static int
3842 udf_check_directory_tree(void)
3843 {
3844 union dscrptr *dscr;
3845 struct udf_fsck_node *root_node, *sys_stream_node;
3846 struct udf_fsck_node *cur_node, *next_node;
3847 struct long_ad root_icb, sys_stream_icb;
3848 bool dont_repair;
3849 int entry, error;
3850
3851 assert(TAILQ_EMPTY(&fs_nodes));
3852
3853 /* (re)init queues and hash lists */
3854 TAILQ_INIT(&fs_nodes);
3855 TAILQ_INIT(&fsck_overlaps);
3856 for (int i = 0; i < HASH_HASHSIZE; i++)
3857 LIST_INIT(&fs_nodes_hash[i]);
3858
3859 /* create a new empty copy of the space bitmaps */
3860 udf_create_new_space_bitmaps_and_reset_freespace();
3861 udf_create_shadow_VAT();
3862
3863 /* start from the root */
3864 root_icb = context.fileset_desc->rootdir_icb;
3865 sys_stream_icb = context.fileset_desc->streamdir_icb;
3866
3867 root_node = udf_new_fsck_node(NULL, &root_icb, strdup(""));
3868 assert(root_node);
3869 TAILQ_INSERT_TAIL(&fs_nodes, root_node, next);
3870 entry = udf_calc_node_hash(&root_node->loc);
3871 LIST_INSERT_HEAD(&fs_nodes_hash[entry], root_node, next_hash);
3872
3873 sys_stream_node = NULL;
3874 if (sys_stream_icb.len) {
3875 sys_stream_node = udf_new_fsck_node(NULL, &sys_stream_icb, strdup("#"));
3876 assert(sys_stream_node);
3877 sys_stream_node->fsck_flags |= FSCK_NODE_FLAG_STREAM_DIR;
3878
3879 TAILQ_INSERT_TAIL(&fs_nodes, sys_stream_node, next);
3880 entry = udf_calc_node_hash(&sys_stream_node->loc);
3881 LIST_INSERT_HEAD(&fs_nodes_hash[entry], sys_stream_node, next_hash);
3882 }
3883
3884 /* pass 1 */
3885 if (!preen)
3886 printf("\tPass 1, reading in directory trees\n");
3887
3888 context.unique_id = MAX(0x10, context.unique_id);
3889 TAILQ_FOREACH(cur_node, &fs_nodes, next) {
3890 /* read in node */
3891 error = udf_read_node_dscr(cur_node, &dscr);
3892 if (!error)
3893 error = udf_extract_node_info(cur_node, dscr, 0);
3894 if (error) {
3895 pwarn("%s : invalid reference or bad descriptor, DELETING\n",
3896 udf_node_path(cur_node));
3897 udf_recursive_keep(cur_node);
3898 cur_node->fsck_flags |= FSCK_NODE_FLAG_NOTFOUND;
3899 if (cur_node->parent) {
3900 if (cur_node->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR)
3901 cur_node->parent->fsck_flags |=
3902 FSCK_NODE_FLAG_WIPE_STREAM_DIR;
3903 else
3904 cur_node->parent->fsck_flags |=
3905 FSCK_NODE_FLAG_REPAIRDIR;
3906 ;
3907 }
3908 free(dscr);
3909 continue;
3910 }
3911
3912 if (print_info) {
3913 pwarn("Processing %s\n", udf_node_path(cur_node));
3914 print_info = 0;
3915 }
3916
3917 /* directory found in stream directory? */
3918 if (cur_node->parent &&
3919 (cur_node->parent->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR) &&
3920 (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY))
3921 {
3922 pwarn("%s : specification violation, directory in stream directory\n",
3923 udf_node_path(cur_node));
3924 if (ask(0, "Clear directory")) {
3925 udf_recursive_keep(cur_node);
3926 cur_node->fsck_flags |= FSCK_NODE_FLAG_NOTFOUND;
3927 cur_node->parent->fsck_flags |=
3928 FSCK_NODE_FLAG_REPAIRDIR;
3929 continue;
3930 }
3931 }
3932 error = udf_process_node_pass1(cur_node, dscr);
3933 free(dscr);
3934
3935 if (error)
3936 return error;
3937 }
3938
3939 /* pass 1b, if there is overlap, find matching pairs */
3940 dont_repair = false;
3941 if (!TAILQ_EMPTY(&fsck_overlaps)) {
3942 struct udf_fsck_overlap *overlap;
3943
3944 dont_repair = true;
3945 pwarn("*** Overlaps detected! rescanning tree for matching pairs ***\n");
3946 TAILQ_FOREACH(cur_node, &fs_nodes, next) {
3947 if (cur_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)
3948 continue;
3949
3950 error = udf_read_node_dscr(cur_node, &dscr);
3951 /* should not fail differently */
3952
3953 if (print_info) {
3954 pwarn("Processing %s\n", udf_node_path(cur_node));
3955 print_info = 0;
3956 }
3957
3958 error = udf_process_file(
3959 dscr,
3960 udf_rw16(cur_node->loc.loc.part_num),
3961 NULL,
3962 AD_FIND_OVERLAP_PAIR,
3963 (void *) cur_node);
3964 /* shouldn't fail */
3965
3966 free(dscr);
3967 }
3968 TAILQ_FOREACH(overlap, &fsck_overlaps, next) {
3969 pwarn("%s :overlaps with %s\n",
3970 udf_node_path(overlap->node),
3971 udf_node_path(overlap->node2));
3972 }
3973 if (!preen)
3974 printf("\n");
3975 pwarn("*** The following files/directories need to be copied/evacuated:\n");
3976 TAILQ_FOREACH(cur_node, &fs_nodes, next) {
3977 if (cur_node->fsck_flags & FSCK_NODE_FLAG_OVERLAP) {
3978 pwarn("%s : found OVERLAP, evacuate\n",
3979 udf_node_path(cur_node));
3980 }
3981 }
3982 }
3983 if (dont_repair) {
3984 if (!preen)
3985 printf("\n");
3986 pwarn("*** Skipping further repair, only updating free space map if needed\n");
3987 pwarn("*** After deep copying and/or evacuation of these files/directories,\n");
3988 pwarn("*** remove files/directories and re-run fsck_udf\n");
3989 error = udf_prepare_writing();
3990 if (error)
3991 return error;
3992
3993 udf_update_lvintd(UDF_INTEGRITY_OPEN);
3994 return 0;
3995 }
3996
3997 /* pass 2a, checking link counts, object sizes and count files/dirs */
3998 if (!preen)
3999 printf("\n\tPass 2, checking link counts, object sizes, stats and cleaning up\n");
4000
4001 TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) {
4002 /* not sane to process files/directories that are not found */
4003 if (cur_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)
4004 continue;
4005
4006 /* shadow VAT */
4007 udf_shadow_VAT_in_use(&cur_node->loc);
4008
4009 /* link counts */
4010 if (cur_node->found_link_count != cur_node->link_count) {
4011 pwarn("%s : link count incorrect; "
4012 "%u instead of declared %u : FIXED\n",
4013 udf_node_path(cur_node),
4014 cur_node->found_link_count, cur_node->link_count);
4015 cur_node->link_count = cur_node->found_link_count;
4016 udf_recursive_keep(cur_node);
4017 cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
4018 }
4019
4020 /* object sizes */
4021 if (cur_node->declared.obj_size != cur_node->found.obj_size) {
4022 pwarn("%s : recorded object size incorrect; "
4023 "%lu instead of declared %lu\n",
4024 udf_node_path(cur_node),
4025 cur_node->found.obj_size, cur_node->declared.obj_size);
4026 cur_node->declared.obj_size = cur_node->found.obj_size;
4027 udf_recursive_keep(cur_node);
4028 cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
4029 }
4030
4031 /* XXX TODO XXX times */
4032 /* XXX TODO XXX extended attributes location for UDF < 1.50 */
4033
4034 /* validity of UniqueID check */
4035 if (cur_node->parent) {
4036 if (cur_node->fsck_flags & FSCK_NODE_FLAG_NEW_UNIQUE_ID) {
4037 pwarn("%s : assigning new UniqueID\n",
4038 udf_node_path(cur_node));
4039 cur_node->unique_id = udf_rw64(context.unique_id);
4040 udf_advance_uniqueid();
4041 udf_recursive_keep(cur_node);
4042 cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
4043 if (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY)
4044 cur_node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
4045 cur_node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
4046 }
4047 if (cur_node->fsck_flags & FSCK_NODE_FLAG_COPY_PARENT_ID) {
4048 /* work already done but make note to operator */
4049 pwarn("%s : fixing stream UniqueID to match parent\n",
4050 udf_node_path(cur_node));
4051 }
4052 } else {
4053 if (cur_node->unique_id != 0) {
4054 pwarn("%s : bad UniqueID, zeroing\n",
4055 udf_node_path(cur_node));
4056 cur_node->unique_id = 0;
4057 cur_node->fsck_flags |=
4058 FSCK_NODE_FLAG_DIRTY | FSCK_NODE_FLAG_REPAIRDIR;
4059 }
4060 }
4061
4062 /* keep nodes in a repairing dir */
4063 if (cur_node->parent)
4064 if (cur_node->parent->fsck_flags & FSCK_NODE_FLAG_REPAIRDIR)
4065 cur_node->fsck_flags |= FSCK_NODE_FLAG_KEEP;
4066
4067 /* stream directories and files in it are not included */
4068 if (!(cur_node->fsck_flags & FSCK_NODE_FLAG_STREAM)) {
4069 /* files / directories counting */
4070 int link_count = cur_node->found_link_count;
4071
4072 /* stream directories don't count as link ECMA 4/14.9.6 */
4073 if (cur_node->fsck_flags & FSCK_NODE_FLAG_HAS_STREAM_DIR)
4074 link_count--;
4075
4076 if (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY)
4077 context.num_directories++;
4078 else
4079 context.num_files += link_count;
4080 ;
4081 }
4082 }
4083
4084 /* pass 2b, cleaning */
4085 open_integrity = 0;
4086 TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) {
4087 /* can we remove the node? (to save memory) */
4088 if (FSCK_NODE_FLAG_OK(cur_node->fsck_flags)) {
4089 TAILQ_REMOVE(&fs_nodes, cur_node, next);
4090 LIST_REMOVE(cur_node, next_hash);
4091 free(cur_node->directory);
4092 bzero(cur_node, sizeof(struct udf_fsck_node));
4093 free(cur_node);
4094 } else {
4095 /* else keep erroring node */
4096 open_integrity = 1;
4097 }
4098 }
4099
4100 if (!preen)
4101 printf("\n\tPreparing disc for writing\n");
4102 error = udf_prepare_writing();
4103 if (error)
4104 return error;
4105
4106 if (open_integrity)
4107 udf_update_lvintd(UDF_INTEGRITY_OPEN);
4108
4109 /* pass 3 */
4110 if (!preen)
4111 printf("\n\tPass 3, fix errors\n");
4112
4113 TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) {
4114 /* not sane to process files/directories that are not found */
4115 if (cur_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)
4116 continue;
4117
4118 /* only interested in bad nodes */
4119 if (FSCK_NODE_FLAG_OK(cur_node->fsck_flags))
4120 continue;
4121
4122 error = udf_read_node_dscr(cur_node, &dscr);
4123 /* should not fail differently */
4124
4125 /* repair directories */
4126 if (cur_node->fsck_flags & FSCK_NODE_FLAG_REPAIRDIR)
4127 udf_node_pass3_repairdir(cur_node, dscr);
4128
4129 /* remove invalid stream directories */
4130 if (cur_node->fsck_flags & FSCK_NODE_FLAG_WIPE_STREAM_DIR) {
4131 assert(udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY);
4132 bzero(&dscr->efe.streamdir_icb, sizeof(struct long_ad));
4133 cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
4134 }
4135
4136 if (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRTY)
4137 udf_node_pass3_writeout_update(cur_node, dscr);
4138 free(dscr);
4139 }
4140 udf_check_shadow_VAT();
4141
4142 return 0;
4143 }
4144
4145
4146 static void
4147 udf_cleanup_after_check(void)
4148 {
4149 struct udf_fsck_node *cur_node, *next_node;
4150
4151 /* XXX yes, there are some small memory leaks here */
4152
4153 /* clean old node info from previous checks */
4154 TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) {
4155 TAILQ_REMOVE(&fs_nodes, cur_node, next);
4156 LIST_REMOVE(cur_node, next_hash);
4157 free(cur_node->directory);
4158 free(cur_node);
4159 }
4160
4161 /* free partition related info */
4162 for (int i = 0; i < UDF_PARTITIONS; i++) {
4163 free(context.partitions[i]);
4164 free(context.part_unalloc_bits[i]);
4165 free(context.part_freed_bits[i]);
4166 }
4167
4168 /* only free potentional big blobs */
4169 free(context.vat_contents);
4170 free(context.lvint_history);
4171
4172 free(shadow_vat_contents);
4173 shadow_vat_contents = NULL;
4174 }
4175
4176
4177 static int
4178 checkfilesys(char *given_dev)
4179 {
4180 struct mmc_trackinfo ti;
4181 int open_flags;
4182 int error;
4183
4184 udf_init_create_context();
4185 context.app_name = "*NetBSD UDF";
4186 context.app_version_main = APP_VERSION_MAIN;
4187 context.app_version_sub = APP_VERSION_SUB;
4188 context.impl_name = IMPL_NAME;
4189
4190 emul_mmc_profile = -1; /* invalid->no emulation */
4191 emul_packetsize = 1; /* reasonable default */
4192 emul_sectorsize = 512; /* minimum allowed sector size */
4193 emul_size = 0; /* empty */
4194
4195 if (!preen)
4196 pwarn("** Checking UDF file system on %s\n", given_dev);
4197
4198 /* reset sticky flags */
4199 rdonly = rdonly_flag;
4200 undo_opening_session = 0; /* trying to undo opening of last crippled session */
4201 vat_writeout = 0; /* to write out the VAT anyway */
4202
4203 /* open disc device or emulated file */
4204 open_flags = rdonly ? O_RDONLY : O_RDWR;
4205 if (udf_opendisc(given_dev, open_flags)) {
4206 udf_closedisc();
4207 warnx("can't open %s", given_dev);
4208 return FSCK_EXIT_CHECK_FAILED;
4209 }
4210
4211 if (!preen)
4212 pwarn("** Phase 1 - discovering format from disc\n\n");
4213
4214 /* check if it is an empty disc or no disc in present */
4215 ti.tracknr = mmc_discinfo.first_track;
4216 error = udf_update_trackinfo(&ti);
4217 if (error || (ti.flags & MMC_TRACKINFO_BLANK)) {
4218 /* no use erroring out */
4219 pwarn("Empty disc\n");
4220 return FSCK_EXIT_OK;
4221 }
4222
4223 context.format_flags = 0;
4224 if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL)
4225 context.format_flags |= FORMAT_SEQUENTIAL;
4226
4227 if ((context.format_flags & FORMAT_SEQUENTIAL) &&
4228 ((mmc_discinfo.disc_state == MMC_STATE_CLOSED) ||
4229 (mmc_discinfo.disc_state == MMC_STATE_FULL))) {
4230 pwarn("Disc is closed or full, can't modify disc\n");
4231 rdonly = 1;
4232 }
4233
4234 if (target_session) {
4235 context.create_new_session = 1;
4236 if (target_session < 0)
4237 target_session += mmc_discinfo.num_sessions;
4238 } else {
4239 target_session = mmc_discinfo.num_sessions;
4240 if (mmc_discinfo.last_session_state == MMC_STATE_EMPTY)
4241 target_session--;
4242 }
4243
4244 error = udf_get_anchors();
4245 if (error) {
4246 udf_closedisc();
4247 pwarn("Failed to retrieve anchors; can't check file system\n");
4248 return FSCK_EXIT_CHECK_FAILED;
4249 }
4250
4251 udf_check_vrs9660();
4252
4253 /* get both VRS areas */
4254 error = udf_check_VDS_areas();
4255 if (error) {
4256 udf_closedisc();
4257 pwarn("Failure reading volume descriptors, disc might be toast\n");
4258 return FSCK_EXIT_CHECK_FAILED;
4259 }
4260
4261 if (udf_rw32(context.logvol_integrity->integrity_type) ==
4262 UDF_INTEGRITY_CLOSED) {
4263 if (!force) {
4264 pwarn("** File system is clean; not checking\n");
4265 return FSCK_EXIT_OK;
4266 }
4267 pwarn("** File system is already clean\n");
4268 if (!preen)
4269 pwarn("\n");
4270 } else {
4271 pwarn("** File system not closed properly\n");
4272 if (!preen)
4273 printf("\n");
4274 }
4275
4276 /*
4277 * Only now read in free/unallocated space bitmap. If it reads in fine
4278 * it doesn't mean its contents is valid though. Sets partition
4279 * lengths too.
4280 */
4281 error = udf_readin_partitions_free_space();
4282 if (error) {
4283 pwarn("Error during free space bitmap reading\n");
4284 udf_update_lvintd(UDF_INTEGRITY_OPEN);
4285 }
4286
4287 if (!preen)
4288 pwarn("** Phase 2 - walking directory tree\n");
4289
4290 udf_suspend_writing();
4291 error = udf_check_directory_tree();
4292 if (error) {
4293 if ((!rdonly) && ask(0, "Write out modifications made until now"))
4294 udf_allow_writing();
4295 else
4296 pwarn("** Aborting repair, not modifying disc\n");
4297 udf_closedisc();
4298 return FSCK_EXIT_CHECK_FAILED;
4299 }
4300
4301 if (!preen)
4302 pwarn("\n** Phase 3 - closing volume if needed\n\n");
4303
4304 /* XXX FAULT INJECTION POINT XXX */
4305 //udf_update_lvintd(UDF_INTEGRITY_OPEN);
4306
4307 if (error && rdonly) {
4308 pwarn("** Aborting repair, nothing written, disc marked read-only\n");
4309 } else {
4310 error = udf_close_volume();
4311 }
4312
4313 udf_closedisc();
4314
4315 if (error)
4316 return FSCK_EXIT_CHECK_FAILED;
4317 return FSCK_EXIT_OK;
4318 }
4319
4320
4321 static void
4322 usage(void)
4323 {
4324 (void)fprintf(stderr, "Usage: %s [-fHnpSsy] file-system ... \n",
4325 getprogname());
4326 exit(FSCK_EXIT_USAGE);
4327 }
4328
4329
4330 static void
4331 got_siginfo(int signo)
4332 {
4333 print_info = 1;
4334 }
4335
4336
4337 int
4338 main(int argc, char **argv)
4339 {
4340 int ret = FSCK_EXIT_OK, erg;
4341 int ch;
4342
4343 while ((ch = getopt(argc, argv, "ps:SynfH")) != -1) {
4344 switch (ch) {
4345 case 'H':
4346 heuristics = 1;
4347 break;
4348 case 'f':
4349 force = 1;
4350 break;
4351 case 'n':
4352 rdonly_flag = alwaysno = 1;
4353 alwaysyes = preen = 0;
4354 break;
4355 case 'y':
4356 alwaysyes = 1;
4357 alwaysno = preen = 0;
4358 break;
4359 case 'p':
4360 /* small automatic repairs */
4361 preen = 1;
4362 alwaysyes = alwaysno = 0;
4363 break;
4364 case 's':
4365 /* session number or relative session */
4366 target_session = atoi(optarg);
4367 break;
4368 case 'S': /* Search for older VATs */
4369 search_older_vat = 1;
4370 break;
4371
4372 default:
4373 usage();
4374 break;
4375 }
4376 }
4377 argc -= optind;
4378 argv += optind;
4379
4380 if (!argc)
4381 usage();
4382
4383 /* TODO SIGINT and SIGQUIT catchers */
4384 #if 0
4385 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
4386 (void) signal(SIGINT, catch);
4387 if (preen)
4388 (void) signal(SIGQUIT, catch);
4389 #endif
4390
4391 signal(SIGINFO, got_siginfo);
4392
4393 while (--argc >= 0) {
4394 setcdevname(*argv, preen);
4395 erg = checkfilesys(*argv++);
4396 if (erg > ret)
4397 ret = erg;
4398 if (!preen)
4399 printf("\n");
4400 udf_cleanup_after_check();
4401 }
4402
4403 return ret;
4404 }
4405
4406
4407 /*VARARGS*/
4408 static int
4409 ask(int def, const char *fmt, ...)
4410 {
4411 va_list ap;
4412
4413 char prompt[256];
4414 int c;
4415
4416 va_start(ap, fmt);
4417 vsnprintf(prompt, sizeof(prompt), fmt, ap);
4418 va_end(ap);
4419 if (alwaysyes || rdonly) {
4420 pwarn("%s? %s\n", prompt, rdonly ? "no" : "yes");
4421 return !rdonly;
4422 }
4423 if (preen) {
4424 pwarn("%s? %s : (default)\n", prompt, def ? "yes" : "no");
4425 return def;
4426 }
4427
4428 do {
4429 pwarn("%s? [yn] ", prompt);
4430 fflush(stdout);
4431 c = getchar();
4432 while (c != '\n' && getchar() != '\n')
4433 if (feof(stdin))
4434 return 0;
4435 } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
4436 return c == 'y' || c == 'Y';
4437 }
4438
4439
4440 /*VARARGS*/
4441 static int
4442 ask_noauto(int def, const char *fmt, ...)
4443 {
4444 va_list ap;
4445
4446 char prompt[256];
4447 int c;
4448
4449 va_start(ap, fmt);
4450 vsnprintf(prompt, sizeof(prompt), fmt, ap);
4451 va_end(ap);
4452 #if 0
4453 if (preen) {
4454 pwarn("%s? %s : (default)\n", prompt, def ? "yes" : "no");
4455 return def;
4456 }
4457 #endif
4458
4459 do {
4460 pwarn("%s? [yn] ", prompt);
4461 fflush(stdout);
4462 c = getchar();
4463 while (c != '\n' && getchar() != '\n')
4464 if (feof(stdin))
4465 return 0;
4466 } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
4467 return c == 'y' || c == 'Y';
4468 }
4469