truncate.cpp 2.3 KB

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