Subversion Repositories NaviCtrl

Rev

Rev 44 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 ingob 1
/*#######################################################################################*/
2
/* !!! THIS IS NOT FREE SOFTWARE !!!                                                     */
3
/*#######################################################################################*/
4
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5
// + Copyright (c) 2008 Ingo Busker, Holger Buss
171 ingob 6
// + Nur für den privaten Gebrauch / NON-COMMERCIAL USE ONLY
1 ingob 7
// + FOR NON COMMERCIAL USE ONLY
8
// + www.MikroKopter.com
9
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation), 
11
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist. 
12
// + Sollten direkte oder indirekte kommerzielle Absichten verfolgt werden, ist mit uns (info@mikrokopter.de) Kontakt 
13
// + bzgl. der Nutzungsbedingungen aufzunehmen. 
14
// + Eine kommerzielle Nutzung ist z.B.Verkauf von MikroKoptern, Bestückung und Verkauf von Platinen oder Bausätzen,
15
// + Verkauf von Luftbildaufnahmen, usw.
16
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
17
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht, 
18
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
19
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
20
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
21
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
22
// + eindeutig als Ursprung verlinkt werden
23
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
24
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
25
// + Benutzung auf eigene Gefahr
26
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
27
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
171 ingob 28
// + Die Portierung oder Nutzung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur 
1 ingob 29
// + mit unserer Zustimmung zulässig
30
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
31
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
32
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
33
// + Redistributions of source code (with or without modifications) must retain the above copyright notice, 
34
// + this list of conditions and the following disclaimer.
35
// +   * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
36
// +     from this software without specific prior written permission.
37
// +   * The use of this project (hardware, software, binary files, sources and documentation) is only permitted 
38
// +     for non-commercial use (directly or indirectly)
39
// +     Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted 
40
// +     with our written permission
41
// +   * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be 
42
// +     clearly linked as origin 
171 ingob 43
// +   * porting the sources to other systems or using the software on other systems (except hardware from www.mikrokopter.de) is not allowed
1 ingob 44
//
45
// +  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
46
// +  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47
// +  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48
// +  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
49
// +  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
50
// +  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
51
// +  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
52
// +  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
53
// +  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54
// +  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
55
// +  POSSIBILITY OF SUCH DAMAGE. 
56
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
41 ingob 57
#include <stdio.h>
58
#include "91x_lib.h"
59
#include "timer.h"
60
#include "fat16.h"
61
#include "sdc.h"
62
#include "uart1.h"
1 ingob 63
 
64
 
65
//________________________________________________________________________________________________________________________________________
66
// Module name:                 fat16.c 
67
// Compiler used:               avr-gcc 3.4.5
41 ingob 68
// Last Modifikation:   16.06.2008
69
// Version:                             2.00
70
// Authors:                             Stephan Busker & Gregor Stobrawa        
71
// Description:                 Source files for FAT16 implementation with read and write-access
72
//                                              Copyright (C) 2008 Stephan Busker & Gregor Stobrawa
1 ingob 73
//........................................................................................................................................
41 ingob 74
// Functions:                   extern s16              Fat16_Init(void);
75
//                                              extern s16              Fat16_Deinit(void);             
76
//                                              extern File_t * fopen_(const u8 *filename, const s8 mode);
77
//                                              extern s16              fclose_(File_t *File);
78
//                                              extern s16              fflush_(File_t *File);
79
//                                              extern s16      fseek_(File_t *File, s32 offset, s16 origin);
80
//                                              extern s16              fgetc_(File_t *File);
81
//                                              extern s16              fputc_(u8 c, File_t *File);
82
//                                              extern u32              fread_(void *buffer, u32 size, u32 count, File_t *File); 
83
//                                              extern u32              fwrite_(void *buffer, u32 size, u32 count, File_t *File);
84
//                                              extern s16              fputs_(const u8 *string, File_t *File);
85
//                                              extern u8 *     fgets_(u8 *string, s16 length, File_t *File);
1 ingob 86
//........................................................................................................................................
41 ingob 87
// ext. functions:              extern SD_Result_t SDC_Init(void;)
88
//                                              extern SD_Result_t SDC_Deinit(void);
89
//                      extern SD_Result_t SDC_GetSector (u32,u8 *);            
90
//                                              extern SD_Result_t SDC_PutSector (u32,u8 *);
1 ingob 91
//........................................................................................................................................
92
//
93
// URL:                                 www.Mikro-Control.de
94
// mailto:                              stephan.busker@mikro-control.de
95
//________________________________________________________________________________________________________________________________________
96
 
41 ingob 97
/*
98
FAT16 Drive Layout:
99
Description                                             Offset
100
Volume Boot Sector                                      Start of Partition
101
Fat Tables                                                      Start + # of Reserved Sectors
102
Root Directory Entry                            Start + # of Reserved + (# of Sectors Per FAT * 2)
103
Data Area (Starts with Cluster #2)      Start + # of Reserved + (# of Sectors Per FAT * 2) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
104
*/
1 ingob 105
 
106
 
41 ingob 107
/*
108
________________________________________________________________________________________________________________________________________
109
 
110
        Structure of an partition entry                        
111
________________________________________________________________________________________________________________________________________
1 ingob 112
 
41 ingob 113
        Partition Entry is 16 bytes long
114
*/
115
typedef struct
116
{
117
        u8      PartitionState;                         // Current State of Partition (00h=Inactive, 80h=Active)
118
        u8      BeginningHead;                          // Beginning of Partition - Head
119
        u16     BeginningCylSec;                        // Beginning of Partition - Cylinder/Sector (See Below)
120
        u8      Type;                                           // Type of Partition (See List Below)
121
        u8      EndHead;                                        // End of Partition - Head
122
        u16     EndCylSec;                                      // End of Partition - Cylinder/Sector
123
        u32     NoSectorsBeforePartition;       // Number of Sectors between the MBR and the First Sector in the Partition
124
        u32     NoSectorsPartition      ;               // Number of Sectors in the Partition
125
} __attribute__((packed)) PartitionEntry_t;
1 ingob 126
 
41 ingob 127
/*
128
Coding of Cylinder/Sector words
1 ingob 129
 
41 ingob 130
Cylinder is 10 bits:  [7:0] at [15:8] and [9:8] at [7:6]
131
Sector is 5 bits:  [5:0] at [5:0]  
132
*/
1 ingob 133
 
41 ingob 134
// Partition Types:
135
#define PART_TYPE_UNKNOWN                       0x00
136
#define PART_TYPE_FAT12                         0x01
137
#define PART_TYPE_XENIX                         0x02
138
#define PART_TYPE_FAT16_ST_32_MB        0x04
139
#define PART_TYPE_EXTDOS                        0x05
140
#define PART_TYPE_FAT16_LT_32_MB        0x06
141
#define PART_TYPE_NTFS                          0x07
142
#define PART_TYPE_FAT32                         0x0B
143
#define PART_TYPE_FAT32LBA                      0x0C
144
#define PART_TYPE_FAT16LBA                      0x0E
145
#define PART_TYPE_EXTDOSLBA                     0x0F
146
#define PART_TYPE_EISA                          0x12
147
#define PART_TYPE_ONTRACK                       0x33
148
#define PART_TYPE_NOVELL                        0x40
149
#define PART_TYPE_DYNAMIC                       0x42
150
#define PART_TYPE_PCIX                          0x4B
151
#define PART_TYPE_LINUX_SWAP            0x82
152
#define PART_TYPE_LINUX_NATIVE          0x83
153
#define PART_TYPE_LINUX_LVM                     0x8E
154
#define PART_TYPE_PHOENIXSAVE           0xA0
155
#define PART_TYPE_FREEBSD                       0xA5
156
#define PART_TYPE_OPENBSD                       0xA6
157
#define PART_TYPE_NETNBSD                       0xA9
158
#define PART_TYPE_CPM                           0xDB
159
#define PART_TYPE_DBFS                          0xE0
160
#define PART_TYPE_BBT                           0xFF
1 ingob 161
 
162
 
41 ingob 163
/*
164
________________________________________________________________________________________________________________________________________
165
 
166
        Structure of the MasterBootRecord                      
167
________________________________________________________________________________________________________________________________________
1 ingob 168
 
41 ingob 169
        Master Boot Record is 512 bytes long
170
        The Master Boot Record is the same for pretty much all Operating Systems.
171
        It is located on the first Sector of the Hard Drive, at Cylinder 0, Head 0, Sector 1
172
*/
173
typedef struct
174
{
175
        u8                              ExecutableCode[446];    // 446 bytes for machine start code     
176
        PartitionEntry_t        PartitionEntry1;                // 16 bytes for partition entry 1                                       
177
        PartitionEntry_t        PartitionEntry2;                // 16 bytes for partition entry 2                                       
178
        PartitionEntry_t        PartitionEntry3;                // 16 bytes for partition entry 3                                       
179
        PartitionEntry_t        PartitionEntry4;                // 16 bytes for partition entry 4                                       
180
        u16                                     ExecutableMarker;               // BIOS-Signature (0x55 0xAA)   
181
} __attribute__((packed)) MBR_Entry_t;
1 ingob 182
 
183
 
41 ingob 184
/*
185
________________________________________________________________________________________________________________________________________
186
 
187
        Structure of the VolumeBootRecord                      
188
________________________________________________________________________________________________________________________________________
24 StephanB 189
 
41 ingob 190
        The Volume Boot Record is 512 bytes long
191
        This information is located in the first sector of every partition.
192
*/
193
typedef struct
194
{
195
        u8  JumpCode[3];                        // Jump Code + NOP
196
        s8  OEMName[8];                         // OEM Name             
197
        u16 BytesPerSector;                     // Bytes Per Sector
198
        u8  SectorsPerCluster;          // Sectors Per Cluster
199
        u16 ReservedSectors;            // Reserved Sectors
200
        u8  NoFATCopies;                        // Number of Copies of FAT
201
        u16 MaxRootEntries;                     // Maximum Root Directory Entries 
202
        u16 NoSectorsInPartSml32MB;     // Number of Sectors in Partition Smaller than 32 MB
203
        u8  MediaDescriptor;            // Media Descriptor (0xF8 for Hard Disks)
204
        u16 SectorsPerFAT;                      // Sectors Per FAT
205
        u16 SectorsPerTrack;            // Sectors Per Track
206
        u16 NoHeads;                            // Number of Heads
207
        u32 NoHiddenSectors;            // Number of Hidden Sectors     in Partition
208
        u32 NoSectors;                          // Number of Sectors in Partition
209
        u16     DriveNo;                                // Logical Drive Number of Partition
210
        u8  ExtendedSig;                        // Extended Signature (0x29)
211
        u32 SerialNo;                           // Serial Number of the Partition
212
        s8  VolumeName[11];                     // Volume Name of the Partititon
213
        s8  FATName[8];                         // FAT Name (FAT16)
214
        u8  ExecutableCode[446];        // 446 bytes for machine start code     
215
        u16 ExecutableMarker;           // Executable Marker (0x55 0xAA)        
216
} __attribute__((packed)) VBR_Entry_t;
1 ingob 217
 
