Subversion Repositories NaviCtrl

Rev

Rev 433 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 433 Rev 450
1
/*#######################################################################################*/
1
/*#######################################################################################*/
2
/* !!! THIS IS NOT FREE SOFTWARE !!!                                                     */
2
/* !!! THIS IS NOT FREE SOFTWARE !!!                                                     */
3
/*#######################################################################################*/
3
/*#######################################################################################*/
4
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5
// + www.MikroKopter.com
5
// + www.MikroKopter.com
6
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7
// + Software Nutzungsbedingungen (english version: see below)
7
// + Software Nutzungsbedingungen (english version: see below)
8
// + der Fa. HiSystems GmbH, Flachsmeerstrasse 2, 26802 Moormerland - nachfolgend Lizenzgeber genannt -
8
// + der Fa. HiSystems GmbH, Flachsmeerstrasse 2, 26802 Moormerland - nachfolgend Lizenzgeber genannt -
9
// + Der Lizenzgeber räumt dem Kunden ein nicht-ausschließliches, zeitlich und räumlich* unbeschränktes Recht ein, die im den
9
// + Der Lizenzgeber räumt dem Kunden ein nicht-ausschließliches, zeitlich und räumlich* unbeschränktes Recht ein, die im den
10
// + Mikrocontroller verwendete Firmware für die Hardware Flight-Ctrl, Navi-Ctrl, BL-Ctrl, MK3Mag & PC-Programm MikroKopter-Tool
10
// + Mikrocontroller verwendete Firmware für die Hardware Flight-Ctrl, Navi-Ctrl, BL-Ctrl, MK3Mag & PC-Programm MikroKopter-Tool
11
// + - nachfolgend Software genannt - nur für private Zwecke zu nutzen.
11
// + - nachfolgend Software genannt - nur für private Zwecke zu nutzen.
12
// + Der Einsatz dieser Software ist nur auf oder mit Produkten des Lizenzgebers zulässig.
12
// + Der Einsatz dieser Software ist nur auf oder mit Produkten des Lizenzgebers zulässig.
13
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
14
// + Die vom Lizenzgeber gelieferte Software ist urheberrechtlich geschützt. Alle Rechte an der Software sowie an sonstigen im
14
// + Die vom Lizenzgeber gelieferte Software ist urheberrechtlich geschützt. Alle Rechte an der Software sowie an sonstigen im
15
// + Rahmen der Vertragsanbahnung und Vertragsdurchführung überlassenen Unterlagen stehen im Verhältnis der Vertragspartner ausschließlich dem Lizenzgeber zu.
15
// + Rahmen der Vertragsanbahnung und Vertragsdurchführung überlassenen Unterlagen stehen im Verhältnis der Vertragspartner ausschließlich dem Lizenzgeber zu.
16
// + Die in der Software enthaltenen Copyright-Vermerke, Markenzeichen, andere Rechtsvorbehalte, Seriennummern sowie
16
// + Die in der Software enthaltenen Copyright-Vermerke, Markenzeichen, andere Rechtsvorbehalte, Seriennummern sowie
17
// + sonstige der Programmidentifikation dienenden Merkmale dürfen vom Kunden nicht verändert oder unkenntlich gemacht werden.
17
// + sonstige der Programmidentifikation dienenden Merkmale dürfen vom Kunden nicht verändert oder unkenntlich gemacht werden.
18
// + Der Kunde trifft angemessene Vorkehrungen für den sicheren Einsatz der Software. Er wird die Software gründlich auf deren
18
// + Der Kunde trifft angemessene Vorkehrungen für den sicheren Einsatz der Software. Er wird die Software gründlich auf deren
19
// + Verwendbarkeit zu dem von ihm beabsichtigten Zweck testen, bevor er diese operativ einsetzt.
19
// + Verwendbarkeit zu dem von ihm beabsichtigten Zweck testen, bevor er diese operativ einsetzt.
20
// + Die Haftung des Lizenzgebers wird - soweit gesetzlich zulässig - begrenzt in Höhe des typischen und vorhersehbaren
20
// + Die Haftung des Lizenzgebers wird - soweit gesetzlich zulässig - begrenzt in Höhe des typischen und vorhersehbaren
21
// + Schadens. Die gesetzliche Haftung bei Personenschäden und nach dem Produkthaftungsgesetz bleibt unberührt. Dem Lizenzgeber steht jedoch der Einwand
21
// + Schadens. Die gesetzliche Haftung bei Personenschäden und nach dem Produkthaftungsgesetz bleibt unberührt. Dem Lizenzgeber steht jedoch der Einwand
22
// + des Mitverschuldens offen.
22
// + des Mitverschuldens offen.
23
// + Der Kunde trifft angemessene Vorkehrungen für den Fall, dass die Software ganz oder teilweise nicht ordnungsgemäß arbeitet.
23
// + Der Kunde trifft angemessene Vorkehrungen für den Fall, dass die Software ganz oder teilweise nicht ordnungsgemäß arbeitet.
24
// + Er wird die Software gründlich auf deren Verwendbarkeit zu dem von ihm beabsichtigten Zweck testen, bevor er diese operativ einsetzt.
24
// + Er wird die Software gründlich auf deren Verwendbarkeit zu dem von ihm beabsichtigten Zweck testen, bevor er diese operativ einsetzt.
25
// + Der Kunde wird er seine Daten vor Einsatz der Software nach dem Stand der Technik sichern.
25
// + Der Kunde wird er seine Daten vor Einsatz der Software nach dem Stand der Technik sichern.
26
// + Der Kunde ist darüber unterrichtet, dass der Lizenzgeber seine Daten im zur Vertragsdurchführung erforderlichen Umfang
26
// + Der Kunde ist darüber unterrichtet, dass der Lizenzgeber seine Daten im zur Vertragsdurchführung erforderlichen Umfang
27
// + und auf Grundlage der Datenschutzvorschriften erhebt, speichert, verarbeitet und, sofern notwendig, an Dritte übermittelt.
27
// + und auf Grundlage der Datenschutzvorschriften erhebt, speichert, verarbeitet und, sofern notwendig, an Dritte übermittelt.
28
// + *) Die räumliche Nutzung bezieht sich nur auf den Einsatzort, nicht auf die Reichweite der programmierten Software.
28
// + *) Die räumliche Nutzung bezieht sich nur auf den Einsatzort, nicht auf die Reichweite der programmierten Software.
29
// + #### ENDE DER NUTZUNGSBEDINGUNGEN ####'
29
// + #### ENDE DER NUTZUNGSBEDINGUNGEN ####'
30
// +  Hinweis: Informationen über erweiterte Nutzungsrechte (wie z.B. Nutzung für nicht-private Zwecke) sind auf Anfrage per Email an info(@)hisystems.de verfügbar.
30
// +  Hinweis: Informationen über erweiterte Nutzungsrechte (wie z.B. Nutzung für nicht-private Zwecke) sind auf Anfrage per Email an info(@)hisystems.de verfügbar.
31
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
31
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
32
// + Software LICENSING TERMS
32
// + Software LICENSING TERMS
33
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
33
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
34
// + of HiSystems GmbH, Flachsmeerstrasse 2, 26802 Moormerland, Germany - the Licensor -
34
// + of HiSystems GmbH, Flachsmeerstrasse 2, 26802 Moormerland, Germany - the Licensor -
35
// + The Licensor grants the customer a non-exclusive license to use the microcontroller firmware of the Flight-Ctrl, Navi-Ctrl, BL-Ctrl, and MK3Mag hardware
35
// + The Licensor grants the customer a non-exclusive license to use the microcontroller firmware of the Flight-Ctrl, Navi-Ctrl, BL-Ctrl, and MK3Mag hardware
36
// + (the Software) exclusively for private purposes. The License is unrestricted with respect to time and territory*.
36
// + (the Software) exclusively for private purposes. The License is unrestricted with respect to time and territory*.
37
// + The Software may only be used with the Licensor's products.
37
// + The Software may only be used with the Licensor's products.
38
// + The Software provided by the Licensor is protected by copyright. With respect to the relationship between the parties to this
38
// + The Software provided by the Licensor is protected by copyright. With respect to the relationship between the parties to this
39
// + agreement, all rights pertaining to the Software and other documents provided during the preparation and execution of this
39
// + agreement, all rights pertaining to the Software and other documents provided during the preparation and execution of this
40
// + agreement shall be the property of the Licensor.
40
// + agreement shall be the property of the Licensor.
41
// + The information contained in the Software copyright notices, trademarks, other legal reservations, serial numbers and other
41
// + The information contained in the Software copyright notices, trademarks, other legal reservations, serial numbers and other
42
// + features that can be used to identify the program may not be altered or defaced by the customer.
42
// + features that can be used to identify the program may not be altered or defaced by the customer.
43
// + The customer shall be responsible for taking reasonable precautions
43
// + The customer shall be responsible for taking reasonable precautions
44
// + for the safe use of the Software. The customer shall test the Software thoroughly regarding its suitability for the
44
// + for the safe use of the Software. The customer shall test the Software thoroughly regarding its suitability for the
45
// + intended purpose before implementing it for actual operation. The Licensor's liability shall be limited to the extent of typical and
45
// + intended purpose before implementing it for actual operation. The Licensor's liability shall be limited to the extent of typical and
46
// + foreseeable damage to the extent permitted by law, notwithstanding statutory liability for bodily injury and product
46
// + foreseeable damage to the extent permitted by law, notwithstanding statutory liability for bodily injury and product
47
// + liability. However, the Licensor shall be entitled to the defense of contributory negligence.
47
// + liability. However, the Licensor shall be entitled to the defense of contributory negligence.
48
// + The customer will take adequate precautions in the case, that the software is not working properly. The customer will test
48
// + The customer will take adequate precautions in the case, that the software is not working properly. The customer will test
49
// + the software for his purpose before any operational usage. The customer will backup his data before using the software.
49
// + the software for his purpose before any operational usage. The customer will backup his data before using the software.
50
// + The customer understands that the Licensor collects, stores and processes, and, where required, forwards, customer data
50
// + The customer understands that the Licensor collects, stores and processes, and, where required, forwards, customer data
51
// + to third parties to the extent necessary for executing the agreement, subject to applicable data protection and privacy regulations.
51
// + to third parties to the extent necessary for executing the agreement, subject to applicable data protection and privacy regulations.
52
// + *) The territory aspect only refers to the place where the Software is used, not its programmed range.
52
// + *) The territory aspect only refers to the place where the Software is used, not its programmed range.
53
// + #### END OF LICENSING TERMS ####
53
// + #### END OF LICENSING TERMS ####
54
// + Note: For information on license extensions (e.g. commercial use), please contact us at info(@)hisystems.de.
54
// + Note: For information on license extensions (e.g. commercial use), please contact us at info(@)hisystems.de.
55
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
55
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
56
#include <stdio.h>
56
#include <stdio.h>
57
#include <string.h>
57
#include <string.h>
58
#include "91x_lib.h"
58
#include "91x_lib.h"
59
#include "timer1.h"
59
#include "timer1.h"
60
#include "fat16.h"
60
#include "fat16.h"
61
#include "sdc.h"
61
#include "sdc.h"
62
#include "uart1.h"
62
#include "uart1.h"
63
#include "main.h"
63
#include "main.h"
64
#include "logging.h"
64
#include "logging.h"
65
#include "debug.h"
65
#include "debug.h"
66
 
66
 
67
 
67
 
68
//________________________________________________________________________________________________________________________________________
68
//________________________________________________________________________________________________________________________________________
69
// Module name:                 fat16.c
69
// Module name:                 fat16.c
70
// Compiler used:               avr-gcc 3.4.5
70
// Compiler used:               avr-gcc 3.4.5
71
// Last Modifikation:   1.12.2012
71
// Last Modifikation:   1.12.2012
72
// Version:                             2.11
72
// Version:                             2.11
73
// Authors:                             Stephan Busker & Gregor Stobrawa
73
// Authors:                             Stephan Busker & Gregor Stobrawa
74
// Description:                 Source files for FAT16 implementation with read and write-access
74
// Description:                 Source files for FAT16 implementation with read and write-access
75
//                                              Copyright (C) 2008 Stephan Busker & Gregor Stobrawa
75
//                                              Copyright (C) 2008 Stephan Busker & Gregor Stobrawa
76
//........................................................................................................................................
76
//........................................................................................................................................
77
// Functions:                   extern s16              Fat16_Init(void);
77
// Functions:                   extern s16              Fat16_Init(void);
78
//                                              extern s16              Fat16_Deinit(void);
78
//                                              extern s16              Fat16_Deinit(void);
79
//                                              extern s8*              FAT16_GetVolumeLabel(void);
79
//                                              extern s8*              FAT16_GetVolumeLabel(void);
80
//
80
//
81
//                                              extern File_t * fopen_(const u8 *filename, const s8 mode);
81
//                                              extern File_t * fopen_(const u8 *filename, const s8 mode);
82
//                                              extern s16              fclose_(File_t *file);
82
//                                              extern s16              fclose_(File_t *file);
83
//                                              extern u8               fexist_(s8 * const filename);
83
//                                              extern u8               fexist_(s8 * const filename);
84
//                                              extern s16              fflush_(File_t *file);
84
//                                              extern s16              fflush_(File_t *file);
85
//                                              extern s16      fseek_(File_t *file, s32 offset, s16 origin);
85
//                                              extern s16      fseek_(File_t *file, s32 offset, s16 origin);
86
//                                              extern s16              fgetc_(File_t *file);
86
//                                              extern s16              fgetc_(File_t *file);
87
//                                              extern s16              fputc_(u8 c, File_t *file);
87
//                                              extern s16              fputc_(u8 c, File_t *file);
88
//                                              extern u32              fread_(void *buffer, u32 size, u32 count, File_t *file);
88
//                                              extern u32              fread_(void *buffer, u32 size, u32 count, File_t *file);
89
//                                              extern u32              fwrite_(void *buffer, u32 size, u32 count, File_t *file);
89
//                                              extern u32              fwrite_(void *buffer, u32 size, u32 count, File_t *file);
90
//                                              extern s16              fputs_(const u8 *string, File_t *File);
90
//                                              extern s16              fputs_(const u8 *string, File_t *File);
91
//                                              extern u8 *     fgets_(u8 *string, s16 length, File_t *file);
91
//                                              extern u8 *     fgets_(u8 *string, s16 length, File_t *file);
92
//                                              extern u8               feof_(File_t * const file);
92
//                                              extern u8               feof_(File_t * const file);
93
//                                              extern u8               fdelete_(s8* const filepath);
93
//                                              extern u8               fdelete_(s8* const filepath);
94
//
94
//
95
//                                              extern s8               *getcwd_(void);
95
//                                              extern s8               *getcwd_(void);
96
//                                              extern u8               chdir_(s8* const dirpath);
96
//                                              extern u8               chdir_(s8* const dirpath);
97
//                                              extern u8               mkdir_(s8* const dirpath);
97
//                                              extern u8               mkdir_(s8* const dirpath);
98
//                                              extern u8               rmdir_(s8* const dirpath);
98
//                                              extern u8               rmdir_(s8* const dirpath);
99
//                                              extern u8               findfirst_(const s8* name, u8 attribmask, Find_t *);
99
//                                              extern u8               findfirst_(const s8* name, u8 attribmask, Find_t *);
100
//                                              extern u8               findnext_(Find_t *);
100
//                                              extern u8               findnext_(Find_t *);
101
//........................................................................................................................................
101
//........................................................................................................................................
102
// ext. functions:              extern SD_Result_t SDC_Init(void;)
102
// ext. functions:              extern SD_Result_t SDC_Init(void;)
103
//                                              extern SD_Result_t SDC_Deinit(void);
103
//                                              extern SD_Result_t SDC_Deinit(void);
104
//                      extern SD_Result_t SDC_GetSector (u32,u8 *);
104
//                      extern SD_Result_t SDC_GetSector (u32,u8 *);
105
//                                              extern SD_Result_t SDC_PutSector (u32,u8 *);
105
//                                              extern SD_Result_t SDC_PutSector (u32,u8 *);
106
//........................................................................................................................................
106
//........................................................................................................................................
107
//
107
//
108
// URL:                                 www.Mikro-Control.de
108
// URL:                                 www.Mikro-Control.de
109
// mailto:                              stephan.busker@mikro-control.de
109
// mailto:                              stephan.busker@mikro-control.de
110
//________________________________________________________________________________________________________________________________________
110
//________________________________________________________________________________________________________________________________________
111
 
111
 
112
/*
112
/*
113
FAT16 Drive Layout:
113
FAT16 Drive Layout:
114
Description                                             Offset
114
Description                                             Offset
115
Volume Boot Sector                                      Start of Partition
115
Volume Boot Sector                                      Start of Partition
116
Fat Tables                                                      Start + # of Reserved Sectors
116
Fat Tables                                                      Start + # of Reserved Sectors
117
Root Directory Entry                            Start + # of Reserved + (# of Sectors Per FAT * 2)
117
Root Directory Entry                            Start + # of Reserved + (# of Sectors Per FAT * 2)
118
Data Area (Starts with Cluster #2)      Start + # of Reserved + (# of Sectors Per FAT * 2) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
118
Data Area (Starts with Cluster #2)      Start + # of Reserved + (# of Sectors Per FAT * 2) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
119
*/
119
*/
120
 
120
 
121
 
121
 
122
 
122
 
123
/*
123
/*
124
________________________________________________________________________________________________________________________________________
124
________________________________________________________________________________________________________________________________________
125
 
125
 
126
        Structure of an partition entry
126
        Structure of an partition entry
127
________________________________________________________________________________________________________________________________________
127
________________________________________________________________________________________________________________________________________
128
 
128
 
129
        Partition Entry is 16 bytes long
129
        Partition Entry is 16 bytes long
130
*/
130
*/
131
typedef struct
131
typedef struct
132
{
132
{
133
        u8      PartitionState;                         // Current State of Partition (00h=Inactive, 80h=Active)
133
        u8      PartitionState;                         // Current State of Partition (00h=Inactive, 80h=Active)
134
        u8      BeginningHead;                          // Beginning of Partition - Head
134
        u8      BeginningHead;                          // Beginning of Partition - Head
135
        u16     BeginningCylSec;                        // Beginning of Partition - Cylinder/Sector (See Below)
135
        u16     BeginningCylSec;                        // Beginning of Partition - Cylinder/Sector (See Below)
136
        u8      Type;                                           // Type of Partition (See List Below)
136
        u8      Type;                                           // Type of Partition (See List Below)
137
        u8      EndHead;                                        // End of Partition - Head
137
        u8      EndHead;                                        // End of Partition - Head
138
        u16     EndCylSec;                                      // End of Partition - Cylinder/Sector
138
        u16     EndCylSec;                                      // End of Partition - Cylinder/Sector
139
        u32     NoSectorsBeforePartition;       // Number of Sectors between the MBR and the First Sector in the Partition
139
        u32     NoSectorsBeforePartition;       // Number of Sectors between the MBR and the First Sector in the Partition
140
        u32     NoSectorsPartition      ;               // Number of Sectors in the Partition
140
        u32     NoSectorsPartition      ;               // Number of Sectors in the Partition
141
} __attribute__((packed)) PartitionEntry_t;
141
} __attribute__((packed)) PartitionEntry_t;
142
 
142
 
143
 
143
 
144
 
144
 
145
/*
145
/*
146
Coding of Cylinder/Sector words
146
Coding of Cylinder/Sector words
147
 
147
 
148
Cylinder is 10 bits:  [7:0] at [15:8] and [9:8] at [7:6]
148
Cylinder is 10 bits:  [7:0] at [15:8] and [9:8] at [7:6]
149
Sector is 5 bits:  [5:0] at [5:0]
149
Sector is 5 bits:  [5:0] at [5:0]
150
*/
150
*/
151
 
151
 
152
// Partition Types:
152
// Partition Types:
153
#define PART_TYPE_UNKNOWN                       0x00
153
#define PART_TYPE_UNKNOWN                       0x00
154
#define PART_TYPE_FAT12                         0x01
154
#define PART_TYPE_FAT12                         0x01
155
#define PART_TYPE_XENIX                         0x02
155
#define PART_TYPE_XENIX                         0x02
156
#define PART_TYPE_FAT16_ST_32_MB        0x04
156
#define PART_TYPE_FAT16_ST_32_MB        0x04
157
#define PART_TYPE_EXTDOS                        0x05
157
#define PART_TYPE_EXTDOS                        0x05
158
#define PART_TYPE_FAT16_LT_32_MB        0x06
158
#define PART_TYPE_FAT16_LT_32_MB        0x06
159
#define PART_TYPE_NTFS                          0x07
159
#define PART_TYPE_NTFS                          0x07
160
#define PART_TYPE_FAT32                         0x0B
160
#define PART_TYPE_FAT32                         0x0B
161
#define PART_TYPE_FAT32LBA                      0x0C
161
#define PART_TYPE_FAT32LBA                      0x0C
162
#define PART_TYPE_FAT16LBA                      0x0E
162
#define PART_TYPE_FAT16LBA                      0x0E
163
#define PART_TYPE_EXTDOSLBA                     0x0F
163
#define PART_TYPE_EXTDOSLBA                     0x0F
164
#define PART_TYPE_EISA                          0x12
164
#define PART_TYPE_EISA                          0x12
165
#define PART_TYPE_ONTRACK                       0x33
165
#define PART_TYPE_ONTRACK                       0x33
166
#define PART_TYPE_NOVELL                        0x40
166
#define PART_TYPE_NOVELL                        0x40
167
#define PART_TYPE_DYNAMIC                       0x42
167
#define PART_TYPE_DYNAMIC                       0x42
168
#define PART_TYPE_PCIX                          0x4B
168
#define PART_TYPE_PCIX                          0x4B
169
#define PART_TYPE_LINUX_SWAP            0x82
169
#define PART_TYPE_LINUX_SWAP            0x82
170
#define PART_TYPE_LINUX_NATIVE          0x83
170
#define PART_TYPE_LINUX_NATIVE          0x83
171
#define PART_TYPE_LINUX_LVM                     0x8E
171
#define PART_TYPE_LINUX_LVM                     0x8E
172
#define PART_TYPE_PHOENIXSAVE           0xA0
172
#define PART_TYPE_PHOENIXSAVE           0xA0
173
#define PART_TYPE_FREEBSD                       0xA5
173
#define PART_TYPE_FREEBSD                       0xA5
174
#define PART_TYPE_OPENBSD                       0xA6
174
#define PART_TYPE_OPENBSD                       0xA6
175
#define PART_TYPE_NETNBSD                       0xA9
175
#define PART_TYPE_NETNBSD                       0xA9
176
#define PART_TYPE_CPM                           0xDB
176
#define PART_TYPE_CPM                           0xDB
177
#define PART_TYPE_DBFS                          0xE0
177
#define PART_TYPE_DBFS                          0xE0
178
#define PART_TYPE_BBT                           0xFF
178
#define PART_TYPE_BBT                           0xFF
179
 
179
 
180
 
180
 
181
/*
181
/*
182
________________________________________________________________________________________________________________________________________
182
________________________________________________________________________________________________________________________________________
183
 
183
 
184
        Structure of the MasterBootRecord
184
        Structure of the MasterBootRecord
185
________________________________________________________________________________________________________________________________________
185
________________________________________________________________________________________________________________________________________
186
 
186
 
187
        Master Boot Record is 512 bytes long
187
        Master Boot Record is 512 bytes long
188
        The Master Boot Record is the same for pretty much all Operating Systems.
188
        The Master Boot Record is the same for pretty much all Operating Systems.
189
        It is located on the first Sector of the Hard Drive, at Cylinder 0, Head 0, Sector 1
189
        It is located on the first Sector of the Hard Drive, at Cylinder 0, Head 0, Sector 1
190
*/
190
*/
191
typedef struct
191
typedef struct
192
{
192
{
193
        u8                              ExecutableCode[446];    // 446 bytes for machine start code
193
        u8                              ExecutableCode[446];    // 446 bytes for machine start code
194
        PartitionEntry_t        PartitionEntry1;                // 16 bytes for partition entry 1
194
        PartitionEntry_t        PartitionEntry1;                // 16 bytes for partition entry 1
195
        PartitionEntry_t        PartitionEntry2;                // 16 bytes for partition entry 2
195
        PartitionEntry_t        PartitionEntry2;                // 16 bytes for partition entry 2
196
        PartitionEntry_t        PartitionEntry3;                // 16 bytes for partition entry 3
196
        PartitionEntry_t        PartitionEntry3;                // 16 bytes for partition entry 3
197
        PartitionEntry_t        PartitionEntry4;                // 16 bytes for partition entry 4
197
        PartitionEntry_t        PartitionEntry4;                // 16 bytes for partition entry 4
198
        u16                                     ExecutableMarker;               // BIOS-Signature (0x55 0xAA)
198
        u16                                     ExecutableMarker;               // BIOS-Signature (0x55 0xAA)
199
} __attribute__((packed)) MBR_Entry_t;
199
} __attribute__((packed)) MBR_Entry_t;
200
 
200
 
201
 
201
 
202
/*
202
/*
203
________________________________________________________________________________________________________________________________________
203
________________________________________________________________________________________________________________________________________
204
 
204
 
205
        Structure of the VolumeBootRecord
205
        Structure of the VolumeBootRecord
206
________________________________________________________________________________________________________________________________________
206
________________________________________________________________________________________________________________________________________
207
 
207
 
208
        The Volume Boot Record is 512 bytes long
208
        The Volume Boot Record is 512 bytes long
209
        This information is located in the first sector of every partition.
209
        This information is located in the first sector of every partition.
210
*/
210
*/
211
typedef struct
211
typedef struct
212
{
212
{
213
        u8  JumpCode[3];                        // Jump Code + NOP
213
        u8  JumpCode[3];                        // Jump Code + NOP
214
        s8  OEMName[8];                         // OEM Name
214
        s8  OEMName[8];                         // OEM Name
215
        u16 BytesPerSector;                     // Bytes Per Sector
215
        u16 BytesPerSector;                     // Bytes Per Sector
216
        u8  SectorsPerCluster;          // Sectors Per Cluster
216
        u8  SectorsPerCluster;          // Sectors Per Cluster
217
        u16 ReservedSectors;            // Reserved Sectors
217
        u16 ReservedSectors;            // Reserved Sectors
218
        u8  NoFATCopies;                        // Number of Copies of FAT
218
        u8  NoFATCopies;                        // Number of Copies of FAT
219
        u16 MaxRootEntries;                     // Maximum Root Directory Entries
219
        u16 MaxRootEntries;                     // Maximum Root Directory Entries
220
        u16 NoSectorsInPartSml32MB;     // Number of Sectors in Partition Smaller than 32 MB
220
        u16 NoSectorsInPartSml32MB;     // Number of Sectors in Partition Smaller than 32 MB
221
        u8  MediaDescriptor;            // Media Descriptor (0xF8 for Hard Disks)
221
        u8  MediaDescriptor;            // Media Descriptor (0xF8 for Hard Disks)
222
        u16 SectorsPerFAT;                      // Sectors Per FAT
222
        u16 SectorsPerFAT;                      // Sectors Per FAT
223
        u16 SectorsPerTrack;            // Sectors Per Track
223
        u16 SectorsPerTrack;            // Sectors Per Track
224
        u16 NoHeads;                            // Number of Heads
224
        u16 NoHeads;                            // Number of Heads
225
        u32 NoHiddenSectors;            // Number of Hidden Sectors     in Partition
225
        u32 NoHiddenSectors;            // Number of Hidden Sectors     in Partition
226
        u32 NoSectors;                          // Number of Sectors in Partition
226
        u32 NoSectors;                          // Number of Sectors in Partition
227
        u16     DriveNo;                                // Logical Drive Number of Partition
227
        u16     DriveNo;                                // Logical Drive Number of Partition
228
        u8  ExtendedSig;                        // Extended Signature (0x29)
228
        u8  ExtendedSig;                        // Extended Signature (0x29)
229
        u32 SerialNo;                           // Serial Number of the Partition
229
        u32 SerialNo;                           // Serial Number of the Partition
230
        s8  VolumeName[11];                     // Volume Name of the Partititon
230
        s8  VolumeName[11];                     // Volume Name of the Partititon
231
        s8  FATName[8];                         // FAT Name (FAT16)
231
        s8  FATName[8];                         // FAT Name (FAT16)
232
        u8  ExecutableCode[446];        // 446 bytes for machine start code
232
        u8  ExecutableCode[446];        // 446 bytes for machine start code
233
        u16 ExecutableMarker;           // Executable Marker (0x55 0xAA)
233
        u16 ExecutableMarker;           // Executable Marker (0x55 0xAA)
234
} __attribute__((packed)) VBR_Entry_t;
234
} __attribute__((packed)) VBR_Entry_t;
235
 
235
 
236
 
236
 
237
 
237
 
238
/*
238
/*
239
________________________________________________________________________________________________________________________________________
239
________________________________________________________________________________________________________________________________________
240
 
240
 
241
        Structure of an directory entry
241
        Structure of an directory entry
242
________________________________________________________________________________________________________________________________________
242
________________________________________________________________________________________________________________________________________
243
 
243
 
244
        Directory entry is 32 bytes.
244
        Directory entry is 32 bytes.
245
*/
245
*/
246
typedef struct
246
typedef struct
247
{
247
{
248
        s8      Name[8];                                        // 8 bytes name, padded with spaces.
248
        s8      Name[8];                                        // 8 bytes name, padded with spaces.
249
        u8      Extension[3];                           // 3 bytes extension, padded with spaces.
249
        u8      Extension[3];                           // 3 bytes extension, padded with spaces.
250
        u8      Attribute;                                      // attribute of the directory entry (unused,archive,read-only,system,directory,volume)
250
        u8      Attribute;                                      // attribute of the directory entry (unused,archive,read-only,system,directory,volume)
251
        u8  Res1;                                               // should be zero
251
        u8  Res1;                                               // should be zero
252
        u8  CreationTime10ms;                   // subsecond resolution of creation time
252
        u8  CreationTime10ms;                   // subsecond resolution of creation time
253
        u16 CreationTime;                               // Time of creation h:m:s
253
        u16 CreationTime;                               // Time of creation h:m:s
254
        u16 CreationDate;                               // Date of creation Y.M.D
254
        u16 CreationDate;                               // Date of creation Y.M.D
255
        u16 LastAccessDate;             // The date where the file was last accessed
255
        u16 LastAccessDate;             // The date where the file was last accessed
256
        u8      Res2[2];                                    // should be zero
256
        u8      Res2[2];                                    // should be zero
257
        u16 ModTime;                                    // date of last write access
257
        u16 ModTime;                                    // date of last write access
258
        u16 ModDate;                                    // date of last write access to the file or directory.
258
        u16 ModDate;                                    // date of last write access to the file or directory.
259
        u16 StartCluster;                               // first cluster of the file or directory.
259
        u16 StartCluster;                               // first cluster of the file or directory.
260
        u32 Size;                                               // size of the file or directory in bytes.
260
        u32 Size;                                               // size of the file or directory in bytes.
261
}  __attribute__((packed)) DirEntry_t;
261
}  __attribute__((packed)) DirEntry_t;
262
 
262
 
263
#define SLOT_EMPTY              0x00    // slot has never been used
263
#define SLOT_EMPTY              0x00    // slot has never been used
264
#define SLOT_E5                 0x05    // the real value is 0xE5
264
#define SLOT_E5                 0x05    // the real value is 0xE5
265
#define SLOT_DELETED            0xE5    // file in this slot deleted
265
#define SLOT_DELETED            0xE5    // file in this slot deleted
266
 
266
 
