forked from espressif/esp-idf
Merge branch 'fix/unopened_stdout_console' into 'master'
fix(newlib/stdio): incorrect stdout redirect with /dev/console Closes IDFGH-12416 See merge request espressif/esp-idf!30324
This commit is contained in:
@@ -50,6 +50,7 @@ CORE: 105: init_newlib_time in components/esp_system/startup_funcs.c on BIT(0)
|
||||
CORE: 110: init_vfs_uart in components/esp_driver_uart/src/uart_vfs.c on BIT(0)
|
||||
CORE: 111: init_vfs_usj in components/esp_driver_usb_serial_jtag/src/usb_serial_jtag_vfs.c on BIT(0)
|
||||
CORE: 112: init_vfs_usj_sec in components/esp_driver_usb_serial_jtag/src/usb_serial_jtag_vfs.c on BIT(0)
|
||||
CORE: 113: init_vfs_nullfs in components/vfs/nullfs.c on BIT(0)
|
||||
CORE: 114: init_vfs_console in components/esp_vfs_console/vfs_console.c on BIT(0)
|
||||
CORE: 115: init_newlib_stdio in components/newlib/newlib_init.c on BIT(0)
|
||||
|
||||
|
@@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_rom_uart.h"
|
||||
@@ -15,6 +16,9 @@
|
||||
#include "driver/uart.h"
|
||||
#include "soc/uart_channel.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_NONE
|
||||
/* Set up UART on UART_0 (console) to be able to
|
||||
notify pytest test case that app booted successfully
|
||||
@@ -49,6 +53,15 @@ void app_main(void)
|
||||
{
|
||||
printf("Hello World\n");
|
||||
|
||||
int fd = open("/dev/null", O_RDWR);
|
||||
assert(fd >= 0 && "Could not open file"); // Standard check
|
||||
|
||||
// Check if correct file descriptor is returned
|
||||
// In this case it should be neither of 0, 1, 2 (== stdin, stdout, stderr)
|
||||
assert(fd > 2 && "Incorrect file descriptor returned, stdin, stdout, stderr were not correctly assigned");
|
||||
|
||||
close(fd);
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_NONE
|
||||
console_none_print();
|
||||
#endif // CONFIG_ESP_CONSOLE_NONE
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#include "esp_vfs_console.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_private/startup_internal.h"
|
||||
#include "esp_vfs_null.h"
|
||||
|
||||
#define STRINGIFY(s) STRINGIFY2(s)
|
||||
#define STRINGIFY2(s) #s
|
||||
@@ -52,6 +53,8 @@ int console_open(const char * path, int flags, int mode)
|
||||
vfs_console.fd_primary = open("/dev/usbserjtag", flags, mode);
|
||||
#elif CONFIG_ESP_CONSOLE_USB_CDC
|
||||
vfs_console.fd_primary = open("/dev/cdcacm", flags, mode);
|
||||
#else
|
||||
vfs_console.fd_primary = open("/dev/null", flags, mode);
|
||||
#endif
|
||||
|
||||
// Secondary port open
|
||||
@@ -207,13 +210,14 @@ esp_err_t esp_vfs_console_register(void)
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
primary_vfs = esp_vfs_null_get_vfs();
|
||||
#endif
|
||||
|
||||
// Secondary vfs part.
|
||||
#if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
|
||||
secondary_vfs = esp_vfs_usb_serial_jtag_get_vfs();
|
||||
#endif
|
||||
|
||||
err = esp_vfs_dev_console_register();
|
||||
return err;
|
||||
}
|
||||
|
@@ -200,7 +200,7 @@ void esp_newlib_init_global_stdio(const char *stdio_dev)
|
||||
|
||||
ESP_SYSTEM_INIT_FN(init_newlib_stdio, CORE, BIT(0), 115)
|
||||
{
|
||||
#if defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_NONE)
|
||||
#if defined(CONFIG_VFS_SUPPORT_IO)
|
||||
esp_newlib_init_global_stdio("/dev/console");
|
||||
#else
|
||||
esp_newlib_init_global_stdio(NULL);
|
||||
|
@@ -7,6 +7,7 @@ endif()
|
||||
list(APPEND sources "vfs.c"
|
||||
"vfs_eventfd.c"
|
||||
"vfs_semihost.c"
|
||||
"nullfs.c"
|
||||
)
|
||||
|
||||
list(APPEND pr esp_timer
|
||||
@@ -23,3 +24,6 @@ idf_component_register(SRCS ${sources}
|
||||
# Some newlib syscalls are implemented in vfs.c, make sure these are always
|
||||
# seen by the linker
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u vfs_include_syscalls_impl")
|
||||
|
||||
# Make sure nullfs is registered
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_vfs_include_nullfs_register")
|
||||
|
@@ -97,4 +97,11 @@ menu "Virtual file system"
|
||||
Define maximum number of host filesystem mount points.
|
||||
endmenu
|
||||
|
||||
config VFS_INITIALIZE_DEV_NULL
|
||||
bool "Initialize /dev/null VFS"
|
||||
default y
|
||||
depends on VFS_SUPPORT_IO
|
||||
help
|
||||
If enabled, /dev/null VFS will be automatically initialized at startup.
|
||||
|
||||
endmenu
|
||||
|
31
components/vfs/include/esp_vfs_null.h
Normal file
31
components/vfs/include/esp_vfs_null.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "esp_vfs.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get VFS structure for /dev/null
|
||||
*
|
||||
* @return VFS structure for /dev/null
|
||||
*/
|
||||
const esp_vfs_t *esp_vfs_null_get_vfs(void);
|
||||
|
||||
/**
|
||||
* @brief Register filesystem for /dev/null
|
||||
*
|
||||
* @return ESP_OK on success; any other value indicates an error
|
||||
*/
|
||||
esp_err_t esp_vfs_null_register(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
323
components/vfs/nullfs.c
Normal file
323
components/vfs/nullfs.c
Normal file
@@ -0,0 +1,323 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include "esp_vfs.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_private/startup_internal.h"
|
||||
|
||||
#include "esp_vfs_null.h"
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
typedef enum {
|
||||
VFS_NULL_CLOSED = 0,
|
||||
VFS_NULL_READ = 1 << 0,
|
||||
VFS_NULL_WRITE = 1 << 1,
|
||||
} vfs_null_flags_t;
|
||||
|
||||
typedef uint32_t vfs_null_ctx_t;
|
||||
#define VFS_NULL_MAX_FDS (sizeof(vfs_null_ctx_t) * 4)
|
||||
|
||||
#define GET_FLAGS(ctx, fd) ((ctx >> (fd * 2)) & 0x3)
|
||||
#define SET_FLAGS(ctx, fd, flags) (ctx |= (flags << (fd * 2)))
|
||||
|
||||
#define WRITABLE(ctx, fd) (GET_FLAGS(ctx, fd) & VFS_NULL_WRITE)
|
||||
#define READABLE(ctx, fd) (GET_FLAGS(ctx, fd) & VFS_NULL_READ)
|
||||
|
||||
#define SET_WRITABLE(ctx, fd) SET_FLAGS(ctx, fd, VFS_NULL_WRITE)
|
||||
#define SET_READABLE(ctx, fd) SET_FLAGS(ctx, fd, VFS_NULL_READ)
|
||||
|
||||
#define FD_IN_RANGE(fd) (fd >= 0 && fd < VFS_NULL_MAX_FDS)
|
||||
#define IS_FD_VALID(fd) (FD_IN_RANGE(fd) && GET_FLAGS(g_fds, fd) != VFS_NULL_CLOSED)
|
||||
|
||||
#ifdef CONFIG_ESP_CONSOLE_NONE // Prevents recursive logging
|
||||
static const char* TAG = "nullfs";
|
||||
#define NULLFS_LOGD(TAG, fmt, ...) ESP_LOGD(TAG, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define NULLFS_LOGD(TAG, fmt, ...)
|
||||
#endif
|
||||
|
||||
static vfs_null_ctx_t g_fds = 0;
|
||||
|
||||
static ssize_t vfs_null_write(int fd, const void *data, size_t size);
|
||||
static off_t vfs_null_lseek(int fd, off_t offset, int whence);
|
||||
static ssize_t vfs_null_read(int fd, void *data, size_t size);
|
||||
static ssize_t vfs_null_pread(int fd, void *data, size_t size, off_t offset);
|
||||
static ssize_t vfs_null_pwrite(int fd, const void *data, size_t size, off_t offset);
|
||||
static int vfs_null_open(const char* path, int flags, int mode);
|
||||
static int vfs_null_close(int fd);
|
||||
static int vfs_null_fstat(int fd, struct stat *st);
|
||||
#if CONFIG_VFS_SUPPORT_DIR
|
||||
static int vfs_null_stat(const char* path, struct stat *st);
|
||||
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||
static int vfs_null_fcntl(int fd, int cmd, int arg);
|
||||
static int vfs_null_ioctl(int fd, int cmd, va_list args);
|
||||
static int vfs_null_fsync(int fd);
|
||||
|
||||
static const esp_vfs_t s_vfs_null = {
|
||||
.flags = ESP_VFS_FLAG_DEFAULT,
|
||||
.write = &vfs_null_write,
|
||||
.lseek = &vfs_null_lseek,
|
||||
.read = &vfs_null_read,
|
||||
.pread = &vfs_null_pread,
|
||||
.pwrite = &vfs_null_pwrite,
|
||||
.open = &vfs_null_open,
|
||||
.close = &vfs_null_close,
|
||||
.fstat = &vfs_null_fstat,
|
||||
#if CONFIG_VFS_SUPPORT_DIR
|
||||
.stat = &vfs_null_stat,
|
||||
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||
.fcntl = &vfs_null_fcntl,
|
||||
.ioctl = &vfs_null_ioctl,
|
||||
.fsync = &vfs_null_fsync,
|
||||
};
|
||||
|
||||
const esp_vfs_t *esp_vfs_null_get_vfs(void)
|
||||
{
|
||||
return &s_vfs_null;
|
||||
}
|
||||
|
||||
esp_err_t esp_vfs_null_register(void)
|
||||
{
|
||||
return esp_vfs_register("/dev/null", &s_vfs_null, NULL);
|
||||
}
|
||||
|
||||
static ssize_t vfs_null_write(int fd, const void *data, size_t size)
|
||||
{
|
||||
UNUSED(data);
|
||||
|
||||
if (FD_IN_RANGE(fd) && WRITABLE(g_fds, fd)) {
|
||||
return size;
|
||||
}
|
||||
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static off_t vfs_null_lseek(int fd, off_t offset, int whence)
|
||||
{
|
||||
UNUSED(offset);
|
||||
|
||||
if (!IS_FD_VALID(fd)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
case SEEK_CUR:
|
||||
case SEEK_END:
|
||||
return 0;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t vfs_null_read(int fd, void *data, size_t size)
|
||||
{
|
||||
UNUSED(data);
|
||||
|
||||
NULLFS_LOGD(TAG, "read %u bytes", size);
|
||||
|
||||
if (FD_IN_RANGE(fd) && READABLE(g_fds, fd)) {
|
||||
return 0; // EOF
|
||||
}
|
||||
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int vfs_null_pread(int fd, void *data, size_t size, off_t offset)
|
||||
{
|
||||
UNUSED(data);
|
||||
UNUSED(size);
|
||||
UNUSED(offset);
|
||||
|
||||
NULLFS_LOGD(TAG, "pread %u bytes at offset %ld", size, offset);
|
||||
|
||||
if (!FD_IN_RANGE(fd) || !READABLE(g_fds, fd)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0; // EOF
|
||||
|
||||
}
|
||||
|
||||
static int vfs_null_pwrite(int fd, const void *data, size_t size, off_t offset)
|
||||
{
|
||||
UNUSED(data);
|
||||
UNUSED(offset);
|
||||
|
||||
NULLFS_LOGD(TAG, "pwrite %u bytes at offset %ld", size, offset);
|
||||
|
||||
if (!FD_IN_RANGE(fd) || !WRITABLE(g_fds, fd)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int vfs_null_get_empty_fd(void)
|
||||
{
|
||||
for (int i = 0; i < VFS_NULL_MAX_FDS; i++) {
|
||||
if (GET_FLAGS(g_fds, i) == VFS_NULL_CLOSED) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int vfs_null_open(const char* path, int flags, int mode)
|
||||
{
|
||||
UNUSED(mode);
|
||||
|
||||
NULLFS_LOGD(TAG, "open %s, flags %d", path, flags);
|
||||
|
||||
// Possibly check if the flags are valid
|
||||
|
||||
if (strcmp(path, "/") != 0) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fd = vfs_null_get_empty_fd();
|
||||
if (fd == -1) {
|
||||
errno = EMFILE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & O_RDWR) {
|
||||
SET_READABLE(g_fds, fd);
|
||||
SET_WRITABLE(g_fds, fd);
|
||||
} else if (flags & O_WRONLY) {
|
||||
SET_WRITABLE(g_fds, fd);
|
||||
} else if (flags & O_RDONLY) {
|
||||
SET_READABLE(g_fds, fd);
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int vfs_null_close(int fd)
|
||||
{
|
||||
if (!FD_IN_RANGE(fd)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
SET_FLAGS(g_fds, fd, VFS_NULL_CLOSED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vfs_null_fstat(int fd, struct stat *st)
|
||||
{
|
||||
if (!FD_IN_RANGE(fd)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(st, 0, sizeof(struct stat));
|
||||
st->st_mode = S_IFCHR | 0666; // Special character device with read/write permissions for everyone
|
||||
st->st_nlink = 1;
|
||||
st->st_uid = 0;
|
||||
st->st_gid = 0;
|
||||
st->st_size = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_VFS_SUPPORT_DIR
|
||||
|
||||
static int vfs_null_stat(const char* path, struct stat *st)
|
||||
{
|
||||
if (strcmp(path, "/") != 0) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(st, 0, sizeof(struct stat));
|
||||
st->st_mode = S_IFCHR | 0666; // Special character device with read/write permissions for everyone
|
||||
st->st_nlink = 1;
|
||||
st->st_uid = 0;
|
||||
st->st_gid = 0;
|
||||
st->st_size = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||
|
||||
static int vfs_null_fcntl(int fd, int cmd, int arg)
|
||||
{
|
||||
UNUSED(arg);
|
||||
|
||||
if (!FD_IN_RANGE(fd)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
default:
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int vfs_null_ioctl(int fd, int cmd, va_list args)
|
||||
{
|
||||
UNUSED(args);
|
||||
|
||||
if (!FD_IN_RANGE(fd)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
default:
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int vfs_null_fsync(int fd)
|
||||
{
|
||||
if (!FD_IN_RANGE(fd)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_VFS_INITIALIZE_DEV_NULL) || defined(CONFIG_ESP_CONSOLE_NONE)
|
||||
ESP_SYSTEM_INIT_FN(init_vfs_nullfs, CORE, BIT(0), 113)
|
||||
{
|
||||
return esp_vfs_null_register();
|
||||
}
|
||||
#endif // CONFIG_VFS_INITIALIZE_DEV_NULL
|
||||
|
||||
void esp_vfs_include_nullfs_register(void)
|
||||
{
|
||||
// Linker hook function, exists to make the linker examine this file
|
||||
}
|
@@ -2,7 +2,7 @@ set(src "test_app_main.c" "test_vfs_access.c"
|
||||
"test_vfs_append.c" "test_vfs_eventfd.c"
|
||||
"test_vfs_fd.c" "test_vfs_lwip.c"
|
||||
"test_vfs_open.c" "test_vfs_paths.c"
|
||||
"test_vfs_select.c"
|
||||
"test_vfs_select.c" "test_vfs_nullfs.c"
|
||||
)
|
||||
|
||||
idf_component_register(SRCS ${src}
|
||||
|
138
components/vfs/test_apps/main/test_vfs_nullfs.c
Normal file
138
components/vfs/test_apps/main/test_vfs_nullfs.c
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "unity.h"
|
||||
#include "esp_vfs.h"
|
||||
|
||||
#include "esp_vfs_null.h"
|
||||
#include "unity_test_runner.h"
|
||||
|
||||
TEST_CASE("Can open and close /dev/null", "[vfs_nullfs]")
|
||||
{
|
||||
int fd = open("/dev/null", O_RDWR);
|
||||
TEST_ASSERT(fd >= 0);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
TEST_CASE("Can write to /dev/null", "[vfs_nullfs]")
|
||||
{
|
||||
int fd = open("/dev/null", O_RDWR);
|
||||
TEST_ASSERT(fd >= 0);
|
||||
|
||||
// Can write to /dev/null
|
||||
ssize_t ret = write(fd, "hello", 5);
|
||||
TEST_ASSERT_EQUAL(5, ret);
|
||||
|
||||
// Write does not change the file offset
|
||||
off_t offset = lseek(fd, 0, SEEK_CUR);
|
||||
TEST_ASSERT_EQUAL(0, offset);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
TEST_CASE("Can read from /dev/null", "[vfs_nullfs]")
|
||||
{
|
||||
int fd = open("/dev/null", O_RDWR);
|
||||
TEST_ASSERT(fd >= 0);
|
||||
|
||||
// Can read from /dev/null
|
||||
char buf[5] = {0};
|
||||
ssize_t ret = read(fd, buf, 5);
|
||||
|
||||
// Read always returns 0 bytes -> EOF
|
||||
TEST_ASSERT_EQUAL(0, ret);
|
||||
|
||||
// Read does not modify the buffer
|
||||
for (int i = 0; i < 5; i++) {
|
||||
TEST_ASSERT_EQUAL(0, buf[i]);
|
||||
}
|
||||
|
||||
// Read does not change the file offset
|
||||
off_t offset = lseek(fd, 0, SEEK_CUR);
|
||||
TEST_ASSERT_EQUAL(0, offset);
|
||||
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
TEST_CASE("Can lseek /dev/null", "[vfs_nullfs]")
|
||||
{
|
||||
int fd = open("/dev/null", O_RDWR);
|
||||
TEST_ASSERT(fd >= 0);
|
||||
|
||||
off_t offset = lseek(fd, 0, SEEK_SET);
|
||||
TEST_ASSERT_EQUAL(0, offset);
|
||||
|
||||
offset = lseek(fd, 0, SEEK_CUR);
|
||||
TEST_ASSERT_EQUAL(0, offset);
|
||||
|
||||
offset = lseek(fd, 0, SEEK_END);
|
||||
TEST_ASSERT_EQUAL(0, offset);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
TEST_CASE("Can fstat /dev/null", "[vfs_nullfs]")
|
||||
{
|
||||
int fd = open("/dev/null", O_RDWR);
|
||||
TEST_ASSERT(fd >= 0);
|
||||
|
||||
struct stat st;
|
||||
int ret = fstat(fd, &st);
|
||||
TEST_ASSERT_EQUAL(0, ret);
|
||||
|
||||
TEST_ASSERT_EQUAL(0, st.st_size);
|
||||
TEST_ASSERT_EQUAL(S_IFCHR, st.st_mode & S_IFMT);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
TEST_CASE("Can fsync /dev/null", "[vfs_nullfs]")
|
||||
{
|
||||
int fd = open("/dev/null", O_RDWR);
|
||||
TEST_ASSERT(fd >= 0);
|
||||
|
||||
int ret = fsync(fd);
|
||||
TEST_ASSERT_EQUAL(0, ret);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
TEST_CASE("Can pread /dev/null", "[vfs_nullfs]")
|
||||
{
|
||||
int fd = open("/dev/null", O_RDWR);
|
||||
TEST_ASSERT(fd >= 0);
|
||||
|
||||
char buf[5] = {0};
|
||||
ssize_t ret = pread(fd, buf, 5, 0);
|
||||
TEST_ASSERT_EQUAL(0, ret);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
TEST_CASE("Can pwrite /dev/null", "[vfs_nullfs]")
|
||||
{
|
||||
int fd = open("/dev/null", O_RDWR);
|
||||
TEST_ASSERT(fd >= 0);
|
||||
|
||||
ssize_t ret = pwrite(fd, "hello", 5, 0);
|
||||
TEST_ASSERT_EQUAL(5, ret);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
TEST_CASE("Can stat /dev/null", "[vfs_nullfs]")
|
||||
{
|
||||
struct stat st;
|
||||
int ret = stat("/dev/null", &st);
|
||||
TEST_ASSERT_EQUAL(0, ret);
|
||||
|
||||
TEST_ASSERT_EQUAL(0, st.st_size);
|
||||
TEST_ASSERT_EQUAL(S_IFCHR, st.st_mode & S_IFMT);
|
||||
}
|
@@ -305,6 +305,7 @@ INPUT = \
|
||||
$(PROJECT_PATH)/components/vfs/include/esp_vfs_dev.h \
|
||||
$(PROJECT_PATH)/components/vfs/include/esp_vfs_eventfd.h \
|
||||
$(PROJECT_PATH)/components/vfs/include/esp_vfs_semihost.h \
|
||||
$(PROJECT_PATH)/components/vfs/include/esp_vfs_null.h \
|
||||
$(PROJECT_PATH)/components/vfs/include/esp_vfs.h \
|
||||
$(PROJECT_PATH)/components/wear_levelling/include/wear_levelling.h \
|
||||
$(PROJECT_PATH)/components/wifi_provisioning/include/wifi_provisioning/manager.h \
|
||||
|
@@ -238,3 +238,5 @@ API Reference
|
||||
.. include-build-file:: inc/uart_vfs.inc
|
||||
|
||||
.. include-build-file:: inc/esp_vfs_eventfd.inc
|
||||
|
||||
.. include-build-file:: inc/esp_vfs_null.inc
|
||||
|
@@ -238,3 +238,5 @@ API 参考
|
||||
.. include-build-file:: inc/uart_vfs.inc
|
||||
|
||||
.. include-build-file:: inc/esp_vfs_eventfd.inc
|
||||
|
||||
.. include-build-file:: inc/esp_vfs_null.inc
|
||||
|
Reference in New Issue
Block a user