Subversion Repositories NaviCtrl

Rev

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

Rev 431 Rev 433
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
 
-
 
307
typedef struct
-
 
308
{
-
 
309
        u8      IsValid;                                // 0 means invalid, else valid
-
 
310
        u8      SectorsPerCluster;              // how many sectors does a cluster contain?
-
 
311
        u8      FatCopies;                              // Numbers of copies of the FAT
-
 
312
        u16     MaxRootEntries;                 // Possible number of entries in the root directory.
-
 
313
        u16     SectorsPerFat;                  // how many sectors does a fat16 contain?
-
 
314
        u32 FirstFatSector;                     // sector of the start of the fat
-
 
315
        u32 FirstRootDirSector;         // sector of the rootdirectory
-
 
316
        u32 FirstDataSector;            // sector of the first cluster containing data (cluster2).
-
 
317
        u32 LastDataSector;                     // the last data sector of the partition
-
 
318
        u8  VolumeLabel[12];        // the volume label
-
 
319
        u32     CurrentWorkingDirectory;// A pointer to the directory we are actual using
-
 
320
        s8      PathToCwd[256];                 // a string containing the complete path to the current working directory
-
 
321
}   __attribute__((packed)) Partition_t;
306
 
322
 
307
 
323
Partition_t     Partition;              // Structure holds partition information
308
Partition_t     Partition;              // Structure holds partition information
324
 
309
 
325
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.
326
 
311
 
327
/********************************************************************************************************************************************/
312
/********************************************************************************************************************************************/
328
/*      Function:               s8 *getcwd_(void);                                                                                                                                                                                                              */
313
/*      Function:               s8 *getcwd_(void);                                                                                                                                                                                                              */
329
/*                                                                                                                                                                                                                                                                                      */
314
/*                                                                                                                                                                                                                                                                                      */
330
/*      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                                                                            */
331
/*                                                                                                                                                                                                                                      */
316
/*                                                                                                                                                                                                                                      */
332
/*                                                                                                                                                                                                                                                                                      */
317
/*                                                                                                                                                                                                                                                                                      */
333
/*      Returnvalue:    pointer to the string containing the path to the CWD                                                                                                                                    */
318
/*      Returnvalue:    pointer to the string containing the path to the CWD                                                                                                                                    */
334
/********************************************************************************************************************************************/
319
/********************************************************************************************************************************************/
335
 
320
 
336
s8 *getcwd_(void)
321
s8 *getcwd_(void)
337
{
322
{
338
        return(Partition.PathToCwd);
323
        return(Partition.PathToCwd);
339
}
324
}
340
 
325
 
341
/********************************************************************************************************************************************/
326
/********************************************************************************************************************************************/
342
/*      Function:               void CWDPath_Push(s8* directory);                                                                                                                                                                               */
327
/*      Function:               void CWDPath_Push(s8* directory);                                                                                                                                                                               */
343
/*                                                                                                                                                                                                                                                                                      */
328
/*                                                                                                                                                                                                                                                                                      */
344
/*      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                                                                                  */
345
/*                                                                                                                                                                                                                                      */
330
/*                                                                                                                                                                                                                                      */
346
/*                                                                                                                                                                                                                                                                                      */
331
/*                                                                                                                                                                                                                                                                                      */
347
/*      Returnvalue:    none                                                                                                                                                                                                                                    */
332
/*      Returnvalue:    none                                                                                                                                                                                                                                    */
348
/********************************************************************************************************************************************/
333
/********************************************************************************************************************************************/
349
 
334
 
350
void CWDPath_Push(s8* directory)
335
void CWDPath_Push(s8* directory)
351
{
336
{
352
        // append the name of the directory to the path
337
        // append the name of the directory to the path
353
        strcat(Partition.PathToCwd, directory);
338
        strcat(Partition.PathToCwd, directory);
354
        // append a '/' after the directoryname
339
        // append a '/' after the directoryname
355
        strcat(Partition.PathToCwd, "/");
340
        strcat(Partition.PathToCwd, "/");
356
}
341
}
357
 
342
 
358
/********************************************************************************************************************************************/
343
/********************************************************************************************************************************************/
359
/*      Function:               CWDPath_Pop(void);                                                                                                                                                                                                              */
344
/*      Function:               CWDPath_Pop(void);                                                                                                                                                                                                              */
360
/*                                                                                                                                                                                                                                                                                      */
345
/*                                                                                                                                                                                                                                                                                      */
361
/*      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                                                                                                               */
362
/*                                                                                                                                                                                                                                      */
347
/*                                                                                                                                                                                                                                      */
363
/*                                                                                                                                                                                                                                                                                      */
348
/*                                                                                                                                                                                                                                                                                      */
364
/*      Returnvalue:    none                                                                                                                                                                                                                                    */
349
/*      Returnvalue:    none                                                                                                                                                                                                                                    */
365
/********************************************************************************************************************************************/
350
/********************************************************************************************************************************************/
366
 
351
 
367
void CWDPath_Pop(void)
352
void CWDPath_Pop(void)
368
{
353
{
369
        // 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
370
        s8 * cptr = Partition.PathToCwd;
355
        s8 * cptr = Partition.PathToCwd;
371
        // lets find the end of the path to the cwd
356
        // lets find the end of the path to the cwd
372
        while(*cptr != 0 ) cptr++;
357
        while(*cptr != 0 ) cptr++;
373
        // if the path is terminated with an '/' then remove it
358
        // if the path is terminated with an '/' then remove it
374
        if((*(cptr-1)) == '/') *(cptr-1) = 0;
359
        if((*(cptr-1)) == '/') *(cptr-1) = 0;
375
        // now lets find the beginning of the last directory entry
360
        // now lets find the beginning of the last directory entry
376
        while((*cptr != '/' ) && cptr > Partition.PathToCwd) cptr--;
361
        while((*cptr != '/' ) && cptr > Partition.PathToCwd) cptr--;
377
        // is there one subdirectory left within the path?
362
        // is there one subdirectory left within the path?
378
        if(cptr > Partition.PathToCwd)
363
        if(cptr > Partition.PathToCwd)
379
        {
364
        {
380
                // we delete the direntry by terminating the path with 0
365
                // we delete the direntry by terminating the path with 0
381
                *(cptr+1) = 0;
366
                *(cptr+1) = 0;
382
        }
367
        }
383
        // 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.
384
        else
369
        else
385
        {
370
        {
386
                *cptr = '/';
371
                *cptr = '/';
387
                *(cptr+1) = 0;
372
                *(cptr+1) = 0;
388
        }
373
        }
389
}
374
}
390
 
375
 
391
/****************************************************************************************************************************************/
376
/****************************************************************************************************************************************/
392
/*      Function:               FileDate(DateTime_t *);                                                                                                                                                                                         */
377
/*      Function:               FileDate(DateTime_t *);                                                                                                                                                                                         */
393
/*                                                                                                                                                                                                                                                                              */
378
/*                                                                                                                                                                                                                                                                              */
394
/*      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.                                                                                       */
395
/*                                                                                                                                                                                                                                                                              */
380
/*                                                                                                                                                                                                                                                                              */
396
/*      Returnvalue:    Returns the DOS date.                                                                                                                                                                                           */
381
/*      Returnvalue:    Returns the DOS date.                                                                                                                                                                                           */
397
/****************************************************************************************************************************************/
382
/****************************************************************************************************************************************/
398
u16 FileDate(DateTime_t * pTimeStruct)
383
u16 FileDate(DateTime_t * pTimeStruct)
399
{
384
{
400
        u16 date = 0;
385
        u16 date = 0;
401
        if(pTimeStruct == NULL)   return date;
386
        if(pTimeStruct == NULL)   return date;
402
        if(!(pTimeStruct->Valid)) return date;
387
        if(!(pTimeStruct->Valid)) return date;
403
 
388
 
404
        date |= (0x007F & (u16)(pTimeStruct->Year - 1980))<<9; // set year
389
        date |= (0x007F & (u16)(pTimeStruct->Year - 1980))<<9; // set year
405
        date |= (0x000F & (u16)(pTimeStruct->Month))<<5; // set month
390
        date |= (0x000F & (u16)(pTimeStruct->Month))<<5; // set month
406
        date |= (0x001F & (u16)(pTimeStruct->Day));
391
        date |= (0x001F & (u16)(pTimeStruct->Day));
407
        return date;
392
        return date;
408
}
393
}
409
 
394
 
410
/****************************************************************************************************************************************/
395
/****************************************************************************************************************************************/
411
/*      Function:               FileTime(DateTime_t *);                                                                                                                                                                                         */
396
/*      Function:               FileTime(DateTime_t *);                                                                                                                                                                                         */
412
/*                                                                                                                                                                                                                                                                              */
397
/*                                                                                                                                                                                                                                                                              */
413
/*      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.                                                                                       */
414
/*                                                                                                                                                                                                                                                                              */
399
/*                                                                                                                                                                                                                                                                              */
415
/*      Returnvalue:    Returns the DOS time.                                                                                                                                                                                           */
400
/*      Returnvalue:    Returns the DOS time.                                                                                                                                                                                           */
416
/****************************************************************************************************************************************/
401
/****************************************************************************************************************************************/
417
 
402
 
418
u16 FileTime(DateTime_t * pTimeStruct)
403
u16 FileTime(DateTime_t * pTimeStruct)
419
{
404
{
420
        u16 time = 0;
405
        u16 time = 0;
421
        if(pTimeStruct == NULL)   return time;
406
        if(pTimeStruct == NULL)   return time;
422
        if(!(pTimeStruct->Valid)) return time;
407
        if(!(pTimeStruct->Valid)) return time;
423
 
408
 
424
        time |= (0x001F & (u16)(pTimeStruct->Hour))<<11;
409
        time |= (0x001F & (u16)(pTimeStruct->Hour))<<11;
425
        time |= (0x003F & (u16)(pTimeStruct->Min))<<5;
410
        time |= (0x003F & (u16)(pTimeStruct->Min))<<5;
426
        time |= (0x001F & (u16)(pTimeStruct->Sec/2));
411
        time |= (0x001F & (u16)(pTimeStruct->Sec/2));
427
        return time;
412
        return time;
428
}
413
}
429
 
414
 
430
/****************************************************************************************************************************************/
415
/****************************************************************************************************************************************/
431
/*      Function:               LockFilePointer();                                                                                                                                                                                                      */
416
/*      Function:               LockFilePointer();                                                                                                                                                                                                      */
432
/*                                                                                                                                                                                                                                                                              */
417
/*                                                                                                                                                                                                                                                                              */
433
/*      Description:    This function trys to lock a free file pointer.                                                                                                                                         */
418
/*      Description:    This function trys to lock a free file pointer.                                                                                                                                         */
434
/*                                                                                                                                                                                                                                                                              */
419
/*                                                                                                                                                                                                                                                                              */
435
/*      Returnvalue:    Returns the Filepointer on success or 0.                                                                                                                                                        */
420
/*      Returnvalue:    Returns the Filepointer on success or 0.                                                                                                                                                        */
436
/****************************************************************************************************************************************/
421
/****************************************************************************************************************************************/
437
File_t * LockFilePointer(void)
422
File_t * LockFilePointer(void)
438
{
423
{
439
        u8 i;
424
        u8 i;
440
        File_t * File = 0;
425
        File_t * File = 0;
441
        for(i = 0; i < FILE_MAX_OPEN; i++)
426
        for(i = 0; i < FILE_MAX_OPEN; i++)
442
        {
427
        {
443
                if(FilePointer[i].State == FSTATE_UNUSED)                                                               // found an unused one
428
                if(FilePointer[i].State == FSTATE_UNUSED)                                                               // found an unused one
444
                {
429
                {
445
                        File = &FilePointer[i];                                                                                         // set pointer to that entry
430
                        File = &FilePointer[i];                                                                                         // set pointer to that entry
446
                        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.
447
                        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.
448
                        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
449
                        FilePointer[i].SectorOfCurrCluster = SECTOR_UNDEFINED;                          // The sector within the current cluster.
434
                        FilePointer[i].SectorOfCurrCluster = SECTOR_UNDEFINED;                          // The sector within the current cluster.
450
                        FilePointer[i].ByteOfCurrSector = 0;                                                            // The byte location within the current sector.
435
                        FilePointer[i].ByteOfCurrSector = 0;                                                            // The byte location within the current sector.
451
                        FilePointer[i].Mode = 0;                                                                                        // Mode of fileoperation (read,write)
436
                        FilePointer[i].Mode = 0;                                                                                        // Mode of fileoperation (read,write)
452
                        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.
453
                        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
454
                        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.
455
                        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.
456
                        FilePointer[i].Attribute = 0;                                                                           // The attribute of the file opened.
441
                        FilePointer[i].Attribute = 0;                                                                           // The attribute of the file opened.
457
                        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.
458
                        FilePointer[i].State = FSTATE_USED;                                                                     // mark it as used
443
                        FilePointer[i].State = FSTATE_USED;                                                                     // mark it as used
459
 
444
 
460
                        break;
445
                        break;
461
                }
446
                }
462
        }
447
        }
463
        return(File);
448
        return(File);
464
}
449
}
465
 
450
 
466
/****************************************************************************************************************************************/
451
/****************************************************************************************************************************************/
467
/*      Function:               UnlockFilePointer(file_t *);                                                                                                                                                                            */
452
/*      Function:               UnlockFilePointer(file_t *);                                                                                                                                                                            */
468
/*                                                                                                                                                                                                                                                                              */
453
/*                                                                                                                                                                                                                                                                              */
469
/*      Description:    This function trys to unlock a file pointer.                                                                                                                                            */
454
/*      Description:    This function trys to unlock a file pointer.                                                                                                                                            */
470
/*                                                                                                                                                                                                                                                                              */
455
/*                                                                                                                                                                                                                                                                              */
471
/*      Returnvalue:    Returns 1 if file pointer was freed else 0.                                                                                                                                                     */
456
/*      Returnvalue:    Returns 1 if file pointer was freed else 0.                                                                                                                                                     */
472
/****************************************************************************************************************************************/
457
/****************************************************************************************************************************************/
473
u8 UnlockFilePointer(File_t * file)
458
u8 UnlockFilePointer(File_t * file)
474
{
459
{
475
        u8 cnt;
460
        u8 cnt;
476
        if(file == NULL) return(0);
461
        if(file == NULL) return(0);
477
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
462
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
478
        {
463
        {
479
                if(&FilePointer[cnt] == file)                                           // filepointer to be freed found?
464
                if(&FilePointer[cnt] == file)                                           // filepointer to be freed found?
480
                {
465
                {
481
                        file->State = FSTATE_UNUSED;
466
                        file->State = FSTATE_UNUSED;
482
                        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.
483
                        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.
484
                        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).
485
                        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).
486
                        file->Mode                                              = 0;                    // mode of fileoperation (read,write)
471
                        file->Mode                                              = 0;                    // mode of fileoperation (read,write)
487
                        file->Size                                              = 0;                    // the size of the opend file in bytes.
472
                        file->Size                                              = 0;                    // the size of the opend file in bytes.
488
                        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
489
                        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.
490
                        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.
491
                        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.
492
                        file->Attribute                                 = 0;                    // the attribute of the file opened.
477
                        file->Attribute                                 = 0;                    // the attribute of the file opened.
493
                        file = NULL;
478
                        file = NULL;
494
                        return(1);
479
                        return(1);
495
                }
480
                }
496
        }
481
        }
497
        return(0);
482
        return(0);
498
}
483
}
499
 
484
 
500
/****************************************************************************************************************************************/
485
/****************************************************************************************************************************************/
501
/*      Function:               s8* SeperateFormatedDirName(const s8*, s8*);                                                                                                                                            */
486
/*      Function:               s8* SeperateFormatedDirName(const s8*, s8*);                                                                                                                                            */
502
/*                                                                                                                                                                                                                                                                              */
487
/*                                                                                                                                                                                                                                                                              */
503
/*      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                                                                                         */
504
/*                                      into the needed format ('test.txt' -> 'TEST    TXT')                                                                                                                            */
489
/*                                      into the needed format ('test.txt' -> 'TEST    TXT')                                                                                                                            */
505
/*                                      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                                                                                           */
506
/*                                                                                                                                                                                                                                                                              */
491
/*                                                                                                                                                                                                                                                                              */
507
/*      Returnvalue:    Return NULL on error or pointer to subpath                                                                                                                                                      */
492
/*      Returnvalue:    Return NULL on error or pointer to subpath                                                                                                                                                      */
508
/****************************************************************************************************************************************/
493
/****************************************************************************************************************************************/
509
s8* SeperateFormatedDirName(const s8 *filepath, s8 *dirname)
494
s8* SeperateFormatedDirName(const s8 *filepath, s8 *dirname)
510
{
495
{
511
        s8* subpath = NULL;
496
        s8* subpath = NULL;
512
        u8 readpointer  = 0;
497
        u8 readpointer  = 0;
513
        u8 writepointer = 0;
498
        u8 writepointer = 0;
514
 
499
 
515
        // search subpath from beginning of filepath
500
        // search subpath from beginning of filepath
516
        subpath = NULL;
501
        subpath = NULL;
517
        readpointer     = 0;
502
        readpointer     = 0;
518
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
503
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
519
        while(subpath == NULL)  // search the filepath until a subpath was found.
504
        while(subpath == NULL)  // search the filepath until a subpath was found.
520
        {
505
        {
521
                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
522
                {
507
                {
523
                        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
524
                }
509
                }
525
                readpointer++;
510
                readpointer++;
526
        }
511
        }
527
 
512
 
528
        // clear dirname with spaces
513
        // clear dirname with spaces
529
        dirname[11] = 0; // terminate dirname
514
        dirname[11] = 0; // terminate dirname
530
        for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' ';
515
        for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' ';
531
 
516
 
532
        // handle the special dirnames "." and ".." seperately
517
        // handle the special dirnames "." and ".." seperately
533
        readpointer = 0;
518
        readpointer = 0;
534
        if(filepath[0] == '/') readpointer++;
519
        if(filepath[0] == '/') readpointer++;
535
        // if we are trying to enter directories "." or ".."
520
        // if we are trying to enter directories "." or ".."
536
        if(filepath[readpointer] == '.')
521
        if(filepath[readpointer] == '.')
537
        {
522
        {
538
                // directory '.'
523
                // directory '.'
539
                if(filepath[readpointer+1] == 0)
524
                if(filepath[readpointer+1] == 0)
540
                {
525
                {
541
                        dirname[0] = '.';
526
                        dirname[0] = '.';
542
                        return((s8*)&filepath[readpointer]);
527
                        return((s8*)&filepath[readpointer]);
543
                }
528
                }
544
                // directory '..'
529
                // directory '..'
545
                if((filepath[readpointer+1] == '.') &&  (filepath[readpointer+2] == 0))
530
                if((filepath[readpointer+1] == '.') &&  (filepath[readpointer+2] == 0))
546
                {
531
                {
547
                        dirname[0] = '.';
532
                        dirname[0] = '.';
548
                        dirname[1] = '.';
533
                        dirname[1] = '.';
549
                        return((s8*)&filepath[readpointer]);
534
                        return((s8*)&filepath[readpointer]);
550
                }
535
                }
551
        }
536
        }
552
 
537
 
553
        writepointer = 0;
538
        writepointer = 0;
554
        // start seperating the dirname from the filepath.
539
        // start seperating the dirname from the filepath.
555
        readpointer = 0;
540
        readpointer = 0;
556
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
541
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
557
        while( &filepath[readpointer] < subpath)
542
        while( &filepath[readpointer] < subpath)
558
        {
543
        {
559
                if(writepointer >= 11) return(NULL);            // dirname to long
544
                if(writepointer >= 11) return(NULL);            // dirname to long
560
                if(filepath[readpointer] == '.')                        // seperating dirname and extension.
545
                if(filepath[readpointer] == '.')                        // seperating dirname and extension.
561
                {
546
                {
562
                        if(writepointer <= 8)
547
                        if(writepointer <= 8)
563
                        {
548
                        {
564
                                readpointer++;                                          // next character in filename
549
                                readpointer++;                                          // next character in filename
565
                                writepointer = 8;                                       // jump to start of extension
550
                                writepointer = 8;                                       // jump to start of extension
566
                        }
551
                        }
567
                        else return(NULL);                                              // dirbasename to long
552
                        else return(NULL);                                              // dirbasename to long
568
                }
553
                }
569
                else
554
                else
570
                {
555
                {
571
                        if((0x60 < filepath[readpointer]) && (filepath[readpointer] < 0x7B))
556
                        if((0x60 < filepath[readpointer]) && (filepath[readpointer] < 0x7B))
572
                        {
557
                        {
573
                                dirname[writepointer] = (filepath[readpointer] - 0x20);                                 // all characters must be upper case.
558
                                dirname[writepointer] = (filepath[readpointer] - 0x20);                                 // all characters must be upper case.
574
                        }
559
                        }
575
                        else
560
                        else
576
                        {
561
                        {
577
                                dirname[writepointer] = filepath[readpointer];
562
                                dirname[writepointer] = filepath[readpointer];
578
                        }
563
                        }
579
                        readpointer++;
564
                        readpointer++;
580
                        writepointer++;
565
                        writepointer++;
581
                }
566
                }
582
        }
567
        }
583
        return(subpath);
568
        return(subpath);
584
}
569
}
585
 
570
 
586
/**************************************************************************************************************************************+*/
571
/**************************************************************************************************************************************+*/
587
/*      Function:       Fat16ClusterToSector( u16 cluster);                                                                                                                                                                             */
572
/*      Function:       Fat16ClusterToSector( u16 cluster);                                                                                                                                                                             */
588
/*                                                                                                                                                                                                                                                                              */
573
/*                                                                                                                                                                                                                                                                              */
589
/*      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                                                                           */
590
/*                                      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.                                                     */
591
/*                                                                                                                                                                                                                                                                              */
576
/*                                                                                                                                                                                                                                                                              */
592
/*      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                                                                                                                          */
593
/****************************************************************************************************************************************/
578
/****************************************************************************************************************************************/
594
u32     Fat16ClusterToSector(u16 cluster)
579
u32     Fat16ClusterToSector(u16 cluster)
595
{
580
{
596
        if(!Partition.IsValid) return SECTOR_UNDEFINED;
581
        if(!Partition.IsValid) return SECTOR_UNDEFINED;
597
        if ((cluster < 2) || (cluster == CLUSTER_UNDEFINED))
582
        if ((cluster < 2) || (cluster == CLUSTER_UNDEFINED))
598
        {
583
        {
599
                return SECTOR_UNDEFINED;
584
                return SECTOR_UNDEFINED;
600
        }
585
        }
601
        else
586
        else
602
        {
587
        {
603
                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
604
        }
589
        }
605
}
590
}
606
 
