Merge pull request #5616 from gebart/pr/vfs

vfs: file system abstraction
pr/rotary
Joakim Nohlgård 6 years ago committed by GitHub
commit 887cc72365

@ -597,6 +597,20 @@ ifneq (,$(filter emcute,$(USEMODULE)))
USEMODULE += xtimer
endif
ifneq (,$(filter constfs,$(USEMODULE)))
USEMODULE += vfs
endif
ifneq (,$(filter devfs,$(USEMODULE)))
USEMODULE += vfs
endif
ifneq (,$(filter vfs,$(USEMODULE)))
ifeq (native, $(BOARD))
USEMODULE += native_vfs
endif
endif
# include package dependencies
-include $(USEPKG:%=$(RIOTPKG)/%/Makefile.dep)

@ -6,12 +6,10 @@ ifneq (,$(filter saul_default,$(USEMODULE)))
USEMODULE += lis3dh
endif
# The RTT clock drives the core clock in the default configuration
FEATURES_REQUIRED += periph_rtt
# The Mulle uses NVRAM to store persistent variables, such as boot count.
USEMODULE += nvram_spi
FEATURES_REQUIRED += periph_spi
USEMODULE += nvram
USEMODULE += devfs
ifneq (,$(filter saul_default,$(USEMODULE)))
USEMODULE += saul_gpio

@ -24,11 +24,13 @@
#include "cpu.h"
#include "mcg.h"
#include "periph/gpio.h"
#include "periph/uart.h"
#include "periph/rtt.h"
#include "periph/spi.h"
#include "nvram-spi.h"
#include "nvram.h"
#include "xtimer.h"
#include "vfs.h"
#include "fs/devfs.h"
static nvram_t mulle_nvram_dev;
nvram_t *mulle_nvram = &mulle_nvram_dev;
@ -39,6 +41,12 @@ static nvram_spi_params_t nvram_spi_params = {
.address_count = MULLE_NVRAM_SPI_ADDRESS_COUNT,
};
static devfs_t mulle_nvram_devfs = {
.path = "/mulle-fram",
.f_op = &nvram_vfs_ops,
.private_data = &mulle_nvram_dev,
};
/** @brief Initialize the GPIO pins controlling the power switches. */
static inline void power_pins_init(void);
@ -210,6 +218,10 @@ static int mulle_nvram_init(void)
return -5;
}
}
/* Register DevFS node */
devfs_register(&mulle_nvram_devfs);
return 0;
}

@ -101,8 +101,8 @@
#ifndef TIME_H
#define TIME_H
#include <inttypes.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
@ -111,12 +111,6 @@ extern "C" {
/** \ingroup avr_time */
/* @{ */
/**
time_t represents seconds elapsed from Midnight, Jan 1 2000 UTC (the Y2K 'epoch').
Its range allows this implementation to represent time up to Tue Feb 7 06:28:15 2136 UTC.
*/
typedef uint32_t time_t;
/**
The time function returns the systems current time stamp.
If timer is not a null pointer, the return value is also assigned to the object it points to.

@ -1,4 +1,5 @@
/*
* Copyright (C) 2016 Eistec AB
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
@ -9,21 +10,98 @@
#ifndef UNISTD_H
#define UNISTD_H
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define STDIN_FILENO 0 ///< stdin file descriptor
#define STDOUT_FILENO 1 ///< stdout file descriptor
#define STDERR_FILENO 2 ///< stderr file descriptor
#define STDIN_FILENO 0 /* standard input file descriptor */
#define STDOUT_FILENO 1 /* standard output file descriptor */
#define STDERR_FILENO 2 /* standard error file descriptor */
int close(int fildes);
#define F_OK 0
#define R_OK 4
#define W_OK 2
#define X_OK 1
typedef uint32_t useconds_t;
int usleep(useconds_t usec);
unsigned int sleep(unsigned int seconds);
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
int access(const char *, int);
unsigned alarm(unsigned);
int chdir(const char *);
int chown(const char *, uid_t, gid_t);
int close(int);
size_t confstr(int, char *, size_t);
int dup(int);
int dup2(int, int);
void _exit(int);
int execl(const char *, const char *, ...);
int execle(const char *, const char *, ...);
int execlp(const char *, const char *, ...);
int execv(const char *, char *const []);
int execve(const char *, char *const [], char *const []);
int execvp(const char *, char *const []);
int faccessat(int, const char *, int, int);
int fchdir(int);
int fchown(int, uid_t, gid_t);
int fchownat(int, const char *, uid_t, gid_t, int);
int fexecve(int, char *const [], char *const []);
pid_t fork(void);
long fpathconf(int, int);
int ftruncate(int, off_t);
char *getcwd(char *, size_t);
gid_t getegid(void);
uid_t geteuid(void);
gid_t getgid(void);
int getgroups(int, gid_t []);
int gethostname(char *, size_t);
char *getlogin(void);
int getlogin_r(char *, size_t);
int getopt(int, char * const [], const char *);
pid_t getpgid(pid_t);
pid_t getpgrp(void);
pid_t getpid(void);
pid_t getppid(void);
pid_t getsid(pid_t);
uid_t getuid(void);
int isatty(int);
int lchown(const char *, uid_t, gid_t);
int link(const char *, const char *);
int linkat(int, const char *, int, const char *, int);
off_t lseek(int, off_t, int);
long pathconf(const char *, int);
int pause(void);
int pipe(int [2]);
ssize_t pread(int, void *, size_t, off_t);
ssize_t pwrite(int, const void *, size_t, off_t);
ssize_t read(int, void *, size_t);
ssize_t readlink(const char *restrict, char *restrict, size_t);
ssize_t readlinkat(int, const char *restrict, char *restrict, size_t);
int rmdir(const char *);
int setegid(gid_t);
int seteuid(uid_t);
int setgid(gid_t);
int setpgid(pid_t, pid_t);
pid_t setsid(void);
int setuid(uid_t);
unsigned sleep(unsigned);
int symlink(const char *, const char *);
int symlinkat(const char *, int, const char *);
long sysconf(int);
pid_t tcgetpgrp(int);
int tcsetpgrp(int, pid_t);
int truncate(const char *, off_t);
char *ttyname(int);
int ttyname_r(int, char *, size_t);
int unlink(const char *);
int unlinkat(int, const char *, int);
int usleep(useconds_t);
ssize_t write(int, const void *, size_t);
#ifdef __cplusplus
}

