#include <sys/statfs.h>
#include <blkid/blkid.h>
-#include "sd-id128.h"
#include "libudev.h"
-#include "path-util.h"
-#include "util.h"
-#include "mkdir.h"
+#include "sd-id128.h"
+
+#include "blkid-util.h"
+#include "btrfs-util.h"
+#include "dirent-util.h"
+#include "efivars.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fstab-util.h"
+#include "generator.h"
+#include "gpt.h"
#include "missing.h"
-#include "udev-util.h"
+#include "mkdir.h"
+#include "mount-util.h"
+#include "parse-util.h"
+#include "path-util.h"
#include "special.h"
+#include "string-util.h"
+#include "udev-util.h"
#include "unit-name.h"
+#include "util.h"
#include "virt.h"
-#include "generator.h"
-#include "gpt.h"
-#include "fileio.h"
-#include "efivars.h"
-#include "blkid-util.h"
-#include "btrfs-util.h"
static const char *arg_dest = "/tmp";
static bool arg_enabled = true;
return 0;
}
-static int add_automount(
- const char *id,
- const char *what,
- const char *where,
- const char *fstype,
- bool rw,
- const char *options,
- const char *description,
- usec_t timeout) {
-
- _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL;
- _cleanup_free_ char *opt, *p = NULL;
- _cleanup_fclose_ FILE *f = NULL;
- int r;
-
- assert(id);
- assert(where);
- assert(description);
-
- if (options)
- opt = strjoin(options, ",noauto", NULL);
- else
- opt = strdup("noauto");
- if (!opt)
- return log_oom();
-
- r = add_mount(id,
- what,
- where,
- fstype,
- rw,
- opt,
- description,
- NULL);
- if (r < 0)
- return r;
-
- r = unit_name_from_path(where, ".automount", &unit);
- if (r < 0)
- return log_error_errno(r, "Failed to generate unit name: %m");
-
- p = strjoin(arg_dest, "/", unit, NULL);
- if (!p)
- return log_oom();
-
- f = fopen(p, "wxe");
- if (!f)
- return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
-
- fprintf(f,
- "# Automatically generated by systemd-gpt-auto-generator\n\n"
- "[Unit]\n"
- "Description=%s\n"
- "Documentation=man:systemd-gpt-auto-generator(8)\n"
- "[Automount]\n"
- "Where=%s\n"
- "TimeoutIdleSec=%lld\n",
- description,
- where,
- (unsigned long long)timeout / USEC_PER_SEC);
-
- r = fflush_and_check(f);
- if (r < 0)
- return log_error_errno(r, "Failed to write unit file %s: %m", p);
-
- lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".wants/", unit, NULL);
- if (!lnk)
- return log_oom();
- mkdir_parents_label(lnk, 0755);
-
- if (symlink(p, lnk) < 0)
- return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
-
- return 0;
-}
-
static bool path_is_busy(const char *where) {
int r;
return 0;
}
-static int add_boot(const char *what) {
#ifdef ENABLE_EFI
+static int add_automount(
+ const char *id,
+ const char *what,
+ const char *where,
+ const char *fstype,
+ bool rw,
+ const char *options,
+ const char *description,
+ usec_t timeout) {
+
+ _cleanup_free_ char *unit = NULL, *lnk = NULL;
+ _cleanup_free_ char *opt, *p = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ int r;
+
+ assert(id);
+ assert(where);
+ assert(description);
+
+ if (options)
+ opt = strjoin(options, ",noauto", NULL);
+ else
+ opt = strdup("noauto");
+ if (!opt)
+ return log_oom();
+
+ r = add_mount(id,
+ what,
+ where,
+ fstype,
+ rw,
+ opt,
+ description,
+ NULL);
+ if (r < 0)
+ return r;
+
+ r = unit_name_from_path(where, ".automount", &unit);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate unit name: %m");
+
+ p = strjoin(arg_dest, "/", unit, NULL);
+ if (!p)
+ return log_oom();
+
+ f = fopen(p, "wxe");
+ if (!f)
+ return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
+
+ fprintf(f,
+ "# Automatically generated by systemd-gpt-auto-generator\n\n"
+ "[Unit]\n"
+ "Description=%s\n"
+ "Documentation=man:systemd-gpt-auto-generator(8)\n"
+ "[Automount]\n"
+ "Where=%s\n"
+ "TimeoutIdleSec=%lld\n",
+ description,
+ where,
+ (unsigned long long)timeout / USEC_PER_SEC);
+
+ r = fflush_and_check(f);
+ if (r < 0)
+ return log_error_errno(r, "Failed to write unit file %s: %m", p);
+
+ lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".wants/", unit, NULL);
+ if (!lnk)
+ return log_oom();
+ mkdir_parents_label(lnk, 0755);
+
+ if (symlink(p, lnk) < 0)
+ return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
+
+ return 0;
+}
+
+static int add_boot(const char *what) {
_cleanup_blkid_free_probe_ blkid_probe b = NULL;
const char *fstype = NULL, *uuid = NULL;
sd_id128_t id, type_id;
return 0;
}
- if (detect_container(NULL) > 0) {
+ if (detect_container() > 0) {
log_debug("In a container, ignoring /boot.");
return 0;
}
+ /* We create an .automount which is not overridden by the .mount from the fstab generator. */
+ if (fstab_is_mount_point("/boot")) {
+ log_debug("/boot specified in fstab, ignoring.");
+ return 0;
+ }
+
if (path_is_busy("/boot")) {
log_debug("/boot already populated, ignoring.");
return 0;
what,
"/boot",
"vfat",
- "EFI System Partition Automount",
- false,
+ true,
"umask=0077",
+ "EFI System Partition Automount",
120 * USEC_PER_SEC);
return r;
+}
#else
+static int add_boot(const char *what) {
return 0;
-#endif
}
+#endif
static int enumerate_partitions(dev_t devnum) {
errno = 0;
r = blkid_do_safeprobe(b);
- if (r == -2 || r == 1) /* no result or uncertain */
+ if (r == 1)
+ return 0; /* no results */
+ else if (r == -2) {
+ log_warning("%s: probe gave ambiguous results, ignoring", node);
return 0;
- else if (r != 0)
+ } else if (r != 0)
return log_error_errno(errno ?: EIO, "%s: failed to probe: %m", node);
errno = 0;
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
_cleanup_udev_device_unref_ struct udev_device *q;
+ unsigned long long flags;
const char *stype, *subnode;
sd_id128_t type_id;
blkid_partition pp;
dev_t qn;
int nr;
- unsigned long long flags;
q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
if (!q)
if (!pp)
continue;
- flags = blkid_partition_get_flags(pp);
-
- /* Ignore partitions that are not marked for automatic
- * mounting on discovery */
- if (flags & GPT_FLAG_NO_AUTO)
- continue;
-
nr = blkid_partition_get_partno(pp);
if (nr < 0)
continue;
if (sd_id128_from_string(stype, &type_id) < 0)
continue;
+ flags = blkid_partition_get_flags(pp);
+
if (sd_id128_equal(type_id, GPT_SWAP)) {
+ if (flags & GPT_FLAG_NO_AUTO)
+ continue;
+
if (flags & GPT_FLAG_READ_ONLY) {
log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode);
continue;
if (boot && nr >= boot_nr)
continue;
+ /* Note that we do not honour the "no-auto"
+ * flag for the ESP, as it is often unset, to
+ * hide it from Windows. */
+
boot_nr = nr;
r = free_and_strdup(&boot, subnode);
} else if (sd_id128_equal(type_id, GPT_HOME)) {
+ if (flags & GPT_FLAG_NO_AUTO)
+ continue;
+
/* We only care for the first /home partition */
if (home && nr >= home_nr)
continue;
} else if (sd_id128_equal(type_id, GPT_SRV)) {
+ if (flags & GPT_FLAG_NO_AUTO)
+ continue;
+
/* We only care for the first /srv partition */
if (srv && nr >= srv_nr)
continue;
assert(path);
assert(dev);
+ /* Get's the block device directly backing a file system. If
+ * the block device is encrypted, returns the device mapper
+ * block device. */
+
if (lstat(path, &st))
return -errno;
return 0;
}
+static int get_block_device_harder(const char *path, dev_t *dev) {
+ _cleanup_closedir_ DIR *d = NULL;
+ _cleanup_free_ char *p = NULL, *t = NULL;
+ struct dirent *de, *found = NULL;
+ const char *q;
+ unsigned maj, min;
+ dev_t dt;
+ int r;
+
+ assert(path);
+ assert(dev);
+
+ /* Gets the backing block device for a file system, and
+ * handles LUKS encrypted file systems, looking for its
+ * immediate parent, if there is one. */
+
+ r = get_block_device(path, &dt);
+ if (r <= 0)
+ return r;
+
+ if (asprintf(&p, "/sys/dev/block/%u:%u/slaves", major(dt), minor(dt)) < 0)
+ return -ENOMEM;
+
+ d = opendir(p);
+ if (!d) {
+ if (errno == ENOENT)
+ goto fallback;
+
+ return -errno;
+ }
+
+ FOREACH_DIRENT_ALL(de, d, return -errno) {
+
+ if (STR_IN_SET(de->d_name, ".", ".."))
+ continue;
+
+ if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
+ continue;
+
+ if (found) /* Don't try to support multiple backing block devices */
+ goto fallback;
+
+ found = de;
+ }
+
+ if (!found)
+ goto fallback;
+
+ q = strjoina(p, "/", found->d_name, "/dev");
+
+ r = read_one_line_file(q, &t);
+ if (r == -ENOENT)
+ goto fallback;
+ if (r < 0)
+ return r;
+
+ if (sscanf(t, "%u:%u", &maj, &min) != 2)
+ return -EINVAL;
+
+ if (maj == 0)
+ goto fallback;
+
+ *dev = makedev(maj, min);
+ return 1;
+
+fallback:
+ *dev = dt;
+ return 1;
+}
+
static int parse_proc_cmdline_item(const char *key, const char *value) {
int r;
dev_t devno;
int r;
- r = get_block_device("/", &devno);
+ r = get_block_device_harder("/", &devno);
if (r < 0)
return log_error_errno(r, "Failed to determine block device of root file system: %m");
else if (r == 0) {
- r = get_block_device("/usr", &devno);
+ r = get_block_device_harder("/usr", &devno);
if (r < 0)
return log_error_errno(r, "Failed to determine block device of /usr file system: %m");
else if (r == 0) {
umask(0022);
- if (detect_container(NULL) > 0) {
+ if (detect_container() > 0) {
log_debug("In a container, exiting.");
return EXIT_SUCCESS;
}