/*
* 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;
}
char* restore = NULL;
char* path = NULL;
int fd = -EBADF;
+ uint64_t id;
int r;
if (!(initsetuid()))
// 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) {
// 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) {
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