218
 
219
 
41 ingob 220
/*
221
________________________________________________________________________________________________________________________________________
222
 
223
        Structure of an directory entry                
224
________________________________________________________________________________________________________________________________________
225
 
226
        Directory entry is 32 bytes.
227
*/
228
typedef struct
1 ingob 229
{
41 ingob 230
        s8      Name[8];                                        // 8 bytes name, padded with spaces.
231
        u8      Extension[3];                           // 3 bytes extension, padded with spaces.
232
        u8      Attribute;                                      // attribute of the directory entry (unused,archive,read-only,system,directory,volume)
233
        u8      Reserved[10];                           // reserved bytes within the directory entry.
234
        u32 DateTime;                                   // date and time of last write access to the file or directory.
235
        u16 StartCluster;                               // first cluster of the file or directory.
236
        u32 Size;                                               // size of the file or directory in bytes.
237
}  __attribute__((packed)) DirEntry_t;
1 ingob 238
 
41 ingob 239
#define SLOT_EMPTY              0x00    // slot has never been used
240
#define SLOT_E5                 0x05    // the real value is 0xe5
241
#define SLOT_DELETED            0xE5    // file in this slot deleted
1 ingob 242
 
41 ingob 243
#define ATTR_NONE               0x00    // normal file
244
#define ATTR_READONLY           0x01    // file is readonly
245
#define ATTR_HIDDEN                     0x02    // file is hidden
246
#define ATTR_SYSTEM                     0x04    // file is a system file
247
#define ATTR_VOLUMELABEL        0x08    // entry is a volume label
248
#define ATTR_LONG_FILENAME      0x0F    // this is a long filename entry
249
#define ATTR_SUBDIRECTORY       0x10    // entry is a directory name
250
#define ATTR_ARCHIVE            0x20    // file is new or modified
24 StephanB 251
 
252
 
41 ingob 253
/*
254
________________________________________________________________________________________________________________________________________
255
 
256
        Structure of an entry within the fileallocationtable.                  
257
________________________________________________________________________________________________________________________________________
258
*/
259
typedef struct
260
{
261
        u16  NextCluster;                               // the next cluster of the file.
262
} __attribute__((packed)) Fat16Entry_t;
1 ingob 263
 
41 ingob 264
// secial fat entries
265
#define FAT16_CLUSTER_FREE                      0x0000
266
#define FAT16_CLUSTER_RESERVED          0x0001
267
#define FAT16_CLUSTER_USED_MIN          0x0002
268
#define FAT16_CLUSTER_USED_MAX          0xFFEF
269
#define FAT16_CLUSTER_ROOTDIR_MIN       0xFFF0
270
#define FAT16_CLUSTER_ROOTDIR_MAX       0xFFF6
271
#define FAT16_CLUSTER_BAD                       0xFFF7
272
#define FAT16_CLUSTER_LAST_MIN          0xFFF8
273
#define FAT16_CLUSTER_LAST_MAX          0xFFFF
274
 
275
/*****************************************************************************************************************************************/
276
/*                                                                                                                                                                                                                                                                               */
277
/*      Global variables needed for read- or write-acces to the FAT16- filesystem.                                                                                                                       */
278
/*                                                                                                                                                                                                                                                                               */
279
/*****************************************************************************************************************************************/
280
 
281
#define MBR_SECTOR                                      0x00    // the masterboot record is located in sector 0.
282
#define DIRENTRY_SIZE                           32              //bytes
283
#define DIRENTRIES_PER_SECTOR           BYTES_PER_SECTOR/DIRENTRY_SIZE
284
#define FAT16_BYTES                                     2
285
#define FAT16_ENTRIES_PER_SECTOR        BYTES_PER_SECTOR/FAT16_BYTES
286
 
287
#define FSTATE_UNUSED   0                                       
288
#define FSTATE_USED             1
289
 
290
typedef struct
1 ingob 291
{
41 ingob 292
        u8      IsValid;                                // 0 means invalid, else valid
293
        u8      SectorsPerCluster;              // how many sectors does a cluster contain?
294
        u8      FatCopies;                              // Numbers of copies of the FAT
295
        u16     MaxRootEntries;                 // Possible number of entries in the root directory.
296
        u16     SectorsPerFat;                  // how many sectors does a fat16 contain?
297
        u32 FirstFatSector;                     // sector of the start of the fat
298
        u32 FirstRootDirSector;         // sector of the rootdirectory
299
        u32 FirstDataSector;            // sector of the first cluster containing data (cluster2).
300
        u32 LastDataSector;                     // the last data sector of the partition
301
} Partition_t;
1 ingob 302
 
41 ingob 303
Partition_t     Partition;                                      // Structure holds partition information
1 ingob 304
 
41 ingob 305
File_t FilePointer[FILE_MAX_OPEN];      // Allocate Memmoryspace for each filepointer used.
1 ingob 306
 
41 ingob 307
 
308
/****************************************************************************************************************************************/
309
/*      Function:               FileDateTime(DateTime_t *);                                                                                                                                                                                     */
310
/*                                                                                                                                                                                                                                                                              */
311
/*      Description:    This function calculates the DOS date time from a pointer to a time structure.                                                                          */
312
/*                                                                                                                                                                                                                                                                              */
313
/*      Returnvalue:    Returns the DOS date time.                                                                                                                                                                                      */
314
/****************************************************************************************************************************************/
315
 
316
u32 FileDateTime(DateTime_t * pTimeStruct)
1 ingob 317
{
41 ingob 318
        u32 datetime = 0;
319
        if((pTimeStruct == 0) || !(pTimeStruct->Valid)) return datetime;
24 StephanB 320
 
41 ingob 321
        datetime |= (0x0000007FL & (u32)(pTimeStruct->Year - 1980))<<25; // set year
322
        datetime |= (0x0000000FL & (u32)(pTimeStruct->Month))<<21; // set month
323
        datetime |= (0x0000001FL & (u32)(pTimeStruct->Day))<<16;
324
        datetime |= (0x0000001FL & (u32)(pTimeStruct->Hour))<<11;
325
        datetime |= (0x0000003FL & (u32)(pTimeStruct->Min))<<5;
326
        datetime |= (0x0000001FL & (u32)(pTimeStruct->Sec/2));
327
        return datetime;
1 ingob 328
}
329
 
330
 
41 ingob 331
/****************************************************************************************************************************************/
332
/*      Function:               LockFilePointer();                                                                                                                                                                                                      */
333
/*                                                                                                                                                                                                                                                                              */
334
/*      Description:    This function trys to lock a free file pointer.                                                                                                                                         */
335
/*                                                                                                                                                                                                                                                                              */
336
/*      Returnvalue:    Returns the Filepointer on success or 0.                                                                                                                                                        */
337
/****************************************************************************************************************************************/
338
File_t * LockFilePointer(void)
1 ingob 339
{
41 ingob 340
        u8 i;
341
        File_t * File = 0;
342
        for(i = 0; i < FILE_MAX_OPEN; i++)
1 ingob 343
        {
41 ingob 344
                if(FilePointer[i].State == FSTATE_UNUSED)               // found an unused one                                                                                  
1 ingob 345
                {
41 ingob 346
                        File = &FilePointer[i];                                         // set pointer to that entry             
347
                        FilePointer[i].State = FSTATE_USED;                     // mark it as used
348
                        break;
1 ingob 349
                }
41 ingob 350
        }
351
        return(File);
1 ingob 352
}
353
 
41 ingob 354
/****************************************************************************************************************************************/
355
/*      Function:               UnlockFilePointer(file_t *);                                                                                                                                                                            */
356
/*                                                                                                                                                                                                                                                                              */
357
/*      Description:    This function trys to unlock a file pointer.                                                                                                                                            */
358
/*                                                                                                                                                                                                                                                                              */
359
/*      Returnvalue:    Returns 1 if file pointer was freed else 0.                                                                                                                                                     */
360
/****************************************************************************************************************************************/
361
u8 UnlockFilePointer(File_t * file)
1 ingob 362
{
41 ingob 363
        u8 cnt;
364
        if(file == NULL) return(0);
365
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
1 ingob 366
        {
41 ingob 367
                if(&FilePointer[cnt] == file)                                           // filepointer to be freed found?
1 ingob 368
                {
41 ingob 369
                        file->State = FSTATE_UNUSED;                                                                                                   
370
                        file->FirstSectorOfFirstCluster = 0;                    // Sectorpointer to the first sector of the first datacluster of the file. 
371
                        file->FirstSectorOfCurrCluster  = 0;
372
                        file->SectorOfCurrCluster               = 0;                    // Pointer to the cluster which is edited at the moment.
373
                        file->SectorOfCurrCluster               = 0;                    // The sector which is edited at the moment (cluster_pointer + sector_index).
374
                        file->ByteOfCurrSector                  = 0;                    // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
375
                        file->Mode                                              = 0;                    // mode of fileoperation (read,write)
376
                        file->Size                                              = 0;                    // the size of the opend file in bytes.
377
                        file->Position                                  = 0;                    // pointer to a character within the file 0 < fileposition < filesize
378
                        file->SectorInCache                     = 0;                    // the last sector read, wich is still in the sectorbuffer.
379
                        file->DirectorySector                   = 0;                    // the sectorposition where the directoryentry has been made.
380
                        file->DirectoryIndex                    = 0;                    // the index to the directoryentry within the specified sector.
381
                        file->Attribute                                 = 0;                    // the attribute of the file opened.
382
                        file = NULL;
383
                        return(1);
1 ingob 384
                }
41 ingob 385
        }
386
        return(0);
387
}
1 ingob 388
 
