]> git.ipfire.org Git - people/ms/ipfire-2.x.git/commitdiff
btrfsctl: Fix number parsing snapshots
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 10 Jul 2025 11:17:20 +0000 (11:17 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 10 Jul 2025 11:17:20 +0000 (11:17 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/misc-progs/btrfsctrl.c

index 3222b981c2cde4e972e5b7c152dcc11b4c955afe..7a68bb0b2e23345d3bb1e736a548f80df23d6063 100644 (file)
@@ -52,14 +52,26 @@ static int btrfsctrl_validate_name(const char* name) {
 /*
  * Validates if a given number of type char only contains digits.
  */
-static int btrfsctrl_validate_number(const char* number) {
-       if (!number)
+static int btrfsctrl_parse_number(uint64_t* result, const char* number) {
+       char* remainder = NULL;
+
+       // Check the input
+       if (!result || !number)
                return -EINVAL;
 
-       // Check if the given id is a valid number
-       if (strspn(number, NUMBERS) != strlen(number)) {
-               return 1;
-       }
+       // Parse the input
+       unsigned long n = strtoul(number, &remainder, 0);
+
+       // Failed to parse
+       if (n == ULONG_MAX)
+               return -errno;
+
+       // If there is a remainder, we could not successfully parse the number
+       if (remainder && *remainder)
+               return -EINVAL;
+
+       // Return the number
+       *result = n;
 
        return 0;
 }
@@ -333,6 +345,7 @@ int main(int argc, char *argv[]) {
        char* restore = NULL;
        char* path = NULL;
        int fd = -EBADF;
+       uint64_t id;
        int r;
 
        if (!(initsetuid()))
@@ -402,16 +415,13 @@ int main(int argc, char *argv[]) {
 
        // Delete a snapshot by it's given ID
        } else if (strcmp(argv[1], "snapshot-delete") == 0) {
-               // Check if the given id is a valid number.
-               r = btrfsctrl_validate_number(argv[2]);
+               // Parse the snapshot ID
+               r = btrfsctrl_parse_number(&id, argv[2]);
                if (r < 0) {
-                       fprintf(stderr, "Invalid snaphot ID: Not a numerical input.\n");
+                       fprintf(stderr, "Invalid snapshot ID: %s\n", strerror(-r));
                        goto ERROR;
                }
 
-               // Convert the given id string to unsigned long int.
-               uint64_t id = strtoul(argv[2], NULL, 0);
-
                // Open a file descriptor to the SNAPSHOTDIR.
                fd = open(SNAPSHOTDIR, O_DIRECTORY);
                if (fd < 0) {
@@ -428,16 +438,13 @@ int main(int argc, char *argv[]) {
 
        // Restore a snapshot with a given ID.
        } else if (strcmp(argv[1], "snapshot-restore") == 0) {
-               // Check if the given id is a valid number.
-               r = btrfsctrl_validate_number(argv[2]);
-               if(r < 0) {
-                       fprintf(stderr, "Invalid snapshot ID. Not a numerical input.\n");
+               // Parse the snapshot ID
+               r = btrfsctrl_parse_number(&id, argv[2]);
+               if (r < 0) {
+                       fprintf(stderr, "Invalid snapshot ID: %s\n", strerror(-r));
                        goto ERROR;
                }
 
-               // Convert the given id string to unsigned long int.
-               uint64_t id = strtoul(argv[2], NULL, 0);
-
                // Get the path of the given snapshot ID.
                r = btrfs_util_subvolume_get_path(ROOTDIR, id, &path);
                if (r != BTRFS_UTIL_OK) {
@@ -509,7 +516,7 @@ int main(int argc, char *argv[]) {
                r = btrfs_util_subvolume_set_read_only(newname, true);
                if (r != BTRFS_UTIL_OK) {
                        fprintf(stderr, "Could not change the rootfs backup to read-only: %s\n",
-                               btrfs_util_strerror(ret));
+                               btrfs_util_strerror(r));
                        goto ERROR;
                }
 #endif