#include "hw.h"
-const char* other_filesystems[] = {
- "/dev",
- "/proc",
- "/sys",
- NULL
-};
-
static int system_chroot(const char* output, const char* path, const char* cmd) {
char chroot_cmd[STRING_SIZE];
}
}
- int r = mount(source, target, fs, flags, NULL);
+ return mount(source, target, fs, flags, NULL);
+}
- if (r) {
- fprintf(stderr, "Error mounting %s to %s (fs = %s, flags = %d): %s\n",
- source, target, fs, flags, strerror(r));
+static int hw_bind_mount(const char* source, const char* prefix) {
+ if (!source || !prefix) {
+ errno = EINVAL;
+ return 1;
}
- return r;
+ char target[PATH_MAX];
+ int r;
+
+ // Format target
+ r = snprintf(target, sizeof(target) - 1, "%s/%s", prefix, source);
+ if (r < 0)
+ return 1;
+
+ // Ensure target exists
+ mkdir(target, S_IRWXU|S_IRWXG|S_IRWXO);
+
+ return hw_mount(source, target, NULL, MS_BIND);
}
-int hw_umount(const char* target) {
- int r = umount2(target, 0);
+int hw_umount(const char* source, const char* prefix) {
+ char target[PATH_MAX];
+ int r;
- if (r && errno == EBUSY) {
- // Give it a moment to settle
- sleep(1);
+ if (prefix)
+ r = snprintf(target, sizeof(target) - 1, "%s/%s", prefix, source);
+ else
+ r = snprintf(target, sizeof(target) - 1, "%s", source);
+ if (r < 0)
+ return r;
- r = umount2(target, MNT_FORCE);
+ // Perform umount
+ r = umount2(target, 0);
+ if (r) {
+ switch (errno) {
+ // Try again with force if umount wasn't successful
+ case EBUSY:
+ sleep(1);
+
+ r = umount2(target, MNT_FORCE);
+ break;
+
+ // target wasn't a mountpoint. Ignore.
+ case EINVAL:
+ r = 0;
+ break;
+
+ // target doesn't exist
+ case ENOENT:
+ r = 0;
+ break;
+ }
}
return r;
static int hw_test_source_medium(const char* path) {
int ret = hw_mount(path, SOURCE_MOUNT_PATH, "iso9660", MS_RDONLY);
+ if (ret != 0) {
+ // 2nd try, ntfs for a rufus converted usb key
+ ret = hw_mount(path, SOURCE_MOUNT_PATH, "ntfs3", MS_RDONLY);
+ }
+ if (ret != 0) {
+ // 3rd try, vfat for a rufus converted usb key
+ ret = hw_mount(path, SOURCE_MOUNT_PATH, "vfat", MS_RDONLY);
+ }
+
// If the source could not be mounted we
// cannot proceed.
if (ret != 0)
ret = access(SOURCE_TEST_FILE, R_OK);
// Umount the test device.
- hw_umount(SOURCE_MOUNT_PATH);
+ hw_umount(SOURCE_MOUNT_PATH, NULL);
return ret;
}
struct hw_disk** ret = hw_create_disks();
struct hw_disk** disks = ret;
+ // Determine the disk device of source if it is a partition
+ char* sourcedisk = NULL;
+ char syssource[PATH_MAX];
+ (void)snprintf(syssource, sizeof(syssource) - 1, "/sys/class/block/%s", sourcedrive + 5);
+ struct udev_device* s_dev = udev_device_new_from_syspath(hw->udev, syssource);
+ const char* s_devtype = udev_device_get_property_value(s_dev, "DEVTYPE");
+ if (s_devtype && (strcmp(s_devtype, "partition") == 0)) {
+ struct udev_device* p_dev = udev_device_get_parent_with_subsystem_devtype(s_dev,"block","disk");
+ if (p_dev) {
+ sourcedisk = udev_device_get_devnode(p_dev);
+ }
+ }
+ if (!sourcedisk) sourcedisk = sourcedrive;
+
struct udev_enumerate* enumerate = udev_enumerate_new(hw->udev);
udev_enumerate_add_match_subsystem(enumerate, "block");
continue;
}
- // Skip sourcedrive if we need to
- if (sourcedrive && (strcmp(dev_path, sourcedrive) == 0)) {
+ // Skip sourcedisk if we need to
+ if (sourcedisk && (strcmp(dev_path, sourcedisk) == 0)) {
udev_device_unref(dev);
continue;
}
snprintf(dest->part_boot_efi, sizeof(dest->part_boot_efi),
"%s%d", path, part_idx++);
- } else
+ } else {
*dest->part_boot_efi = '\0';
+ dest->part_boot_efi_idx = 0;
+ }
if (dest->size_swap > 0)
snprintf(dest->part_swap, sizeof(dest->part_swap), "%s%d", path, part_idx++);
if (*dest->part_bootldr) {
asprintf(&cmd, "%s set %d bios_grub on", cmd, dest->part_boot_idx);
}
- asprintf(&cmd, "%s disk_set pmbr_boot on", cmd);
}
r = mysystem(output, cmd);
}
// bind-mount misc filesystems
- char** otherfs = other_filesystems;
- while (*otherfs) {
- snprintf(target, sizeof(target), "%s%s", prefix, *otherfs);
+ r = hw_bind_mount("/dev", prefix);
+ if (r)
+ return r;
- mkdir(target, S_IRWXU|S_IRWXG|S_IRWXO);
- r = hw_mount(*otherfs, target, NULL, MS_BIND);
- if (r) {
- hw_umount_filesystems(dest, prefix);
+ r = hw_bind_mount("/proc", prefix);
+ if (r)
+ return r;
- return r;
- }
+ r = hw_bind_mount("/sys", prefix);
+ if (r)
+ return r;
- otherfs++;
- }
+ r = hw_bind_mount("/sys/firmware/efi/efivars", prefix);
+ if (r && errno != ENOENT)
+ return r;
return 0;
}
// ESP
if (*dest->part_boot_efi) {
- snprintf(target, sizeof(target), "%s%s", prefix, HW_PATH_BOOT_EFI);
- r = hw_umount(target);
+ r = hw_umount(HW_PATH_BOOT_EFI, prefix);
if (r)
return -1;
}
// boot
if (*dest->part_boot) {
- snprintf(target, sizeof(target), "%s%s", prefix, HW_PATH_BOOT);
- r = hw_umount(target);
+ r = hw_umount(HW_PATH_BOOT, prefix);
if (r)
return -1;
}
}
// misc filesystems
- char** otherfs = other_filesystems;
- while (*otherfs) {
- snprintf(target, sizeof(target), "%s%s", prefix, *otherfs++);
- r = hw_umount(target);
- if (r)
- return -1;
- }
+ r = hw_umount("/sys/firmware/efi/efivars", prefix);
+ if (r)
+ return -1;
+
+ r = hw_umount("/sys", prefix);
+ if (r)
+ return -1;
+
+ r = hw_umount("/proc", prefix);
+ if (r)
+ return -1;
+
+ r = hw_umount("/dev", prefix);
+ if (r)
+ return -1;
// root
- r = hw_umount(prefix);
+ r = hw_umount(prefix, NULL);
if (r)
return -1;