41 ingob 389
/****************************************************************************************************************************************/
390
/*      Function:               SeperateDirName(s8*, s8*);                                                                                                                                                                              */
391
/*                                                                                                                                                                                                                                                                              */
392
/*      Description:    This function seperates the first dirname from filepath and brings them                                                                                         */
393
/*                                      into the needed format ('test.txt' -> 'TEST    TXT')                                                                                                                            */
394
/*                                      The subpath is the pointer to the remaining substring if the filepath                                                                                           */
395
/*                                                                                                                                                                                                                                                                              */
396
/*      Returnvalue:    Return NULL on error or pointer to subpath                                                                                                                                                                                                      */
397
/****************************************************************************************************************************************/
398
s8* SeperateDirName(const s8 *filepath, s8 *dirname)
399
{
400
        s8* subpath = NULL;
401
        u8 readpointer  = 0;
402
        u8 writepointer = 0;
1 ingob 403
 
41 ingob 404
        // search subpath from beginning of filepath                                    
405
        subpath = NULL;
406
        readpointer     = 0;
407
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
408
        while(subpath == NULL)  // search the filepath until a subpath was found.       
1 ingob 409
        {
41 ingob 410
                if(((filepath[readpointer] == 0) || (filepath[readpointer] == '/')))    // if '/' found or end of filepath reached 
411
                {      
412
                        subpath = (s8*)&filepath[readpointer];                          // store the position of the first "/" found after the beginning of the filenpath
413
                }
414
                readpointer++;
415
        }
1 ingob 416
 
41 ingob 417
        // clear dirname with spaces
418
        dirname[11] = 0; // terminate dirname
419
        for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' ';
420
        writepointer = 0;
421
        // start seperating the dirname from the filepath.
422
        readpointer = 0;
423
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
424
        while( &filepath[readpointer] < subpath)
1 ingob 425
        {
41 ingob 426
                if(writepointer >= 11) return(NULL);            // dirname to long
427
                if(filepath[readpointer] == '.')                        // seperating dirname and extension.
1 ingob 428
                {
41 ingob 429
                        if(writepointer <= 8)
1 ingob 430
                        {
41 ingob 431
                                readpointer++;                                          // next character in filename
432
                                writepointer = 8;                                       // jump to start of extension
1 ingob 433
                        }
41 ingob 434
                        else return(NULL);                                              // dirbasename to long                                                          
435
                }
436
                else
437
                {
438
                        if((0x60 < filepath[readpointer]) && (filepath[readpointer] < 0x7B))
439
                        {
440
                                dirname[writepointer] = (filepath[readpointer] - 0x20);                                 // all characters must be upper case.
441
                        }
1 ingob 442
                        else
443
                        {
41 ingob 444
                                dirname[writepointer] = filepath[readpointer];
1 ingob 445
                        }      
41 ingob 446
                        readpointer++;
447
                        writepointer++;
1 ingob 448
                }
41 ingob 449
        }
450
        return(subpath);       
1 ingob 451
}
452
 
453
 
41 ingob 454
/**************************************************************************************************************************************+*/
455
/*      Function:       Fat16ClusterToSector( u16 cluster);                                                                                                                                                                             */
456
/*                                                                                                                                                                                                                                                                              */
457
/*      Description:    This function converts a cluster number given by the fat to the corresponding                                                                           */
458
/*                                      sector that points to the start of the data area that is represented by the cluster number.                                                     */
459
/*                                                                                                                                                                                                                                                                              */
460
/*      Returnvalue: The sector number with the data area of the given cluster                                                                                                                          */
461
/****************************************************************************************************************************************/
462
u32     Fat16ClusterToSector(u16 cluster)
463
{
464
        if(!Partition.IsValid) return 0;
465
        if (cluster < 2) cluster = 2; // the 0. and 1. cluster in the fat are used for the media descriptor 
466
        return ( (cluster - 2) * Partition.SectorsPerCluster) + Partition.FirstDataSector; // the first data sector     is represented by the 2nd cluster
467
}
468
 
469
/****************************************************************************************************************************************/
470
/*      Function:       SectorToFat16Cluster( u32 sector);                                                                                                                                                                              */
471
/*                                                                                                                                                                                                                                                                              */
472
/*      Description:    This function converts a given sector number given to the corresponding                                                                                         */
473
/*                                      cluster number in the fat that represents this data area.                                                                                                                       */
474
/*                                                                                                                                                                                                                                                                              */
475
/*      Returnvalue: The cluster number representing the data area of the sector.                                                                                                                       */
476
/****************************************************************************************************************************************/
477
u16     SectorToFat16Cluster(u32 sector)
478
{
479
        if(!Partition.IsValid) return 0;
480
        return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2);
481
}
482
 
483
 
484
/****************************************************************************************************************************************/
485
/*      Function:       Fat16_Deinit(void);                                                                                                                                                                                                             */
486
/*                                                                                                                                                                                                                                                                              */
487
/*      Description:    This function uninitializes the fat 16 api                                                                                                                                                      */
488
/*                                                                                                                                                                                                                                                                              */
489
/*      Returnvalue: The function returns "0" on success                                                                                                                                                                        */
490
/****************************************************************************************************************************************/
491
u8 Fat16_Deinit(void)
492
{
493
        s16 returnvalue = 0;
494
        u8 cnt;
495
        // declare the filepointers as unused.
496
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
1 ingob 497
        {
41 ingob 498
                if(FilePointer[cnt].State == FSTATE_USED)
1 ingob 499
                {
41 ingob 500
                        returnvalue += fclose_(&FilePointer[cnt]); // try to close open file pointers
1 ingob 501
                }
41 ingob 502
 
1 ingob 503
        }
41 ingob 504
        SDC_Deinit();                   // uninitialize interface to sd-card
505
        Partition.IsValid = 0;  // mark data in partition structure as invalid
506
        return(returnvalue);
1 ingob 507
}
508
 
41 ingob 509
/****************************************************************************************************************************************/
510
/*      Function:               Fat16_Init(void);                                                                                                                                                                                                       */
511
/*                                                                                                                                                                                                                                                                          */
512
/*      Description:    This function reads the Masterbootrecord and finds the position of the Volumebootrecord, the FAT and the Rootdir    */
513
/*                                      and stores the information in global variables.                                                                                                                                     */
514
/*                                                                                                                                                                                                                                                                          */
515
/*      Returnvalue:    The function returns "0" if the filesystem is initialized.                                                                                                                      */
516
/****************************************************************************************************************************************/
517
u8 Fat16_Init(void)
518
{      
519
    u8  cnt     = 0;
520
        u32     partitionfirstsector;
521
        VBR_Entry_t *VBR;              
522
        MBR_Entry_t *MBR;
523
        File_t *file;
524
        u8 result = 0;
1 ingob 525
 
41 ingob 526
        SerialPutString("\r\n FAT16 init...");
527
        Partition.IsValid = 0;
528
 
529
        // declare the filepointers as unused.
530
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
1 ingob 531
        {
41 ingob 532
                FilePointer[cnt].State = FSTATE_UNUSED;                                        
1 ingob 533
        }
41 ingob 534
        // set current file pinter to first position in list
535
        file = &FilePointer[0];                                                                        
536
 
537
        // try to initialise the sd-card.
538
        if(SD_SUCCESS != SDC_Init())                                                   
539
        {  
540
                SerialPutString("SD-Card could not be initialized.");
541
                result = 1;
542
                goto end;      
543
        }
1 ingob 544
 
41 ingob 545
        // SD-Card is initialized successfully
546
        if(SD_SUCCESS != SDC_GetSector((u32)MBR_SECTOR,file->Cache))    // Read the MasterBootRecord
1 ingob 547
        {
41 ingob 548
                SerialPutString("Error reading the MBR.");
549
                result = 2;
550
                goto end;      
1 ingob 551
        }
41 ingob 552
        MBR = (MBR_Entry_t *)file->Cache;                                               // Enter the MBR using the structure MBR_Entry_t.
553
        if((MBR->PartitionEntry1.Type == PART_TYPE_FAT16_ST_32_MB) ||
554
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
555
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
1 ingob 556
        {
41 ingob 557
                // get sector offset 1st partition
558
                partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
559
                // Start of Partition is the Volume Boot Sector
560
                if(SD_SUCCESS != SDC_GetSector(partitionfirstsector,file->Cache)) // Read the volume boot record
1 ingob 561
                {
41 ingob 562
                        SerialPutString("Error reading the VBR.");
563
                        result = 3;
564
                        goto end;      
565
                }                      
1 ingob 566
        }
41 ingob 567
        else  // maybe the medium has no partition assuming sector 0 is the vbr
568
        {
569
                partitionfirstsector = 0;
570
        }
571
 
572
        VBR = (VBR_Entry_t *) file->Cache;                                              // Enter the VBR using the structure VBR_Entry_t.
573
        if(VBR->BytesPerSector != BYTES_PER_SECTOR)
574
        {
575
                SerialPutString("VBR: Sector size not supported.");
576
                result = 4;
577
                goto end;      
578
        }
579
        Partition.SectorsPerCluster             = VBR->SectorsPerCluster;                       // Number of sectors per cluster. Depends on the memorysize of the sd-card.
580
        Partition.FatCopies                     = VBR->NoFATCopies;                                     // Number of fatcopies.
581
        Partition.MaxRootEntries                = VBR->MaxRootEntries;                          // How many Entries are possible in the rootdirectory (FAT16 allows max. 512 entries).
582
        Partition.SectorsPerFat                 = VBR->SectorsPerFAT;                           // The number of sectors per FAT.
583
 
584
        /* Calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster. */
585
        // Calculate the position of the FileAllocationTable: 
586
        // Start + # of Reserved Sectors
587
        Partition.FirstFatSector        =   (u32)(partitionfirstsector + (u32)(VBR->ReservedSectors)); 
588
        // Calculate the position of the Rootdirectory: 
589
        // Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)                                                     
590
        Partition.FirstRootDirSector    =   Partition.FirstFatSector + (u32)((u32)Partition.SectorsPerFat*(u32)Partition.FatCopies);
591
        // Calculate the position of the first datacluster:
592
        // Start + # of Reserved + (# of Sectors Per FAT * # of FAT Copies) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)                
593
        Partition.FirstDataSector       =   Partition.FirstRootDirSector + (u32)(Partition.MaxRootEntries>>4);  // assuming 512 Byte Per Sector
594
        // Calculate the last data sector
595
        if(VBR->NoSectors == 0)
596
        {
597
                SerialPutString("VBR: Bad number of sectors.");
598
                result = 5;
599
                goto end;      
600
        }
601
        Partition.LastDataSector = Partition.FirstDataSector + VBR->NoSectors - 1;
602
        // check for FAT16 in VBR of first partition
603
        if(!((VBR->FATName[0]=='F') && (VBR->FATName[1]=='A') && (VBR->FATName[2]=='T') && (VBR->FATName[3]=='1')&&(VBR->FATName[4]=='6')))
604
        {
605
                SerialPutString("VBR: Partition ist not FAT16 type.");
606
                result = 6;
607
                goto end;
608
        }
609
        Partition.IsValid = 1; // mark data in partition structure as valid
610
        result = 0;
611
        end:
612
        if(result != 0) Fat16_Deinit();
613
        else SerialPutString("ok");
614
        return(result);
1 ingob 615
}
616
 
617
 
41 ingob 618
 
619
/****************************************************************************************************************************************/
620
/* Function:    ClearCurrCluster(File_t*);                                                                                                                                                                                      */
621
/*                                                                                                                                                                                                                                                                              */
622
/* Description: This function fills the current cluster with 0.                                                                                                                                                 */
623
/*                                                                                                                                                                                                                                                                              */
624
/* Returnvalue: The function returns 1 on success else 0.                                                                                                                                                               */
625
/****************************************************************************************************************************************/
626
u8 ClearCurrCluster(File_t * file)
1 ingob 627
{
41 ingob 628
        u8 retvalue = 1;
629
        u32 i;
1 ingob 630
 
41 ingob 631
        if((!Partition.IsValid) || (file == NULL)) return(0);
632
 
633
        for(i = 0; i < BYTES_PER_SECTOR; i++) file->Cache[i] = 0; // clear file cache
634
        for(i = 0; i < Partition.SectorsPerCluster; i++)
1 ingob 635
        {
41 ingob 636
                file->SectorInCache = file->FirstSectorOfCurrCluster + i;
637
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
638
                {
639
                        Fat16_Deinit();
640
                        retvalue = 0;
641
                }
1 ingob 642
        }
41 ingob 643
        return(retvalue);      
1 ingob 644
}
645
 
41 ingob 646
/*****************************************************************************************************************************************/
647
/* Function:    GetNextCluster(File_t* );                                                                                                                                                                                        */
648
/*                                                                                                                                                                                                                                                                               */
649
/* Description: This function finds the next datacluster of the file specified with File *File.                                                                                  */
650
/*                                                                                                                                                                                                                                                                               */
651
/* Returnvalue: The function returns the next cluster or 0 if the last cluster has already reached.                                                                                                      */
652
/*****************************************************************************************************************************************/
653
u16 GetNextCluster(File_t * file)
1 ingob 654
{
41 ingob 655
        u16 cluster = 0;
656
        u32 fat_byte_offset, sector, byte;
657
        Fat16Entry_t * fat;
1 ingob 658
 
41 ingob 659
        if((!Partition.IsValid) || (file == NULL)) return(cluster);
660
        // if sector is within the data area
661
        if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
1 ingob 662
        {
41 ingob 663
                // determine current file cluster
664
                cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);
665
                // calculate byte offset in the fat for corresponding entry
666
                fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
667
                // calculate the sector that contains the current cluster within the fat
668
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
669
                // calculate byte offset of the current cluster within that fat sector
670
                byte = fat_byte_offset % BYTES_PER_SECTOR;
671
                // read this sector to the file cache
672
                if(file->SectorInCache != sector)
1 ingob 673
                {
41 ingob 674
                        file->SectorInCache = sector;                                           // update sector stored in buffer
675
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
24 StephanB 676
                        {
41 ingob 677
                                Fat16_Deinit();
678
                                return (cluster);
679
                        }              
680
                }
681
                // read the next cluster from cache
682
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
683
                cluster = fat->NextCluster;
684
                // if last cluster fat entry 
685
                if(FAT16_CLUSTER_LAST_MIN <= cluster)
686
                {
687
                         cluster = 0;
1 ingob 688
                }
24 StephanB 689
                else
690
                {
41 ingob 691
                        file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
692
                        file->SectorOfCurrCluster = 0;
693
                        file->ByteOfCurrSector = 0;
24 StephanB 694
                }
41 ingob 695
        }      
696
        return(cluster);
1 ingob 697
}
698
 