591
 
607
/****************************************************************************************************************************************/
592
/****************************************************************************************************************************************/
608
/*      Function:       SectorToFat16Cluster( u32 sector);                                                                                                                                                                              */
593
/*      Function:       SectorToFat16Cluster( u32 sector);                                                                                                                                                                              */
609
/*                                                                                                                                                                                                                                                                              */
594
/*                                                                                                                                                                                                                                                                              */
610
/*      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                                                                                         */
611
/*                                      cluster number in the fat that represents this data area.                                                                                                                       */
596
/*                                      cluster number in the fat that represents this data area.                                                                                                                       */
612
/*                                                                                                                                                                                                                                                                              */
597
/*                                                                                                                                                                                                                                                                              */
613
/*      Returnvalue: The cluster number representing the data area of the sector.                                                                                                                       */
598
/*      Returnvalue: The cluster number representing the data area of the sector.                                                                                                                       */
614
/****************************************************************************************************************************************/
599
/****************************************************************************************************************************************/
615
u16     SectorToFat16Cluster(u32 sector)
600
u16     SectorToFat16Cluster(u32 sector)
616
{
601
{
617
        if(!Partition.IsValid) return CLUSTER_UNDEFINED;
602
        if(!Partition.IsValid) return CLUSTER_UNDEFINED;
618
        if((sector == SECTOR_UNDEFINED) || (sector < Partition.FirstDataSector)) return CLUSTER_UNDEFINED;
603
        if((sector == SECTOR_UNDEFINED) || (sector < Partition.FirstDataSector)) return CLUSTER_UNDEFINED;
619
        else return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2);
604
        else return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2);
620
}
605
}
621
 
606
 
622
 
607
 
623
/****************************************************************************************************************************************/
608
/****************************************************************************************************************************************/
624
/*      Function:       Fat16_IsValid(void);                                                                                                                                                                                                    */
609
/*      Function:       Fat16_IsValid(void);                                                                                                                                                                                                    */
625
/*                                                                                                                                                                                                                                                                              */
610
/*                                                                                                                                                                                                                                                                              */
626
/*      Description:    This function return the Fat 16 filesystem state                                                                                                                                        */
611
/*      Description:    This function return the Fat 16 filesystem state                                                                                                                                        */
627
/*                                                                                                                                                                                                                                                                              */
612
/*                                                                                                                                                                                                                                                                              */
628
/*      Returnvalue: The function returns "1" on success                                                                                                                                                                        */
613
/*      Returnvalue: The function returns "1" on success                                                                                                                                                                        */
629
/****************************************************************************************************************************************/
614
/****************************************************************************************************************************************/
630
u8 Fat16_IsValid(void)
615
u8 Fat16_IsValid(void)
631
{
616
{
632
        return(Partition.IsValid);
617
        return(Partition.IsValid);
633
}
618
}
634
 
619
 
635
/****************************************************************************************************************************************/
620
/****************************************************************************************************************************************/
636
/*      Function:       Fat16_Deinit(void);                                                                                                                                                                                                             */
621
/*      Function:       Fat16_Deinit(void);                                                                                                                                                                                                             */
637
/*                                                                                                                                                                                                                                                                              */
622
/*                                                                                                                                                                                                                                                                              */
638
/*      Description:    This function uninitializes the fat 16 api                                                                                                                                                      */
623
/*      Description:    This function uninitializes the fat 16 api                                                                                                                                                      */
639
/*                                                                                                                                                                                                                                                                              */
624
/*                                                                                                                                                                                                                                                                              */
640
/*      Returnvalue: The function returns "0" on success                                                                                                                                                                        */
625
/*      Returnvalue: The function returns "0" on success                                                                                                                                                                        */
641
/****************************************************************************************************************************************/
626
/****************************************************************************************************************************************/
642
u8 Fat16_Deinit(void)
627
u8 Fat16_Deinit(void)
643
{
628
{
644
        s16 returnvalue = 0;
629
        s16 returnvalue = 0;
645
        u8 cnt;
630
        u8 cnt;
646
 
631
 
647
        UART1_PutString("\r\n FAT16 deinit...");
632
        UART1_PutString("\r\n FAT16 deinit...");
648
        // declare the filepointers as unused.
633
        // declare the filepointers as unused.
649
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
634
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
650
        {
635
        {
651
                UnlockFilePointer(&FilePointer[cnt]);
636
                UnlockFilePointer(&FilePointer[cnt]);
652
        }
637
        }
653
        returnvalue = SDC_Deinit();                     // uninitialize interface to sd-card
638
        returnvalue = SDC_Deinit();                     // uninitialize interface to sd-card
654
        Partition.IsValid = 0;  // mark data in partition structure as invalid
639
        Partition.IsValid = 0;  // mark data in partition structure as invalid
655
        Partition.VolumeLabel[0]='\0';
640
        Partition.VolumeLabel[0]='\0';
656
        UART1_PutString("ok");
641
        UART1_PutString("ok");
657
        if(SD_WatchDog > 2000) SD_WatchDog = 2000;
642
        if(SD_WatchDog > 2000) SD_WatchDog = 2000;
658
        SD_LoggingError = 100;
643
        SD_LoggingError = 100;
659
        return(returnvalue);
644
        return(returnvalue);
660
}
645
}
661
 
646
 
662
 
647
 
663
/****************************************************************************************************************************************/
648
/****************************************************************************************************************************************/
664
/*      Function:               Fat16_Init(void);                                                                                                                                                                                                       */
649
/*      Function:               Fat16_Init(void);                                                                                                                                                                                                       */
665
/*                                                                                                                                                                                                                                                                          */
650
/*                                                                                                                                                                                                                                                                          */
666
/*      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    */
667
/*                                      and stores the information in global variables.                                                                                                                                     */
652
/*                                      and stores the information in global variables.                                                                                                                                     */
668
/*                                                                                                                                                                                                                                                                          */
653
/*                                                                                                                                                                                                                                                                          */
669
/*      Returnvalue:    The function returns "0" if the filesystem is initialized.                                                                                                                      */
654
/*      Returnvalue:    The function returns "0" if the filesystem is initialized.                                                                                                                      */
670
/****************************************************************************************************************************************/
655
/****************************************************************************************************************************************/
671
u8 Fat16_Init(void)
656
u8 Fat16_Init(void)
672
{
657
{
673
    u8  cnt     = 0;
658
    u8  cnt     = 0;
674
        u32     partitionfirstsector;
659
        u32     partitionfirstsector;
675
        VBR_Entry_t *VBR;
660
        VBR_Entry_t *VBR;
676
        MBR_Entry_t *MBR;
661
        MBR_Entry_t *MBR;
677
        File_t *file;
662
        File_t *file;
678
        u8 result = 0;
663
        u8 result = 0;
679
 
664
 
680
        UART1_PutString("\r\n FAT16 init...");
665
        UART1_PutString("\r\n FAT16 init...");
681
        Partition.IsValid = 0;
666
        Partition.IsValid = 0;
682
        // declare the filepointers as unused.
667
        // declare the filepointers as unused.
683
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
668
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
684
        {
669
        {
685
                UnlockFilePointer(&FilePointer[cnt]);
670
                UnlockFilePointer(&FilePointer[cnt]);
686
        }
671
        }
687
        // set current file pinter to first position in list
672
        // set current file pinter to first position in list
688
        file = &FilePointer[0];
673
        file = &FilePointer[0];
689
 
674
 
690
        // try to initialize the sd-card.
675
        // try to initialize the sd-card.
691
        if(SD_SUCCESS != SDC_Init())
676
        if(SD_SUCCESS != SDC_Init())
692
        {
677
        {
693
                UART1_PutString("SD-Card could not be initialized.");
678
                UART1_PutString("SD-Card could not be initialized.");
694
                result = 1;
679
                result = 1;
695
                goto end;
680
                goto end;
696
        }
681
        }
697
 
682
 
698
        // SD-Card is initialized successfully
683
        // SD-Card is initialized successfully
699
        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
700
        {
685
        {
701
                UART1_PutString("Error reading the MBR.");
686
                UART1_PutString("Error reading the MBR.");
702
                result = 2;
687
                result = 2;
703
                goto end;
688
                goto end;
704
        }
689
        }
705
        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.
706
        if((MBR->PartitionEntry1.Type == PART_TYPE_FAT16_ST_32_MB) ||
691
        if((MBR->PartitionEntry1.Type == PART_TYPE_FAT16_ST_32_MB) ||
707
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
692
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
708
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
693
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
709
        {
694
        {
710
                // get sector offset 1st partition
695
                // get sector offset 1st partition
711
                partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
696
                partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
712
                // Start of Partition is the Volume Boot Sector
697
                // Start of Partition is the Volume Boot Sector
713
                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
714
                {
699
                {
715
                        UART1_PutString("Error reading the VBR.");
700
                        UART1_PutString("Error reading the VBR.");
716
                        result = 3;
701
                        result = 3;
717
                        goto end;
702
                        goto end;
718
                }
703
                }
719
        }
704
        }
720
        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
721
        {
706
        {
722
                partitionfirstsector = 0;
707
                partitionfirstsector = 0;
723
        }
708
        }
724
 
709
 
725
        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.
726
        if(VBR->BytesPerSector != BYTES_PER_SECTOR)
711
        if(VBR->BytesPerSector != BYTES_PER_SECTOR)
727
        {
712
        {
728
                UART1_PutString("VBR: Sector size not supported.");
713
                UART1_PutString("VBR: Sector size not supported.");
729
                result = 4;
714
                result = 4;
730
                goto end;
715
                goto end;
731
        }
716
        }
732
        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.
733
        Partition.FatCopies                     = VBR->NoFATCopies;                                     // Number of fatcopies.
718
        Partition.FatCopies                     = VBR->NoFATCopies;                                     // Number of fatcopies.
734
        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).
735
        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
736
        Partition.VolumeLabel[0] = '\0';                                                                        // set string terminator
721
        Partition.VolumeLabel[0] = '\0';                                                                        // set string terminator
737
 
722
 
738
        /* 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. */
739
        // Calculate the position of the FileAllocationTable:
724
        // Calculate the position of the FileAllocationTable:
740
        // Start + # of Reserved Sectors
725
        // Start + # of Reserved Sectors
741
        Partition.FirstFatSector        =   (u32)(partitionfirstsector + (u32)(VBR->ReservedSectors));
726
        Partition.FirstFatSector        =   (u32)(partitionfirstsector + (u32)(VBR->ReservedSectors));
742
        // Calculate the position of the Rootdirectory:
727
        // Calculate the position of the Rootdirectory:
743
        // Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)
728
        // Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)
744
        Partition.FirstRootDirSector    =   Partition.FirstFatSector + (u32)((u32)Partition.SectorsPerFat*(u32)Partition.FatCopies);
729
        Partition.FirstRootDirSector    =   Partition.FirstFatSector + (u32)((u32)Partition.SectorsPerFat*(u32)Partition.FatCopies);
745
        // Calculate the position of the first datacluster:
730
        // Calculate the position of the first datacluster:
746
        // 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)
747
        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
748
        // Calculate the last data sector
733
        // Calculate the last data sector
749
        if(VBR->NoSectors == 0)
734
        if(VBR->NoSectors == 0)
750
        {
735
        {
751
                UART1_PutString("VBR: Bad number of sectors.");
736
                UART1_PutString("VBR: Bad number of sectors.");
752
                result = 5;
737
                result = 5;
753
                goto end;
738
                goto end;
754
        }
739
        }
755
        Partition.LastDataSector = Partition.FirstDataSector + VBR->NoSectors - 1;
740
        Partition.LastDataSector = Partition.FirstDataSector + VBR->NoSectors - 1;
756
        // check for FAT16 in VBR of first partition
741
        // check for FAT16 in VBR of first partition
757
        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')))
758
        {
743
        {
759
                UART1_PutString("VBR: Partition ist not FAT16 type.");
744
                UART1_PutString("VBR: Partition ist not FAT16 type.");
760
                result = 6;
745
                result = 6;
761
                goto end;
746
                goto end;
762
        }
747
        }
763
        Partition.IsValid = 1; // mark data in partition structure as valid
748
        Partition.IsValid = 1; // mark data in partition structure as valid
764
        Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
749
        Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
765
        strcpy(Partition.PathToCwd,"/");
750
        strcpy(Partition.PathToCwd,"/");
766
        result = 0;
751
        result = 0;
767
        end:
752
        end:
768
        if(result != 0) Fat16_Deinit();
753
        if(result != 0) Fat16_Deinit();
769
        else UART1_PutString("ok");
754
        else UART1_PutString("ok");
770
        return(result);
755
        return(result);
771
}
756
}
772
 
757
 
773
 
758
 
774
 
759
 
775
/****************************************************************************************************************************************/
760
/****************************************************************************************************************************************/
776
/* Function:    ClearCurrCluster(File_t*);                                                                                                                                                                                      */
761
/* Function:    ClearCurrCluster(File_t*);                                                                                                                                                                                      */
777
/*                                                                                                                                                                                                                                                                              */
762
/*                                                                                                                                                                                                                                                                              */
778
/* Description: This function fills the current cluster with 0.                                                                                                                                                 */
763
/* Description: This function fills the current cluster with 0.                                                                                                                                                 */
779
/*                                                                                                                                                                                                                                                                              */
764
/*                                                                                                                                                                                                                                                                              */
780
/* Returnvalue: The function returns 1 on success else 0.                                                                                                                                                               */
765
/* Returnvalue: The function returns 1 on success else 0.                                                                                                                                                               */
781
/****************************************************************************************************************************************/
766
/****************************************************************************************************************************************/
782
u8 ClearCurrCluster(File_t * file)
767
u8 ClearCurrCluster(File_t * file)
783
{
768
{
784
        u8 retvalue = 1;
769
        u8 retvalue = 1;
785
        u32 i;
770
        u32 i;
786
 
771
 
787
        if((!Partition.IsValid) || (file == NULL)) return(0);
772
        if((!Partition.IsValid) || (file == NULL)) return(0);
788
 
773
 
789
        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
790
        if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return (0); // nothing to do
775
        if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return (0); // nothing to do
791
        for(i = 0; i < Partition.SectorsPerCluster; i++)
776
        for(i = 0; i < Partition.SectorsPerCluster; i++)
792
        {
777
        {
793
                file->SectorInCache = file->FirstSectorOfCurrCluster + i;
778
                file->SectorInCache = file->FirstSectorOfCurrCluster + i;
794
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
779
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
795
                {
780
                {
796
                        Fat16_Deinit();
781
                        Fat16_Deinit();
797
                        return(0);
782
                        return(0);
798
                }
783
                }
799
        }
784
        }
800
        return(retvalue);
785
        return(retvalue);
801
}
786
}
802
 
787
 
803
/*****************************************************************************************************************************************/
788
/*****************************************************************************************************************************************/
804
/* Function:    GetNextCluster(File_t* );                                                                                                                                                                                        */
789
/* Function:    GetNextCluster(File_t* );                                                                                                                                                                                        */
805
/*                                                                                                                                                                                                                                                                               */
790
/*                                                                                                                                                                                                                                                                               */
806
/* 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.                                                                                  */
807
/*                                                                                                                                                                                                                                                                               */
792
/*                                                                                                                                                                                                                                                                               */
808
/* 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.                                                                                                      */
809
/*****************************************************************************************************************************************/
794
/*****************************************************************************************************************************************/
810
u16 GetNextCluster(File_t * file)
795
u16 GetNextCluster(File_t * file)
811
{
796
{
812
        u16 cluster = CLUSTER_UNDEFINED;
797
        u16 cluster = CLUSTER_UNDEFINED;
813
        u32 fat_byte_offset, sector, byte;
798
        u32 fat_byte_offset, sector, byte;
814
        Fat16Entry_t * fat;
799
        Fat16Entry_t * fat;
815
 
800
 
816
        if((!Partition.IsValid) || (file == NULL)) return(cluster);
801
        if((!Partition.IsValid) || (file == NULL)) return(cluster);
817
        if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(cluster);
802
        if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(cluster);
818
        // if sector is within the data area
803
        // if sector is within the data area
819
        if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
804
        if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
820
        {
805
        {
821
                // determine current file cluster
806
                // determine current file cluster
822
                cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);
807
                cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);
823
                // calculate byte offset in the fat for corresponding entry
808
                // calculate byte offset in the fat for corresponding entry
824
                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
825
                // calculate the sector that contains the current cluster within the fat
810
                // calculate the sector that contains the current cluster within the fat
826
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
811
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
827
                // calculate byte offset of the current cluster within that fat sector
812
                // calculate byte offset of the current cluster within that fat sector
828
                byte = fat_byte_offset % BYTES_PER_SECTOR;
813
                byte = fat_byte_offset % BYTES_PER_SECTOR;
829
                // read this sector to the file cache
814
                // read this sector to the file cache
830
                if(file->SectorInCache != sector)
815
                if(file->SectorInCache != sector)
831
                {
816
                {
832
                        file->SectorInCache = sector;                                           // update sector stored in buffer
817
                        file->SectorInCache = sector;                                           // update sector stored in buffer
833
                        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
834
                        {
819
                        {
835
                                Fat16_Deinit();
820
                                Fat16_Deinit();
836
                                return (CLUSTER_UNDEFINED);
821
                                return (CLUSTER_UNDEFINED);
837
                        }
822
                        }
838
                }
823
                }
839
                // read the next cluster from cache
824
                // read the next cluster from cache
840
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
825
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
841
                cluster = fat->NextCluster;
826
                cluster = fat->NextCluster;
842
                // if no next cluster exist
827
                // if no next cluster exist
843
                if(FAT16_CLUSTER_LAST_MIN <= cluster)
828
                if(FAT16_CLUSTER_LAST_MIN <= cluster)
844
                {
829
                {
845
                         cluster = CLUSTER_UNDEFINED; // next cluster is undefined
830
                         cluster = CLUSTER_UNDEFINED; // next cluster is undefined
846
                }
831
                }
847
                else
832
                else
848
                {
833
                {
849
                        file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
834
                        file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
850
                        file->SectorOfCurrCluster = 0;
835
                        file->SectorOfCurrCluster = 0;
851
                        file->ByteOfCurrSector = 0;
836
                        file->ByteOfCurrSector = 0;
852
                }
837
                }
853
        }
838
        }
854
        return(cluster);
839
        return(cluster);
855
}
840
}
856
 
841
 
857
 
842
 
858
 
843
 
859
/****************************************************************************************************************************************/
844
/****************************************************************************************************************************************/
860
/* Function:    FindNextFreeCluster(File_t *);                                                                                                                                                                          */
845
/* Function:    FindNextFreeCluster(File_t *);                                                                                                                                                                          */
861
/*                                                                                                                                                                                                                                                                              */
846
/*                                                                                                                                                                                                                                                                              */
862
/* 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                                                                                                                    */
863
/*                                                                                                                                                                                                                                                                              */
848
/*                                                                                                                                                                                                                                                                              */
864
/* 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.                                                                  */
865
/****************************************************************************************************************************************/
850
/****************************************************************************************************************************************/
866
u16 FindNextFreeCluster(File_t *file)
851
u16 FindNextFreeCluster(File_t *file)
867
{
852
{
868
        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.
869
        u32     curr_sector;                            // current sector
854
        u32     curr_sector;                            // current sector
870
        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).
871
        u16     free_cluster    = CLUSTER_UNDEFINED;    // next free cluster number.
856
        u16     free_cluster    = CLUSTER_UNDEFINED;    // next free cluster number.
872
        Fat16Entry_t * fat;
857
        Fat16Entry_t * fat;
873
 
858
 
874
        if((!Partition.IsValid) || (file == NULL)) return(0);
859
        if((!Partition.IsValid) || (file == NULL)) return(0);
875
 
860
 
876
        // 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.
877
        fat_sector = 0;
862
        fat_sector = 0;
878
        do
863
        do
879
        {
864
        {
880
                curr_sector = Partition.FirstFatSector + fat_sector;    // calculate sector to read
865
                curr_sector = Partition.FirstFatSector + fat_sector;    // calculate sector to read
881
                file->SectorInCache = curr_sector;                                              // upate the sector number of file cache.
866
                file->SectorInCache = curr_sector;                                              // upate the sector number of file cache.
882
                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.
883
                {
868
                {
884
                        Fat16_Deinit();
869
                        Fat16_Deinit();
885
                        return(CLUSTER_UNDEFINED);
870
                        return(CLUSTER_UNDEFINED);
886
                }
871
                }
887
 
872
 
888
                fat = (Fat16Entry_t *)file->Cache;                                              // set fat pointer to file cache
873
                fat = (Fat16Entry_t *)file->Cache;                                              // set fat pointer to file cache
889
 
874
 
890
                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.
891
                {
876
                {
892
                        if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE)            // empty cluster found!!
877
                        if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE)            // empty cluster found!!
893
                        {
878
                        {
894
                                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
895
                                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.
896
                                {
881
                                {
897
                                        Fat16_Deinit();
882
                                        Fat16_Deinit();
898
                                        return(CLUSTER_UNDEFINED);
883
                                        return(CLUSTER_UNDEFINED);
899
                                }
884
                                }
900
                                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);
901
                                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.
902
                        }
887
                        }
903
                }
888
                }
904
                fat_sector++;                                                                                                   // continue the search in next fat sector
889
                fat_sector++;                                                                                                   // continue the search in next fat sector
905
        // 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
906
        }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster));
891
        }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster));
907
        return(free_cluster);
892
        return(free_cluster);
908
}
893
}
909
 
894
 
