Serenity Operating System
at master 93 lines 2.4 kB view raw
1/* 2 * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <LibCore/ArgsParser.h> 8#include <LibCore/System.h> 9#include <LibMain/Main.h> 10#include <fcntl.h> 11#include <stdio.h> 12#include <sys/stat.h> 13#include <unistd.h> 14 15enum TruncateOperation { 16 OP_Set, 17 OP_Grow, 18 OP_Shrink, 19}; 20 21ErrorOr<int> serenity_main(Main::Arguments arguments) 22{ 23 TRY(Core::System::pledge("stdio rpath wpath cpath")); 24 25 StringView resize; 26 StringView reference; 27 StringView file; 28 29 Core::ArgsParser args_parser; 30 args_parser.add_option(resize, "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", "size", 's', "size"); 31 args_parser.add_option(reference, "Resize the target file to match the size of this one", "reference", 'r', "file"); 32 args_parser.add_positional_argument(file, "File path", "file"); 33 args_parser.parse(arguments); 34 35 if (resize.is_empty() && reference.is_empty()) { 36 args_parser.print_usage(stderr, arguments.strings[0]); 37 return 1; 38 } 39 40 if (!resize.is_empty() && !reference.is_empty()) { 41 args_parser.print_usage(stderr, arguments.strings[0]); 42 return 1; 43 } 44 45 auto op = OP_Set; 46 off_t size = 0; 47 48 if (!resize.is_empty()) { 49 DeprecatedString str = resize; 50 51 switch (str[0]) { 52 case '+': 53 op = OP_Grow; 54 str = str.substring(1, str.length() - 1); 55 break; 56 case '-': 57 op = OP_Shrink; 58 str = str.substring(1, str.length() - 1); 59 break; 60 } 61 62 auto size_opt = str.to_int<off_t>(); 63 if (!size_opt.has_value()) { 64 args_parser.print_usage(stderr, arguments.strings[0]); 65 return 1; 66 } 67 size = size_opt.value(); 68 } 69 70 if (!reference.is_empty()) { 71 auto stat = TRY(Core::System::stat(reference)); 72 size = stat.st_size; 73 } 74 75 auto fd = TRY(Core::System::open(file, O_RDWR | O_CREAT, 0666)); 76 auto stat = TRY(Core::System::fstat(fd)); 77 78 switch (op) { 79 case OP_Set: 80 break; 81 case OP_Grow: 82 size = stat.st_size + size; 83 break; 84 case OP_Shrink: 85 size = stat.st_size - size; 86 break; 87 } 88 89 TRY(Core::System::ftruncate(fd, size)); 90 TRY(Core::System::close(fd)); 91 92 return 0; 93}