699
 
41 ingob 700
/****************************************************************************************************************************************/
701
/* Function:    FindNextFreeCluster(File_t *);                                                                                                                                                                          */
702
/*                                                                                                                                                                                                                                                                              */
703
/* Description: This function looks in the fat to find the next free cluster                                                                                                                    */
704
/*                                                                                                                                                                                                                                                                              */
705
/* Returnvalue: The function returns the cluster number of the next free cluster found within the fat.                                                                  */
706
/****************************************************************************************************************************************/
707
u16 FindNextFreeCluster(File_t *file)
1 ingob 708
{
41 ingob 709
        u32 fat_sector;                                 // current sector within the fat relative to the first sector of the fat.
710
        u32     curr_sector;                            // current sector
711
        u16     fat_entry;                                      // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
712
        u16     free_cluster    = 0;            // next free cluster number.
713
        Fat16Entry_t * fat;
714
 
715
        if((!Partition.IsValid) || (file == NULL)) return(0);
24 StephanB 716
 
41 ingob 717
        // start searching for an empty cluster at the beginning of the fat.
718
        fat_sector = 0;
719
        do     
1 ingob 720
        {
41 ingob 721
                curr_sector = Partition.FirstFatSector + fat_sector;    // calculate sector to read
722
                file->SectorInCache = curr_sector;                                              // upate the sector number of file cache.
723
                if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))              // read sector of fat from sd-card.
724
                {
725
                        Fat16_Deinit();
726
                        return(free_cluster);
727
                }
728
 
729
                fat = (Fat16Entry_t *)file->Cache;                                              // set fat pointer to file cache
730
 
731
                for(fat_entry = 0; fat_entry < FAT16_ENTRIES_PER_SECTOR; fat_entry++)                                           // look for an free cluster at all entries in this sector of the fat. 
732
                {
733
                        if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE)            // empty cluster found!!
734
                        {                              
735
                                fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX;    // mark this fat-entry as used 
736
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // and save the sector at the sd-card.
737
                                {
738
                                        Fat16_Deinit();
739
                                        return(free_cluster);
740
                                }
741
                                free_cluster = (u16)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (u32)fat_entry);                          
742
                                fat_entry = FAT16_ENTRIES_PER_SECTOR;                                   // terminate the search for a free cluster in this sector.
743
                        }
744
                }
745
                fat_sector++;                                                                                                   // continue the search in next fat sector
746
        // repeat until the end of the fat is  reached and no free cluster has been found so far                                                                        
747
        }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster));
748
        return(free_cluster);
1 ingob 749
}
750
 
751
 
41 ingob 752
/****************************************************************************************************************************************************/
753
/* Function:    s16 fseek_(File_t *, s32 *, u8)                                                                                                                                                                                                         */
754
/*                                                                                                                                                                                                                                                                                                      */
755
/* Description: This function sets the pointer of the stream relative to the position                                                                                                                           */
756
/*                              specified by origin (SEEK_SET, SEEK_CUR, SEEK_END)                                                                                                                                                                      */
757
/* Returnvalue: Is 1 if seek was successful                                                                                                                                                                                                                                                                     */
758
/****************************************************************************************************************************************************/
759
s16 fseek_(File_t *file, s32 offset, s16 origin)
1 ingob 760
{
41 ingob 761
        s32             fposition       = 0;
762
        s16     retvalue        = 1;
1 ingob 763
 
41 ingob 764
        if((!Partition.IsValid) || (file == NULL)) return(0);
765
        switch(origin)
766
        {
767
                case SEEK_SET:                          // Fileposition relative to the beginning of the file.
768
                        fposition = 0; 
769
                        break;
770
                case SEEK_END:                          // Fileposition relative to the end of the file.
771
                        fposition = (s32)file->Size;
772
                        break;
773
                case SEEK_CUR:                          // Fileposition relative to the current position of the file.
774
                default:
775
                        fposition = file->Position;
776
                        break;
1 ingob 777
        }
41 ingob 778
 
779
        fposition += offset;
780
 
781
        if((fposition >= 0) && (fposition <= (s32)file->Size))          // is the pointer still within the file?
1 ingob 782
        {
41 ingob 783
                // reset file position to start of the file
784
                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
785
                file->SectorOfCurrCluster       = 0;
786
                file->ByteOfCurrSector          = 0;
787
                file->Position                          = 0;
1 ingob 788
 
41 ingob 789
                while(file->Position < fposition)       // repeat until the current position is less than target
1 ingob 790
                {
41 ingob 791
                        file->Position++;                               // increment file position
792
                        file->ByteOfCurrSector++;               // next byte in current sector                                                                          
793
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)                                                                 
794
                        {
795
                                file->ByteOfCurrSector = 0;                                                                             // reading at the beginning of new sector.
796
                                file->SectorOfCurrCluster++;                                                                    // continue reading in next sector
797
                                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
798
                                {
799
                                        if(GetNextCluster(file))                                                                        // Sets the clusterpointer of the file to the next datacluster.
800
                                        {
801
                                                file->SectorOfCurrCluster = 0;         
802
                                        }
803
                                        else // the last cluster was allready reached
804
                                        {
805
                                                file->SectorOfCurrCluster--;                                                    // jump back to the ast sector in the last cluster
806
                                                file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
807
                                        }
808
                                }
809
                        }      
1 ingob 810
                }      
811
        }
41 ingob 812
        if(file->Position == fposition) retvalue = 0;  
1 ingob 813
        return(retvalue);
814
}
815
 
816
 
41 ingob 817
/****************************************************************************************************************************************/
818
/* Function:    u16 DeleteClusterChain(File *file);                                                                                                                                                                             */
819
/*                                                                                                                                                                                                                                                                              */
820
/* Description: This function trances along a cluster chain in the fat and frees all clusters visited.                                                                  */
821
/*                                                                                                                                                                                                                                                                              */
822
/****************************************************************************************************************************************/
823
u8 DeleteClusterChain(u16 StartCluster)
1 ingob 824
{
41 ingob 825
        u16 cluster;                                                                                                           
826
        u32 fat_byte_offset, sector, byte;
827
        Fat16Entry_t * fat;
828
        u8 buffer[BYTES_PER_SECTOR];
829
        u32 sector_in_buffer = 0;
830
        u8 repeat = 0;
831
 
832
        if(!Partition.IsValid) return 0;
833
 
834
        cluster = StartCluster; // init chain trace
835
        // calculate byte offset in the fat for corresponding entry
836
        fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
837
        // calculate the sector that contains the current cluster within the fat
838
        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
839
        // calculate byte offset of the current cluster within that fat sector
840
        byte = fat_byte_offset % BYTES_PER_SECTOR;
841
        do     
1 ingob 842
        {
41 ingob 843
                if(sector != sector_in_buffer)
1 ingob 844
                {
41 ingob 845
                        // read this sector to buffer
846
                        sector_in_buffer = sector;
847
                        if(SD_SUCCESS != SDC_GetSector(sector_in_buffer, buffer)) return 0;     // read sector from sd-card
848
                }              
849
                // read the next cluster from cache
850
                fat = (Fat16Entry_t *)(&(buffer[byte]));
851
                cluster = fat->NextCluster;
852
                if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) ) repeat = 1;
853
                else repeat = 0;
854
 
855
                fat->NextCluster =      FAT16_CLUSTER_FREE; // mark current cluster as free
856
                // calculate byte offset in the fat for corresponding entry
857
                fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
858
                // calculate the sector that contains the current cluster within the fat
859
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
860
                // calculate byte offset of the current cluster within that fat sector
861
                byte = fat_byte_offset % BYTES_PER_SECTOR;
862
                // if new sector is not the sector in buffer or the last cluster in the chain was traced
863
                if((sector != sector_in_buffer) || !repeat)
864
                {       // write sector in buffer
865
                        if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer)) return 0;     
1 ingob 866
                }
41 ingob 867
        }