910
/****************************************************************************************************************************************/
895
/****************************************************************************************************************************************/
911
/* Function:    u8 DeleteClusterChain(File *file);                                                                                                                                                                              */
896
/* Function:    u8 DeleteClusterChain(File *file);                                                                                                                                                                              */
912
/*                                                                                                                                                                                                                                                                              */
897
/*                                                                                                                                                                                                                                                                              */
913
/* 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.                                                                  */
914
/*                                                                                                                                                                                                                                                                              */
899
/*                                                                                                                                                                                                                                                                              */
915
/* Returnvalue: returns 1 in success otherwise 0                                                                                                                                                                                */
900
/* Returnvalue: returns 1 in success otherwise 0                                                                                                                                                                                */
916
/****************************************************************************************************************************************/
901
/****************************************************************************************************************************************/
917
u8 DeleteClusterChain(u16 StartCluster)
902
u8 DeleteClusterChain(u16 StartCluster)
918
{
903
{
919
        u16 cluster;
904
        u16 cluster;
920
        u32 fat_byte_offset, sector, byte;
905
        u32 fat_byte_offset, sector, byte;
921
        Fat16Entry_t * fat;
906
        Fat16Entry_t * fat;
922
        u8 buffer[BYTES_PER_SECTOR];
907
        u8 buffer[BYTES_PER_SECTOR];
923
        u32 sector_in_buffer = 0;
908
        u32 sector_in_buffer = 0;
924
        u8 repeat = 0;
909
        u8 repeat = 0;
925
 
910
 
926
        if(!Partition.IsValid) return(0);
911
        if(!Partition.IsValid) return(0);
927
        if(StartCluster == CLUSTER_UNDEFINED) return(1);
912
        if(StartCluster == CLUSTER_UNDEFINED) return(1);
928
        cluster = StartCluster; // init chain trace
913
        cluster = StartCluster; // init chain trace
929
        // if start cluster is no real cluster
914
        // if start cluster is no real cluster
930
    if(FAT16_CLUSTER_LAST_MIN <= cluster) return(1);
915
    if(FAT16_CLUSTER_LAST_MIN <= cluster) return(1);
931
 
916
 
932
        // calculate byte offset in the fat for corresponding entry
917
        // calculate byte offset in the fat for corresponding entry
933
        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
934
        // calculate the sector that contains the current cluster within the fat
919
        // calculate the sector that contains the current cluster within the fat
935
        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
920
        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
936
        // calculate byte offset of the current cluster within that fat sector
921
        // calculate byte offset of the current cluster within that fat sector
937
        byte = fat_byte_offset % BYTES_PER_SECTOR;
922
        byte = fat_byte_offset % BYTES_PER_SECTOR;
938
        do
923
        do
939
        {
924
        {
940
                if(sector != sector_in_buffer)
925
                if(sector != sector_in_buffer)
941
                {
926
                {
942
                        // read this sector to buffer
927
                        // read this sector to buffer
943
                        sector_in_buffer = sector;
928
                        sector_in_buffer = sector;
944
                        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
945
                }
930
                }
946
                // read the next cluster from cache
931
                // read the next cluster from cache
947
                fat = (Fat16Entry_t *)(&(buffer[byte]));
932
                fat = (Fat16Entry_t *)(&(buffer[byte]));
948
                cluster = fat->NextCluster;
933
                cluster = fat->NextCluster;
949
                fat->NextCluster =      FAT16_CLUSTER_FREE; // mark current cluster as free
934
                fat->NextCluster =      FAT16_CLUSTER_FREE; // mark current cluster as free
950
 
935
 
951
                if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) )
936
                if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) )
952
                {
937
                {
953
                        repeat = 1;
938
                        repeat = 1;
954
                        // 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
955
                        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
956
                        // calculate the sector that contains the current cluster within the fat
941
                        // calculate the sector that contains the current cluster within the fat
957
                        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
942
                        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
958
                        // calculate byte offset of the current cluster within that fat sector
943
                        // calculate byte offset of the current cluster within that fat sector
959
                        byte = fat_byte_offset % BYTES_PER_SECTOR;
944
                        byte = fat_byte_offset % BYTES_PER_SECTOR;
960
                }
945
                }
961
                else repeat = 0;
946
                else repeat = 0;
962
 
947
 
963
                // 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
964
                if((sector != sector_in_buffer) || !repeat)
949
                if((sector != sector_in_buffer) || !repeat)
965
                {       // write sector in buffer
950
                {       // write sector in buffer
966
                        if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer))
951
                        if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer))
967
                        {
952
                        {
968
                                Fat16_Deinit();
953
                                Fat16_Deinit();
969
                                return(0);
954
                                return(0);
970
                        }
955
                        }
971
                }
956
                }
972
        }
957
        }
973
        while(repeat);
958
        while(repeat);
974
 
959
 
975
        return 1;
960
        return 1;
976
}
961
}
977
 
962
 
978
 
963
 
979
/****************************************************************************************************************************************/
964
/****************************************************************************************************************************************/
980
/* Function:    u16 AppendCluster(File *file);                                                                                                                                                                                  */
965
/* Function:    u16 AppendCluster(File *file);                                                                                                                                                                                  */
981
/*                                                                                                                                                                                                                                                                              */
966
/*                                                                                                                                                                                                                                                                              */
982
/* 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.                                                                */
983
/*                                                                                                                                                                                                                                                                              */
968
/*                                                                                                                                                                                                                                                                              */
984
/* 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.                                                */
985
/****************************************************************************************************************************************/
970
/****************************************************************************************************************************************/
986
u16 AppendCluster(File_t *file)
971
u16 AppendCluster(File_t *file)
987
{
972
{
988
        u16 last_cluster, new_cluster = CLUSTER_UNDEFINED;
973
        u16 last_cluster, new_cluster = CLUSTER_UNDEFINED;
989
        u32 fat_byte_offset, sector, byte;
974
        u32 fat_byte_offset, sector, byte;
990
        Fat16Entry_t * fat;
975
        Fat16Entry_t * fat;
991
 
976
 
992
 
977
 
993
        if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
978
        if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
994
 
979
 
995
        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.
996
        if(new_cluster != CLUSTER_UNDEFINED)
981
        if(new_cluster != CLUSTER_UNDEFINED)
997
        {       // 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.
998
                // is there at least one cluster appended to the file?
983
                // is there at least one cluster appended to the file?
999
                if(file->FirstSectorOfLastCluster == CLUSTER_UNDEFINED)
984
                if(file->FirstSectorOfLastCluster == CLUSTER_UNDEFINED)
1000
                {
985
                {
1001
                        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
1002
                        // remember the first sector of the last cluster
987
                        // remember the first sector of the last cluster
1003
                        file->FirstSectorOfLastCluster = file->FirstSectorOfCurrCluster;
988
                        file->FirstSectorOfLastCluster = file->FirstSectorOfCurrCluster;
1004
                        last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);            // determine current file cluster
989
                        last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);            // determine current file cluster
1005
                }
990
                }
1006
                else
991
                else
1007
                {
992
                {
1008
                        last_cluster = SectorToFat16Cluster(file->FirstSectorOfLastCluster);            // determine current file cluster
993
                        last_cluster = SectorToFat16Cluster(file->FirstSectorOfLastCluster);            // determine current file cluster
1009
                }
994
                }
1010
 
995
 
1011
                if(last_cluster != CLUSTER_UNDEFINED)
996
                if(last_cluster != CLUSTER_UNDEFINED)
1012
                {
997
                {
1013
                        // update FAT entry of last cluster
998
                        // update FAT entry of last cluster
1014
                        fat_byte_offset = ((u32)last_cluster)<<1;
999
                        fat_byte_offset = ((u32)last_cluster)<<1;
1015
                        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
1000
                        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
1016
                        byte = fat_byte_offset % BYTES_PER_SECTOR;
1001
                        byte = fat_byte_offset % BYTES_PER_SECTOR;
1017
                        // read the sector containing the last cluster of the file
1002
                        // read the sector containing the last cluster of the file
1018
                        if(file->SectorInCache != sector)
1003
                        if(file->SectorInCache != sector)
1019
                        {
1004
                        {
1020
                                file->SectorInCache = sector;   // update sector stored in buffer
1005
                                file->SectorInCache = sector;   // update sector stored in buffer
1021
                                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
1022
                                {
1007
                                {
1023
                                        Fat16_Deinit();
1008
                                        Fat16_Deinit();
1024
                                        return(0);
1009
                                        return(0);
1025
                                }
1010
                                }
1026
                        }
1011
                        }
1027
                        fat = (Fat16Entry_t *)(&(file->Cache[byte]));
1012
                        fat = (Fat16Entry_t *)(&(file->Cache[byte]));
1028
                        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.
1029
                        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.
1030
                        {
1015
                        {
1031
                                Fat16_Deinit();
1016
                                Fat16_Deinit();
1032
                                return(0);
1017
                                return(0);
1033
                        }
1018
                        }
1034
                        // 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
1035
                        file->FirstSectorOfLastCluster = Fat16ClusterToSector(new_cluster);
1020
                        file->FirstSectorOfLastCluster = Fat16ClusterToSector(new_cluster);
1036
                }
1021
                }
1037
                else // last cluster of the file is undefined
1022
                else // last cluster of the file is undefined
1038
                {   // 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
1039
                    // and its cluster number must be set in the direntry
1024
                    // and its cluster number must be set in the direntry
1040
                        DirEntry_t * dir;
1025
                        DirEntry_t * dir;
1041
                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1026
                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1042
                        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.
1043
                        {
1028
                        {
1044
                                Fat16_Deinit();
1029
                                Fat16_Deinit();
1045
                                return(CLUSTER_UNDEFINED);
1030
                                return(CLUSTER_UNDEFINED);
1046
                        }
1031
                        }
1047
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1032
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1048
                        dir[file->DirectoryIndex].Res1 = 0;
1033
                        dir[file->DirectoryIndex].Res1 = 0;
1049
                        dir[file->DirectoryIndex].Res2[0] = 0;
1034
                        dir[file->DirectoryIndex].Res2[0] = 0;
1050
                        dir[file->DirectoryIndex].Res2[1] = 0;
1035
                        dir[file->DirectoryIndex].Res2[1] = 0;
1051
                        dir[file->DirectoryIndex].StartCluster = new_cluster;           // update startcluster
1036
                        dir[file->DirectoryIndex].StartCluster = new_cluster;           // update startcluster
1052
                    dir[file->DirectoryIndex].ModTime   = FileTime(&SystemTime);// set time
1037
                    dir[file->DirectoryIndex].ModTime   = FileTime(&SystemTime);// set time
1053
                        dir[file->DirectoryIndex].ModDate       = FileDate(&SystemTime);// and date of modification
1038
                        dir[file->DirectoryIndex].ModDate       = FileDate(&SystemTime);// and date of modification
1054
                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1039
                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1055
                        dir[file->DirectoryIndex].Size          = 0;
1040
                        dir[file->DirectoryIndex].Size          = 0;
1056
                        // write sector containing the direntry
1041
                        // write sector containing the direntry
1057
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1042
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1058
                        {
1043
                        {
1059
                                Fat16_Deinit();
1044
                                Fat16_Deinit();
1060
                                return(CLUSTER_UNDEFINED);
1045
                                return(CLUSTER_UNDEFINED);
1061
                        }
1046
                        }
1062
                        // update file info
1047
                        // update file info
1063
                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(new_cluster);
1048
                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(new_cluster);
1064
                        file->FirstSectorOfLastCluster = file->FirstSectorOfFirstCluster;
1049
                        file->FirstSectorOfLastCluster = file->FirstSectorOfFirstCluster;
1065
                        file->Size = 0;
1050
                        file->Size = 0;
1066
                        file->Position = 0;
1051
                        file->Position = 0;
1067
                }
1052
                }
1068
                // update file pointes
1053
                // update file pointes
1069
                file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster);
1054
                file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster);
1070
                file->SectorOfCurrCluster = 0;
1055
                file->SectorOfCurrCluster = 0;
1071
                file->ByteOfCurrSector = 0;
1056
                file->ByteOfCurrSector = 0;
1072
        }
1057
        }
1073
        return(new_cluster);
1058
        return(new_cluster);
1074
}
1059
}
1075
 
1060
 
1076
 
1061
 
1077
/****************************************************************************************************************************************************/
1062
/****************************************************************************************************************************************************/
1078
/* Function:    DirectoryEntryExist(s8 *, u8, u8, File_t *)                                                                                                                                                                                     */
1063
/* Function:    DirectoryEntryExist(s8 *, u8, u8, File_t *)                                                                                                                                                                                     */
1079
/*                                                                                                                                                                                                                                                                                                      */
1064
/*                                                                                                                                                                                                                                                                                                      */
1080
/* 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                     */
1081
/*                                                                                                                                                                                                                                                                                                      */
1066
/*                                                                                                                                                                                                                                                                                                      */
1082
/* 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.                                                                                                                                     */
1083
/****************************************************************************************************************************************************/
1068
/****************************************************************************************************************************************************/
1084
u8 DirectoryEntryExist(s8 *dirname, u8 attribfilter, u8 attribmask, File_t *file)
1069
u8 DirectoryEntryExist(s8 *dirname, u8 attribfilter, u8 attribmask, File_t *file)
1085
{
1070
{
1086
        u32             dir_sector, max_dir_sector, curr_sector;
1071
        u32             dir_sector, max_dir_sector, curr_sector;
1087
        u16     dir_entry = 0;
1072
        u16     dir_entry = 0;
1088
 
1073
 
1089
        u16     end_of_directory_not_reached = 0;
1074
        u16     end_of_directory_not_reached = 0;
1090
        u8              i = 0;
1075
        u8              i = 0;
1091
        u8      direntry_exist = 0;
1076
        u8      direntry_exist = 0;
1092
        DirEntry_t * dir;
1077
        DirEntry_t * dir;
1093
 
1078
 
1094
        // incomming pointers are useless?
1079
        // incomming pointers are useless?
1095
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
1080
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
1096
 
1081
 
1097
        // check sector range to be searched
1082
        // check sector range to be searched
1098
 
1083
 
1099
        // no search area defined?
1084
        // no search area defined?
1100
        if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)
1085
        if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)
1101
        {      
1086
        {      
1102
                return(direntry_exist);
1087
                return(direntry_exist);
1103
        }
1088
        }
1104
        //is search area the root?
1089
        //is search area the root?
1105
        else if(Partition.FirstRootDirSector == file->FirstSectorOfFirstCluster)
1090
        else if(Partition.FirstRootDirSector == file->FirstSectorOfFirstCluster)
1106
        {
1091
        {
1107
                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 
1108
                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
1109
        }
1094
        }
1110
        // is search area within the data cluster range?
1095
        // is search area within the data cluster range?
1111
        else if((Partition.FirstDataSector <= file->FirstSectorOfFirstCluster) && (file->FirstSectorOfFirstCluster <= Partition.LastDataSector))
1096
        else if((Partition.FirstDataSector <= file->FirstSectorOfFirstCluster) && (file->FirstSectorOfFirstCluster <= Partition.LastDataSector))
1112
        {
1097
        {
1113
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max sectors before next cluster
1098
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max sectors before next cluster
1114
                /*
1099
                /*
1115
                //there must be a corresponding directory entry
1100
                //there must be a corresponding directory entry
1116
                if(file->DirectorySector == SECTOR_UNDEFINED)
1101
                if(file->DirectorySector == SECTOR_UNDEFINED)
1117
                {
1102
                {
1118
                        return (direntry_exist);       
1103
                        return (direntry_exist);       
1119
                }
1104
                }
1120
                else // check directory entry
1105
                else // check directory entry
1121
                {
1106
                {
1122
                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1107
                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1123
                        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.
1124
                        {
1109
                        {
1125
                                Fat16_Deinit();
1110
                                Fat16_Deinit();
1126
                                return (direntry_exist);
1111
                                return (direntry_exist);
1127
                        }
1112
                        }
1128
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1113
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1129
                        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
1130
                        {
1115
                        {
1131
                                case SLOT_EMPTY:
1116
                                case SLOT_EMPTY:
1132
                                case SLOT_DELETED:
1117
                                case SLOT_DELETED:
1133
                                        // 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
1134
                                        // therefore no file or subdirectory exist here
1119
                                        // therefore no file or subdirectory exist here
1135
                                        return(direntry_exist);
1120
                                        return(direntry_exist);
1136
                                        break;
1121
                                        break;
1137
                                default:        // and is a real directory
1122
                                default:        // and is a real directory
1138
                                        if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1123
                                        if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1139
                                        {       // 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
1140
                                                return(direntry_exist);
1125
                                                return(direntry_exist);
1141
                                        }
1126
                                        }
1142
                                        break;
1127
                                        break;
1143
                        }
1128
                        }
1144
                        // check that search area matches directory entry
1129
                        // check that search area matches directory entry
1145
                        if(file->FirstSectorOfFirstCluster != Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster))
1130
                        if(file->FirstSectorOfFirstCluster != Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster))
1146
                        {
1131
                        {
1147
                                return (direntry_exist);        
1132
                                return (direntry_exist);        
1148
                        }
1133
                        }
1149
                       
1134
                       
1150
                } */
1135
                } */
1151
        }
1136
        }
1152
        else return (direntry_exist); // bad sector range for search area
1137
        else return (direntry_exist); // bad sector range for search area
1153
       
1138
       
1154
        // update current file data area position to start of first cluster
1139
        // update current file data area position to start of first cluster
1155
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1140
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1156
        file->SectorOfCurrCluster               = 0;
1141
        file->SectorOfCurrCluster               = 0;
1157
        file->ByteOfCurrSector                  = 0;
1142
        file->ByteOfCurrSector                  = 0;
1158
 
1143
 
1159
        do // loop over all data clusters of the current directory entry
1144
        do // loop over all data clusters of the current directory entry
1160
        {
1145
        {
1161
                dir_sector = 0;
1146
                dir_sector = 0;
1162
                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
1163
                {
1148
                {
1164
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1149
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1165
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1150
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1166
                        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
1167
                        {
1152
                        {
1168
                                Fat16_Deinit();
1153
                                Fat16_Deinit();
1169
                                return(direntry_exist);
1154
                                return(direntry_exist);
1170
                        }
1155
                        }
1171
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1156
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1172
                        // search all directory entries within that sector
1157
                        // search all directory entries within that sector
1173
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1158
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1174
                        {   // check for existing dir entry
1159
                        {   // check for existing dir entry
1175
                                switch((u8)dir[dir_entry].Name[0])
1160
                                switch((u8)dir[dir_entry].Name[0])
1176
                                {
1161
                                {
1177
                                        case SLOT_EMPTY:
1162
                                        case SLOT_EMPTY:
1178
                                        case SLOT_DELETED:
1163
                                        case SLOT_DELETED:
1179
                                                // ignore empty or deleted dir entries
1164
                                                // ignore empty or deleted dir entries
1180
                                                break;
1165
                                                break;
1181
                                        default:
1166
                                        default:
1182
                                                // if existing check attributes before names are compared will safe performance
1167
                                                // if existing check attributes before names are compared will safe performance
1183
                                                if ((dir[dir_entry].Attribute & attribmask) != attribfilter) break; // attribute must match
1168
                                                if ((dir[dir_entry].Attribute & attribmask) != attribfilter) break; // attribute must match
1184
                                                // 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.)
1185
                                                i = 0;
1170
                                                i = 0;
1186
                                                while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
1171
                                                while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
1187
                                                if (i < 10) break; // names does not match
1172
                                                if (i < 10) break; // names does not match
1188
                                                // if dirname and attribute have matched
1173
                                                // if dirname and attribute have matched
1189
                                                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
1190
                                                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
1191
                                                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1176
                                                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1192
                                                file->SectorOfCurrCluster = 0;
1177
                                                file->SectorOfCurrCluster = 0;
1193
                                                file->ByteOfCurrSector = 0;
1178
                                                file->ByteOfCurrSector = 0;
1194
                                                file->DirectorySector = curr_sector; // current sector
1179
                                                file->DirectorySector = curr_sector; // current sector
1195
                                                file->DirectoryIndex  = dir_entry; // current direntry in current sector
1180
                                                file->DirectoryIndex  = dir_entry; // current direntry in current sector
1196
                                                file->Size = dir[dir_entry].Size;
1181
                                                file->Size = dir[dir_entry].Size;
1197
                                                direntry_exist = 1; // mark as found
1182
                                                direntry_exist = 1; // mark as found
1198
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1183
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1199
                                } // end of first byte of name check
1184
                                } // end of first byte of name check
1200
                        }
1185
                        }
1201
                        dir_sector++; // search next sector
1186
                        dir_sector++; // search next sector
1202
                // 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
1203
                }while((dir_sector < max_dir_sector) && (!direntry_exist));
1188
                }while((dir_sector < max_dir_sector) && (!direntry_exist));
1204
 
1189
 
1205
                // 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.
1206
                if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1191
                if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1207
                {
1192
                {
1208
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1193
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1209
                }
1194
                }
1210
        }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
1211
        return(direntry_exist);
1196
        return(direntry_exist);
1212
}
1197
}
1213
 
1198
 
1214
 
1199
 