267
/*
267
/*
268
________________________________________________________________________________________________________________________________________
268
________________________________________________________________________________________________________________________________________
269
 
269
 
270
        Structure of an entry within the fileallocationtable.
270
        Structure of an entry within the fileallocationtable.
271
________________________________________________________________________________________________________________________________________
271
________________________________________________________________________________________________________________________________________
272
*/
272
*/
273
typedef struct
273
typedef struct
274
{
274
{
275
        u16  NextCluster;                               // the next cluster of the file.
275
        u16  NextCluster;                               // the next cluster of the file.
276
} __attribute__((packed)) Fat16Entry_t;
276
} __attribute__((packed)) Fat16Entry_t;
277
 
277
 
278
// secial fat entries
278
// secial fat entries
279
#define FAT16_CLUSTER_FREE                      0x0000
279
#define FAT16_CLUSTER_FREE                      0x0000
280
#define FAT16_CLUSTER_RESERVED          0x0001
280
#define FAT16_CLUSTER_RESERVED          0x0001
281
#define FAT16_CLUSTER_USED_MIN          0x0002
281
#define FAT16_CLUSTER_USED_MIN          0x0002
282
#define FAT16_CLUSTER_USED_MAX          0xFFEF
282
#define FAT16_CLUSTER_USED_MAX          0xFFEF
283
#define FAT16_CLUSTER_ROOTDIR_MIN       0xFFF0
283
#define FAT16_CLUSTER_ROOTDIR_MIN       0xFFF0
284
#define FAT16_CLUSTER_ROOTDIR_MAX       0xFFF6
284
#define FAT16_CLUSTER_ROOTDIR_MAX       0xFFF6
285
#define FAT16_CLUSTER_BAD                       0xFFF7
285
#define FAT16_CLUSTER_BAD                       0xFFF7
286
#define FAT16_CLUSTER_LAST_MIN          0xFFF8
286
#define FAT16_CLUSTER_LAST_MIN          0xFFF8
287
#define FAT16_CLUSTER_LAST_MAX          0xFFFF
287
#define FAT16_CLUSTER_LAST_MAX          0xFFFF
288
 
288
 
289
/*****************************************************************************************************************************************/
289
/*****************************************************************************************************************************************/
290
/*                                                                                                                                                                                                                                                                               */
290
/*                                                                                                                                                                                                                                                                               */
291
/*      Global variables needed for read- or write-acces to the FAT16- filesystem.                                                                                                                       */
291
/*      Global variables needed for read- or write-acces to the FAT16- filesystem.                                                                                                                       */
292
/*                                                                                                                                                                                                                                                                               */
292
/*                                                                                                                                                                                                                                                                               */
293
/*****************************************************************************************************************************************/
293
/*****************************************************************************************************************************************/
294
 
294
 
295
#define MBR_SECTOR                                      0x00    // the masterboot record is located in sector 0.
295
#define MBR_SECTOR                                      0x00    // the masterboot record is located in sector 0.
296
#define DIRENTRY_SIZE                           32              //bytes
296
#define DIRENTRY_SIZE                           32              //bytes
297
#define DIRENTRIES_PER_SECTOR           BYTES_PER_SECTOR/DIRENTRY_SIZE
297
#define DIRENTRIES_PER_SECTOR           BYTES_PER_SECTOR/DIRENTRY_SIZE
298
#define FAT16_BYTES                                     2
298
#define FAT16_BYTES                                     2
299
#define FAT16_ENTRIES_PER_SECTOR        BYTES_PER_SECTOR/FAT16_BYTES
299
#define FAT16_ENTRIES_PER_SECTOR        BYTES_PER_SECTOR/FAT16_BYTES
300
 
300
 
301
#define SECTOR_UNDEFINED        0x00000000L
301
#define SECTOR_UNDEFINED        0x00000000L
302
#define CLUSTER_UNDEFINED       0x0000
302
#define CLUSTER_UNDEFINED       0x0000
303
 
303
 
304
#define FSTATE_UNUSED   0
304
#define FSTATE_UNUSED   0
305
#define FSTATE_USED             1
305
#define FSTATE_USED             1
306
 
306
 
307
 
307
 
308
Partition_t     Partition;              // Structure holds partition information
308
Partition_t     Partition;              // Structure holds partition information
309
 
309
 
310
File_t FilePointer[FILE_MAX_OPEN];      // Allocate Memmoryspace for each filepointer used.
310
File_t FilePointer[FILE_MAX_OPEN];      // Allocate Memmoryspace for each filepointer used.
311
 
311
 
312
/********************************************************************************************************************************************/
312
/********************************************************************************************************************************************/
313
/*      Function:               s8 *getcwd_(void);                                                                                                                                                                                                              */
313
/*      Function:               s8 *getcwd_(void);                                                                                                                                                                                                              */
314
/*                                                                                                                                                                                                                                                                                      */
314
/*                                                                                                                                                                                                                                                                                      */
315
/*      Description:    This function returns a pointer to the absolute path of the active partition                                                                            */
315
/*      Description:    This function returns a pointer to the absolute path of the active partition                                                                            */
316
/*                                                                                                                                                                                                                                      */
316
/*                                                                                                                                                                                                                                      */
317
/*                                                                                                                                                                                                                                                                                      */
317
/*                                                                                                                                                                                                                                                                                      */
318
/*      Returnvalue:    pointer to the string containing the path to the CWD                                                                                                                                    */
318
/*      Returnvalue:    pointer to the string containing the path to the CWD                                                                                                                                    */
319
/********************************************************************************************************************************************/
319
/********************************************************************************************************************************************/
320
 
320
 
321
s8 *getcwd_(void)
321
s8 *getcwd_(void)
322
{
322
{
323
        return(Partition.PathToCwd);
323
        return(Partition.PathToCwd);
324
}
324
}
325
 
325
 
326
/********************************************************************************************************************************************/
326
/********************************************************************************************************************************************/
327
/*      Function:               void CWDPath_Push(s8* directory);                                                                                                                                                                               */
327
/*      Function:               void CWDPath_Push(s8* directory);                                                                                                                                                                               */
328
/*                                                                                                                                                                                                                                                                                      */
328
/*                                                                                                                                                                                                                                                                                      */
329
/*      Description:    This function function appends the name of an directory to the path of the CWD                                                                                  */
329
/*      Description:    This function function appends the name of an directory to the path of the CWD                                                                                  */
330
/*                                                                                                                                                                                                                                      */
330
/*                                                                                                                                                                                                                                      */
331
/*                                                                                                                                                                                                                                                                                      */
331
/*                                                                                                                                                                                                                                                                                      */
332
/*      Returnvalue:    none                                                                                                                                                                                                                                    */
332
/*      Returnvalue:    none                                                                                                                                                                                                                                    */
333
/********************************************************************************************************************************************/
333
/********************************************************************************************************************************************/
334
 
334
 
335
void CWDPath_Push(s8* directory)
335
void CWDPath_Push(s8* directory)
336
{
336
{
337
        // append the name of the directory to the path
337
        // append the name of the directory to the path
338
        strcat(Partition.PathToCwd, directory);
338
        strcat(Partition.PathToCwd, directory);
339
        // append a '/' after the directoryname
339
        // append a '/' after the directoryname
340
        strcat(Partition.PathToCwd, "/");
340
        strcat(Partition.PathToCwd, "/");
341
}
341
}
342
 
342
 
343
/********************************************************************************************************************************************/
343
/********************************************************************************************************************************************/
344
/*      Function:               CWDPath_Pop(void);                                                                                                                                                                                                              */
344
/*      Function:               CWDPath_Pop(void);                                                                                                                                                                                                              */
345
/*                                                                                                                                                                                                                                                                                      */
345
/*                                                                                                                                                                                                                                                                                      */
346
/*      Description:    This function removes the last directory from the path to the CWD                                                                                                               */
346
/*      Description:    This function removes the last directory from the path to the CWD                                                                                                               */
347
/*                                                                                                                                                                                                                                      */
347
/*                                                                                                                                                                                                                                      */
348
/*                                                                                                                                                                                                                                                                                      */
348
/*                                                                                                                                                                                                                                                                                      */
349
/*      Returnvalue:    none                                                                                                                                                                                                                                    */
349
/*      Returnvalue:    none                                                                                                                                                                                                                                    */
350
/********************************************************************************************************************************************/
350
/********************************************************************************************************************************************/
351
 
351
 
352
void CWDPath_Pop(void)
352
void CWDPath_Pop(void)
353
{
353
{
354
        // a pointer to the beginning of the absolute path to the cwd
354
        // a pointer to the beginning of the absolute path to the cwd
355
        s8 * cptr = Partition.PathToCwd;
355
        s8 * cptr = Partition.PathToCwd;
356
        // lets find the end of the path to the cwd
356
        // lets find the end of the path to the cwd
357
        while(*cptr != 0 ) cptr++;
357
        while(*cptr != 0 ) cptr++;
358
        // if the path is terminated with an '/' then remove it
358
        // if the path is terminated with an '/' then remove it
359
        if((*(cptr-1)) == '/') *(cptr-1) = 0;
359
        if((*(cptr-1)) == '/') *(cptr-1) = 0;
360
        // now lets find the beginning of the last directory entry
360
        // now lets find the beginning of the last directory entry
361
        while((*cptr != '/' ) && cptr > Partition.PathToCwd) cptr--;
361
        while((*cptr != '/' ) && cptr > Partition.PathToCwd) cptr--;
362
        // is there one subdirectory left within the path?
362
        // is there one subdirectory left within the path?
363
        if(cptr > Partition.PathToCwd)
363
        if(cptr > Partition.PathToCwd)
364
        {
364
        {
365
                // we delete the direntry by terminating the path with 0
365
                // we delete the direntry by terminating the path with 0
366
                *(cptr+1) = 0;
366
                *(cptr+1) = 0;
367
        }
367
        }
368
        // there is no subdirectory left within the path. Therefore we create the root instead.
368
        // there is no subdirectory left within the path. Therefore we create the root instead.
369
        else
369
        else
370
        {
370
        {
371
                *cptr = '/';
371
                *cptr = '/';
372
                *(cptr+1) = 0;
372
                *(cptr+1) = 0;
373
        }
373
        }
374
}
374
}
375
 
375
 
376
/****************************************************************************************************************************************/
376
/****************************************************************************************************************************************/
377
/*      Function:               FileDate(DateTime_t *);                                                                                                                                                                                         */
377
/*      Function:               FileDate(DateTime_t *);                                                                                                                                                                                         */
378
/*                                                                                                                                                                                                                                                                              */
378
/*                                                                                                                                                                                                                                                                              */
379
/*      Description:    This function calculates the DOS date from a pointer to a time structure.                                                                                       */
379
/*      Description:    This function calculates the DOS date from a pointer to a time structure.                                                                                       */
380
/*                                                                                                                                                                                                                                                                              */
380
/*                                                                                                                                                                                                                                                                              */
381
/*      Returnvalue:    Returns the DOS date.                                                                                                                                                                                           */
381
/*      Returnvalue:    Returns the DOS date.                                                                                                                                                                                           */
382
/****************************************************************************************************************************************/
382
/****************************************************************************************************************************************/
383
u16 FileDate(DateTime_t * pTimeStruct)
383
u16 FileDate(DateTime_t * pTimeStruct)
384
{
384
{
385
        u16 date = 0;
385
        u16 date = 0;
386
        if(pTimeStruct == NULL)   return date;
386
        if(pTimeStruct == NULL)   return date;
387
        if(!(pTimeStruct->Valid)) return date;
387
        if(!(pTimeStruct->Valid)) return date;
388
 
388
 
389
        date |= (0x007F & (u16)(pTimeStruct->Year - 1980))<<9; // set year
389
        date |= (0x007F & (u16)(pTimeStruct->Year - 1980))<<9; // set year
390
        date |= (0x000F & (u16)(pTimeStruct->Month))<<5; // set month
390
        date |= (0x000F & (u16)(pTimeStruct->Month))<<5; // set month
391
        date |= (0x001F & (u16)(pTimeStruct->Day));
391
        date |= (0x001F & (u16)(pTimeStruct->Day));
392
        return date;
392
        return date;
393
}
393
}
394
 
394
 
395
/****************************************************************************************************************************************/
395
/****************************************************************************************************************************************/
396
/*      Function:               FileTime(DateTime_t *);                                                                                                                                                                                         */
396
/*      Function:               FileTime(DateTime_t *);                                                                                                                                                                                         */
397
/*                                                                                                                                                                                                                                                                              */
397
/*                                                                                                                                                                                                                                                                              */
398
/*      Description:    This function calculates the DOS time from a pointer to a time structure.                                                                                       */
398
/*      Description:    This function calculates the DOS time from a pointer to a time structure.                                                                                       */
399
/*                                                                                                                                                                                                                                                                              */
399
/*                                                                                                                                                                                                                                                                              */
400
/*      Returnvalue:    Returns the DOS time.                                                                                                                                                                                           */
400
/*      Returnvalue:    Returns the DOS time.                                                                                                                                                                                           */
401
/****************************************************************************************************************************************/
401
/****************************************************************************************************************************************/
402
 
402
 
403
u16 FileTime(DateTime_t * pTimeStruct)
403
u16 FileTime(DateTime_t * pTimeStruct)
404
{
404
{
405
        u16 time = 0;
405
        u16 time = 0;
406
        if(pTimeStruct == NULL)   return time;
406
        if(pTimeStruct == NULL)   return time;
407
        if(!(pTimeStruct->Valid)) return time;
407
        if(!(pTimeStruct->Valid)) return time;
408
 
408
 
409
        time |= (0x001F & (u16)(pTimeStruct->Hour))<<11;
409
        time |= (0x001F & (u16)(pTimeStruct->Hour))<<11;
410
        time |= (0x003F & (u16)(pTimeStruct->Min))<<5;
410
        time |= (0x003F & (u16)(pTimeStruct->Min))<<5;
411
        time |= (0x001F & (u16)(pTimeStruct->Sec/2));
411
        time |= (0x001F & (u16)(pTimeStruct->Sec/2));
412
        return time;
412
        return time;
413
}
413
}
414
 
414
 
415
/****************************************************************************************************************************************/
415
/****************************************************************************************************************************************/
416
/*      Function:               LockFilePointer();                                                                                                                                                                                                      */
416
/*      Function:               LockFilePointer();                                                                                                                                                                                                      */
417
/*                                                                                                                                                                                                                                                                              */
417
/*                                                                                                                                                                                                                                                                              */
418
/*      Description:    This function trys to lock a free file pointer.                                                                                                                                         */
418
/*      Description:    This function trys to lock a free file pointer.                                                                                                                                         */
419
/*                                                                                                                                                                                                                                                                              */
419
/*                                                                                                                                                                                                                                                                              */
420
/*      Returnvalue:    Returns the Filepointer on success or 0.                                                                                                                                                        */
420
/*      Returnvalue:    Returns the Filepointer on success or 0.                                                                                                                                                        */
421
/****************************************************************************************************************************************/
421
/****************************************************************************************************************************************/
422
File_t * LockFilePointer(void)
422
File_t * LockFilePointer(void)
423
{
423
{
424
        u8 i;
424
        u8 i;
425
        File_t * File = 0;
425
        File_t * File = 0;
426
        for(i = 0; i < FILE_MAX_OPEN; i++)
426
        for(i = 0; i < FILE_MAX_OPEN; i++)
427
        {
427
        {
428
                if(FilePointer[i].State == FSTATE_UNUSED)                                                               // found an unused one
428
                if(FilePointer[i].State == FSTATE_UNUSED)                                                               // found an unused one
429
                {
429
                {
430
                        File = &FilePointer[i];                                                                                         // set pointer to that entry
430
                        File = &FilePointer[i];                                                                                         // set pointer to that entry
431
                        FilePointer[i].FirstSectorOfFirstCluster = SECTOR_UNDEFINED;            // First sector of the first cluster of the file.
431
                        FilePointer[i].FirstSectorOfFirstCluster = SECTOR_UNDEFINED;            // First sector of the first cluster of the file.
432
                        FilePointer[i].FirstSectorOfCurrCluster = SECTOR_UNDEFINED;                     // First sector of the cluster which is edited at the moment.
432
                        FilePointer[i].FirstSectorOfCurrCluster = SECTOR_UNDEFINED;                     // First sector of the cluster which is edited at the moment.
433
                        FilePointer[i].FirstSectorOfLastCluster = SECTOR_UNDEFINED;                     // First sector of the last cluster of the file
433
                        FilePointer[i].FirstSectorOfLastCluster = SECTOR_UNDEFINED;                     // First sector of the last cluster of the file
434
                        FilePointer[i].SectorOfCurrCluster = SECTOR_UNDEFINED;                          // The sector within the current cluster.
434
                        FilePointer[i].SectorOfCurrCluster = SECTOR_UNDEFINED;                          // The sector within the current cluster.
435
                        FilePointer[i].ByteOfCurrSector = 0;                                                            // The byte location within the current sector.
435
                        FilePointer[i].ByteOfCurrSector = 0;                                                            // The byte location within the current sector.
436
                        FilePointer[i].Mode = 0;                                                                                        // Mode of fileoperation (read,write)
436
                        FilePointer[i].Mode = 0;                                                                                        // Mode of fileoperation (read,write)
437
                        FilePointer[i].Size = 0;                                                                                        // The size of the opend file in bytes.
437
                        FilePointer[i].Size = 0;                                                                                        // The size of the opend file in bytes.
438
                        FilePointer[i].Position = 0;                                                                            // Pointer to a character within the file 0 < fileposition < filesize
438
                        FilePointer[i].Position = 0;                                                                            // Pointer to a character within the file 0 < fileposition < filesize
439
                        FilePointer[i].DirectorySector = SECTOR_UNDEFINED;                                      // the sectorposition where the directoryentry has been made.
439
                        FilePointer[i].DirectorySector = SECTOR_UNDEFINED;                                      // the sectorposition where the directoryentry has been made.
440
                        FilePointer[i].DirectoryIndex = 0;                                                                      // The index to the directoryentry within the specified sector.
440
                        FilePointer[i].DirectoryIndex = 0;                                                                      // The index to the directoryentry within the specified sector.
441
                        FilePointer[i].Attribute = 0;                                                                           // The attribute of the file opened.
441
                        FilePointer[i].Attribute = 0;                                                                           // The attribute of the file opened.
442
                        FilePointer[i].SectorInCache = SECTOR_UNDEFINED;                                        // The last sector read, which is still in the sector cache.
442
                        FilePointer[i].SectorInCache = SECTOR_UNDEFINED;                                        // The last sector read, which is still in the sector cache.
443
                        FilePointer[i].State = FSTATE_USED;                                                                     // mark it as used
443
                        FilePointer[i].State = FSTATE_USED;                                                                     // mark it as used
444
 
444
 
445
                        break;
445
                        break;
446
                }
446
                }
447
        }
447
        }
448
        return(File);
448
        return(File);
449
}
449
}
450
 
450
 
451
/****************************************************************************************************************************************/
451
/****************************************************************************************************************************************/
452
/*      Function:               UnlockFilePointer(file_t *);                                                                                                                                                                            */
452
/*      Function:               UnlockFilePointer(file_t *);                                                                                                                                                                            */
453
/*                                                                                                                                                                                                                                                                              */
453
/*                                                                                                                                                                                                                                                                              */
454
/*      Description:    This function trys to unlock a file pointer.                                                                                                                                            */
454
/*      Description:    This function trys to unlock a file pointer.                                                                                                                                            */
455
/*                                                                                                                                                                                                                                                                              */
455
/*                                                                                                                                                                                                                                                                              */
456
/*      Returnvalue:    Returns 1 if file pointer was freed else 0.                                                                                                                                                     */
456
/*      Returnvalue:    Returns 1 if file pointer was freed else 0.                                                                                                                                                     */
457
/****************************************************************************************************************************************/
457
/****************************************************************************************************************************************/
458
u8 UnlockFilePointer(File_t * file)
458
u8 UnlockFilePointer(File_t * file)
459
{
459
{
460
        u8 cnt;
460
        u8 cnt;
461
        if(file == NULL) return(0);
461
        if(file == NULL) return(0);
462
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
462
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
463
        {
463
        {
464
                if(&FilePointer[cnt] == file)                                           // filepointer to be freed found?
464
                if(&FilePointer[cnt] == file)                                           // filepointer to be freed found?
465
                {
465
                {
466
                        file->State = FSTATE_UNUSED;
466
                        file->State = FSTATE_UNUSED;
467
                        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;                     // Sectorpointer to the first sector of the first datacluster of the file.
467
                        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;                     // Sectorpointer to the first sector of the first datacluster of the file.
468
                        file->FirstSectorOfCurrCluster  = SECTOR_UNDEFINED;                     // Pointer to the cluster which is edited at the moment.
468
                        file->FirstSectorOfCurrCluster  = SECTOR_UNDEFINED;                     // Pointer to the cluster which is edited at the moment.
469
                        file->SectorOfCurrCluster               = 0;                    // The sector which is edited at the moment (cluster_pointer + sector_index).
469
                        file->SectorOfCurrCluster               = 0;                    // The sector which is edited at the moment (cluster_pointer + sector_index).
470
                        file->ByteOfCurrSector                  = 0;                    // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
470
                        file->ByteOfCurrSector                  = 0;                    // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
471
                        file->Mode                                              = 0;                    // mode of fileoperation (read,write)
471
                        file->Mode                                              = 0;                    // mode of fileoperation (read,write)
472
                        file->Size                                              = 0;                    // the size of the opend file in bytes.
472
                        file->Size                                              = 0;                    // the size of the opend file in bytes.
473
                        file->Position                                  = 0;                    // pointer to a character within the file 0 < fileposition < filesize
473
                        file->Position                                  = 0;                    // pointer to a character within the file 0 < fileposition < filesize
474
                        file->SectorInCache                     = SECTOR_UNDEFINED;                     // the last sector read, wich is still in the sectorbuffer.
474
                        file->SectorInCache                     = SECTOR_UNDEFINED;                     // the last sector read, wich is still in the sectorbuffer.
475
                        file->DirectorySector                   = SECTOR_UNDEFINED;                     // the sectorposition where the directoryentry has been made.
475
                        file->DirectorySector                   = SECTOR_UNDEFINED;                     // the sectorposition where the directoryentry has been made.
476
                        file->DirectoryIndex                    = 0;                    // the index to the directoryentry within the specified sector.
476
                        file->DirectoryIndex                    = 0;                    // the index to the directoryentry within the specified sector.
477
                        file->Attribute                                 = 0;                    // the attribute of the file opened.
477
                        file->Attribute                                 = 0;                    // the attribute of the file opened.
478
                        file = NULL;
478
                        file = NULL;
479
                        return(1);
479
                        return(1);
480
                }
480
                }
481
        }
481
        }
482
        return(0);
482
        return(0);
483
}
483
}
484
 
484
 
485
/****************************************************************************************************************************************/
485
/****************************************************************************************************************************************/
486
/*      Function:               s8* SeperateFormatedDirName(const s8*, s8*);                                                                                                                                            */
486
/*      Function:               s8* SeperateFormatedDirName(const s8*, s8*);                                                                                                                                            */
487
/*                                                                                                                                                                                                                                                                              */
487
/*                                                                                                                                                                                                                                                                              */
488
/*      Description:    This function seperates the first dirname from filepath and brings them                                                                                         */
488
/*      Description:    This function seperates the first dirname from filepath and brings them                                                                                         */
489
/*                                      into the needed format ('test.txt' -> 'TEST    TXT')                                                                                                                            */
489
/*                                      into the needed format ('test.txt' -> 'TEST    TXT')                                                                                                                            */
490
/*                                      The subpath is the pointer to the remaining substring of the filepath                                                                                           */
490
/*                                      The subpath is the pointer to the remaining substring of the filepath                                                                                           */
491
/*                                                                                                                                                                                                                                                                              */
491
/*                                                                                                                                                                                                                                                                              */
492
/*      Returnvalue:    Return NULL on error or pointer to subpath                                                                                                                                                      */
492
/*      Returnvalue:    Return NULL on error or pointer to subpath                                                                                                                                                      */
493
/****************************************************************************************************************************************/
493
/****************************************************************************************************************************************/
494
s8* SeperateFormatedDirName(const s8 *filepath, s8 *dirname)
494
s8* SeperateFormatedDirName(const s8 *filepath, s8 *dirname)
495
{
495
{
496
        s8* subpath = NULL;
496
        s8* subpath = NULL;
497
        u8 readpointer  = 0;
497
        u8 readpointer  = 0;
498
        u8 writepointer = 0;
498
        u8 writepointer = 0;
499
 
499
 
500
        // search subpath from beginning of filepath
500
        // search subpath from beginning of filepath
501
        subpath = NULL;
501
        subpath = NULL;
502
        readpointer     = 0;
502
        readpointer     = 0;
503
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
503
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
504
        while(subpath == NULL)  // search the filepath until a subpath was found.
504
        while(subpath == NULL)  // search the filepath until a subpath was found.
505
        {
505
        {
506
                if(((filepath[readpointer] == 0) || (filepath[readpointer] == '/')))    // if '/' found or end of filepath reached
506
                if(((filepath[readpointer] == 0) || (filepath[readpointer] == '/')))    // if '/' found or end of filepath reached
507
                {
507
                {
508
                        subpath = (s8*)&filepath[readpointer];                          // store the position of the first "/" found after the beginning of the filenpath
508
                        subpath = (s8*)&filepath[readpointer];                          // store the position of the first "/" found after the beginning of the filenpath
509
                }
509
                }
510
                readpointer++;
510
                readpointer++;
511
        }
511
        }
512
 
512
 
513
        // clear dirname with spaces
513
        // clear dirname with spaces
514
        dirname[11] = 0; // terminate dirname
514
        dirname[11] = 0; // terminate dirname
515
        for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' ';
515
        for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' ';
516
 
516
 
517
        // handle the special dirnames "." and ".." seperately
517
        // handle the special dirnames "." and ".." seperately
518
        readpointer = 0;
518
        readpointer = 0;
519
        if(filepath[0] == '/') readpointer++;
519
        if(filepath[0] == '/') readpointer++;
520
        // if we are trying to enter directories "." or ".."
520
        // if we are trying to enter directories "." or ".."
521
        if(filepath[readpointer] == '.')
521
        if(filepath[readpointer] == '.')
522
        {
522
        {
523
                // directory '.'
523
                // directory '.'
524
                if(filepath[readpointer+1] == 0)
524
                if(filepath[readpointer+1] == 0)
525
                {
525
                {
526
                        dirname[0] = '.';
526
                        dirname[0] = '.';
527
                        return((s8*)&filepath[readpointer]);
527
                        return((s8*)&filepath[readpointer]);
528
                }
528
                }
529
                // directory '..'
529
                // directory '..'
530
                if((filepath[readpointer+1] == '.') &&  (filepath[readpointer+2] == 0))
530
                if((filepath[readpointer+1] == '.') &&  (filepath[readpointer+2] == 0))
531
                {
531
                {
532
                        dirname[0] = '.';
532
                        dirname[0] = '.';
533
                        dirname[1] = '.';
533
                        dirname[1] = '.';
534
                        return((s8*)&filepath[readpointer]);
534
                        return((s8*)&filepath[readpointer]);
535
                }
535
                }
536
        }
536
        }
537
 
537
 
538
        writepointer = 0;
538
        writepointer = 0;
539
        // start seperating the dirname from the filepath.
539
        // start seperating the dirname from the filepath.
540
        readpointer = 0;
540
        readpointer = 0;
541
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
541
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
542
        while( &filepath[readpointer] < subpath)
542
        while( &filepath[readpointer] < subpath)
543
        {
543
        {
544
                if(writepointer >= 11) return(NULL);            // dirname to long
544
                if(writepointer >= 11) return(NULL);            // dirname to long
545
                if(filepath[readpointer] == '.')                        // seperating dirname and extension.
545
                if(filepath[readpointer] == '.')                        // seperating dirname and extension.
546
                {
546
                {
547
                        if(writepointer <= 8)
547
                        if(writepointer <= 8)
548
                        {
548
                        {
549
                                readpointer++;                                          // next character in filename
549
                                readpointer++;                                          // next character in filename
550
                                writepointer = 8;                                       // jump to start of extension
550
                                writepointer = 8;                                       // jump to start of extension
551
                        }
551
                        }
552
                        else return(NULL);                                              // dirbasename to long
552
                        else return(NULL);                                              // dirbasename to long
553
                }
553
                }
554
                else
554
                else
555
                {
555
                {
556
                        if((0x60 < filepath[readpointer]) && (filepath[readpointer] < 0x7B))
556
                        if((0x60 < filepath[readpointer]) && (filepath[readpointer] < 0x7B))
557
                        {
557
                        {
558
                                dirname[writepointer] = (filepath[readpointer] - 0x20);                                 // all characters must be upper case.
558
                                dirname[writepointer] = (filepath[readpointer] - 0x20);                                 // all characters must be upper case.
559
                        }
559
                        }
560
                        else
560
                        else
561
                        {
561
                        {
562
                                dirname[writepointer] = filepath[readpointer];
562
                                dirname[writepointer] = filepath[readpointer];
563
                        }
563
                        }
564
                        readpointer++;
564
                        readpointer++;
565
                        writepointer++;
565
                        writepointer++;
566
                }
566
                }
567
        }
567
        }
568
        return(subpath);
568
        return(subpath);
569
}
569
}
570
 
570
 
571
/**************************************************************************************************************************************+*/
571
/**************************************************************************************************************************************+*/
572
/*      Function:       Fat16ClusterToSector( u16 cluster);                                                                                                                                                                             */
572
/*      Function:       Fat16ClusterToSector( u16 cluster);                                                                                                                                                                             */
573
/*                                                                                                                                                                                                                                                                              */
573
/*                                                                                                                                                                                                                                                                              */
574
/*      Description:    This function converts a cluster number given by the fat to the corresponding                                                                           */
574
/*      Description:    This function converts a cluster number given by the fat to the corresponding                                                                           */
575
/*                                      sector that points to the start of the data area that is represented by the cluster number.                                                     */
575
/*                                      sector that points to the start of the data area that is represented by the cluster number.                                                     */
576
/*                                                                                                                                                                                                                                                                              */
576
/*                                                                                                                                                                                                                                                                              */
577
/*      Returnvalue: The sector number with the data area of the given cluster                                                                                                                          */
577
/*      Returnvalue: The sector number with the data area of the given cluster                                                                                                                          */
578
/****************************************************************************************************************************************/
578
/****************************************************************************************************************************************/
579
u32     Fat16ClusterToSector(u16 cluster)
579
u32     Fat16ClusterToSector(u16 cluster)
580
{
580
{
581
        if(!Partition.IsValid) return SECTOR_UNDEFINED;
581
        if(!Partition.IsValid) return SECTOR_UNDEFINED;
582
        if ((cluster < 2) || (cluster == CLUSTER_UNDEFINED))
582
        if ((cluster < 2) || (cluster == CLUSTER_UNDEFINED))
583
        {
583
        {
584
                return SECTOR_UNDEFINED;
584
                return SECTOR_UNDEFINED;
585
        }
585
        }
586
        else
586
        else
587
        {
587
        {
588
                return ( (cluster - 2) * Partition.SectorsPerCluster) + Partition.FirstDataSector; // the first data sector     is represented by the 2nd cluster
588
                return ( (cluster - 2) * Partition.SectorsPerCluster) + Partition.FirstDataSector; // the first data sector     is represented by the 2nd cluster
589
        }
589
        }
590
}
590
}
591
 
591
 
