main.c revision 1.12 1 /* $NetBSD: main.c,v 1.12 2022/04/25 15:18:15 reinoud 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.12 2022/04/25 15:18:15 reinoud 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_rw32(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_rw32(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 %" PRIi64 " 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 = udf_rw32(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 (void)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 error = 0;
1877 vat_writeout = 1;
1878 goto ok;
1879 }
1880
1881 implext = (struct impl_extattr_entry *) (ea_start + offset);
1882 error = udf_impl_extattr_check(implext);
1883 if (error) {
1884 /* VAT LVExtension checksum failed */
1885 error = 0;
1886 vat_writeout = 1;
1887 goto ok;
1888 }
1889
1890 /* paranoia */
1891 if (a_l != sizeof(*implext) -2 + udf_rw32(implext->iu_l) + sizeof(lvext)) {
1892 /* VAT LVExtension size doesn't compute */
1893 error = 0;
1894 vat_writeout = 1;
1895 goto ok;
1896 }
1897
1898 /*
1899 * We have found our "VAT LVExtension attribute. BUT due to a
1900 * bug in the specification it might not be word aligned so
1901 * copy first to avoid panics on some machines (!!)
1902 */
1903 lvextpos = implext->data + udf_rw32(implext->iu_l);
1904 memcpy(&lvext, lvextpos, sizeof(lvext));
1905
1906 /* check if it was updated the last time */
1907 if (udf_rw64(lvext.unique_id_chk) == vat_unique_id) {
1908 lvinfo->num_files = lvext.num_files;
1909 lvinfo->num_directories = lvext.num_directories;
1910 udf_update_logvolname(lvext.logvol_id);
1911 } else {
1912 /* VAT LVExtension out of date */
1913 vat_writeout = 1;
1914 }
1915 } else {
1916 /* VAT 2.xy format */
1917 /* definition */
1918 vat = (struct udf_vat *) (*vat_contents);
1919 vat_offset = udf_rw16(vat->header_len);
1920 vat_entries = (vat_length - vat_offset)/4;
1921
1922 if (heuristics) {
1923 if (vat->impl_use_len == 0) {
1924 uint32_t start_val;
1925 start_val = udf_rw32(*((uint32_t *) vat->data));
1926 if (start_val == 0x694d2a00) {
1927 /* "<0>*Mic"osoft Windows */
1928 pwarn("Heuristics found corrupted MS Windows VAT\n");
1929 if (ask(0, "Repair")) {
1930 vat->impl_use_len = udf_rw16(32);
1931 vat->header_len = udf_rw16(udf_rw16(vat->header_len) + 32);
1932 vat_offset += 32;
1933 vat_writeout = 1;
1934 }
1935 }
1936 }
1937 }
1938 assert(lvinfo);
1939 lvinfo->num_files = vat->num_files;
1940 lvinfo->num_directories = vat->num_directories;
1941 lvinfo->min_udf_readver = vat->min_udf_readver;
1942 lvinfo->min_udf_writever = vat->min_udf_writever;
1943 lvinfo->max_udf_writever = vat->max_udf_writever;
1944
1945 udf_update_logvolname(vat->logvol_id);
1946 }
1947
1948 /* XXX FAULT INJECTION POINT XXX */
1949 //vat_writeout = 1;
1950
1951 ok:
1952 /* extra sanity checking */
1953 if (tag_id == TAGID_FENTRY) {
1954 /* nothing checked as yet */
1955 } else {
1956 /*
1957 * The following VAT violations are ignored but demand a clean VAT
1958 * writeout for sanity
1959 */
1960 if (!is_zero(&dscr->efe.streamdir_icb, sizeof(struct long_ad))) {
1961 /* VAT specification violation:
1962 * VAT has no cleared streamdir reference */
1963 vat_writeout = 1;
1964 }
1965 if (!is_zero(&dscr->efe.ex_attr_icb, sizeof(struct long_ad))) {
1966 /* VAT specification violation:
1967 * VAT has no cleared extended attribute reference */
1968 vat_writeout = 1;
1969 }
1970 if (dscr->efe.obj_size != dscr->efe.inf_len) {
1971 /* VAT specification violation:
1972 * VAT has invalid object size */
1973 vat_writeout = 1;
1974 }
1975 }
1976
1977 if (!vat_writeout) {
1978 context.logvol_integrity->lvint_next_unique_id = udf_rw64(vat_unique_id);
1979 context.logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_CLOSED);
1980 context.logvol_integrity->time = *mtime;
1981 }
1982
1983 context.unique_id = vat_unique_id;
1984 context.vat_allocated = UDF_ROUNDUP(vat_length, context.sector_size);
1985 context.vat_contents = *vat_contents;
1986 context.vat_start = vat_offset;
1987 context.vat_size = vat_offset + vat_entries * 4;
1988
1989 out:
1990 if (error) {
1991 free(*vat_contents);
1992 *vat_contents = NULL;
1993 }
1994
1995 return error;
1996 }
1997
1998
1999 #define VAT_BLK 256
2000 static int
2001 udf_search_vat(union udf_pmap *mapping, int log_part)
2002 {
2003 union dscrptr *vat_candidate, *accepted_vat;
2004 struct part_desc *pdesc;
2005 struct mmc_trackinfo *ti, *ti_s;
2006 uint32_t part_start;
2007 uint32_t vat_loc, early_vat_loc, late_vat_loc, accepted_vat_loc;
2008 uint32_t first_possible_vat_location, last_possible_vat_location;
2009 uint8_t *vat_contents, *accepted_vat_contents;
2010 int num_tracks, tracknr, found_a_VAT, valid_loc, error;
2011
2012 /*
2013 * Start reading forward in blocks from the first possible vat
2014 * location. If not found in this block, start again a bit before
2015 * until we get a hit.
2016 */
2017
2018 /* get complete list of all our valid ranges */
2019 ti_s = calloc(mmc_discinfo.num_tracks, sizeof(struct mmc_trackinfo));
2020 for (tracknr = 1; tracknr <= mmc_discinfo.num_tracks; tracknr++) {
2021 ti = &ti_s[tracknr];
2022 ti->tracknr = tracknr;
2023 (void) udf_update_trackinfo(ti);
2024 }
2025
2026 /* derive our very first track number our base partition covers */
2027 pdesc = context.partitions[context.data_part];
2028 part_start = udf_rw32(pdesc->start_loc);
2029 for (int cnt = 0; cnt < UDF_PARTITIONS; cnt++) {
2030 pdesc = context.partitions[cnt];
2031 if (!pdesc)
2032 continue;
2033 part_start = MIN(part_start, udf_rw32(pdesc->start_loc));
2034 }
2035 num_tracks = mmc_discinfo.num_tracks;
2036 for (tracknr = 1, ti = NULL; tracknr <= num_tracks; tracknr++) {
2037 ti = &ti_s[tracknr];
2038 if ((part_start >= ti->track_start) &&
2039 (part_start <= ti->track_start + ti->track_size))
2040 break;
2041 }
2042 context.first_ti_partition = *ti;
2043
2044 first_possible_vat_location = context.first_ti_partition.track_start;
2045 last_possible_vat_location = context.last_ti.track_start +
2046 context.last_ti.track_size -
2047 context.last_ti.free_blocks + 1;
2048
2049 /* initial guess is around 16 sectors back */
2050 late_vat_loc = last_possible_vat_location;
2051 early_vat_loc = MAX(late_vat_loc - 16, first_possible_vat_location);
2052
2053 if (!preen)
2054 printf("Full VAT range search from %d to %d\n",
2055 first_possible_vat_location,
2056 last_possible_vat_location);
2057
2058 vat_writeout = 0;
2059 accepted_vat = NULL;
2060 accepted_vat_contents = NULL;
2061 accepted_vat_loc = 0;
2062 do {
2063 vat_loc = early_vat_loc;
2064 if (!preen) {
2065 printf("\tChecking range %8d to %8d\n",
2066 early_vat_loc, late_vat_loc);
2067 fflush(stdout);
2068 }
2069 found_a_VAT = 0;
2070 while (vat_loc <= late_vat_loc) {
2071 if (print_info) {
2072 pwarn("\nchecking for VAT in sector %8d\n", vat_loc);
2073 print_info = 0;
2074 }
2075 /* check if its in readable range */
2076 valid_loc = 0;
2077 for (tracknr = 1; tracknr <= num_tracks; tracknr++) {
2078 ti = &ti_s[tracknr];
2079 if (!(ti->flags & MMC_TRACKINFO_BLANK) &&
2080 ((vat_loc >= ti->track_start) &&
2081 (vat_loc <= ti->track_start + ti->track_size))) {
2082 valid_loc = 1;
2083 break;
2084 }
2085 }
2086 if (!valid_loc) {
2087 vat_loc++;
2088 continue;
2089 }
2090
2091 error = udf_read_dscr_phys(vat_loc, &vat_candidate);
2092 if (!vat_candidate)
2093 error = ENOENT;
2094 if (!error)
2095 error = udf_check_for_vat(vat_candidate);
2096 if (error) {
2097 vat_loc++; /* walk forward */
2098 continue;
2099 }
2100
2101 if (accepted_vat) {
2102 /* check if newer vat time stamp is the same */
2103 if (udf_compare_mtimes(
2104 udf_file_mtime(vat_candidate),
2105 udf_file_mtime(accepted_vat)
2106 ) == 0) {
2107 free(vat_candidate);
2108 vat_loc++; /* walk forward */
2109 continue;
2110 }
2111 }
2112
2113 /* check if its contents are OK */
2114 error = udf_extract_vat(
2115 vat_candidate, &vat_contents);
2116 if (error) {
2117 /* unlikely */
2118 // pwarn("Unreadable or malformed VAT encountered\n");
2119 free(vat_candidate);
2120 vat_loc++;
2121 continue;
2122 }
2123 /* accept new vat */
2124 free(accepted_vat);
2125 free(accepted_vat_contents);
2126
2127 accepted_vat = vat_candidate;
2128 accepted_vat_contents = vat_contents;
2129 accepted_vat_loc = vat_loc;
2130 vat_candidate = NULL;
2131 vat_contents = NULL;
2132
2133 found_a_VAT = 1;
2134
2135 vat_loc++; /* walk forward */
2136 };
2137
2138 if (found_a_VAT && accepted_vat) {
2139 /* VAT accepted */
2140 if (!preen)
2141 udf_print_vat_details(accepted_vat);
2142 if (vat_writeout)
2143 pwarn("\tVAT accepted but marked dirty\n");
2144 if (!preen && !vat_writeout)
2145 pwarn("\tLogical volume integrity state set to CLOSED\n");
2146 if (!search_older_vat)
2147 break;
2148 if (!ask_noauto(0, "\tSearch older VAT"))
2149 break;
2150 late_vat_loc = accepted_vat_loc - 1;
2151 } else {
2152 late_vat_loc = early_vat_loc - 1;
2153 }
2154 if (early_vat_loc == first_possible_vat_location)
2155 break;
2156 early_vat_loc = first_possible_vat_location;
2157 if (late_vat_loc > VAT_BLK)
2158 early_vat_loc = MAX(early_vat_loc, late_vat_loc - VAT_BLK);
2159 } while (late_vat_loc > first_possible_vat_location);
2160
2161 if (!preen)
2162 printf("\n");
2163
2164 undo_opening_session = 0;
2165
2166 if (!accepted_vat) {
2167 if ((context.last_ti.sessionnr > 1) &&
2168 ask_noauto(0, "Undo opening of last session")) {
2169 undo_opening_session = 1;
2170 pwarn("Undoing opening of last session not implemented!\n");
2171 error = ENOENT;
2172 goto error_out;
2173 } else {
2174 pwarn("No valid VAT found!\n");
2175 error = ENOENT;
2176 goto error_out;
2177 }
2178 }
2179 if (last_possible_vat_location - accepted_vat_loc > 16) {
2180 assert(accepted_vat);
2181 pwarn("Selected VAT is not the latest or not at the end of "
2182 "track.\n");
2183 vat_writeout = 1;
2184 }
2185
2186 /* XXX FAULT INJECTION POINT XXX */
2187 //vat_writeout = 1;
2188 //udf_update_lvintd(UDF_INTEGRITY_OPEN);
2189
2190 return 0;
2191
2192 error_out:
2193 free(accepted_vat);
2194 free(accepted_vat_contents);
2195
2196 return error;
2197 }
2198
2199 /* ------------------------- sparables support ------------------------- */
2200
2201 static int
2202 udf_read_spareables(union udf_pmap *mapping, int log_part)
2203 {
2204 union dscrptr *dscr;
2205 struct part_map_spare *pms = &mapping->pms;
2206 uint32_t lb_num;
2207 int spar, error;
2208
2209 for (spar = 0; spar < pms->n_st; spar++) {
2210 lb_num = pms->st_loc[spar];
2211 error = udf_read_dscr_phys(lb_num, &dscr);
2212 if (error && !preen)
2213 pwarn("Error reading spareable table %d\n", spar);
2214 if (!error && dscr) {
2215 if (udf_rw16(dscr->tag.id) == TAGID_SPARING_TABLE) {
2216 free(context.sparing_table);
2217 context.sparing_table = &dscr->spt;
2218 dscr = NULL;
2219 break; /* we're done */
2220 }
2221 }
2222 free(dscr);
2223 }
2224 if (context.sparing_table == NULL)
2225 return ENOENT;
2226 return 0;
2227 }
2228
2229 /* ------------------------- metadata support ------------------------- */
2230
2231 static bool
2232 udf_metadata_node_supported(void)
2233 {
2234 struct extfile_entry *efe;
2235 struct short_ad *short_ad;
2236 uint32_t len;
2237 uint32_t flags;
2238 uint8_t *data_pos;
2239 int dscr_size, l_ea, l_ad, icbflags, addr_type;
2240
2241 /* we have to look into the file's allocation descriptors */
2242
2243 efe = context.meta_file;
2244 dscr_size = sizeof(struct extfile_entry) - 1;
2245 l_ea = udf_rw32(efe->l_ea);
2246 l_ad = udf_rw32(efe->l_ad);
2247
2248 icbflags = udf_rw16(efe->icbtag.flags);
2249 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
2250 if (addr_type != UDF_ICB_SHORT_ALLOC) {
2251 warnx("specification violation: metafile not using"
2252 "short allocs");
2253 return false;
2254 }
2255
2256 data_pos = (uint8_t *) context.meta_file + dscr_size + l_ea;
2257 short_ad = (struct short_ad *) data_pos;
2258 while (l_ad > 0) {
2259 len = udf_rw32(short_ad->len);
2260 flags = UDF_EXT_FLAGS(len);
2261 if (flags == UDF_EXT_REDIRECT) {
2262 warnx("implementation limit: no support for "
2263 "extent redirections in metadata file");
2264 return false;
2265 }
2266 short_ad++;
2267 l_ad -= sizeof(struct short_ad);
2268 }
2269 /* we passed all of them */
2270 return true;
2271 }
2272
2273
2274 static int
2275 udf_read_metadata_nodes(union udf_pmap *mapping, int log_part)
2276 {
2277 union dscrptr *dscr1, *dscr2, *dscr3;
2278 struct part_map_meta *pmm = &mapping->pmm;
2279 uint16_t raw_phys_part, phys_part;
2280 int tagid, file_type, error;
2281
2282 /*
2283 * BUGALERT: some rogue implementations use random physical
2284 * partition numbers to break other implementations so lookup
2285 * the number.
2286 */
2287
2288 raw_phys_part = udf_rw16(pmm->part_num);
2289 phys_part = udf_find_raw_phys(raw_phys_part);
2290
2291 error = udf_read_dscr_virt(layout.meta_file, phys_part, &dscr1);
2292 if (!error) {
2293 tagid = udf_rw16(dscr1->tag.id);
2294 file_type = dscr1->efe.icbtag.file_type;
2295 if ((tagid != TAGID_EXTFENTRY) ||
2296 (file_type != UDF_ICB_FILETYPE_META_MAIN))
2297 error = ENOENT;
2298 }
2299 if (error) {
2300 pwarn("Bad primary metadata file descriptor\n");
2301 free(dscr1);
2302 dscr1 = NULL;
2303 }
2304
2305 error = udf_read_dscr_virt(layout.meta_mirror, phys_part, &dscr2);
2306 if (!error) {
2307 tagid = udf_rw16(dscr2->tag.id);
2308 file_type = dscr2->efe.icbtag.file_type;
2309 if ((tagid != TAGID_EXTFENTRY) ||
2310 (file_type != UDF_ICB_FILETYPE_META_MIRROR))
2311 error = ENOENT;
2312 }
2313 if (error) {
2314 pwarn("Bad mirror metadata file descriptor\n");
2315 free(dscr2);
2316 dscr2 = NULL;
2317 }
2318
2319 if ((dscr1 == NULL) && (dscr2 == NULL)) {
2320 pwarn("No valid metadata file descriptors found!\n");
2321 return -1;
2322 }
2323
2324 error = 0;
2325 if ((dscr1 == NULL) && dscr2) {
2326 dscr1 = malloc(context.sector_size);
2327 memcpy(dscr1, dscr2, context.sector_size);
2328 dscr1->efe.icbtag.file_type = UDF_ICB_FILETYPE_META_MAIN;
2329 if (ask(1, "Fix up bad primary metadata file descriptor")) {
2330 error = udf_write_dscr_virt(dscr1,
2331 layout.meta_file, phys_part, 1);
2332 }
2333 }
2334 if (dscr1 && (dscr2 == NULL)) {
2335 dscr2 = malloc(context.sector_size);
2336 memcpy(dscr2, dscr1, context.sector_size);
2337 dscr2->efe.icbtag.file_type = UDF_ICB_FILETYPE_META_MIRROR;
2338 if (ask(1, "Fix up bad mirror metadata file descriptor")) {
2339 error = udf_write_dscr_virt(dscr2,
2340 layout.meta_mirror, phys_part, 1);
2341 }
2342 }
2343 if (error)
2344 pwarn("Copying metadata file descriptor failed, "
2345 "trying to continue\n");
2346
2347 context.meta_file = &dscr1->efe;
2348 context.meta_mirror = &dscr2->efe;
2349
2350 dscr3 = NULL;
2351 if (layout.meta_bitmap != 0xffffffff) {
2352 error = udf_read_dscr_virt(layout.meta_bitmap, phys_part, &dscr3);
2353 if (!error) {
2354 tagid = udf_rw16(dscr3->tag.id);
2355 file_type = dscr3->efe.icbtag.file_type;
2356 if ((tagid != TAGID_EXTFENTRY) ||
2357 (file_type != UDF_ICB_FILETYPE_META_BITMAP))
2358 error = ENOENT;
2359 }
2360 if (error) {
2361 pwarn("Bad metadata bitmap file descriptor\n");
2362 free(dscr3);
2363 dscr3 = NULL;
2364 }
2365
2366 if (dscr3 == NULL) {
2367 pwarn("implementation limit: can't repair missing or "
2368 "damaged metadata bitmap descriptor\n");
2369 return -1;
2370 }
2371
2372 context.meta_bitmap = &dscr3->efe;
2373 }
2374
2375 /* TODO early check if meta_file has allocation extent redirections */
2376 if (!udf_metadata_node_supported())
2377 return EINVAL;
2378
2379 return 0;
2380 }
2381
2382 /* ------------------------- VDS readin ------------------------- */
2383
2384 /* checks if the VDS information is correct and complete */
2385 static int
2386 udf_process_vds(void) {
2387 union dscrptr *dscr;
2388 union udf_pmap *mapping;
2389 struct part_desc *pdesc;
2390 struct long_ad fsd_loc;
2391 uint8_t *pmap_pos;
2392 char *domain_name, *map_name;
2393 const char *check_name;
2394 int pmap_stype, pmap_size;
2395 int pmap_type, log_part, phys_part, raw_phys_part; //, maps_on;
2396 int n_pm, n_phys, n_virt, n_spar, n_meta;
2397 int len, error;
2398
2399 /* we need at least an anchor (trivial, but for safety) */
2400 if (context.anchors[0] == NULL) {
2401 pwarn("sanity check: no anchors?\n");
2402 return EINVAL;
2403 }
2404
2405 /* we need at least one primary and one logical volume descriptor */
2406 if ((context.primary_vol == NULL) || (context.logical_vol) == NULL) {
2407 pwarn("sanity check: missing primary or missing logical volume\n");
2408 return EINVAL;
2409 }
2410
2411 /* we need at least one partition descriptor */
2412 if (context.partitions[0] == NULL) {
2413 pwarn("sanity check: missing partition descriptor\n");
2414 return EINVAL;
2415 }
2416
2417 /* check logical volume sector size versus device sector size */
2418 if (udf_rw32(context.logical_vol->lb_size) != context.sector_size) {
2419 pwarn("sanity check: lb_size != sector size\n");
2420 return EINVAL;
2421 }
2422
2423 /* check domain name, should never fail */
2424 domain_name = (char *) context.logical_vol->domain_id.id;
2425 if (strncmp(domain_name, "*OSTA UDF Compliant", 20)) {
2426 pwarn("sanity check: disc not OSTA UDF Compliant, aborting\n");
2427 return EINVAL;
2428 }
2429
2430 /* retrieve logical volume integrity sequence */
2431 udf_retrieve_lvint();
2432
2433 /* check if we support this disc, ie less or equal to 0x250 */
2434 if (udf_rw16(context.logvol_info->min_udf_writever) > 0x250) {
2435 pwarn("implementation limit: minimum write version UDF 2.60 "
2436 "and on are not supported\n");
2437 return EINVAL;
2438 }
2439
2440 /*
2441 * check logvol mappings: effective virt->log partmap translation
2442 * check and recording of the mapping results. Saves expensive
2443 * strncmp() in tight places.
2444 */
2445 n_pm = udf_rw32(context.logical_vol->n_pm); /* num partmaps */
2446 pmap_pos = context.logical_vol->maps;
2447
2448 if (n_pm > UDF_PMAPS) {
2449 pwarn("implementation limit: too many logvol mappings\n");
2450 return EINVAL;
2451 }
2452
2453 /* count types and set partition numbers */
2454 context.data_part = context.metadata_part = context.fids_part = 0;
2455 n_phys = n_virt = n_spar = n_meta = 0;
2456 for (log_part = 0; log_part < n_pm; log_part++) {
2457 mapping = (union udf_pmap *) pmap_pos;
2458 pmap_stype = pmap_pos[0];
2459 pmap_size = pmap_pos[1];
2460 switch (pmap_stype) {
2461 case 1: /* physical mapping */
2462 /* volseq = udf_rw16(mapping->pm1.vol_seq_num); */
2463 raw_phys_part = udf_rw16(mapping->pm1.part_num);
2464 pmap_type = UDF_VTOP_TYPE_PHYS;
2465 n_phys++;
2466 context.data_part = log_part;
2467 context.metadata_part = log_part;
2468 context.fids_part = log_part;
2469 break;
2470 case 2: /* virtual/sparable/meta mapping */
2471 map_name = (char *) mapping->pm2.part_id.id;
2472 /* volseq = udf_rw16(mapping->pm2.vol_seq_num); */
2473 raw_phys_part = udf_rw16(mapping->pm2.part_num);
2474 pmap_type = UDF_VTOP_TYPE_UNKNOWN;
2475 len = UDF_REGID_ID_SIZE;
2476
2477 check_name = "*UDF Virtual Partition";
2478 if (strncmp(map_name, check_name, len) == 0) {
2479 pmap_type = UDF_VTOP_TYPE_VIRT;
2480 n_virt++;
2481 context.metadata_part = log_part;
2482 context.format_flags |= FORMAT_VAT;
2483 break;
2484 }
2485 check_name = "*UDF Sparable Partition";
2486 if (strncmp(map_name, check_name, len) == 0) {
2487 pmap_type = UDF_VTOP_TYPE_SPAREABLE;
2488 n_spar++;
2489 layout.spareable_blockingnr = udf_rw16(mapping->pms.packet_len);
2490
2491 context.data_part = log_part;
2492 context.metadata_part = log_part;
2493 context.fids_part = log_part;
2494 context.format_flags |= FORMAT_SPAREABLE;
2495 break;
2496 }
2497 check_name = "*UDF Metadata Partition";
2498 if (strncmp(map_name, check_name, len) == 0) {
2499 pmap_type = UDF_VTOP_TYPE_META;
2500 n_meta++;
2501 layout.meta_file = udf_rw32(mapping->pmm.meta_file_lbn);
2502 layout.meta_mirror = udf_rw32(mapping->pmm.meta_mirror_file_lbn);
2503 layout.meta_bitmap = udf_rw32(mapping->pmm.meta_bitmap_file_lbn);
2504 layout.meta_blockingnr = udf_rw32(mapping->pmm.alloc_unit_size);
2505 layout.meta_alignment = udf_rw16(mapping->pmm.alignment_unit_size);
2506 /* XXX metadata_flags in mapping->pmm.flags? XXX */
2507
2508 context.metadata_part = log_part;
2509 context.fids_part = log_part;
2510 context.format_flags |= FORMAT_META;
2511 break;
2512 }
2513 break;
2514 default:
2515 return EINVAL;
2516 }
2517
2518 /*
2519 * BUGALERT: some rogue implementations use random physical
2520 * partition numbers to break other implementations so lookup
2521 * the number.
2522 */
2523 phys_part = udf_find_raw_phys(raw_phys_part);
2524
2525 if (phys_part == UDF_PARTITIONS) {
2526 pwarn("implementation limit: too many partitions\n");
2527 return EINVAL;
2528 }
2529 if (pmap_type == UDF_VTOP_TYPE_UNKNOWN) {
2530 pwarn("implementation limit: encountered unknown "
2531 "logvol mapping `%s`!\n", map_name);
2532 return EINVAL;
2533 }
2534
2535 context.vtop [log_part] = phys_part;
2536 context.vtop_tp[log_part] = pmap_type;
2537
2538 pmap_pos += pmap_size;
2539 }
2540 /* not winning the beauty contest */
2541 context.vtop_tp[UDF_VTOP_RAWPART] = UDF_VTOP_TYPE_RAW;
2542
2543 /* test some basic UDF assertions/requirements */
2544 if ((n_virt > 1) || (n_spar > 1) || (n_meta > 1)) {
2545 pwarn("Sanity check: format error, more than one "
2546 "virtual, sparable or meta mapping\n");
2547 return EINVAL;
2548 }
2549
2550 if (n_virt) {
2551 if ((n_phys == 0) || n_spar || n_meta) {
2552 pwarn("Sanity check: format error, no backing for "
2553 "virtual partition\n");
2554 return EINVAL;
2555 }
2556 }
2557 if (n_spar + n_phys == 0) {
2558 pwarn("Sanity check: can't combine a sparable and a "
2559 "physical partition\n");
2560 return EINVAL;
2561 }
2562
2563 /* print format type as derived */
2564 if (!preen) {
2565 char bits[255];
2566 snprintb(bits, sizeof(bits), FORMAT_FLAGBITS, context.format_flags);
2567 printf("Format flags %s\n\n", bits);
2568 }
2569
2570 /* read supporting tables */
2571 pmap_pos = context.logical_vol->maps;
2572 for (log_part = 0; log_part < n_pm; log_part++) {
2573 mapping = (union udf_pmap *) pmap_pos;
2574 pmap_size = pmap_pos[1];
2575 switch (context.vtop_tp[log_part]) {
2576 case UDF_VTOP_TYPE_PHYS :
2577 /* nothing */
2578 break;
2579 case UDF_VTOP_TYPE_VIRT :
2580 /* search and load VAT */
2581 error = udf_search_vat(mapping, log_part);
2582 if (error) {
2583 pwarn("Couldn't find virtual allocation table\n");
2584 return ENOENT;
2585 }
2586 break;
2587 case UDF_VTOP_TYPE_SPAREABLE :
2588 /* load one of the sparable tables */
2589 error = udf_read_spareables(mapping, log_part);
2590 if (error) {
2591 pwarn("Couldn't load sparable blocks tables\n");
2592 return ENOENT;
2593 }
2594 break;
2595 case UDF_VTOP_TYPE_META :
2596 /* load the associated file descriptors */
2597 error = udf_read_metadata_nodes(mapping, log_part);
2598 if (error) {
2599 pwarn("Couldn't read in the metadata descriptors\n");
2600 return ENOENT;
2601 }
2602
2603 /*
2604 * We have to extract the partition size from the meta
2605 * data file length
2606 */
2607 context.part_size[log_part] =
2608 udf_rw64(context.meta_file->inf_len) / context.sector_size;
2609 break;
2610 default:
2611 break;
2612 }
2613 pmap_pos += pmap_size;
2614 }
2615
2616 /*
2617 * Free/unallocated space bitmap readin delayed; the FS might be
2618 * closed already; no need to read in copious amount of data only to
2619 * not use it later.
2620 *
2621 * For now, extract partition sizes in our context
2622 */
2623 for (int cnt = 0; cnt < UDF_PARTITIONS; cnt++) {
2624 pdesc = context.partitions[cnt];
2625 if (!pdesc)
2626 continue;
2627
2628 context.part_size[cnt] = udf_rw32(pdesc->part_len);
2629 context.part_unalloc_bits[cnt] = NULL;
2630 }
2631
2632 /* read file set descriptor */
2633 fsd_loc = context.logical_vol->lv_fsd_loc;
2634 error = udf_read_dscr_virt(
2635 udf_rw32(fsd_loc.loc.lb_num),
2636 udf_rw16(fsd_loc.loc.part_num), &dscr);
2637 if (error) {
2638 pwarn("Couldn't read in file set descriptor\n");
2639 pwarn("implementation limit: can't fix this\n");
2640 return ENOENT;
2641 }
2642 if (udf_rw16(dscr->tag.id) != TAGID_FSD) {
2643 pwarn("Expected fsd at (p %d, lb %d)\n",
2644 udf_rw16(fsd_loc.loc.part_num),
2645 udf_rw32(fsd_loc.loc.lb_num));
2646 pwarn("File set descriptor not pointing to a file set!\n");
2647 return ENOENT;
2648 }
2649 context.fileset_desc = &dscr->fsd;
2650
2651 /* signal its OK for now */
2652 return 0;
2653 }
2654
2655
2656 #define UDF_UPDATE_DSCR(name, dscr) \
2657 if (name) {\
2658 free (name); \
2659 updated = 1; \
2660 } \
2661 name = calloc(1, dscr_size); \
2662 memcpy(name, dscr, dscr_size);
2663
2664 static void
2665 udf_process_vds_descriptor(union dscrptr *dscr, int dscr_size) {
2666 struct pri_vol_desc *pri;
2667 struct logvol_desc *lvd;
2668 uint16_t raw_phys_part, phys_part;
2669 int updated = 0;
2670
2671 switch (udf_rw16(dscr->tag.id)) {
2672 case TAGID_PRI_VOL : /* primary partition */
2673 UDF_UPDATE_DSCR(context.primary_vol, dscr);
2674 pri = context.primary_vol;
2675
2676 context.primary_name = malloc(32);
2677 context.volset_name = malloc(128);
2678
2679 udf_to_unix_name(context.volset_name, 32, pri->volset_id, 32,
2680 &pri->desc_charset);
2681 udf_to_unix_name(context.primary_name, 128, pri->vol_id, 128,
2682 &pri->desc_charset);
2683
2684 if (!preen && !updated) {
2685 pwarn("Volume set `%s`\n", context.volset_name);
2686 pwarn("Primary volume `%s`\n", context.primary_name);
2687 }
2688 break;
2689 case TAGID_LOGVOL : /* logical volume */
2690 UDF_UPDATE_DSCR(context.logical_vol, dscr);
2691 /* could check lvd->domain_id */
2692 lvd = context.logical_vol;
2693 context.logvol_name = malloc(128);
2694
2695 udf_to_unix_name(context.logvol_name, 128, lvd->logvol_id, 128,
2696 &lvd->desc_charset);
2697
2698 if (!preen && !updated)
2699 pwarn("Logical volume `%s`\n", context.logvol_name);
2700 break;
2701 case TAGID_UNALLOC_SPACE : /* unallocated space */
2702 UDF_UPDATE_DSCR(context.unallocated, dscr);
2703 break;
2704 case TAGID_IMP_VOL : /* implementation */
2705 UDF_UPDATE_DSCR(context.implementation, dscr);
2706 break;
2707 case TAGID_PARTITION : /* partition(s) */
2708 /* not much use if its not allocated */
2709 if ((udf_rw16(dscr->pd.flags) & UDF_PART_FLAG_ALLOCATED) == 0) {
2710 pwarn("Ignoring unallocated partition\n");
2711 break;
2712 }
2713 raw_phys_part = udf_rw16(dscr->pd.part_num);
2714 phys_part = udf_find_raw_phys(raw_phys_part);
2715
2716 if (phys_part >= UDF_PARTITIONS) {
2717 pwarn("Too many physical partitions, ignoring\n");
2718 break;
2719 }
2720 UDF_UPDATE_DSCR(context.partitions[phys_part], dscr);
2721 break;
2722 case TAGID_TERM : /* terminator */
2723 break;
2724 case TAGID_VOL : /* volume space ext */
2725 pwarn("Ignoring VDS extender\n");
2726 break;
2727 default :
2728 pwarn("Unknown VDS type %d found, ignored\n",
2729 udf_rw16(dscr->tag.id));
2730 }
2731 }
2732
2733
2734 static void
2735 udf_read_vds_extent(union dscrptr *dscr, int vds_size) {
2736 uint8_t *pos;
2737 int sector_size = context.sector_size;
2738 int dscr_size;
2739
2740 pos = (uint8_t *) dscr;
2741 while (vds_size) {
2742 /* process the descriptor */
2743 dscr = (union dscrptr *) pos;
2744
2745 /* empty block terminates */
2746 if (is_zero(dscr, sector_size))
2747 return;
2748
2749 /* terminator terminates */
2750 if (udf_rw16(dscr->tag.id) == TAGID_TERM)
2751 return;
2752
2753 if (udf_check_tag(dscr))
2754 pwarn("Bad descriptor sum in vds, ignoring\n");
2755
2756 dscr_size = udf_tagsize(dscr, sector_size);
2757 if (udf_check_tag_payload(dscr, dscr_size))
2758 pwarn("Bad descriptor CRC in vds, ignoring\n");
2759
2760 udf_process_vds_descriptor(dscr, dscr_size);
2761
2762 pos += dscr_size;
2763 vds_size -= dscr_size;
2764 }
2765 }
2766
2767
2768 static int
2769 udf_copy_VDS_area(void *destbuf, void *srcbuf)
2770 {
2771 pwarn("TODO implement VDS copy area, signalling success\n");
2772 return 0;
2773 }
2774
2775
2776 /* XXX why two buffers and not just read descritor by descriptor XXX */
2777 static int
2778 udf_check_VDS_areas(void) {
2779 union dscrptr *vds1_buf, *vds2_buf;
2780 int vds1_size, vds2_size;
2781 int error, error1, error2;
2782
2783 vds1_size = layout.vds1_size * context.sector_size;
2784 vds2_size = layout.vds2_size * context.sector_size;
2785 vds1_buf = calloc(1, vds1_size);
2786 vds2_buf = calloc(1, vds2_size);
2787 assert(vds1_buf); assert(vds2_buf);
2788
2789 error1 = udf_read_phys(vds1_buf, layout.vds1, layout.vds1_size);
2790 error2 = udf_read_phys(vds2_buf, layout.vds2, layout.vds2_size);
2791
2792 if (error1 && error2) {
2793 pwarn("Can't read both volume descriptor areas!\n");
2794 return -1;
2795 }
2796
2797 if (!error1) {
2798 /* retrieve data from VDS 1 */
2799 udf_read_vds_extent(vds1_buf, vds1_size);
2800 context.vds_buf = vds1_buf;
2801 context.vds_size = vds1_size;
2802 free(vds2_buf);
2803 }
2804 if (!error2) {
2805 /* retrieve data from VDS 2 */
2806 udf_read_vds_extent(vds2_buf, vds2_size);
2807 context.vds_buf = vds2_buf;
2808 context.vds_size = vds2_size;
2809 free(vds1_buf);
2810 }
2811 /* check if all is correct and complete */
2812 error = udf_process_vds();
2813 if (error)
2814 return error;
2815
2816 /* TODO check if both area's are logically the same */
2817 error = 0;
2818 if (!error1 && error2) {
2819 /* first OK, second faulty */
2820 pwarn("Backup volume descriptor missing or damaged\n");
2821 if (context.format_flags & FORMAT_SEQUENTIAL) {
2822 pwarn("Can't fixup backup volume descriptor on "
2823 "SEQUENTIAL media\n");
2824 } else if (ask(1, "Fixup backup volume descriptor")) {
2825 error = udf_copy_VDS_area(vds2_buf, vds1_buf);
2826 pwarn("\n");
2827 }
2828 }
2829 if (error1 && !error2) {
2830 /* second OK, first faulty */
2831 pwarn("Primary volume descriptor missing or damaged\n");
2832 if (context.format_flags & FORMAT_SEQUENTIAL) {
2833 pwarn("Can't fix up primary volume descriptor on "
2834 "SEQUENTIAL media\n");
2835 } else if (ask(1, "Fix up primary volume descriptor")) {
2836 error = udf_copy_VDS_area(vds1_buf, vds2_buf);
2837 }
2838 }
2839 if (error)
2840 pwarn("copying VDS areas failed!\n");
2841 if (!preen)
2842 printf("\n");
2843
2844 return error;
2845 }
2846
2847 /* --------------------------------------------------------------------- */
2848
2849 static int
2850 udf_prepare_writing(void)
2851 {
2852 union dscrptr *zero_dscr, *dscr;
2853 struct mmc_trackinfo ti;
2854 uint32_t first_lba, loc;
2855 int sector_size = context.sector_size;
2856 int error;
2857
2858 error = udf_prepare_disc();
2859 if (error) {
2860 pwarn("*** Preparing disc for writing failed!\n");
2861 return error;
2862 }
2863
2864 /* if we are not on sequential media, we're done */
2865 if ((mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) == 0)
2866 return 0;
2867 assert(context.format_flags & FORMAT_VAT);
2868
2869 /* if the disc is full, we drop back to read only */
2870 if (mmc_discinfo.disc_state == MMC_STATE_FULL)
2871 rdonly = 1;
2872 if (rdonly)
2873 return 0;
2874
2875 /* check if we need to open the last track */
2876 ti.tracknr = mmc_discinfo.last_track_last_session;
2877 error = udf_update_trackinfo(&ti);
2878 if (error)
2879 return error;
2880 if (!(ti.flags & MMC_TRACKINFO_BLANK) &&
2881 (ti.flags & MMC_TRACKINFO_NWA_VALID)) {
2882 /*
2883 * Not closed; translate next_writable to a position relative to our
2884 * backing partition
2885 */
2886 context.alloc_pos[context.data_part] = ti.next_writable -
2887 udf_rw32(context.partitions[context.data_part]->start_loc);
2888 wrtrack_skew = ti.next_writable % layout.blockingnr;
2889 return 0;
2890 }
2891 assert(ti.flags & MMC_TRACKINFO_NWA_VALID);
2892
2893 /* just in case */
2894 udf_suspend_writing();
2895
2896 /* 'add' a new track */
2897 udf_update_discinfo();
2898 memset(&context.last_ti, 0, sizeof(struct mmc_trackinfo));
2899 context.last_ti.tracknr = mmc_discinfo.first_track_last_session;
2900 (void) udf_update_trackinfo(&context.last_ti);
2901
2902 assert(mmc_discinfo.last_session_state == MMC_STATE_EMPTY);
2903 first_lba = context.last_ti.track_start;
2904 wrtrack_skew = context.last_ti.track_start % layout.blockingnr;
2905
2906 /*
2907 * location of iso9660 vrs is defined as first sector AFTER 32kb,
2908 * minimum `sector size' 2048
2909 */
2910 layout.iso9660_vrs = ((32*1024 + sector_size - 1) / sector_size)
2911 + first_lba;
2912
2913 /* anchor starts at specified offset in sectors */
2914 layout.anchors[0] = first_lba + 256;
2915
2916 /* ready for appending, write preamble, we are using overwrite here! */
2917 if ((zero_dscr = calloc(1, context.sector_size)) == NULL)
2918 return ENOMEM;
2919 loc = first_lba;
2920 for (; loc < first_lba + 256; loc++) {
2921 if ((error = udf_write_sector(zero_dscr, loc))) {
2922 free(zero_dscr);
2923 return error;
2924 }
2925 }
2926 free(zero_dscr);
2927
2928 /* write new ISO9660 volume recognition sequence */
2929 if ((error = udf_write_iso9660_vrs())) {
2930 pwarn("internal error: can't write iso966 VRS in new session!\n");
2931 rdonly = 1;
2932 return error;
2933 }
2934
2935 /* write out our old anchor, VDS spaces will be reused */
2936 assert(context.anchors[0]);
2937 dscr = (union dscrptr *) context.anchors[0];
2938 loc = layout.anchors[0];
2939 if ((error = udf_write_dscr_phys(dscr, loc, 1))) {
2940 pwarn("internal error: can't write anchor in new session!\n");
2941 rdonly = 1;
2942 return error;
2943 }
2944
2945 context.alloc_pos[context.data_part] = first_lba + 257 -
2946 udf_rw32(context.partitions[context.data_part]->start_loc);
2947
2948 return 0;
2949 }
2950
2951
2952 static int
2953 udf_close_volume_vat(void)
2954 {
2955 int integrity_type;
2956
2957 /* only write out when its open */
2958 integrity_type = udf_rw32(context.logvol_integrity->integrity_type);
2959 if (integrity_type == UDF_INTEGRITY_CLOSED)
2960 return 0;
2961
2962 if (!preen)
2963 printf("\n");
2964 if (!ask(1, "Write out modifications"))
2965 return 0;
2966
2967 /* writeout our VAT contents */
2968 udf_allow_writing();
2969 return udf_writeout_VAT();
2970 }
2971
2972
2973 static int
2974 udf_close_volume(void)
2975 {
2976 struct part_desc *part;
2977 struct part_hdr_desc *phd;
2978 struct logvol_int_desc *lvid;
2979 struct udf_logvol_info *lvinfo;
2980 struct logvol_desc *logvol;
2981 uint32_t bitmap_len, bitmap_lb, bitmap_numlb;
2982 int i, equal, error;
2983
2984 lvid = context.logvol_integrity;
2985 logvol = context.logical_vol;
2986 lvinfo = context.logvol_info;
2987 assert(lvid);
2988 assert(logvol);
2989 assert(lvinfo);
2990
2991 /* check our highest unique id */
2992 if (context.unique_id > udf_rw64(lvid->lvint_next_unique_id)) {
2993 pwarn("Last unique id updated from %" PRIi64 " to %" PRIi64 " : FIXED\n",
2994 udf_rw64(lvid->lvint_next_unique_id),
2995 context.unique_id);
2996 open_integrity = 1;
2997 }
2998
2999 /* check file/directory counts */
3000 if (context.num_files != udf_rw32(lvinfo->num_files)) {
3001 pwarn("Number of files corrected from %d to %d : FIXED\n",
3002 udf_rw32(lvinfo->num_files),
3003 context.num_files);
3004 open_integrity = 1;
3005 }
3006 if (context.num_directories != udf_rw32(lvinfo->num_directories)) {
3007 pwarn("Number of directories corrected from %d to %d : FIXED\n",
3008 udf_rw32(lvinfo->num_directories),
3009 context.num_directories);
3010 open_integrity = 1;
3011 }
3012
3013 if (vat_writeout)
3014 open_integrity = 1;
3015
3016 if (open_integrity)
3017 udf_update_lvintd(UDF_INTEGRITY_OPEN);
3018
3019 if (context.format_flags & FORMAT_VAT)
3020 return udf_close_volume_vat();
3021
3022 /* adjust free space accounting! */
3023 for (i = 0; i < UDF_PARTITIONS; i++) {
3024 part = context.partitions[i];
3025 if (!part)
3026 continue;
3027 phd = &part->pd_part_hdr;
3028 bitmap_len = udf_rw32(phd->unalloc_space_bitmap.len);
3029 bitmap_lb = udf_rw32(phd->unalloc_space_bitmap.lb_num);
3030
3031 if (bitmap_len == 0) {
3032 error = 0;
3033 continue;
3034 }
3035
3036 equal = memcmp( recorded_part_unalloc_bits[i],
3037 context.part_unalloc_bits[i],
3038 bitmap_len) == 0;
3039
3040 if (!equal || (context.part_free[i] != recorded_part_free[i])) {
3041 if (!equal)
3042 pwarn("Calculated bitmap for partition %d not equal "
3043 "to recorded one : FIXED\n", i);
3044 pwarn("Free space on partition %d corrected "
3045 "from %d to %d blocks : FIXED\n", i,
3046 recorded_part_free[i],
3047 context.part_free[i]);
3048
3049 /* write out updated free space map */
3050 pwarn("Updating unallocated bitmap for partition\n");
3051 if (!preen)
3052 printf("Writing free space map "
3053 "for partition %d\n", i);
3054 error = 0;
3055 if (context.vtop_tp[i] == UDF_VTOP_TYPE_META) {
3056 if (context.meta_bitmap) {
3057 assert(i == context.metadata_part);
3058 error = udf_process_file(
3059 (union dscrptr *) context.meta_bitmap,
3060 context.data_part,
3061 (uint8_t **) &(context.part_unalloc_bits[i]),
3062 AD_SAVE_FILE, NULL);
3063 }
3064 } else {
3065 bitmap_numlb = udf_bytes_to_sectors(bitmap_len);
3066 error = udf_write_dscr_virt(
3067 (union dscrptr *) context.part_unalloc_bits[i],
3068 bitmap_lb,
3069 i,
3070 bitmap_numlb);
3071 }
3072 if (error)
3073 pwarn("Updating unallocated bitmap failed, "
3074 "continuing\n");
3075 udf_update_lvintd(UDF_INTEGRITY_OPEN);
3076 }
3077 }
3078
3079 /* write out the logical volume integrity sequence */
3080 error = udf_writeout_lvint();
3081
3082 return error;
3083 }
3084
3085 /* --------------------------------------------------------------------- */
3086
3087 /*
3088 * Main part of file system checking.
3089 *
3090 * Walk the entire directory tree and check all link counts and rebuild the
3091 * free space map (if present) on the go.
3092 */
3093
3094 static struct udf_fsck_node *
3095 udf_new_fsck_node(struct udf_fsck_node *parent, struct long_ad *loc, char *fname)
3096 {
3097 struct udf_fsck_node *this;
3098 this = calloc(1, sizeof(struct udf_fsck_node));
3099 if (!this)
3100 return NULL;
3101
3102 this->parent = parent;
3103 this->fname = strdup(fname);
3104 this->loc = *loc;
3105 this->fsck_flags = 0;
3106
3107 this->link_count = 0;
3108 this->found_link_count = 0;
3109
3110 return this;
3111 }
3112
3113
3114 static void
3115 udf_node_path_piece(char *pathname, struct udf_fsck_node *node)
3116 {
3117 if (node->parent) {
3118 udf_node_path_piece(pathname, node->parent);
3119 if (node->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR)
3120 strcat(pathname, "");
3121 else
3122 strcat(pathname, "/");
3123 }
3124 strcat(pathname, node->fname);
3125 }
3126
3127
3128 static char *
3129 udf_node_path(struct udf_fsck_node *node)
3130 {
3131 static char pathname[MAXPATHLEN + 10];
3132
3133 strcpy(pathname, "`");
3134 if (node->parent)
3135 udf_node_path_piece(pathname, node);
3136 else
3137 strcat(pathname, "/");
3138 strcat(pathname, "'");
3139
3140 return pathname;
3141 }
3142
3143
3144 static void
3145 udf_recursive_keep(struct udf_fsck_node *node)
3146 {
3147 while (node->parent) {
3148 node = node->parent;
3149 node->fsck_flags |= FSCK_NODE_FLAG_KEEP;
3150 }
3151 }
3152
3153
3154 static int
3155 udf_quick_check_fids(struct udf_fsck_node *node, union dscrptr *dscr)
3156 {
3157 struct udf_fsck_fid_context fid_context;
3158 int error;
3159
3160 fid_context.fid_offset = 0;
3161 fid_context.data_left = node->found.inf_len;
3162 error = udf_process_file(dscr, context.fids_part,
3163 &node->directory,
3164 AD_CHECK_FIDS,
3165 &fid_context);
3166
3167 return error;
3168 }
3169
3170
3171 /* read descriptor at node's location */
3172 static int
3173 udf_read_node_dscr(struct udf_fsck_node *node, union dscrptr **dscrptr)
3174 {
3175 *dscrptr = NULL;
3176 return udf_read_dscr_virt(
3177 udf_rw32(node->loc.loc.lb_num),
3178 udf_rw16(node->loc.loc.part_num),
3179 dscrptr);
3180 }
3181
3182
3183 static int
3184 udf_extract_node_info(struct udf_fsck_node *node, union dscrptr *dscr,
3185 int be_quiet)
3186 {
3187 struct icb_tag *icb = NULL;
3188 struct file_entry *fe = NULL;
3189 struct extfile_entry *efe = NULL;
3190 int ad_type, error;
3191
3192 if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
3193 fe = (struct file_entry *) dscr;
3194 icb = &fe->icbtag;
3195 node->declared.inf_len = udf_rw64(fe->inf_len);
3196 node->declared.obj_size = udf_rw64(fe->inf_len);
3197 node->declared.logblks_rec = udf_rw64(fe->logblks_rec);
3198 node->link_count = udf_rw16(fe->link_cnt);
3199 node->unique_id = udf_rw64(fe->unique_id);
3200
3201 /* XXX FAULT INJECTION POINT XXX */
3202 //if (fe->unique_id == 33) { return ENOENT;}
3203
3204 }
3205 if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
3206 efe = (struct extfile_entry *) dscr;
3207 icb = &efe->icbtag;
3208 node->declared.inf_len = udf_rw64(efe->inf_len);
3209 node->declared.obj_size = udf_rw64(efe->obj_size);
3210 node->declared.logblks_rec = udf_rw64(efe->logblks_rec);
3211 node->link_count = udf_rw16(efe->link_cnt);
3212 node->unique_id = udf_rw64(efe->unique_id);
3213 node->streamdir_loc = efe->streamdir_icb;
3214 if (node->streamdir_loc.len)
3215 node->fsck_flags |= FSCK_NODE_FLAG_HAS_STREAM_DIR;
3216
3217 /* XXX FAULT INJECTION POINT XXX */
3218 //if (efe->unique_id == 0x891) { return ENOENT;}
3219
3220 }
3221
3222 if (!fe && !efe) {
3223 //printf("NOT REFERENCING AN FE/EFE!\n");
3224 return ENOENT;
3225 }
3226
3227 if (node->unique_id >= context.unique_id)
3228 context.unique_id = node->unique_id+1;
3229
3230 ad_type = udf_rw16(icb->flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
3231 if ((ad_type != UDF_ICB_INTERN_ALLOC) &&
3232 (ad_type != UDF_ICB_SHORT_ALLOC) &&
3233 (ad_type != UDF_ICB_LONG_ALLOC)) {
3234 pwarn("%s : unknown allocation type\n",
3235 udf_node_path(node));
3236 return EINVAL;
3237 }
3238
3239 bzero(&node->found, sizeof(node->found));
3240 error = udf_process_file(dscr, udf_rw16(node->loc.loc.part_num), NULL,
3241 AD_GATHER_STATS, (void *) &node->found);
3242
3243 switch (icb->file_type) {
3244 case UDF_ICB_FILETYPE_RANDOMACCESS :
3245 case UDF_ICB_FILETYPE_BLOCKDEVICE :
3246 case UDF_ICB_FILETYPE_CHARDEVICE :
3247 case UDF_ICB_FILETYPE_FIFO :
3248 case UDF_ICB_FILETYPE_SOCKET :
3249 case UDF_ICB_FILETYPE_SYMLINK :
3250 case UDF_ICB_FILETYPE_REALTIME :
3251 break;
3252 default:
3253 /* unknown or unsupported file type, TODO clearing? */
3254 free(dscr);
3255 pwarn("%s : specification violation, unknown file type %d\n",
3256 udf_node_path(node), icb->file_type);
3257 return ENOENT;
3258 case UDF_ICB_FILETYPE_STREAMDIR :
3259 case UDF_ICB_FILETYPE_DIRECTORY :
3260 /* read in the directory contents */
3261 error = udf_readin_file(dscr, udf_rw16(node->loc.loc.part_num),
3262 &node->directory, NULL);
3263
3264 /* XXX FAULT INJECTION POINT XXX */
3265 //if (dscr->efe.unique_id == 109) node->directory[125] = 0xff;
3266 //if (dscr->efe.unique_id == 310) memset(node->directory+1024, 0, 300);
3267
3268 if (error && !be_quiet) {
3269 pwarn("%s : directory has read errors\n",
3270 udf_node_path(node));
3271 if (ask(0, "Directory could be fixed or cleared. "
3272 "Wipe defective directory")) {
3273 return ENOENT;
3274 }
3275 udf_recursive_keep(node);
3276 node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3277 }
3278 node->fsck_flags |= FSCK_NODE_FLAG_DIRECTORY;
3279 error = udf_quick_check_fids(node, dscr);
3280 if (error) {
3281 if (!(node->fsck_flags & FSCK_NODE_FLAG_REPAIRDIR))
3282 pwarn("%s : directory file entries need repair\n",
3283 udf_node_path(node));
3284 udf_recursive_keep(node);
3285 node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3286 }
3287 }
3288
3289 /* XXX FAULT INJECTION POINT XXX */
3290 //if (fe->unique_id == 0) node->link_count++;
3291 //if (efe->unique_id == 0) node->link_count++;
3292 //if (efe->unique_id == 772) { node->declared.inf_len += 205; node->declared.obj_size -= 0; }
3293
3294 return 0;
3295 }
3296
3297
3298 static void
3299 udf_fixup_lengths_pass1(struct udf_fsck_node *node, union dscrptr *dscr)
3300 {
3301 int64_t diff;
3302
3303 /* file length check */
3304 diff = node->found.inf_len - node->declared.inf_len;
3305 if (diff) {
3306 pwarn("%s : recorded information length incorrect: "
3307 "%" PRIu64 " instead of declared %" PRIu64 "\n",
3308 udf_node_path(node),
3309 node->found.inf_len, node->declared.inf_len);
3310 node->declared.inf_len = node->found.inf_len;
3311 udf_recursive_keep(node);
3312 node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
3313 }
3314
3315 /* recorded logical blocks count check */
3316 diff = node->found.logblks_rec - node->declared.logblks_rec;
3317 if (diff) {
3318 pwarn("%s : logical blocks recorded incorrect: "
3319 "%" PRIu64 " instead of declared %" PRIu64 ", fixing\n",
3320 udf_node_path(node),
3321 node->found.logblks_rec, node->declared.logblks_rec);
3322 node->declared.logblks_rec = node->found.logblks_rec;
3323 udf_recursive_keep(node);
3324 node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
3325 }
3326
3327 /* tally object sizes for streamdirs */
3328 node->found.obj_size = node->found.inf_len;
3329 if (node->fsck_flags & FSCK_NODE_FLAG_STREAM_ENTRY) {
3330 assert(node->parent); /* streamdir itself */
3331 if (node->parent->parent)
3332 node->parent->parent->found.obj_size +=
3333 node->found.inf_len;
3334 }
3335
3336 /* check descriptor CRC length */
3337 if (udf_rw16(dscr->tag.desc_crc_len) !=
3338 udf_tagsize(dscr, 1) - sizeof(struct desc_tag)) {
3339 pwarn("%s : node file descriptor CRC length mismatch; "
3340 "%d declared, %zu\n",
3341 udf_node_path(node), udf_rw16(dscr->tag.desc_crc_len),
3342 udf_tagsize(dscr, 1) - sizeof(struct desc_tag));
3343 udf_recursive_keep(node);
3344 node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
3345 }
3346 }
3347
3348
3349 static void
3350 udf_node_pass1_add_entry(struct udf_fsck_node *node,
3351 struct fileid_desc *fid, struct dirent *dirent)
3352 {
3353 struct udf_fsck_node *leaf_node;
3354 int entry;
3355
3356 /* skip deleted FID entries */
3357 if (fid->file_char & UDF_FILE_CHAR_DEL)
3358 return;
3359
3360 if (udf_rw32(fid->icb.loc.lb_num) == 0) {
3361 pwarn("%s : FileID entry `%s` has invalid location\n",
3362 udf_node_path(node), dirent->d_name);
3363 udf_recursive_keep(node);
3364 if (node->parent)
3365 node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3366 return;
3367 }
3368
3369 /* increase parent link count */
3370 if (fid->file_char & UDF_FILE_CHAR_PAR) {
3371 if (node->parent)
3372 node->parent->found_link_count++;
3373 return;
3374 }
3375
3376 /* lookup if we already know this node */
3377 leaf_node = udf_node_lookup(&fid->icb);
3378 if (leaf_node) {
3379 /* got a hard link! */
3380 leaf_node->found_link_count++;
3381 return;
3382 }
3383
3384 /* create new node */
3385 leaf_node = udf_new_fsck_node(
3386 node, &fid->icb, dirent->d_name);
3387 if (node->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR)
3388 leaf_node->fsck_flags |= FSCK_NODE_FLAG_STREAM_ENTRY;
3389
3390 TAILQ_INSERT_TAIL(&fs_nodes, leaf_node, next);
3391 entry = udf_calc_node_hash(&fid->icb);
3392 LIST_INSERT_HEAD(&fs_nodes_hash[entry], leaf_node, next_hash);
3393 }
3394
3395
3396 static void
3397 udf_node_pass1_add_streamdir_entry(struct udf_fsck_node *node)
3398 {
3399 struct udf_fsck_node *leaf_node;
3400 int entry;
3401
3402 /* check for recursion */
3403 if (node->fsck_flags & FSCK_NODE_FLAG_STREAM) {
3404 /* recursive streams are not allowed by spec */
3405 pwarn("%s : specification violation, recursive stream dir\n",
3406 udf_node_path(node));
3407 udf_recursive_keep(node);
3408 node->fsck_flags |= FSCK_NODE_FLAG_WIPE_STREAM_DIR;
3409 return;
3410 }
3411
3412 /* lookup if we already know this node */
3413 leaf_node = udf_node_lookup(&node->streamdir_loc);
3414 if (leaf_node) {
3415 pwarn("%s : specification violation, hardlinked streamdir\n",
3416 udf_node_path(leaf_node));
3417 udf_recursive_keep(node);
3418 node->fsck_flags |= FSCK_NODE_FLAG_WIPE_STREAM_DIR;
3419 return;
3420 }
3421
3422 /* create new node */
3423 leaf_node = udf_new_fsck_node(
3424 node, &node->streamdir_loc, strdup(""));
3425 leaf_node->fsck_flags |= FSCK_NODE_FLAG_STREAM_DIR;
3426
3427 /* streamdirs have link count 0 : ECMA 4/14.9.6 */
3428 leaf_node->found_link_count--;
3429
3430 /* insert in to lists */
3431 TAILQ_INSERT_TAIL(&fs_nodes, leaf_node, next);
3432 entry = udf_calc_node_hash(&node->streamdir_loc);
3433 LIST_INSERT_HEAD(&fs_nodes_hash[entry], leaf_node, next_hash);
3434 }
3435
3436
3437 static int
3438 udf_process_node_pass1(struct udf_fsck_node *node, union dscrptr *dscr)
3439 {
3440 struct fileid_desc *fid;
3441 struct dirent dirent;
3442 struct charspec osta_charspec;
3443 int64_t fpos, new_length, rest_len;
3444 uint32_t fid_len;
3445 uint8_t *bpos;
3446 int isdir;
3447 int error;
3448
3449 isdir = node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY;
3450
3451 /* keep link count */
3452 node->found_link_count++;
3453
3454 if (isdir) {
3455 assert(node->directory);
3456 udf_rebuild_fid_stream(node, &new_length);
3457 node->found.inf_len = new_length;
3458 rest_len = new_length;
3459 }
3460
3461 udf_fixup_lengths_pass1(node, dscr);
3462
3463 /* check UniqueID */
3464 if (node->parent) {
3465 if (node->fsck_flags & FSCK_NODE_FLAG_STREAM) {
3466
3467 /* XXX FAULT INJECTION POINT XXX */
3468 //node->unique_id = 0xdeadbeefcafe;
3469
3470 if (node->unique_id != node->parent->unique_id) {
3471 pwarn("%s : stream file/dir UniqueID mismatch "
3472 "with parent\n",
3473 udf_node_path(node));
3474 /* do the work here prematurely for our siblings */
3475 udf_recursive_keep(node);
3476 node->unique_id = node->parent->unique_id;
3477 node->fsck_flags |= FSCK_NODE_FLAG_COPY_PARENT_ID |
3478 FSCK_NODE_FLAG_DIRTY;
3479 assert(node->parent);
3480 node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3481 }
3482 } else if (node->unique_id < 16) {
3483 pwarn("%s : file has bad UniqueID\n",
3484 udf_node_path(node));
3485 udf_recursive_keep(node);
3486 node->fsck_flags |= FSCK_NODE_FLAG_NEW_UNIQUE_ID;
3487 assert(node->parent);
3488 node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3489 }
3490 } else {
3491 /* rootdir */
3492 if (node->unique_id != 0) {
3493 pwarn("%s : has bad UniqueID, has to be zero\n",
3494 udf_node_path(node));
3495 udf_recursive_keep(node);
3496 node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3497 }
3498 }
3499
3500 /* add streamdir if present */
3501 if (node->fsck_flags & FSCK_NODE_FLAG_HAS_STREAM_DIR)
3502 udf_node_pass1_add_streamdir_entry(node);
3503
3504 /* add all children */
3505 if (isdir) {
3506 node->fsck_flags |= FSCK_NODE_FLAG_PAR_NOT_FOUND;
3507 rest_len = node->found.inf_len;
3508
3509 /* walk through all our FIDs in the directory stream */
3510 bpos = node->directory;
3511 fpos = 0;
3512 while (rest_len > 0) {
3513 fid = (struct fileid_desc *) bpos;
3514 fid_len = udf_fidsize(fid);
3515
3516 /* get printable name */
3517 memset(&dirent, 0, sizeof(dirent));
3518 udf_osta_charset(&osta_charspec);
3519 udf_to_unix_name(dirent.d_name, NAME_MAX,
3520 (char *) fid->data + udf_rw16(fid->l_iu), fid->l_fi,
3521 &osta_charspec);
3522 dirent.d_namlen = strlen(dirent.d_name);
3523
3524 /* '..' has no name, so provide one */
3525 if (fid->file_char & UDF_FILE_CHAR_PAR) {
3526 strcpy(dirent.d_name, "..");
3527 node->fsck_flags &= ~FSCK_NODE_FLAG_PAR_NOT_FOUND;
3528 }
3529
3530 udf_node_pass1_add_entry(node, fid, &dirent);
3531
3532 fpos += fid_len;
3533 bpos += fid_len;
3534 rest_len -= fid_len;
3535 }
3536 }
3537
3538 error = udf_process_file(dscr, udf_rw16(node->loc.loc.part_num), NULL,
3539 AD_CHECK_USED, node);
3540 if (error) {
3541 pwarn("%s : internal error: checking for being allocated shouldn't fail\n",
3542 udf_node_path(node));
3543 return EINVAL;
3544 }
3545 /* file/directory is OK and referenced as its size won't change */
3546 error = udf_process_file(dscr, udf_rw16(node->loc.loc.part_num), NULL,
3547 AD_MARK_AS_USED, NULL);
3548 if (error) {
3549 pwarn("%s : internal error: marking allocated shouldn't fail\n",
3550 udf_node_path(node));
3551 return EINVAL;
3552 }
3553 (void) fpos;
3554 return 0;
3555 }
3556
3557
3558 static void
3559 udf_node_pass3_repairdir(struct udf_fsck_node *node, union dscrptr *dscr)
3560 {
3561 struct fileid_desc *fid, *last_empty_fid;
3562 struct udf_fsck_node *file_node;
3563 struct udf_fsck_fid_context fid_context;
3564 struct dirent dirent;
3565 struct charspec osta_charspec;
3566 int64_t fpos, rest_len;
3567 uint32_t fid_len;
3568 uint8_t *bpos;
3569 int parent_missing;
3570 int error;
3571
3572 pwarn("%s : fixing up directory\n", udf_node_path(node));
3573 assert(node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY);
3574
3575 rest_len = node->found.inf_len;
3576
3577 udf_osta_charset(&osta_charspec);
3578 bpos = node->directory;
3579 fpos = 0;
3580 parent_missing = (node->fsck_flags & FSCK_NODE_FLAG_PAR_NOT_FOUND)? 1:0;
3581
3582 last_empty_fid = NULL;
3583 while (rest_len > 0) {
3584 fid = (struct fileid_desc *) bpos;
3585 fid_len = udf_fidsize(fid);
3586
3587 /* get printable name */
3588 memset(&dirent, 0, sizeof(dirent));
3589 udf_to_unix_name(dirent.d_name, NAME_MAX,
3590 (char *) fid->data + udf_rw16(fid->l_iu), fid->l_fi,
3591 &osta_charspec);
3592 dirent.d_namlen = strlen(dirent.d_name);
3593
3594 /* '..' has no name, so provide one */
3595 if (fid->file_char & UDF_FILE_CHAR_PAR) {
3596 strcpy(dirent.d_name, "..");
3597 }
3598
3599 /* only look up when not deleted */
3600 file_node = NULL;
3601 if ((fid->file_char & UDF_FILE_CHAR_DEL) == 0)
3602 file_node = udf_node_lookup(&fid->icb);
3603
3604 /* if found */
3605 if (file_node) {
3606 /* delete files which couldn't be found */
3607 if (file_node && (file_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)) {
3608 fid->file_char |= UDF_FILE_CHAR_DEL;
3609 memset(&fid->icb, 0, sizeof(struct long_ad));
3610 }
3611
3612 /* fix up FID UniqueID errors */
3613 if (fid->icb.longad_uniqueid != file_node->unique_id)
3614 fid->icb.longad_uniqueid = udf_rw64(file_node->unique_id);
3615 } else {
3616 /* just mark it deleted if not found */
3617 fid->file_char |= UDF_FILE_CHAR_DEL;
3618 }
3619
3620 if (fid->file_char & UDF_FILE_CHAR_DEL) {
3621 memset(&fid->icb, 0 , sizeof(struct long_ad));
3622 if (context.dscrver == 2) {
3623 uint8_t *cpos;
3624 /* compression IDs are preserved */
3625 cpos = (fid->data + udf_rw16(fid->l_iu));
3626 if (*cpos == 254)
3627 *cpos = 8;
3628 if (*cpos == 255)
3629 *cpos = 16;
3630 }
3631 }
3632
3633 fpos += fid_len;
3634 bpos += fid_len;
3635 rest_len -= fid_len;
3636 assert(rest_len >= 0);
3637 }
3638 if (parent_missing) {
3639 /* this should be valid or we're in LALA land */
3640 assert(last_empty_fid);
3641 pwarn("%s : implementation limit, can't fix up missing parent node yet!\n",
3642 udf_node_path(node));
3643 }
3644
3645 node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
3646
3647 fid_context.fid_offset = 0;
3648 fid_context.data_left = node->found.inf_len;
3649 error = udf_process_file(dscr, context.fids_part,
3650 &node->directory,
3651 AD_ADJUST_FIDS | AD_SAVE_FILE,
3652 &fid_context);
3653 if (error)
3654 pwarn("Failed to write out directory!\n");
3655 (void) fpos;
3656 }
3657
3658
3659 static void
3660 udf_node_pass3_writeout_update(struct udf_fsck_node *node, union dscrptr *dscr)
3661 {
3662 struct file_entry *fe = NULL;
3663 struct extfile_entry *efe = NULL;
3664 int crc_len, error;
3665
3666 vat_writeout = 1;
3667 if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
3668 fe = (struct file_entry *) dscr;
3669 fe->inf_len = udf_rw64(node->declared.inf_len);
3670 fe->logblks_rec = udf_rw64(node->declared.logblks_rec);
3671 fe->link_cnt = udf_rw16(node->link_count);
3672 fe->unique_id = udf_rw64(node->unique_id);
3673 }
3674 if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
3675 efe = (struct extfile_entry *) dscr;
3676 efe->inf_len = udf_rw64(node->declared.inf_len);
3677 efe->obj_size = udf_rw64(node->declared.obj_size);
3678 efe->logblks_rec = udf_rw64(node->declared.logblks_rec);
3679 efe->link_cnt = udf_rw16(node->link_count);
3680 efe->unique_id = udf_rw64(node->unique_id);
3681 /* streamdir directly cleared in dscr */
3682 }
3683
3684 /* fixup CRC length (if needed) */
3685 crc_len = udf_tagsize(dscr, 1) - sizeof(struct desc_tag);
3686 dscr->tag.desc_crc_len = udf_rw16(crc_len);
3687
3688 pwarn("%s : updating node\n", udf_node_path(node));
3689 error = udf_write_dscr_virt(dscr, udf_rw32(node->loc.loc.lb_num),
3690 udf_rw16(node->loc.loc.part_num), 1);
3691 udf_shadow_VAT_in_use(&node->loc);
3692 if (error)
3693 pwarn("%s failed\n", __func__);
3694 }
3695
3696
3697 static void
3698 udf_create_new_space_bitmaps_and_reset_freespace(void)
3699 {
3700 struct space_bitmap_desc *sbd, *new_sbd;
3701 struct part_desc *part;
3702 struct part_hdr_desc *phd;
3703 uint32_t bitmap_len, bitmap_lb, bitmap_numlb;
3704 uint32_t cnt;
3705 int i, p, dscr_size;
3706 int error;
3707
3708 /* copy recorded freespace info and clear counters */
3709 for (i = 0; i < UDF_PARTITIONS; i++) {
3710 recorded_part_free[i] = context.part_free[i];
3711 context.part_free[i] = context.part_size[i];
3712 }
3713
3714 /* clone existing bitmaps */
3715 for (i = 0; i < UDF_PARTITIONS; i++) {
3716 sbd = context.part_unalloc_bits[i];
3717 recorded_part_unalloc_bits[i] = sbd;
3718 if (sbd == NULL)
3719 continue;
3720 dscr_size = udf_tagsize((union dscrptr *) sbd,
3721 context.sector_size);
3722 new_sbd = calloc(1, dscr_size);
3723 memcpy(new_sbd, sbd, sizeof(struct space_bitmap_desc)-1);
3724
3725 /* fill space with 0xff to indicate free */
3726 for (cnt = 0; cnt < udf_rw32(sbd->num_bytes); cnt++)
3727 new_sbd->data[cnt] = 0xff;
3728
3729 context.part_unalloc_bits[i] = new_sbd;
3730 }
3731
3732 /* allocate the space bitmaps themselves (normally one) */
3733 for (i = 0; i < UDF_PARTITIONS; i++) {
3734 part = context.partitions[i];
3735 if (!part)
3736 continue;
3737
3738 phd = &part->pd_part_hdr;
3739 bitmap_len = udf_rw32(phd->unalloc_space_bitmap.len);
3740 bitmap_lb = udf_rw32(phd->unalloc_space_bitmap.lb_num);
3741 if (bitmap_len == 0)
3742 continue;
3743
3744 bitmap_numlb = udf_bytes_to_sectors(bitmap_len);
3745 sbd = context.part_unalloc_bits[i];
3746 assert(sbd);
3747
3748 udf_mark_allocated(bitmap_lb, context.vtop[i], bitmap_numlb);
3749 }
3750
3751 /* special case for metadata partition */
3752 if (context.format_flags & FORMAT_META) {
3753 i = context.metadata_part;
3754 p = context.vtop[i];
3755 assert(context.vtop_tp[i] == UDF_VTOP_TYPE_META);
3756 error = udf_process_file((union dscrptr *) context.meta_file,
3757 p, NULL, AD_MARK_AS_USED, NULL);
3758 error = udf_process_file((union dscrptr *) context.meta_mirror,
3759 p, NULL, AD_MARK_AS_USED, NULL);
3760 if (context.meta_bitmap) {
3761 error = udf_process_file(
3762 (union dscrptr *) context.meta_bitmap,
3763 p, NULL, AD_MARK_AS_USED, NULL);
3764 assert(error == 0);
3765 }
3766 }
3767
3768 /* mark fsd allocation ! */
3769 udf_mark_allocated(udf_rw32(context.fileset_desc->tag.tag_loc),
3770 context.metadata_part, 1);
3771 }
3772
3773
3774 static void
3775 udf_shadow_VAT_in_use(struct long_ad *loc)
3776 {
3777 uint32_t i;
3778 uint8_t *vat_pos, *shadow_vat_pos;
3779
3780 if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
3781 return;
3782
3783 i = udf_rw32(loc->loc.lb_num);
3784 vat_pos = context.vat_contents + context.vat_start + i*4;
3785 shadow_vat_pos = shadow_vat_contents + context.vat_start + i*4;
3786 /* keeping endian */
3787 *(uint32_t *) shadow_vat_pos = *(uint32_t *) vat_pos;
3788 }
3789
3790
3791 static void
3792 udf_create_shadow_VAT(void)
3793 {
3794 struct long_ad fsd_loc;
3795 uint32_t vat_entries, i;
3796 uint8_t *vat_pos;
3797
3798 if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
3799 return;
3800
3801 shadow_vat_contents = calloc(1, context.vat_allocated);
3802 assert(shadow_vat_contents);
3803 memcpy(shadow_vat_contents, context.vat_contents, context.vat_size);
3804
3805 vat_entries = (context.vat_size - context.vat_start)/4;
3806 for (i = 0; i < vat_entries; i++) {
3807 vat_pos = shadow_vat_contents + context.vat_start + i*4;
3808 *(uint32_t *) vat_pos = udf_rw32(0xffffffff);
3809 }
3810
3811 /*
3812 * Record our FSD in this shadow VAT since its the only one outside
3813 * the nodes.
3814 */
3815 memset(&fsd_loc, 0, sizeof(struct long_ad));
3816 fsd_loc.loc.lb_num = context.fileset_desc->tag.tag_loc;
3817 udf_shadow_VAT_in_use(&fsd_loc);
3818 }
3819
3820
3821 static void
3822 udf_check_shadow_VAT(void)
3823 {
3824 uint32_t vat_entries, i;
3825 uint8_t *vat_pos, *shadow_vat_pos;
3826 int difference = 0;
3827
3828 if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
3829 return;
3830
3831 vat_entries = (context.vat_size - context.vat_start)/4;
3832 for (i = 0; i < vat_entries; i++) {
3833 vat_pos = context.vat_contents + context.vat_start + i*4;
3834 shadow_vat_pos = shadow_vat_contents + context.vat_start + i*4;
3835 if (*(uint32_t *) vat_pos != *(uint32_t *) shadow_vat_pos) {
3836 difference++;
3837 }
3838 }
3839 memcpy(context.vat_contents, shadow_vat_contents, context.vat_size);
3840 if (difference) {
3841 if (!preen)
3842 printf("\t\t");
3843 pwarn("%d unused VAT entries cleaned\n", difference);
3844 vat_writeout = 1;
3845 }
3846 }
3847
3848
3849 static int
3850 udf_check_directory_tree(void)
3851 {
3852 union dscrptr *dscr;
3853 struct udf_fsck_node *root_node, *sys_stream_node;
3854 struct udf_fsck_node *cur_node, *next_node;
3855 struct long_ad root_icb, sys_stream_icb;
3856 bool dont_repair;
3857 int entry, error;
3858
3859 assert(TAILQ_EMPTY(&fs_nodes));
3860
3861 /* (re)init queues and hash lists */
3862 TAILQ_INIT(&fs_nodes);
3863 TAILQ_INIT(&fsck_overlaps);
3864 for (int i = 0; i < HASH_HASHSIZE; i++)
3865 LIST_INIT(&fs_nodes_hash[i]);
3866
3867 /* create a new empty copy of the space bitmaps */
3868 udf_create_new_space_bitmaps_and_reset_freespace();
3869 udf_create_shadow_VAT();
3870
3871 /* start from the root */
3872 root_icb = context.fileset_desc->rootdir_icb;
3873 sys_stream_icb = context.fileset_desc->streamdir_icb;
3874
3875 root_node = udf_new_fsck_node(NULL, &root_icb, strdup(""));
3876 assert(root_node);
3877 TAILQ_INSERT_TAIL(&fs_nodes, root_node, next);
3878 entry = udf_calc_node_hash(&root_node->loc);
3879 LIST_INSERT_HEAD(&fs_nodes_hash[entry], root_node, next_hash);
3880
3881 sys_stream_node = NULL;
3882 if (sys_stream_icb.len) {
3883 sys_stream_node = udf_new_fsck_node(NULL, &sys_stream_icb, strdup("#"));
3884 assert(sys_stream_node);
3885 sys_stream_node->fsck_flags |= FSCK_NODE_FLAG_STREAM_DIR;
3886
3887 TAILQ_INSERT_TAIL(&fs_nodes, sys_stream_node, next);
3888 entry = udf_calc_node_hash(&sys_stream_node->loc);
3889 LIST_INSERT_HEAD(&fs_nodes_hash[entry], sys_stream_node, next_hash);
3890 }
3891
3892 /* pass 1 */
3893 if (!preen)
3894 printf("\tPass 1, reading in directory trees\n");
3895
3896 context.unique_id = MAX(0x10, context.unique_id);
3897 TAILQ_FOREACH(cur_node, &fs_nodes, next) {
3898 /* read in node */
3899 error = udf_read_node_dscr(cur_node, &dscr);
3900 if (!error)
3901 error = udf_extract_node_info(cur_node, dscr, 0);
3902 if (error) {
3903 pwarn("%s : invalid reference or bad descriptor, DELETING\n",
3904 udf_node_path(cur_node));
3905 udf_recursive_keep(cur_node);
3906 cur_node->fsck_flags |= FSCK_NODE_FLAG_NOTFOUND;
3907 if (cur_node->parent) {
3908 if (cur_node->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR)
3909 cur_node->parent->fsck_flags |=
3910 FSCK_NODE_FLAG_WIPE_STREAM_DIR;
3911 else
3912 cur_node->parent->fsck_flags |=
3913 FSCK_NODE_FLAG_REPAIRDIR;
3914 ;
3915 }
3916 free(dscr);
3917 continue;
3918 }
3919
3920 if (print_info) {
3921 pwarn("Processing %s\n", udf_node_path(cur_node));
3922 print_info = 0;
3923 }
3924
3925 /* directory found in stream directory? */
3926 if (cur_node->parent &&
3927 (cur_node->parent->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR) &&
3928 (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY))
3929 {
3930 pwarn("%s : specification violation, directory in stream directory\n",
3931 udf_node_path(cur_node));
3932 if (ask(0, "Clear directory")) {
3933 udf_recursive_keep(cur_node);
3934 cur_node->fsck_flags |= FSCK_NODE_FLAG_NOTFOUND;
3935 cur_node->parent->fsck_flags |=
3936 FSCK_NODE_FLAG_REPAIRDIR;
3937 continue;
3938 }
3939 }
3940 error = udf_process_node_pass1(cur_node, dscr);
3941 free(dscr);
3942
3943 if (error)
3944 return error;
3945 }
3946
3947 /* pass 1b, if there is overlap, find matching pairs */
3948 dont_repair = false;
3949 if (!TAILQ_EMPTY(&fsck_overlaps)) {
3950 struct udf_fsck_overlap *overlap;
3951
3952 dont_repair = true;
3953 pwarn("*** Overlaps detected! rescanning tree for matching pairs ***\n");
3954 TAILQ_FOREACH(cur_node, &fs_nodes, next) {
3955 if (cur_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)
3956 continue;
3957
3958 error = udf_read_node_dscr(cur_node, &dscr);
3959 /* should not fail differently */
3960
3961 if (print_info) {
3962 pwarn("Processing %s\n", udf_node_path(cur_node));
3963 print_info = 0;
3964 }
3965
3966 error = udf_process_file(
3967 dscr,
3968 udf_rw16(cur_node->loc.loc.part_num),
3969 NULL,
3970 AD_FIND_OVERLAP_PAIR,
3971 (void *) cur_node);
3972 /* shouldn't fail */
3973
3974 free(dscr);
3975 }
3976 TAILQ_FOREACH(overlap, &fsck_overlaps, next) {
3977 pwarn("%s :overlaps with %s\n",
3978 udf_node_path(overlap->node),
3979 udf_node_path(overlap->node2));
3980 }
3981 if (!preen)
3982 printf("\n");
3983 pwarn("*** The following files/directories need to be copied/evacuated:\n");
3984 TAILQ_FOREACH(cur_node, &fs_nodes, next) {
3985 if (cur_node->fsck_flags & FSCK_NODE_FLAG_OVERLAP) {
3986 pwarn("%s : found OVERLAP, evacuate\n",
3987 udf_node_path(cur_node));
3988 }
3989 }
3990 }
3991 if (dont_repair) {
3992 if (!preen)
3993 printf("\n");
3994 pwarn("*** Skipping further repair, only updating free space map if needed\n");
3995 pwarn("*** After deep copying and/or evacuation of these files/directories,\n");
3996 pwarn("*** remove files/directories and re-run fsck_udf\n");
3997 error = udf_prepare_writing();
3998 if (error)
3999 return error;
4000
4001 udf_update_lvintd(UDF_INTEGRITY_OPEN);
4002 return 0;
4003 }
4004
4005 /* pass 2a, checking link counts, object sizes and count files/dirs */
4006 if (!preen)
4007 printf("\n\tPass 2, checking link counts, object sizes, stats and cleaning up\n");
4008
4009 TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) {
4010 /* not sane to process files/directories that are not found */
4011 if (cur_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)
4012 continue;
4013
4014 /* shadow VAT */
4015 udf_shadow_VAT_in_use(&cur_node->loc);
4016
4017 /* link counts */
4018 if (cur_node->found_link_count != cur_node->link_count) {
4019 pwarn("%s : link count incorrect; "
4020 "%u instead of declared %u : FIXED\n",
4021 udf_node_path(cur_node),
4022 cur_node->found_link_count, cur_node->link_count);
4023 cur_node->link_count = cur_node->found_link_count;
4024 udf_recursive_keep(cur_node);
4025 cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
4026 }
4027
4028 /* object sizes */
4029 if (cur_node->declared.obj_size != cur_node->found.obj_size) {
4030 pwarn("%s : recorded object size incorrect; "
4031 "%" PRIu64 " instead of declared %" PRIu64 "\n",
4032 udf_node_path(cur_node),
4033 cur_node->found.obj_size, cur_node->declared.obj_size);
4034 cur_node->declared.obj_size = cur_node->found.obj_size;
4035 udf_recursive_keep(cur_node);
4036 cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
4037 }
4038
4039 /* XXX TODO XXX times */
4040 /* XXX TODO XXX extended attributes location for UDF < 1.50 */
4041
4042 /* validity of UniqueID check */
4043 if (cur_node->parent) {
4044 if (cur_node->fsck_flags & FSCK_NODE_FLAG_NEW_UNIQUE_ID) {
4045 pwarn("%s : assigning new UniqueID\n",
4046 udf_node_path(cur_node));
4047 cur_node->unique_id = udf_rw64(context.unique_id);
4048 udf_advance_uniqueid();
4049 udf_recursive_keep(cur_node);
4050 cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
4051 if (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY)
4052 cur_node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
4053 cur_node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
4054 }
4055 if (cur_node->fsck_flags & FSCK_NODE_FLAG_COPY_PARENT_ID) {
4056 /* work already done but make note to operator */
4057 pwarn("%s : fixing stream UniqueID to match parent\n",
4058 udf_node_path(cur_node));
4059 }
4060 } else {
4061 if (cur_node->unique_id != 0) {
4062 pwarn("%s : bad UniqueID, zeroing\n",
4063 udf_node_path(cur_node));
4064 cur_node->unique_id = 0;
4065 cur_node->fsck_flags |=
4066 FSCK_NODE_FLAG_DIRTY | FSCK_NODE_FLAG_REPAIRDIR;
4067 }
4068 }
4069
4070 /* keep nodes in a repairing dir */
4071 if (cur_node->parent)
4072 if (cur_node->parent->fsck_flags & FSCK_NODE_FLAG_REPAIRDIR)
4073 cur_node->fsck_flags |= FSCK_NODE_FLAG_KEEP;
4074
4075 /* stream directories and files in it are not included */
4076 if (!(cur_node->fsck_flags & FSCK_NODE_FLAG_STREAM)) {
4077 /* files / directories counting */
4078 int link_count = cur_node->found_link_count;
4079
4080 /* stream directories don't count as link ECMA 4/14.9.6 */
4081 if (cur_node->fsck_flags & FSCK_NODE_FLAG_HAS_STREAM_DIR)
4082 link_count--;
4083
4084 if (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY)
4085 context.num_directories++;
4086 else
4087 context.num_files += link_count;
4088 ;
4089 }
4090 }
4091
4092 /* pass 2b, cleaning */
4093 open_integrity = 0;
4094 TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) {
4095 /* can we remove the node? (to save memory) */
4096 if (FSCK_NODE_FLAG_OK(cur_node->fsck_flags)) {
4097 TAILQ_REMOVE(&fs_nodes, cur_node, next);
4098 LIST_REMOVE(cur_node, next_hash);
4099 free(cur_node->directory);
4100 bzero(cur_node, sizeof(struct udf_fsck_node));
4101 free(cur_node);
4102 } else {
4103 /* else keep erroring node */
4104 open_integrity = 1;
4105 }
4106 }
4107
4108 if (!preen)
4109 printf("\n\tPreparing disc for writing\n");
4110 error = udf_prepare_writing();
4111 if (error)
4112 return error;
4113
4114 if (open_integrity)
4115 udf_update_lvintd(UDF_INTEGRITY_OPEN);
4116
4117 /* pass 3 */
4118 if (!preen)
4119 printf("\n\tPass 3, fix errors\n");
4120
4121 TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) {
4122 /* not sane to process files/directories that are not found */
4123 if (cur_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)
4124 continue;
4125
4126 /* only interested in bad nodes */
4127 if (FSCK_NODE_FLAG_OK(cur_node->fsck_flags))
4128 continue;
4129
4130 error = udf_read_node_dscr(cur_node, &dscr);
4131 /* should not fail differently */
4132
4133 /* repair directories */
4134 if (cur_node->fsck_flags & FSCK_NODE_FLAG_REPAIRDIR)
4135 udf_node_pass3_repairdir(cur_node, dscr);
4136
4137 /* remove invalid stream directories */
4138 if (cur_node->fsck_flags & FSCK_NODE_FLAG_WIPE_STREAM_DIR) {
4139 assert(udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY);
4140 bzero(&dscr->efe.streamdir_icb, sizeof(struct long_ad));
4141 cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
4142 }
4143
4144 if (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRTY)
4145 udf_node_pass3_writeout_update(cur_node, dscr);
4146 free(dscr);
4147 }
4148 udf_check_shadow_VAT();
4149
4150 return 0;
4151 }
4152
4153
4154 static void
4155 udf_cleanup_after_check(void)
4156 {
4157 struct udf_fsck_node *cur_node, *next_node;
4158
4159 /* XXX yes, there are some small memory leaks here */
4160
4161 /* clean old node info from previous checks */
4162 TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) {
4163 TAILQ_REMOVE(&fs_nodes, cur_node, next);
4164 LIST_REMOVE(cur_node, next_hash);
4165 free(cur_node->directory);
4166 free(cur_node);
4167 }
4168
4169 /* free partition related info */
4170 for (int i = 0; i < UDF_PARTITIONS; i++) {
4171 free(context.partitions[i]);
4172 free(context.part_unalloc_bits[i]);
4173 free(context.part_freed_bits[i]);
4174 }
4175
4176 /* only free potentional big blobs */
4177 free(context.vat_contents);
4178 free(context.lvint_history);
4179
4180 free(shadow_vat_contents);
4181 shadow_vat_contents = NULL;
4182 }
4183
4184
4185 static int
4186 checkfilesys(char *given_dev)
4187 {
4188 struct mmc_trackinfo ti;
4189 int open_flags;
4190 int error;
4191
4192 udf_init_create_context();
4193 context.app_name = "*NetBSD UDF";
4194 context.app_version_main = APP_VERSION_MAIN;
4195 context.app_version_sub = APP_VERSION_SUB;
4196 context.impl_name = IMPL_NAME;
4197
4198 emul_mmc_profile = -1; /* invalid->no emulation */
4199 emul_packetsize = 1; /* reasonable default */
4200 emul_sectorsize = 512; /* minimum allowed sector size */
4201 emul_size = 0; /* empty */
4202
4203 if (!preen)
4204 pwarn("** Checking UDF file system on %s\n", given_dev);
4205
4206 /* reset sticky flags */
4207 rdonly = rdonly_flag;
4208 undo_opening_session = 0; /* trying to undo opening of last crippled session */
4209 vat_writeout = 0; /* to write out the VAT anyway */
4210
4211 /* open disc device or emulated file */
4212 open_flags = rdonly ? O_RDONLY : O_RDWR;
4213 if (udf_opendisc(given_dev, open_flags)) {
4214 udf_closedisc();
4215 warnx("can't open %s", given_dev);
4216 return FSCK_EXIT_CHECK_FAILED;
4217 }
4218
4219 if (!preen)
4220 pwarn("** Phase 1 - discovering format from disc\n\n");
4221
4222 /* check if it is an empty disc or no disc in present */
4223 ti.tracknr = mmc_discinfo.first_track;
4224 error = udf_update_trackinfo(&ti);
4225 if (error || (ti.flags & MMC_TRACKINFO_BLANK)) {
4226 /* no use erroring out */
4227 pwarn("Empty disc\n");
4228 return FSCK_EXIT_OK;
4229 }
4230
4231 context.format_flags = 0;
4232 if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL)
4233 context.format_flags |= FORMAT_SEQUENTIAL;
4234
4235 if ((context.format_flags & FORMAT_SEQUENTIAL) &&
4236 ((mmc_discinfo.disc_state == MMC_STATE_CLOSED) ||
4237 (mmc_discinfo.disc_state == MMC_STATE_FULL))) {
4238 pwarn("Disc is closed or full, can't modify disc\n");
4239 rdonly = 1;
4240 }
4241
4242 if (target_session) {
4243 context.create_new_session = 1;
4244 if (target_session < 0)
4245 target_session += mmc_discinfo.num_sessions;
4246 } else {
4247 target_session = mmc_discinfo.num_sessions;
4248 if (mmc_discinfo.last_session_state == MMC_STATE_EMPTY)
4249 target_session--;
4250 }
4251
4252 error = udf_get_anchors();
4253 if (error) {
4254 udf_closedisc();
4255 pwarn("Failed to retrieve anchors; can't check file system\n");
4256 return FSCK_EXIT_CHECK_FAILED;
4257 }
4258
4259 udf_check_vrs9660();
4260
4261 /* get both VRS areas */
4262 error = udf_check_VDS_areas();
4263 if (error) {
4264 udf_closedisc();
4265 pwarn("Failure reading volume descriptors, disc might be toast\n");
4266 return FSCK_EXIT_CHECK_FAILED;
4267 }
4268
4269 if (udf_rw32(context.logvol_integrity->integrity_type) ==
4270 UDF_INTEGRITY_CLOSED) {
4271 if (!force) {
4272 pwarn("** File system is clean; not checking\n");
4273 return FSCK_EXIT_OK;
4274 }
4275 pwarn("** File system is already clean\n");
4276 if (!preen)
4277 pwarn("\n");
4278 } else {
4279 pwarn("** File system not closed properly\n");
4280 if (!preen)
4281 printf("\n");
4282 }
4283
4284 /*
4285 * Only now read in free/unallocated space bitmap. If it reads in fine
4286 * it doesn't mean its contents is valid though. Sets partition
4287 * lengths too.
4288 */
4289 error = udf_readin_partitions_free_space();
4290 if (error) {
4291 pwarn("Error during free space bitmap reading\n");
4292 udf_update_lvintd(UDF_INTEGRITY_OPEN);
4293 }
4294
4295 if (!preen)
4296 pwarn("** Phase 2 - walking directory tree\n");
4297
4298 udf_suspend_writing();
4299 error = udf_check_directory_tree();
4300 if (error) {
4301 if ((!rdonly) && ask(0, "Write out modifications made until now"))
4302 udf_allow_writing();
4303 else
4304 pwarn("** Aborting repair, not modifying disc\n");
4305 udf_closedisc();
4306 return FSCK_EXIT_CHECK_FAILED;
4307 }
4308
4309 if (!preen)
4310 pwarn("\n** Phase 3 - closing volume if needed\n\n");
4311
4312 /* XXX FAULT INJECTION POINT XXX */
4313 //udf_update_lvintd(UDF_INTEGRITY_OPEN);
4314
4315 if (error && rdonly) {
4316 pwarn("** Aborting repair, nothing written, disc marked read-only\n");
4317 } else {
4318 error = udf_close_volume();
4319 }
4320
4321 udf_closedisc();
4322
4323 if (error)
4324 return FSCK_EXIT_CHECK_FAILED;
4325 return FSCK_EXIT_OK;
4326 }
4327
4328
4329 static void
4330 usage(void)
4331 {
4332 (void)fprintf(stderr, "Usage: %s [-fHnpSsy] file-system ... \n",
4333 getprogname());
4334 exit(FSCK_EXIT_USAGE);
4335 }
4336
4337
4338 static void
4339 got_siginfo(int signo)
4340 {
4341 print_info = 1;
4342 }
4343
4344
4345 int
4346 main(int argc, char **argv)
4347 {
4348 int ret = FSCK_EXIT_OK, erg;
4349 int ch;
4350
4351 while ((ch = getopt(argc, argv, "ps:SynfH")) != -1) {
4352 switch (ch) {
4353 case 'H':
4354 heuristics = 1;
4355 break;
4356 case 'f':
4357 force = 1;
4358 break;
4359 case 'n':
4360 rdonly_flag = alwaysno = 1;
4361 alwaysyes = preen = 0;
4362 break;
4363 case 'y':
4364 alwaysyes = 1;
4365 alwaysno = preen = 0;
4366 break;
4367 case 'p':
4368 /* small automatic repairs */
4369 preen = 1;
4370 alwaysyes = alwaysno = 0;
4371 break;
4372 case 's':
4373 /* session number or relative session */
4374 target_session = atoi(optarg);
4375 break;
4376 case 'S': /* Search for older VATs */
4377 search_older_vat = 1;
4378 break;
4379
4380 default:
4381 usage();
4382 break;
4383 }
4384 }
4385 argc -= optind;
4386 argv += optind;
4387
4388 if (!argc)
4389 usage();
4390
4391 /* TODO SIGINT and SIGQUIT catchers */
4392 #if 0
4393 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
4394 (void) signal(SIGINT, catch);
4395 if (preen)
4396 (void) signal(SIGQUIT, catch);
4397 #endif
4398
4399 signal(SIGINFO, got_siginfo);
4400
4401 while (--argc >= 0) {
4402 setcdevname(*argv, preen);
4403 erg = checkfilesys(*argv++);
4404 if (erg > ret)
4405 ret = erg;
4406 if (!preen)
4407 printf("\n");
4408 udf_cleanup_after_check();
4409 }
4410
4411 return ret;
4412 }
4413
4414
4415 /*VARARGS*/
4416 static int __printflike(2, 3)
4417 ask(int def, const char *fmt, ...)
4418 {
4419 va_list ap;
4420
4421 char prompt[256];
4422 int c;
4423
4424 va_start(ap, fmt);
4425 vsnprintf(prompt, sizeof(prompt), fmt, ap);
4426 va_end(ap);
4427 if (alwaysyes || rdonly) {
4428 pwarn("%s? %s\n", prompt, rdonly ? "no" : "yes");
4429 return !rdonly;
4430 }
4431 if (preen) {
4432 pwarn("%s? %s : (default)\n", prompt, def ? "yes" : "no");
4433 return def;
4434 }
4435
4436 do {
4437 pwarn("%s? [yn] ", prompt);
4438 fflush(stdout);
4439 c = getchar();
4440 while (c != '\n' && getchar() != '\n')
4441 if (feof(stdin))
4442 return 0;
4443 } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
4444 return c == 'y' || c == 'Y';
4445 }
4446
4447
4448 /*VARARGS*/
4449 static int __printflike(2, 3)
4450 ask_noauto(int def, const char *fmt, ...)
4451 {
4452 va_list ap;
4453
4454 char prompt[256];
4455 int c;
4456
4457 va_start(ap, fmt);
4458 vsnprintf(prompt, sizeof(prompt), fmt, ap);
4459 va_end(ap);
4460 #if 0
4461 if (preen) {
4462 pwarn("%s? %s : (default)\n", prompt, def ? "yes" : "no");
4463 return def;
4464 }
4465 #endif
4466
4467 do {
4468 pwarn("%s? [yn] ", prompt);
4469 fflush(stdout);
4470 c = getchar();
4471 while (c != '\n' && getchar() != '\n')
4472 if (feof(stdin))
4473 return 0;
4474 } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
4475 return c == 'y' || c == 'Y';
4476 }
4477