mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
VFS: Implement utime()
This commit is contained in:
parent
ada3bc3fb5
commit
fb334baa7c
@ -52,7 +52,7 @@
|
|||||||
/* This option switches f_expand function. (0:Disable or 1:Enable) */
|
/* This option switches f_expand function. (0:Disable or 1:Enable) */
|
||||||
|
|
||||||
|
|
||||||
#define FF_USE_CHMOD 0
|
#define FF_USE_CHMOD 1
|
||||||
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
|
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
|
||||||
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
|
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ static int vfs_fat_mkdir(void* ctx, const char* name, mode_t mode);
|
|||||||
static int vfs_fat_rmdir(void* ctx, const char* name);
|
static int vfs_fat_rmdir(void* ctx, const char* name);
|
||||||
static int vfs_fat_access(void* ctx, const char *path, int amode);
|
static int vfs_fat_access(void* ctx, const char *path, int amode);
|
||||||
static int vfs_fat_truncate(void* ctx, const char *path, off_t length);
|
static int vfs_fat_truncate(void* ctx, const char *path, off_t length);
|
||||||
|
static int vfs_fat_utime(void* ctx, const char *path, const struct utimbuf *times);
|
||||||
|
|
||||||
static vfs_fat_ctx_t* s_fat_ctxs[FF_VOLUMES] = { NULL, NULL };
|
static vfs_fat_ctx_t* s_fat_ctxs[FF_VOLUMES] = { NULL, NULL };
|
||||||
//backwards-compatibility with esp_vfs_fat_unregister()
|
//backwards-compatibility with esp_vfs_fat_unregister()
|
||||||
@ -146,6 +147,7 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, siz
|
|||||||
.rmdir_p = &vfs_fat_rmdir,
|
.rmdir_p = &vfs_fat_rmdir,
|
||||||
.access_p = &vfs_fat_access,
|
.access_p = &vfs_fat_access,
|
||||||
.truncate_p = &vfs_fat_truncate,
|
.truncate_p = &vfs_fat_truncate,
|
||||||
|
.utime_p = &vfs_fat_utime,
|
||||||
};
|
};
|
||||||
size_t ctx_size = sizeof(vfs_fat_ctx_t) + max_files * sizeof(FIL);
|
size_t ctx_size = sizeof(vfs_fat_ctx_t) + max_files * sizeof(FIL);
|
||||||
vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) calloc(1, ctx_size);
|
vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) calloc(1, ctx_size);
|
||||||
@ -824,3 +826,55 @@ out:
|
|||||||
_lock_release(&fat_ctx->lock);
|
_lock_release(&fat_ctx->lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int vfs_fat_utime(void *ctx, const char *path, const struct utimbuf *times)
|
||||||
|
{
|
||||||
|
FILINFO filinfo_time;
|
||||||
|
|
||||||
|
{
|
||||||
|
struct tm tm_time;
|
||||||
|
|
||||||
|
if (times) {
|
||||||
|
localtime_r(×->modtime, &tm_time);
|
||||||
|
} else {
|
||||||
|
// use current time
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
localtime_r(&tv.tv_sec, &tm_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tm_time.tm_year < 80) {
|
||||||
|
// FATFS cannot handle years before 1980
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_date_t fdate;
|
||||||
|
fat_time_t ftime;
|
||||||
|
|
||||||
|
// this time transformation is esentially the reverse of the one in vfs_fat_stat()
|
||||||
|
fdate.mday = tm_time.tm_mday;
|
||||||
|
fdate.mon = tm_time.tm_mon + 1; // January in fdate.mon is 1, and 0 in tm_time.tm_mon
|
||||||
|
fdate.year = tm_time.tm_year - 80; // tm_time.tm_year=0 is 1900, tm_time.tm_year=0 is 1980
|
||||||
|
ftime.sec = tm_time.tm_sec / 2, // ftime.sec counts seconds by 2
|
||||||
|
ftime.min = tm_time.tm_min;
|
||||||
|
ftime.hour = tm_time.tm_hour;
|
||||||
|
|
||||||
|
filinfo_time.fdate = fdate.as_int;
|
||||||
|
filinfo_time.ftime = ftime.as_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfs_fat_ctx_t *fat_ctx = (vfs_fat_ctx_t *) ctx;
|
||||||
|
_lock_acquire(&fat_ctx->lock);
|
||||||
|
prepend_drive_to_path(fat_ctx, &path, NULL);
|
||||||
|
FRESULT res = f_utime(path, &filinfo_time);
|
||||||
|
_lock_release(&fat_ctx->lock);
|
||||||
|
|
||||||
|
if (res != FR_OK) {
|
||||||
|
ESP_LOGD(TAG, "%s: fresult=%d", __func__, res);
|
||||||
|
errno = fresult_to_errno(res);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/unistd.h>
|
#include <sys/unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <utime.h>
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
@ -246,6 +247,81 @@ void test_fatfs_stat(const char* filename, const char* root_dir)
|
|||||||
TEST_ASSERT_FALSE(st.st_mode & S_IFREG);
|
TEST_ASSERT_FALSE(st.st_mode & S_IFREG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_fatfs_utime(const char* filename, const char* root_dir)
|
||||||
|
{
|
||||||
|
struct stat achieved_stat;
|
||||||
|
struct tm desired_tm;
|
||||||
|
struct utimbuf desired_time = {
|
||||||
|
.actime = 0, // access time is not supported
|
||||||
|
.modtime = 0,
|
||||||
|
};
|
||||||
|
time_t false_now = 0;
|
||||||
|
memset(&desired_tm, 0, sizeof(struct tm));
|
||||||
|
|
||||||
|
{
|
||||||
|
// Setting up a false actual time - used when the file is created and for modification with the current time
|
||||||
|
desired_tm.tm_mon = 10 - 1;
|
||||||
|
desired_tm.tm_mday = 31;
|
||||||
|
desired_tm.tm_year = 2018 - 1900;
|
||||||
|
desired_tm.tm_hour = 10;
|
||||||
|
desired_tm.tm_min = 35;
|
||||||
|
desired_tm.tm_sec = 23;
|
||||||
|
|
||||||
|
false_now = mktime(&desired_tm);
|
||||||
|
|
||||||
|
struct timeval now = { .tv_sec = false_now };
|
||||||
|
settimeofday(&now, NULL);
|
||||||
|
}
|
||||||
|
test_fatfs_create_file_with_text(filename, "");
|
||||||
|
|
||||||
|
// 00:00:00. January 1st, 1980 - FATFS cannot handle earlier dates
|
||||||
|
desired_tm.tm_mon = 1 - 1;
|
||||||
|
desired_tm.tm_mday = 1;
|
||||||
|
desired_tm.tm_year = 1980 - 1900;
|
||||||
|
desired_tm.tm_hour = 0;
|
||||||
|
desired_tm.tm_min = 0;
|
||||||
|
desired_tm.tm_sec = 0;
|
||||||
|
printf("Testing mod. time: %s", asctime(&desired_tm));
|
||||||
|
desired_time.modtime = mktime(&desired_tm);
|
||||||
|
TEST_ASSERT_EQUAL(0, utime(filename, &desired_time));
|
||||||
|
TEST_ASSERT_EQUAL(0, stat(filename, &achieved_stat));
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(desired_time.modtime, achieved_stat.st_mtime);
|
||||||
|
|
||||||
|
// current time
|
||||||
|
TEST_ASSERT_EQUAL(0, utime(filename, NULL));
|
||||||
|
TEST_ASSERT_EQUAL(0, stat(filename, &achieved_stat));
|
||||||
|
printf("Mod. time changed to (false actual time): %s", ctime(&achieved_stat.st_mtime));
|
||||||
|
TEST_ASSERT_NOT_EQUAL(desired_time.modtime, achieved_stat.st_mtime);
|
||||||
|
TEST_ASSERT(false_now - achieved_stat.st_mtime <= 2); // two seconds of tolerance are given
|
||||||
|
|
||||||
|
// 23:59:08. December 31st, 2037
|
||||||
|
desired_tm.tm_mon = 12 - 1;
|
||||||
|
desired_tm.tm_mday = 31;
|
||||||
|
desired_tm.tm_year = 2037 - 1900;
|
||||||
|
desired_tm.tm_hour = 23;
|
||||||
|
desired_tm.tm_min = 59;
|
||||||
|
desired_tm.tm_sec = 8;
|
||||||
|
printf("Testing mod. time: %s", asctime(&desired_tm));
|
||||||
|
desired_time.modtime = mktime(&desired_tm);
|
||||||
|
TEST_ASSERT_EQUAL(0, utime(filename, &desired_time));
|
||||||
|
TEST_ASSERT_EQUAL(0, stat(filename, &achieved_stat));
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(desired_time.modtime, achieved_stat.st_mtime);
|
||||||
|
|
||||||
|
//WARNING: it has the Unix Millenium bug (Y2K38)
|
||||||
|
|
||||||
|
// 00:00:00. January 1st, 1970 - FATFS cannot handle years before 1980
|
||||||
|
desired_tm.tm_mon = 1 - 1;
|
||||||
|
desired_tm.tm_mday = 1;
|
||||||
|
desired_tm.tm_year = 1970 - 1900;
|
||||||
|
desired_tm.tm_hour = 0;
|
||||||
|
desired_tm.tm_min = 0;
|
||||||
|
desired_tm.tm_sec = 0;
|
||||||
|
printf("Testing mod. time: %s", asctime(&desired_tm));
|
||||||
|
desired_time.modtime = mktime(&desired_tm);
|
||||||
|
TEST_ASSERT_EQUAL(-1, utime(filename, &desired_time));
|
||||||
|
TEST_ASSERT_EQUAL(EINVAL, errno);
|
||||||
|
}
|
||||||
|
|
||||||
void test_fatfs_unlink(const char* filename)
|
void test_fatfs_unlink(const char* filename)
|
||||||
{
|
{
|
||||||
test_fatfs_create_file_with_text(filename, "unlink\n");
|
test_fatfs_create_file_with_text(filename, "unlink\n");
|
||||||
|
@ -49,6 +49,8 @@ void test_fatfs_truncate_file(const char* path);
|
|||||||
|
|
||||||
void test_fatfs_stat(const char* filename, const char* root_dir);
|
void test_fatfs_stat(const char* filename, const char* root_dir);
|
||||||
|
|
||||||
|
void test_fatfs_utime(const char* filename, const char* root_dir);
|
||||||
|
|
||||||
void test_fatfs_unlink(const char* filename);
|
void test_fatfs_unlink(const char* filename);
|
||||||
|
|
||||||
void test_fatfs_link_rename(const char* filename_prefix);
|
void test_fatfs_link_rename(const char* filename_prefix);
|
||||||
|
@ -116,6 +116,13 @@ TEST_CASE("(SD) stat returns correct values", "[fatfs][test_env=UT_T1_SDMODE]")
|
|||||||
test_teardown();
|
test_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("(SD) utime sets modification time", "[fatfs][test_env=UT_T1_SDMODE]")
|
||||||
|
{
|
||||||
|
test_setup();
|
||||||
|
test_fatfs_utime("/sdcard/utime.txt", "/sdcard");
|
||||||
|
test_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("(SD) unlink removes a file", "[fatfs][test_env=UT_T1_SDMODE]")
|
TEST_CASE("(SD) unlink removes a file", "[fatfs][test_env=UT_T1_SDMODE]")
|
||||||
{
|
{
|
||||||
test_setup();
|
test_setup();
|
||||||
|
@ -110,6 +110,13 @@ TEST_CASE("(WL) stat returns correct values", "[fatfs][wear_levelling]")
|
|||||||
test_teardown();
|
test_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("(WL) utime sets modification time", "[fatfs][wear_levelling]")
|
||||||
|
{
|
||||||
|
test_setup();
|
||||||
|
test_fatfs_utime("/spiflash/utime.txt", "/spiflash");
|
||||||
|
test_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("(WL) unlink removes a file", "[fatfs][wear_levelling]")
|
TEST_CASE("(WL) unlink removes a file", "[fatfs][wear_levelling]")
|
||||||
{
|
{
|
||||||
test_setup();
|
test_setup();
|
||||||
|
@ -6,6 +6,7 @@ set(COMPONENT_SRCS "locks.c"
|
|||||||
"syscall_table.c"
|
"syscall_table.c"
|
||||||
"syscalls.c"
|
"syscalls.c"
|
||||||
"termios.c"
|
"termios.c"
|
||||||
|
"utime.c"
|
||||||
"time.c")
|
"time.c")
|
||||||
set(COMPONENT_ADD_INCLUDEDIRS platform_include include)
|
set(COMPONENT_ADD_INCLUDEDIRS platform_include include)
|
||||||
|
|
||||||
|
35
components/newlib/platform_include/sys/utime.h
Normal file
35
components/newlib/platform_include/sys/utime.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef _UTIME_H_
|
||||||
|
#define _UTIME_H_
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct utimbuf {
|
||||||
|
time_t actime; // access time
|
||||||
|
time_t modtime; // modification time
|
||||||
|
};
|
||||||
|
|
||||||
|
int utime(const char *path, const struct utimbuf *times);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _UTIME_H_ */
|
21
components/newlib/utime.c
Normal file
21
components/newlib/utime.c
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <utime.h>
|
||||||
|
#include "esp_vfs.h"
|
||||||
|
|
||||||
|
int utime(const char *path, const struct utimbuf *times)
|
||||||
|
{
|
||||||
|
return esp_vfs_utime(path, times);
|
||||||
|
}
|
@ -71,6 +71,7 @@ static int vfs_spiffs_mkdir(void* ctx, const char* name, mode_t mode);
|
|||||||
static int vfs_spiffs_rmdir(void* ctx, const char* name);
|
static int vfs_spiffs_rmdir(void* ctx, const char* name);
|
||||||
static void vfs_spiffs_update_mtime(spiffs *fs, spiffs_file f);
|
static void vfs_spiffs_update_mtime(spiffs *fs, spiffs_file f);
|
||||||
static time_t vfs_spiffs_get_mtime(const spiffs_stat* s);
|
static time_t vfs_spiffs_get_mtime(const spiffs_stat* s);
|
||||||
|
static int vfs_spiffs_utime(void *ctx, const char *path, const struct utimbuf *times);
|
||||||
|
|
||||||
static esp_spiffs_t * _efs[CONFIG_SPIFFS_MAX_PARTITIONS];
|
static esp_spiffs_t * _efs[CONFIG_SPIFFS_MAX_PARTITIONS];
|
||||||
|
|
||||||
@ -347,7 +348,12 @@ esp_err_t esp_vfs_spiffs_register(const esp_vfs_spiffs_conf_t * conf)
|
|||||||
.seekdir_p = &vfs_spiffs_seekdir,
|
.seekdir_p = &vfs_spiffs_seekdir,
|
||||||
.telldir_p = &vfs_spiffs_telldir,
|
.telldir_p = &vfs_spiffs_telldir,
|
||||||
.mkdir_p = &vfs_spiffs_mkdir,
|
.mkdir_p = &vfs_spiffs_mkdir,
|
||||||
.rmdir_p = &vfs_spiffs_rmdir
|
.rmdir_p = &vfs_spiffs_rmdir,
|
||||||
|
#ifdef CONFIG_SPIFFS_USE_MTIME
|
||||||
|
.utime_p = &vfs_spiffs_utime,
|
||||||
|
#else
|
||||||
|
.utime_p = NULL,
|
||||||
|
#endif // CONFIG_SPIFFS_USE_MTIME
|
||||||
};
|
};
|
||||||
|
|
||||||
esp_err_t err = esp_spiffs_init(conf);
|
esp_err_t err = esp_spiffs_init(conf);
|
||||||
@ -744,3 +750,49 @@ static time_t vfs_spiffs_get_mtime(const spiffs_stat* s)
|
|||||||
#endif
|
#endif
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SPIFFS_USE_MTIME
|
||||||
|
static int vfs_spiffs_update_mtime_value(spiffs *fs, const char *path, time_t t)
|
||||||
|
{
|
||||||
|
int ret = SPIFFS_OK;
|
||||||
|
spiffs_stat s;
|
||||||
|
if (CONFIG_SPIFFS_META_LENGTH > sizeof(t)) {
|
||||||
|
ret = SPIFFS_stat(fs, path, &s);
|
||||||
|
}
|
||||||
|
if (ret == SPIFFS_OK) {
|
||||||
|
memcpy(s.meta, &t, sizeof(t));
|
||||||
|
ret = SPIFFS_update_meta(fs, path, s.meta);
|
||||||
|
}
|
||||||
|
if (ret != SPIFFS_OK) {
|
||||||
|
ESP_LOGW(TAG, "Failed to update mtime (%d)", ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif //CONFIG_SPIFFS_USE_MTIME
|
||||||
|
|
||||||
|
#ifdef CONFIG_SPIFFS_USE_MTIME
|
||||||
|
static int vfs_spiffs_utime(void *ctx, const char *path, const struct utimbuf *times)
|
||||||
|
{
|
||||||
|
assert(path);
|
||||||
|
|
||||||
|
esp_spiffs_t *efs = (esp_spiffs_t *) ctx;
|
||||||
|
time_t t;
|
||||||
|
|
||||||
|
if (times) {
|
||||||
|
t = times->modtime;
|
||||||
|
} else {
|
||||||
|
// use current time
|
||||||
|
t = time(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = vfs_spiffs_update_mtime_value(efs->fs, path, t);
|
||||||
|
|
||||||
|
if (ret != SPIFFS_OK) {
|
||||||
|
errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs));
|
||||||
|
SPIFFS_clearerr(efs->fs);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif //CONFIG_SPIFFS_USE_MTIME
|
||||||
|
@ -649,4 +649,69 @@ TEST_CASE("mtime is updated when file is opened", "[spiffs]")
|
|||||||
|
|
||||||
test_teardown();
|
test_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("utime() works well", "[spiffs]")
|
||||||
|
{
|
||||||
|
const char filename[] = "/spiffs/utime.txt";
|
||||||
|
struct stat achieved_stat;
|
||||||
|
struct tm desired_tm;
|
||||||
|
struct utimbuf desired_time = {
|
||||||
|
.actime = 0, // access time is not supported
|
||||||
|
.modtime = 0,
|
||||||
|
};
|
||||||
|
time_t false_now = 0;
|
||||||
|
memset(&desired_tm, 0, sizeof(struct tm));
|
||||||
|
|
||||||
|
test_setup();
|
||||||
|
{
|
||||||
|
// Setting up a false actual time - used when the file is created and for modification with the current time
|
||||||
|
desired_tm.tm_mon = 10 - 1;
|
||||||
|
desired_tm.tm_mday = 31;
|
||||||
|
desired_tm.tm_year = 2018 - 1900;
|
||||||
|
desired_tm.tm_hour = 10;
|
||||||
|
desired_tm.tm_min = 35;
|
||||||
|
desired_tm.tm_sec = 23;
|
||||||
|
|
||||||
|
false_now = mktime(&desired_tm);
|
||||||
|
|
||||||
|
struct timeval now = { .tv_sec = false_now };
|
||||||
|
settimeofday(&now, NULL);
|
||||||
|
}
|
||||||
|
test_spiffs_create_file_with_text(filename, "");
|
||||||
|
|
||||||
|
// 00:00:00. January 1st, 1900
|
||||||
|
desired_tm.tm_mon = 1 - 1;
|
||||||
|
desired_tm.tm_mday = 1;
|
||||||
|
desired_tm.tm_year = 0;
|
||||||
|
desired_tm.tm_hour = 0;
|
||||||
|
desired_tm.tm_min = 0;
|
||||||
|
desired_tm.tm_sec = 0;
|
||||||
|
printf("Testing mod. time: %s", asctime(&desired_tm));
|
||||||
|
desired_time.modtime = mktime(&desired_tm);
|
||||||
|
TEST_ASSERT_EQUAL(0, utime(filename, &desired_time));
|
||||||
|
TEST_ASSERT_EQUAL(0, stat(filename, &achieved_stat));
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(desired_time.modtime, achieved_stat.st_mtime);
|
||||||
|
|
||||||
|
// 23:59:08. December 31st, 2145
|
||||||
|
desired_tm.tm_mon = 12 - 1;
|
||||||
|
desired_tm.tm_mday = 31;
|
||||||
|
desired_tm.tm_year = 2145 - 1900;
|
||||||
|
desired_tm.tm_hour = 23;
|
||||||
|
desired_tm.tm_min = 59;
|
||||||
|
desired_tm.tm_sec = 8;
|
||||||
|
printf("Testing mod. time: %s", asctime(&desired_tm));
|
||||||
|
desired_time.modtime = mktime(&desired_tm);
|
||||||
|
TEST_ASSERT_EQUAL(0, utime(filename, &desired_time));
|
||||||
|
TEST_ASSERT_EQUAL(0, stat(filename, &achieved_stat));
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(desired_time.modtime, achieved_stat.st_mtime);
|
||||||
|
|
||||||
|
// Current time
|
||||||
|
TEST_ASSERT_EQUAL(0, utime(filename, NULL));
|
||||||
|
TEST_ASSERT_EQUAL(0, stat(filename, &achieved_stat));
|
||||||
|
printf("Mod. time changed to (false actual time): %s", ctime(&achieved_stat.st_mtime));
|
||||||
|
TEST_ASSERT_NOT_EQUAL(desired_time.modtime, achieved_stat.st_mtime);
|
||||||
|
TEST_ASSERT(false_now - achieved_stat.st_mtime <= 2); // two seconds of tolerance are given
|
||||||
|
|
||||||
|
test_teardown();
|
||||||
|
}
|
||||||
#endif // CONFIG_SPIFFS_USE_MTIME
|
#endif // CONFIG_SPIFFS_USE_MTIME
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <utime.h>
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
@ -180,6 +181,10 @@ typedef struct
|
|||||||
int (*truncate_p)(void* ctx, const char *path, off_t length);
|
int (*truncate_p)(void* ctx, const char *path, off_t length);
|
||||||
int (*truncate)(const char *path, off_t length);
|
int (*truncate)(const char *path, off_t length);
|
||||||
};
|
};
|
||||||
|
union {
|
||||||
|
int (*utime_p)(void* ctx, const char *path, const struct utimbuf *times);
|
||||||
|
int (*utime)(const char *path, const struct utimbuf *times);
|
||||||
|
};
|
||||||
#ifdef CONFIG_SUPPORT_TERMIOS
|
#ifdef CONFIG_SUPPORT_TERMIOS
|
||||||
union {
|
union {
|
||||||
int (*tcsetattr_p)(void *ctx, int fd, int optional_actions, const struct termios *p);
|
int (*tcsetattr_p)(void *ctx, int fd, int optional_actions, const struct termios *p);
|
||||||
@ -330,6 +335,7 @@ int esp_vfs_stat(struct _reent *r, const char * path, struct stat * st);
|
|||||||
int esp_vfs_link(struct _reent *r, const char* n1, const char* n2);
|
int esp_vfs_link(struct _reent *r, const char* n1, const char* n2);
|
||||||
int esp_vfs_unlink(struct _reent *r, const char *path);
|
int esp_vfs_unlink(struct _reent *r, const char *path);
|
||||||
int esp_vfs_rename(struct _reent *r, const char *src, const char *dst);
|
int esp_vfs_rename(struct _reent *r, const char *src, const char *dst);
|
||||||
|
int esp_vfs_utime(const char *path, const struct utimbuf *times);
|
||||||
/**@}*/
|
/**@}*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1094,3 +1094,17 @@ int tcsendbreak(int fd, int duration)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif // CONFIG_SUPPORT_TERMIOS
|
#endif // CONFIG_SUPPORT_TERMIOS
|
||||||
|
|
||||||
|
int esp_vfs_utime(const char *path, const struct utimbuf *times)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
const vfs_entry_t* vfs = get_vfs_for_path(path);
|
||||||
|
struct _reent* r = __getreent();
|
||||||
|
if (vfs == NULL) {
|
||||||
|
__errno_r(r) = ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
const char* path_within_vfs = translate_path(vfs, path);
|
||||||
|
CHECK_AND_CALL(ret, r, vfs, utime, path_within_vfs, times);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user