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;
}
}
"-o", "ro", NULL);
if (!rc) {
dev->mounted = true;
+ dev->mounted_rw = false;
dev->unmount = true;
return 0;
}
if (!rc) {
dev->mounted = true;
+ dev->mounted_rw = true;
dev->unmount = true;
return 0;
}
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)))
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
char *mount_path;
const char *device_path;
bool mounted;
+ bool mounted_rw;
bool unmount;
bool notified;
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 */
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;
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 */
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;