@ -0,0 +1,120 @@
/*
* Copyright (C) 2016 Eistec AB
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @file
* @brief POSIX compatible sys/stat.h definitions
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
*/
#ifndef SYS_STAT_H_
#define SYS_STAT_H_
#include <time.h> /* for struct timespec */
#include <sys/types.h> /* for fsblkcnt_t, fsfilcnt_t */
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief File information
*/
struct stat {
dev_t st_dev; /**< Device ID of device containing file. */
ino_t st_ino; /**< File serial number. */
mode_t st_mode; /**< Mode of file (see below). */
nlink_t st_nlink; /**< Number of hard links to the file. */
uid_t st_uid; /**< User ID of file. */
gid_t st_gid; /**< Group ID of file. */
dev_t st_rdev; /**< Device ID (if file is character or block special). */
/**
* For regular files, the file size in bytes.
* For symbolic links, the length in bytes of the pathname contained in the
* symbolic link.
* For a shared memory object, the length in bytes.
* For a typed memory object, the length in bytes.
* For other file types, the use of this field is unspecified.
*/
off_t st_size;
struct timespec st_atim; /**< Last data access timestamp. */
struct timespec st_mtim; /**< Last data modification timestamp. */
struct timespec st_ctim; /**< Last file status change timestamp. */
/**
* A file system-specific preferred I/O block size for this object. In some
* file system types, this may vary from file to file.
*/
blksize_t st_blksize;
blkcnt_t st_blocks; /**< Number of blocks allocated for this object. */
};
/* These bitmasks and numbers are the same as in newlib */
#define S_IFMT 0170000 /* type of file */
#define S_IFDIR 0040000 /* directory */
#define S_IFCHR 0020000 /* character special */
#define S_IFBLK 0060000 /* block special */
#define S_IFREG 0100000 /* regular */
#define S_IFLNK 0120000 /* symbolic link */
#define S_IFSOCK 0140000 /* socket */
#define S_IFIFO 0010000 /* fifo */
/* These numbers are well-known and can be found in the manual page for sys_stat.h */
#define S_IRWXU 0700 /**< Read, write, execute/search by owner. */
#define S_IRUSR 0400 /**< Read permission, owner. */
#define S_IWUSR 0200 /**< Write permission, owner. */
#define S_IXUSR 0100 /**< Execute/search permission, owner. */
#define S_IRWXG 070 /**< Read, write, execute/search by group. */
#define S_IRGRP 040 /**< Read permission, group. */
#define S_IWGRP 020 /**< Write permission, group. */
#define S_IXGRP 010 /**< Execute/search permission, group. */
#define S_IRWXO 07 /**< Read, write, execute/search by others. */
#define S_IROTH 04 /**< Read permission, others. */
#define S_IWOTH 02 /**< Write permission, others. */
#define S_IXOTH 01 /**< Execute/search permission, others. */
#define S_ISUID 04000 /**< Set-user-ID on execution. */
#define S_ISGID 02000 /**< Set-group-ID on execution. */
#define S_ISVTX 01000 /**< On directories, restricted deletion flag */
/* File type test macros, taken from newlib */
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
/* These function prototypes are required by the standard */
int chmod(const char *, mode_t);
int fchmod(int, mode_t);
int fchmodat(int, const char *, mode_t, int);
int fstat(int, struct stat *);
int fstatat(int, const char *restrict, struct stat *restrict, int);
int futimens(int, const struct timespec [2]);
int lstat(const char *restrict, struct stat *restrict);
int mkdir(const char *, mode_t);
int mkdirat(int, const char *, mode_t);
int mkfifo(const char *, mode_t);
int mkfifoat(int, const char *, mode_t);
int mknod(const char *, mode_t, dev_t);
int mknodat(int, const char *, mode_t, dev_t);
int stat(const char *restrict, struct stat *restrict);
mode_t umask(mode_t);
int utimensat(int, const char *, const struct timespec [2], int);
/* Special tv_nsec values for futimens(2) and utimensat(2). */
#define UTIME_NOW (-2L)
#define UTIME_OMIT (-1L)
#ifdef __cplusplus
}
#endif
#endif /* SYS_STAT_H_ */
/** @} */

