1/* dosfsck.c  -  User interface */
2
3/* Written 1993 by Werner Almesberger */
4
5/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
6 * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
7
8
9#include "../version.h"
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <stdarg.h>
15#include <unistd.h>
16#include <getopt.h>
17
18#include "common.h"
19#include "dosfsck.h"
20#include "io.h"
21#include "boot.h"
22#include "fat.h"
23#include "file.h"
24#include "check.h"
25
26
27int interactive = 0,list = 0,test = 0,verbose = 0,write_immed = 0;
28int atari_format = 0;
29unsigned n_files = 0;
30void *mem_queue = NULL;
31
32
33static void usage(char *name)
34{
35    fprintf(stderr,"usage: %s [-aAflrstvVwy] [-d path -d ...] "
36      "[-u path -u ...]\n%15sdevice\n",name,"");
37    fprintf(stderr,"  -a       automatically repair the file system\n");
38    fprintf(stderr,"  -A       toggle Atari file system format\n");
39    fprintf(stderr,"  -d path  drop that file\n");
40    fprintf(stderr,"  -f       salvage unused chains to files\n");
41    fprintf(stderr,"  -l       list path names\n");
42    fprintf(stderr,"  -r       interactively repair the file system\n");
43    fprintf(stderr,"  -s       show the volume label, if any, and exit\n");
44    fprintf(stderr,"  -t       test for bad clusters\n");
45    fprintf(stderr,"  -u path  try to undelete that (non-directory) file\n");
46    fprintf(stderr,"  -v       verbose mode\n");
47    fprintf(stderr,"  -V       perform a verification pass\n");
48    fprintf(stderr,"  -w       write changes to disk immediately\n");
49    fprintf(stderr,"  -y       same as -a, for compat with other *fsck\n");
50    exit(2);
51}
52
53
54/*
55 * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant
56 * of MS-DOS filesystem by default.
57 */
58static void check_atari( void )
59{
60#ifdef __mc68000__
61    FILE *f;
62    char line[128], *p;
63
64    if (!(f = fopen( "/proc/hardware", "r" ))) {
65	perror( "/proc/hardware" );
66	return;
67    }
68
69    while( fgets( line, sizeof(line), f ) ) {
70	if (strncmp( line, "Model:", 6 ) == 0) {
71	    p = line + 6;
72	    p += strspn( p, " \t" );
73	    if (strncmp( p, "Atari ", 6 ) == 0)
74		atari_format = 1;
75	    break;
76	}
77    }
78    fclose( f );
79#endif
80}
81
82
83extern int filter_printf(const char *format, ...)
84{
85    char new_format[1000];
86    const char *follow_old;
87    char *follow_new;
88    va_list ap;
89    int result;
90
91    fprintf(stdout, "<script>check_fat_filesystem_info(\"");
92    follow_old = format;
93    follow_new = new_format;
94    while (*follow_old != 0)
95    {
96	if (*follow_old == '\n')
97	{
98	    /* empty */
99	}
100	else if (*follow_old == '"')
101	{
102	    *follow_new = '\\';
103	    ++follow_new;
104	    *follow_new = '"';
105	    ++follow_new;
106	}
107	else if (*follow_old == '\\')
108	{
109	    *follow_new = '\\';
110	    ++follow_new;
111	    *follow_new = '\\';
112	    ++follow_new;
113	}
114	else
115	{
116	    *follow_new = *follow_old;
117	    ++follow_new;
118	}
119	++follow_old;
120    }
121    *follow_new = 0;
122    va_start(ap, format);
123    result = vprintf(new_format, ap);
124    va_end(ap);
125    fprintf(stdout, "\");</script>\n");
126    fflush(stdout);
127    return result;
128}
129
130
131int main(int argc,char **argv)
132{
133    DOS_FS fs;
134    int rw,salvage_files,verify,show_label,c;
135    unsigned long free_clusters;
136
137    rw = salvage_files = verify = show_label = 0;
138    interactive = 0;
139    check_atari();
140
141    while ((c = getopt(argc,argv,"Aad:flrstu:vVwy")) != EOF)
142	switch (c) {
143	    case 'A': /* toggle Atari format */
144	  	atari_format = !atari_format;
145		break;
146	    case 'a':
147	    case 'y':
148		rw = 1;
149		interactive = 0;
150		salvage_files = 1;
151		break;
152	    case 'd':
153		file_add(optarg,fdt_drop);
154		break;
155	    case 'f':
156		salvage_files = 1;
157		break;
158	    case 'l':
159		list = 1;
160		break;
161	    case 'r':
162		rw = 1;
163		interactive = 1;
164		break;
165	    case 's':
166		show_label = 1;
167		break;
168	    case 't':
169		test = 1;
170		break;
171	    case 'u':
172		file_add(optarg,fdt_undelete);
173		break;
174	    case 'v':
175		verbose = 1;
176		printf("dosfsck " VERSION " (" VERSION_DATE ")\n");
177		break;
178	    case 'V':
179		verify = 1;
180		break;
181	    case 'w':
182		write_immed = 1;
183		break;
184	    default:
185		usage(argv[0]);
186	}
187    if ((test || write_immed) && !rw) {
188	fprintf(stderr,"-t and -w require -a or -r\n");
189	exit(2);
190    }
191    if (optind != argc-1) usage(argv[0]);
192
193    printf( "dosfsck " VERSION ", " VERSION_DATE ", FAT32, LFN\n" );
194    fs_open(argv[optind],rw);
195    read_boot(&fs);
196    if (show_label) {
197	if (!scan_root_for_volume_label(&fs))
198	    fprintf(stdout, "No volume label found.\n");
199	fprintf(stdout, "Volume ID: 0x%02x%02x%02x%02x\n",
200		(unsigned)(fs.volume_id[0]), (unsigned)(fs.volume_id[1]),
201		(unsigned)(fs.volume_id[2]), (unsigned)(fs.volume_id[3]));
202	qfree(&mem_queue);
203	return fs_close(rw) ? 1 : 0;
204    }
205    if (verify) printf("Starting check/repair pass.\n");
206    while (read_fat(&fs), scan_root(&fs)) qfree(&mem_queue);
207    if (test) fix_bad(&fs);
208    if (salvage_files) reclaim_file(&fs);
209    else reclaim_free(&fs);
210    free_clusters = update_free(&fs);
211    file_unused();
212    qfree(&mem_queue);
213    if (verify) {
214	printf("Starting verification pass.\n");
215	read_fat(&fs);
216	scan_root(&fs);
217	reclaim_free(&fs);
218	qfree(&mem_queue);
219    }
220
221    if (fs_changed()) {
222	if (rw) {
223	    if (interactive)
224		rw = get_key("yn","Perform changes ? (y/n)") == 'y';
225	    else printf("Performing changes.\n");
226	}
227	else
228	    printf("Leaving file system unchanged.\n");
229    }
230
231    printf( "%s: %u files, %lu/%lu clusters\n", argv[optind],
232	    n_files, fs.clusters - free_clusters, fs.clusters );
233
234    return fs_close(rw) ? 1 : 0;
235}
236
237/* Local Variables: */
238/* tab-width: 8     */
239/* End:             */
240