source: rtems/c/src/lib/libbsp/arm/nds/libfat/source/fatdir.c @ 311dfa6

4.104.114.95
Last change on this file since 311dfa6 was 311dfa6, checked in by Joel Sherrill <joel.sherrill@…>, on 04/16/08 at 18:37:33

2008-04-16 Matthieu Bucchianeri <mbucchia@…>

  • ChangeLog?, Makefile.am, README, bsp_specs, configure.ac, mk_libnds.sh, patch.libnds, preinstall.am, block/block.c, clock/clock.c, console/console.c, coproc/coproc.S, coproc/coproc.c, coproc/coproc.ld, dswifi/dswifi_license.txt, dswifi/makefile, dswifi/arm7/makefile, dswifi/arm7/source/wifi_arm7.c, dswifi/arm7/source/wifi_arm7.h, dswifi/arm9/makefile, dswifi/arm9/source/sgIP.c, dswifi/arm9/source/sgIP.h, dswifi/arm9/source/sgIP_ARP.c, dswifi/arm9/source/sgIP_ARP.h, dswifi/arm9/source/sgIP_Config.h, dswifi/arm9/source/sgIP_DHCP.c, dswifi/arm9/source/sgIP_DHCP.h, dswifi/arm9/source/sgIP_DNS.c, dswifi/arm9/source/sgIP_DNS.h, dswifi/arm9/source/sgIP_Hub.c, dswifi/arm9/source/sgIP_Hub.h, dswifi/arm9/source/sgIP_ICMP.c, dswifi/arm9/source/sgIP_ICMP.h, dswifi/arm9/source/sgIP_IP.c, dswifi/arm9/source/sgIP_IP.h, dswifi/arm9/source/sgIP_TCP.c, dswifi/arm9/source/sgIP_TCP.h, dswifi/arm9/source/sgIP_UDP.c, dswifi/arm9/source/sgIP_UDP.h, dswifi/arm9/source/sgIP_memblock.c, dswifi/arm9/source/sgIP_memblock.h, dswifi/arm9/source/sgIP_sockets.c, dswifi/arm9/source/sgIP_sockets.h, dswifi/arm9/source/wifi_arm9.c, dswifi/arm9/source/wifi_arm9.h, dswifi/common/source/dsregs.h, dswifi/common/source/spinlock.h, dswifi/common/source/spinlock.s, dswifi/common/source/wifi_shared.h, dswifi/include/dswifi7.h, dswifi/include/dswifi9.h, dswifi/include/dswifi_version.h, dswifi/include/netdb.h, dswifi/include/sgIP_errno.h, dswifi/include/netinet/in.h, fb/fb.c, fb/fb.h, include/bsp.h, include/my_ipc.h, include/tm27.h, include/types.h, include/sys/iosupport.h, irq/irq.c, irq/irq.h, libfat/gba/include/fat.h, libfat/include/fat.h, libfat/nds/include/fat.h, libfat/source/bit_ops.h, libfat/source/cache.c, libfat/source/cache.h, libfat/source/common.h, libfat/source/directory.c, libfat/source/directory.h, libfat/source/fatdir.c, libfat/source/fatdir.h, libfat/source/fatfile.c, libfat/source/fatfile.h, libfat/source/file_allocation_table.c, libfat/source/file_allocation_table.h, libfat/source/filetime.c, libfat/source/filetime.h, libfat/source/libfat.c, libfat/source/mem_allocate.h, libfat/source/partition.c, libfat/source/partition.h, libfat/source/disc_io/disc.c, libfat/source/disc_io/disc.h, libfat/source/disc_io/disc_io.h, libfat/source/disc_io/io_cf_common.c, libfat/source/disc_io/io_cf_common.h, libfat/source/disc_io/io_dldi.h, libfat/source/disc_io/io_dldi.s, libfat/source/disc_io/io_efa2.c, libfat/source/disc_io/io_efa2.h, libfat/source/disc_io/io_fcsr.c, libfat/source/disc_io/io_fcsr.h, libfat/source/disc_io/io_m3_common.c, libfat/source/disc_io/io_m3_common.h, libfat/source/disc_io/io_m3cf.c, libfat/source/disc_io/io_m3cf.h, libfat/source/disc_io/io_m3sd.c, libfat/source/disc_io/io_m3sd.h, libfat/source/disc_io/io_mpcf.c, libfat/source/disc_io/io_mpcf.h, libfat/source/disc_io/io_njsd.c, libfat/source/disc_io/io_njsd.h, libfat/source/disc_io/io_nmmc.c, libfat/source/disc_io/io_nmmc.h, libfat/source/disc_io/io_sc_common.c, libfat/source/disc_io/io_sc_common.h, libfat/source/disc_io/io_sccf.c, libfat/source/disc_io/io_sccf.h, libfat/source/disc_io/io_scsd.c, libfat/source/disc_io/io_scsd.h, libfat/source/disc_io/io_scsd_s.s, libfat/source/disc_io/io_sd_common.c, libfat/source/disc_io/io_sd_common.h, libnds/Makefile.arm7, libnds/Makefile.arm9, libnds/libnds_license.txt, libnds/basicARM7/source/defaultARM7.c, libnds/include/default_font_bin.h, libnds/include/gbfs.h, libnds/include/nds.h, libnds/include/nds/bios.h, libnds/include/nds/card.h, libnds/include/nds/dma.h, libnds/include/nds/interrupts.h, libnds/include/nds/ipc.h, libnds/include/nds/jtypes.h, libnds/include/nds/memory.h, libnds/include/nds/registers_alt.h, libnds/include/nds/reload.h, libnds/include/nds/system.h, libnds/include/nds/timers.h, libnds/include/nds/arm7/audio.h, libnds/include/nds/arm7/clock.h, libnds/include/nds/arm7/serial.h, libnds/include/nds/arm7/touch.h, libnds/include/nds/arm9/background.h, libnds/include/nds/arm9/boxtest.h, libnds/include/nds/arm9/cache.h, libnds/include/nds/arm9/console.h, libnds/include/nds/arm9/exceptions.h, libnds/include/nds/arm9/image.h, libnds/include/nds/arm9/input.h, libnds/include/nds/arm9/math.h, libnds/include/nds/arm9/ndsmotion.h, libnds/include/nds/arm9/pcx.h, libnds/include/nds/arm9/postest.h, libnds/include/nds/arm9/rumble.h, libnds/include/nds/arm9/sound.h, libnds/include/nds/arm9/sprite.h, libnds/include/nds/arm9/trig_lut.h, libnds/include/nds/arm9/video.h, libnds/include/nds/arm9/videoGL.h, libnds/source/arm7/audio.c, libnds/source/arm7/clock.c, libnds/source/arm7/microphone.c, libnds/source/arm7/spi.c, libnds/source/arm7/touch.c, libnds/source/arm7/userSettings.c, libnds/source/arm9/COS.bin, libnds/source/arm9/COS.s, libnds/source/arm9/SIN.bin, libnds/source/arm9/SIN.s, libnds/source/arm9/TAN.bin, libnds/source/arm9/TAN.s, libnds/source/arm9/boxtest.c, libnds/source/arm9/console.c, libnds/source/arm9/dcache.s, libnds/source/arm9/default_font.bin, libnds/source/arm9/default_font.s, libnds/source/arm9/exceptionHandler.S, libnds/source/arm9/exceptionHandler.s, libnds/source/arm9/exceptions.c, libnds/source/arm9/gurumeditation.c, libnds/source/arm9/icache.s, libnds/source/arm9/image.c, libnds/source/arm9/initSystem.c, libnds/source/arm9/keys.c, libnds/source/arm9/ndsmotion.c, libnds/source/arm9/pcx.c, libnds/source/arm9/rumble.c, libnds/source/arm9/sound.c, libnds/source/arm9/system.c, libnds/source/arm9/touch.c, libnds/source/arm9/video.c, libnds/source/arm9/videoGL.c, libnds/source/common/biosCalls.s, libnds/source/common/card.c, libnds/source/common/gbfs.c, libnds/source/common/interruptDispatcher.s, libnds/source/common/interrupts.c, rtc/rtc.c, sound/sound.c, sound/sound.h, start/start.S, startup/linkcmds, startup/start.c, timer/timer.c, tools/Makefile.am, tools/bin2s, tools/bin2s.c, tools/configure.ac, tools/runtest, tools/ndstool/include/arm7_sha1_homebrew.h, tools/ndstool/include/arm7_sha1_nintendo.h, tools/ndstool/include/banner.h, tools/ndstool/include/bigint.h, tools/ndstool/include/crc.h, tools/ndstool/include/default_icon.h, tools/ndstool/include/encryption.h, tools/ndstool/include/header.h, tools/ndstool/include/hook.h, tools/ndstool/include/little.h, tools/ndstool/include/loadme.h, tools/ndstool/include/logo.h, tools/ndstool/include/ndscreate.h, tools/ndstool/include/ndsextract.h, tools/ndstool/include/ndstool.h, tools/ndstool/include/ndstree.h, tools/ndstool/include/overlay.h, tools/ndstool/include/passme.h, tools/ndstool/include/passme_sram.h, tools/ndstool/include/passme_vhd1.h, tools/ndstool/include/passme_vhd2.h, tools/ndstool/include/raster.h, tools/ndstool/include/sha1.h, tools/ndstool/include/types.h, tools/ndstool/source/arm7_sha1_homebrew.c, tools/ndstool/source/arm7_sha1_nintendo.c, tools/ndstool/source/banner.cpp, tools/ndstool/source/bigint.cpp, tools/ndstool/source/compile_date.c, tools/ndstool/source/crc.cpp, tools/ndstool/source/default_icon.c, tools/ndstool/source/encryption.cpp, tools/ndstool/source/header.cpp, tools/ndstool/source/hook.cpp, tools/ndstool/source/loadme.c, tools/ndstool/source/logo.cpp, tools/ndstool/source/ndscodes.cpp, tools/ndstool/source/ndscreate.cpp, tools/ndstool/source/ndsextract.cpp, tools/ndstool/source/ndstool.cpp, tools/ndstool/source/ndstree.cpp, tools/ndstool/source/passme.cpp, tools/ndstool/source/passme_sram.c, tools/ndstool/source/raster.cpp, tools/ndstool/source/sha1.cpp, touchscreen/README.reco, touchscreen/parser.c, touchscreen/reco.c, touchscreen/reco.h, touchscreen/touchscreen.c, touchscreen/touchscreen.h, wifi/compat.c, wifi/compat.h, wifi/wifi.c: New files.
  • Property mode set to 100644
