+++ /dev/null
-/*\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