1215
/****************************************************************************************************************************************/
1200
/****************************************************************************************************************************************/
1216
/*      Function:               CreateDirectoryEntry(s8 *, u16, File_t *)                                                                                                                                                       */
1201
/*      Function:               CreateDirectoryEntry(s8 *, u16, File_t *)                                                                                                                                                       */
1217
/*                                                                                                                                                                                                                                                                              */
1202
/*                                                                                                                                                                                                                                                                              */
1218
/*      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.                                                           */
1219
/*                                      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.                                                                                                      */
1220
/*                                                                                                                                                                                                                                                                              */
1205
/*                                                                                                                                                                                                                                                                              */
1221
/*      Returnvalue:    Return 0 on error                                                                                                                                                                                                       */
1206
/*      Returnvalue:    Return 0 on error                                                                                                                                                                                                       */
1222
/****************************************************************************************************************************************/
1207
/****************************************************************************************************************************************/
1223
u8 CreateDirectoryEntry(s8 *dirname, u8 attrib, File_t *file)
1208
u8 CreateDirectoryEntry(s8 *dirname, u8 attrib, File_t *file)
1224
{
1209
{
1225
        u32 dir_sector, max_dir_sector, curr_sector;
1210
        u32 dir_sector, max_dir_sector, curr_sector;
1226
        u16 dir_entry   = 0;
1211
        u16 dir_entry   = 0;
1227
        u16 subdircluster, dircluster = 0;
1212
        u16 subdircluster, dircluster = 0;
1228
        u16 end_of_directory_not_reached = 0;
1213
        u16 end_of_directory_not_reached = 0;
1229
        u8      i                       = 0;
1214
        u8      i                       = 0;
1230
        u8      retvalue        = 0;
1215
        u8      retvalue        = 0;
1231
        DirEntry_t *dir;
1216
        DirEntry_t *dir;
1232
 
1217
 
1233
        // incomming pointers are useless?
1218
        // incomming pointers are useless?
1234
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(retvalue);
1219
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(retvalue);
1235
 
1220
 
1236
        // check sector range to be searched
1221
        // check sector range to be searched
1237
 
1222
 
1238
        // no creation area defined?
1223
        // no creation area defined?
1239
        if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)
1224
        if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)
1240
        {      
1225
        {      
1241
                return(retvalue);
1226
                return(retvalue);
1242
        }
1227
        }
1243
        //is creation area the root?
1228
        //is creation area the root?
1244
        else if(Partition.FirstRootDirSector == file->FirstSectorOfFirstCluster)
1229
        else if(Partition.FirstRootDirSector == file->FirstSectorOfFirstCluster)
1245
        {
1230
        {
1246
                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 
1247
                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
1248
        }
1233
        }
1249
        // is creation area within the data cluster range?
1234
        // is creation area within the data cluster range?
1250
        else if((Partition.FirstDataSector <= file->FirstSectorOfFirstCluster) && (file->FirstSectorOfFirstCluster <= Partition.LastDataSector))
1235
        else if((Partition.FirstDataSector <= file->FirstSectorOfFirstCluster) && (file->FirstSectorOfFirstCluster <= Partition.LastDataSector))
1251
        {
1236
        {
1252
                max_dir_sector = Partition.SectorsPerCluster;                                   // limit max sectors before next cluster
1237
                max_dir_sector = Partition.SectorsPerCluster;                                   // limit max sectors before next cluster
1253
                // there must be a corresponding directory entry
1238
                // there must be a corresponding directory entry
1254
                if(file->DirectorySector == SECTOR_UNDEFINED)
1239
                if(file->DirectorySector == SECTOR_UNDEFINED)
1255
                {
1240
                {
1256
                        return (retvalue);     
1241
                        return (retvalue);     
1257
                }
1242
                }
1258
                else // check directory entry
1243
                else // check directory entry
1259
                {
1244
                {
1260
                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1245
                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1261
                        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.
1262
                        {
1247
                        {
1263
                                Fat16_Deinit();
1248
                                Fat16_Deinit();
1264
                                return (retvalue);
1249
                                return (retvalue);
1265
                        }
1250
                        }
1266
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1251
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1267
                        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
1268
                        {
1253
                        {
1269
                                case SLOT_EMPTY:
1254
                                case SLOT_EMPTY:
1270
                                case SLOT_DELETED:
1255
                                case SLOT_DELETED:
1271
                                        // 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
1272
                                        // therefore no file or subdirectory exist here
1257
                                        // therefore no file or subdirectory exist here
1273
                                        return(retvalue);
1258
                                        return(retvalue);
1274
                                        break;
1259
                                        break;
1275
                                default:        // and is a real directory
1260
                                default:        // and is a real directory
1276
                                        if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1261
                                        if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1277
                                        {       // 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
1278
                                                return(retvalue);
1263
                                                return(retvalue);
1279
                                        }
1264
                                        }
1280
                                        break;
1265
                                        break;
1281
                        }
1266
                        }
1282
                        // check that search area matches directory entry
1267
                        // check that search area matches directory entry
1283
                        if(file->FirstSectorOfFirstCluster != Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster))
1268
                        if(file->FirstSectorOfFirstCluster != Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster))
1284
                        {
1269
                        {
1285
                                return (retvalue);      
1270
                                return (retvalue);      
1286
                        }
1271
                        }
1287
                }
1272
                }
1288
        }
1273
        }
1289
        else return(retvalue); // bad sector range for search area
1274
        else return(retvalue); // bad sector range for search area
1290
 
1275
 
1291
        // if the new directory entry is a subdirectory
1276
        // if the new directory entry is a subdirectory
1292
        if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)
1277
        if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)
1293
        {       // get a free cluster for its content
1278
        {       // get a free cluster for its content
1294
                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.
1295
        }
1280
        }
1296
        else // a normal file
1281
        else // a normal file
1297
        {       // has no data cluster after creation
1282
        {       // has no data cluster after creation
1298
                subdircluster = CLUSTER_UNDEFINED;
1283
                subdircluster = CLUSTER_UNDEFINED;
1299
        }
1284
        }
1300
 
1285
 
1301
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1286
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1302
        file->SectorOfCurrCluster               = 0;
1287
        file->SectorOfCurrCluster               = 0;
1303
        do // loop over all clusters of current directory
1288
        do // loop over all clusters of current directory
1304
        {
1289
        {
1305
                dir_sector = 0; // reset sector counter within a new cluster
1290
                dir_sector = 0; // reset sector counter within a new cluster
1306
                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
1307
                {
1292
                {
1308
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1293
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1309
                        file->SectorInCache = curr_sector;                                                      // update the sector number of file cache.
1294
                        file->SectorInCache = curr_sector;                                                      // update the sector number of file cache.
1310
                        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.
1311
                        {
1296
                        {
1312
                                Fat16_Deinit();
1297
                                Fat16_Deinit();
1313
                                return(retvalue);
1298
                                return(retvalue);
1314
                        }
1299
                        }
1315
 
1300
 
1316
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1301
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1317
                        // search all directory entries of a sector
1302
                        // search all directory entries of a sector
1318
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1303
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1319
                        {       // check if current direntry is available
1304
                        {       // check if current direntry is available
1320
                                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))
1321
                                {       // a free direntry was found
1306
                                {       // a free direntry was found
1322
                                        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
1323
                                        dir[dir_entry].Attribute    = attrib;
1308
                                        dir[dir_entry].Attribute    = attrib;
1324
                                        dir[dir_entry].Res1 = 0;
1309
                                        dir[dir_entry].Res1 = 0;
1325
                                        dir[dir_entry].CreationTime10ms = (u8)(SystemTime.mSec/10);
1310
                                        dir[dir_entry].CreationTime10ms = (u8)(SystemTime.mSec/10);
1326
                                        dir[dir_entry].CreationTime     = FileTime(&SystemTime);
1311
                                        dir[dir_entry].CreationTime     = FileTime(&SystemTime);
1327
                                        dir[dir_entry].CreationDate     = FileDate(&SystemTime);
1312
                                        dir[dir_entry].CreationDate     = FileDate(&SystemTime);
1328
                                        dir[dir_entry].LastAccessDate = dir[dir_entry].CreationDate;
1313
                                        dir[dir_entry].LastAccessDate = dir[dir_entry].CreationDate;
1329
                                        dir[dir_entry].Res2[0] = 0;
1314
                                        dir[dir_entry].Res2[0] = 0;
1330
                                        dir[dir_entry].Res2[1] = 0;
1315
                                        dir[dir_entry].Res2[1] = 0;
1331
                                        dir[dir_entry].ModTime = dir[dir_entry].CreationTime;
1316
                                        dir[dir_entry].ModTime = dir[dir_entry].CreationTime;
1332
                                        dir[dir_entry].ModDate = dir[dir_entry].CreationDate;
1317
                                        dir[dir_entry].ModDate = dir[dir_entry].CreationDate;
1333
                                        // Set the attribute of the new directoryentry.
1318
                                        // Set the attribute of the new directoryentry.
1334
                                        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.
1335
                                        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.
1336
                                        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
1337
                                        {
1322
                                        {
1338
                                                Fat16_Deinit();
1323
                                                Fat16_Deinit();
1339
                                                return(retvalue);
1324
                                                return(retvalue);
1340
                                        }
1325
                                        }
1341
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster);  // Calculate absolute sectorposition of first datacluster.
1326
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster);  // Calculate absolute sectorposition of first datacluster.
1342
                                        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.
1343
                                        file->SectorOfCurrCluster               = 0;                                                            // reset sector of cureen cluster
1328
                                        file->SectorOfCurrCluster               = 0;                                                            // reset sector of cureen cluster
1344
                                        file->ByteOfCurrSector                  = 0;                                                            // reset the byte location within the current sector
1329
                                        file->ByteOfCurrSector                  = 0;                                                            // reset the byte location within the current sector
1345
                                        file->Attribute                                 = attrib;                                               // set file attribute to dir attribute
1330
                                        file->Attribute                                 = attrib;                                               // set file attribute to dir attribute
1346
                                        file->Size                                              = 0;                                                        // new file has no size
1331
                                        file->Size                                              = 0;                                                        // new file has no size
1347
                                        file->DirectorySector                   = curr_sector;
1332
                                        file->DirectorySector                   = curr_sector;
1348
                                        file->DirectoryIndex                    = dir_entry;
1333
                                        file->DirectoryIndex                    = dir_entry;
1349
                                        // prepare subdirectory data cluster
1334
                                        // prepare subdirectory data cluster
1350
                                        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
1351
                                        {
1336
                                        {
1352
                                                ClearCurrCluster(file); // fill cluster with zeros
1337
                                                ClearCurrCluster(file); // fill cluster with zeros
1353
                                                file->SectorInCache = file->FirstSectorOfFirstCluster;
1338
                                                file->SectorInCache = file->FirstSectorOfFirstCluster;
1354
                                                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.
1355
                                                {
1340
                                                {
1356
                                                        Fat16_Deinit();
1341
                                                        Fat16_Deinit();
1357
                                                        return(retvalue);
1342
                                                        return(retvalue);
1358
                                                }
1343
                                                }
1359
                                                dir = (DirEntry_t *)file->Cache;
1344
                                                dir = (DirEntry_t *)file->Cache;
1360
                                                // create direntry "." to current dir
1345
                                                // create direntry "." to current dir
1361
                                                dir[0].Name[0] = 0x2E;
1346
                                                dir[0].Name[0] = 0x2E;
1362
                                                for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
1347
                                                for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
1363
                                                dir[0].Attribute = ATTR_SUBDIRECTORY;
1348
                                                dir[0].Attribute = ATTR_SUBDIRECTORY;
1364
                                                dir[0].StartCluster = subdircluster;
1349
                                                dir[0].StartCluster = subdircluster;
1365
                                                dir[0].Size = 0;
1350
                                                dir[0].Size = 0;
1366
                                                // create direntry ".." to the upper dir
1351
                                                // create direntry ".." to the upper dir
1367
                                                dir[1].Name[0] = 0x2E;
1352
                                                dir[1].Name[0] = 0x2E;
1368
                                                dir[1].Name[1] = 0x2E;
1353
                                                dir[1].Name[1] = 0x2E;
1369
                                                for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
1354
                                                for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
1370
                                                dir[1].Attribute = ATTR_SUBDIRECTORY;
1355
                                                dir[1].Attribute = ATTR_SUBDIRECTORY;
1371
                                                dir[1].StartCluster = dircluster;
1356
                                                dir[1].StartCluster = dircluster;
1372
                                                dir[1].Size = 0;
1357
                                                dir[1].Size = 0;
1373
                                                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.
1374
                                                {
1359
                                                {
1375
                                                        Fat16_Deinit();
1360
                                                        Fat16_Deinit();
1376
                                                        return(retvalue);
1361
                                                        return(retvalue);
1377
                                                }
1362
                                                }
1378
                                        }
1363
                                        }
1379
                                        retvalue = 1;
1364
                                        retvalue = 1;
1380
                                        dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1365
                                        dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1381
                                }
1366
                                }
1382
                        }
1367
                        }
1383
                        dir_sector++; // search next sector
1368
                        dir_sector++; // search next sector
1384
                // 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
1385
                }while((dir_sector < max_dir_sector) && (!retvalue));
1370
                }while((dir_sector < max_dir_sector) && (!retvalue));
1386
 
1371
 
1387
                // 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.
1388
                if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1373
                if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1389
                {
1374
                {
1390
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1375
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1391
                }
1376
                }
1392
        }while((end_of_directory_not_reached) && (!retvalue));
1377
        }while((end_of_directory_not_reached) && (!retvalue));
1393
        // 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.
1394
        // 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.
1395
        // 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
1396
        // within a subdirectory of root.
1381
        // within a subdirectory of root.
1397
 
1382
 
1398
        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.
1399
}
1384
}
1400
 
1385
 
1401
/********************************************************************************************************************************************/
1386
/********************************************************************************************************************************************/
1402
/*      Function:               u8 DeleteDirectoryEntry(File_t *file)                                                                                                                                                                   */
1387
/*      Function:               u8 DeleteDirectoryEntry(File_t *file)                                                                                                                                                                   */
1403
/*      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                                                                  */
1404
/*                                                                                                                                                                                                                                      */
1389
/*                                                                                                                                                                                                                                      */
1405
/*                                                                                                                                                                                                                                                                                      */
1390
/*                                                                                                                                                                                                                                                                                      */
1406
/*      Returnvalue:    1 on succes and 0 on error                                                                                                                                                                                              */
1391
/*      Returnvalue:    1 on succes and 0 on error                                                                                                                                                                                              */
1407
/********************************************************************************************************************************************/
1392
/********************************************************************************************************************************************/
1408
u8 DeleteDirectoryEntry(File_t *file)
1393
u8 DeleteDirectoryEntry(File_t *file)
1409
{
1394
{
1410
        DirEntry_t *DirectoryEntry = NULL;
1395
        DirEntry_t *DirectoryEntry = NULL;
1411
        u8 retval = 0;
1396
        u8 retval = 0;
1412
 
1397
 
1413
        if((!Partition.IsValid) || (file == NULL)) return (retval);
1398
        if((!Partition.IsValid) || (file == NULL)) return (retval);
1414
        // valid directory sector?
1399
        // valid directory sector?
1415
        if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.LastDataSector))
1400
        if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.LastDataSector))
1416
        {
1401
        {
1417
                // 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 
1418
                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);
1419
                // get access to the elements of the directoryentry
1404
                // get access to the elements of the directoryentry
1420
                DirectoryEntry = (DirEntry_t *)file->Cache;
1405
                DirectoryEntry = (DirEntry_t *)file->Cache;
1421
                // delete the directoryentry
1406
                // delete the directoryentry
1422
                DirectoryEntry[file->DirectoryIndex].Name[0] = SLOT_DELETED;
1407
                DirectoryEntry[file->DirectoryIndex].Name[0] = SLOT_DELETED;
1423
                DirectoryEntry[file->DirectoryIndex].Attribute = 0;
1408
                DirectoryEntry[file->DirectoryIndex].Attribute = 0;
1424
                DirectoryEntry[file->DirectoryIndex].Size = 0;
1409
                DirectoryEntry[file->DirectoryIndex].Size = 0;
1425
                // 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 
1426
                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;
1427
        }
1412
        }
1428
        return(retval);
1413
        return(retval);
1429
}
1414
}
1430
 
1415
 
1431
/********************************************************************************************************************************************/
1416
/********************************************************************************************************************************************/
1432
/*      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);                                                                                    */
1433
/*                                                                                                                                                                                                                                                                                      */
1418
/*                                                                                                                                                                                                                                                                                      */
1434
/*      Description:    This function looks for the specified file including its subdirectories.                                                                                                */
1419
/*      Description:    This function looks for the specified file including its subdirectories.                                                                                                */
1435
/*                  If the file is found the Filepointer properties are updated.                                                                                                                        */
1420
/*                  If the file is found the Filepointer properties are updated.                                                                                                                        */
1436
/*                                                                                                                                                                                                                                                                                      */
1421
/*                                                                                                                                                                                                                                                                                      */
1437
/*      Returnvalue:    1 if file is found else 0.                                                                                                                                                                                              */
1422
/*      Returnvalue:    1 if file is found else 0.                                                                                                                                                                                              */
1438
/********************************************************************************************************************************************/
1423
/********************************************************************************************************************************************/
1439
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)
1440
{
1425
{
1441
        s8* path = 0;
1426
        s8* path = 0;
1442
        s8* subpath = 0;
1427
        s8* subpath = 0;
1443
        u8 af, am, file_exist = 0;
1428
        u8 af, am, file_exist = 0;
1444
        s8 dirname[12]; // 8+3 + temination character
1429
        s8 dirname[12]; // 8+3 + temination character
1445
 
1430
 
1446
        // if incomming pointers are useless return immediatly
1431
        // if incomming pointers are useless return immediatly
1447
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1432
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1448
 
1433
 
1449
        // trace along the filepath
1434
        // trace along the filepath
1450
        path = (s8*)filename;                                                           // start at the beginning of the filename string
1435
        path = (s8*)filename;                                                           // start at the beginning of the filename string
1451
        file->DirectoryIndex = 0;                                                       // start search at first dir entry of cluster
1436
        file->DirectoryIndex = 0;                                                       // start search at first dir entry of cluster
1452
        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
1453
        {
1438
        {
1454
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;         // start at RootDirectory with file search      
1439
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;         // start at RootDirectory with file search      
1455
        }
1440
        }
1456
        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
1457
        {
1442
        {
1458
                file->FirstSectorOfFirstCluster = Partition.CurrentWorkingDirectory;
1443
                file->FirstSectorOfFirstCluster = Partition.CurrentWorkingDirectory;
1459
        }
1444
        }
1460
        // 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
1461
        while((*path != 0) && !file_exist)
1446
        while((*path != 0) && !file_exist)
1462
        {       // separate dirname and subpath from filepath string
1447
        {       // separate dirname and subpath from filepath string
1463
                subpath = SeperateFormatedDirName(path, dirname);
1448
                subpath = SeperateFormatedDirName(path, dirname);
1464
                if(subpath != NULL)
1449
                if(subpath != NULL)
1465
                {
1450
                {
1466
                        if(*subpath == 0)
1451
                        if(*subpath == 0)
1467
                        {       // empty subpath indicates last element of dir chain
1452
                        {       // empty subpath indicates last element of dir chain
1468
                                af = attribfilter;
1453
                                af = attribfilter;
1469
                                am = attribmask;
1454
                                am = attribmask;
1470
                        }
1455
                        }
1471
                        else  // it must be a subdirectory and no volume label
1456
                        else  // it must be a subdirectory and no volume label
1472
                        {
1457
                        {
1473
                                af = ATTR_SUBDIRECTORY;
1458
                                af = ATTR_SUBDIRECTORY;
1474
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1459
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1475
                        }
1460
                        }
1476
                        if(!DirectoryEntryExist(dirname, af, am, file))
1461
                        if(!DirectoryEntryExist(dirname, af, am, file))
1477
                        {
1462
                        {
1478
                                return(file_exist); // subdirectory does not exist
1463
                                return(file_exist); // subdirectory does not exist
1479
                        }
1464
                        }
1480
                        else
1465
                        else
1481
                        {
1466
                        {
1482
                                if (*subpath == 0)
1467
                                if (*subpath == 0)
1483
                                {
1468
                                {
1484
                                        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
1485
                                }
1470
                                }
1486
                        }
1471
                        }
1487
                }
1472
                }
1488
                else // error seperating the subpath
1473
                else // error seperating the subpath
1489
                {
1474
                {
1490
                        return(file_exist); // bad subdir format
1475
                        return(file_exist); // bad subdir format
1491
                }
1476
                }
1492
                path = subpath;
1477
                path = subpath;
1493
                subpath = 0;
1478
                subpath = 0;
1494
        }
1479
        }
1495
        return(file_exist);
1480
        return(file_exist);
1496
}
1481
}
1497
 
1482
 
1498
 
1483
 
