diff --git a/components/fatfs/src/vfs_fat.c b/components/fatfs/src/vfs_fat.c index b1192b602..62a0f5434 100644 --- a/components/fatfs/src/vfs_fat.c +++ b/components/fatfs/src/vfs_fat.c @@ -395,8 +395,23 @@ static int vfs_fat_fstat(void* ctx, int fd, struct stat * st) return 0; } +static inline mode_t get_stat_mode(bool is_dir) +{ + return S_IRWXU | S_IRWXG | S_IRWXO | + ((is_dir) ? S_IFDIR : S_IFREG); +} + static int vfs_fat_stat(void* ctx, const char * path, struct stat * st) { + if (strcmp(path, "/") == 0) { + /* FatFS f_stat function does not work for the drive root. + * Just pretend that this is a directory. + */ + memset(st, 0, sizeof(*st)); + st->st_mode = get_stat_mode(true); + return 0; + } + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; _lock_acquire(&fat_ctx->lock); prepend_drive_to_path(fat_ctx, &path, NULL); @@ -408,9 +423,10 @@ static int vfs_fat_stat(void* ctx, const char * path, struct stat * st) errno = fresult_to_errno(res); return -1; } + + memset(st, 0, sizeof(*st)); st->st_size = info.fsize; - st->st_mode = S_IRWXU | S_IRWXG | S_IRWXO | - ((info.fattrib & AM_DIR) ? S_IFDIR : S_IFREG); + st->st_mode = get_stat_mode((info.fattrib & AM_DIR) != 0); struct tm tm; uint16_t fdate = info.fdate; tm.tm_mday = fdate & 0x1f; diff --git a/components/fatfs/test/test_fatfs_common.c b/components/fatfs/test/test_fatfs_common.c index ca27cdd4b..799d36f1b 100644 --- a/components/fatfs/test/test_fatfs_common.c +++ b/components/fatfs/test/test_fatfs_common.c @@ -125,15 +125,15 @@ void test_fatfs_lseek(const char* filename) TEST_ASSERT_EQUAL(0, fclose(f)); } -void test_fatfs_stat(const char* filename) +void test_fatfs_stat(const char* filename, const char* root_dir) { struct tm tm; - tm.tm_year = 2016 - 1900; - tm.tm_mon = 0; - tm.tm_mday = 10; - tm.tm_hour = 16; - tm.tm_min = 30; - tm.tm_sec = 0; + tm.tm_year = 2017 - 1900; + tm.tm_mon = 11; + tm.tm_mday = 8; + tm.tm_hour = 19; + tm.tm_min = 51; + tm.tm_sec = 10; time_t t = mktime(&tm); printf("Setting time: %s", asctime(&tm)); struct timeval now = { .tv_sec = t }; @@ -151,6 +151,11 @@ void test_fatfs_stat(const char* filename) TEST_ASSERT(st.st_mode & S_IFREG); TEST_ASSERT_FALSE(st.st_mode & S_IFDIR); + + memset(&st, 0, sizeof(st)); + TEST_ASSERT_EQUAL(0, stat(root_dir, &st)); + TEST_ASSERT(st.st_mode & S_IFDIR); + TEST_ASSERT_FALSE(st.st_mode & S_IFREG); } void test_fatfs_unlink(const char* filename) diff --git a/components/fatfs/test/test_fatfs_common.h b/components/fatfs/test/test_fatfs_common.h index dcc31e37d..36e7ca62b 100644 --- a/components/fatfs/test/test_fatfs_common.h +++ b/components/fatfs/test/test_fatfs_common.h @@ -43,7 +43,7 @@ void test_fatfs_open_max_files(const char* filename_prefix, size_t files_count); void test_fatfs_lseek(const char* filename); -void test_fatfs_stat(const char* filename); +void test_fatfs_stat(const char* filename, const char* root_dir); void test_fatfs_unlink(const char* filename); diff --git a/components/fatfs/test/test_fatfs_sdmmc.c b/components/fatfs/test/test_fatfs_sdmmc.c index 6935fc708..3610511a9 100644 --- a/components/fatfs/test/test_fatfs_sdmmc.c +++ b/components/fatfs/test/test_fatfs_sdmmc.c @@ -105,7 +105,7 @@ TEST_CASE("(SD) can lseek", "[fatfs][sdcard][ignore]") TEST_CASE("(SD) stat returns correct values", "[fatfs][ignore]") { test_setup(); - test_fatfs_stat("/sdcard/stat.txt"); + test_fatfs_stat("/sdcard/stat.txt", "/sdcard"); test_teardown(); } diff --git a/components/fatfs/test/test_fatfs_spiflash.c b/components/fatfs/test/test_fatfs_spiflash.c index bcc396b93..47116cd8d 100644 --- a/components/fatfs/test/test_fatfs_spiflash.c +++ b/components/fatfs/test/test_fatfs_spiflash.c @@ -100,7 +100,7 @@ TEST_CASE("(WL) can lseek", "[fatfs][wear_levelling]") TEST_CASE("(WL) stat returns correct values", "[fatfs][wear_levelling]") { test_setup(); - test_fatfs_stat("/spiflash/stat.txt"); + test_fatfs_stat("/spiflash/stat.txt", "/spiflash"); test_teardown(); }