discover: Add device_{request,release}_write
authorJeremy Kerr <jk@ozlabs.org>
Tue, 1 Oct 2013 04:27:35 +0000 (12:27 +0800)
committerJeremy Kerr <jk@ozlabs.org>
Tue, 1 Oct 2013 04:52:00 +0000 (12:52 +0800)
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 <jk@ozlabs.org>
discover/device-handler.c
discover/device-handler.h
discover/parser.c
discover/parser.h
test/parser/utils.c

index fc280af186fb9d8e400bd59ef6a5b42b9118a39b..04a44848d4c452db00e7c9e80cda0b5c6274ac9e 100644 (file)
@@ -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
 
index 5dbc349fadb93aa541f6c684abd57bb9972fc7e7..6b36e075000ecd2bcad00e9edf912463e9221010 100644 (file)
@@ -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 */
index d34600d18f1526856945689f4fbb0723cbdefc28..48169167974d6150a2670aaba4576053e133da9e 100644 (file)
@@ -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;
index c1b4012d67cb29764fbb499cb27224555137b4d8..2aaa07744d62281334df79fdaa3411321a4cc5d5 100644 (file)
@@ -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 */
index d1ced73a6365fff837902fd027811a1d0db500e4..33efda80536f8354ebc4e10e6b64fe1299755831 100644 (file)
@@ -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;