1499
/********************************************************************************************************************************************/
1484
/********************************************************************************************************************************************/
1500
/*      Function:               FileCreate(const s8* filename, u8 attrib, File_t *file);                                                                                                                                */
1485
/*      Function:               FileCreate(const s8* filename, u8 attrib, File_t *file);                                                                                                                                */
1501
/*                                                                                                                                                                                                                                                                                      */
1486
/*                                                                                                                                                                                                                                                                                      */
1502
/*      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                                                                               */
1503
/*                                      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                                                              */
1504
/*                                      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                                                                                               */
1505
/*                                                                                                                                                                                                                                                                                      */
1490
/*                                                                                                                                                                                                                                                                                      */
1506
/*      Returnvalue:    1 if file was created else 0.                                                                                                                                                                                   */
1491
/*      Returnvalue:    1 if file was created else 0.                                                                                                                                                                                   */
1507
/********************************************************************************************************************************************/
1492
/********************************************************************************************************************************************/
1508
u8 FileCreate(const s8* filename, const u8 attrib, File_t *file)
1493
u8 FileCreate(const s8* filename, const u8 attrib, File_t *file)
1509
{
1494
{
1510
        s8 *path = 0;
1495
        s8 *path = 0;
1511
        s8 *subpath = 0;
1496
        s8 *subpath = 0;
1512
        u8 af, am, file_created = 0;
1497
        u8 af, am, file_created = 0;
1513
        s8 dirname[12];
1498
        s8 dirname[12];
1514
        s8 txt[60];
1499
        s8 txt[60];
1515
        u8 i=0;
1500
        u8 i=0;
1516
 
1501
 
1517
        // if incomming pointers are useless return immediatly
1502
        // if incomming pointers are useless return immediatly
1518
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return(0);
1503
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return(0);
1519
 
1504
 
1520
        // trace along the filepath
1505
        // trace along the filepath
1521
        path = (s8*)filename;
1506
        path = (s8*)filename;
1522
 
1507
 
1523
        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
1524
        {
1509
        {
1525
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;         // start at RootDirectory with file search      
1510
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;         // start at RootDirectory with file search      
1526
        }
1511
        }
1527
        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
1528
        {
1513
        {
1529
                file->FirstSectorOfFirstCluster = Partition.CurrentWorkingDirectory;
1514
                file->FirstSectorOfFirstCluster = Partition.CurrentWorkingDirectory;
1530
        }
1515
        }
1531
        file->DirectoryIndex = 0;
1516
        file->DirectoryIndex = 0;
1532
 
1517
 
1533
        // 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
1534
        while((*path != 0) && !file_created)
1519
        while((*path != 0) && !file_created)
1535
        {   // separate dirname and subpath from filepath string
1520
        {   // separate dirname and subpath from filepath string
1536
                subpath = SeperateFormatedDirName(path, dirname);
1521
                subpath = SeperateFormatedDirName(path, dirname);
1537
                if(subpath != NULL)
1522
                if(subpath != NULL)
1538
                {
1523
                {
1539
                        if(*subpath == 0)
1524
                        if(*subpath == 0)
1540
                        {       // empty subpath indicates last element of dir chain
1525
                        {       // empty subpath indicates last element of dir chain
1541
                                af = ATTR_NONE;
1526
                                af = ATTR_NONE;
1542
                                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
1543
                        }
1528
                        }
1544
                        else  // it must be a subdirectory but no volume label
1529
                        else  // it must be a subdirectory but no volume label
1545
                        {
1530
                        {
1546
                                af = ATTR_SUBDIRECTORY;
1531
                                af = ATTR_SUBDIRECTORY;
1547
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1532
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1548
                        }
1533
                        }
1549
                        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
1550
                        {  // try to create subdir or file
1535
                        {  // try to create subdir or file
1551
                                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
1552
                                if(!CreateDirectoryEntry(dirname, af, file))
1537
                                if(!CreateDirectoryEntry(dirname, af, file))
1553
                                {       // could not be created
1538
                                {       // could not be created
1554
                                        return(file_created);
1539
                                        return(file_created);
1555
                                }
1540
                                }
1556
                                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
1557
                        }
1542
                        }
1558
                        sprintf(txt+i, "s:%06d",file->FirstSectorOfFirstCluster);
1543
                        sprintf(txt+i, "s:%06d",file->FirstSectorOfFirstCluster);
1559
                        i+=8;
1544
                        i+=8;
1560
                }
1545
                }
1561
                else // error seperating the subpath
1546
                else // error seperating the subpath
1562
                {
1547
                {
1563
                        return(file_created); // bad subdir format
1548
                        return(file_created); // bad subdir format
1564
                }
1549
                }
1565
                path = subpath;
1550
                path = subpath;
1566
                subpath = NULL;
1551
                subpath = NULL;
1567
        }
1552
        }
1568
        Debug(txt);
1553
        Debug(txt);
1569
        return(file_created);
1554
        return(file_created);
1570
}
1555
}
1571
 
1556
 
1572
 
1557
 
1573
/********************************************************************************************************************************************/
1558
/********************************************************************************************************************************************/
1574
/*      Function:               void Slashing_Path(s8*)                                                                                                                                                                                                 */
1559
/*      Function:               void Slashing_Path(s8*)                                                                                                                                                                                                 */
1575
/*                                                                                                                                                                                                                                                                                      */
1560
/*                                                                                                                                                                                                                                                                                      */
1576
/*      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                                                                              */
1577
/*                                                                                                                                                                                                                                      */
1562
/*                                                                                                                                                                                                                                      */
1578
/*                                                                                                                                                                                                                                                                                      */
1563
/*                                                                                                                                                                                                                                                                                      */
1579
/*      Returnvalue:                                                                                                                                                                                                                                                    */
1564
/*      Returnvalue:                                                                                                                                                                                                                                                    */
1580
/********************************************************************************************************************************************/
1565
/********************************************************************************************************************************************/
1581
void Slashing_Path(s8* path)
1566
void Slashing_Path(s8* path)
1582
{
1567
{
1583
        s8 *cptr = path;
1568
        s8 *cptr = path;
1584
        while(*cptr != 0 )
1569
        while(*cptr != 0 )
1585
        {
1570
        {
1586
                if(*cptr == '\\') *cptr = '/'; // replace \ by /
1571
                if(*cptr == '\\') *cptr = '/'; // replace \ by /
1587
                cptr++;
1572
                cptr++;
1588
        }
1573
        }
1589
}
1574
}
1590
 
1575
 
1591
/********************************************************************************************************************************************/
1576
/********************************************************************************************************************************************/
1592
/*      Function:               File_t * fopen_(s8* filename, s8 mode);                                                                                                                                                                 */
1577
/*      Function:               File_t * fopen_(s8* filename, s8 mode);                                                                                                                                                                 */
1593
/*                                                                                                                                                                                                                                                                                      */
1578
/*                                                                                                                                                                                                                                                                                      */
1594
/*      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    */
1595
/*                                      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.    */
1596
/*                                                                                                                                                                                                                                                                                      */
1581
/*                                                                                                                                                                                                                                                                                      */
1597
/*      Returnvalue:    The filepointer to the file or 0 if faild.                                                                                                                                                              */
1582
/*      Returnvalue:    The filepointer to the file or 0 if faild.                                                                                                                                                              */
1598
/********************************************************************************************************************************************/
1583
/********************************************************************************************************************************************/
1599
File_t * fopen_(s8* const filename, const s8 mode)
1584
File_t * fopen_(s8* const filename, const s8 mode)
1600
{
1585
{
1601
        File_t *file    = 0;
1586
        File_t *file    = 0;
1602
        s8 *cptr;
1587
        s8 *cptr;
1603
 
1588
 
1604
        if((!Partition.IsValid) || (filename == 0)) return(file);
1589
        if((!Partition.IsValid) || (filename == 0)) return(file);
1605
 
1590
 
1606
        // Look for an unused filepointer in the file pointer list?
1591
        // Look for an unused filepointer in the file pointer list?
1607
        file = LockFilePointer();
1592
        file = LockFilePointer();
1608
        // if no unused file pointer was found return 0
1593
        // if no unused file pointer was found return 0
1609
        if(file == NULL) return(file);
1594
        if(file == NULL) return(file);
1610
 
1595
 
1611
        // now we have found a free filepointer and claimed it
1596
        // now we have found a free filepointer and claimed it
1612
        file->Mode                                              = mode;         // mode of fileoperation (read,write)
1597
        file->Mode                                              = mode;         // mode of fileoperation (read,write)
1613
        file->Attribute                                 = 0;            // the attribute of the file opened.
1598
        file->Attribute                                 = 0;            // the attribute of the file opened.
1614
 
1599
 
1615
        // bring the path into the correct syntax
1600
        // bring the path into the correct syntax
1616
        Slashing_Path(filename);
1601
        Slashing_Path(filename);
1617
        cptr = filename;
1602
        cptr = filename;
1618
 
1603
 
1619
        // 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
1620
        if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
1605
        if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
1621
        {  // file exist
1606
        {  // file exist
1622
                switch(mode)  // check mode
1607
                switch(mode)  // check mode
1623
                {
1608
                {
1624
                        case 'a':       // if mode is: append to file
1609
                        case 'a':       // if mode is: append to file
1625
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1610
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1626
                                {       // file is marked as readonly --> do not open this file
1611
                                {       // file is marked as readonly --> do not open this file
1627
                                        fclose_(file);
1612
                                        fclose_(file);
1628
                                        file = NULL;
1613
                                        file = NULL;
1629
                                }
1614
                                }
1630
                                else
1615
                                else
1631
                                {       // file is not marked as read only --> goto end of file
1616
                                {       // file is not marked as read only --> goto end of file
1632
                                        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
1633
                                }
1618
                                }
1634
                                break;
1619
                                break;
1635
                        case 'w':       // if mode is: write to file
1620
                        case 'w':       // if mode is: write to file
1636
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1621
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1637
                                {       // file is marked as readonly --> do not open this file
1622
                                {       // file is marked as readonly --> do not open this file
1638
                                        fclose_(file);
1623
                                        fclose_(file);
1639
                                        file = NULL;
1624
                                        file = NULL;
1640
                                }
1625
                                }
1641
                                else
1626
                                else
1642
                                {       // file is not marked as read only
1627
                                {       // file is not marked as read only
1643
                                        DirEntry_t * dir;
1628
                                        DirEntry_t * dir;
1644
                                        // free all clusters of that file
1629
                                        // free all clusters of that file
1645
                                        DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster));
1630
                                        DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster));
1646
                                        // update directory entry of that file
1631
                                        // update directory entry of that file
1647
                                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1632
                                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1648
                                        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.
1649
                                        {
1634
                                        {
1650
                                                Fat16_Deinit();
1635
                                                Fat16_Deinit();
1651
                                                return(NULL);
1636
                                                return(NULL);
1652
                                        }
1637
                                        }
1653
                                        dir = (DirEntry_t *)file->Cache;                                                                // set pointer to directory
1638
                                        dir = (DirEntry_t *)file->Cache;                                                                // set pointer to directory
1654
                                    dir[file->DirectoryIndex].ModTime   = FileTime(&SystemTime);        // set modification time
1639
                                    dir[file->DirectoryIndex].ModTime   = FileTime(&SystemTime);        // set modification time
1655
                                        dir[file->DirectoryIndex].ModDate       = FileDate(&SystemTime);        // set modification date
1640
                                        dir[file->DirectoryIndex].ModDate       = FileDate(&SystemTime);        // set modification date
1656
                                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1641
                                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1657
                                        dir[file->DirectoryIndex].StartCluster = CLUSTER_UNDEFINED;             // update startcluster
1642
                                        dir[file->DirectoryIndex].StartCluster = CLUSTER_UNDEFINED;             // update startcluster
1658
                                        dir[file->DirectoryIndex].Size          = 0;
1643
                                        dir[file->DirectoryIndex].Size          = 0;
1659
                                        // write sector containing the direntry
1644
                                        // write sector containing the direntry
1660
                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1645
                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1661
                                        {
1646
                                        {
1662
                                                Fat16_Deinit();
1647
                                                Fat16_Deinit();
1663
                                                return(NULL);
1648
                                                return(NULL);
1664
                                        }
1649
                                        }
1665
                                        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
1650
                                        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
1666
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1651
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1667
                                        file->SectorOfCurrCluster = 0;
1652
                                        file->SectorOfCurrCluster = 0;
1668
                                        file->ByteOfCurrSector = 0;
1653
                                        file->ByteOfCurrSector = 0;
1669
                                        file->Size = 0;
1654
                                        file->Size = 0;
1670
                                        file->Position = 0;
1655
                                        file->Position = 0;
1671
                                        fseek_(file, 0, SEEK_SET);
1656
                                        fseek_(file, 0, SEEK_SET);
1672
                                }
1657
                                }
1673
                                break;
1658
                                break;
1674
                        case 'r':       // if mode is: read from file
1659
                        case 'r':       // if mode is: read from file
1675
                                // goto end of file
1660
                                // goto end of file
1676
                                fseek_(file, 0, SEEK_SET);
1661
                                fseek_(file, 0, SEEK_SET);
1677
                                break;
1662
                                break;
1678
                        default: // other modes are not supported
1663
                        default: // other modes are not supported
1679
                                fclose_(file);
1664
                                fclose_(file);
1680
                                file = NULL;
1665
                                file = NULL;
1681
                        break;
1666
                        break;
1682
                }
1667
                }
1683
                return(file);
1668
                return(file);
1684
        }
1669
        }
1685
        else // file does not exist
1670
        else // file does not exist
1686
        {
1671
        {
1687
                switch(mode)  // check mode
1672
                switch(mode)  // check mode
1688
                {
1673
                {
1689
                        case 'a':
1674
                        case 'a':
1690
                        case 'w': // if mode is write or append
1675
                        case 'w': // if mode is write or append
1691
                                // try to create the file
1676
                                // try to create the file
1692
                                if(!FileCreate(filename, ATTR_ARCHIVE, file))
1677
                                if(!FileCreate(filename, ATTR_ARCHIVE, file))
1693
                                { // if it could not be created
1678
                                { // if it could not be created
1694
                                        fclose_(file);
1679
                                        fclose_(file);
1695
                                        file = NULL;
1680
                                        file = NULL;
1696
                                }
1681
                                }
1697
                                break;
1682
                                break;
1698
                        case 'r': // else opened for 'r'
1683
                        case 'r': // else opened for 'r'
1699
                        default:  // if unsupported mode
1684
                        default:  // if unsupported mode
1700
                                fclose_(file);
1685
                                fclose_(file);
1701
                                file = NULL;
1686
                                file = NULL;
1702
                                break;
1687
                                break;
1703
                }
1688
                }
1704
                return(file);
1689
                return(file);
1705
        }
1690
        }
1706
        // we should never come to this point
1691
        // we should never come to this point
1707
        fclose_(file);
1692
        fclose_(file);
1708
        file = NULL;
1693
        file = NULL;
1709
        return(file);
1694
        return(file);
1710
}
1695
}
1711
 
1696
 
1712
/****************************************************************************************************************************************************/
1697
/****************************************************************************************************************************************************/
1713
/* Function:    s16 fseek_(File_t *, s32 *, u8)                                                                                                                                                                                                         */
1698
/* Function:    s16 fseek_(File_t *, s32 *, u8)                                                                                                                                                                                                         */
1714
/*                                                                                                                                                                                                                                                                                                      */
1699
/*                                                                                                                                                                                                                                                                                                      */
1715
/* 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                                                                                                                           */
1716
/*                              specified by origin (SEEK_SET, SEEK_CUR, SEEK_END)                                                                                                                                                                      */
1701
/*                              specified by origin (SEEK_SET, SEEK_CUR, SEEK_END)                                                                                                                                                                      */
1717
/* Returnvalue: Is 0 if seek was successful                                                                                                                                                                                                                     */
1702
/* Returnvalue: Is 0 if seek was successful                                                                                                                                                                                                                     */
1718
/****************************************************************************************************************************************************/
1703
/****************************************************************************************************************************************************/
1719
s16 fseek_(File_t *file, s32 offset, s16 origin)
1704
s16 fseek_(File_t *file, s32 offset, s16 origin)
1720
{
1705
{
1721
        s32             fposition       = 0;
1706
        s32             fposition       = 0;
1722
        s16     retvalue        = 1;
1707
        s16     retvalue        = 1;
1723
        u32             byte_index       = 0;   // the byteindex within a sector
1708
        u32             byte_index       = 0;   // the byteindex within a sector
1724
        u32             sector_index  = 0;      // the  sectorindex within a cluster
1709
        u32             sector_index  = 0;      // the  sectorindex within a cluster
1725
        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
1726
 
1711
 
1727
        // check if the partition is valid
1712
        // check if the partition is valid
1728
        if((!Partition.IsValid) || (file == NULL)) return(retvalue);
1713
        if((!Partition.IsValid) || (file == NULL)) return(retvalue);
1729
        switch(origin)
1714
        switch(origin)
1730
        {
1715
        {
1731
                case SEEK_SET:                          // Fileposition relative to the beginning of the file.
1716
                case SEEK_SET:                          // Fileposition relative to the beginning of the file.
1732
                        fposition = 0;
1717
                        fposition = 0;
1733
                        break;
1718
                        break;
1734
                case SEEK_END:                          // Fileposition relative to the end of the file.
1719
                case SEEK_END:                          // Fileposition relative to the end of the file.
1735
                        fposition = (s32)file->Size;
1720
                        fposition = (s32)file->Size;
1736
                        break;
1721
                        break;
1737
                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.
1738
                default:
1723
                default:
1739
                        fposition = file->Position;
1724
                        fposition = file->Position;
1740
                        break;
1725
                        break;
1741
        }
1726
        }
1742
 
1727
 
1743
        // calculate the specified fileposition according to the selected mode
1728
        // calculate the specified fileposition according to the selected mode
1744
        fposition += offset;
1729
        fposition += offset;
1745
        // is the fileposition within the file?
1730
        // is the fileposition within the file?
1746
        if((fposition >= 0) && (fposition <= (s32)file->Size))
1731
        if((fposition >= 0) && (fposition <= (s32)file->Size))
1747
        {
1732
        {
1748
                // initialize the filepointer to start of the file
1733
                // initialize the filepointer to start of the file
1749
                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1734
                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1750
                file->SectorOfCurrCluster       = 0;
1735
                file->SectorOfCurrCluster       = 0;
1751
                file->ByteOfCurrSector          = 0;
1736
                file->ByteOfCurrSector          = 0;
1752
                file->Position                          = 0;
1737
                file->Position                          = 0;
1753
                // has the specified file at least one valid sector attached?
1738
                // has the specified file at least one valid sector attached?
1754
                if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(retvalue);
1739
                if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(retvalue);
1755
                // 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
1756
                sector_index = (u32) ((u32)fposition >> 9);      // 512 bytes per sector
1741
                sector_index = (u32) ((u32)fposition >> 9);      // 512 bytes per sector
1757
                // calculate the index of the cluster containing the specified sector
1742
                // calculate the index of the cluster containing the specified sector
1758
                cluster_index = (u32) sector_index / Partition.SectorsPerCluster;
1743
                cluster_index = (u32) sector_index / Partition.SectorsPerCluster;
1759
                // 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
1760
                sector_index = (sector_index % Partition.SectorsPerCluster);
1745
                sector_index = (sector_index % Partition.SectorsPerCluster);
1761
                // calculate the index of the byteposition the fileposition points to
1746
                // calculate the index of the byteposition the fileposition points to
1762
                byte_index = (u32) fposition % 512;
1747
                byte_index = (u32) fposition % 512;
1763
                // parse the fat till the calculated cluster has been reached
1748
                // parse the fat till the calculated cluster has been reached
1764
                while(cluster_index--) GetNextCluster(file);
1749
                while(cluster_index--) GetNextCluster(file);
1765
                // set the filepointer to the specified sector and byteposition
1750
                // set the filepointer to the specified sector and byteposition
1766
                file->SectorOfCurrCluster = (u8) sector_index;
1751
                file->SectorOfCurrCluster = (u8) sector_index;
1767
                file->ByteOfCurrSector = (u16) byte_index;
1752
                file->ByteOfCurrSector = (u16) byte_index;
1768
                // the fileposition now equals the filepointer
1753
                // the fileposition now equals the filepointer
1769
                file->Position = (u32)fposition;
1754
                file->Position = (u32)fposition;
1770
                // the specified fileposition has been reached
1755
                // the specified fileposition has been reached
1771
                retvalue = 0;
1756
                retvalue = 0;
1772
        }
1757
        }
1773
        return(retvalue);
1758
        return(retvalue);
1774
}
1759
}
1775
 
1760
 
1776
/****************************************************************************************************************************************************/
1761
/****************************************************************************************************************************************************/
1777
/* Function:    fflush_(File *);                                                                                                                                                                                                                                        */
1762
/* Function:    fflush_(File *);                                                                                                                                                                                                                                        */
1778
/*                                                                                                                                                                                                                                                                                                      */
1763
/*                                                                                                                                                                                                                                                                                                      */
1779
/* 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.                                                                                            */
1780
/*                                                                                                                                                                                                                                                                                                      */
1765
/*                                                                                                                                                                                                                                                                                                      */
1781
/* Returnvalue: 0 on success EOF on error                                                                                                                                                                                                                       */
1766
/* Returnvalue: 0 on success EOF on error                                                                                                                                                                                                                       */
1782
/****************************************************************************************************************************************************/
1767
/****************************************************************************************************************************************************/
1783
s16     fflush_(File_t *file)
1768
s16     fflush_(File_t *file)
1784
{
1769
{
1785
        DirEntry_t *dir;
1770
        DirEntry_t *dir;
1786
 
1771
 
1787
        if((file == NULL) || (!Partition.IsValid)) return (EOF);
1772
        if((file == NULL) || (!Partition.IsValid)) return (EOF);
1788
 
1773
 
1789
        switch(file->Mode)
1774
        switch(file->Mode)
1790
        {
1775
        {
1791
                case 'a':
1776
                case 'a':
1792
                case 'w':
1777
                case 'w':
1793
                        if(file->ByteOfCurrSector > 0)                                                                          // has data been added to the file?
1778
                        if(file->ByteOfCurrSector > 0)                                                                          // has data been added to the file?
1794
                        {
1779
                        {
1795
                                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
1796
                                {
1781
                                {
1797
                                        Fat16_Deinit();
1782
                                        Fat16_Deinit();
1798
                                        return(EOF);
1783
                                        return(EOF);
1799
                                }
1784
                                }
1800
                        }
1785
                        }
1801
                        file->SectorInCache     = file->DirectorySector;
1786
                        file->SectorInCache     = file->DirectorySector;
1802
                        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.
1803
                        {
1788
                        {
1804
                                Fat16_Deinit();
1789
                                Fat16_Deinit();
1805
                                return(EOF);
1790
                                return(EOF);
1806
                        }
1791
                        }
1807
 
1792
 
1808
                        dir = (DirEntry_t *)file->Cache;
1793
                        dir = (DirEntry_t *)file->Cache;
1809
                        // update file size and modification time & date
1794
                        // update file size and modification time & date
1810
                        dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime);
1795
                        dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime);
1811
                        dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime);
1796
                        dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime);
1812
                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1797
                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1813
                        dir[file->DirectoryIndex].Size = file->Size;                                            // update file size
1798
                        dir[file->DirectoryIndex].Size = file->Size;                                            // update file size
1814
                        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
1815
                        {
1800
                        {
1816
                                Fat16_Deinit();
1801
                                Fat16_Deinit();
1817
                                return(EOF);
1802
                                return(EOF);
1818
                        }
1803
                        }
1819
                        break;
1804
                        break;
1820
                case 'r':
1805
                case 'r':
1821
                default:
1806
                default:
1822
                        // do nothing!
1807
                        // do nothing!
1823
                        return(EOF);
1808
                        return(EOF);
1824
                        break;
1809
                        break;
1825
 
1810
 
1826
        }
1811
        }
1827
        return(0);
1812
        return(0);
1828
}
1813
}
1829
 
1814
 
