Rev 407 | Rev 431 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 407 | Rev 427 | ||
---|---|---|---|
Line 5... | Line 5... | ||
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 |
Line 30... | Line 30... | ||
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. |
Line 60... | Line 60... | ||
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" |
|
Line 65... | Line 66... | ||
65 | 66 | ||
66 | 67 | ||
67 | //________________________________________________________________________________________________________________________________________ |
68 | //________________________________________________________________________________________________________________________________________ |
68 | // Module name: fat16.c |
69 | // Module name: fat16.c |
69 | // Compiler used: avr-gcc 3.4.5 |
70 | // Compiler used: avr-gcc 3.4.5 |
70 | // Last Modifikation: 20.03.2010 |
71 | // Last Modifikation: 1.12.2012 |
71 | // Version: 2.10 |
72 | // Version: 2.11 |
72 | // Authors: Stephan Busker & Gregor Stobrawa |
73 | // Authors: Stephan Busker & Gregor Stobrawa |
73 | // Description: Source files for FAT16 implementation with read and write-access |
74 | // Description: Source files for FAT16 implementation with read and write-access |
74 | // Copyright (C) 2008 Stephan Busker & Gregor Stobrawa |
75 | // Copyright (C) 2008 Stephan Busker & Gregor Stobrawa |
75 | //........................................................................................................................................ |
76 | //........................................................................................................................................ |
76 | // Functions: extern s16 Fat16_Init(void); |
77 | // Functions: extern s16 Fat16_Init(void); |
- | 78 | // extern s16 Fat16_Deinit(void); |
|
77 | // extern s16 Fat16_Deinit(void); |
79 | // extern s8* FAT16_GetVolumeLabel(void); |
78 | // extern s8* FAT16_GetVolumeLabel(void); |
80 | // |
79 | // extern File_t * fopen_(const u8 *filename, const s8 mode); |
81 | // extern File_t * fopen_(const u8 *filename, const s8 mode); |
80 | // extern s16 fclose_(File_t *File); |
82 | // extern s16 fclose_(File_t *file); |
81 | // extern u8 fexist_(s8 * const filename); |
83 | // extern u8 fexist_(s8 * const filename); |
82 | // extern s16 fflush_(File_t *File); |
84 | // extern s16 fflush_(File_t *file); |
83 | // extern s16 fseek_(File_t *File, s32 offset, s16 origin); |
85 | // extern s16 fseek_(File_t *file, s32 offset, s16 origin); |
84 | // extern s16 fgetc_(File_t *File); |
86 | // extern s16 fgetc_(File_t *file); |
85 | // extern s16 fputc_(u8 c, File_t *File); |
87 | // extern s16 fputc_(u8 c, File_t *file); |
86 | // 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); |
87 | // 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); |
88 | // 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); |
|
- | 92 | // extern u8 feof_(File_t * const file); |
|
- | 93 | // extern u8 fdelete_(s8* const filepath); |
|
- | 94 | // |
|
- | 95 | // extern s8 *getcwd_(void); |
|
- | 96 | // extern u8 chdir_(s8* const dirpath); |
|
- | 97 | // extern u8 mkdir_(s8* const dirpath); |
|
- | 98 | // extern u8 rmdir_(s8* const dirpath); |
|
89 | // extern u8 * fgets_(u8 *string, s16 length, File_t *File); |
99 | // extern u8 findfirst_(const s8* name, u8 attribmask, Find_t *); |
90 | // extern u8 feof_(File_t * const file); |
100 | // extern u8 findnext_(Find_t *); |
91 | //........................................................................................................................................ |
101 | //........................................................................................................................................ |
92 | // ext. functions: extern SD_Result_t SDC_Init(void;) |
102 | // ext. functions: extern SD_Result_t SDC_Init(void;) |
93 | // extern SD_Result_t SDC_Deinit(void); |
103 | // extern SD_Result_t SDC_Deinit(void); |
Line 249... | Line 259... | ||
249 | u16 StartCluster; // first cluster of the file or directory. |
259 | u16 StartCluster; // first cluster of the file or directory. |
250 | u32 Size; // size of the file or directory in bytes. |
260 | u32 Size; // size of the file or directory in bytes. |
251 | } __attribute__((packed)) DirEntry_t; |
261 | } __attribute__((packed)) DirEntry_t; |
Line 252... | Line 262... | ||
252 | 262 | ||
253 | #define SLOT_EMPTY 0x00 // slot has never been used |
263 | #define SLOT_EMPTY 0x00 // slot has never been used |
254 | #define SLOT_E5 0x05 // the real value is 0xe5 |
264 | #define SLOT_E5 0x05 // the real value is 0xE5 |
Line 255... | Line -... | ||
255 | #define SLOT_DELETED 0xE5 // file in this slot deleted |
- | |
256 | - | ||
257 | #define ATTR_NONE 0x00 // normal file |
- | |
258 | #define ATTR_READONLY 0x01 // file is readonly |
- | |
259 | #define ATTR_HIDDEN 0x02 // file is hidden |
- | |
260 | #define ATTR_SYSTEM 0x04 // file is a system file |
- | |
261 | #define ATTR_VOLUMELABEL 0x08 // entry is a volume label |
- | |
262 | #define ATTR_LONG_FILENAME 0x0F // this is a long filename entry |
- | |
263 | #define ATTR_SUBDIRECTORY 0x10 // entry is a directory name |
- | |
264 | #define ATTR_ARCHIVE 0x20 // file is new or modified |
- | |
265 | 265 | #define SLOT_DELETED 0xE5 // file in this slot deleted |
|
266 | 266 | ||
Line 267... | Line 267... | ||
267 | /* |
267 | /* |
268 | ________________________________________________________________________________________________________________________________________ |
268 | ________________________________________________________________________________________________________________________________________ |
Line 314... | Line 314... | ||
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; |
Line 322... | Line 322... | ||
322 | 322 | ||
Line 323... | Line 323... | ||
323 | Partition_t Partition; // Structure holds partition information |
323 | Partition_t Partition; // Structure holds partition information |
Line -... | Line 324... | ||
- | 324 | ||
- | 325 | File_t FilePointer[FILE_MAX_OPEN]; // Allocate Memmoryspace for each filepointer used. |
|
- | 326 | ||
- | 327 | /********************************************************************************************************************************************/ |
|
- | 328 | /* Function: s8 *getcwd_(void); */ |
|
- | 329 | /* */ |
|
- | 330 | /* Description: This function returns a pointer to the absolute path of the active partition */ |
|
- | 331 | /* */ |
|
Line -... | Line 332... | ||
- | 332 | /* */ |
|
- | 333 | /* Returnvalue: pointer to the string containing the path to the CWD */ |
|
- | 334 | /********************************************************************************************************************************************/ |
|
- | 335 | ||
Line -... | Line 336... | ||
- | 336 | s8 *getcwd_(void) |
|
- | 337 | { |
|
- | 338 | return(Partition.PathToCwd); |
|
- | 339 | } |
|
- | 340 | ||
- | 341 | /********************************************************************************************************************************************/ |
|
- | 342 | /* Function: void CWDPath_Push(s8* directory); */ |
|
- | 343 | /* */ |
|
- | 344 | /* Description: This function function appends the name of an directory to the path of the CWD */ |
|
- | 345 | /* */ |
|
- | 346 | /* */ |
|
- | 347 | /* Returnvalue: none */ |
|
- | 348 | /********************************************************************************************************************************************/ |
|
- | 349 | ||
- | 350 | void CWDPath_Push(s8* directory) |
|
- | 351 | { |
|
- | 352 | // append the name of the directory to the path |
|
- | 353 | strcat(Partition.PathToCwd, directory); |
|
- | 354 | // append a '/' after the directoryname |
|
- | 355 | strcat(Partition.PathToCwd, "/"); |
|
- | 356 | } |
|
- | 357 | ||
- | 358 | /********************************************************************************************************************************************/ |
|
- | 359 | /* Function: CWDPath_Pop(void); */ |
|
- | 360 | /* */ |
|
- | 361 | /* Description: This function removes the last directory from the path to the CWD */ |
|
- | 362 | /* */ |
|
- | 363 | /* */ |
|
- | 364 | /* Returnvalue: none */ |
|
- | 365 | /********************************************************************************************************************************************/ |
|
- | 366 | ||
- | 367 | void CWDPath_Pop(void) |
|
- | 368 | { |
|
- | 369 | // a pointer to the beginning of the absolute path to the cwd |
|
- | 370 | s8 * cptr = Partition.PathToCwd; |
|
- | 371 | // lets find the end of the path to the cwd |
|
- | 372 | while(*cptr != 0 ) cptr++; |
|
- | 373 | // if the path is terminated with an '/' then remove it |
|
- | 374 | if((*(cptr-1)) == '/') *(cptr-1) = 0; |
|
- | 375 | // now lets find the beginning of the last directory entry |
|
- | 376 | while((*cptr != '/' ) && cptr > Partition.PathToCwd) cptr--; |
|
- | 377 | // is there one subdirectory left within the path? |
|
- | 378 | if(cptr > Partition.PathToCwd) |
|
- | 379 | { |
|
- | 380 | // we delete the direntry by terminating the path with 0 |
|
- | 381 | *(cptr+1) = 0; |
|
- | 382 | } |
|
- | 383 | // there is no subdirectory left within the path. Therefore we create the root instead. |
|
- | 384 | else |
|
Line 324... | Line 385... | ||
324 | 385 | { |
|
325 | File_t FilePointer[FILE_MAX_OPEN]; // Allocate Memmoryspace for each filepointer used. |
386 | *cptr = '/'; |
326 | 387 | *(cptr+1) = 0; |
|
327 | 388 | } |
|
Line 377... | Line 438... | ||
377 | { |
438 | { |
378 | u8 i; |
439 | u8 i; |
379 | File_t * File = 0; |
440 | File_t * File = 0; |
380 | for(i = 0; i < FILE_MAX_OPEN; i++) |
441 | for(i = 0; i < FILE_MAX_OPEN; i++) |
381 | { |
442 | { |
382 | if(FilePointer[i].State == FSTATE_UNUSED) // found an unused one |
443 | if(FilePointer[i].State == FSTATE_UNUSED) // found an unused one |
383 | { |
444 | { |
384 | 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. |
|
- | 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 |
|
- | 449 | FilePointer[i].SectorOfCurrCluster = SECTOR_UNDEFINED; // The sector within the current cluster. |
|
- | 450 | FilePointer[i].ByteOfCurrSector = 0; // The byte location within the current sector. |
|
- | 451 | FilePointer[i].Mode = 0; // Mode of fileoperation (read,write) |
|
- | 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 |
|
- | 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. |
|
- | 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. |
|
385 | FilePointer[i].State = FSTATE_USED; // mark it as used |
458 | FilePointer[i].State = FSTATE_USED; // mark it as used |
- | 459 | ||
386 | break; |
460 | break; |
387 | } |
461 | } |
388 | } |
462 | } |
389 | return(File); |
463 | return(File); |
390 | } |
464 | } |
Line 422... | Line 496... | ||
422 | } |
496 | } |
423 | return(0); |
497 | return(0); |
424 | } |
498 | } |
Line 425... | Line 499... | ||
425 | 499 | ||
426 | /****************************************************************************************************************************************/ |
500 | /****************************************************************************************************************************************/ |
427 | /* Function: SeperateDirName(s8*, s8*); */ |
501 | /* Function: s8* SeperateFormatedDirName(const s8*, s8*); */ |
428 | /* */ |
502 | /* */ |
429 | /* 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 */ |
430 | /* into the needed format ('test.txt' -> 'TEST TXT') */ |
504 | /* into the needed format ('test.txt' -> 'TEST TXT') */ |
431 | /* 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 */ |
432 | /* */ |
506 | /* */ |
433 | /* Returnvalue: Return NULL on error or pointer to subpath */ |
507 | /* Returnvalue: Return NULL on error or pointer to subpath */ |
434 | /****************************************************************************************************************************************/ |
508 | /****************************************************************************************************************************************/ |
435 | s8* SeperateDirName(const s8 *filepath, s8 *dirname) |
509 | s8* SeperateFormatedDirName(const s8 *filepath, s8 *dirname) |
436 | { |
510 | { |
437 | s8* subpath = NULL; |
511 | s8* subpath = NULL; |
438 | u8 readpointer = 0; |
512 | u8 readpointer = 0; |
Line 456... | Line 530... | ||
456 | for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' '; |
530 | for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' '; |
Line 457... | Line 531... | ||
457 | 531 | ||
458 | // handle the special dirnames "." and ".." seperately |
532 | // handle the special dirnames "." and ".." seperately |
459 | readpointer = 0; |
533 | readpointer = 0; |
460 | if(filepath[0] == '/') readpointer++; |
534 | if(filepath[0] == '/') readpointer++; |
461 | // if we are trying to enter directories "." or ".." |
535 | // if we are trying to enter directories "." or ".." |
462 | if(filepath[readpointer] == '.') |
536 | if(filepath[readpointer] == '.') |
463 | { |
537 | { |
464 | // directory '.' |
538 | // directory '.' |
465 | if(filepath[readpointer+1] == 0) |
539 | if(filepath[readpointer+1] == 0) |
466 | { |
540 | { |
467 | dirname[0] = '.'; |
541 | dirname[0] = '.'; |
468 | return((s8*)&filepath[readpointer]); |
542 | return((s8*)&filepath[readpointer]); |
469 | } |
543 | } |
470 | // directory '..' |
544 | // directory '..' |
471 | if((filepath[readpointer+1] == '.') && (filepath[readpointer+2] == 0)) |
545 | if((filepath[readpointer+1] == '.') && (filepath[readpointer+2] == 0)) |
472 | { |
546 | { |
473 | dirname[0] = '.'; |
547 | dirname[0] = '.'; |
474 | dirname[1] = '.'; |
548 | dirname[1] = '.'; |
475 | return((s8*)&filepath[readpointer]); |
549 | return((s8*)&filepath[readpointer]); |
Line 507... | Line 581... | ||
507 | } |
581 | } |
508 | } |
582 | } |
509 | return(subpath); |
583 | return(subpath); |
510 | } |
584 | } |
Line 511... | Line -... | ||
511 | - | ||
512 | 585 | ||
513 | /**************************************************************************************************************************************+*/ |
586 | /**************************************************************************************************************************************+*/ |
514 | /* Function: Fat16ClusterToSector( u16 cluster); */ |
587 | /* Function: Fat16ClusterToSector( u16 cluster); */ |
515 | /* */ |
588 | /* */ |
516 | /* 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 */ |
Line 572... | Line 645... | ||
572 | u8 cnt; |
645 | u8 cnt; |
Line 573... | Line 646... | ||
573 | 646 | ||
574 | UART1_PutString("\r\n FAT16 deinit..."); |
647 | UART1_PutString("\r\n FAT16 deinit..."); |
575 | // declare the filepointers as unused. |
648 | // declare the filepointers as unused. |
576 | for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++) |
649 | for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++) |
577 | { |
650 | { |
578 | UnlockFilePointer(&FilePointer[cnt]); |
651 | UnlockFilePointer(&FilePointer[cnt]); |
579 | } |
652 | } |
580 | returnvalue = SDC_Deinit(); // uninitialize interface to sd-card |
653 | returnvalue = SDC_Deinit(); // uninitialize interface to sd-card |
581 | Partition.IsValid = 0; // mark data in partition structure as invalid |
654 | Partition.IsValid = 0; // mark data in partition structure as invalid |
Line 584... | Line 657... | ||
584 | if(SD_WatchDog > 2000) SD_WatchDog = 2000; |
657 | if(SD_WatchDog > 2000) SD_WatchDog = 2000; |
585 | SD_LoggingError = 100; |
658 | SD_LoggingError = 100; |
586 | return(returnvalue); |
659 | return(returnvalue); |
587 | } |
660 | } |
Line -... | Line 661... | ||
- | 661 | ||
588 | 662 | ||
589 | /****************************************************************************************************************************************/ |
663 | /****************************************************************************************************************************************/ |
590 | /* Function: Fat16_Init(void); */ |
664 | /* Function: Fat16_Init(void); */ |
591 | /* */ |
665 | /* */ |
592 | /* 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 */ |
Line 686... | Line 760... | ||
686 | result = 6; |
760 | result = 6; |
687 | goto end; |
761 | goto end; |
688 | } |
762 | } |
689 | Partition.IsValid = 1; // mark data in partition structure as valid |
763 | Partition.IsValid = 1; // mark data in partition structure as valid |
690 | Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector; |
764 | Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector; |
691 | strcpy(Partition.PathToCwd,"/"); |
765 | strcpy(Partition.PathToCwd,"/"); |
692 | result = 0; |
766 | result = 0; |
693 | end: |
767 | end: |
694 | if(result != 0) Fat16_Deinit(); |
768 | if(result != 0) Fat16_Deinit(); |
695 | else UART1_PutString("ok"); |
769 | else UART1_PutString("ok"); |
696 | return(result); |
770 | return(result); |
Line 711... | Line 785... | ||
711 | u32 i; |
785 | u32 i; |
Line 712... | Line 786... | ||
712 | 786 | ||
Line 713... | Line 787... | ||
713 | if((!Partition.IsValid) || (file == NULL)) return(0); |
787 | if((!Partition.IsValid) || (file == NULL)) return(0); |
714 | 788 | ||
715 | 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 |
716 | if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return (0); // nothing to do |
790 | if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return (0); // nothing to do |
717 | for(i = 0; i < Partition.SectorsPerCluster; i++) |
791 | for(i = 0; i < Partition.SectorsPerCluster; i++) |
718 | { |
792 | { |
719 | file->SectorInCache = file->FirstSectorOfCurrCluster + i; |
793 | file->SectorInCache = file->FirstSectorOfCurrCluster + i; |
Line 831... | Line 905... | ||
831 | // 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 |
832 | }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster)); |
906 | }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster)); |
833 | return(free_cluster); |
907 | return(free_cluster); |
834 | } |
908 | } |
Line 835... | Line -... | ||
835 | - | ||
836 | - | ||
837 | /****************************************************************************************************************************************************/ |
- | |
838 | /* Function: s16 fseek_(File_t *, s32 *, u8) */ |
- | |
839 | /* */ |
- | |
840 | /* Description: This function sets the pointer of the stream relative to the position */ |
- | |
841 | /* specified by origin (SEEK_SET, SEEK_CUR, SEEK_END) */ |
- | |
842 | /* Returnvalue: Is 0 if seek was successful */ |
- | |
843 | /****************************************************************************************************************************************************/ |
- | |
844 | s16 fseek_(File_t *file, s32 offset, s16 origin) |
- | |
845 | { |
- | |
846 | s32 fposition = 0; |
- | |
847 | s16 retvalue = 1; |
- | |
848 | - | ||
849 | // the byteindex within a sector |
- | |
850 | u32 byte_index = 0; |
- | |
851 | // the sectorindex within a cluster |
- | |
852 | u32 sector_index = 0; |
- | |
853 | // the index of the cluster within the clusterchain inside the fat |
- | |
854 | u32 cluster_index = 0; |
- | |
855 | - | ||
856 | // check if the partition is valid |
- | |
857 | if((!Partition.IsValid) || (file == NULL)) return(retvalue); |
- | |
858 | //...................................................... |
- | |
859 | if(origin == SEEK_SET) // Fileposition relative to the beginning of the file. |
- | |
860 | { |
- | |
861 | fposition = 0; |
- | |
862 | } |
- | |
863 | //...................................................... |
- | |
864 | else if(origin == SEEK_END) // Fileposition relative to the end of the file. |
- | |
865 | { |
- | |
866 | fposition = (s32) file->Size; |
- | |
867 | } |
- | |
868 | //...................................................... |
- | |
869 | else if(origin == SEEK_CUR) // Fileposition relative to the current position of the file. |
- | |
870 | { |
- | |
871 | fposition = (s32)file->Position; |
- | |
872 | } |
- | |
873 | - | ||
874 | // calculate the specified fileposition according to the selected mode |
- | |
875 | fposition += offset; // Die Absolute Dateiposition welche durch fseek angesprungen werden soll. |
- | |
876 | // is the fileposition within the file? |
- | |
877 | if((fposition >= 0) && (fposition <= (s32)file->Size)) // Ist die berechnete Dateiposition innerhalb der geöffneten Datei? |
- | |
878 | { |
- | |
879 | // initialize the filepointer |
- | |
880 | file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; |
- | |
881 | file->SectorOfCurrCluster = 0; |
- | |
882 | file->ByteOfCurrSector = 0; |
- | |
883 | file->Position = 0; |
- | |
884 | // has the specified file at least one valid sector attached? |
- | |
885 | if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(retvalue); |
- | |
886 | // calculate the absolute number of the sector wich contains the fileposition we are looking for |
- | |
887 | sector_index = (u32) ((u32)fposition >> 9); |
- | |
888 | // calculate the index of the cluster containing the specified sector |
- | |
889 | cluster_index = (u32) sector_index / Partition.SectorsPerCluster; |
- | |
890 | // the absolute sectornumber becomes relative to the beginning of the specified cluster |
- | |
891 | sector_index = (sector_index % Partition.SectorsPerCluster); |
- | |
892 | // calculate the index of the byteposition the fileposition points to |
- | |
893 | byte_index = (u32) fposition % 512; |
- | |
894 | // parse the fat till the calculated cluster has been reached |
- | |
895 | while(cluster_index--) GetNextCluster(file); |
- | |
896 | // set the filepointer to the specified sector and byteposition |
- | |
897 | file->SectorOfCurrCluster = (u8) sector_index; |
- | |
898 | file->ByteOfCurrSector = (u16) byte_index; |
- | |
899 | // the fileposition now equals the filepointer |
- | |
900 | file->Position = (u32)fposition; |
- | |
901 | // the specified fileposition has been reached |
- | |
902 | retvalue = 0; |
- | |
903 | } |
- | |
904 | return(retvalue); |
- | |
905 | } |
- | |
906 | - | ||
907 | 909 | ||
908 | /****************************************************************************************************************************************/ |
910 | /****************************************************************************************************************************************/ |
909 | /* Function: u16 DeleteClusterChain(File *file); */ |
911 | /* Function: u8 DeleteClusterChain(File *file); */ |
910 | /* */ |
912 | /* */ |
911 | /* 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 | /* */ |
|
912 | /* */ |
915 | /* Returnvalue: returns 1 in success otherwise 0 */ |
913 | /****************************************************************************************************************************************/ |
916 | /****************************************************************************************************************************************/ |
914 | u8 DeleteClusterChain(u16 StartCluster) |
917 | u8 DeleteClusterChain(u16 StartCluster) |
915 | { |
918 | { |
916 | u16 cluster; |
919 | u16 cluster; |
Line 919... | Line 922... | ||
919 | u8 buffer[BYTES_PER_SECTOR]; |
922 | u8 buffer[BYTES_PER_SECTOR]; |
920 | u32 sector_in_buffer = 0; |
923 | u32 sector_in_buffer = 0; |
921 | u8 repeat = 0; |
924 | u8 repeat = 0; |
Line 922... | Line 925... | ||
922 | 925 | ||
923 | if(!Partition.IsValid) return(0); |
926 | if(!Partition.IsValid) return(0); |
924 | if(StartCluster == CLUSTER_UNDEFINED) return(0); |
927 | if(StartCluster == CLUSTER_UNDEFINED) return(1); |
925 | cluster = StartCluster; // init chain trace |
928 | cluster = StartCluster; // init chain trace |
926 | // if start cluster is no real cluster |
929 | // if start cluster is no real cluster |
Line 927... | Line 930... | ||
927 | if(FAT16_CLUSTER_LAST_MIN <= cluster) return 1; |
930 | if(FAT16_CLUSTER_LAST_MIN <= cluster) return(1); |
928 | 931 | ||
929 | // calculate byte offset in the fat for corresponding entry |
932 | // calculate byte offset in the fat for corresponding entry |
930 | 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 |
Line 978... | Line 981... | ||
978 | /* */ |
981 | /* */ |
979 | /* 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. */ |
980 | /* */ |
983 | /* */ |
981 | /* 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. */ |
982 | /****************************************************************************************************************************************/ |
985 | /****************************************************************************************************************************************/ |
983 | - | ||
984 | u16 AppendCluster(File_t *file) |
986 | u16 AppendCluster(File_t *file) |
985 | { |
987 | { |
986 | u16 last_cluster, new_cluster = CLUSTER_UNDEFINED; |
988 | u16 last_cluster, new_cluster = CLUSTER_UNDEFINED; |
987 | u32 fat_byte_offset, sector, byte; |
989 | u32 fat_byte_offset, sector, byte; |
988 | Fat16Entry_t * fat; |
990 | Fat16Entry_t * fat; |
Line -... | Line 991... | ||
- | 991 | ||
989 | 992 | ||
Line 990... | Line 993... | ||
990 | if((!Partition.IsValid) || (file == NULL)) return(new_cluster); |
993 | if((!Partition.IsValid) || (file == NULL)) return(new_cluster); |
991 | 994 | ||
992 | 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) |
|
- | 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? |
|
993 | if(new_cluster != CLUSTER_UNDEFINED) |
999 | if(file->FirstSectorOfLastCluster == CLUSTER_UNDEFINED) |
- | 1000 | { |
|
- | 1001 | fseek_(file, 0, SEEK_END); // jump to the end of the file |
|
994 | { // A free cluster was found and can be added to the end of the file. |
1002 | // remember the first sector of the last cluster |
- | 1003 | file->FirstSectorOfLastCluster = file->FirstSectorOfCurrCluster; |
|
- | 1004 | last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster); // determine current file cluster |
|
- | 1005 | } |
|
- | 1006 | else |
|
- | 1007 | { |
|
- | 1008 | last_cluster = SectorToFat16Cluster(file->FirstSectorOfLastCluster); // determine current file cluster |
|
995 | fseek_(file, 0, SEEK_END); // jump to the end of the file |
1009 | } |
996 | last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster); // determine current file cluster |
1010 | |
997 | if(last_cluster != CLUSTER_UNDEFINED) |
1011 | if(last_cluster != CLUSTER_UNDEFINED) |
998 | { |
1012 | { |
999 | // update FAT entry of last cluster |
1013 | // update FAT entry of last cluster |
Line 1015... | Line 1029... | ||
1015 | 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. |
1016 | { |
1030 | { |
1017 | Fat16_Deinit(); |
1031 | Fat16_Deinit(); |
1018 | return(0); |
1032 | return(0); |
1019 | } |
1033 | } |
- | 1034 | // now the new cluster appended to the fat is the last cluster |
|
- | 1035 | file->FirstSectorOfLastCluster = Fat16ClusterToSector(new_cluster); |
|
1020 | } |
1036 | } |
1021 | else // last cluster of the file is undefined |
1037 | else // last cluster of the file is undefined |
1022 | { // 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 |
1023 | // and its cluster number must be set in the direntry |
1039 | // and its cluster number must be set in the direntry |
1024 | DirEntry_t * dir; |
1040 | DirEntry_t * dir; |
Line 1030... | Line 1046... | ||
1030 | } |
1046 | } |
1031 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
1047 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
1032 | dir[file->DirectoryIndex].Res1 = 0; |
1048 | dir[file->DirectoryIndex].Res1 = 0; |
1033 | dir[file->DirectoryIndex].Res2[0] = 0; |
1049 | dir[file->DirectoryIndex].Res2[0] = 0; |
1034 | dir[file->DirectoryIndex].Res2[1] = 0; |
1050 | dir[file->DirectoryIndex].Res2[1] = 0; |
1035 | dir[file->DirectoryIndex].StartCluster = new_cluster; // update startcluster |
1051 | dir[file->DirectoryIndex].StartCluster = new_cluster; // update startcluster |
1036 | dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime);// set time |
1052 | dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime);// set time |
1037 | dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime);// and date of modification |
1053 | dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime);// and date of modification |
1038 | dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate; |
1054 | dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate; |
1039 | dir[file->DirectoryIndex].Size = 0; |
1055 | dir[file->DirectoryIndex].Size = 0; |
1040 | // write sector containing the direntry |
1056 | // write sector containing the direntry |
1041 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
1057 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
1042 | { |
1058 | { |
1043 | Fat16_Deinit(); |
1059 | Fat16_Deinit(); |
1044 | return(CLUSTER_UNDEFINED); |
1060 | return(CLUSTER_UNDEFINED); |
1045 | } |
1061 | } |
1046 | // update file info |
1062 | // update file info |
1047 | file->FirstSectorOfFirstCluster = Fat16ClusterToSector(new_cluster); |
1063 | file->FirstSectorOfFirstCluster = Fat16ClusterToSector(new_cluster); |
- | 1064 | file->FirstSectorOfLastCluster = file->FirstSectorOfFirstCluster; |
|
1048 | file->Size = 0; |
1065 | file->Size = 0; |
1049 | file->Position = 0; |
1066 | file->Position = 0; |
1050 | } |
1067 | } |
1051 | // update file pointes |
1068 | // update file pointes |
1052 | file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster); |
1069 | file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster); |
Line 1076... | Line 1093... | ||
1076 | 1093 | ||
1077 | // if incomming pointers are useless return immediatly |
1094 | // if incomming pointers are useless return immediatly |
Line 1078... | Line 1095... | ||
1078 | if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist); |
1095 | if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist); |
1079 | 1096 | ||
1080 | // dir entries can be searched only in filesclusters that have |
1097 | // dir entries can be searched only in filesclusters that have |
1081 | // a corresponding dir entry with adir-flag set in its attribute |
1098 | // a corresponding dir entry with a dir-flag set in its attribute |
1082 | // or direct within the root directory area |
1099 | // or direct within the root directory area |
1083 | file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; |
1100 | file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; |
1084 | // no current directory exist therefore assume searching in the root |
1101 | // no current directory exist therefore assume searching in the root |
Line 1089... | Line 1106... | ||
1089 | } |
1106 | } |
1090 | // within the root directory area we can read sectors sequentially until the end of this area |
1107 | // within the root directory area we can read sectors sequentially until the end of this area |
1091 | else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector)) |
1108 | else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector)) |
1092 | { |
1109 | { |
1093 | max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR; |
1110 | max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR; |
- | 1111 | file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector; |
|
1094 | } |
1112 | } |
1095 | // within the data clusters we can read sectors sequentially only within the cluster |
1113 | // within the data clusters we can read sectors sequentially only within the cluster |
1096 | else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector)) |
1114 | else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector)) |
1097 | { |
1115 | { |
1098 | max_dir_sector = Partition.SectorsPerCluster; // limit max secters before next cluster |
1116 | max_dir_sector = Partition.SectorsPerCluster; // limit max sectors before next cluster |
1099 | } |
1117 | } |
1100 | else return (direntry_exist); // bad sector range for directory sector of the file |
1118 | else return (direntry_exist); // bad sector range for directory sector of the file |
1101 | // if search area is not defined yet |
1119 | // if search area is not defined yet, i.e. not in the root directory area |
1102 | if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED) |
1120 | if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED) |
1103 | { |
1121 | { |
1104 | // check if the directory entry of current file is existent and has the dir-flag set |
1122 | // check if the directory entry of current file is existent and has the dir-flag set |
1105 | file->SectorInCache = file->DirectorySector; // update the sector number of file cache. |
1123 | file->SectorInCache = file->DirectorySector; // update the sector number of file cache. |
1106 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1124 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
Line 1112... | Line 1130... | ||
1112 | switch((u8)dir[file->DirectoryIndex].Name[0]) // check if current directory exist |
1130 | switch((u8)dir[file->DirectoryIndex].Name[0]) // check if current directory exist |
1113 | { |
1131 | { |
1114 | case SLOT_EMPTY: |
1132 | case SLOT_EMPTY: |
1115 | case SLOT_DELETED: |
1133 | case SLOT_DELETED: |
1116 | // the directrory pointer of this file points to a deleted or not existen directory |
1134 | // the directrory pointer of this file points to a deleted or not existen directory |
1117 | // therefore no file or subdirectory can be created |
1135 | // therefore no file or subdirectory exist here |
1118 | return (direntry_exist); |
1136 | return (direntry_exist); |
1119 | break; |
1137 | break; |
1120 | default: // and is a real directory |
1138 | default: // and is a real directory |
1121 | if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY) |
1139 | if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY) |
1122 | { // current file is not a directory therefore no file or subdirectory can be created here |
1140 | { // current file is not a directory therefore no file or subdirectory can be created here |
Line 1124... | Line 1142... | ||
1124 | } |
1142 | } |
1125 | break; |
1143 | break; |
1126 | } |
1144 | } |
1127 | file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster); |
1145 | file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster); |
1128 | } |
1146 | } |
1129 | - | ||
1130 | // update current file data area position to start of first cluster |
1147 | // update current file data area position to start of first cluster |
1131 | file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; |
1148 | file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; |
1132 | file->SectorOfCurrCluster = 0; |
1149 | file->SectorOfCurrCluster = 0; |
1133 | file->ByteOfCurrSector = 0; |
1150 | file->ByteOfCurrSector = 0; |
Line 1222... | Line 1239... | ||
1222 | } |
1239 | } |
1223 | // within the root directory area we can read sectors sequentially until the end of this area |
1240 | // within the root directory area we can read sectors sequentially until the end of this area |
1224 | else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector)) |
1241 | else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector)) |
1225 | { |
1242 | { |
1226 | max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR; |
1243 | max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR; |
- | 1244 | dircluster = 0; |
|
- | 1245 | file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector; |
|
1227 | } |
1246 | } |
1228 | // within the data clusters we can read sectors sequentially only within the cluster |
1247 | // within the data clusters we can read sectors sequentially only within the cluster |
1229 | else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector)) |
1248 | else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector)) |
1230 | { |
1249 | { |
1231 | max_dir_sector = Partition.SectorsPerCluster; |
1250 | max_dir_sector = Partition.SectorsPerCluster; |
- | 1251 | file->FirstSectorOfFirstCluster = Partition.CurrentWorkingDirectory; |
|
1232 | } |
1252 | } |
1233 | else return (retvalue); // bad sector range for directory sector of the file |
1253 | else return (retvalue); // bad sector range for directory sector of the file |
1234 | // if search area is not defined yet |
1254 | // if search area is not defined yet |
1235 | if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED) |
1255 | if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED) |
1236 | { |
1256 | { |
Line 1259... | Line 1279... | ||
1259 | file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster); |
1279 | file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster); |
1260 | } |
1280 | } |
Line 1261... | Line 1281... | ||
1261 | 1281 | ||
1262 | // if the new direntry is a subdirectory |
1282 | // if the new direntry is a subdirectory |
1263 | if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY) |
1283 | if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY) |
1264 | { // get a free clutser for its content |
1284 | { // get a free cluster for its content |
1265 | subdircluster = FindNextFreeCluster(file); // get the next free cluster on the disk and mark it as used. |
1285 | subdircluster = FindNextFreeCluster(file); // get the next free cluster on the disk and mark it as used. |
1266 | } |
1286 | } |
1267 | else // a normal file |
1287 | else // a normal file |
1268 | { // has no data cluster after creation |
1288 | { // has no data cluster after creation |
Line 1275... | Line 1295... | ||
1275 | { |
1295 | { |
1276 | dir_sector = 0; // reset sector counter within a new cluster |
1296 | dir_sector = 0; // reset sector counter within a new cluster |
1277 | do // loop over all sectors of a cluster or all sectors of the root directory |
1297 | do // loop over all sectors of a cluster or all sectors of the root directory |
1278 | { |
1298 | { |
1279 | curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
1299 | curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
1280 | file->SectorInCache = curr_sector; // upate the sector number of file cache. |
1300 | file->SectorInCache = curr_sector; // update the sector number of file cache. |
1281 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1301 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1282 | { |
1302 | { |
1283 | Fat16_Deinit(); |
1303 | Fat16_Deinit(); |
1284 | return(0); |
1304 | return(0); |
1285 | } |
1305 | } |
Line 1368... | Line 1388... | ||
1368 | 1388 | ||
1369 | return(retvalue); // return 1 if file has been created otherwise return 0. |
1389 | return(retvalue); // return 1 if file has been created otherwise return 0. |
Line 1370... | Line 1390... | ||
1370 | } |
1390 | } |
- | 1391 | ||
- | 1392 | /********************************************************************************************************************************************/ |
|
- | 1393 | /* Function: u8 DeleteDirectoryEntry(File_t *file) */ |
|
- | 1394 | /* Description: This function deletes the directoryentry of the file to be deleted from the filesystem */ |
|
- | 1395 | /* */ |
|
- | 1396 | /* */ |
|
- | 1397 | /* Returnvalue: 1 on succes and 0 on error */ |
|
- | 1398 | /********************************************************************************************************************************************/ |
|
- | 1399 | u8 DeleteDirectoryEntry(File_t *file) |
|
- | 1400 | { |
|
- | 1401 | DirEntry_t *DirectoryEntry = NULL; |
|
- | 1402 | u8 retval = 0; |
|
- | 1403 | ||
- | 1404 | if((!Partition.IsValid) || (file == NULL)) return (retval); |
|
- | 1405 | ||
- | 1406 | // try to read the sector containing the directoryentry of the file to be deleted |
|
- | 1407 | if(SD_SUCCESS != SDC_GetSector((u32) file->DirectorySector,file->Cache)) return(retval); |
|
- | 1408 | // get access to the elements of the directoryentry |
|
- | 1409 | DirectoryEntry = (DirEntry_t *)file->Cache; |
|
- | 1410 | // delete the directoryentry |
|
- | 1411 | DirectoryEntry[file->DirectoryIndex].Name[0] = SLOT_DELETED; |
|
- | 1412 | DirectoryEntry[file->DirectoryIndex].Attribute = 0; |
|
- | 1413 | DirectoryEntry[file->DirectoryIndex].Size = 0; |
|
- | 1414 | // 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; |
|
- | 1416 | return(retval); |
|
- | 1417 | } |
|
1371 | 1418 | ||
1372 | /********************************************************************************************************************************************/ |
1419 | /********************************************************************************************************************************************/ |
1373 | /* Function: FileExist(const s8* filename, u8 attribfilter, u8 attribmask, File_t *file); */ |
1420 | /* Function: FileExist(const s8* filename, u8 attribfilter, u8 attribmask, File_t *file); */ |
1374 | /* */ |
1421 | /* */ |
1375 | /* Description: This function looks for the specified file including its subdirectories beginning */ |
- | |
1376 | /* in the rootdirectory of the drive. If the file is found the Filepointer properties are */ |
1422 | /* Description: This function looks for the specified file including its subdirectories. */ |
1377 | /* updated. */ |
1423 | /* If the file is found the Filepointer properties are updated. */ |
1378 | /* */ |
1424 | /* */ |
1379 | /* Returnvalue: 1 if file is found else 0. */ |
1425 | /* Returnvalue: 1 if file is found else 0. */ |
1380 | /********************************************************************************************************************************************/ |
1426 | /********************************************************************************************************************************************/ |
Line 1387... | Line 1433... | ||
1387 | 1433 | ||
1388 | // if incomming pointers are useless return immediatly |
1434 | // if incomming pointers are useless return immediatly |
Line 1389... | Line 1435... | ||
1389 | if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0; |
1435 | if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0; |
1390 | 1436 | ||
1391 | // trace along the filepath |
- | |
1392 | path = (s8*)filename; // start a the beginning of the filename string |
1437 | // trace along the filepath |
1393 | file->DirectorySector = 0; // start at RootDirectory with file search |
1438 | path = (s8*)filename; // start at the beginning of the filename string |
- | 1439 | file->DirectoryIndex = 0; |
|
- | 1440 | if(path[0] == '/') // if a path begins with a '/' the search starts at RootDirectory with file search |
|
- | 1441 | { |
|
1394 | file->DirectoryIndex = 0; |
1442 | file->DirectorySector = Partition.FirstRootDirSector; // start at RootDirectory with file search |
1395 | /* if a path begins with a '/' at index 0 the search starts at the rootdirectory otherwise we will start relative to the cwd */ |
1443 | } |
1396 | if(path[0] != '/') |
- | |
1397 | { |
- | |
1398 | /* is the current working directory the rootdirectory? */ |
- | |
1399 | if(Partition.CurrentWorkingDirectory == Partition.FirstRootDirSector) file->DirectorySector = 0; |
1444 | else // if a path begins not with a '/' the search starts relative to the CWD |
1400 | /* otherwise we are working in an subdirectory */ |
1445 | { |
1401 | else file->DirectorySector = Partition.CurrentWorkingDirectory; |
1446 | file->DirectorySector = Partition.CurrentWorkingDirectory; |
1402 | } |
1447 | } |
1403 | // as long as the file was not found and the remaining path is not empty |
1448 | // as long as the file was not found and the remaining path is not empty |
1404 | while((*path != 0) && !file_exist) |
1449 | while((*path != 0) && !file_exist) |
1405 | { // separate dirname and subpath from filepath string |
1450 | { // separate dirname and subpath from filepath string |
1406 | subpath = SeperateDirName(path, dirname); |
1451 | subpath = SeperateFormatedDirName(path, dirname); |
1407 | if(subpath != NULL) |
1452 | if(subpath != NULL) |
1408 | { |
1453 | { |
1409 | if(*subpath == 0) |
1454 | if(*subpath == 0) |
Line 1454... | Line 1499... | ||
1454 | s8 *subpath = 0; |
1499 | s8 *subpath = 0; |
1455 | u8 af, am, file_created = 0; |
1500 | u8 af, am, file_created = 0; |
1456 | s8 dirname[12]; |
1501 | s8 dirname[12]; |
Line 1457... | Line 1502... | ||
1457 | 1502 | ||
1458 | // if incomming pointers are useless return immediatly |
1503 | // if incomming pointers are useless return immediatly |
Line 1459... | Line 1504... | ||
1459 | if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0; |
1504 | if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return(0); |
- | 1505 | ||
- | 1506 | // trace along the filepath |
|
1460 | 1507 | path = (s8*)filename; |
|
- | 1508 | ||
1461 | // trace along the filepath |
1509 | if(path[0] == '/') // if a path begins with a '/' the search starts at RootDirectory with file search |
- | 1510 | { |
|
- | 1511 | file->DirectorySector = Partition.FirstRootDirSector; // start at RootDirectory with file search |
|
- | 1512 | } |
|
- | 1513 | else // if a path begins not with a '/' the search starts relative to the CWD |
|
- | 1514 | { |
|
1462 | path = (s8*)filename; // start a the beginning of the filename string |
1515 | file->DirectorySector = Partition.CurrentWorkingDirectory; |
- | 1516 | } |
|
1463 | file->DirectorySector = 0; // start at RootDirectory with file search |
1517 | file->DirectoryIndex = 0; |
1464 | file->DirectoryIndex = 0; |
1518 | |
1465 | // as long as the file was not created and the remaining file path is not empty |
1519 | // as long as the file was not created and the remaining file path is not empty |
1466 | while((*path != 0) && !file_created) |
1520 | while((*path != 0) && !file_created) |
1467 | { // separate dirname and subpath from filepath string |
1521 | { // separate dirname and subpath from filepath string |
1468 | subpath = SeperateDirName(path, dirname); |
1522 | subpath = SeperateFormatedDirName(path, dirname); |
1469 | if(subpath != NULL) |
1523 | if(subpath != NULL) |
1470 | { |
1524 | { |
1471 | if(*subpath == 0) |
1525 | if(*subpath == 0) |
1472 | { // empty subpath indicates last element of dir chain |
1526 | { // empty subpath indicates last element of dir chain |
1473 | af = ATTR_NONE; |
1527 | af = ATTR_NONE; |
1474 | am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL; // any file that is no subdir or volume label |
1528 | am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL; // any file that is no subdir or volume label |
1475 | } |
1529 | } |
1476 | else // it must be a subdirectory and no volume label |
1530 | else // it must be a subdirectory but no volume label |
1477 | { |
1531 | { |
1478 | af = ATTR_SUBDIRECTORY; |
1532 | af = ATTR_SUBDIRECTORY; |
1479 | am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL; |
1533 | am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL; |
Line 1483... | Line 1537... | ||
1483 | if(*subpath == 0) af = attrib; // if last element in dir chain take the given attribute |
1537 | if(*subpath == 0) af = attrib; // if last element in dir chain take the given attribute |
1484 | if(!CreateDirectoryEntry(dirname, af, file)) |
1538 | if(!CreateDirectoryEntry(dirname, af, file)) |
1485 | { // could not be created |
1539 | { // could not be created |
1486 | return(file_created); |
1540 | return(file_created); |
1487 | } |
1541 | } |
1488 | else if (*subpath == 0) file_created = 1; // last element of path chain was created |
1542 | else if(*subpath == 0) file_created = 1; // last element of path chain was created |
1489 | } |
1543 | } |
1490 | } |
1544 | } |
1491 | else // error seperating the subpath |
1545 | else // error seperating the subpath |
1492 | { |
1546 | { |
1493 | return file_created; // bad subdir format |
1547 | return file_created; // bad subdir format |
1494 | } |
1548 | } |
1495 | path = subpath; |
1549 | path = subpath; |
1496 | subpath = 0; |
1550 | subpath = NULL; |
1497 | } |
1551 | } |
1498 | return (file_created); |
1552 | return (file_created); |
1499 | } |
1553 | } |
Line 1500... | Line 1554... | ||
1500 | 1554 | ||
- | 1555 | ||
- | 1556 | /********************************************************************************************************************************************/ |
|
- | 1557 | /* Function: void Slashing_Path(s8*) */ |
|
- | 1558 | /* */ |
|
- | 1559 | /* Description: This function replaces all \ by / in the string pointed to by the argument */ |
|
- | 1560 | /* */ |
|
- | 1561 | /* */ |
|
- | 1562 | /* Returnvalue: */ |
|
- | 1563 | /********************************************************************************************************************************************/ |
|
- | 1564 | void Slashing_Path(s8* path) |
|
- | 1565 | { |
|
- | 1566 | s8 *cptr = path; |
|
- | 1567 | while(*cptr != 0 ) |
|
- | 1568 | { |
|
- | 1569 | if(*cptr == '\\') *cptr = '/'; // replace \ by / |
|
- | 1570 | cptr++; |
|
- | 1571 | } |
|
- | 1572 | } |
|
1501 | 1573 | ||
1502 | /********************************************************************************************************************************************/ |
1574 | /********************************************************************************************************************************************/ |
1503 | /* Function: File_t * fopen_(s8* filename, s8 mode); */ |
1575 | /* Function: File_t * fopen_(s8* filename, s8 mode); */ |
1504 | /* */ |
1576 | /* */ |
1505 | /* Description: This function looks for the specified file in the rootdirectory of the drive. If the file is found the number of the */ |
1577 | /* Description: This function looks for the specified file in the rootdirectory of the drive. If the file is found the number of the */ |
1506 | /* corrosponding filepointer is returned. Only modes 'r' (reading) and 'a' append are implemented yet. */ |
1578 | /* corrosponding filepointer is returned. Only modes 'r' (reading), 'w' (writing) and 'a' (append) are implemented yet. */ |
1507 | /* */ |
1579 | /* */ |
1508 | /* Returnvalue: The filepointer to the file or 0 if faild. */ |
1580 | /* Returnvalue: The filepointer to the file or 0 if faild. */ |
1509 | /********************************************************************************************************************************************/ |
1581 | /********************************************************************************************************************************************/ |
1510 | File_t * fopen_(s8 * const filename, const s8 mode) |
1582 | File_t * fopen_(s8* const filename, const s8 mode) |
1511 | { |
1583 | { |
Line 1512... | Line 1584... | ||
1512 | File_t *file = 0; |
1584 | File_t *file = 0; |
Line 1518... | Line 1590... | ||
1518 | file = LockFilePointer(); |
1590 | file = LockFilePointer(); |
1519 | // if no unused file pointer was found return 0 |
1591 | // if no unused file pointer was found return 0 |
1520 | if(file == NULL) return(file); |
1592 | if(file == NULL) return(file); |
Line 1521... | Line 1593... | ||
1521 | 1593 | ||
1522 | // now we have found a free filepointer and claimed it |
- | |
1523 | // so let initiate its property values |
- | |
1524 | file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; // Sectorpointer to the first sector of the first datacluster of the file. |
- | |
1525 | file->FirstSectorOfCurrCluster = SECTOR_UNDEFINED; // Pointer to the cluster which is edited at the moment. |
- | |
1526 | file->SectorOfCurrCluster = 0; // The sector which is edited at the moment (cluster_pointer + sector_index). |
- | |
1527 | file->ByteOfCurrSector = 0; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index). |
1594 | // now we have found a free filepointer and claimed it |
1528 | file->Mode = mode; // mode of fileoperation (read,write) |
- | |
1529 | file->Size = 0; // the size of the opened file in bytes. |
- | |
1530 | file->Position = 0; // pointer to a byte within the file 0 < fileposition < filesize |
- | |
1531 | file->SectorInCache = SECTOR_UNDEFINED; // the last sector read, wich is still in the sectorbuffer. |
- | |
1532 | file->DirectorySector = SECTOR_UNDEFINED; // the sectorposition where the directoryentry has been made. |
- | |
1533 | file->DirectoryIndex = 0; // the index to the directoryentry within the specified sector. |
1595 | file->Mode = mode; // mode of fileoperation (read,write) |
Line 1534... | Line 1596... | ||
1534 | file->Attribute = 0; // the attribute of the file opened. |
1596 | file->Attribute = 0; // the attribute of the file opened. |
- | 1597 | ||
1535 | 1598 | // bring the path into the correct syntax |
|
1536 | // bring the path into the correct syntax |
- | |
1537 | cptr = filename; |
- | |
1538 | // search the whole string |
- | |
1539 | while(*cptr != 0) |
- | |
1540 | { |
- | |
1541 | // replace all '\' by '/' |
- | |
1542 | if(*cptr == '\\') *cptr = '/'; |
1599 | Slashing_Path(filename); |
1543 | cptr++; |
1600 | cptr = filename; |
1544 | } |
1601 | |
1545 | // check if a real file (no directory) to the given filename exist |
1602 | // check if a real file (no directory) to the given filename exist |
1546 | if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file)) |
1603 | if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file)) |
1547 | { // file exist |
1604 | { // file exist |
Line 1578... | Line 1635... | ||
1578 | } |
1635 | } |
1579 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
1636 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
1580 | dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime); // set modification time |
1637 | dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime); // set modification time |
1581 | dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime); // set modification date |
1638 | dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime); // set modification date |
1582 | dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate; |
1639 | dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate; |
1583 | dir[file->DirectoryIndex].StartCluster = CLUSTER_UNDEFINED; // update startcluster |
1640 | dir[file->DirectoryIndex].StartCluster = CLUSTER_UNDEFINED; // update startcluster |
1584 | dir[file->DirectoryIndex].Size = 0; |
1641 | dir[file->DirectoryIndex].Size = 0; |
1585 | // write sector containing the direntry |
1642 | // write sector containing the direntry |
1586 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
1643 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
1587 | { |
1644 | { |
1588 | Fat16_Deinit(); |
1645 | Fat16_Deinit(); |
Line 1617... | Line 1674... | ||
1617 | // try to create the file |
1674 | // try to create the file |
1618 | if(!FileCreate(filename, ATTR_ARCHIVE, file)) |
1675 | if(!FileCreate(filename, ATTR_ARCHIVE, file)) |
1619 | { // if it could not be created |
1676 | { // if it could not be created |
1620 | fclose_(file); |
1677 | fclose_(file); |
1621 | file = NULL; |
1678 | file = NULL; |
1622 | } |
1679 | } |
1623 | break; |
1680 | break; |
1624 | case 'r': // else opened for 'r' |
1681 | case 'r': // else opened for 'r' |
1625 | default: // if unsupported mode |
1682 | default: // if unsupported mode |
1626 | fclose_(file); |
1683 | fclose_(file); |
1627 | file = NULL; |
1684 | file = NULL; |
Line 1634... | Line 1691... | ||
1634 | file = NULL; |
1691 | file = NULL; |
1635 | return(file); |
1692 | return(file); |
1636 | } |
1693 | } |
Line 1637... | Line 1694... | ||
1637 | 1694 | ||
- | 1695 | /****************************************************************************************************************************************************/ |
|
- | 1696 | /* Function: s16 fseek_(File_t *, s32 *, u8) */ |
|
- | 1697 | /* */ |
|
- | 1698 | /* Description: This function sets the pointer of the stream relative to the position */ |
|
- | 1699 | /* specified by origin (SEEK_SET, SEEK_CUR, SEEK_END) */ |
|
- | 1700 | /* Returnvalue: Is 0 if seek was successful */ |
|
- | 1701 | /****************************************************************************************************************************************************/ |
|
- | 1702 | s16 fseek_(File_t *file, s32 offset, s16 origin) |
|
- | 1703 | { |
|
- | 1704 | s32 fposition = 0; |
|
- | 1705 | s16 retvalue = 1; |
|
- | 1706 | u32 byte_index = 0; // the byteindex within a sector |
|
- | 1707 | 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 |
|
- | 1709 | ||
- | 1710 | // check if the partition is valid |
|
- | 1711 | if((!Partition.IsValid) || (file == NULL)) return(retvalue); |
|
- | 1712 | switch(origin) |
|
- | 1713 | { |
|
- | 1714 | case SEEK_SET: // Fileposition relative to the beginning of the file. |
|
- | 1715 | fposition = 0; |
|
- | 1716 | break; |
|
- | 1717 | case SEEK_END: // Fileposition relative to the end of the file. |
|
- | 1718 | fposition = (s32)file->Size; |
|
- | 1719 | break; |
|
- | 1720 | case SEEK_CUR: // Fileposition relative to the current position of the file. |
|
- | 1721 | default: |
|
- | 1722 | fposition = file->Position; |
|
- | 1723 | break; |
|
- | 1724 | } |
|
- | 1725 | ||
- | 1726 | // calculate the specified fileposition according to the selected mode |
|
- | 1727 | fposition += offset; |
|
- | 1728 | // is the fileposition within the file? |
|
- | 1729 | if((fposition >= 0) && (fposition <= (s32)file->Size)) |
|
- | 1730 | { |
|
- | 1731 | // initialize the filepointer to start of the file |
|
- | 1732 | file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; |
|
- | 1733 | file->SectorOfCurrCluster = 0; |
|
- | 1734 | file->ByteOfCurrSector = 0; |
|
- | 1735 | file->Position = 0; |
|
- | 1736 | // has the specified file at least one valid sector attached? |
|
- | 1737 | if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(retvalue); |
|
- | 1738 | // 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 |
|
- | 1740 | // calculate the index of the cluster containing the specified sector |
|
- | 1741 | cluster_index = (u32) sector_index / Partition.SectorsPerCluster; |
|
- | 1742 | // the absolute sectornumber becomes relative to the beginning of the specified cluster |
|
- | 1743 | sector_index = (sector_index % Partition.SectorsPerCluster); |
|
- | 1744 | // calculate the index of the byteposition the fileposition points to |
|
- | 1745 | byte_index = (u32) fposition % 512; |
|
- | 1746 | // parse the fat till the calculated cluster has been reached |
|
- | 1747 | while(cluster_index--) GetNextCluster(file); |
|
- | 1748 | // set the filepointer to the specified sector and byteposition |
|
- | 1749 | file->SectorOfCurrCluster = (u8) sector_index; |
|
- | 1750 | file->ByteOfCurrSector = (u16) byte_index; |
|
- | 1751 | // the fileposition now equals the filepointer |
|
- | 1752 | file->Position = (u32)fposition; |
|
- | 1753 | // the specified fileposition has been reached |
|
- | 1754 | retvalue = 0; |
|
- | 1755 | } |
|
- | 1756 | return(retvalue); |
|
- | 1757 | } |
|
- | 1758 | ||
1638 | /****************************************************************************************************************************************************/ |
1759 | /****************************************************************************************************************************************************/ |
1639 | /* Function: fflush_(File *); */ |
1760 | /* Function: fflush_(File *); */ |
1640 | /* */ |
1761 | /* */ |
1641 | /* Description: This function writes the data already in the buffer but not yet written to the file. */ |
1762 | /* Description: This function writes the data already in the buffer but not yet written to the file. */ |
1642 | /* */ |
1763 | /* */ |
Line 1687... | Line 1808... | ||
1687 | 1808 | ||
1688 | } |
1809 | } |
1689 | return(0); |
1810 | return(0); |
Line 1690... | Line -... | ||
1690 | } |
- | |
1691 | - | ||
1692 | /****************************************************************************************************************************************/ |
- | |
1693 | /* Function: fclose_(File *file); */ |
- | |
1694 | /* */ |
- | |
1695 | /* Description: This function closes the open file by writing the remaining data */ |
- | |
1696 | /* from the buffer to the device and entering the filesize in the directory entry. */ |
- | |
1697 | /* */ |
- | |
1698 | /* Returnvalue: 0 on success EOF on error */ |
- | |
1699 | /****************************************************************************************************************************************/ |
- | |
1700 | s16 fclose_(File_t *file) |
- | |
1701 | { |
- | |
1702 | s16 returnvalue = EOF; |
- | |
1703 | - | ||
1704 | if(file == NULL) return(returnvalue); |
- | |
1705 | returnvalue = fflush_(file); |
- | |
1706 | UnlockFilePointer(file); |
- | |
1707 | return(returnvalue); |
- | |
1708 | } |
1811 | } |
1709 | 1812 | ||
1710 | /********************************************************************************************************************************************/ |
1813 | /********************************************************************************************************************************************/ |
1711 | /* Function: fgetc_(File *file); */ |
1814 | /* Function: fgetc_(File *file); */ |
1712 | /* */ |
1815 | /* */ |
Line 1779... | Line 1882... | ||
1779 | case 'w': |
1882 | case 'w': |
1780 | case 'a': |
1883 | case 'a': |
1781 | // If file position equals to file size, then the end of file has been reached. |
1884 | // If file position equals to file size, then the end of file has been reached. |
1782 | // In this case it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR |
1885 | // In this case it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR |
1783 | // and a new cluster should be appended. |
1886 | // and a new cluster should be appended. |
1784 | // If the first sector of first cluster is unvalid, then the file claims no data clusters |
1887 | // If the first sector of first cluster is unvalid, then the file claims no data clusters |
1785 | // and size should be zero, therefore append a new Cluster too. |
1888 | // and size should be zero, therefore append a new Cluster too. |
1786 | if(((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR)) || (file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)) |
1889 | if(((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR)) || (file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)) |
1787 | { |
1890 | { |
1788 | if(CLUSTER_UNDEFINED == AppendCluster(file)) return(EOF); |
1891 | if(CLUSTER_UNDEFINED == AppendCluster(file)) return(EOF); |
1789 | } |
1892 | } |
1790 | 1893 | ||
1791 | curr_sector = file->FirstSectorOfCurrCluster; |
1894 | curr_sector = file->FirstSectorOfCurrCluster; |
1792 | curr_sector += file->SectorOfCurrCluster; |
1895 | curr_sector += file->SectorOfCurrCluster; |
1793 | if(file->SectorInCache != curr_sector) |
1896 | if(file->SectorInCache != curr_sector) |
1794 | { |
1897 | { |
1795 | file->SectorInCache = curr_sector; |
1898 | file->SectorInCache = curr_sector; |
Line 1797... | Line 1900... | ||
1797 | { |
1900 | { |
1798 | Fat16_Deinit(); |
1901 | Fat16_Deinit(); |
1799 | return(EOF); |
1902 | return(EOF); |
1800 | } |
1903 | } |
1801 | } |
1904 | } |
1802 | 1905 | ||
1803 | file->Cache[file->ByteOfCurrSector] = (u8)c; // write databyte into the buffer. The byte will be written to the device at once |
1906 | file->Cache[file->ByteOfCurrSector] = (u8)c; // write databyte into the buffer. The byte will be written to the device at once |
1804 | 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. |
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. |
1805 | file->Position++; // the actual positon within the file. |
1908 | file->Position++; // the actual positon within the file. |
1806 | file->ByteOfCurrSector++; // goto next byte in sector |
1909 | file->ByteOfCurrSector++; // goto next byte in sector |
1807 | if(file->ByteOfCurrSector >= BYTES_PER_SECTOR) // if the end of this sector is reached yet |
1910 | if(file->ByteOfCurrSector >= BYTES_PER_SECTOR) // if the end of this sector is reached yet |
1808 | { // save the sector to the sd-card |
1911 | { // save the sector to the sd-card |
1809 | 1912 | ||
1810 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
1913 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
1811 | { |
1914 | { |
1812 | Fat16_Deinit(); |
1915 | Fat16_Deinit(); |
1813 | return(EOF); |
1916 | return(EOF); |
1814 | } |
1917 | } |
Line 1907... | Line 2010... | ||
1907 | while((object_cnt < count) && success) |
2010 | while((object_cnt < count) && success) |
1908 | { |
2011 | { |
1909 | object_size = size; |
2012 | object_size = size; |
1910 | while((size > 0) && success) |
2013 | while((size > 0) && success) |
1911 | { |
2014 | { |
1912 | c = fputc_(*pbuff, file); // write a byte from the buffer to the opened file. |
2015 | c = fputc_(*pbuff, file); // write a byte from the buffer to the opened file. |
1913 | if(c != EOF) |
2016 | if(c != EOF) |
1914 | { |
2017 | { |
1915 | pbuff++; |
2018 | pbuff++; |
1916 | size--; |
2019 | size--; |
1917 | } |
2020 | } |
Line 1921... | Line 2024... | ||
1921 | } |
2024 | } |
1922 | } |
2025 | } |
1923 | if(success) object_cnt++; |
2026 | if(success) object_cnt++; |
1924 | } |
2027 | } |
Line 1925... | Line 2028... | ||
1925 | 2028 | ||
1926 | return(object_cnt); // return the number of objects succesfully written to the file |
2029 | return(object_cnt); // return the number of objects succesfully written to the file |
Line 1927... | Line 2030... | ||
1927 | } |
2030 | } |
1928 | 2031 | ||
Line 1986... | Line 2089... | ||
1986 | *pbuff = 0; // set string terminator |
2089 | *pbuff = 0; // set string terminator |
1987 | return(string); |
2090 | return(string); |
1988 | } |
2091 | } |
Line 1989... | Line 2092... | ||
1989 | 2092 | ||
- | 2093 | /****************************************************************************************************************************************/ |
|
- | 2094 | /* Function: fclose_(File *file); */ |
|
- | 2095 | /* */ |
|
- | 2096 | /* 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. */ |
|
- | 2098 | /* */ |
|
- | 2099 | /* Returnvalue: 0 on success EOF on error */ |
|
- | 2100 | /****************************************************************************************************************************************/ |
|
- | 2101 | s16 fclose_(File_t *file) |
|
- | 2102 | { |
|
- | 2103 | s16 returnvalue = EOF; |
|
- | 2104 | ||
- | 2105 | if(file == NULL) return(returnvalue); |
|
- | 2106 | returnvalue = fflush_(file); |
|
- | 2107 | UnlockFilePointer(file); |
|
- | 2108 | return(returnvalue); |
|
- | 2109 | } |
|
- | 2110 | ||
- | 2111 | ||
1990 | /****************************************************************************************************************************************/ |
2112 | /****************************************************************************************************************************************/ |
1991 | /* Function: fexist_(const u8*); */ |
2113 | /* Function: fexist_(const u8*); */ |
1992 | /* */ |
2114 | /* */ |
1993 | /* Description: This function checks if a file already exist. */ |
2115 | /* Description: This function checks if a file already exist. */ |
1994 | /* */ |
2116 | /* */ |
Line 2021... | Line 2143... | ||
2021 | { |
2143 | { |
2022 | return(1); |
2144 | return(1); |
2023 | } |
2145 | } |
2024 | } |
2146 | } |
Line -... | Line 2147... | ||
- | 2147 | ||
- | 2148 | ||
- | 2149 | /********************************************************************************************************************************************/ |
|
- | 2150 | /* Function: fdelete_(s8* filepath); */ |
|
- | 2151 | /* */ |
|
- | 2152 | /* Description: This function deletes the file with the specified filename from the filesystem */ |
|
- | 2153 | /* */ |
|
- | 2154 | /* */ |
|
- | 2155 | /* Returnvalue: 1 : specified file deleted succesfully 0: specified file not found */ |
|
- | 2156 | /********************************************************************************************************************************************/ |
|
- | 2157 | ||
- | 2158 | u8 fdelete_(s8* const filepath) |
|
- | 2159 | { |
|
- | 2160 | u8 retvalue = 0; |
|
- | 2161 | File_t file; |
|
- | 2162 | ||
- | 2163 | if(filepath == NULL) return(0); |
|
- | 2164 | // correct filepath formatting |
|
- | 2165 | Slashing_Path(filepath); |
|
- | 2166 | // if file is existent |
|
- | 2167 | if(FileExist(filepath, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, &file)) |
|
- | 2168 | { |
|
- | 2169 | // and is not marked as readonly? |
|
- | 2170 | if((file.Attribute & ATTR_READONLY) != ATTR_READONLY) |
|
- | 2171 | { |
|
- | 2172 | // try to delete the file content from the filesystem |
|
- | 2173 | if(DeleteClusterChain(file.FirstSectorOfFirstCluster)) |
|
- | 2174 | { |
|
- | 2175 | // and try delete the directory entry of the file |
|
- | 2176 | retvalue = DeleteDirectoryEntry(&file); |
|
- | 2177 | } |
|
- | 2178 | } |
|
- | 2179 | } |
|
- | 2180 | return(retvalue); |
|
- | 2181 | } |
|
2025 | 2182 | ||
2026 | /****************************************************************************************************************************************************/ |
2183 | /****************************************************************************************************************************************************/ |
2027 | /* Function: s8* FAT16_GetVolumeLabel(void) */ |
2184 | /* Function: s8* FAT16_GetVolumeLabel(void) */ |
2028 | /* */ |
2185 | /* */ |
2029 | /* Description: This function returns the volume label */ |
2186 | /* Description: This function returns the volume label */ |
Line 2037... | Line 2194... | ||
2037 | u16 dir_entry = 0; |
2194 | u16 dir_entry = 0; |
2038 | u8 i = 0; |
2195 | u8 i = 0; |
Line 2039... | Line 2196... | ||
2039 | 2196 | ||
2040 | DirEntry_t * dir; |
2197 | DirEntry_t * dir; |
2041 | File_t *file = NULL; |
2198 | File_t *file = NULL; |
2042 | 2199 | ||
2043 | // if Partition is not valud return NULL |
2200 | // if Partition is not valid return NULL |
2044 | if(!Partition.IsValid) return(pVolumeLabel); |
2201 | if(!Partition.IsValid) return(pVolumeLabel); |
2045 | // if Volume label was read before return it |
2202 | // if Volume label was read before return it |
2046 | if(Partition.VolumeLabel[0]!= '\0') return (Partition.VolumeLabel); |
2203 | if(Partition.VolumeLabel[0]!= '\0') return (Partition.VolumeLabel); |
2047 | // try to catch a file pointer |
2204 | // try to catch a file pointer |
2048 | file = LockFilePointer(); |
2205 | file = LockFilePointer(); |
2049 | if(file == NULL) return(pVolumeLabel); |
2206 | if(file == NULL) return(pVolumeLabel); |
2050 | // search dir entries direct within the root directory area |
2207 | // search dir entries direct within the root directory area |
2051 | file->DirectorySector = 0; |
2208 | file->DirectorySector = 0; |
2052 | max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR; |
2209 | max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR; |
2053 | file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector; |
2210 | file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector; |
2054 | 2211 | ||
2055 | // update current file data area position to start of first cluster |
2212 | // update current file data area position to start of first cluster |
2056 | file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; |
2213 | file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; |
2057 | file->SectorOfCurrCluster = 0; |
2214 | file->SectorOfCurrCluster = 0; |
Line 2102... | Line 2259... | ||
2102 | UnlockFilePointer(file); |
2259 | UnlockFilePointer(file); |
2103 | return(pVolumeLabel); |
2260 | return(pVolumeLabel); |
2104 | } |
2261 | } |
Line 2105... | Line -... | ||
2105 | - | ||
2106 | - | ||
2107 | - | ||
2108 | #define ATTR_NONE 0x00 // normal file |
- | |
2109 | #define ATTR_READONLY 0x01 // file is readonly |
- | |
2110 | #define ATTR_HIDDEN 0x02 // file is hidden |
- | |
2111 | #define ATTR_SYSTEM 0x04 // file is a system file |
- | |
2112 | #define ATTR_VOLUMELABEL 0x08 // entry is a volume label |
- | |
2113 | #define ATTR_LONG_FILENAME 0x0F // this is a long filename entry |
- | |
2114 | #define ATTR_SUBDIRECTORY 0x10 // entry is a directory name |
- | |
2115 | #define ATTR_ARCHIVE 0x20 // file is new or modified |
- | |
2116 | 2262 | ||
2117 | 2263 | ||
2118 | /********************************************************************************************************************************************/ |
2264 | /********************************************************************************************************************************************/ |
2119 | /* Function: u8 FindItem(Find_t); */ |
2265 | /* Function: u8 FindItem(Find_t); */ |
2120 | /* */ |
2266 | /* */ |
2121 | /* Description: This function looks for the item specified by global structure FindElement in the actual directory */ |
2267 | /* Description: This function looks for the item specified by global structure FindElement in the actual directory */ |
2122 | /* */ |
2268 | /* */ |
2123 | /* */ |
2269 | /* */ |
Line 2124... | Line 2270... | ||
2124 | /* Returnvalue: TRUE if an matching element was found */ |
2270 | /* Returnvalue: TRUE if an matching element was found */ |
2125 | /********************************************************************************************************************************************/ |
2271 | /********************************************************************************************************************************************/ |
2126 | 2272 | ||
Line 2133... | Line 2279... | ||
2133 | u8 readpointer = 0; |
2279 | u8 readpointer = 0; |
2134 | u8 writepointer = 0; |
2280 | u8 writepointer = 0; |
2135 | u8 retvalue = 0; |
2281 | u8 retvalue = 0; |
2136 | DirEntry_t *DirectoryEntry; |
2282 | DirEntry_t *DirectoryEntry; |
2137 | File_t file; |
2283 | File_t file; |
- | 2284 | SD_Result_t res=0; |
|
Line 2138... | Line 2285... | ||
2138 | 2285 | ||
2139 | file.FirstSectorOfCurrCluster = findelement->fp.FirstSectorOfCurrCluster; |
2286 | file.FirstSectorOfCurrCluster = findelement->fp.FirstSectorOfCurrCluster; |
2140 | file.SectorOfCurrCluster = findelement->fp.SectorOfCurrCluster; |
2287 | file.SectorOfCurrCluster = findelement->fp.SectorOfCurrCluster; |
Line 2150... | Line 2297... | ||
2150 | { |
2297 | { |
2151 | max_dir_sector = Partition.SectorsPerCluster; // limit max secters before next cluster |
2298 | max_dir_sector = Partition.SectorsPerCluster; // limit max secters before next cluster |
2152 | } |
2299 | } |
Line 2153... | Line 2300... | ||
2153 | 2300 | ||
2154 | do |
2301 | do |
2155 | { // search the next 16 rootentries in this sector of the roordirectory. |
2302 | { // 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. |
|
2156 | if(SD_SUCCESS != SDC_GetSector(((u32) file.FirstSectorOfCurrCluster + (u32)file.SectorOfCurrCluster), file.Cache)); // Read the Rootdirectory. |
2304 | if(res != SD_SUCCESS) |
2157 | { |
2305 | { |
2158 | Fat16_Deinit(); |
2306 | Fat16_Deinit(); |
2159 | return(0); |
2307 | return(0); |
2160 | } |
2308 | } |
2161 | 2309 | ||
Line 2162... | Line 2310... | ||
2162 | DirectoryEntry = (DirEntry_t *)file.Cache; |
2310 | DirectoryEntry = (DirEntry_t *)file.Cache; |
2163 | 2311 | ||
2164 | while((!retvalue)&&(index<16)) |
2312 | while((!retvalue)&&(index < 16)) |
2165 | { |
2313 | { |
2166 | i=0; |
2314 | i = 0; |
2167 | if((u8) DirectoryEntry[index].Name[0] != 0xe5) // ignore deleted items. |
2315 | if( (u8)DirectoryEntry[index].Name[0] != SLOT_DELETED) // ignore deleted items. |
2168 | { |
2316 | { |
2169 | while((i<=10)&&((DirectoryEntry[index].Name[i] == findelement->searchstring[i]) || (findelement->searchstring[i]=='*') || findelement->searchstring[i]=='?')) |
2317 | while((i <= 10) && ( (DirectoryEntry[index].Name[i] == findelement->searchstring[i]) || (findelement->searchstring[i] == '*') || findelement->searchstring[i] == '?')) |
2170 | { |
2318 | { |
2171 | i++; |
2319 | i++; |
2172 | } |
2320 | } |
2173 | } |
2321 | } |
- | 2322 | if((DirectoryEntry[index].Attribute & 0x30) && (DirectoryEntry[index].Attribute & findelement->attribmask) && (i == 11)) |
|
- | 2323 | { |
|
2174 | if((DirectoryEntry[index].Attribute <= 0x30) && (DirectoryEntry[index].Attribute & findelement->attribmask) && (i==11)) |
2324 | /* initialize the namestring with 0 */ |
2175 | { |
2325 | for(i = 0; i < 12; i++) findelement->name[i] = 0; |
2176 | for(readpointer=0;readpointer<=10;readpointer++) |
2326 | for(readpointer = 0; readpointer <= 10; readpointer++) |
2177 | { |
2327 | { |
2178 | if((DirectoryEntry[index].Name[readpointer] != ' ') && (readpointer!=8)) |
2328 | if((DirectoryEntry[index].Name[readpointer] != ' ') && (readpointer!=8)) |
2179 | { |
2329 | { |
2180 | findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer]; // copy the name of the item found to the find_structure. |
2330 | findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer]; // copy the name of the item found to the find_structure. |
2181 | writepointer++; |
2331 | writepointer++; |
2182 | } |
2332 | } |
2183 | else |
2333 | else |
2184 | { |
2334 | { |
2185 | if(DirectoryEntry[index].Attribute == ATTR_ARCHIVE) |
2335 | if(DirectoryEntry[index].Attribute == ATTR_ARCHIVE) |
2186 | { |
2336 | { |
2187 | if(readpointer < 8) readpointer=8; |
2337 | if(readpointer < 8) readpointer = 8; |
2188 | if(DirectoryEntry[index].Name[readpointer] != ' ') |
2338 | if(DirectoryEntry[index].Name[readpointer] != ' ') |
2189 | { |
2339 | { |
2190 | findelement->name[writepointer] = '.'; // then seperate the name and the extension by a '.' at index 8. |
2340 | findelement->name[writepointer] = '.'; // then seperate the name and the extension by a '.' at index 8. |
2191 | writepointer++; |
2341 | writepointer++; |
2192 | findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer]; // copy the name of the item found to the find_structure. |
2342 | findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer]; // copy the name of the item found to the find_structure. |
2193 | writepointer++; |
2343 | writepointer++; |
2194 | } |
2344 | } |
2195 | else break; |
2345 | else break; |
2196 | } |
2346 | } |
2197 | else break; |
- | |
2198 | } |
- | |
2199 | /* terminate the namestring with 0 for debugpurposes*/ |
2347 | else break; |
2200 | findelement->name[12] = 0; |
2348 | } |
2201 | } |
2349 | } |
2202 | findelement->fp.FirstSectorOfFirstCluster = (u32) DirectoryEntry[index].StartCluster; |
2350 | findelement->fp.FirstSectorOfFirstCluster = (u32) DirectoryEntry[index].StartCluster; |
2203 | findelement->fp.DirectoryIndex = index; |
2351 | findelement->fp.DirectoryIndex = index; |
2204 | findelement->fp.FirstSectorOfCurrCluster = file.FirstSectorOfCurrCluster; |
2352 | findelement->fp.FirstSectorOfCurrCluster = file.FirstSectorOfCurrCluster; |
2205 | findelement->fp.DirectorySector = (file.FirstSectorOfCurrCluster + file.SectorOfCurrCluster); |
2353 | findelement->fp.DirectorySector = (file.FirstSectorOfCurrCluster + file.SectorOfCurrCluster); |
2206 | findelement->fp.SectorOfCurrCluster = file.SectorOfCurrCluster; |
2354 | findelement->fp.SectorOfCurrCluster = file.SectorOfCurrCluster; |
2207 | findelement->fp.Size = DirectoryEntry[index].Size; |
2355 | findelement->fp.Size = DirectoryEntry[index].Size; |
2208 | findelement->fp.Attribute = DirectoryEntry[index].Attribute; |
2356 | findelement->fp.Attribute = DirectoryEntry[index].Attribute; |
2209 | retvalue = 1; |
2357 | retvalue = 1; |
2210 | } |
2358 | } |
2211 | /* search the next sector */ |
2359 | /* search the next sector */ |
2212 | index++; |
2360 | index++; |
2213 | } |
2361 | } |
2214 | /* this sector has been searched but we havn't found what we are looking for. Therefore we have to find the next sector */ |
2362 | /* this sector has been searched but we havn't found what we are looking for. Therefore we have to find the next sector */ |
2215 | if(!retvalue) // file not found in this sector so take next sector. |
2363 | if(!retvalue) // file not found in this sector so take next sector. |
2216 | { |
2364 | { |
2217 | /* in the next sector we start looking for the specified entry beginning at index 0 */ |
2365 | /* in the next sector we start looking for the specified entry beginning at index 0 */ |
2218 | index = 0; |
2366 | index = 0; |
2219 | /* there are still sectors to be read within the cluster or within the linear addresspace of the rootdirectory */ |
2367 | /* there are still sectors to be read within the cluster or within the linear addresspace of the rootdirectory */ |
2220 | if(file.SectorOfCurrCluster < max_dir_sector-1) file.SectorOfCurrCluster++; else end_of_directory_not_reached = 0; |
2368 | 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 */ |
|
- | 2370 | else if(Partition.FirstDataSector <= file.FirstSectorOfCurrCluster) |
|
- | 2371 | { |
|
- | 2372 | end_of_directory_not_reached = GetNextCluster(&file); |
|
- | 2373 | } |
|
2221 | /* 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 */ |
2374 | // within the rootdirectory we abort searching for elements after the maximun number of possible rootentries has beensearched |
2222 | if(Partition.FirstDataSector <= file.FirstSectorOfCurrCluster) |
2375 | else |
2223 | { |
2376 | { |
2224 | end_of_directory_not_reached = GetNextCluster(&file); |
2377 | end_of_directory_not_reached = 0; |
2225 | } |
2378 | } |
2226 | } |
2379 | } |
Line 2227... | Line 2380... | ||
2227 | } |
2380 | } |
2228 | while((end_of_directory_not_reached) && (!retvalue) ); |
2381 | while((end_of_directory_not_reached) && (!retvalue) ); |
Line 2247... | Line 2400... | ||
2247 | u8 index = 0; |
2400 | u8 index = 0; |
Line 2248... | Line 2401... | ||
2248 | 2401 | ||
Line 2249... | Line 2402... | ||
2249 | findelement->fp.DirectoryIndex++; |
2402 | findelement->fp.DirectoryIndex++; |
2250 | 2403 | ||
Line 2251... | Line 2404... | ||
2251 | /* before we start searching an element we clear the complete namestring within the structure FindElement */ |
2404 | /* before we start searching an element we clear the complete namestring within the structure FindElement */ |
2252 | for(index=0;index<11;index++) findelement->name[index] = 0; |
2405 | for(index = 0; index < 11; index++) findelement->name[index] = 0; |
2253 | 2406 | ||
2254 | if(FindItem(findelement)) |
2407 | if(FindItem(findelement)) |
Line 2255... | Line 2408... | ||
2255 | { |
2408 | { |
2256 | itemfound = 1; |
2409 | itemfound = 1; |
Line 2271... | Line 2424... | ||
2271 | /* Returnvalue: (1) if Element was found. (0) if no valid element was found */ |
2424 | /* Returnvalue: (1) if Element was found. (0) if no valid element was found */ |
2272 | /********************************************************************************************************************************************/ |
2425 | /********************************************************************************************************************************************/ |
2273 | u8 findfirst_(const s8* name, u8 attribmask, Find_t *findelement) |
2426 | u8 findfirst_(const s8* name, u8 attribmask, Find_t *findelement) |
2274 | { |
2427 | { |
2275 | u8 itemfound = 0; |
2428 | u8 itemfound = 0; |
2276 | u8 index = 0; |
2429 | u8 index = 0; |
Line 2277... | Line 2430... | ||
2277 | 2430 | ||
2278 | /* initialize the FindElement structure */ |
2431 | /* initialize the FindElement structure */ |
2279 | findelement->fp.FirstSectorOfFirstCluster = 0; // First sector of the first cluster of the file. |
2432 | findelement->fp.FirstSectorOfFirstCluster = 0; // First sector of the first cluster of the file. |
2280 | findelement->fp.FirstSectorOfCurrCluster = Partition.CurrentWorkingDirectory; // First sector of the cluster which is edited at the moment. |
2433 | findelement->fp.FirstSectorOfCurrCluster = Partition.CurrentWorkingDirectory; // First sector of the cluster which is edited at the moment. |
2281 | findelement->fp.SectorOfCurrCluster = 0; // The sector within the current cluster. |
2434 | findelement->fp.SectorOfCurrCluster = 0; // The sector within the current cluster. |
2282 | findelement->fp.ByteOfCurrSector = 0; // The byte location within the current sector. |
2435 | findelement->fp.ByteOfCurrSector = 0; // The byte location within the current sector. |
2283 | findelement->fp.Size = 0; // The size of the opend file in bytes. |
2436 | findelement->fp.Size = 0; // The size of the opend file in bytes. |
2284 | findelement->fp.Position = 0; // Pointer to a character within the file 0 < fileposition < filesize |
2437 | findelement->fp.Position = 0; // Pointer to a character within the file 0 < fileposition < filesize |
2285 | findelement->fp.DirectorySector = 0; // the sectorposition where the directoryentry has been made. |
2438 | findelement->fp.DirectorySector = 0; // the sectorposition where the directoryentry has been made. |
2286 | findelement->fp.DirectoryIndex = 0; // The index to the directoryentry within the specified sector. |
2439 | findelement->fp.DirectoryIndex = 0; // The index to the directoryentry within the specified sector. |
2287 | findelement->attribfilter = 0; |
2440 | findelement->attribfilter = 0; |
2288 | findelement->attribmask = attribmask; |
2441 | findelement->attribmask = attribmask; |
Line 2289... | Line 2442... | ||
2289 | findelement->searchstring[0]=0; |
2442 | findelement->searchstring[0] = 0; // terminate string at the begin (=NULL) |
2290 | 2443 | ||
- | 2444 | // bring it to the 8.3 format |
|
2291 | /* seperate the name of the element to be found from the filepath and bring it to the 8.3*/ |
2445 | if(NULL == SeperateFormatedDirName(name, findelement->searchstring)) return(0); |
2292 | SeperateDirName(name, findelement->searchstring); |
2446 | |
2293 | /* after the name of the element is in 8.3 we process the wildcards (*). After an * all following character are wildcards to */ |
2447 | //process the wildcards (*). After an * all following character are wildcards to |
2294 | for(index=0;index<8;index++) |
2448 | for(index = 0;index < 8;index++) |
2295 | { |
2449 | { |
2296 | /* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */ |
2450 | /* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */ |
2297 | if(findelement->searchstring[index] == '*') |
2451 | if(findelement->searchstring[index] == '*') |
2298 | { |
2452 | { |
2299 | /* */ |
2453 | /* */ |
2300 | while(++index <8) findelement->searchstring[index] = '*'; |
2454 | while(++index < 8) findelement->searchstring[index] = '*'; |
2301 | } |
2455 | } |
2302 | } |
2456 | } |
2303 | for(index=8;index<11;index++) |
2457 | for(index = 8;index < 11;index++) |
2304 | { |
2458 | { |
2305 | /* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */ |
2459 | /* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */ |
2306 | if(findelement->searchstring[index] == '*') |
2460 | if(findelement->searchstring[index] == '*') |
2307 | { |
2461 | { |
2308 | /* */ |
2462 | /* */ |
2309 | while(++index <11) findelement->searchstring[index] = '*'; |
2463 | while(++index < 11) findelement->searchstring[index] = '*'; |
2310 | } |
2464 | } |
2311 | } |
2465 | } |
2312 | 2466 | ||
2313 | /* the value of ...DirectoryIndex will be incremented in findnext_() thererfore it has to be decremented in findfirst_() */ |
2467 | /* the value of ...DirectoryIndex will be incremented in findnext_() thererfore it has to be decremented in findfirst_() */ |
2314 | findelement->fp.DirectoryIndex--; |
2468 | findelement->fp.DirectoryIndex--; |
Line 2315... | Line 2469... | ||
2315 | /* now lets search for the item within the direcory */ |
2469 | /* now lets search for the item within the direcory */ |
2316 | itemfound = findnext_(findelement); |
2470 | itemfound = findnext_(findelement); |
Line 2317... | Line -... | ||
2317 | - | ||
2318 | return(itemfound); |
- | |
2319 | } |
- | |
2320 | - | ||
2321 | - | ||
2322 | /********************************************************************************************************************************************/ |
- | |
2323 | /* Function: u8 GetDirCount(s8* filepath); */ |
- | |
2324 | /* */ |
- | |
2325 | /* Description: This function counts the number of subdirectories the dirpath contains */ |
- | |
2326 | /* */ |
- | |
2327 | /* */ |
- | |
2328 | /* Returnvalue: then number of subdirectories within the specified path */ |
- | |
2329 | /********************************************************************************************************************************************/ |
- | |
2330 | u8 GetDirCount(u8 *dirpath) |
- | |
2331 | { |
- | |
2332 | u8 i=0; |
- | |
2333 | u8 cnt=0; |
- | |
2334 | - | ||
2335 | while(dirpath[i] != 0 ) |
- | |
2336 | { |
- | |
2337 | if(dirpath[i]=='/') |
- | |
2338 | { |
- | |
2339 | if(dirpath[i+1]!=0) cnt++; // ignore last'/' |
- | |
2340 | } |
- | |
2341 | i++; |
- | |
2342 | } |
- | |
2343 | i=0; |
- | |
2344 | return(cnt); |
2471 | |
2345 | } |
2472 | return(itemfound); |
2346 | 2473 | } |
|
2347 | 2474 | ||
2348 | /********************************************************************************************************************************************/ |
2475 | /********************************************************************************************************************************************/ |
2349 | /* Funtion: char *GetSubDirectory (char *dirpath, char *directory) */ |
2476 | /* Function: s8 *GetSubDirectory (s8 *dirpath, s8 *directory) */ |
2350 | /* */ |
2477 | /* */ |
2351 | /* Description: this function returns a pointer to the beginning of the next subdirectory or NULL */ |
2478 | /* Description: this function parses the dirpath string and copies the first directroy name to the location pointed to by directroy */ |
2352 | /* */ |
2479 | /* */ |
2353 | /* */ |
2480 | /* */ |
2354 | /* returnvalue: number of subdirectories in the filepath */ |
2481 | /* returnvalue: a pointer to the beginning of the next subdirectory or NULL */ |
2355 | /********************************************************************************************************************************************/ |
2482 | /********************************************************************************************************************************************/ |
2356 | u8 * GetSubDirectory(u8 *dirpath, u8 *directory) |
2483 | s8 * GetSubDirectory(s8 *dirpath, s8 *directory) |
2357 | { |
2484 | { |
2358 | u8 *cptr = dirpath; |
2485 | s8 *cptr = dirpath; |
2359 | u8 *dptr = directory; |
2486 | s8 *dptr = directory; |
2360 | u8 *retvalue = NULL; |
2487 | s8 *remainingpath = NULL; |
2361 | 2488 | ||
2362 | /* if the first character of the path is an '/' we go to the next character */ |
2489 | /* if the first character of the path is an '/' we go to the next character */ |
2363 | if(*cptr == '/') cptr++; |
2490 | if(*cptr == '/') cptr++; |
2364 | /* search end of path or subdirectory*/ |
2491 | /* search end of path or subdirectory*/ |
2365 | while((*cptr != 0) && (*cptr != '/')) |
2492 | while((*cptr != 0) && (*cptr != '/')) |
2366 | { |
2493 | { |
2367 | *dptr = *cptr; |
2494 | *dptr = *cptr; // copy to directory string buffer |
2368 | dptr++; |
2495 | dptr++; |
Line 2369... | Line 2496... | ||
2369 | cptr++; |
2496 | cptr++; |
2370 | } |
2497 | } |
Line -... | Line 2498... | ||
- | 2498 | if(*cptr!=0) remainingpath = ++cptr; // return pointer to remaining path string |
|
2371 | if(*cptr!=0) retvalue = ++cptr; |
2499 | *dptr = 0; // terminate directory name string |
2372 | *dptr = 0; |
2500 | |
2373 | 2501 | return(remainingpath); |
|
2374 | return(retvalue); |
2502 | } |
2375 | } |
2503 | |
2376 | 2504 | ||
2377 | /********************************************************************************************************************************************/ |
2505 | /********************************************************************************************************************************************/ |
2378 | /* Function: s8 *GetPath(void); */ |
2506 | /* Function: u8 chdir_(s8* const path); */ |
Line 2379... | Line 2507... | ||
2379 | /* */ |
2507 | /* */ |
2380 | /* Description: This function function returns a pointer to the absolute path of the active partition */ |
2508 | /* Description: This function changes the current working directory to the directory specified by the filepath */ |
- | 2509 | /* by function findfirst() */ |
|
2381 | /* */ |
2510 | /* */ |
2382 | /* */ |
- | |
- | 2511 | /* Returnvalue: */ |
|
- | 2512 | /********************************************************************************************************************************************/ |
|
- | 2513 | ||
- | 2514 | u8 chdir_(s8* const path) |
|
- | 2515 | { |
|
Line 2383... | Line -... | ||
2383 | /* Returnvalue: */ |
- | |
2384 | /********************************************************************************************************************************************/ |
2516 | u8 retvalue = 0; // the value returned by this function |
2385 | 2517 | u32 ultemp = 0; // temp. variable |
|
2386 | s8 *GetPath(void) |
- | |
2387 | { |
- | |
2388 | return(Partition.PathToCwd); |
2518 | s8 *dirpath = path; // pointer to the remaining path string |
2389 | } |
- | |
2390 | - | ||
Line 2391... | Line -... | ||
2391 | /********************************************************************************************************************************************/ |
- | |
2392 | /* Function: void SetPathToRoot(void); */ |
- | |
2393 | /* */ |
2519 | s8 dirname[64]; // a buffer containing the name of the subdirectory we are actually looking for |
2394 | /* Description: This function sets the path to the rootdirectory */ |
2520 | Find_t fe; // The findelement needed for function findfirst to find the subdirectory entry |
2395 | /* */ |
- | |
- | 2521 | s8 tp[256]; // temporarily we remember the actual path until the operation has finished successfully |
|
Line -... | Line 2522... | ||
- | 2522 | u32 tcwd = 0; // temporarily we remember the actual current working directory |
|
- | 2523 | ||
- | 2524 | if(path == NULL) return(0); // return immediately of no path is given |
|
- | 2525 | // correct filepath formatting |
|
- | 2526 | Slashing_Path(path); |
|
- | 2527 | ||
- | 2528 | // lets remember the actual path and correspondig directory sector |
|
- | 2529 | strcpy(tp, Partition.PathToCwd); |
|
2396 | /* */ |
2530 | tcwd = Partition.CurrentWorkingDirectory; |
2397 | /* Returnvalue: */ |
2531 | |
- | 2532 | if(path[0] == '/') // if the path is absolute we begin at the rootdirectory |
|
- | 2533 | { |
|
2398 | /********************************************************************************************************************************************/ |
2534 | strcpy(Partition.PathToCwd, "/"); |
- | 2535 | Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector; |
|
- | 2536 | } |
|
- | 2537 | // parse through all the subdirectories within the path |
|
- | 2538 | do |
|
2399 | 2539 | { |
|
- | 2540 | dirpath = GetSubDirectory(dirpath, dirname); // get the name of the subdirectory we are looking for and the remainig path |
|
2400 | void SetPathToRoot(void) |
2541 | if(dirname[0] == 0) // if no directory name is available |
2401 | { |
2542 | { |
- | 2543 | retvalue = 1; // we are done |
|
- | 2544 | break; // break the loop |
|
- | 2545 | } |
|
- | 2546 | // search for the next subdirectory within the path |
|
2402 | /* lets point to the rootdirectory */ |
2547 | if(findfirst_(dirname, ATTR_SUBDIRECTORY, &fe)) |
- | 2548 | { |
|
- | 2549 | // 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(); |
|
- | 2551 | // we try to change into the actual directory so there's nothing todo |
|
- | 2552 | else if(dirname[0] == '.') return(1); |
|
- | 2553 | // otherwise we append the name of the directory we are changing in to the path |
|
2403 | strcpy(Partition.PathToCwd, "/"); |
2554 | else CWDPath_Push(dirname); |
- | 2555 | // The startcluster within an directory entry specifies the position within the fat where the file or directory starts |
|
- | 2556 | ultemp = (u32) fe.fp.FirstSectorOfFirstCluster; |
|
- | 2557 | // do we have to change into the rootdirectory? |
|
- | 2558 | if(ultemp) |
|
- | 2559 | { |
|
- | 2560 | // the first 2 entries are reserved for '.' and '..' |
|
- | 2561 | 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 |
|
- | 2563 | 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 |
|
- | 2565 | ultemp += Partition.FirstDataSector; |
|
- | 2566 | // the cwd now points to the specified directory |
|
- | 2567 | Partition.CurrentWorkingDirectory = ultemp; |
|
- | 2568 | } |
|
- | 2569 | else // (=0) root directory |
|
- | 2570 | { |
|
- | 2571 | // the cwd now points to the rootdirectory |
|
- | 2572 | Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector; |
|
Line 2404... | Line 2573... | ||
2404 | } |
2573 | } |
- | 2574 | retvalue = 1; |
|
2405 | 2575 | } |
|
2406 | /********************************************************************************************************************************************/ |
2576 | else // subdirectory not found |
2407 | /* Function: void AppendDirToPath(s8* directory); */ |
2577 | { |
2408 | /* */ |
- | |
- | 2578 | retvalue = 0; // no success tracing along the given directory chain |
|
2409 | /* Description: This function function appends the name of an directory to the Path to the CWD */ |
2579 | break; // break the loop |
2410 | /* */ |
2580 | } |
Line -... | Line 2581... | ||
- | 2581 | } |
|
2411 | /* */ |
2582 | while(dirpath != NULL); // do this until all subdirectories have been found |
2412 | /* Returnvalue: */ |
2583 | |
2413 | /********************************************************************************************************************************************/ |
2584 | // if we could not change to the specified directory we restore the actual path |
2414 | 2585 | if(!retvalue) |
|
2415 | void AppendDirToPath(s8* directory) |
2586 | { |
2416 | { |
2587 | Partition.CurrentWorkingDirectory = tcwd; |
2417 | /* append the name of the directory to the path */ |
2588 | strcpy(Partition.PathToCwd, tp); |
2418 | strcat(Partition.PathToCwd, directory); |
2589 | } |
Line 2419... | Line 2590... | ||
2419 | /* append a '/' after the directoryname */ |
2590 | return(retvalue); |
2420 | strcat(Partition.PathToCwd, "/"); |
2591 | } |
- | 2592 | ||
- | 2593 | ||
- | 2594 | /********************************************************************************************************************************************/ |
|
- | 2595 | /* Function: u8 rmdir_(s8* dname); */ |
|
- | 2596 | /* */ |
|
- | 2597 | /* Description: This function deletes the directory with the specified filename from the filesystem */ |
|
- | 2598 | /* */ |
|
- | 2599 | /* */ |
|
- | 2600 | /* Returnvalue: 1 : specified directory deleted succesfully 0: specified directory not found */ |
|
- | 2601 | /********************************************************************************************************************************************/ |
|
- | 2602 | ||
2421 | } |
2603 | u8 rmdir_(s8* const dirpath) |
- | 2604 | { |
|
- | 2605 | u8 retvalue = 0; |
|
2422 | 2606 | Find_t fe; |
|
- | 2607 | u32 cwd; |
|
- | 2608 | s8 path[256]; |
|
- | 2609 | s8 *dn; |
|
- | 2610 | s8 *dp; |
|
- | 2611 | ||
2423 | /********************************************************************************************************************************************/ |
2612 | if(dirpath == NULL) return(0); |
2424 | /* Function: RemoveLastDirFromPath(void); */ |
2613 | // correct filepath formatting |
2425 | /* */ |
2614 | Slashing_Path(dirpath); |
2426 | /* Description: This function removes the last directory from the path to the cwd */ |
2615 | |
2427 | /* */ |
2616 | // remember the current workingdirectory |
2428 | /* */ |
2617 | cwd = Partition.CurrentWorkingDirectory; |
2429 | /* Returnvalue: */ |
2618 | |
2430 | /********************************************************************************************************************************************/ |
2619 | // create local copy of the path |
2431 | 2620 | strcpy(path, dirpath); |
|
2432 | void RemoveLastDirFromPath(void) |
2621 | // seperate the filepath from the last directory within the path that shall be deleted |
2433 | { |
2622 | // start searching for the name of the directory to be deleted from the beginning of the path |
- | 2623 | dn = path; |
|
- | 2624 | dp = path; |
|
2434 | /* a pointer to the beginning of the absolute path to the cwd */ |
2625 | // search the complete path until the end of the string is found |
2435 | s8 * cptr = Partition.PathToCwd; |
2626 | while(*dn != 0) dn++; |
2436 | /* lets find the end of the path to the cwd */ |
2627 | // now check if the last directory whithin the path is terminated with an '/' and remove the '/' from the directoryname |
2437 | while(*cptr != 0 ) cptr++; |
2628 | if(*(dn-1) == '/') *--dn = 0; |
- | 2629 | // now find the beginning of the last directoryentry |
|
- | 2630 | while((*dn != '/') && (dn > path)) dn--; |
|
- | 2631 | // beginning of the last directory found |
|
- | 2632 | if(*dn == '/') |
|
- | 2633 | { |
|
- | 2634 | // remove the directoryname from the path by terminating the path with 0 |
|
2438 | /* if the path is terminated with an '/' */ |
2635 | *dn = 0; |
- | 2636 | // the dirname begins 1 character after the terminated path |
|
- | 2637 | dn++; |
|
- | 2638 | } |
|
- | 2639 | // we couldn't find a path before the directory to be deleted or no directoryname at all |
|
- | 2640 | else |
|
- | 2641 | { |
|
- | 2642 | // there is no path before the name of the directory to be deleted |
|
- | 2643 | if(dn == path) |
|
- | 2644 | { |
|
- | 2645 | // if there is a name of a directory to be deleted? |
|
- | 2646 | 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 |
|
- | 2648 | dp = NULL; |
|
- | 2649 | } |
|
- | 2650 | ||
- | 2651 | } |
|
- | 2652 | // switch to the directory containing the directory to be deleted if neccessary |
|
- | 2653 | if(dp != NULL) |
|
- | 2654 | { |
|
- | 2655 | if(!chdir_(dp)) return(0); |
|
- | 2656 | } |
|
- | 2657 | // now we have to find the specified directory to be deleted |
|
- | 2658 | retvalue = findfirst_(dn, 0xff, &fe); |
|
- | 2659 | // was the specified directory found? |
|
- | 2660 | if(retvalue) |
|
- | 2661 | { |
|
- | 2662 | // before we delete the directory we check if the directory is empty |
|
- | 2663 | if(chdir_(dn)) |
|
- | 2664 | { |
|
- | 2665 | if(findfirst_("*.*", 0xff, &fe)) |
|
- | 2666 | { |
|
- | 2667 | // 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; |
|
- | 2669 | while(findnext_(&fe)) |
|
- | 2670 | { |
|
2439 | if((*(cptr-1)) == '/') *(cptr-1)=0; |
2671 | if((strncmp(fe.name, ".", 1) != 0) && (strncmp(fe.name, "..", 2) != 0)) retvalue = 0; |
- | 2672 | } |
|
- | 2673 | } |
|
- | 2674 | chdir_(".."); |
|
- | 2675 | } |
|
- | 2676 | // directory couldn't be entered, is a real file? |
|
- | 2677 | else |
|
- | 2678 | { |
|
- | 2679 | retvalue = 0; |
|
- | 2680 | } |
|
- | 2681 | // specified directory is empty |
|
- | 2682 | if(retvalue) |
|
2440 | /* now lets find the beginning of the last directorientry */ |
2683 | { |
- | 2684 | 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 |
|
- | 2686 | if(findfirst_(dn, 0xff, &fe)) |
|
- | 2687 | { |
|
- | 2688 | // try to clear the allocated clusters within the fat |
|
2441 | while((*cptr != '/' ) && cptr > Partition.PathToCwd) cptr--; |
2689 | if(DeleteClusterChain(fe.fp.FirstSectorOfFirstCluster)) |
Line -... | Line 2690... | ||
- | 2690 | { |
|
2442 | /* is there one subdirectory left within the path? */ |
2691 | // delete the directoryentry within the specified directory |
2443 | if(cptr > Partition.PathToCwd) |
2692 | if(DeleteDirectoryEntry(&(fe.fp))) retvalue = 1; |
2444 | { |
2693 | } |
2445 | /* we delete the direntry by terminating the path with 0 */ |
2694 | } |
2446 | *cptr = 0; |
2695 | } |
2447 | } |
2696 | } |
2448 | /* there is no subdirectory left within the path. Therefore we create the root instead. */ |
2697 | |
2449 | else |
2698 | // restore the actual path |
2450 | { |
- | |
2451 | *cptr = '/'; |
- | |
2452 | *(cptr+1) = 0; |
- | |
2453 | } |
- | |
2454 | } |
- | |
2455 | - | ||
2456 | /********************************************************************************************************************************************/ |
- | |
2457 | /* Function: chdir_(s8* filepath); */ |
- | |
2458 | /* */ |
- | |
2459 | /* Description: This function changed the current working directory to the directory specified by the filepath */ |
- | |
Line 2460... | Line 2699... | ||
2460 | /* by function findfirst() */ |
2699 | Partition.CurrentWorkingDirectory = cwd; |
2461 | /* */ |
2700 | |
2462 | /* Returnvalue: */ |
- | |
2463 | /********************************************************************************************************************************************/ |
- | |
2464 | /* |
- | |
2465 | #define ATTR_NONE 0x00 // normal file |
- | |
2466 | #define ATTR_READONLY 0x01 // file is readonly |
- | |
2467 | #define ATTR_HIDDEN 0x02 // file is hidden |
- | |
2468 | #define ATTR_SYSTEM 0x04 // file is a system file |
- | |
2469 | #define ATTR_VOLUMELABEL 0x08 // entry is a volume label |
2701 | return(retvalue); |
2470 | #define ATTR_LONG_FILENAME 0x0F // this is a long filename entry |
2702 | } |
Line 2471... | Line -... | ||
2471 | #define ATTR_SUBDIRECTORY 0x10 // entry is a directory name |
- | |
2472 | #define ATTR_ARCHIVE 0x20 // file is new or modified |
- | |
2473 | */ |
- | |
2474 | - | ||
2475 | u8 chdir_(s8 *path) |
- | |
2476 | { |
2703 | |
2477 | u8 retvalue = 0; // the value returned by this function |
- | |
2478 | u32 ultemp = 0; // temp. variable |
- | |
2479 | u8 *directory = path; // pointer to a directoryname within the path |
2704 | |
2480 | u8 dircount = 0; // the number of subdirectoryentries within the path |
- | |
2481 | u8 cache[64]; // a buffer containing the name of the subdirectory we are actually looking for |
- | |
2482 | Find_t fe; // The findelement needed for function findfirst to find the subdirectoryentry |
- | |
2483 | s8 tp[256]; // temporarily we remember the actual path until the operation has finished successfully |
2705 | /********************************************************************************************************************************************/ |
2484 | u32 cwdt = 0; |
- | |
2485 | s8 *cptr; |
- | |
2486 | - | ||
2487 | /* bring the path into the correct syntax */ |
- | |
2488 | cptr = path; |
- | |
2489 | /* search the whole string */ |
- | |
2490 | while(*cptr != 0 ) |
- | |
2491 | { |
- | |
2492 | if(*cptr == '\\') *cptr = '/'; |
- | |
2493 | cptr++; |
- | |
2494 | } |
- | |
2495 | /* lets remember the actual path */ |
- | |
2496 | strcpy(tp, Partition.PathToCwd); |
2706 | /* Function: mkdir_(s8* dirpath); */ |
2497 | cwdt = Partition.CurrentWorkingDirectory; |
- | |
2498 | /* how many subdirectories are there within the path? */ |
- | |
2499 | dircount = GetDirCount(path); |
- | |
2500 | /* if the path is absolute we begin at the rootdirectory */ |
2707 | /* */ |
2501 | if(path[0] == '/') |
- | |
2502 | { |
- | |
2503 | strcpy(Partition.PathToCwd, "/"); |
- | |
2504 | Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector; |
- | |
2505 | /* if there is no other pathinformation we only switch to the rootdirectory. So theres nothing left todo.*/ |
- | |
2506 | if(!dircount) return(1); |
- | |
2507 | } |
- | |
2508 | /* now we parse through all the subdirectories within the path */ |
- | |
2509 | do |
- | |
2510 | { |
- | |
2511 | /* until all the subdirectories within the path have been processed */ |
- | |
2512 | if(dircount) dircount--; |
- | |
2513 | /* this is the name of the next subdirectory we are looking for */ |
- | |
2514 | directory = GetSubDirectory(directory, cache); |
- | |
2515 | /* search for the next subdirectory within the path */ |
- | |
2516 | if(findfirst_(cache, ATTR_SUBDIRECTORY, &fe)) |
- | |
2517 | { |
- | |
2518 | /* we try to change into the directory "..". Now we have to delete the last direntry from the path */ |
- | |
2519 | if(strcmp(cache,"..") == 0) RemoveLastDirFromPath(); |
- | |
2520 | /* we try to change into the actual directory so there's nothing todo */ |
- | |
2521 | else if(cache[0] == '.') return(1); |
- | |
2522 | /* otherwise we append the name of the directory we are changing in to the path */ |
- | |
2523 | else AppendDirToPath(cache); |
- | |
2524 | /* The startcluster within an directoryentry specifies the position within the fat where the file or directory starts */ |
- | |
2525 | ultemp = (u32) fe.fp.FirstSectorOfFirstCluster; |
- | |
2526 | /* the first 2 entries are reserved for '.' and '..' */ |
- | |
2527 | ultemp -= 2; |
2708 | /* Description: This function creates the directory with the specified pathname in the filesystem */ |
2528 | /* 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*/ |
2709 | /* */ |
2529 | ultemp *= Partition.SectorsPerCluster; |
- | |
2530 | /* at least we make the sectoraddress absolute by adding the relative address to the beginning of the datasection of the active partition */ |
2710 | /* */ |
2531 | ultemp += Partition.FirstDataSector; |
2711 | /* Returnvalue: 1 : specified directory created succesfully 0: specified dir exist already */ |
2532 | /* the cwd now points to the specified directory */ |
2712 | /********************************************************************************************************************************************/ |
- | 2713 | ||
- | 2714 | u8 mkdir_(s8* const dirpath) |
|
- | 2715 | { |
|
- | 2716 | u8 retvalue = 0; |
|
- | 2717 | File_t file; |
|
- | 2718 | ||
- | 2719 | if(dirpath == NULL) return(0); |