root / Whitix / branches / hybrid / fs / fat / dir.c

Revision 138, 7.3 kB (checked in by mwhitworth, 8 months ago)

Change behaviour when ReadDir buffer is full.

Line 
1/*  This file is part of Whitix.
2 *
3 *  Whitix is free software; you can redistribute it and/or modify
4 *  it under the terms of the GNU General Public License as published by
5 *  the Free Software Foundation; either version 2 of the License, or
6 *  (at your option) any later version.
7 *
8 *  Whitix is distributed in the hope that it will be useful,
9 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 *  GNU General Public License for more details.
12 *
13 *  You should have received a copy of the GNU General Public License
14 *  along with Whitix; if not, write to the Free Software
15 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16 *
17 */
18
19#include "fat.h"
20
21#include <console.h>
22#include <error.h>
23#include <typedefs.h>
24
25/***********************************************************************
26 *
27 * FUNCTION: FatGetDirEntry
28 *
29 * DESCRIPTION: Get the directory entry at currPos
30 *
31 * PARAMETERS: vNode - vNode to find directory entry in.
32 *                         dirEntry - directory entry structure to fill in.
33 *                         currPos - current position in the vNode.
34 *
35 * RETURNS: Usual error codes in error.h
36 *
37 ***********************************************************************/
38
39int FatGetDirEntry(struct VNode* vNode,struct FatDirEntry* dirEntry,int currPos)
40{
41        struct Buffer* buff;
42        int offset;
43
44        if (!vNode || !vNode->superBlock)
45                return -EFAULT;
46
47        buff=FatBlockRead(vNode,currPos/BYTES_PER_SECTOR(vNode->superBlock));
48        if (!buff)
49                return -EIO;
50
51        offset=currPos & (BYTES_PER_SECTOR(vNode->superBlock)-1);
52        memcpy((char*)dirEntry,(char*)((DWORD)buff->data+offset),sizeof(struct FatDirEntry));
53
54        BlockFree(buff);
55        return 0;
56}
57
58/***********************************************************************
59 *
60 * FUNCTION: FatGetLongName
61 *
62 * DESCRIPTION: Get the long file name for a directory entry.
63 *
64 * PARAMETERS: vNode - directory vfs node.
65 *                         pos - position in vNode.
66 *                         longName - buffer to return name into.
67 *                         currDirEntry - current directory entry to return info to.
68 *
69 * RETURNS: Usual error codes in error.h
70 *
71 ***********************************************************************/
72
73int FatGetLongName(struct VNode* vNode,int* pos,char* longName,struct FatDirEntry* currDirEntry)
74{
75        struct FatDirSlot* slot=(struct FatDirSlot*)currDirEntry;
76        DWORD numSlots=FAT_LONG_ENTRIES(slot->id);
77        BYTE checkSum=slot->checkSum,shortCheckSum;
78        int offset,i;
79
80        if (!(FAT_IS_LONG(slot->id)) || !numSlots || numSlots > 20)
81                return -EINVAL;
82
83        while (1)
84        {
85                numSlots--;
86                offset=numSlots*13; /* 13 characters are stored per directory slot */
87
88                for (i=0; i<5; i++)
89                        longName[offset+i]=slot->name[i*2];
90
91                for (i=0; i<6; i++)
92                        longName[offset+5+i]=slot->name2[i*2];
93
94                for (i=0; i<2; i++)
95                        longName[offset+11+i]=slot->name3[i*2];
96
97                /* End of name */
98                if (slot->id & 0x40)
99                        longName[offset+13]='\0';
100
101                FatGetDirEntry(vNode,currDirEntry,FAT_DIR_POS(*pos));
102               
103                ++(*pos);
104
105                if (!numSlots)
106                        break;
107
108                slot=(struct FatDirSlot*)currDirEntry;
109
110                /* Several sanity checks */
111                if (slot->attr != ATTR_EXT || (FAT_LONG_ENTRIES(slot->id)) != numSlots || (slot->checkSum != checkSum))
112                        return -EINVAL;
113        }
114
115        /* Check that the checksum of the current (short entry) is the same
116           as all the checksums before. */
117        shortCheckSum=FatCheckSum(currDirEntry->fileName);
118
119        if (UNLIKELY(shortCheckSum != checkSum))
120                return -EINVAL;
121        else
122                return 0;
123}
124
125/***********************************************************************
126 *
127 * FUNCTION: FatScanDir
128 *
129 * DESCRIPTION: Scan a directory for a name or a free entry.
130 *
131 * PARAMETERS: vNode - directory vfs node.
132 *                         name - name of entry to be found.
133 *                         nameLength - length of name.
134 *                         retVal - directory entry to be returned.
135 *                         vNum - vfs node number to be returned.
136 *
137 * RETURNS: Usual error codes in error.h
138 *
139 ***********************************************************************/
140
141int FatScanDir(struct VNode* vNode,const char* name,int nameLength,struct FatDirEntry* retVal,DWORD* vNum,DWORD* dirPos)
142{
143        int pos=0,sec,offset,found=0,isLongName=0;
144        struct FatDirEntry currDirEntry;
145        char longName[255];
146        char fatName[12];
147
148        /*
149         * If the name is shorter than 11 characters, and not funnily formatted
150         * then there will not be a long file name entry for it, so we must refer
151         * back to the short name entry.
152         */
153
154//      printf("%s, nameLen = %d, base len = %d, extension len = %d\n",name,nameLength,FatBaseNameLen(name,nameLength),FatExtensionLen(name,nameLength));
155
156        if (!FatIsLong(name,nameLength))
157                if (FatCreateShortName(vNode,fatName,(char*)name,nameLength))
158                        return -EINVAL;
159
160        while (pos < vNode->size)
161        {
162                /* No more directory entries */
163                if (FatGetDirEntry(vNode,&currDirEntry,FAT_DIR_POS(pos)))
164                        break;
165
166                FatPosToSecOffset(vNode,pos,&sec,&offset);
167                ++pos;
168
169                if (!currDirEntry.fileName[0])
170                        break;
171
172                if (!FAT_VALID_DE(&currDirEntry))
173                        continue;
174
175                if (currDirEntry.attribute == ATTR_EXT)
176                {
177                        /* Failed to get the long name? */
178                        if (FatGetLongName(vNode,&pos,longName,&currDirEntry))
179                                continue;
180
181                        FatPosToSecOffset(vNode,pos-1,&sec,&offset);
182                        isLongName=1;
183                }
184
185                if (isLongName)
186                {
187                        /* Compare normal name */
188                        if (nameLength == strlen(longName) && !strnicmp(name,longName,strlen(longName)))
189                                found=1;
190
191                        isLongName=0;
192                }else
193                        /* Otherwise compare 8.3 name */
194                        if (!strncmp((const char*)currDirEntry.fileName,fatName,11))
195                                found=1;
196
197                if (found)
198                {
199                        if (retVal)
200                                memcpy(retVal,&currDirEntry,sizeof(struct FatDirEntry));
201
202                        if (vNum)
203                                *vNum=SS_TO_VNUM(sec,offset);
204
205                        if (dirPos)
206                                *dirPos=--pos;
207
208                        return 0;
209                }
210        }
211
212        return -ENOENT;
213}
214
215/***********************************************************************
216 *
217 * FUNCTION: FatReadDir
218 *
219 * DESCRIPTION: Read directory entries into a buffer.
220 *
221 * PARAMETERS: file - directory in question.
222 *                         dirEntries - parameter to VfsFillDir.
223 *
224 * RETURNS: Usual error codes in error.h
225 *
226 ***********************************************************************/
227
228int FatReadDir(struct File* file,void* dirEntries)
229{
230        struct FatDirEntry currDirEntry;
231        int sec,offset;
232        char* fillName;
233        char newName[12]="";
234        char longName[256]; /* Used as a buffer. */
235        int isLongName=0;
236
237        while (file->position < file->vNode->size)
238        {
239                if (FatGetDirEntry(file->vNode,&currDirEntry,FAT_DIR_POS(file->position)))
240                        break;
241
242                FatPosToSecOffset(file->vNode,file->position,&sec,&offset);
243
244                ++file->position;
245
246                /* Means there are no new entries */
247                if (!currDirEntry.fileName[0])
248                        break;
249
250                if (!FAT_VALID_DE(&currDirEntry))
251                        continue;
252
253                if ((currDirEntry.attribute & ATTR_LABEL) && currDirEntry.attribute != ATTR_EXT)
254                        continue;
255
256                if (currDirEntry.attribute == ATTR_EXT)
257                {
258                        if (FatGetLongName(file->vNode,&file->position,longName,&currDirEntry))
259                                continue;
260
261                        FatPosToSecOffset(file->vNode,file->position-1,&sec,&offset);
262                        isLongName=1;
263                }
264
265                if (isLongName)
266                {
267                        fillName=longName;
268                        isLongName=0;
269                }else{
270                        FatNameToStr(currDirEntry.fileName,newName);
271                        fillName=newName;
272                }
273
274                if (FillDir(dirEntries,fillName,strlen(fillName),SS_TO_VNUM(sec,offset)))
275                        break;
276        }
277
278        return 0;
279}
Note: See TracBrowser for help on using the browser.