diff --git a/firmware/common/dir.c b/firmware/common/dir.c index 4b4a5fa65d..aa55aeb9e9 100644 --- a/firmware/common/dir.c +++ b/firmware/common/dir.c @@ -67,6 +67,26 @@ static int strip_volume(const char* name, char* namecopy) #endif /* #ifdef HAVE_MULTIVOLUME */ +#ifdef HAVE_HOTSWAP +// release all dir handles on a given volume "by force", to avoid leaks +int release_dirs(int volume) +{ + DIR* pdir = opendirs; + int dd; + int closed = 0; + for ( dd=0; ddfatdir.file.volume == volume) + { + pdir->busy = false; /* mark as available, no further action */ + closed++; + } + } + return closed; /* return how many we did */ +} +#endif /* #ifdef HAVE_HOTSWAP */ + + DIR* opendir(const char* name) { char namecopy[MAX_PATH]; @@ -154,6 +174,10 @@ struct dirent* readdir(DIR* dir) { struct fat_direntry entry; struct dirent* theent = &(dir->theent); + + if (!dir->busy) + return NULL; + #ifdef HAVE_MULTIVOLUME /* Volumes (secondary file systems) get inserted into the root directory of the first volume, since we have no separate top level. */ diff --git a/firmware/common/disk.c b/firmware/common/disk.c index 923dffbe46..fd6de55ddb 100644 --- a/firmware/common/disk.c +++ b/firmware/common/disk.c @@ -23,6 +23,8 @@ #ifdef HAVE_MMC #include "ata_mmc.h" #endif +#include "file.h" /* for release_dirs() */ +#include "dir.h" /* for release_files() */ #include "disk.h" /* Partition table entry layout: @@ -44,6 +46,7 @@ ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 )) static struct partinfo part[8]; /* space for 4 partitions on 2 drives */ +static int vol_drive[NUM_VOLUMES]; /* mounted to which drive (-1 if none) */ struct partinfo* disk_init(IF_MV_NONVOID(int drive)) { @@ -95,46 +98,86 @@ struct partinfo* disk_partinfo(int partition) int disk_mount_all(void) { - struct partinfo* pinfo; - int i,j; - int mounted = 0; - bool found; - int drives = 1; + int mounted; + int i; + + fat_init(); /* reset all mounted partitions */ + for (i=0; isize; } + + +#ifdef HAVE_HOTSWAP +// release all file handles on a given volume "by force", to avoid leaks +int release_files(int volume) +{ + struct filedesc* pfile = openfiles; + int fd; + int closed = 0; + for ( fd=0; fdfatfile.volume == volume) + { + pfile->busy = false; /* mark as available, no further action */ + closed++; + } + } + return closed; /* return how many we did */ +} +#endif /* #ifdef HAVE_HOTSWAP */ diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 3adca5e864..78aebd2e2b 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c @@ -482,7 +482,7 @@ int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) long startsector) return 0; } -#ifdef HAVE_MULTIVOLUME +#ifdef HAVE_HOTSWAP int fat_unmount(int volume, bool flush) { int rc; @@ -511,7 +511,7 @@ int fat_unmount(int volume, bool flush) fat_bpb->mounted = false; return rc; } -#endif +#endif /* #ifdef HAVE_HOTSWAP */ void fat_recalc_free(IF_MV_NONVOID(int volume)) { diff --git a/firmware/export/disk.h b/firmware/export/disk.h index e8525d1f75..e10fe9e7dc 100644 --- a/firmware/export/disk.h +++ b/firmware/export/disk.h @@ -35,5 +35,7 @@ struct partinfo { struct partinfo* disk_init(IF_MV_NONVOID(int volume)); struct partinfo* disk_partinfo(int partition); int disk_mount_all(void); /* returns the # of successful mounts */ +int disk_mount(int drive); +int disk_unmount(int drive); #endif diff --git a/firmware/include/dir.h b/firmware/include/dir.h index 5c157e4696..8dcbb8e900 100644 --- a/firmware/include/dir.h +++ b/firmware/include/dir.h @@ -84,6 +84,8 @@ extern int rmdir(const char* name); extern struct dirent* readdir(DIR* dir); +extern int release_dirs(int volume); + #endif /* DIRFUNCTIONS_DEFINED */ #endif diff --git a/firmware/include/file.h b/firmware/include/file.h index e76abaaa96..387c34cdd8 100644 --- a/firmware/include/file.h +++ b/firmware/include/file.h @@ -87,6 +87,7 @@ extern int remove(const char* pathname); extern int rename(const char* path, const char* newname); extern int ftruncate(int fd, off_t length); extern off_t filesize(int fd); +extern int release_files(int volume); #endif /* SIMULATOR */ #endif