@ -7,22 +7,41 @@
* directory for more details.
*/
#ifndef AVR_TYPES_H
#define AVR_TYPES_H
#ifndef SYS_TYPES_H_
#define SYS_TYPES_H_
#include <inttypes.h>
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef int16_t suseconds_t;
typedef signed int ssize_t;
typedef unsigned int off_t;
typedef int32_t blkcnt_t; /**< Used for file block counts */
typedef int32_t blksize_t; /**< Used for block sizes */
typedef uint32_t clock_t; /**< Used for system times in clock ticks */
typedef uint32_t clockid_t; /**< Used for clock ID type in the clock and timer functions */
typedef int16_t dev_t; /**< Used for device IDs */
typedef uint32_t fsblkcnt_t; /**< Used for file system block counts */
typedef uint32_t fsfilcnt_t; /**< Used for file system file counts */
typedef uint16_t gid_t; /**< Used for group IDs */
typedef uint16_t id_t; /**< Used as a general identifier */
typedef uint32_t ino_t; /**< Used for file serial numbers */
typedef uint32_t key_t; /**< Used for XSI interprocess communication */
typedef uint32_t mode_t; /**< Used for some file attributes */
typedef uint16_t nlink_t; /**< Used for link counts */
typedef int32_t off_t; /**< Used for file sizes and offsets */
typedef int pid_t; /**< Used for process IDs and process group IDs */
typedef unsigned int size_t; /**< Used for sizes of objects */
typedef signed int ssize_t; /**< Used for a count of bytes or an error indication */
typedef int32_t suseconds_t; /**< Used for time in microseconds */
typedef int32_t time_t; /**< Used for time in seconds */
typedef uint32_t timer_t; /**< Used for timer ID returned by timer_create() */
typedef uint16_t uid_t; /**< Used for user IDs */
typedef uint32_t useconds_t; /**< Used for time in microseconds */
#ifdef __cplusplus
}
#endif
#endif /* ifndef AVR_TYPES_H */
#endif /* SYS_TYPES_H_ */

@ -62,12 +62,27 @@ struct timeval {
time_t tv_usec; /**< microseconds */
};
/**
* @brief Definition of `clockid_t` for the MSP430
*
* @todo Remove once msp430 libc supports clockid_t
*/
typedef int clockid_t;
typedef int32_t blkcnt_t; /**< Used for file block counts */
typedef int32_t blksize_t; /**< Used for block sizes */
typedef uint32_t clock_t; /**< Used for system times in clock ticks */
typedef uint32_t clockid_t; /**< Used for clock ID type in the clock and timer functions */
typedef int16_t dev_t; /**< Used for device IDs */
typedef uint32_t fsblkcnt_t; /**< Used for file system block counts */
typedef uint32_t fsfilcnt_t; /**< Used for file system file counts */
typedef uint16_t gid_t; /**< Used for group IDs */
typedef uint16_t id_t; /**< Used as a general identifier */
typedef uint32_t ino_t; /**< Used for file serial numbers */
typedef uint32_t key_t; /**< Used for XSI interprocess communication */
typedef uint32_t mode_t; /**< Used for some file attributes */
typedef uint16_t nlink_t; /**< Used for link counts */
typedef int32_t off_t; /**< Used for file sizes and offsets */
typedef int pid_t; /**< Used for process IDs and process group IDs */
typedef unsigned int size_t; /**< Used for sizes of objects */
typedef signed int ssize_t; /**< Used for a count of bytes or an error indication */
typedef int32_t suseconds_t; /**< Used for time in microseconds */
typedef uint32_t timer_t; /**< Used for timer ID returned by timer_create() */
typedef uint16_t uid_t; /**< Used for user IDs */
typedef uint32_t useconds_t; /**< Used for time in microseconds */
#ifdef __cplusplus
}