File size: 14.3 KB
Line 
1/*
2 fatdir.c
3 
4 Functions used by the newlib disc stubs to interface with
5 this library
6
7 Copyright (c) 2006 Michael "Chishm" Chisholm
8       
9 Redistribution and use in source and binary forms, with or without modification,
10 are permitted provided that the following conditions are met:
11
12  1. Redistributions of source code must retain the above copyright notice,
13     this list of conditions and the following disclaimer.
14  2. Redistributions in binary form must reproduce the above copyright notice,
15     this list of conditions and the following disclaimer in the documentation and/or
16     other materials provided with the distribution.
17  3. The name of the author may not be used to endorse or promote products derived
18     from this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
21 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30        2006-08-13 - Chishm
31                * Moved all externally visible directory related functions to fatdir
32                * Added _FAT_mkdir_r
33               
34        2006-08-14 - Chishm
35                * Added directory iterator functions
36
37        2006-08-19 - Chishm
38                * Updated dirnext return values to return correctly
39               
40        2006-10-01 - Chishm
41                * Now clears the whole cluster when creating a new directory, bug found by Hermes
42               
43        2007-01-10 - Chishm
44                * Updated directory iterator functions for DevkitPro r20
45*/
46
47#include <string.h>
48#include <errno.h>
49#include <ctype.h>
50#include <unistd.h>
51#include <sys/dir.h>
52
53#include "fatdir.h"
54
55#include "cache.h"
56#include "file_allocation_table.h"
57#include "partition.h"
58#include "directory.h"
59#include "bit_ops.h"
60#include "filetime.h"
61
62
63int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st) {
64        PARTITION* partition = NULL;
65       
66        DIR_ENTRY dirEntry;
67       
68        // Get the partition this file is on
69        partition = _FAT_partition_getPartitionFromPath (path);
70       
71        if (partition == NULL) {
72                r->_errno = ENODEV;
73                return -1;
74        }
75
76        // Move the path pointer to the start of the actual path
77        if (strchr (path, ':') != NULL) {
78                path = strchr (path, ':') + 1;
79        }
80        if (strchr (path, ':') != NULL) {
81                r->_errno = EINVAL;
82                return -1;
83        }
84
85        // Search for the file on the disc
86        if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, NULL)) {
87                r->_errno = ENOENT;
88                return -1;
89        }
90       
91        // Fill in the stat struct
92        _FAT_directory_entryStat (partition, &dirEntry, st);
93       
94        return 0;
95}
96
97int _FAT_link_r (struct _reent *r, const char *existing, const char *newLink) {
98        r->_errno = ENOTSUP;
99        return -1;
100}
101
102int _FAT_unlink_r (struct _reent *r, const char *path) {
103        PARTITION* partition = NULL;
104        DIR_ENTRY dirEntry;
105        DIR_ENTRY dirContents;
106        u32 cluster;
107        bool nextEntry;
108        bool errorOccured = false;
109       
110        // Get the partition this directory is on
111        partition = _FAT_partition_getPartitionFromPath (path);
112       
113        if (partition == NULL) {
114                r->_errno = ENODEV;
115                return -1;
116        }
117
118        // Make sure we aren't trying to write to a read-only disc
119        if (partition->readOnly) {
120                r->_errno = EROFS;
121                return -1;
122        }       
123
124        // Move the path pointer to the start of the actual path
125        if (strchr (path, ':') != NULL) {
126                path = strchr (path, ':') + 1;
127        }
128        if (strchr (path, ':') != NULL) {
129                r->_errno = EINVAL;
130                return -1;
131        }
132       
133        // Search for the file on the disc
134        if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, NULL)) {
135                r->_errno = ENOENT;
136                return -1;
137        }
138       
139        cluster = _FAT_directory_entryGetCluster (dirEntry.entryData);
140
141       
142        // If this is a directory, make sure it is empty
143        if (_FAT_directory_isDirectory (&dirEntry)) {
144                nextEntry = _FAT_directory_getFirstEntry (partition, &dirContents, cluster);
145       
146                while (nextEntry) {
147                        if (!_FAT_directory_isDot (&dirContents)) {
148                                // The directory had something in it that isn't a reference to itself or it's parent
149                                r->_errno = EPERM;
150                                return -1;
151                        }
152                        nextEntry = _FAT_directory_getNextEntry (partition, &dirContents);
153                }
154        }
155
156        if (cluster != CLUSTER_FREE) {
157                // Remove the cluster chain for this file
158                if (!_FAT_fat_clearLinks (partition, cluster)) {
159                        r->_errno = EIO;
160                        errorOccured = true;
161                }
162        }
163
164        // Remove the directory entry for this file
165        if (!_FAT_directory_removeEntry (partition, &dirEntry)) {
166                r->_errno = EIO;
167                errorOccured = true;
168        }
169       
170        // Flush any sectors in the disc cache
171        if (!_FAT_cache_flush(partition->cache)) {
172                r->_errno = EIO;
173                errorOccured = true;
174        }
175       
176        if (errorOccured) {
177                return -1;
178        } else {
179                return 0;
180        }
181}
182
183int _FAT_chdir_r (struct _reent *r, const char *path) {
184        PARTITION* partition = NULL;
185       
186        // Get the partition this directory is on
187        partition = _FAT_partition_getPartitionFromPath (path);
188       
189        if (partition == NULL) {
190                r->_errno = ENODEV;
191                return -1;
192        }
193
194        // Move the path pointer to the start of the actual path
195        if (strchr (path, ':') != NULL) {
196                path = strchr (path, ':') + 1;
197        }
198        if (strchr (path, ':') != NULL) {
199                r->_errno = EINVAL;
200                return -1;
201        }
202       
203        // Set the default device to match this one
204        if (!_FAT_partition_setDefaultPartition (partition)) {
205                r->_errno = ENOENT;
206                return -1;
207        }
208
209        // Try changing directory
210        if (_FAT_directory_chdir (partition, path)) {
211                // Successful
212                return 0;
213        } else {
214                // Failed
215                r->_errno = ENOTDIR;
216                return -1;
217        }
218}
219
220int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) {
221        PARTITION* partition = NULL;
222        DIR_ENTRY oldDirEntry;
223        DIR_ENTRY newDirEntry;
224        const char *pathEnd;
225        u32 dirCluster;
226       
227        // Get the partition this directory is on
228        partition = _FAT_partition_getPartitionFromPath (oldName);
229       
230        if (partition == NULL) {
231                r->_errno = ENODEV;
232                return -1;
233        }
234       
235        // Make sure the same partition is used for the old and new names
236        if (partition != _FAT_partition_getPartitionFromPath (newName)) {
237                r->_errno = EXDEV;
238                return -1;
239        }
240
241        // Make sure we aren't trying to write to a read-only disc
242        if (partition->readOnly) {
243                r->_errno = EROFS;
244                return -1;
245        }       
246
247        // Move the path pointer to the start of the actual path
248        if (strchr (oldName, ':') != NULL) {
249                oldName = strchr (oldName, ':') + 1;
250        }
251        if (strchr (oldName, ':') != NULL) {
252                r->_errno = EINVAL;
253                return -1;
254        }
255        if (strchr (newName, ':') != NULL) {
256                newName = strchr (newName, ':') + 1;
257        }
258        if (strchr (newName, ':') != NULL) {
259                r->_errno = EINVAL;
260                return -1;
261        }
262
263        // Search for the file on the disc
264        if (!_FAT_directory_entryFromPath (partition, &oldDirEntry, oldName, NULL)) {
265                r->_errno = ENOENT;
266                return -1;
267        }
268       
269        // Make sure there is no existing file / directory with the new name
270        if (_FAT_directory_entryFromPath (partition, &newDirEntry, newName, NULL)) {
271                r->_errno = EEXIST;
272                return -1;
273        }
274
275        // Create the new file entry
276        // Get the directory it has to go in
277        pathEnd = strrchr (newName, DIR_SEPARATOR);
278        if (pathEnd == NULL) {
279                // No path was specified
280                dirCluster = partition->cwdCluster;
281                pathEnd = newName;
282        } else {
283                // Path was specified -- get the right dirCluster
284                // Recycling newDirEntry, since it needs to be recreated anyway
285                if (!_FAT_directory_entryFromPath (partition, &newDirEntry, newName, pathEnd) ||
286                        !_FAT_directory_isDirectory(&newDirEntry)) {
287                        r->_errno = ENOTDIR;
288                        return -1;
289                }
290                dirCluster = _FAT_directory_entryGetCluster (newDirEntry.entryData);
291                // Move the pathEnd past the last DIR_SEPARATOR
292                pathEnd += 1;
293        }
294
295        // Copy the entry data
296        memcpy (&newDirEntry, &oldDirEntry, sizeof(DIR_ENTRY));
297       
298        // Set the new name
299        strncpy (newDirEntry.filename, pathEnd, MAX_FILENAME_LENGTH - 1);
300       
301        // Write the new entry
302        if (!_FAT_directory_addEntry (partition, &newDirEntry, dirCluster)) {
303                r->_errno = ENOSPC;
304                return -1;
305        }
306       
307        // Remove the old entry
308        if (!_FAT_directory_removeEntry (partition, &oldDirEntry)) {
309                r->_errno = EIO;
310                return -1;
311        }
312       
313        // Flush any sectors in the disc cache
314        if (!_FAT_cache_flush (partition->cache)) {
315                r->_errno = EIO;
316                return -1;
317        }
318
319        return 0;
320}
321
322int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) {
323        PARTITION* partition = NULL;
324        bool fileExists;
325        DIR_ENTRY dirEntry;
326        const char* pathEnd;
327        u32 parentCluster, dirCluster;
328        u8 newEntryData[DIR_ENTRY_DATA_SIZE];
329       
330        partition = _FAT_partition_getPartitionFromPath (path);
331       
332        if (partition == NULL) {
333                r->_errno = ENODEV;
334                return -1;
335        }
336
337        // Move the path pointer to the start of the actual path
338        if (strchr (path, ':') != NULL) {
339                path = strchr (path, ':') + 1;
340        }
341        if (strchr (path, ':') != NULL) {
342                r->_errno = EINVAL;
343                return -1;
344        }
345       
346        // Search for the file/directory on the disc
347        fileExists = _FAT_directory_entryFromPath (partition, &dirEntry, path, NULL);
348       
349        // Make sure it doesn't exist
350        if (fileExists) {
351                r->_errno = EEXIST;
352                return -1;
353        }
354       
355        if (partition->readOnly) {
356                // We can't write to a read-only partition
357                r->_errno = EROFS;
358                return -1;
359        }       
360       
361        // Get the directory it has to go in
362        pathEnd = strrchr (path, DIR_SEPARATOR);
363        if (pathEnd == NULL) {
364                // No path was specified
365                parentCluster = partition->cwdCluster;
366                pathEnd = path;
367        } else {
368                // Path was specified -- get the right parentCluster
369                // Recycling dirEntry, since it needs to be recreated anyway
370                if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, pathEnd) ||
371                        !_FAT_directory_isDirectory(&dirEntry)) {
372                        r->_errno = ENOTDIR;
373                        return -1;
374                }
375                parentCluster = _FAT_directory_entryGetCluster (dirEntry.entryData);
376                // Move the pathEnd past the last DIR_SEPARATOR
377                pathEnd += 1;
378        }
379        // Create the entry data
380        strncpy (dirEntry.filename, pathEnd, MAX_FILENAME_LENGTH - 1);
381        memset (dirEntry.entryData, 0, DIR_ENTRY_DATA_SIZE);
382       
383        // Set the creation time and date
384        dirEntry.entryData[DIR_ENTRY_cTime_ms] = 0;
385        u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cTime, _FAT_filetime_getTimeFromRTC());
386        u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cDate, _FAT_filetime_getDateFromRTC());
387       
388        // Set the directory attribute
389        dirEntry.entryData[DIR_ENTRY_attributes] = ATTRIB_DIR;
390       
391        // Get a cluster for the new directory
392        dirCluster = _FAT_fat_linkFreeClusterCleared (partition, CLUSTER_FREE);
393        if (dirCluster == CLUSTER_FREE) {
394                // No space left on disc for the cluster
395                r->_errno = ENOSPC;
396                return -1;
397        }
398        u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cluster, dirCluster);
399        u16_to_u8array (dirEntry.entryData, DIR_ENTRY_clusterHigh, dirCluster >> 16);
400
401        // Write the new directory's entry to it's parent
402        if (!_FAT_directory_addEntry (partition, &dirEntry, parentCluster)) {
403                r->_errno = ENOSPC;
404                return -1;
405        }
406       
407        // Create the dot entry within the directory
408        memset (newEntryData, 0, DIR_ENTRY_DATA_SIZE);
409        memset (newEntryData, ' ', 11);
410        newEntryData[DIR_ENTRY_name] = '.';
411        newEntryData[DIR_ENTRY_attributes] = ATTRIB_DIR;
412        u16_to_u8array (newEntryData, DIR_ENTRY_cluster, dirCluster);
413        u16_to_u8array (newEntryData, DIR_ENTRY_clusterHigh, dirCluster >> 16);
414       
415        // Write it to the directory, erasing that sector in the process
416        _FAT_cache_eraseWritePartialSector ( partition->cache, newEntryData,
417                _FAT_fat_clusterToSector (partition, dirCluster), 0, DIR_ENTRY_DATA_SIZE);
418       
419       
420        // Create the double dot entry within the directory
421        newEntryData[DIR_ENTRY_name + 1] = '.';
422        u16_to_u8array (newEntryData, DIR_ENTRY_cluster, parentCluster);
423        u16_to_u8array (newEntryData, DIR_ENTRY_clusterHigh, parentCluster >> 16);
424
425        // Write it to the directory
426        _FAT_cache_writePartialSector ( partition->cache, newEntryData,
427                _FAT_fat_clusterToSector (partition, dirCluster), DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE);
428
429        // Flush any sectors in the disc cache
430        if (!_FAT_cache_flush(partition->cache)) {
431                r->_errno = EIO;
432                return -1;
433        }
434
435        return 0;
436}
437
438DIR_ITER* _FAT_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path) {
439        DIR_ENTRY dirEntry;
440        DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct);
441        bool fileExists;
442       
443        state->partition = _FAT_partition_getPartitionFromPath (path);
444
445        if (state->partition == NULL) {
446                r->_errno = ENODEV;
447                return NULL;
448        }
449
450        // Move the path pointer to the start of the actual path
451        if (strchr (path, ':') != NULL) {
452                path = strchr (path, ':') + 1;
453        }
454        if (strchr (path, ':') != NULL) {
455                r->_errno = EINVAL;
456                return NULL;
457        }
458        // Get the start cluster of the directory
459        fileExists = _FAT_directory_entryFromPath (state->partition, &dirEntry, path, NULL);
460       
461        if (!fileExists) {
462                r->_errno = ENOENT;
463                return NULL;
464        }
465       
466        // Make sure it is a directory
467        if (! _FAT_directory_isDirectory (&dirEntry)) {
468                r->_errno = ENOTDIR;
469                return NULL;
470        }
471
472        // Save the start cluster for use when resetting the directory data
473        state->startCluster = _FAT_directory_entryGetCluster (dirEntry.entryData);
474       
475        // Get the first entry for use with a call to dirnext
476        state->validEntry =
477                _FAT_directory_getFirstEntry (state->partition, &(state->currentEntry), state->startCluster);
478       
479        // We are now using this entry
480        state->inUse = true;
481        return (DIR_ITER*) state;
482}
483
484int _FAT_dirreset_r (struct _reent *r, DIR_ITER *dirState) {
485        DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct);
486
487        // Make sure we are still using this entry
488        if (!state->inUse) {
489                r->_errno = EBADF;
490                return -1;
491        }
492
493        // Get the first entry for use with a call to dirnext
494        state->validEntry =
495                _FAT_directory_getFirstEntry (state->partition, &(state->currentEntry), state->startCluster);
496
497        return 0;
498}
499
500int _FAT_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat) {
501        DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct);
502
503        // Make sure we are still using this entry
504        if (!state->inUse) {
505                r->_errno = EBADF;
506                return -1;
507        }
508       
509        // Make sure there is another file to report on
510        if (! state->validEntry) {
511                r->_errno = ENOENT;
512                return -1;
513        }
514
515        // Get the filename
516        strncpy (filename, state->currentEntry.filename, MAX_FILENAME_LENGTH);
517        // Get the stats, if requested
518        if (filestat != NULL) {
519                _FAT_directory_entryStat (state->partition, &(state->currentEntry), filestat);
520        }
521       
522        // Look for the next entry for use next time
523        state->validEntry =
524                _FAT_directory_getNextEntry (state->partition, &(state->currentEntry));
525
526        return 0;
527}
528
529int _FAT_dirclose_r (struct _reent *r, DIR_ITER *dirState) {
530        DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct);
531       
532        // We are no longer using this entry
533        state->inUse = false;
534
535        return 0;
536}
Note: See TracBrowser for help on using the repository browser.