1830
/********************************************************************************************************************************************/
1815
/********************************************************************************************************************************************/
1831
/*      Function:               fgetc_(File *file);                                                                                                                                                                                                             */
1816
/*      Function:               fgetc_(File *file);                                                                                                                                                                                                             */
1832
/*                                                                                                                                                                                                                                                                                      */
1817
/*                                                                                                                                                                                                                                                                                      */
1833
/*      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              */
1834
/*                                      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.    */
1835
/*                                                                                                                                                                                                                                                                                      */
1820
/*                                                                                                                                                                                                                                                                                      */
1836
/*      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.                                   */
1837
/********************************************************************************************************************************************/
1822
/********************************************************************************************************************************************/
1838
s16 fgetc_(File_t *file)
1823
s16 fgetc_(File_t *file)
1839
{
1824
{
1840
        s16 c = EOF;
1825
        s16 c = EOF;
1841
        u32 curr_sector;
1826
        u32 curr_sector;
1842
 
1827
 
1843
        if( (!Partition.IsValid) || (file == NULL)) return(c);
1828
        if( (!Partition.IsValid) || (file == NULL)) return(c);
1844
        // 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.
1845
        if((0 < file->Size) && ((file->Position) < file->Size) )
1830
        if((0 < file->Size) && ((file->Position) < file->Size) )
1846
        {
1831
        {
1847
                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.
1848
                curr_sector += file->SectorOfCurrCluster;
1833
                curr_sector += file->SectorOfCurrCluster;
1849
 
1834
 
1850
                if(file->SectorInCache != curr_sector)
1835
                if(file->SectorInCache != curr_sector)
1851
                {
1836
                {
1852
                        file->SectorInCache = curr_sector;
1837
                        file->SectorInCache = curr_sector;
1853
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
1838
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
1854
                        {
1839
                        {
1855
                                Fat16_Deinit();
1840
                                Fat16_Deinit();
1856
                                return(EOF);
1841
                                return(EOF);
1857
                        }
1842
                        }
1858
                }
1843
                }
1859
                c = (s16) file->Cache[file->ByteOfCurrSector];
1844
                c = (s16) file->Cache[file->ByteOfCurrSector];
1860
                file->Position++;                                                                       // increment file position
1845
                file->Position++;                                                                       // increment file position
1861
                file->ByteOfCurrSector++;                                                       // goto next byte in sector
1846
                file->ByteOfCurrSector++;                                                       // goto next byte in sector
1862
                if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if end of sector
1847
                if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if end of sector
1863
                {
1848
                {
1864
                        file->ByteOfCurrSector = 0;                                             //  reset byte location
1849
                        file->ByteOfCurrSector = 0;                                             //  reset byte location
1865
                        file->SectorOfCurrCluster++;                                    //      next sector
1850
                        file->SectorOfCurrCluster++;                                    //      next sector
1866
                        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.
1867
                        {
1852
                        {
1868
 
1853
 
1869
                                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.
1870
                                {
1855
                                {
1871
                                        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.
1872
                                }
1857
                                }
1873
                                else // the last cluster was allready reached
1858
                                else // the last cluster was allready reached
1874
                                {
1859
                                {
1875
                                        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
1876
                                        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
1877
                                }
1862
                                }
1878
                        }
1863
                        }
1879
                }
1864
                }
1880
        }
1865
        }
1881
        return(c);
1866
        return(c);
1882
}
1867
}
1883
 
1868
 
1884
/********************************************************************************************************************************************/
1869
/********************************************************************************************************************************************/
1885
/*      Function:               fputc_( const s8 c, File *file);                                                                                                                                                                                */
1870
/*      Function:               fputc_( const s8 c, File *file);                                                                                                                                                                                */
1886
/*                                                                                                                                                                                                                                                                                      */
1871
/*                                                                                                                                                                                                                                                                                      */
1887
/*      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.                                 */
1888
/*                                      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.    */
1889
/*                                                                                                                                                                                                                                                                                      */
1874
/*                                                                                                                                                                                                                                                                                      */
1890
/*      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.                                                                                               */
1891
/********************************************************************************************************************************************/
1876
/********************************************************************************************************************************************/
1892
s16 fputc_(const s8 c, File_t *file)
1877
s16 fputc_(const s8 c, File_t *file)
1893
{
1878
{
1894
        u32 curr_sector  = 0;
1879
        u32 curr_sector  = 0;
1895
 
1880
 
1896
        if((!Partition.IsValid) || (file == NULL)) return(EOF);
1881
        if((!Partition.IsValid) || (file == NULL)) return(EOF);
1897
        switch(file->Mode)
1882
        switch(file->Mode)
1898
        {
1883
        {
1899
                case 'w':
1884
                case 'w':
1900
                case 'a':
1885
                case 'a':
1901
                        // 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.
1902
                        // 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
1903
                        // and a new cluster should be appended.
1888
                        // and a new cluster should be appended.
1904
                        // 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
1905
                        // and size should be zero, therefore append a new Cluster too.
1890
                        // and size should be zero, therefore append a new Cluster too.
1906
                        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))
1907
                        {
1892
                        {
1908
                                if(CLUSTER_UNDEFINED == AppendCluster(file)) return(EOF);
1893
                                if(CLUSTER_UNDEFINED == AppendCluster(file)) return(EOF);
1909
                        }
1894
                        }
1910
 
1895
 
1911
                        curr_sector  = file->FirstSectorOfCurrCluster;
1896
                        curr_sector  = file->FirstSectorOfCurrCluster;
1912
                        curr_sector += file->SectorOfCurrCluster;
1897
                        curr_sector += file->SectorOfCurrCluster;
1913
                        if(file->SectorInCache != curr_sector)
1898
                        if(file->SectorInCache != curr_sector)
1914
                        {
1899
                        {
1915
                                file->SectorInCache = curr_sector;
1900
                                file->SectorInCache = curr_sector;
1916
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
1901
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
1917
                                {
1902
                                {
1918
                                        Fat16_Deinit();
1903
                                        Fat16_Deinit();
1919
                                        return(EOF);
1904
                                        return(EOF);
1920
                                }
1905
                                }
1921
                        }
1906
                        }
1922
 
1907
 
1923
                        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
1924
                        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.
1925
                        file->Position++;                                                                       // the actual positon within the file.
1910
                        file->Position++;                                                                       // the actual positon within the file.
1926
                        file->ByteOfCurrSector++;                                                       // goto next byte in sector
1911
                        file->ByteOfCurrSector++;                                                       // goto next byte in sector
1927
                        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
1928
                        {       // save the sector to the sd-card
1913
                        {       // save the sector to the sd-card
1929
 
1914
 
1930
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1915
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1931
                                {
1916
                                {
1932
                                        Fat16_Deinit();
1917
                                        Fat16_Deinit();
1933
                                        return(EOF);
1918
                                        return(EOF);
1934
                                }
1919
                                }
1935
                                file->ByteOfCurrSector = 0;                                             //  reset byte location
1920
                                file->ByteOfCurrSector = 0;                                             //  reset byte location
1936
                                file->SectorOfCurrCluster++;                                    //      next sector
1921
                                file->SectorOfCurrCluster++;                                    //      next sector
1937
                                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.
1938
                                {
1923
                                {
1939
                                        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.
1940
                                        { // if current cluster was the last cluster of the file
1925
                                        { // if current cluster was the last cluster of the file
1941
                                                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.
1942
                                                {
1927
                                                {
1943
                                                        file->SectorOfCurrCluster--;                            // jump back to last sector of last cluster
1928
                                                        file->SectorOfCurrCluster--;                            // jump back to last sector of last cluster
1944
                                                        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
1945
                                                        return(EOF);
1930
                                                        return(EOF);
1946
                                                }
1931
                                                }
1947
                                        }
1932
                                        }
1948
                                        else // next cluster
1933
                                        else // next cluster
1949
                                        {
1934
                                        {
1950
                                                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.
1951
                                        }
1936
                                        }
1952
                                }
1937
                                }
1953
                        }
1938
                        }
1954
                        break;
1939
                        break;
1955
                case 'r':
1940
                case 'r':
1956
                default:
1941
                default:
1957
                        return(EOF);
1942
                        return(EOF);
1958
                        break;
1943
                        break;
1959
        } // EOF switch(file->Mode)
1944
        } // EOF switch(file->Mode)
1960
        return(0);
1945
        return(0);
1961
}
1946
}
1962
 
1947
 
1963
 
1948
 
1964
/****************************************************************************************************************************************/
1949
/****************************************************************************************************************************************/
1965
/*      Function:               fread_(void *buffer, s32 size, s32 count, File *File);                                                                                                                          */
1950
/*      Function:               fread_(void *buffer, s32 size, s32 count, File *File);                                                                                                                          */
1966
/*                                                                                                                                                                                                                                                                              */
1951
/*                                                                                                                                                                                                                                                                              */
1967
/*      Description:    This function reads count objects of the specified size                                                                                                                         */
1952
/*      Description:    This function reads count objects of the specified size                                                                                                                         */
1968
/*                                      from the actual position of the file to the specified buffer.                                                                                                           */
1953
/*                                      from the actual position of the file to the specified buffer.                                                                                                           */
1969
/*                                                                                                                                                                                                                                                                              */
1954
/*                                                                                                                                                                                                                                                                              */
1970
/*      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.                                                                                      */
1971
/****************************************************************************************************************************************/
1956
/****************************************************************************************************************************************/
1972
u32 fread_(void *buffer, u32 size, u32 count, File_t *file)
1957
u32 fread_(void *buffer, u32 size, u32 count, File_t *file)
1973
{
1958
{
1974
        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.
1975
        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.
1976
        u8 *pbuff       = 0;                                                                                    // a pointer to the actual bufferposition.
1961
        u8 *pbuff       = 0;                                                                                    // a pointer to the actual bufferposition.
1977
        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.
1978
        s16 c;
1963
        s16 c;
1979
 
1964
 
1980
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1965
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1981
 
1966
 
1982
        pbuff = (u8 *) buffer;                                                                                  // cast the void pointer to an u8 *
1967
        pbuff = (u8 *) buffer;                                                                                  // cast the void pointer to an u8 *
1983
 
1968
 
1984
        while((object_cnt < count) && success)
1969
        while((object_cnt < count) && success)
1985
        {
1970
        {
1986
                object_size = size;
1971
                object_size = size;
1987
                while((size > 0) && success)
1972
                while((size > 0) && success)
1988
                {
1973
                {
1989
                        c = fgetc_(file);
1974
                        c = fgetc_(file);
1990
                        if(c != EOF)
1975
                        if(c != EOF)
1991
                        {
1976
                        {
1992
                                *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.
1993
                                pbuff++;
1978
                                pbuff++;
1994
                                size--;
1979
                                size--;
1995
                        }
1980
                        }
1996
                        else // error or end of file reached
1981
                        else // error or end of file reached
1997
                        {
1982
                        {
1998
                                success = 0;
1983
                                success = 0;
1999
                        }
1984
                        }
2000
                }
1985
                }
2001
                if(success) object_cnt++;
1986
                if(success) object_cnt++;
2002
        }
1987
        }
2003
        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
2004
}
1989
}
2005
 
1990
 
2006
 
1991
 
2007
/****************************************************************************************************************************************/
1992
/****************************************************************************************************************************************/
2008
/*      Function:               fwrite_(void *buffer, s32 size, s32 count, File *file);                                                                                                                         */
1993
/*      Function:               fwrite_(void *buffer, s32 size, s32 count, File *file);                                                                                                                         */
2009
/*                                                                                                                                                                                                                                                                              */
1994
/*                                                                                                                                                                                                                                                                              */
2010
/*      Description:    This function writes count objects of the specified size                                                                                                                        */
1995
/*      Description:    This function writes count objects of the specified size                                                                                                                        */
2011
/*                                      from the buffer pointer to the actual position in the file.                                                                                                                     */
1996
/*                                      from the buffer pointer to the actual position in the file.                                                                                                                     */
2012
/*                                                                                                                                                                                                                                                                              */
1997
/*                                                                                                                                                                                                                                                                              */
2013
/*      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.                                                                                      */
2014
/****************************************************************************************************************************************/
1999
/****************************************************************************************************************************************/
2015
u32 fwrite_(void *buffer, u32 size, u32 count, File_t *file)
2000
u32 fwrite_(void *buffer, u32 size, u32 count, File_t *file)
2016
{
2001
{
2017
        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.
2018
        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.
2019
        u8 *pbuff           = 0;                                                                                                                // a pointer to the actual bufferposition.
2004
        u8 *pbuff           = 0;                                                                                                                // a pointer to the actual bufferposition.
2020
        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.
2021
        s16 c;
2006
        s16 c;
2022
 
2007
 
2023
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
2008
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
2024
        if(file->Mode == 'r') return (0); // opened read only
2009
        if(file->Mode == 'r') return (0); // opened read only
2025
        pbuff = (u8 *) buffer;                                                                                                          // cast the void pointer to an u8 *
2010
        pbuff = (u8 *) buffer;                                                                                                          // cast the void pointer to an u8 *
2026
 
2011
 
2027
        while((object_cnt < count) && success)
2012
        while((object_cnt < count) && success)
2028
        {
2013
        {
2029
                object_size = size;
2014
                object_size = size;
2030
                while((size > 0) && success)
2015
                while((size > 0) && success)
2031
                {
2016
                {
2032
                        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.
2033
                        if(c != EOF)
2018
                        if(c != EOF)
2034
                        {
2019
                        {
2035
                                pbuff++;
2020
                                pbuff++;
2036
                                size--;
2021
                                size--;
2037
                        }
2022
                        }
2038
                        else
2023
                        else
2039
                        {
2024
                        {
2040
                                success = 0;
2025
                                success = 0;
2041
                        }
2026
                        }
2042
                }
2027
                }
2043
                if(success) object_cnt++;
2028
                if(success) object_cnt++;
2044
        }
2029
        }
2045
 
2030
 
2046
        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
2047
}
2032
}
2048
 
2033
 
2049
 
2034
 
2050
/****************************************************************************************************************************************/
2035
/****************************************************************************************************************************************/
2051
/*      Function:               fputs_(const s8 *string, File_t *File);                                                                                                                                                         */
2036
/*      Function:               fputs_(const s8 *string, File_t *File);                                                                                                                                                         */
2052
/*                                                                                                                                                                                                                                                                              */
2037
/*                                                                                                                                                                                                                                                                              */
2053
/*      Description:    This function writes a string to the specified file.                                                                                                                            */
2038
/*      Description:    This function writes a string to the specified file.                                                                                                                            */
2054
/*                                                                                                                                                                                                                                                                              */
2039
/*                                                                                                                                                                                                                                                                              */
2055
/*      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.                                                                                                                       */
2056
/****************************************************************************************************************************************/
2041
/****************************************************************************************************************************************/
2057
s16 fputs_(s8 * const string, File_t * const file)
2042
s16 fputs_(s8 * const string, File_t * const file)
2058
{
2043
{
2059
        u8 i=0;
2044
        u8 i=0;
2060
        s16 c = 0;
2045
        s16 c = 0;
2061
 
2046
 
2062
        if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(EOF);
2047
        if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(EOF);
2063
        if(file->Mode == 'r') return(EOF);
2048
        if(file->Mode == 'r') return(EOF);
2064
        while((string[i] != 0)&& (c != EOF))
2049
        while((string[i] != 0)&& (c != EOF))
2065
        {
2050
        {
2066
                c = fputc_(string[i], file);
2051
                c = fputc_(string[i], file);
2067
                i++;
2052
                i++;
2068
        }
2053
        }
2069
        return(c);
2054
        return(c);
2070
}
2055
}
2071
 
2056
 
2072
/****************************************************************************************************************************************/
2057
/****************************************************************************************************************************************/
2073
/*      Function:               fgets_(s8 *, s16 , File_t *);                                                                                                                                                                           */
2058
/*      Function:               fgets_(s8 *, s16 , File_t *);                                                                                                                                                                           */
2074
/*                                                                                                                                                                                                                                                                              */
2059
/*                                                                                                                                                                                                                                                                              */
2075
/*      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.                                                                                             */
2076
/*                                                                                                                                                                                                                                                                              */
2061
/*                                                                                                                                                                                                                                                                              */
2077
/*      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.                                                                                                                       */
2078
/****************************************************************************************************************************************/
2063
/****************************************************************************************************************************************/
2079
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)
2080
{
2065
{
2081
        s8 *pbuff;
2066
        s8 *pbuff;
2082
        s16 c = 0, bytecount;
2067
        s16 c = 0, bytecount;
2083
 
2068
 
2084
        if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length < 1)) return (0);
2069
        if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length < 1)) return (0);
2085
        bytecount = length;
2070
        bytecount = length;
2086
        pbuff = string;                                                         // set write pointer to start of string
2071
        pbuff = string;                                                         // set write pointer to start of string
2087
        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.
2088
        {
2073
        {
2089
                c = fgetc_(file);                                               // read a character from the opened file.
2074
                c = fgetc_(file);                                               // read a character from the opened file.
2090
                switch(c)
2075
                switch(c)
2091
                {
2076
                {
2092
                        case 0x0A:                                                      // new line
2077
                        case 0x0A:                                                      // new line
2093
                                *pbuff = 0;                                             // set string terminator
2078
                                *pbuff = 0;                                             // set string terminator
2094
                                return(string);                                 // return normal
2079
                                return(string);                                 // return normal
2095
 
2080
 
2096
                        case EOF:
2081
                        case EOF:
2097
                                *pbuff = 0;                                             // set string terminator
2082
                                *pbuff = 0;                                             // set string terminator
2098
                                return(0);
2083
                                return(0);
2099
 
2084
 
2100
                        default:
2085
                        default:
2101
                                *pbuff++ = (s8)c;                               // copy byte to string
2086
                                *pbuff++ = (s8)c;                               // copy byte to string
2102
                                bytecount--;
2087
                                bytecount--;
2103
                                break;
2088
                                break;
2104
                }
2089
                }
2105
        }
2090
        }
2106
        *pbuff = 0;     // set string terminator
2091
        *pbuff = 0;     // set string terminator
2107
        return(string);
2092
        return(string);
2108
}
2093
}
2109
 
2094
 
2110
/****************************************************************************************************************************************/
2095
/****************************************************************************************************************************************/
2111
/*      Function:               fclose_(File *file);                                                                                                                                                                                            */
2096
/*      Function:               fclose_(File *file);                                                                                                                                                                                            */
2112
/*                                                                                                                                                                                                                                                                              */
2097
/*                                                                                                                                                                                                                                                                              */
2113
/*      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                                                                                                        */
2114
/*                                      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.                                                                         */
2115
/*                                                                                                                                                                                                                                                                              */
2100
/*                                                                                                                                                                                                                                                                              */
2116
/*      Returnvalue:    0 on success EOF on error                                                                                                                                                                                       */
2101
/*      Returnvalue:    0 on success EOF on error                                                                                                                                                                                       */
2117
/****************************************************************************************************************************************/
2102
/****************************************************************************************************************************************/
2118
s16 fclose_(File_t *file)
2103
s16 fclose_(File_t *file)
2119
{
2104
{
2120
        s16 returnvalue = EOF;
2105
        s16 returnvalue = EOF;
2121
 
2106
 
2122
        if(file == NULL) return(returnvalue);
2107
        if(file == NULL) return(returnvalue);
2123
        returnvalue = fflush_(file);
2108
        returnvalue = fflush_(file);
2124
        UnlockFilePointer(file);
2109
        UnlockFilePointer(file);
2125
        return(returnvalue);
2110
        return(returnvalue);
2126
}
2111
}
2127
 
2112
 
2128
 
2113
 
2129
/****************************************************************************************************************************************/
2114
/****************************************************************************************************************************************/
2130
/*      Function:               fexist_(const u8*);                                                                                                                                                                                                     */
2115
/*      Function:               fexist_(const u8*);                                                                                                                                                                                                     */
2131
/*                                                                                                                                                                                                                                                                              */
2116
/*                                                                                                                                                                                                                                                                              */
2132
/*      Description:    This function checks if a file already exist.                                                                                                                                           */
2117
/*      Description:    This function checks if a file already exist.                                                                                                                                           */
2133
/*                                                                                                                                                                                                                                                                              */
2118
/*                                                                                                                                                                                                                                                                              */
2134
/*      Returnvalue:    1 if the file exist else 0.                                                                                                                                                                                     */
2119
/*      Returnvalue:    1 if the file exist else 0.                                                                                                                                                                                     */
2135
/****************************************************************************************************************************************/
2120
/****************************************************************************************************************************************/
2136
u8 fexist_(s8 * const filename)
2121
u8 fexist_(s8 * const filename)
2137
{
2122
{
2138
        u8 exist = 0;
2123
        u8 exist = 0;
2139
        File_t *file = 0;
2124
        File_t *file = 0;
2140
        file = LockFilePointer();
2125
        file = LockFilePointer();
2141
        exist = FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file);
2126
        exist = FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file);
2142
        UnlockFilePointer(file);
2127
        UnlockFilePointer(file);
2143
        return(exist);
2128
        return(exist);
2144
}
2129
}
2145
 
2130
 
2146
/****************************************************************************************************************************************/
2131
/****************************************************************************************************************************************/
2147
/*      Function:               feof_(File_t *File);                                                                                                                                                                                            */
2132
/*      Function:               feof_(File_t *File);                                                                                                                                                                                            */
2148
/*                                                                                                                                                                                                                                                                              */
2133
/*                                                                                                                                                                                                                                                                              */
2149
/*      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.                                                                                                                                               */
2150
/*                                                                                                                                                                                                                                                                              */
2135
/*                                                                                                                                                                                                                                                                              */
2151
/*      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.                                                                                                                                                                           */
2152
/****************************************************************************************************************************************/
2137
/****************************************************************************************************************************************/
2153
u8 feof_(File_t *file)
2138
u8 feof_(File_t *file)
2154
{
2139
{
2155
        if(((file->Position)+1) < (file->Size))
2140
        if(((file->Position)+1) < (file->Size))
2156
        {
2141
        {
2157
                return(0);
2142
                return(0);
2158
        }
2143
        }
2159
        else
2144
        else
2160
        {
2145
        {
2161
                return(1);
2146
                return(1);
2162
        }
2147
        }
2163
}
2148
}
2164
 