@ -31,6 +31,10 @@
extern "C" {
#endif
#define SEEK_SET 0 /* Seek from beginning of file. */
#define SEEK_CUR 1 /* Seek from current position. */
#define SEEK_END 2 /* Seek from end of file. */
int getchar(void);
#ifdef __cplusplus

@ -0,0 +1,128 @@
/*
* Copyright (C) 2016 Eistec AB
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @file
* @brief POSIX compatible sys/stat.h definitions
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
*/
/* If building on native we need to use the system libraries instead */
#ifdef CPU_NATIVE
#pragma GCC system_header
/* without the GCC pragma above #include_next will trigger a pedantic error */
#include_next <sys/stat.h>
#else
#ifndef SYS_STAT_H_
#define SYS_STAT_H_
#include <time.h> /* for struct timespec */
#include <sys/types.h> /* for fsblkcnt_t, fsfilcnt_t */
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief File information
*/
struct stat {
dev_t st_dev; /**< Device ID of device containing file. */
ino_t st_ino; /**< File serial number. */
mode_t st_mode; /**< Mode of file (see below). */
nlink_t st_nlink; /**< Number of hard links to the file. */
uid_t st_uid; /**< User ID of file. */
gid_t st_gid; /**< Group ID of file. */
dev_t st_rdev; /**< Device ID (if file is character or block special). */
/**
* For regular files, the file size in bytes.
* For symbolic links, the length in bytes of the pathname contained in the
* symbolic link.
* For a shared memory object, the length in bytes.
* For a typed memory object, the length in bytes.
* For other file types, the use of this field is unspecified.
*/
off_t st_size;
struct timespec st_atim; /**< Last data access timestamp. */
struct timespec st_mtim; /**< Last data modification timestamp. */
struct timespec st_ctim; /**< Last file status change timestamp. */
/**
* A file system-specific preferred I/O block size for this object. In some
* file system types, this may vary from file to file.
*/
blksize_t st_blksize;
blkcnt_t st_blocks; /**< Number of blocks allocated for this object. */
};
/* These bitmasks and numbers are the same as in newlib */
#define S_IFMT 0170000 /* type of file */
#define S_IFDIR 0040000 /* directory */
#define S_IFCHR 0020000 /* character special */
#define S_IFBLK 0060000 /* block special */
#define S_IFREG 0100000 /* regular */
#define S_IFLNK 0120000 /* symbolic link */
#define S_IFSOCK 0140000 /* socket */
#define S_IFIFO 0010000 /* fifo */
/* These numbers are well-known and can be found in the manual page for sys_stat.h */
#define S_IRWXU 0700 /**< Read, write, execute/search by owner. */
#define S_IRUSR 0400 /**< Read permission, owner. */
#define S_IWUSR 0200 /**< Write permission, owner. */
#define S_IXUSR 0100 /**< Execute/search permission, owner. */
#define S_IRWXG 070 /**< Read, write, execute/search by group. */
#define S_IRGRP 040 /**< Read permission, group. */
#define S_IWGRP 020 /**< Write permission, group. */
#define S_IXGRP 010 /**< Execute/search permission, group. */
#define S_IRWXO 07 /**< Read, write, execute/search by others. */
#define S_IROTH 04 /**< Read permission, others. */
#define S_IWOTH 02 /**< Write permission, others. */
#define S_IXOTH 01 /**< Execute/search permission, others. */
#define S_ISUID 04000 /**< Set-user-ID on execution. */
#define S_ISGID 02000 /**< Set-group-ID on execution. */
#define S_ISVTX 01000 /**< On directories, restricted deletion flag */
/* File type test macros, taken from newlib */
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
/* These function prototypes are required by the standard */
int chmod(const char *, mode_t);
int fchmod(int, mode_t);
int fchmodat(int, const char *, mode_t, int);
int fstat(int, struct stat *);
int fstatat(int, const char *restrict, struct stat *restrict, int);
int futimens(int, const struct timespec [2]);
int lstat(const char *restrict, struct stat *restrict);
int mkdir(const char *, mode_t);
int mkdirat(int, const char *, mode_t);
int mkfifo(const char *, mode_t);
int mkfifoat(int, const char *, mode_t);
int mknod(const char *, mode_t, dev_t);
int mknodat(int, const char *, mode_t, dev_t);
int stat(const char *restrict, struct stat *restrict);
mode_t umask(mode_t);
int utimensat(int, const char *, const struct timespec [2], int);
/* Special tv_nsec values for futimens(2) and utimensat(2). */
#define UTIME_NOW (-2L)
#define UTIME_OMIT (-1L)
#ifdef __cplusplus
}
#endif
#endif /* SYS_STAT_H_ */
#endif /* CPU_NATIVE */
/** @} */

