1 | /*
|
2 | * Doku, siehe http://www.mikrocontroller.net/articles/AVR_FAT32
|
3 | * Neuste Version: http://www.mikrocontroller.net/svnbrowser/avr-fat32/
|
4 | * Autor: Daniel R.
|
5 | */
|
6 |
|
7 | #include <string.h>
|
8 | #include <stdlib.h>
|
9 |
|
10 | #include "config.h"
|
11 | #include "mmc.h"
|
12 | #include "fat.h"
|
13 | #include "file.h"
|
14 |
|
15 | #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
|
16 | unsigned char multiblock_flag;
|
17 | #endif
|
18 |
|
19 |
|
20 | //*******************************************************************************************************************************
|
21 | // funktionsprototypen die nur in dieser datei benutzt werden !
|
22 | #if (MMC_LS==TRUE)
|
23 | static void lsRowsOfClust (fptr uputs_ptr, unsigned long int start_sec); // zeigt reihen eines clusters an, ab start_sec, muss zeiger auf eine ausgabe funktion überbeben bekommen
|
24 | #endif
|
25 | //*******************************************************************************************************************************
|
26 |
|
27 |
|
28 | #if (MMC_FILE_EXSISTS==TRUE)
|
29 | // *******************************************************************************************************************************
|
30 | // prueft ob es die datei im aktuellen verzeichnis gibt.
|
31 | // ffopen wuerde die datei direkt anlegen, falls es sie noch nicht gibt!
|
32 | // *******************************************************************************************************************************
|
33 | unsigned char ffileExsists ( unsigned char name[]){
|
34 | return fat_loadFileDataFromDir(name);
|
35 | }
|
36 | #endif
|
37 |
|
38 | //*******************************************************************************************************************************
|
39 | // 2 moeglichkeiten beim oeffnen, datei existiert(return MMC_FILE_EXISTS) oder muss angelegt werden(return MMC_FILE_NEW)
|
40 | // zuerst wird geprueft ob es die datei im verzeichniss gibt. danach wird entschieden, ob die datei geoeffnet wird oder angelegt.
|
41 | // -beim oeffnen werden die bekannten cluster gesucht maximal MAX_CLUSTERS_IN_ROW in reihe. dann wird der 1. sektor der datei auf
|
42 | // den puffer fat.sector geladen. jetzt kann man ffread lesen...
|
43 | // -beim anlegen werden freie cluster gesucht, maximal MAX_CLUSTERS_IN_ROW in reihe. dann wird das struct file gefuellt.
|
44 | // danach wird der dateieintrag gemacht(auf karte). dort wird auch geprueft ob genügend platz im aktuellen verzeichniss existiert.
|
45 | // moeglicherweise wird der 1. cluster der datei nochmal geaendert. jetzt ist der erste frei sektor bekannt und es kann geschrieben werden.
|
46 | //*******************************************************************************************************************************
|
47 | unsigned char ffopen( unsigned char name[]){
|
48 |
|
49 | unsigned char file_flag = fat_loadFileDataFromDir(name); //pruefung ob datei vorhanden. wenn vorhanden, laden der daten auf das file struct.
|
50 |
|
51 | if( file_flag==TRUE ){ /** datei existiert, anlegen nicht noetig! **/
|
52 | fat_getFatChainClustersInRow( file.firstCluster ); // verkettete cluster aus der fat-chain suchen.
|
53 | file.name = name;
|
54 |
|
55 | #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
|
56 | fat.currentSectorNr = fat.startSectors;
|
57 | multiblock_flag = TRUE;
|
58 | mmc_multi_block_start_read (fat.startSectors);
|
59 | mmc_multi_block_read_sector (fat.sector);
|
60 | #else
|
61 | fat_loadSector( fat.startSectors ); // laed die ersten 512 bytes der datei auf puffer:sector.
|
62 | #endif
|
63 |
|
64 | return MMC_FILE_EXISTS;
|
65 | }
|
66 |
|
67 | #if (MMC_WRITE==TRUE) // anlegen ist schreiben !
|
68 | else{ /** datei existiert nicht, also anlegen ! (nur wenn schreiben option an ist)**/
|
69 | file.name = name; // pointer "sichern" ;)
|
70 | fat_makeFileEntry(name,0x20); // DATEI ANLEGEN auf karte
|
71 | #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
|
72 | multiblock_flag = FALSE;
|
73 | mmc_multi_block_start_write(fat.currentSectorNr);
|
74 | #endif
|
75 | fat.bufferDirty = TRUE; // puffer dirty weil geschrieben und noch nicht auf karte.
|
76 | return MMC_FILE_NEW;
|
77 | }
|
78 | #endif
|
79 |
|
80 |
|
81 | #if (MMC_WRITE==FALSE)
|
82 | return MMC_FILE_NOT_EXISTS; // wird nur bei readonly zurueckgegeben, wenn datei nicht gefunden wurde.
|
83 | #endif
|
84 |
|
85 | }
|
86 |
|
87 |
|
88 | //*******************************************************************************************************************************
|
89 | // schließt die datei operation ab. eigentlich nur noetig wenn geschrieben/ueberschrieben wurde. es gibt 2 moeglichkeiten :
|
90 | // 1. die datei wird geschlossen und es wurde über die alte datei länge hinaus geschrieben.
|
91 | // 2. die datei wird geschlossen und man war innerhalb der datei groeße, dann muss nur der aktuelle sektor geschrieben werden.
|
92 | // der erste fall ist komplizierter, weil ermittelt werden muss wie viele sektoren neu beschrieben wurden um diese zu verketten
|
93 | // und die neue datei laenge muss ermitt weden. abschließend wird entweder (fall 2) nur der aktuelle sektor geschrieben, oder
|
94 | // der aktuallisierte datei eintrag und die cluster (diese werden verkettet, siehe fileUpdate() ).
|
95 | //*******************************************************************************************************************************
|
96 | unsigned char ffclose(){
|
97 |
|
98 | #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
|
99 | if(multiblock_flag == TRUE){
|
100 | mmc_multi_block_stop_read(); // stoppen von multiblock aktion
|
101 | }
|
102 | else{
|
103 | mmc_multi_block_stop_write(); // stoppen von multiblock aktion
|
104 | }
|
105 | #endif
|
106 |
|
107 | #if (MMC_WRITE==TRUE) /** 2 moeglichkeiten beim schließen !! (lesend spielt keine rolle, nichts muss geupdatet werden) **/
|
108 | fflushFileData();
|
109 | #endif
|
110 |
|
111 | fat.cntOfBytes=0;
|
112 | file.seek=0;
|
113 |
|
114 | return TRUE;
|
115 | }
|
116 |
|
117 |
|
118 | #if (MMC_WRITE==TRUE)
|
119 | // *******************************************************************************************************************************
|
120 | // füllt grade bearbeiteten sektor auf, verkette die bis jetzt benutzten cluster. macht datei eintrag update.
|
121 | // *******************************************************************************************************************************
|
122 | void fflushFileData(void){
|
123 |
|
124 | unsigned long int save_length;
|
125 | unsigned long int save_currentSectorNr;
|
126 | unsigned short save_cntOfBytes;
|
127 | unsigned short row;
|
128 |
|
129 | #if (MMC_ENDIANNESS_LITTLE == TRUE)
|
130 | void *psector;
|
131 | #else
|
132 | unsigned char *psector;
|
133 | #endif
|
134 |
|
135 | /** 2 moeglichkeiten ab hier **/
|
136 | /** 1.) es wurde über die alte datei groeße hinaus geschrieben **/
|
137 | if( file.length < file.seek+fat.cntOfBytes ) {
|
138 |
|
139 | save_length = file.seek + fat.cntOfBytes;
|
140 | save_currentSectorNr = fat.currentSectorNr;
|
141 |
|
142 | // wenn fat.cntOfBytes == 0 ist der sektor gerade vorher schon geschrieben worden oder es ist noch nichts hinein geschrieben worden. dann wert so setzten, dass die schleife uebersprungen wird
|
143 | save_cntOfBytes = fat.cntOfBytes==0 ? 512 : fat.cntOfBytes;
|
144 | while( save_cntOfBytes < 512 ){ // sektor ist beschrieben worden, daher rest mit 00 fuellen
|
145 | fat.sector[save_cntOfBytes] = 0x00; // beschreibt ungenutzte bytes mit 0x00
|
146 | save_cntOfBytes+=1;
|
147 | fat.bufferDirty = TRUE;
|
148 | }
|
149 |
|
150 | // cluster chain verketten, dann dateieitrag mit neuer groeße updaten!
|
151 | fat_setClusterChain(fat_secToClust(fat.startSectors),fat_secToClust(fat.currentSectorNr)); // verketten der geschriebenen cluster
|
152 |
|
153 | // dateigroeße updaten !!
|
154 | fat_loadSector(file.entrySector); // laden des sektors mit dem dateieintrag zwecks update :)
|
155 | row = file.row;
|
156 | row <<=5;
|
157 | psector =& fat.sector[row+28];
|
158 |
|
159 | #if (MMC_ENDIANNESS_LITTLE == TRUE)
|
160 | *(unsigned long int*)psector = save_length;
|
161 | #else
|
162 | *psector++ = save_length;
|
163 | *psector++ = save_length >> 8;
|
164 | *psector++ = save_length >> 16;
|
165 | *psector = save_length >> 24;
|
166 | #endif
|
167 |
|
168 | file.length = save_length; // die richtige groeße sichern. wurde ja ueber alte dateigroeße hinaus geschrieben
|
169 | fat.startSectors = save_currentSectorNr; // da die sektoren bis zu save_currentSectorNr schon verkettet wurden, reicht es jetzt die kette ab da zu betrachten.
|
170 |
|
171 | // dafuer sorgen, dass der sektor mit dem geaenderten dateieintrag geschrieben wird, beim neuladen. datensektor der datei neuladen, falls noch weitere bytes geschrieben werden.
|
172 | fat.bufferDirty = TRUE;
|
173 | fat_loadSector( save_currentSectorNr );
|
174 | }
|
175 |
|
176 | /** 2.) es wurde nicht über die alte datei groeße hinaus geschrieben **/
|
177 | else if( fat.bufferDirty == TRUE){
|
178 | fat_writeSector( fat.currentSectorNr ); // einfach den gerade bearbeiteten sektor schreiben reicht, alle dateiinfos stimmen weil nicht ueber die alte groeße hinaus geschrieben
|
179 | }
|
180 |
|
181 |
|
182 | }
|
183 | #endif
|
184 |
|
185 | #if (MMC_SEEK==TRUE)
|
186 | // *******************************************************************************************************************************
|
187 | // offset byte wird übergeben. es wird durch die sektoren der datei gespult (gerechnet), bis der sektor mit dem offset byte erreicht
|
188 | // ist, dann wird der sektor geladen und der zaehler für die bytes eines sektors gesetzt. wenn das byte nicht in den sektoren ist,
|
189 | // die "vorgesucht" wurden, muessen noch weitere sektoren der datei gesucht werden (sec > fat.endSectors).
|
190 | // *******************************************************************************************************************************
|
191 | void ffseek(unsigned long int offset){
|
192 |
|
193 | unsigned long int sectors; // zum durchgehen durch die sektoren der datei
|
194 |
|
195 | #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
|
196 | unsigned char seek_end;
|
197 | seek_end = FALSE;
|
198 |
|
199 | if(offset == file.length) { // zum ende spulen, kann dann nur schreiben sein...
|
200 | seek_end = TRUE;
|
201 | }
|
202 | if(multiblock_flag == FALSE){
|
203 | mmc_multi_block_stop_write();
|
204 | }
|
205 | else {
|
206 | mmc_multi_block_stop_read();
|
207 | }
|
208 | #endif
|
209 |
|
210 | #if (MMC_OVER_WRITE==TRUE && MMC_WRITE==TRUE)
|
211 | fflushFileData(); // fat verketten und datei update auf der karte !
|
212 | #endif
|
213 |
|
214 | fat_getFatChainClustersInRow(file.firstCluster); // suchen von anfang der cluster chain aus, das geht nicht vom ende zum anfang oder so, weil es eine einfach verkettete liste ist !
|
215 | sectors = fat.startSectors; // sektor variable zum durchgehen durch die sektoren
|
216 | file.seek=0; // weil auch von anfang an der chain gesucht wird mit 0 initialisiert
|
217 |
|
218 | // suchen des sektors in dem offset ist
|
219 | while( offset>=512 ){
|
220 | sectors += 1; // da byte nicht in diesem sektor ist, muss hochgezählt werden
|
221 | offset -= 512; // ein sektor weniger in dem das byte sein kann
|
222 | file.seek += 512; // file.seek update, damit bei ffclose() die richtige leange herauskommt
|
223 | fat.cntSecs -= 1; // damit die zu lesenden/schreibenden sektoren in einer reihe stimmen
|
224 | if ( fat.cntSecs==0 ){ // es müssen mehr sektoren der datei gesucht werden. sektoren in einer reihe durchgegangen
|
225 | fat_getFatChainClustersInRow(fat_getNextCluster( file.lastCluster ) ); // suchen von weiteren sektoren der datei in einer reihe
|
226 | sectors = fat.startSectors; // setzen des 1. sektors der neu geladenen, zum weitersuchen !
|
227 | }
|
228 | }
|
229 |
|
230 | fat_loadSector(sectors); // sektor mit offset byte laden
|
231 | fat.cntOfBytes = offset; // setzen des lese zaehlers
|
232 |
|
233 | #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
|
234 | if(seek_end == TRUE) {
|
235 | mmc_multi_block_start_write(sectors); // starten von multiblock aktion
|
236 | fat.bufferDirty = TRUE;
|
237 | }
|
238 | else {
|
239 | mmc_multi_block_start_read(sectors); // starten von multiblock aktion
|
240 | }
|
241 | #endif
|
242 | }
|
243 | #endif
|
244 |
|
245 |
|
246 | #if (MMC_CD==TRUE)
|
247 | // *******************************************************************************************************************************
|
248 | // wechselt verzeichniss. start immer im root Dir.
|
249 | // es MUSS in das direktory gewechselt werden, in dem die datei zum lesen/schreiben ist !
|
250 | // *******************************************************************************************************************************
|
251 | unsigned char ffcd( unsigned char name[]){
|
252 |
|
253 | if(name[0]==0){ // ZUM ROOTDIR FAT16/32
|
254 | fat.dir=0; // root dir
|
255 | return TRUE;
|
256 | }
|
257 |
|
258 | if(TRUE==fat_loadFileDataFromDir(name)){ // NICHT ROOTDIR (fat16/32)
|
259 | fat.dir=file.firstCluster; // zeigt auf 1.cluster des dir (fat16/32)
|
260 | return TRUE;
|
261 | }
|
262 |
|
263 | return FALSE; // dir nicht gewechselt (nicht da?) !!
|
264 | }
|
265 |
|
266 | //*******************************************************************************************************************************
|
267 | // wechselt in das parent verzeichniss (ein verzeichniss zurück !)
|
268 | // die variable fat.dir enthält den start cluster des direktory in dem man sich grade befindet, anhand diesem,
|
269 | // kann der "." bzw ".." eintrag im ersten sektor des direktory ausgelesen und das parent direktory bestimmt werden.
|
270 | //*******************************************************************************************************************************
|
271 | unsigned char ffcdLower(void){
|
272 |
|
273 | if(fat.dir==0)return FALSE; // im root dir, man kann nicht hoeher !
|
274 |
|
275 | fat_loadSector(fat_clustToSec(fat.dir)); // laed 1. sektor des aktuellen direktory.
|
276 | fat_loadRowOfSector(1); // ".." eintrag (parent dir) ist 0 wenn parent == root
|
277 | fat.dir=file.firstCluster; // dir setzen
|
278 |
|
279 | return TRUE;
|
280 | }
|
281 | #endif
|
282 |
|
283 |
|
284 | #if (MMC_LS==TRUE)
|
285 | // *******************************************************************************************************************************
|
286 | // zeigt reihen eines clusters an, wird für ffls benoetigt !
|
287 | // es wird ab dem start sektor start_sec, der dazugehoerige cluster angezeigt. geprüft wird ob es ein richtiger
|
288 | // eintrag in der reihe ist (nicht geloescht, nicht frei usw). die sektoren des clusters werden nachgeladen.
|
289 | // die dateien werden mit namen und datei groeße angezeigt.
|
290 | // *******************************************************************************************************************************
|
291 | static void lsRowsOfClust (fptr uputs_ptr,unsigned long int start_sec){
|
292 |
|
293 | unsigned short row; // reihen
|
294 | unsigned char sec; // sektoren
|
295 | unsigned char tmp[11]; // tmp string zur umwandlung
|
296 | unsigned char i; // um dateinamen zu lesen
|
297 |
|
298 | sec=0;
|
299 | do{
|
300 | fat_loadSector( start_sec + sec ); // sektoren des clusters laden
|
301 | for( row=0; row<512; row+=32 ){ // geht durch reihen des sektors
|
302 |
|
303 | if( (fat.sector[row+11]==0x20||fat.sector[row+11]==0x10) && (fat.sector[row]!=0xE5 && fat.sector[row]!=0x00) ){
|
304 | for( i=0 ; i<10 ; i++ ){
|
305 | tmp[i]=fat.sector[row+i];
|
306 | }
|
307 | tmp[i]='\0';
|
308 | fat_loadRowOfSector(row); // reihe eines sektors (auf den puffer) laden
|
309 | uputs_ptr(tmp);
|
310 |
|
311 | uputs_ptr((unsigned char*)" ");
|
312 | ultoa(file.length,(char*)tmp,10);
|
313 | uputs_ptr(tmp);
|
314 | uputs_ptr((unsigned char*)"\n");
|
315 | }
|
316 | }
|
317 | }while( ++sec < fat.secPerClust );
|
318 | }
|
319 |
|
320 | // *******************************************************************************************************************************
|
321 | // zeigt inhalt eines direktory an.
|
322 | // unterscheidung ob man sich im rootDir befindet noetig, weil bei fat16 im root dir eine bestimmt anzahl sektoren durchsucht
|
323 | // werden müssen und bei fat32 ab einem start cluster ! ruft lsRowsOfClust auf um cluster/sektoren anzuzeigen.
|
324 | // *******************************************************************************************************************************
|
325 | void ffls(fptr uputs_ptr){
|
326 |
|
327 | unsigned char sectors; // variable um durch sektoren zu zaehlen
|
328 | unsigned long int clusters; // variable um durch cluster des verzeichnisses zu gehen
|
329 |
|
330 | // bestimmen ab welchem cluster eintraege angezeigt werden sollen, bzw in welchem ordner man sich befindet
|
331 | clusters = fat.dir==0?fat.rootDir:fat.dir;
|
332 |
|
333 | // root-dir fat16 nach eintrag durchsuchen. es bleiben noch 3 moeglichkeiten: nicht root-dir fat16, nicht root-dir fat32 und root-dir fat32
|
334 | if(fat.dir==0 && fat.fatType==16){
|
335 | sectors = 0;
|
336 | do{
|
337 | // root-dir eintraege anzeigen
|
338 | lsRowsOfClust( uputs_ptr, clusters + sectors );
|
339 | sectors += fat.secPerClust;
|
340 | }while( sectors < (unsigned char)32 );
|
341 | }
|
342 |
|
343 | // root-dir fat32 oder nicht root-dir fat32/16, nach eintrag durchsuchen
|
344 | else {
|
345 | // durch cluster des verzeichnisses gehen und eintraege anzeigen
|
346 | while(!((clusters>=0x0ffffff8&&fat.fatType==32)||(clusters>=0xfff8&&fat.fatType==16))){ // prueft ob weitere sektoren zum lesen da sind (fat32||fat16)
|
347 | lsRowsOfClust( uputs_ptr, fat_clustToSec(clusters) ); // zeigt reihen des clusters an
|
348 | clusters = fat_getNextCluster(clusters); // liest naechsten cluster des dir-eintrags (unterverzeichniss groeßer 16 einträge)
|
349 | }
|
350 | }
|
351 |
|
352 | }
|
353 | #endif
|
354 |
|
355 |
|
356 |
|
357 | #if (MMC_WRITE==TRUE && MMC_MKDIR==TRUE)
|
358 | // *******************************************************************************************************************************
|
359 | // erstellt einen dir eintrag im aktuellen verzeichniss.
|
360 | // prüft ob es den den dir-namen schon gibt, dann wird nichts angelegt.
|
361 | // wenn ok, dann wird ein freier cluster gesucht, als ende markiert, der eintrag ins dir geschrieben.
|
362 | // dann wird der cluster des dirs aufbereitet. der erste sektor des clusters enthält den "." und ".." eintrag.
|
363 | // der "." hat den 1. cluster des eigenen dirs. der ".." eintrag ist der 1. cluster des parent dirs.
|
364 | // ein dir wird immer mit 0x00 initialisiert ! also alle einträge der sektoren des clusters ( bis auf . und .. einträge)!
|
365 | // *******************************************************************************************************************************
|
366 | void ffmkdir( unsigned char name[]){
|
367 |
|
368 | unsigned char i; // variable zum zaehlen der sektoren eines clusters.
|
369 | unsigned int j; // variable zum zaehlen der sektor bytes auf dem puffer fat.sector.
|
370 |
|
371 | if(TRUE==fat_loadFileDataFromDir(name)) // prueft ob dirname im dir schon vorhanden, wenn ja, abbruch !
|
372 | return ;
|
373 |
|
374 | // cluster in fat setzen, und ordner eintrg im aktuellen verzeichniss machen.
|
375 | fat_getFreeClustersInRow(2); // holt neue freie cluster, ab 2 ...
|
376 | fat_setCluster(fat_secToClust(fat.startSectors),0x0fffffff); // fat16/32 cluster chain ende setzen. (neuer ordner in fat)
|
377 | file.firstCluster = fat_secToClust(fat.startSectors); // damit fat_makeFileEntry den cluster richtig setzen kann
|
378 | fat_makeFileEntry(name,0x10); // macht dir eintrag im aktuellen verzeichniss (legt ordner im partent verzeichniss an)
|
379 |
|
380 | // aufbereiten des puffers
|
381 | j=511;
|
382 | do{
|
383 | fat.sector[j]=0x00; //schreibt puffer fat.sector voll mit 0x00==leer
|
384 | }while(j--);
|
385 |
|
386 | // aufbereiten des clusters
|
387 | for(i=1;i<fat.secPerClust;i++){ // ein dir cluster muss mit 0x00 initialisiert werden !
|
388 | fat_writeSector(fat.startSectors+i); // loeschen des cluster (ueberschreibt mit 0x00), wichtig bei ffls!
|
389 | }
|
390 |
|
391 | // aufbereiten des neuen dir sektors mit "." und ".." eintraegen !
|
392 | file.row=0;
|
393 | fat_makeSfnDataEntry((unsigned char*)". ",0x10,file.firstCluster,0); // macht "." eintrag des dirs
|
394 | file.row=1;
|
395 | fat_makeSfnDataEntry((unsigned char*)".. ",0x10,fat.dir,0); // macht ".." eintrag des dirs
|
396 |
|
397 | // "." und ".." eintrag auf karte schreiben
|
398 | mmc_write_sector(fat.startSectors,fat.sector);
|
399 | }
|
400 | #endif
|
401 |
|
402 |
|
403 |
|
404 | #if (MMC_WRITE==TRUE && MMC_RM==TRUE)
|
405 | //*******************************************************************************************************************************
|
406 | // loescht datei/ordner aus aktuellem verzeichniss, wenn es die/den datei/ordner gibt.
|
407 | // loescht dateien und ordner rekursiv !
|
408 | //*******************************************************************************************************************************
|
409 | unsigned char ffrm( unsigned char name[] ){
|
410 |
|
411 | #if(MMC_RM_FILES_ONLY==FALSE)
|
412 | unsigned long int parent; // vaterverzeichnis cluster
|
413 | unsigned long int own; // cluster des eigenen verzeichnis
|
414 | unsigned long int clustsOfDir; // um durch die cluster eines dirs zu gehen
|
415 | unsigned char cntSecOfClust; // um durch die sektoren eines clusters zu gehen
|
416 | #endif
|
417 |
|
418 | unsigned short row; // um durch die reihen eines sektors zu gehen. springt immer auf das anfangsbyte eines eintrags
|
419 | unsigned char fileAttrib; // zum sichern des dateiattributs
|
420 |
|
421 | // datei/ordner nicht vorhanden, dann nicht loschen...
|
422 | if(FALSE==fat_loadFileDataFromDir(name)){
|
423 | return FALSE;
|
424 | }
|
425 |
|
426 | // reihe zu byte offset umrechnen, attribut sichern. anhand des attributs wird spaeter weiter entschieden
|
427 | row=file.row;
|
428 | row=row<<5;
|
429 | fileAttrib = fat.sector[row+11];
|
430 |
|
431 | #if(MMC_RM_FILES_ONLY==TRUE)
|
432 | // keine datei, also abbruch !
|
433 | if(fileAttrib!=0x20) return FALSE;
|
434 | #endif
|
435 |
|
436 | //////// ob ordner oder datei, der sfn und lfn muss geloescht werden!
|
437 | fat.bufferDirty = TRUE; // damit beim laden der geaenderte puffer geschrieben wird
|
438 | do{
|
439 | fat.sector[row]=0xE5;
|
440 | if( row==0 ){ // eintraege gehen im vorherigen sektor weiter
|
441 | fat_loadSector(fat.lastSectorNr); // der davor ist noch bekannt. selbst wenn der aus dem cluster davor stammt.
|
442 | fat.bufferDirty = TRUE;
|
443 | row=512; // da nochmal row-=32 gemacht wird, kommt man so auf den anfang der letzten zeile
|
444 | }
|
445 | row -= 32;
|
446 | }while( fat.sector[row+11]==0x0f ); // geht durch alle reihen bis neuer eintrag erkannt wird...
|
447 |
|
448 | #if(MMC_RM_FILES_ONLY==TRUE)
|
449 | fat_delClusterChain(file.firstCluster); // loescht die zu der datei gehoerige cluster-chain aus der fat.
|
450 | #else
|
451 | //// ist datei. dann nur noch cluster-chain loeschen und fertig.
|
452 | if( fileAttrib == 0x20 ){
|
453 | fat_delClusterChain(file.firstCluster); // loescht die zu der datei gehoerige cluster-chain aus der fat.
|
454 | }
|
455 | //// ist ordner. jetzt rekursiv durch alle zweige/aeste des baums, den dieser ordner evtl. aufspannt, und alles loeschen!
|
456 | else{
|
457 | clustsOfDir = file.firstCluster;
|
458 | // jetzt eigentlichen ordnerinhalt rekursiv loeschen!
|
459 | do{
|
460 | do{
|
461 | cntSecOfClust=0;
|
462 | do{
|
463 | fat_loadSector( fat_clustToSec(clustsOfDir) + cntSecOfClust ); // in ordner wechseln / neuen cluster laden zum bearbeiten
|
464 | row=0;
|
465 | do{
|
466 | // nach einem leeren eintrag kommt nix mehr. cntSecOfClust wird auch gesetzt, damit man auch durch die naechste schleife faellt!
|
467 | if(fat.sector[row]==0x00){
|
468 | cntSecOfClust = fat.secPerClust;
|
469 | break;
|
470 | }
|
471 |
|
472 | // sfn eintrag erkannt. eintrag geloescht markieren, cluster chain loeschen, diesen sektor neu laden!
|
473 | if( fat.sector[row]!=0xE5 && fat.sector[row+11]!=0x10 && fat.sector[row+11]!=0x0F ){
|
474 | fat_loadRowOfSector(row);
|
475 | fat.sector[row] = 0xE5; // hier evtl. nur pruefen ob file.firstCluster nicht schon in der fat geloescht ist...
|
476 | fat.bufferDirty = TRUE;
|
477 | fat_delClusterChain(file.firstCluster);
|
478 | fat_loadSector( fat_clustToSec(clustsOfDir) + cntSecOfClust ); // aktuellen sektor wieder laden...wurde bei fat_delClusterChain geaendert
|
479 | }
|
480 |
|
481 | // punkt eintrag erkannt, own und parent sichern!
|
482 | if( fat.sector[row]=='.' && row==0 && fat.sector[row+11]==0x10){
|
483 | fat_loadRowOfSector(row);
|
484 | own = file.firstCluster;
|
485 | fat_loadRowOfSector(row+32);
|
486 | parent = file.firstCluster;
|
487 | }
|
488 |
|
489 | // ordner erkannt. jetzt ordner eintrag loeschen, hinein wechseln und alles von vorne...
|
490 | if( fat.sector[row]!='.' && fat.sector[row]!=0xE5 && fat.sector[row+11]==0x10){
|
491 | fat_loadRowOfSector(row);
|
492 | fat.sector[row] = 0xE5;
|
493 | fat.bufferDirty = TRUE;
|
494 | clustsOfDir = file.firstCluster;
|
495 | fat_loadSector( fat_clustToSec(clustsOfDir) ); // hier wird in das dir gewechselt!
|
496 | row = 0;
|
497 | cntSecOfClust = 0;
|
498 | continue;
|
499 | }
|
500 |
|
501 | row += 32;
|
502 | }while( row < 512 );
|
503 | }while( ++cntSecOfClust < fat.secPerClust );
|
504 | clustsOfDir = fat_getNextCluster(clustsOfDir); // holen des folgeclusters um durch die chain zu gehen
|
505 | }while( !((clustsOfDir>=0x0ffffff8 && fat.fatType==32) || (clustsOfDir==0xfff8 && fat.fatType==16)) ); // geht durch cluster des dirs.
|
506 |
|
507 | // hier ist man am ende eines astes. also ast loeschen und zuruck zum stamm :)
|
508 | fat_delClusterChain(own);
|
509 |
|
510 | // stamm ist ein weiterer ast wenn parent!=fat.dir. ast wird oben geladen und weiter verarbeitet
|
511 | clustsOfDir = parent;
|
512 |
|
513 | }while(parent!=fat.dir);
|
514 | }
|
515 | #endif
|
516 | return TRUE; // alles ok, datei/ordner geloescht !
|
517 | }
|
518 | #endif
|
519 |
|
520 |
|
521 | // *******************************************************************************************************************************
|
522 | // liest 512 bytes aus dem puffer fat.sector. dann werden neue 512 bytes der datei geladen, sind nicht genuegend verkettete
|
523 | // sektoren in einer reihe bekannt, wird in der fat nachgeschaut. dann werden weiter bekannte nachgeladen...
|
524 | // *******************************************************************************************************************************
|
525 | unsigned char ffread(void){
|
526 |
|
527 | unsigned long int nc;
|
528 |
|
529 | if( fat.cntOfBytes == 512 ){ // EINEN SEKTOR GLESEN (ab hier 2 moeglichkeiten !)
|
530 |
|
531 | fat.cntSecs-=1; // anzahl der sektoren am stück werden weniger, bis zu 0 dann müssen neue gesucht werden...
|
532 |
|
533 | if( 0==fat.cntSecs ){ //1.) noetig mehr sektoren der chain zu laden (mit ein bisschen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes)
|
534 |
|
535 | #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
|
536 | mmc_multi_block_stop_read (); // stoppen von multiblock aktion
|
537 | #endif
|
538 |
|
539 | nc = fat_secToClust( fat.currentSectorNr ); // umrechnen der aktuellen sektor position in cluster
|
540 | nc = fat_getNextCluster(nc); // in der fat nach neuem ketten anfang suchen
|
541 | fat_getFatChainClustersInRow(nc); // zusammenhängende cluster/sektoren der datei suchen
|
542 | fat.currentSectorNr = fat.startSectors - 1; // hier muss erniedrigt werden, da nach dem if immer ++ gemacht wird
|
543 |
|
544 | #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
|
545 | mmc_multi_block_start_read (fat.startSectors); // starten von multiblock lesen ab dem neu gesuchten start sektor der kette.
|
546 | #endif
|
547 | }
|
548 |
|
549 | fat.cntOfBytes = 0;
|
550 |
|
551 | #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
|
552 | fat.currentSectorNr+=1;
|
553 | mmc_multi_block_read_sector (fat.sector); //2.) bekannte sektoren reichen noch, also einfach nachladen..
|
554 | #else
|
555 | fat_loadSector(fat.currentSectorNr+1); //2.) die bekannten in einer reihe reichen noch.(nur alle 512 bytes)
|
556 | #endif
|
557 | }
|
558 | return fat.sector[fat.cntOfBytes++];
|
559 | }
|
560 |
|
561 |
|
562 |
|
563 | #if (MMC_OVER_WRITE==FALSE && MMC_WRITE==TRUE) // nicht ueberschreibende write funktion
|
564 | //*******************************************************************************************************************************
|
565 | // schreibt 512 byte bloecke auf den puffer fat.sector. dann wird dieser auf die karte geschrieben. wenn genügend feie
|
566 | // sektoren zum beschreiben bekannt sind(datenmenge zu groß), muss nicht in der fat nachgeschaut werden. sollten nicht genügend
|
567 | // zusammenhängende sektoren bekannt sein, werden die alten verkettet und neue gesucht. es ist noetig sich den letzten bekannten
|
568 | // einer kette zu merken -> file.lastCluster, um auch nicht zusammenhängende cluster verketten zu koennen (fat_setClusterChain macht das)!
|
569 | //*******************************************************************************************************************************
|
570 | void ffwrite( unsigned char c){
|
571 |
|
572 | fat.sector[fat.cntOfBytes++] = c; // schreiben des chars auf den puffer sector und zähler erhoehen (pre-increment)
|
573 |
|
574 | if( fat.cntOfBytes==512 ){ /** SEKTOR VOLL ( 2 moeglichkeiten ab hier !) **/
|
575 | file.seek += 512; // position in der datei erhoehen, weil grade 512 bytes geschrieben
|
576 | fat.cntOfBytes = 0; // rücksetzen des sektor byte zählers
|
577 | fat.cntSecs -= 1; // noch maximal cntSecs sekoren zum beschreiben bekannt...
|
578 |
|
579 | #if (MMC_MULTI_BLOCK==TRUE)
|
580 | mmc_multi_block_write_sector(fat.sector); /** 1.) genügend leere zum beschreiben bekannt **/
|
581 | #else
|
582 | mmc_write_sector(fat.currentSectorNr,fat.sector); //genügend leere zum beschreiben bekannt
|
583 | #endif
|
584 |
|
585 | fat.currentSectorNr += 1; // nächsten sektor zum beschreiben.
|
586 |
|
587 | if( fat.cntSecs==0 ){ /** 2.) es ist noetig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes) **/
|
588 | #if (MMC_MULTI_BLOCK==TRUE)
|
589 | mmc_multi_block_stop_write();
|
590 | #endif
|
591 | fat.bufferDirty = FALSE; // sonst würde das suchen von clustern wieder eine schreiboperation ausloesen... siehe fat_writeSector
|
592 | fat_setClusterChain( fat_secToClust(fat.startSectors) , fat_secToClust(fat.currentSectorNr-1) ); // verketten der beschriebenen
|
593 | fat_getFreeClustersInRow(file.lastCluster); // suchen von leeren sektoren.
|
594 | fat.currentSectorNr = fat.startSectors; // setzen des 1. sektors der neuen reihe zum schreiben.
|
595 | fat.bufferDirty = TRUE;
|
596 | #if (MMC_MULTI_BLOCK==TRUE)
|
597 | mmc_multi_block_start_write(fat.currentSectorNr);
|
598 | #endif
|
599 | }
|
600 | }
|
601 | }
|
602 | #else // ueberschreibende write funktion
|
603 | //*******************************************************************************************************************************
|
604 | // schreibt 512 byte bloecke auf den puffer fat.sector. dann wird dieser auf die karte geschrieben. wenn genuegend feie
|
605 | // sektoren zum beschreiben bekannt sind, muss nicht in der fat nachgeschaut werden. sollten nicht genuegend zusammenhaengende
|
606 | // sektoren bekannt sein(datenmenge zu groß), werden die alten verkettet und neue gesucht. es ist noetig sich den letzten bekannten einer
|
607 | // kette zu merken -> file.lastCluster, um auch nicht zusammenhaengende cluster verketten zu koennen (fat_setClusterChain macht das)!
|
608 | // es ist beim überschreiben noetig, die schon beschriebenen sektoren der datei zu laden, damit man die richtigen daten
|
609 | // hat. das ist bloed, weil so ein daten overhead von 50% entsteht. da lesen aber schneller als schreiben geht, verliert man nicht 50% an geschwindigkeit.
|
610 | //*******************************************************************************************************************************
|
611 | void ffwrite( unsigned char c){
|
612 |
|
613 | fat.sector[ fat.cntOfBytes++ ]=c; // schreiben des chars auf den puffer sector und zähler erhoehen (pre-increment)
|
614 |
|
615 | if( fat.cntOfBytes==512 ){ /** SEKTOR VOLL ( 3 moeglichkeiten ab hier !) **/
|
616 |
|
617 | fat.cntOfBytes = 0; // ruecksetzen des sektor byte zählers.
|
618 | file.seek += 512; // position in der datei erhoehen, weil grade 512 bytes geschrieben.
|
619 | mmc_write_sector( fat.currentSectorNr,fat.sector ); /** 1.) vollen sektor auf karte schreiben, es sind noch freie sektoren bekannt**/
|
620 | fat.currentSectorNr +=1; // naechsten sektor zum beschreiben.
|
621 | fat.cntSecs -=1;
|
622 |
|
623 | if( fat.cntSecs==0 ){ // ende der bekannten in einer reihe erreicht (freie oder verkettete)
|
624 | if( file.seek > file.length ){ /** 2.) außerhalb der datei, jetzt ist es noetig die beschriebenen cluster zu verketten und neue freie zu suchen **/
|
625 | fat.bufferDirty = FALSE; // damit nicht durch z.b. fat_getNextCluster nochmal dieser sektor gescchrieben wird, siehe fat_loadSector
|
626 | fat_setClusterChain( fat_secToClust(fat.startSectors) , fat_secToClust(fat.currentSectorNr-1) ); // verketten der beschriebenen.
|
627 | fat_getFreeClustersInRow( file.lastCluster ); // neue leere sektoren benoetigt, also suchen.
|
628 | fat.currentSectorNr = fat.startSectors; // setzen des 1. sektors der neuen reihe zum schreiben.
|
629 | fat.bufferDirty = TRUE;
|
630 | }
|
631 | else { /** 3.) noch innerhalb der datei, aber es muessen neue verkettete cluster gesucht werden, zum ueberschreiben **/
|
632 | fat_getFatChainClustersInRow( fat_getNextCluster(file.lastCluster) ); // noch innerhalb der datei, deshlab verkettete suchen.
|
633 | fat.currentSectorNr = fat.startSectors; // setzen des 1. sektors der neuen reihe zum schreiben.
|
634 | }
|
635 | }
|
636 | if( file.seek<=file.length ){
|
637 | mmc_read_sector(fat.currentSectorNr,fat.sector); // wegen ueberschreiben, muss der zu beschreibende sektor geladen werden (zustand 3)...
|
638 | }
|
639 | }
|
640 | }
|
641 | #endif
|
642 |
|
643 |
|
644 | #if (MMC_WRITE_STRING==TRUE && MMC_WRITE==TRUE)
|
645 | // *******************************************************************************************************************************
|
646 | // schreibt string auf karte, siehe ffwrite()
|
647 | // ein string sind zeichen, '\0' bzw. 0x00 bzw dezimal 0 wird als string ende gewertet !!
|
648 | // wenn sonderzeichen auf die karte sollen, lieber ffwrite benutzen!
|
649 | // *******************************************************************************************************************************
|
650 | void ffwrites( unsigned char *s ){
|
651 | while (*s){
|
652 | ffwrite(*s++);
|
653 | }
|
654 | fat.bufferDirty = TRUE;
|
655 | }
|
656 | #endif
|