Cleanup in elf.c with .bss section clean; adm command mounts cdrom instead of floppy...
[ZeXOS.git] / kernel / drivers / fs / fat.c
blob00018312a9441dd7d36c5ff4e972df9b1d180fc8
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <build.h>
24 #ifdef ARCH_i386
26 #include <system.h>
27 #include <string.h>
28 #include <cache.h>
29 #include <vfs.h>
31 int cele;
33 static unsigned char tolower (char c)
35 return ((c >= 'A' && c <= 'Z') ? c + 32: c);
38 static void dec2bin (long decimal, char *binary)
40 int k = 0, n = 0;
41 int neg_flag = 0;
42 int remain;
43 char temp[80];
45 // take care of negative input
46 if (decimal < 0) {
47 decimal = -decimal;
48 neg_flag = 1;
49 } do {
50 remain = decimal % 2;
51 decimal = decimal / 2; // whittle down decimal
52 temp[k++] = remain + 0x30; // makes characters 0 or 1
53 } while (decimal > 0);
55 if (neg_flag)
56 temp[k++] = '-'; // add back - sign
57 else
58 temp[k++] = ' '; // or space
60 while (k >= 0)
61 binary[n ++] = temp[-- k]; // reverse spelling
63 binary[n - 1] = 0; // end with NULL
66 static void parse_attr (char* binary,int y)
69 0x01 000001 Read only
70 0x02 000010 Hidden
71 0x04 000100 System file
72 0x08 001000 Volume ID
73 0x10 010000 Directory
74 0x20 100000 Binary which stands for Archive
77 int i;
78 int x = 0;
80 dir[y].read=0;
81 dir[y].hidden=0;
82 dir[y].system=0;
83 dir[y].volume=0;
84 dir[y].dir=0;
85 dir[y].bin=0;
87 for (i = strlen (binary) - 1; i >= 0; i --) {
88 if(binary[i] == '1') {
89 switch (x) {
90 case 0: dir[y].read=1; break;
91 case 1: dir[y].hidden=1; break;
92 case 2: dir[y].system=1; break;
93 case 3: dir[y].volume=1; break;
94 case 4: dir[y].dir=1; break;
95 case 5: dir[y].bin=1; break;
98 x++;
102 static int fat_read (unsigned int byte, unsigned int byte2)
104 BYTE text[512];
106 unsigned char *buf = text;
107 unsigned int i = 0;
108 unsigned int x;
109 unsigned int start = -1;
110 unsigned int next = 0;
111 unsigned int test = 0;
112 unsigned int pom = 0;
114 if (!read_block (1, text, 1))
115 return 0;
117 buf = text;
118 for(x = 0; x < 512; x ++) {
119 //if (i>byte-3 && i<byte+3)
120 //kprintf("%x",*buf);
121 if (i == byte)
122 start = *buf;
124 if (i == byte2 && start != -1) {
125 if (start == 0xf0 && *buf == 0xff)
126 return -2;
128 next = ((*buf << 8 | start) >> 4);
129 test = (*buf << 8 | start);
131 if (cele == 0)
132 next = (*buf << 8 | start) & 0x0FFF;
134 if (next < 0)
135 next = next * (-1);
136 //kprintf("\nnext=%x %d start=%x end=%x byte=%d byte1=%d cele=%d test=%x\n",next,next,start,*buf,byte,byte2,cele,test);
138 return next;
141 *buf ++;
142 i ++;
145 return -1;
149 static int fat_nextsector (int i)
151 cele = (i * 150) % 100;
152 return (i * 150) / 100;
155 static void read_f (unsigned int cluster)
157 static BYTE text1[512] = "";
158 unsigned char *buf;
159 unsigned int x;
160 // kprintf("\n*** %d\n",cluster);
161 read_block (33 + cluster, text1, 1);
162 //strcpy(buf,text1);
163 //text1[strlen(text1)-4]='\0';
165 unsigned len = 512;
167 /* FIXME: lot of work with elf */
168 //file_cache = (unsigned char *) krealloc ((void *) file_cache, file_cache_id+len);
170 cache_add (text1, len);
172 // kprintf ("file_cache: %d\n", file_cache_id);
175 // 33 sector = open space
176 static unsigned long read_file (int aa, vfs_content_t *content)
178 int i;
179 int byte;
180 int next = 0;
181 int sect;
182 cele=0;
184 cache_t *cache = cache_create (0, 0, 0);
186 if (!cache)
187 return 0;
189 //kprintf("name=%s start=%d fat=%d\n",dir[aa].name,dir[aa].start,next);
190 next = fat_nextsector (dir[aa].start);
191 sect = fat_read (next,next+1);
193 next = fat_nextsector (sect);
194 read_f (dir[aa].start-2);
195 // file_cache[strlen(file_cache)-4]='\0';
197 for (i = 0; i < 2000; i++) {
198 //DPRINT (DBG_DRIVER | DBG_FS, "next: %d sect: %d", next, sect);
200 if (sect < 0 || sect == 4095)
201 break;
202 //file_cache[strlen (file_cache)-4] = '\0';
203 read_f (sect-2);
204 sect = fat_read (next, next+1);
205 next = fat_nextsector (sect);
208 content->ptr = (char *) &cache->data;
209 content->len = cache->limit;
211 return cache->limit;
214 unsigned read_dir (int aa)
216 static BYTE text[512];
217 unsigned char *buf = text;
218 int x;
219 int i = 0;
220 int y = 0;
221 char *bin;
222 int label = 0;
223 unsigned int start;
224 /* vymazeme nazvy vsech souboru */
225 for(x = 0; x < 223; x ++)
226 dir[x].name[0] = '\0';
228 if (aa == -1) {
229 if (!read_block (19, text, 1))
230 return 0;
231 //printf ("ret: %d\n", ret);
232 } else {
233 if (!read_block (33+dir[aa].start-2, text, 1))
234 return 0;
237 buf = text;
239 for (x = 0; x < 512; x ++) {
240 if (i == 31) {
241 i=-1;
242 y++;
243 label = 0;
246 if (i == 26)
247 start = *buf;
249 if (i == 27 && label == 0)
250 dir[y].start = (*buf << 8 | start);
252 if (i == 11 && (*buf == 0x0f || *buf == 0x00)) {
253 strcpy (dir[y].name, "");
254 label = 1;
255 y --;
257 if (i == 11 && *buf != 0x0f && *buf != 0x00) {
258 dec2bin (*buf,bin);
259 parse_attr (bin, y);
261 if (i <= 10 && i >= 0)
262 dir[y].name[i] = tolower (*buf);
264 i ++;
265 *buf ++;
268 return 1;
272 FAT12
273 WRITE function
276 static void write_f (unsigned int cluster, char *text1)
278 if (!write_block (33 + cluster, text1, 1)) {
279 printf ("error -> FAT12 -> !floppy write\n");
280 return;
283 DPRINT (DBG_DRIVER | DBG_FS, "FAT12 -> write_f (): OK");
286 // 33 sector = open space
287 static void write_file (int aa, char *buf)
289 int i;
290 int byte;
291 int next = 0;
292 int sect;
293 cele=0;
295 //kprintf("name=%s start=%d fat=%d\n",dir[aa].name,dir[aa].start,next);
297 next = fat_nextsector (dir[aa].start);
298 sect = fat_read (next, next+1);
300 next = fat_nextsector (sect);
301 read_f (dir[aa].start-2);
303 for(i = 0; i < 100; i++) {
304 //DPRINT (DBG_DRIVER | DBG_FS, "next: %d sect: %d", next, sect);
306 if (sect < 0 || sect == 4095)
307 break;
309 write_f (sect-2, buf);
310 sect = fat_read (next, next+1);
311 next = fat_nextsector (sect);
315 /* TODO: in development */
316 static void write_dir (int aa)
318 static BYTE text[512];
319 unsigned char *buf = text;
320 int x;
321 int i = 0;
322 int y = 0;
323 char *bin;
324 int label = 0;
325 unsigned int start;
326 /* vymazeme nazvy vsech souboru */
327 for(x = 0; x < 223; x ++)
328 dir[x].name[0] = '\0';
330 if (aa == -1)
331 write_block (19, text, 1);
332 else
333 write_block (33+dir[aa].start-2, text, 1);
335 buf = text;
337 for (x = 0; x < 512; x ++) {
338 if (i == 31) {
339 i=-1;
340 y++;
341 label = 0;
344 if (i == 26)
345 start = *buf;
347 if (i == 27 && label == 0)
348 dir[y].start = (*buf << 8 | start);
350 if (i == 11 && (*buf == 0x0f || *buf == 0x00)) {
351 strcpy (dir[y].name, "");
352 label = 1;
353 y --;
355 if (i == 11 && *buf != 0x0f && *buf != 0x00) {
356 dec2bin (*buf,bin);
357 parse_attr (bin, y);
359 if (i <= 10 && i >= 0)
360 dir[y].name[i] = tolower (*buf);
362 i ++;
363 *buf ++;
367 bool fat_handler (unsigned act, char *block, unsigned n, unsigned long l)
369 switch (act) {
370 case FS_ACT_INIT:
372 /* nothing */
373 return 1;
375 break;
376 case FS_ACT_READ:
378 l = read_file (n, (vfs_content_t *) block);
380 return 1;
382 break;
383 case FS_ACT_WRITE:
385 unsigned y = 0;
386 while (y < (l+512))
387 y += 512;
389 char *buf = (char *) kmalloc (sizeof (char) * (y+1));
391 if (!buf) {
392 DPRINT (DBG_DRIVER | DBG_FS, "ERROR -> FAT WRITE : out of memory");
393 return 0;
396 memset (buf, 0, y);
397 memcpy (buf, block, l);
399 int i;
401 for (i = 0; i < (y/512); i ++);
402 write_file (n, buf+(i*512));
404 kfree (buf);
406 return 1;
408 break;
409 case FS_ACT_CHDIR:
411 read_dir (n);
413 return 1;
415 break;
418 return 0;
420 #endif