Synch'd with documentation.
[AROS.git] / rom / filesys / afs / volumes.c
blob5266065ea0f69de893107c2dc761e7810686721e
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /*
7 * -date------ -name------------------- -description-----------------------------
8 * 26-dec-2007 [Tomasz Wiszkowski] added disk validation
9 * 04-jan-2008 [Tomasz Wiszkowski] corrected tabulation
10 * 05-jan-2008 [Tomasz Wiszkowski] removed requester prompting for validation
11 * to allow volume validation during boot-up
14 #include <string.h>
16 #ifndef DEBUG
17 #define DEBUG 0
18 #endif
20 #include "os.h"
21 #include "bitmap.h"
22 #include "checksums.h"
23 #include "error.h"
24 #include "afsblocks.h"
25 #include "baseredef.h"
26 #include "validator.h"
29 BOOL mediumPresent(struct IOHandle *ioh) {
30 return (ioh->ioflags & IOHF_DISK_IN)==IOHF_DISK_IN;
33 /*******************************************
34 Name : newMedium
35 Descr.: build infos for a new medium
36 Input : volume -
37 Output: 0 for success; error code otherwise
38 ********************************************/
39 LONG newMedium(struct AFSBase *afsbase, struct Volume *volume) {
40 struct BlockCache *blockbuffer;
41 UWORD i;
42 BOOL gotdostype = FALSE;
43 LONG error;
44 ULONG dostype;
45 UBYTE dosflags;
47 /* Check validity of root block first, since boot block may be left over
48 from an overwritten partition of a different size
49 Read bootblock first to prevent multiple seeks when using floppies
50 */
51 blockbuffer=getBlock(afsbase, volume,0);
52 volume->dostype = dostype = 0;
53 volume->dosflags = dosflags = 0;
54 if (blockbuffer != NULL) {
55 gotdostype = TRUE;
56 dostype = OS_BE2LONG(blockbuffer->buffer[0]) & 0xFFFFFF00;
57 dosflags = OS_BE2LONG(blockbuffer->buffer[0]) & 0xFF;
60 blockbuffer=getBlock(afsbase, volume,volume->rootblock);
61 if (blockbuffer == NULL) {
62 volume->dostype = ID_UNREADABLE_DISK;
63 return ERROR_UNKNOWN;
65 if (calcChkSum(volume->SizeBlock, blockbuffer->buffer) != 0 ||
66 OS_BE2LONG(blockbuffer->buffer[BLK_PRIMARY_TYPE]) != T_SHORT ||
67 OS_BE2LONG(blockbuffer->buffer[BLK_SECONDARY_TYPE(volume)]) != ST_ROOT)
69 D(bug("[afs] newMedium: incorrect checksum or root block type (%ld)\n",
70 OS_BE2LONG(blockbuffer->buffer[BLK_SECONDARY_TYPE(volume)])));
71 volume->dostype = ID_NOT_REALLY_DOS;
72 return ERROR_NOT_A_DOS_DISK;
75 if (gotdostype == FALSE) {
76 volume->dostype = ID_UNREADABLE_DISK;
77 return ERROR_UNKNOWN;
79 if (dostype != 0x444F5300)
81 blockbuffer = getBlock(afsbase, volume, 1);
82 dostype = OS_BE2LONG(blockbuffer->buffer[0]) & 0xFFFFFF00;
83 dosflags = OS_BE2LONG(blockbuffer->buffer[0]) & 0xFF;
85 if (dostype != 0x444F5300)
87 D(bug("[afs] newMedium: incorrect DOS type (0x%lx)\n",
88 volume->dostype));
89 volume->dostype = ID_NOT_REALLY_DOS;
90 return ERROR_NOT_A_DOS_DISK;
92 blockbuffer=getBlock(afsbase, volume,volume->rootblock);
93 if (blockbuffer == NULL) {
94 volume->dostype = ID_UNREADABLE_DISK;
95 return ERROR_UNKNOWN;
98 volume->dostype = dostype;
99 volume->dosflags = dosflags;
101 for (i=0;i<=24;i++)
103 volume->bitmapblockpointers[i]=OS_BE2LONG
105 blockbuffer->buffer[BLK_BITMAP_POINTERS_START(volume)+i]
108 volume->bitmapextensionblock=OS_BE2LONG
110 blockbuffer->buffer[BLK_BITMAP_EXTENSION(volume)]
112 if (!blockbuffer->buffer[BLK_BITMAP_VALID_FLAG(volume)])
114 /* since our disk is invalid at this point, *
115 * we want to spawn a new process that will *
116 * perform disk validation while we move on */
118 volume->usedblockscount=0;
119 volume->state = ID_VALIDATING;
121 launchValidator(afsbase, volume);
125 * it's safe to assume that the block is still there
127 blockbuffer=getBlock(afsbase, volume,volume->rootblock);
129 if (blockbuffer->buffer[BLK_BITMAP_VALID_FLAG(volume)])
131 blockbuffer->flags |= BCF_USED; // won't be cleared until volume is ejected
132 volume->usedblockscount=countUsedBlocks(afsbase, volume);
133 volume->state = diskWritable(afsbase, &volume->ioh) ?
134 ID_VALIDATED : ID_WRITE_PROTECTED;
136 error = osMediumInit(afsbase, volume, blockbuffer);
137 if (error != 0)
138 return error;
139 /* for free block searching */
140 volume->lastaccess=volume->rootblock;
141 return 0;
144 /*******************************************
145 Name : initVolume
146 Descr.: maybe a better name would be mountVolume
147 allocate resources for a new mounted device
148 Input : device - device pointer
149 blockdevice - name of blockdevice
150 unit - unit number of blockdevice
151 devicedef - medium geometry data
152 error - return error code
153 Output: 0 on error (error set dos dos error);
154 pointer to struct Volume on success
155 ********************************************/
156 struct Volume *initVolume
158 struct AFSBase *afsbase,
159 struct Device *device,
160 CONST_STRPTR blockdevice,
161 ULONG unit,
162 ULONG flags,
163 struct DosEnvec *devicedef,
164 LONG *error
167 struct Volume *volume;
169 if (blockdevice == NULL) {
170 *error = ERROR_NO_DISK;
171 return NULL;
174 volume = AllocMem(sizeof(struct Volume) + strlen(blockdevice) + 1,MEMF_PUBLIC | MEMF_CLEAR);
175 if (volume != NULL)
177 volume->device = device;
178 volume->ioh.blockdevice = (STRPTR)(&volume[1]); /* Data after the volume alloc */
179 strcpy(volume->ioh.blockdevice, blockdevice);
180 volume->ioh.unit = unit;
181 volume->ioh.flags = flags;
182 volume->SizeBlock = devicedef->de_SizeBlock
183 * devicedef->de_SectorPerBlock;
184 volume->sectorsize = devicedef->de_SizeBlock << 2;
185 volume->blocksectors = devicedef->de_SectorPerBlock;
186 if (devicedef->de_TableSize>=20)
187 volume->bootblocks=devicedef->de_BootBlocks;
188 else
189 volume->bootblocks=devicedef->de_Reserved;
190 volume->numbuffers = devicedef->de_NumBuffers;
191 volume->blockcache=initCache(afsbase, volume, volume->numbuffers);
192 if (volume->blockcache != NULL)
194 if (openBlockDevice(afsbase, &volume->ioh)!= NULL)
196 volume->countblocks =
199 devicedef->de_HighCyl-devicedef->de_LowCyl+1
200 )*devicedef->de_Surfaces*devicedef->de_BlocksPerTrack
202 devicedef->de_SectorPerBlock
204 volume->rootblock =(volume->countblocks-1+devicedef->de_Reserved)/2;
205 volume->startblock=
206 devicedef->de_LowCyl*
207 devicedef->de_Surfaces*
208 devicedef->de_BlocksPerTrack;
209 volume->lastblock=
211 (devicedef->de_HighCyl+1)
212 *devicedef->de_Surfaces
213 *devicedef->de_BlocksPerTrack
214 )-1;
215 check64BitSupport(afsbase, volume);
216 volume->ah.volume=volume;
217 if (mediumPresent(&volume->ioh))
219 *error = newMedium(afsbase, volume);
221 else
222 *error = 0;
223 if ((*error == 0) || (*error == ERROR_NOT_A_DOS_DISK))
225 D(bug("[afs] initVolume: BootBlocks=%d\n",volume->bootblocks));
226 D(bug("[afs] initVolume: RootBlock=%ld\n",volume->rootblock));
227 volume->ah.header_block = volume->rootblock;
228 return volume;
231 else
233 *error=ERROR_NO_FREE_STORE;
235 freeCache(afsbase, volume->blockcache);
237 else
239 *error=ERROR_NO_FREE_STORE;
241 FreeMem(volume,sizeof(struct Volume) + strlen(blockdevice) + 1);
243 else
244 *error=ERROR_NO_FREE_STORE;
245 return NULL;
248 /*******************************************
249 Name : uninitVolume
250 Descr.: maybe a better name would be unmountVolume
251 free resources allocated by initVolume
252 Input : volume - volume to unmount
253 Output: -
254 ********************************************/
255 void uninitVolume(struct AFSBase *afsbase, struct Volume *volume) {
257 osMediumFree(afsbase, volume, TRUE);
258 if (volume->blockcache != NULL)
259 freeCache(afsbase, volume->blockcache);
260 closeBlockDevice(afsbase, &volume->ioh);
261 FreeMem(volume,sizeof(struct Volume) + strlen(volume->ioh.blockdevice) + 1);
265 LONG writeprotectVolume(struct AFSBase *afsbase, struct Volume *volume, BOOL on, ULONG key)
267 LONG error = 0;
269 if(on && (volume->state == ID_WRITE_PROTECTED))
270 { // Already write protected
271 error = ERROR_DISK_WRITE_PROTECTED;
272 D(bug("[AFS] Volume: Already write protected (%l)\n", error));
273 } else {
274 if(on)
275 { // Attempt to write protect
276 if (key)
277 { // With a key
278 volume->key = key;
279 volume->state = ID_WRITE_PROTECTED; // : ID_VALIDATED;
280 } else { // Without a key
281 volume->state = ID_WRITE_PROTECTED;
283 } else { // Attempt to write enable
284 if (volume->key)
285 { // There is a key
286 if(key == volume->key)
287 { // Key is correct
288 volume->state = ID_VALIDATED;
289 volume->key = 0;
290 } else { // Key is incorrect
291 error = ERROR_INVALID_COMPONENT_NAME;
292 D(bug("[AFS] Volume: Wrong key (%l)\n", error));
293 return error;
295 } else { // There is no key
296 volume->state = ID_VALIDATED;
300 /* Return success indicator */
301 return error;
303 /* vim: set noet ts=3 ai fdm=marker fmr={,} :*/