前段时间实习,一直在搞Python,都把Linux和C丢一边了,这段时间准备重新复习一下Linux下的C编程,加深理解。
今天写了一段忑恶心的代码,Linux下的chmod的简单实现,主要是支持两种方式:
1. 输入一个八进制数直接修改文件的权限;
2. 通过"u+w, g-wr"等方式来修改,不使用getopt函数解析参数,直接自己手动解析;
主要是string_chmod函数写得让自己都感到恶心,中午也没想到比较好的解决方法,功能是实现了,但是代码重复太多了,还有就是因为前段时间工作看惯了Python代码,现在看这样的代码确实太恶了。
代码和执行结果如下:
/*
* filename: my_chmod.c
* Email: lin.jian1986@gmail.com
* Date: 2008/10/24
*/
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <assert.h>
#include "../my_error.h"
#define MODE O777
#define CHMOD(file, MODE); { \
if ( chmod(file, statbuf.st_mode) < 0 ) \
my_error( "chmod" ); \
break; \
}
/* return 'n' when arg is number, or 's' if arg is string*/
int number_or_string( const char *arg )
{
assert( arg != NULL );
if ( arg[0] >= '0' && arg[0] <= '9' )
return 'n';
return 's';
}
/* the implement of number argument */
void number_chmod( const char *arg, const char *file )
{
int mode;
mode = atoi( arg );
if ( mode > 777 || mode < 0 ) {
fprintf( stderr, "usage: mode" );
exit ( 1 );
}
/* To change a decimal system to a octal system */
sscanf( arg, "%o", &mode );
if ( chmod(file, mode) == -1 )
exit ( 2 );
}
/* the implement of string argument */
void string_chmod( const char *arg, const char *file )
{
int i, j;
int mode;
struct stat statbuf;
if ( stat(file, &statbuf) < 0 )
my_error( "stat" );
for ( i = 0; i < strlen(arg); i += j + 1 ) {
/* if change the user mode */
if ( arg[i] == 'u' ) {
for ( j = 2; arg[i + j] != ' ' && arg[i + j] != '\t'; ++j ) {
switch ( arg[i + j] ) {
case 'r':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IRUSR;
else
statbuf.st_mode &= ~S_IRUSR;
CHMOD(file, MODE);
case 'w':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IWUSR;
else
statbuf.st_mode &= ~S_IWUSR;
CHMOD(file, MODE);
case 'x':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IXUSR;
else
statbuf.st_mode &= ~S_IXUSR;
CHMOD(file, MODE);
default:
exit ( 1 );
}
}
}
/* if change the group mode */
else if ( arg[i] == 'g' ) {
for ( j = 2; arg[i + j] != ' ' && arg[i + j] != '\t'; ++j ) {
switch ( arg[i + j] ) {
case 'r':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IRGRP;
else
statbuf.st_mode &= ~S_IRGRP;
CHMOD(file, MODE);
case 'w':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IWGRP;
else
statbuf.st_mode &= ~S_IWGRP;
CHMOD(file, MODE);
case 'x':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IXGRP;
else
statbuf.st_mode &= ~S_IXGRP;
CHMOD(file, MODE);
default:
exit ( 1 );
}
}
}
/* if change the other user mode */
else if ( arg[i] == 'o' ) {
for ( j = 2; arg[i + j] != ' ' && arg[i + j] != '\t'; ++j ) {
switch ( arg[i + j] ) {
case 'r':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IROTH;
else
statbuf.st_mode &= ~S_IROTH;
CHMOD(file, MODE);
case 'w':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IWOTH;
else
statbuf.st_mode &= ~S_IWOTH;
CHMOD(file, MODE);
case 'x':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IXOTH;
else
statbuf.st_mode &= ~S_IXOTH;
CHMOD(file, MODE);
default:
exit ( 1 );
}
}
}
}
}
int main( int argc, char *argv[] )
{
int mode;
char buf[20];
if ( argc < 3 ) {
fprintf( stderr, "usage: argc < 3" );
exit (1);
}
if ( number_or_string(argv[1]) == 'n' )
number_chmod( argv[1], argv[argc - 1] );
else {
strcpy( buf, argv[1] );
for ( int i = 2; i < argc - 1; i++ ) {
strcat( buf, " ");
strcat( buf, argv[i] );
}
string_chmod( buf, argv[argc - 1] );
}
return 0;
}
ken@ken-laptop:~/linux_c/chap6$ ls -l test.c
-rwxrwxrwx 1 ken ken 0 2008-10-23 19:14 test.c
ken@ken-laptop:~/linux_c/chap6$ ./my_chmod 745 test.c
ken@ken-laptop:~/linux_c/chap6$ ls -l test.c
-rwxr--r-x 1 ken ken 0 2008-10-23 19:14 test.c
ken@ken-laptop:~/linux_c/chap6$ ./my_chmod u-rw g+w o-rx test.c
ken@ken-laptop:~/linux_c/chap6$ ls -l test.c
---xrw---- 1 ken ken 0 2008-10-23 19:14 test.c
今天写了一段忑恶心的代码,Linux下的chmod的简单实现,主要是支持两种方式:
1. 输入一个八进制数直接修改文件的权限;
2. 通过"u+w, g-wr"等方式来修改,不使用getopt函数解析参数,直接自己手动解析;
主要是string_chmod函数写得让自己都感到恶心,中午也没想到比较好的解决方法,功能是实现了,但是代码重复太多了,还有就是因为前段时间工作看惯了Python代码,现在看这样的代码确实太恶了。
代码和执行结果如下:
/*
* filename: my_chmod.c
* Email: lin.jian1986@gmail.com
* Date: 2008/10/24
*/
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <assert.h>
#include "../my_error.h"
#define MODE O777
#define CHMOD(file, MODE); { \
if ( chmod(file, statbuf.st_mode) < 0 ) \
my_error( "chmod" ); \
break; \
}
/* return 'n' when arg is number, or 's' if arg is string*/
int number_or_string( const char *arg )
{
assert( arg != NULL );
if ( arg[0] >= '0' && arg[0] <= '9' )
return 'n';
return 's';
}
/* the implement of number argument */
void number_chmod( const char *arg, const char *file )
{
int mode;
mode = atoi( arg );
if ( mode > 777 || mode < 0 ) {
fprintf( stderr, "usage: mode" );
exit ( 1 );
}
/* To change a decimal system to a octal system */
sscanf( arg, "%o", &mode );
if ( chmod(file, mode) == -1 )
exit ( 2 );
}
/* the implement of string argument */
void string_chmod( const char *arg, const char *file )
{
int i, j;
int mode;
struct stat statbuf;
if ( stat(file, &statbuf) < 0 )
my_error( "stat" );
for ( i = 0; i < strlen(arg); i += j + 1 ) {
/* if change the user mode */
if ( arg[i] == 'u' ) {
for ( j = 2; arg[i + j] != ' ' && arg[i + j] != '\t'; ++j ) {
switch ( arg[i + j] ) {
case 'r':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IRUSR;
else
statbuf.st_mode &= ~S_IRUSR;
CHMOD(file, MODE);
case 'w':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IWUSR;
else
statbuf.st_mode &= ~S_IWUSR;
CHMOD(file, MODE);
case 'x':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IXUSR;
else
statbuf.st_mode &= ~S_IXUSR;
CHMOD(file, MODE);
default:
exit ( 1 );
}
}
}
/* if change the group mode */
else if ( arg[i] == 'g' ) {
for ( j = 2; arg[i + j] != ' ' && arg[i + j] != '\t'; ++j ) {
switch ( arg[i + j] ) {
case 'r':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IRGRP;
else
statbuf.st_mode &= ~S_IRGRP;
CHMOD(file, MODE);
case 'w':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IWGRP;
else
statbuf.st_mode &= ~S_IWGRP;
CHMOD(file, MODE);
case 'x':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IXGRP;
else
statbuf.st_mode &= ~S_IXGRP;
CHMOD(file, MODE);
default:
exit ( 1 );
}
}
}
/* if change the other user mode */
else if ( arg[i] == 'o' ) {
for ( j = 2; arg[i + j] != ' ' && arg[i + j] != '\t'; ++j ) {
switch ( arg[i + j] ) {
case 'r':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IROTH;
else
statbuf.st_mode &= ~S_IROTH;
CHMOD(file, MODE);
case 'w':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IWOTH;
else
statbuf.st_mode &= ~S_IWOTH;
CHMOD(file, MODE);
case 'x':
if ( arg[i + 1] == '+' )
statbuf.st_mode |= S_IXOTH;
else
statbuf.st_mode &= ~S_IXOTH;
CHMOD(file, MODE);
default:
exit ( 1 );
}
}
}
}
}
int main( int argc, char *argv[] )
{
int mode;
char buf[20];
if ( argc < 3 ) {
fprintf( stderr, "usage: argc < 3" );
exit (1);
}
if ( number_or_string(argv[1]) == 'n' )
number_chmod( argv[1], argv[argc - 1] );
else {
strcpy( buf, argv[1] );
for ( int i = 2; i < argc - 1; i++ ) {
strcat( buf, " ");
strcat( buf, argv[i] );
}
string_chmod( buf, argv[argc - 1] );
}
return 0;
}
ken@ken-laptop:~/linux_c/chap6$ ls -l test.c
-rwxrwxrwx 1 ken ken 0 2008-10-23 19:14 test.c
ken@ken-laptop:~/linux_c/chap6$ ./my_chmod 745 test.c
ken@ken-laptop:~/linux_c/chap6$ ls -l test.c
-rwxr--r-x 1 ken ken 0 2008-10-23 19:14 test.c
ken@ken-laptop:~/linux_c/chap6$ ./my_chmod u-rw g+w o-rx test.c
ken@ken-laptop:~/linux_c/chap6$ ls -l test.c
---xrw---- 1 ken ken 0 2008-10-23 19:14 test.c
作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/1856/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!
评论列表