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
dir.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 "dir.h"
45 #include "util.h"
46 #include "volume.h"
47 #include "drv.h"
48 #include "fat.h"
49 #include "file.h"
50 
51 #include "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 
57 /****************************************************************************
58  *
59  * _f_findfilewc
60  *
61  * internal function to finding file in directory entry with or without
62  * wildcard
63  *
64  * INPUTS
65  *
66  * name - filename
67  * ext - fileextension
68  * pos - where to start searching, and contains current position
69  * pde - store back the directory entry pointer
70  * wc - wildcard checking?
71  *
72  * RETURNS
73  *
74  * 0 - if file was not found
75  * 1 - if file was found
76  *
77  ***************************************************************************/
78 unsigned char _f_findfilewc ( char * name, char * ext, F_POS * pos, F_DIRENTRY * * pde, unsigned char wc )
79 {
80  while ( pos->cluster < F_CLUSTER_RESERVED )
81  {
82  for ( ; pos->sector < pos->sectorend ; pos->sector++ )
83  {
84  F_DIRENTRY * de = (F_DIRENTRY *)( gl_sector + sizeof( F_DIRENTRY ) * pos->pos );
85 
86  if ( _f_readglsector( pos->sector ) )
87  {
88  return 0; /*not found*/
89  }
90 
91  for ( ; pos->pos < F_SECTOR_SIZE / sizeof( F_DIRENTRY ) ; de++, pos->pos++ )
92  {
93  unsigned char b, ok;
94 
95  if ( !de->name[0] )
96  {
97  return 0; /*empty*/
98  }
99 
100  if ( (unsigned char)( de->name[0] ) == 0xe5 )
101  {
102  continue; /*deleted*/
103  }
104 
105  if ( de->attr & F_ATTR_VOLUME )
106  {
107  continue;
108  }
109 
110  if ( wc )
111  {
112  for ( b = 0, ok = 1 ; b < sizeof( de->name ) ; b++ )
113  {
114  if ( name[b] == '*' )
115  {
116  break;
117  }
118 
119  if ( name[b] != '?' )
120  {
121  if ( de->name[b] != name[b] )
122  {
123  ok = 0;
124  break;
125  }
126  }
127  }
128 
129  if ( ok )
130  {
131  for ( b = 0, ok = 1 ; b < sizeof( de->ext ) ; b++ )
132  {
133  if ( ext[b] == '*' )
134  {
135  if ( pde )
136  {
137  *pde = de;
138  }
139 
140  return 1;
141  }
142 
143  if ( ext[b] != '?' )
144  {
145  if ( de->ext[b] != ext[b] )
146  {
147  ok = 0;
148  break;
149  }
150  }
151  }
152 
153  if ( ok )
154  {
155  if ( pde )
156  {
157  *pde = de;
158  }
159 
160  return 1;
161  }
162  }
163  }
164  else
165  {
166  for ( b = 0, ok = 1 ; b < sizeof( de->name ) ; b++ )
167  {
168  if ( de->name[b] != name[b] )
169  {
170  ok = 0;
171  break;
172  }
173  }
174 
175  if ( ok )
176  {
177  for ( b = 0, ok = 1 ; b < sizeof( de->ext ) ; b++ )
178  {
179  if ( de->ext[b] != ext[b] )
180  {
181  ok = 0;
182  break;
183  }
184  }
185 
186  if ( ok )
187  {
188  if ( pde )
189  {
190  *pde = de;
191  }
192 
193  return 1;
194  }
195  }
196  }
197  }
198 
199  pos->pos = 0;
200  }
201 
202  if ( !pos->cluster )
203  {
205  {
207  }
208  else
209  {
210  return 0;
211  }
212  }
213 
214  {
215  unsigned long nextcluster;
216  gl_volume.fatsector = (unsigned long)-1;
217  if ( _f_getclustervalue( pos->cluster, &nextcluster ) )
218  {
219  return 0; /*not found*/
220  }
221 
222  if ( nextcluster >= F_CLUSTER_RESERVED )
223  {
224  return 0; /*eof*/
225  }
226 
227  _f_clustertopos( nextcluster, pos );
228  }
229  } /* _f_findfilewc */
230 
231  return 0;
232 }
233 
234 
235 /****************************************************************************
236  *
237  * _f_getfilename
238  *
239  * create a complete filename from name and extension
240  *
241  * INPUTS
242  *
243  * dest - where to store filename
244  * name - name of the file
245  * ext - extension of the file
246  *
247  ***************************************************************************/
248 static void _f_getfilename ( char * dest, char * name, char * ext )
249 {
250  unsigned char a, len;
251 
252  for ( len = a = F_MAXNAME ; a ; a--, len-- )
253  {
254  if ( name[a - 1] != ' ' )
255  {
256  break;
257  }
258  }
259 
260  for ( a = 0 ; a < len ; a++ )
261  {
262  *dest++ = *name++;
263  }
264 
265 
266  for ( len = a = F_MAXEXT ; a ; a--, len-- )
267  {
268  if ( ext[a - 1] != ' ' )
269  {
270  break;
271  }
272  }
273 
274  if ( len )
275  {
276  *dest++ = '.';
277  }
278 
279  for ( a = 0 ; a < len ; a++ )
280  {
281  *dest++ = *ext++;
282  }
283 
284  *dest = 0; /*terminateit*/
285 } /* _f_getfilename */
286 
287 
288 
289 
290 /****************************************************************************
291  *
292  * _f_getdecluster
293  *
294  * get a directory entry structure start cluster value
295  *
296  * INPUTS
297  *
298  * de - directory entry
299  *
300  * RETURNS
301  *
302  * directory entry cluster value
303  *
304  ***************************************************************************/
305 unsigned long _f_getdecluster ( F_DIRENTRY * de )
306 {
307  unsigned long cluster;
308 
310  {
311  cluster = _f_getword( &de->clusterhi );
312  cluster <<= 16;
313  cluster |= _f_getword( &de->clusterlo );
314  return cluster;
315  }
316 
317  return _f_getword( &de->clusterlo );
318 }
319 
320 
321 /****************************************************************************
322  *
323  * _f_setdecluster
324  *
325  * set a directory entry structure start cluster value
326  *
327  * INPUTS
328  *
329  * de - directory entry
330  * cluster - value of the start cluster
331  *
332  ***************************************************************************/
333 void _f_setdecluster ( F_DIRENTRY * de, unsigned long cluster )
334 {
335  _f_setword( &de->clusterlo, (unsigned short)( cluster & 0xffff ) );
337  {
338  _f_setword( &de->clusterhi, (unsigned short)( cluster >> 16 ) );
339  }
340  else
341  {
342  _f_setword( &de->clusterhi, (unsigned short)0 );
343  }
344 }
345 
346 
347 /****************************************************************************
348  *
349  * _f_findpath
350  *
351  * finding out if path is valid in F_NAME and
352  * correct path info with absolute path (removes relatives)
353  *
354  * INPUTS
355  *
356  * fsname - filled structure with path,drive
357  * pos - where to start searching, and contains current position
358  *
359  * RETURNS
360  *
361  * 0 - if path was not found or invalid
362  * 1 - if path was found
363  *
364  ***************************************************************************/
365 unsigned char _f_findpath ( F_NAME * fsname, F_POS * pos )
366 {
367  char * path = fsname->path;
368  char * mpath = path;
369  F_DIRENTRY * de;
370 
371  _f_clustertopos( 0, pos );
372 
373  for ( ; *path ; )
374  {
375  char name[F_MAXNAME];
376  char ext[F_MAXEXT];
377 
378  unsigned char len = _f_setnameext( path, name, ext );
379 
380  if ( ( pos->cluster == 0 ) && ( len == 1 ) && ( name[0] == '.' ) )
381  {
382  _f_clustertopos( 0, pos );
383  }
384  else
385  {
386  if ( !_f_findfilewc( name, ext, pos, &de, 0 ) )
387  {
388  return 0;
389  }
390 
391  if ( !( de->attr & F_ATTR_DIR ) )
392  {
393  return 0;
394  }
395 
396  _f_clustertopos( _f_getdecluster( de ), pos );
397  }
398 
399 
400  if ( name[0] == '.' )
401  {
402  if ( len == 1 )
403  {
404  path += len;
405 
406  if ( !( *path ) )
407  {
408  if ( mpath != fsname->path )
409  {
410  mpath--; /*if we are now at the top*/
411  }
412 
413  break;
414  }
415 
416  path++;
417  continue;
418  }
419 
420  if ( name[1] != '.' )
421  {
422  return 0; /*invalid name*/
423  }
424 
425  if ( len != 2 )
426  {
427  return 0; /*invalid name !*/
428  }
429 
430  path += len;
431 
432  if ( mpath == fsname->path )
433  {
434  return 0; /*we are in the top*/
435  }
436 
437  mpath--; /*no on separator*/
438  for ( ; ; )
439  {
440  if ( mpath == fsname->path )
441  {
442  break; /*we are now at the top*/
443  }
444 
445  mpath--;
446  if ( *mpath == '/' )
447  {
448  mpath++;
449  break;
450  }
451  }
452 
453  if ( !( *path ) )
454  {
455  if ( mpath != fsname->path )
456  {
457  mpath--; /*if we are now at the top*/
458  }
459 
460  break;
461  }
462 
463  path++;
464  continue;
465  }
466  else
467  {
468  if ( path == mpath ) /*if no was dots just step*/
469  {
470  path += len;
471  mpath += len;
472  }
473  else
474  {
475  unsigned char a;
476  for ( a = 0 ; a < len ; a++ )
477  {
478  *mpath++ = *path++; /*copy if in different pos*/
479  }
480  }
481  }
482 
483  if ( !( *path ) )
484  {
485  break;
486  }
487 
488  path++;
489  *mpath++ = '/'; /*add separator*/
490  }
491 
492  *mpath = 0; /*terminate it*/
493  return 1;
494 } /* _f_findpath */
495 
496 
497 /****************************************************************************
498  *
499  * fn_getcwd
500  *
501  * getting a current working directory of current drive
502  *
503  * INPUTS
504  *
505  * buffer - where to store current working folder
506  * maxlen - buffer length (possible size is F_MAXPATH)
507  *
508  * RETURNS
509  *
510  * error code or zero if successful
511  *
512  ***************************************************************************/
513 unsigned char fn_getcwd ( char * buffer, unsigned char maxlen, char root )
514 {
515  unsigned char a;
516 
517  if ( !maxlen )
518  {
519  return F_NO_ERROR;
520  }
521 
522  maxlen--; /*need for termination*/
523  if ( root && maxlen )
524  {
525  *buffer++ = '/';
526  maxlen--;
527  }
528 
529  for ( a = 0 ; a < maxlen ; a++ )
530  {
531  char ch = gl_volume.cwd[a];
532  buffer[a] = ch;
533  if ( !ch )
534  {
535  break;
536  }
537  }
538 
539  buffer[a] = 0; /*add terminator at the end*/
540 
541  return F_NO_ERROR;
542 } /* fn_getcwd */
543 
544 
545 
546 /****************************************************************************
547  *
548  * fn_findfirst
549  *
550  * find a file(s) or directory(s) in directory
551  *
552  * INPUTS
553  *
554  * filename - filename (with or without wildcards)
555  * find - where to store found file information
556  *
557  * RETURNS
558  *
559  * error code or zero if successful
560  *
561  ***************************************************************************/
562 unsigned char fn_findfirst ( const char * filename, F_FIND * find )
563 {
564  unsigned char ret;
565 
566  if ( _f_setfsname( filename, &find->findfsname ) )
567  {
568  return F_ERR_INVALIDNAME; /*invalid name*/
569  }
570 
571  if ( _f_checkname( find->findfsname.filename, find->findfsname.fileext ) )
572  {
573  return F_ERR_INVALIDNAME; /*invalid name, wildcard is ok*/
574  }
575 
576 
577  ret = _f_getvolume();
578  if ( ret )
579  {
580  return ret;
581  }
582 
583  if ( !_f_findpath( &find->findfsname, &find->pos ) )
584  {
585  return F_ERR_INVALIDDIR; /*search for path*/
586  }
587 
588  return fn_findnext( find );
589 } /* fn_findfirst */
590 
591 
592 
593 /****************************************************************************
594  *
595  * fn_findnext
596  *
597  * find further file(s) or directory(s) in directory
598  *
599  * INPUTS
600  *
601  * find - where to store found file information (findfirst should call 1st)
602  *
603  * RETURNS
604  *
605  * error code or zero if successful
606  *
607  ***************************************************************************/
608 unsigned char fn_findnext ( F_FIND * find )
609 {
610  F_DIRENTRY * de;
611  unsigned char a;
612  unsigned char ret;
613 
614  ret = _f_getvolume();
615  if ( ret )
616  {
617  return ret;
618  }
619 
620  if ( !_f_findfilewc( find->findfsname.filename, find->findfsname.fileext, &find->pos, &de, 1 ) )
621  {
622  return F_ERR_NOTFOUND;
623  }
624 
625  for ( a = 0 ; a < F_MAXNAME ; a++ )
626  {
627  find->name[a] = de->name[a];
628  }
629 
630  for ( a = 0 ; a < F_MAXEXT ; a++ )
631  {
632  find->ext[a] = de->ext[a];
633  }
634 
635  _f_getfilename( find->filename, (char *)de->name, (char *)de->ext );
636 
637  find->attr = de->attr;
638  find->cdate = _f_getword( &de->cdate );
639  find->ctime = _f_getword( &de->ctime );
640  find->filesize = (long)_f_getlong( &de->filesize );
641  find->cluster = _f_getdecluster( de );
642  find->pos.pos++; /*goto next position*/
643 
644  return 0;
645 } /* fn_findnext */
646 
647 
648 
649 /****************************************************************************
650  *
651  * fn_chdir
652  *
653  * change current working directory
654  *
655  * INPUTS
656  *
657  * dirname - new working directory name
658  *
659  * RETURNS
660  *
661  * 0 - if successfully
662  * other - if any error
663  *
664  ***************************************************************************/
665 unsigned char fn_chdir ( const char * dirname )
666 {
667  F_POS pos;
668  F_NAME fsname;
669  unsigned char len;
670  unsigned char a;
671  unsigned char ret;
672 
673  ret = _f_setfsname( dirname, &fsname );
674 
675  if ( ret == 1 )
676  {
677  return F_ERR_INVALIDNAME; /*invalid name*/
678  }
679 
680  if ( _f_checknamewc( fsname.filename, fsname.fileext ) )
681  {
682  return F_ERR_INVALIDNAME; /*invalid name*/
683  }
684 
685  ret = _f_getvolume();
686  if ( ret )
687  {
688  return ret;
689  }
690 
691  for ( len = 0 ; fsname.path[len] ; )
692  {
693  len++;
694  }
695 
696  if ( len && ( ( fsname.filename[0] != 32 ) || ( fsname.fileext[0] != 32 ) ) )
697  {
698  fsname.path[len++] = '/';
699  }
700 
701  _f_getfilename( fsname.path + len, fsname.filename, fsname.fileext );
702 
703  if ( !( _f_findpath( &fsname, &pos ) ) )
704  {
705  return F_ERR_NOTFOUND;
706  }
707 
708  for ( a = 0 ; a < F_MAXPATH ; a++ )
709  {
710  gl_volume.cwd[a] = fsname.path[a];
711  }
712 
713  return F_NO_ERROR;
714 } /* fn_chdir */
715 
716 
717 
718 /****************************************************************************
719  *
720  * _f_initentry
721  *
722  * init directory entry, this function is called if a new entry is coming
723  *
724  * INPUTS
725  *
726  * de - directory entry which needs to be initialized
727  * name - fil ename (8)
728  * ext - file extension (3)
729  *
730  ***************************************************************************/
731 static void _f_initentry ( F_DIRENTRY * de, char * name, char * ext )
732 {
733  unsigned short date;
734  unsigned short time;
735 
736  psp_memset( de, 0, sizeof( F_DIRENTRY ) ); /*reset all entries*/
737 
738  psp_memcpy( de->name, name, sizeof( de->name ) );
739  psp_memcpy( de->ext, ext, sizeof( de->ext ) );
740 
741  f_igettimedate( &time, &date );
742  _f_setword( &de->cdate, date ); /*if there is realtime clock then creation date could be set from*/
743  _f_setword( &de->ctime, time ); /*if there is realtime clock then creation time could be set from*/
744 }
745 
746 
747 
748 
749 
750 /****************************************************************************
751  *
752  * _f_addentry
753  *
754  * Add a new directory entry into driectory list
755  *
756  * INPUTS
757  *
758  * fs_name - filled structure what to add into directory list
759  * pos - where directory cluster chains starts
760  * pde - F_DIRENTRY pointer where to store the entry where it was added
761  *
762  * RETURNS
763  *
764  * 0 - if successfully added
765  * other - if any error (see FS_xxx errorcodes)
766  *
767  ***************************************************************************/
768 unsigned char _f_addentry ( F_NAME * fsname, F_POS * pos, F_DIRENTRY * * pde )
769 {
770  unsigned char ret;
771  unsigned short date;
772  unsigned short time;
773 
774  if ( !fsname->filename[0] )
775  {
776  return F_ERR_INVALIDNAME;
777  }
778 
779  if ( fsname->filename[0] == '.' )
780  {
781  return F_ERR_INVALIDNAME;
782  }
783 
784  while ( pos->cluster < F_CLUSTER_RESERVED )
785  {
786  for ( ; pos->sector < pos->sectorend ; pos->sector++ )
787  {
788  F_DIRENTRY * de = (F_DIRENTRY *)( gl_sector + sizeof( F_DIRENTRY ) * pos->pos );
789 
790  ret = _f_readglsector( pos->sector );
791  if ( ret )
792  {
793  return ret;
794  }
795 
796  for ( ; pos->pos < F_SECTOR_SIZE / sizeof( F_DIRENTRY ) ; de++, pos->pos++ )
797  {
798  if ( ( !de->name[0] ) || ( (unsigned char)( de->name[0] ) == 0xe5 ) )
799  {
800  _f_initentry( de, fsname->filename, fsname->fileext );
802  {
803  f_igettimedate( &time, &date );
804  _f_setword( &de->crtdate, date ); /*if there is realtime clock then creation date could be set from*/
805  _f_setword( &de->crttime, time ); /*if there is realtime clock then creation time could be set from*/
806  _f_setword( &de->lastaccessdate, date ); /*if there is realtime clock then creation date could be set from*/
807  }
808 
809  if ( pde )
810  {
811  *pde = de;
812  }
813 
814  return F_NO_ERROR;
815  }
816  }
817 
818  pos->pos = 0;
819  }
820 
821  if ( !pos->cluster )
822  {
824  {
826  }
827  else
828  {
829  return F_ERR_NOMOREENTRY;
830  }
831  }
832 
833  {
834  unsigned long cluster;
835 
836  gl_volume.fatsector = (unsigned long)-1;
837  ret = _f_getclustervalue( pos->cluster, &cluster ); /*try to get next cluster*/
838  if ( ret )
839  {
840  return ret;
841  }
842 
843  if ( cluster < F_CLUSTER_RESERVED )
844  {
845  _f_clustertopos( cluster, pos );
846  }
847  else
848  {
849  ret = _f_alloccluster( &cluster ); /*get a new one*/
850  if ( ret )
851  {
852  return ret;
853  }
854 
855  if ( cluster < F_CLUSTER_RESERVED )
856  {
857  if ( gl_file.mode != F_FILE_CLOSE )
858  {
859  return F_ERR_NOMOREENTRY;
860  }
861 
862  _f_clustertopos( cluster, &gl_file.pos );
863 
865  if ( ret )
866  {
867  return ret;
868  }
869 
871  if ( ret )
872  {
873  return ret;
874  }
875 
876  ret = _f_writefatsector();
877  if ( ret )
878  {
879  return ret;
880  }
881 
882  gl_volume.fatsector = (unsigned long)-1;
884  while ( gl_file.pos.sector < gl_file.pos.sectorend )
885  {
887  if ( ret )
888  {
889  return ret;
890  }
891 
892  gl_file.pos.sector++;
893  }
894 
896  }
897  else
898  {
899  return F_ERR_NOMOREENTRY;
900  }
901  }
902  }
903  } /* _f_addentry */
904 
905  return F_ERR_NOMOREENTRY;
906 }
907 
908 
909 
910 /****************************************************************************
911  *
912  * fn_mkdir
913  *
914  * making a new directory
915  *
916  * INPUTS
917  *
918  * dirname - new directory name
919  *
920  * RETURNS
921  *
922  * error code or zero if successful
923  *
924  ***************************************************************************/
925 unsigned char fn_mkdir ( const char * dirname )
926 {
927  F_POS posdir;
928  F_POS pos;
929  F_DIRENTRY * de;
930  F_NAME fsname;
931  unsigned long cluster;
932  unsigned char ret;
933 
934  #if F_FILE_CHANGED_EVENT
935  ST_FILE_CHANGED fc;
936  #endif
937 
938  if ( _f_setfsname( dirname, &fsname ) )
939  {
940  return F_ERR_INVALIDNAME; /*invalid name*/
941  }
942 
943  if ( _f_checknamewc( fsname.filename, fsname.fileext ) )
944  {
945  return F_ERR_INVALIDNAME; /*invalid name*/
946  }
947 
948  ret = _f_getvolume();
949  if ( ret )
950  {
951  return ret;
952  }
953 
954  if ( !_f_findpath( &fsname, &posdir ) )
955  {
956  return F_ERR_INVALIDDIR;
957  }
958 
959  pos = posdir;
960 
961  if ( fsname.filename[0] == '.' )
962  {
963  return F_ERR_NOTFOUND;
964  }
965 
966  if ( _f_findfilewc( fsname.filename, fsname.fileext, &pos, &de, 0 ) )
967  {
968  return F_ERR_DUPLICATED;
969  }
970 
971  pos = posdir;
972 
973  gl_volume.fatsector = (unsigned long)-1;
974  ret = _f_alloccluster( &cluster );
975  if ( ret )
976  {
977  return ret;
978  }
979 
980  ret = _f_addentry( &fsname, &pos, &de );
981  if ( ret )
982  {
983  return ret;
984  }
985 
986  de->attr |= F_ATTR_DIR; /*set as directory*/
987 
988  #if F_FILE_CHANGED_EVENT
989  if ( f_filechangedevent )
990  {
991  fc.action = FACTION_ADDED;
992  fc.flags = FFLAGS_DIR_NAME | FFLAGS_ATTRIBUTES | FFLAGS_SIZE | FFLAGS_LAST_WRITE;
993  fc.attr = de->attr;
994  fc.ctime = _f_getword( de->ctime );
995  fc.cdate = _f_getword( de->cdate );
996  fc.filesize = _f_getlong( de->filesize );
997  }
998 
999  #endif
1000 
1001  if ( gl_file.mode != F_FILE_CLOSE )
1002  {
1003  return F_ERR_LOCKED;
1004  }
1005 
1006  _f_clustertopos( cluster, &gl_file.pos );
1007  _f_setdecluster( de, cluster ); /*new dir*/
1008 
1009  (void)_f_writeglsector( (unsigned long)-1 ); /*write actual directory sector*/
1010 
1011 
1012  de = (F_DIRENTRY *)gl_sector;
1013 
1014  _f_initentry( de, ". ", " " );
1015  de->attr = F_ATTR_DIR; /*set as directory*/
1016  _f_setdecluster( de, cluster ); /*current*/
1017  de++;
1018 
1019  _f_initentry( de, ".. ", " " );
1020  de->attr = F_ATTR_DIR; /*set as directory*/
1021  _f_setdecluster( de, posdir.cluster ); /*parent*/
1022  de++;
1023 
1024  psp_memset( de, 0, ( F_SECTOR_SIZE - 2 * sizeof( F_DIRENTRY ) ) );
1025 
1026 
1028  if ( ret )
1029  {
1030  return ret;
1031  }
1032 
1033  gl_file.pos.sector++;
1034  psp_memset( gl_sector, 0, ( 2 * sizeof( F_DIRENTRY ) ) );
1035  while ( gl_file.pos.sector < gl_file.pos.sectorend )
1036  {
1038  if ( ret )
1039  {
1040  return ret;
1041  }
1042 
1043  gl_file.pos.sector++;
1044  }
1045 
1046  gl_volume.fatsector = (unsigned long)-1;
1048  if ( ret )
1049  {
1050  return ret;
1051  }
1052 
1053  ret = _f_writefatsector();
1054  #if F_FILE_CHANGED_EVENT
1055  if ( f_filechangedevent && !ret )
1056  {
1057  fc.action = FACTION_ADDED;
1058  fc.flags = FFLAGS_DIR_NAME;
1059 
1060  if ( !_f_createfullname( fc.filename, sizeof( fc.filename ), fsname.path, fsname.filename, fsname.fileext ) )
1061  {
1062  f_filechangedevent( &fc );
1063  }
1064  }
1065 
1066  #endif
1067 
1068  return ret;
1069 } /* fn_mkdir */
1070 
1071 
1072 
1073 /****************************************************************************
1074  *
1075  * fn_rmdir
1076  *
1077  * Remove directory, only could be removed if empty
1078  *
1079  * INPUTS
1080  *
1081  * dirname - which directory needed to be removed
1082  *
1083  * RETURNS
1084  *
1085  * error code or zero if successful
1086  *
1087  ***************************************************************************/
1088 unsigned char fn_rmdir ( const char * dirname )
1089 {
1090  unsigned char ret;
1091  F_POS pos;
1092  F_DIRENTRY * de;
1093  F_NAME fsname;
1094  unsigned long dirsector;
1095  unsigned char a;
1096 
1097  if ( _f_setfsname( dirname, &fsname ) )
1098  {
1099  return F_ERR_INVALIDNAME; /*invalid name*/
1100  }
1101 
1102  if ( _f_checknamewc( fsname.filename, fsname.fileext ) )
1103  {
1104  return F_ERR_INVALIDNAME; /*invalid name*/
1105  }
1106 
1107  if ( fsname.filename[0] == '.' )
1108  {
1109  return F_ERR_NOTFOUND;
1110  }
1111 
1112  ret = _f_getvolume();
1113  if ( ret )
1114  {
1115  return ret;
1116  }
1117 
1118  if ( !( _f_findpath( &fsname, &pos ) ) )
1119  {
1120  return F_ERR_INVALIDDIR;
1121  }
1122 
1123  if ( !_f_findfilewc( fsname.filename, fsname.fileext, &pos, &de, 0 ) )
1124  {
1125  return F_ERR_NOTFOUND;
1126  }
1127 
1128  if ( !( de->attr & F_ATTR_DIR ) )
1129  {
1130  return F_ERR_INVALIDDIR; /*not a directory*/
1131  }
1132 
1133  dirsector = gl_volume.actsector;
1134 
1135  if ( gl_file.mode != F_FILE_CLOSE )
1136  {
1137  return F_ERR_LOCKED;
1138  }
1139 
1141 
1142  for ( ; ; )
1143  {
1144  F_DIRENTRY * de2;
1145  char ch = 0;
1146 
1147  ret = _f_getcurrsector();
1148  if ( ret == F_ERR_EOF )
1149  {
1150  break;
1151  }
1152 
1153  if ( ret )
1154  {
1155  return ret;
1156  }
1157 
1158  de2 = (F_DIRENTRY *)gl_sector;
1159  for ( a = 0 ; a < ( F_SECTOR_SIZE / sizeof( F_DIRENTRY ) ) ; a++, de2++ )
1160  {
1161  ch = de2->name[0];
1162  if ( !ch )
1163  {
1164  break;
1165  }
1166 
1167  if ( (unsigned char)ch == 0xe5 )
1168  {
1169  continue;
1170  }
1171 
1172  if ( ch == '.' )
1173  {
1174  continue;
1175  }
1176 
1177  return F_ERR_NOTEMPTY; /*something is there*/
1178  }
1179 
1180  if ( !ch )
1181  {
1182  break;
1183  }
1184 
1185  gl_file.pos.sector++;
1186  }
1187 
1188  ret = _f_readglsector( dirsector );
1189  if ( ret )
1190  {
1191  return ret;
1192  }
1193 
1194  de->name[0] = (unsigned char)0xe5;
1195 
1196  ret = _f_writeglsector( dirsector );
1197  if ( ret )
1198  {
1199  return ret;
1200  }
1201 
1202  gl_volume.fatsector = (unsigned long)-1;
1203  ret = _f_removechain( _f_getdecluster( de ) );
1204  #if F_FILE_CHANGED_EVENT
1205  if ( f_filechangedevent && !ret )
1206  {
1207  ST_FILE_CHANGED fc;
1208  fc.action = FACTION_REMOVED;
1209  fc.flags = FFLAGS_DIR_NAME;
1210 
1211  if ( !_f_createfullname( fc.filename, sizeof( fc.filename ), fsname.path, fsname.filename, fsname.fileext ) )
1212  {
1213  f_filechangedevent( &fc );
1214  }
1215  }
1216 
1217  #endif
1218  return ret;
1219 } /* fn_rmdir */
1220 
1221 
unsigned char _f_removechain(unsigned long cluster)
Definition: fat.c:564
unsigned char fn_getcwd(char *buffer, unsigned char maxlen, char root)
Definition: dir.c:513
unsigned char ext[F_MAXEXT]
Definition: dir.h:78
unsigned char _f_writefatsector(void)
Definition: fat.c:64
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
char ext[F_MAXEXT]
Definition: fat_sl.h:77
unsigned long pos
Definition: fat_sl.h:70
long filesize
Definition: fat_sl.h:84
Definition: fat_sl.h:58
unsigned long actsector
Definition: volume.h:83
unsigned char name[F_MAXNAME]
Definition: dir.h:77
#define F_ATTR_VOLUME
Definition: fat_sl.h:92
void f_igettimedate(unsigned short *time, unsigned short *date)
Definition: util.c:298
F_NAME findfsname
Definition: fat_sl.h:86
F_BOOTRECORD bootrecord
Definition: volume.h:78
#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
#define F_MAXNAME
Definition: fat_sl.h:55
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
#define F_MAXPATH
Definition: config_fat_sl.h:59
unsigned char attr
Definition: fat_sl.h:78
unsigned short ctime
Definition: fat_sl.h:80
unsigned long _f_getlong(void *)
Definition: util.c:116
char cwd[F_MAXPATH]
Definition: volume.h:88
unsigned char _f_getcurrsector(void)
Definition: fat.c:471
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 fn_mkdir(const char *dirname)
Definition: dir.c:925
unsigned char _f_writeglsector(unsigned long sector)
Definition: drv.c:96
unsigned char fn_findnext(F_FIND *find)
Definition: dir.c:608
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
char name[F_MAXNAME]
Definition: fat_sl.h:76
unsigned short _f_getword(void *)
Definition: util.c:68
unsigned char _f_checkname(char *, char *)
Definition: util_sfn.c:112
unsigned char mode
Definition: fat_sl.h:114
unsigned char ctime[2]
Definition: dir.h:88
Definition: dir.h:75
Definition: fat_sl.h:73
void _f_setword(void *, unsigned short)
Definition: util.c:92
unsigned char attr
Definition: dir.h:79
unsigned char mediatype
Definition: volume.h:89
#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
unsigned long cluster
Definition: fat_sl.h:82
Definition: fat_sl.h:65
F_POS pos
Definition: fat_sl.h:87
unsigned long sector
Definition: fat_sl.h:68
F_POS pos
Definition: fat_sl.h:116
unsigned short cdate
Definition: fat_sl.h:81
char path[F_MAXPATH]
Definition: fat_sl.h:60
unsigned char fn_findfirst(const char *filename, F_FIND *find)
Definition: dir.c:562
unsigned char crtdate[2]
Definition: dir.h:84
F_VOLUME gl_volume
Definition: volume.c:60
unsigned char _f_setfsname(const char *, F_NAME *)
Definition: util_sfn.c:286
#define F_CLUSTER_LAST
Definition: fat_sl.h:100
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
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
unsigned long rootcluster
Definition: volume.h:61
#define F_CLUSTER_RESERVED
Definition: fat_sl.h:98
unsigned char _f_getclustervalue(unsigned long cluster, unsigned long *pvalue)
Definition: fat.c:302
char filename[F_MAXPATH]
Definition: fat_sl.h:75
unsigned char fn_chdir(const char *dirname)
Definition: dir.c:665
unsigned char _f_setnameext(char *, char *, char *)
Definition: util_sfn.c:191
#define F_MAXEXT
Definition: fat_sl.h:56
unsigned char fn_rmdir(const char *dirname)
Definition: dir.c:1088
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
unsigned char _f_setclustervalue(unsigned long cluster, unsigned long _tdata)
Definition: fat.c:163