Signed-off-by: Stefan Schantl stefan.schantl@ipfire.org --- src/installer/hw.c | 80 ++++++++++++++++++++++++++++++++++++++++++++-- src/installer/hw.h | 20 ++++++++++++ 2 files changed, 98 insertions(+), 2 deletions(-)
diff --git a/src/installer/hw.c b/src/installer/hw.c index 11dbcd96d..8396d83cf 100644 --- a/src/installer/hw.c +++ b/src/installer/hw.c @@ -810,6 +810,7 @@ int hw_create_partitions(struct hw_destination* dest, const char* output) {
static int hw_format_filesystem(const char* path, int fs, const char* output) { char cmd[STRING_SIZE] = "\0"; + int r;
// Swap if (fs == HW_FS_SWAP) { @@ -829,7 +830,9 @@ static int hw_format_filesystem(const char* path, int fs, const char* output) {
// BTRFS } else if (fs == HW_FS_BTRFS) { - snprintf(cmd, sizeof(cmd), "/usr/bin/mkfs.btrfs -f %s", path); + r = hw_create_btrfs_layout(path, output); + + return r;
// FAT32 } else if (fs == HW_FS_FAT32) { @@ -838,7 +841,7 @@ static int hw_format_filesystem(const char* path, int fs, const char* output) {
assert(*cmd);
- int r = mysystem(output, cmd); + r = mysystem(output, cmd);
return r; } @@ -875,6 +878,59 @@ int hw_create_filesystems(struct hw_destination* dest, const char* output) { return 0; }
+int hw_create_btrfs_layout(const char* path, const char* output) { + const struct btrfs_subvolumes* subvolume = NULL; + char cmd[STRING_SIZE]; + char volume[STRING_SIZE]; + int r; + + r = snprintf(cmd, sizeof(cmd), "/usr/bin/mkfs.btrfs -f %s", path); + if (r < 0) { + return r; + } + + // Create the main BTRFS file system. + r = mysystem(output, cmd); + + if (r) { + return r; + } + + + // We need to mount the FS in order to create any subvolumes. + r = hw_mount(path, DESTINATION_MOUNT_PATH, "btrfs", 0); + + if (r) { + return r; + } + + // Loop through the list of subvolumes to create. + for ( subvolume = btrfs_subvolumes; subvolume->name; subvolume++ ) { + r = snprintf(volume, sizeof(volume), "%s", subvolume->name); + + // Abort if snprintf fails. + if (r < 0) { + return r; + } + + // Call function to create the subvolume + r = hw_create_btrfs_subvolume(output, volume); + + if (r) { + return r; + } + } + + // Umount the main BTRFS after subvolume creation. + r = hw_umount(DESTINATION_MOUNT_PATH, 0); + + if (r) { + return r; + } + + return 0; +} + int hw_mount_filesystems(struct hw_destination* dest, const char* prefix) { char target[STRING_SIZE];
@@ -1224,3 +1280,23 @@ int hw_restore_backup(const char* output, const char* backup_path, const char* d
return 0; } + +int hw_create_btrfs_subvolume(const char* output, const char* subvolume) { + char command [STRING_SIZE]; + int r; + + // Abort if the command could not be assigned. + r = snprintf(command, sizeof(command), "/usr/bin/btrfs subvolume create %s/%s", DESTINATION_MOUNT_PATH, subvolume); + if (r < 0) { + return r; + } + + // Create the subvolume + r = mysystem(output, command); + + if (r) { + return r; + } + + return 0; +} diff --git a/src/installer/hw.h b/src/installer/hw.h index e5ee65a6d..73a5233e2 100644 --- a/src/installer/hw.h +++ b/src/installer/hw.h @@ -104,6 +104,26 @@ struct hw_destination { unsigned long long size_root; };
+// Struct to define the BTRFS subvolumes layout +static const struct btrfs_subvolumes { + const char* name; + const char* mount_path; +} btrfs_subvolumes[] = { + { "@", "/" }, + { "@snapshots", "/.snapshots" }, + { "@home", "/home" }, + { "@root", "/root" }, + { "@cache", "/var/cache" }, + { "@backups", "/var/ipfire/backup" }, + { "@lib", "/var/lib" }, + { "@logs", "/var/log" }, + { "@mails", "/var/mail" }, + { "@tmp", "/var/tmp" }, + + // Sentinel + { NULL }, +}; + struct hw* hw_init(); void hw_free(struct hw* hw);