592
/****************************************************************************************************************************************/
592
/****************************************************************************************************************************************/
593
/*      Function:       SectorToFat16Cluster( u32 sector);                                                                                                                                                                              */
593
/*      Function:       SectorToFat16Cluster( u32 sector);                                                                                                                                                                              */
594
/*                                                                                                                                                                                                                                                                              */
594
/*                                                                                                                                                                                                                                                                              */
595
/*      Description:    This function converts a given sector number given to the corresponding                                                                                         */
595
/*      Description:    This function converts a given sector number given to the corresponding                                                                                         */
596
/*                                      cluster number in the fat that represents this data area.                                                                                                                       */
596
/*                                      cluster number in the fat that represents this data area.                                                                                                                       */
597
/*                                                                                                                                                                                                                                                                              */
597
/*                                                                                                                                                                                                                                                                              */
598
/*      Returnvalue: The cluster number representing the data area of the sector.                                                                                                                       */
598
/*      Returnvalue: The cluster number representing the data area of the sector.                                                                                                                       */
599
/****************************************************************************************************************************************/
599
/****************************************************************************************************************************************/
600
u16     SectorToFat16Cluster(u32 sector)
600
u16     SectorToFat16Cluster(u32 sector)
601
{
601
{
602
        if(!Partition.IsValid) return CLUSTER_UNDEFINED;
602
        if(!Partition.IsValid) return CLUSTER_UNDEFINED;
603
        if((sector == SECTOR_UNDEFINED) || (sector < Partition.FirstDataSector)) return CLUSTER_UNDEFINED;
603
        if((sector == SECTOR_UNDEFINED) || (sector < Partition.FirstDataSector)) return CLUSTER_UNDEFINED;
604
        else return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2);
604
        else return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2);
605
}
605
}
606
 
606
 
607
 
607
 
608
/****************************************************************************************************************************************/
608
/****************************************************************************************************************************************/
609
/*      Function:       Fat16_IsValid(void);                                                                                                                                                                                                    */
609
/*      Function:       Fat16_IsValid(void);                                                                                                                                                                                                    */
610
/*                                                                                                                                                                                                                                                                              */
610
/*                                                                                                                                                                                                                                                                              */
611
/*      Description:    This function return the Fat 16 filesystem state                                                                                                                                        */
611
/*      Description:    This function return the Fat 16 filesystem state                                                                                                                                        */
612
/*                                                                                                                                                                                                                                                                              */
612
/*                                                                                                                                                                                                                                                                              */
613
/*      Returnvalue: The function returns "1" on success                                                                                                                                                                        */
613
/*      Returnvalue: The function returns "1" on success                                                                                                                                                                        */
614
/****************************************************************************************************************************************/
614
/****************************************************************************************************************************************/
615
u8 Fat16_IsValid(void)
615
u8 Fat16_IsValid(void)
616
{
616
{
617
        return(Partition.IsValid);
617
        return(Partition.IsValid);
618
}
618
}
619
 
619
 
620
/****************************************************************************************************************************************/
620
/****************************************************************************************************************************************/
621
/*      Function:       Fat16_Deinit(void);                                                                                                                                                                                                             */
621
/*      Function:       Fat16_Deinit(void);                                                                                                                                                                                                             */
622
/*                                                                                                                                                                                                                                                                              */
622
/*                                                                                                                                                                                                                                                                              */
623
/*      Description:    This function uninitializes the fat 16 api                                                                                                                                                      */
623
/*      Description:    This function uninitializes the fat 16 api                                                                                                                                                      */
624
/*                                                                                                                                                                                                                                                                              */
624
/*                                                                                                                                                                                                                                                                              */
625
/*      Returnvalue: The function returns "0" on success                                                                                                                                                                        */
625
/*      Returnvalue: The function returns "0" on success                                                                                                                                                                        */
626
/****************************************************************************************************************************************/
626
/****************************************************************************************************************************************/
627
u8 Fat16_Deinit(void)
627
u8 Fat16_Deinit(void)
628
{
628
{
629
        s16 returnvalue = 0;
629
        s16 returnvalue = 0;
630
        u8 cnt;
630
        u8 cnt;
631
 
631
 
632
        UART1_PutString("\r\n FAT16 deinit...");
632
        UART1_PutString("\r\n FAT16 deinit...");
633
        // declare the filepointers as unused.
633
        // declare the filepointers as unused.
634
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
634
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
635
        {
635
        {
636
                UnlockFilePointer(&FilePointer[cnt]);
636
                UnlockFilePointer(&FilePointer[cnt]);
637
        }
637
        }
638
        returnvalue = SDC_Deinit();                     // uninitialize interface to sd-card
638
        returnvalue = SDC_Deinit();                     // uninitialize interface to sd-card
639
        Partition.IsValid = 0;  // mark data in partition structure as invalid
639
        Partition.IsValid = 0;  // mark data in partition structure as invalid
640
        Partition.VolumeLabel[0]='\0';
640
        Partition.VolumeLabel[0]='\0';
641
        UART1_PutString("ok");
641
        UART1_PutString("ok");
642
        if(SD_WatchDog > 2000) SD_WatchDog = 2000;
642
        if(SD_WatchDog > 2000) SD_WatchDog = 2000;
643
        SD_LoggingError = 100;
643
        SD_LoggingError = 100;
644
        return(returnvalue);
644
        return(returnvalue);
645
}
645
}
646
 
646
 
647
 
647
 
648
/****************************************************************************************************************************************/
648
/****************************************************************************************************************************************/
649
/*      Function:               Fat16_Init(void);                                                                                                                                                                                                       */
649
/*      Function:               Fat16_Init(void);                                                                                                                                                                                                       */
650
/*                                                                                                                                                                                                                                                                          */
650
/*                                                                                                                                                                                                                                                                          */
651
/*      Description:    This function reads the Masterbootrecord and finds the position of the Volumebootrecord, the FAT and the Rootdir    */
651
/*      Description:    This function reads the Masterbootrecord and finds the position of the Volumebootrecord, the FAT and the Rootdir    */
652
/*                                      and stores the information in global variables.                                                                                                                                     */
652
/*                                      and stores the information in global variables.                                                                                                                                     */
653
/*                                                                                                                                                                                                                                                                          */
653
/*                                                                                                                                                                                                                                                                          */
654
/*      Returnvalue:    The function returns "0" if the filesystem is initialized.                                                                                                                      */
654
/*      Returnvalue:    The function returns "0" if the filesystem is initialized.                                                                                                                      */
655
/****************************************************************************************************************************************/
655
/****************************************************************************************************************************************/
656
u8 Fat16_Init(void)
656
u8 Fat16_Init(void)
657
{
657
{
658
    u8  cnt     = 0;
658
    u8  cnt     = 0;
659
        u32     partitionfirstsector;
659
        u32     partitionfirstsector;
660
        VBR_Entry_t *VBR;
660
        VBR_Entry_t *VBR;
661
        MBR_Entry_t *MBR;
661
        MBR_Entry_t *MBR;
662
        File_t *file;
662
        File_t *file;
663
        u8 result = 0;
663
        u8 result = 0;
664
 
664
 
665
        UART1_PutString("\r\n FAT16 init...");
665
        UART1_PutString("\r\n FAT16 init...");
666
        Partition.IsValid = 0;
666
        Partition.IsValid = 0;
667
        // declare the filepointers as unused.
667
        // declare the filepointers as unused.
668
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
668
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
669
        {
669
        {
670
                UnlockFilePointer(&FilePointer[cnt]);
670
                UnlockFilePointer(&FilePointer[cnt]);
671
        }
671
        }
672
        // set current file pinter to first position in list
672
        // set current file pinter to first position in list
673
        file = &FilePointer[0];
673
        file = &FilePointer[0];
674
 
674
 
675
        // try to initialize the sd-card.
675
        // try to initialize the sd-card.
676
        if(SD_SUCCESS != SDC_Init())
676
        if(SD_SUCCESS != SDC_Init(1))
677
        {
677
        {
678
                UART1_PutString("SD-Card could not be initialized.");
678
                UART1_PutString("SD-Card could not be initialized.");
679
                result = 1;
679
                result = 1;
680
                goto end;
680
                goto end;
681
        }
681
        }
682
 
682
 
683
        // SD-Card is initialized successfully
683
        // SD-Card is initialized successfully
684
        if(SD_SUCCESS != SDC_GetSector((u32)MBR_SECTOR,file->Cache))    // Read the MasterBootRecord
684
        if(SD_SUCCESS != SDC_GetSector((u32)MBR_SECTOR,file->Cache))    // Read the MasterBootRecord
685
        {
685
        {
686
                UART1_PutString("Error reading the MBR.");
686
                UART1_PutString("Error reading the MBR.");
687
                result = 2;
687
                result = 2;
688
                goto end;
688
                goto end;
689
        }
689
        }
690
        MBR = (MBR_Entry_t *)file->Cache;                                               // Enter the MBR using the structure MBR_Entry_t.
690
        MBR = (MBR_Entry_t *)file->Cache;                                               // Enter the MBR using the structure MBR_Entry_t.
691
        if((MBR->PartitionEntry1.Type == PART_TYPE_FAT16_ST_32_MB) ||
691
        if((MBR->PartitionEntry1.Type == PART_TYPE_FAT16_ST_32_MB) ||
692
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
692
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
693
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
693
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
694
        {
694
        {
695
                // get sector offset 1st partition
695
                // get sector offset 1st partition
696
                partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
696
                partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
697
                // Start of Partition is the Volume Boot Sector
697
                // Start of Partition is the Volume Boot Sector
698
                if(SD_SUCCESS != SDC_GetSector(partitionfirstsector,file->Cache)) // Read the volume boot record
698
                if(SD_SUCCESS != SDC_GetSector(partitionfirstsector,file->Cache)) // Read the volume boot record
699
                {
699
                {
700
                        UART1_PutString("Error reading the VBR.");
700
                        UART1_PutString("Error reading the VBR.");
701
                        result = 3;
701
                        result = 3;
702
                        goto end;
702
                        goto end;
703
                }
703
                }
704
        }
704
        }
705
        else  // maybe the medium has no partition assuming sector 0 is the vbr
705
        else  // maybe the medium has no partition assuming sector 0 is the vbr
706
        {
706
        {
707
                partitionfirstsector = 0;
707
                partitionfirstsector = 0;
708
        }
708
        }
709
 
709
 
710
        VBR = (VBR_Entry_t *) file->Cache;                                              // Enter the VBR using the structure VBR_Entry_t.
710
        VBR = (VBR_Entry_t *) file->Cache;                                              // Enter the VBR using the structure VBR_Entry_t.
711
        if(VBR->BytesPerSector != BYTES_PER_SECTOR)
711
        if(VBR->BytesPerSector != BYTES_PER_SECTOR)
712
        {
712
        {
713
                UART1_PutString("VBR: Sector size not supported.");
713
                UART1_PutString("VBR: Sector size not supported.");
714
                result = 4;
714
                result = 4;
715
                goto end;
715
                goto end;
716
        }
716
        }
717
        Partition.SectorsPerCluster             = VBR->SectorsPerCluster;                       // Number of sectors per cluster. Depends on the memorysize of the sd-card.
717
        Partition.SectorsPerCluster             = VBR->SectorsPerCluster;                       // Number of sectors per cluster. Depends on the memorysize of the sd-card.
718
        Partition.FatCopies                     = VBR->NoFATCopies;                                     // Number of fatcopies.
718
        Partition.FatCopies                     = VBR->NoFATCopies;                                     // Number of fatcopies.
719
        Partition.MaxRootEntries                = VBR->MaxRootEntries;                          // How many Entries are possible in the rootdirectory (FAT16 allows max. 512 entries).
719
        Partition.MaxRootEntries                = VBR->MaxRootEntries;                          // How many Entries are possible in the rootdirectory (FAT16 allows max. 512 entries).
720
        Partition.SectorsPerFat                 = VBR->SectorsPerFAT;                           // The number of sectors per FAT                                // copy volume label
720
        Partition.SectorsPerFat                 = VBR->SectorsPerFAT;                           // The number of sectors per FAT                                // copy volume label
721
        Partition.VolumeLabel[0] = '\0';                                                                        // set string terminator
721
        Partition.VolumeLabel[0] = '\0';                                                                        // set string terminator
722
 
722
 
723
        /* Calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster. */
723
        /* Calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster. */
724
        // Calculate the position of the FileAllocationTable:
724
        // Calculate the position of the FileAllocationTable:
725
        // Start + # of Reserved Sectors
725
        // Start + # of Reserved Sectors
726
        Partition.FirstFatSector        =   (u32)(partitionfirstsector + (u32)(VBR->ReservedSectors));
726
        Partition.FirstFatSector        =   (u32)(partitionfirstsector + (u32)(VBR->ReservedSectors));
727
        // Calculate the position of the Rootdirectory:
727
        // Calculate the position of the Rootdirectory:
728
        // Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)
728
        // Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)
729
        Partition.FirstRootDirSector    =   Partition.FirstFatSector + (u32)((u32)Partition.SectorsPerFat*(u32)Partition.FatCopies);
729
        Partition.FirstRootDirSector    =   Partition.FirstFatSector + (u32)((u32)Partition.SectorsPerFat*(u32)Partition.FatCopies);
730
        // Calculate the position of the first datacluster:
730
        // Calculate the position of the first datacluster:
731
        // Start + # of Reserved + (# of Sectors Per FAT * # of FAT Copies) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
731
        // Start + # of Reserved + (# of Sectors Per FAT * # of FAT Copies) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
732
        Partition.FirstDataSector       =   Partition.FirstRootDirSector + (u32)(Partition.MaxRootEntries>>4);  // assuming 512 Byte Per Sector
732
        Partition.FirstDataSector       =   Partition.FirstRootDirSector + (u32)(Partition.MaxRootEntries>>4);  // assuming 512 Byte Per Sector
733
        // Calculate the last data sector
733
        // Calculate the last data sector
734
        if(VBR->NoSectors == 0)
734
        if(VBR->NoSectors == 0)
735
        {
735
        {
736
                UART1_PutString("VBR: Bad number of sectors.");
736
                UART1_PutString("VBR: Bad number of sectors.");
737
                result = 5;
737
                result = 5;
738
                goto end;
738
                goto end;
739
        }
739
        }
740
        Partition.LastDataSector = Partition.FirstDataSector + VBR->NoSectors - 1;
740
        Partition.LastDataSector = Partition.FirstDataSector + VBR->NoSectors - 1;
741
        // check for FAT16 in VBR of first partition
741
        // check for FAT16 in VBR of first partition
742
        if(!((VBR->FATName[0]=='F') && (VBR->FATName[1]=='A') && (VBR->FATName[2]=='T') && (VBR->FATName[3]=='1')&&(VBR->FATName[4]=='6')))
742
        if(!((VBR->FATName[0]=='F') && (VBR->FATName[1]=='A') && (VBR->FATName[2]=='T') && (VBR->FATName[3]=='1')&&(VBR->FATName[4]=='6')))
743
        {
743
        {
744
                UART1_PutString("VBR: Partition ist not FAT16 type.");
744
                UART1_PutString("VBR: Partition ist not FAT16 type.");
745
                result = 6;
745
                result = 6;
746
                goto end;
746
                goto end;
747
        }
747
        }
748
        Partition.IsValid = 1; // mark data in partition structure as valid
748
        Partition.IsValid = 1; // mark data in partition structure as valid
749
        Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
749
        Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
750
        strcpy(Partition.PathToCwd,"/");
750
        strcpy(Partition.PathToCwd,"/");
751
        result = 0;
751
        result = 0;
752
        end:
752
        end:
753
        if(result != 0) Fat16_Deinit();
753
        if(result != 0) Fat16_Deinit();
754
        else UART1_PutString("ok");
754
        else UART1_PutString("ok");
755
        return(result);
755
        return(result);
756
}
756
}
757
 
757
 
758
 
758
 
759
 
759
 
760
/****************************************************************************************************************************************/
760
/****************************************************************************************************************************************/
761
/* Function:    ClearCurrCluster(File_t*);                                                                                                                                                                                      */
761
/* Function:    ClearCurrCluster(File_t*);                                                                                                                                                                                      */
762
/*                                                                                                                                                                                                                                                                              */
762
/*                                                                                                                                                                                                                                                                              */
763
/* Description: This function fills the current cluster with 0.                                                                                                                                                 */
763
/* Description: This function fills the current cluster with 0.                                                                                                                                                 */
764
/*                                                                                                                                                                                                                                                                              */
764
/*                                                                                                                                                                                                                                                                              */
765
/* Returnvalue: The function returns 1 on success else 0.                                                                                                                                                               */
765
/* Returnvalue: The function returns 1 on success else 0.                                                                                                                                                               */
766
/****************************************************************************************************************************************/
766
/****************************************************************************************************************************************/
767
u8 ClearCurrCluster(File_t * file)
767
u8 ClearCurrCluster(File_t * file)
768
{
768
{
769
        u8 retvalue = 1;
769
        u8 retvalue = 1;
770
        u32 i;
770
        u32 i;
771
 
771
 
772
        if((!Partition.IsValid) || (file == NULL)) return(0);
772
        if((!Partition.IsValid) || (file == NULL)) return(0);
773
 
773
 
774
        for(i = 0; i < BYTES_PER_SECTOR; i++) file->Cache[i] = 0; // clear file cache
774
        for(i = 0; i < BYTES_PER_SECTOR; i++) file->Cache[i] = 0; // clear file cache
775
        if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return (0); // nothing to do
775
        if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return (0); // nothing to do
776
        for(i = 0; i < Partition.SectorsPerCluster; i++)
776
        for(i = 0; i < Partition.SectorsPerCluster; i++)
777
        {
777
        {
778
                file->SectorInCache = file->FirstSectorOfCurrCluster + i;
778
                file->SectorInCache = file->FirstSectorOfCurrCluster + i;
779
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
779
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
780
                {
780
                {
781
                        Fat16_Deinit();
781
                        Fat16_Deinit();
782
                        return(0);
782
                        return(0);
783
                }
783
                }
784
        }
784
        }
785
        return(retvalue);
785
        return(retvalue);
786
}
786
}
787
 
787
 
788
/*****************************************************************************************************************************************/
788
/*****************************************************************************************************************************************/
789
/* Function:    GetNextCluster(File_t* );                                                                                                                                                                                        */
789
/* Function:    GetNextCluster(File_t* );                                                                                                                                                                                        */
790
/*                                                                                                                                                                                                                                                                               */
790
/*                                                                                                                                                                                                                                                                               */
791
/* Description: This function finds the next datacluster of the file specified with File *File.                                                                                  */
791
/* Description: This function finds the next datacluster of the file specified with File *File.                                                                                  */
792
/*                                                                                                                                                                                                                                                                               */
792
/*                                                                                                                                                                                                                                                                               */
793
/* Returnvalue: The function returns the next cluster or 0 if the last cluster has already reached.                                                                                                      */
793
/* Returnvalue: The function returns the next cluster or 0 if the last cluster has already reached.                                                                                                      */
794
/*****************************************************************************************************************************************/
794
/*****************************************************************************************************************************************/
795
u16 GetNextCluster(File_t * file)
795
u16 GetNextCluster(File_t * file)
796
{
796
{
797
        u16 cluster = CLUSTER_UNDEFINED;
797
        u16 cluster = CLUSTER_UNDEFINED;
798
        u32 fat_byte_offset, sector, byte;
798
        u32 fat_byte_offset, sector, byte;
799
        Fat16Entry_t * fat;
799
        Fat16Entry_t * fat;
800
 
800
 
801
        if((!Partition.IsValid) || (file == NULL)) return(cluster);
801
        if((!Partition.IsValid) || (file == NULL)) return(cluster);
802
        if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(cluster);
802
        if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(cluster);
803
        // if sector is within the data area
803
        // if sector is within the data area
804
        if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
804
        if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
805
        {
805
        {
806
                // determine current file cluster
806
                // determine current file cluster
807
                cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);
807
                cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);
808
                // calculate byte offset in the fat for corresponding entry
808
                // calculate byte offset in the fat for corresponding entry
809
                fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
809
                fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
810
                // calculate the sector that contains the current cluster within the fat
810
                // calculate the sector that contains the current cluster within the fat
811
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
811
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
812
                // calculate byte offset of the current cluster within that fat sector
812
                // calculate byte offset of the current cluster within that fat sector
813
                byte = fat_byte_offset % BYTES_PER_SECTOR;
813
                byte = fat_byte_offset % BYTES_PER_SECTOR;
814
                // read this sector to the file cache
814
                // read this sector to the file cache
815
                if(file->SectorInCache != sector)
815
                if(file->SectorInCache != sector)
816
                {
816
                {
817
                        file->SectorInCache = sector;                                           // update sector stored in buffer
817
                        file->SectorInCache = sector;                                           // update sector stored in buffer
818
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
818
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
819
                        {
819
                        {
820
                                Fat16_Deinit();
820
                                Fat16_Deinit();
821
                                return (CLUSTER_UNDEFINED);
821
                                return (CLUSTER_UNDEFINED);
822
                        }
822
                        }
823
                }
823
                }
824
                // read the next cluster from cache
824
                // read the next cluster from cache
825
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
825
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
826
                cluster = fat->NextCluster;
826
                cluster = fat->NextCluster;
827
                // if no next cluster exist
827
                // if no next cluster exist
828
                if(FAT16_CLUSTER_LAST_MIN <= cluster)
828
                if(FAT16_CLUSTER_LAST_MIN <= cluster)
829
                {
829
                {
830
                         cluster = CLUSTER_UNDEFINED; // next cluster is undefined
830
                         cluster = CLUSTER_UNDEFINED; // next cluster is undefined
831
                }
831
                }
832
                else
832
                else
833
                {
833
                {
834
                        file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
834
                        file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
835
                        file->SectorOfCurrCluster = 0;
835
                        file->SectorOfCurrCluster = 0;
836
                        file->ByteOfCurrSector = 0;
836
                        file->ByteOfCurrSector = 0;
837
                }
837
                }
838
        }
838
        }
839
        return(cluster);
839
        return(cluster);
840
}
840
}
841
 
841
 
842
 
842
 
843
 
843
 
844
/****************************************************************************************************************************************/
844
/****************************************************************************************************************************************/
845
/* Function:    FindNextFreeCluster(File_t *);                                                                                                                                                                          */
845
/* Function:    FindNextFreeCluster(File_t *);                                                                                                                                                                          */
846
/*                                                                                                                                                                                                                                                                              */
846
/*                                                                                                                                                                                                                                                                              */
847
/* Description: This function looks in the fat to find the next free cluster                                                                                                                    */
847
/* Description: This function looks in the fat to find the next free cluster                                                                                                                    */
848
/*                                                                                                                                                                                                                                                                              */
848
/*                                                                                                                                                                                                                                                                              */
849
/* Returnvalue: The function returns the cluster number of the next free cluster found within the fat.                                                                  */
849
/* Returnvalue: The function returns the cluster number of the next free cluster found within the fat.                                                                  */
850
/****************************************************************************************************************************************/
850
/****************************************************************************************************************************************/
851
u16 FindNextFreeCluster(File_t *file)
851
u16 FindNextFreeCluster(File_t *file)
852
{
852
{
853
        u32 fat_sector;                                 // current sector within the fat relative to the first sector of the fat.
853
        u32 fat_sector;                                 // current sector within the fat relative to the first sector of the fat.
854
        u32     curr_sector;                            // current sector
854
        u32     curr_sector;                            // current sector
855
        u16     fat_entry;                                      // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
855
        u16     fat_entry;                                      // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
856
        u16     free_cluster    = CLUSTER_UNDEFINED;    // next free cluster number.
856
        u16     free_cluster    = CLUSTER_UNDEFINED;    // next free cluster number.
857
        Fat16Entry_t * fat;
857
        Fat16Entry_t * fat;
858
 
858
 
859
        if((!Partition.IsValid) || (file == NULL)) return(0);
859
        if((!Partition.IsValid) || (file == NULL)) return(0);
860
 
860
 
861
        // start searching for an empty cluster at the beginning of the fat.
861
        // start searching for an empty cluster at the beginning of the fat.
862
        fat_sector = 0;
862
        fat_sector = 0;
863
        do
863
        do
864
        {
864
        {
865
                curr_sector = Partition.FirstFatSector + fat_sector;    // calculate sector to read
865
                curr_sector = Partition.FirstFatSector + fat_sector;    // calculate sector to read
866
                file->SectorInCache = curr_sector;                                              // upate the sector number of file cache.
866
                file->SectorInCache = curr_sector;                                              // upate the sector number of file cache.
867
                if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))              // read sector of fat from sd-card.
867
                if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))              // read sector of fat from sd-card.
868
                {
868
                {
869
                        Fat16_Deinit();
869
                        Fat16_Deinit();
870
                        return(CLUSTER_UNDEFINED);
870
                        return(CLUSTER_UNDEFINED);
871
                }
871
                }
872
 
872
 
873
                fat = (Fat16Entry_t *)file->Cache;                                              // set fat pointer to file cache
873
                fat = (Fat16Entry_t *)file->Cache;                                              // set fat pointer to file cache
874
 
874
 
875
                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.
875
                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.
876
                {
876
                {
877
                        if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE)            // empty cluster found!!
877
                        if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE)            // empty cluster found!!
878
                        {
878
                        {
879
                                fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX;    // mark this fat-entry as used
879
                                fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX;    // mark this fat-entry as used
880
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // and save the sector at the sd-card.
880
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // and save the sector at the sd-card.
881
                                {
881
                                {
882
                                        Fat16_Deinit();
882
                                        Fat16_Deinit();
883
                                        return(CLUSTER_UNDEFINED);
883
                                        return(CLUSTER_UNDEFINED);
884
                                }
884
                                }
885
                                free_cluster = (u16)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (u32)fat_entry);
885
                                free_cluster = (u16)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (u32)fat_entry);
886
                                fat_entry = FAT16_ENTRIES_PER_SECTOR;                                   // terminate the search for a free cluster in this sector.
886
                                fat_entry = FAT16_ENTRIES_PER_SECTOR;                                   // terminate the search for a free cluster in this sector.
887
                        }
887
                        }
888
                }
888
                }
889
                fat_sector++;                                                                                                   // continue the search in next fat sector
889
                fat_sector++;                                                                                                   // continue the search in next fat sector
890
        // repeat until the end of the fat is  reached and no free cluster has been found so far
890
        // repeat until the end of the fat is  reached and no free cluster has been found so far
891
        }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster));
891
        }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster));
892
        return(free_cluster);
892
        return(free_cluster);
893
}
893
}
894
 
894
 
895
/****************************************************************************************************************************************/
895
/****************************************************************************************************************************************/
896
/* Function:    u8 DeleteClusterChain(File *file);                                                                                                                                                                              */
896
/* Function:    u8 DeleteClusterChain(File *file);                                                                                                                                                                              */
897
/*                                                                                                                                                                                                                                                                              */
897
/*                                                                                                                                                                                                                                                                              */
898
/* Description: This function trances along a cluster chain in the fat and frees all clusters visited.                                                                  */
898
/* Description: This function trances along a cluster chain in the fat and frees all clusters visited.                                                                  */
899
/*                                                                                                                                                                                                                                                                              */
899
/*                                                                                                                                                                                                                                                                              */
900
/* Returnvalue: returns 1 in success otherwise 0                                                                                                                                                                                */
900
/* Returnvalue: returns 1 in success otherwise 0                                                                                                                                                                                */
901
/****************************************************************************************************************************************/
901
/****************************************************************************************************************************************/
902
u8 DeleteClusterChain(u16 StartCluster)
902
u8 DeleteClusterChain(u16 StartCluster)
903
{
903
{
904
        u16 cluster;
904
        u16 cluster;
905
        u32 fat_byte_offset, sector, byte;
905
        u32 fat_byte_offset, sector, byte;
906
        Fat16Entry_t * fat;
906
        Fat16Entry_t * fat;
907
        u8 buffer[BYTES_PER_SECTOR];
907
        u8 buffer[BYTES_PER_SECTOR];
908
        u32 sector_in_buffer = 0;
908
        u32 sector_in_buffer = 0;
909
        u8 repeat = 0;
909
        u8 repeat = 0;
910
 
910
 
911
        if(!Partition.IsValid) return(0);
911
        if(!Partition.IsValid) return(0);
912
        if(StartCluster == CLUSTER_UNDEFINED) return(1);
912
        if(StartCluster == CLUSTER_UNDEFINED) return(1);
913
        cluster = StartCluster; // init chain trace
913
        cluster = StartCluster; // init chain trace
914
        // if start cluster is no real cluster
914
        // if start cluster is no real cluster
915
    if(FAT16_CLUSTER_LAST_MIN <= cluster) return(1);
915
    if(FAT16_CLUSTER_LAST_MIN <= cluster) return(1);
916
 
916
 
917
        // calculate byte offset in the fat for corresponding entry
917
        // calculate byte offset in the fat for corresponding entry
918
        fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
918
        fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
919
        // calculate the sector that contains the current cluster within the fat
919
        // calculate the sector that contains the current cluster within the fat
920
        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
920
        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
921
        // calculate byte offset of the current cluster within that fat sector
921
        // calculate byte offset of the current cluster within that fat sector
922
        byte = fat_byte_offset % BYTES_PER_SECTOR;
922
        byte = fat_byte_offset % BYTES_PER_SECTOR;
923
        do
923
        do
924
        {
924
        {
925
                if(sector != sector_in_buffer)
925
                if(sector != sector_in_buffer)
926
                {
926
                {
927
                        // read this sector to buffer
927
                        // read this sector to buffer
928
                        sector_in_buffer = sector;
928
                        sector_in_buffer = sector;
929
                        if(SD_SUCCESS != SDC_GetSector(sector_in_buffer, buffer)) return 0;     // read sector from sd-card
929
                        if(SD_SUCCESS != SDC_GetSector(sector_in_buffer, buffer)) return 0;     // read sector from sd-card
930
                }
930
                }
931
                // read the next cluster from cache
931
                // read the next cluster from cache
932
                fat = (Fat16Entry_t *)(&(buffer[byte]));
932
                fat = (Fat16Entry_t *)(&(buffer[byte]));
933
                cluster = fat->NextCluster;
933
                cluster = fat->NextCluster;
934
                fat->NextCluster =      FAT16_CLUSTER_FREE; // mark current cluster as free
934
                fat->NextCluster =      FAT16_CLUSTER_FREE; // mark current cluster as free
935
 
935
 
936
                if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) )
936
                if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) )
937
                {
937
                {
938
                        repeat = 1;
938
                        repeat = 1;
939
                        // calculate sector byte and byte offset in the fat for the next cluster
939
                        // calculate sector byte and byte offset in the fat for the next cluster
940
                        fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
940
                        fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
941
                        // calculate the sector that contains the current cluster within the fat
941
                        // calculate the sector that contains the current cluster within the fat
942
                        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
942
                        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
943
                        // calculate byte offset of the current cluster within that fat sector
943
                        // calculate byte offset of the current cluster within that fat sector
944
                        byte = fat_byte_offset % BYTES_PER_SECTOR;
944
                        byte = fat_byte_offset % BYTES_PER_SECTOR;
945
                }
945
                }
946
                else repeat = 0;
946
                else repeat = 0;
947
 
947
 
948
                // if new sector is not the sector in buffer or the last cluster in the chain was traced
948
                // if new sector is not the sector in buffer or the last cluster in the chain was traced
949
                if((sector != sector_in_buffer) || !repeat)
949
                if((sector != sector_in_buffer) || !repeat)
950
                {       // write sector in buffer
950
                {       // write sector in buffer
951
                        if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer))
951
                        if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer))
952
                        {
952
                        {
953
                                Fat16_Deinit();
953
                                Fat16_Deinit();
954
                                return(0);
954
                                return(0);
955
                        }
955
                        }
956
                }
956
                }
957
        }
957
        }
958
        while(repeat);
958
        while(repeat);
959
 
959
 
960
        return 1;
960
        return 1;
961
}
961
}
962
 
962
 
963
 
963
 
