summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjorn Andersson <bjorn.andersson@linaro.org>2019-07-12 21:26:43 -0700
committerBjorn Andersson <bjorn.andersson@linaro.org>2019-07-17 12:23:02 -0700
commitc35633ab2312393b40bd07c8937a9d66672c89eb (patch)
tree66422823bca47e1c29442dcb50ea2d4a61bb8a11
parente6d703b3c8b85a5d665e0f4fc4ebe43c32903126 (diff)
storage: Allow read only backing storage
Add a new argument '-r' to prevent writes back to the backing storage. This is useful for experimenting with the remote storage, without having the files overwritten. Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
-rw-r--r--rmtfs.c10
-rw-r--r--rmtfs.h4
-rw-r--r--storage.c136
3 files changed, 134 insertions, 16 deletions
diff --git a/rmtfs.c b/rmtfs.c
index 7cf5d0a..41aabbb 100644
--- a/rmtfs.c
+++ b/rmtfs.c
@@ -449,17 +449,23 @@ static int run_rmtfs(void)
int main(int argc, char **argv)
{
+ bool read_only = false;
int ret;
int option;
const char *storage_root = NULL;
- while ((option = getopt(argc, argv, "o:v")) != -1) {
+ while ((option = getopt(argc, argv, "o:rv")) != -1) {
switch (option) {
/* -o sets the directory where EFS images are stored. */
case 'o':
storage_root = optarg;
break;
+ /* -r to avoid writing to storage */
+ case 'r':
+ read_only = true;
+ break;
+
/* -v is for verbose */
case 'v':
dbgprintf_enabled = 1;
@@ -475,7 +481,7 @@ int main(int argc, char **argv)
if (!rmem)
return 1;
- ret = storage_init(storage_root);
+ ret = storage_init(storage_root, read_only);
if (ret) {
fprintf(stderr, "failed to initialize storage system\n");
goto close_rmtfs_mem;
diff --git a/rmtfs.h b/rmtfs.h
index 6286325..7bc3a64 100644
--- a/rmtfs.h
+++ b/rmtfs.h
@@ -25,7 +25,7 @@ ssize_t rmtfs_mem_write(struct rmtfs_mem *rmem, unsigned long phys_address, cons
struct rmtfd;
-int storage_init(const char *storage_root);
+int storage_init(const char *storage_root, bool read_only);
struct rmtfd *storage_open(unsigned node, const char *path);
struct rmtfd *storage_get(unsigned node, int caller_id);
void storage_close(struct rmtfd *rmtfd);
@@ -33,6 +33,6 @@ int storage_get_caller_id(const struct rmtfd *rmtfd);
int storage_get_error(const struct rmtfd *rmtfd);
void storage_exit(void);
ssize_t storage_pread(const struct rmtfd *rmtfd, void *buf, size_t nbyte, off_t offset);
-ssize_t storage_pwrite(const struct rmtfd *rmtfd, const void *buf, size_t nbyte, off_t offset);
+ssize_t storage_pwrite(struct rmtfd *rmtfd, const void *buf, size_t nbyte, off_t offset);
#endif
diff --git a/storage.c b/storage.c
index 7610492..2b7ffa5 100644
--- a/storage.c
+++ b/storage.c
@@ -1,3 +1,4 @@
+#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
@@ -8,6 +9,9 @@
#include "rmtfs.h"
#define MAX_CALLERS 10
+#define STORAGE_MAX_SIZE (16 * 1024 * 1024)
+
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
struct partition {
const char *path;
@@ -20,9 +24,13 @@ struct rmtfd {
int fd;
unsigned dev_error;
const struct partition *partition;
+
+ void *shadow_buf;
+ size_t shadow_len;
};
static const char *storage_dir = "/boot";
+static int storage_read_only;
static const struct partition partition_table[] = {
{ "/boot/modem_fs1", "modem_fs1" },
@@ -34,13 +42,17 @@ static const struct partition partition_table[] = {
static struct rmtfd rmtfds[MAX_CALLERS];
-int storage_init(const char *storage_root)
+static int storage_populate_shadow_buf(struct rmtfd *rmtfd, const char *file);
+
+int storage_init(const char *storage_root, bool read_only)
{
int i;
if (storage_root)
storage_dir = storage_root;
+ storage_read_only = read_only;
+
for (i = 0; i < MAX_CALLERS; i++) {
rmtfds[i].id = i;
rmtfds[i].fd = -1;
@@ -56,6 +68,7 @@ struct rmtfd *storage_open(unsigned node, const char *path)
struct rmtfd *rmtfd = NULL;
size_t pathlen;
int saved_errno;
+ int ret;
int fd;
int i;
@@ -90,17 +103,29 @@ found:
pathlen = strlen(storage_dir) + strlen(part->actual) + 2;
fspath = alloca(pathlen);
snprintf(fspath, pathlen, "%s/%s", storage_dir, part->actual);
- fd = open(fspath, O_RDWR);
- if (fd < 0) {
- saved_errno = errno;
- fprintf(stderr, "[storage] failed to open '%s' (requested '%s'): %s\n",
- fspath, part->path, strerror(saved_errno));
- errno = saved_errno;
- return NULL;
+ if (!storage_read_only) {
+ fd = open(fspath, O_RDWR);
+ if (fd < 0) {
+ saved_errno = errno;
+ fprintf(stderr, "[storage] failed to open '%s' (requested '%s'): %s\n",
+ fspath, part->path, strerror(saved_errno));
+ errno = saved_errno;
+ return NULL;
+ }
+ rmtfd->fd = fd;
+ rmtfd->shadow_len = 0;
+ } else {
+ ret = storage_populate_shadow_buf(rmtfd, fspath);
+ if (ret < 0) {
+ saved_errno = errno;
+ fprintf(stderr, "[storage] failed to open '%s' (requested '%s'): %s\n",
+ fspath, part->path, strerror(saved_errno));
+ errno = saved_errno;
+ return NULL;
+ }
}
rmtfd->node = node;
- rmtfd->fd = fd;
rmtfd->partition = part;
return rmtfd;
@@ -110,6 +135,11 @@ void storage_close(struct rmtfd *rmtfd)
{
close(rmtfd->fd);
rmtfd->fd = -1;
+
+ free(rmtfd->shadow_buf);
+ rmtfd->shadow_buf = NULL;
+ rmtfd->shadow_len = 0;
+
rmtfd->partition = NULL;
}
@@ -149,11 +179,93 @@ void storage_exit(void)
ssize_t storage_pread(const struct rmtfd *rmtfd, void *buf, size_t nbyte, off_t offset)
{
- return pread(rmtfd->fd, buf, nbyte, offset);
+ ssize_t n;
+
+ if (!storage_read_only) {
+ n = pread(rmtfd->fd, buf, nbyte, offset);
+ } else {
+ n = MIN(nbyte, rmtfd->shadow_len - offset);
+ if (n > 0)
+ memcpy(buf, rmtfd->shadow_buf + offset, n);
+ else
+ n = 0;
+ }
+
+ if (n < nbyte)
+ memset(buf + n, 0, nbyte - n);
+
+ return nbyte;
}
-ssize_t storage_pwrite(const struct rmtfd *rmtfd, const void *buf, size_t nbyte, off_t offset)
+ssize_t storage_pwrite(struct rmtfd *rmtfd, const void *buf, size_t nbyte, off_t offset)
{
- return pwrite(rmtfd->fd, buf, nbyte, offset);
+ size_t new_len = offset + nbyte;
+ void *new_buf;
+
+ if (!storage_read_only)
+ return pwrite(rmtfd->fd, buf, nbyte, offset);
+
+ if (new_len >= STORAGE_MAX_SIZE) {
+ fprintf(stderr, "write to %zd bytes exceededs max size\n", new_len);
+ errno = -EINVAL;
+ return -1;
+ }
+
+ if (new_len > rmtfd->shadow_len) {
+ new_buf = realloc(rmtfd->shadow_buf, new_len);
+ if (!new_buf) {
+ errno = -ENOMEM;
+ return -1;
+ }
+
+ rmtfd->shadow_buf = new_buf;
+ rmtfd->shadow_len = new_len;
+ }
+
+ memcpy(rmtfd->shadow_buf + offset, buf, nbyte);
+
+ return nbyte;
}
+static int storage_populate_shadow_buf(struct rmtfd *rmtfd, const char *file)
+{
+ ssize_t len;
+ ssize_t n;
+ void *buf;
+ int ret;
+ int fd;
+
+ fd = open(file, O_RDONLY);
+ if (fd < 0)
+ return -1;
+
+ len = lseek(fd, 0, SEEK_END);
+ if (len < 0) {
+ ret = -1;
+ goto err_close_fd;
+ }
+
+ lseek(fd, 0, SEEK_SET);
+
+ buf = calloc(1, len);
+ if (!buf) {
+ ret = -1;
+ goto err_close_fd;
+ }
+
+ n = read(fd, buf, len);
+ if (n < 0) {
+ ret = -1;
+ goto err_close_fd;
+ }
+
+ rmtfd->shadow_buf = buf;
+ rmtfd->shadow_len = n;
+
+ ret = 0;
+
+err_close_fd:
+ close(fd);
+
+ return ret;
+}