868
        while(repeat);
869
 
870
        return 1;
1 ingob 871
}
872
 
873
 
41 ingob 874
/****************************************************************************************************************************************/
875
/* Function:    u16 AppendCluster(File *file);                                                                                                                                                                                  */
876
/*                                                                                                                                                                                                                                                                              */
877
/* Description: This function looks in the fat to find the next free cluster and appends it to the file.                                                                */
878
/*                                                                                                                                                                                                                                                                              */
879
/* Returnvalue: The function returns the appened cluster number or 0 of no cluster was appended.                                                                                                                                                */
880
/****************************************************************************************************************************************/
881
u16 AppendCluster(File_t *file)
1 ingob 882
{
41 ingob 883
        u16 last_cluster, new_cluster = 0;                                                                                                             
884
        u32 fat_byte_offset, sector, byte;
885
        Fat16Entry_t * fat;
1 ingob 886
 
41 ingob 887
        if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
1 ingob 888
 
41 ingob 889
        new_cluster = FindNextFreeCluster(file);        // the next free cluster found on the disk.
890
        if(new_cluster)
891
        {       // A free cluster was found and can be added to the end of the file. 
892
                fseek_(file, 0, SEEK_END);                                                                                                      // jump to the end of the file
893
                last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);            // determine current file cluster 
894
                fat_byte_offset = ((u32)last_cluster)<<1;
895
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
896
                byte = fat_byte_offset % BYTES_PER_SECTOR;
1 ingob 897
 
41 ingob 898
                if(file->SectorInCache != sector)
899
                {
900
                        file->SectorInCache = sector;                                           // update sector stored in buffer
901
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
902
                        {
903
                                Fat16_Deinit();
904
                                return(0);
905
                        }      
906
                }                                            
907
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
908
                fat->NextCluster = new_cluster;                                                 // append the free cluster to the end of the file in the FAT.
909
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // save the modified sector to the FAT.
910
                {
911
                        Fat16_Deinit();
912
                        return(0);
913
                }
914
                file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster);
915
                file->SectorOfCurrCluster = 0;
916
                file->ByteOfCurrSector = 0;
917
        }
918
        return(new_cluster);
1 ingob 919
}
920
 
41 ingob 921
/****************************************************************************************************************************************************/
922
/* Function:    DirectoryEntryExist(s8 *, u8, u8, File_t *)                                                                                                                                                                                     */
923
/*                                                                                                                                                                                                                                                                                                      */
924
/* Description: This function searches all possible dir entries until the file or directory is found or the end of the directory is reached                     */
925
/*                                                                                                                                                                                                                                                                                                      */
926
/* Returnvalue: This function returns 1 if the directory entry specified was found.                                                                                                                                     */
927
/****************************************************************************************************************************************************/
928
u8 DirectoryEntryExist(s8 *dirname, u8 attribfilter, u8 attribmask, File_t *file)
929
{
930
        u32             dir_sector, max_dir_sector, curr_sector;
931
        u16     dir_entry = 0;
24 StephanB 932
 
41 ingob 933
        u16     end_of_directory_not_reached = 0;
934
        u8              i = 0;
935
        u8      direntry_exist = 0;
936
        DirEntry_t * dir;
24 StephanB 937
 
41 ingob 938
        // if incomming pointers are useless return immediatly
939
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
940
 
941
        // dir entries can be searched only in filesclusters that have 
942
        // a corresponding dir entry with adir-flag set in its attribute 
943
        // or direct within the root directory area
24 StephanB 944
 
41 ingob 945
        file->FirstSectorOfFirstCluster = 0;
946
        // no current directory exist therefore assume searching in the root
947
        if(file->DirectorySector == 0)
24 StephanB 948
        {
41 ingob 949
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
950
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
951
        }
952
        // within the root directory area we can read sectors sequentially until the end of this area
953
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
954
        {
955
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
956
        }
957
        // within the data clusters we can read sectors sequentially only within the cluster  
958
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
959
        {
960
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
961
        }
962
        else return (direntry_exist); // bad sector range for directory sector of the file
963
        // if search area is not defined yet
964
        if(file->FirstSectorOfFirstCluster == 0)
965
        {
966
                // check if the directory entry of current file is existent and has the dir-flag set
967
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
968
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
24 StephanB 969
                {
41 ingob 970
                        Fat16_Deinit();
971
                        return(direntry_exist);
24 StephanB 972
                }
41 ingob 973
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
974
                switch((u8)dir[file->DirectoryIndex].Name[0])                                   // check if current directory exist
24 StephanB 975
                {
41 ingob 976
                        case SLOT_EMPTY:
977
                        case SLOT_DELETED:
978
                                // the directrory pointer of this file points to a deleted or not existen directory
979
                                // therefore no file or subdirectory can be created
980
                                return (direntry_exist);
981
                                break;
982
                        default:        // and is a real directory 
983
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
984
                                {       // current file is not a directory therefore no file or subdirectory can be created here
985
                                        return (direntry_exist);
986
                                }
987
                                break;
24 StephanB 988
                }
41 ingob 989
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster);
24 StephanB 990
        }
991
 
41 ingob 992
        // update current file data area position to start of first cluster
993
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
994
        file->SectorOfCurrCluster               = 0;           
995
        file->ByteOfCurrSector                  = 0;
24 StephanB 996
 
41 ingob 997
        do // loop over all data clusters of the current directory entry
998
        {      
999
                dir_sector = 0; // reset sector counter within a new cluster
1000
                do // loop over all sectors of a cluster or all sectors of the root directory
1001
                {      
1002
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1003
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1004
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
1005
                        {
1006
                                Fat16_Deinit();
1007
                                return(direntry_exist);
1008
                        }
1009
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1010
                        // search all directory entries within that sector
1011
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1012
                        {   // check for existing dir entry
1013
                                switch((u8)dir[dir_entry].Name[0])
1014
                                {
1015
                                        case SLOT_EMPTY:
1016
                                        case SLOT_DELETED:
1017
                                                // ignore empty or deleted dir entries
1018
                                                break;
1019
                                        default:
1020
                                                // if existing check attributes before names are compared will safe performance
1021
                                                if ((dir[dir_entry].Attribute & attribmask) != attribfilter) break; // attribute must match
1022
                                                // then compare the name to the giveb dirname (first 11 characters include 8 chars of basename and 3 chars extension.)
1023
                                                i = 0;
1024
                                                while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
1025
                                                if (i < 10) break; // names does not match
1026
                                                // if dirname and attribute have matched
1027
                                                file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
1028
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster                                                        
1029
                                                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1030
                                                file->SectorOfCurrCluster = 0;
1031
                                                file->ByteOfCurrSector = 0;
1032
                                                file->DirectorySector = curr_sector; // current sector
1033
                                                file->DirectoryIndex  = dir_entry; // current direntry in current sector
1034
                                                file->Size = dir[dir_entry].Size;      
1035
                                                direntry_exist = 1; // mark as found    
1036
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop        
1037
                                } // end of first byte of name check
1038
                        }
1039
                        dir_sector++; // search next sector
1040
                // stop if we reached the end of the cluster or the end of the root dir
1041
                }while((dir_sector < max_dir_sector) && (!direntry_exist));
1 ingob 1042
 
41 ingob 1043
                // if we are seaching in the data area and the file not found in this cluster so take next cluster.
1044
                if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))                                                                                  
1045
                {
1046
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1047
                }
1048
        }while((end_of_directory_not_reached) && (!direntry_exist)); // repeat until a next cluster exist an no
1049
        return(direntry_exist);
1 ingob 1050
}
1051
 
1052
 
41 ingob 1053
/****************************************************************************************************************************************/
1054
/*      Function:               CreateDirectoryEntry(s8 *, u16, File_t *)                                                                                                                                                       */
1055
/*                                                                                                                                                                                                                                                                              */
1056
/*      Description:    This function looks for the next free position in the directory and creates an entry.                                                           */
1057
/*                                      The type of an directory entry is specified by the file attribute.                                                                                                      */
1058
/*                                                                                                                                                                                                                                                                              */
1059
/*      Returnvalue:    Return 0 on error                                                                                                                                                                                                       */
1060
/****************************************************************************************************************************************/
1061
u8 CreateDirectoryEntry(s8 *dirname, u8 attrib, File_t *file)
1 ingob 1062
{
41 ingob 1063
        u32 dir_sector, max_dir_sector, curr_sector;
1064
        u16 dir_entry   = 0;
1065
        u16 subdircluster, dircluster = 0;
1066
        u16 end_of_directory_not_reached = 0;
1067
        u8      i                       = 0;
1068
        u8      retvalue        = 0;   
1069
        DirEntry_t *dir;
1070
 
1071
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return (retvalue);
1072
        // It is not checked here that the dir entry that should be created is already existent!
1 ingob 1073
 
41 ingob 1074
        // Dir entries can be created only in file-clusters that have 
1075
        // the dir-flag set in its attribute or within the root directory
1 ingob 1076
 
41 ingob 1077
        file->FirstSectorOfFirstCluster = 0;
1078
        // no current directory exist therefore assume creating in the root
1079
        if(file->DirectorySector == 0)
24 StephanB 1080
        {
41 ingob 1081
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1082
                dircluster = 0;
1083
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
1084
        }
1085
        // within the root directory area we can read sectors sequentially until the end of this area
1086
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
1087
        {
1088
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1089
        }
1090
        // within the data clusters we can read sectors sequentially only within the cluster  
1091
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
1092
        {
1093
                max_dir_sector = Partition.SectorsPerCluster;
1094
        }
1095
        else return (retvalue); // bad sector range for directory sector of the file 
1096
        // if search area is not defined yet
1097
        if(file->FirstSectorOfFirstCluster == 0)
1098
        {
1099
            // check if the directory entry of current file is existent and has the dir-flag set
1100
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1101
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. 
1102
                {
1103
                        Fat16_Deinit();
1104
                        return(retvalue);
1105
                }              
1106
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1107
                switch((u8)dir[file->DirectoryIndex].Name[0])                                   // check if current directory exist
1108
                {
1109
                        case SLOT_EMPTY:
1110
                        case SLOT_DELETED:
1111
                                return (retvalue);
1112
                                break;
1113
                        default:        // and is a real directory 
1114
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1115
                                {       // current file is not a directory therefore no file or subdirectory can be created here
1116
                                        return (retvalue);
1117
                                }
1118
                                break;
1119
                }
1120
                dircluster = dir[file->DirectoryIndex].StartCluster;
1121
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster);
1122
        }
1123
 
1124
        subdircluster = FindNextFreeCluster(file);      // get the next free cluster on the disk and mark it as used.
1125
        if(subdircluster)
