2020-01-18 08:38:21 +00:00
/*
2021-11-23 11:27:33 +00:00
* Copyright ( c ) 2018 - 2021 , Andreas Kling < kling @ serenityos . org >
2020-01-18 08:38:21 +00:00
*
2021-04-22 08:24:48 +00:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-01-18 08:38:21 +00:00
*/
2020-02-06 14:04:03 +00:00
# include <LibCore/ArgsParser.h>
2021-11-23 11:27:33 +00:00
# include <LibCore/System.h>
# include <LibMain/Main.h>
2021-04-11 03:53:37 +00:00
# include <fcntl.h>
2019-08-03 03:25:51 +00:00
# include <stdio.h>
# include <sys/stat.h>
# include <unistd.h>
enum TruncateOperation {
OP_Set ,
OP_Grow ,
OP_Shrink ,
} ;
2021-11-23 11:27:33 +00:00
ErrorOr < int > serenity_main ( Main : : Arguments arguments )
2019-08-03 03:25:51 +00:00
{
2021-11-27 22:26:34 +00:00
TRY ( Core : : System : : pledge ( " stdio rpath wpath cpath " ) ) ;
2021-11-23 11:31:21 +00:00
2022-07-11 20:42:03 +00:00
StringView resize ;
StringView reference ;
StringView file ;
2020-01-27 17:25:36 +00:00
2020-02-02 11:34:39 +00:00
Core : : ArgsParser args_parser ;
2020-01-27 17:25:36 +00:00
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 " ) ;
args_parser . add_option ( reference , " Resize the target file to match the size of this one " , " reference " , ' r ' , " file " ) ;
args_parser . add_positional_argument ( file , " File path " , " file " ) ;
2021-11-23 11:27:33 +00:00
args_parser . parse ( arguments ) ;
2020-01-27 17:25:36 +00:00
2022-07-11 20:42:03 +00:00
if ( resize . is_empty ( ) & & reference . is_empty ( ) ) {
2021-11-23 11:27:33 +00:00
args_parser . print_usage ( stderr , arguments . argv [ 0 ] ) ;
2020-01-27 17:25:36 +00:00
return 1 ;
2019-08-03 03:25:51 +00:00
}
2022-07-11 20:42:03 +00:00
if ( ! resize . is_empty ( ) & & ! reference . is_empty ( ) ) {
2021-11-23 11:27:33 +00:00
args_parser . print_usage ( stderr , arguments . argv [ 0 ] ) ;
2020-01-27 17:25:36 +00:00
return 1 ;
2019-08-03 03:25:51 +00:00
}
auto op = OP_Set ;
2021-03-17 18:39:15 +00:00
off_t size = 0 ;
2019-08-03 03:25:51 +00:00
2022-07-11 20:42:03 +00:00
if ( ! resize . is_empty ( ) ) {
2022-12-04 18:02:33 +00:00
DeprecatedString str = resize ;
2019-08-03 03:25:51 +00:00
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 ;
}
2021-03-17 18:39:15 +00:00
auto size_opt = str . to_int < off_t > ( ) ;
2020-06-12 19:07:52 +00:00
if ( ! size_opt . has_value ( ) ) {
2021-11-23 11:27:33 +00:00
args_parser . print_usage ( stderr , arguments . argv [ 0 ] ) ;
2020-01-27 17:25:36 +00:00
return 1 ;
2019-08-03 03:25:51 +00:00
}
2020-06-12 19:07:52 +00:00
size = size_opt . value ( ) ;
2019-08-03 03:25:51 +00:00
}
2022-07-11 20:42:03 +00:00
if ( ! reference . is_empty ( ) ) {
2021-11-23 11:27:33 +00:00
auto stat = TRY ( Core : : System : : stat ( reference ) ) ;
size = stat . st_size ;
2019-08-03 03:25:51 +00:00
}
2021-11-23 11:27:33 +00:00
auto fd = TRY ( Core : : System : : open ( file , O_RDWR | O_CREAT , 0666 ) ) ;
auto stat = TRY ( Core : : System : : fstat ( fd ) ) ;
2019-08-03 03:25:51 +00:00
switch ( op ) {
case OP_Set :
break ;
case OP_Grow :
2021-11-23 11:27:33 +00:00
size = stat . st_size + size ;
2019-08-03 03:25:51 +00:00
break ;
case OP_Shrink :
2021-11-23 11:27:33 +00:00
size = stat . st_size - size ;
2019-08-03 03:25:51 +00:00
break ;
}
2021-11-23 11:27:33 +00:00
TRY ( Core : : System : : ftruncate ( fd , size ) ) ;
TRY ( Core : : System : : close ( fd ) ) ;
2019-08-03 03:25:51 +00:00
return 0 ;
}