]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/FreeRTOS-Plus-FAT-SL/fat_sl/common/dir.c
Update to MIT licensed FreeRTOS V10.0.0 - see https://www.freertos.org/History.txt
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-FAT-SL / fat_sl / common / dir.c
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-FAT-SL/fat_sl/common/dir.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-FAT-SL/fat_sl/common/dir.c
deleted file mode 100644 (file)
index 92fd0d9..0000000
+++ /dev/null
@@ -1,1221 +0,0 @@
-/*\r
- * FreeRTOS+FAT SL V1.0.1 (C) 2014 HCC Embedded\r
- *\r
- * The FreeRTOS+FAT SL license terms are different to the FreeRTOS license \r
- * terms.\r
- * \r
- * FreeRTOS+FAT SL uses a dual license model that allows the software to be used \r
- * under a standard GPL open source license, or a commercial license.  The \r
- * standard GPL license (unlike the modified GPL license under which FreeRTOS \r
- * itself is distributed) requires that all software statically linked with \r
- * FreeRTOS+FAT SL is also distributed under the same GPL V2 license terms.  \r
- * Details of both license options follow:\r
- * \r
- * - Open source licensing -\r
- * FreeRTOS+FAT SL is a free download and may be used, modified, evaluated and\r
- * distributed without charge provided the user adheres to version two of the \r
- * GNU General Public License (GPL) and does not remove the copyright notice or \r
- * this text.  The GPL V2 text is available on the gnu.org web site, and on the\r
- * following URL: http://www.FreeRTOS.org/gpl-2.0.txt.\r
- * \r
- * - Commercial licensing -\r
- * Businesses and individuals who for commercial or other reasons cannot comply\r
- * with the terms of the GPL V2 license must obtain a commercial license before \r
- * incorporating FreeRTOS+FAT SL into proprietary software for distribution in \r
- * any form.  Commercial licenses can be purchased from \r
- * http://shop.freertos.org/fat_sl and do not require any source files to be \r
- * changed.\r
- *\r
- * FreeRTOS+FAT SL is distributed in the hope that it will be useful.  You\r
- * cannot use FreeRTOS+FAT SL unless you agree that you use the software 'as\r
- * is'.  FreeRTOS+FAT SL is provided WITHOUT ANY WARRANTY; without even the\r
- * implied warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A\r
- * PARTICULAR PURPOSE. Real Time Engineers Ltd. and HCC Embedded disclaims all\r
- * conditions and terms, be they implied, expressed, or statutory.\r
- *\r
- * http://www.FreeRTOS.org\r
- * http://www.FreeRTOS.org/FreeRTOS-Plus\r
- *\r
- */\r
-\r
-#include "../../api/fat_sl.h"\r
-#include "../../psp/include/psp_string.h"\r
-\r
-#include "dir.h"\r
-#include "util.h"\r
-#include "volume.h"\r
-#include "drv.h"\r
-#include "fat.h"\r
-#include "file.h"\r
-\r
-#include "../../version/ver_fat_sl.h"\r
-#if VER_FAT_SL_MAJOR != 5 || VER_FAT_SL_MINOR != 2\r
- #error Incompatible FAT_SL version number!\r
-#endif\r
-\r
-\r
-/****************************************************************************\r
- *\r
- * _f_findfilewc\r
- *\r
- * internal function to finding file in directory entry with or without\r
- * wildcard\r
- *\r
- * INPUTS\r
- *\r
- * name - filename\r
- * ext - fileextension\r
- * pos - where to start searching, and contains current position\r
- * pde - store back the directory entry pointer\r
- * wc - wildcard checking?\r
- *\r
- * RETURNS\r
- *\r
- * 0 - if file was not found\r
- * 1 - if file was found\r
- *\r
- ***************************************************************************/\r
-unsigned char _f_findfilewc ( char * name, char * ext, F_POS * pos, F_DIRENTRY * * pde, unsigned char wc )\r
-{\r
-  while ( pos->cluster < F_CLUSTER_RESERVED )\r
-  {\r
-    for ( ; pos->sector < pos->sectorend ; pos->sector++ )\r
-    {\r
-      F_DIRENTRY * de = (F_DIRENTRY *)( gl_sector + sizeof( F_DIRENTRY ) * pos->pos );\r
-\r
-      if ( _f_readglsector( pos->sector ) )\r
-      {\r
-        return 0;                                         /*not found*/\r
-      }\r
-\r
-      for ( ; pos->pos < F_SECTOR_SIZE / sizeof( F_DIRENTRY ) ; de++, pos->pos++ )\r
-      {\r
-        unsigned char  b, ok;\r
-\r
-        if ( !de->name[0] )\r
-        {\r
-          return 0;                                                /*empty*/\r
-        }\r
-\r
-        if ( (unsigned char)( de->name[0] ) == 0xe5 )\r
-        {\r
-          continue;                                                 /*deleted*/\r
-        }\r
-\r
-        if ( de->attr & F_ATTR_VOLUME )\r
-        {\r
-          continue;\r
-        }\r
-\r
-        if ( wc )\r
-        {\r
-          for ( b = 0, ok = 1 ; b < sizeof( de->name ) ; b++ )\r
-          {\r
-            if ( name[b] == '*' )\r
-            {\r
-              break;\r
-            }\r
-\r
-            if ( name[b] != '?' )\r
-            {\r
-              if ( de->name[b] != name[b] )\r
-              {\r
-                ok = 0;\r
-                break;\r
-              }\r
-            }\r
-          }\r
-\r
-          if ( ok )\r
-          {\r
-            for ( b = 0, ok = 1 ; b < sizeof( de->ext ) ; b++ )\r
-            {\r
-              if ( ext[b] == '*' )\r
-              {\r
-                if ( pde )\r
-                {\r
-                  *pde = de;\r
-                }\r
-\r
-                return 1;\r
-              }\r
-\r
-              if ( ext[b] != '?' )\r
-              {\r
-                if ( de->ext[b] != ext[b] )\r
-                {\r
-                  ok = 0;\r
-                  break;\r
-                }\r
-              }\r
-            }\r
-\r
-            if ( ok )\r
-            {\r
-              if ( pde )\r
-              {\r
-                *pde = de;\r
-              }\r
-\r
-              return 1;\r
-            }\r
-          }\r
-        }\r
-        else\r
-        {\r
-          for ( b = 0, ok = 1 ; b < sizeof( de->name ) ; b++ )\r
-          {\r
-            if ( de->name[b] != name[b] )\r
-            {\r
-              ok = 0;\r
-              break;\r
-            }\r
-          }\r
-\r
-          if ( ok )\r
-          {\r
-            for ( b = 0, ok = 1 ; b < sizeof( de->ext ) ; b++ )\r
-            {\r
-              if ( de->ext[b] != ext[b] )\r
-              {\r
-                ok = 0;\r
-                break;\r
-              }\r
-            }\r
-\r
-            if ( ok )\r
-            {\r
-              if ( pde )\r
-              {\r
-                *pde = de;\r
-              }\r
-\r
-              return 1;\r
-            }\r
-          }\r
-        }\r
-      }\r
-\r
-      pos->pos = 0;\r
-    }\r
-\r
-    if ( !pos->cluster )\r
-    {\r
-      if ( gl_volume.mediatype == F_FAT32_MEDIA )\r
-      {\r
-        pos->cluster = gl_volume.bootrecord.rootcluster;\r
-      }\r
-      else\r
-      {\r
-        return 0;\r
-      }\r
-    }\r
-\r
-    {\r
-      unsigned long  nextcluster;\r
-      gl_volume.fatsector = (unsigned long)-1;\r
-      if ( _f_getclustervalue( pos->cluster, &nextcluster ) )\r
-      {\r
-        return 0;                                                          /*not found*/\r
-      }\r
-\r
-      if ( nextcluster >= F_CLUSTER_RESERVED )\r
-      {\r
-        return 0;                                            /*eof*/\r
-      }\r
-\r
-      _f_clustertopos( nextcluster, pos );\r
-    }\r
-  } /* _f_findfilewc */\r
-\r
-  return 0;\r
-}\r
-\r
-\r
-/****************************************************************************\r
- *\r
- * _f_getfilename\r
- *\r
- * create a complete filename from name and extension\r
- *\r
- * INPUTS\r
- *\r
- * dest - where to store filename\r
- * name - name of the file\r
- * ext - extension of the file\r
- *\r
- ***************************************************************************/\r
-static void _f_getfilename ( char * dest, char * name, char * ext )\r
-{\r
-  unsigned char  a, len;\r
-\r
-  for ( len = a = F_MAXNAME ; a ; a--, len-- )\r
-  {\r
-    if ( name[a - 1] != ' ' )\r
-    {\r
-      break;\r
-    }\r
-  }\r
-\r
-  for ( a = 0 ; a < len ; a++ )\r
-  {\r
-    *dest++ = *name++;\r
-  }\r
-\r
-\r
-  for ( len = a = F_MAXEXT ; a ; a--, len-- )\r
-  {\r
-    if ( ext[a - 1] != ' ' )\r
-    {\r
-      break;\r
-    }\r
-  }\r
-\r
-  if ( len )\r
-  {\r
-    *dest++ = '.';\r
-  }\r
-\r
-  for ( a = 0 ; a < len ; a++ )\r
-  {\r
-    *dest++ = *ext++;\r
-  }\r
-\r
-  *dest = 0; /*terminateit*/\r
-} /* _f_getfilename */\r
-\r
-\r
-\r
-\r
-/****************************************************************************\r
- *\r
- * _f_getdecluster\r
- *\r
- * get a directory entry structure start cluster value\r
- *\r
- * INPUTS\r
- *\r
- * de - directory entry\r
- *\r
- * RETURNS\r
- *\r
- * directory entry cluster value\r
- *\r
- ***************************************************************************/\r
-unsigned long _f_getdecluster ( F_DIRENTRY * de )\r
-{\r
-  unsigned long  cluster;\r
-\r
-  if ( gl_volume.mediatype == F_FAT32_MEDIA )\r
-  {\r
-    cluster = _f_getword( &de->clusterhi );\r
-    cluster <<= 16;\r
-    cluster |= _f_getword( &de->clusterlo );\r
-    return cluster;\r
-  }\r
-\r
-  return _f_getword( &de->clusterlo );\r
-}\r
-\r
-\r
-/****************************************************************************\r
- *\r
- * _f_setdecluster\r
- *\r
- * set a directory entry structure start cluster value\r
- *\r
- * INPUTS\r
- *\r
- * de - directory entry\r
- * cluster - value of the start cluster\r
- *\r
- ***************************************************************************/\r
-void _f_setdecluster ( F_DIRENTRY * de, unsigned long cluster )\r
-{\r
-  _f_setword( &de->clusterlo, (unsigned short)( cluster & 0xffff ) );\r
-  if ( gl_volume.mediatype == F_FAT32_MEDIA )\r
-  {\r
-    _f_setword( &de->clusterhi, (unsigned short)( cluster >> 16 ) );\r
-  }\r
-  else\r
-  {\r
-    _f_setword( &de->clusterhi, (unsigned short)0 );\r
-  }\r
-}\r
-\r
-\r
-/****************************************************************************\r
- *\r
- * _f_findpath\r
- *\r
- * finding out if path is valid in F_NAME and\r
- * correct path info with absolute path (removes relatives)\r
- *\r
- * INPUTS\r
- *\r
- * fsname - filled structure with path,drive\r
- * pos - where to start searching, and contains current position\r
- *\r
- * RETURNS\r
- *\r
- * 0 - if path was not found or invalid\r
- * 1 - if path was found\r
- *\r
- ***************************************************************************/\r
-unsigned char _f_findpath ( F_NAME * fsname, F_POS * pos )\r
-{\r
-  char       * path = fsname->path;\r
-  char       * mpath = path;\r
-  F_DIRENTRY * de;\r
-\r
-  _f_clustertopos( 0, pos );\r
-\r
-  for ( ; *path ; )\r
-  {\r
-    char           name[F_MAXNAME];\r
-    char           ext[F_MAXEXT];\r
-\r
-    unsigned char  len = _f_setnameext( path, name, ext );\r
-\r
-    if ( ( pos->cluster == 0 ) && ( len == 1 ) && ( name[0] == '.' ) )\r
-    {\r
-      _f_clustertopos( 0, pos );\r
-    }\r
-    else\r
-    {\r
-      if ( !_f_findfilewc( name, ext, pos, &de, 0 ) )\r
-      {\r
-        return 0;\r
-      }\r
-\r
-      if ( !( de->attr & F_ATTR_DIR ) )\r
-      {\r
-        return 0;\r
-      }\r
-\r
-      _f_clustertopos( _f_getdecluster( de ), pos );\r
-    }\r
-\r
-\r
-    if ( name[0] == '.' )\r
-    {\r
-      if ( len == 1 )\r
-      {\r
-        path += len;\r
-\r
-        if ( !( *path ) )\r
-        {\r
-          if ( mpath != fsname->path )\r
-          {\r
-            mpath--;                                  /*if we are now at the top*/\r
-          }\r
-\r
-          break;\r
-        }\r
-\r
-        path++;\r
-        continue;\r
-      }\r
-\r
-      if ( name[1] != '.' )\r
-      {\r
-        return 0;                       /*invalid name*/\r
-      }\r
-\r
-      if ( len != 2 )\r
-      {\r
-        return 0;                 /*invalid name !*/\r
-      }\r
-\r
-      path += len;\r
-\r
-      if ( mpath == fsname->path )\r
-      {\r
-        return 0;                              /*we are in the top*/\r
-      }\r
-\r
-      mpath--;       /*no on separator*/\r
-      for ( ; ; )\r
-      {\r
-        if ( mpath == fsname->path )\r
-        {\r
-          break;                                /*we are now at the top*/\r
-        }\r
-\r
-        mpath--;\r
-        if ( *mpath == '/' )\r
-        {\r
-          mpath++;\r
-          break;\r
-        }\r
-      }\r
-\r
-      if ( !( *path ) )\r
-      {\r
-        if ( mpath != fsname->path )\r
-        {\r
-          mpath--;                                /*if we are now at the top*/\r
-        }\r
-\r
-        break;\r
-      }\r
-\r
-      path++;\r
-      continue;\r
-    }\r
-    else\r
-    {\r
-      if ( path == mpath )                              /*if no was dots just step*/\r
-      {\r
-        path += len;\r
-        mpath += len;\r
-      }\r
-      else\r
-      {\r
-        unsigned char  a;\r
-        for ( a = 0 ; a < len ; a++ )\r
-        {\r
-          *mpath++ = *path++;                            /*copy if in different pos*/\r
-        }\r
-      }\r
-    }\r
-\r
-    if ( !( *path ) )\r
-    {\r
-      break;\r
-    }\r
-\r
-    path++;\r
-    *mpath++ = '/';   /*add separator*/\r
-  }\r
-\r
-  *mpath = 0; /*terminate it*/\r
-  return 1;\r
-} /* _f_findpath */\r
-\r
-\r
-/****************************************************************************\r
- *\r
- * fn_getcwd\r
- *\r
- * getting a current working directory of current drive\r
- *\r
- * INPUTS\r
- *\r
- * buffer - where to store current working folder\r
- * maxlen - buffer length (possible size is F_MAXPATH)\r
- *\r
- * RETURNS\r
- *\r
- * error code or zero if successful\r
- *\r
- ***************************************************************************/\r
-unsigned char fn_getcwd ( char * buffer, unsigned char maxlen, char root )\r
-{\r
-  unsigned char  a;\r
-\r
-  if ( !maxlen )\r
-  {\r
-    return F_NO_ERROR;\r
-  }\r
-\r
-  maxlen--;     /*need for termination*/\r
-  if ( root && maxlen )\r
-  {\r
-    *buffer++ = '/';\r
-    maxlen--;\r
-  }\r
-\r
-  for ( a = 0 ; a < maxlen ; a++ )\r
-  {\r
-    char  ch = gl_volume.cwd[a];\r
-    buffer[a] = ch;\r
-    if ( !ch )\r
-    {\r
-      break;\r
-    }\r
-  }\r
-\r
-  buffer[a] = 0;    /*add terminator at the end*/\r
-\r
-  return F_NO_ERROR;\r
-} /* fn_getcwd */\r
-\r
-\r
-\r
-/****************************************************************************\r
- *\r
- * fn_findfirst\r
- *\r
- * find a file(s) or directory(s) in directory\r
- *\r
- * INPUTS\r
- *\r
- * filename - filename (with or without wildcards)\r
- * find - where to store found file information\r
- *\r
- * RETURNS\r
- *\r
- * error code or zero if successful\r
- *\r
- ***************************************************************************/\r
-unsigned char fn_findfirst ( const char * filename, F_FIND * find )\r
-{\r
-  unsigned char  ret;\r
-\r
-  if ( _f_setfsname( filename, &find->findfsname ) )\r
-  {\r
-    return F_ERR_INVALIDNAME;  /*invalid name*/\r
-  }\r
-\r
-  if ( _f_checkname( find->findfsname.filename, find->findfsname.fileext ) )\r
-  {\r
-    return F_ERR_INVALIDNAME;  /*invalid name, wildcard is ok*/\r
-  }\r
-\r
-\r
-  ret = _f_getvolume();\r
-  if ( ret )\r
-  {\r
-    return ret;\r
-  }\r
-\r
-  if ( !_f_findpath( &find->findfsname, &find->pos ) )\r
-  {\r
-    return F_ERR_INVALIDDIR;   /*search for path*/\r
-  }\r
-\r
-  return fn_findnext( find );\r
-} /* fn_findfirst */\r
-\r
-\r
-\r
-/****************************************************************************\r
- *\r
- * fn_findnext\r
- *\r
- * find further file(s) or directory(s) in directory\r
- *\r
- * INPUTS\r
- *\r
- * find - where to store found file information (findfirst should call 1st)\r
- *\r
- * RETURNS\r
- *\r
- * error code or zero if successful\r
- *\r
- ***************************************************************************/\r
-unsigned char fn_findnext ( F_FIND * find )\r
-{\r
-  F_DIRENTRY   * de;\r
-  unsigned char  a;\r
-  unsigned char  ret;\r
-\r
-  ret = _f_getvolume();\r
-  if ( ret )\r
-  {\r
-    return ret;\r
-  }\r
-\r
-  if ( !_f_findfilewc( find->findfsname.filename, find->findfsname.fileext, &find->pos, &de, 1 ) )\r
-  {\r
-    return F_ERR_NOTFOUND;\r
-  }\r
-\r
-  for ( a = 0 ; a < F_MAXNAME ; a++ )\r
-  {\r
-    find->name[a] = de->name[a];\r
-  }\r
-\r
-  for ( a = 0 ; a < F_MAXEXT ; a++ )\r
-  {\r
-    find->ext[a] = de->ext[a];\r
-  }\r
-\r
-  _f_getfilename( find->filename, (char *)de->name, (char *)de->ext );\r
-\r
-  find->attr = de->attr;\r
-  find->cdate = _f_getword( &de->cdate );\r
-  find->ctime = _f_getword( &de->ctime );\r
-  find->filesize = (long)_f_getlong( &de->filesize );\r
-  find->cluster = _f_getdecluster( de );\r
-  find->pos.pos++;   /*goto next position*/\r
-\r
-  return 0;\r
-} /* fn_findnext */\r
-\r
-\r
-\r
-/****************************************************************************\r
- *\r
- * fn_chdir\r
- *\r
- * change current working directory\r
- *\r
- * INPUTS\r
- *\r
- * dirname - new working directory name\r
- *\r
- * RETURNS\r
- *\r
- * 0 - if successfully\r
- * other - if any error\r
- *\r
- ***************************************************************************/\r
-unsigned char fn_chdir ( const char * dirname )\r
-{\r
-  F_POS          pos;\r
-  F_NAME         fsname;\r
-  unsigned char  len;\r
-  unsigned char  a;\r
-  unsigned char  ret;\r
-\r
-  ret = _f_setfsname( dirname, &fsname );\r
-\r
-  if ( ret == 1 )\r
-  {\r
-    return F_ERR_INVALIDNAME;             /*invalid name*/\r
-  }\r
-\r
-  if ( _f_checknamewc( fsname.filename, fsname.fileext ) )\r
-  {\r
-    return F_ERR_INVALIDNAME;                                                    /*invalid name*/\r
-  }\r
-\r
-  ret = _f_getvolume();\r
-  if ( ret )\r
-  {\r
-    return ret;\r
-  }\r
-\r
-  for ( len = 0 ; fsname.path[len] ; )\r
-  {\r
-    len++;\r
-  }\r
-\r
-  if ( len && ( ( fsname.filename[0] != 32 ) || ( fsname.fileext[0] != 32 ) ) )\r
-  {\r
-    fsname.path[len++] = '/';\r
-  }\r
-\r
-  _f_getfilename( fsname.path + len, fsname.filename, fsname.fileext );\r
-\r
-  if ( !( _f_findpath( &fsname, &pos ) ) )\r
-  {\r
-    return F_ERR_NOTFOUND;\r
-  }\r
-\r
-  for ( a = 0 ; a < F_MAXPATH ; a++ )\r
-  {\r
-    gl_volume.cwd[a] = fsname.path[a];\r
-  }\r
-\r
-  return F_NO_ERROR;\r
-} /* fn_chdir */\r
-\r
-\r
-\r
-/****************************************************************************\r
- *\r
- * _f_initentry\r
- *\r
- * init directory entry, this function is called if a new entry is coming\r
- *\r
- * INPUTS\r
- *\r
- * de - directory entry which needs to be initialized\r
- * name - fil ename  (8)\r
- * ext - file extension (3)\r
- *\r
- ***************************************************************************/\r
-static void _f_initentry ( F_DIRENTRY * de, char * name, char * ext )\r
-{\r
-  unsigned short  date;\r
-  unsigned short  time;\r
-\r
-  psp_memset( de, 0, sizeof( F_DIRENTRY ) ); /*reset all entries*/\r
-\r
-  psp_memcpy( de->name, name, sizeof( de->name ) );\r
-  psp_memcpy( de->ext, ext, sizeof( de->ext ) );\r
-\r
-  f_igettimedate( &time, &date );\r
-  _f_setword( &de->cdate, date ); /*if there is realtime clock then creation date could be set from*/\r
-  _f_setword( &de->ctime, time ); /*if there is realtime clock then creation time could be set from*/\r
-}\r
-\r
-\r
-\r
-\r
-\r
-/****************************************************************************\r
- *\r
- * _f_addentry\r
- *\r
- * Add a new directory entry into driectory list\r
- *\r
- * INPUTS\r
- *\r
- * fs_name - filled structure what to add into directory list\r
- * pos - where directory cluster chains starts\r
- * pde - F_DIRENTRY pointer where to store the entry where it was added\r
- *\r
- * RETURNS\r
- *\r
- * 0 - if successfully added\r
- * other - if any error (see FS_xxx errorcodes)\r
- *\r
- ***************************************************************************/\r
-unsigned char _f_addentry ( F_NAME * fsname, F_POS * pos, F_DIRENTRY * * pde )\r
-{\r
-  unsigned char   ret;\r
-  unsigned short  date;\r
-  unsigned short  time;\r
-\r
-  if ( !fsname->filename[0] )\r
-  {\r
-    return F_ERR_INVALIDNAME;\r
-  }\r
-\r
-  if ( fsname->filename[0] == '.' )\r
-  {\r
-    return F_ERR_INVALIDNAME;\r
-  }\r
-\r
-  while ( pos->cluster < F_CLUSTER_RESERVED )\r
-  {\r
-    for ( ; pos->sector < pos->sectorend ; pos->sector++ )\r
-    {\r
-      F_DIRENTRY * de = (F_DIRENTRY *)( gl_sector + sizeof( F_DIRENTRY ) * pos->pos );\r
-\r
-      ret = _f_readglsector( pos->sector );\r
-      if ( ret )\r
-      {\r
-        return ret;\r
-      }\r
-\r
-      for ( ; pos->pos < F_SECTOR_SIZE / sizeof( F_DIRENTRY ) ; de++, pos->pos++ )\r
-      {\r
-        if ( ( !de->name[0] ) || ( (unsigned char)( de->name[0] ) == 0xe5 ) )\r
-        {\r
-          _f_initentry( de, fsname->filename, fsname->fileext );\r
-          if ( gl_volume.mediatype == F_FAT32_MEDIA )\r
-          {\r
-            f_igettimedate( &time, &date );\r
-            _f_setword( &de->crtdate, date );             /*if there is realtime clock then creation date could be set from*/\r
-            _f_setword( &de->crttime, time );             /*if there is realtime clock then creation time could be set from*/\r
-            _f_setword( &de->lastaccessdate, date );      /*if there is realtime clock then creation date could be set from*/\r
-          }\r
-\r
-          if ( pde )\r
-          {\r
-            *pde = de;\r
-          }\r
-\r
-          return F_NO_ERROR;\r
-        }\r
-      }\r
-\r
-      pos->pos = 0;\r
-    }\r
-\r
-    if ( !pos->cluster )\r
-    {\r
-      if ( gl_volume.mediatype == F_FAT32_MEDIA )\r
-      {\r
-        pos->cluster = gl_volume.bootrecord.rootcluster;\r
-      }\r
-      else\r
-      {\r
-        return F_ERR_NOMOREENTRY;\r
-      }\r
-    }\r
-\r
-    {\r
-      unsigned long  cluster;\r
-\r
-      gl_volume.fatsector = (unsigned long)-1;\r
-      ret = _f_getclustervalue( pos->cluster, &cluster );    /*try to get next cluster*/\r
-      if ( ret )\r
-      {\r
-        return ret;\r
-      }\r
-\r
-      if ( cluster < F_CLUSTER_RESERVED )\r
-      {\r
-        _f_clustertopos( cluster, pos );\r
-      }\r
-      else\r
-      {\r
-        ret = _f_alloccluster( &cluster );        /*get a new one*/\r
-        if ( ret )\r
-        {\r
-          return ret;\r
-        }\r
-\r
-        if ( cluster < F_CLUSTER_RESERVED )\r
-        {\r
-          if ( gl_file.mode != F_FILE_CLOSE )\r
-          {\r
-            return F_ERR_NOMOREENTRY;\r
-          }\r
-\r
-          _f_clustertopos( cluster, &gl_file.pos );\r
-\r
-          ret = _f_setclustervalue( gl_file.pos.cluster, F_CLUSTER_LAST );\r
-          if ( ret )\r
-          {\r
-            return ret;\r
-          }\r
-\r
-          ret = _f_setclustervalue( pos->cluster, gl_file.pos.cluster );\r
-          if ( ret )\r
-          {\r
-            return ret;\r
-          }\r
-\r
-          ret = _f_writefatsector();\r
-          if ( ret )\r
-          {\r
-            return ret;\r
-          }\r
-\r
-          gl_volume.fatsector = (unsigned long)-1;\r
-          psp_memset( gl_sector, 0, F_SECTOR_SIZE );\r
-          while ( gl_file.pos.sector < gl_file.pos.sectorend )\r
-          {\r
-            ret = _f_writeglsector( gl_file.pos.sector );\r
-            if ( ret )\r
-            {\r
-              return ret;\r
-            }\r
-\r
-            gl_file.pos.sector++;\r
-          }\r
-\r
-          _f_clustertopos( gl_file.pos.cluster, pos );\r
-        }\r
-        else\r
-        {\r
-          return F_ERR_NOMOREENTRY;\r
-        }\r
-      }\r
-    }\r
-  } /* _f_addentry */\r
-\r
-  return F_ERR_NOMOREENTRY;\r
-}\r
-\r
-\r
-\r
-/****************************************************************************\r
- *\r
- * fn_mkdir\r
- *\r
- * making a new directory\r
- *\r
- * INPUTS\r
- *\r
- * dirname - new directory name\r
- *\r
- * RETURNS\r
- *\r
- * error code or zero if successful\r
- *\r
- ***************************************************************************/\r
-unsigned char fn_mkdir ( const char * dirname )\r
-{\r
-  F_POS          posdir;\r
-  F_POS          pos;\r
-  F_DIRENTRY   * de;\r
-  F_NAME         fsname;\r
-  unsigned long  cluster;\r
-  unsigned char  ret;\r
-\r
- #if F_FILE_CHANGED_EVENT\r
-  ST_FILE_CHANGED  fc;\r
- #endif\r
-\r
-  if ( _f_setfsname( dirname, &fsname ) )\r
-  {\r
-    return F_ERR_INVALIDNAME;                                    /*invalid name*/\r
-  }\r
-\r
-  if ( _f_checknamewc( fsname.filename, fsname.fileext ) )\r
-  {\r
-    return F_ERR_INVALIDNAME;                                                    /*invalid name*/\r
-  }\r
-\r
-  ret = _f_getvolume();\r
-  if ( ret )\r
-  {\r
-    return ret;\r
-  }\r
-\r
-  if ( !_f_findpath( &fsname, &posdir ) )\r
-  {\r
-    return F_ERR_INVALIDDIR;\r
-  }\r
-\r
-  pos = posdir;\r
-\r
-  if ( fsname.filename[0] == '.' )\r
-  {\r
-    return F_ERR_NOTFOUND;\r
-  }\r
-\r
-  if ( _f_findfilewc( fsname.filename, fsname.fileext, &pos, &de, 0 ) )\r
-  {\r
-    return F_ERR_DUPLICATED;\r
-  }\r
-\r
-  pos = posdir;\r
-\r
-  gl_volume.fatsector = (unsigned long)-1;\r
-  ret = _f_alloccluster( &cluster );\r
-  if ( ret )\r
-  {\r
-    return ret;\r
-  }\r
-\r
-  ret = _f_addentry( &fsname, &pos, &de );\r
-  if ( ret )\r
-  {\r
-    return ret;\r
-  }\r
-\r
-  de->attr |= F_ATTR_DIR;       /*set as directory*/\r
-\r
- #if F_FILE_CHANGED_EVENT\r
-  if ( f_filechangedevent )\r
-  {\r
-    fc.action = FACTION_ADDED;\r
-    fc.flags = FFLAGS_DIR_NAME | FFLAGS_ATTRIBUTES | FFLAGS_SIZE | FFLAGS_LAST_WRITE;\r
-    fc.attr = de->attr;\r
-    fc.ctime = _f_getword( de->ctime );\r
-    fc.cdate = _f_getword( de->cdate );\r
-    fc.filesize = _f_getlong( de->filesize );\r
-  }\r
-\r
- #endif\r
-\r
-  if ( gl_file.mode != F_FILE_CLOSE )\r
-  {\r
-    return F_ERR_LOCKED;\r
-  }\r
-\r
-  _f_clustertopos( cluster, &gl_file.pos );\r
-  _f_setdecluster( de, cluster ); /*new dir*/\r
-\r
-  (void)_f_writeglsector( (unsigned long)-1 );  /*write actual directory sector*/\r
-\r
-\r
-  de = (F_DIRENTRY *)gl_sector;\r
-\r
-  _f_initentry( de, ".       ", "   " );\r
-  de->attr = F_ATTR_DIR;          /*set as directory*/\r
-  _f_setdecluster( de, cluster ); /*current*/\r
-  de++;\r
-\r
-  _f_initentry( de, "..      ", "   " );\r
-  de->attr = F_ATTR_DIR;                 /*set as directory*/\r
-  _f_setdecluster( de, posdir.cluster ); /*parent*/\r
-  de++;\r
-\r
-  psp_memset( de, 0, ( F_SECTOR_SIZE - 2 * sizeof( F_DIRENTRY ) ) );\r
-\r
-\r
-  ret = _f_writeglsector( gl_file.pos.sector );\r
-  if ( ret )\r
-  {\r
-    return ret;\r
-  }\r
-\r
-  gl_file.pos.sector++;\r
-  psp_memset( gl_sector, 0, ( 2 * sizeof( F_DIRENTRY ) ) );\r
-  while ( gl_file.pos.sector < gl_file.pos.sectorend )\r
-  {\r
-    ret = _f_writeglsector( gl_file.pos.sector );\r
-    if ( ret )\r
-    {\r
-      return ret;\r
-    }\r
-\r
-    gl_file.pos.sector++;\r
-  }\r
-\r
-  gl_volume.fatsector = (unsigned long)-1;\r
-  ret = _f_setclustervalue( gl_file.pos.cluster, F_CLUSTER_LAST );\r
-  if ( ret )\r
-  {\r
-    return ret;\r
-  }\r
-\r
-  ret = _f_writefatsector();\r
- #if F_FILE_CHANGED_EVENT\r
-  if ( f_filechangedevent && !ret )\r
-  {\r
-    fc.action = FACTION_ADDED;\r
-    fc.flags = FFLAGS_DIR_NAME;\r
-\r
-    if ( !_f_createfullname( fc.filename, sizeof( fc.filename ), fsname.path, fsname.filename, fsname.fileext ) )\r
-    {\r
-      f_filechangedevent( &fc );\r
-    }\r
-  }\r
-\r
- #endif\r
-\r
-  return ret;\r
-} /* fn_mkdir */\r
-\r
-\r
-\r
-/****************************************************************************\r
- *\r
- * fn_rmdir\r
- *\r
- * Remove directory, only could be removed if empty\r
- *\r
- * INPUTS\r
- *\r
- * dirname - which directory needed to be removed\r
- *\r
- * RETURNS\r
- *\r
- * error code or zero if successful\r
- *\r
- ***************************************************************************/\r
-unsigned char fn_rmdir ( const char * dirname )\r
-{\r
-  unsigned char  ret;\r
-  F_POS          pos;\r
-  F_DIRENTRY   * de;\r
-  F_NAME         fsname;\r
-  unsigned long  dirsector;\r
-  unsigned char  a;\r
-\r
-  if ( _f_setfsname( dirname, &fsname ) )\r
-  {\r
-    return F_ERR_INVALIDNAME;                                    /*invalid name*/\r
-  }\r
-\r
-  if ( _f_checknamewc( fsname.filename, fsname.fileext ) )\r
-  {\r
-    return F_ERR_INVALIDNAME;                                                    /*invalid name*/\r
-  }\r
-\r
-  if ( fsname.filename[0] == '.' )\r
-  {\r
-    return F_ERR_NOTFOUND;\r
-  }\r
-\r
-  ret = _f_getvolume();\r
-  if ( ret )\r
-  {\r
-    return ret;\r
-  }\r
-\r
-  if ( !( _f_findpath( &fsname, &pos ) ) )\r
-  {\r
-    return F_ERR_INVALIDDIR;\r
-  }\r
-\r
-  if ( !_f_findfilewc( fsname.filename, fsname.fileext, &pos, &de, 0 ) )\r
-  {\r
-    return F_ERR_NOTFOUND;\r
-  }\r
-\r
-  if ( !( de->attr & F_ATTR_DIR ) )\r
-  {\r
-    return F_ERR_INVALIDDIR;                                       /*not a directory*/\r
-  }\r
-\r
-  dirsector = gl_volume.actsector;\r
-\r
-  if ( gl_file.mode != F_FILE_CLOSE )\r
-  {\r
-    return F_ERR_LOCKED;\r
-  }\r
-\r
-  _f_clustertopos( _f_getdecluster( de ), &gl_file.pos );\r
-\r
-  for ( ; ; )\r
-  {\r
-    F_DIRENTRY * de2;\r
-    char         ch = 0;\r
-\r
-    ret = _f_getcurrsector();\r
-    if ( ret == F_ERR_EOF )\r
-    {\r
-      break;\r
-    }\r
-\r
-    if ( ret )\r
-    {\r
-      return ret;\r
-    }\r
-\r
-    de2 = (F_DIRENTRY *)gl_sector;\r
-    for ( a = 0 ; a < ( F_SECTOR_SIZE / sizeof( F_DIRENTRY ) ) ; a++, de2++ )\r
-    {\r
-      ch = de2->name[0];\r
-      if ( !ch )\r
-      {\r
-        break;\r
-      }\r
-\r
-      if ( (unsigned char)ch == 0xe5 )\r
-      {\r
-        continue;\r
-      }\r
-\r
-      if ( ch == '.' )\r
-      {\r
-        continue;\r
-      }\r
-\r
-      return F_ERR_NOTEMPTY;       /*something is there*/\r
-    }\r
-\r
-    if ( !ch )\r
-    {\r
-      break;\r
-    }\r
-\r
-    gl_file.pos.sector++;\r
-  }\r
-\r
-  ret = _f_readglsector( dirsector );\r
-  if ( ret )\r
-  {\r
-    return ret;\r
-  }\r
-\r
-  de->name[0] = (unsigned char)0xe5;\r
-\r
-  ret = _f_writeglsector( dirsector );\r
-  if ( ret )\r
-  {\r
-    return ret;\r
-  }\r
-\r
-  gl_volume.fatsector = (unsigned long)-1;\r
-  ret = _f_removechain( _f_getdecluster( de ) );\r
- #if F_FILE_CHANGED_EVENT\r
-  if ( f_filechangedevent && !ret )\r
-  {\r
-    ST_FILE_CHANGED  fc;\r
-    fc.action = FACTION_REMOVED;\r
-    fc.flags = FFLAGS_DIR_NAME;\r
-\r
-    if ( !_f_createfullname( fc.filename, sizeof( fc.filename ), fsname.path, fsname.filename, fsname.fileext ) )\r
-    {\r
-      f_filechangedevent( &fc );\r
-    }\r
-  }\r
-\r
- #endif\r
-  return ret;\r
-} /* fn_rmdir */\r
-\r
-\r