Serenity Operating System
at hosted 131 lines 3.7 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <LibCore/ArgsParser.h> 28 29#include <stdio.h> 30#include <sys/stat.h> 31#include <unistd.h> 32 33enum TruncateOperation { 34 OP_Set, 35 OP_Grow, 36 OP_Shrink, 37}; 38 39int main(int argc, char** argv) 40{ 41 const char* resize = nullptr; 42 const char* reference = nullptr; 43 const char* file = nullptr; 44 45 Core::ArgsParser args_parser; 46 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"); 47 args_parser.add_option(reference, "Resize the target file to match the size of this one", "reference", 'r', "file"); 48 args_parser.add_positional_argument(file, "File path", "file"); 49 args_parser.parse(argc, argv); 50 51 if (!resize && !reference) { 52 args_parser.print_usage(stderr, argv[0]); 53 return 1; 54 } 55 56 if (resize && reference) { 57 args_parser.print_usage(stderr, argv[0]); 58 return 1; 59 } 60 61 auto op = OP_Set; 62 int size = 0; 63 64 if (resize) { 65 String str = resize; 66 67 switch (str[0]) { 68 case '+': 69 op = OP_Grow; 70 str = str.substring(1, str.length() - 1); 71 break; 72 case '-': 73 op = OP_Shrink; 74 str = str.substring(1, str.length() - 1); 75 break; 76 } 77 78 bool ok; 79 size = str.to_int(ok); 80 if (!ok) { 81 args_parser.print_usage(stderr, argv[0]); 82 return 1; 83 } 84 } 85 86 if (reference) { 87 struct stat st; 88 int rc = stat(reference, &st); 89 if (rc < 0) { 90 perror("stat"); 91 return 1; 92 } 93 94 size = st.st_size; 95 } 96 97 int fd = open(file, O_RDWR | O_CREAT, 0666); 98 if (fd < 0) { 99 perror("open"); 100 return 1; 101 } 102 103 struct stat st; 104 if (fstat(fd, &st) < 0) { 105 perror("fstat"); 106 return 1; 107 } 108 109 switch (op) { 110 case OP_Set: 111 break; 112 case OP_Grow: 113 size = st.st_size + size; 114 break; 115 case OP_Shrink: 116 size = st.st_size - size; 117 break; 118 } 119 120 if (ftruncate(fd, size) < 0) { 121 perror("ftruncate"); 122 return 1; 123 } 124 125 if (close(fd) < 0) { 126 perror("close"); 127 return 1; 128 } 129 130 return 0; 131}