@ -1,4 +1,5 @@
/*
* Copyright (C) 2016 Eistec AB
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
@ -9,23 +10,98 @@
#ifndef UNISTD_H
#define UNISTD_H
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "msp430_types.h"
#define STDIN_FILENO 0 /* standard input file descriptor */
#define STDOUT_FILENO 1 /* standard output file descriptor */
#define STDERR_FILENO 2 /* standard error file descriptor */
#define STDIN_FILENO 0 ///< stdin file descriptor
#define STDOUT_FILENO 1 ///< stdout file descriptor
#define STDERR_FILENO 2 ///< stderr file descriptor
#define F_OK 0
#define R_OK 4
#define W_OK 2
#define X_OK 1
int close(int fildes);
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
typedef uint32_t useconds_t;
int usleep(useconds_t usec);
unsigned int sleep(unsigned int seconds);
int access(const char *, int);
unsigned alarm(unsigned);
int chdir(const char *);
int chown(const char *, uid_t, gid_t);
int close(int);
size_t confstr(int, char *, size_t);
int dup(int);
int dup2(int, int);
void _exit(int);
int execl(const char *, const char *, ...);
int execle(const char *, const char *, ...);
int execlp(const char *, const char *, ...);
int execv(const char *, char *const []);
int execve(const char *, char *const [], char *const []);
int execvp(const char *, char *const []);
int faccessat(int, const char *, int, int);
int fchdir(int);
int fchown(int, uid_t, gid_t);
int fchownat(int, const char *, uid_t, gid_t, int);
int fexecve(int, char *const [], char *const []);
pid_t fork(void);
long fpathconf(int, int);
int ftruncate(int, off_t);
char *getcwd(char *, size_t);
gid_t getegid(void);
uid_t geteuid(void);
gid_t getgid(void);
int getgroups(int, gid_t []);
int gethostname(char *, size_t);
char *getlogin(void);
int getlogin_r(char *, size_t);
int getopt(int, char * const [], const char *);
pid_t getpgid(pid_t);
pid_t getpgrp(void);
pid_t getpid(void);
pid_t getppid(void);
pid_t getsid(pid_t);
uid_t getuid(void);
int isatty(int);
int lchown(const char *, uid_t, gid_t);
int link(const char *, const char *);
int linkat(int, const char *, int, const char *, int);
off_t lseek(int, off_t, int);
long pathconf(const char *, int);
int pause(void);
int pipe(int [2]);
ssize_t pread(int, void *, size_t, off_t);
ssize_t pwrite(int, const void *, size_t, off_t);
ssize_t read(int, void *, size_t);
ssize_t readlink(const char *restrict, char *restrict, size_t);
ssize_t readlinkat(int, const char *restrict, char *restrict, size_t);
int rmdir(const char *);
int setegid(gid_t);
int seteuid(uid_t);
int setgid(gid_t);
int setpgid(pid_t, pid_t);
pid_t setsid(void);
int setuid(uid_t);
unsigned sleep(unsigned);
int symlink(const char *, const char *);
int symlinkat(const char *, int, const char *);
long sysconf(int);
pid_t tcgetpgrp(int);
int tcsetpgrp(int, pid_t);
int truncate(const char *, off_t);
char *ttyname(int);
int ttyname_r(int, char *, size_t);
int unlink(const char *);
int unlinkat(int, const char *, int);
int usleep(useconds_t);
ssize_t write(int, const void *, size_t);
#ifdef __cplusplus
}

@ -177,4 +177,15 @@ splx_(int sr)
}
/*---------------------------------------------------------------------------*/
size_t strnlen(const char *s, size_t maxlen)
{
size_t len;
for (len = 0; len < maxlen; len++, s++) {
if (!*s)
break;
}
return (len);
}
extern void board_init(void);

@ -1,6 +1,7 @@
MODULE = cpu
DIRS += periph
DIRS += vfs
ifneq (,$(filter netdev2_tap,$(USEMODULE)))
DIRS += netdev2_tap

@ -0,0 +1,3 @@
MODULE=native_vfs
include $(RIOTBASE)/Makefile.base

@ -0,0 +1,150 @@
/*
* Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.de>
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for
* more details.
*/
/**
* @ingroup native_cpu
* @{
*
* @file
* @brief VFS wrappers for POSIX file I/O functions
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <unistd.h>
#include "vfs.h"
int open(const char *name, int flags, ...)
{
unsigned mode = 0;
if ((flags & O_CREAT)) {
va_list ap;
va_start(ap, flags);
mode = va_arg(ap, unsigned);
va_end(ap);
}
int fd = vfs_open(name, flags, mode);
if (fd < 0) {
/* vfs returns negative error codes */
errno = -fd;
return -1;
}
return fd;
}
ssize_t read(int fd, void *dest, size_t count)
{
int res = vfs_read(fd, dest, count);
if (res < 0) {
/* vfs returns negative error codes */
errno = -res;
return -1;
}
return res;
}
ssize_t write(int fd, const void *src, size_t count)
{
int res = vfs_write(fd, src, count);
if (res < 0) {
/* vfs returns negative error codes */
errno = -res;
return -1;
}
return res;
}
int close(int fd)
{
int res = vfs_close(fd);
if (res < 0) {
/* vfs returns negative error codes */
errno = -res;
return -1;
}
return res;
}
int fcntl(int fd, int cmd, ...)
{
unsigned long arg;
va_list ap;
va_start(ap, cmd);
arg = va_arg(ap, unsigned long);
va_end(ap);
int res = vfs_fcntl(fd, cmd, arg);
if (res < 0) {
/* vfs returns negative error codes */
errno = -res;
return -1;
}
return res;
}
off_t lseek(int fd, off_t off, int whence)
{
int res = vfs_lseek(fd, off, whence);
if (res < 0) {
/* vfs returns negative error codes */
errno = -res;
return -1;
}
return res;
}
int fstat(int fd, struct stat *buf)
{
int res = vfs_fstat(fd, buf);
if (res < 0) {
/* vfs returns negative error codes */
errno = -res;
return -1;
}
return 0;
}
int stat(const char *name, struct stat *st)
{
int res = vfs_stat(name, st);
if (res < 0) {
/* vfs returns negative error codes */
errno = -res;
return -1;
}
return 0;
}
int unlink(const char *path)
{
int res = vfs_unlink(path);
if (res < 0) {
/* vfs returns negative error codes */
errno = -res;
return -1;
}
return 0;
}
/** @} */

