source: trunk/minix/commands/i386/mtools-3.9.7/fat.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 21.1 KB
Line 
1#include "sysincludes.h"
2#include "msdos.h"
3#include "stream.h"
4#include "mtools.h"
5#include "fsP.h"
6
7extern Stream_t *default_drive;
8
9#ifdef HAVE_LONG_LONG
10typedef long long fatBitMask;
11#else
12typedef long fatBitMask;
13#endif
14
15typedef struct FatMap_t {
16 unsigned char *data;
17 fatBitMask dirty;
18 fatBitMask valid;
19} FatMap_t;
20
21#define SECT_PER_ENTRY (sizeof(fatBitMask)*8)
22#define ONE ((fatBitMask) 1)
23
24static inline int readSector(Fs_t *This, char *buf, unsigned int off,
25 size_t size)
26{
27 return READS(This->Next, buf, sectorsToBytes((Stream_t *)This, off),
28 size << This->sectorShift);
29}
30
31
32static inline int forceReadSector(Fs_t *This, char *buf, unsigned int off,
33 size_t size)
34{
35 return force_read(This->Next, buf, sectorsToBytes((Stream_t *)This, off),
36 size << This->sectorShift);
37}
38
39
40static inline int writeSector(Fs_t *This, char *buf, unsigned int off,
41 size_t size)
42{
43 return WRITES(This->Next, buf, sectorsToBytes((Stream_t*)This, off),
44 size << This->sectorShift);
45}
46
47static inline int forceWriteSector(Fs_t *This, char *buf, unsigned int off,
48 size_t size)
49{
50 return force_write(This->Next, buf, sectorsToBytes((Stream_t*)This, off),
51 size << This->sectorShift);
52}
53
54
55static FatMap_t *GetFatMap(Fs_t *Stream)
56{
57 int nr_entries,i;
58 FatMap_t *map;
59
60 Stream->fat_error = 0;
61 nr_entries = (Stream->fat_len + SECT_PER_ENTRY - 1) / SECT_PER_ENTRY;
62 map = NewArray(nr_entries, FatMap_t);
63 if(!map)
64 return 0;
65
66 for(i=0; i< nr_entries; i++) {
67 map[i].data = 0;
68 map[i].valid = 0;
69 map[i].dirty = 0;
70 }
71
72 return map;
73}
74
75static inline int locate(Fs_t *Stream, int offset, int *slot, int *bit)
76{
77 if(offset >= Stream->fat_len)
78 return -1;
79 *slot = offset / SECT_PER_ENTRY;
80 *bit = offset % SECT_PER_ENTRY;
81 return 0;
82}
83
84static inline int fatReadSector(Fs_t *This, int sector, int slot,
85 int bit, int dupe)
86{
87 int fat_start, ret;
88
89 dupe = (dupe + This->primaryFat) % This->num_fat;
90 fat_start = This->fat_start + This->fat_len * dupe;
91
92 /* first, read as much as the buffer can give us */
93 ret = readSector(This,
94 (char *)(This->FatMap[slot].data+(bit<<This->sectorShift)),
95 fat_start+sector,
96 (SECT_PER_ENTRY - bit%SECT_PER_ENTRY));
97 if(ret < 0)
98 return 0;
99
100 if(ret < This->sector_size) {
101 /* if we got less than one sector's worth, insist to get at
102 * least one sector */
103 ret = forceReadSector(This,
104 (char *) (This->FatMap[slot].data +
105 (bit << This->sectorShift)),
106 fat_start+sector, 1);
107 if(ret < This->sector_size)
108 return 0;
109 return 1;
110 }
111
112 return ret >> This->sectorShift;
113}
114
115
116static int fatWriteSector(Fs_t *This, int sector, int slot, int bit, int dupe)
117{
118 int fat_start;
119
120 dupe = (dupe + This->primaryFat) % This->num_fat;
121 if(dupe && !This->writeAllFats)
122 return This->sector_size;
123
124 fat_start = This->fat_start + This->fat_len * dupe;
125
126 return forceWriteSector(This,
127 (char *)
128 (This->FatMap[slot].data + bit * This->sector_size),
129 fat_start+sector, 1);
130}
131
132static unsigned char *loadSector(Fs_t *This,
133 unsigned int sector, fatAccessMode_t mode,
134 int recurs)
135{
136 int slot, bit, i, ret;
137
138 if(locate(This,sector, &slot, &bit) < 0)
139 return 0;
140#if 0
141 if (((This->fat_len + SECT_PER_ENTRY - 1) / SECT_PER_ENTRY) <= slot) {
142 fprintf(stderr,"This should not happen\n");
143 fprintf(stderr, "fat_len = %d\n", This->fat_len);
144 fprintf(stderr, "SECT_PER_ENTRY=%d\n", (int)SECT_PER_ENTRY);
145 fprintf(stderr, "sector = %d slot = %d bit=%d\n",
146 sector, slot, bit);
147 fprintf(stderr, "left = %d",(int)
148 ((This->fat_len+SECT_PER_ENTRY-1) / SECT_PER_ENTRY));
149 return 0;
150 }
151#endif
152 if(!This->FatMap[slot].data) {
153 /* allocate the storage space */
154 This->FatMap[slot].data =
155 malloc(This->sector_size * SECT_PER_ENTRY);
156 if(!This->FatMap[slot].data)
157 return 0;
158 memset(This->FatMap[slot].data, 0xee,
159 This->sector_size * SECT_PER_ENTRY);
160 }
161
162 if(! (This->FatMap[slot].valid & (ONE << bit))) {
163 ret = -1;
164 for(i=0; i< This->num_fat; i++) {
165 /* read the sector */
166 ret = fatReadSector(This, sector, slot, bit, i);
167
168 if(ret == 0) {
169 fprintf(stderr,
170 "Error reading fat number %d\n", i);
171 continue;
172 }
173 break;
174 }
175
176 /* all copies bad. Return error */
177 if(ret == 0)
178 return 0;
179
180 for(i=0; i < ret; i++)
181 This->FatMap[slot].valid |= ONE << (bit + i);
182
183 if(!recurs && ret == 1)
184 /* do some prefetching, if we happened to only
185 * get one sector */
186 loadSector(This, sector+1, mode, 1);
187 if(!recurs && batchmode)
188 for(i=0; i < 1024; i++)
189 loadSector(This, sector+i, mode, 1);
190 }
191
192 if(mode == FAT_ACCESS_WRITE) {
193 This->FatMap[slot].dirty |= ONE << bit;
194 This->fat_dirty = 1;
195 }
196 return This->FatMap[slot].data + (bit << This->sectorShift);
197}
198
199
200static unsigned char *getAddress(Fs_t *Stream,
201 unsigned int num, fatAccessMode_t mode)
202{
203 unsigned char *ret;
204 int sector;
205 int offset;
206
207 sector = num >> Stream->sectorShift;
208 ret = 0;
209 if(sector == Stream->lastFatSectorNr &&
210 Stream->lastFatAccessMode >= mode)
211 ret = Stream->lastFatSectorData;
212 if(!ret) {
213 ret = loadSector(Stream, sector, mode, 0);
214 if(!ret)
215 return 0;
216 Stream->lastFatSectorNr = sector;
217 Stream->lastFatSectorData = ret;
218 Stream->lastFatAccessMode = mode;
219 }
220 offset = num & Stream->sectorMask;
221 return ret+offset;
222}
223
224
225static int readByte(Fs_t *Stream, int start)
226{
227 unsigned char *address;
228
229 address = getAddress(Stream, start, FAT_ACCESS_READ);
230 if(!address)
231 return -1;
232 return *address;
233}
234
235
236/*
237 * Fat 12 encoding:
238 * | byte n | byte n+1 | byte n+2 |
239 * |7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
240 * | | | | | | | | | | | | | | | | | | | | | | | | |
241 * | n+0.0 | n+0.5 | n+1.0 | n+1.5 | n+2.0 | n+2.5 |
242 * \_____ \____ \______/________/_____ /
243 * ____\______\________/ _____/ ____\_/
244 * / \ \ / / \
245 * | n+1.5 | n+0.0 | n+0.5 | n+2.0 | n+2.5 | n+1.0 |
246 * | FAT entry k | FAT entry k+1 |
247 */
248
249 /*
250 * Get and decode a FAT (file allocation table) entry. Returns the cluster
251 * number on success or 1 on failure.
252 */
253
254static unsigned int fat12_decode(Fs_t *Stream, unsigned int num)
255{
256 unsigned int start = num * 3 / 2;
257 int byte0 = readByte(Stream, start);
258 int byte1 = readByte(Stream, start+1);
259
260 if (num < 2 || byte0 < 0 || byte1 < 0 || num > Stream->num_clus+1) {
261 fprintf(stderr,"[1] Bad address %d\n", num);
262 return 1;
263 }
264
265 if (num & 1)
266 return (byte1 << 4) | ((byte0 & 0xf0)>>4);
267 else
268 return ((byte1 & 0xf) << 8) | byte0;
269}
270
271
272/*
273 * Puts a code into the FAT table. Is the opposite of fat_decode(). No
274 * sanity checking is done on the code. Returns a 1 on error.
275 */
276static void fat12_encode(Fs_t *Stream, unsigned int num, unsigned int code)
277{
278 int start = num * 3 / 2;
279 unsigned char *address0 = getAddress(Stream, start, FAT_ACCESS_WRITE);
280 unsigned char *address1 = getAddress(Stream, start+1, FAT_ACCESS_WRITE);
281
282 if (num & 1) {
283 /* (odd) not on byte boundary */
284 *address0 = (*address0 & 0x0f) | ((code << 4) & 0xf0);
285 *address1 = (code >> 4) & 0xff;
286 } else {
287 /* (even) on byte boundary */
288 *address0 = code & 0xff;
289 *address1 = (*address1 & 0xf0) | ((code >> 8) & 0x0f);
290 }
291}
292
293
294/*
295 * Fat 16 encoding:
296 * | byte n | byte n+1 |
297 * |7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
298 * | | | | | | | | | | | | | | | | |
299 * | FAT entry k |
300 */
301
302static unsigned int fat16_decode(Fs_t *Stream, unsigned int num)
303{
304 unsigned char *address = getAddress(Stream, num << 1, FAT_ACCESS_READ);
305 return _WORD(address);
306}
307
308static void fat16_encode(Fs_t *Stream, unsigned int num, unsigned int code)
309{
310 unsigned char *address = getAddress(Stream, num << 1, FAT_ACCESS_WRITE);
311 set_word(address, code);
312}
313
314
315static unsigned int fast_fat16_decode(Fs_t *Stream, unsigned int num)
316{
317 unsigned short *address =
318 (unsigned short *) getAddress(Stream, num << 1,
319 FAT_ACCESS_READ);
320 return *address;
321}
322
323static void fast_fat16_encode(Fs_t *Stream, unsigned int num, unsigned int code)
324{
325 unsigned short *address =
326 (unsigned short *) getAddress(Stream, num << 1,
327 FAT_ACCESS_WRITE);
328 *address = code;
329}
330
331
332
333
334/*
335 * Fat 32 encoding
336 */
337static unsigned int fat32_decode(Fs_t *Stream, unsigned int num)
338{
339 unsigned char *address = getAddress(Stream, num << 2, FAT_ACCESS_READ);
340 return _DWORD(address);
341}
342
343static void fat32_encode(Fs_t *Stream, unsigned int num, unsigned int code)
344{
345 unsigned char *address = getAddress(Stream, num << 2, FAT_ACCESS_WRITE);
346 set_dword(address, code);
347}
348
349
350static unsigned int fast_fat32_decode(Fs_t *Stream, unsigned int num)
351{
352 unsigned int *address =
353 (unsigned int *) getAddress(Stream, num << 2,
354 FAT_ACCESS_READ);
355 return *address;
356}
357
358static void fast_fat32_encode(Fs_t *Stream, unsigned int num, unsigned int code)
359{
360 unsigned int *address =
361 (unsigned int *) getAddress(Stream, num << 2,
362 FAT_ACCESS_WRITE);
363 *address = code;
364}
365
366
367/*
368 * Write the FAT table to the disk. Up to now the FAT manipulation has
369 * been done in memory. All errors are fatal. (Might not be too smart
370 * to wait till the end of the program to write the table. Oh well...)
371 */
372
373void fat_write(Fs_t *This)
374{
375 int i, j, dups, ret, bit, slot;
376 int fat_start;
377
378 /*fprintf(stderr, "Fat write\n");*/
379
380 if (!This->fat_dirty)
381 return;
382
383 dups = This->num_fat;
384 if (This->fat_error)
385 dups = 1;
386
387
388 for(i=0; i<dups; i++){
389 j = 0;
390 fat_start = This->fat_start + i*This->fat_len;
391 for(slot=0;j<This->fat_len;slot++) {
392 if(!This->FatMap[slot].dirty) {
393 j += SECT_PER_ENTRY;
394 continue;
395 }
396 for(bit=0;
397 bit < SECT_PER_ENTRY && j<This->fat_len;
398 bit++,j++) {
399 if(!(This->FatMap[slot].dirty & (ONE << bit)))
400 continue;
401 ret = fatWriteSector(This,j,slot, bit, i);
402 if (ret < This->sector_size){
403 if (ret < 0 ){
404 perror("error in fat_write");
405 exit(1);
406 } else {
407 fprintf(stderr,
408 "end of file in fat_write\n");
409 exit(1);
410 }
411 }
412 /* if last dupe, zero it out */
413 if(i==dups-1)
414 This->FatMap[slot].dirty &= ~(1<<bit);
415 }
416 }
417 }
418 /* write the info sector, if any */
419 if(This->infoSectorLoc && This->infoSectorLoc != MAX32) {
420 /* initialize info sector */
421 InfoSector_t *infoSector;
422 infoSector = (InfoSector_t *) safe_malloc(This->sector_size);
423 set_dword(infoSector->signature1, INFOSECT_SIGNATURE1);
424 memset(infoSector->filler1, sizeof(infoSector->filler1),0);
425 memset(infoSector->filler2, sizeof(infoSector->filler2),0);
426 set_dword(infoSector->signature2, INFOSECT_SIGNATURE2);
427 set_dword(infoSector->pos, This->last);
428 set_dword(infoSector->count, This->freeSpace);
429 set_dword(infoSector->signature3, 0xaa55);
430 if(forceWriteSector(This, (char *)infoSector, This->infoSectorLoc, 1) !=
431 This->sector_size)
432 fprintf(stderr,"Trouble writing the info sector\n");
433 free(infoSector);
434 }
435 This->fat_dirty = 0;
436 This->lastFatAccessMode = FAT_ACCESS_READ;
437}
438
439
440
441/*
442 * Zero-Fat
443 * Used by mformat.
444 */
445int zero_fat(Fs_t *Stream, int media_descriptor)
446{
447 int i, j;
448 int fat_start;
449 unsigned char *buf;
450
451 buf = malloc(Stream->sector_size);
452 if(!buf) {
453 perror("alloc fat sector buffer");
454 return -1;
455 }
456 for(i=0; i< Stream->num_fat; i++) {
457 fat_start = Stream->fat_start + i*Stream->fat_len;
458 for(j = 0; j < Stream->fat_len; j++) {
459 if(j <= 1)
460 memset(buf, 0, Stream->sector_size);
461 if(!j) {
462 buf[0] = media_descriptor;
463 buf[2] = buf[1] = 0xff;
464 if(Stream->fat_bits > 12)
465 buf[3] = 0xff;
466 if(Stream->fat_bits > 16) {
467 buf[4] = 0xff;
468 buf[5] = 0xff;
469 buf[6] = 0xff;
470 buf[7] = 0x0f;
471 }
472 }
473
474 if(forceWriteSector(Stream, (char *)buf,
475 fat_start + j, 1) !=
476 Stream->sector_size) {
477 fprintf(stderr,
478 "Trouble initializing a FAT sector\n");
479 free(buf);
480 return -1;
481 }
482 }
483 }
484
485 free(buf);
486 Stream->FatMap = GetFatMap(Stream);
487 if (Stream->FatMap == NULL) {
488 perror("alloc fat map");
489 return -1;
490 }
491 return 0;
492}
493
494
495void set_fat12(Fs_t *This)
496{
497 This->fat_bits = 12;
498 This->end_fat = 0xfff;
499 This->last_fat = 0xff6;
500 This->fat_decode = fat12_decode;
501 This->fat_encode = fat12_encode;
502}
503
504static char word_endian_test[] = { 0x34, 0x12 };
505
506void set_fat16(Fs_t *This)
507{
508 This->fat_bits = 16;
509 This->end_fat = 0xffff;
510 This->last_fat = 0xfff6;
511
512 if(sizeof(unsigned short) == 2 &&
513 * (unsigned short *) word_endian_test == 0x1234) {
514 This->fat_decode = fast_fat16_decode;
515 This->fat_encode = fast_fat16_encode;
516 } else {
517 This->fat_decode = fat16_decode;
518 This->fat_encode = fat16_encode;
519 }
520}
521
522static char dword_endian_test[] = { 0x78, 0x56, 0x34, 0x12 };
523
524void set_fat32(Fs_t *This)
525{
526 This->fat_bits = 32;
527 This->end_fat = 0xfffffff;
528 This->last_fat = 0xffffff6;
529
530 if(sizeof(unsigned int) == 4 &&
531 * (unsigned int *) dword_endian_test == 0x12345678) {
532 This->fat_decode = fast_fat32_decode;
533 This->fat_encode = fast_fat32_encode;
534 } else {
535 This->fat_decode = fat32_decode;
536 This->fat_encode = fat32_encode;
537 }
538}
539
540
541static int check_fat(Fs_t *This)
542{
543 /*
544 * This is only a sanity check. For disks with really big FATs,
545 * there is no point in checking the whole FAT.
546 */
547
548 int i, f, tocheck;
549 if(mtools_skip_check)
550 return 0;
551
552 /* too few sectors in the FAT */
553 if(This->fat_len < NEEDED_FAT_SIZE(This))
554 return -1;
555 /* we do not warn about too much sectors in FAT, which may
556 * happen when a partition has been shrunk using FIPS, or on
557 * other occurrences */
558
559 tocheck = This->num_clus;
560 if (tocheck < 0 || tocheck + 1 >= This->last_fat) {
561 fprintf(stderr, "Too many clusters in FAT\n");
562 return -1;
563 }
564
565 if(tocheck > 4096)
566 tocheck = 4096;
567
568 for ( i= 3 ; i < tocheck; i++){
569 f = This->fat_decode(This,i);
570 if (f == 1 || (f < This->last_fat && f > This->num_clus)){
571 fprintf(stderr,
572 "Cluster # at %d too big(%#x)\n", i,f);
573 fprintf(stderr,"Probably non MS-DOS disk\n");
574 return -1;
575 }
576 }
577 return 0;
578}
579
580
581/*
582 * Read the first sector of FAT table into memory. Crude error detection on
583 * wrong FAT encoding scheme.
584 */
585static int check_media_type(Fs_t *This, struct bootsector *boot,
586 unsigned int tot_sectors)
587{
588 unsigned char *address;
589
590 This->num_clus = (tot_sectors - This->clus_start) / This->cluster_size;
591
592 This->FatMap = GetFatMap(This);
593 if (This->FatMap == NULL) {
594 perror("alloc fat map");
595 return -1;
596 }
597
598 address = getAddress(This, 0, FAT_ACCESS_READ);
599 if(!address) {
600 fprintf(stderr,
601 "Could not read first FAT sector\n");
602 return -1;
603 }
604
605 if(mtools_skip_check)
606 return 0;
607
608 if(!address[0] && !address[1] && !address[2])
609 /* Some Atari disks have zeroes where Dos has media descriptor
610 * and 0xff. Do not consider this as an error */
611 return 0;
612
613 if((address[0] != boot->descr && boot->descr >= 0xf0 &&
614 ((address[0] != 0xf9 && address[0] != 0xf7)
615 || boot->descr != 0xf0)) || address[0] < 0xf0) {
616 fprintf(stderr,
617 "Bad media types %02x/%02x, probably non-MSDOS disk\n",
618 address[0],
619 boot->descr);
620 return -1;
621 }
622
623 if(address[1] != 0xff || address[2] != 0xff){
624 fprintf(stderr,"Initial byte of fat is not 0xff\n");
625 return -1;
626 }
627
628 return 0;
629}
630
631static int fat_32_read(Fs_t *This, struct bootsector *boot,
632 unsigned int tot_sectors)
633{
634 int size;
635
636 This->fat_len = DWORD(ext.fat32.bigFat);
637 This->writeAllFats = !(boot->ext.fat32.extFlags[0] & 0x80);
638 This->primaryFat = boot->ext.fat32.extFlags[0] & 0xf;
639 This->rootCluster = DWORD(ext.fat32.rootCluster);
640 This->clus_start = This->fat_start + This->num_fat * This->fat_len;
641
642 /* read the info sector */
643 size = This->sector_size;
644 This->infoSectorLoc = WORD(ext.fat32.infoSector);
645 if(This->sector_size >= 512 &&
646 This->infoSectorLoc && This->infoSectorLoc != MAX32) {
647 InfoSector_t *infoSector;
648 infoSector = (InfoSector_t *) safe_malloc(size);
649 if(forceReadSector(This, (char *)infoSector,
650 This->infoSectorLoc, 1) == This->sector_size &&
651 _DWORD(infoSector->signature1) == INFOSECT_SIGNATURE1 &&
652 _DWORD(infoSector->signature2) == INFOSECT_SIGNATURE2) {
653 This->freeSpace = _DWORD(infoSector->count);
654 This->last = _DWORD(infoSector->pos);
655 }
656 free(infoSector);
657 }
658
659 set_fat32(This);
660 return(check_media_type(This,boot, tot_sectors) ||
661 check_fat(This));
662}
663
664
665static int old_fat_read(Fs_t *This, struct bootsector *boot,
666 int config_fat_bits,
667 size_t tot_sectors, int nodups)
668{
669 This->writeAllFats = 1;
670 This->primaryFat = 0;
671 This->dir_start = This->fat_start + This->num_fat * This->fat_len;
672 This->clus_start = This->dir_start + This->dir_len;
673 This->infoSectorLoc = MAX32;
674
675 if(nodups)
676 This->num_fat = 1;
677
678 if(check_media_type(This,boot, tot_sectors))
679 return -1;
680
681 if(This->num_clus > FAT12) {
682 set_fat16(This);
683 /* third FAT byte must be 0xff */
684 if(!mtools_skip_check && readByte(This, 3) != 0xff)
685 return -1;
686 } else
687 set_fat12(This);
688
689 return check_fat(This);
690}
691
692/*
693 * Read the first sector of the FAT table into memory and initialize
694 * structures.
695 */
696int fat_read(Fs_t *This, struct bootsector *boot, int fat_bits,
697 size_t tot_sectors, int nodups)
698{
699 This->fat_error = 0;
700 This->fat_dirty = 0;
701 This->last = MAX32;
702 This->freeSpace = MAX32;
703 This->lastFatSectorNr = 0;
704 This->lastFatSectorData = 0;
705
706 if(This->fat_len)
707 return old_fat_read(This, boot, fat_bits, tot_sectors, nodups);
708 else
709 return fat_32_read(This, boot, tot_sectors);
710}
711
712
713unsigned int fatDecode(Fs_t *This, unsigned int pos)
714{
715 int ret;
716
717 ret = This->fat_decode(This, pos);
718 if(ret && (ret < 2 || ret > This->num_clus+1) && ret < This->last_fat) {
719 fprintf(stderr, "Bad FAT entry %d at %d\n", ret, pos);
720 This->fat_error++;
721 }
722 return ret;
723}
724
725/* append a new cluster */
726void fatAppend(Fs_t *This, unsigned int pos, unsigned int newpos)
727{
728 This->fat_encode(This, pos, newpos);
729 This->fat_encode(This, newpos, This->end_fat);
730 if(This->freeSpace != MAX32)
731 This->freeSpace--;
732}
733
734/* de-allocates the given cluster */
735void fatDeallocate(Fs_t *This, unsigned int pos)
736{
737 This->fat_encode(This, pos, 0);
738 if(This->freeSpace != MAX32)
739 This->freeSpace++;
740}
741
742/* allocate a new cluster */
743void fatAllocate(Fs_t *This, unsigned int pos, unsigned int value)
744{
745 This->fat_encode(This, pos, value);
746 if(This->freeSpace != MAX32)
747 This->freeSpace--;
748}
749
750void fatEncode(Fs_t *This, unsigned int pos, unsigned int value)
751{
752 unsigned int oldvalue = This->fat_decode(This, pos);
753 This->fat_encode(This, pos, value);
754 if(This->freeSpace != MAX32) {
755 if(oldvalue)
756 This->freeSpace++;
757 if(value)
758 This->freeSpace--;
759 }
760}
761
762unsigned int get_next_free_cluster(Fs_t *This, unsigned int last)
763{
764 int i;
765
766 if(This->last != MAX32)
767 last = This->last;
768
769 if (last < 2 ||
770 last >= This->num_clus+1)
771 last = 1;
772
773 for (i=last+1; i< This->num_clus+2; i++) {
774 if (!fatDecode(This, i)) {
775 This->last = i;
776 return i;
777 }
778 }
779
780 for(i=2; i < last+1; i++) {
781 if (!fatDecode(This, i)) {
782 This->last = i;
783 return i;
784 }
785 }
786
787
788 fprintf(stderr,"No free cluster %d %d\n", This->preallocatedClusters,
789 This->last);
790 return 1;
791}
792
793int fat_error(Stream_t *Dir)
794{
795 Stream_t *Stream = GetFs(Dir);
796 DeclareThis(Fs_t);
797
798 if(This->fat_error)
799 fprintf(stderr,"Fat error detected\n");
800
801 return This->fat_error;
802}
803
804int fat32RootCluster(Stream_t *Dir)
805{
806 Stream_t *Stream = GetFs(Dir);
807 DeclareThis(Fs_t);
808
809 if(This->fat_bits == 32)
810 return This->rootCluster;
811 else
812 return 0;
813}
814
815
816/*
817 * Get the amount of free space on the diskette
818 */
819
820mt_size_t getfree(Stream_t *Dir)
821{
822 Stream_t *Stream = GetFs(Dir);
823 DeclareThis(Fs_t);
824
825 if(This->freeSpace == MAX32 || This->freeSpace == 0) {
826 register unsigned int i;
827 size_t total;
828
829 total = 0L;
830 for (i = 2; i < This->num_clus + 2; i++)
831 if (!fatDecode(This,i))
832 total++;
833 This->freeSpace = total;
834 }
835 return sectorsToBytes((Stream_t*)This,
836 This->freeSpace * This->cluster_size);
837}
838
839
840/*
841 * Ensure that there is a minimum of total sectors free
842 */
843int getfreeMinClusters(Stream_t *Dir, size_t size)
844{
845 Stream_t *Stream = GetFs(Dir);
846 DeclareThis(Fs_t);
847 register unsigned int i, last;
848 size_t total;
849
850 if(batchmode && This->freeSpace == MAX32)
851 getfree(Stream);
852
853 if(This->freeSpace != MAX32) {
854 if(This->freeSpace >= size)
855 return 1;
856 else {
857 fprintf(stderr, "Disk full\n");
858 got_signal = 1;
859 return 0;
860 }
861 }
862
863 total = 0L;
864
865 /* we start at the same place where we'll start later to actually
866 * allocate the sectors. That way, the same sectors of the FAT, which
867 * are already loaded during getfreeMin will be able to be reused
868 * during get_next_free_cluster */
869 last = This->last;
870
871 if ( last < 2 || last >= This->num_clus + 2)
872 last = 1;
873 for (i=last+1; i< This->num_clus+2; i++){
874 if (!fatDecode(This, i))
875 total++;
876 if(total >= size)
877 return 1;
878 }
879 for(i=2; i < last+1; i++){
880 if (!fatDecode(This, i))
881 total++;
882 if(total >= size)
883 return 1;
884 }
885 fprintf(stderr, "Disk full\n");
886 got_signal = 1;
887 return 0;
888}
889
890
891int getfreeMinBytes(Stream_t *Dir, mt_size_t size)
892{
893 Stream_t *Stream = GetFs(Dir);
894 DeclareThis(Fs_t);
895 size_t size2;
896
897 size2 = size / (This->sector_size * This->cluster_size);
898 if(size % (This->sector_size * This->cluster_size))
899 size2++;
900 return getfreeMinClusters(Dir, size2);
901}
902
903
904unsigned int getStart(Stream_t *Dir, struct directory *dir)
905{
906 Stream_t *Stream = GetFs(Dir);
907 unsigned int first;
908
909 first = START(dir);
910 if(fat32RootCluster(Stream))
911 first |= STARTHI(dir) << 16;
912 return first;
913}
914
915int fs_free(Stream_t *Stream)
916{
917 DeclareThis(Fs_t);
918
919 if(This->FatMap) {
920 int i, nr_entries;
921 nr_entries = (This->fat_len + SECT_PER_ENTRY - 1) /
922 SECT_PER_ENTRY;
923 for(i=0; i< nr_entries; i++)
924 if(This->FatMap[i].data)
925 free(This->FatMap[i].data);
926 free(This->FatMap);
927 }
928 return 0;
929}
Note: See TracBrowser for help on using the repository browser.