mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-02 04:04:31 +02:00
Merge branch 'bugfix/fatfs_stat' into 'master'
Fix stat behavior for FATFS mount point See merge request !1652
This commit is contained in:
@@ -43,6 +43,25 @@ typedef struct {
|
|||||||
struct dirent cur_dirent;
|
struct dirent cur_dirent;
|
||||||
} vfs_fat_dir_t;
|
} vfs_fat_dir_t;
|
||||||
|
|
||||||
|
/* Date and time storage formats in FAT */
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
uint16_t mday : 5; /* Day of month, 1 - 31 */
|
||||||
|
uint16_t mon : 4; /* Month, 1 - 12 */
|
||||||
|
uint16_t year : 7; /* Year, counting from 1980. E.g. 37 for 2017 */
|
||||||
|
};
|
||||||
|
uint16_t as_int;
|
||||||
|
} fat_date_t;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
uint16_t sec : 5; /* Seconds divided by 2. E.g. 21 for 42 seconds */
|
||||||
|
uint16_t min : 6; /* Minutes, 0 - 59 */
|
||||||
|
uint16_t hour : 5; /* Hour, 0 - 23 */
|
||||||
|
};
|
||||||
|
uint16_t as_int;
|
||||||
|
} fat_time_t;
|
||||||
|
|
||||||
static const char* TAG = "vfs_fat";
|
static const char* TAG = "vfs_fat";
|
||||||
|
|
||||||
static ssize_t vfs_fat_write(void* p, int fd, const void * data, size_t size);
|
static ssize_t vfs_fat_write(void* p, int fd, const void * data, size_t size);
|
||||||
@@ -395,8 +414,23 @@ static int vfs_fat_fstat(void* ctx, int fd, struct stat * st)
|
|||||||
return 0;
|
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)
|
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;
|
vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx;
|
||||||
_lock_acquire(&fat_ctx->lock);
|
_lock_acquire(&fat_ctx->lock);
|
||||||
prepend_drive_to_path(fat_ctx, &path, NULL);
|
prepend_drive_to_path(fat_ctx, &path, NULL);
|
||||||
@@ -408,22 +442,20 @@ static int vfs_fat_stat(void* ctx, const char * path, struct stat * st)
|
|||||||
errno = fresult_to_errno(res);
|
errno = fresult_to_errno(res);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(st, 0, sizeof(*st));
|
||||||
st->st_size = info.fsize;
|
st->st_size = info.fsize;
|
||||||
st->st_mode = S_IRWXU | S_IRWXG | S_IRWXO |
|
st->st_mode = get_stat_mode((info.fattrib & AM_DIR) != 0);
|
||||||
((info.fattrib & AM_DIR) ? S_IFDIR : S_IFREG);
|
fat_date_t fdate = { .as_int = info.fdate };
|
||||||
struct tm tm;
|
fat_time_t ftime = { .as_int = info.ftime };
|
||||||
uint16_t fdate = info.fdate;
|
struct tm tm = {
|
||||||
tm.tm_mday = fdate & 0x1f;
|
.tm_mday = fdate.mday,
|
||||||
fdate >>= 5;
|
.tm_mon = fdate.mon - 1, /* unlike tm_mday, tm_mon is zero-based */
|
||||||
tm.tm_mon = (fdate & 0xf) - 1;
|
.tm_year = fdate.year + 80,
|
||||||
fdate >>=4;
|
.tm_sec = ftime.sec * 2,
|
||||||
tm.tm_year = fdate + 80;
|
.tm_min = ftime.min,
|
||||||
uint16_t ftime = info.ftime;
|
.tm_hour = ftime.hour
|
||||||
tm.tm_sec = (ftime & 0x1f) * 2;
|
};
|
||||||
ftime >>= 5;
|
|
||||||
tm.tm_min = (ftime & 0x3f);
|
|
||||||
ftime >>= 6;
|
|
||||||
tm.tm_hour = (ftime & 0x1f);
|
|
||||||
st->st_mtime = mktime(&tm);
|
st->st_mtime = mktime(&tm);
|
||||||
st->st_atime = 0;
|
st->st_atime = 0;
|
||||||
st->st_ctime = 0;
|
st->st_ctime = 0;
|
||||||
|
@@ -125,15 +125,15 @@ void test_fatfs_lseek(const char* filename)
|
|||||||
TEST_ASSERT_EQUAL(0, fclose(f));
|
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;
|
struct tm tm;
|
||||||
tm.tm_year = 2016 - 1900;
|
tm.tm_year = 2017 - 1900;
|
||||||
tm.tm_mon = 0;
|
tm.tm_mon = 11;
|
||||||
tm.tm_mday = 10;
|
tm.tm_mday = 8;
|
||||||
tm.tm_hour = 16;
|
tm.tm_hour = 19;
|
||||||
tm.tm_min = 30;
|
tm.tm_min = 51;
|
||||||
tm.tm_sec = 0;
|
tm.tm_sec = 10;
|
||||||
time_t t = mktime(&tm);
|
time_t t = mktime(&tm);
|
||||||
printf("Setting time: %s", asctime(&tm));
|
printf("Setting time: %s", asctime(&tm));
|
||||||
struct timeval now = { .tv_sec = t };
|
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(st.st_mode & S_IFREG);
|
||||||
TEST_ASSERT_FALSE(st.st_mode & S_IFDIR);
|
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)
|
void test_fatfs_unlink(const char* filename)
|
||||||
|
@@ -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_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);
|
void test_fatfs_unlink(const char* filename);
|
||||||
|
|
||||||
|
@@ -105,7 +105,7 @@ TEST_CASE("(SD) can lseek", "[fatfs][sdcard][ignore]")
|
|||||||
TEST_CASE("(SD) stat returns correct values", "[fatfs][ignore]")
|
TEST_CASE("(SD) stat returns correct values", "[fatfs][ignore]")
|
||||||
{
|
{
|
||||||
test_setup();
|
test_setup();
|
||||||
test_fatfs_stat("/sdcard/stat.txt");
|
test_fatfs_stat("/sdcard/stat.txt", "/sdcard");
|
||||||
test_teardown();
|
test_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -100,7 +100,7 @@ TEST_CASE("(WL) can lseek", "[fatfs][wear_levelling]")
|
|||||||
TEST_CASE("(WL) stat returns correct values", "[fatfs][wear_levelling]")
|
TEST_CASE("(WL) stat returns correct values", "[fatfs][wear_levelling]")
|
||||||
{
|
{
|
||||||
test_setup();
|
test_setup();
|
||||||
test_fatfs_stat("/spiflash/stat.txt");
|
test_fatfs_stat("/spiflash/stat.txt", "/spiflash");
|
||||||
test_teardown();
|
test_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user