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