@ -36,7 +36,7 @@ for FILE in ${FILES}; do
| sed -e 's/$/ /' \
| tr -d '\r\n' \
| sed -e 's/ */ /g' \
| grep -v -q '#ifdef __cplusplus extern "C" { #endif'; \
| grep -v -q '#ifdef __cplusplus extern "C" {'; \
then
EXIT_CODE=1
echo "file does not have a C++ compatible header: '${FILE}'"

@ -0,0 +1,16 @@
# Introduction
This tool creates a .c file including all data from a local directory as data
structures that can be mounted using constfs.
# Usage
mkconstfs.py /path/to/files /
#include "vfs.h"
#include "fs/constfs.h"
extern const vfs_mount_t _constfs;
[...]
vfs_mount((vfs_mount_t *)&_constfs);

@ -0,0 +1,91 @@
#!/usr/bin/env python3
import codecs
import os
import sys
FILE_TYPE = "static const uint8_t"
def mkconstfs(root_path, mount_point, constfs_name):
print("/* This file was automatically generated by mkconstfs */")
print("#include \"fs/constfs.h\"")
print("")
for dirname, subdir_list, file_list in os.walk(root_path):
target_dirname = os.path.join("/", dirname[len(root_path):])
for fname in file_list:
local_fname = os.path.join(dirname, fname)
target_fname = os.path.join(target_dirname, fname)
print_file_data(local_fname, target_fname)
print("\nstatic const constfs_file_t _files[] = {")
for mangled_name, target_name, _ in files:
print(" {")
print(" .path = \"%s\"," % target_name)
print(" .data = %s," % mangled_name)
print(" .size = sizeof(%s)" % mangled_name)
print(" },")
print("};")
print("""
static const constfs_t _fs_data = {
.files = _files,
.nfiles = sizeof(_files) / sizeof(_files[0]),
};
vfs_mount_t %s = {
.fs = &constfs_file_system,
.mount_point = \"%s\",
.private_data = (void *)&_fs_data,
};
""" % (constfs_name, mount_point))
def mangle_name(fname):
fname = fname.replace("/", "__")
fname = fname.replace(".", "__")
return fname
def print_file_data(local_fname, target_fname):
mangled_name = mangle_name(target_fname)
print(FILE_TYPE, mangled_name, "[] = {", end="")
line_length = 8
nread = 0
with open(local_fname, 'rb') as f:
byte = f.read(1)
while byte:
if nread == 0:
print("\n ", end="")
elif nread % line_length == 0:
print(",\n ", end="")
else:
print(", ", end="")
nread += 1
print ("0x" + codecs.encode(byte, 'hex').decode('ascii'), end="")
# Do stuff with byte.
byte = f.read(1)
print("\n};")
files.append((mangled_name, target_fname, nread))
files = []
if __name__=="__main__":
mountpoint = "/"
constfs_name = "_constfs"
if len(sys.argv) < 2:
print("usage: mkconstfs.py <path> [mountpoint] [constfs_name]")
exit(1)
path = sys.argv[1]
if len(sys.argv) > 2:
mountpoint = sys.argv[2]
if len(sys.argv) > 3:
constfs_name = sys.argv[3]
mkconstfs(path, mountpoint, constfs_name)

@ -818,6 +818,7 @@ EXCLUDE_SYMLINKS = NO
# exclude all test directories for example use the pattern */test/*
EXCLUDE_PATTERNS = */board/*/tools/* \
*/cpu/atmega_common/include/sys/*.h \
*/cpu/msp430_common/include/stdatomic.h \
*/cpu/msp430_common/include/sys/*.h \
*/cpu/native/osx-libc-extra \

@ -150,6 +150,7 @@ ifneq (,$(filter nrfmin,$(USEMODULE)))
endif
ifneq (,$(filter nvram_spi,$(USEMODULE)))
USEMODULE += nvram
USEMODULE += xtimer
endif

@ -30,6 +30,10 @@
#include <stdint.h>
#include <stddef.h>
#if MODULE_VFS
#include "vfs.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -79,6 +83,10 @@ typedef struct nvram {
void *extra;
} nvram_t;
#if MODULE_VFS
extern const vfs_file_ops_t nvram_vfs_ops;
#endif
#ifdef __cplusplus
}
#endif

@ -0,0 +1,3 @@
MODULE = nvram
include $(RIOTBASE)/Makefile.base

