【转】贴一段恶心的chmod简单实现代码,很重要!

jackxiang 2009-7-23 15:57 | |
前段时间实习,一直在搞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

作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/1856/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!

评论列表
发表评论

昵称

网址

电邮

打开HTML 打开UBB 打开表情 隐藏 记住我 [登入] [注册]