964
/****************************************************************************************************************************************/
964
/****************************************************************************************************************************************/
965
/* Function:    u16 AppendCluster(File *file);                                                                                                                                                                                  */
965
/* Function:    u16 AppendCluster(File *file);                                                                                                                                                                                  */
966
/*                                                                                                                                                                                                                                                                              */
966
/*                                                                                                                                                                                                                                                                              */
967
/* Description: This function looks in the fat to find the next free cluster and appends it to the file.                                                                */
967
/* Description: This function looks in the fat to find the next free cluster and appends it to the file.                                                                */
968
/*                                                                                                                                                                                                                                                                              */
968
/*                                                                                                                                                                                                                                                                              */
969
/* Returnvalue: The function returns the appened cluster number or CLUSTER_UNDEFINED of no cluster was appended.                                                */
969
/* Returnvalue: The function returns the appened cluster number or CLUSTER_UNDEFINED of no cluster was appended.                                                */
970
/****************************************************************************************************************************************/
970
/****************************************************************************************************************************************/
971
u16 AppendCluster(File_t *file)
971
u16 AppendCluster(File_t *file)
972
{
972
{
973
        u16 last_cluster, new_cluster = CLUSTER_UNDEFINED;
973
        u16 last_cluster, new_cluster = CLUSTER_UNDEFINED;
974
        u32 fat_byte_offset, sector, byte;
974
        u32 fat_byte_offset, sector, byte;
975
        Fat16Entry_t * fat;
975
        Fat16Entry_t * fat;
976
 
976
 
977
 
977
 
978
        if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
978
        if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
979
 
979
 
980
        new_cluster = FindNextFreeCluster(file);        // the next free cluster found on the disk.
980
        new_cluster = FindNextFreeCluster(file);        // the next free cluster found on the disk.
981
        if(new_cluster != CLUSTER_UNDEFINED)
981
        if(new_cluster != CLUSTER_UNDEFINED)
982
        {       // A free cluster was found and can be added to the end of the file.
982
        {       // A free cluster was found and can be added to the end of the file.
983
                // is there at least one cluster appended to the file?
983
                // is there at least one cluster appended to the file?
984
                if(file->FirstSectorOfLastCluster == CLUSTER_UNDEFINED)
984
                if(file->FirstSectorOfLastCluster == CLUSTER_UNDEFINED)
985
                {
985
                {
986
                        fseek_(file, 0, SEEK_END);                                                                                                      // jump to the end of the file
986
                        fseek_(file, 0, SEEK_END);                                                                                                      // jump to the end of the file
987
                        // remember the first sector of the last cluster
987
                        // remember the first sector of the last cluster
988
                        file->FirstSectorOfLastCluster = file->FirstSectorOfCurrCluster;
988
                        file->FirstSectorOfLastCluster = file->FirstSectorOfCurrCluster;
989
                        last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);            // determine current file cluster
989
                        last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);            // determine current file cluster
990
                }
990
                }
991
                else
991
                else
992
                {
992
                {
993
                        last_cluster = SectorToFat16Cluster(file->FirstSectorOfLastCluster);            // determine current file cluster
993
                        last_cluster = SectorToFat16Cluster(file->FirstSectorOfLastCluster);            // determine current file cluster
994
                }
994
                }
995
 
995
 
996
                if(last_cluster != CLUSTER_UNDEFINED)
996
                if(last_cluster != CLUSTER_UNDEFINED)
997
                {
997
                {
998
                        // update FAT entry of last cluster
998
                        // update FAT entry of last cluster
999
                        fat_byte_offset = ((u32)last_cluster)<<1;
999
                        fat_byte_offset = ((u32)last_cluster)<<1;
1000
                        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
1000
                        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
1001
                        byte = fat_byte_offset % BYTES_PER_SECTOR;
1001
                        byte = fat_byte_offset % BYTES_PER_SECTOR;
1002
                        // read the sector containing the last cluster of the file
1002
                        // read the sector containing the last cluster of the file
1003
                        if(file->SectorInCache != sector)
1003
                        if(file->SectorInCache != sector)
1004
                        {
1004
                        {
1005
                                file->SectorInCache = sector;   // update sector stored in buffer
1005
                                file->SectorInCache = sector;   // update sector stored in buffer
1006
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
1006
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
1007
                                {
1007
                                {
1008
                                        Fat16_Deinit();
1008
                                        Fat16_Deinit();
1009
                                        return(0);
1009
                                        return(0);
1010
                                }
1010
                                }
1011
                        }
1011
                        }
1012
                        fat = (Fat16Entry_t *)(&(file->Cache[byte]));
1012
                        fat = (Fat16Entry_t *)(&(file->Cache[byte]));
1013
                        fat->NextCluster = new_cluster;                                                 // append the free cluster to the end of the file in the FAT.
1013
                        fat->NextCluster = new_cluster;                                                 // append the free cluster to the end of the file in the FAT.
1014
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // save the modified sector to the FAT.
1014
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // save the modified sector to the FAT.
1015
                        {
1015
                        {
1016
                                Fat16_Deinit();
1016
                                Fat16_Deinit();
1017
                                return(0);
1017
                                return(0);
1018
                        }
1018
                        }
1019
                        // now the new cluster appended to the fat is the last cluster
1019
                        // now the new cluster appended to the fat is the last cluster
1020
                        file->FirstSectorOfLastCluster = Fat16ClusterToSector(new_cluster);
1020
                        file->FirstSectorOfLastCluster = Fat16ClusterToSector(new_cluster);
1021
                }
1021
                }
1022
                else // last cluster of the file is undefined
1022
                else // last cluster of the file is undefined
1023
                {   // then the new cluster must be the first one of the file
1023
                {   // then the new cluster must be the first one of the file
1024
                    // and its cluster number must be set in the direntry
1024
                    // and its cluster number must be set in the direntry
1025
                        DirEntry_t * dir;
1025
                        DirEntry_t * dir;
1026
                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1026
                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1027
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1027
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1028
                        {
1028
                        {
1029
                                Fat16_Deinit();
1029
                                Fat16_Deinit();
1030
                                return(CLUSTER_UNDEFINED);
1030
                                return(CLUSTER_UNDEFINED);
1031
                        }
1031
                        }
1032
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1032
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1033
                        dir[file->DirectoryIndex].Res1 = 0;
1033
                        dir[file->DirectoryIndex].Res1 = 0;
1034
                        dir[file->DirectoryIndex].Res2[0] = 0;
1034
                        dir[file->DirectoryIndex].Res2[0] = 0;
1035
                        dir[file->DirectoryIndex].Res2[1] = 0;
1035
                        dir[file->DirectoryIndex].Res2[1] = 0;
1036
                        dir[file->DirectoryIndex].StartCluster = new_cluster;           // update startcluster
1036
                        dir[file->DirectoryIndex].StartCluster = new_cluster;           // update startcluster
1037
                    dir[file->DirectoryIndex].ModTime   = FileTime(&SystemTime);// set time
1037
                    dir[file->DirectoryIndex].ModTime   = FileTime(&SystemTime);// set time
1038
                        dir[file->DirectoryIndex].ModDate       = FileDate(&SystemTime);// and date of modification
1038
                        dir[file->DirectoryIndex].ModDate       = FileDate(&SystemTime);// and date of modification
1039
                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1039
                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1040
                        dir[file->DirectoryIndex].Size          = 0;
1040
                        dir[file->DirectoryIndex].Size          = 0;
1041
                        // write sector containing the direntry
1041
                        // write sector containing the direntry
1042
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1042
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1043
                        {
1043
                        {
1044
                                Fat16_Deinit();
1044
                                Fat16_Deinit();
1045
                                return(CLUSTER_UNDEFINED);
1045
                                return(CLUSTER_UNDEFINED);
1046
                        }
1046
                        }
1047
                        // update file info
1047
                        // update file info
1048
                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(new_cluster);
1048
                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(new_cluster);
1049
                        file->FirstSectorOfLastCluster = file->FirstSectorOfFirstCluster;
1049
                        file->FirstSectorOfLastCluster = file->FirstSectorOfFirstCluster;
1050
                        file->Size = 0;
1050
                        file->Size = 0;
1051
                        file->Position = 0;
1051
                        file->Position = 0;
1052
                }
1052
                }
1053
                // update file pointes
1053
                // update file pointes
1054
                file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster);
1054
                file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster);
1055
                file->SectorOfCurrCluster = 0;
1055
                file->SectorOfCurrCluster = 0;
1056
                file->ByteOfCurrSector = 0;
1056
                file->ByteOfCurrSector = 0;
1057
        }
1057
        }
1058
        return(new_cluster);
1058
        return(new_cluster);
1059
}
1059
}
1060
 
1060
 
1061
 
1061
 
1062
/****************************************************************************************************************************************************/
1062
/****************************************************************************************************************************************************/
1063
/* Function:    DirectoryEntryExist(s8 *, u8, u8, File_t *)                                                                                                                                                                                     */
1063
/* Function:    DirectoryEntryExist(s8 *, u8, u8, File_t *)                                                                                                                                                                                     */
1064
/*                                                                                                                                                                                                                                                                                                      */
1064
/*                                                                                                                                                                                                                                                                                                      */
1065
/* Description: This function searches all possible dir entries until the file or directory is found or the end of the directory is reached                     */
1065
/* Description: This function searches all possible dir entries until the file or directory is found or the end of the directory is reached                     */
1066
/*                                                                                                                                                                                                                                                                                                      */
1066
/*                                                                                                                                                                                                                                                                                                      */
1067
/* Returnvalue: This function returns 1 if the directory entry specified was found.                                                                                                                                     */
1067
/* Returnvalue: This function returns 1 if the directory entry specified was found.                                                                                                                                     */
1068
/****************************************************************************************************************************************************/
1068
/****************************************************************************************************************************************************/
1069
u8 DirectoryEntryExist(s8 *dirname, u8 attribfilter, u8 attribmask, File_t *file)
1069
u8 DirectoryEntryExist(s8 *dirname, u8 attribfilter, u8 attribmask, File_t *file)
1070
{
1070
{
1071
        u32             dir_sector, max_dir_sector, curr_sector;
1071
        u32             dir_sector, max_dir_sector, curr_sector;
1072
        u16     dir_entry = 0;
1072
        u16     dir_entry = 0;
1073
 
1073
 
1074
        u16     end_of_directory_not_reached = 0;
1074
        u16     end_of_directory_not_reached = 0;
1075
        u8              i = 0;
1075
        u8              i = 0;
1076
        u8      direntry_exist = 0;
1076
        u8      direntry_exist = 0;
1077
        DirEntry_t * dir;
1077
        DirEntry_t * dir;
1078
 
1078
 
1079
        // incomming pointers are useless?
1079
        // incomming pointers are useless?
1080
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
1080
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
1081
 
1081
 
1082
        // check sector range to be searched
1082
        // check sector range to be searched
1083
 
1083
 
1084
        // no search area defined?
1084
        // no search area defined?
1085
        if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)
1085
        if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)
1086
        {      
1086
        {      
1087
                return(direntry_exist);
1087
                return(direntry_exist);
1088
        }
1088
        }
1089
        //is search area the root?
1089
        //is search area the root?
1090
        else if(Partition.FirstRootDirSector == file->FirstSectorOfFirstCluster)
1090
        else if(Partition.FirstRootDirSector == file->FirstSectorOfFirstCluster)
1091
        {
1091
        {
1092
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR; // limit to  size of root 
1092
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR; // limit to  size of root 
1093
                file->DirectorySector = SECTOR_UNDEFINED; // if we have to search within the root, there is no corresponding directory entry available
1093
                file->DirectorySector = SECTOR_UNDEFINED; // if we have to search within the root, there is no corresponding directory entry available
1094
        }
1094
        }
1095
        // is search area within the data cluster range?
1095
        // is search area within the data cluster range?
1096
        else if((Partition.FirstDataSector <= file->FirstSectorOfFirstCluster) && (file->FirstSectorOfFirstCluster <= Partition.LastDataSector))
1096
        else if((Partition.FirstDataSector <= file->FirstSectorOfFirstCluster) && (file->FirstSectorOfFirstCluster <= Partition.LastDataSector))
1097
        {
1097
        {
1098
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max sectors before next cluster
1098
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max sectors before next cluster
1099
                /*
1099
                /*
1100
                //there must be a corresponding directory entry
1100
                //there must be a corresponding directory entry
1101
                if(file->DirectorySector == SECTOR_UNDEFINED)
1101
                if(file->DirectorySector == SECTOR_UNDEFINED)
1102
                {
1102
                {
1103
                        return (direntry_exist);       
1103
                        return (direntry_exist);       
1104
                }
1104
                }
1105
                else // check directory entry
1105
                else // check directory entry
1106
                {
1106
                {
1107
                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1107
                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1108
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1108
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1109
                        {
1109
                        {
1110
                                Fat16_Deinit();
1110
                                Fat16_Deinit();
1111
                                return (direntry_exist);
1111
                                return (direntry_exist);
1112
                        }
1112
                        }
1113
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1113
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1114
                        switch((u8)dir[file->DirectoryIndex].Name[0])                           // check if current directory exist
1114
                        switch((u8)dir[file->DirectoryIndex].Name[0])                           // check if current directory exist
1115
                        {
1115
                        {
1116
                                case SLOT_EMPTY:
1116
                                case SLOT_EMPTY:
1117
                                case SLOT_DELETED:
1117
                                case SLOT_DELETED:
1118
                                        // the directrory pointer of this file points to a deleted or not existen directory
1118
                                        // the directrory pointer of this file points to a deleted or not existen directory
1119
                                        // therefore no file or subdirectory exist here
1119
                                        // therefore no file or subdirectory exist here
1120
                                        return(direntry_exist);
1120
                                        return(direntry_exist);
1121
                                        break;
1121
                                        break;
1122
                                default:        // and is a real directory
1122
                                default:        // and is a real directory
1123
                                        if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1123
                                        if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1124
                                        {       // current file is not a directory therefore no file or subdirectory can be searched here
1124
                                        {       // current file is not a directory therefore no file or subdirectory can be searched here
1125
                                                return(direntry_exist);
1125
                                                return(direntry_exist);
1126
                                        }
1126
                                        }
1127
                                        break;
1127
                                        break;
1128
                        }
1128
                        }
1129
                        // check that search area matches directory entry
1129
                        // check that search area matches directory entry
1130
                        if(file->FirstSectorOfFirstCluster != Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster))
1130
                        if(file->FirstSectorOfFirstCluster != Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster))
1131
                        {
1131
                        {
1132
                                return (direntry_exist);        
1132
                                return (direntry_exist);        
1133
                        }
1133
                        }
1134
                       
1134
                       
1135
                } */
1135
                } */
1136
        }
1136
        }
1137
        else return (direntry_exist); // bad sector range for search area
1137
        else return (direntry_exist); // bad sector range for search area
1138
       
1138
       
1139
        // update current file data area position to start of first cluster
1139
        // update current file data area position to start of first cluster
1140
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1140
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1141
        file->SectorOfCurrCluster               = 0;
1141
        file->SectorOfCurrCluster               = 0;
1142
        file->ByteOfCurrSector                  = 0;
1142
        file->ByteOfCurrSector                  = 0;
1143
 
1143
 
1144
        do // loop over all data clusters of the current directory entry
1144
        do // loop over all data clusters of the current directory entry
1145
        {
1145
        {
1146
                dir_sector = 0;
1146
                dir_sector = 0;
1147
                do // loop over all sectors of a cluster or all sectors of the root directory
1147
                do // loop over all sectors of a cluster or all sectors of the root directory
1148
                {
1148
                {
1149
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1149
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1150
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1150
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1151
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
1151
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
1152
                        {
1152
                        {
1153
                                Fat16_Deinit();
1153
                                Fat16_Deinit();
1154
                                return(direntry_exist);
1154
                                return(direntry_exist);
1155
                        }
1155
                        }
1156
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1156
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1157
                        // search all directory entries within that sector
1157
                        // search all directory entries within that sector
1158
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1158
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1159
                        {   // check for existing dir entry
1159
                        {   // check for existing dir entry
1160
                                switch((u8)dir[dir_entry].Name[0])
1160
                                switch((u8)dir[dir_entry].Name[0])
1161
                                {
1161
                                {
1162
                                        case SLOT_EMPTY:
1162
                                        case SLOT_EMPTY:
1163
                                        case SLOT_DELETED:
1163
                                        case SLOT_DELETED:
1164
                                                // ignore empty or deleted dir entries
1164
                                                // ignore empty or deleted dir entries
1165
                                                break;
1165
                                                break;
1166
                                        default:
1166
                                        default:
1167
                                                // if existing check attributes before names are compared will safe performance
1167
                                                // if existing check attributes before names are compared will safe performance
1168
                                                if ((dir[dir_entry].Attribute & attribmask) != attribfilter) break; // attribute must match
1168
                                                if ((dir[dir_entry].Attribute & attribmask) != attribfilter) break; // attribute must match
1169
                                                // then compare the name to the giveb dirname (first 11 characters include 8 chars of basename and 3 chars extension.)
1169
                                                // then compare the name to the giveb dirname (first 11 characters include 8 chars of basename and 3 chars extension.)
1170
                                                i = 0;
1170
                                                i = 0;
1171
                                                while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
1171
                                                while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
1172
                                                if (i < 10) break; // names does not match
1172
                                                if (i < 10) break; // names does not match
1173
                                                // if dirname and attribute have matched
1173
                                                // if dirname and attribute have matched
1174
                                                file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
1174
                                                file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
1175
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster
1175
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster
1176
                                                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1176
                                                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1177
                                                file->SectorOfCurrCluster = 0;
1177
                                                file->SectorOfCurrCluster = 0;
1178
                                                file->ByteOfCurrSector = 0;
1178
                                                file->ByteOfCurrSector = 0;
1179
                                                file->DirectorySector = curr_sector; // current sector
1179
                                                file->DirectorySector = curr_sector; // current sector
1180
                                                file->DirectoryIndex  = dir_entry; // current direntry in current sector
1180
                                                file->DirectoryIndex  = dir_entry; // current direntry in current sector
1181
                                                file->Size = dir[dir_entry].Size;
1181
                                                file->Size = dir[dir_entry].Size;
1182
                                                direntry_exist = 1; // mark as found
1182
                                                direntry_exist = 1; // mark as found
1183
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1183
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1184
                                } // end of first byte of name check
1184
                                } // end of first byte of name check
1185
                        }
1185
                        }
1186
                        dir_sector++; // search next sector
1186
                        dir_sector++; // search next sector
1187
                // stop if we reached the end of the cluster or the end of the root dir
1187
                // stop if we reached the end of the cluster or the end of the root dir
1188
                }while((dir_sector < max_dir_sector) && (!direntry_exist));
1188
                }while((dir_sector < max_dir_sector) && (!direntry_exist));
1189
 
1189
 
1190
                // if we are seaching in the data area and the file not found in this cluster so take next cluster.
1190
                // if we are seaching in the data area and the file not found in this cluster so take next cluster.
1191
                if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1191
                if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1192
                {
1192
                {
1193
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1193
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1194
                }
1194
                }
1195
        }while((end_of_directory_not_reached) && (!direntry_exist)); // repeat until a next cluster exist an no match has been found
1195
        }while((end_of_directory_not_reached) && (!direntry_exist)); // repeat until a next cluster exist an no match has been found
1196
        return(direntry_exist);
1196
        return(direntry_exist);
1197
}
1197
}
1198
 
1198
 
1199
 
1199
 
1200
/****************************************************************************************************************************************/
1200
/****************************************************************************************************************************************/
1201
/*      Function:               CreateDirectoryEntry(s8 *, u16, File_t *)                                                                                                                                                       */
1201
/*      Function:               CreateDirectoryEntry(s8 *, u16, File_t *)                                                                                                                                                       */
1202
/*                                                                                                                                                                                                                                                                              */
1202
/*                                                                                                                                                                                                                                                                              */
1203
/*      Description:    This function looks for the next free position in the directory and creates an entry.                                                           */
1203
/*      Description:    This function looks for the next free position in the directory and creates an entry.                                                           */
1204
/*                                      The type of an directory entry is specified by the file attribute.                                                                                                      */
1204
/*                                      The type of an directory entry is specified by the file attribute.                                                                                                      */
1205
/*                                                                                                                                                                                                                                                                              */
1205
/*                                                                                                                                                                                                                                                                              */
1206
/*      Returnvalue:    Return 0 on error                                                                                                                                                                                                       */
1206
/*      Returnvalue:    Return 0 on error                                                                                                                                                                                                       */
1207
/****************************************************************************************************************************************/
1207
/****************************************************************************************************************************************/
1208
u8 CreateDirectoryEntry(s8 *dirname, u8 attrib, File_t *file)
1208
u8 CreateDirectoryEntry(s8 *dirname, u8 attrib, File_t *file)
1209
{
1209
{
1210
        u32 dir_sector, max_dir_sector, curr_sector;
1210
        u32 dir_sector, max_dir_sector, curr_sector;
1211
        u16 dir_entry   = 0;
1211
        u16 dir_entry   = 0;
1212
        u16 subdircluster, dircluster = 0;
1212
        u16 subdircluster, dircluster = 0;
1213
        u16 end_of_directory_not_reached = 0;
1213
        u16 end_of_directory_not_reached = 0;
1214
        u8      i                       = 0;
1214
        u8      i                       = 0;
1215
        u8      retvalue        = 0;
1215
        u8      retvalue        = 0;
1216
        DirEntry_t *dir;
1216
        DirEntry_t *dir;
1217
 
1217
 
1218
        // incomming pointers are useless?
1218
        // incomming pointers are useless?
1219
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(retvalue);
1219
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(retvalue);
1220
 
1220
 
1221
        // check sector range to be searched
1221
        // check sector range to be searched
1222
 
1222
 
1223
        // no creation area defined?
1223
        // no creation area defined?
1224
        if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)
1224
        if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)
1225
        {      
1225
        {      
1226
                return(retvalue);
1226
                return(retvalue);
1227
        }
1227
        }
1228
        //is creation area the root?
1228
        //is creation area the root?
1229
        else if(Partition.FirstRootDirSector == file->FirstSectorOfFirstCluster)
1229
        else if(Partition.FirstRootDirSector == file->FirstSectorOfFirstCluster)
1230
        {
1230
        {
1231
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;  // limit to  size of root 
1231
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;  // limit to  size of root 
1232
                file->DirectorySector = SECTOR_UNDEFINED; // if we have to search within the root, there is no corresponding directory entry available
1232
                file->DirectorySector = SECTOR_UNDEFINED; // if we have to search within the root, there is no corresponding directory entry available
1233
        }
1233
        }
1234
        // is creation area within the data cluster range?
1234
        // is creation area within the data cluster range?
1235
        else if((Partition.FirstDataSector <= file->FirstSectorOfFirstCluster) && (file->FirstSectorOfFirstCluster <= Partition.LastDataSector))
1235
        else if((Partition.FirstDataSector <= file->FirstSectorOfFirstCluster) && (file->FirstSectorOfFirstCluster <= Partition.LastDataSector))
1236
        {
1236
        {
1237
                max_dir_sector = Partition.SectorsPerCluster;                                   // limit max sectors before next cluster
1237
                max_dir_sector = Partition.SectorsPerCluster;                                   // limit max sectors before next cluster
1238
                // there must be a corresponding directory entry
1238
                // there must be a corresponding directory entry
1239
                if(file->DirectorySector == SECTOR_UNDEFINED)
1239
                if(file->DirectorySector == SECTOR_UNDEFINED)
1240
                {
1240
                {
1241
                        return (retvalue);     
1241
                        return (retvalue);     
1242
                }
1242
                }
1243
                else // check directory entry
1243
                else // check directory entry
1244
                {
1244
                {
1245
                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1245
                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1246
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read in the sector.
1246
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read in the sector.
1247
                        {
1247
                        {
1248
                                Fat16_Deinit();
1248
                                Fat16_Deinit();
1249
                                return (retvalue);
1249
                                return (retvalue);
1250
                        }
1250
                        }
1251
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1251
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1252
                        switch((u8)dir[file->DirectoryIndex].Name[0])                           // check if current directory exist
1252
                        switch((u8)dir[file->DirectoryIndex].Name[0])                           // check if current directory exist
1253
                        {
1253
                        {
1254
                                case SLOT_EMPTY:
1254
                                case SLOT_EMPTY:
1255
                                case SLOT_DELETED:
1255
                                case SLOT_DELETED:
1256
                                        // the directrory pointer of this file points to a deleted or not existen directory
1256
                                        // the directrory pointer of this file points to a deleted or not existen directory
1257
                                        // therefore no file or subdirectory exist here
1257
                                        // therefore no file or subdirectory exist here
1258
                                        return(retvalue);
1258
                                        return(retvalue);
1259
                                        break;
1259
                                        break;
1260
                                default:        // and is a real directory
1260
                                default:        // and is a real directory
1261
                                        if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1261
                                        if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1262
                                        {       // current file is not a directory therefore no file or subdirectory can be created here
1262
                                        {       // current file is not a directory therefore no file or subdirectory can be created here
1263
                                                return(retvalue);
1263
                                                return(retvalue);
1264
                                        }
1264
                                        }
1265
                                        break;
1265
                                        break;
1266
                        }
1266
                        }
1267
                        // check that search area matches directory entry
1267
                        // check that search area matches directory entry
1268
                        if(file->FirstSectorOfFirstCluster != Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster))
1268
                        if(file->FirstSectorOfFirstCluster != Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster))
1269
                        {
1269
                        {
1270
                                return (retvalue);      
1270
                                return (retvalue);      
1271
                        }
1271
                        }
1272
                }
1272
                }
1273
        }
1273
        }
1274
        else return(retvalue); // bad sector range for search area
1274
        else return(retvalue); // bad sector range for search area
1275
 
1275
 
1276
        // if the new directory entry is a subdirectory
1276
        // if the new directory entry is a subdirectory
1277
        if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)
1277
        if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)
1278
        {       // get a free cluster for its content
1278
        {       // get a free cluster for its content
1279
                subdircluster = FindNextFreeCluster(file);      // get the next free cluster on the disk and mark it as used.
1279
                subdircluster = FindNextFreeCluster(file);      // get the next free cluster on the disk and mark it as used.
1280
        }
1280
        }
1281
        else // a normal file
1281
        else // a normal file
1282
        {       // has no data cluster after creation
1282
        {       // has no data cluster after creation
1283
                subdircluster = CLUSTER_UNDEFINED;
1283
                subdircluster = CLUSTER_UNDEFINED;
1284
        }
1284
        }
1285
 
1285
 
1286
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1286
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1287
        file->SectorOfCurrCluster               = 0;
1287
        file->SectorOfCurrCluster               = 0;
1288
        do // loop over all clusters of current directory
1288
        do // loop over all clusters of current directory
1289
        {
1289
        {
1290
                dir_sector = 0; // reset sector counter within a new cluster
1290
                dir_sector = 0; // reset sector counter within a new cluster
1291
                do // loop over all sectors of a cluster or all sectors of the root directory
1291
                do // loop over all sectors of a cluster or all sectors of the root directory
1292
                {
1292
                {
1293
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1293
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1294
                        file->SectorInCache = curr_sector;                                                      // update the sector number of file cache.
1294
                        file->SectorInCache = curr_sector;                                                      // update the sector number of file cache.
1295
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1295
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1296
                        {
1296
                        {
1297
                                Fat16_Deinit();
1297
                                Fat16_Deinit();
1298
                                return(retvalue);
1298
                                return(retvalue);
1299
                        }
1299
                        }
1300
 
1300
 
1301
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1301
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1302
                        // search all directory entries of a sector
1302
                        // search all directory entries of a sector
1303
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1303
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1304
                        {       // check if current direntry is available
1304
                        {       // check if current direntry is available
1305
                                if(((u8)dir[dir_entry].Name[0] == SLOT_EMPTY) || ((u8)dir[dir_entry].Name[0] == SLOT_DELETED))
1305
                                if(((u8)dir[dir_entry].Name[0] == SLOT_EMPTY) || ((u8)dir[dir_entry].Name[0] == SLOT_DELETED))
1306
                                {       // a free direntry was found
1306
                                {       // a free direntry was found
1307
                                        for(i = 0; i < 11; i++) dir[dir_entry].Name[i] = dirname[i];            // Set dir name
1307
                                        for(i = 0; i < 11; i++) dir[dir_entry].Name[i] = dirname[i];            // Set dir name
1308
                                        dir[dir_entry].Attribute    = attrib;
1308
                                        dir[dir_entry].Attribute    = attrib;
1309
                                        dir[dir_entry].Res1 = 0;
1309
                                        dir[dir_entry].Res1 = 0;
1310
                                        dir[dir_entry].CreationTime10ms = (u8)(SystemTime.mSec/10);
1310
                                        dir[dir_entry].CreationTime10ms = (u8)(SystemTime.mSec/10);
1311
                                        dir[dir_entry].CreationTime     = FileTime(&SystemTime);
1311
                                        dir[dir_entry].CreationTime     = FileTime(&SystemTime);
1312
                                        dir[dir_entry].CreationDate     = FileDate(&SystemTime);
1312
                                        dir[dir_entry].CreationDate     = FileDate(&SystemTime);
1313
                                        dir[dir_entry].LastAccessDate = dir[dir_entry].CreationDate;
1313
                                        dir[dir_entry].LastAccessDate = dir[dir_entry].CreationDate;
1314
                                        dir[dir_entry].Res2[0] = 0;
1314
                                        dir[dir_entry].Res2[0] = 0;
1315
                                        dir[dir_entry].Res2[1] = 0;
1315
                                        dir[dir_entry].Res2[1] = 0;
1316
                                        dir[dir_entry].ModTime = dir[dir_entry].CreationTime;
1316
                                        dir[dir_entry].ModTime = dir[dir_entry].CreationTime;
1317
                                        dir[dir_entry].ModDate = dir[dir_entry].CreationDate;
1317
                                        dir[dir_entry].ModDate = dir[dir_entry].CreationDate;
1318
                                        // Set the attribute of the new directoryentry.
1318
                                        // Set the attribute of the new directoryentry.
1319
                                        dir[dir_entry].StartCluster = subdircluster;                                            // copy the location of the first datacluster to the directoryentry.
1319
                                        dir[dir_entry].StartCluster = subdircluster;                                            // copy the location of the first datacluster to the directoryentry.
1320
                                        dir[dir_entry].Size             = 0;                                                                    // the new createted file has no content yet.
1320
                                        dir[dir_entry].Size             = 0;                                                                    // the new createted file has no content yet.
1321
                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to card
1321
                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to card
1322
                                        {
1322
                                        {
1323
                                                Fat16_Deinit();
1323
                                                Fat16_Deinit();
1324
                                                return(retvalue);
1324
                                                return(retvalue);
1325
                                        }
1325
                                        }
1326
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster);  // Calculate absolute sectorposition of first datacluster.
1326
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster);  // Calculate absolute sectorposition of first datacluster.
1327
                                        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;      // Start reading the file with the first sector of the first datacluster.
1327
                                        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;      // Start reading the file with the first sector of the first datacluster.
1328
                                        file->SectorOfCurrCluster               = 0;                                                            // reset sector of cureen cluster
1328
                                        file->SectorOfCurrCluster               = 0;                                                            // reset sector of cureen cluster
1329
                                        file->ByteOfCurrSector                  = 0;                                                            // reset the byte location within the current sector
1329
                                        file->ByteOfCurrSector                  = 0;                                                            // reset the byte location within the current sector
1330
                                        file->Attribute                                 = attrib;                                               // set file attribute to dir attribute
1330
                                        file->Attribute                                 = attrib;                                               // set file attribute to dir attribute
1331
                                        file->Size                                              = 0;                                                        // new file has no size
1331
                                        file->Size                                              = 0;                                                        // new file has no size
1332
                                        file->DirectorySector                   = curr_sector;
1332
                                        file->DirectorySector                   = curr_sector;
1333
                                        file->DirectoryIndex                    = dir_entry;
1333
                                        file->DirectoryIndex                    = dir_entry;
1334
                                        // prepare subdirectory data cluster
1334
                                        // prepare subdirectory data cluster
1335
                                        if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)                           // if a new directory was created then initilize the data area
1335
                                        if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)                           // if a new directory was created then initilize the data area
1336
                                        {
1336
                                        {
1337
                                                ClearCurrCluster(file); // fill cluster with zeros
1337
                                                ClearCurrCluster(file); // fill cluster with zeros
1338
                                                file->SectorInCache = file->FirstSectorOfFirstCluster;
1338
                                                file->SectorInCache = file->FirstSectorOfFirstCluster;
1339
                                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1339
                                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1340
                                                {
1340
                                                {
1341
                                                        Fat16_Deinit();
1341
                                                        Fat16_Deinit();
1342
                                                        return(retvalue);
1342
                                                        return(retvalue);
1343
                                                }
1343
                                                }
1344
                                                dir = (DirEntry_t *)file->Cache;
1344
                                                dir = (DirEntry_t *)file->Cache;
1345
                                                // create direntry "." to current dir
1345
                                                // create direntry "." to current dir
1346
                                                dir[0].Name[0] = 0x2E;
1346
                                                dir[0].Name[0] = 0x2E;
1347
                                                for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
1347
                                                for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
1348
                                                dir[0].Attribute = ATTR_SUBDIRECTORY;
1348
                                                dir[0].Attribute = ATTR_SUBDIRECTORY;
1349
                                                dir[0].StartCluster = subdircluster;
1349
                                                dir[0].StartCluster = subdircluster;
1350
                                                dir[0].Size = 0;
1350
                                                dir[0].Size = 0;
1351
                                                // create direntry ".." to the upper dir
1351
                                                // create direntry ".." to the upper dir
1352
                                                dir[1].Name[0] = 0x2E;
1352
                                                dir[1].Name[0] = 0x2E;
1353
                                                dir[1].Name[1] = 0x2E;
1353
                                                dir[1].Name[1] = 0x2E;
1354
                                                for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
1354
                                                for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
1355
                                                dir[1].Attribute = ATTR_SUBDIRECTORY;
1355
                                                dir[1].Attribute = ATTR_SUBDIRECTORY;
1356
                                                dir[1].StartCluster = dircluster;
1356
                                                dir[1].StartCluster = dircluster;
1357
                                                dir[1].Size = 0;
1357
                                                dir[1].Size = 0;
1358
                                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector.
1358
                                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector.
1359
                                                {
1359
                                                {
1360
                                                        Fat16_Deinit();
1360
                                                        Fat16_Deinit();
1361
                                                        return(retvalue);
1361
                                                        return(retvalue);
1362
                                                }
1362
                                                }
1363
                                        }
1363
                                        }
1364
                                        retvalue = 1;
1364
                                        retvalue = 1;
1365
                                        dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1365
                                        dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1366
                                }
1366
                                }
1367
                        }
1367
                        }
