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-05 20:09:20 +03:00
if ( chmod ( file , mode ) ! = 0 ) {
2023-11-06 18:32:22 +03:00
if ( ! s_flag )
fprintf ( stderr , " chmod: unable to chown %s: %s \n " , file , strerror ( errno ) ) ;
2023-11-01 12:25:51 +03:00
return 1 ;
}
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 ) ;
2023-11-06 18:32:22 +03:00
2023-11-01 12:25:51 +03:00
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 ) {
get_stat = mu_get_lstat ;
2023-11-06 23:00:26 +03:00
/* Arg hacking */
char * arg , * * argp ;
argp = argv ;
while ( ( arg = * + + argp ) ) {
if ( arg [ 0 ] ! = ' - ' ) {
arg = NULL ;
2023-10-24 13:59:42 +03:00
break ;
2023-11-06 23:00:26 +03:00
}
2023-10-24 13:59:42 +03:00
2023-11-06 23:00:26 +03:00
if ( arg [ 1 ] & & ( ! strchr ( " -x " , arg [ 1 ] ) | | ! strchr ( " -r " , arg [ 1 ] ) | | ! strchr ( " -w " , arg [ 1 ] ) ) ) {
arg [ 0 ] = ' a ' ;
break ;
}
}
2023-10-24 13:59:42 +03:00
2023-11-06 23:00:26 +03:00
int opt ;
while ( ( opt = getopt ( argc , argv , " RfH " ) ! = - 1 ) ) {
switch ( opt ) {
case ' R ' :
r_flag = 1 ;
break ;
2023-10-24 13:59:42 +03:00
2023-11-06 23:00:26 +03:00
case ' f ' :
s_flag = 1 ;
break ;
2023-11-01 12:25:51 +03:00
2023-11-06 23:00:26 +03:00
case ' H ' :
get_stat = mu_get_stat ;
break ;
2023-11-01 14:17:25 +03:00
2023-11-06 23:00:26 +03:00
default :
2023-11-06 23:52:48 +03:00
printf ( " chmod [ugoa]{+|-}[rwxXst] / [0 - 777] [file1 file2...] \n \t [-H if a command line argument is a symbolic link] \n \t [-R recursive] [-s silent] \n " ) ;
2023-11-06 23:00:26 +03:00
return 0 ;
}
2023-10-24 13:59:42 +03:00
}
2023-11-06 23:00:26 +03:00
if ( argv [ optind ] = = NULL ) {
2023-11-01 12:25:51 +03:00
fprintf ( stderr , " chmod: missing operand \n " ) ;
2023-11-06 23:00:26 +03:00
return 0 ;
2023-11-01 12:25:51 +03:00
}
2023-11-06 23:00:26 +03:00
/* Fix arg */
if ( arg )
arg [ 0 ] = ' - ' ;
char * mode_arg = argv [ optind ] ;
argv + = optind ;
argc - = optind ;
2023-11-01 12:25:51 +03:00
int ret = 0 ;
2023-11-06 23:00:26 +03:00
for ( int i = 1 ; 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
}