From 9fbd73a208c9465b4bf9e2c80c7290b72e62ead1 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Tue, 1 Oct 2013 12:27:35 +0800 Subject: [PATCH 1/1] discover: Add device_{request,release}_write Add a pair of functions to the parser API to allow write access to the underlying device. We'll use this in the GRUB2 parser to implement environment persistence. Signed-off-by: Jeremy Kerr --- discover/device-handler.c | 56 ++++++++++++++++++++++++++++++++++++--- discover/device-handler.h | 4 +++ discover/parser.c | 29 ++++++++++++++++++++ discover/parser.h | 9 +++++++ test/parser/utils.c | 30 +++++++++++++++++++++ 5 files changed, 125 insertions(+), 3 deletions(-) diff --git a/discover/device-handler.c b/discover/device-handler.c index fc280af..04a4484 100644 --- a/discover/device-handler.c +++ b/discover/device-handler.c @@ -721,12 +721,15 @@ static bool check_existing_mount(struct discover_device *dev) continue; if (mntstat.st_rdev == devstat.st_rdev) { - pb_debug("%s: %s is already mounted at %s\n" - __func__, dev->device_path, - mnt->mnt_dir); dev->mount_path = talloc_strdup(dev, mnt->mnt_dir); + dev->mounted_rw = !!hasmntopt(mnt, "rw"); dev->mounted = true; dev->unmount = false; + + pb_debug("%s: %s is already mounted (r%c) at %s\n", + __func__, dev->device_path, + dev->mounted_rw ? 'w' : 'o', + mnt->mnt_dir); break; } } @@ -763,6 +766,7 @@ static int mount_device(struct discover_device *dev) "-o", "ro", NULL); if (!rc) { dev->mounted = true; + dev->mounted_rw = false; dev->unmount = true; return 0; } @@ -773,6 +777,7 @@ static int mount_device(struct discover_device *dev) if (!rc) { dev->mounted = true; + dev->mounted_rw = true; dev->unmount = true; return 0; } @@ -805,6 +810,39 @@ static int umount_device(struct discover_device *dev) return 0; } + +int device_request_write(struct discover_device *dev, bool *release) +{ + int rc; + + *release = false; + + if (!dev->mounted) + return -1; + + if (dev->mounted_rw) + return 0; + + rc = process_run_simple(dev, pb_system_apps.mount, dev->mount_path, + "-o", "remount,rw", NULL); + if (rc) + return -1; + + dev->mounted_rw = true; + *release = true; + return 0; +} + +void device_release_write(struct discover_device *dev, bool release) +{ + if (!release) + return; + + process_run_simple(dev, pb_system_apps.mount, dev->mount_path, + "-o", "remount,ro", NULL); + dev->mounted_rw = false; +} + #else static int umount_device(struct discover_device *dev __attribute__((unused))) @@ -818,5 +856,17 @@ static int __attribute__((unused)) mount_device( return 0; } +int device_request_write(struct discover_device *dev __attribute__((unused)), + bool *release) +{ + *release = true; + return 0; +} + +void device_release_write(struct discover_device *dev __attribute__((unused)), + bool release __attribute__((unused))) +{ +} + #endif diff --git a/discover/device-handler.h b/discover/device-handler.h index 5dbc349..6b36e07 100644 --- a/discover/device-handler.h +++ b/discover/device-handler.h @@ -36,6 +36,7 @@ struct discover_device { char *mount_path; const char *device_path; bool mounted; + bool mounted_rw; bool unmount; bool notified; @@ -124,4 +125,7 @@ void device_handler_boot(struct device_handler *handler, struct boot_command *cmd); void device_handler_cancel_default(struct device_handler *handler); +int device_request_write(struct discover_device *dev, bool *release); +void device_release_write(struct discover_device *dev, bool release); + #endif /* _DEVICE_HANDLER_H */ diff --git a/discover/parser.c b/discover/parser.c index d34600d..4816916 100644 --- a/discover/parser.c +++ b/discover/parser.c @@ -49,6 +49,35 @@ int parser_request_file(struct discover_context *ctx, return rc; } +int parser_replace_file(struct discover_context *ctx, + struct discover_device *dev, const char *filename, + char *buf, int len) +{ + bool release; + char *path; + int rc; + + if (!dev->mounted) + return -1; + + rc = device_request_write(dev, &release); + if (rc) { + pb_log("Can't write file %s: device doesn't allow write\n", + dev->device_path); + return -1; + } + + path = local_path(ctx, dev, filename); + + rc = replace_file(path, buf, len); + + talloc_free(path); + + device_release_write(dev, release); + + return rc; +} + static int download_config(struct discover_context *ctx, char **buf, int *len) { struct load_url_result *result; diff --git a/discover/parser.h b/discover/parser.h index c1b4012..2aaa077 100644 --- a/discover/parser.h +++ b/discover/parser.h @@ -51,8 +51,17 @@ void parser_init(void); void iterate_parsers(struct discover_context *ctx, enum conf_method method); int parse_user_event(struct discover_context *ctx, struct event *event); +/* File IO functions for parsers; these should be the only interface that + * parsers use to access a device's filesystem. + * + * These are intended for small amounts of data, typically text configuration + * and state files. + */ int parser_request_file(struct discover_context *ctx, struct discover_device *dev, const char *filename, char **buf, int *len); +int parser_replace_file(struct discover_context *ctx, + struct discover_device *dev, const char *filename, + char *buf, int len); #endif /* _PARSER_H */ diff --git a/test/parser/utils.c b/test/parser/utils.c index d1ced73..33efda8 100644 --- a/test/parser/utils.c +++ b/test/parser/utils.c @@ -186,6 +186,36 @@ int parser_request_file(struct discover_context *ctx, return -1; } +int parser_replace_file(struct discover_context *ctx, + struct discover_device *dev, const char *filename, + char *buf, int len) +{ + struct parser_test *test = ctx->test_data; + struct test_file *f, *file; + + list_for_each_entry(&test->files, f, list) { + if (f->dev != dev) + continue; + if (strcmp(f->name, filename)) + continue; + + file = f; + break; + } + + if (!file) { + file = talloc_zero(test, struct test_file); + file->dev = dev; + file->name = filename; + list_add(&test->files, &file->list); + } else { + talloc_free(file->data); + } + + file->data = talloc_memdup(test, buf, len); + file->size = len; + return 0; +} int test_run_parser(struct parser_test *test, const char *parser_name) { struct p_item* i; -- 2.39.2