@ -0,0 +1,136 @@
/*
* Copyright (C) 2016 Eistec AB
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
#if MODULE_VFS
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include "nvram.h"
#include "vfs.h"
/**
* @ingroup nvram
* @{
*
* @file
*
* @brief NVRAM generic VFS operations
*
* This allows the nvram driver to register as a node on DevFS
*
* See boards/mulle or tests/unittests/tests-devfs for examples on how to use.
*
* Tested with nvram_spi on Mulle
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
*/
static int nvram_vfs_fstat(vfs_file_t *filp, struct stat *buf);
static off_t nvram_vfs_lseek(vfs_file_t *filp, off_t off, int whence);
static ssize_t nvram_vfs_read(vfs_file_t *filp, void *dest, size_t nbytes);
static ssize_t nvram_vfs_write(vfs_file_t *filp, const void *src, size_t nbytes);
const vfs_file_ops_t nvram_vfs_ops = {
.fstat = nvram_vfs_fstat,
.lseek = nvram_vfs_lseek,
.read = nvram_vfs_read,
.write = nvram_vfs_write,
};
static int nvram_vfs_fstat(vfs_file_t *filp, struct stat *buf)
{
if (buf == NULL) {
return -EFAULT;
}
nvram_t *dev = filp->private_data.ptr;
if (dev == NULL) {
return -EFAULT;
}
buf->st_nlink = 1;
buf->st_size = dev->size;
return 0;
}
static off_t nvram_vfs_lseek(vfs_file_t *filp, off_t off, int whence)
{
nvram_t *dev = filp->private_data.ptr;
if (dev == NULL) {
return -EFAULT;
}
switch (whence) {
case SEEK_SET:
break;
case SEEK_CUR:
off += filp->pos;
break;
case SEEK_END:
off += dev->size;
break;
default:
return -EINVAL;
}
if (off < 0) {
/* the resulting file offset would be negative */
return -EINVAL;
}
/* POSIX allows seeking past the end of the file */
filp->pos = off;
return off;
}
static ssize_t nvram_vfs_read(vfs_file_t *filp, void *dest, size_t nbytes)
{
nvram_t *dev = filp->private_data.ptr;
if (dev == NULL) {
return -EFAULT;
}
uint32_t src = filp->pos;
if (src >= dev->size) {
return 0;
}
if (src + nbytes > dev->size) {
nbytes = dev->size - src;
}
int res = dev->read(dev, dest, src, nbytes);
if (res < 0) {
return res;
}
/* Advance file position */
filp->pos += res;
return res;
}
static ssize_t nvram_vfs_write(vfs_file_t *filp, const void *src, size_t nbytes)
{
nvram_t *dev = filp->private_data.ptr;
if (dev == NULL) {
return -EFAULT;
}
uint32_t dest = filp->pos;
if (dest >= dev->size) {
return 0;
}
if (dest + nbytes > dev->size) {
nbytes = dev->size - dest;
}
int res = dev->write(dev, src, dest, nbytes);
if (res < 0) {
return res;
}
/* Advance file position */
filp->pos += res;
return res;
}
/** @} */
#else
typedef int dont_be_pedantic;
#endif /* MODULE_VFS */

@ -112,6 +112,14 @@ ifneq (,$(filter emcute,$(USEMODULE)))
DIRS += net/application_layer/emcute
endif
ifneq (,$(filter constfs,$(USEMODULE)))
DIRS += fs/constfs
endif
ifneq (,$(filter devfs,$(USEMODULE)))
DIRS += fs/devfs
endif
DIRS += $(dir $(wildcard $(addsuffix /Makefile, ${USEMODULE})))
include $(RIOTBASE)/Makefile.base