1126
        {
1127
                file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1128
                file->SectorOfCurrCluster               = 0;
1129
                do // loop over all clusters of current directory
1130
                {      
1131
                        dir_sector = 0; // reset sector counter within a new cluster
1132
                        do // loop over all sectors of a cluster or all sectors of the root directory
1 ingob 1133
                        {
41 ingob 1134
                                curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number                                                                      
1135
                                file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1136
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. 
24 StephanB 1137
                                {
41 ingob 1138
                                        Fat16_Deinit();
1139
                                        return(retvalue);
1140
                                }              
1141
                                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1142
                                // search all directory entries of a sector
1143
                                for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1144
                                {       // check if current direntry is available
1145
                                        if(((u8)dir[dir_entry].Name[0] == SLOT_EMPTY) || ((u8)dir[dir_entry].Name[0] == SLOT_DELETED))
1146
                                        {       // a free direntry was found    
1147
                                                for(i = 0; i < 11; i++) dir[dir_entry].Name[i] = dirname[i];            // Set dir name
1148
                                                dir[dir_entry].Attribute    = attrib;                                                           // Set the attribute of the new directoryentry.
1149
                                                dir[dir_entry].StartCluster = subdircluster;                                            // copy the location of the first datacluster to the directoryentry.
1150
                                                dir[dir_entry].DateTime         = FileDateTime(&SystemTime);                    // set date/time
1151
                                                dir[dir_entry].Size             = 0;                                                                    // the new createted file has no content yet.
1152
                                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to card
1153
                                                {
1154
                                                        Fat16_Deinit();
1155
                                                        return(retvalue);
1156
                                                }
1157
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster);  // Calculate absolute sectorposition of first datacluster.
1158
                                                file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;      // Start reading the file with the first sector of the first datacluster.
1159
                                                file->SectorOfCurrCluster               = 0;                                                            // reset sector of cureen cluster
1160
                                                file->ByteOfCurrSector                  = 0;                                                            // reset the byte location within the current sector
1161
                                                file->Attribute                                 = attrib;                                               // set file attribute to dir attribute
1162
                                                file->Size                                              = 0;                                                        // new file has no size
1163
                                                file->DirectorySector                   = curr_sector;
1164
                                                file->DirectoryIndex                    = dir_entry;
1165
                                                if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)                           // if a new directory was created then initilize the data area          
1166
                                                {      
1167
                                                        ClearCurrCluster(file); // fill cluster with zeros
1168
                                                        file->SectorInCache = file->FirstSectorOfFirstCluster;
1169
                                                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. 
1170
                                                        {
1171
                                                                Fat16_Deinit();
1172
                                                                return(retvalue);
1173
                                                        }      
1174
                                                        dir = (DirEntry_t *)file->Cache;
1175
                                                        // create direntry "." to current dir
1176
                                                        dir[0].Name[0] = 0x2E;
1177
                                                        for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
1178
                                                        dir[0].Attribute = ATTR_SUBDIRECTORY;
1179
                                                        dir[0].StartCluster = subdircluster;
1180
                                                        dir[0].DateTime = 0;
1181
                                                        dir[0].Size = 0;
1182
                                                        // create direntry ".." to the upper dir
1183
                                                        dir[1].Name[0] = 0x2E;
1184
                                                        dir[1].Name[1] = 0x2E;
1185
                                                        for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
1186
                                                        dir[1].Attribute = ATTR_SUBDIRECTORY;
1187
                                                        dir[1].StartCluster = dircluster;
1188
                                                        dir[1].DateTime = 0;
1189
                                                        dir[1].Size = 0;
1190
                                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector. 
1191
                                                        {
1192
                                                                Fat16_Deinit();
1193
                                                                return(retvalue);
1194
                                                        }              
1195
                                                }      
1196
                                                retvalue = 1;
1197
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop        
1198
                                        }
24 StephanB 1199
                                }                      
41 ingob 1200
                                dir_sector++; // search next sector
1201
                        // stop if we reached the end of the cluster or the end of the root dir
1202
                        }while((dir_sector < max_dir_sector) && (!retvalue));
1203
 
1204
                        // if we are seaching in the data area and the file not found in this cluster so take next cluster.
1205
                        if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))                                                                                
24 StephanB 1206
                        {
41 ingob 1207
                                end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
24 StephanB 1208
                        }
41 ingob 1209
                }while((end_of_directory_not_reached) && (!retvalue));
1210
                // Perhaps we are at the end of the last cluster of a directory file an have no free direntry found.
1211
                // Then we would need to add a cluster to that file and create the new direntry there.
1212
                // This code is not implemented yet, because its occurs only if more that 32*32=1024 direntries are
1213
                // within a subdirectory of root.
1 ingob 1214
        }
41 ingob 1215
        return(retvalue);       // return 1 if file has been created otherwise return 0.
1 ingob 1216
}
1217
 
41 ingob 1218
/********************************************************************************************************************************************/
1219
/*      Function:               FileExist(const s8* filename, u8 attribfilter, u8 attribmask, File_t *file);                                                                                    */
1220
/*                                                                                                                                                                                                                                                                                      */
1221
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
1222
/*                                      in the rootdirectory of the drive. If the file is found the Filepointer properties are                                                                  */
1223
/*                                      updated.                                                                                                                                                                                                                                */
1224
/*                                                                                                                                                                                                                                                                                      */
1225
/*      Returnvalue:    1 if file is found else 0.                                                                                                                                                                                              */
1226
/********************************************************************************************************************************************/
1227
u8 FileExist(const s8* filename, const u8 attribfilter, const u8 attribmask, File_t *file)
1 ingob 1228
{
41 ingob 1229
        s8* path = 0;
1230
        s8* subpath = 0;
1231
        u8 af, am, file_exist = 0;
1232
        s8 dirname[12]; // 8+3 + temination character
1 ingob 1233
 
41 ingob 1234
        // if incomming pointers are useless return immediatly
1235
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1 ingob 1236
 
41 ingob 1237
        // trace along the filepath
1238
        path = (s8*)filename;                                                           // start a the beginning of the filename string
1239
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1240
        file->DirectoryIndex = 0;
1241
        // as long as the file was not found and the remaining path is not empty
1242
        while((*path != 0) && !file_exist)
1243
        {       // separate dirname and subpath from filepath string
1244
                subpath = SeperateDirName(path, dirname);
1245
                if(subpath != NULL)
1246
                {      
1247
                        if(*subpath == 0)        
1248
                        {       // empty subpath indicates last element of dir chain
1249
                                af = attribfilter;
1250
                                am = attribmask;
1251
                        }
1252
                        else  // it must be a subdirectory and no volume label
1 ingob 1253
                        {
41 ingob 1254
                                af = ATTR_SUBDIRECTORY;
1255
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1256
                        }
1257
                        if(!DirectoryEntryExist(dirname, af, am, file))
1258
                        {
1259
                                return (file_exist); // subdirectory does not exist
1260
                        }
1261
                        else
1262
                        {      
1263
                                if (*subpath == 0)
24 StephanB 1264
                                {
41 ingob 1265
                                        file_exist = 1; // last element of path chain was found with the given attribute filter
24 StephanB 1266
                                }
1 ingob 1267
                        }
1268
                }
41 ingob 1269
                else // error seperating the subpath
1 ingob 1270
                {
41 ingob 1271
                        return file_exist; // bad subdir format
1 ingob 1272
                }
41 ingob 1273
                path = subpath;
1274
                subpath = 0;
1 ingob 1275
        }
41 ingob 1276
        return (file_exist);
1 ingob 1277
}
1278
 
24 StephanB 1279
 
41 ingob 1280
/********************************************************************************************************************************************/
1281
/*      Function:               FileCreate(const s8* filename, u8 attrib, File_t *file);                                                                                                                                */
1282
/*                                                                                                                                                                                                                                                                                      */
1283
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
1284
/*                                      in the rootdirectory of the partition. If the file is found the Filepointer properties are                                                              */
1285
/*                                      updated. If file or its subdirectories are not found they will be created                                                                                               */                                                                                                             
1286
/*                                                                                                                                                                                                                                                                                      */
1287
/*      Returnvalue:    1 if file was created else 0.                                                                                                                                                                                   */
1288
/********************************************************************************************************************************************/
1289
u8 FileCreate(const s8* filename, const u8 attrib, File_t *file)
1290
{
1291
        s8 *path = 0;
1292
        s8 *subpath = 0;
1293
        u8 af, am, file_created = 0;
1294
        s8 dirname[12];
24 StephanB 1295
 
41 ingob 1296
        // if incomming pointers are useless return immediatly
1297
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1 ingob 1298
 
41 ingob 1299
        // trace along the filepath
1300
        path = (s8*)filename;                                                                   // start a the beginning of the filename string
1301
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1302
        file->DirectoryIndex = 0;
1303
        // as long as the file was not created and the remaining file path is not empty
1304
        while((*path != 0) && !file_created)
1305
        {   // separate dirname and subpath from filepath string
1306
                subpath = SeperateDirName(path, dirname);
1307
                if(subpath != NULL)
24 StephanB 1308
                {
41 ingob 1309
                        if(*subpath == 0)        
1310
                        {       // empty subpath indicates last element of dir chain
1311
                                af = ATTR_NONE;
1312
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;  // any file that is no subdir or volume label
24 StephanB 1313
                        }
41 ingob 1314
                        else  // it must be a subdirectory and no volume label
24 StephanB 1315
                        {
41 ingob 1316
                                af = ATTR_SUBDIRECTORY;
1317
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
24 StephanB 1318
                        }
41 ingob 1319
                        if(!DirectoryEntryExist(dirname, af, am, file)) // if subdir or file is not existent
1320
                        {  // try to create subdir or file
1321
                                if(*subpath == 0) af = attrib; // if last element in dir chain take the given attribute
1322
                                if(!CreateDirectoryEntry(dirname, af, file))
1323
                                {       // could not be created
1324
                                        return(file_created);  
1325
                                }
1326
                                else if (*subpath == 0) file_created = 1; // last element of path chain was created
24 StephanB 1327
                        }
1328
                }
41 ingob 1329
                else // error seperating the subpath
24 StephanB 1330
                {
41 ingob 1331
                        return file_created; // bad subdir format
24 StephanB 1332
                }
41 ingob 1333
                path = subpath;
1334
                subpath = 0;
1335
        }
1336
        return (file_created);
24 StephanB 1337
}
1 ingob 1338
 
24 StephanB 1339
 
