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