X-Git-Url: https://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=devices%2Fudev-helper.c;h=87a7fc19ab431827c15ec1615cd94a23b5b5d113;hp=661fb08b4ef9c2021984109b78d2d3af68fe9943;hb=a57e4ef92b8e590643a325d309511306c5b941a9;hpb=7d7c328016aca3e14aee6268a2e7881d3440e226 diff --git a/devices/udev-helper.c b/devices/udev-helper.c index 661fb08..87a7fc1 100644 --- a/devices/udev-helper.c +++ b/devices/udev-helper.c @@ -19,6 +19,7 @@ #include #include "parser.h" +#include "paths.h" #include "petitboot-paths.h" /* Define below to operate without the frontend */ @@ -183,67 +184,95 @@ int connect_to_socket() #endif } -struct device_map { - char *dev, *mnt; -}; +static int mkdir_recursive(const char *dir) +{ + char *str, *sep; + int mode = 0755; + struct stat statbuf; -#define DEVICE_MAP_SIZE 32 -static struct device_map device_map[DEVICE_MAP_SIZE]; + pb_log("mkdir_recursive(%s)\n", dir); -const char *mountpoint_for_device(const char *dev_path) -{ - int i; - const char *basename; - - /* shorten '/dev/foo' to 'foo' */ - basename = strrchr(dev_path, '/'); - if (basename) - basename++; - else - basename = dev_path; - - /* check existing entries in the map */ - for (i = 0; (i < DEVICE_MAP_SIZE) && device_map[i].dev; i++) - if (!strcmp(device_map[i].dev, basename)) - return device_map[i].mnt; - - if (i == DEVICE_MAP_SIZE) - return NULL; - - device_map[i].dev = strdup(dev_path); - asprintf(&device_map[i].mnt, "%s/%s", TMP_DIR, basename); - return device_map[i].mnt; + if (!*dir) + return 0; + + if (!stat(dir, &statbuf)) { + if (!S_ISDIR(statbuf.st_mode)) { + pb_log("%s: %s exists, but isn't a directory\n", + __func__, dir); + return -1; + } + return 0; + } + + str = strdup(dir); + sep = strchr(*str == '/' ? str + 1 : str, '/'); + + while (1) { + + /* terminate the path at sep */ + if (sep) + *sep = '\0'; + pb_log("mkdir(%s)\n", str); + + if (mkdir(str, mode) && errno != EEXIST) { + pb_log("mkdir(%s): %s\n", str, strerror(errno)); + return -1; + } + + if (!sep) + break; + + /* reset dir to the full path */ + strcpy(str, dir); + sep = strchr(sep + 1, '/'); + } + + free(str); + + return 0; } -/** - * Resolve a path given in a config file, to a path in the local filesystem. - * Paths may be of the form: - * device:path (eg /dev/sda:/boot/vmlinux) - * - * or just a path: - * /boot/vmlinux - * - in this case, the default mountpoint is used. - * - * Returns a newly-allocated string containing a full path to the file in path - */ -char *resolve_path(const char *path, const char *default_mountpoint) +static void setup_device_links(const char *device) { - char *ret; - const char *devpath, *sep; + struct link { + char *env, *dir; + } *link, links[] = { + { + .env = "ID_FS_UUID", + .dir = "disk/by-uuid" + }, + { + .env = "ID_FS_LABEL", + .dir = "disk/by-label" + }, + { + .env = NULL + } + }; - sep = strchr(path, ':'); - if (!sep) { - devpath = default_mountpoint; - asprintf(&ret, "%s/%s", devpath, path); - } else { - /* copy just the device name into tmp */ - char *dev = strndup(path, sep - path); - devpath = mountpoint_for_device(dev); - asprintf(&ret, "%s/%s", devpath, sep + 1); - free(dev); - } + for (link = links; link->env; link++) { + char *value, *dir, *path; - return ret; + value = getenv(link->env); + if (!value) + continue; + + value = encode_label(value); + dir = join_paths(TMP_DIR, link->dir); + path = join_paths(dir, value); + + if (!mkdir_recursive(dir)) { + unlink(path); + if (symlink(mountpoint_for_device(device), path)) { + pb_log("symlink(%s): %s\n", + path, strerror(errno)); + } + } + + free(path); + free(dir); + free(value); + } } int mount_device(const char *dev_path) @@ -286,8 +315,10 @@ int mount_device(const char *dev_path) goto out; } - if (WIFEXITED(status) && WEXITSTATUS(status) == 0) + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + setup_device_links(dev_path); rc = 0; + } out: return rc; @@ -399,7 +430,8 @@ static int is_removable_device(const char *sysfs_path) static int is_ignored_device(const char *devname) { - static const char *ignored_devices[] = { "/dev/ram", NULL }; + static const char *ignored_devices[] = + { "/dev/ram", "/dev/loop", NULL }; const char **dev; for (dev = ignored_devices; *dev; dev++) @@ -457,35 +489,30 @@ static int poll_device_plug(const char *dev_path, /* Polling loop for optical drive */ for (; (*optical) != 0; ) { - pb_log("poll for optical drive insertion ...\n"); fd = open(dev_path, O_RDONLY|O_NONBLOCK); if (fd < 0) return EXIT_FAILURE; rc = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT); close(fd); - if (rc == -1) { - pb_log("not an optical drive, fallback...\n"); + if (rc == -1) break; - } + *optical = 1; if (rc == CDS_DISC_OK) return EXIT_SUCCESS; - pb_log("no... waiting\n"); detach_and_sleep(REMOVABLE_SLEEP_DELAY); } /* Fall back to bare open() */ *optical = 0; for (;;) { - pb_log("poll for non-optical drive insertion ...\n"); fd = open(dev_path, O_RDONLY); if (fd < 0 && errno != ENOMEDIUM) return EXIT_FAILURE; close(fd); if (fd >= 0) return EXIT_SUCCESS; - pb_log("no... waiting\n"); detach_and_sleep(REMOVABLE_SLEEP_DELAY); } } @@ -495,7 +522,6 @@ static int poll_device_unplug(const char *dev_path, int optical) int rc, fd; for (;optical;) { - pb_log("poll for optical drive removal ...\n"); fd = open(dev_path, O_RDONLY|O_NONBLOCK); if (fd < 0) return EXIT_FAILURE; @@ -503,20 +529,17 @@ static int poll_device_unplug(const char *dev_path, int optical) close(fd); if (rc != CDS_DISC_OK) return EXIT_SUCCESS; - pb_log("no... waiting\n"); detach_and_sleep(REMOVABLE_SLEEP_DELAY); } /* Fall back to bare open() */ for (;;) { - pb_log("poll for non-optical drive removal ...\n"); fd = open(dev_path, O_RDONLY); if (fd < 0 && errno != ENOMEDIUM) return EXIT_FAILURE; close(fd); if (fd < 0) return EXIT_SUCCESS; - pb_log("no... waiting\n"); detach_and_sleep(REMOVABLE_SLEEP_DELAY); } } @@ -551,7 +574,7 @@ int main(int argc, char **argv) action = getenv("ACTION"); - logf = fopen("/var/tmp/petitboot-udev-helpers.log", "a"); + logf = fopen("/var/log/petitboot-udev-helpers.log", "a"); if (!logf) logf = stdout; pb_log("%d started\n", getpid()); @@ -562,6 +585,8 @@ int main(int argc, char **argv) return EXIT_FAILURE; } + set_mount_base(TMP_DIR); + if (connect_to_socket()) return EXIT_FAILURE;