2 * FreeRTOS+FAT SL V1.0.1 (C) 2014 HCC Embedded
\r
4 * The FreeRTOS+FAT SL license terms are different to the FreeRTOS license
\r
7 * FreeRTOS+FAT SL uses a dual license model that allows the software to be used
\r
8 * under a standard GPL open source license, or a commercial license. The
\r
9 * standard GPL license (unlike the modified GPL license under which FreeRTOS
\r
10 * itself is distributed) requires that all software statically linked with
\r
11 * FreeRTOS+FAT SL is also distributed under the same GPL V2 license terms.
\r
12 * Details of both license options follow:
\r
14 * - Open source licensing -
\r
15 * FreeRTOS+FAT SL is a free download and may be used, modified, evaluated and
\r
16 * distributed without charge provided the user adheres to version two of the
\r
17 * GNU General Public License (GPL) and does not remove the copyright notice or
\r
18 * this text. The GPL V2 text is available on the gnu.org web site, and on the
\r
19 * following URL: http://www.FreeRTOS.org/gpl-2.0.txt.
\r
21 * - Commercial licensing -
\r
22 * Businesses and individuals who for commercial or other reasons cannot comply
\r
23 * with the terms of the GPL V2 license must obtain a commercial license before
\r
24 * incorporating FreeRTOS+FAT SL into proprietary software for distribution in
\r
25 * any form. Commercial licenses can be purchased from
\r
26 * http://shop.freertos.org/fat_sl and do not require any source files to be
\r
29 * FreeRTOS+FAT SL is distributed in the hope that it will be useful. You
\r
30 * cannot use FreeRTOS+FAT SL unless you agree that you use the software 'as
\r
31 * is'. FreeRTOS+FAT SL is provided WITHOUT ANY WARRANTY; without even the
\r
32 * implied warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A
\r
33 * PARTICULAR PURPOSE. Real Time Engineers Ltd. and HCC Embedded disclaims all
\r
34 * conditions and terms, be they implied, expressed, or statutory.
\r
36 * http://www.FreeRTOS.org
\r
37 * http://www.FreeRTOS.org/FreeRTOS-Plus
\r
41 #include "../../api/fat_sl.h"
\r
42 #include "../../psp/include/psp_string.h"
\r
51 #include "../../version/ver_fat_sl.h"
\r
52 #if VER_FAT_SL_MAJOR != 5 || VER_FAT_SL_MINOR != 2
\r
53 #error Incompatible FAT_SL version number!
\r
56 static unsigned char _f_stepnextsector ( void );
\r
59 /****************************************************************************
\r
67 * filename - file whose length is needed
\r
71 * length of the file
\r
73 ***************************************************************************/
\r
75 long fn_filelength ( const char * filename )
\r
81 if ( _f_setfsname( filename, &fsname ) )
\r
83 return 0; /*invalid name*/
\r
86 if ( _f_checknamewc( fsname.filename, fsname.fileext ) )
\r
88 return 0; /*invalid name*/
\r
91 if ( _f_getvolume() )
\r
93 return 0; /*can't get the size*/
\r
96 if ( !_f_findpath( &fsname, &pos ) )
\r
101 if ( !_f_findfilewc( fsname.filename, fsname.fileext, &pos, &de, 0 ) )
\r
106 if ( de->attr & F_ATTR_DIR )
\r
108 return 0; /*directory*/
\r
111 return (long)_f_getlong( &de->filesize );
\r
112 } /* fn_filelength */
\r
118 /****************************************************************************
\r
120 * _f_emptywritebuffer
\r
122 * empty write buffer if it contains unwritten data
\r
125 * error code or zero if successful
\r
127 ***************************************************************************/
\r
128 static unsigned char _f_stepnextsector ( void )
\r
131 unsigned char b_alloc;
\r
134 gl_volume.fatsector = (unsigned long)-1;
\r
135 if ( gl_file.startcluster == 0 )
\r
141 ++gl_file.pos.sector;
\r
142 if ( gl_file.pos.sector >= gl_file.pos.sectorend )
\r
144 unsigned long value;
\r
146 ret = _f_getclustervalue( gl_file.pos.cluster, &value );
\r
152 if ( ( value >= 2 ) && ( value < F_CLUSTER_RESERVED ) ) /*we are in chain*/
\r
154 _f_clustertopos( value, &gl_file.pos ); /*go to next cluster*/
\r
163 if ( b_alloc != 0 )
\r
165 unsigned long nextcluster;
\r
167 ret = _f_alloccluster( &nextcluster );
\r
173 ret = _f_setclustervalue( nextcluster, F_CLUSTER_LAST );
\r
179 if ( gl_file.startcluster == 0 )
\r
181 gl_file.startcluster = nextcluster;
\r
185 ret = _f_setclustervalue( gl_file.pos.cluster, nextcluster );
\r
192 _f_clustertopos( nextcluster, &gl_file.pos );
\r
194 return _f_writefatsector();
\r
198 } /* _f_stepnextsector */
\r
201 /****************************************************************************
\r
205 * Extend file to a certain size
\r
207 ***************************************************************************/
\r
208 static unsigned char _f_extend ( long size )
\r
210 unsigned long _size;
\r
213 size -= gl_file.filesize;
\r
214 _size = (unsigned long)size;
\r
216 if ( gl_file.startcluster == 0 )
\r
218 if ( _f_stepnextsector() )
\r
220 return F_ERR_WRITE;
\r
225 if ( ( gl_file.relpos > 0 ) && ( gl_file.relpos < F_SECTOR_SIZE ) )
\r
227 rc = _f_getcurrsector();
\r
235 if ( gl_file.relpos + _size >= F_SECTOR_SIZE )
\r
237 if ( gl_file.relpos < F_SECTOR_SIZE )
\r
239 psp_memset( gl_sector + gl_file.relpos, 0, ( F_SECTOR_SIZE - gl_file.relpos ) );
\r
240 _size -= ( F_SECTOR_SIZE - gl_file.relpos );
\r
242 if ( _f_writeglsector( gl_file.pos.sector ) )
\r
244 return F_ERR_WRITE;
\r
248 if ( _f_stepnextsector() )
\r
250 return F_ERR_WRITE;
\r
253 psp_memset( gl_sector, 0, F_SECTOR_SIZE );
\r
255 while ( _size >= F_SECTOR_SIZE )
\r
257 if ( _f_writeglsector( gl_file.pos.sector ) )
\r
259 return F_ERR_WRITE;
\r
262 if ( _f_stepnextsector() )
\r
264 return F_ERR_WRITE;
\r
267 psp_memset( gl_sector, 0, F_SECTOR_SIZE );
\r
269 _size -= F_SECTOR_SIZE;
\r
274 psp_memset( gl_sector + gl_file.relpos, 0, ( F_SECTOR_SIZE - gl_file.relpos ) );
\r
275 _size += gl_file.relpos;
\r
278 gl_file.modified = 1;
\r
279 gl_file.filesize += size;
\r
280 gl_file.abspos = gl_file.filesize & ( ~( F_SECTOR_SIZE - 1 ) );
\r
281 gl_file.relpos = _size;
\r
288 /****************************************************************************
\r
292 * subfunction for f_seek it moves position into given offset and read
\r
293 * the current sector
\r
296 * offset - position from start
\r
300 * error code or zero if successful
\r
302 ***************************************************************************/
\r
303 static unsigned char _f_fseek ( long offset )
\r
305 unsigned long cluster;
\r
307 unsigned char ret = F_NO_ERROR;
\r
315 if ( ( (unsigned long) offset <= gl_file.filesize )
\r
316 && ( (unsigned long) offset >= gl_file.abspos )
\r
317 && ( (unsigned long) offset < gl_file.abspos + F_SECTOR_SIZE ) )
\r
319 gl_file.relpos = (unsigned short)( offset - gl_file.abspos );
\r
323 if ( gl_file.modified )
\r
325 ret = _f_writeglsector( (unsigned long)-1 );
\r
328 gl_file.mode = F_FILE_CLOSE; /*cant accessed any more*/
\r
333 if ( gl_file.startcluster )
\r
335 gl_file.abspos = 0;
\r
336 gl_file.relpos = 0;
\r
337 gl_file.pos.cluster = gl_file.startcluster;
\r
338 remain = gl_file.filesize;
\r
340 tmp = gl_volume.bootrecord.sector_per_cluster;
\r
341 tmp *= F_SECTOR_SIZE; /* set to cluster size */
\r
344 gl_volume.fatsector = (unsigned long)-1;
\r
345 while ( (unsigned long)offset >= tmp )
\r
347 ret = _f_getclustervalue( gl_file.pos.cluster, &cluster );
\r
350 gl_file.mode = F_FILE_CLOSE;
\r
354 if ( (long) tmp >= remain )
\r
361 gl_file.abspos += tmp;
\r
362 if ( cluster >= F_CLUSTER_RESERVED )
\r
367 gl_file.pos.cluster = cluster;
\r
370 _f_clustertopos( gl_file.pos.cluster, &gl_file.pos );
\r
371 if ( remain && offset )
\r
373 while ( ( offset > (long) F_SECTOR_SIZE )
\r
374 && ( remain > (long) F_SECTOR_SIZE ) )
\r
376 gl_file.pos.sector++;
\r
377 offset -= F_SECTOR_SIZE;
\r
378 remain -= F_SECTOR_SIZE;
\r
379 gl_file.abspos += F_SECTOR_SIZE;
\r
383 if ( remain < offset )
\r
385 gl_file.relpos = (unsigned short)remain;
\r
386 ret = _f_extend( gl_file.filesize + offset - remain );
\r
390 gl_file.relpos = (unsigned short)offset;
\r
395 ret = _f_extend( offset );
\r
404 /****************************************************************************
\r
408 * open a file for reading/writing/appending
\r
412 * filename - which file need to be opened
\r
413 * mode - string how to open ("r"-read, "w"-write, "w+"-overwrite, "a"-append
\r
417 * F_FILE pointer if successfully
\r
420 ***************************************************************************/
\r
421 F_FILE * fn_open ( const char * filename, const char * mode )
\r
425 unsigned short date;
\r
426 unsigned short time;
\r
427 unsigned char m_mode = F_FILE_CLOSE;
\r
429 if ( mode[1] == 0 )
\r
431 if ( mode[0] == 'r' )
\r
433 m_mode = F_FILE_RD;
\r
436 if ( mode[0] == 'w' )
\r
438 m_mode = F_FILE_WR;
\r
441 if ( mode[0] == 'a' )
\r
447 if ( ( mode[1] == '+' ) && ( mode[2] == 0 ) )
\r
449 if ( mode[0] == 'r' )
\r
451 m_mode = F_FILE_RDP;
\r
454 if ( mode[0] == 'w' )
\r
456 m_mode = F_FILE_WRP;
\r
459 if ( mode[0] == 'a' )
\r
461 m_mode = F_FILE_AP;
\r
466 if ( m_mode == F_FILE_CLOSE )
\r
468 return 0; /*invalid mode*/
\r
471 if ( _f_setfsname( filename, &fsname ) )
\r
473 return 0; /*invalid name*/
\r
476 if ( _f_checknamewc( fsname.filename, fsname.fileext ) )
\r
478 return 0; /*invalid name*/
\r
481 if ( fsname.filename[0] == '.' )
\r
486 if ( _f_getvolume() )
\r
488 return 0; /*cant open any*/
\r
491 if ( gl_file.mode != F_FILE_CLOSE )
\r
496 psp_memset( &gl_file, 0, sizeof( F_FILE ) );
\r
498 if ( !_f_findpath( &fsname, &gl_file.dirpos ) )
\r
505 case F_FILE_RDP: /*r*/
\r
506 case F_FILE_RD: /*r*/
\r
507 if ( !_f_findfilewc( fsname.filename, fsname.fileext, &gl_file.dirpos, &de, 0 ) )
\r
512 if ( de->attr & F_ATTR_DIR )
\r
514 return 0; /*directory*/
\r
517 gl_file.startcluster = _f_getdecluster( de );
\r
519 if ( gl_file.startcluster )
\r
521 _f_clustertopos( gl_file.startcluster, &gl_file.pos );
\r
522 gl_file.filesize = _f_getlong( &de->filesize );
\r
523 gl_file.abspos = (unsigned long) (-1 * (long) F_SECTOR_SIZE);
\r
524 if ( _f_fseek( 0 ) )
\r
530 #if F_FILE_CHANGED_EVENT
\r
531 if ( m_mode == F_FILE_RDP )
\r
533 _f_createfullname( gl_file.filename, sizeof( gl_file.filename ), fsname.path, fsname.filename, fsname.fileext );
\r
541 case F_FILE_A: /*a*/
\r
542 psp_memcpy( &( gl_file.pos ), &( gl_file.dirpos ), sizeof( F_POS ) );
\r
543 if ( _f_findfilewc( fsname.filename, fsname.fileext, &gl_file.dirpos, &de, 0 ) )
\r
545 if ( de->attr & ( F_ATTR_DIR | F_ATTR_READONLY ) )
\r
550 gl_file.startcluster = _f_getdecluster( de );
\r
551 gl_file.filesize = _f_getlong( &de->filesize );
\r
553 if ( gl_file.startcluster )
\r
555 _f_clustertopos( gl_file.startcluster, &gl_file.pos );
\r
556 gl_file.abspos = (unsigned long) (-1 * (long) F_SECTOR_SIZE); /*forcing seek to read 1st sector! abspos=0;*/
\r
557 if ( _f_fseek( (long)gl_file.filesize ) )
\r
559 gl_file.mode = F_FILE_CLOSE;
\r
566 psp_memcpy( &( gl_file.dirpos ), &( gl_file.pos ), sizeof( F_POS ) );
\r
567 _f_clustertopos( gl_file.dirpos.cluster, &gl_file.pos );
\r
569 if ( _f_addentry( &fsname, &gl_file.dirpos, &de ) )
\r
571 return 0; /*couldnt be added*/
\r
574 de->attr |= F_ATTR_ARC; /*set as archiv*/
\r
575 if ( _f_writeglsector( (unsigned long)-1 ) )
\r
581 #if F_FILE_CHANGED_EVENT
\r
582 _f_createfullname( gl_file.filename, sizeof( gl_file.filename ), fsname.path, fsname.filename, fsname.fileext );
\r
587 case F_FILE_WR: /*w*/
\r
588 case F_FILE_WRP: /*w+*/
\r
589 _f_clustertopos( gl_file.dirpos.cluster, &gl_file.pos );
\r
590 if ( _f_findfilewc( fsname.filename, fsname.fileext, &gl_file.pos, &de, 0 ) )
\r
592 unsigned long cluster = _f_getdecluster( de ); /*exist*/
\r
594 if ( de->attr & ( F_ATTR_DIR | F_ATTR_READONLY ) )
\r
599 psp_memcpy( &( gl_file.dirpos ), &( gl_file.pos ), sizeof( F_POS ) );
\r
601 _f_setlong( de->filesize, 0 ); /*reset size;*/
\r
602 de->attr |= F_ATTR_ARC; /*set as archiv*/
\r
603 _f_setword( de->clusterlo, 0 ); /*no points anywhere*/
\r
604 _f_setword( de->clusterhi, 0 );
\r
606 if ( gl_volume.mediatype == F_FAT32_MEDIA )
\r
608 f_igettimedate( &time, &date );
\r
609 _f_setword( &de->crtdate, date ); /*if there is realtime clock then creation date could be set from*/
\r
610 _f_setword( &de->crttime, time ); /*if there is realtime clock then creation time could be set from*/
\r
611 _f_setword( &de->lastaccessdate, date ); /*if there is realtime clock then creation date could be set from*/
\r
614 if ( _f_writeglsector( (unsigned long)-1 ) )
\r
619 if ( _f_removechain( cluster ) )
\r
621 return 0; /*remove */
\r
626 if ( _f_addentry( &fsname, &gl_file.dirpos, &de ) )
\r
628 return 0; /*couldnt be added*/
\r
631 psp_memset( &gl_file, 0, 21 );
\r
632 de->attr |= F_ATTR_ARC; /*set as archiv*/
\r
633 if ( _f_writeglsector( (unsigned long)-1 ) )
\r
639 #if F_FILE_CHANGED_EVENT
\r
640 _f_createfullname( gl_file.filename, sizeof( gl_file.filename ), fsname.path, fsname.filename, fsname.fileext );
\r
646 return 0; /*invalid mode*/
\r
649 gl_file.mode = m_mode; /* lock it */
\r
650 return (F_FILE *)1;
\r
654 /****************************************************************************
\r
655 * _f_updatefileentry
\r
656 * Updated a file directory entry or removes the entry
\r
657 * and the fat chain belonging to it.
\r
658 ***************************************************************************/
\r
659 static unsigned char _f_updatefileentry ( int remove )
\r
662 unsigned short date;
\r
663 unsigned short time;
\r
665 de = (F_DIRENTRY *)( gl_sector + sizeof( F_DIRENTRY ) * gl_file.dirpos.pos );
\r
666 if ( _f_readglsector( gl_file.dirpos.sector ) || remove )
\r
668 _f_setdecluster( de, 0 );
\r
669 _f_setlong( &de->filesize, 0 );
\r
670 (void)_f_writeglsector( (unsigned long)-1 );
\r
671 (void)_f_removechain( gl_file.startcluster );
\r
672 return F_ERR_WRITE;
\r
675 _f_setdecluster( de, gl_file.startcluster );
\r
676 _f_setlong( &de->filesize, gl_file.filesize );
\r
677 f_igettimedate( &time, &date );
\r
678 _f_setword( &de->cdate, date ); /*if there is realtime clock then creation date could be set from*/
\r
679 _f_setword( &de->ctime, time ); /*if there is realtime clock then creation time could be set from*/
\r
680 if ( gl_volume.mediatype == F_FAT32_MEDIA )
\r
682 _f_setword( &de->lastaccessdate, date ); /*if there is realtime clock then creation date could be set from*/
\r
685 return _f_writeglsector( (unsigned long)-1 );
\r
686 } /* _f_updatefileentry */
\r
689 /****************************************************************************
\r
693 * close a previously opened file
\r
697 * filehandle - which file needs to be closed
\r
701 * error code or zero if successful
\r
703 ***************************************************************************/
\r
704 unsigned char fn_close ( F_FILE * f )
\r
708 #if F_FILE_CHANGED_EVENT
\r
709 unsigned char mode;
\r
714 return F_ERR_NOTOPEN;
\r
717 ret = _f_getvolume();
\r
723 if ( gl_file.mode == F_FILE_CLOSE )
\r
725 return F_ERR_NOTOPEN;
\r
728 else if ( gl_file.mode == F_FILE_RD )
\r
730 gl_file.mode = F_FILE_CLOSE;
\r
735 #if F_FILE_CHANGED_EVENT
\r
738 gl_file.mode = F_FILE_CLOSE;
\r
740 if ( gl_file.modified )
\r
742 if ( _f_writeglsector( (unsigned long)-1 ) )
\r
744 (void)_f_updatefileentry( 1 );
\r
745 return F_ERR_WRITE;
\r
749 ret = _f_updatefileentry( 0 );
\r
751 #if F_FILE_CHANGED_EVENT
\r
752 if ( f_filechangedevent && !ret )
\r
754 ST_FILE_CHANGED fc;
\r
755 if ( ( mode == F_FILE_WR ) || ( mode == F_FILE_WRP ) )
\r
757 fc.action = FACTION_ADDED;
\r
758 fc.flags = FFLAGS_FILE_NAME;
\r
760 else if ( ( mode == F_FILE_A ) || ( mode == F_FILE_RDP ) )
\r
762 fc.action = FACTION_MODIFIED;
\r
763 fc.flags = FFLAGS_FILE_NAME | FFLAGS_SIZE;
\r
766 strcpy( fc.filename, f->filename );
\r
767 if ( f->filename[0] )
\r
769 f_filechangedevent( &fc );
\r
772 f->filename[0] = '\0';
\r
775 #endif /* if F_FILE_CHANGED_EVENT */
\r
781 /****************************************************************************
\r
785 * flush a previously opened file
\r
789 * filehandle - which file needs to be closed
\r
793 * error code or zero if successful
\r
795 ***************************************************************************/
\r
796 unsigned char fn_flush ( F_FILE * f )
\r
802 return F_ERR_NOTOPEN;
\r
805 ret = _f_getvolume();
\r
811 if ( gl_file.mode == F_FILE_CLOSE )
\r
813 return F_ERR_NOTOPEN;
\r
815 else if ( gl_file.mode != F_FILE_RD )
\r
817 if ( gl_file.modified )
\r
819 if ( _f_writeglsector( (unsigned long)-1 ) )
\r
821 (void)_f_updatefileentry( 1 );
\r
822 return F_ERR_WRITE;
\r
826 return _f_updatefileentry( 0 );
\r
833 /****************************************************************************
\r
837 * read data from file
\r
841 * buf - where the store data
\r
842 * size - size of items to be read
\r
843 * _size_t - number of items need to be read
\r
844 * filehandle - file where to read from
\r
848 * with the number of read bytes
\r
850 ***************************************************************************/
\r
851 long fn_read ( void * buf, long size, long _size_st, F_FILE * f )
\r
853 char * buffer = (char *)buf;
\r
861 if ( ( gl_file.mode & ( F_FILE_RD | F_FILE_RDP | F_FILE_WRP | F_FILE_AP ) ) == 0 )
\r
868 _size_st = retsize;
\r
871 if ( _f_getvolume() )
\r
873 return 0; /*cant read any*/
\r
876 if ( size + gl_file.relpos + gl_file.abspos >= gl_file.filesize ) /*read len longer than the file*/
\r
878 size = (long)( ( gl_file.filesize ) - ( gl_file.relpos ) - ( gl_file.abspos ) ); /*calculate new size*/
\r
886 if ( _f_getcurrsector() )
\r
888 gl_file.mode = F_FILE_CLOSE; /*no more read allowed*/
\r
894 unsigned long rdsize = (unsigned long)size;
\r
896 if ( gl_file.relpos == F_SECTOR_SIZE )
\r
900 gl_file.abspos += gl_file.relpos;
\r
901 gl_file.relpos = 0;
\r
903 if ( gl_file.modified )
\r
905 ret = _f_writeglsector( (unsigned long)-1 ); /*empty write buffer */
\r
908 gl_file.mode = F_FILE_CLOSE; /*no more read allowed*/
\r
913 gl_file.pos.sector++; /*goto next*/
\r
915 ret = _f_getcurrsector();
\r
916 if ( ( ret == F_ERR_EOF ) && ( !size ) )
\r
923 gl_file.mode = F_FILE_CLOSE; /*no more read allowed*/
\r
933 if ( rdsize >= F_SECTOR_SIZE - gl_file.relpos )
\r
935 rdsize = (unsigned long)( F_SECTOR_SIZE - gl_file.relpos );
\r
938 psp_memcpy( buffer, gl_sector + gl_file.relpos, rdsize ); /*always less than 512*/
\r
941 gl_file.relpos += rdsize;
\r
946 return retsize / _size_st;
\r
950 /****************************************************************************
\r
954 * write data into file
\r
958 * buf - where the store data
\r
959 * size - size of items to be read
\r
960 * size_t - number of items need to be read
\r
961 * filehandle - file where to read from
\r
965 * with the number of read bytes
\r
967 ***************************************************************************/
\r
969 long fn_write ( const void * buf, long size, long _size_st, F_FILE * f )
\r
971 char * buffer = (char *)buf;
\r
980 if ( ( gl_file.mode & ( F_FILE_WR | F_FILE_A | F_FILE_RDP | F_FILE_WRP | F_FILE_AP ) ) == 0 )
\r
987 _size_st = retsize;
\r
995 if ( _f_getvolume() )
\r
997 return 0; /*can't write*/
\r
1000 if ( ( gl_file.mode ) & ( F_FILE_A | F_FILE_AP ) )
\r
1002 if ( _f_fseek( (long)gl_file.filesize ) )
\r
1004 gl_file.mode = F_FILE_CLOSE;
\r
1009 if ( gl_file.startcluster == 0 )
\r
1011 if ( _f_stepnextsector() )
\r
1013 gl_file.mode = F_FILE_CLOSE;
\r
1019 if ( _f_getcurrsector() )
\r
1021 gl_file.mode = F_FILE_CLOSE;
\r
1028 unsigned long wrsize = (unsigned long)size;
\r
1030 if ( gl_file.relpos == F_SECTOR_SIZE )
\r
1032 if ( gl_file.modified )
\r
1034 if ( _f_writeglsector( gl_file.pos.sector ) )
\r
1036 gl_file.mode = F_FILE_CLOSE;
\r
1037 if ( _f_updatefileentry( 0 ) == 0 )
\r
1047 gl_file.modified = 0;
\r
1050 if ( _f_stepnextsector() )
\r
1052 gl_file.mode = F_FILE_CLOSE;
\r
1053 if ( _f_updatefileentry( 0 ) == 0 )
\r
1063 gl_file.abspos += gl_file.relpos;
\r
1064 gl_file.relpos = 0;
\r
1066 if ( wrsize && ( wrsize < F_SECTOR_SIZE ) )
\r
1068 ret = _f_getcurrsector();
\r
1072 if ( ret != F_ERR_EOF )
\r
1074 gl_file.mode = F_FILE_CLOSE; /*no more read allowed*/
\r
1086 if ( wrsize >= F_SECTOR_SIZE - gl_file.relpos )
\r
1088 wrsize = (unsigned long)( F_SECTOR_SIZE - gl_file.relpos );
\r
1092 psp_memcpy( gl_sector + gl_file.relpos, buffer, wrsize );
\r
1093 gl_file.modified = 1; /*sector is modified*/
\r
1096 gl_file.relpos += wrsize;
\r
1098 retsize += wrsize;
\r
1100 if ( gl_file.filesize < gl_file.abspos + gl_file.relpos )
\r
1102 gl_file.filesize = gl_file.abspos + gl_file.relpos;
\r
1106 return retsize / _size_st;
\r
1111 /****************************************************************************
\r
1115 * moves position into given offset in given file
\r
1119 * filehandle - F_FILE structure which file position needed to be modified
\r
1120 * offset - relative position
\r
1121 * whence - where to calculate position (F_SEEK_SET,F_SEEK_CUR,F_SEEK_END)
\r
1125 * 0 - if successfully
\r
1126 * other - if any error
\r
1128 ***************************************************************************/
\r
1131 unsigned char fn_seek ( F_FILE * f, long offset, unsigned char whence )
\r
1133 unsigned char ret;
\r
1137 return F_ERR_NOTOPEN;
\r
1140 if ( ( gl_file.mode & ( F_FILE_RD | F_FILE_WR | F_FILE_A | F_FILE_RDP | F_FILE_WRP | F_FILE_AP ) ) == 0 )
\r
1142 return F_ERR_NOTOPEN;
\r
1145 ret = _f_getvolume();
\r
1151 if ( whence == F_SEEK_CUR )
\r
1153 return _f_fseek( (long)( gl_file.abspos + gl_file.relpos + offset ) );
\r
1155 else if ( whence == F_SEEK_END )
\r
1157 return _f_fseek( (long)( gl_file.filesize + offset ) );
\r
1159 else if ( whence == F_SEEK_SET )
\r
1161 return _f_fseek( offset );
\r
1164 return F_ERR_NOTUSEABLE;
\r
1169 /****************************************************************************
\r
1173 * Tells the current position of opened file
\r
1177 * filehandle - which file needs the position
\r
1181 * position in the file from start
\r
1183 ***************************************************************************/
\r
1185 long fn_tell ( F_FILE * f )
\r
1192 if ( ( gl_file.mode & ( F_FILE_RD | F_FILE_WR | F_FILE_A | F_FILE_RDP | F_FILE_WRP | F_FILE_AP ) ) == 0 )
\r
1197 return (long)( gl_file.abspos + gl_file.relpos );
\r
1202 /****************************************************************************
\r
1206 * Tells if the current position is end of file or not
\r
1210 * filehandle - which file needs the checking
\r
1215 * other - if EOF or invalid file handle
\r
1217 ***************************************************************************/
\r
1219 unsigned char fn_eof ( F_FILE * f )
\r
1223 return F_ERR_NOTOPEN; /*if error*/
\r
1226 if ( gl_file.abspos + gl_file.relpos < gl_file.filesize )
\r
1231 return F_ERR_EOF; /*EOF*/
\r
1237 /****************************************************************************
\r
1241 * set the fileposition in the opened file to the begining
\r
1245 * filehandle - which file needs to be rewinded
\r
1249 * error code or zero if successful
\r
1251 ***************************************************************************/
\r
1253 unsigned char fn_rewind ( F_FILE * filehandle )
\r
1255 return fn_seek( filehandle, 0L, F_SEEK_SET );
\r
1260 /****************************************************************************
\r
1264 * write a character into file
\r
1268 * ch - what to write into file
\r
1269 * filehandle - file where to write
\r
1273 * with the number of written bytes (1-success, 0-not successfully)
\r
1275 ***************************************************************************/
\r
1277 int fn_putc ( int ch, F_FILE * filehandle )
\r
1279 unsigned char tmpch = (unsigned char)ch;
\r
1281 if ( fn_write( &tmpch, 1, 1, filehandle ) )
\r
1293 /****************************************************************************
\r
1297 * get a character from file
\r
1301 * filehandle - file where to read from
\r
1305 * with the read character or -1 if read was not successfully
\r
1307 ***************************************************************************/
\r
1308 int fn_getc ( F_FILE * filehandle )
\r
1312 if ( !fn_read( &ch, 1, 1, filehandle ) )
\r
1322 /****************************************************************************
\r
1330 * filename - file which wanted to be deleted (with or without path)
\r
1334 * error code or zero if successful
\r
1336 ***************************************************************************/
\r
1337 unsigned char fn_delete ( const char * filename )
\r
1342 unsigned char ret;
\r
1344 if ( _f_setfsname( filename, &fsname ) )
\r
1346 return F_ERR_INVALIDNAME; /*invalid name*/
\r
1349 if ( _f_checknamewc( fsname.filename, fsname.fileext ) )
\r
1351 return F_ERR_INVALIDNAME; /*invalid name*/
\r
1354 if ( fsname.filename[0] == '.' )
\r
1356 return F_ERR_NOTFOUND;
\r
1359 ret = _f_getvolume();
\r
1365 if ( !( _f_findpath( &fsname, &pos ) ) )
\r
1367 return F_ERR_INVALIDDIR;
\r
1370 if ( !_f_findfilewc( fsname.filename, fsname.fileext, &pos, &de, 0 ) )
\r
1372 return F_ERR_NOTFOUND;
\r
1375 if ( de->attr & F_ATTR_DIR )
\r
1377 return F_ERR_INVALIDDIR; /*directory*/
\r
1380 if ( de->attr & F_ATTR_READONLY )
\r
1382 return F_ERR_ACCESSDENIED; /*readonly*/
\r
1385 if ( ( gl_file.mode != F_FILE_CLOSE ) && ( gl_file.dirpos.sector == pos.sector ) && ( gl_file.dirpos.pos == pos.pos ) )
\r
1387 return F_ERR_LOCKED;
\r
1390 de->name[0] = (unsigned char)0xe5; /*removes it*/
\r
1391 ret = _f_writeglsector( (unsigned long)-1 );
\r
1397 ret = _f_removechain( _f_getdecluster( de ) );
\r
1399 #if F_FILE_CHANGED_EVENT
\r
1400 if ( f_filechangedevent && !ret )
\r
1402 ST_FILE_CHANGED fc;
\r
1403 fc.action = FACTION_REMOVED;
\r
1404 fc.flags = FFLAGS_FILE_NAME;
\r
1406 if ( !_f_createfullname( fc.filename, sizeof( fc.filename ), fsname.path, fsname.filename, fsname.fileext ) )
\r
1408 f_filechangedevent( &fc );
\r
1420 /****************************************************************************
\r
1426 * INPUT: f - file pointer
\r
1427 * filesize - required new size
\r
1428 * RETURN: F_NO_ERROR - on success
\r
1431 ***************************************************************************/
\r
1432 unsigned char _f_seteof ( F_FILE * f, long filesize )
\r
1434 unsigned char rc = F_NO_ERROR;
\r
1438 return F_ERR_NOTOPEN; /*if error*/
\r
1441 if ( ( unsigned long) filesize < gl_file.filesize )
\r
1443 rc = _f_fseek( filesize );
\r
1444 if ( rc == F_NO_ERROR )
\r
1446 unsigned long cluster;
\r
1447 rc = _f_getclustervalue( gl_file.pos.cluster, &cluster );
\r
1448 if ( rc == F_NO_ERROR )
\r
1450 if ( cluster != F_CLUSTER_LAST )
\r
1452 rc = _f_removechain( cluster );
\r
1458 rc = _f_setclustervalue( gl_file.pos.cluster, F_CLUSTER_LAST );
\r
1464 rc = _f_writefatsector();
\r
1471 gl_file.filesize = (unsigned long)filesize;
\r
1475 else if ( (unsigned long) filesize > gl_file.filesize )
\r
1477 rc = _f_fseek( filesize );
\r
1484 /****************************************************************************
\r
1490 * INPUT: f - file pointer
\r
1491 * filesize - required new size
\r
1492 * RETURN: F_NO_ERROR - on success
\r
1495 ***************************************************************************/
\r
1496 unsigned char fn_seteof ( F_FILE * f )
\r
1498 unsigned char rc = F_NO_ERROR;
\r
1500 rc = _f_seteof( f, ( gl_file.abspos + gl_file.relpos ) );
\r
1508 /****************************************************************************
\r
1512 * Open a file and set end of file
\r
1514 * INPUT: filename - name of the file
\r
1515 * filesize - required new size
\r
1516 * RETURN: NULL on error, otherwise file pointer
\r
1518 ***************************************************************************/
\r
1519 F_FILE * fn_truncate ( const char * filename, long filesize )
\r
1521 F_FILE * f = fn_open( filename, "r+" );
\r
1526 rc = _f_fseek( (long)gl_file.filesize );
\r
1527 if ( rc == F_NO_ERROR )
\r
1529 rc = _f_seteof( f, filesize );
\r
1540 } /* fn_truncate */
\r