1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * Copyright 2004 Martin Fuchs
3*c2c66affSColin Finck  *
4*c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
5*c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
6*c2c66affSColin Finck  * License as published by the Free Software Foundation; either
7*c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
8*c2c66affSColin Finck  *
9*c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
10*c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12*c2c66affSColin Finck  * Lesser General Public License for more details.
13*c2c66affSColin Finck  *
14*c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
15*c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
16*c2c66affSColin Finck  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17*c2c66affSColin Finck  */
18*c2c66affSColin Finck 
19*c2c66affSColin Finck 
20*c2c66affSColin Finck  //
21*c2c66affSColin Finck  // Explorer clone
22*c2c66affSColin Finck  //
23*c2c66affSColin Finck  // fatfs.h
24*c2c66affSColin Finck  //
25*c2c66affSColin Finck  // Martin Fuchs, 01.02.2004
26*c2c66affSColin Finck  //
27*c2c66affSColin Finck 
28*c2c66affSColin Finck 
29*c2c66affSColin Finck  /// FAT file system file-entry
30*c2c66affSColin Finck struct FATEntry : public Entry
31*c2c66affSColin Finck {
FATEntryFATEntry32*c2c66affSColin Finck 	FATEntry(Entry* parent, unsigned cluster) : Entry(parent, ET_FAT), _cluster(cluster) {}
33*c2c66affSColin Finck 
34*c2c66affSColin Finck protected:
FATEntryFATEntry35*c2c66affSColin Finck 	FATEntry() : Entry(ET_FAT) {}
36*c2c66affSColin Finck 
37*c2c66affSColin Finck 	virtual bool get_path(PTSTR path, size_t path_count) const;
38*c2c66affSColin Finck 	virtual ShellPath create_absolute_pidl() const;
39*c2c66affSColin Finck 
40*c2c66affSColin Finck 	DWORD	_cluster;
41*c2c66affSColin Finck };
42*c2c66affSColin Finck 
43*c2c66affSColin Finck 
44*c2c66affSColin Finck struct FATDrive;
45*c2c66affSColin Finck 
46*c2c66affSColin Finck  /// FAT file system directory-entry
47*c2c66affSColin Finck struct FATDirectory : public FATEntry, public Directory
48*c2c66affSColin Finck {
49*c2c66affSColin Finck 	FATDirectory(FATDrive& drive, LPCTSTR root_path);
50*c2c66affSColin Finck 	FATDirectory(FATDrive& drive, Entry* parent, LPCTSTR path, unsigned cluster);
51*c2c66affSColin Finck 	~FATDirectory();
52*c2c66affSColin Finck 
53*c2c66affSColin Finck 	virtual void read_directory(int scan_flags=0);
54*c2c66affSColin Finck 	virtual const void* get_next_path_component(const void*) const;
55*c2c66affSColin Finck 	virtual Entry* find_entry(const void*);
56*c2c66affSColin Finck 
57*c2c66affSColin Finck protected:
58*c2c66affSColin Finck 	FATDrive&	_drive;
59*c2c66affSColin Finck 
60*c2c66affSColin Finck 	struct dirsecz* _secarr;
61*c2c66affSColin Finck 	int 	_cur_bufs;
62*c2c66affSColin Finck 	int 	_ents;
63*c2c66affSColin Finck 	struct dirent* _dir;
64*c2c66affSColin Finck 	struct Kette* _alloc;
65*c2c66affSColin Finck 
66*c2c66affSColin Finck 	bool	read_dir();
67*c2c66affSColin Finck };
68*c2c66affSColin Finck 
69*c2c66affSColin Finck 
70*c2c66affSColin Finck #pragma pack(push, 1)
71*c2c66affSColin Finck 
72*c2c66affSColin Finck struct BootSector {
73*c2c66affSColin Finck 	BYTE	jmp[3];
74*c2c66affSColin Finck 	char	OEM[8];
75*c2c66affSColin Finck 	WORD	BytesPerSector; 	// dpb.bsec
76*c2c66affSColin Finck 	BYTE	SectorsPerCluster;	// dpb.sclus + 1
77*c2c66affSColin Finck 	WORD	ReservedSectors;	// dpb.ffatsec
78*c2c66affSColin Finck 	BYTE	NumberFATs;
79*c2c66affSColin Finck 	WORD	RootEntries;		// dpb.ndir
80*c2c66affSColin Finck 	WORD	Sectors16;
81*c2c66affSColin Finck 	BYTE	MediaDescr;
82*c2c66affSColin Finck 	WORD	SectorsPerFAT;
83*c2c66affSColin Finck 	WORD	SectorsPerTrack;
84*c2c66affSColin Finck 	WORD	Heads;
85*c2c66affSColin Finck 	DWORD	HiddenSectors;
86*c2c66affSColin Finck 	DWORD	Sectors32;
87*c2c66affSColin Finck 	BYTE	DriveUnit;
88*c2c66affSColin Finck 	WORD	ExtBootFlag;
89*c2c66affSColin Finck 	DWORD	SerialNr;
90*c2c66affSColin Finck 	char	Label[11];
91*c2c66affSColin Finck 	char	FileSystem[8];
92*c2c66affSColin Finck 	BYTE	BootCode[448];
93*c2c66affSColin Finck 	BYTE	BootSignature[2];
94*c2c66affSColin Finck };
95*c2c66affSColin Finck 
96*c2c66affSColin Finck struct BootSector32 {
97*c2c66affSColin Finck 	BYTE	jmp[3];
98*c2c66affSColin Finck 	char	OEM[8];
99*c2c66affSColin Finck 	WORD	BytesPerSector;
100*c2c66affSColin Finck 	BYTE	SectorsPerCluster;
101*c2c66affSColin Finck 	WORD	ReservedSectors;
102*c2c66affSColin Finck 	BYTE	NumberFATs;
103*c2c66affSColin Finck 	WORD	reserved1;	// immer 0 f�r FAT32
104*c2c66affSColin Finck 	WORD	Sectors16;
105*c2c66affSColin Finck 	BYTE	MediaDescr;
106*c2c66affSColin Finck 	WORD	reserved2;	// immer 0 f�r FAT32
107*c2c66affSColin Finck 	WORD	SectorsPerTrack;
108*c2c66affSColin Finck 	WORD	Heads;
109*c2c66affSColin Finck 	DWORD	HiddenSectors;
110*c2c66affSColin Finck 	DWORD	Sectors32;
111*c2c66affSColin Finck 	DWORD	SectorsPerFAT32;
112*c2c66affSColin Finck 	DWORD	unknown1;
113*c2c66affSColin Finck 	DWORD	RootSectors; // correct?
114*c2c66affSColin Finck 	char	unknown2[6];
115*c2c66affSColin Finck 	char	FileSystem[8];
116*c2c66affSColin Finck 	BYTE	BootCode[448];
117*c2c66affSColin Finck 	BYTE	BootSignature[2];
118*c2c66affSColin Finck };
119*c2c66affSColin Finck 
120*c2c66affSColin Finck 
121*c2c66affSColin Finck struct filetime {
122*c2c66affSColin Finck 	WORD	sec2	: 5;
123*c2c66affSColin Finck 	WORD	min 	: 6;
124*c2c66affSColin Finck 	WORD	hour	: 5;
125*c2c66affSColin Finck };
126*c2c66affSColin Finck 
127*c2c66affSColin Finck struct filedate {
128*c2c66affSColin Finck 	WORD	day 	: 5;
129*c2c66affSColin Finck 	WORD	month	: 4;
130*c2c66affSColin Finck 	WORD	year	: 7;
131*c2c66affSColin Finck };
132*c2c66affSColin Finck 
133*c2c66affSColin Finck typedef struct {
134*c2c66affSColin Finck 	unsigned readonly	: 1;
135*c2c66affSColin Finck 	unsigned hidden		: 1;
136*c2c66affSColin Finck 	unsigned system		: 1;
137*c2c66affSColin Finck 	unsigned volume		: 1;
138*c2c66affSColin Finck 	unsigned directory 	: 1;
139*c2c66affSColin Finck 	unsigned archived	: 1;
140*c2c66affSColin Finck 	unsigned deleted	: 1;
141*c2c66affSColin Finck } fattr;
142*c2c66affSColin Finck 
143*c2c66affSColin Finck typedef union {
144*c2c66affSColin Finck 	char	b;
145*c2c66affSColin Finck 	fattr  a;
146*c2c66affSColin Finck } FAT_attribute;
147*c2c66affSColin Finck 
148*c2c66affSColin Finck struct DEntry_E {
149*c2c66affSColin Finck 	char			name[8];
150*c2c66affSColin Finck 	char			ext[3];
151*c2c66affSColin Finck 	char			attr;
152*c2c66affSColin Finck 	char			rsrvd[10];
153*c2c66affSColin Finck 	struct filetime	time;
154*c2c66affSColin Finck 	struct filedate	date;
155*c2c66affSColin Finck 	WORD			fclus;
156*c2c66affSColin Finck 	DWORD 			size;
157*c2c66affSColin Finck };
158*c2c66affSColin Finck 
159*c2c66affSColin Finck union DEntry {
160*c2c66affSColin Finck 	DEntry_E E;
161*c2c66affSColin Finck 	BYTE B[8+3+1+10+sizeof(struct filetime)+sizeof(struct filedate)+sizeof(WORD)+sizeof(DWORD)];
162*c2c66affSColin Finck };
163*c2c66affSColin Finck 
164*c2c66affSColin Finck #pragma pack(pop)
165*c2c66affSColin Finck 
166*c2c66affSColin Finck 
167*c2c66affSColin Finck #define BufLen	512
168*c2c66affSColin Finck 
169*c2c66affSColin Finck struct Buffer {
170*c2c66affSColin Finck  BYTE	dat[BufLen];
171*c2c66affSColin Finck };
172*c2c66affSColin Finck 
173*c2c66affSColin Finck struct Cache {
174*c2c66affSColin Finck  BYTE	dat[BufLen];
175*c2c66affSColin Finck };
176*c2c66affSColin Finck 
177*c2c66affSColin Finck struct dskrwblk {
178*c2c66affSColin Finck  DWORD			sec;
179*c2c66affSColin Finck  WORD			anz;
180*c2c66affSColin Finck  struct buffer	far *buf;
181*c2c66affSColin Finck };
182*c2c66affSColin Finck 
183*c2c66affSColin Finck #define RONLY			0x01
184*c2c66affSColin Finck #define HIDDEN			0x02
185*c2c66affSColin Finck #define SYSTEM			0x04
186*c2c66affSColin Finck #define VOLUME			0x08
187*c2c66affSColin Finck #define DIRENT			0x10
188*c2c66affSColin Finck #define ARCHIVE 		0x20
189*c2c66affSColin Finck 
190*c2c66affSColin Finck #define _A_DELETED		0x40
191*c2c66affSColin Finck #define _A_ILLEGAL		0x80
192*c2c66affSColin Finck #define IS_LNAME(a) ((a&0xFF)==0x0F)	// "& 0xFF" correct?
193*c2c66affSColin Finck 
194*c2c66affSColin Finck #define FAT_DEL_CHAR	(char)0xe5
195*c2c66affSColin Finck 
196*c2c66affSColin Finck #define AddP(p,s)  {(int&)p += s;}
197*c2c66affSColin Finck 
198*c2c66affSColin Finck struct dirent {
199*c2c66affSColin Finck 	union DEntry  ent[1];
200*c2c66affSColin Finck };
201*c2c66affSColin Finck 
202*c2c66affSColin Finck struct dirsecz {
203*c2c66affSColin Finck 	DWORD  s[32];  // 32 only as placeholder
204*c2c66affSColin Finck };
205*c2c66affSColin Finck 
206*c2c66affSColin Finck struct Kette {
207*c2c66affSColin Finck  struct Kette*	Vorw;
208*c2c66affSColin Finck  struct Kette*	Rueck;
209*c2c66affSColin Finck  union DEntry*	Ent;
210*c2c66affSColin Finck };
211*c2c66affSColin Finck 
212*c2c66affSColin Finck 
213*c2c66affSColin Finck #define	MK_P(ofs)		((void*) ((size_t)(ofs)))
214*c2c66affSColin Finck #define	MK_LONG(l,h)	((DWORD)WORD(l)|((DWORD)WORD(h)<<16))
215*c2c66affSColin Finck 
216*c2c66affSColin Finck #define	spoke(ofs,w)	(*((BYTE*)MK_P(ofs)) = (BYTE)(w))
217*c2c66affSColin Finck #define	wpoke(ofs,w)	(*((WORD*)MK_P(ofs)) = (WORD)(w))
218*c2c66affSColin Finck #define	dpoke(ofs,w)	(*((DWORD*)MK_P(ofs)) = (DWORD)(w))
219*c2c66affSColin Finck #define	speek(ofs)		(*((BYTE*)MK_P(ofs)))
220*c2c66affSColin Finck #define	wpeek(ofs)		(*((WORD*)MK_P(ofs)))
221*c2c66affSColin Finck #define	dpeek(p)		(*((DWORD*)MK_P(p)))
222*c2c66affSColin Finck 
223*c2c66affSColin Finck 
224*c2c66affSColin Finck  /// FAT drive root entry
225*c2c66affSColin Finck struct FATDrive : public FATDirectory
226*c2c66affSColin Finck {
227*c2c66affSColin Finck 	FATDrive(LPCTSTR path);
228*c2c66affSColin Finck /*
229*c2c66affSColin Finck 	FATDrive(Entry* parent, LPCTSTR path)
230*c2c66affSColin Finck 	 :	FATEntry(parent)
231*c2c66affSColin Finck 	{
232*c2c66affSColin Finck 		_path = _tcsdup(path);
233*c2c66affSColin Finck 	}
234*c2c66affSColin Finck */
235*c2c66affSColin Finck 	~FATDrive();
236*c2c66affSColin Finck 
237*c2c66affSColin Finck 	HANDLE	_hDrive;
238*c2c66affSColin Finck 	BootSector	_boot_sector;
239*c2c66affSColin Finck 	int 	_bufl;
240*c2c66affSColin Finck 	int 	_bufents;
241*c2c66affSColin Finck 	int 	_SClus;
242*c2c66affSColin Finck 
243*c2c66affSColin Finck #define	CACHE_SIZE_LOW	32
244*c2c66affSColin Finck 	Cache*	_FATCache;
245*c2c66affSColin Finck 	int		_CacheCount;
246*c2c66affSColin Finck 	DWORD*	_CacheSec;	// numbers of buffered cache sectors
247*c2c66affSColin Finck 	int*	_CacheCnt;	// counters for cache usage
248*c2c66affSColin Finck 	bool*	_CacheDty;	// dirty flags for cache
249*c2c66affSColin Finck 	int		_Caches;
250*c2c66affSColin Finck 	bool	_cache_empty;
251*c2c66affSColin Finck 	int		_read_ahead;
252*c2c66affSColin Finck 
253*c2c66affSColin Finck 	bool	read_sector(DWORD sec, Buffer* buf, int len);
254*c2c66affSColin Finck 	DWORD	read_FAT(DWORD Clus, bool& ok);
255*c2c66affSColin Finck 
256*c2c66affSColin Finck 	void	small_cache();
257*c2c66affSColin Finck 	void	reset_cache();
258*c2c66affSColin Finck 	bool	read_cache(DWORD sec, Buffer** bufptr);
259*c2c66affSColin Finck 	int		get_cache_buffer();
260*c2c66affSColin Finck };
261