diff --git a/src/errorAndExit.c b/src/errorAndExit.c index a7d8f1d..b13f252 100644 --- a/src/errorAndExit.c +++ b/src/errorAndExit.c @@ -13,5 +13,6 @@ void errorAndExit() { fprintf(stderr, " -k, --keys: Optionally, the three decryption keys used to decrypt the file before inflation.\n"); fprintf(stderr, " -p, --previous: Optionally, the location of the previous version of this file, in case this disk only contains the xdelta3 differences and not an actual file.\n"); fprintf(stderr, " -t, --target: The path where the extracted file is saved to. If not specified, the file is outputted to stdout.\n"); + fprintf(stderr, " -l, --limit: The maximum disk write speed in bytes per second, defaults to 30 MB/s if not specified.\n"); exit(1); } diff --git a/src/parseArguments.c b/src/parseArguments.c index a6bf2d3..2d8fe15 100644 --- a/src/parseArguments.c +++ b/src/parseArguments.c @@ -6,6 +6,7 @@ #include "decrypt.h" #include "errorAndExit.h" #include "parseArguments.h" +#include "rateLimiter.h" //Uses GNU's getopt_long_only(), see https://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Options.html @@ -17,6 +18,7 @@ static struct option long_options[] = { {"keys", required_argument, 0, 'k'}, {"previous", required_argument, 0, 'p'}, {"target", required_argument, 0, 't'}, + {"limit", required_argument, 0, 'l'}, {NULL, 0, 0, 0}, }; @@ -82,6 +84,9 @@ struct arguments parseArguments(int argc, char *argv[]) { case 't': //target file path where extracted file is saved to state.target = optarg; break; + case 'l': //disk write limit + setDiskSpeed(atol(optarg)); + break; case '?': errorAndExit(); break; diff --git a/src/rateLimiter.c b/src/rateLimiter.c index 679a62c..bf0578e 100644 --- a/src/rateLimiter.c +++ b/src/rateLimiter.c @@ -8,20 +8,25 @@ #include "rateLimiter.h" #include "utils/min.h" -//How many bytes we can write to disk per second: 30 MB/s. Use 0 to specify no limit -#define DISK_SPEED 30UL * 1024UL * 1024UL +//How many bytes we can write to disk per second. Use 0 to specify no limit. Default is 30 MB/s. +unsigned long diskSpeed = 30UL * 1024UL * 1024UL; /** If we are not writing to disk, how many seconds the capacity can keep increasing before it reaches the limit. * Increasing this value can result in a spike of data once we are writing to disk again, but then allows the data * to quickly be written without having to wait for capacity to be available. */ #define MAX_IDLE_TIME 3UL //Capacity can be filled up to this maximum amount -#define CAPACITY_MAX DISK_SPEED * MAX_IDLE_TIME +#define CAPACITY_MAX diskSpeed * MAX_IDLE_TIME //The current amount of free capacity unsigned long capacity = 0UL; time_t prevTime = 0; +/** Set disk speed to the given speed in bytes per second. */ +void setDiskSpeed(unsigned long newSpeed) { + diskSpeed = newSpeed; +} + /** Increases the capacity based on time elapsed since the last time this function was called */ void increaseCapacity() { //Get seconds since the last time this function was called, or default to 1 if this is the first time this function is called @@ -34,7 +39,7 @@ void increaseCapacity() { timeElapsed = prevTime - prevTimeCache; } - capacity = min(CAPACITY_MAX, capacity + timeElapsed * DISK_SPEED); + capacity = min(CAPACITY_MAX, capacity + timeElapsed * diskSpeed); } /** Pauses execution until the given amount of capacity is available */ diff --git a/src/rateLimiter.h b/src/rateLimiter.h index 890691d..84c580b 100644 --- a/src/rateLimiter.h +++ b/src/rateLimiter.h @@ -1,4 +1,7 @@ #pragma once +/** Set disk speed to the given speed in bytes per second. */ +void setDiskSpeed(unsigned long newSpeed); + /** Pauses execution until the given amount of capacity is available */ void consumeCapacity(unsigned long numBytes);