2149
 
2165
 
2150
 
2166
/********************************************************************************************************************************************/
2151
/********************************************************************************************************************************************/
2167
/*      Function:               fdelete_(s8* filepath);                                                                                                                                                                                                 */
2152
/*      Function:               fdelete_(s8* filepath);                                                                                                                                                                                                 */
2168
/*                                                                                                                                                                                                                                                                                      */
2153
/*                                                                                                                                                                                                                                                                                      */
2169
/*      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                                                                                  */
2170
/*                                                                                                                                                                                                                                      */
2155
/*                                                                                                                                                                                                                                      */
2171
/*                                                                                                                                                                                                                                                                                      */
2156
/*                                                                                                                                                                                                                                                                                      */
2172
/*      Returnvalue:    1 : specified file deleted succesfully 0: specified file not found                                                                                                              */
2157
/*      Returnvalue:    1 : specified file deleted succesfully 0: specified file not found                                                                                                              */
2173
/********************************************************************************************************************************************/
2158
/********************************************************************************************************************************************/
2174
 
2159
 
2175
u8 fdelete_(s8* const filepath)
2160
u8 fdelete_(s8* const filepath)
2176
{
2161
{
2177
        u8 retvalue = 0;
2162
        u8 retvalue = 0;
2178
        File_t file;
2163
        File_t file;
2179
 
2164
 
2180
        if(filepath == NULL) return(0);
2165
        if(filepath == NULL) return(0);
2181
        // correct filepath formatting
2166
        // correct filepath formatting
2182
        Slashing_Path(filepath);
2167
        Slashing_Path(filepath);
2183
        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.
2184
        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.
2185
        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
2186
        file.SectorOfCurrCluster = SECTOR_UNDEFINED;                    // The sector within the current cluster.
2171
        file.SectorOfCurrCluster = SECTOR_UNDEFINED;                    // The sector within the current cluster.
2187
        file.ByteOfCurrSector = 0;                                                              // The byte location within the current sector.
2172
        file.ByteOfCurrSector = 0;                                                              // The byte location within the current sector.
2188
        file.Mode = 0;                                                                                  // Mode of fileoperation (read,write)
2173
        file.Mode = 0;                                                                                  // Mode of fileoperation (read,write)
2189
        file.Size = 0;                                                                                  // The size of the opend file in bytes.
2174
        file.Size = 0;                                                                                  // The size of the opend file in bytes.
2190
        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
2191
        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.
2192
        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.
2193
        file.Attribute = 0;                                                                             // The attribute of the file opened.
2178
        file.Attribute = 0;                                                                             // The attribute of the file opened.
2194
        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.
2195
        file.State = FSTATE_USED;                                                               // mark it as used
2180
        file.State = FSTATE_USED;                                                               // mark it as used
2196
       
2181
       
2197
        // if file is existent
2182
        // if file is existent
2198
        if(FileExist(filepath, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, &file))
2183
        if(FileExist(filepath, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, &file))
2199
        {
2184
        {
2200
                // and is not marked as readonly?
2185
                // and is not marked as readonly?
2201
                if((file.Attribute & ATTR_READONLY) != ATTR_READONLY)
2186
                if((file.Attribute & ATTR_READONLY) != ATTR_READONLY)
2202
                {
2187
                {
2203
                        // try to delete the file content from the filesystem
2188
                        // try to delete the file content from the filesystem
2204
                        if(DeleteClusterChain(file.FirstSectorOfFirstCluster))
2189
                        if(DeleteClusterChain(file.FirstSectorOfFirstCluster))
2205
                        {
2190
                        {
2206
                                // and try delete the directory entry of the file
2191
                                // and try delete the directory entry of the file
2207
                                retvalue = DeleteDirectoryEntry(&file);
2192
                                retvalue = DeleteDirectoryEntry(&file);
2208
                        }      
2193
                        }      
2209
                }
2194
                }
2210
        }
2195
        }
2211
        return(retvalue);
2196
        return(retvalue);
2212
}
2197
}
2213
 
2198
 
2214
/****************************************************************************************************************************************************/
2199
/****************************************************************************************************************************************************/
2215
/* Function:    s8* FAT16_GetVolumeLabel(void)                                                                                                                                                                                                                  */
2200
/* Function:    s8* FAT16_GetVolumeLabel(void)                                                                                                                                                                                                                  */
2216
/*                                                                                                                                                                                                                                                                                                      */
2201
/*                                                                                                                                                                                                                                                                                                      */
2217
/* Description: This function returns the volume label                                                                                                                                                                                          */
2202
/* Description: This function returns the volume label                                                                                                                                                                                          */
2218
/*                                                                                                                                                                                                                                                                                                      */
2203
/*                                                                                                                                                                                                                                                                                                      */
2219
/* 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.                                                                                                                     */
2220
/****************************************************************************************************************************************************/
2205
/****************************************************************************************************************************************************/
2221
s8* FAT16_GetVolumeLabel(void)
2206
s8* FAT16_GetVolumeLabel(void)
2222
{
2207
{
2223
        s8              *pVolumeLabel = NULL;
2208
        s8              *pVolumeLabel = NULL;
2224
        u32             dir_sector, max_dir_sector, curr_sector;
2209
        u32             dir_sector, max_dir_sector, curr_sector;
2225
        u16     dir_entry = 0;
2210
        u16     dir_entry = 0;
2226
        u8              i = 0;
2211
        u8              i = 0;
2227
 
2212
 
2228
        DirEntry_t * dir;
2213
        DirEntry_t * dir;
2229
        File_t *file = NULL;
2214
        File_t *file = NULL;
2230
 
2215
 
2231
        // if Partition is not valid return NULL
2216
        // if Partition is not valid return NULL
2232
        if(!Partition.IsValid) return(pVolumeLabel);
2217
        if(!Partition.IsValid) return(pVolumeLabel);
2233
        // if Volume label was read before return it
2218
        // if Volume label was read before return it
2234
        if(Partition.VolumeLabel[0]!= '\0') return (Partition.VolumeLabel);
2219
        if(Partition.VolumeLabel[0]!= '\0') return (Partition.VolumeLabel);
2235
        // try to catch a file pointer
2220
        // try to catch a file pointer
2236
        file = LockFilePointer();
2221
        file = LockFilePointer();
2237
        if(file == NULL) return(pVolumeLabel);
2222
        if(file == NULL) return(pVolumeLabel);
2238
        // search dir entries direct within the root directory area
2223
        // search dir entries direct within the root directory area
2239
        file->DirectorySector = 0;
2224
        file->DirectorySector = 0;
2240
        max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
2225
        max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
2241
        file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
2226
        file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
2242
 
2227
 
2243
        // update current file data area position to start of first cluster
2228
        // update current file data area position to start of first cluster
2244
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
2229
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
2245
        file->SectorOfCurrCluster               = 0;
2230
        file->SectorOfCurrCluster               = 0;
2246
        file->ByteOfCurrSector                  = 0;
2231
        file->ByteOfCurrSector                  = 0;
2247
 
2232
 
2248
        dir_sector = 0; // reset sector counter within a new cluster
2233
        dir_sector = 0; // reset sector counter within a new cluster
2249
        do // loop over all sectors of the root directory
2234
        do // loop over all sectors of the root directory
2250
        {
2235
        {
2251
                curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
2236
                curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
2252
                file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
2237
                file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
2253
                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
2254
                {
2239
                {
2255
                        Fat16_Deinit();
2240
                        Fat16_Deinit();
2256
                        return(NULL);
2241
                        return(NULL);
2257
                }
2242
                }
2258
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
2243
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
2259
                // search all directory entries within that sector
2244
                // search all directory entries within that sector
2260
                for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
2245
                for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
2261
                {   // check for existing dir entry
2246
                {   // check for existing dir entry
2262
                        switch((u8)dir[dir_entry].Name[0])
2247
                        switch((u8)dir[dir_entry].Name[0])
2263
                        {
2248
                        {
2264
                                case SLOT_EMPTY:
2249
                                case SLOT_EMPTY:
2265
                                case SLOT_DELETED:
2250
                                case SLOT_DELETED:
2266
                                        // ignore empty or deleted dir entries
2251
                                        // ignore empty or deleted dir entries
2267
                                        break;
2252
                                        break;
2268
                                default:
2253
                                default:
2269
                                        // check attributes for volume label
2254
                                        // check attributes for volume label
2270
                                        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
2271
                                        // (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.)
2272
                                        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];
2273
                                        Partition.VolumeLabel[11] = '\0'; // terminate string
2258
                                        Partition.VolumeLabel[11] = '\0'; // terminate string
2274
                                        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
2275
                                        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
2276
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
2261
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
2277
                                        file->SectorOfCurrCluster = 0;
2262
                                        file->SectorOfCurrCluster = 0;
2278
                                        file->ByteOfCurrSector = 0;
2263
                                        file->ByteOfCurrSector = 0;
2279
                                        file->DirectorySector = curr_sector; // current sector
2264
                                        file->DirectorySector = curr_sector; // current sector
2280
                                        file->DirectoryIndex  = dir_entry; // current direntry in current sector
2265
                                        file->DirectoryIndex  = dir_entry; // current direntry in current sector
2281
                                        file->Size = dir[dir_entry].Size;
2266
                                        file->Size = dir[dir_entry].Size;
2282
                                        dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
2267
                                        dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
2283
                                        pVolumeLabel =  Partition.VolumeLabel;
2268
                                        pVolumeLabel =  Partition.VolumeLabel;
2284
                        } // end of first byte of name check
2269
                        } // end of first byte of name check
2285
                }
2270
                }
2286
                dir_sector++; // search next sector
2271
                dir_sector++; // search next sector
2287
        // 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
2288
        }while((dir_sector < max_dir_sector) && (!pVolumeLabel));
2273
        }while((dir_sector < max_dir_sector) && (!pVolumeLabel));
2289
 
2274
 
2290
        UnlockFilePointer(file);
2275
        UnlockFilePointer(file);
2291
        return(pVolumeLabel);
2276
        return(pVolumeLabel);
2292
}
2277
}
2293
 
2278
 
2294
 
2279
 
2295
/********************************************************************************************************************************************/
2280
/********************************************************************************************************************************************/
2296
/*      Function:               u8 FindItem(Find_t);                                                                                                                                                                                                    */
2281
/*      Function:               u8 FindItem(Find_t);                                                                                                                                                                                                    */
2297
/*                                                                                                                                                                                                                                                                                      */
2282
/*                                                                                                                                                                                                                                                                                      */
2298
/*      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                                      */
2299
/*                                                                                                                                                                                                                                                              */
2284
/*                                                                                                                                                                                                                                                              */
2300
/*                                                                                                                                                                                                                                                                                      */
2285
/*                                                                                                                                                                                                                                                                                      */
2301
/*      Returnvalue:    TRUE if an matching element was found                                                                                                                                                                   */
2286
/*      Returnvalue:    TRUE if an matching element was found                                                                                                                                                                   */
2302
/********************************************************************************************************************************************/
2287
/********************************************************************************************************************************************/
2303
 
2288
 
2304
u8 FindItem(Find_t *findelement)
2289
u8 FindItem(Find_t *findelement)
2305
{
2290
{
2306
        u16             index = 0;
2291
        u16             index = 0;
2307
        u16             max_dir_sector = 0;
2292
        u16             max_dir_sector = 0;
2308
        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.
2309
        u8              i = 0;
2294
        u8              i = 0;
2310
        u8              readpointer = 0;
2295
        u8              readpointer = 0;
2311
        u8              writepointer = 0;
2296
        u8              writepointer = 0;
2312
        u8              retvalue = 0;
2297
        u8              retvalue = 0;
2313
        DirEntry_t      *DirectoryEntry;
2298
        DirEntry_t      *DirectoryEntry;
2314
        File_t  file;
2299
        File_t  file;
2315
        SD_Result_t res=0;
2300
        SD_Result_t res=0;
2316
 
2301
 
2317
        file.FirstSectorOfCurrCluster   = findelement->fp.FirstSectorOfCurrCluster;
2302
        file.FirstSectorOfCurrCluster   = findelement->fp.FirstSectorOfCurrCluster;
2318
        file.SectorOfCurrCluster        = findelement->fp.SectorOfCurrCluster;
2303
        file.SectorOfCurrCluster        = findelement->fp.SectorOfCurrCluster;
2319
        index                                                   = findelement->fp.DirectoryIndex;
2304
        index                                                   = findelement->fp.DirectoryIndex;
2320
 
2305
 
2321
        // 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
2322
        if((Partition.FirstRootDirSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster < Partition.FirstDataSector))
2307
        if((Partition.FirstRootDirSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster < Partition.FirstDataSector))
2323
        {
2308
        {
2324
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
2309
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
2325
        }
2310
        }
2326
        // 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
2327
        else if((Partition.FirstDataSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster <= Partition.LastDataSector))
2312
        else if((Partition.FirstDataSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster <= Partition.LastDataSector))
2328
        {
2313
        {
2329
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
2314
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
2330
        }
2315
        }
2331
 
2316
 
2332
        do
2317
        do
2333
        {       // search the next 16 rootentries in this sector of the roordirectory.
2318
        {       // search the next 16 rootentries in this sector of the roordirectory.
2334
                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.
2335
                if(res != SD_SUCCESS)
2320
                if(res != SD_SUCCESS)
2336
                {
2321
                {
2337
                        Fat16_Deinit();
2322
                        Fat16_Deinit();
2338
                        return(0);
2323
                        return(0);
2339
                }
2324
                }
2340
 
2325
 
2341
                DirectoryEntry = (DirEntry_t *)file.Cache;
2326
                DirectoryEntry = (DirEntry_t *)file.Cache;
2342
 
2327
 
2343
                while((!retvalue)&&(index < 16))
2328
                while((!retvalue)&&(index < 16))
2344
                {
2329
                {
2345
                        i = 0;
2330
                        i = 0;
2346
                        if( (u8)DirectoryEntry[index].Name[0] != SLOT_DELETED)          // ignore deleted items.
2331
                        if( (u8)DirectoryEntry[index].Name[0] != SLOT_DELETED)          // ignore deleted items.
2347
                        {
2332
                        {
2348
                                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] == '?'))
2349
                                {
2334
                                {
2350
                                        i++;
2335
                                        i++;
2351
                                }
2336
                                }
2352
                        }
2337
                        }
2353
                        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))
2354
                        {
2339
                        {
2355
                /* initialize the namestring with 0 */
2340
                /* initialize the namestring with 0 */
2356
                        for(i = 0; i < 12; i++) findelement->name[i] = 0;
2341
                        for(i = 0; i < 12; i++) findelement->name[i] = 0;
2357
                for(readpointer = 0; readpointer <= 10; readpointer++)
2342
                for(readpointer = 0; readpointer <= 10; readpointer++)
2358
                                {
2343
                                {
2359
                                        if((DirectoryEntry[index].Name[readpointer] != ' ') && (readpointer!=8))
2344
                                        if((DirectoryEntry[index].Name[readpointer] != ' ') && (readpointer!=8))
2360
                                        {
2345
                                        {
2361
                                                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.
2362
                                                writepointer++;
2347
                                                writepointer++;
2363
                                        }
2348
                                        }
2364
                                        else
2349
                                        else
2365
                                        {
2350
                                        {
2366
                                                if(DirectoryEntry[index].Attribute == ATTR_ARCHIVE)
2351
                                                if(DirectoryEntry[index].Attribute == ATTR_ARCHIVE)
2367
                                                {
2352
                                                {
2368
                                        if(readpointer < 8) readpointer = 8;
2353
                                        if(readpointer < 8) readpointer = 8;
2369
                                        if(DirectoryEntry[index].Name[readpointer] != ' ')
2354
                                        if(DirectoryEntry[index].Name[readpointer] != ' ')
2370
                                        {
2355
                                        {
2371
                                        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.
2372
                                        writepointer++;
2357
                                        writepointer++;
2373
                                        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.
2374
                                        writepointer++;
2359
                                        writepointer++;
2375
                                        }
2360
                                        }
2376
                                            else break;
2361
                                            else break;
2377
                                                }
2362
                                                }
2378
                            else break;
2363
                            else break;
2379
                        }
2364
                        }
2380
                                }
2365
                                }
2381
                                findelement->fp.FirstSectorOfFirstCluster = (u32) DirectoryEntry[index].StartCluster;
2366
                                findelement->fp.FirstSectorOfFirstCluster = (u32) DirectoryEntry[index].StartCluster;
2382
                                findelement->fp.DirectoryIndex   = index;
2367
                                findelement->fp.DirectoryIndex   = index;
2383
                                findelement->fp.FirstSectorOfCurrCluster   = file.FirstSectorOfCurrCluster;
2368
                                findelement->fp.FirstSectorOfCurrCluster   = file.FirstSectorOfCurrCluster;
2384
                                findelement->fp.DirectorySector  = (file.FirstSectorOfCurrCluster + file.SectorOfCurrCluster);
2369
                                findelement->fp.DirectorySector  = (file.FirstSectorOfCurrCluster + file.SectorOfCurrCluster);
2385
                                findelement->fp.SectorOfCurrCluster      = file.SectorOfCurrCluster;
2370
                                findelement->fp.SectorOfCurrCluster      = file.SectorOfCurrCluster;
2386
                findelement->fp.Size            = DirectoryEntry[index].Size;
2371
                findelement->fp.Size            = DirectoryEntry[index].Size;
2387
                                findelement->fp.Attribute               = DirectoryEntry[index].Attribute;
2372
                                findelement->fp.Attribute               = DirectoryEntry[index].Attribute;
2388
                retvalue = 1;
2373
                retvalue = 1;
2389
                        }
2374
                        }
2390
                        /* search the next sector */
2375
                        /* search the next sector */
2391
                        index++;
2376
                        index++;
2392
                }
2377
                }
2393
                /* 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 */
2394
                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.
2395
                {
2380
                {
2396
                        /* 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 */
2397
                        index = 0;
2382
                        index = 0;
2398
                        /* 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 */
2399
                        if(file.SectorOfCurrCluster < max_dir_sector-1)  file.SectorOfCurrCluster++;
2384
                        if(file.SectorOfCurrCluster < max_dir_sector-1)  file.SectorOfCurrCluster++;
2400
                        /* 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 */
2401
                        else if(Partition.FirstDataSector <= file.FirstSectorOfCurrCluster)
2386
                        else if(Partition.FirstDataSector <= file.FirstSectorOfCurrCluster)
2402
                        {
2387
                        {
2403
                                end_of_directory_not_reached = GetNextCluster(&file);
2388
                                end_of_directory_not_reached = GetNextCluster(&file);
2404
                        }
2389
                        }
2405
                        // 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
2406
                        else
2391
                        else
2407
                        {
2392
                        {
2408
                                end_of_directory_not_reached = 0;
2393
                                end_of_directory_not_reached = 0;
2409
                        }
2394
                        }
2410
                }
2395
                }
2411
        }
2396
        }
2412
        while((end_of_directory_not_reached) && (!retvalue) );
2397
        while((end_of_directory_not_reached) && (!retvalue) );
2413
 
2398
 
2414
        return(retvalue);
2399
        return(retvalue);
2415
}
2400
}
2416
 
2401
 
2417
 
2402
 
2418
 
2403
 
2419
 
2404
 
2420
/********************************************************************************************************************************************/
2405
/********************************************************************************************************************************************/
2421
/*      Function:               findnext_(Find_t *);                                                                                                                                                                                                                    */
2406
/*      Function:               findnext_(Find_t *);                                                                                                                                                                                                                    */
2422
/*                                                                                                                                                                                                                                                                                      */
2407
/*                                                                                                                                                                                                                                                                                      */
2423
/*      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  */
2424
/*                  by function findfirst()                                                                                                                                                                                                     */
2409
/*                  by function findfirst()                                                                                                                                                                                                     */
2425
/*                                                                                                                                                                                                                                                                                      */
2410
/*                                                                                                                                                                                                                                                                                      */
2426
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2411
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2427
/********************************************************************************************************************************************/
2412
/********************************************************************************************************************************************/
2428
u8 findnext_(Find_t * findelement)
2413
u8 findnext_(Find_t * findelement)
2429
{
2414
{
2430
        u8 itemfound = 0;
2415
        u8 itemfound = 0;
2431
        u8 index = 0;
2416
        u8 index = 0;
2432
 
2417
 
2433
        findelement->fp.DirectoryIndex++;
2418
        findelement->fp.DirectoryIndex++;
2434
 
2419
 
2435
        /* 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 */
2436
        for(index = 0; index < 11; index++) findelement->name[index] = 0;
2421
        for(index = 0; index < 11; index++) findelement->name[index] = 0;
2437
 
2422
 
2438
        if(FindItem(findelement))
2423
        if(FindItem(findelement))
2439
        {
2424
        {
2440
                itemfound = 1;
2425
                itemfound = 1;
2441
        }
2426
        }
2442
 
2427
 
2443
        return(itemfound);
2428
        return(itemfound);
2444
}
2429
}
2445
 
2430
 
2446
 
2431
 
2447
 
2432
 