1368
                        dir_sector++; // search next sector
1368
                        dir_sector++; // search next sector
1369
                // stop if we reached the end of the cluster or the end of the root dir
1369
                // stop if we reached the end of the cluster or the end of the root dir
1370
                }while((dir_sector < max_dir_sector) && (!retvalue));
1370
                }while((dir_sector < max_dir_sector) && (!retvalue));
1371
 
1371
 
1372
                // if we are seaching in the data area and the file not found in this cluster so take next cluster.
1372
                // if we are seaching in the data area and the file not found in this cluster so take next cluster.
1373
                if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1373
                if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1374
                {
1374
                {
1375
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1375
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1376
                }
1376
                }
1377
        }while((end_of_directory_not_reached) && (!retvalue));
1377
        }while((end_of_directory_not_reached) && (!retvalue));
1378
        // Perhaps we are at the end of the last cluster of a directory file and have no free direntry found.
1378
        // Perhaps we are at the end of the last cluster of a directory file and have no free direntry found.
1379
        // Then we would need to add a cluster to that file and create the new direntry there.
1379
        // Then we would need to add a cluster to that file and create the new direntry there.
1380
        // This code is not implemented yet, because its occurs only if more that 32*32=1024 direntries are
1380
        // This code is not implemented yet, because its occurs only if more that 32*32=1024 direntries are
1381
        // within a subdirectory of root.
1381
        // within a subdirectory of root.
1382
 
1382
 
1383
        return(retvalue);       // return 1 if file has been created otherwise return 0.
1383
        return(retvalue);       // return 1 if file has been created otherwise return 0.
1384
}
1384
}
1385
 
1385
 
1386
/********************************************************************************************************************************************/
1386
/********************************************************************************************************************************************/
1387
/*      Function:               u8 DeleteDirectoryEntry(File_t *file)                                                                                                                                                                   */
1387
/*      Function:               u8 DeleteDirectoryEntry(File_t *file)                                                                                                                                                                   */
1388
/*      Description:    This function deletes the directoryentry of the file to be deleted from the filesystem                                                                  */
1388
/*      Description:    This function deletes the directoryentry of the file to be deleted from the filesystem                                                                  */
1389
/*                                                                                                                                                                                                                                      */
1389
/*                                                                                                                                                                                                                                      */
1390
/*                                                                                                                                                                                                                                                                                      */
1390
/*                                                                                                                                                                                                                                                                                      */
1391
/*      Returnvalue:    1 on succes and 0 on error                                                                                                                                                                                              */
1391
/*      Returnvalue:    1 on succes and 0 on error                                                                                                                                                                                              */
1392
/********************************************************************************************************************************************/
1392
/********************************************************************************************************************************************/
1393
u8 DeleteDirectoryEntry(File_t *file)
1393
u8 DeleteDirectoryEntry(File_t *file)
1394
{
1394
{
1395
        DirEntry_t *DirectoryEntry = NULL;
1395
        DirEntry_t *DirectoryEntry = NULL;
1396
        u8 retval = 0;
1396
        u8 retval = 0;
1397
 
1397
 
1398
        if((!Partition.IsValid) || (file == NULL)) return (retval);
1398
        if((!Partition.IsValid) || (file == NULL)) return (retval);
1399
        // valid directory sector?
1399
        // valid directory sector?
1400
        if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.LastDataSector))
1400
        if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.LastDataSector))
1401
        {
1401
        {
1402
                // try to  read the sector containing the directory entry of the file to be deleted 
1402
                // try to  read the sector containing the directory entry of the file to be deleted 
1403
                if(SD_SUCCESS != SDC_GetSector((u32) file->DirectorySector,file->Cache)) return(retval);
1403
                if(SD_SUCCESS != SDC_GetSector((u32) file->DirectorySector,file->Cache)) return(retval);
1404
                // get access to the elements of the directoryentry
1404
                // get access to the elements of the directoryentry
1405
                DirectoryEntry = (DirEntry_t *)file->Cache;
1405
                DirectoryEntry = (DirEntry_t *)file->Cache;
1406
                // delete the directoryentry
1406
                // delete the directoryentry
1407
                DirectoryEntry[file->DirectoryIndex].Name[0] = SLOT_DELETED;
1407
                DirectoryEntry[file->DirectoryIndex].Name[0] = SLOT_DELETED;
1408
                DirectoryEntry[file->DirectoryIndex].Attribute = 0;
1408
                DirectoryEntry[file->DirectoryIndex].Attribute = 0;
1409
                DirectoryEntry[file->DirectoryIndex].Size = 0;
1409
                DirectoryEntry[file->DirectoryIndex].Size = 0;
1410
                // the file has been deleted from the directory, save the modified sector back to the filesystem 
1410
                // the file has been deleted from the directory, save the modified sector back to the filesystem 
1411
                if(SD_SUCCESS == SDC_PutSector((u32) file->DirectorySector,file->Cache)) retval = 1;
1411
                if(SD_SUCCESS == SDC_PutSector((u32) file->DirectorySector,file->Cache)) retval = 1;
1412
        }
1412
        }
1413
        return(retval);
1413
        return(retval);
1414
}
1414
}
1415
 
1415
 
1416
/********************************************************************************************************************************************/
1416
/********************************************************************************************************************************************/
1417
/*      Function:               FileExist(const s8* filename, u8 attribfilter, u8 attribmask, File_t *file);                                                                                    */
1417
/*      Function:               FileExist(const s8* filename, u8 attribfilter, u8 attribmask, File_t *file);                                                                                    */
1418
/*                                                                                                                                                                                                                                                                                      */
1418
/*                                                                                                                                                                                                                                                                                      */
1419
/*      Description:    This function looks for the specified file including its subdirectories.                                                                                                */
1419
/*      Description:    This function looks for the specified file including its subdirectories.                                                                                                */
1420
/*                  If the file is found the Filepointer properties are updated.                                                                                                                        */
1420
/*                  If the file is found the Filepointer properties are updated.                                                                                                                        */
1421
/*                                                                                                                                                                                                                                                                                      */
1421
/*                                                                                                                                                                                                                                                                                      */
1422
/*      Returnvalue:    1 if file is found else 0.                                                                                                                                                                                              */
1422
/*      Returnvalue:    1 if file is found else 0.                                                                                                                                                                                              */
1423
/********************************************************************************************************************************************/
1423
/********************************************************************************************************************************************/
1424
u8 FileExist(const s8* filename, const u8 attribfilter, const u8 attribmask, File_t *file)
1424
u8 FileExist(const s8* filename, const u8 attribfilter, const u8 attribmask, File_t *file)
1425
{
1425
{
1426
        s8* path = 0;
1426
        s8* path = 0;
1427
        s8* subpath = 0;
1427
        s8* subpath = 0;
1428
        u8 af, am, file_exist = 0;
1428
        u8 af, am, file_exist = 0;
1429
        s8 dirname[12]; // 8+3 + temination character
1429
        s8 dirname[12]; // 8+3 + temination character
1430
 
1430
 
1431
        // if incomming pointers are useless return immediatly
1431
        // if incomming pointers are useless return immediatly
1432
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1432
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1433
 
1433
 
1434
        // trace along the filepath
1434
        // trace along the filepath
1435
        path = (s8*)filename;                                                           // start at the beginning of the filename string
1435
        path = (s8*)filename;                                                           // start at the beginning of the filename string
1436
        file->DirectoryIndex = 0;                                                       // start search at first dir entry of cluster
1436
        file->DirectoryIndex = 0;                                                       // start search at first dir entry of cluster
1437
        if(path[0] == '/') // if a path begins  with a '/' the search starts at RootDirectory with file search
1437
        if(path[0] == '/') // if a path begins  with a '/' the search starts at RootDirectory with file search
1438
        {
1438
        {
1439
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;         // start at RootDirectory with file search      
1439
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;         // start at RootDirectory with file search      
1440
        }
1440
        }
1441
        else // if a path begins not with a '/' the search starts relative to the CWD
1441
        else // if a path begins not with a '/' the search starts relative to the CWD
1442
        {
1442
        {
1443
                file->FirstSectorOfFirstCluster = Partition.CurrentWorkingDirectory;
1443
                file->FirstSectorOfFirstCluster = Partition.CurrentWorkingDirectory;
1444
        }
1444
        }
1445
        // as long as the file was not found and the remaining path is not empty
1445
        // as long as the file was not found and the remaining path is not empty
1446
        while((*path != 0) && !file_exist)
1446
        while((*path != 0) && !file_exist)
1447
        {       // separate dirname and subpath from filepath string
1447
        {       // separate dirname and subpath from filepath string
1448
                subpath = SeperateFormatedDirName(path, dirname);
1448
                subpath = SeperateFormatedDirName(path, dirname);
1449
                if(subpath != NULL)
1449
                if(subpath != NULL)
1450
                {
1450
                {
1451
                        if(*subpath == 0)
1451
                        if(*subpath == 0)
1452
                        {       // empty subpath indicates last element of dir chain
1452
                        {       // empty subpath indicates last element of dir chain
1453
                                af = attribfilter;
1453
                                af = attribfilter;
1454
                                am = attribmask;
1454
                                am = attribmask;
1455
                        }
1455
                        }
1456
                        else  // it must be a subdirectory and no volume label
1456
                        else  // it must be a subdirectory and no volume label
1457
                        {
1457
                        {
1458
                                af = ATTR_SUBDIRECTORY;
1458
                                af = ATTR_SUBDIRECTORY;
1459
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1459
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1460
                        }
1460
                        }
1461
                        if(!DirectoryEntryExist(dirname, af, am, file))
1461
                        if(!DirectoryEntryExist(dirname, af, am, file))
1462
                        {
1462
                        {
1463
                                return(file_exist); // subdirectory does not exist
1463
                                return(file_exist); // subdirectory does not exist
1464
                        }
1464
                        }
1465
                        else
1465
                        else
1466
                        {
1466
                        {
1467
                                if (*subpath == 0)
1467
                                if (*subpath == 0)
1468
                                {
1468
                                {
1469
                                        file_exist = 1; // last element of path chain was found with the given attribute filter
1469
                                        file_exist = 1; // last element of path chain was found with the given attribute filter
1470
                                }
1470
                                }
1471
                        }
1471
                        }
1472
                }
1472
                }
1473
                else // error seperating the subpath
1473
                else // error seperating the subpath
1474
                {
1474
                {
1475
                        return(file_exist); // bad subdir format
1475
                        return(file_exist); // bad subdir format
1476
                }
1476
                }
1477
                path = subpath;
1477
                path = subpath;
1478
                subpath = 0;
1478
                subpath = 0;
1479
        }
1479
        }
1480
        return(file_exist);
1480
        return(file_exist);
1481
}
1481
}
1482
 
1482
 
1483
 
1483
 
1484
/********************************************************************************************************************************************/
1484
/********************************************************************************************************************************************/
1485
/*      Function:               FileCreate(const s8* filename, u8 attrib, File_t *file);                                                                                                                                */
1485
/*      Function:               FileCreate(const s8* filename, u8 attrib, File_t *file);                                                                                                                                */
1486
/*                                                                                                                                                                                                                                                                                      */
1486
/*                                                                                                                                                                                                                                                                                      */
1487
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
1487
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
1488
/*                                      in the rootdirectory of the partition. If the file is found the Filepointer properties are                                                              */
1488
/*                                      in the rootdirectory of the partition. If the file is found the Filepointer properties are                                                              */
1489
/*                                      updated. If file or its subdirectories are not found they will be created                                                                                               */
1489
/*                                      updated. If file or its subdirectories are not found they will be created                                                                                               */
1490
/*                                                                                                                                                                                                                                                                                      */
1490
/*                                                                                                                                                                                                                                                                                      */
1491
/*      Returnvalue:    1 if file was created else 0.                                                                                                                                                                                   */
1491
/*      Returnvalue:    1 if file was created else 0.                                                                                                                                                                                   */
1492
/********************************************************************************************************************************************/
1492
/********************************************************************************************************************************************/
1493
u8 FileCreate(const s8* filename, const u8 attrib, File_t *file)
1493
u8 FileCreate(const s8* filename, const u8 attrib, File_t *file)
1494
{
1494
{
1495
        s8 *path = 0;
1495
        s8 *path = 0;
1496
        s8 *subpath = 0;
1496
        s8 *subpath = 0;
1497
        u8 af, am, file_created = 0;
1497
        u8 af, am, file_created = 0;
1498
        s8 dirname[12];
1498
        s8 dirname[12];
1499
        s8 txt[60];
1499
        s8 txt[60];
1500
        u8 i=0;
1500
        u8 i=0;
1501
 
1501
 
1502
        // if incomming pointers are useless return immediatly
1502
        // if incomming pointers are useless return immediatly
1503
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return(0);
1503
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return(0);
1504
 
1504
 
1505
        // trace along the filepath
1505
        // trace along the filepath
1506
        path = (s8*)filename;
1506
        path = (s8*)filename;
1507
 
1507
 
1508
        if(path[0] == '/') // if a path begins  with a '/' the search starts at RootDirectory with file search
1508
        if(path[0] == '/') // if a path begins  with a '/' the search starts at RootDirectory with file search
1509
        {
1509
        {
1510
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;         // start at RootDirectory with file search      
1510
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;         // start at RootDirectory with file search      
1511
        }
1511
        }
1512
        else // if a path begins not with a '/' the search starts relative to the CWD
1512
        else // if a path begins not with a '/' the search starts relative to the CWD
1513
        {
1513
        {
1514
                file->FirstSectorOfFirstCluster = Partition.CurrentWorkingDirectory;
1514
                file->FirstSectorOfFirstCluster = Partition.CurrentWorkingDirectory;
1515
        }
1515
        }
1516
        file->DirectoryIndex = 0;
1516
        file->DirectoryIndex = 0;
1517
 
1517
 
1518
        // as long as the file was not created and the remaining file path is not empty
1518
        // as long as the file was not created and the remaining file path is not empty
1519
        while((*path != 0) && !file_created)
1519
        while((*path != 0) && !file_created)
1520
        {   // separate dirname and subpath from filepath string
1520
        {   // separate dirname and subpath from filepath string
1521
                subpath = SeperateFormatedDirName(path, dirname);
1521
                subpath = SeperateFormatedDirName(path, dirname);
1522
                if(subpath != NULL)
1522
                if(subpath != NULL)
1523
                {
1523
                {
1524
                        if(*subpath == 0)
1524
                        if(*subpath == 0)
1525
                        {       // empty subpath indicates last element of dir chain
1525
                        {       // empty subpath indicates last element of dir chain
1526
                                af = ATTR_NONE;
1526
                                af = ATTR_NONE;
1527
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;  // any file that is no subdir or volume label
1527
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;  // any file that is no subdir or volume label
1528
                        }
1528
                        }
1529
                        else  // it must be a subdirectory but no volume label
1529
                        else  // it must be a subdirectory but no volume label
1530
                        {
1530
                        {
1531
                                af = ATTR_SUBDIRECTORY;
1531
                                af = ATTR_SUBDIRECTORY;
1532
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1532
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1533
                        }
1533
                        }
1534
                        if(!DirectoryEntryExist(dirname, af, am, file)) // if subdir or file is not existent
1534
                        if(!DirectoryEntryExist(dirname, af, am, file)) // if subdir or file is not existent
1535
                        {  // try to create subdir or file
1535
                        {  // try to create subdir or file
1536
                                if(*subpath == 0) af = attrib; // if last element in dir chain take the given attribute
1536
                                if(*subpath == 0) af = attrib; // if last element in dir chain take the given attribute
1537
                                if(!CreateDirectoryEntry(dirname, af, file))
1537
                                if(!CreateDirectoryEntry(dirname, af, file))
1538
                                {       // could not be created
1538
                                {       // could not be created
1539
                                        return(file_created);
1539
                                        return(file_created);
1540
                                }
1540
                                }
1541
                                else if(*subpath == 0) file_created = 1; // last element of path chain was created
1541
                                else if(*subpath == 0) file_created = 1; // last element of path chain was created
1542
                        }
1542
                        }
1543
                        sprintf(txt+i, "s:%06d",file->FirstSectorOfFirstCluster);
1543
                        sprintf(txt+i, "s:%06d",file->FirstSectorOfFirstCluster);
1544
                        i+=8;
1544
                        i+=8;
1545
                }
1545
                }
1546
                else // error seperating the subpath
1546
                else // error seperating the subpath
1547
                {
1547
                {
1548
                        return(file_created); // bad subdir format
1548
                        return(file_created); // bad subdir format
1549
                }
1549
                }
1550
                path = subpath;
1550
                path = subpath;
1551
                subpath = NULL;
1551
                subpath = NULL;
1552
        }
1552
        }
1553
        Debug(txt);
1553
        Debug(txt);
1554
        return(file_created);
1554
        return(file_created);
1555
}
1555
}
1556
 
1556
 
1557
 
1557
 
1558
/********************************************************************************************************************************************/
1558
/********************************************************************************************************************************************/
1559
/*      Function:               void Slashing_Path(s8*)                                                                                                                                                                                                 */
1559
/*      Function:               void Slashing_Path(s8*)                                                                                                                                                                                                 */
1560
/*                                                                                                                                                                                                                                                                                      */
1560
/*                                                                                                                                                                                                                                                                                      */
1561
/*      Description:    This function replaces all \ by / in the string pointed to by the argument                                                                              */
1561
/*      Description:    This function replaces all \ by / in the string pointed to by the argument                                                                              */
1562
/*                                                                                                                                                                                                                                      */
1562
/*                                                                                                                                                                                                                                      */
1563
/*                                                                                                                                                                                                                                                                                      */
1563
/*                                                                                                                                                                                                                                                                                      */
1564
/*      Returnvalue:                                                                                                                                                                                                                                                    */
1564
/*      Returnvalue:                                                                                                                                                                                                                                                    */
1565
/********************************************************************************************************************************************/
1565
/********************************************************************************************************************************************/
1566
void Slashing_Path(s8* path)
1566
void Slashing_Path(s8* path)
1567
{
1567
{
1568
        s8 *cptr = path;
1568
        s8 *cptr = path;
1569
        while(*cptr != 0 )
1569
        while(*cptr != 0 )
1570
        {
1570
        {
1571
                if(*cptr == '\\') *cptr = '/'; // replace \ by /
1571
                if(*cptr == '\\') *cptr = '/'; // replace \ by /
1572
                cptr++;
1572
                cptr++;
1573
        }
1573
        }
1574
}
1574
}
1575
 
1575
 
1576
/********************************************************************************************************************************************/
1576
/********************************************************************************************************************************************/
1577
/*      Function:               File_t * fopen_(s8* filename, s8 mode);                                                                                                                                                                 */
1577
/*      Function:               File_t * fopen_(s8* filename, s8 mode);                                                                                                                                                                 */
1578
/*                                                                                                                                                                                                                                                                                      */
1578
/*                                                                                                                                                                                                                                                                                      */
1579
/*      Description:    This function looks for the specified file in the rootdirectory of the drive. If the file is found the number of the    */
1579
/*      Description:    This function looks for the specified file in the rootdirectory of the drive. If the file is found the number of the    */
1580
/*                                      corrosponding filepointer is returned. Only modes 'r' (reading), 'w' (writing) and 'a' (append) are implemented yet.    */
1580
/*                                      corrosponding filepointer is returned. Only modes 'r' (reading), 'w' (writing) and 'a' (append) are implemented yet.    */
1581
/*                                                                                                                                                                                                                                                                                      */
1581
/*                                                                                                                                                                                                                                                                                      */
1582
/*      Returnvalue:    The filepointer to the file or 0 if faild.                                                                                                                                                              */
1582
/*      Returnvalue:    The filepointer to the file or 0 if faild.                                                                                                                                                              */
1583
/********************************************************************************************************************************************/
1583
/********************************************************************************************************************************************/
1584
File_t * fopen_(s8* const filename, const s8 mode)
1584
File_t * fopen_(s8* const filename, const s8 mode)
1585
{
1585
{
1586
        File_t *file    = 0;
1586
        File_t *file    = 0;
1587
        s8 *cptr;
1587
        s8 *cptr;
1588
 
1588
 
1589
        if((!Partition.IsValid) || (filename == 0)) return(file);
1589
        if((!Partition.IsValid) || (filename == 0)) return(file);
1590
 
1590
 
1591
        // Look for an unused filepointer in the file pointer list?
1591
        // Look for an unused filepointer in the file pointer list?
1592
        file = LockFilePointer();
1592
        file = LockFilePointer();
1593
        // if no unused file pointer was found return 0
1593
        // if no unused file pointer was found return 0
1594
        if(file == NULL) return(file);
1594
        if(file == NULL) return(file);
1595
 
1595
 
1596
        // now we have found a free filepointer and claimed it
1596
        // now we have found a free filepointer and claimed it
1597
        file->Mode                                              = mode;         // mode of fileoperation (read,write)
1597
        file->Mode                                              = mode;         // mode of fileoperation (read,write)
1598
        file->Attribute                                 = 0;            // the attribute of the file opened.
1598
        file->Attribute                                 = 0;            // the attribute of the file opened.
1599
 
1599
 
1600
        // bring the path into the correct syntax
1600
        // bring the path into the correct syntax
1601
        Slashing_Path(filename);
1601
        Slashing_Path(filename);
1602
        cptr = filename;
1602
        cptr = filename;
1603
 
1603
 
1604
        // check if a real file (no directory) to the given filename exist
1604
        // check if a real file (no directory) to the given filename exist
1605
        if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
1605
        if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
1606
        {  // file exist
1606
        {  // file exist
1607
                switch(mode)  // check mode
1607
                switch(mode)  // check mode
1608
                {
1608
                {
1609
                        case 'a':       // if mode is: append to file
1609
                        case 'a':       // if mode is: append to file
1610
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1610
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1611
                                {       // file is marked as readonly --> do not open this file
1611
                                {       // file is marked as readonly --> do not open this file
1612
                                        fclose_(file);
1612
                                        fclose_(file);
1613
                                        file = NULL;
1613
                                        file = NULL;
1614
                                }
1614
                                }
1615
                                else
1615
                                else
1616
                                {       // file is not marked as read only --> goto end of file
1616
                                {       // file is not marked as read only --> goto end of file
1617
                                        fseek_(file, 0, SEEK_END);              // point to the end of the file
1617
                                        fseek_(file, 0, SEEK_END);              // point to the end of the file
1618
                                }
1618
                                }
1619
                                break;
1619
                                break;
1620
                        case 'w':       // if mode is: write to file
1620
                        case 'w':       // if mode is: write to file
1621
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1621
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1622
                                {       // file is marked as readonly --> do not open this file
1622
                                {       // file is marked as readonly --> do not open this file
1623
                                        fclose_(file);
1623
                                        fclose_(file);
1624
                                        file = NULL;
1624
                                        file = NULL;
1625
                                }
1625
                                }
1626
                                else
1626
                                else
1627
                                {       // file is not marked as read only
1627
                                {       // file is not marked as read only
1628
                                        DirEntry_t * dir;
1628
                                        DirEntry_t * dir;
1629
                                        // free all clusters of that file
1629
                                        // free all clusters of that file
1630
                                        DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster));
1630
                                        DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster));
1631
                                        // update directory entry of that file
1631
                                        // update directory entry of that file
1632
                                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1632
                                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1633
                                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1633
                                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1634
                                        {
1634
                                        {
1635
                                                Fat16_Deinit();
1635
                                                Fat16_Deinit();
1636
                                                return(NULL);
1636
                                                return(NULL);
1637
                                        }
1637
                                        }
1638
                                        dir = (DirEntry_t *)file->Cache;                                                                // set pointer to directory
1638
                                        dir = (DirEntry_t *)file->Cache;                                                                // set pointer to directory
1639
                                    dir[file->DirectoryIndex].ModTime   = FileTime(&SystemTime);        // set modification time
1639
                                    dir[file->DirectoryIndex].ModTime   = FileTime(&SystemTime);        // set modification time
1640
                                        dir[file->DirectoryIndex].ModDate       = FileDate(&SystemTime);        // set modification date
1640
                                        dir[file->DirectoryIndex].ModDate       = FileDate(&SystemTime);        // set modification date
1641
                                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1641
                                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1642
                                        dir[file->DirectoryIndex].StartCluster = CLUSTER_UNDEFINED;             // update startcluster
1642
                                        dir[file->DirectoryIndex].StartCluster = CLUSTER_UNDEFINED;             // update startcluster
1643
                                        dir[file->DirectoryIndex].Size          = 0;
1643
                                        dir[file->DirectoryIndex].Size          = 0;
1644
                                        // write sector containing the direntry
1644
                                        // write sector containing the direntry
1645
                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1645
                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1646
                                        {
1646
                                        {
1647
                                                Fat16_Deinit();
1647
                                                Fat16_Deinit();
1648
                                                return(NULL);
1648
                                                return(NULL);
1649
                                        }
1649
                                        }
1650
                                        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
1650
                                        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
1651
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1651
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1652
                                        file->SectorOfCurrCluster = 0;
1652
                                        file->SectorOfCurrCluster = 0;
1653
                                        file->ByteOfCurrSector = 0;
1653
                                        file->ByteOfCurrSector = 0;
1654
                                        file->Size = 0;
1654
                                        file->Size = 0;
1655
                                        file->Position = 0;
1655
                                        file->Position = 0;
1656
                                        fseek_(file, 0, SEEK_SET);
1656
                                        fseek_(file, 0, SEEK_SET);
1657
                                }
1657
                                }
1658
                                break;
1658
                                break;
1659
                        case 'r':       // if mode is: read from file
1659
                        case 'r':       // if mode is: read from file
1660
                                // goto end of file
1660
                                // goto end of file
1661
                                fseek_(file, 0, SEEK_SET);
1661
                                fseek_(file, 0, SEEK_SET);
1662
                                break;
1662
                                break;
1663
                        default: // other modes are not supported
1663
                        default: // other modes are not supported
1664
                                fclose_(file);
1664
                                fclose_(file);
1665
                                file = NULL;
1665
                                file = NULL;
1666
                        break;
1666
                        break;
1667
                }
1667
                }
1668
                return(file);
1668
                return(file);
1669
        }
1669
        }
1670
        else // file does not exist
1670
        else // file does not exist
1671
        {
1671
        {
1672
                switch(mode)  // check mode
1672
                switch(mode)  // check mode
1673
                {
1673
                {
1674
                        case 'a':
1674
                        case 'a':
1675
                        case 'w': // if mode is write or append
1675
                        case 'w': // if mode is write or append
1676
                                // try to create the file
1676
                                // try to create the file
1677
                                if(!FileCreate(filename, ATTR_ARCHIVE, file))
1677
                                if(!FileCreate(filename, ATTR_ARCHIVE, file))
1678
                                { // if it could not be created
1678
                                { // if it could not be created
1679
                                        fclose_(file);
1679
                                        fclose_(file);
1680
                                        file = NULL;
1680
                                        file = NULL;
1681
                                }
1681
                                }
1682
                                break;
1682
                                break;
1683
                        case 'r': // else opened for 'r'
1683
                        case 'r': // else opened for 'r'
1684
                        default:  // if unsupported mode
1684
                        default:  // if unsupported mode
1685
                                fclose_(file);
1685
                                fclose_(file);
1686
                                file = NULL;
1686
                                file = NULL;
1687
                                break;
1687
                                break;
1688
                }
1688
                }
1689
                return(file);
1689
                return(file);
1690
        }
1690
        }
1691
        // we should never come to this point
1691
        // we should never come to this point
1692
        fclose_(file);
1692
        fclose_(file);
1693
        file = NULL;
1693
        file = NULL;
1694
        return(file);
1694
        return(file);
1695
}
1695
}
1696
 
1696
 
