Belarusian
[AROS.git] / tools / adflib / adf_raw.c
blob3f7d05509c7461eb56e49e178770fc390e00c63a
1 /*
2 * ADF Library. (C) 1997-1998 Laurent Clevy
4 * adf_raw.c
6 * logical disk/volume code
7 */
9 #include <limits.h>
10 #include <stdlib.h>
11 #include <string.h>
13 #include "adf_str.h"
14 #include "adf_raw.h"
15 #include "adf_blk.h"
16 #include "adf_disk.h"
17 #include "adf_util.h"
18 #include "adf_err.h"
19 #include "defendian.h"
21 extern struct Env adfEnv;
23 int swapTable[MAX_SWTYPE+1][15]={
24 { 4, SW_CHAR, 2, SW_LONG, 1012, SW_CHAR, 0, 1024 }, /* first bytes of boot */
25 { 108, SW_LONG, 40, SW_CHAR, 10, SW_LONG, 0, 512 }, /* root */
26 { 6, SW_LONG, 488, SW_CHAR, 0, 512 }, /* data */
27 /* file, dir, entry */
28 { 82, SW_LONG, 92, SW_CHAR, 3, SW_LONG, 36, SW_CHAR, 11, SW_LONG, 0, 512 },
29 { 6, SW_LONG, 0, 24 }, /* cache */
30 { 128, SW_LONG, 0, 512 }, /* bitmap, fext */
31 /* link */
32 { 6, SW_LONG, 64, SW_CHAR, 86, SW_LONG, 32, SW_CHAR, 12, SW_LONG, 0, 512 },
33 { 4, SW_CHAR, 39, SW_LONG, 56, SW_CHAR, 10, SW_LONG, 0, 256 }, /* RDSK */
34 { 4, SW_CHAR, 127, SW_LONG, 0, 512 }, /* BADB */
35 { 4, SW_CHAR, 8, SW_LONG, 32, SW_CHAR, 31, SW_LONG, 4, SW_CHAR, /* PART */
36 15, SW_LONG, 0, 256 },
37 { 4, SW_CHAR, 7, SW_LONG, 4, SW_CHAR, 55, SW_LONG, 0, 256 }, /* FSHD */
38 { 4, SW_CHAR, 4, SW_LONG, 492, SW_CHAR, 0, 512 } /* LSEG */
43 * swapEndian
45 * magic :-) endian swap function (big -> little for read, little to big for write)
48 void
49 swapEndian( unsigned char *buf, int type )
51 int i,j;
52 int p;
54 i=0;
55 p=0;
57 if (type>MAX_SWTYPE || type<0)
58 adfEnv.eFct("SwapEndian: type do not exist");
60 while( swapTable[type][i]!=0 ) {
61 for(j=0; j<swapTable[type][i]; j++) {
62 switch( swapTable[type][i+1] ) {
63 case SW_LONG:
64 *(unsigned long*)(buf+p)=Long(buf+p);
65 p+=4;
66 break;
67 case SW_SHORT:
68 *(unsigned short*)(buf+p)=Short(buf+p);
69 p+=2;
70 break;
71 case SW_CHAR:
72 p++;
73 break;
74 default:
78 i+=2;
80 if (p!=swapTable[type][i+1])
81 (*adfEnv.wFct)("Warning: Endian Swapping length\n");
91 * adfReadRootBlock
93 * ENDIAN DEPENDENT
95 RETCODE
96 adfReadRootBlock(struct Volume* vol, long nSect, struct bRootBlock* root)
98 unsigned char buf[LOGICAL_BLOCK_SIZE];
100 if (adfReadBlock(vol, nSect, buf)!=RC_OK)
101 return RC_ERROR;
103 memcpy(root, buf, LOGICAL_BLOCK_SIZE);
104 #ifdef LITT_ENDIAN
105 swapEndian((unsigned char*)root, SWBL_ROOT);
106 #endif
108 if (root->type!=T_HEADER || root->secType!=ST_ROOT) {
109 (*adfEnv.wFct)("adfReadRootBlock : id not found");
110 return RC_ERROR;
112 if (root->checkSum!=adfNormalSum(buf, 20, LOGICAL_BLOCK_SIZE)) {
113 (*adfEnv.wFct)("adfReadRootBlock : invalid checksum");
114 return RC_ERROR;
117 return RC_OK;
122 * adfWriteRootBlock
126 RETCODE adfWriteRootBlock(struct Volume* vol, long nSect, struct bRootBlock* root)
128 unsigned char buf[LOGICAL_BLOCK_SIZE];
129 unsigned long newSum;
132 root->type = T_HEADER;
133 root->headerKey = 0L;
134 root->highSeq = 0L;
135 root->hashTableSize = HT_SIZE;
136 root->firstData = 0L;
137 /* checkSum, hashTable */
138 /* bmflag */
139 /* bmPages, bmExt */
140 root->nextSameHash = 0L;
141 root->parent = 0L;
142 root->secType = ST_ROOT;
144 memcpy(buf, root, LOGICAL_BLOCK_SIZE);
145 #ifdef LITT_ENDIAN
146 swapEndian(buf, SWBL_ROOT);
147 #endif
149 newSum = adfNormalSum(buf,20,LOGICAL_BLOCK_SIZE);
150 swLong(buf+20, newSum);
151 // *(unsigned long*)(buf+20) = swapLong((unsigned char*)&newSum);
153 // dumpBlock(buf);
154 if (adfWriteBlock(vol, nSect, buf)!=RC_OK)
155 return RC_ERROR;
156 //printf("adfWriteRootBlock %ld\n",nSect);
157 return RC_OK;
162 * adfReadBootBlock
164 * ENDIAN DEPENDENT
166 RETCODE
167 adfReadBootBlock(struct Volume* vol, struct bBootBlock* boot)
169 unsigned char buf[1024];
171 //puts("22");
172 if (adfReadBlock(vol, 0, buf)!=RC_OK)
173 return RC_ERROR;
174 //puts("11");
175 if (adfReadBlock(vol, 1, buf+LOGICAL_BLOCK_SIZE)!=RC_OK)
176 return RC_ERROR;
178 memcpy(boot, buf, LOGICAL_BLOCK_SIZE*2);
179 #ifdef LITT_ENDIAN
180 swapEndian((unsigned char*)boot,SWBL_BOOT);
181 #endif
182 if ( strncmp("DOS",boot->dosType,3)!=0 ) {
183 (*adfEnv.wFct)("adfReadBootBlock : DOS id not found");
184 return RC_ERROR;
187 if ( boot->data[0]!=0 && adfBootSum(buf)!=boot->checkSum ) {
188 printf("compsum=%lx sum=%lx\n", adfBootSum(buf),boot->checkSum );
189 (*adfEnv.wFct)("adfReadBootBlock : incorrect checksum");
192 return RC_OK;
196 * adfWriteBootBlock
199 * write bootcode ?
201 RETCODE
202 adfWriteBootBlock(struct Volume* vol, struct bBootBlock* boot)
204 unsigned char buf[LOGICAL_BLOCK_SIZE*2];
205 unsigned long newSum;
207 boot->dosType[0] = 'D';
208 boot->dosType[1] = 'O';
209 boot->dosType[2] = 'S';
210 memcpy(buf, boot, LOGICAL_BLOCK_SIZE*2);
211 #ifdef LITT_ENDIAN
212 swapEndian(buf, SWBL_BOOT);
213 #endif
215 if (boot->rootBlock==880 || boot->data[0]!=0) {
216 newSum = adfBootSum(buf);
217 //fprintf(stderr,"sum %x %x\n",newSum,adfBootSum2(buf));
218 swLong(buf+4,newSum);
219 // *(unsigned long*)(buf+4) = swapLong((unsigned char*)&newSum);
222 /* dumpBlock(buf);
223 dumpBlock(buf+512);
225 if (adfWriteBlock(vol, 0, buf)!=RC_OK)
226 return RC_ERROR;
227 if (adfWriteBlock(vol, 1, buf+512)!=RC_OK)
228 return RC_ERROR;
229 //puts("adfWriteBootBlock");
230 return RC_OK;
235 * NormalSum
237 * buf = where the block is stored
238 * offset = checksum place (in bytes)
239 * bufLen = buffer length (in bytes)
241 unsigned long
242 adfNormalSum( UCHAR* buf, int offset, int bufLen )
244 long newsum;
245 int i;
247 newsum=0L;
248 for(i=0; i < (bufLen/4); i++)
249 if ( i != (offset/4) ) /* old chksum */
250 newsum+=Long(buf+i*4);
251 newsum=(-newsum); /* WARNING */
253 return(newsum);
257 * adfBitmapSum
260 unsigned long
261 adfBitmapSum(unsigned char *buf)
263 unsigned long newSum;
264 int i;
266 newSum = 0L;
267 for(i=1; i<128; i++)
268 newSum-=Long(buf+i*4);
269 return(newSum);
274 * adfBootSum
277 unsigned long
278 adfBootSum(unsigned char *buf)
280 unsigned long d, newSum;
281 int i;
283 newSum=0L;
284 for(i=0; i<256; i++) {
285 if (i!=1) {
286 d = Long(buf+i*4);
287 if ( (ULONG_MAX-newSum)<d )
288 newSum++;
289 newSum+=d;
292 newSum = ~newSum; /* not */
294 return(newSum);
297 unsigned long
298 adfBootSum2(unsigned char *buf)
300 unsigned long prevsum, newSum;
301 int i;
303 prevsum = newSum=0L;
304 for(i=0; i<1024/sizeof(unsigned long); i++) {
305 if (i!=1) {
306 prevsum = newSum;
307 newSum += Long(buf+i*4);
308 if (newSum < prevsum)
309 newSum++;
312 newSum = ~newSum; /* not */
314 return(newSum);
318 /*#######################################################################################*/