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
*/
2023-07-22 14:05:16 +00:00
# include <AK/CharacterTypes.h>
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>
2019-08-03 03:25:51 +00:00
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 ( ) ) {
2023-02-21 11:44:41 +00:00
args_parser . print_usage ( stderr , arguments . strings [ 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 ( ) ) {
2023-02-21 11:44:41 +00:00
args_parser . print_usage ( stderr , arguments . strings [ 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 ( ) ) {
2023-07-22 13:34:06 +00:00
switch ( resize [ 0 ] ) {
2019-08-03 03:25:51 +00:00
case ' + ' :
op = OP_Grow ;
2023-07-22 13:34:06 +00:00
resize = resize . substring_view ( 1 ) ;
2019-08-03 03:25:51 +00:00
break ;
case ' - ' :
op = OP_Shrink ;
2023-07-22 13:34:06 +00:00
resize = resize . substring_view ( 1 ) ;
2019-08-03 03:25:51 +00:00
break ;
}
2023-07-22 14:05:16 +00:00
auto suffix = resize [ resize . length ( ) - 1 ] ;
i64 multiplier = 1 ;
if ( ! AK : : is_ascii_digit ( suffix ) ) {
switch ( to_ascii_lowercase ( suffix ) ) {
case ' k ' :
multiplier = KiB ;
resize = resize . substring_view ( 0 , resize . length ( ) - 1 ) ;
break ;
case ' m ' :
multiplier = MiB ;
resize = resize . substring_view ( 0 , resize . length ( ) - 1 ) ;
break ;
case ' g ' :
multiplier = GiB ;
resize = resize . substring_view ( 0 , resize . length ( ) - 1 ) ;
break ;
default :
args_parser . print_usage ( stderr , arguments . strings [ 0 ] ) ;
return 1 ;
}
}
2023-07-22 13:34:06 +00:00
auto size_opt = resize . to_int < off_t > ( ) ;
2023-07-22 14:05:16 +00:00
if ( ! size_opt . has_value ( ) | | Checked < off_t > : : multiplication_would_overflow ( size_opt . value ( ) , multiplier ) ) {
2023-02-21 11:44:41 +00:00
args_parser . print_usage ( stderr , arguments . strings [ 0 ] ) ;
2020-01-27 17:25:36 +00:00
return 1 ;
2019-08-03 03:25:51 +00:00
}
2023-07-22 14:05:16 +00:00
size = size_opt . value ( ) * multiplier ;
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 :
2023-07-22 14:49:22 +00:00
size = max ( stat . st_size - size , 0 ) ;
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 ;
}