tizen 2.3 release
[framework/system/deviced.git] / src / fsck-msdos / check.c
1 /*
2  * Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank
3  * Copyright (c) 1995 Martin Husemann
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Martin Husemann
16  *      and Wolfgang Solfrank.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <stdio.h>
38 #include <unistd.h>
39 #include <fcntl.h>
40
41 #include "ext.h"
42 #include "fsutil.h"
43
44 /*
45  * If the FAT > this size then skip comparing, lest we risk
46  * OOMing the framework. in the future we need to just re-write
47  * this whole thing and optimize for less memory
48  */
49 #define FAT_COMPARE_MAX_KB 4096
50
51 int
52 checkfilesys(const char *fname)
53 {
54         int dosfs;
55         struct bootblock boot;
56         struct fatEntry *fat = NULL;
57         int i, finish_dosdirsection=0;
58         int mod = 0;
59         int ret = 8;
60         int quiet = 0;
61         int skip_fat_compare = 0;
62
63         rdonly = alwaysno;
64         if (!quiet)
65                 printf("** %s", fname);
66
67         dosfs = open(fname, rdonly ? O_RDONLY : O_RDWR, 0);
68         if (dosfs < 0 && !rdonly) {
69                 dosfs = open(fname, O_RDONLY, 0);
70                 if (dosfs >= 0)
71                         pwarn(" (NO WRITE)\n");
72                 else if (!quiet)
73                         printf("\n");
74                 rdonly = 1;
75         } else if (!quiet)
76                 printf("\n");
77
78         if (dosfs < 0) {
79                 perror("Can't open");
80                 return 8;
81         }
82
83         if (readboot(dosfs, &boot) == FSFATAL) {
84                 close(dosfs);
85                 printf("\n");
86                 return 8;
87         }
88
89         if (skipclean && preen && checkdirty(dosfs, &boot)) {
90                 printf("%s: ", fname);
91                 printf("FILESYSTEM CLEAN; SKIPPING CHECKS\n");
92                 ret = 0;
93                 goto out;
94         }
95
96         if (((boot.FATsecs * boot.BytesPerSec) / 1024) > FAT_COMPARE_MAX_KB)
97             skip_fat_compare = 1;
98
99         if (!quiet)  {
100                 if (skip_fat_compare)
101                         printf("** Phase 1 - Read FAT (compare skipped)\n");
102                 else if (boot.ValidFat < 0)
103                         printf("** Phase 1 - Read and Compare FATs\n");
104                 else
105                         printf("** Phase 1 - Read FAT\n");
106         }
107
108         mod |= readfat(dosfs, &boot, boot.ValidFat >= 0 ? boot.ValidFat : 0, &fat);
109         if (mod & FSFATAL) {
110                 printf("Fatal error during readfat()\n");
111                 if (fat)
112                         free(fat);
113                 close(dosfs);
114                 return 8;
115         }
116
117         if (!skip_fat_compare && boot.ValidFat < 0)
118                 for (i = 1; i < (int)boot.FATs; i++) {
119                         struct fatEntry *currentFat;
120
121                         mod |= readfat(dosfs, &boot, i, &currentFat);
122
123                         if (mod & FSFATAL) {
124                                 printf("Fatal error during readfat() for comparison\n");
125                                 goto out;
126                         }
127
128                         mod |= comparefat(&boot, fat, currentFat, i);
129                         free(currentFat);
130                         if (mod & FSFATAL) {
131                                 printf("Fatal error during FAT comparison\n");
132                                 goto out;
133                         }
134                 }
135
136         if (!quiet)
137                 printf("** Phase 2 - Check Cluster Chains\n");
138
139         mod |= checkfat(&boot, fat);
140         if (mod & FSFATAL) {
141                 printf("Fatal error during FAT check\n");
142                 goto out;
143         }
144         /* delay writing FATs */
145
146         if (!quiet)
147                 printf("** Phase 3 - Checking Directories\n");
148
149         mod |= resetDosDirSection(&boot, fat);
150         finish_dosdirsection = 1;
151         if (mod & FSFATAL) {
152                 printf("Fatal error during resetDosDirSection()\n");
153                 goto out;
154         }
155         /* delay writing FATs */
156
157         mod |= handleDirTree(dosfs, &boot, fat);
158         if (mod & FSFATAL)
159                 goto out;
160
161         if (!quiet)
162                 printf("** Phase 4 - Checking for Lost Files\n");
163
164         mod |= checklost(dosfs, &boot, fat);
165         if (mod & FSFATAL)
166                 goto out;
167
168         /* now write the FATs */
169         if (mod & FSFATMOD) {
170                 if (ask(1, "Update FATs")) {
171                         mod |= writefat(dosfs, &boot, fat, mod & FSFIXFAT);
172                         if (mod & FSFATAL) {
173                                 printf("Fatal error during writefat()\n");
174                                 goto out;
175                         }
176                 } else
177                         mod |= FSERROR;
178         }
179
180         if (boot.NumBad)
181                 pwarn("%d files, %d free (%d clusters), %d bad (%d clusters)\n",
182                       boot.NumFiles,
183                       boot.NumFree * boot.ClusterSize / 1024, boot.NumFree,
184                       boot.NumBad * boot.ClusterSize / 1024, boot.NumBad);
185         else
186                 pwarn("%d files, %d free (%d clusters)\n",
187                       boot.NumFiles,
188                       boot.NumFree * boot.ClusterSize / 1024, boot.NumFree);
189
190         if (mod && (mod & FSERROR) == 0) {
191                 if (mod & FSDIRTY) {
192                         if (ask(1, "MARK FILE SYSTEM CLEAN") == 0)
193                                 mod &= ~FSDIRTY;
194
195                         if (mod & FSDIRTY) {
196                                 pwarn("MARKING FILE SYSTEM CLEAN\n");
197                                 mod |= writefat(dosfs, &boot, fat, 1);
198                         } else {
199                                 pwarn("\n***** FILE SYSTEM IS LEFT MARKED AS DIRTY *****\n");
200                                 mod |= FSERROR; /* file system not clean */
201                         }
202                 }
203         }
204
205         if (mod & (FSFATAL | FSERROR))
206                 goto out;
207
208         ret = 0;
209
210     out:
211         if (finish_dosdirsection)
212                 finishDosDirSection();
213         free(fat);
214         close(dosfs);
215
216         if (mod & (FSFATMOD|FSDIRMOD)) {
217                 pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n");
218                 return 4;
219         }
220
221         return ret;
222 }