X-Git-Url: https://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=devices%2Fudev-helper.c;h=4826f9da73f2cf16a2e86e9d58ce6ad1d5e719da;hp=fdb128eaab28d9596f4ff9943925c5a789003d55;hb=63b749195c6910306ecc86636ba8ab55789af03f;hpb=bdb389592338a2f69af98d763a39c617374c1233 diff --git a/devices/udev-helper.c b/devices/udev-helper.c index fdb128e..4826f9d 100644 --- a/devices/udev-helper.c +++ b/devices/udev-helper.c @@ -1,4 +1,6 @@ +#define _GNU_SOURCE + #include #include #include @@ -33,7 +35,7 @@ void pb_log(const char *fmt, ...) va_list ap; va_start(ap, fmt); - fprintf(logf, fmt, ap); + vfprintf(logf, fmt, ap); va_end(ap); } @@ -181,28 +183,92 @@ int connect_to_socket() #endif } -int mount_device(const char *dev_path, char *mount_path) +struct device_map { + char *dev, *mnt; +}; + +#define DEVICE_MAP_SIZE 32 +static struct device_map device_map[DEVICE_MAP_SIZE]; + +const char *mountpoint_for_device(const char *dev_path) { - char *dir; + int i; const char *basename; - int pid, status, rc = -1; - basename = strrchr(dev_path, '/'); - if (basename) - basename++; - else + /* shorten '/dev/foo' to 'foo' */ + basename = strrchr(dev_path, '/'); + if (basename) + basename++; + else basename = dev_path; - - /* create a unique mountpoint */ - dir = malloc(strlen(TMP_DIR) + 13 + strlen(basename)); - sprintf(dir, "%s/mnt-%s-XXXXXX", TMP_DIR, basename); - - if (!mkdtemp(dir)) { - pb_log("failed to create temporary directory in %s: %s", - TMP_DIR, strerror(errno)); - goto out; + + /* 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; +} + +/** + * 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) +{ + char *ret; + const char *devpath, *sep; + + 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); } + return ret; +} + +int mount_device(const char *dev_path) +{ + const char *dir; + int pid, status, rc = -1; + struct stat statbuf; + + dir = mountpoint_for_device(dev_path); + + if (stat(dir, &statbuf)) { + if (mkdir(dir, 0755)) { + pb_log("couldn't create directory %s: %s\n", + dir, strerror(errno)); + goto out; + } + } else { + if (!S_ISDIR(statbuf.st_mode)) { + pb_log("mountpoint %s exists, " + "but isn't a directory\n", dir); + goto out; + } + } + + pid = fork(); if (pid == -1) { pb_log("%s: fork failed: %s\n", __FUNCTION__, strerror(errno)); @@ -220,13 +286,10 @@ int mount_device(const char *dev_path, char *mount_path) goto out; } - if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { - strcpy(mount_path, dir); + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) rc = 0; - } out: - free(dir); return rc; } @@ -348,9 +411,9 @@ static int is_ignored_device(const char *devname) static int found_new_device(const char *dev_path) { - char mountpoint[PATH_MAX]; + const char *mountpoint = mountpoint_for_device(dev_path); - if (mount_device(dev_path, mountpoint)) { + if (mount_device(dev_path)) { pb_log("failed to mount %s\n", dev_path); return EXIT_FAILURE; } @@ -488,7 +551,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());