]> git.ozlabs.org Git - petitboot/blob - discover/device-handler.c
d41bb4b0bb924e02b4d0b70f9021d77a08285242
[petitboot] / discover / device-handler.c
1 #include <assert.h>
2 #include <inttypes.h>
3 #include <stdlib.h>
4 #include <stdbool.h>
5 #include <unistd.h>
6 #include <string.h>
7 #include <errno.h>
8 #include <mntent.h>
9 #include <locale.h>
10 #include <sys/stat.h>
11 #include <sys/wait.h>
12 #include <sys/mount.h>
13
14 #include <talloc/talloc.h>
15 #include <list/list.h>
16 #include <log/log.h>
17 #include <types/types.h>
18 #include <system/system.h>
19 #include <process/process.h>
20 #include <url/url.h>
21 #include <i18n/i18n.h>
22 #include <pb-config/pb-config.h>
23
24 #include <sys/sysmacros.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <netdb.h>
28 #include <arpa/inet.h>
29
30 #include "device-handler.h"
31 #include "discover-server.h"
32 #include "devmapper.h"
33 #include "user-event.h"
34 #include "platform.h"
35 #include "event.h"
36 #include "parser.h"
37 #include "resource.h"
38 #include "paths.h"
39 #include "sysinfo.h"
40 #include "boot.h"
41 #include "udev.h"
42 #include "network.h"
43 #include "ipmi.h"
44
45 enum default_priority {
46         DEFAULT_PRIORITY_TEMP_USER      = 1,
47         DEFAULT_PRIORITY_REMOTE         = 2,
48         DEFAULT_PRIORITY_LOCAL_FIRST    = 3,
49         DEFAULT_PRIORITY_LOCAL_LAST     = 0xfe,
50         DEFAULT_PRIORITY_DISABLED       = 0xff,
51 };
52
53 static int default_rescan_timeout = 5 * 60; /* seconds */
54
55 struct progress_info {
56         unsigned int                    percentage;
57         unsigned long                   size;           /* size in bytes */
58
59         const struct process_info       *procinfo;
60         struct list_item        list;
61 };
62
63 struct crypt_info {
64         struct discover_device  *source_device;
65         char                    *dm_name;
66
67         struct list_item        list;
68 };
69
70 struct device_handler {
71         struct discover_server  *server;
72         int                     dry_run;
73
74         struct pb_udev          *udev;
75         struct network          *network;
76         struct user_event       *user_event;
77
78         struct discover_device  **devices;
79         unsigned int            n_devices;
80
81         struct ramdisk_device   **ramdisks;
82         unsigned int            n_ramdisks;
83
84         struct waitset          *waitset;
85         struct waiter           *timeout_waiter;
86         bool                    autoboot_enabled;
87         unsigned int            sec_to_boot;
88         struct autoboot_option  *temp_autoboot;
89
90         struct discover_boot_option *default_boot_option;
91         struct discover_boot_option *last_boot_option;
92         int                     default_boot_option_priority;
93
94         struct list             unresolved_boot_options;
95
96         struct boot_task        *pending_boot;
97         bool                    pending_boot_is_default;
98
99         struct list             progress;
100         unsigned int            n_progress;
101
102         struct plugin_option    **plugins;
103         unsigned int            n_plugins;
104         bool                    plugin_installing;
105
106         struct list             crypt_devices;
107 };
108
109 static int mount_device(struct discover_device *dev);
110 static int umount_device(struct discover_device *dev);
111
112 static int device_handler_init_sources(struct device_handler *handler);
113 static void device_handler_reinit_sources(struct device_handler *handler);
114
115 static void device_handler_update_lang(const char *lang);
116
117 void discover_context_add_boot_option(struct discover_context *ctx,
118                 struct discover_boot_option *boot_option)
119 {
120         boot_option->source = ctx->parser;
121         list_add_tail(&ctx->boot_options, &boot_option->list);
122         talloc_steal(ctx, boot_option);
123 }
124
125 /**
126  * device_handler_get_device_count - Get the count of current handler devices.
127  */
128
129 int device_handler_get_device_count(const struct device_handler *handler)
130 {
131         return handler->n_devices;
132 }
133
134 /**
135  * device_handler_get_device - Get a handler device by index.
136  */
137
138 const struct discover_device *device_handler_get_device(
139         const struct device_handler *handler, unsigned int index)
140 {
141         if (index >= handler->n_devices) {
142                 assert(0 && "bad index");
143                 return NULL;
144         }
145
146         return handler->devices[index];
147 }
148
149 /**
150  * device_handler_get_plugin_count - Get the count of current handler plugins.
151  */
152 int device_handler_get_plugin_count(const struct device_handler *handler)
153 {
154         return handler->n_plugins;
155 }
156
157 /**
158  * discover_handler_get_plugin - Get a handler plugin by index.
159  */
160 const struct plugin_option *device_handler_get_plugin(
161         const struct device_handler *handler, unsigned int index)
162 {
163         if (index >= handler->n_plugins) {
164                 assert(0 && "bad index");
165                 return NULL;
166         }
167
168         return handler->plugins[index];
169 }
170
171 struct network *device_handler_get_network(
172                 const struct device_handler *handler)
173 {
174         return handler->network;
175 }
176
177 struct discover_boot_option *discover_boot_option_create(
178                 struct discover_context *ctx,
179                 struct discover_device *device)
180 {
181         struct discover_boot_option *opt;
182
183         opt = talloc_zero(ctx, struct discover_boot_option);
184         opt->option = talloc_zero(opt, struct boot_option);
185         opt->device = device;
186
187         return opt;
188 }
189
190 static int device_match_uuid(struct discover_device *dev, const char *uuid)
191 {
192         return dev->uuid && !strcmp(dev->uuid, uuid);
193 }
194
195 static int device_match_label(struct discover_device *dev, const char *label)
196 {
197         return dev->label && !strcmp(dev->label, label);
198 }
199
200 static int device_match_id(struct discover_device *dev, const char *id)
201 {
202         return !strcmp(dev->device->id, id);
203 }
204
205 static int device_match_serial(struct discover_device *dev, const char *serial)
206 {
207         const char *val = discover_device_get_param(dev, "ID_SERIAL");
208         return val && !strcmp(val, serial);
209 }
210
211 static struct discover_device *device_lookup(
212                 struct device_handler *device_handler,
213                 int (match_fn)(struct discover_device *, const char *),
214                 const char *str)
215 {
216         struct discover_device *dev;
217         unsigned int i;
218
219         if (!str)
220                 return NULL;
221
222         for (i = 0; i < device_handler->n_devices; i++) {
223                 dev = device_handler->devices[i];
224
225                 if (match_fn(dev, str))
226                         return dev;
227         }
228
229         return NULL;
230 }
231
232 struct discover_device *device_lookup_by_name(struct device_handler *handler,
233                 const char *name)
234 {
235         if (!strncmp(name, "/dev/", strlen("/dev/")))
236                 name += strlen("/dev/");
237
238         return device_lookup_by_id(handler, name);
239 }
240
241 struct discover_device *device_lookup_by_uuid(
242                 struct device_handler *device_handler,
243                 const char *uuid)
244 {
245         return device_lookup(device_handler, device_match_uuid, uuid);
246 }
247
248 struct discover_device *device_lookup_by_label(
249                 struct device_handler *device_handler,
250                 const char *label)
251 {
252         return device_lookup(device_handler, device_match_label, label);
253 }
254
255 struct discover_device *device_lookup_by_id(
256                 struct device_handler *device_handler,
257                 const char *id)
258 {
259         return device_lookup(device_handler, device_match_id, id);
260 }
261
262 struct discover_device *device_lookup_by_serial(
263                 struct device_handler *device_handler,
264                 const char *serial)
265 {
266         return device_lookup(device_handler, device_match_serial, serial);
267 }
268
269 void device_handler_destroy(struct device_handler *handler)
270 {
271         talloc_free(handler);
272 }
273
274 static int destroy_device(void *arg)
275 {
276         struct discover_device *dev = arg;
277         struct process *p;
278
279         umount_device(dev);
280
281         devmapper_destroy_snapshot(dev);
282
283         if (dev->crypt_device) {
284                 const char *argv[] = {
285                         pb_system_apps.cryptsetup,
286                         "luksClose",
287                         dev->device->id,
288                         NULL
289                 };
290
291                 p = process_create(dev);
292                 p->path = pb_system_apps.cryptsetup;
293                 p->argv = argv;
294
295                 if (process_run_async(p)) {
296                         pb_log("Failed to run cryptsetup\n");
297                         return -1;
298                 }
299         }
300
301         return 0;
302 }
303
304 struct discover_device *discover_device_create(struct device_handler *handler,
305                 const char *uuid, const char *id)
306 {
307         struct discover_device *dev;
308
309         if (uuid)
310                 dev = device_lookup_by_uuid(handler, uuid);
311         else
312                 dev = device_lookup_by_id(handler, id);
313
314         if (dev)
315                 return dev;
316
317         dev = talloc_zero(handler, struct discover_device);
318         dev->device = talloc_zero(dev, struct device);
319         dev->device->id = talloc_strdup(dev->device, id);
320         dev->uuid = talloc_strdup(dev, uuid);
321         list_init(&dev->params);
322         list_init(&dev->boot_options);
323
324         talloc_set_destructor(dev, destroy_device);
325
326         return dev;
327 }
328
329 struct discover_device_param {
330         char                    *name;
331         char                    *value;
332         struct list_item        list;
333 };
334
335 void discover_device_set_param(struct discover_device *device,
336                 const char *name, const char *value)
337 {
338         struct discover_device_param *param;
339         bool found = false;
340
341         list_for_each_entry(&device->params, param, list) {
342                 if (!strcmp(param->name, name)) {
343                         found = true;
344                         break;
345                 }
346         }
347
348         if (!found) {
349                 if (!value)
350                         return;
351                 param = talloc(device, struct discover_device_param);
352                 param->name = talloc_strdup(param, name);
353                 list_add(&device->params, &param->list);
354         } else {
355                 if (!value) {
356                         list_remove(&param->list);
357                         talloc_free(param);
358                         return;
359                 }
360                 talloc_free(param->value);
361         }
362
363         param->value = talloc_strdup(param, value);
364 }
365
366 const char *discover_device_get_param(struct discover_device *device,
367                 const char *name)
368 {
369         struct discover_device_param *param;
370
371         list_for_each_entry(&device->params, param, list) {
372                 if (!strcmp(param->name, name))
373                         return param->value;
374         }
375         return NULL;
376 }
377
378 static void set_env_variables(const struct config *config)
379 {
380         if (config->http_proxy)
381                 setenv("http_proxy", config->http_proxy, 1);
382         else
383                 unsetenv("http_proxy");
384
385         if (config->https_proxy)
386                 setenv("https_proxy", config->https_proxy, 1);
387         else
388                 unsetenv("https_proxy");
389
390         /* Reduce noise in the log from LVM listing open file descriptors */
391         setenv("LVM_SUPPRESS_FD_WARNINGS", "1", 1);
392 }
393
394 struct device_handler *device_handler_init(struct discover_server *server,
395                 struct waitset *waitset, int dry_run)
396 {
397         struct device_handler *handler;
398         int rc;
399
400         handler = talloc_zero(NULL, struct device_handler);
401         handler->server = server;
402         handler->waitset = waitset;
403         handler->dry_run = dry_run;
404         handler->autoboot_enabled = config_autoboot_active(config_get());
405
406         list_init(&handler->unresolved_boot_options);
407
408         list_init(&handler->progress);
409         list_init(&handler->crypt_devices);
410
411         /* set up our mount point base */
412         pb_mkdir_recursive(mount_base());
413
414         parser_init();
415
416         if (config_get()->safe_mode)
417                 return handler;
418
419         set_env_variables(config_get());
420
421         rc = device_handler_init_sources(handler);
422         if (rc) {
423                 talloc_free(handler);
424                 return NULL;
425         }
426
427         return handler;
428 }
429
430 void device_handler_reinit(struct device_handler *handler)
431 {
432         struct discover_boot_option *opt, *tmp;
433         struct crypt_info *crypt, *c;
434         struct ramdisk_device *ramdisk;
435         struct config *config;
436         unsigned int i;
437
438         device_handler_cancel_default(handler);
439         /* Cancel any pending non-default boot */
440         if (handler->pending_boot) {
441                 boot_cancel(handler->pending_boot);
442                 handler->pending_boot = NULL;
443                 handler->pending_boot_is_default = false;
444         }
445
446         /* Cancel any remaining async jobs */
447         process_stop_async_all();
448         pending_network_jobs_cancel();
449
450         /* free unresolved boot options */
451         list_for_each_entry_safe(&handler->unresolved_boot_options,
452                         opt, tmp, list)
453                 talloc_free(opt);
454         list_init(&handler->unresolved_boot_options);
455
456         /* drop all devices */
457         for (i = 0; i < handler->n_devices; i++) {
458                 struct discover_device *device = handler->devices[i];
459                 discover_server_notify_device_remove(handler->server,
460                                 device->device);
461                 ramdisk = device->ramdisk;
462                 if (device->requery_waiter)
463                         waiter_remove(device->requery_waiter);
464                 talloc_free(device);
465                 talloc_free(ramdisk);
466         }
467
468         talloc_free(handler->devices);
469         handler->devices = NULL;
470         handler->n_devices = 0;
471         talloc_free(handler->ramdisks);
472         handler->ramdisks = NULL;
473         handler->n_ramdisks = 0;
474
475         /* drop any known plugins */
476         for (i = 0; i < handler->n_plugins; i++)
477                 talloc_free(handler->plugins[i]);
478         talloc_free(handler->plugins);
479         handler->plugins = NULL;
480         handler->n_plugins = 0;
481
482         discover_server_notify_plugins_remove(handler->server);
483
484         /* forget encrypted devices */
485         list_for_each_entry_safe(&handler->crypt_devices, crypt, c, list)
486                 talloc_free(crypt);
487         list_init(&handler->crypt_devices);
488
489         set_env_variables(config_get());
490
491         /* If the safe mode warning was active disable it now */
492         if (config_get()->safe_mode) {
493                 config = config_copy(handler, config_get());
494                 config->safe_mode = false;
495                 config_set(config);
496                 discover_server_notify_config(handler->server, config);
497         }
498
499         /* Force rediscovery on SCSI devices */
500         process_run_simple(handler, pb_system_apps.scsi_rescan, NULL);
501
502         device_handler_reinit_sources(handler);
503 }
504
505 void device_handler_remove(struct device_handler *handler,
506                 struct discover_device *device)
507 {
508         struct discover_boot_option *opt, *tmp;
509         unsigned int i;
510
511         if (device->requery_waiter)
512                 waiter_remove(device->requery_waiter);
513
514         list_for_each_entry_safe(&device->boot_options, opt, tmp, list) {
515                 if (opt == handler->default_boot_option) {
516                         pb_log("Default option %s cancelled since device removed",
517                                         opt->option->name);
518                         device_handler_cancel_default(handler);
519                         break;
520                 }
521         }
522
523         for (i = 0; i < handler->n_devices; i++)
524                 if (handler->devices[i] == device)
525                         break;
526
527         if (i == handler->n_devices) {
528                 talloc_free(device);
529                 return;
530         }
531
532         /* Free any unresolved options, as they're currently allocated
533          * against the handler */
534         list_for_each_entry_safe(&handler->unresolved_boot_options,
535                         opt, tmp, list) {
536                 if (opt->device != device)
537                         continue;
538                 list_remove(&opt->list);
539                 talloc_free(opt);
540         }
541
542         /* if this is a network device, we have to unregister it from the
543          * network code */
544         if (device->device->type == DEVICE_TYPE_NETWORK)
545                 network_unregister_device(handler->network, device);
546
547         handler->n_devices--;
548         memmove(&handler->devices[i], &handler->devices[i + 1],
549                 (handler->n_devices - i) * sizeof(handler->devices[0]));
550         handler->devices = talloc_realloc(handler, handler->devices,
551                 struct discover_device *, handler->n_devices);
552
553         if (device->notified)
554                 discover_server_notify_device_remove(handler->server,
555                                                         device->device);
556
557         talloc_free(device);
558 }
559
560 void device_handler_status(struct device_handler *handler,
561                 struct status *status)
562 {
563         pb_debug("%s: %s\n", __func__, status->message);
564         discover_server_notify_boot_status(handler->server, status);
565 }
566
567 static void _device_handler_vstatus(struct device_handler *handler,
568                 enum status_type type, const char *fmt, va_list ap)
569 {
570         struct status status;
571
572         status.type = type;
573         status.message = talloc_vasprintf(handler, fmt, ap);
574         status.backlog = false;
575         status.boot_active = false;
576
577         device_handler_status(handler, &status);
578
579         talloc_free(status.message);
580 }
581
582 static void _device_handler_vdevstatus(struct device_handler *handler,
583                 struct discover_device *device, enum status_type type,
584                 const char *fmt, va_list ap)
585 {
586         char *msg;
587
588         msg = talloc_asprintf(handler, "[%s] %s",
589                         device ? device->device->id : "unknown", fmt);
590         _device_handler_vstatus(handler, type, msg, ap);
591         talloc_free(msg);
592 }
593
594 void device_handler_status_dev_info(struct device_handler *handler,
595                 struct discover_device *dev, const char *fmt, ...)
596 {
597         va_list ap;
598
599         va_start(ap, fmt);
600         _device_handler_vdevstatus(handler, dev, STATUS_INFO, fmt, ap);
601         va_end(ap);
602 }
603
604 void device_handler_status_dev_err(struct device_handler *handler,
605                 struct discover_device *dev, const char *fmt, ...)
606 {
607         va_list ap;
608
609         va_start(ap, fmt);
610         _device_handler_vdevstatus(handler, dev, STATUS_ERROR, fmt, ap);
611         va_end(ap);
612 }
613
614 void device_handler_status_info(struct device_handler *handler,
615                 const char *fmt, ...)
616 {
617         va_list ap;
618
619         va_start(ap, fmt);
620         _device_handler_vstatus(handler, STATUS_INFO, fmt, ap);
621         va_end(ap);
622 }
623
624 void device_handler_status_err(struct device_handler *handler,
625                 const char *fmt, ...)
626 {
627         va_list ap;
628
629         va_start(ap, fmt);
630         _device_handler_vstatus(handler, STATUS_ERROR, fmt, ap);
631         va_end(ap);
632 }
633
634 void device_handler_status_download(struct device_handler *handler,
635                 const struct process_info *procinfo,
636                 unsigned int percentage, unsigned int size, char suffix)
637 {
638         struct progress_info *p, *progress = NULL;
639         uint64_t current_converted, current = 0;
640         const char *units = " kMGTP";
641         unsigned long size_bytes;
642         char *update = NULL;
643         double total = 0;
644         unsigned int i;
645         int unit = 0;
646
647         list_for_each_entry(&handler->progress, p, list)
648                 if (p->procinfo == procinfo)
649                         progress = p;
650
651         if (!progress) {
652                 pb_log("Registering new progress struct\n");
653                 progress = talloc_zero(handler, struct progress_info);
654                 if (!progress) {
655                         pb_log("Failed to allocate room for progress struct\n");
656                         return;
657                 }
658                 progress->procinfo = procinfo;
659                 list_add(&handler->progress, &progress->list);
660                 handler->n_progress++;
661         }
662
663         size_bytes = size;
664         for (i = 0; i < strlen(units); i++) {
665                 if (units[i] == suffix)
666                         break;
667         }
668
669         if (i >= strlen(units)) {
670             pb_log("Couldn't recognise suffix '%c'\n", suffix);
671             size_bytes = 0;
672         } else {
673                 while (i--)
674                         size_bytes <<= 10;
675         }
676
677         progress->percentage = percentage;
678         progress->size = size_bytes;
679
680         /*
681          * Aggregate the info we have and update status. If a progress struct
682          * has zero for both percentage and size we assume progress information
683          * is unavailable and fall back to a generic progress message.
684          */
685         list_for_each_entry(&handler->progress, p, list) {
686                 uint64_t c;
687                 double t;
688                 if (!p->percentage || !p->size) {
689                         update = talloc_asprintf(handler,
690                                         _("%u downloads in progress..."),
691                                         handler->n_progress);
692                         current = total = 0;
693                         break;
694                 }
695
696                 c = p->size;
697                 t = (100 * c) / p->percentage;
698
699                 current += c;
700                 total += t;
701         }
702
703         if (total) {
704                 current_converted = current;
705                 while (current_converted >= 1000) {
706                         current_converted >>= 10;
707                         unit++;
708                 }
709                 update = talloc_asprintf(handler,
710                                 _("%u %s downloading: %.0f%% - %" PRIu64 "%cB"),
711                                 handler->n_progress,
712                                 ngettext("item", "items", handler->n_progress),
713                                 (current / total) * 100, current_converted,
714                                 units[unit]);
715         }
716
717         if (!update) {
718                 pb_log_fn("failed to allocate new status\n");
719         } else {
720                 device_handler_status_info(handler, "%s\n", update);
721                 talloc_free(update);
722         }
723 }
724
725 static void device_handler_plugin_scan_device(struct device_handler *handler,
726                 struct discover_device *dev)
727 {
728         int rc;
729
730         pb_debug("Scanning %s for plugin files\n", dev->device->id);
731
732         rc = process_run_simple(handler, pb_system_apps.pb_plugin,
733                                 "scan", dev->mount_path,
734                                 NULL);
735         if (rc)
736                 pb_log("Error from pb-plugin scan %s\n",
737                                 dev->mount_path);
738 }
739
740 void device_handler_status_download_remove(struct device_handler *handler,
741                 struct process_info *procinfo)
742 {
743         struct progress_info *p, *tmp;
744
745         list_for_each_entry_safe(&handler->progress, p, tmp, list)
746                 if (p->procinfo == procinfo) {
747                         list_remove(&p->list);
748                         talloc_free(p);
749                         handler->n_progress--;
750                 }
751 }
752
753 static void device_handler_boot_status_cb(void *arg, struct status *status)
754 {
755         struct device_handler *handler = arg;
756
757         /* boot had failed; update handler state to allow a new default if one
758          * is found later
759          */
760         if (status->type == STATUS_ERROR) {
761                 handler->pending_boot = NULL;
762                 handler->default_boot_option = NULL;
763         }
764
765         device_handler_status(handler, status);
766 }
767
768 static void countdown_status(struct device_handler *handler,
769                 struct discover_boot_option *opt, unsigned int sec)
770 {
771         struct status status;
772
773         status.type = STATUS_INFO;
774         status.message = talloc_asprintf(handler,
775                         _("Booting in %d sec: [%s] %s"), sec,
776                         opt->device->device->id, opt->option->name);
777         status.backlog = false;
778
779         device_handler_status(handler, &status);
780
781         talloc_free(status.message);
782 }
783
784 static int default_timeout(void *arg)
785 {
786         struct device_handler *handler = arg;
787         struct discover_boot_option *opt;
788
789         if (!handler->default_boot_option)
790                 return 0;
791
792         if (handler->pending_boot)
793                 return 0;
794
795         opt = handler->default_boot_option;
796
797         handler->last_boot_option = opt;
798
799         if (handler->sec_to_boot) {
800                 countdown_status(handler, opt, handler->sec_to_boot);
801                 handler->sec_to_boot--;
802                 handler->timeout_waiter = waiter_register_timeout(
803                                                 handler->waitset, 1000,
804                                                 default_timeout, handler);
805                 return 0;
806         }
807
808         handler->timeout_waiter = NULL;
809
810         pb_log("Timeout expired, booting default option %s\n", opt->option->id);
811
812         platform_pre_boot();
813
814         handler->pending_boot = boot(handler, handler->default_boot_option,
815                         NULL, handler->dry_run, device_handler_boot_status_cb,
816                         handler);
817         handler->pending_boot_is_default = true;
818         return 0;
819 }
820
821 struct {
822         enum ipmi_bootdev       ipmi_type;
823         enum device_type        device_type;
824 } device_type_map[] = {
825         { IPMI_BOOTDEV_NETWORK, DEVICE_TYPE_NETWORK },
826         { IPMI_BOOTDEV_DISK, DEVICE_TYPE_DISK },
827         { IPMI_BOOTDEV_DISK, DEVICE_TYPE_USB },
828         { IPMI_BOOTDEV_CDROM, DEVICE_TYPE_OPTICAL },
829 };
830
831 static bool ipmi_device_type_matches(enum ipmi_bootdev ipmi_type,
832                 enum device_type device_type)
833 {
834         unsigned int i;
835
836         for (i = 0; i < ARRAY_SIZE(device_type_map); i++) {
837                 if (device_type_map[i].device_type == device_type)
838                         return device_type_map[i].ipmi_type == ipmi_type;
839         }
840
841         return false;
842 }
843
844 static bool autoboot_option_matches(struct autoboot_option *opt,
845                 struct discover_device *dev)
846 {
847         if (opt->boot_type == BOOT_DEVICE_UUID)
848                 if (!strcmp(opt->uuid, dev->uuid))
849                         return true;
850
851         if (opt->boot_type == BOOT_DEVICE_TYPE)
852                 if (opt->type == dev->device->type ||
853                     opt->type == DEVICE_TYPE_ANY)
854                         return true;
855
856         return false;
857 }
858
859 static int autoboot_option_priority(const struct config *config,
860                                 struct discover_boot_option *opt)
861 {
862         struct autoboot_option *auto_opt;
863         unsigned int i;
864
865         for (i = 0; i < config->n_autoboot_opts; i++) {
866                 auto_opt = &config->autoboot_opts[i];
867                 if (autoboot_option_matches(auto_opt, opt->device))
868                         return DEFAULT_PRIORITY_LOCAL_FIRST + i;
869         }
870
871         return -1;
872 }
873
874 /*
875  * We have different priorities to resolve conflicts between boot options that
876  * report to be the default for their device. This function assigns a priority
877  * for these options.
878  */
879 static enum default_priority default_option_priority(
880                 struct device_handler *handler,
881                 struct discover_boot_option *opt)
882 {
883         const struct config *config;
884
885         /* Temporary user-provided autoboot options have highest priority */
886         if (handler->temp_autoboot) {
887                 if (autoboot_option_matches(handler->temp_autoboot,
888                                         opt->device))
889                         return DEFAULT_PRIORITY_TEMP_USER;
890
891                 pb_debug("handler: disabled default priority due to "
892                                 "temporary user override\n");
893                 return DEFAULT_PRIORITY_DISABLED;
894         }
895
896         config = config_get();
897
898         /* Next highest priority to IPMI-configured boot options. If we have an
899          * IPMI bootdev configuration set, then we don't allow any other
900          * defaults */
901         if (config->ipmi_bootdev) {
902                 bool ipmi_match = ipmi_device_type_matches(config->ipmi_bootdev,
903                                 opt->device->device->type);
904                 if (ipmi_match)
905                         return DEFAULT_PRIORITY_REMOTE;
906
907                 pb_debug("handler: disabled default priority due to "
908                                 "non-matching IPMI type %x\n",
909                                 config->ipmi_bootdev);
910                 return DEFAULT_PRIORITY_DISABLED;
911         }
912
913         /* Next, try to match the option against the user-defined autoboot
914          * options, either by device UUID or type. */
915         if (config->n_autoboot_opts) {
916                 int boot_match = autoboot_option_priority(config, opt);
917                 if (boot_match > 0)
918                         return boot_match;
919         } else {
920                 /* If there is no specific boot order, boot any device */
921                 return DEFAULT_PRIORITY_LOCAL_FIRST;
922         }
923
924         /* If the option didn't match any entry in the array, it is disabled */
925         pb_debug("handler: disabled default priority due to "
926                         "non-matching UUID or type\n");
927         return DEFAULT_PRIORITY_DISABLED;
928 }
929
930 static void set_default(struct device_handler *handler,
931                 struct discover_boot_option *opt)
932 {
933         enum default_priority cur_prio, new_prio;
934
935         if (!handler->autoboot_enabled)
936                 return;
937
938         pb_debug("handler: new default option: %s\n", opt->option->id);
939
940         new_prio = default_option_priority(handler, opt);
941
942         /* Anything outside our range prevents a default boot */
943         if (new_prio >= DEFAULT_PRIORITY_DISABLED)
944                 return;
945
946         pb_debug("handler: calculated priority %d\n", new_prio);
947
948         /* Resolve any conflicts: if we have a new default option, it only
949          * replaces the current if it has a higher priority. */
950         if (handler->default_boot_option) {
951
952                 cur_prio = handler->default_boot_option_priority;
953
954                 if (new_prio < cur_prio) {
955                         pb_log("handler: new prio %d beats "
956                                         "old prio %d for %s\n",
957                                         new_prio, cur_prio,
958                                         handler->default_boot_option
959                                                 ->option->id);
960                         handler->default_boot_option = opt;
961                         handler->default_boot_option_priority = new_prio;
962                         /* extend the timeout a little, so the user sees some
963                          * indication of the change */
964                         handler->sec_to_boot += 2;
965                 }
966
967                 return;
968         }
969
970         if (handler->default_boot_option)
971                 handler->default_boot_option->option->is_autoboot_default = false;
972         opt->option->is_autoboot_default = true;
973
974         handler->sec_to_boot = config_get()->autoboot_timeout_sec;
975         handler->default_boot_option = opt;
976         handler->default_boot_option_priority = new_prio;
977
978         pb_log("handler: boot option %s set as default, timeout %u sec.\n",
979                opt->option->id, handler->sec_to_boot);
980
981         default_timeout(handler);
982 }
983
984 static char *autoboot_option_desc(void *ctx, const struct autoboot_option *opt)
985 {
986         const char *type, *val;
987
988         if (opt->boot_type == BOOT_DEVICE_TYPE) {
989                 type = _("device type");
990                 val = device_type_display_name(opt->type);
991         } else if (opt->boot_type == BOOT_DEVICE_UUID) {
992                 type = _("device UUID");
993                 val = opt->uuid;
994         } else {
995                 type = _("unknown specifier");
996                 val = NULL;
997         }
998
999         return talloc_asprintf(ctx, "%s = %s", type, val);
1000 }
1001
1002 void device_handler_apply_temp_autoboot(struct device_handler *handler,
1003                 struct autoboot_option *opt)
1004 {
1005         unsigned int i;
1006         char *desc;
1007
1008         handler->temp_autoboot = talloc_steal(handler, opt);
1009
1010         desc = autoboot_option_desc(handler, opt);
1011         device_handler_status_info(handler,
1012                         _("Applying temporary autoboot override: %s"),
1013                         desc);
1014         talloc_free(desc);
1015
1016         if (!handler->autoboot_enabled)
1017                 return;
1018
1019         if (!handler->default_boot_option)
1020                 return;
1021
1022         if (autoboot_option_matches(opt, handler->default_boot_option->device))
1023                 return;
1024
1025         /* cancel the default, and rescan available options */
1026         device_handler_cancel_default(handler);
1027
1028         handler->autoboot_enabled = true;
1029
1030         for (i = 0; i < handler->n_devices; i++) {
1031                 struct discover_device *dev = handler->devices[i];
1032                 struct discover_boot_option *boot_opt;
1033
1034                 if (!autoboot_option_matches(opt, dev))
1035                         continue;
1036
1037                 list_for_each_entry(&dev->boot_options, boot_opt, list) {
1038                         if (boot_opt->option->is_default) {
1039                                 set_default(handler, boot_opt);
1040                                 break;
1041                         }
1042                 }
1043         }
1044 }
1045
1046 static bool resource_is_resolved(struct resource *res)
1047 {
1048         return !res || res->resolved;
1049 }
1050
1051 /* We only use this in an assert, which will disappear if we're compiling
1052  * with NDEBUG, so we need the 'used' attribute for these builds */
1053 static bool __attribute__((used)) boot_option_is_resolved(
1054                 struct discover_boot_option *opt)
1055 {
1056         return resource_is_resolved(opt->boot_image) &&
1057                 resource_is_resolved(opt->initrd) &&
1058                 resource_is_resolved(opt->dtb) &&
1059                 resource_is_resolved(opt->args_sig_file) &&
1060                 resource_is_resolved(opt->icon);
1061 }
1062
1063 static bool resource_resolve(struct resource *res, const char *name,
1064                 struct discover_boot_option *opt,
1065                 struct device_handler *handler)
1066 {
1067         struct parser *parser = opt->source;
1068
1069         if (resource_is_resolved(res))
1070                 return true;
1071
1072         pb_debug("Attempting to resolve resource %s->%s with parser %s\n",
1073                         opt->option->id, name, parser->name);
1074         parser->resolve_resource(handler, res);
1075
1076         return res->resolved;
1077 }
1078
1079 static bool boot_option_resolve(struct discover_boot_option *opt,
1080                 struct device_handler *handler)
1081 {
1082         return resource_resolve(opt->boot_image, "boot_image", opt, handler) &&
1083                 resource_resolve(opt->initrd, "initrd", opt, handler) &&
1084                 resource_resolve(opt->dtb, "dtb", opt, handler) &&
1085                 resource_resolve(opt->args_sig_file, "args_sig_file", opt,
1086                         handler) &&
1087                 resource_resolve(opt->icon, "icon", opt, handler);
1088 }
1089
1090 static void boot_option_finalise(struct device_handler *handler,
1091                 struct discover_boot_option *opt)
1092 {
1093         assert(boot_option_is_resolved(opt));
1094
1095         /* check that the parsers haven't set any of the final data */
1096         assert(!opt->option->boot_image_file);
1097         assert(!opt->option->initrd_file);
1098         assert(!opt->option->dtb_file);
1099         assert(!opt->option->icon_file);
1100         assert(!opt->option->device_id);
1101         assert(!opt->option->args_sig_file);
1102
1103         if (opt->boot_image)
1104                 opt->option->boot_image_file = opt->boot_image->url->full;
1105         if (opt->initrd)
1106                 opt->option->initrd_file = opt->initrd->url->full;
1107         if (opt->dtb)
1108                 opt->option->dtb_file = opt->dtb->url->full;
1109         if (opt->icon)
1110                 opt->option->icon_file = opt->icon->url->full;
1111         if (opt->args_sig_file)
1112                 opt->option->args_sig_file = opt->args_sig_file->url->full;
1113
1114         opt->option->device_id = opt->device->device->id;
1115
1116         if (opt->option->is_default)
1117                 set_default(handler, opt);
1118 }
1119
1120 static void notify_boot_option(struct device_handler *handler,
1121                 struct discover_boot_option *opt)
1122 {
1123         struct discover_device *dev = opt->device;
1124
1125         if (!dev->notified)
1126                 discover_server_notify_device_add(handler->server,
1127                                                   opt->device->device);
1128         dev->notified = true;
1129         discover_server_notify_boot_option_add(handler->server, opt->option);
1130 }
1131
1132 static void process_boot_option_queue(struct device_handler *handler)
1133 {
1134         struct discover_boot_option *opt, *tmp;
1135
1136         list_for_each_entry_safe(&handler->unresolved_boot_options,
1137                         opt, tmp, list) {
1138
1139                 pb_debug("queue: attempting resolution for %s\n",
1140                                 opt->option->id);
1141
1142                 if (!boot_option_resolve(opt, handler))
1143                         continue;
1144
1145                 pb_debug("\tresolved!\n");
1146
1147                 list_remove(&opt->list);
1148                 list_add_tail(&opt->device->boot_options, &opt->list);
1149                 talloc_steal(opt->device, opt);
1150                 boot_option_finalise(handler, opt);
1151                 notify_boot_option(handler, opt);
1152         }
1153 }
1154
1155 struct discover_context *device_handler_discover_context_create(
1156                 struct device_handler *handler,
1157                 struct discover_device *device)
1158 {
1159         struct discover_context *ctx;
1160
1161         ctx = talloc_zero(handler, struct discover_context);
1162         ctx->handler = handler;
1163         ctx->device = device;
1164         list_init(&ctx->boot_options);
1165
1166         return ctx;
1167 }
1168
1169 void device_handler_add_device(struct device_handler *handler,
1170                 struct discover_device *device)
1171 {
1172         handler->n_devices++;
1173         handler->devices = talloc_realloc(handler, handler->devices,
1174                                 struct discover_device *, handler->n_devices);
1175         handler->devices[handler->n_devices - 1] = device;
1176
1177         if (device->device->type == DEVICE_TYPE_NETWORK)
1178                 network_register_device(handler->network, device);
1179 }
1180
1181 void device_handler_add_ramdisk(struct device_handler *handler,
1182                 const char *path)
1183 {
1184         struct ramdisk_device *dev;
1185         unsigned int i;
1186
1187         if (!path)
1188                 return;
1189
1190         for (i = 0; i < handler->n_ramdisks; i++)
1191                 if (!strcmp(handler->ramdisks[i]->path, path))
1192                         return;
1193
1194         dev = talloc_zero(handler, struct ramdisk_device);
1195         if (!dev) {
1196                 pb_log("Failed to allocate memory to track %s\n", path);
1197                 return;
1198         }
1199
1200         dev->path = talloc_strdup(handler, path);
1201
1202         handler->ramdisks = talloc_realloc(handler, handler->ramdisks,
1203                                 struct ramdisk_device *,
1204                                 handler->n_ramdisks + 1);
1205         if (!handler->ramdisks) {
1206                 pb_log("Failed to reallocate memory"
1207                        "- ramdisk tracking inconsistent!\n");
1208                 return;
1209         }
1210
1211         handler->ramdisks[i] = dev;
1212         i = handler->n_ramdisks++;
1213 }
1214
1215 struct ramdisk_device *device_handler_get_ramdisk(
1216                 struct device_handler *handler)
1217 {
1218         unsigned int i;
1219         char *name;
1220         dev_t id;
1221
1222         /* Check if free ramdisk exists */
1223         for (i = 0; i < handler->n_ramdisks; i++)
1224                 if (!handler->ramdisks[i]->snapshot &&
1225                     !handler->ramdisks[i]->origin &&
1226                     !handler->ramdisks[i]->base)
1227                         return handler->ramdisks[i];
1228
1229         /* Otherwise create a new one */
1230         name = talloc_asprintf(handler, "/dev/ram%d",
1231                         handler->n_ramdisks);
1232         if (!name) {
1233                 pb_debug("Failed to allocate memory to name /dev/ram%d",
1234                         handler->n_ramdisks);
1235                 return NULL;
1236         }
1237
1238         id = makedev(1, handler->n_ramdisks);
1239         if (mknod(name, S_IFBLK, id)) {
1240                 if (errno == EEXIST) {
1241                         /* We haven't yet received updates for existing
1242                          * ramdisks - add and use this one */
1243                         pb_debug("Using untracked ramdisk %s\n", name);
1244                 } else {
1245                         pb_log("Failed to create new ramdisk %s: %s\n",
1246                                name, strerror(errno));
1247                         return NULL;
1248                 }
1249         }
1250         device_handler_add_ramdisk(handler, name);
1251         talloc_free(name);
1252
1253         return handler->ramdisks[i];
1254 }
1255
1256 void device_handler_release_ramdisk(struct discover_device *device)
1257 {
1258         struct ramdisk_device *ramdisk = device->ramdisk;
1259
1260         talloc_free(ramdisk->snapshot);
1261         talloc_free(ramdisk->origin);
1262         talloc_free(ramdisk->base);
1263
1264         ramdisk->snapshot = ramdisk->origin = ramdisk->base = NULL;
1265         ramdisk->sectors = 0;
1266
1267         device->ramdisk = NULL;
1268 }
1269
1270 /*
1271  * Check if a device name matches the name of an encrypted device that has been
1272  * opened. If it matches remove it from the list and remove the original crypt
1273  * discover device.
1274  */
1275 bool device_handler_found_crypt_device(struct device_handler *handler,
1276                 const char *name)
1277 {
1278         struct crypt_info *crypt, *c;
1279
1280         list_for_each_entry_safe(&handler->crypt_devices, crypt, c, list) {
1281                 if (!strncmp(crypt->dm_name, name, strlen(crypt->dm_name))) {
1282                         device_handler_remove(handler, crypt->source_device);
1283                         list_remove(&crypt->list);
1284                         talloc_free(crypt);
1285                         return true;
1286                 }
1287         }
1288
1289         return false;
1290 }
1291
1292 static void cryptsetup_cb(struct process *process)
1293 {
1294         struct device_handler *handler = process->data;
1295         struct crypt_info *crypt, *c;
1296
1297         if (process->exit_status == 0)
1298                 return;
1299         device_handler_status_err(handler,
1300                         _("Failed to open encrypted device %s"),
1301                         process->argv[2]);
1302
1303         /*
1304          * Failed to open the device; stop tracking it, but don't remove
1305          * the source device.
1306          */
1307         list_for_each_entry_safe(&handler->crypt_devices, crypt, c, list) {
1308                 if (!strncmp(crypt->dm_name, process->argv[3],
1309                                         strlen(crypt->dm_name))) {
1310                         list_remove(&crypt->list);
1311                         talloc_free(crypt);
1312                         break;
1313                 }
1314         }
1315 }
1316
1317 void device_handler_open_encrypted_dev(struct device_handler *handler,
1318                 char *password, char *device_id)
1319 {
1320         struct discover_device *dev;
1321         struct crypt_info *crypt;
1322         const char *device_path, **argv;
1323         struct process *p;
1324         char *name;
1325         int result;
1326
1327         dev = device_lookup_by_id(handler, device_id);
1328         if (!dev) {
1329                 pb_log_fn("Can't find device %s\n", device_id);
1330                 device_handler_status_err(handler,
1331                                 _("Encrypted device %s does not exist"),
1332                                 device_id);
1333                 return;
1334         }
1335
1336         device_path = dev->device_path;
1337         name = talloc_asprintf(handler, "luks_%s", device_id);
1338
1339         p = process_create(handler);
1340         /* talloc argv under the process so we can access it in cryptsetup_cb */
1341         argv = talloc_zero_array(p, const char *, 6);
1342         argv[0] = talloc_strdup(argv, pb_system_apps.cryptsetup);
1343         argv[1] = talloc_asprintf(argv, "luksOpen");
1344         argv[2] = talloc_strdup(argv, device_path);
1345         argv[3] = talloc_strdup(argv, name);
1346         argv[4] = talloc_asprintf(argv, "-");
1347         argv[5] = NULL;
1348
1349         p->path = pb_system_apps.cryptsetup;
1350         p->argv = (const char **)argv;
1351         p->exit_cb = cryptsetup_cb;
1352         p->data = handler;
1353         p->keep_stdout = true;
1354         p->pipe_stdin = talloc_asprintf(p, "%s\n", password);
1355
1356         result = process_run_async(p);
1357         if (result) {
1358                 pb_log("Failed to run cryptsetup\n");
1359                 return;
1360         }
1361
1362         crypt = talloc(handler, struct crypt_info);
1363         crypt->source_device = dev;
1364         crypt->dm_name = name;
1365         talloc_steal(crypt, name);
1366         list_add(&handler->crypt_devices, &crypt->list);
1367 }
1368
1369 void device_handler_add_encrypted_dev(struct device_handler *handler,
1370                 struct discover_device *dev)
1371 {
1372         system_info_register_blockdev(dev->device->id, dev->uuid, "");
1373         discover_server_notify_device_add(handler->server,
1374                                           dev->device);
1375         dev->notified = true;
1376         if (!device_lookup_by_uuid(handler, dev->uuid))
1377                 device_handler_add_device(handler, dev);
1378 }
1379
1380 /* Start discovery on a hotplugged device. The device will be in our devices
1381  * array, but has only just been initialised by the hotplug source.
1382  */
1383 int device_handler_discover(struct device_handler *handler,
1384                 struct discover_device *dev)
1385 {
1386         struct discover_context *ctx;
1387         int rc;
1388
1389         device_handler_status_dev_info(handler, dev,
1390                 /*
1391                  * TRANSLATORS: this string will be passed the type of the
1392                  * device (eg "disk" or "network"), which will be translated
1393                  * accordingly.
1394                  */
1395                 _("Processing new %s device"),
1396                 device_type_display_name(dev->device->type));
1397
1398         /* create our context */
1399         ctx = device_handler_discover_context_create(handler, dev);
1400
1401         rc = mount_device(dev);
1402         if (rc)
1403                 goto out;
1404
1405         /* add this device to our system info */
1406         system_info_register_blockdev(dev->device->id, dev->uuid,
1407                         dev->mount_path);
1408
1409         /* run the parsers. This will populate the ctx's boot_option list. */
1410         iterate_parsers(ctx);
1411
1412         /* add discovered stuff to the handler */
1413         device_handler_discover_context_commit(handler, ctx);
1414
1415         process_boot_option_queue(handler);
1416
1417         /* Check this device for pb-plugins */
1418         device_handler_plugin_scan_device(handler, dev);
1419 out:
1420         talloc_unlink(handler, ctx);
1421
1422         return 0;
1423 }
1424
1425 struct requery_data {
1426         struct device_handler   *handler;
1427         struct discover_device  *device;
1428 };
1429
1430 static int device_handler_requery_timeout_fn(void *data)
1431 {
1432         struct discover_boot_option *opt, *tmp;
1433         struct requery_data *rqd = data;
1434         struct device_handler *handler;
1435         struct discover_device *device;
1436         bool autoboot;
1437
1438         handler = rqd->handler;
1439         device = rqd->device;
1440
1441         talloc_free(rqd);
1442
1443         /* network_requery_device may re-add a timeout, so clear the device
1444          * waiter here, so we can potentially start a new one. */
1445         device->requery_waiter = NULL;
1446
1447         /* We keep the device around, but get rid of the parsed boot
1448          * options on that device. That involves delaring out the lists,
1449          * and potentially cancelling a default.
1450          */
1451         list_for_each_entry_safe(&handler->unresolved_boot_options,
1452                         opt, tmp, list) {
1453                 if (opt->device != device)
1454                         continue;
1455                 list_remove(&opt->list);
1456                 talloc_free(opt);
1457         }
1458
1459         /* Track whether autoboot was enabled, if we cancel a default option
1460          * it will be switched off.
1461          */
1462         autoboot = handler->autoboot_enabled;
1463
1464         list_for_each_entry_safe(&device->boot_options, opt, tmp, list) {
1465                 if (opt == handler->default_boot_option) {
1466                         pb_log("Default option %s cancelled since device is being requeried\n",
1467                                         opt->option->name);
1468                         device_handler_cancel_default(handler);
1469                 }
1470                 list_remove(&opt->list);
1471                 talloc_free(opt);
1472         }
1473
1474         handler->autoboot_enabled = autoboot;
1475
1476         discover_server_notify_device_remove(handler->server, device->device);
1477         device->notified = false;
1478
1479         network_requery_device(handler->network, device);
1480
1481         return 0;
1482 }
1483
1484 /* Schedule a requery in timeout (seconds).
1485  *
1486  * Special values of timeout:
1487  *   0: no requery
1488  *  -1: use default
1489  */
1490 void device_handler_start_requery_timeout( struct device_handler *handler,
1491                 struct discover_device *dev, int timeout)
1492 {
1493         struct requery_data *rqd;
1494
1495         if (dev->requery_waiter)
1496                 return;
1497
1498         if (timeout == -1)
1499                 timeout = default_rescan_timeout;
1500         else if (timeout == 0)
1501                 return;
1502
1503         rqd = talloc(dev, struct requery_data);
1504         rqd->handler = handler;
1505         rqd->device = dev;
1506
1507         pb_debug("starting requery timeout for device %s, in %d sec\n",
1508                         dev->device->id, timeout);
1509
1510         dev->requery_waiter = waiter_register_timeout(handler->waitset,
1511                         timeout * 1000, device_handler_requery_timeout_fn, rqd);
1512 }
1513
1514 static int event_requery_timeout(struct event *event)
1515 {
1516         int timeout = -1;
1517         unsigned long x;
1518         const char *str;
1519         char *endp;
1520
1521         if (!event)
1522                 return timeout;
1523
1524         str = event_get_param(event, "reboottime");
1525         if (!str)
1526                 return timeout;
1527
1528         x = strtoul(str, &endp, 0);
1529         if (endp != str)
1530                 timeout = x;
1531
1532         return timeout;
1533 }
1534
1535
1536 /* Incoming dhcp event */
1537 int device_handler_dhcp(struct device_handler *handler,
1538                 struct discover_device *dev, struct event *event)
1539 {
1540         struct discover_context *ctx;
1541         const char *ip;
1542
1543         if (event_get_param(event, "ipv6"))
1544                 ip = event_get_param(event, "ipv6");
1545         else
1546                 ip = event_get_param(event, "ip");
1547
1548         device_handler_status_dev_info(handler, dev,
1549                         _("Processing DHCP lease response (ip: %s)"), ip);
1550
1551         pending_network_jobs_start();
1552
1553         /* create our context */
1554         ctx = device_handler_discover_context_create(handler, dev);
1555         talloc_steal(ctx, event);
1556         ctx->event = event;
1557
1558         device_handler_start_requery_timeout(handler, dev,
1559                         event_requery_timeout(event));
1560
1561         iterate_parsers(ctx);
1562
1563         device_handler_discover_context_commit(handler, ctx);
1564
1565         talloc_unlink(handler, ctx);
1566
1567         return 0;
1568 }
1569
1570 struct discover_boot_option *device_handler_find_option_by_name(
1571                 struct device_handler *handler, const char *device,
1572                 const char *name)
1573 {
1574         size_t len = strlen(name);
1575         unsigned int i;
1576
1577         for (i = 0; i < handler->n_devices; i++) {
1578                 struct discover_device *dev = handler->devices[i];
1579                 struct discover_boot_option *opt;
1580
1581                 list_for_each_entry(&dev->boot_options, opt, list)
1582                         /* Match exactly, partial matches can be quite common */
1583                         if (strlen(opt->option->name) == len &&
1584                                         !strcmp(opt->option->name, name))
1585                                 if (!dev || !strcmp(opt->option->device_id, device))
1586                                         return opt;
1587         }
1588
1589         return NULL;
1590 }
1591
1592 static struct discover_boot_option *find_boot_option_by_id(
1593                 struct device_handler *handler, const char *id)
1594 {
1595         unsigned int i;
1596
1597         for (i = 0; i < handler->n_devices; i++) {
1598                 struct discover_device *dev = handler->devices[i];
1599                 struct discover_boot_option *opt;
1600
1601                 list_for_each_entry(&dev->boot_options, opt, list)
1602                         if (!strcmp(opt->option->id, id))
1603                                 return opt;
1604         }
1605
1606         return NULL;
1607 }
1608
1609 void device_handler_boot(struct device_handler *handler,
1610                 bool change_default, struct boot_command *cmd)
1611 {
1612         struct discover_boot_option *opt = NULL;
1613
1614         if (cmd->option_id && strlen(cmd->option_id))
1615                 opt = find_boot_option_by_id(handler, cmd->option_id);
1616
1617         /* Don't allow a normal client to change the default */
1618         if (!change_default && handler->last_boot_option &&
1619                         opt != handler->last_boot_option) {
1620                 pb_log("Non-root user tried to change boot option\n");
1621                 device_handler_status_err(handler,
1622                                 "Must be root to change default boot option\n");
1623                 return;
1624         }
1625
1626         if (handler->pending_boot)
1627                 boot_cancel(handler->pending_boot);
1628
1629         platform_pre_boot();
1630
1631         handler->pending_boot = boot(handler, opt, cmd, handler->dry_run,
1632                         device_handler_boot_status_cb, handler);
1633         handler->pending_boot_is_default = false;
1634 }
1635
1636 void device_handler_cancel_default(struct device_handler *handler)
1637 {
1638         if (handler->timeout_waiter)
1639                 waiter_remove(handler->timeout_waiter);
1640
1641         handler->timeout_waiter = NULL;
1642         handler->autoboot_enabled = false;
1643
1644         /* we only send status if we had a default boot option queued */
1645         if (!handler->default_boot_option)
1646                 return;
1647
1648         pb_log("Cancelling default boot option\n");
1649
1650         if (handler->pending_boot && handler->pending_boot_is_default) {
1651                 boot_cancel(handler->pending_boot);
1652                 handler->pending_boot = NULL;
1653                 handler->pending_boot_is_default = false;
1654         }
1655
1656         handler->default_boot_option = NULL;
1657
1658         device_handler_status_info(handler, _("Default boot cancelled"));
1659 }
1660
1661 void device_handler_update_config(struct device_handler *handler,
1662                 struct config *config)
1663 {
1664         int rc;
1665
1666         rc = config_set(config);
1667         if (rc) {
1668                 device_handler_status_err(handler,
1669                                 "Failed to update configuration!");
1670                 return;
1671         }
1672
1673         discover_server_notify_config(handler->server, config);
1674         device_handler_update_lang(config->lang);
1675         device_handler_reinit(handler);
1676 }
1677
1678 static char *device_from_addr(void *ctx, struct pb_url *url)
1679 {
1680         char *ipaddr, *buf, *tok, *dev = NULL;
1681         bool ipv6_route;
1682         const char *delim = " ";
1683         struct sockaddr_in *ipv4;
1684         struct sockaddr_in6 *ipv6;
1685         struct addrinfo *res;
1686         struct process *p;
1687         int rc;
1688
1689         /* Confirm url->host is either a valid hostname, or a
1690          * valid IPv4 or IPv6 address */
1691         rc = getaddrinfo(url->host, NULL, NULL, &res);
1692         if (rc) {
1693                 pb_debug("%s: Invalid URL\n",__func__);
1694                 return NULL;
1695         }
1696
1697         switch (res->ai_family) {
1698         case AF_INET:   /* ipv4 */
1699                 ipaddr = talloc_array(ctx,char,INET_ADDRSTRLEN);
1700                 ipv4 = (struct sockaddr_in *) res->ai_addr;
1701                 inet_ntop(AF_INET, &(ipv4->sin_addr), ipaddr, INET_ADDRSTRLEN);
1702                 ipv6_route = false;
1703                 break;
1704         case AF_INET6:  /* ipv6 */
1705                 ipaddr = talloc_array(ctx,char,INET6_ADDRSTRLEN);
1706                 ipv6 = (struct sockaddr_in6 *) res->ai_addr;
1707                 inet_ntop(AF_INET6, &(ipv6->sin6_addr), ipaddr, INET6_ADDRSTRLEN);
1708                 ipv6_route = true;
1709                 break;
1710         default:        /* error */
1711                 freeaddrinfo(res);
1712                 return NULL;
1713         }
1714         freeaddrinfo(res);
1715
1716         const char *argv[] = {
1717                 pb_system_apps.ip,
1718                 ipv6_route ? "-6" : "-4",
1719                 "route", "show", "to", "match",
1720                 ipaddr,
1721                 NULL
1722         };
1723
1724         p = process_create(ctx);
1725
1726         p->path = pb_system_apps.ip;
1727         p->argv = argv;
1728         p->keep_stdout = true;
1729
1730         rc = process_run_sync(p);
1731
1732         if (rc || p->exit_status) {
1733                 /* ip has complained for some reason; most likely
1734                  * there is no route to the host - bail out */
1735                 pb_debug("%s: `ip` returns non-zero exit status\n", __func__);
1736                 pb_debug("ip buf: %s\n", p->stdout_buf);
1737                 process_release(p);
1738                 return NULL;
1739         }
1740
1741         buf = p->stdout_buf;
1742         /* If a route is found, ip-route output will be of the form
1743          * "... dev DEVNAME ... " */
1744         tok = strtok(buf, delim);
1745         while (tok) {
1746                 if (!strcmp(tok, "dev")) {
1747                         tok = strtok(NULL, delim);
1748                         dev = talloc_strdup(ctx, tok);
1749                         break;
1750                 }
1751                 tok = strtok(NULL, delim);
1752         }
1753
1754         process_release(p);
1755         if (dev)
1756                 pb_debug("%s: Found interface '%s'\n", __func__,dev);
1757         return dev;
1758 }
1759
1760 static void process_url_cb(struct load_url_result *result, void *data)
1761 {
1762         struct device_handler *handler;
1763         struct discover_context *ctx;
1764         struct discover_device *dev;
1765         struct event *event = data;
1766         const char *mac;
1767
1768         if (result->status != LOAD_OK) {
1769                 pb_log_fn("Load failed for %s\n", result->url->full);
1770                 return;
1771         }
1772
1773         if (!event)
1774                 return;
1775
1776         handler = talloc_parent(event);
1777         if (!handler)
1778                 return;
1779
1780         event->device = device_from_addr(event, result->url);
1781         if (!event->device) {
1782                 pb_log("Downloaded a file but can't find its interface - pretending it was local\n");
1783                 event->device = talloc_asprintf(event, "local");
1784         }
1785
1786         mac = event_get_param(event, "mac");
1787         char *url = talloc_asprintf(event, "file://%s", result->local);
1788         event_set_param(event, "pxeconffile-local", url);
1789
1790         dev = discover_device_create(handler, mac, event->device);
1791         ctx = device_handler_discover_context_create(handler, dev);
1792         talloc_steal(ctx, event);
1793         ctx->event = event;
1794
1795         iterate_parsers(ctx);
1796
1797         device_handler_discover_context_commit(handler, ctx);
1798
1799         talloc_unlink(handler, ctx);
1800 }
1801
1802 void device_handler_process_url(struct device_handler *handler,
1803                 const char *url, const char *mac, const char *ip)
1804 {
1805         struct discover_context *ctx;
1806         struct discover_device *dev;
1807         bool allow_async = false;
1808         struct pb_url *pb_url;
1809         struct event *event;
1810
1811         event = talloc_zero(handler, struct event);
1812         event->type = EVENT_TYPE_USER;
1813         event->action = EVENT_ACTION_URL;
1814
1815         pb_url = pb_url_parse(event, url);
1816         if (!pb_url || (pb_url->scheme != pb_url_file && !pb_url->host)) {
1817                 device_handler_status_err(handler, _("Invalid config URL!"));
1818                 talloc_free(event);
1819                 return;
1820         }
1821
1822         if (url[strlen(url) - 1] == '/') {
1823                 event_set_param(event, "pxepathprefix", url);
1824                 event_set_param(event, "mac", mac);
1825                 event_set_param(event, "ip", ip);
1826                 event->device = device_from_addr(event, pb_url);
1827                 if (!event->device) {
1828                         device_handler_status_err(handler,
1829                                         _("Unable to route to host %s"),
1830                                         pb_url->host);
1831                         talloc_free(event);
1832                         return;
1833                 }
1834         } else {
1835                 event_set_param(event, "pxeconffile", url);
1836                 allow_async = true;
1837         }
1838
1839         if (pb_url->scheme == pb_url_file)
1840                 event->device = talloc_asprintf(event, "local");
1841         else if (allow_async) {
1842                 /* If file is remote load asynchronously before passing to
1843                  * parser. This allows us to wait for network to be available */
1844                 if (!load_url_async(handler, pb_url, process_url_cb, event,
1845                                         NULL, handler)) {
1846                         pb_log("Failed to load url %s\n", pb_url->full);
1847                         device_handler_status_err(handler, _("Failed to load URL!"));
1848                         talloc_free(event);
1849                 }
1850                 return;
1851         }
1852
1853         /* If path is local we can parse straight away */
1854
1855         dev = discover_device_create(handler, mac, event->device);
1856         if (pb_url->scheme == pb_url_file)
1857                 dev->device->type = DEVICE_TYPE_ANY;
1858         ctx = device_handler_discover_context_create(handler, dev);
1859         talloc_steal(ctx, event);
1860         ctx->event = event;
1861
1862         iterate_parsers(ctx);
1863
1864         device_handler_discover_context_commit(handler, ctx);
1865
1866         talloc_unlink(handler, ctx);
1867 }
1868
1869 static void plugin_install_cb(struct process *process)
1870 {
1871         struct device_handler *handler = process->data;
1872
1873         if (!handler) {
1874                 pb_log_fn("Missing data!\n");
1875                 return;
1876         }
1877
1878         handler->plugin_installing = false;
1879         if (process->exit_status) {
1880                 device_handler_status_err(handler, "Plugin failed to install!");
1881                 pb_log("Failed to install plugin:\n%s\n", process->stdout_buf);
1882         }
1883 }
1884
1885 void device_handler_install_plugin(struct device_handler *handler,
1886                 const char *plugin_file)
1887 {
1888         struct process *p;
1889         int result;
1890
1891         if (handler->plugin_installing) {
1892                 pb_log("Plugin install cancelled - install already running");
1893                 return;
1894         }
1895
1896         p = process_create(handler);
1897         if (!p) {
1898                 pb_log("install_plugin: Failed to create process\n");
1899                 return;
1900         }
1901
1902         const char *argv[] = {
1903                 pb_system_apps.pb_plugin,
1904                 "install",
1905                 "auto",
1906                 plugin_file,
1907                 NULL
1908         };
1909
1910         p->path = pb_system_apps.pb_plugin;
1911         p->argv = argv;
1912         p->exit_cb = plugin_install_cb;
1913         p->data = handler;
1914         p->keep_stdout = true;
1915
1916         result = process_run_async(p);
1917
1918         if (result)
1919                 device_handler_status_err(handler, "Could not install plugin");
1920         else
1921                 handler->plugin_installing = true;
1922 }
1923
1924 #ifndef PETITBOOT_TEST
1925
1926 /**
1927  * context_commit - Commit a temporary discovery context to the handler,
1928  * and notify the clients about any new options / devices
1929  */
1930 void device_handler_discover_context_commit(struct device_handler *handler,
1931                 struct discover_context *ctx)
1932 {
1933         struct discover_device *dev = ctx->device;
1934         struct discover_boot_option *opt, *tmp;
1935
1936         if (!device_lookup_by_uuid(handler, dev->uuid))
1937                 device_handler_add_device(handler, dev);
1938
1939         /* move boot options from the context to the device */
1940         list_for_each_entry_safe(&ctx->boot_options, opt, tmp, list) {
1941                 list_remove(&opt->list);
1942
1943                 /* All boot options need at least a kernel image */
1944                 if (!opt->boot_image || !opt->boot_image->url) {
1945                         pb_log("boot option %s is missing boot image, ignoring\n",
1946                                 opt->option->id);
1947                         talloc_free(opt);
1948                         continue;
1949                 }
1950
1951                 if (boot_option_resolve(opt, handler)) {
1952                         pb_log("boot option %s is resolved, "
1953                                         "sending to clients\n",
1954                                         opt->option->id);
1955                         list_add_tail(&dev->boot_options, &opt->list);
1956                         talloc_steal(dev, opt);
1957                         boot_option_finalise(handler, opt);
1958                         notify_boot_option(handler, opt);
1959                 } else {
1960                         if (!opt->source->resolve_resource) {
1961                                 pb_log("parser %s gave us an unresolved "
1962                                         "resource (%s), but no way to "
1963                                         "resolve it\n",
1964                                         opt->source->name, opt->option->id);
1965                                 talloc_free(opt);
1966                         } else {
1967                                 pb_log("boot option %s is unresolved, "
1968                                                 "adding to queue\n",
1969                                                 opt->option->id);
1970                                 list_add(&handler->unresolved_boot_options,
1971                                                 &opt->list);
1972                                 talloc_steal(handler, opt);
1973                         }
1974                 }
1975         }
1976 }
1977
1978 void device_handler_add_plugin_option(struct device_handler *handler,
1979                 struct plugin_option *opt)
1980 {
1981         struct plugin_option *tmp;
1982         unsigned int i;
1983
1984         for (i = 0; i < handler->n_plugins; i++) {
1985                 tmp = handler->plugins[i];
1986                 /* If both id and version match, ignore */
1987                 if (strncmp(opt->id, tmp->id, strlen(opt->id)) == 0 &&
1988                                 strcmp(opt->version, tmp->version) == 0) {
1989                         pb_log("discover: Plugin '%s' already exists, ignoring\n",
1990                                         opt->id);
1991                         return;
1992                 }
1993         }
1994
1995         handler->plugins = talloc_realloc(handler, handler->plugins,
1996                         struct plugin_option *, handler->n_plugins + 1);
1997         if (!handler->plugins) {
1998                 pb_log("Failed to allocate memory for new plugin\n");
1999                 handler->n_plugins = 0;
2000                 return;
2001         }
2002
2003         handler->plugins[handler->n_plugins++] = opt;
2004         discover_server_notify_plugin_option_add(handler->server, opt);
2005 }
2006
2007 static void device_handler_update_lang(const char *lang)
2008 {
2009         const char *cur_lang;
2010
2011         if (!lang)
2012                 return;
2013
2014         cur_lang = setlocale(LC_ALL, NULL);
2015         if (cur_lang && !strcmp(cur_lang, lang))
2016                 return;
2017
2018         setlocale(LC_ALL, lang);
2019 }
2020
2021 static int device_handler_init_sources(struct device_handler *handler)
2022 {
2023         /* init our device sources: udev, network and user events */
2024         handler->user_event = user_event_init(handler, handler->waitset);
2025         if (!handler->user_event)
2026                 return -1;
2027
2028         handler->network = network_init(handler, handler->waitset,
2029                         handler->dry_run);
2030         if (!handler->network)
2031                 return -1;
2032
2033         handler->udev = udev_init(handler, handler->waitset);
2034         if (!handler->udev)
2035                 return -1;
2036
2037         return 0;
2038 }
2039
2040 static void device_handler_reinit_sources(struct device_handler *handler)
2041 {
2042         /* if we haven't initialised sources previously (becuase we started in
2043          * safe mode), then init once here. */
2044         if (!(handler->udev || handler->network || handler->user_event)) {
2045                 device_handler_init_sources(handler);
2046                 return;
2047         }
2048
2049         system_info_reinit();
2050
2051         network_shutdown(handler->network);
2052         handler->network = network_init(handler, handler->waitset,
2053                         handler->dry_run);
2054
2055         udev_reinit(handler->udev);
2056 }
2057
2058 static inline const char *get_device_path(struct discover_device *dev)
2059 {
2060         return dev->ramdisk ? dev->ramdisk->snapshot : dev->device_path;
2061 }
2062
2063 static char *check_subvols(struct discover_device *dev)
2064 {
2065         const char *fstype = discover_device_get_param(dev, "ID_FS_TYPE");
2066         struct stat sb;
2067         char *path;
2068         int rc;
2069
2070         if (strncmp(fstype, "btrfs", strlen("btrfs")))
2071                 return dev->mount_path;
2072
2073         /* On btrfs a device's root may be under a subvolume path */
2074         path = join_paths(dev, dev->mount_path, "@");
2075         rc = stat(path, &sb);
2076         if (!rc && S_ISDIR(sb.st_mode)) {
2077                 pb_debug("Using '%s' for btrfs root path\n", path);
2078                 return path;
2079         }
2080
2081         talloc_free(path);
2082         return dev->mount_path;
2083 }
2084
2085 static bool check_existing_mount(struct discover_device *dev)
2086 {
2087         struct stat devstat, mntstat;
2088         const char *device_path;
2089         struct mntent *mnt;
2090         FILE *fp;
2091         int rc;
2092
2093         device_path = get_device_path(dev);
2094
2095         rc = stat(device_path, &devstat);
2096         if (rc) {
2097                 pb_debug("%s: stat failed: %s\n", __func__, strerror(errno));
2098                 return false;
2099         }
2100
2101         if (!S_ISBLK(devstat.st_mode)) {
2102                 pb_debug("%s: %s isn't a block device?\n", __func__,
2103                                 dev->device_path);
2104                 return false;
2105         }
2106
2107         fp = fopen("/proc/self/mounts", "r");
2108
2109         for (;;) {
2110                 mnt = getmntent(fp);
2111                 if (!mnt)
2112                         break;
2113
2114                 if (!mnt->mnt_fsname || mnt->mnt_fsname[0] != '/')
2115                         continue;
2116
2117                 rc = stat(mnt->mnt_fsname, &mntstat);
2118                 if (rc)
2119                         continue;
2120
2121                 if (!S_ISBLK(mntstat.st_mode))
2122                         continue;
2123
2124                 if (mntstat.st_rdev == devstat.st_rdev) {
2125                         dev->mount_path = talloc_strdup(dev, mnt->mnt_dir);
2126                         dev->root_path = check_subvols(dev);
2127                         dev->mounted_rw = !!hasmntopt(mnt, "rw");
2128                         dev->mounted = true;
2129                         dev->unmount = false;
2130
2131                         pb_debug("%s: %s is already mounted (r%c) at %s\n",
2132                                         __func__, dev->device_path,
2133                                         dev->mounted_rw ? 'w' : 'o',
2134                                         mnt->mnt_dir);
2135                         break;
2136                 }
2137         }
2138
2139         fclose(fp);
2140
2141         return mnt != NULL;
2142 }
2143
2144 /*
2145  * Attempt to mount a filesystem safely, while handling certain filesytem-
2146  * specific options
2147  */
2148 static int try_mount(const char *device_path, const char *mount_path,
2149                              const char *fstype, unsigned long flags,
2150                              bool have_snapshot)
2151 {
2152         const char *fs, *safe_opts;
2153         int rc;
2154
2155         /* Mount ext3 as ext4 instead so 'norecovery' can be used */
2156         if (strncmp(fstype, "ext3", strlen("ext3")) == 0) {
2157                 pb_debug("Mounting ext3 filesystem as ext4\n");
2158                 fs = "ext4";
2159         } else
2160                 fs = fstype;
2161
2162         if (strncmp(fs, "xfs", strlen("xfs")) == 0 ||
2163             strncmp(fs, "ext4", strlen("ext4")) == 0)
2164                 safe_opts = "norecovery";
2165         else
2166                 safe_opts = NULL;
2167
2168         errno = 0;
2169         /* If no snapshot is available don't attempt recovery */
2170         if (!have_snapshot)
2171                 return mount(device_path, mount_path, fs, flags, safe_opts);
2172
2173         rc = mount(device_path, mount_path, fs, flags, NULL);
2174
2175         if (!rc)
2176                 return rc;
2177
2178         /* Mounting failed; some filesystems will fail to mount if a recovery
2179          * journal exists (eg. cross-endian XFS), so try again with norecovery
2180          * where that option is available.
2181          * If mounting read-write just return the error as norecovery is not a
2182          * valid option */
2183         if ((flags & MS_RDONLY) != MS_RDONLY || !safe_opts)
2184                 return rc;
2185
2186         errno = 0;
2187         return mount(device_path, mount_path, fs, flags, safe_opts);
2188 }
2189
2190 static int mount_device(struct discover_device *dev)
2191 {
2192         const char *fstype, *device_path;
2193         int rc;
2194
2195         if (!dev->device_path)
2196                 return -1;
2197
2198         if (dev->mounted)
2199                 return 0;
2200
2201         if (check_existing_mount(dev))
2202                 return 0;
2203
2204         fstype = discover_device_get_param(dev, "ID_FS_TYPE");
2205         if (!fstype)
2206                 return 0;
2207
2208         dev->mount_path = join_paths(dev, mount_base(),
2209                                         dev->device_path);
2210
2211         if (pb_mkdir_recursive(dev->mount_path)) {
2212                 pb_log("couldn't create mount directory %s: %s\n",
2213                                 dev->mount_path, strerror(errno));
2214                 goto err_free;
2215         }
2216
2217         device_path = get_device_path(dev);
2218
2219         pb_log("mounting device %s read-only\n", dev->device_path);
2220         rc = try_mount(device_path, dev->mount_path, fstype,
2221                        MS_RDONLY | MS_SILENT, dev->ramdisk);
2222
2223         /* If mount fails clean up any snapshot and try again */
2224         if (rc && dev->ramdisk) {
2225                 pb_log("couldn't mount snapshot for %s: mount failed: %s\n",
2226                                 device_path, strerror(errno));
2227                 pb_log("falling back to actual device\n");
2228
2229                 devmapper_destroy_snapshot(dev);
2230
2231                 device_path = get_device_path(dev);
2232                 pb_log("mounting device %s read-only\n", dev->device_path);
2233                 rc = try_mount(device_path, dev->mount_path, fstype,
2234                                MS_RDONLY | MS_SILENT, dev->ramdisk);
2235         }
2236
2237         if (!rc) {
2238                 dev->mounted = true;
2239                 dev->mounted_rw = false;
2240                 dev->unmount = true;
2241                 dev->root_path = check_subvols(dev);
2242                 return 0;
2243         }
2244
2245         pb_log("couldn't mount device %s: mount failed: %s\n",
2246                         device_path, strerror(errno));
2247
2248         pb_rmdir_recursive(mount_base(), dev->mount_path);
2249 err_free:
2250         talloc_free(dev->mount_path);
2251         dev->mount_path = NULL;
2252         return -1;
2253 }
2254
2255 static int umount_device(struct discover_device *dev)
2256 {
2257         const char *device_path;
2258         int rc;
2259
2260         if (!dev->mounted || !dev->unmount)
2261                 return 0;
2262
2263         device_path = get_device_path(dev);
2264
2265         pb_log("unmounting device %s\n", device_path);
2266         rc = umount(dev->mount_path);
2267         if (rc)
2268                 return -1;
2269
2270         dev->mounted = false;
2271
2272         pb_rmdir_recursive(mount_base(), dev->mount_path);
2273
2274         talloc_free(dev->mount_path);
2275         dev->mount_path = NULL;
2276         dev->root_path = NULL;
2277
2278         return 0;
2279 }
2280
2281 int device_request_write(struct discover_device *dev, bool *release)
2282 {
2283         const char *fstype, *device_path;
2284         const struct config *config;
2285         int rc;
2286
2287         *release = false;
2288
2289         config = config_get();
2290         if (!config->allow_writes)
2291                 return -1;
2292
2293         if (!dev->mounted)
2294                 return -1;
2295
2296         if (dev->mounted_rw)
2297                 return 0;
2298
2299         fstype = discover_device_get_param(dev, "ID_FS_TYPE");
2300
2301         device_path = get_device_path(dev);
2302
2303         pb_log("remounting device %s read-write\n", device_path);
2304
2305         rc = umount(dev->mount_path);
2306         if (rc) {
2307                 pb_log("Failed to unmount %s: %s\n",
2308                        dev->mount_path, strerror(errno));
2309                 return -1;
2310         }
2311
2312         rc = try_mount(device_path, dev->mount_path, fstype,
2313                        MS_SILENT, dev->ramdisk);
2314         if (rc)
2315                 goto mount_ro;
2316
2317         dev->mounted_rw = true;
2318         *release = true;
2319         return 0;
2320
2321 mount_ro:
2322         pb_log("Unable to remount device %s read-write: %s\n",
2323                device_path, strerror(errno));
2324         rc = try_mount(device_path, dev->mount_path, fstype,
2325                        MS_RDONLY | MS_SILENT, dev->ramdisk);
2326         if (rc)
2327                 pb_log("Unable to recover mount for %s: %s\n",
2328                        device_path, strerror(errno));
2329         return -1;
2330 }
2331
2332 void device_release_write(struct discover_device *dev, bool release)
2333 {
2334         const char *fstype, *device_path;
2335
2336         if (!release)
2337                 return;
2338
2339         device_path = get_device_path(dev);
2340
2341         fstype = discover_device_get_param(dev, "ID_FS_TYPE");
2342
2343         pb_log("remounting device %s read-only\n", device_path);
2344
2345         if (umount(dev->mount_path)) {
2346                 pb_log("Failed to unmount %s\n", dev->mount_path);
2347                 return;
2348         }
2349         dev->mounted_rw = dev->mounted = false;
2350
2351         if (dev->ramdisk) {
2352                 devmapper_merge_snapshot(dev);
2353                 /* device_path becomes stale after merge */
2354                 device_path = get_device_path(dev);
2355         }
2356
2357         if (try_mount(device_path, dev->mount_path, fstype,
2358                        MS_RDONLY | MS_SILENT, dev->ramdisk))
2359                 pb_log("Failed to remount %s read-only: %s\n",
2360                        device_path, strerror(errno));
2361         else
2362                 dev->mounted = true;
2363 }
2364
2365 void device_sync_snapshots(struct device_handler *handler, const char *device)
2366 {
2367         struct discover_device *dev = NULL;
2368         unsigned int i;
2369
2370         if (device) {
2371                 /* Find matching device and sync */
2372                 dev = device_lookup_by_name(handler, device);
2373                 if (!dev) {
2374                         pb_log("%s: device name '%s' unrecognised\n",
2375                                 __func__, device);
2376                         return;
2377                 }
2378                 if (dev->ramdisk)
2379                         device_release_write(dev, true);
2380                 else
2381                         pb_log("%s has no snapshot to merge, skipping\n",
2382                                 dev->device->id);
2383                 return;
2384         }
2385
2386         /* Otherwise sync all relevant devices */
2387         for (i = 0; i < handler->n_devices; i++) {
2388                 dev = handler->devices[i];
2389                 if (dev->device->type != DEVICE_TYPE_DISK &&
2390                         dev->device->type != DEVICE_TYPE_USB)
2391                         continue;
2392                 if (dev->ramdisk)
2393                         device_release_write(dev, true);
2394                 else
2395                         pb_log("%s has no snapshot to merge, skipping\n",
2396                                 dev->device->id);
2397         }
2398 }
2399
2400 #else
2401
2402 void device_handler_discover_context_commit(
2403                 struct device_handler *handler __attribute__((unused)),
2404                 struct discover_context *ctx __attribute__((unused)))
2405 {
2406         pb_log_fn("stubbed out for test cases\n");
2407 }
2408
2409 static void device_handler_update_lang(const char *lang __attribute__((unused)))
2410 {
2411 }
2412
2413 static int device_handler_init_sources(
2414                 struct device_handler *handler __attribute__((unused)))
2415 {
2416         return 0;
2417 }
2418
2419 static void device_handler_reinit_sources(
2420                 struct device_handler *handler __attribute__((unused)))
2421 {
2422 }
2423
2424 static int umount_device(struct discover_device *dev __attribute__((unused)))
2425 {
2426         return 0;
2427 }
2428
2429 static int __attribute__((unused)) mount_device(
2430                 struct discover_device *dev __attribute__((unused)))
2431 {
2432         return 0;
2433 }
2434
2435 int device_request_write(struct discover_device *dev __attribute__((unused)),
2436                 bool *release)
2437 {
2438         *release = true;
2439         return 0;
2440 }
2441
2442 void device_release_write(struct discover_device *dev __attribute__((unused)),
2443         bool release __attribute__((unused)))
2444 {
2445 }
2446
2447 void device_sync_snapshots(
2448                 struct device_handler *handler __attribute__((unused)),
2449                 const char *device __attribute__((unused)))
2450 {
2451 }
2452
2453 #endif