xref: /netbsd-src/sbin/fsck_udf/main.c (revision 2ff65d1cde9ab208a6ca05043d200cd432f84644)
1 /*	$NetBSD: main.c,v 1.14 2023/08/03 08:06:11 mrg 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.14 2023/08/03 08:06:11 mrg 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;
LIST_HEAD(udf_fsck_node_hash_list,udf_fsck_node)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
printtime(time_t ftime)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
udf_print_timestamp(const char * prefix,struct timestamp * timestamp,const char * suffix)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, &timespec);
262 	printf("%s", prefix);
263 	printtime(timespec.tv_sec);
264 	printf("%s", suffix);
265 }
266 
267 
268 static int
udf_compare_mtimes(struct timestamp * t1,struct timestamp * t2)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
udf_calc_node_hash(struct long_ad * icb)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 *
udf_node_lookup(struct long_ad * icb)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
udf_wipe_and_reallocate(union dscrptr * dscrptr,int vpart_num,uint32_t * l_adp)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
udf_copy_fid_verbatim(struct fileid_desc * sfid,struct fileid_desc * dfid,uint64_t dfpos,uint64_t drest)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
udf_rebuild_fid_stream(struct udf_fsck_node * node,int64_t * rest_lenp)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
udf_quick_check_fids_piece(uint8_t * piece,uint32_t piece_len,struct udf_fsck_fid_context * fid_context,uint32_t lb_num)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
udf_fids_fixup(uint8_t * piece,uint32_t piece_len,struct udf_fsck_fid_context * fid_context,uint32_t lb_num)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
udf_check_if_allocated(struct udf_fsck_node * node,int flags,uint32_t start_lb,int partnr,uint32_t piece_len)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
udf_check_overlap_pair(struct udf_fsck_node * node,int flags,uint32_t start_lb,int partnr,uint32_t piece_len)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
udf_process_ad(union dscrptr * dscrptr,int action,uint8_t ** resultp,int vpart_num,uint64_t fpos,struct short_ad * short_adp,struct long_ad * long_adp,void * process_context)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
udf_process_file(union dscrptr * dscrptr,int vpart_num,uint8_t ** resultp,int action,void * process_context)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
udf_readin_file(union dscrptr * dscrptr,int vpart_num,uint8_t ** resultp,struct udf_fsck_file_stats * statsp)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
udf_check_vrs9660(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
udf_find_anchor(int anum)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
udf_get_anchors(void)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
udf_retrieve_lvint(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
udf_writeout_lvint(void)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
udf_readin_partitions_free_space(void)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
udf_update_logvolname(char * logvol_id)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 *
udf_file_mtime(union dscrptr * dscr)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
udf_print_vat_details(union dscrptr * dscr)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
udf_check_for_vat(union dscrptr * dscr)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
udf_extract_vat(union dscrptr * dscr,uint8_t ** vat_contents)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
udf_search_vat(union udf_pmap * mapping,int log_part)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
udf_read_spareables(union udf_pmap * mapping,int log_part)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
udf_metadata_node_supported(void)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
udf_read_metadata_nodes(union udf_pmap * mapping,int log_part)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
udf_process_vds(void)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
udf_process_vds_descriptor(union dscrptr * dscr,int dscr_size)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
udf_read_vds_extent(union dscrptr * dscr,int vds_size)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
udf_copy_VDS_area(void * destbuf,void * srcbuf)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
udf_check_VDS_areas(void)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 		vds2_buf = NULL;
2804 	}
2805 	if (!error2) {
2806 		/* retrieve data from VDS 2 */
2807 		udf_read_vds_extent(vds2_buf, vds2_size);
2808 		context.vds_buf  = vds2_buf;
2809 		context.vds_size = vds2_size;
2810 		free(vds1_buf);
2811 		vds1_buf = NULL;
2812 	}
2813 	/* check if all is correct and complete */
2814 	error = udf_process_vds();
2815 	if (error)
2816 		return error;
2817 
2818 	/* TODO check if both area's are logically the same */
2819 	error = 0;
2820 	if (!error1 && error2) {
2821 		/* first OK, second faulty */
2822 		pwarn("Backup volume descriptor missing or damaged\n");
2823 		if (context.format_flags & FORMAT_SEQUENTIAL) {
2824 			pwarn("Can't fixup backup volume descriptor on "
2825 			      "SEQUENTIAL media\n");
2826 		} else if (ask(1, "Fixup backup volume descriptor")) {
2827 			error = udf_copy_VDS_area(vds2_buf, vds1_buf);
2828 			pwarn("\n");
2829 		}
2830 	}
2831 	if (error1 && !error2) {
2832 		/* second OK, first faulty */
2833 		pwarn("Primary volume descriptor missing or damaged\n");
2834 		if (context.format_flags & FORMAT_SEQUENTIAL) {
2835 			pwarn("Can't fix up primary volume descriptor on "
2836 			      "SEQUENTIAL media\n");
2837 		} else if (ask(1, "Fix up primary volume descriptor")) {
2838 			error = udf_copy_VDS_area(vds1_buf, vds2_buf);
2839 		}
2840 	}
2841 	if (error)
2842 		pwarn("copying VDS areas failed!\n");
2843 	if (!preen)
2844 		printf("\n");
2845 
2846 	return error;
2847 }
2848 
2849 /* --------------------------------------------------------------------- */
2850 
2851 static int
udf_prepare_writing(void)2852 udf_prepare_writing(void)
2853 {
2854 	union dscrptr *zero_dscr, *dscr;
2855 	struct mmc_trackinfo ti;
2856 	uint32_t first_lba, loc;
2857 	int sector_size = context.sector_size;
2858 	int error;
2859 
2860 	error = udf_prepare_disc();
2861 	if (error) {
2862 		pwarn("*** Preparing disc for writing failed!\n");
2863 		return error;
2864 	}
2865 
2866 	/* if we are not on sequential media, we're done */
2867 	if ((context.format_flags & FORMAT_VAT) == 0)
2868 		return 0;
2869 
2870 	/* if the disc is full, we drop back to read only */
2871 	if (mmc_discinfo.disc_state == MMC_STATE_FULL)
2872 		rdonly = 1;
2873 	if (rdonly)
2874 		return 0;
2875 
2876 	/* check if we need to open the last track */
2877 	ti.tracknr = mmc_discinfo.last_track_last_session;
2878 	error = udf_update_trackinfo(&ti);
2879 	if (error)
2880 		return error;
2881 	if (!(ti.flags & MMC_TRACKINFO_BLANK) &&
2882 	     (ti.flags & MMC_TRACKINFO_NWA_VALID)) {
2883 		/*
2884 		 * Not closed; translate next_writable to a position relative to our
2885 		 * backing partition
2886 		 */
2887 		context.alloc_pos[context.data_part] = ti.next_writable -
2888 			udf_rw32(context.partitions[context.data_part]->start_loc);
2889 		wrtrack_skew = ti.next_writable % layout.blockingnr;
2890 		return 0;
2891 	}
2892 	assert(ti.flags & MMC_TRACKINFO_NWA_VALID);
2893 
2894 	/* just in case */
2895 	udf_suspend_writing();
2896 
2897 	/* 'add' a new track */
2898 	udf_update_discinfo();
2899 	memset(&context.last_ti, 0, sizeof(struct mmc_trackinfo));
2900 	context.last_ti.tracknr = mmc_discinfo.first_track_last_session;
2901 	(void) udf_update_trackinfo(&context.last_ti);
2902 
2903 	assert(mmc_discinfo.last_session_state == MMC_STATE_EMPTY);
2904 	first_lba = context.last_ti.track_start;
2905 	wrtrack_skew = context.last_ti.track_start % layout.blockingnr;
2906 
2907 	/*
2908 	 * location of iso9660 vrs is defined as first sector AFTER 32kb,
2909 	 * minimum `sector size' 2048
2910 	 */
2911 	layout.iso9660_vrs = ((32*1024 + sector_size - 1) / sector_size)
2912 		+ first_lba;
2913 
2914 	/* anchor starts at specified offset in sectors */
2915 	layout.anchors[0] = first_lba + 256;
2916 
2917 	/* ready for appending, write preamble, we are using overwrite here! */
2918 	if ((zero_dscr = calloc(1, context.sector_size)) == NULL)
2919 		return ENOMEM;
2920 	loc = first_lba;
2921 	for (; loc < first_lba + 256; loc++) {
2922 		if ((error = udf_write_sector(zero_dscr, loc))) {
2923 			free(zero_dscr);
2924 			return error;
2925 		}
2926 	}
2927 	free(zero_dscr);
2928 
2929 	/* write new ISO9660 volume recognition sequence */
2930 	if ((error = udf_write_iso9660_vrs())) {
2931 		pwarn("internal error: can't write iso966 VRS in new session!\n");
2932 		rdonly = 1;
2933 		return error;
2934 	}
2935 
2936 	/* write out our old anchor, VDS spaces will be reused */
2937 	assert(context.anchors[0]);
2938 	dscr = (union dscrptr *) context.anchors[0];
2939 	loc  = layout.anchors[0];
2940 	if ((error = udf_write_dscr_phys(dscr, loc, 1))) {
2941 		pwarn("internal error: can't write anchor in new session!\n");
2942 		rdonly = 1;
2943 		return error;
2944 	}
2945 
2946 	context.alloc_pos[context.data_part] = first_lba + 257 -
2947 		udf_rw32(context.partitions[context.data_part]->start_loc);
2948 
2949 	return 0;
2950 }
2951 
2952 
2953 static int
udf_close_volume_vat(void)2954 udf_close_volume_vat(void)
2955 {
2956 	int integrity_type;
2957 
2958 	/* only write out when its open */
2959 	integrity_type = udf_rw32(context.logvol_integrity->integrity_type);
2960 	if (integrity_type == UDF_INTEGRITY_CLOSED)
2961 		return 0;
2962 
2963 	if (!preen)
2964 		printf("\n");
2965 	if (!ask(1, "Write out modifications"))
2966 		return 0;
2967 
2968 	/* writeout our VAT contents */
2969 	udf_allow_writing();
2970 	return udf_writeout_VAT();
2971 }
2972 
2973 
2974 static int
udf_close_volume(void)2975 udf_close_volume(void)
2976 {
2977 	struct part_desc       *part;
2978 	struct part_hdr_desc   *phd;
2979 	struct logvol_int_desc *lvid;
2980 	struct udf_logvol_info *lvinfo;
2981 	struct logvol_desc     *logvol;
2982 	uint32_t bitmap_len, bitmap_lb, bitmap_numlb;
2983 	int i, equal, error;
2984 
2985 	lvid = context.logvol_integrity;
2986 	logvol = context.logical_vol;
2987 	lvinfo = context.logvol_info;
2988 	assert(lvid);
2989 	assert(logvol);
2990 	assert(lvinfo);
2991 
2992 	/* check our highest unique id */
2993 	if (context.unique_id > udf_rw64(lvid->lvint_next_unique_id)) {
2994 		pwarn("Last unique id updated from %" PRIi64 " to %" PRIi64 " : FIXED\n",
2995 				udf_rw64(lvid->lvint_next_unique_id),
2996 				context.unique_id);
2997 		open_integrity = 1;
2998 	}
2999 
3000 	/* check file/directory counts */
3001 	if (context.num_files != udf_rw32(lvinfo->num_files)) {
3002 		pwarn("Number of files corrected from %d to %d : FIXED\n",
3003 				udf_rw32(lvinfo->num_files),
3004 				context.num_files);
3005 		open_integrity = 1;
3006 	}
3007 	if (context.num_directories != udf_rw32(lvinfo->num_directories)) {
3008 		pwarn("Number of directories corrected from %d to %d : FIXED\n",
3009 				udf_rw32(lvinfo->num_directories),
3010 				context.num_directories);
3011 		open_integrity = 1;
3012 	}
3013 
3014 	if (vat_writeout)
3015 		open_integrity = 1;
3016 
3017 	if (open_integrity)
3018 		udf_update_lvintd(UDF_INTEGRITY_OPEN);
3019 
3020 	if (context.format_flags & FORMAT_VAT)
3021 		return udf_close_volume_vat();
3022 
3023 	/* adjust free space accounting! */
3024 	for (i = 0; i < UDF_PARTITIONS; i++) {
3025 		part = context.partitions[i];
3026 		if (!part)
3027 			continue;
3028 		phd = &part->pd_part_hdr;
3029 		bitmap_len = udf_rw32(phd->unalloc_space_bitmap.len);
3030 		bitmap_lb  = udf_rw32(phd->unalloc_space_bitmap.lb_num);
3031 
3032 		if (bitmap_len == 0) {
3033 			error = 0;
3034 			continue;
3035 		}
3036 
3037 		equal = memcmp( recorded_part_unalloc_bits[i],
3038 				context.part_unalloc_bits[i],
3039 				bitmap_len) == 0;
3040 
3041 		if (!equal || (context.part_free[i] != recorded_part_free[i])) {
3042 			if (!equal)
3043 				pwarn("Calculated bitmap for partition %d not equal "
3044 				      "to recorded one : FIXED\n", i);
3045 			pwarn("Free space on partition %d corrected "
3046 			      "from %d to %d blocks : FIXED\n", i,
3047 			      recorded_part_free[i],
3048 			      context.part_free[i]);
3049 
3050 			/* write out updated free space map */
3051 			pwarn("Updating unallocated bitmap for partition\n");
3052 			if (!preen)
3053 				printf("Writing free space map "
3054 				       "for partition %d\n", i);
3055 			error = 0;
3056 			if (context.vtop_tp[i] == UDF_VTOP_TYPE_META) {
3057 				if (context.meta_bitmap) {
3058 					assert(i == context.metadata_part);
3059 					error = udf_process_file(
3060 						(union dscrptr *) context.meta_bitmap,
3061 						context.data_part,
3062 						(uint8_t **) &(context.part_unalloc_bits[i]),
3063 						AD_SAVE_FILE, NULL);
3064 				}
3065 			} else {
3066 				bitmap_numlb = udf_bytes_to_sectors(bitmap_len);
3067 				error = udf_write_dscr_virt(
3068 					(union dscrptr *) context.part_unalloc_bits[i],
3069 					bitmap_lb,
3070 					i,
3071 					bitmap_numlb);
3072 			}
3073 			if (error)
3074 				pwarn("Updating unallocated bitmap failed, "
3075 				      "continuing\n");
3076 			udf_update_lvintd(UDF_INTEGRITY_OPEN);
3077 		}
3078 	}
3079 
3080 	/* write out the logical volume integrity sequence */
3081 	error = udf_writeout_lvint();
3082 
3083 	return error;
3084 }
3085 
3086 /* --------------------------------------------------------------------- */
3087 
3088 /*
3089  * Main part of file system checking.
3090  *
3091  * Walk the entire directory tree and check all link counts and rebuild the
3092  * free space map (if present) on the go.
3093  */
3094 
3095 static struct udf_fsck_node *
udf_new_fsck_node(struct udf_fsck_node * parent,struct long_ad * loc,char * fname)3096 udf_new_fsck_node(struct udf_fsck_node *parent, struct long_ad *loc, char *fname)
3097 {
3098 	struct udf_fsck_node *this;
3099 	this = calloc(1, sizeof(struct udf_fsck_node));
3100 	if (!this)
3101 		return NULL;
3102 
3103 	this->parent = parent;
3104 	this->fname = strdup(fname);
3105 	this->loc = *loc;
3106 	this->fsck_flags = 0;
3107 
3108 	this->link_count = 0;
3109 	this->found_link_count = 0;
3110 
3111 	return this;
3112 }
3113 
3114 
3115 static void
udf_node_path_piece(char * pathname,struct udf_fsck_node * node)3116 udf_node_path_piece(char *pathname, struct udf_fsck_node *node)
3117 {
3118 	if (node->parent) {
3119 		udf_node_path_piece(pathname, node->parent);
3120 		if (node->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR)
3121 			strcat(pathname, "");
3122 		else
3123 			strcat(pathname, "/");
3124 	}
3125 	strcat(pathname, node->fname);
3126 }
3127 
3128 
3129 static char *
udf_node_path(struct udf_fsck_node * node)3130 udf_node_path(struct udf_fsck_node *node)
3131 {
3132 	static char pathname[MAXPATHLEN + 10];
3133 
3134 	strcpy(pathname, "`");
3135 	if (node->parent)
3136 		udf_node_path_piece(pathname, node);
3137 	else
3138 		strcat(pathname, "/");
3139 	strcat(pathname, "'");
3140 
3141 	return pathname;
3142 }
3143 
3144 
3145 static void
udf_recursive_keep(struct udf_fsck_node * node)3146 udf_recursive_keep(struct udf_fsck_node *node)
3147 {
3148 	while (node->parent) {
3149 		node = node->parent;
3150 		node->fsck_flags |= FSCK_NODE_FLAG_KEEP;
3151 	}
3152 }
3153 
3154 
3155 static int
udf_quick_check_fids(struct udf_fsck_node * node,union dscrptr * dscr)3156 udf_quick_check_fids(struct udf_fsck_node *node, union dscrptr *dscr)
3157 {
3158 	struct udf_fsck_fid_context fid_context;
3159 	int error;
3160 
3161 	fid_context.fid_offset = 0;
3162 	fid_context.data_left = node->found.inf_len;
3163 	error = udf_process_file(dscr, context.fids_part,
3164 			&node->directory,
3165 			AD_CHECK_FIDS,
3166 			&fid_context);
3167 
3168 	return error;
3169 }
3170 
3171 
3172 /* read descriptor at node's location */
3173 static int
udf_read_node_dscr(struct udf_fsck_node * node,union dscrptr ** dscrptr)3174 udf_read_node_dscr(struct udf_fsck_node *node, union dscrptr **dscrptr)
3175 {
3176 	*dscrptr = NULL;
3177 	return udf_read_dscr_virt(
3178 			udf_rw32(node->loc.loc.lb_num),
3179 			udf_rw16(node->loc.loc.part_num),
3180 			dscrptr);
3181 }
3182 
3183 
3184 static int
udf_extract_node_info(struct udf_fsck_node * node,union dscrptr * dscr,int be_quiet)3185 udf_extract_node_info(struct udf_fsck_node *node, union dscrptr *dscr,
3186 		int be_quiet)
3187 {
3188 	struct icb_tag       *icb = NULL;
3189 	struct file_entry    *fe  = NULL;
3190 	struct extfile_entry *efe = NULL;
3191 	int ad_type, error;
3192 
3193 	if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
3194 		fe = (struct file_entry *) dscr;
3195 		icb = &fe->icbtag;
3196 		node->declared.inf_len     = udf_rw64(fe->inf_len);
3197 		node->declared.obj_size    = udf_rw64(fe->inf_len);
3198 		node->declared.logblks_rec = udf_rw64(fe->logblks_rec);
3199 		node->link_count           = udf_rw16(fe->link_cnt);
3200 		node->unique_id            = udf_rw64(fe->unique_id);
3201 
3202 /* XXX FAULT INJECTION POINT XXX */
3203 //if (fe->unique_id == 33) { return ENOENT;}
3204 
3205 	}
3206 	if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
3207 		efe = (struct extfile_entry *) dscr;
3208 		icb = &efe->icbtag;
3209 		node->declared.inf_len     = udf_rw64(efe->inf_len);
3210 		node->declared.obj_size    = udf_rw64(efe->obj_size);
3211 		node->declared.logblks_rec = udf_rw64(efe->logblks_rec);
3212 		node->link_count           = udf_rw16(efe->link_cnt);
3213 		node->unique_id            = udf_rw64(efe->unique_id);
3214 		node->streamdir_loc = efe->streamdir_icb;
3215 		if (node->streamdir_loc.len)
3216 			node->fsck_flags |= FSCK_NODE_FLAG_HAS_STREAM_DIR;
3217 
3218 /* XXX FAULT INJECTION POINT XXX */
3219 //if (efe->unique_id == 0x891) { return ENOENT;}
3220 
3221 	}
3222 
3223 	if (!fe && !efe) {
3224 //printf("NOT REFERENCING AN FE/EFE!\n");
3225 		return ENOENT;
3226 	}
3227 
3228 	if (node->unique_id >= context.unique_id)
3229 		context.unique_id = node->unique_id+1;
3230 
3231 	ad_type = udf_rw16(icb->flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
3232 	if ((ad_type != UDF_ICB_INTERN_ALLOC) &&
3233 			(ad_type != UDF_ICB_SHORT_ALLOC) &&
3234 			(ad_type != UDF_ICB_LONG_ALLOC)) {
3235 		pwarn("%s : unknown allocation type\n",
3236 				udf_node_path(node));
3237 		return EINVAL;
3238 	}
3239 
3240 	bzero(&node->found, sizeof(node->found));
3241 	error = udf_process_file(dscr, udf_rw16(node->loc.loc.part_num), NULL,
3242 			AD_GATHER_STATS, (void *) &node->found);
3243 
3244 	switch (icb->file_type) {
3245 	case UDF_ICB_FILETYPE_RANDOMACCESS :
3246 	case UDF_ICB_FILETYPE_BLOCKDEVICE :
3247 	case UDF_ICB_FILETYPE_CHARDEVICE :
3248 	case UDF_ICB_FILETYPE_FIFO :
3249 	case UDF_ICB_FILETYPE_SOCKET :
3250 	case UDF_ICB_FILETYPE_SYMLINK :
3251 	case UDF_ICB_FILETYPE_REALTIME :
3252 		break;
3253 	default:
3254 		/* unknown or unsupported file type, TODO clearing? */
3255 		free(dscr);
3256 		pwarn("%s : specification violation, unknown file type %d\n",
3257 			udf_node_path(node), icb->file_type);
3258 		return ENOENT;
3259 	case UDF_ICB_FILETYPE_STREAMDIR :
3260 	case UDF_ICB_FILETYPE_DIRECTORY :
3261 		/* read in the directory contents */
3262 		error = udf_readin_file(dscr, udf_rw16(node->loc.loc.part_num),
3263 				&node->directory, NULL);
3264 
3265 /* XXX FAULT INJECTION POINT XXX */
3266 //if (dscr->efe.unique_id == 109) node->directory[125] = 0xff;
3267 //if (dscr->efe.unique_id == 310) memset(node->directory+1024, 0, 300);
3268 
3269 		if (error && !be_quiet) {
3270 			pwarn("%s : directory has read errors\n",
3271 				udf_node_path(node));
3272 			if (ask(0, "Directory could be fixed or cleared. "
3273 				   "Wipe defective directory")) {
3274 				return ENOENT;
3275 			}
3276 			udf_recursive_keep(node);
3277 			node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3278 		}
3279 		node->fsck_flags |= FSCK_NODE_FLAG_DIRECTORY;
3280 		error = udf_quick_check_fids(node, dscr);
3281 		if (error) {
3282 			if (!(node->fsck_flags & FSCK_NODE_FLAG_REPAIRDIR))
3283 				pwarn("%s : directory file entries need repair\n",
3284 					udf_node_path(node));
3285 			udf_recursive_keep(node);
3286 			node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3287 		}
3288 	}
3289 
3290 /* XXX FAULT INJECTION POINT XXX */
3291 //if (fe->unique_id == 0) node->link_count++;
3292 //if (efe->unique_id == 0) node->link_count++;
3293 //if (efe->unique_id == 772) { node->declared.inf_len += 205; node->declared.obj_size -= 0; }
3294 
3295 	return 0;
3296 }
3297 
3298 
3299 static void
udf_fixup_lengths_pass1(struct udf_fsck_node * node,union dscrptr * dscr)3300 udf_fixup_lengths_pass1(struct udf_fsck_node *node, union dscrptr *dscr)
3301 {
3302 	int64_t diff;
3303 
3304 	/* file length check */
3305 	diff = node->found.inf_len - node->declared.inf_len;
3306 	if (diff) {
3307 		pwarn("%s : recorded information length incorrect: "
3308 			"%" PRIu64 " instead of declared %" PRIu64 "\n",
3309 			udf_node_path(node),
3310 			node->found.inf_len, node->declared.inf_len);
3311 			node->declared.inf_len = node->found.inf_len;
3312 		udf_recursive_keep(node);
3313 		node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
3314 	}
3315 
3316 	/* recorded logical blocks count check */
3317 	diff = node->found.logblks_rec - node->declared.logblks_rec;
3318 	if (diff) {
3319 		pwarn("%s : logical blocks recorded incorrect: "
3320 		      "%" PRIu64 " instead of declared %" PRIu64 ", fixing\n",
3321 			udf_node_path(node),
3322 			node->found.logblks_rec, node->declared.logblks_rec);
3323 		node->declared.logblks_rec = node->found.logblks_rec;
3324 		udf_recursive_keep(node);
3325 		node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
3326 	}
3327 
3328 	/* tally object sizes for streamdirs */
3329 	node->found.obj_size = node->found.inf_len;
3330 	if (node->fsck_flags & FSCK_NODE_FLAG_STREAM_ENTRY) {
3331 		assert(node->parent);		/* streamdir itself */
3332 		if (node->parent->parent)
3333 			node->parent->parent->found.obj_size +=
3334 				node->found.inf_len;
3335 	}
3336 
3337 	/* check descriptor CRC length */
3338 	if (udf_rw16(dscr->tag.desc_crc_len) !=
3339 			udf_tagsize(dscr, 1) - sizeof(struct desc_tag)) {
3340 		pwarn("%s : node file descriptor CRC length mismatch; "
3341 			"%d declared, %zu\n",
3342 			udf_node_path(node), udf_rw16(dscr->tag.desc_crc_len),
3343 			udf_tagsize(dscr, 1) - sizeof(struct desc_tag));
3344 		udf_recursive_keep(node);
3345 		node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
3346 	}
3347 }
3348 
3349 
3350 static void
udf_node_pass1_add_entry(struct udf_fsck_node * node,struct fileid_desc * fid,struct dirent * dirent)3351 udf_node_pass1_add_entry(struct udf_fsck_node *node,
3352 		struct fileid_desc *fid, struct dirent *dirent)
3353 {
3354 	struct udf_fsck_node *leaf_node;
3355 	int entry;
3356 
3357 	/* skip deleted FID entries */
3358 	if (fid->file_char & UDF_FILE_CHAR_DEL)
3359 		return;
3360 
3361 	if (udf_rw32(fid->icb.loc.lb_num) == 0) {
3362 		pwarn("%s : FileID entry `%s` has invalid location\n",
3363 				udf_node_path(node), dirent->d_name);
3364 		udf_recursive_keep(node);
3365 		if (node->parent)
3366 			node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3367 		return;
3368 	}
3369 
3370 	/* increase parent link count */
3371 	if (fid->file_char & UDF_FILE_CHAR_PAR) {
3372 		if (node->parent)
3373 			node->parent->found_link_count++;
3374 		return;
3375 	}
3376 
3377 	/* lookup if we already know this node */
3378 	leaf_node = udf_node_lookup(&fid->icb);
3379 	if (leaf_node) {
3380 		/* got a hard link! */
3381 		leaf_node->found_link_count++;
3382 		return;
3383 	}
3384 
3385 	/* create new node */
3386 	leaf_node = udf_new_fsck_node(
3387 			node, &fid->icb, dirent->d_name);
3388 	if (node->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR)
3389 		leaf_node->fsck_flags |= FSCK_NODE_FLAG_STREAM_ENTRY;
3390 
3391 	TAILQ_INSERT_TAIL(&fs_nodes, leaf_node, next);
3392 	entry = udf_calc_node_hash(&fid->icb);
3393 	LIST_INSERT_HEAD(&fs_nodes_hash[entry], leaf_node, next_hash);
3394 }
3395 
3396 
3397 static void
udf_node_pass1_add_streamdir_entry(struct udf_fsck_node * node)3398 udf_node_pass1_add_streamdir_entry(struct udf_fsck_node *node)
3399 {
3400 	struct udf_fsck_node *leaf_node;
3401 	int entry;
3402 
3403 	/* check for recursion */
3404 	if (node->fsck_flags & FSCK_NODE_FLAG_STREAM) {
3405 		/* recursive streams are not allowed by spec */
3406 		pwarn("%s : specification violation, recursive stream dir\n",
3407 			udf_node_path(node));
3408 		udf_recursive_keep(node);
3409 		node->fsck_flags |= FSCK_NODE_FLAG_WIPE_STREAM_DIR;
3410 		return;
3411 	}
3412 
3413 	/* lookup if we already know this node */
3414 	leaf_node = udf_node_lookup(&node->streamdir_loc);
3415 	if (leaf_node) {
3416 		pwarn("%s : specification violation, hardlinked streamdir\n",
3417 			udf_node_path(leaf_node));
3418 		udf_recursive_keep(node);
3419 		node->fsck_flags |= FSCK_NODE_FLAG_WIPE_STREAM_DIR;
3420 		return;
3421 	}
3422 
3423 	/* create new node */
3424 	leaf_node = udf_new_fsck_node(
3425 			node, &node->streamdir_loc, strdup(""));
3426 	leaf_node->fsck_flags |= FSCK_NODE_FLAG_STREAM_DIR;
3427 
3428 	/* streamdirs have link count 0 : ECMA 4/14.9.6 */
3429 	leaf_node->found_link_count--;
3430 
3431 	/* insert in to lists */
3432 	TAILQ_INSERT_TAIL(&fs_nodes, leaf_node, next);
3433 	entry = udf_calc_node_hash(&node->streamdir_loc);
3434 	LIST_INSERT_HEAD(&fs_nodes_hash[entry], leaf_node, next_hash);
3435 }
3436 
3437 
3438 static int
udf_process_node_pass1(struct udf_fsck_node * node,union dscrptr * dscr)3439 udf_process_node_pass1(struct udf_fsck_node *node, union dscrptr *dscr)
3440 {
3441 	struct fileid_desc *fid;
3442 	struct dirent dirent;
3443 	struct charspec osta_charspec;
3444 	int64_t fpos, new_length, rest_len;
3445 	uint32_t fid_len;
3446 	uint8_t *bpos;
3447 	int isdir;
3448 	int error;
3449 
3450 	isdir = node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY;
3451 
3452 	/* keep link count */
3453 	node->found_link_count++;
3454 
3455 	if (isdir) {
3456 		assert(node->directory);
3457 		udf_rebuild_fid_stream(node, &new_length);
3458 		node->found.inf_len = new_length;
3459 		rest_len = new_length;
3460 	}
3461 
3462 	udf_fixup_lengths_pass1(node, dscr);
3463 
3464 	/* check UniqueID */
3465 	if (node->parent) {
3466 		if (node->fsck_flags & FSCK_NODE_FLAG_STREAM) {
3467 
3468 /* XXX FAULT INJECTION POINT XXX */
3469 //node->unique_id = 0xdeadbeefcafe;
3470 
3471 			if (node->unique_id != node->parent->unique_id) {
3472 				pwarn("%s : stream file/dir UniqueID mismatch "
3473 				      "with parent\n",
3474 						udf_node_path(node));
3475 				/* do the work here prematurely for our siblings */
3476 				udf_recursive_keep(node);
3477 				node->unique_id = node->parent->unique_id;
3478 				node->fsck_flags |= FSCK_NODE_FLAG_COPY_PARENT_ID |
3479 					FSCK_NODE_FLAG_DIRTY;
3480 				assert(node->parent);
3481 				node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3482 			}
3483 		} else if (node->unique_id < 16) {
3484 			pwarn("%s : file has bad UniqueID\n",
3485 					udf_node_path(node));
3486 			udf_recursive_keep(node);
3487 			node->fsck_flags |= FSCK_NODE_FLAG_NEW_UNIQUE_ID;
3488 			assert(node->parent);
3489 			node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3490 		}
3491 	} else {
3492 		/* rootdir */
3493 		if (node->unique_id != 0) {
3494 			pwarn("%s : has bad UniqueID, has to be zero\n",
3495 					udf_node_path(node));
3496 			udf_recursive_keep(node);
3497 			node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
3498 		}
3499 	}
3500 
3501 	/* add streamdir if present */
3502 	if (node->fsck_flags & FSCK_NODE_FLAG_HAS_STREAM_DIR)
3503 		udf_node_pass1_add_streamdir_entry(node);
3504 
3505 	/* add all children */
3506 	if (isdir) {
3507 		node->fsck_flags |= FSCK_NODE_FLAG_PAR_NOT_FOUND;
3508 		rest_len = node->found.inf_len;
3509 
3510 		/* walk through all our FIDs in the directory stream */
3511 		bpos = node->directory;
3512 		fpos = 0;
3513 		while (rest_len > 0) {
3514 			fid = (struct fileid_desc *) bpos;
3515 			fid_len = udf_fidsize(fid);
3516 
3517 			/* get printable name */
3518 			memset(&dirent, 0, sizeof(dirent));
3519 			udf_osta_charset(&osta_charspec);
3520 			udf_to_unix_name(dirent.d_name, NAME_MAX,
3521 				(char *) fid->data + udf_rw16(fid->l_iu), fid->l_fi,
3522 				&osta_charspec);
3523 			dirent.d_namlen = strlen(dirent.d_name);
3524 
3525 			/* '..' has no name, so provide one */
3526 			if (fid->file_char & UDF_FILE_CHAR_PAR) {
3527 				strcpy(dirent.d_name, "..");
3528 				node->fsck_flags &= ~FSCK_NODE_FLAG_PAR_NOT_FOUND;
3529 			}
3530 
3531 			udf_node_pass1_add_entry(node, fid, &dirent);
3532 
3533 			fpos += fid_len;
3534 			bpos += fid_len;
3535 			rest_len -= fid_len;
3536 		}
3537 	}
3538 
3539 	error = udf_process_file(dscr, udf_rw16(node->loc.loc.part_num), NULL,
3540 			AD_CHECK_USED, node);
3541 	if (error) {
3542 		pwarn("%s : internal error: checking for being allocated shouldn't fail\n",
3543 			udf_node_path(node));
3544 		return EINVAL;
3545 	}
3546 	/* file/directory is OK and referenced as its size won't change */
3547 	error = udf_process_file(dscr, udf_rw16(node->loc.loc.part_num), NULL,
3548 			AD_MARK_AS_USED, NULL);
3549 	if (error) {
3550 		pwarn("%s : internal error: marking allocated shouldn't fail\n",
3551 			udf_node_path(node));
3552 		return EINVAL;
3553 	}
3554 	(void) fpos;
3555 	return 0;
3556 }
3557 
3558 
3559 static void
udf_node_pass3_repairdir(struct udf_fsck_node * node,union dscrptr * dscr)3560 udf_node_pass3_repairdir(struct udf_fsck_node *node, union dscrptr *dscr)
3561 {
3562 	struct fileid_desc *fid, *last_empty_fid;
3563 	struct udf_fsck_node *file_node;
3564 	struct udf_fsck_fid_context fid_context;
3565 	struct dirent dirent;
3566 	struct charspec osta_charspec;
3567 	int64_t fpos, rest_len;
3568 	uint32_t fid_len;
3569 	uint8_t *bpos;
3570 	int parent_missing;
3571 	int error;
3572 
3573 	pwarn("%s : fixing up directory\n", udf_node_path(node));
3574 	assert(node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY);
3575 
3576 	rest_len = node->found.inf_len;
3577 
3578 	udf_osta_charset(&osta_charspec);
3579 	bpos = node->directory;
3580 	fpos = 0;
3581 	parent_missing = (node->fsck_flags & FSCK_NODE_FLAG_PAR_NOT_FOUND)? 1:0;
3582 
3583 	last_empty_fid = NULL;
3584 	while (rest_len > 0) {
3585 		fid = (struct fileid_desc *) bpos;
3586 		fid_len = udf_fidsize(fid);
3587 
3588 		/* get printable name */
3589 		memset(&dirent, 0, sizeof(dirent));
3590 		udf_to_unix_name(dirent.d_name, NAME_MAX,
3591 			(char *) fid->data + udf_rw16(fid->l_iu), fid->l_fi,
3592 			&osta_charspec);
3593 		dirent.d_namlen = strlen(dirent.d_name);
3594 
3595 		/* '..' has no name, so provide one */
3596 		if (fid->file_char & UDF_FILE_CHAR_PAR) {
3597 			strcpy(dirent.d_name, "..");
3598 		}
3599 
3600 		/* only look up when not deleted */
3601 		file_node = NULL;
3602 		if ((fid->file_char & UDF_FILE_CHAR_DEL) == 0)
3603 			file_node = udf_node_lookup(&fid->icb);
3604 
3605 		/* if found */
3606 		if (file_node) {
3607 			/* delete files which couldn't be found */
3608 			if (file_node && (file_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)) {
3609 				fid->file_char |= UDF_FILE_CHAR_DEL;
3610 				memset(&fid->icb, 0, sizeof(struct long_ad));
3611 			}
3612 
3613 			/* fix up FID UniqueID errors */
3614 			if (fid->icb.longad_uniqueid != file_node->unique_id)
3615 				fid->icb.longad_uniqueid = udf_rw64(file_node->unique_id);
3616 		} else {
3617 			/* just mark it deleted if not found */
3618 			fid->file_char |= UDF_FILE_CHAR_DEL;
3619 		}
3620 
3621 		if (fid->file_char & UDF_FILE_CHAR_DEL) {
3622 			memset(&fid->icb, 0 , sizeof(struct long_ad));
3623 			if (context.dscrver == 2) {
3624 				uint8_t *cpos;
3625 				/* compression IDs are preserved */
3626 				cpos = (fid->data + udf_rw16(fid->l_iu));
3627 				if (*cpos == 254)
3628 					*cpos = 8;
3629 				if (*cpos == 255)
3630 					*cpos = 16;
3631 			}
3632 		}
3633 
3634 		fpos += fid_len;
3635 		bpos += fid_len;
3636 		rest_len -= fid_len;
3637 		assert(rest_len >= 0);
3638 	}
3639 	if (parent_missing) {
3640 		/* this should be valid or we're in LALA land */
3641 		assert(last_empty_fid);
3642 		pwarn("%s : implementation limit, can't fix up missing parent node yet!\n",
3643 			udf_node_path(node));
3644 	}
3645 
3646 	node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
3647 
3648 	fid_context.fid_offset = 0;
3649 	fid_context.data_left = node->found.inf_len;
3650 	error = udf_process_file(dscr, context.fids_part,
3651 			&node->directory,
3652 			AD_ADJUST_FIDS | AD_SAVE_FILE,
3653 			&fid_context);
3654 	if (error)
3655 		pwarn("Failed to write out directory!\n");
3656 	(void) fpos;
3657 }
3658 
3659 
3660 static void
udf_node_pass3_writeout_update(struct udf_fsck_node * node,union dscrptr * dscr)3661 udf_node_pass3_writeout_update(struct udf_fsck_node *node, union dscrptr *dscr)
3662 {
3663 	struct file_entry    *fe  = NULL;
3664 	struct extfile_entry *efe = NULL;
3665 	int crc_len, error;
3666 
3667 	vat_writeout = 1;
3668 	if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
3669 		fe = (struct file_entry *) dscr;
3670 		fe->inf_len      = udf_rw64(node->declared.inf_len);
3671 		fe->logblks_rec  = udf_rw64(node->declared.logblks_rec);
3672 		fe->link_cnt     = udf_rw16(node->link_count);
3673 		fe->unique_id    = udf_rw64(node->unique_id);
3674 	}
3675 	if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
3676 		efe = (struct extfile_entry *) dscr;
3677 		efe->inf_len     = udf_rw64(node->declared.inf_len);
3678 		efe->obj_size    = udf_rw64(node->declared.obj_size);
3679 		efe->logblks_rec = udf_rw64(node->declared.logblks_rec);
3680 		efe->link_cnt    = udf_rw16(node->link_count);
3681 		efe->unique_id   = udf_rw64(node->unique_id);
3682 		/* streamdir directly cleared in dscr */
3683 	}
3684 
3685 	/* fixup CRC length (if needed) */
3686 	crc_len = udf_tagsize(dscr, 1) - sizeof(struct desc_tag);
3687 	dscr->tag.desc_crc_len = udf_rw16(crc_len);
3688 
3689 	pwarn("%s : updating node\n", udf_node_path(node));
3690 	error = udf_write_dscr_virt(dscr, udf_rw32(node->loc.loc.lb_num),
3691 			udf_rw16(node->loc.loc.part_num), 1);
3692 	udf_shadow_VAT_in_use(&node->loc);
3693 	if (error)
3694 		pwarn("%s failed\n", __func__);
3695 }
3696 
3697 
3698 static void
udf_create_new_space_bitmaps_and_reset_freespace(void)3699 udf_create_new_space_bitmaps_and_reset_freespace(void)
3700 {
3701 	struct space_bitmap_desc *sbd, *new_sbd;
3702 	struct part_desc *part;
3703 	struct part_hdr_desc *phd;
3704 	uint32_t bitmap_len, bitmap_lb, bitmap_numlb;
3705 	uint32_t cnt;
3706 	int i, p, dscr_size;
3707 	int error;
3708 
3709 	/* copy recorded freespace info and clear counters */
3710 	for (i = 0; i < UDF_PARTITIONS; i++) {
3711 		recorded_part_free[i] = context.part_free[i];
3712 		context.part_free[i]  = context.part_size[i];
3713 	}
3714 
3715 	/* clone existing bitmaps */
3716 	for (i = 0; i < UDF_PARTITIONS; i++) {
3717 		sbd = context.part_unalloc_bits[i];
3718 		recorded_part_unalloc_bits[i] = sbd;
3719 		if (sbd == NULL)
3720 			continue;
3721 		dscr_size = udf_tagsize((union dscrptr *) sbd,
3722 				context.sector_size);
3723 		new_sbd = calloc(1, dscr_size);
3724 		memcpy(new_sbd, sbd, sizeof(struct space_bitmap_desc)-1);
3725 
3726 		/* fill space with 0xff to indicate free */
3727 		for (cnt = 0; cnt < udf_rw32(sbd->num_bytes); cnt++)
3728 			new_sbd->data[cnt] = 0xff;
3729 
3730 		context.part_unalloc_bits[i] = new_sbd;
3731 	}
3732 
3733 	/* allocate the space bitmaps themselves (normally one) */
3734 	for (i = 0; i < UDF_PARTITIONS; i++) {
3735 		part = context.partitions[i];
3736 		if (!part)
3737 			continue;
3738 
3739 		phd = &part->pd_part_hdr;
3740 		bitmap_len = udf_rw32(phd->unalloc_space_bitmap.len);
3741 		bitmap_lb  = udf_rw32(phd->unalloc_space_bitmap.lb_num);
3742 		if (bitmap_len == 0)
3743 			continue;
3744 
3745 		bitmap_numlb = udf_bytes_to_sectors(bitmap_len);
3746 		sbd = context.part_unalloc_bits[i];
3747 		assert(sbd);
3748 
3749 		udf_mark_allocated(bitmap_lb, context.vtop[i], bitmap_numlb);
3750 	}
3751 
3752 	/* special case for metadata partition */
3753 	if (context.format_flags & FORMAT_META) {
3754 		i = context.metadata_part;
3755 		p = context.vtop[i];
3756 		assert(context.vtop_tp[i] == UDF_VTOP_TYPE_META);
3757 		error = udf_process_file((union dscrptr *) context.meta_file,
3758 			p, NULL, AD_MARK_AS_USED, NULL);
3759 		error = udf_process_file((union dscrptr *) context.meta_mirror,
3760 			p, NULL, AD_MARK_AS_USED, NULL);
3761 		if (context.meta_bitmap) {
3762 			error = udf_process_file(
3763 				(union dscrptr *) context.meta_bitmap,
3764 				p, NULL, AD_MARK_AS_USED, NULL);
3765 			assert(error == 0);
3766 		}
3767 	}
3768 
3769 	/* mark fsd allocation ! */
3770 	udf_mark_allocated(udf_rw32(context.fileset_desc->tag.tag_loc),
3771 		context.metadata_part, 1);
3772 }
3773 
3774 
3775 static void
udf_shadow_VAT_in_use(struct long_ad * loc)3776 udf_shadow_VAT_in_use(struct long_ad *loc)
3777 {
3778 	uint32_t i;
3779 	uint8_t *vat_pos, *shadow_vat_pos;
3780 
3781 	if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
3782 		return;
3783 
3784 	i = udf_rw32(loc->loc.lb_num);
3785 	vat_pos = context.vat_contents + context.vat_start + i*4;
3786 	shadow_vat_pos = shadow_vat_contents + context.vat_start + i*4;
3787 	/* keeping endian */
3788 	*(uint32_t *) shadow_vat_pos = *(uint32_t *) vat_pos;
3789 }
3790 
3791 
3792 static void
udf_create_shadow_VAT(void)3793 udf_create_shadow_VAT(void)
3794 {
3795 	struct long_ad fsd_loc;
3796 	uint32_t  vat_entries, i;
3797 	uint8_t *vat_pos;
3798 
3799 	if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
3800 		return;
3801 
3802 	shadow_vat_contents = calloc(1, context.vat_allocated);
3803 	assert(shadow_vat_contents);
3804 	memcpy(shadow_vat_contents, context.vat_contents, context.vat_size);
3805 
3806 	vat_entries = (context.vat_size - context.vat_start)/4;
3807 	for (i = 0; i < vat_entries; i++) {
3808 		vat_pos = shadow_vat_contents + context.vat_start + i*4;
3809 		*(uint32_t *) vat_pos = udf_rw32(0xffffffff);
3810 	}
3811 
3812 	/*
3813 	 * Record our FSD in this shadow VAT since its the only one outside
3814 	 * the nodes.
3815 	 */
3816 	memset(&fsd_loc, 0, sizeof(struct long_ad));
3817 	fsd_loc.loc.lb_num = context.fileset_desc->tag.tag_loc;
3818 	udf_shadow_VAT_in_use(&fsd_loc);
3819 }
3820 
3821 
3822 static void
udf_check_shadow_VAT(void)3823 udf_check_shadow_VAT(void)
3824 {
3825 	uint32_t vat_entries, i;
3826 	uint8_t *vat_pos, *shadow_vat_pos;
3827 	int difference = 0;
3828 
3829 	if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
3830 		return;
3831 
3832 	vat_entries = (context.vat_size - context.vat_start)/4;
3833 	for (i = 0; i < vat_entries; i++) {
3834 		vat_pos = context.vat_contents + context.vat_start + i*4;
3835 		shadow_vat_pos = shadow_vat_contents + context.vat_start + i*4;
3836 		if (*(uint32_t *) vat_pos != *(uint32_t *) shadow_vat_pos) {
3837 			difference++;
3838 		}
3839 	}
3840 	memcpy(context.vat_contents, shadow_vat_contents, context.vat_size);
3841 	if (difference) {
3842 		if (!preen)
3843 			printf("\t\t");
3844 		pwarn("%d unused VAT entries cleaned\n", difference);
3845 		vat_writeout = 1;
3846 	}
3847 }
3848 
3849 
3850 static int
udf_check_directory_tree(void)3851 udf_check_directory_tree(void)
3852 {
3853 	union dscrptr *dscr;
3854 	struct udf_fsck_node *root_node, *sys_stream_node;
3855 	struct udf_fsck_node *cur_node, *next_node;
3856 	struct long_ad root_icb, sys_stream_icb;
3857 	bool dont_repair;
3858 	int entry, error;
3859 
3860 	assert(TAILQ_EMPTY(&fs_nodes));
3861 
3862 	/* (re)init queues and hash lists */
3863 	TAILQ_INIT(&fs_nodes);
3864 	TAILQ_INIT(&fsck_overlaps);
3865 	for (int i = 0; i < HASH_HASHSIZE; i++)
3866 		LIST_INIT(&fs_nodes_hash[i]);
3867 
3868 	/* create a new empty copy of the space bitmaps */
3869 	udf_create_new_space_bitmaps_and_reset_freespace();
3870 	udf_create_shadow_VAT();
3871 
3872 	/* start from the root */
3873 	root_icb       = context.fileset_desc->rootdir_icb;
3874 	sys_stream_icb = context.fileset_desc->streamdir_icb;
3875 
3876 	root_node = udf_new_fsck_node(NULL, &root_icb, strdup(""));
3877 	assert(root_node);
3878 	TAILQ_INSERT_TAIL(&fs_nodes, root_node, next);
3879 	entry = udf_calc_node_hash(&root_node->loc);
3880 	LIST_INSERT_HEAD(&fs_nodes_hash[entry], root_node, next_hash);
3881 
3882 	sys_stream_node = NULL;
3883 	if (sys_stream_icb.len) {
3884 		sys_stream_node = udf_new_fsck_node(NULL, &sys_stream_icb, strdup("#"));
3885 		assert(sys_stream_node);
3886 		sys_stream_node->fsck_flags |= FSCK_NODE_FLAG_STREAM_DIR;
3887 
3888 		TAILQ_INSERT_TAIL(&fs_nodes, sys_stream_node, next);
3889 		entry = udf_calc_node_hash(&sys_stream_node->loc);
3890 		LIST_INSERT_HEAD(&fs_nodes_hash[entry], sys_stream_node, next_hash);
3891 	}
3892 
3893 	/* pass 1 */
3894 	if (!preen)
3895 		printf("\tPass 1, reading in directory trees\n");
3896 
3897 	context.unique_id = MAX(0x10, context.unique_id);
3898 	TAILQ_FOREACH(cur_node, &fs_nodes, next) {
3899 		/* read in node */
3900 		error = udf_read_node_dscr(cur_node, &dscr);
3901 		if (!error)
3902 			error = udf_extract_node_info(cur_node, dscr, 0);
3903 		if (error) {
3904 			pwarn("%s : invalid reference or bad descriptor, DELETING\n",
3905 				udf_node_path(cur_node));
3906 			udf_recursive_keep(cur_node);
3907 			cur_node->fsck_flags |= FSCK_NODE_FLAG_NOTFOUND;
3908 			if (cur_node->parent) {
3909 				if (cur_node->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR)
3910 					cur_node->parent->fsck_flags |=
3911 						FSCK_NODE_FLAG_WIPE_STREAM_DIR;
3912 				else
3913 					cur_node->parent->fsck_flags |=
3914 						FSCK_NODE_FLAG_REPAIRDIR;
3915 				;
3916 			}
3917 			free(dscr);
3918 			continue;
3919 		}
3920 
3921 		if (print_info) {
3922 			pwarn("Processing %s\n", udf_node_path(cur_node));
3923 			print_info = 0;
3924 		}
3925 
3926 		/* directory found in stream directory? */
3927 		if (cur_node->parent &&
3928 			(cur_node->parent->fsck_flags & FSCK_NODE_FLAG_STREAM_DIR) &&
3929 			(cur_node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY))
3930 		{
3931 			pwarn("%s : specification violation, directory in stream directory\n",
3932 				udf_node_path(cur_node));
3933 			if (ask(0, "Clear directory")) {
3934 				udf_recursive_keep(cur_node);
3935 				cur_node->fsck_flags |= FSCK_NODE_FLAG_NOTFOUND;
3936 				cur_node->parent->fsck_flags |=
3937 					FSCK_NODE_FLAG_REPAIRDIR;
3938 				continue;
3939 			}
3940 		}
3941 		error = udf_process_node_pass1(cur_node, dscr);
3942 		free(dscr);
3943 
3944 		if (error)
3945 			return error;
3946 	}
3947 
3948 	/* pass 1b, if there is overlap, find matching pairs */
3949 	dont_repair = false;
3950 	if (!TAILQ_EMPTY(&fsck_overlaps)) {
3951 		struct udf_fsck_overlap *overlap;
3952 
3953 		dont_repair = true;
3954 		pwarn("*** Overlaps detected! rescanning tree for matching pairs ***\n");
3955 		TAILQ_FOREACH(cur_node, &fs_nodes, next) {
3956 			if (cur_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)
3957 				continue;
3958 
3959 			error = udf_read_node_dscr(cur_node, &dscr);
3960 			/* should not fail differently */
3961 
3962 			if (print_info) {
3963 				pwarn("Processing %s\n", udf_node_path(cur_node));
3964 				print_info = 0;
3965 			}
3966 
3967 			error = udf_process_file(
3968 					dscr,
3969 					udf_rw16(cur_node->loc.loc.part_num),
3970 					NULL,
3971 					AD_FIND_OVERLAP_PAIR,
3972 					(void *) cur_node);
3973 			/* shouldn't fail */
3974 
3975 			free(dscr);
3976 		}
3977 		TAILQ_FOREACH(overlap, &fsck_overlaps, next) {
3978 			pwarn("%s :overlaps with %s\n",
3979 				udf_node_path(overlap->node),
3980 				udf_node_path(overlap->node2));
3981 		}
3982 		if (!preen)
3983 			printf("\n");
3984 		pwarn("*** The following files/directories need to be copied/evacuated:\n");
3985 		TAILQ_FOREACH(cur_node, &fs_nodes, next) {
3986 			if (cur_node->fsck_flags & FSCK_NODE_FLAG_OVERLAP) {
3987 				pwarn("%s : found OVERLAP, evacuate\n",
3988 					udf_node_path(cur_node));
3989 			}
3990 		}
3991 	}
3992 	if (dont_repair) {
3993 		if (!preen)
3994 			printf("\n");
3995 		pwarn("*** Skipping further repair, only updating free space map if needed\n");
3996 		pwarn("*** After deep copying and/or evacuation of these files/directories,\n");
3997 		pwarn("*** remove files/directories and re-run fsck_udf\n");
3998 		error = udf_prepare_writing();
3999 		if (error)
4000 			return error;
4001 
4002 		udf_update_lvintd(UDF_INTEGRITY_OPEN);
4003 		return 0;
4004 	}
4005 
4006 	/* pass 2a, checking link counts, object sizes and count files/dirs */
4007 	if (!preen)
4008 		printf("\n\tPass 2, checking link counts, object sizes, stats and cleaning up\n");
4009 
4010 	TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) {
4011 		/* not sane to process files/directories that are not found */
4012 		if (cur_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)
4013 			continue;
4014 
4015 		/* shadow VAT */
4016 		udf_shadow_VAT_in_use(&cur_node->loc);
4017 
4018 		/* link counts */
4019 		if (cur_node->found_link_count != cur_node->link_count) {
4020 			pwarn("%s : link count incorrect; "
4021 			      "%u instead of declared %u : FIXED\n",
4022 				udf_node_path(cur_node),
4023 				cur_node->found_link_count, cur_node->link_count);
4024 			cur_node->link_count = cur_node->found_link_count;
4025 			udf_recursive_keep(cur_node);
4026 			cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
4027 		}
4028 
4029 		/* object sizes */
4030 		if (cur_node->declared.obj_size != cur_node->found.obj_size) {
4031 			pwarn("%s : recorded object size incorrect; "
4032 			      "%" PRIu64 " instead of declared %" PRIu64 "\n",
4033 				udf_node_path(cur_node),
4034 				cur_node->found.obj_size, cur_node->declared.obj_size);
4035 			cur_node->declared.obj_size = cur_node->found.obj_size;
4036 			udf_recursive_keep(cur_node);
4037 			cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
4038 		}
4039 
4040 		/* XXX TODO XXX times */
4041 		/* XXX TODO XXX extended attributes location for UDF < 1.50 */
4042 
4043 		/* validity of UniqueID check */
4044 		if (cur_node->parent) {
4045 			if (cur_node->fsck_flags & FSCK_NODE_FLAG_NEW_UNIQUE_ID) {
4046 				pwarn("%s : assigning new UniqueID\n",
4047 					udf_node_path(cur_node));
4048 				cur_node->unique_id = udf_rw64(context.unique_id);
4049 				udf_advance_uniqueid();
4050 				udf_recursive_keep(cur_node);
4051 				cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
4052 				if (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY)
4053 					cur_node->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
4054 				cur_node->parent->fsck_flags |= FSCK_NODE_FLAG_REPAIRDIR;
4055 			}
4056 			if (cur_node->fsck_flags & FSCK_NODE_FLAG_COPY_PARENT_ID) {
4057 				/* work already done but make note to operator */
4058 				pwarn("%s : fixing stream UniqueID to match parent\n",
4059 					udf_node_path(cur_node));
4060 			}
4061 		} else {
4062 			if (cur_node->unique_id != 0) {
4063 				pwarn("%s : bad UniqueID, zeroing\n",
4064 						udf_node_path(cur_node));
4065 				cur_node->unique_id = 0;
4066 				cur_node->fsck_flags |=
4067 					FSCK_NODE_FLAG_DIRTY | FSCK_NODE_FLAG_REPAIRDIR;
4068 			}
4069 		}
4070 
4071 		/* keep nodes in a repairing dir */
4072 		if (cur_node->parent)
4073 			if (cur_node->parent->fsck_flags & FSCK_NODE_FLAG_REPAIRDIR)
4074 				cur_node->fsck_flags |= FSCK_NODE_FLAG_KEEP;
4075 
4076 		/* stream directories and files in it are not included */
4077 		if (!(cur_node->fsck_flags & FSCK_NODE_FLAG_STREAM)) {
4078 			/* files / directories counting */
4079 			int link_count = cur_node->found_link_count;
4080 
4081 			/* stream directories don't count as link ECMA 4/14.9.6 */
4082 			if (cur_node->fsck_flags & FSCK_NODE_FLAG_HAS_STREAM_DIR)
4083 				link_count--;
4084 
4085 			if (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRECTORY)
4086 				context.num_directories++;
4087 			else
4088 				context.num_files += link_count;
4089 			;
4090 		}
4091 	}
4092 
4093 	/* pass 2b, cleaning */
4094 	open_integrity = 0;
4095 	TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) {
4096 		/* can we remove the node? (to save memory) */
4097 		if (FSCK_NODE_FLAG_OK(cur_node->fsck_flags)) {
4098 			TAILQ_REMOVE(&fs_nodes, cur_node, next);
4099 			LIST_REMOVE(cur_node, next_hash);
4100 			free(cur_node->directory);
4101 			bzero(cur_node, sizeof(struct udf_fsck_node));
4102 			free(cur_node);
4103 		} else {
4104 			/* else keep erroring node */
4105 			open_integrity = 1;
4106 		}
4107 	}
4108 
4109 	if (!preen)
4110 		printf("\n\tPreparing disc for writing\n");
4111 	error = udf_prepare_writing();
4112 	if (error)
4113 		return error;
4114 
4115 	if (open_integrity)
4116 		udf_update_lvintd(UDF_INTEGRITY_OPEN);
4117 
4118 	/* pass 3 */
4119 	if (!preen)
4120 		printf("\n\tPass 3, fix errors\n");
4121 
4122 	TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) {
4123 		/* not sane to process files/directories that are not found */
4124 		if (cur_node->fsck_flags & FSCK_NODE_FLAG_NOTFOUND)
4125 			continue;
4126 
4127 		/* only interested in bad nodes */
4128 		if (FSCK_NODE_FLAG_OK(cur_node->fsck_flags))
4129 			continue;
4130 
4131 		error = udf_read_node_dscr(cur_node, &dscr);
4132 		/* should not fail differently */
4133 
4134 		/* repair directories */
4135 		if (cur_node->fsck_flags & FSCK_NODE_FLAG_REPAIRDIR)
4136 			udf_node_pass3_repairdir(cur_node, dscr);
4137 
4138 		/* remove invalid stream directories */
4139 		if (cur_node->fsck_flags & FSCK_NODE_FLAG_WIPE_STREAM_DIR) {
4140 			assert(udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY);
4141 			bzero(&dscr->efe.streamdir_icb, sizeof(struct long_ad));
4142 			cur_node->fsck_flags |= FSCK_NODE_FLAG_DIRTY;
4143 		}
4144 
4145 		if (cur_node->fsck_flags & FSCK_NODE_FLAG_DIRTY)
4146 			udf_node_pass3_writeout_update(cur_node, dscr);
4147 		free(dscr);
4148 	}
4149 	udf_check_shadow_VAT();
4150 
4151 	return 0;
4152 }
4153 
4154 
4155 static void
udf_cleanup_after_check(void)4156 udf_cleanup_after_check(void)
4157 {
4158 	struct udf_fsck_node *cur_node, *next_node;
4159 
4160 	/* XXX yes, there are some small memory leaks here */
4161 
4162 	/* clean old node info from previous checks */
4163 	TAILQ_FOREACH_SAFE(cur_node, &fs_nodes, next, next_node) {
4164 		TAILQ_REMOVE(&fs_nodes, cur_node, next);
4165 		LIST_REMOVE(cur_node, next_hash);
4166 		free(cur_node->directory);
4167 		free(cur_node);
4168 	}
4169 
4170 	/* free partition related info */
4171 	for (int i = 0; i < UDF_PARTITIONS; i++) {
4172 		free(context.partitions[i]);
4173 		free(context.part_unalloc_bits[i]);
4174 		free(context.part_freed_bits[i]);
4175 	}
4176 
4177 	/* only free potentional big blobs */
4178 	free(context.vat_contents);
4179 	free(context.lvint_history);
4180 
4181 	free(shadow_vat_contents);
4182 	shadow_vat_contents = NULL;
4183 }
4184 
4185 
4186 static int
checkfilesys(char * given_dev)4187 checkfilesys(char *given_dev)
4188 {
4189 	struct mmc_trackinfo ti;
4190 	int open_flags;
4191 	int error;
4192 
4193 	udf_init_create_context();
4194 	context.app_name         = "*NetBSD UDF";
4195 	context.app_version_main = APP_VERSION_MAIN;
4196 	context.app_version_sub  = APP_VERSION_SUB;
4197 	context.impl_name        = IMPL_NAME;
4198 
4199 	emul_mmc_profile  =  -1;	/* invalid->no emulation	*/
4200 	emul_packetsize   =   1;	/* reasonable default		*/
4201 	emul_sectorsize   = 512;	/* minimum allowed sector size	*/
4202 	emul_size	  =   0;	/* empty			*/
4203 
4204 	if (!preen)
4205 		pwarn("** Checking UDF file system on %s\n", given_dev);
4206 
4207 	/* reset sticky flags */
4208 	rdonly = rdonly_flag;
4209 	undo_opening_session = 0;	/* trying to undo opening of last crippled session */
4210 	vat_writeout = 0;		/* to write out the VAT anyway */
4211 
4212 	/* open disc device or emulated file */
4213 	open_flags = rdonly ? O_RDONLY : O_RDWR;
4214 	if (udf_opendisc(given_dev, open_flags)) {
4215 		udf_closedisc();
4216 		warnx("can't open %s", given_dev);
4217 		return FSCK_EXIT_CHECK_FAILED;
4218 	}
4219 
4220 	if (!preen)
4221 		pwarn("** Phase 1 - discovering format from disc\n\n");
4222 
4223 	/* check if it is an empty disc or no disc in present */
4224 	ti.tracknr = mmc_discinfo.first_track;
4225 	error = udf_update_trackinfo(&ti);
4226 	if (error || (ti.flags & MMC_TRACKINFO_BLANK)) {
4227 		/* no use erroring out */
4228 		pwarn("Empty disc\n");
4229 		return FSCK_EXIT_OK;
4230 	}
4231 
4232 	context.format_flags = 0;
4233 	if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL)
4234 		context.format_flags |= FORMAT_SEQUENTIAL;
4235 
4236 	if ((context.format_flags & FORMAT_SEQUENTIAL) &&
4237 		    ((mmc_discinfo.disc_state == MMC_STATE_CLOSED) ||
4238 		     (mmc_discinfo.disc_state == MMC_STATE_FULL))) {
4239 		pwarn("Disc is closed or full, can't modify disc\n");
4240 		rdonly = 1;
4241 	}
4242 
4243 	if (target_session) {
4244 		context.create_new_session = 1;
4245 		if (target_session < 0)
4246 			target_session += mmc_discinfo.num_sessions;
4247 	} else {
4248 		target_session = mmc_discinfo.num_sessions;
4249 		if (mmc_discinfo.last_session_state == MMC_STATE_EMPTY)
4250 			target_session--;
4251 	}
4252 
4253 	error = udf_get_anchors();
4254 	if (error) {
4255 		udf_closedisc();
4256 		pwarn("Failed to retrieve anchors; can't check file system\n");
4257 		return FSCK_EXIT_CHECK_FAILED;
4258 	}
4259 
4260 	udf_check_vrs9660();
4261 
4262 	/* get both VRS areas */
4263 	error = udf_check_VDS_areas();
4264 	if (error) {
4265 		udf_closedisc();
4266 		pwarn("Failure reading volume descriptors, disc might be toast\n");
4267 		return FSCK_EXIT_CHECK_FAILED;
4268 	}
4269 
4270 	if (udf_rw32(context.logvol_integrity->integrity_type) ==
4271 		UDF_INTEGRITY_CLOSED) {
4272 		if (!force) {
4273 			pwarn("** File system is clean; not checking\n");
4274 			return FSCK_EXIT_OK;
4275 		}
4276 		pwarn("** File system is already clean\n");
4277 		if (!preen)
4278 			pwarn("\n");
4279 	} else {
4280 		pwarn("** File system not closed properly\n");
4281 		if (!preen)
4282 			printf("\n");
4283 	}
4284 
4285 	/*
4286 	 * Only now read in free/unallocated space bitmap. If it reads in fine
4287 	 * it doesn't mean its contents is valid though. Sets partition
4288 	 * lengths too.
4289 	 */
4290 	error = udf_readin_partitions_free_space();
4291 	if (error) {
4292 		pwarn("Error during free space bitmap reading\n");
4293 		udf_update_lvintd(UDF_INTEGRITY_OPEN);
4294 	}
4295 
4296 	if (!preen)
4297 		pwarn("** Phase 2 - walking directory tree\n");
4298 
4299 	udf_suspend_writing();
4300 	error = udf_check_directory_tree();
4301 	if (error) {
4302 		if ((!rdonly) && ask(0, "Write out modifications made until now"))
4303 			udf_allow_writing();
4304 		else
4305 			pwarn("** Aborting repair, not modifying disc\n");
4306 		udf_closedisc();
4307 		return FSCK_EXIT_CHECK_FAILED;
4308 	}
4309 
4310 	if (!preen)
4311 		pwarn("\n** Phase 3 - closing volume if needed\n\n");
4312 
4313 /* XXX FAULT INJECTION POINT XXX */
4314 //udf_update_lvintd(UDF_INTEGRITY_OPEN);
4315 
4316 	if (error && rdonly) {
4317 		pwarn("** Aborting repair, nothing written, disc marked read-only\n");
4318 	} else {
4319 		error = udf_close_volume();
4320 	}
4321 
4322 	udf_closedisc();
4323 
4324 	if (error)
4325 		return FSCK_EXIT_CHECK_FAILED;
4326 	return FSCK_EXIT_OK;
4327 }
4328 
4329 
4330 static void
usage(void)4331 usage(void)
4332 {
4333     	(void)fprintf(stderr, "Usage: %s [-fHnpSsy] file-system ... \n",
4334 	    getprogname());
4335 	exit(FSCK_EXIT_USAGE);
4336 }
4337 
4338 
4339 static void
got_siginfo(int signo)4340 got_siginfo(int signo)
4341 {
4342 	print_info = 1;
4343 }
4344 
4345 
4346 int
main(int argc,char ** argv)4347 main(int argc, char **argv)
4348 {
4349 	int ret = FSCK_EXIT_OK, erg;
4350 	int ch;
4351 
4352 	while ((ch = getopt(argc, argv, "ps:SynfH")) != -1) {
4353 		switch (ch) {
4354 		case 'H':
4355 			heuristics = 1;
4356 			break;
4357 		case 'f':
4358 			force = 1;
4359 			break;
4360 		case 'n':
4361 			rdonly_flag = alwaysno = 1;
4362 			alwaysyes = preen = 0;
4363 			break;
4364 		case 'y':
4365 			alwaysyes = 1;
4366 			alwaysno = preen = 0;
4367 			break;
4368 		case 'p':
4369 			/* small automatic repairs */
4370 			preen = 1;
4371 			alwaysyes = alwaysno = 0;
4372 			break;
4373 		case 's':
4374 			/* session number or relative session */
4375 			target_session = atoi(optarg);
4376 			break;
4377 		case 'S':		/* Search for older VATs */
4378 			search_older_vat = 1;
4379 			break;
4380 
4381 		default:
4382 			usage();
4383 			break;
4384 		}
4385 	}
4386 	argc -= optind;
4387 	argv += optind;
4388 
4389 	if (!argc)
4390 		usage();
4391 
4392 	/* TODO SIGINT and SIGQUIT catchers */
4393 #if 0
4394 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
4395 		(void) signal(SIGINT, catch);
4396 	if (preen)
4397 		(void) signal(SIGQUIT, catch);
4398 #endif
4399 
4400 	signal(SIGINFO, got_siginfo);
4401 
4402 	while (--argc >= 0) {
4403 		setcdevname(*argv, preen);
4404 		erg = checkfilesys(*argv++);
4405 		if (erg > ret)
4406 			ret = erg;
4407 		if (!preen)
4408 			printf("\n");
4409 		udf_cleanup_after_check();
4410 	}
4411 
4412 	return ret;
4413 }
4414 
4415 
4416 /*VARARGS*/
4417 static int __printflike(2, 3)
ask(int def,const char * fmt,...)4418 ask(int def, const char *fmt, ...)
4419 {
4420 	va_list ap;
4421 
4422 	char prompt[256];
4423 	int c;
4424 
4425 	va_start(ap, fmt);
4426 	vsnprintf(prompt, sizeof(prompt), fmt, ap);
4427 	va_end(ap);
4428 	if (alwaysyes || rdonly) {
4429 		pwarn("%s? %s\n", prompt, rdonly ? "no" : "yes");
4430 		return !rdonly;
4431 	}
4432 	if (preen) {
4433 		pwarn("%s? %s : (default)\n", prompt, def ? "yes" : "no");
4434 		return def;
4435 	}
4436 
4437 	do {
4438 		pwarn("%s? [yn] ", prompt);
4439 		fflush(stdout);
4440 		c = getchar();
4441 		while (c != '\n' && getchar() != '\n')
4442 			if (feof(stdin))
4443 				return 0;
4444 	} while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
4445 	return c == 'y' || c == 'Y';
4446 }
4447 
4448 
4449 /*VARARGS*/
4450 static int __printflike(2, 3)
ask_noauto(int def,const char * fmt,...)4451 ask_noauto(int def, const char *fmt, ...)
4452 {
4453 	va_list ap;
4454 
4455 	char prompt[256];
4456 	int c;
4457 
4458 	va_start(ap, fmt);
4459 	vsnprintf(prompt, sizeof(prompt), fmt, ap);
4460 	va_end(ap);
4461 #if 0
4462 	if (preen) {
4463 		pwarn("%s? %s : (default)\n", prompt, def ? "yes" : "no");
4464 		return def;
4465 	}
4466 #endif
4467 
4468 	do {
4469 		pwarn("%s? [yn] ", prompt);
4470 		fflush(stdout);
4471 		c = getchar();
4472 		while (c != '\n' && getchar() != '\n')
4473 			if (feof(stdin))
4474 				return 0;
4475 	} while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
4476 	return c == 'y' || c == 'Y';
4477 }
4478