Subversion Repositories NaviCtrl

Rev

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

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