@ -32,6 +32,10 @@ ifneq (,$(filter oneway_malloc,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/oneway-malloc/include
endif
ifneq (,$(filter vfs,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
endif
ifneq (,$(filter cpp11-compat,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/cpp11-compat/include
# make sure cppsupport.o is linked explicitly because __dso_handle is not

@ -152,6 +152,11 @@ void auto_init(void)
DEBUG("Auto init gcoap module.\n");
gcoap_init();
#endif
#ifdef MODULE_DEVFS
DEBUG("Mounting /dev\n");
extern void auto_init_devfs(void);
auto_init_devfs();
#endif
/* initialize network devices */
#ifdef MODULE_AUTO_INIT_GNRC_NETIF

@ -0,0 +1,2 @@
MODULE=constfs
include $(RIOTBASE)/Makefile.base

@ -0,0 +1,319 @@
/*
* Copyright (C) 2016 Eistec AB
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup fs_constfs
* @{
*
* @file
* @brief ConstFS implementation
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
*
* @}
*/
/* Required for strnlen in string.h, when building with -std=c99 */
#define _DEFAULT_SOURCE 1
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include "fs/constfs.h"
#include "vfs.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/* File system operations */
static int constfs_mount(vfs_mount_t *mountp);
static int constfs_umount(vfs_mount_t *mountp);
static int constfs_unlink(vfs_mount_t *mountp, const char *name);
static int constfs_stat(vfs_mount_t *mountp, const char *restrict name, struct stat *restrict buf);
static int constfs_statvfs(vfs_mount_t *mountp, const char *restrict path, struct statvfs *restrict buf);
/* File operations */
static int constfs_close(vfs_file_t *filp);
static int constfs_fstat(vfs_file_t *filp, struct stat *buf);
static off_t constfs_lseek(vfs_file_t *filp, off_t off, int whence);
static int constfs_open(vfs_file_t *filp, const char *name, int flags, mode_t mode, const char *abs_path);
static ssize_t constfs_read(vfs_file_t *filp, void *dest, size_t nbytes);
static ssize_t constfs_write(vfs_file_t *filp, const void *src, size_t nbytes);
/* Directory operations */
static int constfs_opendir(vfs_DIR *dirp, const char *dirname, const char *abs_path);
static int constfs_readdir(vfs_DIR *dirp, vfs_dirent_t *entry);
static int constfs_closedir(vfs_DIR *dirp);
static const vfs_file_system_ops_t constfs_fs_ops = {
.mount = constfs_mount,
.umount = constfs_umount,
.unlink = constfs_unlink,
.statvfs = constfs_statvfs,
.stat = constfs_stat,
};
static const vfs_file_ops_t constfs_file_ops = {
.close = constfs_close,
.fstat = constfs_fstat,
.lseek = constfs_lseek,
.open = constfs_open,
.read = constfs_read,
.write = constfs_write,
};
static const vfs_dir_ops_t constfs_dir_ops = {
.opendir = constfs_opendir,
.readdir = constfs_readdir,
.closedir = constfs_closedir,
};
const vfs_file_system_t constfs_file_system = {
.f_op = &constfs_file_ops,
.fs_op = &constfs_fs_ops,
.d_op = &constfs_dir_ops,
};
/**
* @internal
* @brief Fill a file information struct with information about the file
* pointed to by @p fp
*
* @param[in] fp file to query
* @param[out] buf output buffer
*/
static void _constfs_write_stat(const constfs_file_t *fp, struct stat *restrict buf);
static int constfs_mount(vfs_mount_t *mountp)
{
/* perform any extra initialization here */
(void) mountp; /* prevent warning: unused parameter */
return 0;
}
static int constfs_umount(vfs_mount_t *mountp)
{
/* free resources and perform any clean up here */
(void) mountp; /* prevent warning: unused parameter */
return 0;
}
static int constfs_unlink(vfs_mount_t *mountp, const char *name)
{
/* Removing files is prohibited */
(void) mountp; /* prevent warning: unused parameter */
(void) name; /* prevent warning: unused parameter */
return -EROFS;
}
static int constfs_stat(vfs_mount_t *mountp, const char *restrict name, struct stat *restrict buf)
{
(void) name;
/* Fill out some information about this file */
if (buf == NULL) {
return -EFAULT;
}
constfs_t *fs = mountp->private_data;
/* linear search through the files array */
for (size_t i = 0; i < fs->nfiles; ++i) {
DEBUG("constfs_stat ? \"%s\"\n", fs->files[i].path);
if (strcmp(fs->files[i].path, name) == 0) {
DEBUG("constfs_stat: Found :)\n");
_constfs_write_stat(&fs->files[i], buf);
buf->st_ino = i;
return 0;
}
}
DEBUG("constfs_stat: Not found :(\n");
return -ENOENT;
}
static int constfs_statvfs(vfs_mount_t *mountp, const char *restrict path, struct statvfs *restrict buf)
{
(void) path;
/* Fill out some information about this file system */
if (buf == NULL) {
return -EFAULT;
}
constfs_t *fs = mountp->private_data;
/* clear out the stat buffer first */
memset(buf, 0, sizeof(*buf));
buf->f_bsize = sizeof(uint8_t); /* block size */
buf->f_frsize = sizeof(uint8_t); /* fundamental block size */
fsblkcnt_t f_blocks = 0;
for (size_t i = 0; i < fs->nfiles; ++i) {
f_blocks += fs->files[i].size;
}
buf->f_blocks = f_blocks; /* Blocks total */
buf->f_bfree = 0; /* Blocks free */
buf->f_bavail = 0; /* Blocks available to non-privileged processes */
buf->f_files = fs->nfiles; /* Total number of file serial numbers */
buf->f_ffree = 0; /* Total number of free file serial numbers */
buf->f_favail = 0; /* Number of file serial numbers available to non-privileged process */
buf->f_fsid = 0; /* File system id */
buf->f_flag = (ST_RDONLY | ST_NOSUID); /* File system flags */
buf->f_namemax = UINT8_MAX; /* Maximum file name length */
return 0;
}
static int constfs_close(vfs_file_t *filp)
{
/* perform any necessary clean ups */
(void) filp; /* prevent warning: unused parameter */
return 0;
}
static int constfs_fstat(vfs_file_t *filp, struct stat *buf)