1 /*
2 	repair.c (09.03.17)
3 	exFAT file system implementation library.
4 
5 	Free exFAT implementation.
6 	Copyright (C) 2010-2023  Andrew Nayenko
7 
8 	This program is free software; you can redistribute it and/or modify
9 	it under the terms of the GNU General Public License as published by
10 	the Free Software Foundation, either version 2 of the License, or
11 	(at your option) any later version.
12 
13 	This program is distributed in the hope that it will be useful,
14 	but WITHOUT ANY WARRANTY; without even the implied warranty of
15 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 	GNU General Public License for more details.
17 
18 	You should have received a copy of the GNU General Public License along
19 	with this program; if not, write to the Free Software Foundation, Inc.,
20 	51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 
23 #include "exfat.h"
24 #ifndef __UBOOT__
25 #include <strings.h>
26 #endif
27 
28 int exfat_errors_fixed;
29 
exfat_ask_to_fix(const struct exfat * ef)30 bool exfat_ask_to_fix(const struct exfat* ef)
31 {
32 	const char* question = "Fix (Y/N)?";
33 #ifndef __UBOOT__
34 	char answer[8];
35 	bool yeah, nope;
36 #endif
37 
38 	switch (ef->repair)
39 	{
40 	case EXFAT_REPAIR_NO:
41 		return false;
42 	case EXFAT_REPAIR_YES:
43 		printf("%s %s", question, "Y\n");
44 		return true;
45 	case EXFAT_REPAIR_ASK:
46 #ifndef __UBOOT__
47 		do
48 		{
49 			printf("%s ", question);
50 			fflush(stdout);
51 			if (fgets(answer, sizeof(answer), stdin))
52 			{
53 				yeah = strcasecmp(answer, "Y\n") == 0;
54 				nope = strcasecmp(answer, "N\n") == 0;
55 			}
56 			else
57 			{
58 				yeah = false;
59 				nope = true;
60 			}
61 		}
62 		while (!yeah && !nope);
63 		return yeah;
64 #else
65 	default:
66 		/* Do not attempt to repair FS in U-Boot. */
67 		return false;
68 #endif
69 	}
70 	exfat_bug("invalid repair option value: %d", ef->repair);
71 #ifdef __UBOOT__
72 	return false;
73 #endif
74 }
75 
exfat_fix_invalid_vbr_checksum(const struct exfat * ef,void * sector,uint32_t vbr_checksum)76 bool exfat_fix_invalid_vbr_checksum(const struct exfat* ef, void* sector,
77 		uint32_t vbr_checksum)
78 {
79 	size_t i;
80 	off_t sector_size = SECTOR_SIZE(*ef->sb);
81 
82 	for (i = 0; i < sector_size / sizeof(vbr_checksum); i++)
83 		((le32_t*) sector)[i] = cpu_to_le32(vbr_checksum);
84 	if (exfat_pwrite(ef->dev, sector, sector_size, 11 * sector_size) < 0)
85 	{
86 		exfat_error("failed to write correct VBR checksum");
87 		return false;
88 	}
89 	exfat_errors_fixed++;
90 	return true;
91 }
92 
exfat_fix_invalid_node_checksum(UNUSED const struct exfat * ef,struct exfat_node * node)93 bool exfat_fix_invalid_node_checksum(UNUSED const struct exfat* ef,
94 		struct exfat_node* node)
95 {
96 	/* checksum will be rewritten by exfat_flush_node() */
97 	node->is_dirty = true;
98 
99 	exfat_errors_fixed++;
100 	return true;
101 }
102 
exfat_fix_unknown_entry(struct exfat * ef,struct exfat_node * dir,const struct exfat_entry * entry,off_t offset)103 bool exfat_fix_unknown_entry(struct exfat* ef, struct exfat_node* dir,
104 		const struct exfat_entry* entry, off_t offset)
105 {
106 	struct exfat_entry deleted = *entry;
107 
108 	deleted.type &= ~EXFAT_ENTRY_VALID;
109 	if (exfat_generic_pwrite(ef, dir, &deleted, sizeof(struct exfat_entry),
110 			offset) != sizeof(struct exfat_entry))
111 		return false;
112 
113 	exfat_errors_fixed++;
114 	return true;
115 }
116