commit
887cc72365
@ -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_ */
|
||||
|
||||
/** @} */
|
@ -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 */
|
||||
|
||||
/** @} */
|
@ -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;
|
||||
}
|
||||
|
||||
/** @} */
|
@ -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)
|
@ -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 */
|
@ -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)
|
||||