1697
/****************************************************************************************************************************************************/
1697
/****************************************************************************************************************************************************/
1698
/* Function:    s16 fseek_(File_t *, s32 *, u8)                                                                                                                                                                                                         */
1698
/* Function:    s16 fseek_(File_t *, s32 *, u8)                                                                                                                                                                                                         */
1699
/*                                                                                                                                                                                                                                                                                                      */
1699
/*                                                                                                                                                                                                                                                                                                      */
1700
/* Description: This function sets the pointer of the stream relative to the position                                                                                                                           */
1700
/* Description: This function sets the pointer of the stream relative to the position                                                                                                                           */
1701
/*                              specified by origin (SEEK_SET, SEEK_CUR, SEEK_END)                                                                                                                                                                      */
1701
/*                              specified by origin (SEEK_SET, SEEK_CUR, SEEK_END)                                                                                                                                                                      */
1702
/* Returnvalue: Is 0 if seek was successful                                                                                                                                                                                                                     */
1702
/* Returnvalue: Is 0 if seek was successful                                                                                                                                                                                                                     */
1703
/****************************************************************************************************************************************************/
1703
/****************************************************************************************************************************************************/
1704
s16 fseek_(File_t *file, s32 offset, s16 origin)
1704
s16 fseek_(File_t *file, s32 offset, s16 origin)
1705
{
1705
{
1706
        s32             fposition       = 0;
1706
        s32             fposition       = 0;
1707
        s16     retvalue        = 1;
1707
        s16     retvalue        = 1;
1708
        u32             byte_index       = 0;   // the byteindex within a sector
1708
        u32             byte_index       = 0;   // the byteindex within a sector
1709
        u32             sector_index  = 0;      // the  sectorindex within a cluster
1709
        u32             sector_index  = 0;      // the  sectorindex within a cluster
1710
        u32     cluster_index = 0;      // the index of the cluster within the clusterchain inside the fat
1710
        u32     cluster_index = 0;      // the index of the cluster within the clusterchain inside the fat
1711
 
1711
 
1712
        // check if the partition is valid
1712
        // check if the partition is valid
1713
        if((!Partition.IsValid) || (file == NULL)) return(retvalue);
1713
        if((!Partition.IsValid) || (file == NULL)) return(retvalue);
1714
        switch(origin)
1714
        switch(origin)
1715
        {
1715
        {
1716
                case SEEK_SET:                          // Fileposition relative to the beginning of the file.
1716
                case SEEK_SET:                          // Fileposition relative to the beginning of the file.
1717
                        fposition = 0;
1717
                        fposition = 0;
1718
                        break;
1718
                        break;
1719
                case SEEK_END:                          // Fileposition relative to the end of the file.
1719
                case SEEK_END:                          // Fileposition relative to the end of the file.
1720
                        fposition = (s32)file->Size;
1720
                        fposition = (s32)file->Size;
1721
                        break;
1721
                        break;
1722
                case SEEK_CUR:                          // Fileposition relative to the current position of the file.
1722
                case SEEK_CUR:                          // Fileposition relative to the current position of the file.
1723
                default:
1723
                default:
1724
                        fposition = file->Position;
1724
                        fposition = file->Position;
1725
                        break;
1725
                        break;
1726
        }
1726
        }
1727
 
1727
 
1728
        // calculate the specified fileposition according to the selected mode
1728
        // calculate the specified fileposition according to the selected mode
1729
        fposition += offset;
1729
        fposition += offset;
1730
        // is the fileposition within the file?
1730
        // is the fileposition within the file?
1731
        if((fposition >= 0) && (fposition <= (s32)file->Size))
1731
        if((fposition >= 0) && (fposition <= (s32)file->Size))
1732
        {
1732
        {
1733
                // initialize the filepointer to start of the file
1733
                // initialize the filepointer to start of the file
1734
                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1734
                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1735
                file->SectorOfCurrCluster       = 0;
1735
                file->SectorOfCurrCluster       = 0;
1736
                file->ByteOfCurrSector          = 0;
1736
                file->ByteOfCurrSector          = 0;
1737
                file->Position                          = 0;
1737
                file->Position                          = 0;
1738
                // has the specified file at least one valid sector attached?
1738
                // has the specified file at least one valid sector attached?
1739
                if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(retvalue);
1739
                if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(retvalue);
1740
                // calculate the absolute number of the sector wich contains the fileposition we are looking for
1740
                // calculate the absolute number of the sector wich contains the fileposition we are looking for
1741
                sector_index = (u32) ((u32)fposition >> 9);      // 512 bytes per sector
1741
                sector_index = (u32) ((u32)fposition >> 9);      // 512 bytes per sector
1742
                // calculate the index of the cluster containing the specified sector
1742
                // calculate the index of the cluster containing the specified sector
1743
                cluster_index = (u32) sector_index / Partition.SectorsPerCluster;
1743
                cluster_index = (u32) sector_index / Partition.SectorsPerCluster;
1744
                // the absolute sectornumber becomes relative to the beginning of the specified cluster
1744
                // the absolute sectornumber becomes relative to the beginning of the specified cluster
1745
                sector_index = (sector_index % Partition.SectorsPerCluster);
1745
                sector_index = (sector_index % Partition.SectorsPerCluster);
1746
                // calculate the index of the byteposition the fileposition points to
1746
                // calculate the index of the byteposition the fileposition points to
1747
                byte_index = (u32) fposition % 512;
1747
                byte_index = (u32) fposition % 512;
1748
                // parse the fat till the calculated cluster has been reached
1748
                // parse the fat till the calculated cluster has been reached
1749
                while(cluster_index--) GetNextCluster(file);
1749
                while(cluster_index--) GetNextCluster(file);
1750
                // set the filepointer to the specified sector and byteposition
1750
                // set the filepointer to the specified sector and byteposition
1751
                file->SectorOfCurrCluster = (u8) sector_index;
1751
                file->SectorOfCurrCluster = (u8) sector_index;
1752
                file->ByteOfCurrSector = (u16) byte_index;
1752
                file->ByteOfCurrSector = (u16) byte_index;
1753
                // the fileposition now equals the filepointer
1753
                // the fileposition now equals the filepointer
1754
                file->Position = (u32)fposition;
1754
                file->Position = (u32)fposition;
1755
                // the specified fileposition has been reached
1755
                // the specified fileposition has been reached
1756
                retvalue = 0;
1756
                retvalue = 0;
1757
        }
1757
        }
1758
        return(retvalue);
1758
        return(retvalue);
1759
}
1759
}
1760
 
1760
 
1761
/****************************************************************************************************************************************************/
1761
/****************************************************************************************************************************************************/
1762
/* Function:    fflush_(File *);                                                                                                                                                                                                                                        */
1762
/* Function:    fflush_(File *);                                                                                                                                                                                                                                        */
1763
/*                                                                                                                                                                                                                                                                                                      */
1763
/*                                                                                                                                                                                                                                                                                                      */
1764
/* Description: This function writes the data already in the buffer but not yet written to the file.                                                                                            */
1764
/* Description: This function writes the data already in the buffer but not yet written to the file.                                                                                            */
1765
/*                                                                                                                                                                                                                                                                                                      */
1765
/*                                                                                                                                                                                                                                                                                                      */
1766
/* Returnvalue: 0 on success EOF on error                                                                                                                                                                                                                       */
1766
/* Returnvalue: 0 on success EOF on error                                                                                                                                                                                                                       */
1767
/****************************************************************************************************************************************************/
1767
/****************************************************************************************************************************************************/
1768
s16     fflush_(File_t *file)
1768
s16     fflush_(File_t *file)
1769
{
1769
{
1770
        DirEntry_t *dir;
1770
        DirEntry_t *dir;
1771
 
1771
 
1772
        if((file == NULL) || (!Partition.IsValid)) return (EOF);
1772
        if((file == NULL) || (!Partition.IsValid)) return (EOF);
1773
 
1773
 
1774
        switch(file->Mode)
1774
        switch(file->Mode)
1775
        {
1775
        {
1776
                case 'a':
1776
                case 'a':
1777
                case 'w':
1777
                case 'w':
1778
                        if(file->ByteOfCurrSector > 0)                                                                          // has data been added to the file?
1778
                        if(file->ByteOfCurrSector > 0)                                                                          // has data been added to the file?
1779
                        {
1779
                        {
1780
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// save the data still in the buffer
1780
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// save the data still in the buffer
1781
                                {
1781
                                {
1782
                                        Fat16_Deinit();
1782
                                        Fat16_Deinit();
1783
                                        return(EOF);
1783
                                        return(EOF);
1784
                                }
1784
                                }
1785
                        }
1785
                        }
1786
                        file->SectorInCache     = file->DirectorySector;
1786
                        file->SectorInCache     = file->DirectorySector;
1787
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))                                       // read the directory entry for this file.
1787
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))                                       // read the directory entry for this file.
1788
                        {
1788
                        {
1789
                                Fat16_Deinit();
1789
                                Fat16_Deinit();
1790
                                return(EOF);
1790
                                return(EOF);
1791
                        }
1791
                        }
1792
 
1792
 
1793
                        dir = (DirEntry_t *)file->Cache;
1793
                        dir = (DirEntry_t *)file->Cache;
1794
                        // update file size and modification time & date
1794
                        // update file size and modification time & date
1795
                        dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime);
1795
                        dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime);
1796
                        dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime);
1796
                        dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime);
1797
                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1797
                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1798
                        dir[file->DirectoryIndex].Size = file->Size;                                            // update file size
1798
                        dir[file->DirectoryIndex].Size = file->Size;                                            // update file size
1799
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to sd-card
1799
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to sd-card
1800
                        {
1800
                        {
1801
                                Fat16_Deinit();
1801
                                Fat16_Deinit();
1802
                                return(EOF);
1802
                                return(EOF);
1803
                        }
1803
                        }
1804
                        break;
1804
                        break;
1805
                case 'r':
1805
                case 'r':
1806
                default:
1806
                default:
1807
                        // do nothing!
1807
                        // do nothing!
1808
                        return(EOF);
1808
                        return(EOF);
1809
                        break;
1809
                        break;
1810
 
1810
 
1811
        }
1811
        }
1812
        return(0);
1812
        return(0);
1813
}
1813
}
1814
 
1814
 
1815
/********************************************************************************************************************************************/
1815
/********************************************************************************************************************************************/
1816
/*      Function:               fgetc_(File *file);                                                                                                                                                                                                             */
1816
/*      Function:               fgetc_(File *file);                                                                                                                                                                                                             */
1817
/*                                                                                                                                                                                                                                                                                      */
1817
/*                                                                                                                                                                                                                                                                                      */
1818
/*      Description:    This function reads and returns one character from the specified file. Is the end of the actual sector reached the              */
1818
/*      Description:    This function reads and returns one character from the specified file. Is the end of the actual sector reached the              */
1819
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1819
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1820
/*                                                                                                                                                                                                                                                                                      */
1820
/*                                                                                                                                                                                                                                                                                      */
1821
/*      Returnvalue:    The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.                                   */
1821
/*      Returnvalue:    The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.                                   */
1822
/********************************************************************************************************************************************/
1822
/********************************************************************************************************************************************/
1823
s16 fgetc_(File_t *file)
1823
s16 fgetc_(File_t *file)
1824
{
1824
{
1825
        s16 c = EOF;
1825
        s16 c = EOF;
1826
        u32 curr_sector;
1826
        u32 curr_sector;
1827
 
1827
 
1828
        if( (!Partition.IsValid) || (file == NULL)) return(c);
1828
        if( (!Partition.IsValid) || (file == NULL)) return(c);
1829
        // if the end of the file is not reached, get the next character.
1829
        // if the end of the file is not reached, get the next character.
1830
        if((0 < file->Size) && ((file->Position) < file->Size) )
1830
        if((0 < file->Size) && ((file->Position) < file->Size) )
1831
        {
1831
        {
1832
                curr_sector  = file->FirstSectorOfCurrCluster;          // calculate the sector of the next character to be read.
1832
                curr_sector  = file->FirstSectorOfCurrCluster;          // calculate the sector of the next character to be read.
1833
                curr_sector += file->SectorOfCurrCluster;
1833
                curr_sector += file->SectorOfCurrCluster;
1834
 
1834
 
1835
                if(file->SectorInCache != curr_sector)
1835
                if(file->SectorInCache != curr_sector)
1836
                {
1836
                {
1837
                        file->SectorInCache = curr_sector;
1837
                        file->SectorInCache = curr_sector;
1838
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
1838
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
1839
                        {
1839
                        {
1840
                                Fat16_Deinit();
1840
                                Fat16_Deinit();
1841
                                return(EOF);
1841
                                return(EOF);
1842
                        }
1842
                        }
1843
                }
1843
                }
1844
                c = (s16) file->Cache[file->ByteOfCurrSector];
1844
                c = (s16) file->Cache[file->ByteOfCurrSector];
1845
                file->Position++;                                                                       // increment file position
1845
                file->Position++;                                                                       // increment file position
1846
                file->ByteOfCurrSector++;                                                       // goto next byte in sector
1846
                file->ByteOfCurrSector++;                                                       // goto next byte in sector
1847
                if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if end of sector
1847
                if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if end of sector
1848
                {
1848
                {
1849
                        file->ByteOfCurrSector = 0;                                             //  reset byte location
1849
                        file->ByteOfCurrSector = 0;                                             //  reset byte location
1850
                        file->SectorOfCurrCluster++;                                    //      next sector
1850
                        file->SectorOfCurrCluster++;                                    //      next sector
1851
                        if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
1851
                        if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
1852
                        {
1852
                        {
1853
 
1853
 
1854
                                if(GetNextCluster(file))                                                                                // Sets the clusterpointer of the file to the next datacluster.
1854
                                if(GetNextCluster(file))                                                                                // Sets the clusterpointer of the file to the next datacluster.
1855
                                {
1855
                                {
1856
                                        file->SectorOfCurrCluster = 0;                                                          // start reading new cluster at first sector of the cluster.
1856
                                        file->SectorOfCurrCluster = 0;                                                          // start reading new cluster at first sector of the cluster.
1857
                                }
1857
                                }
1858
                                else // the last cluster was allready reached
1858
                                else // the last cluster was allready reached
1859
                                {
1859
                                {
1860
                                        file->SectorOfCurrCluster--;                                                    // jump back to the last sector in the last cluster
1860
                                        file->SectorOfCurrCluster--;                                                    // jump back to the last sector in the last cluster
1861
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
1861
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
1862
                                }
1862
                                }
1863
                        }
1863
                        }
1864
                }
1864
                }
1865
        }
1865
        }
1866
        return(c);
1866
        return(c);
1867
}
1867
}
1868
 
1868
 
1869
/********************************************************************************************************************************************/
1869
/********************************************************************************************************************************************/
1870
/*      Function:               fputc_( const s8 c, File *file);                                                                                                                                                                                */
1870
/*      Function:               fputc_( const s8 c, File *file);                                                                                                                                                                                */
1871
/*                                                                                                                                                                                                                                                                                      */
1871
/*                                                                                                                                                                                                                                                                                      */
1872
/*      Description:    This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries.                                 */
1872
/*      Description:    This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries.                                 */
1873
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1873
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1874
/*                                                                                                                                                                                                                                                                                      */
1874
/*                                                                                                                                                                                                                                                                                      */
1875
/*      Returnvalue:    The function returns the character written to the stream or EOF on error.                                                                                               */
1875
/*      Returnvalue:    The function returns the character written to the stream or EOF on error.                                                                                               */
1876
/********************************************************************************************************************************************/
1876
/********************************************************************************************************************************************/
1877
s16 fputc_(const s8 c, File_t *file)
1877
s16 fputc_(const s8 c, File_t *file)
1878
{
1878
{
1879
        u32 curr_sector  = 0;
1879
        u32 curr_sector  = 0;
1880
 
1880
 
1881
        if((!Partition.IsValid) || (file == NULL)) return(EOF);
1881
        if((!Partition.IsValid) || (file == NULL)) return(EOF);
1882
        switch(file->Mode)
1882
        switch(file->Mode)
1883
        {
1883
        {
1884
                case 'w':
1884
                case 'w':
1885
                case 'a':
1885
                case 'a':
1886
                        // If file position equals to file size, then the end of file has been reached.
1886
                        // If file position equals to file size, then the end of file has been reached.
1887
                        // In this case it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR
1887
                        // In this case it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR
1888
                        // and a new cluster should be appended.
1888
                        // and a new cluster should be appended.
1889
                        // If the first sector of first cluster is unvalid, then the file claims no data clusters
1889
                        // If the first sector of first cluster is unvalid, then the file claims no data clusters
1890
                        // and size should be zero, therefore append a new Cluster too.
1890
                        // and size should be zero, therefore append a new Cluster too.
1891
                        if(((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR)) || (file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED))
1891
                        if(((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR)) || (file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED))
1892
                        {
1892
                        {
1893
                                if(CLUSTER_UNDEFINED == AppendCluster(file)) return(EOF);
1893
                                if(CLUSTER_UNDEFINED == AppendCluster(file)) return(EOF);
1894
                        }
1894
                        }
1895
 
1895
 
1896
                        curr_sector  = file->FirstSectorOfCurrCluster;
1896
                        curr_sector  = file->FirstSectorOfCurrCluster;
1897
                        curr_sector += file->SectorOfCurrCluster;
1897
                        curr_sector += file->SectorOfCurrCluster;
1898
                        if(file->SectorInCache != curr_sector)
1898
                        if(file->SectorInCache != curr_sector)
1899
                        {
1899
                        {
1900
                                file->SectorInCache = curr_sector;
1900
                                file->SectorInCache = curr_sector;
1901
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
1901
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
1902
                                {
1902
                                {
1903
                                        Fat16_Deinit();
1903
                                        Fat16_Deinit();
1904
                                        return(EOF);
1904
                                        return(EOF);
1905
                                }
1905
                                }
1906
                        }
1906
                        }
1907
 
1907
 
1908
                        file->Cache[file->ByteOfCurrSector] = (u8)c;            // write databyte into the buffer. The byte will be written to the device at once
1908
                        file->Cache[file->ByteOfCurrSector] = (u8)c;            // write databyte into the buffer. The byte will be written to the device at once
1909
                        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.
1909
                        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.
1910
                        file->Position++;                                                                       // the actual positon within the file.
1910
                        file->Position++;                                                                       // the actual positon within the file.
1911
                        file->ByteOfCurrSector++;                                                       // goto next byte in sector
1911
                        file->ByteOfCurrSector++;                                                       // goto next byte in sector
1912
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if the end of this sector is reached yet
1912
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if the end of this sector is reached yet
1913
                        {       // save the sector to the sd-card
1913
                        {       // save the sector to the sd-card
1914
 
1914
 
1915
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1915
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1916
                                {
1916
                                {
1917
                                        Fat16_Deinit();
1917
                                        Fat16_Deinit();
1918
                                        return(EOF);
1918
                                        return(EOF);
1919
                                }
1919
                                }
1920
                                file->ByteOfCurrSector = 0;                                             //  reset byte location
1920
                                file->ByteOfCurrSector = 0;                                             //  reset byte location
1921
                                file->SectorOfCurrCluster++;                                    //      next sector
1921
                                file->SectorOfCurrCluster++;                                    //      next sector
1922
                                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT.
1922
                                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT.
1923
                                {
1923
                                {
1924
                                        if(!GetNextCluster(file))                                                               // Sets the clusterpointer of the file to the next datacluster.
1924
                                        if(!GetNextCluster(file))                                                               // Sets the clusterpointer of the file to the next datacluster.
1925
                                        { // if current cluster was the last cluster of the file
1925
                                        { // if current cluster was the last cluster of the file
1926
                                                if(!AppendCluster(file))                                                // append a new and free cluster at the end of the file.
1926
                                                if(!AppendCluster(file))                                                // append a new and free cluster at the end of the file.
1927
                                                {
1927
                                                {
1928
                                                        file->SectorOfCurrCluster--;                            // jump back to last sector of last cluster
1928
                                                        file->SectorOfCurrCluster--;                            // jump back to last sector of last cluster
1929
                                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;      // set byte location to 1 byte over sector len
1929
                                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;      // set byte location to 1 byte over sector len
1930
                                                        return(EOF);
1930
                                                        return(EOF);
1931
                                                }
1931
                                                }
1932
                                        }
1932
                                        }
1933
                                        else // next cluster
1933
                                        else // next cluster
1934
                                        {
1934
                                        {
1935
                                                file->SectorOfCurrCluster = 0;                                                  // start reading new cluster at first sector of the cluster.
1935
                                                file->SectorOfCurrCluster = 0;                                                  // start reading new cluster at first sector of the cluster.
1936
                                        }
1936
                                        }
1937
                                }
1937
                                }
1938
                        }
1938
                        }
1939
                        break;
1939
                        break;
1940
                case 'r':
1940
                case 'r':
1941
                default:
1941
                default:
1942
                        return(EOF);
1942
                        return(EOF);
1943
                        break;
1943
                        break;
1944
        } // EOF switch(file->Mode)
1944
        } // EOF switch(file->Mode)
1945
        return(0);
1945
        return(0);
1946
}
1946
}
1947
 
1947
 
1948
 
1948
 
1949
/****************************************************************************************************************************************/
1949
/****************************************************************************************************************************************/
1950
/*      Function:               fread_(void *buffer, s32 size, s32 count, File *File);                                                                                                                          */
1950
/*      Function:               fread_(void *buffer, s32 size, s32 count, File *File);                                                                                                                          */
1951
/*                                                                                                                                                                                                                                                                              */
1951
/*                                                                                                                                                                                                                                                                              */
1952
/*      Description:    This function reads count objects of the specified size                                                                                                                         */
1952
/*      Description:    This function reads count objects of the specified size                                                                                                                         */
1953
/*                                      from the actual position of the file to the specified buffer.                                                                                                           */
1953
/*                                      from the actual position of the file to the specified buffer.                                                                                                           */
1954
/*                                                                                                                                                                                                                                                                              */
1954
/*                                                                                                                                                                                                                                                                              */
1955
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1955
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1956
/****************************************************************************************************************************************/
1956
/****************************************************************************************************************************************/
1957
u32 fread_(void *buffer, u32 size, u32 count, File_t *file)
1957
u32 fread_(void *buffer, u32 size, u32 count, File_t *file)
1958
{
1958
{
1959
        u32 object_cnt  = 0;                                                                                    // count the number of objects read from the file.
1959
        u32 object_cnt  = 0;                                                                                    // count the number of objects read from the file.
1960
        u32 object_size = 0;                                                                                    // count the number of bytes read from the actual object.
1960
        u32 object_size = 0;                                                                                    // count the number of bytes read from the actual object.
1961
        u8 *pbuff       = 0;                                                                                    // a pointer to the actual bufferposition.
1961
        u8 *pbuff       = 0;                                                                                    // a pointer to the actual bufferposition.
1962
        u8 success      = 1;                                                                                    // no error occured during read operation to the file.
1962
        u8 success      = 1;                                                                                    // no error occured during read operation to the file.
1963
        s16 c;
1963
        s16 c;
1964
 
1964
 
1965
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1965
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1966
 
1966
 
1967
        pbuff = (u8 *) buffer;                                                                                  // cast the void pointer to an u8 *
1967
        pbuff = (u8 *) buffer;                                                                                  // cast the void pointer to an u8 *
1968
 
1968
 
1969
        while((object_cnt < count) && success)
1969
        while((object_cnt < count) && success)
1970
        {
1970
        {
1971
                object_size = size;
1971
                object_size = size;
1972
                while((size > 0) && success)
1972
                while((size > 0) && success)
1973
                {
1973
                {
1974
                        c = fgetc_(file);
1974
                        c = fgetc_(file);
1975
                        if(c != EOF)
1975
                        if(c != EOF)
1976
                        {
1976
                        {
1977
                                *pbuff = (u8)c;                                                                         // read a byte from the buffer to the opened file.
1977
                                *pbuff = (u8)c;                                                                         // read a byte from the buffer to the opened file.
1978
                                pbuff++;
1978
                                pbuff++;
1979
                                size--;
1979
                                size--;
1980
                        }
1980
                        }
1981
                        else // error or end of file reached
1981
                        else // error or end of file reached
1982
                        {
1982
                        {
1983
                                success = 0;
1983
                                success = 0;
1984
                        }
1984
                        }
1985
                }
1985
                }
1986
                if(success) object_cnt++;
1986
                if(success) object_cnt++;
1987
        }
1987
        }
1988
        return(object_cnt);                                                                                             // return the number of objects succesfully read from the file
1988
        return(object_cnt);                                                                                             // return the number of objects succesfully read from the file
1989
}
1989
}
1990
 
1990
 
1991
 
1991
 
1992
/****************************************************************************************************************************************/
1992
/****************************************************************************************************************************************/
1993
/*      Function:               fwrite_(void *buffer, s32 size, s32 count, File *file);                                                                                                                         */
1993
/*      Function:               fwrite_(void *buffer, s32 size, s32 count, File *file);                                                                                                                         */
1994
/*                                                                                                                                                                                                                                                                              */
1994
/*                                                                                                                                                                                                                                                                              */
1995
/*      Description:    This function writes count objects of the specified size                                                                                                                        */
1995
/*      Description:    This function writes count objects of the specified size                                                                                                                        */
1996
/*                                      from the buffer pointer to the actual position in the file.                                                                                                                     */
1996
/*                                      from the buffer pointer to the actual position in the file.                                                                                                                     */
1997
/*                                                                                                                                                                                                                                                                              */
1997
/*                                                                                                                                                                                                                                                                              */
1998
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1998
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1999
/****************************************************************************************************************************************/
1999
/****************************************************************************************************************************************/
2000
u32 fwrite_(void *buffer, u32 size, u32 count, File_t *file)
2000
u32 fwrite_(void *buffer, u32 size, u32 count, File_t *file)
2001
{
2001
{
2002
        u32 object_cnt  = 0;                                                                                                            // count the number of objects written to the file.
2002
        u32 object_cnt  = 0;                                                                                                            // count the number of objects written to the file.
2003
        u32 object_size = 0;                                                                                                            // count the number of bytes written from the actual object.
2003
        u32 object_size = 0;                                                                                                            // count the number of bytes written from the actual object.
2004
        u8 *pbuff           = 0;                                                                                                                // a pointer to the actual bufferposition.
2004
        u8 *pbuff           = 0;                                                                                                                // a pointer to the actual bufferposition.
2005
        u8 success      = 1;                                                                                                            // no error occured during write operation to the file.
2005
        u8 success      = 1;                                                                                                            // no error occured during write operation to the file.
2006
        s16 c;
2006
        s16 c;
2007
 
2007
 
2008
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
2008
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
2009
        if(file->Mode == 'r') return (0); // opened read only
2009
        if(file->Mode == 'r') return (0); // opened read only
2010
        pbuff = (u8 *) buffer;                                                                                                          // cast the void pointer to an u8 *
2010
        pbuff = (u8 *) buffer;                                                                                                          // cast the void pointer to an u8 *
2011
 
2011
 
2012
        while((object_cnt < count) && success)
2012
        while((object_cnt < count) && success)
2013
        {
2013
        {
2014
                object_size = size;
2014
                object_size = size;
2015
                while((size > 0) && success)
2015
                while((size > 0) && success)
2016
                {
2016
                {
2017
                        c = fputc_(*pbuff, file);                                                                                       // write a byte from the buffer to the opened file.
2017
                        c = fputc_(*pbuff, file);                                                                                       // write a byte from the buffer to the opened file.
2018
                        if(c != EOF)
2018
                        if(c != EOF)
2019
                        {
2019
                        {
2020
                                pbuff++;
2020
                                pbuff++;
2021
                                size--;
2021
                                size--;
2022
                        }
2022
                        }
2023
                        else
2023
                        else
2024
                        {
2024
                        {
2025
                                success = 0;
2025
                                success = 0;
2026
                        }
2026
                        }
2027
                }
2027
                }
2028
                if(success) object_cnt++;
2028
                if(success) object_cnt++;
2029
        }
2029
        }
2030
 
2030
 
2031
        return(object_cnt);             // return the number of objects succesfully written to the file
2031
        return(object_cnt);             // return the number of objects succesfully written to the file
2032
}
2032
}
2033
 
2033
 
2034
 
2034
 
2035
/****************************************************************************************************************************************/
2035
/****************************************************************************************************************************************/
2036
/*      Function:               fputs_(const s8 *string, File_t *File);                                                                                                                                                         */
2036
/*      Function:               fputs_(const s8 *string, File_t *File);                                                                                                                                                         */
2037
/*                                                                                                                                                                                                                                                                              */
2037
/*                                                                                                                                                                                                                                                                              */
2038
/*      Description:    This function writes a string to the specified file.                                                                                                                            */
2038
/*      Description:    This function writes a string to the specified file.                                                                                                                            */
2039
/*                                                                                                                                                                                                                                                                              */
2039
/*                                                                                                                                                                                                                                                                              */
2040
/*      Returnvalue:    The function returns a no negative value or EOF on error.                                                                                                                       */
2040
/*      Returnvalue:    The function returns a no negative value or EOF on error.                                                                                                                       */
2041
/****************************************************************************************************************************************/
2041
/****************************************************************************************************************************************/
2042
s16 fputs_(s8 * const string, File_t * const file)
2042
s16 fputs_(s8 * const string, File_t * const file)
2043
{
2043
{
2044
        u8 i=0;
2044
        u8 i=0;
2045
        s16 c = 0;
2045
        s16 c = 0;
2046
 
2046
 
2047
        if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(EOF);
2047
        if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(EOF);
2048
        if(file->Mode == 'r') return(EOF);
2048
        if(file->Mode == 'r') return(EOF);
2049
        while((string[i] != 0)&& (c != EOF))
2049
        while((string[i] != 0)&& (c != EOF))
2050
        {
2050
        {
2051
                c = fputc_(string[i], file);
2051
                c = fputc_(string[i], file);
2052
                i++;
2052
                i++;
2053
        }
2053
        }
2054
        return(c);
2054
        return(c);
2055
}
2055
}
2056
 
2056
 
2057
/****************************************************************************************************************************************/
2057
/****************************************************************************************************************************************/
2058
/*      Function:               fgets_(s8 *, s16 , File_t *);                                                                                                                                                                           */
2058
/*      Function:               fgets_(s8 *, s16 , File_t *);                                                                                                                                                                           */
2059
/*                                                                                                                                                                                                                                                                              */
2059
/*                                                                                                                                                                                                                                                                              */
2060
/*      Description:    This function reads a string from the file to the specifies string.                                                                                             */
2060
/*      Description:    This function reads a string from the file to the specifies string.                                                                                             */
2061
/*                                                                                                                                                                                                                                                                              */
2061
/*                                                                                                                                                                                                                                                                              */
2062
/*      Returnvalue:    A pointer to the string read from the file or 0 on error.                                                                                                                       */
2062
/*      Returnvalue:    A pointer to the string read from the file or 0 on error.                                                                                                                       */
2063
/****************************************************************************************************************************************/
2063
/****************************************************************************************************************************************/
2064
s8 * fgets_(s8 * const string, s16 const length, File_t * const file)
2064
s8 * fgets_(s8 * const string, s16 const length, File_t * const file)
2065
{
2065
{
2066
        s8 *pbuff;
2066
        s8 *pbuff;
2067
        s16 c = 0, bytecount;
2067
        s16 c = 0, bytecount;
2068
 
2068
 
2069
        if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length < 1)) return (0);
2069
        if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length < 1)) return (0);
2070
        bytecount = length;
2070
        bytecount = length;
2071
        pbuff = string;                                                         // set write pointer to start of string
2071
        pbuff = string;                                                         // set write pointer to start of string
2072
        while(bytecount > 1)                                            // read the length-1 characters from the file to the string.
2072
        while(bytecount > 1)                                            // read the length-1 characters from the file to the string.
2073
        {
2073
        {
2074
                c = fgetc_(file);                                               // read a character from the opened file.
2074
                c = fgetc_(file);                                               // read a character from the opened file.
2075
                switch(c)
2075
                switch(c)
2076
                {
2076
                {
2077
                        case 0x0A:                                                      // new line
2077
                        case 0x0A:                                                      // new line
2078
                                *pbuff = 0;                                             // set string terminator
2078
                                *pbuff = 0;                                             // set string terminator
2079
                                return(string);                                 // return normal
2079
                                return(string);                                 // return normal
2080
 
2080
 
2081
                        case EOF:
2081
                        case EOF:
2082
                                *pbuff = 0;                                             // set string terminator
2082
                                *pbuff = 0;                                             // set string terminator
2083
                                return(0);
2083
                                return(0);
2084
 
2084
 
2085
                        default:
2085
                        default:
2086
                                *pbuff++ = (s8)c;                               // copy byte to string
2086
                                *pbuff++ = (s8)c;                               // copy byte to string
2087
                                bytecount--;
2087
                                bytecount--;
2088
                                break;
2088
                                break;
2089
                }
2089
                }
2090
        }
2090
        }