41 ingob 1340
/********************************************************************************************************************************************/
1341
/*      Function:               File_t * fopen_(s8* filename, s8 mode);                                                                                                                                                                 */
1342
/*                                                                                                                                                                                                                                                                                      */
1343
/*      Description:    This function looks for the specified file in the rootdirectory of the drive. If the file is found the number of the    */
1344
/*                                      corrosponding filepointer is returned. Only modes 'r' (reading) and 'a' append are implemented yet.                                             */
1345
/*                                                                                                                                                                                                                                                                                      */
1346
/*      Returnvalue:    The filepointer to the file or 0 if faild.                                                                                                                                                              */
1347
/********************************************************************************************************************************************/
1348
File_t * fopen_(const s8 *filename, const s8 mode)
1349
{                      
1350
        File_t *file    = 0;
24 StephanB 1351
 
41 ingob 1352
        if((!Partition.IsValid) || (filename == 0)) return(file);
1353
 
1354
        // Look for an unused filepointer in the file pointer list?
1355
        file = LockFilePointer();
1356
        // if no unused file pointer was found return 0
1357
        if(file == NULL) return(file);
1358
 
1359
        // now we have found a free filepointer and claimed it
1360
        // so let initiate its property values
1361
        file->FirstSectorOfFirstCluster = 0;            // Sectorpointer to the first sector of the first datacluster of the file. 
1362
        file->FirstSectorOfCurrCluster  = 0;            // Pointer to the cluster which is edited at the moment.
1363
        file->SectorOfCurrCluster               = 0;            // The sector which is edited at the moment (cluster_pointer + sector_index).
1364
        file->ByteOfCurrSector                  = 0;            // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
1365
        file->Mode                                              = mode;         // mode of fileoperation (read,write)
1366
        file->Size                                              = 0;            // the size of the opened file in bytes.
1367
        file->Position                                  = 0;            // pointer to a byte within the file 0 < fileposition < filesize
1368
        file->SectorInCache                             = 0;            // the last sector read, wich is still in the sectorbuffer.
1369
        file->DirectorySector                   = 0;            // the sectorposition where the directoryentry has been made.
1370
        file->DirectoryIndex                    = 0;            // the index to the directoryentry within the specified sector.
1371
        file->Attribute                                 = 0;            // the attribute of the file opened.
1372
 
1373
        // check if a real file (no directory) to the given filename exist
1374
        if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
1375
        {  // file exist
1376
                switch(mode)  // check mode
1 ingob 1377
                {
41 ingob 1378
                        case 'a':       // if mode is: append to file
1379
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1380
                                {       // file is marked as readonly --> do not open this file
1381
                                        fclose_(file);
1382
                                        file = NULL;
1383
                                }
1384
                                else
1385
                                {       // file is not marked as read only --> goto end of file
1386
                                        fseek_(file, 0, SEEK_END);              // point to the end of the file
1387
                                }
1388
                                break;
1389
                        case 'w':       // if mode is: write to file
1390
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1391
                                {       // file is marked as readonly --> do not open this file
1392
                                        fclose_(file);
1393
                                        file = NULL;
1394
                                }
1395
                                else
1396
                                {       // file is not marked as read only --> goto start of file
1397
                                        // free all clusters of that file
1398
                                        DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster));
1399
                                        // mar an empy cluster as the last one and store the corresponding sector
1400
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(FindNextFreeCluster(file));
1401
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1402
                                        file->SectorOfCurrCluster = 0;
1403
                                        file->ByteOfCurrSector = 0;
1404
                                        file->Size = 0;
1405
                                        file->Position = 0;
1406
                                        fseek_(file, 0, SEEK_SET);
1407
                                }
1408
                                break;
1409
                        case 'r':       // if mode is: read from file
1410
                                // goto end of file 
1411
                                fseek_(file, 0, SEEK_SET);
1412
                                break;
1413
                        default: // other modes are not supported
1414
                                fclose_(file);
1415
                                file = NULL;
24 StephanB 1416
                        break;
1 ingob 1417
                }
41 ingob 1418
                return(file);  
1 ingob 1419
        }
41 ingob 1420
        else // file does not exist
1421
        {
1422
                switch(mode)  // check mode
1423
                {
1424
                        case 'a':
1425
                        case 'w': // if mode is write or append
1426
                                // try to create the file
1427
                                if(!FileCreate(filename, ATTR_ARCHIVE, file))
1428
                                { // if it could not be created
1429
                                        fclose_(file);
1430
                                        file = NULL;
1431
                                }
1432
                                break;
1433
                        case 'r': // else opened for 'r'
1434
                        default:  // of unsupported mode
1435
                                fclose_(file);
1436
                                file = NULL;
1437
                                break; 
1438
                }
1439
                return(file);                  
1440
        }
1441
        // we should never come to this point
1442
        fclose_(file);
1443
        file = NULL;
24 StephanB 1444
        return(file);
1445
}
1446
 
41 ingob 1447
/****************************************************************************************************************************************************/
1448
/* Function:    fflush_(File *);                                                                                                                                                                                                                                        */
1449
/*                                                                                                                                                                                                                                                                                                      */
1450
/* Description: This function writes the data already in the buffer but not yet written to the file.                                                                                            */
1451
/*                                                                                                                                                                                                                                                                                                      */
1452
/* Returnvalue: 0 on success EOF on error                                                                                                                                                                                                                       */
1453
/****************************************************************************************************************************************************/
1454
s16     fflush_(File_t *file)
24 StephanB 1455
{
41 ingob 1456
        DirEntry_t *dir;       
1 ingob 1457
 
41 ingob 1458
        if((file == NULL) || (!Partition.IsValid)) return (EOF);
1459
 
1460
        switch(file->Mode)
24 StephanB 1461
        {
41 ingob 1462
                case 'a':
1463
                case 'w':
1464
                        if(file->ByteOfCurrSector > 0)                                                                          // has data been added to the file?             
1465
                        {
1466
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// save the data still in the buffer 
1467
                                {
1468
                                        Fat16_Deinit();
1469
                                        return(EOF);   
1470
                                }                                      
1471
                        }
1472
                        file->SectorInCache     = file->DirectorySector;
1473
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))                                       // read the directory entry for this file.
1474
                        {
1475
                                Fat16_Deinit();
1476
                                return(EOF);    
1477
                        }
1478
 
1479
                        dir = (DirEntry_t *)file->Cache;
1480
                        dir[file->DirectoryIndex].Size = file->Size;                                            // update file size
1481
                        dir[file->DirectoryIndex].DateTime = FileDateTime(&SystemTime);         // update date time
1482
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to sd-card
1483
                        {
1484
                                Fat16_Deinit();
1485
                                return(EOF);
1486
                        }
1487
                        break;
1488
                case 'r':
1489
                default:
1490
                        return(EOF);
1491
                        break;
1492
 
24 StephanB 1493
        }
41 ingob 1494
        return(0);
24 StephanB 1495
}
1 ingob 1496
 
41 ingob 1497
/****************************************************************************************************************************************/
1498
/*      Function:               fclose_(File *file);                                                                                                                                                                                            */
1499
/*                                                                                                                                                                                                                                                                              */
1500
/*      Description:    This function closes the open file by writing the remaining data                                                                                                        */
1501
/*                                      from the buffer to the device and entering the filesize in the directory entry.                                                                         */
1502
/*                                                                                                                                                                                                                                                                              */
1503
/*      Returnvalue:    0 on success EOF on error                                                                                                                                                                                       */
1504
/****************************************************************************************************************************************/
1505
s16 fclose_(File_t *file)
24 StephanB 1506
{
41 ingob 1507
        s16 returnvalue = EOF;
24 StephanB 1508
 
41 ingob 1509
        if(file == NULL) return(returnvalue);
1510
        returnvalue = fflush_(file);
1511
        UnlockFilePointer(file);
1512
        return(returnvalue);
24 StephanB 1513
}
1514
 
41 ingob 1515
/********************************************************************************************************************************************/
1516
/*      Function:               fgetc_(File *file);                                                                                                                                                                                                             */
1517
/*                                                                                                                                                                                                                                                                                      */
1518
/*      Description:    This function reads and returns one character from the specified file. Is the end of the actual sector reached the              */
1519
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1520
/*                                                                                                                                                                                                                                                                                      */
1521
/*      Returnvalue:    The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.                                   */
1522
/********************************************************************************************************************************************/
1523
s16 fgetc_(File_t *file)
1524
{      
1525
        s16 c = EOF;
1526
        u32 curr_sector;
24 StephanB 1527
 
41 ingob 1528
        if( (!Partition.IsValid) || (file == NULL)) return(c);
1529
        // if the end of the file is not reached, get the next character.
1530
        if((0 < file->Size) && ((file->Position+1) < file->Size) )                                                             
1 ingob 1531
        {
41 ingob 1532
                curr_sector  = file->FirstSectorOfCurrCluster;          // calculate the sector of the next character to be read.
1533
                curr_sector += file->SectorOfCurrCluster;                      
24 StephanB 1534
 
41 ingob 1535
                if(file->SectorInCache != curr_sector)
1 ingob 1536
                {
41 ingob 1537
                        file->SectorInCache = curr_sector;
1538
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
1539
                        {
1540
                                Fat16_Deinit();
1541
                                return(c);
1542
                        }              
1543
                }      
1544
                c = (s16) file->Cache[file->ByteOfCurrSector];
1545
                file->Position++;                                                                       // increment file position
1546
                file->ByteOfCurrSector++;                                                       // goto next byte in sector             
1547
                if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if end of sector
24 StephanB 1548
                {
41 ingob 1549
                        file->ByteOfCurrSector = 0;                                             //  reset byte location
1550
                        file->SectorOfCurrCluster++;                                    //      next sector
1551
                        if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
24 StephanB 1552
                        {
41 ingob 1553
 
1554
                                if(GetNextCluster(file))                                                                                // Sets the clusterpointer of the file to the next datacluster.
24 StephanB 1555
                                {
41 ingob 1556
                                        file->SectorOfCurrCluster = 0;                                                          // start reading new cluster at first sector of the cluster.
1557
                                }
1558
                                else // the last cluster was allready reached
1559
                                {
1560
                                        file->SectorOfCurrCluster--;                                                    // jump back to the last sector in the last cluster
1561
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
1562
                                }
1 ingob 1563
                        }
24 StephanB 1564
                }
1565
        }
41 ingob 1566
        return(c);
24 StephanB 1567
}
1568
 
