From 9111d3626a98522f4f0152e87b816ba476e6cd72 Mon Sep 17 00:00:00 2001 From: Conrad Pankoff Date: Sat, 3 Aug 2019 13:25:51 +1000 Subject: Userland: Implement truncate command This has a known bug in that you can't specify a negative size value. This bug stems from the argument parser, and once it's fixed there, everything should work here. --- Userland/truncate.cpp | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 Userland/truncate.cpp (limited to 'Userland') diff --git a/Userland/truncate.cpp b/Userland/truncate.cpp new file mode 100644 index 0000000000..f4d2d20912 --- /dev/null +++ b/Userland/truncate.cpp @@ -0,0 +1,106 @@ +#include + +#include +#include +#include + +enum TruncateOperation { + OP_Set, + OP_Grow, + OP_Shrink, +}; + +int main(int argc, char** argv) +{ + CArgsParser args_parser("truncate"); + + args_parser.add_arg("s", "size", "Resize the target file to (or by) this size. Prefix with + or - to expand or shrink the file, or a bare number to set the size exactly."); + args_parser.add_arg("r", "reference", "Resize the target file to match the size of this one."); + args_parser.add_required_single_value("file"); + + CArgsParserResult args = args_parser.parse(argc, argv); + + if (!args.is_present("s") && !args.is_present("r")) { + args_parser.print_usage(); + return -1; + } + + if (args.is_present("s") && args.is_present("r")) { + args_parser.print_usage(); + return -1; + } + + auto op = OP_Set; + int size = 0; + + if (args.is_present("s")) { + auto str = args.get("s"); + + switch (str[0]) { + case '+': + op = OP_Grow; + str = str.substring(1, str.length() - 1); + break; + case '-': + op = OP_Shrink; + str = str.substring(1, str.length() - 1); + break; + } + + bool ok; + size = str.to_int(ok); + if (!ok) { + args_parser.print_usage(); + return -1; + } + } + + if (args.is_present("r")) { + struct stat st; + int rc = stat(args.get("r").characters(), &st); + if (rc < 0) { + perror("stat"); + return -1; + } + + op = OP_Set; + size = st.st_size; + } + + auto name = args.get_single_values()[0]; + + int fd = open(name.characters(), O_CREAT, 0666); + if (fd < 0) { + perror("open"); + return -1; + } + + struct stat st; + if (fstat(fd, &st) < 0) { + perror("fstat"); + return -1; + } + + switch (op) { + case OP_Set: + break; + case OP_Grow: + size = st.st_size + size; + break; + case OP_Shrink: + size = st.st_size - size; + break; + } + + if (ftruncate(fd, size) < 0) { + perror("ftruncate"); + return -1; + } + + if (close(fd) < 0) { + perror("close"); + return -1; + } + + return 0; +} -- cgit v1.2.3