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