SAM4S-EK_FreeRTOS+FAT-SL  1.0
An example project to test the functionality of FreeRTOS+FAT-SL using SD card as data storage medium
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Modules
file.c
Go to the documentation of this file.
1 /*
2  * FreeRTOS+FAT SL V1.0.1 (C) 2014 HCC Embedded
3  *
4  * The FreeRTOS+FAT SL license terms are different to the FreeRTOS license
5  * terms.
6  *
7  * FreeRTOS+FAT SL uses a dual license model that allows the software to be used
8  * under a standard GPL open source license, or a commercial license. The
9  * standard GPL license (unlike the modified GPL license under which FreeRTOS
10  * itself is distributed) requires that all software statically linked with
11  * FreeRTOS+FAT SL is also distributed under the same GPL V2 license terms.
12  * Details of both license options follow:
13  *
14  * - Open source licensing -
15  * FreeRTOS+FAT SL is a free download and may be used, modified, evaluated and
16  * distributed without charge provided the user adheres to version two of the
17  * GNU General Public License (GPL) and does not remove the copyright notice or
18  * this text. The GPL V2 text is available on the gnu.org web site, and on the
19  * following URL: http://www.FreeRTOS.org/gpl-2.0.txt.
20  *
21  * - Commercial licensing -
22  * Businesses and individuals who for commercial or other reasons cannot comply
23  * with the terms of the GPL V2 license must obtain a commercial license before
24  * incorporating FreeRTOS+FAT SL into proprietary software for distribution in
25  * any form. Commercial licenses can be purchased from
26  * http://shop.freertos.org/fat_sl and do not require any source files to be
27  * changed.
28  *
29  * FreeRTOS+FAT SL is distributed in the hope that it will be useful. You
30  * cannot use FreeRTOS+FAT SL unless you agree that you use the software 'as
31  * is'. FreeRTOS+FAT SL is provided WITHOUT ANY WARRANTY; without even the
32  * implied warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A
33  * PARTICULAR PURPOSE. Real Time Engineers Ltd. and HCC Embedded disclaims all
34  * conditions and terms, be they implied, expressed, or statutory.
35  *
36  * http://www.FreeRTOS.org
37  * http://www.FreeRTOS.org/FreeRTOS-Plus
38  *
39  */
40 
41 #include "fat_sl.h"
42 #include "psp_string.h"
43 
44 #include "util.h"
45 #include "volume.h"
46 #include "drv.h"
47 #include "fat.h"
48 #include "dir.h"
49 #include "file.h"
50 
51 #include "../../version/ver_fat_sl.h"
52 #if VER_FAT_SL_MAJOR != 5 || VER_FAT_SL_MINOR != 2
53  #error Incompatible FAT_SL version number!
54 #endif
55 
56 static unsigned char _f_stepnextsector ( void );
57 
58 
59 /****************************************************************************
60  *
61  * fn_filelength
62  *
63  * Get a file length
64  *
65  * INPUTS
66  *
67  * filename - file whose length is needed
68  *
69  * RETURNS
70  *
71  * length of the file
72  *
73  ***************************************************************************/
74 
75 long fn_filelength ( const char * filename )
76 {
77  F_POS pos;
78  F_DIRENTRY * de;
79  F_NAME fsname;
80 
81  if ( _f_setfsname( filename, &fsname ) )
82  {
83  return 0; /*invalid name*/
84  }
85 
86  if ( _f_checknamewc( fsname.filename, fsname.fileext ) )
87  {
88  return 0; /*invalid name*/
89  }
90 
91  if ( _f_getvolume() )
92  {
93  return 0; /*can't get the size*/
94  }
95 
96  if ( !_f_findpath( &fsname, &pos ) )
97  {
98  return 0;
99  }
100 
101  if ( !_f_findfilewc( fsname.filename, fsname.fileext, &pos, &de, 0 ) )
102  {
103  return 0;
104  }
105 
106  if ( de->attr & F_ATTR_DIR )
107  {
108  return 0; /*directory*/
109  }
110 
111  return (long)_f_getlong( &de->filesize );
112 } /* fn_filelength */
113 
114 
115 
116 
117 
118 /****************************************************************************
119  *
120  * _f_emptywritebuffer
121  *
122  * empty write buffer if it contains unwritten data
123  *
124  * RETURNS
125  * error code or zero if successful
126  *
127  ***************************************************************************/
128 static unsigned char _f_stepnextsector ( void )
129 {
130  unsigned char ret;
131  unsigned char b_alloc;
132 
133  b_alloc = 0;
134  gl_volume.fatsector = (unsigned long)-1;
135  if ( gl_file.startcluster == 0 )
136  {
137  b_alloc = 1;
138  }
139  else
140  {
141  ++gl_file.pos.sector;
143  {
144  unsigned long value;
145 
146  ret = _f_getclustervalue( gl_file.pos.cluster, &value );
147  if ( ret )
148  {
149  return ret;
150  }
151 
152  if ( ( value >= 2 ) && ( value < F_CLUSTER_RESERVED ) ) /*we are in chain*/
153  {
154  _f_clustertopos( value, &gl_file.pos ); /*go to next cluster*/
155  }
156  else
157  {
158  b_alloc = 1;
159  }
160  }
161  }
162 
163  if ( b_alloc != 0 )
164  {
165  unsigned long nextcluster;
166 
167  ret = _f_alloccluster( &nextcluster );
168  if ( ret )
169  {
170  return ret;
171  }
172 
173  ret = _f_setclustervalue( nextcluster, F_CLUSTER_LAST );
174  if ( ret )
175  {
176  return ret;
177  }
178 
179  if ( gl_file.startcluster == 0 )
180  {
181  gl_file.startcluster = nextcluster;
182  }
183  else
184  {
185  ret = _f_setclustervalue( gl_file.pos.cluster, nextcluster );
186  if ( ret )
187  {
188  return ret;
189  }
190  }
191 
192  _f_clustertopos( nextcluster, &gl_file.pos );
193 
194  return _f_writefatsector();
195  }
196 
197  return F_NO_ERROR;
198 } /* _f_stepnextsector */
199 
200 
201 /****************************************************************************
202  *
203  * _f_extend
204  *
205  * Extend file to a certain size
206  *
207  ***************************************************************************/
208 static unsigned char _f_extend ( long size )
209 {
210  unsigned long _size;
211  unsigned char rc;
212 
213  size -= gl_file.filesize;
214  _size = (unsigned long)size;
215 
216  if ( gl_file.startcluster == 0 )
217  {
218  if ( _f_stepnextsector() )
219  {
220  return F_ERR_WRITE;
221  }
222  }
223  else
224  {
225  if ( ( gl_file.relpos > 0 ) && ( gl_file.relpos < F_SECTOR_SIZE ) )
226  {
227  rc = _f_getcurrsector();
228  if ( rc )
229  {
230  return rc;
231  }
232  }
233  }
234 
235  if ( gl_file.relpos + _size >= F_SECTOR_SIZE )
236  {
237  if ( gl_file.relpos < F_SECTOR_SIZE )
238  {
240  _size -= ( F_SECTOR_SIZE - gl_file.relpos );
241 
243  {
244  return F_ERR_WRITE;
245  }
246  }
247 
248  if ( _f_stepnextsector() )
249  {
250  return F_ERR_WRITE;
251  }
252 
254 
255  while ( _size >= F_SECTOR_SIZE )
256  {
258  {
259  return F_ERR_WRITE;
260  }
261 
262  if ( _f_stepnextsector() )
263  {
264  return F_ERR_WRITE;
265  }
266 
268 
269  _size -= F_SECTOR_SIZE;
270  }
271  }
272  else
273  {
275  _size += gl_file.relpos;
276  }
277 
278  gl_file.modified = 1;
279  gl_file.filesize += size;
280  gl_file.abspos = gl_file.filesize & ( ~( F_SECTOR_SIZE - 1 ) );
281  gl_file.relpos = _size;
282 
283  return F_NO_ERROR;
284 } /* _f_extend */
285 
286 
287 
288 /****************************************************************************
289  *
290  * _f_fseek
291  *
292  * subfunction for f_seek it moves position into given offset and read
293  * the current sector
294  *
295  * INPUTS
296  * offset - position from start
297  *
298  * RETURNS
299  *
300  * error code or zero if successful
301  *
302  ***************************************************************************/
303 static unsigned char _f_fseek ( long offset )
304 {
305  unsigned long cluster;
306  unsigned long tmp;
307  unsigned char ret = F_NO_ERROR;
308  long remain;
309 
310  if ( offset < 0 )
311  {
312  offset = 0;
313  }
314 
315  if ( ( (unsigned long) offset <= gl_file.filesize )
316  && ( (unsigned long) offset >= gl_file.abspos )
317  && ( (unsigned long) offset < gl_file.abspos + F_SECTOR_SIZE ) )
318  {
319  gl_file.relpos = (unsigned short)( offset - gl_file.abspos );
320  }
321  else
322  {
323  if ( gl_file.modified )
324  {
325  ret = _f_writeglsector( (unsigned long)-1 );
326  if ( ret )
327  {
328  gl_file.mode = F_FILE_CLOSE; /*cant accessed any more*/
329  return ret;
330  }
331  }
332 
333  if ( gl_file.startcluster )
334  {
335  gl_file.abspos = 0;
336  gl_file.relpos = 0;
338  remain = gl_file.filesize;
339 
341  tmp *= F_SECTOR_SIZE; /* set to cluster size */
342 
343  /*calc cluster*/
344  gl_volume.fatsector = (unsigned long)-1;
345  while ( (unsigned long)offset >= tmp )
346  {
347  ret = _f_getclustervalue( gl_file.pos.cluster, &cluster );
348  if ( ret )
349  {
351  return ret;
352  }
353 
354  if ( (long) tmp >= remain )
355  {
356  break;
357  }
358 
359  remain -= tmp;
360  offset -= tmp;
361  gl_file.abspos += tmp;
362  if ( cluster >= F_CLUSTER_RESERVED )
363  {
364  break;
365  }
366 
367  gl_file.pos.cluster = cluster;
368  }
369 
371  if ( remain && offset )
372  {
373  while ( ( offset > (long) F_SECTOR_SIZE )
374  && ( remain > (long) F_SECTOR_SIZE ) )
375  {
376  gl_file.pos.sector++;
377  offset -= F_SECTOR_SIZE;
378  remain -= F_SECTOR_SIZE;
380  }
381  }
382 
383  if ( remain < offset )
384  {
385  gl_file.relpos = (unsigned short)remain;
386  ret = _f_extend( gl_file.filesize + offset - remain );
387  }
388  else
389  {
390  gl_file.relpos = (unsigned short)offset;
391  }
392  }
393  else
394  {
395  ret = _f_extend( offset );
396  }
397  }
398 
399  return ret;
400 } /* _f_fseek */
401 
402 
403 
404 /****************************************************************************
405  *
406  * fn_open
407  *
408  * open a file for reading/writing/appending
409  *
410  * INPUTS
411  *
412  * filename - which file need to be opened
413  * mode - string how to open ("r"-read, "w"-write, "w+"-overwrite, "a"-append
414  *
415  * RETURNS
416  *
417  * F_FILE pointer if successfully
418  * 0 - if any error
419  *
420  ***************************************************************************/
421 F_FILE * fn_open ( const char * filename, const char * mode )
422 {
423  F_DIRENTRY * de;
424  F_NAME fsname;
425  unsigned short date;
426  unsigned short time;
427  unsigned char m_mode = F_FILE_CLOSE;
428 
429  if ( mode[1] == 0 )
430  {
431  if ( mode[0] == 'r' )
432  {
433  m_mode = F_FILE_RD;
434  }
435 
436  if ( mode[0] == 'w' )
437  {
438  m_mode = F_FILE_WR;
439  }
440 
441  if ( mode[0] == 'a' )
442  {
443  m_mode = F_FILE_A;
444  }
445  }
446 
447  if ( ( mode[1] == '+' ) && ( mode[2] == 0 ) )
448  {
449  if ( mode[0] == 'r' )
450  {
451  m_mode = F_FILE_RDP;
452  }
453 
454  if ( mode[0] == 'w' )
455  {
456  m_mode = F_FILE_WRP;
457  }
458 
459  if ( mode[0] == 'a' )
460  {
461  m_mode = F_FILE_AP;
462  }
463 
464  }
465 
466  if ( m_mode == F_FILE_CLOSE )
467  {
468  return 0; /*invalid mode*/
469  }
470 
471  if ( _f_setfsname( filename, &fsname ) )
472  {
473  return 0; /*invalid name*/
474  }
475 
476  if ( _f_checknamewc( fsname.filename, fsname.fileext ) )
477  {
478  return 0; /*invalid name*/
479  }
480 
481  if ( fsname.filename[0] == '.' )
482  {
483  return 0;
484  }
485 
486  if ( _f_getvolume() )
487  {
488  return 0; /*cant open any*/
489  }
490 
491  if ( gl_file.mode != F_FILE_CLOSE )
492  {
493  return 0;
494  }
495 
496  psp_memset( &gl_file, 0, sizeof( F_FILE ) );
497 
498  if ( !_f_findpath( &fsname, &gl_file.dirpos ) )
499  {
500  return 0;
501  }
502 
503  switch ( m_mode )
504  {
505  case F_FILE_RDP: /*r*/
506  case F_FILE_RD: /*r*/
507  if ( !_f_findfilewc( fsname.filename, fsname.fileext, &gl_file.dirpos, &de, 0 ) )
508  {
509  return 0;
510  }
511 
512  if ( de->attr & F_ATTR_DIR )
513  {
514  return 0; /*directory*/
515  }
516 
518 
519  if ( gl_file.startcluster )
520  {
523  gl_file.abspos = (unsigned long) (-1 * (long) F_SECTOR_SIZE);
524  if ( _f_fseek( 0 ) )
525  {
526  return 0;
527  }
528  }
529 
530 #if F_FILE_CHANGED_EVENT
531  if ( m_mode == F_FILE_RDP )
532  {
533  _f_createfullname( gl_file.filename, sizeof( gl_file.filename ), fsname.path, fsname.filename, fsname.fileext );
534  }
535 
536 #endif
537 
538  break;
539 
540  case F_FILE_AP:
541  case F_FILE_A: /*a*/
542  psp_memcpy( &( gl_file.pos ), &( gl_file.dirpos ), sizeof( F_POS ) );
543  if ( _f_findfilewc( fsname.filename, fsname.fileext, &gl_file.dirpos, &de, 0 ) )
544  {
545  if ( de->attr & ( F_ATTR_DIR | F_ATTR_READONLY ) )
546  {
547  return 0;
548  }
549 
552 
553  if ( gl_file.startcluster )
554  {
556  gl_file.abspos = (unsigned long) (-1 * (long) F_SECTOR_SIZE); /*forcing seek to read 1st sector! abspos=0;*/
557  if ( _f_fseek( (long)gl_file.filesize ) )
558  {
560  return 0;
561  }
562  }
563  }
564  else
565  {
566  psp_memcpy( &( gl_file.dirpos ), &( gl_file.pos ), sizeof( F_POS ) );
568 
569  if ( _f_addentry( &fsname, &gl_file.dirpos, &de ) )
570  {
571  return 0; /*couldnt be added*/
572  }
573 
574  de->attr |= F_ATTR_ARC; /*set as archiv*/
575  if ( _f_writeglsector( (unsigned long)-1 ) )
576  {
577  return 0;
578  }
579  }
580 
581  #if F_FILE_CHANGED_EVENT
582  _f_createfullname( gl_file.filename, sizeof( gl_file.filename ), fsname.path, fsname.filename, fsname.fileext );
583  #endif
584  break;
585 
586 
587  case F_FILE_WR: /*w*/
588  case F_FILE_WRP: /*w+*/
590  if ( _f_findfilewc( fsname.filename, fsname.fileext, &gl_file.pos, &de, 0 ) )
591  {
592  unsigned long cluster = _f_getdecluster( de ); /*exist*/
593 
594  if ( de->attr & ( F_ATTR_DIR | F_ATTR_READONLY ) )
595  {
596  return 0;
597  }
598 
599  psp_memcpy( &( gl_file.dirpos ), &( gl_file.pos ), sizeof( F_POS ) );
600 
601  _f_setlong( de->filesize, 0 ); /*reset size;*/
602  de->attr |= F_ATTR_ARC; /*set as archiv*/
603  _f_setword( de->clusterlo, 0 ); /*no points anywhere*/
604  _f_setword( de->clusterhi, 0 );
605 
607  {
608  f_igettimedate( &time, &date );
609  _f_setword( &de->crtdate, date ); /*if there is realtime clock then creation date could be set from*/
610  _f_setword( &de->crttime, time ); /*if there is realtime clock then creation time could be set from*/
611  _f_setword( &de->lastaccessdate, date ); /*if there is realtime clock then creation date could be set from*/
612  }
613 
614  if ( _f_writeglsector( (unsigned long)-1 ) )
615  {
616  return 0;
617  }
618 
619  if ( _f_removechain( cluster ) )
620  {
621  return 0; /*remove */
622  }
623  }
624  else
625  {
626  if ( _f_addentry( &fsname, &gl_file.dirpos, &de ) )
627  {
628  return 0; /*couldnt be added*/
629  }
630 
631  psp_memset( &gl_file, 0, 21 );
632  de->attr |= F_ATTR_ARC; /*set as archiv*/
633  if ( _f_writeglsector( (unsigned long)-1 ) )
634  {
635  return 0;
636  }
637  }
638 
639  #if F_FILE_CHANGED_EVENT
640  _f_createfullname( gl_file.filename, sizeof( gl_file.filename ), fsname.path, fsname.filename, fsname.fileext );
641  #endif
642 
643  break;
644 
645  default:
646  return 0; /*invalid mode*/
647  } /* switch */
648 
649  gl_file.mode = m_mode; /* lock it */
650  return (F_FILE *)1;
651 } /* fn_open */
652 
653 
654 /****************************************************************************
655  * _f_updatefileentry
656  * Updated a file directory entry or removes the entry
657  * and the fat chain belonging to it.
658  ***************************************************************************/
659 static unsigned char _f_updatefileentry ( int remove )
660 {
661  F_DIRENTRY * de;
662  unsigned short date;
663  unsigned short time;
664 
665  de = (F_DIRENTRY *)( gl_sector + sizeof( F_DIRENTRY ) * gl_file.dirpos.pos );
666  if ( _f_readglsector( gl_file.dirpos.sector ) || remove )
667  {
668  _f_setdecluster( de, 0 );
669  _f_setlong( &de->filesize, 0 );
670  (void)_f_writeglsector( (unsigned long)-1 );
672  return F_ERR_WRITE;
673  }
674 
677  f_igettimedate( &time, &date );
678  _f_setword( &de->cdate, date ); /*if there is realtime clock then creation date could be set from*/
679  _f_setword( &de->ctime, time ); /*if there is realtime clock then creation time could be set from*/
681  {
682  _f_setword( &de->lastaccessdate, date ); /*if there is realtime clock then creation date could be set from*/
683  }
684 
685  return _f_writeglsector( (unsigned long)-1 );
686 } /* _f_updatefileentry */
687 
688 
689 /****************************************************************************
690  *
691  * fn_close
692  *
693  * close a previously opened file
694  *
695  * INPUTS
696  *
697  * filehandle - which file needs to be closed
698  *
699  * RETURNS
700  *
701  * error code or zero if successful
702  *
703  ***************************************************************************/
704 unsigned char fn_close ( F_FILE * f )
705 {
706  unsigned char ret;
707 
708 #if F_FILE_CHANGED_EVENT
709  unsigned char mode;
710 #endif
711 
712  if ( !f )
713  {
714  return F_ERR_NOTOPEN;
715  }
716 
717  ret = _f_getvolume();
718  if ( ret )
719  {
720  return ret;
721  }
722 
723  if ( gl_file.mode == F_FILE_CLOSE )
724  {
725  return F_ERR_NOTOPEN;
726  }
727 
728  else if ( gl_file.mode == F_FILE_RD )
729  {
731  return F_NO_ERROR;
732  }
733  else
734  {
735  #if F_FILE_CHANGED_EVENT
736  mode = f->mode;
737  #endif
739 
740  if ( gl_file.modified )
741  {
742  if ( _f_writeglsector( (unsigned long)-1 ) )
743  {
744  (void)_f_updatefileentry( 1 );
745  return F_ERR_WRITE;
746  }
747  }
748 
749  ret = _f_updatefileentry( 0 );
750 
751  #if F_FILE_CHANGED_EVENT
752  if ( f_filechangedevent && !ret )
753  {
754  ST_FILE_CHANGED fc;
755  if ( ( mode == F_FILE_WR ) || ( mode == F_FILE_WRP ) )
756  {
757  fc.action = FACTION_ADDED;
758  fc.flags = FFLAGS_FILE_NAME;
759  }
760  else if ( ( mode == F_FILE_A ) || ( mode == F_FILE_RDP ) )
761  {
762  fc.action = FACTION_MODIFIED;
763  fc.flags = FFLAGS_FILE_NAME | FFLAGS_SIZE;
764  }
765 
766  strcpy( fc.filename, f->filename );
767  if ( f->filename[0] )
768  {
769  f_filechangedevent( &fc );
770  }
771 
772  f->filename[0] = '\0';
773  }
774 
775  #endif /* if F_FILE_CHANGED_EVENT */
776  return ret;
777  }
778 } /* fn_close */
779 
780 
781 /****************************************************************************
782  *
783  * fn_flush
784  *
785  * flush a previously opened file
786  *
787  * INPUTS
788  *
789  * filehandle - which file needs to be closed
790  *
791  * RETURNS
792  *
793  * error code or zero if successful
794  *
795  ***************************************************************************/
796 unsigned char fn_flush ( F_FILE * f )
797 {
798  unsigned char ret;
799 
800  if ( !f )
801  {
802  return F_ERR_NOTOPEN;
803  }
804 
805  ret = _f_getvolume();
806  if ( ret )
807  {
808  return ret;
809  }
810 
811  if ( gl_file.mode == F_FILE_CLOSE )
812  {
813  return F_ERR_NOTOPEN;
814  }
815  else if ( gl_file.mode != F_FILE_RD )
816  {
817  if ( gl_file.modified )
818  {
819  if ( _f_writeglsector( (unsigned long)-1 ) )
820  {
821  (void)_f_updatefileentry( 1 );
822  return F_ERR_WRITE;
823  }
824  }
825 
826  return _f_updatefileentry( 0 );
827  }
828 
829  return F_NO_ERROR;
830 } /* fn_flush */
831 
832 
833 /****************************************************************************
834  *
835  * fn_read
836  *
837  * read data from file
838  *
839  * INPUTS
840  *
841  * buf - where the store data
842  * size - size of items to be read
843  * _size_t - number of items need to be read
844  * filehandle - file where to read from
845  *
846  * RETURNS
847  *
848  * with the number of read bytes
849  *
850  ***************************************************************************/
851 long fn_read ( void * buf, long size, long _size_st, F_FILE * f )
852 {
853  char * buffer = (char *)buf;
854  long retsize;
855 
856  if ( !f )
857  {
858  return 0;
859  }
860 
861  if ( ( gl_file.mode & ( F_FILE_RD | F_FILE_RDP | F_FILE_WRP | F_FILE_AP ) ) == 0 )
862  {
863  return 0;
864  }
865 
866  retsize = size;
867  size *= _size_st;
868  _size_st = retsize;
869  retsize = 0;
870 
871  if ( _f_getvolume() )
872  {
873  return 0; /*cant read any*/
874  }
875 
876  if ( size + gl_file.relpos + gl_file.abspos >= gl_file.filesize ) /*read len longer than the file*/
877  {
878  size = (long)( ( gl_file.filesize ) - ( gl_file.relpos ) - ( gl_file.abspos ) ); /*calculate new size*/
879  }
880 
881  if ( size <= 0 )
882  {
883  return 0;
884  }
885 
886  if ( _f_getcurrsector() )
887  {
888  gl_file.mode = F_FILE_CLOSE; /*no more read allowed*/
889  return 0;
890  }
891 
892  for( ; ; )
893  {
894  unsigned long rdsize = (unsigned long)size;
895 
896  if ( gl_file.relpos == F_SECTOR_SIZE )
897  {
898  unsigned char ret;
899 
901  gl_file.relpos = 0;
902 
903  if ( gl_file.modified )
904  {
905  ret = _f_writeglsector( (unsigned long)-1 ); /*empty write buffer */
906  if ( ret )
907  {
908  gl_file.mode = F_FILE_CLOSE; /*no more read allowed*/
909  return retsize;
910  }
911  }
912 
913  gl_file.pos.sector++; /*goto next*/
914 
915  ret = _f_getcurrsector();
916  if ( ( ret == F_ERR_EOF ) && ( !size ) )
917  {
918  return retsize;
919  }
920 
921  if ( ret )
922  {
923  gl_file.mode = F_FILE_CLOSE; /*no more read allowed*/
924  return retsize;
925  }
926  }
927 
928  if ( !size )
929  {
930  break;
931  }
932 
933  if ( rdsize >= F_SECTOR_SIZE - gl_file.relpos )
934  {
935  rdsize = (unsigned long)( F_SECTOR_SIZE - gl_file.relpos );
936  }
937 
938  psp_memcpy( buffer, gl_sector + gl_file.relpos, rdsize ); /*always less than 512*/
939 
940  buffer += rdsize;
941  gl_file.relpos += rdsize;
942  size -= rdsize;
943  retsize += rdsize;
944  }
945 
946  return retsize / _size_st;
947 } /* fn_read */
948 
949 
950 /****************************************************************************
951  *
952  * fn_write
953  *
954  * write data into file
955  *
956  * INPUTS
957  *
958  * buf - where the store data
959  * size - size of items to be read
960  * size_t - number of items need to be read
961  * filehandle - file where to read from
962  *
963  * RETURNS
964  *
965  * with the number of read bytes
966  *
967  ***************************************************************************/
968 
969 long fn_write ( const void * buf, long size, long _size_st, F_FILE * f )
970 {
971  char * buffer = (char *)buf;
972  long retsize;
973  long ret = 0;
974 
975  if ( !f )
976  {
977  return 0;
978  }
979 
980  if ( ( gl_file.mode & ( F_FILE_WR | F_FILE_A | F_FILE_RDP | F_FILE_WRP | F_FILE_AP ) ) == 0 )
981  {
982  return 0;
983  }
984 
985  retsize = size;
986  size *= _size_st;
987  _size_st = retsize;
988  retsize = 0;
989 
990  if ( size == 0 )
991  {
992  return 0;
993  }
994 
995  if ( _f_getvolume() )
996  {
997  return 0; /*can't write*/
998  }
999 
1000  if ( ( gl_file.mode ) & ( F_FILE_A | F_FILE_AP ) )
1001  {
1002  if ( _f_fseek( (long)gl_file.filesize ) )
1003  {
1005  return 0;
1006  }
1007  }
1008 
1009  if ( gl_file.startcluster == 0 )
1010  {
1011  if ( _f_stepnextsector() )
1012  {
1014  return 0;
1015  }
1016  }
1017  else
1018  {
1019  if ( _f_getcurrsector() )
1020  {
1022  return 0;
1023  }
1024  }
1025 
1026  for( ; ; )
1027  {
1028  unsigned long wrsize = (unsigned long)size;
1029 
1030  if ( gl_file.relpos == F_SECTOR_SIZE )
1031  { /*now full*/
1032  if ( gl_file.modified )
1033  {
1035  {
1037  if ( _f_updatefileentry( 0 ) == 0 )
1038  {
1039  return retsize;
1040  }
1041  else
1042  {
1043  return 0;
1044  }
1045  }
1046 
1047  gl_file.modified = 0;
1048  }
1049 
1050  if ( _f_stepnextsector() )
1051  {
1053  if ( _f_updatefileentry( 0 ) == 0 )
1054  {
1055  return retsize;
1056  }
1057  else
1058  {
1059  return 0;
1060  }
1061  }
1062 
1064  gl_file.relpos = 0;
1065 
1066  if ( wrsize && ( wrsize < F_SECTOR_SIZE ) )
1067  {
1068  ret = _f_getcurrsector();
1069 
1070  if ( ret )
1071  {
1072  if ( ret != F_ERR_EOF )
1073  {
1074  gl_file.mode = F_FILE_CLOSE; /*no more read allowed*/
1075  return retsize;
1076  }
1077  }
1078  }
1079  }
1080 
1081  if ( !size )
1082  {
1083  break;
1084  }
1085 
1086  if ( wrsize >= F_SECTOR_SIZE - gl_file.relpos )
1087  {
1088  wrsize = (unsigned long)( F_SECTOR_SIZE - gl_file.relpos );
1089  }
1090 
1091 
1092  psp_memcpy( gl_sector + gl_file.relpos, buffer, wrsize );
1093  gl_file.modified = 1; /*sector is modified*/
1094 
1095  buffer += wrsize;
1096  gl_file.relpos += wrsize;
1097  size -= wrsize;
1098  retsize += wrsize;
1099 
1101  {
1103  }
1104  }
1105  return retsize / _size_st;
1106 } /* fn_write */
1107 
1108 
1109 
1110 /****************************************************************************
1111  *
1112  * fn_seek
1113  *
1114  * moves position into given offset in given file
1115  *
1116  * INPUTS
1117  *
1118  * filehandle - F_FILE structure which file position needed to be modified
1119  * offset - relative position
1120  * whence - where to calculate position (F_SEEK_SET,F_SEEK_CUR,F_SEEK_END)
1121  *
1122  * RETURNS
1123  *
1124  * 0 - if successfully
1125  * other - if any error
1126  *
1127  ***************************************************************************/
1128 
1129 
1130 unsigned char fn_seek ( F_FILE * f, long offset, unsigned char whence )
1131 {
1132  unsigned char ret;
1133 
1134  if ( !f )
1135  {
1136  return F_ERR_NOTOPEN;
1137  }
1138 
1139  if ( ( gl_file.mode & ( F_FILE_RD | F_FILE_WR | F_FILE_A | F_FILE_RDP | F_FILE_WRP | F_FILE_AP ) ) == 0 )
1140  {
1141  return F_ERR_NOTOPEN;
1142  }
1143 
1144  ret = _f_getvolume();
1145  if ( ret )
1146  {
1147  return ret;
1148  }
1149 
1150  if ( whence == F_SEEK_CUR )
1151  {
1152  return _f_fseek( (long)( gl_file.abspos + gl_file.relpos + offset ) );
1153  }
1154  else if ( whence == F_SEEK_END )
1155  {
1156  return _f_fseek( (long)( gl_file.filesize + offset ) );
1157  }
1158  else if ( whence == F_SEEK_SET )
1159  {
1160  return _f_fseek( offset );
1161  }
1162 
1163  return F_ERR_NOTUSEABLE;
1164 } /* fn_seek */
1165 
1166 
1167 
1168 /****************************************************************************
1169  *
1170  * fn_tell
1171  *
1172  * Tells the current position of opened file
1173  *
1174  * INPUTS
1175  *
1176  * filehandle - which file needs the position
1177  *
1178  * RETURNS
1179  *
1180  * position in the file from start
1181  *
1182  ***************************************************************************/
1183 
1184 long fn_tell ( F_FILE * f )
1185 {
1186  if ( !f )
1187  {
1188  return 0;
1189  }
1190 
1191  if ( ( gl_file.mode & ( F_FILE_RD | F_FILE_WR | F_FILE_A | F_FILE_RDP | F_FILE_WRP | F_FILE_AP ) ) == 0 )
1192  {
1193  return 0;
1194  }
1195 
1196  return (long)( gl_file.abspos + gl_file.relpos );
1197 }
1198 
1199 
1200 
1201 /****************************************************************************
1202  *
1203  * fn_eof
1204  *
1205  * Tells if the current position is end of file or not
1206  *
1207  * INPUTS
1208  *
1209  * filehandle - which file needs the checking
1210  *
1211  * RETURNS
1212  *
1213  * 0 - if not EOF
1214  * other - if EOF or invalid file handle
1215  *
1216  ***************************************************************************/
1217 
1218 unsigned char fn_eof ( F_FILE * f )
1219 {
1220  if ( !f )
1221  {
1222  return F_ERR_NOTOPEN; /*if error*/
1223  }
1224 
1226  {
1227  return 0;
1228  }
1229 
1230  return F_ERR_EOF; /*EOF*/
1231 }
1232 
1233 
1234 
1235 
1236 /****************************************************************************
1237  *
1238  * fn_rewind
1239  *
1240  * set the fileposition in the opened file to the begining
1241  *
1242  * INPUTS
1243  *
1244  * filehandle - which file needs to be rewinded
1245  *
1246  * RETURNS
1247  *
1248  * error code or zero if successful
1249  *
1250  ***************************************************************************/
1251 
1252 unsigned char fn_rewind ( F_FILE * filehandle )
1253 {
1254  return fn_seek( filehandle, 0L, F_SEEK_SET );
1255 }
1256 
1257 
1258 
1259 /****************************************************************************
1260  *
1261  * fn_putc
1262  *
1263  * write a character into file
1264  *
1265  * INPUTS
1266  *
1267  * ch - what to write into file
1268  * filehandle - file where to write
1269  *
1270  * RETURNS
1271  *
1272  * with the number of written bytes (1-success, 0-not successfully)
1273  *
1274  ***************************************************************************/
1275 
1276 int fn_putc ( int ch, F_FILE * filehandle )
1277 {
1278  unsigned char tmpch = (unsigned char)ch;
1279 
1280  if ( fn_write( &tmpch, 1, 1, filehandle ) )
1281  {
1282  return ch;
1283  }
1284  else
1285  {
1286  return -1;
1287  }
1288 }
1289 
1290 
1291 
1292 /****************************************************************************
1293  *
1294  * fn_getc
1295  *
1296  * get a character from file
1297  *
1298  * INPUTS
1299  *
1300  * filehandle - file where to read from
1301  *
1302  * RETURNS
1303  *
1304  * with the read character or -1 if read was not successfully
1305  *
1306  ***************************************************************************/
1307 int fn_getc ( F_FILE * filehandle )
1308 {
1309  unsigned char ch;
1310 
1311  if ( !fn_read( &ch, 1, 1, filehandle ) )
1312  {
1313  return -1;
1314  }
1315 
1316  return (int)ch;
1317 }
1318 
1319 
1320 
1321 /****************************************************************************
1322  *
1323  * fn_delete
1324  *
1325  * delete a file
1326  *
1327  * INPUTS
1328  *
1329  * filename - file which wanted to be deleted (with or without path)
1330  *
1331  * RETURNS
1332  *
1333  * error code or zero if successful
1334  *
1335  ***************************************************************************/
1336 unsigned char fn_delete ( const char * filename )
1337 {
1338  F_POS pos;
1339  F_DIRENTRY * de;
1340  F_NAME fsname;
1341  unsigned char ret;
1342 
1343  if ( _f_setfsname( filename, &fsname ) )
1344  {
1345  return F_ERR_INVALIDNAME; /*invalid name*/
1346  }
1347 
1348  if ( _f_checknamewc( fsname.filename, fsname.fileext ) )
1349  {
1350  return F_ERR_INVALIDNAME; /*invalid name*/
1351  }
1352 
1353  if ( fsname.filename[0] == '.' )
1354  {
1355  return F_ERR_NOTFOUND;
1356  }
1357 
1358  ret = _f_getvolume();
1359  if ( ret )
1360  {
1361  return ret;
1362  }
1363 
1364  if ( !( _f_findpath( &fsname, &pos ) ) )
1365  {
1366  return F_ERR_INVALIDDIR;
1367  }
1368 
1369  if ( !_f_findfilewc( fsname.filename, fsname.fileext, &pos, &de, 0 ) )
1370  {
1371  return F_ERR_NOTFOUND;
1372  }
1373 
1374  if ( de->attr & F_ATTR_DIR )
1375  {
1376  return F_ERR_INVALIDDIR; /*directory*/
1377  }
1378 
1379  if ( de->attr & F_ATTR_READONLY )
1380  {
1381  return F_ERR_ACCESSDENIED; /*readonly*/
1382  }
1383 
1384  if ( ( gl_file.mode != F_FILE_CLOSE ) && ( gl_file.dirpos.sector == pos.sector ) && ( gl_file.dirpos.pos == pos.pos ) )
1385  {
1386  return F_ERR_LOCKED;
1387  }
1388 
1389  de->name[0] = (unsigned char)0xe5; /*removes it*/
1390  ret = _f_writeglsector( (unsigned long)-1 );
1391  if ( ret )
1392  {
1393  return ret;
1394  }
1395 
1396  ret = _f_removechain( _f_getdecluster( de ) );
1397 
1398  #if F_FILE_CHANGED_EVENT
1399  if ( f_filechangedevent && !ret )
1400  {
1401  ST_FILE_CHANGED fc;
1402  fc.action = FACTION_REMOVED;
1403  fc.flags = FFLAGS_FILE_NAME;
1404 
1405  if ( !_f_createfullname( fc.filename, sizeof( fc.filename ), fsname.path, fsname.filename, fsname.fileext ) )
1406  {
1407  f_filechangedevent( &fc );
1408  }
1409  }
1410 
1411  #endif
1412 
1413  return ret;
1414 } /* fn_delete */
1415 
1416 
1417 
1418 
1419 /****************************************************************************
1420  *
1421  * _f_seteof
1422  *
1423  * Set end of file
1424  *
1425  * INPUT: f - file pointer
1426  * filesize - required new size
1427  * RETURN: F_NO_ERROR - on success
1428  * other if error
1429  *
1430  ***************************************************************************/
1431 unsigned char _f_seteof ( F_FILE * f, long filesize )
1432 {
1433  unsigned char rc = F_NO_ERROR;
1434 
1435  if ( !f )
1436  {
1437  return F_ERR_NOTOPEN; /*if error*/
1438  }
1439 
1440  if ( ( unsigned long) filesize < gl_file.filesize )
1441  {
1442  rc = _f_fseek( filesize );
1443  if ( rc == F_NO_ERROR )
1444  {
1445  unsigned long cluster;
1446  rc = _f_getclustervalue( gl_file.pos.cluster, &cluster );
1447  if ( rc == F_NO_ERROR )
1448  {
1449  if ( cluster != F_CLUSTER_LAST )
1450  {
1451  rc = _f_removechain( cluster );
1452  if ( rc )
1453  {
1454  return rc;
1455  }
1456 
1458  if ( rc )
1459  {
1460  return rc;
1461  }
1462 
1463  rc = _f_writefatsector();
1464  if ( rc )
1465  {
1466  return rc;
1467  }
1468  }
1469 
1470  gl_file.filesize = (unsigned long)filesize;
1471  }
1472  }
1473  }
1474  else if ( (unsigned long) filesize > gl_file.filesize )
1475  {
1476  rc = _f_fseek( filesize );
1477  }
1478 
1479  return rc;
1480 } /* _f_seteof */
1481 
1482 
1483 /****************************************************************************
1484  *
1485  * fn_seteof
1486  *
1487  * Set end of file
1488  *
1489  * INPUT: f - file pointer
1490  * filesize - required new size
1491  * RETURN: F_NO_ERROR - on success
1492  * other if error
1493  *
1494  ***************************************************************************/
1495 unsigned char fn_seteof ( F_FILE * f )
1496 {
1497  unsigned char rc = F_NO_ERROR;
1498 
1499  rc = _f_seteof( f, ( gl_file.abspos + gl_file.relpos ) );
1500 
1501  return rc;
1502 } /* fn_seteof */
1503 
1504 
1505 
1506 
1507 /****************************************************************************
1508  *
1509  * fn_truncate
1510  *
1511  * Open a file and set end of file
1512  *
1513  * INPUT: filename - name of the file
1514  * filesize - required new size
1515  * RETURN: NULL on error, otherwise file pointer
1516  *
1517  ***************************************************************************/
1518 F_FILE * fn_truncate ( const char * filename, long filesize )
1519 {
1520  F_FILE * f = fn_open( filename, "r+" );
1521  unsigned char rc;
1522 
1523  if ( f != NULL )
1524  {
1525  rc = _f_fseek( (long)gl_file.filesize );
1526  if ( rc == F_NO_ERROR )
1527  {
1528  rc = _f_seteof( f, filesize );
1529  }
1530 
1531  if ( rc )
1532  {
1533  fn_close( f );
1534  f = NULL;
1535  }
1536  }
1537 
1538  return f;
1539 } /* fn_truncate */
1540 
unsigned char _f_removechain(unsigned long cluster)
Definition: fat.c:564
long fn_filelength(const char *filename)
Definition: file.c:75
int fn_putc(int ch, F_FILE *filehandle)
Definition: file.c:1276
unsigned char fn_eof(F_FILE *f)
Definition: file.c:1218
unsigned char _f_writefatsector(void)
Definition: fat.c:64
unsigned long abspos
Definition: fat_sl.h:109
#define F_FILE_A
Definition: file.h:56
unsigned long _f_getdecluster(F_DIRENTRY *de)
Definition: dir.c:305
F_FILE gl_file
Definition: volume.c:61
unsigned long fatsector
Definition: volume.h:84
void _f_setlong(void *, unsigned long)
Definition: util.c:144
unsigned long pos
Definition: fat_sl.h:70
Definition: fat_sl.h:58
unsigned char name[F_MAXNAME]
Definition: dir.h:77
#define F_ATTR_READONLY
Definition: fat_sl.h:95
void f_igettimedate(unsigned short *time, unsigned short *date)
Definition: util.c:298
#define F_FILE_AP
Definition: file.h:59
unsigned char fn_delete(const char *filename)
Definition: file.c:1336
F_BOOTRECORD bootrecord
Definition: volume.h:78
unsigned long startcluster
Definition: fat_sl.h:111
#define psp_memcpy(d, s, l)
Definition: psp_string.h:52
unsigned char cdate[2]
Definition: dir.h:89
unsigned char filesize[4]
Definition: dir.h:91
unsigned char _f_getvolume(void)
Definition: volume.c:719
unsigned char sector_per_cluster
Definition: volume.h:58
unsigned char _f_checknamewc(const char *, const char *)
Definition: util_sfn.c:145
unsigned char _f_alloccluster(unsigned long *pcluster)
Definition: fat.c:512
void _f_clustertopos(unsigned long cluster, F_POS *pos)
Definition: fat.c:431
unsigned long _f_getlong(void *)
Definition: util.c:116
F_POS dirpos
Definition: fat_sl.h:117
unsigned char fn_seek(F_FILE *f, long offset, unsigned char whence)
Definition: file.c:1130
unsigned long relpos
Definition: fat_sl.h:112
unsigned char _f_getcurrsector(void)
Definition: fat.c:471
unsigned char fn_close(F_FILE *f)
Definition: file.c:704
unsigned long sectorend
Definition: fat_sl.h:69
unsigned char _f_findpath(F_NAME *fsname, F_POS *pos)
Definition: dir.c:365
#define F_ATTR_DIR
Definition: fat_sl.h:91
unsigned char _f_seteof(F_FILE *f, long filesize)
Definition: file.c:1431
unsigned char _f_writeglsector(unsigned long sector)
Definition: drv.c:96
long fn_write(const void *buf, long size, long _size_st, F_FILE *f)
Definition: file.c:969
unsigned char lastaccessdate[2]
Definition: dir.h:85
unsigned char _f_findfilewc(char *name, char *ext, F_POS *pos, F_DIRENTRY **pde, unsigned char wc)
Definition: dir.c:78
void _f_setdecluster(F_DIRENTRY *de, unsigned long cluster)
Definition: dir.c:333
unsigned char mode
Definition: fat_sl.h:114
unsigned char ctime[2]
Definition: dir.h:88
#define F_ATTR_ARC
Definition: fat_sl.h:90
Definition: dir.h:75
void _f_setword(void *, unsigned short)
Definition: util.c:92
unsigned char attr
Definition: dir.h:79
unsigned char mediatype
Definition: volume.h:89
unsigned char modified
Definition: fat_sl.h:113
#define F_SECTOR_SIZE
Definition: config_fat_sl.h:57
#define F_FILE_CLOSE
Definition: file.h:53
#define psp_memset(d, c, l)
Definition: psp_string.h:54
Definition: fat_sl.h:65
long fn_tell(F_FILE *f)
Definition: file.c:1184
unsigned long sector
Definition: fat_sl.h:68
F_POS pos
Definition: fat_sl.h:116
#define F_FILE_WR
Definition: file.h:55
unsigned long filesize
Definition: fat_sl.h:110
char path[F_MAXPATH]
Definition: fat_sl.h:60
unsigned char crtdate[2]
Definition: dir.h:84
F_VOLUME gl_volume
Definition: volume.c:60
unsigned char fn_flush(F_FILE *f)
Definition: file.c:796
unsigned char _f_setfsname(const char *, F_NAME *)
Definition: util_sfn.c:286
#define F_CLUSTER_LAST
Definition: fat_sl.h:100
long fn_read(void *buf, long size, long _size_st, F_FILE *f)
Definition: file.c:851
unsigned char fn_rewind(F_FILE *filehandle)
Definition: file.c:1252
unsigned char clusterhi[2]
Definition: dir.h:87
int _f_createfullname(char *buffer, int buffersize, char *path, char *filename, char *fileext)
Definition: util_sfn.c:437
unsigned char _f_readglsector(unsigned long sector)
Definition: drv.c:178
#define F_FILE_WRP
Definition: file.h:58
char filename[F_MAXNAME]
Definition: fat_sl.h:61
char gl_sector[F_SECTOR_SIZE]
Definition: volume.c:62
unsigned char crttime[2]
Definition: dir.h:83
unsigned char _f_addentry(F_NAME *fsname, F_POS *pos, F_DIRENTRY **pde)
Definition: dir.c:768
#define F_CLUSTER_RESERVED
Definition: fat_sl.h:98
unsigned char _f_getclustervalue(unsigned long cluster, unsigned long *pvalue)
Definition: fat.c:302
F_FILE * fn_truncate(const char *filename, long filesize)
Definition: file.c:1518
Definition: fat_sl.h:107
F_FILE * fn_open(const char *filename, const char *mode)
Definition: file.c:421
#define F_FILE_RD
Definition: file.h:54
int fn_getc(F_FILE *filehandle)
Definition: file.c:1307
unsigned char clusterlo[2]
Definition: dir.h:90
unsigned long cluster
Definition: fat_sl.h:67
char fileext[F_MAXEXT]
Definition: fat_sl.h:62
#define F_FILE_RDP
Definition: file.h:57
unsigned char fn_seteof(F_FILE *f)
Definition: file.c:1495
unsigned char _f_setclustervalue(unsigned long cluster, unsigned long _tdata)
Definition: fat.c:163