]> git.ipfire.org Git - people/stevee/ipfire-2.x.git/commitdiff
installer: Add code to create a BTRFS subvolume layout
authorStefan Schantl <stefan.schantl@ipfire.org>
Wed, 20 Mar 2024 03:55:04 +0000 (04:55 +0100)
committerStefan Schantl <stefan.schantl@ipfire.org>
Sat, 23 Mar 2024 10:46:36 +0000 (11:46 +0100)
Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
src/installer/hw.c
src/installer/hw.h

index 11dbcd96d73d96062d3eb1dafcce7303d7985ab7..8396d83cf62befc37d04a454dc64f6117d66641e 100644 (file)
@@ -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;
+}
index e5ee65a6d2a7f706aa3d982c2dea6f26daec673b..73a5233e20ccba402e9c0bd33bfb09e78043cd38 100644 (file)
@@ -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);