41 ingob 1569
/********************************************************************************************************************************************/
1570
/*      Function:               fputc_( const s8 c, File *file);                                                                                                                                                                                */
1571
/*                                                                                                                                                                                                                                                                                      */
1572
/*      Description:    This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries.                                 */
1573
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1574
/*                                                                                                                                                                                                                                                                                      */
1575
/*      Returnvalue:    The function returns the character written to the stream or EOF on error.                                                                                               */
1576
/********************************************************************************************************************************************/
1577
s16 fputc_(const s8 c, File_t *file)
1578
{      
1579
        u32 curr_sector  = 0;
24 StephanB 1580
 
41 ingob 1581
        if((!Partition.IsValid) || (file == NULL)) return(EOF);
24 StephanB 1582
 
41 ingob 1583
        // If file position equals to file size, then the end of file has reached.
1584
        // In this chase it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR 
1585
        // and a new cluster should be appended.
1586
        if((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR))
1587
        {
1588
                if(!AppendCluster(file)) return(EOF);
1589
        }
24 StephanB 1590
 
41 ingob 1591
        curr_sector  = file->FirstSectorOfCurrCluster;
1592
        curr_sector += file->SectorOfCurrCluster;
1593
        if(file->SectorInCache != curr_sector)
1594
        {
1595
                file->SectorInCache = curr_sector;
1596
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
24 StephanB 1597
                {
41 ingob 1598
                        Fat16_Deinit();
1599
                        return(EOF);
1600
                }                      
1601
        }
1602
 
1603
        file->Cache[file->ByteOfCurrSector] = (u8)c;                    // write databyte into the buffer. The byte will be written to the device at once
1604
        if(file->Size == file->Position) file->Size++;          // a character has been written to the file so the size is incremented only when the character has been added at the end of the file.
1605
        file->Position++;                                                                       // the actual positon within the file.
1606
        file->ByteOfCurrSector++;                                                       // goto next byte in sector 
1607
        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if the end of this sector is reached yet
1608
        {       // save the sector to the sd-card
1609
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1610
                {
1611
                        Fat16_Deinit();
1612
                        return(EOF);
1613
                }
1614
                file->ByteOfCurrSector = 0;                                             //  reset byte location
1615
                file->SectorOfCurrCluster++;                                    //      next sector
1616
                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT.
1617
                {
1618
                        if(!GetNextCluster(file))                                                               // Sets the clusterpointer of the file to the next datacluster.
1619
                        { // if current cluster was the last cluster of the file
1620
                                if(!AppendCluster(file))                                                // append a new and free cluster at the end of the file.
24 StephanB 1621
                                {
41 ingob 1622
                                        file->SectorOfCurrCluster--;                            // jump back to last sector of last cluster
1623
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;      // set byte location to 1 byte over sector len
1624
                                        return(EOF);
24 StephanB 1625
                                }
1 ingob 1626
                        }
41 ingob 1627
                        else // next cluster
24 StephanB 1628
                        {
41 ingob 1629
                                file->SectorOfCurrCluster = 0;                                                  // start reading new cluster at first sector of the cluster.
1630
                        }                                              
1 ingob 1631
                }
1632
        }
41 ingob 1633
        return(0);
24 StephanB 1634
}
1635
 
1636
 
41 ingob 1637
/****************************************************************************************************************************************/
1638
/*      Function:               fread_(void *buffer, s32 size, s32 count, File *File);                                                                                                                          */
1639
/*                                                                                                                                                                                                                                                                              */
1640
/*      Description:    This function reads count objects of the specified size                                                                                                                         */
1641
/*                                      from the actual position of the file to the specified buffer.                                                                                                           */
1642
/*                                                                                                                                                                                                                                                                              */
1643
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1644
/****************************************************************************************************************************************/
1645
u32 fread_(void *buffer, u32 size, u32 count, File_t *file)
1646
{
1647
        u32 object_cnt  = 0;                                                                                    // count the number of objects read from the file.
1648
        u32 object_size = 0;                                                                                    // count the number of bytes read from the actual object.
1649
        u8 *pbuff       = 0;                                                                                    // a pointer to the actual bufferposition.
1650
        u8 success      = 1;                                                                                    // no error occured during read operation to the file.
1651
        s16 c; 
24 StephanB 1652
 
41 ingob 1653
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
24 StephanB 1654
 
41 ingob 1655
        pbuff = (u8 *) buffer;                                                                                  // cast the void pointer to an u8 *
24 StephanB 1656
 
41 ingob 1657
        while((object_cnt < count) && success)
24 StephanB 1658
        {
41 ingob 1659
                object_size = size;
1660
                while((size > 0) && success)
1661
                {
1662
                        c = fgetc_(file);
1663
                        if(c != EOF)
1664
                        {
1665
                                *pbuff = (u8)c;                                                                         // read a byte from the buffer to the opened file.
1666
                                pbuff++;
1667
                                size--;
1668
                        }
1669
                        else // error or end of file reached
1670
                        {
1671
                                success = 0;   
1672
                        }
1673
                }
1674
                if(success) object_cnt++;
1675
        }              
1676
        return(object_cnt);                                                                                             // return the number of objects succesfully read from the file
1 ingob 1677
}
1678
 
24 StephanB 1679
 
41 ingob 1680
/****************************************************************************************************************************************/
1681
/*      Function:               fwrite_(void *buffer, s32 size, s32 count, File *file);                                                                                                                         */
1682
/*                                                                                                                                                                                                                                                                              */
1683
/*      Description:    This function writes count objects of the specified size                                                                                                                        */
1684
/*                                      from the buffer pointer to the actual position in the file.                                                                                                                     */
1685
/*                                                                                                                                                                                                                                                                              */
1686
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1687
/****************************************************************************************************************************************/
1688
u32 fwrite_(void *buffer, u32 size, u32 count, File_t *file)
1 ingob 1689
{
41 ingob 1690
        u32 object_cnt  = 0;                                                                                                            // count the number of objects written to the file.
1691
        u32 object_size = 0;                                                                                                            // count the number of bytes written from the actual object.
1692
        u8 *pbuff           = 0;                                                                                                                // a pointer to the actual bufferposition.
1693
        u8 success      = 1;                                                                                                            // no error occured during write operation to the file.
1694
        s16 c; 
24 StephanB 1695
 
41 ingob 1696
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1697
 
1698
        pbuff = (u8 *) buffer;                                                                                                          // cast the void pointer to an u8 *
24 StephanB 1699
 
41 ingob 1700
        while((object_cnt < count) && success)
1 ingob 1701
        {
41 ingob 1702
                object_size = size;
1703
                while((size > 0) && success)
1 ingob 1704
                {
41 ingob 1705
                        c = fputc_(*pbuff, file);                                                                               // write a byte from the buffer to the opened file.
1706
                        if(c != EOF)
24 StephanB 1707
                        {
41 ingob 1708
                                pbuff++;
1709
                                size--;
24 StephanB 1710
                        }
41 ingob 1711
                        else
24 StephanB 1712
                        {
41 ingob 1713
                                success = 0;
24 StephanB 1714
                        }
1 ingob 1715
                }
41 ingob 1716
                if(success) object_cnt++;
1717
        }              
24 StephanB 1718
 
41 ingob 1719
        return(object_cnt);                                                                                                                             // return the number of objects succesfully written to the file
1720
}                                                                                                                                                                              
1 ingob 1721
 
24 StephanB 1722
 
41 ingob 1723
/****************************************************************************************************************************************/
1724
/*      Function:               fputs_(const s8 *string, File_t *File);                                                                                                                                                         */
1725
/*                                                                                                                                                                                                                                                                              */
1726
/*      Description:    This function writes a string to the specified file.                                                                                                                            */
1727
/*                                                                                                                                                                                                                                                                              */
1728
/*      Returnvalue:    The function returns a no negative value or EOF on error.                                                                                                                       */
1729
/****************************************************************************************************************************************/
1730
s16 fputs_(const s8 *string, File_t *file)
24 StephanB 1731
{
41 ingob 1732
        u8 i=0;
1733
        s16 c = 0;
24 StephanB 1734
 
41 ingob 1735
        if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(0);
24 StephanB 1736
 
41 ingob 1737
        while((string[i] != 0)&& (c != EOF))
24 StephanB 1738
        {
41 ingob 1739
                c = fputc_(string[i], file);
1740
                i++;
24 StephanB 1741
        }
41 ingob 1742
        return(c);
24 StephanB 1743
}
1744
 
41 ingob 1745
/****************************************************************************************************************************************/
1746
/*      Function:               fgets_(s8 *, s16 , File_t *);                                                                                                                                                                           */
1747
/*                                                                                                                                                                                                                                                                              */
1748
/*      Description:    This function reads a string from the file to the specifies string.                                                                                             */
1749
/*                                                                                                                                                                                                                                                                              */
1750
/*      Returnvalue:    A pointer to the string read from the file or 0 on error.                                                                                                                       */
1751
/****************************************************************************************************************************************/
1752
u8 * fgets_(s8 *string, s16 length, File_t *file)
24 StephanB 1753
{
41 ingob 1754
        u8 *pbuff;
1755
        s16 c = 0;
24 StephanB 1756
 
41 ingob 1757
        if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length = 0)) return (0);
1758
        pbuff = string;
1759
        while(length > 1)                                                       // read the count-1 characters from the file to the string.
24 StephanB 1760
        {
41 ingob 1761
                c = fgetc_(file);                                               // read a character from the opened file.
1762
                switch(c)
1 ingob 1763
                {
41 ingob 1764
                        case 0x0A:
1765
                                c = 0;                                                  // set string terminator
1766
                                length = 1;                                             // stop loop
1767
                                break;
1768
 
1769
                        case EOF:
1770
                                c = 0;                                                  // set string terminator
1771
                                length = 1;                                             // stop loop
1772
                                break; 
1 ingob 1773
                }
41 ingob 1774
                *pbuff = (u8)c;                                                 // copy byte to string
1775
                length--;
1776
                pbuff++;
24 StephanB 1777
        }
41 ingob 1778
        return(string);
24 StephanB 1779
}
1780
 
41 ingob 1781
/****************************************************************************************************************************************/
1782
/*      Function:               fexist_(const u8*);                                                                                                                                                                                                     */
1783
/*                                                                                                                                                                                                                                                                              */
1784
/*      Description:    This function checks if a file already exist.                                                                                                                                           */
1785
/*                                                                                                                                                                                                                                                                              */
1786
/*      Returnvalue:    1 if the file exist else 0.                                                                                                                                                                                     */
1787
/****************************************************************************************************************************************/
1788
u8 fexist_(const s8* filename)
24 StephanB 1789
{
41 ingob 1790
        u8 exist = 0;
1791
        File_t *file = 0;
1792
        file = LockFilePointer();
1793
        exist = FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file);
1794
        UnlockFilePointer(file);
1795
        return(exist);
1 ingob 1796
}
24 StephanB 1797
 
41 ingob 1798
/****************************************************************************************************************************************/
1799
/*      Function:               feof_(File_t *File);                                                                                                                                                                                            */
1800
/*                                                                                                                                                                                                                                                                              */
1801
/*      Description:    This function checks wether the end of the file has been reached.                                                                                                                                               */
1802
/*                                                                                                                                                                                                                                                                              */
1803
/*      Returnvalue:    0 if the end of the file was not reached otherwise 1.                                                                                                                                                                           */
1804
/****************************************************************************************************************************************/
1805
u8 feof_(File_t *file)
24 StephanB 1806
{      
41 ingob 1807
        if(((file->Position)+1) < (file->Size))
24 StephanB 1808
        {
1809
                return(0);
1810
        }
1811
        else
1812
        {
1813
                return(1);     
1814
        }
1815
}
41 ingob 1816
 
1817