2091
        *pbuff = 0;     // set string terminator
2091
        *pbuff = 0;     // set string terminator
2092
        return(string);
2092
        return(string);
2093
}
2093
}
2094
 
2094
 
2095
/****************************************************************************************************************************************/
2095
/****************************************************************************************************************************************/
2096
/*      Function:               fclose_(File *file);                                                                                                                                                                                            */
2096
/*      Function:               fclose_(File *file);                                                                                                                                                                                            */
2097
/*                                                                                                                                                                                                                                                                              */
2097
/*                                                                                                                                                                                                                                                                              */
2098
/*      Description:    This function closes the open file by writing the remaining data                                                                                                        */
2098
/*      Description:    This function closes the open file by writing the remaining data                                                                                                        */
2099
/*                                      from the buffer to the device and entering the filesize in the directory entry.                                                                         */
2099
/*                                      from the buffer to the device and entering the filesize in the directory entry.                                                                         */
2100
/*                                                                                                                                                                                                                                                                              */
2100
/*                                                                                                                                                                                                                                                                              */
2101
/*      Returnvalue:    0 on success EOF on error                                                                                                                                                                                       */
2101
/*      Returnvalue:    0 on success EOF on error                                                                                                                                                                                       */
2102
/****************************************************************************************************************************************/
2102
/****************************************************************************************************************************************/
2103
s16 fclose_(File_t *file)
2103
s16 fclose_(File_t *file)
2104
{
2104
{
2105
        s16 returnvalue = EOF;
2105
        s16 returnvalue = EOF;
2106
 
2106
 
2107
        if(file == NULL) return(returnvalue);
2107
        if(file == NULL) return(returnvalue);
2108
        returnvalue = fflush_(file);
2108
        returnvalue = fflush_(file);
2109
        UnlockFilePointer(file);
2109
        UnlockFilePointer(file);
2110
        return(returnvalue);
2110
        return(returnvalue);
2111
}
2111
}
2112
 
2112
 
2113
 
2113
 
2114
/****************************************************************************************************************************************/
2114
/****************************************************************************************************************************************/
2115
/*      Function:               fexist_(const u8*);                                                                                                                                                                                                     */
2115
/*      Function:               fexist_(const u8*);                                                                                                                                                                                                     */
2116
/*                                                                                                                                                                                                                                                                              */
2116
/*                                                                                                                                                                                                                                                                              */
2117
/*      Description:    This function checks if a file already exist.                                                                                                                                           */
2117
/*      Description:    This function checks if a file already exist.                                                                                                                                           */
2118
/*                                                                                                                                                                                                                                                                              */
2118
/*                                                                                                                                                                                                                                                                              */
2119
/*      Returnvalue:    1 if the file exist else 0.                                                                                                                                                                                     */
2119
/*      Returnvalue:    1 if the file exist else 0.                                                                                                                                                                                     */
2120
/****************************************************************************************************************************************/
2120
/****************************************************************************************************************************************/
2121
u8 fexist_(s8 * const filename)
2121
u8 fexist_(s8 * const filename)
2122
{
2122
{
2123
        u8 exist = 0;
2123
        u8 exist = 0;
2124
        File_t *file = 0;
2124
        File_t *file = 0;
2125
        file = LockFilePointer();
2125
        file = LockFilePointer();
2126
        exist = FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file);
2126
        exist = FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file);
2127
        UnlockFilePointer(file);
2127
        UnlockFilePointer(file);
2128
        return(exist);
2128
        return(exist);
2129
}
2129
}
2130
 
2130
 
2131
/****************************************************************************************************************************************/
2131
/****************************************************************************************************************************************/
2132
/*      Function:               feof_(File_t *File);                                                                                                                                                                                            */
2132
/*      Function:               feof_(File_t *File);                                                                                                                                                                                            */
2133
/*                                                                                                                                                                                                                                                                              */
2133
/*                                                                                                                                                                                                                                                                              */
2134
/*      Description:    This function checks wether the end of the file has been reached.                                                                                                                                               */
2134
/*      Description:    This function checks wether the end of the file has been reached.                                                                                                                                               */
2135
/*                                                                                                                                                                                                                                                                              */
2135
/*                                                                                                                                                                                                                                                                              */
2136
/*      Returnvalue:    0 if the end of the file was not reached otherwise 1.                                                                                                                                                                           */
2136
/*      Returnvalue:    0 if the end of the file was not reached otherwise 1.                                                                                                                                                                           */
2137
/****************************************************************************************************************************************/
2137
/****************************************************************************************************************************************/
2138
u8 feof_(File_t *file)
2138
u8 feof_(File_t *file)
2139
{
2139
{
2140
        if(((file->Position)+1) < (file->Size))
2140
        if(((file->Position)+1) < (file->Size))
2141
        {
2141
        {
2142
                return(0);
2142
                return(0);
2143
        }
2143
        }
2144
        else
2144
        else
2145
        {
2145
        {
2146
                return(1);
2146
                return(1);
2147
        }
2147
        }
2148
}
2148
}
2149
 
2149
 
2150
 
2150
 
2151
/********************************************************************************************************************************************/
2151
/********************************************************************************************************************************************/
2152
/*      Function:               fdelete_(s8* filepath);                                                                                                                                                                                                 */
2152
/*      Function:               fdelete_(s8* filepath);                                                                                                                                                                                                 */
2153
/*                                                                                                                                                                                                                                                                                      */
2153
/*                                                                                                                                                                                                                                                                                      */
2154
/*      Description:    This function deletes the file with the specified filename from the filesystem                                                                                  */
2154
/*      Description:    This function deletes the file with the specified filename from the filesystem                                                                                  */
2155
/*                                                                                                                                                                                                                                      */
2155
/*                                                                                                                                                                                                                                      */
2156
/*                                                                                                                                                                                                                                                                                      */
2156
/*                                                                                                                                                                                                                                                                                      */
2157
/*      Returnvalue:    1 : specified file deleted succesfully 0: specified file not found                                                                                                              */
2157
/*      Returnvalue:    1 : specified file deleted succesfully 0: specified file not found                                                                                                              */
2158
/********************************************************************************************************************************************/
2158
/********************************************************************************************************************************************/
2159
 
2159
 
2160
u8 fdelete_(s8* const filepath)
2160
u8 fdelete_(s8* const filepath)
2161
{
2161
{
2162
        u8 retvalue = 0;
2162
        u8 retvalue = 0;
2163
        File_t file;
2163
        File_t file;
2164
 
2164
 
2165
        if(filepath == NULL) return(0);
2165
        if(filepath == NULL) return(0);
2166
        // correct filepath formatting
2166
        // correct filepath formatting
2167
        Slashing_Path(filepath);
2167
        Slashing_Path(filepath);
2168
        file.FirstSectorOfFirstCluster = SECTOR_UNDEFINED;              // First sector of the first cluster of the file.
2168
        file.FirstSectorOfFirstCluster = SECTOR_UNDEFINED;              // First sector of the first cluster of the file.
2169
        file.FirstSectorOfCurrCluster = SECTOR_UNDEFINED;               // First sector of the cluster which is edited at the moment.
2169
        file.FirstSectorOfCurrCluster = SECTOR_UNDEFINED;               // First sector of the cluster which is edited at the moment.
2170
        file.FirstSectorOfLastCluster = SECTOR_UNDEFINED;               // First sector of the last cluster of the file
2170
        file.FirstSectorOfLastCluster = SECTOR_UNDEFINED;               // First sector of the last cluster of the file
2171
        file.SectorOfCurrCluster = SECTOR_UNDEFINED;                    // The sector within the current cluster.
2171
        file.SectorOfCurrCluster = SECTOR_UNDEFINED;                    // The sector within the current cluster.
2172
        file.ByteOfCurrSector = 0;                                                              // The byte location within the current sector.
2172
        file.ByteOfCurrSector = 0;                                                              // The byte location within the current sector.
2173
        file.Mode = 0;                                                                                  // Mode of fileoperation (read,write)
2173
        file.Mode = 0;                                                                                  // Mode of fileoperation (read,write)
2174
        file.Size = 0;                                                                                  // The size of the opend file in bytes.
2174
        file.Size = 0;                                                                                  // The size of the opend file in bytes.
2175
        file.Position = 0;                                                                              // Pointer to a character within the file 0 < fileposition < filesize
2175
        file.Position = 0;                                                                              // Pointer to a character within the file 0 < fileposition < filesize
2176
        file.DirectorySector = SECTOR_UNDEFINED;                                // the sectorposition where the directoryentry has been made.
2176
        file.DirectorySector = SECTOR_UNDEFINED;                                // the sectorposition where the directoryentry has been made.
2177
        file.DirectoryIndex = 0;                                                                // The index to the directoryentry within the specified sector.
2177
        file.DirectoryIndex = 0;                                                                // The index to the directoryentry within the specified sector.
2178
        file.Attribute = 0;                                                                             // The attribute of the file opened.
2178
        file.Attribute = 0;                                                                             // The attribute of the file opened.
2179
        file.SectorInCache = SECTOR_UNDEFINED;                                  // The last sector read, which is still in the sector cache.
2179
        file.SectorInCache = SECTOR_UNDEFINED;                                  // The last sector read, which is still in the sector cache.
2180
        file.State = FSTATE_USED;                                                               // mark it as used
2180
        file.State = FSTATE_USED;                                                               // mark it as used
2181
       
2181
       
2182
        // if file is existent
2182
        // if file is existent
2183
        if(FileExist(filepath, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, &file))
2183
        if(FileExist(filepath, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, &file))
2184
        {
2184
        {
2185
                // and is not marked as readonly?
2185
                // and is not marked as readonly?
2186
                if((file.Attribute & ATTR_READONLY) != ATTR_READONLY)
2186
                if((file.Attribute & ATTR_READONLY) != ATTR_READONLY)
2187
                {
2187
                {
2188
                        // try to delete the file content from the filesystem
2188
                        // try to delete the file content from the filesystem
2189
                        if(DeleteClusterChain(file.FirstSectorOfFirstCluster))
2189
                        if(DeleteClusterChain(file.FirstSectorOfFirstCluster))
2190
                        {
2190
                        {
2191
                                // and try delete the directory entry of the file
2191
                                // and try delete the directory entry of the file
2192
                                retvalue = DeleteDirectoryEntry(&file);
2192
                                retvalue = DeleteDirectoryEntry(&file);
2193
                        }      
2193
                        }      
2194
                }
2194
                }
2195
        }
2195
        }
2196
        return(retvalue);
2196
        return(retvalue);
2197
}
2197
}
2198
 
2198
 
2199
/****************************************************************************************************************************************************/
2199
/****************************************************************************************************************************************************/
2200
/* Function:    s8* FAT16_GetVolumeLabel(void)                                                                                                                                                                                                                  */
2200
/* Function:    s8* FAT16_GetVolumeLabel(void)                                                                                                                                                                                                                  */
2201
/*                                                                                                                                                                                                                                                                                                      */
2201
/*                                                                                                                                                                                                                                                                                                      */
2202
/* Description: This function returns the volume label                                                                                                                                                                                          */
2202
/* Description: This function returns the volume label                                                                                                                                                                                          */
2203
/*                                                                                                                                                                                                                                                                                                      */
2203
/*                                                                                                                                                                                                                                                                                                      */
2204
/* Returnvalue: This function returns the pointer to the volume label or NULL if not found.                                                                                                                     */
2204
/* Returnvalue: This function returns the pointer to the volume label or NULL if not found.                                                                                                                     */
2205
/****************************************************************************************************************************************************/
2205
/****************************************************************************************************************************************************/
2206
s8* FAT16_GetVolumeLabel(void)
2206
s8* FAT16_GetVolumeLabel(void)
2207
{
2207
{
2208
        s8              *pVolumeLabel = NULL;
2208
        s8              *pVolumeLabel = NULL;
2209
        u32             dir_sector, max_dir_sector, curr_sector;
2209
        u32             dir_sector, max_dir_sector, curr_sector;
2210
        u16     dir_entry = 0;
2210
        u16     dir_entry = 0;
2211
        u8              i = 0;
2211
        u8              i = 0;
2212
 
2212
 
2213
        DirEntry_t * dir;
2213
        DirEntry_t * dir;
2214
        File_t *file = NULL;
2214
        File_t *file = NULL;
2215
 
2215
 
2216
        // if Partition is not valid return NULL
2216
        // if Partition is not valid return NULL
2217
        if(!Partition.IsValid) return(pVolumeLabel);
2217
        if(!Partition.IsValid) return(pVolumeLabel);
2218
        // if Volume label was read before return it
2218
        // if Volume label was read before return it
2219
        if(Partition.VolumeLabel[0]!= '\0') return (Partition.VolumeLabel);
2219
        if(Partition.VolumeLabel[0]!= '\0') return (Partition.VolumeLabel);
2220
        // try to catch a file pointer
2220
        // try to catch a file pointer
2221
        file = LockFilePointer();
2221
        file = LockFilePointer();
2222
        if(file == NULL) return(pVolumeLabel);
2222
        if(file == NULL) return(pVolumeLabel);
2223
        // search dir entries direct within the root directory area
2223
        // search dir entries direct within the root directory area
2224
        file->DirectorySector = 0;
2224
        file->DirectorySector = 0;
2225
        max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
2225
        max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
2226
        file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
2226
        file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
2227
 
2227
 
2228
        // update current file data area position to start of first cluster
2228
        // update current file data area position to start of first cluster
2229
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
2229
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
2230
        file->SectorOfCurrCluster               = 0;
2230
        file->SectorOfCurrCluster               = 0;
2231
        file->ByteOfCurrSector                  = 0;
2231
        file->ByteOfCurrSector                  = 0;
2232
 
2232
 
2233
        dir_sector = 0; // reset sector counter within a new cluster
2233
        dir_sector = 0; // reset sector counter within a new cluster
2234
        do // loop over all sectors of the root directory
2234
        do // loop over all sectors of the root directory
2235
        {
2235
        {
2236
                curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
2236
                curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
2237
                file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
2237
                file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
2238
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
2238
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
2239
                {
2239
                {
2240
                        Fat16_Deinit();
2240
                        Fat16_Deinit();
2241
                        return(NULL);
2241
                        return(NULL);
2242
                }
2242
                }
2243
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
2243
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
2244
                // search all directory entries within that sector
2244
                // search all directory entries within that sector
2245
                for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
2245
                for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
2246
                {   // check for existing dir entry
2246
                {   // check for existing dir entry
2247
                        switch((u8)dir[dir_entry].Name[0])
2247
                        switch((u8)dir[dir_entry].Name[0])
2248
                        {
2248
                        {
2249
                                case SLOT_EMPTY:
2249
                                case SLOT_EMPTY:
2250
                                case SLOT_DELETED:
2250
                                case SLOT_DELETED:
2251
                                        // ignore empty or deleted dir entries
2251
                                        // ignore empty or deleted dir entries
2252
                                        break;
2252
                                        break;
2253
                                default:
2253
                                default:
2254
                                        // check attributes for volume label
2254
                                        // check attributes for volume label
2255
                                        if ((dir[dir_entry].Attribute & ATTR_VOLUMELABEL) != ATTR_VOLUMELABEL) break; // attribute must match
2255
                                        if ((dir[dir_entry].Attribute & ATTR_VOLUMELABEL) != ATTR_VOLUMELABEL) break; // attribute must match
2256
                                        // (first 11 characters include 8 chars of basename and 3 chars extension.)
2256
                                        // (first 11 characters include 8 chars of basename and 3 chars extension.)
2257
                                        for(i = 0; i<11;i++) Partition.VolumeLabel[i] = dir[dir_entry].Name[i];
2257
                                        for(i = 0; i<11;i++) Partition.VolumeLabel[i] = dir[dir_entry].Name[i];
2258
                                        Partition.VolumeLabel[11] = '\0'; // terminate string
2258
                                        Partition.VolumeLabel[11] = '\0'; // terminate string
2259
                                        file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
2259
                                        file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
2260
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster
2260
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster
2261
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
2261
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
2262
                                        file->SectorOfCurrCluster = 0;
2262
                                        file->SectorOfCurrCluster = 0;
2263
                                        file->ByteOfCurrSector = 0;
2263
                                        file->ByteOfCurrSector = 0;
2264
                                        file->DirectorySector = curr_sector; // current sector
2264
                                        file->DirectorySector = curr_sector; // current sector
2265
                                        file->DirectoryIndex  = dir_entry; // current direntry in current sector
2265
                                        file->DirectoryIndex  = dir_entry; // current direntry in current sector
2266
                                        file->Size = dir[dir_entry].Size;
2266
                                        file->Size = dir[dir_entry].Size;
2267
                                        dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
2267
                                        dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
2268
                                        pVolumeLabel =  Partition.VolumeLabel;
2268
                                        pVolumeLabel =  Partition.VolumeLabel;
2269
                        } // end of first byte of name check
2269
                        } // end of first byte of name check
2270
                }
2270
                }
2271
                dir_sector++; // search next sector
2271
                dir_sector++; // search next sector
2272
        // stop if we reached the end of the cluster or the end of the root dir
2272
        // stop if we reached the end of the cluster or the end of the root dir
2273
        }while((dir_sector < max_dir_sector) && (!pVolumeLabel));
2273
        }while((dir_sector < max_dir_sector) && (!pVolumeLabel));
2274
 
2274
 
2275
        UnlockFilePointer(file);
2275
        UnlockFilePointer(file);
2276
        return(pVolumeLabel);
2276
        return(pVolumeLabel);
2277
}
2277
}
2278
 
2278
 
2279
 
2279
 
2280
/********************************************************************************************************************************************/
2280
/********************************************************************************************************************************************/
2281
/*      Function:               u8 FindItem(Find_t);                                                                                                                                                                                                    */
2281
/*      Function:               u8 FindItem(Find_t);                                                                                                                                                                                                    */
2282
/*                                                                                                                                                                                                                                                                                      */
2282
/*                                                                                                                                                                                                                                                                                      */
2283
/*      Description:    This function looks for the item specified by global structure FindElement in the actual directory                                      */
2283
/*      Description:    This function looks for the item specified by global structure FindElement in the actual directory                                      */
2284
/*                                                                                                                                                                                                                                                              */
2284
/*                                                                                                                                                                                                                                                              */
2285
/*                                                                                                                                                                                                                                                                                      */
2285
/*                                                                                                                                                                                                                                                                                      */
2286
/*      Returnvalue:    TRUE if an matching element was found                                                                                                                                                                   */
2286
/*      Returnvalue:    TRUE if an matching element was found                                                                                                                                                                   */
2287
/********************************************************************************************************************************************/
2287
/********************************************************************************************************************************************/
2288
 
2288
 
2289
u8 FindItem(Find_t *findelement)
2289
u8 FindItem(Find_t *findelement)
2290
{
2290
{
2291
        u16             index = 0;
2291
        u16             index = 0;
2292
        u16             max_dir_sector = 0;
2292
        u16             max_dir_sector = 0;
2293
        u16     end_of_directory_not_reached = 1;                                                                               // the directory has been read completely without a result.
2293
        u16     end_of_directory_not_reached = 1;                                                                               // the directory has been read completely without a result.
2294
        u8              i = 0;
2294
        u8              i = 0;
2295
        u8              readpointer = 0;
2295
        u8              readpointer = 0;
2296
        u8              writepointer = 0;
2296
        u8              writepointer = 0;
2297
        u8              retvalue = 0;
2297
        u8              retvalue = 0;
2298
        DirEntry_t      *DirectoryEntry;
2298
        DirEntry_t      *DirectoryEntry;
2299
        File_t  file;
2299
        File_t  file;
2300
        SD_Result_t res=0;
2300
        SD_Result_t res=0;
2301
 
2301
 
2302
        file.FirstSectorOfCurrCluster   = findelement->fp.FirstSectorOfCurrCluster;
2302
        file.FirstSectorOfCurrCluster   = findelement->fp.FirstSectorOfCurrCluster;
2303
        file.SectorOfCurrCluster        = findelement->fp.SectorOfCurrCluster;
2303
        file.SectorOfCurrCluster        = findelement->fp.SectorOfCurrCluster;
2304
        index                                                   = findelement->fp.DirectoryIndex;
2304
        index                                                   = findelement->fp.DirectoryIndex;
2305
 
2305
 
2306
        // within the root directory area we can read sectors sequentially until the end of this area
2306
        // within the root directory area we can read sectors sequentially until the end of this area
2307
        if((Partition.FirstRootDirSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster < Partition.FirstDataSector))
2307
        if((Partition.FirstRootDirSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster < Partition.FirstDataSector))
2308
        {
2308
        {
2309
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
2309
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
2310
        }
2310
        }
2311
        // within the data clusters we can read sectors sequentially only within the cluster
2311
        // within the data clusters we can read sectors sequentially only within the cluster
2312
        else if((Partition.FirstDataSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster <= Partition.LastDataSector))
2312
        else if((Partition.FirstDataSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster <= Partition.LastDataSector))
2313
        {
2313
        {
2314
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
2314
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
2315
        }
2315
        }
2316
 
2316
 
2317
        do
2317
        do
2318
        {       // search the next 16 rootentries in this sector of the roordirectory.
2318
        {       // search the next 16 rootentries in this sector of the roordirectory.
2319
                res = SDC_GetSector(((u32) file.FirstSectorOfCurrCluster + (u32)file.SectorOfCurrCluster), file.Cache);                                         // Read the Rootdirectory.
2319
                res = SDC_GetSector(((u32) file.FirstSectorOfCurrCluster + (u32)file.SectorOfCurrCluster), file.Cache);                                         // Read the Rootdirectory.
2320
                if(res != SD_SUCCESS)
2320
                if(res != SD_SUCCESS)
2321
                {
2321
                {
2322
                        Fat16_Deinit();
2322
                        Fat16_Deinit();
2323
                        return(0);
2323
                        return(0);
2324
                }
2324
                }
2325
 
2325
 
2326
                DirectoryEntry = (DirEntry_t *)file.Cache;
2326
                DirectoryEntry = (DirEntry_t *)file.Cache;
2327
 
2327
 
2328
                while((!retvalue)&&(index < 16))
2328
                while((!retvalue)&&(index < 16))
2329
                {
2329
                {
2330
                        i = 0;
2330
                        i = 0;
2331
                        if( (u8)DirectoryEntry[index].Name[0] != SLOT_DELETED)          // ignore deleted items.
2331
                        if( (u8)DirectoryEntry[index].Name[0] != SLOT_DELETED)          // ignore deleted items.
2332
                        {
2332
                        {
2333
                                while((i <= 10) && ( (DirectoryEntry[index].Name[i] == findelement->searchstring[i]) || (findelement->searchstring[i] == '*') || findelement->searchstring[i] == '?'))
2333
                                while((i <= 10) && ( (DirectoryEntry[index].Name[i] == findelement->searchstring[i]) || (findelement->searchstring[i] == '*') || findelement->searchstring[i] == '?'))
2334
                                {
2334
                                {
2335
                                        i++;
2335
                                        i++;
2336
                                }
2336
                                }
2337
                        }
2337
                        }
2338
                        if((DirectoryEntry[index].Attribute & 0x30) && (DirectoryEntry[index].Attribute & findelement->attribmask) && (i == 11))
2338
                        if((DirectoryEntry[index].Attribute & 0x30) && (DirectoryEntry[index].Attribute & findelement->attribmask) && (i == 11))
2339
                        {
2339
                        {
2340
                /* initialize the namestring with 0 */
2340
                /* initialize the namestring with 0 */
2341
                        for(i = 0; i < 12; i++) findelement->name[i] = 0;
2341
                        for(i = 0; i < 12; i++) findelement->name[i] = 0;
2342
                for(readpointer = 0; readpointer <= 10; readpointer++)
2342
                for(readpointer = 0; readpointer <= 10; readpointer++)
2343
                                {
2343
                                {
2344
                                        if((DirectoryEntry[index].Name[readpointer] != ' ') && (readpointer!=8))
2344
                                        if((DirectoryEntry[index].Name[readpointer] != ' ') && (readpointer!=8))
2345
                                        {
2345
                                        {
2346
                                                findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer];      // copy the name of the item found to the find_structure.
2346
                                                findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer];      // copy the name of the item found to the find_structure.
2347
                                                writepointer++;
2347
                                                writepointer++;
2348
                                        }
2348
                                        }
2349
                                        else
2349
                                        else
2350
                                        {
2350
                                        {
2351
                                                if(DirectoryEntry[index].Attribute == ATTR_ARCHIVE)
2351
                                                if(DirectoryEntry[index].Attribute == ATTR_ARCHIVE)
2352
                                                {
2352
                                                {
2353
                                        if(readpointer < 8) readpointer = 8;
2353
                                        if(readpointer < 8) readpointer = 8;
2354
                                        if(DirectoryEntry[index].Name[readpointer] != ' ')
2354
                                        if(DirectoryEntry[index].Name[readpointer] != ' ')
2355
                                        {
2355
                                        {
2356
                                        findelement->name[writepointer] = '.';                                                  // then seperate the name and the extension by a '.' at index 8.
2356
                                        findelement->name[writepointer] = '.';                                                  // then seperate the name and the extension by a '.' at index 8.
2357
                                        writepointer++;
2357
                                        writepointer++;
2358
                                        findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer];      // copy the name of the item found to the find_structure.
2358
                                        findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer];      // copy the name of the item found to the find_structure.
2359
                                        writepointer++;
2359
                                        writepointer++;
2360
                                        }
2360
                                        }
2361
                                            else break;
2361
                                            else break;
2362
                                                }
2362
                                                }
2363
                            else break;
2363
                            else break;
2364
                        }
2364
                        }
2365
                                }
2365
                                }
2366
                                findelement->fp.FirstSectorOfFirstCluster = (u32) DirectoryEntry[index].StartCluster;
2366
                                findelement->fp.FirstSectorOfFirstCluster = (u32) DirectoryEntry[index].StartCluster;
2367
                                findelement->fp.DirectoryIndex   = index;
2367
                                findelement->fp.DirectoryIndex   = index;
2368
                                findelement->fp.FirstSectorOfCurrCluster   = file.FirstSectorOfCurrCluster;
2368
                                findelement->fp.FirstSectorOfCurrCluster   = file.FirstSectorOfCurrCluster;
2369
                                findelement->fp.DirectorySector  = (file.FirstSectorOfCurrCluster + file.SectorOfCurrCluster);
2369
                                findelement->fp.DirectorySector  = (file.FirstSectorOfCurrCluster + file.SectorOfCurrCluster);
2370
                                findelement->fp.SectorOfCurrCluster      = file.SectorOfCurrCluster;
2370
                                findelement->fp.SectorOfCurrCluster      = file.SectorOfCurrCluster;
2371
                findelement->fp.Size            = DirectoryEntry[index].Size;
2371
                findelement->fp.Size            = DirectoryEntry[index].Size;
2372
                                findelement->fp.Attribute               = DirectoryEntry[index].Attribute;
2372
                                findelement->fp.Attribute               = DirectoryEntry[index].Attribute;
2373
                retvalue = 1;
2373
                retvalue = 1;
2374
                        }
2374
                        }
2375
                        /* search the next sector */
2375
                        /* search the next sector */
2376
                        index++;
2376
                        index++;
2377
                }
2377
                }
2378
                /* this sector has been searched but we havn't found what we are looking for. Therefore we have to find the next sector */
2378
                /* this sector has been searched but we havn't found what we are looking for. Therefore we have to find the next sector */
2379
                if(!retvalue)                                                                                                                           // file not found in this sector so take next sector.
2379
                if(!retvalue)                                                                                                                           // file not found in this sector so take next sector.
2380
                {
2380
                {
2381
                        /* in the next sector we start looking for the specified entry beginning at index 0 */
2381
                        /* in the next sector we start looking for the specified entry beginning at index 0 */
2382
                        index = 0;
2382
                        index = 0;
2383
                        /* there are still sectors to be read within the cluster or within the linear addresspace of the rootdirectory */
2383
                        /* there are still sectors to be read within the cluster or within the linear addresspace of the rootdirectory */
2384
                        if(file.SectorOfCurrCluster < max_dir_sector-1)  file.SectorOfCurrCluster++;
2384
                        if(file.SectorOfCurrCluster < max_dir_sector-1)  file.SectorOfCurrCluster++;
2385
                        /* if we are looking for an directoryentry outside the rootdirectory and have reached the end of the cluster we have to get the next one */
2385
                        /* if we are looking for an directoryentry outside the rootdirectory and have reached the end of the cluster we have to get the next one */
2386
                        else if(Partition.FirstDataSector <= file.FirstSectorOfCurrCluster)
2386
                        else if(Partition.FirstDataSector <= file.FirstSectorOfCurrCluster)
2387
                        {
2387
                        {
2388
                                end_of_directory_not_reached = GetNextCluster(&file);
2388
                                end_of_directory_not_reached = GetNextCluster(&file);
2389
                        }
2389
                        }
2390
                        // within the rootdirectory we abort searching for elements after the maximun number of possible rootentries has beensearched
2390
                        // within the rootdirectory we abort searching for elements after the maximun number of possible rootentries has beensearched
2391
                        else
2391
                        else
2392
                        {
2392
                        {
2393
                                end_of_directory_not_reached = 0;
2393
                                end_of_directory_not_reached = 0;
2394
                        }
2394
                        }
2395
                }
2395
                }
2396
        }
2396
        }
2397
        while((end_of_directory_not_reached) && (!retvalue) );
2397
        while((end_of_directory_not_reached) && (!retvalue) );
2398
 
2398
 
2399
        return(retvalue);
2399
        return(retvalue);
2400
}
2400
}
2401
 
2401
 
2402
 
2402
 
2403
 
2403
 
2404
 
2404
 
2405
/********************************************************************************************************************************************/
2405
/********************************************************************************************************************************************/
2406
/*      Function:               findnext_(Find_t *);                                                                                                                                                                                                                    */
2406
/*      Function:               findnext_(Find_t *);                                                                                                                                                                                                                    */
2407
/*                                                                                                                                                                                                                                                                                      */
2407
/*                                                                                                                                                                                                                                                                                      */
2408
/*      Description:    This function looks for the next item in the specified directory with a matching filename and fileattributes specified  */
2408
/*      Description:    This function looks for the next item in the specified directory with a matching filename and fileattributes specified  */
2409
/*                  by function findfirst()                                                                                                                                                                                                     */
2409
/*                  by function findfirst()                                                                                                                                                                                                     */
2410
/*                                                                                                                                                                                                                                                                                      */
2410
/*                                                                                                                                                                                                                                                                                      */
2411
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2411
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2412
/********************************************************************************************************************************************/
2412
/********************************************************************************************************************************************/
2413
u8 findnext_(Find_t * findelement)
2413
u8 findnext_(Find_t * findelement)
2414
{
2414
{
2415
        u8 itemfound = 0;
2415
        u8 itemfound = 0;
2416
        u8 index = 0;
2416
        u8 index = 0;
2417
 
2417
 
2418
        findelement->fp.DirectoryIndex++;
2418
        findelement->fp.DirectoryIndex++;
2419
 
2419
 
2420
        /* before we start searching an element we clear the complete namestring within the structure FindElement */
2420
        /* before we start searching an element we clear the complete namestring within the structure FindElement */
2421
        for(index = 0; index < 11; index++) findelement->name[index] = 0;
2421
        for(index = 0; index < 11; index++) findelement->name[index] = 0;
2422
 
2422
 
2423
        if(FindItem(findelement))
2423
        if(FindItem(findelement))
2424
        {
2424
        {
2425
                itemfound = 1;
2425
                itemfound = 1;
2426
        }
2426
        }
2427
 
2427
 
2428
        return(itemfound);
2428
        return(itemfound);
2429
}
2429
}
2430
 
