Added pfsdoctor. Includes PFS3 v19 large partition and file size support.
[AROS.git] / rom / filesys / pfs3 / pfsdoctor / console.c
blob7d90a84b5fcecc29037adcc09b7021d75bf9fd3a
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <stdlib.h>
5 #include <string.h>
7 #include <exec/types.h>
8 #include <exec/memory.h>
9 #include <intuition/intuition.h>
10 #include <proto/exec.h>
11 #include <proto/dos.h>
12 #include <dos/dos.h>
13 #include <dos/filehandler.h>
15 #include "pfs3.h"
16 #include "doctor.h"
18 enum mode mode = repair; /* check, repair, unformat or search */
20 struct Window *CheckRepairWnd;
21 struct stats stats;
23 struct
25 char name[200];
26 } targetdevice;
27 static BOOL verbose = FALSE;
28 FILE *logfh = NULL;
29 static BOOL directscsi = FALSE;
30 static BOOL inhibited = FALSE;
32 static const char *accessmodes[] = { "", "Standard", "Direct SCSI", "TD64", "NSD" };
34 void dummyMsg(char *message)
38 void guiMsg(const char *format, ...)
40 va_list parms;
41 va_start (parms, format);
42 vprintf (format, parms);
43 va_end (parms);
46 void guiUpdateStats(void)
50 void guiStatus(int level, char *message, long maxval)
52 printf("%s...\n", message);
55 void guiProgress(int level, long progress)
59 int guiAskUser(char *message, char *okstr, char *cancelstr)
61 char ch = 0;
62 for (;;) {
63 printf("%s\n", message);
64 printf("1=<%s> 0=<%s>\n", okstr, cancelstr);
65 scanf("%c", &ch);
66 if (ch == '1')
67 return 1;
68 if (ch == '0')
69 return 0;
73 #define OV_Flags LDF_DEVICES|LDF_VOLUMES
74 static BOOL OpenVolume(void)
76 struct DosList *dl;
77 ULONG cylsectors, b;
78 BOOL t;
79 int i;
80 UBYTE *detectbuf;
82 /* get device doslist */
83 dl = LockDosList (OV_Flags|LDF_READ);
84 dl = FindDosEntry(dl, targetdevice.name, OV_Flags);
86 if (dl && dl->dol_Type == DLT_VOLUME)
88 struct DosList *dl2;
89 struct DosInfo *di;
91 di = (struct DosInfo *)BADDR(((struct RootNode *)DOSBase->dl_Root)->rn_Info);
92 for (dl2 = (struct DosList *)BADDR(di->di_DevInfo);
93 dl2;
94 dl2 = (struct DosList *)BADDR(dl2->dol_Next))
96 if (dl2->dol_Type == DLT_DEVICE && dl->dol_Task == dl2->dol_Task)
98 unsigned char *dname;
100 dl = dl2;
101 dname = (char *)BADDR(dl->dol_Name);
102 strncpy(targetdevice.name, dname+1, *dname);
103 targetdevice.name[*dname] = 0;
104 break;
109 if (!dl || dl->dol_Type == DLT_VOLUME)
111 UnLockDosList(OV_Flags|LDF_READ);
112 guiMsg("DEVICE "); guiMsg(targetdevice.name);
113 guiMsg(" not found\nEXITING ...\n\n");
114 return FALSE;
117 UnLockDosList(OV_Flags|LDF_READ);
119 /* inhibit device */
120 targetdevice.name[strlen(targetdevice.name)] = ':';
121 targetdevice.name[strlen(targetdevice.name)] = 0;
122 if (!(inhibited = Inhibit(targetdevice.name, DOSTRUE)))
124 guiMsg("Device could not be inhibited.\nEXITING ...\n\n");
125 return FALSE;
128 /* init volume structure */
129 memset(&volume, 0, sizeof(volume));
130 volume.fssm = (struct FileSysStartupMsg *)BADDR(dl->dol_misc.dol_handler.dol_Startup);
131 volume.dosenvec = (struct DosEnvec *)BADDR(volume.fssm->fssm_Environ);
132 strcpy(volume.devicename, targetdevice.name);
133 cylsectors = volume.dosenvec->de_Surfaces * volume.dosenvec->de_BlocksPerTrack;
134 volume.firstblock = volume.dosenvec->de_LowCyl * cylsectors;
135 volume.lastblock = (volume.dosenvec->de_HighCyl + 1) * cylsectors - 1;
136 b = volume.blocksize = volume.dosenvec->de_SizeBlock << 2;
137 for (i=-1; b; i++)
138 b >>= 1;
139 volume.blockshift = i;
140 volume.rescluster = 0;
141 volume.disksize = volume.lastblock - volume.firstblock + 1;
142 volume.lastreserved = volume.disksize - 256; /* temp value, calculated later */
144 volume.status = guiStatus;
145 volume.showmsg = guiMsg;
146 volume.askuser = guiAskUser;
147 volume.progress = guiProgress;
148 volume.updatestats = guiUpdateStats;
149 volume.getblock = vol_GetBlock;
150 volume.writeblock = vol_WriteBlock;
151 BCPLtoCString(volume.execdevice, (UBYTE *)BADDR(volume.fssm->fssm_Device));
152 volume.execunit = volume.fssm->fssm_Unit;
154 if (verbose) {
155 UBYTE name[FNSIZE];
156 BCPLtoCString(name, (UBYTE *)BADDR(volume.fssm->fssm_Device));
157 volume.showmsg("Device: %s:%lu\n", name, volume.fssm->fssm_Unit);
158 volume.showmsg("Firstblock: %lu\n", volume.firstblock);
159 volume.showmsg("Lastblock : %lu\n", volume.lastblock);
160 volume.showmsg("Blocksize : %lu\n", volume.blocksize);
163 /* open device */
164 if (!OpenDiskDevice(volume.fssm, &volume.port, &volume.request, &t))
166 guiMsg("Device could not be opened.\nEXITING ...\n\n");
167 return FALSE;
170 InitCache(64, 32); /* make this configurable ? */
172 detectbuf = AllocVec(volume.blocksize, MEMF_PUBLIC);
173 if (!detectbuf) {
174 printf("Could not allocated %ld byte buffer.\n", volume.blocksize);
175 return FALSE;
177 if (!DetectAccessmode(detectbuf, directscsi)) {
178 printf("PFSDoctor failed to access this disk\n"
179 "above the 4G boundary after attempting\n"
180 "TD64, NSD and Direct SCSI\n");
181 FreeVec(detectbuf);
182 return FALSE;
184 FreeVec(detectbuf);
185 printf("Autodetected disk access mode: %s\n", accessmodes[volume.accessmode]);
187 if (volume.accessmode == ACCESS_DS)
189 volume.getrawblocks = dev_GetBlocksDS;
190 volume.writerawblocks = dev_WriteBlocksDS;
192 else
194 if (volume.accessmode == ACCESS_TD64)
195 volume.td64mode = TRUE;
196 else if (volume.accessmode == ACCESS_NSD)
197 volume.nsdmode = TRUE;
198 volume.getrawblocks = dev_GetBlocks;
199 volume.writerawblocks = dev_WriteBlocks;
202 if (mode == check)
203 volume.writerawblocks = dev_WriteBlocksDummy;
205 return TRUE;
208 static void CloseVolume(void)
210 FreeCache();
212 if (inhibited)
213 Inhibit(targetdevice.name, FALSE);
215 if (volume.request)
217 if (!(CheckIO((struct IORequest *)volume.request)))
218 AbortIO((struct IORequest *)volume.request);
220 WaitIO((struct IORequest *)volume.request);
221 CloseDevice((struct IORequest *)volume.request);
224 if (volume.request)
225 DeleteIORequest(volume.request);
227 if (volume.port)
228 DeleteMsgPort(volume.port);
230 volume.request = NULL;
231 volume.port = NULL;
234 #define TEMPLATE "DEVICE/A,CHECK/S,REPAIR/S,SEARCH/S,UNFORMAT/S,VERBOSE/S,LOGFILE/K,DIRECTSCSI/S"
236 #define ARGS_DEVICE 0
237 #define ARGS_CHECK 1
238 #define ARGS_REPAIR 2
239 #define ARGS_SEARCH 3
240 #define ARGS_UNFORMAT 4
241 #define ARGS_VERBOSE 5
242 #define ARGS_LOGFILE 6
243 #define ARGS_DIRECTSCSI 7
244 #define ARGS_SIZE 8
246 int main(int argc, char *argv[])
248 struct RDArgs *rdarg;
249 LONG args[ARGS_SIZE] = { 0 };
250 int cnt = 0;
251 uint32 opties;
253 if (!(rdarg = ReadArgs (TEMPLATE, args, NULL)))
255 PrintFault (ERROR_REQUIRED_ARG_MISSING, "pfsdoctor");
256 return RETURN_FAIL;
259 strcpy(targetdevice.name, (char*)args[ARGS_DEVICE]);
261 if (args[ARGS_VERBOSE])
262 verbose = TRUE;
264 if (args[ARGS_CHECK]) {
265 mode = check;
266 cnt++;
268 if (args[ARGS_REPAIR]) {
269 mode = repair;
270 cnt++;
272 if (args[ARGS_SEARCH]) {
273 mode = search;
274 cnt++;
276 if (args[ARGS_UNFORMAT]) {
277 mode = unformat;
278 cnt++;
281 if (args[ARGS_DIRECTSCSI]) {
282 directscsi = TRUE;
285 if (cnt == 0) {
286 printf("CHECK, REPAIR, SEARCH or UNFORMAT required.\n");
287 return RETURN_FAIL;
289 if (cnt > 1) {
290 printf("Only one command (CHECK, REPAIR, SEARCH, UNFORMAT) parameter allowed.\n");
291 return RETURN_FAIL;
294 if (args[ARGS_LOGFILE]) {
295 logfh = fopen((char*)args[ARGS_LOGFILE], "w");
296 if (!logfh) {
297 printf("Could not open log file '%s'\n", (char*)args[ARGS_LOGFILE]);
298 return RETURN_FAIL;
302 if (mode == repair)
303 opties = SSF_FIX|SSF_ANALYSE|SSF_GEN_BMMASK;
304 else if (mode == unformat)
305 opties = SSF_UNFORMAT|SSF_FIX|SSF_ANALYSE|SSF_GEN_BMMASK;
306 else
307 opties = SSF_CHECK|SSF_ANALYSE|SSF_GEN_BMMASK;
309 if (verbose)
310 opties |= SSF_VERBOSE;
312 if (OpenVolume()) {
313 StandardScan(opties);
314 CloseVolume();
317 if (logfh)
318 fclose(logfh);
320 FreeArgs(rdarg);
321 return 0;