diff --git a/src/boot/ostree-prepare-root.service b/src/boot/ostree-prepare-root.service index 510d866a4c..797148c9bc 100644 --- a/src/boot/ostree-prepare-root.service +++ b/src/boot/ostree-prepare-root.service @@ -17,7 +17,6 @@ Description=OSTree Prepare OS/ Documentation=man:ostree(1) DefaultDependencies=no -ConditionKernelCommandLine=ostree ConditionPathExists=/etc/initrd-release OnFailure=emergency.target After=sysroot.mount diff --git a/src/boot/ostree-remount.service b/src/boot/ostree-remount.service index 7c0d01a3bb..9e58a08aa5 100644 --- a/src/boot/ostree-remount.service +++ b/src/boot/ostree-remount.service @@ -17,7 +17,6 @@ Description=OSTree Remount OS/ Bind Mounts Documentation=man:ostree(1) DefaultDependencies=no -ConditionKernelCommandLine=ostree OnFailure=emergency.target Conflicts=umount.target # Run after core mounts diff --git a/src/switchroot/ostree-mount-util.h b/src/switchroot/ostree-mount-util.h index 92bc802786..34e67a1643 100644 --- a/src/switchroot/ostree-mount-util.h +++ b/src/switchroot/ostree-mount-util.h @@ -21,6 +21,7 @@ #ifndef __OSTREE_MOUNT_UTIL_H_ #define __OSTREE_MOUNT_UTIL_H_ +#include #include #include #include @@ -72,6 +73,19 @@ read_proc_cmdline (void) return cmdline; } +static inline void +free_char(char **to_free) +{ + free(*to_free); +} + +static inline void +close_dir(DIR **dir) +{ + if (*dir) + closedir(*dir); +} + static inline char * read_proc_cmdline_ostree (void) { @@ -106,6 +120,69 @@ read_proc_cmdline_ostree (void) return ret; } +static inline char* +gen_ostree_target (const char* prepend) +{ + char dir_str[PATH_MAX]; + int dir_str_len = snprintf(dir_str, sizeof(dir_str), "%s", prepend); + int dir_str_cap = PATH_MAX - dir_str_len; + int prepend_len = dir_str_len; + dir_str_len += snprintf(dir_str + prepend_len, sizeof(dir_str), "%s", "/ostree"); + dir_str_cap = PATH_MAX - dir_str_len; + char* append_from = dir_str + dir_str_len; + int appended_len = 0; + DIR __attribute__ ((cleanup(close_dir))) *dir = opendir(dir_str); + if (!dir) + { + fprintf(stderr, "'%s' %d", strerror(errno), __LINE__); + return ""; + } + + struct dirent *ent = 0; + for (time_t latest = 0; (ent = readdir(dir)); ) + { + if (ent->d_type == DT_LNK) + { + struct stat lsb; + lsb.st_mtime = 0; + lstat(ent->d_name, &lsb); + if (latest <= lsb.st_mtime) + { + appended_len = snprintf(append_from, dir_str_cap, "/%s", ent->d_name); + latest = lsb.st_mtime; + } + } + } + + dir_str_len += appended_len; + dir_str_cap = PATH_MAX - dir_str_len; + + for (int i = 0; i < 3; ++i) + { + DIR __attribute__ ((cleanup(close_dir))) *dir1 = opendir(dir_str); + if (!dir1) + { + fprintf(stderr, "%s:%d\n", strerror(errno), __LINE__); + return ""; + } + + while ((ent = readdir(dir1))) + { + if (ent->d_name[0] != '.') + { + dir_str_len += snprintf(dir_str + dir_str_len, dir_str_cap, "/%s", ent->d_name); + dir_str_cap = PATH_MAX - dir_str_len; + break; + } + } + } + + /* We don't want the initial part included, we want to start at /ostree from + * the caller. + */ + return strdup(dir_str + prepend_len); +} + /* This is an API for other projects to determine whether or not the * currently running system is ostree-controlled. */ diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c index a5fbc8a810..bffc6269c9 100644 --- a/src/switchroot/ostree-prepare-root.c +++ b/src/switchroot/ostree-prepare-root.c @@ -124,11 +124,17 @@ resolve_deploy_path (const char * root_mountpoint) { char destpath[PATH_MAX]; struct stat stbuf; - char *ostree_target, *deploy_path; + char __attribute__ ((cleanup(free_char))) *ostree_target; + char *deploy_path; ostree_target = read_proc_cmdline_ostree (); if (!ostree_target) - errx (EXIT_FAILURE, "No OSTree target; expected ostree=/ostree/boot.N/..."); + { + ostree_target = gen_ostree_target (root_mountpoint); + } + + if (!ostree_target) + errx (EXIT_FAILURE, "Could not find OSTree target either via ostree=/ostree/boot.N/ or searching,..."); if (snprintf (destpath, sizeof(destpath), "%s/%s", root_mountpoint, ostree_target) < 0) err (EXIT_FAILURE, "failed to assemble ostree target path"); diff --git a/src/switchroot/ostree-system-generator.c b/src/switchroot/ostree-system-generator.c index bd0901bcff..f85db2e1fe 100644 --- a/src/switchroot/ostree-system-generator.c +++ b/src/switchroot/ostree-system-generator.c @@ -62,7 +62,10 @@ main(int argc, char *argv[]) * exit so that we don't error, but at the same time work where switchroot * is PID 1 (and so hasn't created /run/ostree-booted). */ - char *ostree_cmdline = read_proc_cmdline_ostree (); + char __attribute__ ((cleanup(free_char))) *ostree_cmdline = read_proc_cmdline_ostree (); + if (!ostree_cmdline) + ostree_cmdline = gen_ostree_target("/sysroot"); + if (!ostree_cmdline) exit (EXIT_SUCCESS);