1 /*
2 * ADF Library. (C) 1997-2002 Laurent Clevy
3 *
4 * adf_salv.c
5 *
6 * $Id$
7 *
8 * undelete and salvage code : EXPERIMENTAL !
9 *
10 * This file is part of ADFLib.
11 *
12 * ADFLib is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * ADFLib is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with Foobar; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 *
26 */
27
28 #include<string.h>
29 #include<stdlib.h>
30
31 #include "adf_salv.h"
32 #include "adf_bitm.h"
33 #include "adf_util.h"
34 #include "adf_disk.h"
35 #include "adf_dir.h"
36 #include "adf_file.h"
37 #include "adf_cache.h"
38
39 extern struct Env adfEnv;
40
41 /*
42 * adfFreeGenBlock
43 *
44 */
adfFreeGenBlock(struct GenBlock * block)45 void adfFreeGenBlock(struct GenBlock* block)
46 {
47 if (block->name!=NULL)
48 free(block->name);
49 }
50
51
52 /*
53 * adfFreeDelList
54 *
55 */
adfFreeDelList(struct List * list)56 void adfFreeDelList(struct List* list)
57 {
58 struct List *cell;
59
60 cell = list;
61 while(cell!=NULL) {
62 adfFreeGenBlock((struct GenBlock*)cell->content);
63 cell = cell->next;
64 }
65 freeList(list);
66 }
67
68
69 /*
70 * adfGetDelEnt
71 *
72 */
adfGetDelEnt(struct Volume * vol)73 struct List* adfGetDelEnt(struct Volume *vol)
74 {
75 struct GenBlock *block;
76 int32_t i;
77 struct List *list, *head;
78 BOOL delEnt;
79
80 list = head = NULL;
81 block = NULL;
82 delEnt = TRUE;
83 for(i=vol->firstBlock; i<=vol->lastBlock; i++) {
84 if (adfIsBlockFree(vol, i)) {
85 if (delEnt) {
86 block = (struct GenBlock*)malloc(sizeof(struct GenBlock));
87 if (!block) return NULL;
88 /*printf("%p\n",block);*/
89 }
90
91 adfReadGenBlock(vol, i, block);
92
93 delEnt = (block->type==T_HEADER
94 && (block->secType==ST_DIR || block->secType==ST_FILE) );
95
96 if (delEnt) {
97 if (head==NULL)
98 list = head = newCell(NULL, (void*)block);
99 else
100 list = newCell(list, (void*)block);
101 }
102 }
103 }
104
105 if (block!=NULL && list!=NULL && block!=list->content) {
106 free(block);
107 /* printf("%p\n",block);*/
108 }
109 return head;
110 }
111
112
113 /*
114 * adfReadGenBlock
115 *
116 */
adfReadGenBlock(struct Volume * vol,SECTNUM nSect,struct GenBlock * block)117 RETCODE adfReadGenBlock(struct Volume *vol, SECTNUM nSect, struct GenBlock *block)
118 {
119 uint8_t buf[LOGICAL_BLOCK_SIZE];
120 int len;
121 char name[MAXNAMELEN+1];
122
123 if (adfReadBlock(vol, nSect, buf)!=RC_OK)
124 return RC_ERROR;
125
126 block->type =(int) swapLong(buf);
127 block->secType =(int) swapLong(buf+vol->blockSize-4);
128 block->sect = nSect;
129 block->name = NULL;
130
131 if (block->type==T_HEADER) {
132 switch(block->secType) {
133 case ST_FILE:
134 case ST_DIR:
135 case ST_LFILE:
136 case ST_LDIR:
137 len = min(MAXNAMELEN, buf[vol->blockSize-80]);
138 strncpy(name, (char*)buf+vol->blockSize-79, len);
139 name[len] = '\0';
140 block->name = strdup(name);
141 block->parent = swapLong(buf+vol->blockSize-12);
142 break;
143 case ST_ROOT:
144 break;
145 default:
146 ;
147 }
148 }
149 return RC_OK;
150 }
151
152
153 /*
154 * adfCheckParent
155 *
156 */
adfCheckParent(struct Volume * vol,SECTNUM pSect)157 RETCODE adfCheckParent(struct Volume* vol, SECTNUM pSect)
158 {
159 struct GenBlock block;
160
161 if (adfIsBlockFree(vol, pSect)) {
162 (*adfEnv.wFct)("adfCheckParent : parent doesn't exists");
163 return RC_ERROR;
164 }
165
166 /* verify if parent is a DIR or ROOT */
167 adfReadGenBlock(vol, pSect, &block);
168 if ( block.type!=T_HEADER
169 || (block.secType!=ST_DIR && block.secType!=ST_ROOT) ) {
170 (*adfEnv.wFct)("adfCheckParent : parent secType is incorrect");
171 return RC_ERROR;
172 }
173
174 return RC_OK;
175 }
176
177
178 /*
179 * adfUndelDir
180 *
181 */
adfUndelDir(struct Volume * vol,SECTNUM pSect,SECTNUM nSect,struct bDirBlock * entry)182 RETCODE adfUndelDir(struct Volume* vol, SECTNUM pSect, SECTNUM nSect,
183 struct bDirBlock* entry)
184 {
185 RETCODE rc;
186 struct bEntryBlock parent;
187 char name[MAXNAMELEN+1];
188
189 /* check if the given parent sector pointer seems OK */
190 if ( (rc=adfCheckParent(vol,pSect)) != RC_OK)
191 return rc;
192
193 if (pSect!=entry->parent) {
194 (*adfEnv.wFct)("adfUndelDir : the given parent sector isn't the entry parent");
195 return RC_ERROR;
196 }
197
198 if (!adfIsBlockFree(vol, entry->headerKey))
199 return RC_ERROR;
200 if (isDIRCACHE(vol->dosType) && !adfIsBlockFree(vol,entry->extension))
201 return RC_ERROR;
202
203 if (adfReadEntryBlock(vol, pSect, &parent)!=RC_OK)
204 return RC_ERROR;
205
206 strncpy(name, entry->dirName, entry->nameLen);
207 name[(int)entry->nameLen] = '\0';
208 /* insert the entry in the parent hashTable, with the headerKey sector pointer */
209 adfSetBlockUsed(vol,entry->headerKey);
210 adfCreateEntry(vol, &parent, name, entry->headerKey);
211
212 if (isDIRCACHE(vol->dosType)) {
213 adfAddInCache(vol, &parent, (struct bEntryBlock *)entry);
214 adfSetBlockUsed(vol,entry->extension);
215 }
216
217 adfUpdateBitmap(vol);
218
219 return RC_OK;
220 }
221
222
223 /*
224 * adfUndelFile
225 *
226 */
adfUndelFile(struct Volume * vol,SECTNUM pSect,SECTNUM nSect,struct bFileHeaderBlock * entry)227 RETCODE adfUndelFile(struct Volume* vol, SECTNUM pSect, SECTNUM nSect, struct bFileHeaderBlock* entry)
228 {
229 int32_t i;
230 char name[MAXNAMELEN+1];
231 struct bEntryBlock parent;
232 RETCODE rc;
233 struct FileBlocks fileBlocks;
234
235 /* check if the given parent sector pointer seems OK */
236 if ( (rc=adfCheckParent(vol,pSect)) != RC_OK)
237 return rc;
238
239 if (pSect!=entry->parent) {
240 (*adfEnv.wFct)("adfUndelFile : the given parent sector isn't the entry parent");
241 return RC_ERROR;
242 }
243
244 adfGetFileBlocks(vol, entry, &fileBlocks);
245
246 for(i=0; i<fileBlocks.nbData; i++)
247 if ( !adfIsBlockFree(vol,fileBlocks.data[i]) )
248 return RC_ERROR;
249 else
250 adfSetBlockUsed(vol, fileBlocks.data[i]);
251 for(i=0; i<fileBlocks.nbExtens; i++)
252 if ( !adfIsBlockFree(vol,fileBlocks.extens[i]) )
253 return RC_ERROR;
254 else
255 adfSetBlockUsed(vol, fileBlocks.extens[i]);
256
257 free(fileBlocks.data);
258 free(fileBlocks.extens);
259
260 if (adfReadEntryBlock(vol, pSect, &parent)!=RC_OK)
261 return RC_ERROR;
262
263 strncpy(name, entry->fileName, entry->nameLen);
264 name[(int)entry->nameLen] = '\0';
265 /* insert the entry in the parent hashTable, with the headerKey sector pointer */
266 adfCreateEntry(vol, &parent, name, entry->headerKey);
267
268 if (isDIRCACHE(vol->dosType))
269 adfAddInCache(vol, &parent, (struct bEntryBlock *)entry);
270
271 adfUpdateBitmap(vol);
272
273 return RC_OK;
274 }
275
276
277 /*
278 * adfUndelEntry
279 *
280 */
adfUndelEntry(struct Volume * vol,SECTNUM parent,SECTNUM nSect)281 RETCODE adfUndelEntry(struct Volume* vol, SECTNUM parent, SECTNUM nSect)
282 {
283 struct bEntryBlock entry;
284
285 adfReadEntryBlock(vol,nSect,&entry);
286
287 switch(entry.secType) {
288 case ST_FILE:
289 adfUndelFile(vol, parent, nSect, (struct bFileHeaderBlock*)&entry);
290 break;
291 case ST_DIR:
292 adfUndelDir(vol, parent, nSect, (struct bDirBlock*)&entry);
293 break;
294 default:
295 ;
296 }
297
298 return RC_OK;
299 }
300
301
302 /*
303 * adfCheckFile
304 *
305 */
adfCheckFile(struct Volume * vol,SECTNUM nSect,struct bFileHeaderBlock * file,int level)306 RETCODE adfCheckFile(struct Volume* vol, SECTNUM nSect,
307 struct bFileHeaderBlock* file, int level)
308 {
309 struct bFileExtBlock extBlock;
310 struct bOFSDataBlock dataBlock;
311 struct FileBlocks fileBlocks;
312 int n;
313
314 adfGetFileBlocks(vol,file,&fileBlocks);
315 /*printf("data %ld ext %ld\n",fileBlocks.nbData,fileBlocks.nbExtens);*/
316 if (isOFS(vol->dosType)) {
317 /* checks OFS datablocks */
318 for(n=0; n<fileBlocks.nbData; n++) {
319 /*printf("%ld\n",fileBlocks.data[n]);*/
320 adfReadDataBlock(vol,fileBlocks.data[n],&dataBlock);
321 if (dataBlock.headerKey!=fileBlocks.header)
322 (*adfEnv.wFct)("adfCheckFile : headerKey incorrect");
323 if (dataBlock.seqNum!=n+1)
324 (*adfEnv.wFct)("adfCheckFile : seqNum incorrect");
325 if (n<fileBlocks.nbData-1) {
326 if (dataBlock.nextData!=fileBlocks.data[n+1])
327 (*adfEnv.wFct)("adfCheckFile : nextData incorrect");
328 if (dataBlock.dataSize!=vol->datablockSize)
329 (*adfEnv.wFct)("adfCheckFile : dataSize incorrect");
330 }
331 else { /* last datablock */
332 if (dataBlock.nextData!=0)
333 (*adfEnv.wFct)("adfCheckFile : nextData incorrect");
334 }
335 }
336 }
337 for(n=0; n<fileBlocks.nbExtens; n++) {
338 adfReadFileExtBlock(vol,fileBlocks.extens[n],&extBlock);
339 if (extBlock.parent!=file->headerKey)
340 (*adfEnv.wFct)("adfCheckFile : extBlock parent incorrect");
341 if (n<fileBlocks.nbExtens-1) {
342 if (extBlock.extension!=fileBlocks.extens[n+1])
343 (*adfEnv.wFct)("adfCheckFile : nextData incorrect");
344 }
345 else
346 if (extBlock.extension!=0)
347 (*adfEnv.wFct)("adfCheckFile : nextData incorrect");
348 }
349
350 free(fileBlocks.data);
351 free(fileBlocks.extens);
352
353 return RC_OK;
354 }
355
356
357 /*
358 * adfCheckDir
359 *
360 */
adfCheckDir(struct Volume * vol,SECTNUM nSect,struct bDirBlock * dir,int level)361 RETCODE adfCheckDir(struct Volume* vol, SECTNUM nSect, struct bDirBlock* dir,
362 int level)
363 {
364
365
366
367
368 return RC_OK;
369 }
370
371
372 /*
373 * adfCheckEntry
374 *
375 */
adfCheckEntry(struct Volume * vol,SECTNUM nSect,int level)376 RETCODE adfCheckEntry(struct Volume* vol, SECTNUM nSect, int level)
377 {
378 struct bEntryBlock entry;
379 RETCODE rc;
380
381 adfReadEntryBlock(vol,nSect,&entry);
382
383 switch(entry.secType) {
384 case ST_FILE:
385 rc = adfCheckFile(vol, nSect, (struct bFileHeaderBlock*)&entry, level);
386 break;
387 case ST_DIR:
388 rc = adfCheckDir(vol, nSect, (struct bDirBlock*)&entry, level);
389 break;
390 default:
391 /* printf("adfCheckEntry : not supported\n");*/ /* BV */
392 rc = RC_ERROR;
393 }
394
395 return rc;
396 }
397
398
399 /*#############################################################################*/
400