2448
/********************************************************************************************************************************************/
2433
/********************************************************************************************************************************************/
2449
/*      Function:               findfirst_(s8* filename, u8 attribmask, Find_t *);                                                                                                                                              */
2434
/*      Function:               findfirst_(s8* filename, u8 attribmask, Find_t *);                                                                                                                                              */
2450
/*                                                                                                                                                                                                                                                                                      */
2435
/*                                                                                                                                                                                                                                                                                      */
2451
/*      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                   */
2452
/*                                      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                                                                                                   */
2453
/*                                                                                                                                                                                                                                                                                      */
2438
/*                                                                                                                                                                                                                                                                                      */
2454
/*                                                                                                                                                                                                                                                                                      */
2439
/*                                                                                                                                                                                                                                                                                      */
2455
/*      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                                                                                                                     */
2456
/********************************************************************************************************************************************/
2441
/********************************************************************************************************************************************/
2457
u8 findfirst_(const s8* name, u8 attribmask, Find_t *findelement)
2442
u8 findfirst_(const s8* name, u8 attribmask, Find_t *findelement)
2458
{
2443
{
2459
        u8 itemfound = 0;
2444
        u8 itemfound = 0;
2460
        u8 index = 0;
2445
        u8 index = 0;
2461
 
2446
 
2462
        /* initialize the FindElement structure */
2447
        /* initialize the FindElement structure */
2463
        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.
2464
        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.
2465
        findelement->fp.SectorOfCurrCluster = 0;                                                // The sector within the current cluster.
2450
        findelement->fp.SectorOfCurrCluster = 0;                                                // The sector within the current cluster.
2466
        findelement->fp.ByteOfCurrSector = 0;                                                   // The byte location within the current sector.
2451
        findelement->fp.ByteOfCurrSector = 0;                                                   // The byte location within the current sector.
2467
        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.
2468
        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
2469
        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.
2470
        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.
2471
        findelement->attribfilter = 0;
2456
        findelement->attribfilter = 0;
2472
        findelement->attribmask = attribmask;
2457
        findelement->attribmask = attribmask;
2473
        findelement->searchstring[0] = 0;                                                               // terminate string at the begin (=NULL)
2458
        findelement->searchstring[0] = 0;                                                               // terminate string at the begin (=NULL)
2474
 
2459
 
2475
        // bring it to the 8.3 format
2460
        // bring it to the 8.3 format
2476
        if(NULL == SeperateFormatedDirName(name, findelement->searchstring)) return(0);
2461
        if(NULL == SeperateFormatedDirName(name, findelement->searchstring)) return(0);
2477
 
2462
 
2478
        //process the wildcards (*). After an * all following character are wildcards to
2463
        //process the wildcards (*). After an * all following character are wildcards to
2479
        for(index = 0;index < 8;index++)
2464
        for(index = 0;index < 8;index++)
2480
        {
2465
        {
2481
                /* 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 */
2482
                if(findelement->searchstring[index] == '*')
2467
                if(findelement->searchstring[index] == '*')
2483
                {
2468
                {
2484
                        /*  */
2469
                        /*  */
2485
                        while(++index < 8) findelement->searchstring[index] = '*';
2470
                        while(++index < 8) findelement->searchstring[index] = '*';
2486
                }
2471
                }
2487
        }
2472
        }
2488
        for(index = 8;index < 11;index++)
2473
        for(index = 8;index < 11;index++)
2489
        {
2474
        {
2490
                /* 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 */
2491
                if(findelement->searchstring[index] == '*')
2476
                if(findelement->searchstring[index] == '*')
2492
                {
2477
                {
2493
                        /*  */
2478
                        /*  */
2494
                        while(++index < 11) findelement->searchstring[index] = '*';
2479
                        while(++index < 11) findelement->searchstring[index] = '*';
2495
                }
2480
                }
2496
        }
2481
        }
2497
 
2482
 
2498
        /* 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_() */
2499
        findelement->fp.DirectoryIndex--;
2484
        findelement->fp.DirectoryIndex--;
2500
        /* now lets search for the item within the direcory */
2485
        /* now lets search for the item within the direcory */
2501
        itemfound = findnext_(findelement);
2486
        itemfound = findnext_(findelement);
2502
 
2487
 
2503
        return(itemfound);
2488
        return(itemfound);
2504
}
2489
}
2505
 
2490
 
2506
/********************************************************************************************************************************************/
2491
/********************************************************************************************************************************************/
2507
/* Function:    s8 *GetSubDirectory (s8 *dirpath, s8 *directory)                                                                                                                                                        */
2492
/* Function:    s8 *GetSubDirectory (s8 *dirpath, s8 *directory)                                                                                                                                                        */
2508
/*                                                                                                                                                                                                                                                                                      */
2493
/*                                                                                                                                                                                                                                                                                      */
2509
/* 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                     */
2510
/*                                                                                                                                                                                                                                                                                      */
2495
/*                                                                                                                                                                                                                                                                                      */
2511
/*                                                                                                                                                                                                                                                                                      */
2496
/*                                                                                                                                                                                                                                                                                      */
2512
/* 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                                                                                                                            */
2513
/********************************************************************************************************************************************/
2498
/********************************************************************************************************************************************/
2514
s8 * GetSubDirectory(s8 *dirpath, s8 *directory)
2499
s8 * GetSubDirectory(s8 *dirpath, s8 *directory)
2515
{
2500
{
2516
   s8 *cptr = dirpath;
2501
   s8 *cptr = dirpath;
2517
   s8 *dptr = directory;
2502
   s8 *dptr = directory;
2518
   s8 *remainingpath = NULL;
2503
   s8 *remainingpath = NULL;
2519
 
2504
 
2520
   /* 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 */
2521
   if(*cptr == '/') cptr++;
2506
   if(*cptr == '/') cptr++;
2522
   /* search end of path or subdirectory*/
2507
   /* search end of path or subdirectory*/
2523
   while((*cptr != 0) && (*cptr != '/'))
2508
   while((*cptr != 0) && (*cptr != '/'))
2524
   {
2509
   {
2525
      *dptr = *cptr;   // copy to directory string buffer
2510
      *dptr = *cptr;   // copy to directory string buffer
2526
       dptr++;
2511
       dptr++;
2527
       cptr++;
2512
       cptr++;
2528
   }
2513
   }
2529
   if(*cptr!=0) remainingpath = ++cptr; // return pointer to remaining path string
2514
   if(*cptr!=0) remainingpath = ++cptr; // return pointer to remaining path string
2530
   *dptr = 0; // terminate directory name string
2515
   *dptr = 0; // terminate directory name string
2531
 
2516
 
2532
   return(remainingpath);
2517
   return(remainingpath);
2533
}
2518
}
2534
 
2519
 
2535
 
2520
 
2536
/********************************************************************************************************************************************/
2521
/********************************************************************************************************************************************/
2537
/*      Function:               u8 chdir_(s8* const path);                                                                                                                                                                                              */
2522
/*      Function:               u8 chdir_(s8* const path);                                                                                                                                                                                              */
2538
/*                                                                                                                                                                                                                                                                                      */
2523
/*                                                                                                                                                                                                                                                                                      */
2539
/*      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                                                  */
2540
/*                  by function findfirst()                                                                                                                                                                                                     */
2525
/*                  by function findfirst()                                                                                                                                                                                                     */
2541
/*                                                                                                                                                                                                                                                                                      */
2526
/*                                                                                                                                                                                                                                                                                      */
2542
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2527
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2543
/********************************************************************************************************************************************/
2528
/********************************************************************************************************************************************/
2544
 
2529
 
2545
u8 chdir_(s8* const path)
2530
u8 chdir_(s8* const path)
2546
{
2531
{
2547
        u8              retvalue = 0;                                   // the value returned by this function
2532
        u8              retvalue = 0;                                   // the value returned by this function
2548
        u32     ultemp = 0;                                             // temp. variable
2533
        u32     ultemp = 0;                                             // temp. variable
2549
        s8      *dirpath = path;                                // pointer to the remaining path string
2534
        s8      *dirpath = path;                                // pointer to the remaining path string
2550
        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
2551
        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
2552
        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
2553
        u32     tcwd = 0;                                               // temporarily we remember the actual current working directory
2538
        u32     tcwd = 0;                                               // temporarily we remember the actual current working directory
2554
 
2539
 
2555
        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
2556
        // correct filepath formatting
2541
        // correct filepath formatting
2557
        Slashing_Path(path);
2542
        Slashing_Path(path);
2558
 
2543
 
2559
        // lets remember the actual path and correspondig directory sector
2544
        // lets remember the actual path and correspondig directory sector
2560
        strcpy(tp, Partition.PathToCwd);
2545
        strcpy(tp, Partition.PathToCwd);
2561
        tcwd = Partition.CurrentWorkingDirectory;
2546
        tcwd = Partition.CurrentWorkingDirectory;
2562
 
2547
 
2563
        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
2564
        {
2549
        {
2565
                strcpy(Partition.PathToCwd, "/");
2550
                strcpy(Partition.PathToCwd, "/");
2566
                Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
2551
                Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
2567
        }
2552
        }
2568
        // parse through all the subdirectories within the path
2553
        // parse through all the subdirectories within the path
2569
        do
2554
        do
2570
        {
2555
        {
2571
                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
2572
                if(dirname[0] == 0)             // if no directory name is available 
2557
                if(dirname[0] == 0)             // if no directory name is available 
2573
                {
2558
                {
2574
                        retvalue = 1;                   // we are done
2559
                        retvalue = 1;                   // we are done
2575
                        break;                                  // break the loop
2560
                        break;                                  // break the loop
2576
                }      
2561
                }      
2577
                // search for the next subdirectory within the path
2562
                // search for the next subdirectory within the path
2578
                if(findfirst_(dirname, ATTR_SUBDIRECTORY, &fe))
2563
                if(findfirst_(dirname, ATTR_SUBDIRECTORY, &fe))
2579
                {
2564
                {
2580
                        // 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
2581
                        if(strcmp(dirname, "..") == 0) CWDPath_Pop();
2566
                        if(strcmp(dirname, "..") == 0) CWDPath_Pop();
2582
                        // 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
2583
                        else if(dirname[0] == '.') return(1);
2568
                        else if(dirname[0] == '.') return(1);
2584
                        // 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
2585
                        else CWDPath_Push(dirname);
2570
                        else CWDPath_Push(dirname);
2586
                        // 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
2587
                        ultemp = (u32) fe.fp.FirstSectorOfFirstCluster;
2572
                        ultemp = (u32) fe.fp.FirstSectorOfFirstCluster;
2588
                        // do we have to change into the rootdirectory?
2573
                        // do we have to change into the rootdirectory?
2589
                        if(ultemp)
2574
                        if(ultemp)
2590
                        {
2575
                        {
2591
                                // the first 2 entries are reserved for '.' and '..' 
2576
                                // the first 2 entries are reserved for '.' and '..' 
2592
                                ultemp -= 2;
2577
                                ultemp -= 2;
2593
                                // 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
2594
                                ultemp *= Partition.SectorsPerCluster;
2579
                                ultemp *= Partition.SectorsPerCluster;
2595
                                // 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
2596
                                ultemp += Partition.FirstDataSector;
2581
                                ultemp += Partition.FirstDataSector;
2597
                                // the cwd now points to the specified directory
2582
                                // the cwd now points to the specified directory
2598
                                Partition.CurrentWorkingDirectory = ultemp;
2583
                                Partition.CurrentWorkingDirectory = ultemp;
2599
                        }
2584
                        }
2600
                        else // (=0) root directory 
2585
                        else // (=0) root directory 
2601
                        {
2586
                        {
2602
                                // the cwd now points to the rootdirectory
2587
                                // the cwd now points to the rootdirectory
2603
                                Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
2588
                                Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
2604
                        }
2589
                        }
2605
                        retvalue = 1;
2590
                        retvalue = 1;
2606
                }
2591
                }
2607
                else // subdirectory not found
2592
                else // subdirectory not found
2608
                {
2593
                {
2609
                        retvalue = 0;           // no success tracing along the given directory chain
2594
                        retvalue = 0;           // no success tracing along the given directory chain
2610
                        break;                          // break the loop
2595
                        break;                          // break the loop
2611
                }
2596
                }
2612
        }
2597
        }
2613
        while(dirpath != NULL);  // do this until all subdirectories have been found
2598
        while(dirpath != NULL);  // do this until all subdirectories have been found
2614
 
2599
 
2615
        // 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 
2616
        if(!retvalue)
2601
        if(!retvalue)
2617
        {
2602
        {
2618
                Partition.CurrentWorkingDirectory = tcwd;
2603
                Partition.CurrentWorkingDirectory = tcwd;
2619
                strcpy(Partition.PathToCwd, tp);
2604
                strcpy(Partition.PathToCwd, tp);
2620
        }
2605
        }
2621
        return(retvalue);
2606
        return(retvalue);
2622
}
2607
}
2623
 
2608
 
2624
 
2609
 
2625
/********************************************************************************************************************************************/
2610
/********************************************************************************************************************************************/
2626
/*      Function:               u8 rmdir_(s8* dname);                                                                                                                                                                                                           */
2611
/*      Function:               u8 rmdir_(s8* dname);                                                                                                                                                                                                           */
2627
/*                                                                                                                                                                                                                                                                                      */
2612
/*                                                                                                                                                                                                                                                                                      */
2628
/*      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                                                                             */
2629
/*                                                                                                                                                                                                                                      */
2614
/*                                                                                                                                                                                                                                      */
2630
/*                                                                                                                                                                                                                                                                                      */
2615
/*                                                                                                                                                                                                                                                                                      */
2631
/*      Returnvalue:    1 : specified directory deleted succesfully 0: specified directory not found                                                                                    */
2616
/*      Returnvalue:    1 : specified directory deleted succesfully 0: specified directory not found                                                                                    */
2632
/********************************************************************************************************************************************/
2617
/********************************************************************************************************************************************/
2633
 
2618
 
2634
u8 rmdir_(s8* const dirpath)
2619
u8 rmdir_(s8* const dirpath)
2635
{
2620
{
2636
        u8 retvalue = 0;
2621
        u8 retvalue = 0;
2637
        Find_t fe;
2622
        Find_t fe;
2638
        u32 cwd;
2623
        u32 cwd;
2639
        s8 path[256];
2624
        s8 path[256];
2640
        s8 *dn;
2625
        s8 *dn;
2641
        s8 *dp;
2626
        s8 *dp;
2642
 
2627
 
2643
        if(dirpath == NULL) return(0);
2628
        if(dirpath == NULL) return(0);
2644
        // correct filepath formatting
2629
        // correct filepath formatting
2645
        Slashing_Path(dirpath);
2630
        Slashing_Path(dirpath);
2646
 
2631
 
2647
    // remember the current workingdirectory
2632
    // remember the current workingdirectory
2648
        cwd = Partition.CurrentWorkingDirectory;
2633
        cwd = Partition.CurrentWorkingDirectory;
2649
 
2634
 
2650
        // create local copy of the path
2635
        // create local copy of the path
2651
        strcpy(path, dirpath);
2636
        strcpy(path, dirpath);
2652
        // 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
2653
        // 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
2654
        dn = path;
2639
        dn = path;
2655
        dp = path;
2640
        dp = path;
2656
        // 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
2657
        while(*dn != 0) dn++;
2642
        while(*dn != 0) dn++;
2658
        // 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
2659
        if(*(dn-1) == '/') *--dn = 0;
2644
        if(*(dn-1) == '/') *--dn = 0;
2660
        // now find the beginning of the last directoryentry
2645
        // now find the beginning of the last directoryentry
2661
        while((*dn != '/') && (dn > path)) dn--;
2646
        while((*dn != '/') && (dn > path)) dn--;
2662
        // beginning of the last directory found
2647
        // beginning of the last directory found
2663
        if(*dn == '/')
2648
        if(*dn == '/')
2664
        {
2649
        {
2665
                // 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
2666
                *dn = 0;
2651
                *dn = 0;
2667
                // the dirname begins 1 character after the terminated path
2652
                // the dirname begins 1 character after the terminated path
2668
                dn++;
2653
                dn++;
2669
        }
2654
        }
2670
        // 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
2671
        else
2656
        else
2672
        {
2657
        {
2673
                // 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
2674
                if(dn == path)
2659
                if(dn == path)
2675
                {
2660
                {
2676
                        // if there is a name of a directory to be deleted?
2661
                        // if there is a name of a directory to be deleted?
2677
                        if(*dn == 0) return(0);
2662
                        if(*dn == 0) return(0);
2678
                        // 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
2679
                        dp = NULL;
2664
                        dp = NULL;
2680
                }
2665
                }
2681
 
2666
 
2682
        }
2667
        }
2683
        // 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
2684
        if(dp != NULL)
2669
        if(dp != NULL)
2685
        {
2670
        {
2686
                if(!chdir_(dp)) return(0);
2671
                if(!chdir_(dp)) return(0);
2687
        }
2672
        }
2688
        // now we have to find the specified directory to be deleted
2673
        // now we have to find the specified directory to be deleted
2689
        retvalue = findfirst_(dn, 0xff, &fe);
2674
        retvalue = findfirst_(dn, 0xff, &fe);
2690
        // was the specified directory found?
2675
        // was the specified directory found?
2691
        if(retvalue)
2676
        if(retvalue)
2692
        {
2677
        {
2693
                // 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
2694
                if(chdir_(dn))
2679
                if(chdir_(dn))
2695
                {
2680
                {
2696
                        if(findfirst_("*.*", 0xff, &fe))
2681
                        if(findfirst_("*.*", 0xff, &fe))
2697
                        {
2682
                        {
2698
                                // 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
2699
                                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;
2700
                                while(findnext_(&fe))
2685
                                while(findnext_(&fe))
2701
                                {
2686
                                {
2702
                                        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;
2703
                                }
2688
                                }
2704
                        }
2689
                        }
2705
                        chdir_("..");
2690
                        chdir_("..");
2706
                }
2691
                }
2707
                // directory couldn't be entered, is a real file?
2692
                // directory couldn't be entered, is a real file?
2708
                else
2693
                else
2709
                {
2694
                {
2710
                        retvalue = 0;
2695
                        retvalue = 0;
2711
                }
2696
                }
2712
                // specified directory is empty
2697
                // specified directory is empty
2713
                if(retvalue)
2698
                if(retvalue)
2714
                {
2699
                {
2715
                        retvalue = 0;
2700
                        retvalue = 0;
2716
                        // 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
2717
                        if(findfirst_(dn, 0xff, &fe))
2702
                        if(findfirst_(dn, 0xff, &fe))
2718
                        {
2703
                        {
2719
                                Debug("found");
2704
                                Debug("found");
2720
                                // try to clear the allocated clusters within the fat
2705
                                // try to clear the allocated clusters within the fat
2721
                                if(DeleteClusterChain(fe.fp.FirstSectorOfFirstCluster))
2706
                                if(DeleteClusterChain(fe.fp.FirstSectorOfFirstCluster))
2722
                                {
2707
                                {
2723
                                        // delete the directoryentry within the specified directory
2708
                                        // delete the directoryentry within the specified directory
2724
                                        if(DeleteDirectoryEntry(&(fe.fp))) retvalue = 1;
2709
                                        if(DeleteDirectoryEntry(&(fe.fp))) retvalue = 1;
2725
                                }
2710
                                }
2726
                        }
2711
                        }
2727
                }
2712
                }
2728
        }
2713
        }
2729
 
2714
 
2730
        // restore the actual path
2715
        // restore the actual path
2731
        Partition.CurrentWorkingDirectory = cwd;
2716
        Partition.CurrentWorkingDirectory = cwd;
2732
 
2717
 
2733
        return(retvalue);
2718
        return(retvalue);
2734
}
2719
}
2735
 
2720
 
2736
 
2721
 
2737
/********************************************************************************************************************************************/
2722
/********************************************************************************************************************************************/
2738
/*      Function:               mkdir_(s8* dirpath);                                                                                                                                                                                                    */
2723
/*      Function:               mkdir_(s8* dirpath);                                                                                                                                                                                                    */
2739
/*                                                                                                                                                                                                                                                                                      */
2724
/*                                                                                                                                                                                                                                                                                      */
2740
/*      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                                                                               */
2741
/*                                                                                                                                                                                                                                      */
2726
/*                                                                                                                                                                                                                                      */
2742
/*                                                                                                                                                                                                                                                                                      */
2727
/*                                                                                                                                                                                                                                                                                      */
2743
/*      Returnvalue:    1 : specified directory created succesfully 0: specified dir exist already                                                                                              */
2728
/*      Returnvalue:    1 : specified directory created succesfully 0: specified dir exist already                                                                                              */
2744
/********************************************************************************************************************************************/
2729
/********************************************************************************************************************************************/
2745
 
2730
 
2746
u8 mkdir_(s8* const dirpath)
2731
u8 mkdir_(s8* const dirpath)
2747
{
2732
{
2748
        u8 retvalue = 0;
2733
        u8 retvalue = 0;
2749
        File_t file;
2734
        File_t file;
2750
 
2735
 
2751
        if(dirpath == NULL) return(0);
2736
        if(dirpath == NULL) return(0);
2752
        // correct filepath formatting
2737
        // correct filepath formatting
2753
        Slashing_Path(dirpath);
2738
        Slashing_Path(dirpath);
2754
        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.
2755
        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.
2756
        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
2757
        file.SectorOfCurrCluster = SECTOR_UNDEFINED;                    // The sector within the current cluster.
2742
        file.SectorOfCurrCluster = SECTOR_UNDEFINED;                    // The sector within the current cluster.
2758
        file.ByteOfCurrSector = 0;                                                              // The byte location within the current sector.
2743
        file.ByteOfCurrSector = 0;                                                              // The byte location within the current sector.
2759
        file.Mode = 0;                                                                                  // Mode of fileoperation (read,write)
2744
        file.Mode = 0;                                                                                  // Mode of fileoperation (read,write)
2760
        file.Size = 0;                                                                                  // The size of the opend file in bytes.
2745
        file.Size = 0;                                                                                  // The size of the opend file in bytes.
2761
        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
2762
        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.
2763
        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.
2764
        file.Attribute = 0;                                                                             // The attribute of the file opened.
2749
        file.Attribute = 0;                                                                             // The attribute of the file opened.
2765
        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.
2766
        file.State = FSTATE_USED;                                                               // mark it as used
2751
        file.State = FSTATE_USED;                                                               // mark it as used
2767
        // if directory is not existent
2752
        // if directory is not existent
2768
        if(!FileExist(dirpath, ATTR_SUBDIRECTORY, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, &file))
2753
        if(!FileExist(dirpath, ATTR_SUBDIRECTORY, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, &file))
2769
        {
2754
        {
2770
                retvalue = FileCreate(dirpath, ATTR_SUBDIRECTORY, &file);
2755
                retvalue = FileCreate(dirpath, ATTR_SUBDIRECTORY, &file);
2771
        }
2756
        }
2772
        return(retvalue);
2757
        return(retvalue);
2773
}
2758
}
2774
 
2759
 
2775
 
2760
 
2776
 
2761
 
2777
 
2762
 
2778
 
2763
 
2779
 
2764
 
2780
 
2765
 
2781
 
2766