summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Kerr <jk@ozlabs.org>2008-01-07 21:25:22 +1100
committerJeremy Kerr <jk@ozlabs.org>2008-01-07 21:25:22 +1100
commitd56c4f5febce598f7ddc1fd5e78ec6ee621a0d9b (patch)
tree5ee8e974ce8067606090d1a6b7e9c7a4d1977f14
parentaab818c10b1fa68b968cabc852680f8ec0fe1360 (diff)
downloadtalos-petitboot-d56c4f5febce598f7ddc1fd5e78ec6ee621a0d9b.tar.gz
talos-petitboot-d56c4f5febce598f7ddc1fd5e78ec6ee621a0d9b.zip
Create uuid and label symlinks when mounting devices
When we discover a device with ID_FS_UUID or ID_FS_LABEL properties, create a symlink in the mount tree. This will end up with a mount tree structure mirroring /dev, and allow devices to be referenced by uuid when booting is attempted. Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
-rw-r--r--devices/paths.c2
-rw-r--r--devices/paths.h4
-rw-r--r--devices/udev-helper.c95
3 files changed, 99 insertions, 2 deletions
diff --git a/devices/paths.c b/devices/paths.c
index e9bf6cb..2373c28 100644
--- a/devices/paths.c
+++ b/devices/paths.c
@@ -15,7 +15,7 @@ struct device_map {
#define DEVICE_MAP_SIZE 32
static struct device_map device_map[DEVICE_MAP_SIZE];
-static char *encode_label(const char *label)
+char *encode_label(const char *label)
{
char *str, *c;
int i;
diff --git a/devices/paths.h b/devices/paths.h
index a6f01c4..26d4ce4 100644
--- a/devices/paths.h
+++ b/devices/paths.h
@@ -45,5 +45,9 @@ void set_mount_base(const char *path);
*/
char *join_paths(const char *a, const char *b);
+/**
+ * encode a disk label (or uuid) for use in a symlink.
+ */
+char *encode_label(const char *label);
#endif /* PATHS_H */
diff --git a/devices/udev-helper.c b/devices/udev-helper.c
index a55d378..f77777a 100644
--- a/devices/udev-helper.c
+++ b/devices/udev-helper.c
@@ -184,6 +184,97 @@ int connect_to_socket()
#endif
}
+static int mkdir_recursive(const char *dir)
+{
+ char *str, *sep;
+ int mode = 0755;
+ struct stat statbuf;
+
+ pb_log("mkdir_recursive(%s)\n", dir);
+
+ 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;
+}
+
+static void setup_device_links(const char *device)
+{
+ 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
+ }
+ };
+
+ for (link = links; link->env; link++) {
+ char *value, *dir, *path;
+
+ 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)
{
const char *dir;
@@ -224,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;
OpenPOWER on IntegriCloud