2430
 
2431
 
2431
 
2432
 
2432
 
2433
/********************************************************************************************************************************************/
2433
/********************************************************************************************************************************************/
2434
/*      Function:               findfirst_(s8* filename, u8 attribmask, Find_t *);                                                                                                                                              */
2434
/*      Function:               findfirst_(s8* filename, u8 attribmask, Find_t *);                                                                                                                                              */
2435
/*                                                                                                                                                                                                                                                                                      */
2435
/*                                                                                                                                                                                                                                                                                      */
2436
/*      Description:    This function looks for the first item in the specified directory with a matching filename and fileattributes                   */
2436
/*      Description:    This function looks for the first item in the specified directory with a matching filename and fileattributes                   */
2437
/*                                      The filename of the element found is transformed from 8.3 to a string                                                                                                   */
2437
/*                                      The filename of the element found is transformed from 8.3 to a string                                                                                                   */
2438
/*                                                                                                                                                                                                                                                                                      */
2438
/*                                                                                                                                                                                                                                                                                      */
2439
/*                                                                                                                                                                                                                                                                                      */
2439
/*                                                                                                                                                                                                                                                                                      */
2440
/*      Returnvalue:    (1) if Element was found. (0) if no valid element was found                                                                                                                     */
2440
/*      Returnvalue:    (1) if Element was found. (0) if no valid element was found                                                                                                                     */
2441
/********************************************************************************************************************************************/
2441
/********************************************************************************************************************************************/
2442
u8 findfirst_(const s8* name, u8 attribmask, Find_t *findelement)
2442
u8 findfirst_(const s8* name, u8 attribmask, Find_t *findelement)
2443
{
2443
{
2444
        u8 itemfound = 0;
2444
        u8 itemfound = 0;
2445
        u8 index = 0;
2445
        u8 index = 0;
2446
 
2446
 
2447
        /* initialize the FindElement structure */
2447
        /* initialize the FindElement structure */
2448
        findelement->fp.FirstSectorOfFirstCluster = 0;                                  // First sector of the first cluster of the file.
2448
        findelement->fp.FirstSectorOfFirstCluster = 0;                                  // First sector of the first cluster of the file.
2449
        findelement->fp.FirstSectorOfCurrCluster = Partition.CurrentWorkingDirectory;   // First sector of the cluster which is edited at the moment.
2449
        findelement->fp.FirstSectorOfCurrCluster = Partition.CurrentWorkingDirectory;   // First sector of the cluster which is edited at the moment.
2450
        findelement->fp.SectorOfCurrCluster = 0;                                                // The sector within the current cluster.
2450
        findelement->fp.SectorOfCurrCluster = 0;                                                // The sector within the current cluster.
2451
        findelement->fp.ByteOfCurrSector = 0;                                                   // The byte location within the current sector.
2451
        findelement->fp.ByteOfCurrSector = 0;                                                   // The byte location within the current sector.
2452
        findelement->fp.Size = 0;                                                                               // The size of the opend file in bytes.
2452
        findelement->fp.Size = 0;                                                                               // The size of the opend file in bytes.
2453
        findelement->fp.Position = 0;                                                                   // Pointer to a character within the file 0 < fileposition < filesize
2453
        findelement->fp.Position = 0;                                                                   // Pointer to a character within the file 0 < fileposition < filesize
2454
        findelement->fp.DirectorySector = 0;                                                    // the sectorposition where the directoryentry has been made.
2454
        findelement->fp.DirectorySector = 0;                                                    // the sectorposition where the directoryentry has been made.
2455
        findelement->fp.DirectoryIndex = 0;                                                             // The index to the directoryentry within the specified sector.
2455
        findelement->fp.DirectoryIndex = 0;                                                             // The index to the directoryentry within the specified sector.
2456
        findelement->attribfilter = 0;
2456
        findelement->attribfilter = 0;
2457
        findelement->attribmask = attribmask;
2457
        findelement->attribmask = attribmask;
2458
        findelement->searchstring[0] = 0;                                                               // terminate string at the begin (=NULL)
2458
        findelement->searchstring[0] = 0;                                                               // terminate string at the begin (=NULL)
2459
 
2459
 
2460
        // bring it to the 8.3 format
2460
        // bring it to the 8.3 format
2461
        if(NULL == SeperateFormatedDirName(name, findelement->searchstring)) return(0);
2461
        if(NULL == SeperateFormatedDirName(name, findelement->searchstring)) return(0);
2462
 
2462
 
2463
        //process the wildcards (*). After an * all following character are wildcards to
2463
        //process the wildcards (*). After an * all following character are wildcards to
2464
        for(index = 0;index < 8;index++)
2464
        for(index = 0;index < 8;index++)
2465
        {
2465
        {
2466
                /* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */
2466
                /* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */
2467
                if(findelement->searchstring[index] == '*')
2467
                if(findelement->searchstring[index] == '*')
2468
                {
2468
                {
2469
                        /*  */
2469
                        /*  */
2470
                        while(++index < 8) findelement->searchstring[index] = '*';
2470
                        while(++index < 8) findelement->searchstring[index] = '*';
2471
                }
2471
                }
2472
        }
2472
        }
2473
        for(index = 8;index < 11;index++)
2473
        for(index = 8;index < 11;index++)
2474
        {
2474
        {
2475
                /* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */
2475
                /* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */
2476
                if(findelement->searchstring[index] == '*')
2476
                if(findelement->searchstring[index] == '*')
2477
                {
2477
                {
2478
                        /*  */
2478
                        /*  */
2479
                        while(++index < 11) findelement->searchstring[index] = '*';
2479
                        while(++index < 11) findelement->searchstring[index] = '*';
2480
                }
2480
                }
2481
        }
2481
        }
2482
 
2482
 
2483
        /* the value of ...DirectoryIndex will be incremented in findnext_() thererfore it has to be decremented in findfirst_() */
2483
        /* the value of ...DirectoryIndex will be incremented in findnext_() thererfore it has to be decremented in findfirst_() */
2484
        findelement->fp.DirectoryIndex--;
2484
        findelement->fp.DirectoryIndex--;
2485
        /* now lets search for the item within the direcory */
2485
        /* now lets search for the item within the direcory */
2486
        itemfound = findnext_(findelement);
2486
        itemfound = findnext_(findelement);
2487
 
2487
 
2488
        return(itemfound);
2488
        return(itemfound);
2489
}
2489
}
2490
 
2490
 
2491
/********************************************************************************************************************************************/
2491
/********************************************************************************************************************************************/
2492
/* Function:    s8 *GetSubDirectory (s8 *dirpath, s8 *directory)                                                                                                                                                        */
2492
/* Function:    s8 *GetSubDirectory (s8 *dirpath, s8 *directory)                                                                                                                                                        */
2493
/*                                                                                                                                                                                                                                                                                      */
2493
/*                                                                                                                                                                                                                                                                                      */
2494
/* Description: this function parses the dirpath string and copies the first directroy name to the location pointed to by directroy                     */
2494
/* Description: this function parses the dirpath string and copies the first directroy name to the location pointed to by directroy                     */
2495
/*                                                                                                                                                                                                                                                                                      */
2495
/*                                                                                                                                                                                                                                                                                      */
2496
/*                                                                                                                                                                                                                                                                                      */
2496
/*                                                                                                                                                                                                                                                                                      */
2497
/* returnvalue:  a pointer to the beginning of the next subdirectory or NULL                                                                                                                            */
2497
/* returnvalue:  a pointer to the beginning of the next subdirectory or NULL                                                                                                                            */
2498
/********************************************************************************************************************************************/
2498
/********************************************************************************************************************************************/
2499
s8 * GetSubDirectory(s8 *dirpath, s8 *directory)
2499
s8 * GetSubDirectory(s8 *dirpath, s8 *directory)
2500
{
2500
{
2501
   s8 *cptr = dirpath;
2501
   s8 *cptr = dirpath;
2502
   s8 *dptr = directory;
2502
   s8 *dptr = directory;
2503
   s8 *remainingpath = NULL;
2503
   s8 *remainingpath = NULL;
2504
 
2504
 
2505
   /* if the first character of the path is an '/' we go to the next character */
2505
   /* if the first character of the path is an '/' we go to the next character */
2506
   if(*cptr == '/') cptr++;
2506
   if(*cptr == '/') cptr++;
2507
   /* search end of path or subdirectory*/
2507
   /* search end of path or subdirectory*/
2508
   while((*cptr != 0) && (*cptr != '/'))
2508
   while((*cptr != 0) && (*cptr != '/'))
2509
   {
2509
   {
2510
      *dptr = *cptr;   // copy to directory string buffer
2510
      *dptr = *cptr;   // copy to directory string buffer
2511
       dptr++;
2511
       dptr++;
2512
       cptr++;
2512
       cptr++;
2513
   }
2513
   }
2514
   if(*cptr!=0) remainingpath = ++cptr; // return pointer to remaining path string
2514
   if(*cptr!=0) remainingpath = ++cptr; // return pointer to remaining path string
2515
   *dptr = 0; // terminate directory name string
2515
   *dptr = 0; // terminate directory name string
2516
 
2516
 
2517
   return(remainingpath);
2517
   return(remainingpath);
2518
}
2518
}
2519
 
2519
 
2520
 
2520
 
2521
/********************************************************************************************************************************************/
2521
/********************************************************************************************************************************************/
2522
/*      Function:               u8 chdir_(s8* const path);                                                                                                                                                                                              */
2522
/*      Function:               u8 chdir_(s8* const path);                                                                                                                                                                                              */
2523
/*                                                                                                                                                                                                                                                                                      */
2523
/*                                                                                                                                                                                                                                                                                      */
2524
/*      Description:    This function changes the current working directory to the directory specified by the filepath                                                  */
2524
/*      Description:    This function changes the current working directory to the directory specified by the filepath                                                  */
2525
/*                  by function findfirst()                                                                                                                                                                                                     */
2525
/*                  by function findfirst()                                                                                                                                                                                                     */
2526
/*                                                                                                                                                                                                                                                                                      */
2526
/*                                                                                                                                                                                                                                                                                      */
2527
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2527
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2528
/********************************************************************************************************************************************/
2528
/********************************************************************************************************************************************/
2529
 
2529
 
2530
u8 chdir_(s8* const path)
2530
u8 chdir_(s8* const path)
2531
{
2531
{
2532
        u8              retvalue = 0;                                   // the value returned by this function
2532
        u8              retvalue = 0;                                   // the value returned by this function
2533
        u32     ultemp = 0;                                             // temp. variable
2533
        u32     ultemp = 0;                                             // temp. variable
2534
        s8      *dirpath = path;                                // pointer to the remaining path string
2534
        s8      *dirpath = path;                                // pointer to the remaining path string
2535
        s8      dirname[64];                                    // a buffer containing the name of the subdirectory we are actually looking for
2535
        s8      dirname[64];                                    // a buffer containing the name of the subdirectory we are actually looking for
2536
        Find_t  fe;                                                             // The findelement needed for function findfirst to find the subdirectory entry
2536
        Find_t  fe;                                                             // The findelement needed for function findfirst to find the subdirectory entry
2537
        s8              tp[256];                                                // temporarily we remember the actual path until the operation has finished successfully
2537
        s8              tp[256];                                                // temporarily we remember the actual path until the operation has finished successfully
2538
        u32     tcwd = 0;                                               // temporarily we remember the actual current working directory
2538
        u32     tcwd = 0;                                               // temporarily we remember the actual current working directory
2539
 
2539
 
2540
        if(path == NULL) return(0);                             // return immediately of no path is given
2540
        if(path == NULL) return(0);                             // return immediately of no path is given
2541
        // correct filepath formatting
2541
        // correct filepath formatting
2542
        Slashing_Path(path);
2542
        Slashing_Path(path);
2543
 
2543
 
2544
        // lets remember the actual path and correspondig directory sector
2544
        // lets remember the actual path and correspondig directory sector
2545
        strcpy(tp, Partition.PathToCwd);
2545
        strcpy(tp, Partition.PathToCwd);
2546
        tcwd = Partition.CurrentWorkingDirectory;
2546
        tcwd = Partition.CurrentWorkingDirectory;
2547
 
2547
 
2548
        if(path[0] == '/') // if the path is absolute we begin at the rootdirectory
2548
        if(path[0] == '/') // if the path is absolute we begin at the rootdirectory
2549
        {
2549
        {
2550
                strcpy(Partition.PathToCwd, "/");
2550
                strcpy(Partition.PathToCwd, "/");
2551
                Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
2551
                Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
2552
        }
2552
        }
2553
        // parse through all the subdirectories within the path
2553
        // parse through all the subdirectories within the path
2554
        do
2554
        do
2555
        {
2555
        {
2556
                dirpath = GetSubDirectory(dirpath, dirname); // get the name of the subdirectory we are looking for and the remainig path
2556
                dirpath = GetSubDirectory(dirpath, dirname); // get the name of the subdirectory we are looking for and the remainig path
2557
                if(dirname[0] == 0)             // if no directory name is available 
2557
                if(dirname[0] == 0)             // if no directory name is available 
2558
                {
2558
                {
2559
                        retvalue = 1;                   // we are done
2559
                        retvalue = 1;                   // we are done
2560
                        break;                                  // break the loop
2560
                        break;                                  // break the loop
2561
                }      
2561
                }      
2562
                // search for the next subdirectory within the path
2562
                // search for the next subdirectory within the path
2563
                if(findfirst_(dirname, ATTR_SUBDIRECTORY, &fe))
2563
                if(findfirst_(dirname, ATTR_SUBDIRECTORY, &fe))
2564
                {
2564
                {
2565
                        // we try to change into the directory "..". Now we have to delete the last direntry from the path
2565
                        // we try to change into the directory "..". Now we have to delete the last direntry from the path
2566
                        if(strcmp(dirname, "..") == 0) CWDPath_Pop();
2566
                        if(strcmp(dirname, "..") == 0) CWDPath_Pop();
2567
                        // we try to change into the actual directory so there's nothing todo
2567
                        // we try to change into the actual directory so there's nothing todo
2568
                        else if(dirname[0] == '.') return(1);
2568
                        else if(dirname[0] == '.') return(1);
2569
                        // otherwise we append the name of the directory we are changing in to the path
2569
                        // otherwise we append the name of the directory we are changing in to the path
2570
                        else CWDPath_Push(dirname);
2570
                        else CWDPath_Push(dirname);
2571
                        // The startcluster within an directory entry specifies the position within the fat where the file or directory starts
2571
                        // The startcluster within an directory entry specifies the position within the fat where the file or directory starts
2572
                        ultemp = (u32) fe.fp.FirstSectorOfFirstCluster;
2572
                        ultemp = (u32) fe.fp.FirstSectorOfFirstCluster;
2573
                        // do we have to change into the rootdirectory?
2573
                        // do we have to change into the rootdirectory?
2574
                        if(ultemp)
2574
                        if(ultemp)
2575
                        {
2575
                        {
2576
                                // the first 2 entries are reserved for '.' and '..' 
2576
                                // the first 2 entries are reserved for '.' and '..' 
2577
                                ultemp -= 2;
2577
                                ultemp -= 2;
2578
                                // now we have to transform the position within the fat into the corrosponding sectoraddress relative to the beginning of the datasection of the active partition
2578
                                // now we have to transform the position within the fat into the corrosponding sectoraddress relative to the beginning of the datasection of the active partition
2579
                                ultemp *= Partition.SectorsPerCluster;
2579
                                ultemp *= Partition.SectorsPerCluster;
2580
                                // at least we make the sectoraddress absolute by adding the relative address to the beginning of the datasection of the active partition
2580
                                // at least we make the sectoraddress absolute by adding the relative address to the beginning of the datasection of the active partition
2581
                                ultemp += Partition.FirstDataSector;
2581
                                ultemp += Partition.FirstDataSector;
2582
                                // the cwd now points to the specified directory
2582
                                // the cwd now points to the specified directory
2583
                                Partition.CurrentWorkingDirectory = ultemp;
2583
                                Partition.CurrentWorkingDirectory = ultemp;
2584
                        }
2584
                        }
2585
                        else // (=0) root directory 
2585
                        else // (=0) root directory 
2586
                        {
2586
                        {
2587
                                // the cwd now points to the rootdirectory
2587
                                // the cwd now points to the rootdirectory
2588
                                Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
2588
                                Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
2589
                        }
2589
                        }
2590
                        retvalue = 1;
2590
                        retvalue = 1;
2591
                }
2591
                }
2592
                else // subdirectory not found
2592
                else // subdirectory not found
2593
                {
2593
                {
2594
                        retvalue = 0;           // no success tracing along the given directory chain
2594
                        retvalue = 0;           // no success tracing along the given directory chain
2595
                        break;                          // break the loop
2595
                        break;                          // break the loop
2596
                }
2596
                }
2597
        }
2597
        }
2598
        while(dirpath != NULL);  // do this until all subdirectories have been found
2598
        while(dirpath != NULL);  // do this until all subdirectories have been found
2599
 
2599
 
2600
        // if we could not change to the specified directory we restore the actual path 
2600
        // if we could not change to the specified directory we restore the actual path 
2601
        if(!retvalue)
2601
        if(!retvalue)
2602
        {
2602
        {
2603
                Partition.CurrentWorkingDirectory = tcwd;
2603
                Partition.CurrentWorkingDirectory = tcwd;
2604
                strcpy(Partition.PathToCwd, tp);
2604
                strcpy(Partition.PathToCwd, tp);
2605
        }
2605
        }
2606
        return(retvalue);
2606
        return(retvalue);
2607
}
2607
}
2608
 
2608
 
2609
 
2609
 
2610
/********************************************************************************************************************************************/
2610
/********************************************************************************************************************************************/
2611
/*      Function:               u8 rmdir_(s8* dname);                                                                                                                                                                                                           */
2611
/*      Function:               u8 rmdir_(s8* dname);                                                                                                                                                                                                           */
2612
/*                                                                                                                                                                                                                                                                                      */
2612
/*                                                                                                                                                                                                                                                                                      */
2613
/*      Description:    This function deletes the directory with the specified filename from the filesystem                                                                             */
2613
/*      Description:    This function deletes the directory with the specified filename from the filesystem                                                                             */
2614
/*                                                                                                                                                                                                                                      */
2614
/*                                                                                                                                                                                                                                      */
2615
/*                                                                                                                                                                                                                                                                                      */
2615
/*                                                                                                                                                                                                                                                                                      */
2616
/*      Returnvalue:    1 : specified directory deleted succesfully 0: specified directory not found                                                                                    */
2616
/*      Returnvalue:    1 : specified directory deleted succesfully 0: specified directory not found                                                                                    */
2617
/********************************************************************************************************************************************/
2617
/********************************************************************************************************************************************/
2618
 
2618
 
2619
u8 rmdir_(s8* const dirpath)
2619
u8 rmdir_(s8* const dirpath)
2620
{
2620
{
2621
        u8 retvalue = 0;
2621
        u8 retvalue = 0;
2622
        Find_t fe;
2622
        Find_t fe;
2623
        u32 cwd;
2623
        u32 cwd;
2624
        s8 path[256];
2624
        s8 path[256];
2625
        s8 *dn;
2625
        s8 *dn;
2626
        s8 *dp;
2626
        s8 *dp;
2627
 
2627
 
2628
        if(dirpath == NULL) return(0);
2628
        if(dirpath == NULL) return(0);
2629
        // correct filepath formatting
2629
        // correct filepath formatting
2630
        Slashing_Path(dirpath);
2630
        Slashing_Path(dirpath);
2631
 
2631
 
2632
    // remember the current workingdirectory
2632
    // remember the current workingdirectory
2633
        cwd = Partition.CurrentWorkingDirectory;
2633
        cwd = Partition.CurrentWorkingDirectory;
2634
 
2634
 
2635
        // create local copy of the path
2635
        // create local copy of the path
2636
        strcpy(path, dirpath);
2636
        strcpy(path, dirpath);
2637
        // seperate the filepath from the last directory within the path that shall be deleted
2637
        // seperate the filepath from the last directory within the path that shall be deleted
2638
        // start searching for the name of the directory to be deleted from the beginning of the path
2638
        // start searching for the name of the directory to be deleted from the beginning of the path
2639
        dn = path;
2639
        dn = path;
2640
        dp = path;
2640
        dp = path;
2641
        // search the complete path until the end of the string is found
2641
        // search the complete path until the end of the string is found
2642
        while(*dn != 0) dn++;
2642
        while(*dn != 0) dn++;
2643
        // now check if the last directory whithin the path is terminated with an '/' and remove the '/' from the directoryname
2643
        // now check if the last directory whithin the path is terminated with an '/' and remove the '/' from the directoryname
2644
        if(*(dn-1) == '/') *--dn = 0;
2644
        if(*(dn-1) == '/') *--dn = 0;
2645
        // now find the beginning of the last directoryentry
2645
        // now find the beginning of the last directoryentry
2646
        while((*dn != '/') && (dn > path)) dn--;
2646
        while((*dn != '/') && (dn > path)) dn--;
2647
        // beginning of the last directory found
2647
        // beginning of the last directory found
2648
        if(*dn == '/')
2648
        if(*dn == '/')
2649
        {
2649
        {
2650
                // remove the directoryname from the path by terminating the path with 0
2650
                // remove the directoryname from the path by terminating the path with 0
2651
                *dn = 0;
2651
                *dn = 0;
2652
                // the dirname begins 1 character after the terminated path
2652
                // the dirname begins 1 character after the terminated path
2653
                dn++;
2653
                dn++;
2654
        }
2654
        }
2655
        // we couldn't find a path before the directory to be deleted or no directoryname at all
2655
        // we couldn't find a path before the directory to be deleted or no directoryname at all
2656
        else
2656
        else
2657
        {
2657
        {
2658
                // there is no path before the name of the directory to be deleted
2658
                // there is no path before the name of the directory to be deleted
2659
                if(dn == path)
2659
                if(dn == path)
2660
                {
2660
                {
2661
                        // if there is a name of a directory to be deleted?
2661
                        // if there is a name of a directory to be deleted?
2662
                        if(*dn == 0) return(0);
2662
                        if(*dn == 0) return(0);
2663
                        // the directory to be deleted is within the actual directory therefore we don't have to change the directory before deleting the directory
2663
                        // the directory to be deleted is within the actual directory therefore we don't have to change the directory before deleting the directory
2664
                        dp = NULL;
2664
                        dp = NULL;
2665
                }
2665
                }
2666
 
2666
 
2667
        }
2667
        }
2668
        // switch to the directory containing the directory to be deleted if neccessary
2668
        // switch to the directory containing the directory to be deleted if neccessary
2669
        if(dp != NULL)
2669
        if(dp != NULL)
2670
        {
2670
        {
2671
                if(!chdir_(dp)) return(0);
2671
                if(!chdir_(dp)) return(0);
2672
        }
2672
        }
2673
        // now we have to find the specified directory to be deleted
2673
        // now we have to find the specified directory to be deleted
2674
        retvalue = findfirst_(dn, 0xff, &fe);
2674
        retvalue = findfirst_(dn, 0xff, &fe);
2675
        // was the specified directory found?
2675
        // was the specified directory found?
2676
        if(retvalue)
2676
        if(retvalue)
2677
        {
2677
        {
2678
                // before we delete the directory we check if the directory is empty
2678
                // before we delete the directory we check if the directory is empty
2679
                if(chdir_(dn))
2679
                if(chdir_(dn))
2680
                {
2680
                {
2681
                        if(findfirst_("*.*", 0xff, &fe))
2681
                        if(findfirst_("*.*", 0xff, &fe))
2682
                        {
2682
                        {
2683
                                // within an directory that shall be deleted only the entries . and .. are allowed
2683
                                // within an directory that shall be deleted only the entries . and .. are allowed
2684
                                if((strncmp(fe.name, ".", 1) != 0) && (strncmp(fe.name, "..", 2) != 0)) retvalue = 0;
2684
                                if((strncmp(fe.name, ".", 1) != 0) && (strncmp(fe.name, "..", 2) != 0)) retvalue = 0;
2685
                                while(findnext_(&fe))
2685
                                while(findnext_(&fe))
2686
                                {
2686
                                {
2687
                                        if((strncmp(fe.name, ".", 1) != 0) && (strncmp(fe.name, "..", 2) != 0)) retvalue = 0;
2687
                                        if((strncmp(fe.name, ".", 1) != 0) && (strncmp(fe.name, "..", 2) != 0)) retvalue = 0;
2688
                                }
2688
                                }
2689
                        }
2689
                        }
2690
                        chdir_("..");
2690
                        chdir_("..");
2691
                }
2691
                }
2692
                // directory couldn't be entered, is a real file?
2692
                // directory couldn't be entered, is a real file?
2693
                else
2693
                else
2694
                {
2694
                {
2695
                        retvalue = 0;
2695
                        retvalue = 0;
2696
                }
2696
                }
2697
                // specified directory is empty
2697
                // specified directory is empty
2698
                if(retvalue)
2698
                if(retvalue)
2699
                {
2699
                {
2700
                        retvalue = 0;
2700
                        retvalue = 0;
2701
                        // we have modified the result of the findfirst_ operation therefore we have to redo findfirst_ to get detailed infos about the directory entry to be deleted
2701
                        // we have modified the result of the findfirst_ operation therefore we have to redo findfirst_ to get detailed infos about the directory entry to be deleted
2702
                        if(findfirst_(dn, 0xff, &fe))
2702
                        if(findfirst_(dn, 0xff, &fe))
2703
                        {
2703
                        {
2704
                                Debug("found");
2704
                                Debug("found");
2705
                                // try to clear the allocated clusters within the fat
2705
                                // try to clear the allocated clusters within the fat
2706
                                if(DeleteClusterChain(fe.fp.FirstSectorOfFirstCluster))
2706
                                if(DeleteClusterChain(fe.fp.FirstSectorOfFirstCluster))
2707
                                {
2707
                                {
2708
                                        // delete the directoryentry within the specified directory
2708
                                        // delete the directoryentry within the specified directory
2709
                                        if(DeleteDirectoryEntry(&(fe.fp))) retvalue = 1;
2709
                                        if(DeleteDirectoryEntry(&(fe.fp))) retvalue = 1;
2710
                                }
2710
                                }
2711
                        }
2711
                        }
2712
                }
2712
                }
2713
        }
2713
        }
2714
 
2714
 
2715
        // restore the actual path
2715
        // restore the actual path
2716
        Partition.CurrentWorkingDirectory = cwd;
2716
        Partition.CurrentWorkingDirectory = cwd;
2717
 
2717
 
2718
        return(retvalue);
2718
        return(retvalue);
2719
}
2719
}
2720
 
2720
 
2721
 
2721
 
2722
/********************************************************************************************************************************************/
2722
/********************************************************************************************************************************************/
2723
/*      Function:               mkdir_(s8* dirpath);                                                                                                                                                                                                    */
2723
/*      Function:               mkdir_(s8* dirpath);                                                                                                                                                                                                    */
2724
/*                                                                                                                                                                                                                                                                                      */
2724
/*                                                                                                                                                                                                                                                                                      */
2725
/*      Description:    This function creates the directory with the specified pathname in the filesystem                                                                               */
2725
/*      Description:    This function creates the directory with the specified pathname in the filesystem                                                                               */
2726
/*                                                                                                                                                                                                                                      */
2726
/*                                                                                                                                                                                                                                      */
2727
/*                                                                                                                                                                                                                                                                                      */
2727
/*                                                                                                                                                                                                                                                                                      */
2728
/*      Returnvalue:    1 : specified directory created succesfully 0: specified dir exist already                                                                                              */
2728
/*      Returnvalue:    1 : specified directory created succesfully 0: specified dir exist already                                                                                              */
2729
/********************************************************************************************************************************************/
2729
/********************************************************************************************************************************************/
2730
 
2730
 
2731
u8 mkdir_(s8* const dirpath)
2731
u8 mkdir_(s8* const dirpath)
2732
{
2732
{
2733
        u8 retvalue = 0;
2733
        u8 retvalue = 0;
2734
        File_t file;
2734
        File_t file;
2735
 
2735
 
2736
        if(dirpath == NULL) return(0);
2736
        if(dirpath == NULL) return(0);
2737
        // correct filepath formatting
2737
        // correct filepath formatting
2738
        Slashing_Path(dirpath);
2738
        Slashing_Path(dirpath);
2739
        file.FirstSectorOfFirstCluster = SECTOR_UNDEFINED;              // First sector of the first cluster of the file.
2739
        file.FirstSectorOfFirstCluster = SECTOR_UNDEFINED;              // First sector of the first cluster of the file.
2740
        file.FirstSectorOfCurrCluster = SECTOR_UNDEFINED;               // First sector of the cluster which is edited at the moment.
2740
        file.FirstSectorOfCurrCluster = SECTOR_UNDEFINED;               // First sector of the cluster which is edited at the moment.
2741
        file.FirstSectorOfLastCluster = SECTOR_UNDEFINED;               // First sector of the last cluster of the file
2741
        file.FirstSectorOfLastCluster = SECTOR_UNDEFINED;               // First sector of the last cluster of the file
2742
        file.SectorOfCurrCluster = SECTOR_UNDEFINED;                    // The sector within the current cluster.
2742
        file.SectorOfCurrCluster = SECTOR_UNDEFINED;                    // The sector within the current cluster.
2743
        file.ByteOfCurrSector = 0;                                                              // The byte location within the current sector.
2743
        file.ByteOfCurrSector = 0;                                                              // The byte location within the current sector.
2744
        file.Mode = 0;                                                                                  // Mode of fileoperation (read,write)
2744
        file.Mode = 0;                                                                                  // Mode of fileoperation (read,write)
2745
        file.Size = 0;                                                                                  // The size of the opend file in bytes.
2745
        file.Size = 0;                                                                                  // The size of the opend file in bytes.
2746
        file.Position = 0;                                                                              // Pointer to a character within the file 0 < fileposition < filesize
2746
        file.Position = 0;                                                                              // Pointer to a character within the file 0 < fileposition < filesize
2747
        file.DirectorySector = SECTOR_UNDEFINED;                                // the sectorposition where the directoryentry has been made.
2747
        file.DirectorySector = SECTOR_UNDEFINED;                                // the sectorposition where the directoryentry has been made.
2748
        file.DirectoryIndex = 0;                                                                // The index to the directoryentry within the specified sector.
2748
        file.DirectoryIndex = 0;                                                                // The index to the directoryentry within the specified sector.
2749
        file.Attribute = 0;                                                                             // The attribute of the file opened.
2749
        file.Attribute = 0;                                                                             // The attribute of the file opened.
2750
        file.SectorInCache = SECTOR_UNDEFINED;                                  // The last sector read, which is still in the sector cache.
2750
        file.SectorInCache = SECTOR_UNDEFINED;                                  // The last sector read, which is still in the sector cache.
2751
        file.State = FSTATE_USED;                                                               // mark it as used
2751
        file.State = FSTATE_USED;                                                               // mark it as used
2752
        // if directory is not existent
2752
        // if directory is not existent
2753
        if(!FileExist(dirpath, ATTR_SUBDIRECTORY, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, &file))
2753
        if(!FileExist(dirpath, ATTR_SUBDIRECTORY, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, &file))
2754
        {
2754
        {
2755
                retvalue = FileCreate(dirpath, ATTR_SUBDIRECTORY, &file);
2755
                retvalue = FileCreate(dirpath, ATTR_SUBDIRECTORY, &file);
2756
        }
2756
        }
2757
        return(retvalue);
2757
        return(retvalue);
2758
}
2758
}
2759
 
2759
 
2760
 
2760
 
2761
 
2761
 
2762
 
2762
 
2763
 
2763
 
2764
 
2764
 
2765
 
2765
 
2766
 
2766