2023-10-24 13:59:42 +03:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
2023-11-01 12:25:51 +03:00
# include <dirent.h>
2023-10-24 13:59:42 +03:00
# include <sys/stat.h>
2023-11-01 12:25:51 +03:00
# include "make_path.h"
# include "get_stat.h"
2023-11-01 14:17:25 +03:00
# include "parse_mode.h"
2023-10-24 13:59:42 +03:00
2023-11-01 12:25:51 +03:00
int ( * get_stat ) ( const char * prog_name , const char * path , struct stat * stat_path ) ;
unsigned int r_flag ;
unsigned int s_flag ;
2023-10-24 13:59:42 +03:00
2023-11-02 12:51:20 +03:00
int change ( const char * file , const char * mode_arg ) {
2023-11-01 12:25:51 +03:00
struct stat old_file ;
if ( get_stat ( " chmod " , file , & old_file ) )
return 1 ;
2023-11-02 12:51:20 +03:00
mode_t mode = mu_parse_mode ( mode_arg , old_file . st_mode ) ;
2023-11-01 12:25:51 +03:00
if ( chmod ( file , mode ) = = 0 ) {
struct stat new_file ;
if ( get_stat ( " chmod " , file , & new_file ) )
return 1 ;
if ( old_file . st_mode ! = new_file . st_mode )
return 0 ;
if ( ! s_flag )
fprintf ( stderr , " chmod: %s unchanged \n " , file ) ;
return 1 ;
}
else
fprintf ( stderr , " chmod: unable to chown %s: %s \n " , file , strerror ( errno ) ) ;
return 0 ;
}
2023-11-02 12:51:20 +03:00
int chtree ( const char * dst , const char * mode_arg ) {
int ret = change ( dst , mode_arg ) ;
2023-11-01 12:25:51 +03:00
struct stat stat_path ;
if ( get_stat ( " chmod " , dst , & stat_path ) )
return 1 ;
if ( ! S_ISDIR ( stat_path . st_mode ) | | ! r_flag )
return ret ;
DIR * dir = opendir ( dst ) ;
if ( dir = = NULL ) {
if ( ! s_flag )
fprintf ( stderr , " chown: %s: Can`t open directory \n " , dst ) ;
return 1 ;
}
struct dirent * ep ;
while ( ( ep = readdir ( dir ) ) ! = NULL ) {
if ( ! strcmp ( ep - > d_name , " . " ) | | ! strcmp ( ep - > d_name , " .. " ) )
continue ;
char * full_path = mu_make_path ( " chmod " , dst , ep - > d_name ) ;
if ( full_path = = NULL )
continue ;
2023-11-02 12:51:20 +03:00
if ( chtree ( full_path , mode_arg ) )
2023-11-01 12:25:51 +03:00
ret = 1 ;
free ( full_path ) ;
}
closedir ( dir ) ;
return ret ;
}
int main ( int argc , char * * argv ) {
2023-10-24 13:59:42 +03:00
int i ;
2023-11-01 12:25:51 +03:00
get_stat = mu_get_lstat ;
2023-10-24 13:59:42 +03:00
for ( i = 1 ; i < argc ; i + + ) {
if ( argv [ i ] [ 0 ] ! = ' - ' )
break ;
else if ( ! strcmp ( argv [ i ] , " -r " ) )
r_flag = 1 ;
2023-11-01 12:25:51 +03:00
else if ( ! strcmp ( argv [ i ] , " -s " ) | | ! strcmp ( argv [ i ] , " -f " ) )
2023-10-24 13:59:42 +03:00
s_flag = 1 ;
2023-11-01 12:25:51 +03:00
else if ( ! strcmp ( argv [ i ] , " -H " ) )
get_stat = mu_get_stat ;
2023-10-24 13:59:42 +03:00
else if ( ! strcmp ( argv [ i ] , " --help " ) ) {
2023-11-01 14:17:25 +03:00
printf ( " chmod [-H if a command line argument is a symbolic link] [-r recursive] [-s silent] [ugoa]{+|-|=}[rwxXst] / [sstrwxrwxrwx] [file1 file2...] \n " ) ;
2023-10-24 13:59:42 +03:00
return 0 ;
}
2023-11-01 14:17:25 +03:00
if ( argc - i < = 2 )
break ;
2023-10-24 13:59:42 +03:00
}
2023-11-01 15:33:16 +03:00
if ( argc - i < 2 ) {
2023-11-01 12:25:51 +03:00
fprintf ( stderr , " chmod: missing operand \n " ) ;
return 1 ;
}
2023-11-02 12:51:20 +03:00
char * mode_arg = argv [ i ] ;
2023-11-01 12:25:51 +03:00
argv + + ;
argc - - ;
int ret = 0 ;
for ( ; i < argc ; i + + )
2023-11-02 12:51:20 +03:00
if ( chtree ( argv [ i ] , mode_arg ) )
2023-11-01 12:25:51 +03:00
ret = 1 ;
return ret ;
2023-10-24 13:59:42 +03:00
}