Unix/Linux编程实践教程–chmod在Centos7.3的实现
2017-06-24 16:14
513 查看
环境:centos 7.3 x86_64
如果搜一下man就会发现,里面有两个chmod,一个是
所以要实现的chmod命令,无非就是把用户的输入解释成对应的mode_t类型,然后交给chmod系统调用进行处理即可。
目标,支持符号和八进制数两种表示法。符号表示法仅支持
程序流程大概是这样的:
解析mode
对于每个文件调用chmod进行设置或修改
代码大概是这样的,用了一些位操作去减少代码的长度:
效果:
测试脚本:
如果搜一下man就会发现,里面有两个chmod,一个是
chmod(1),一个是
chmod(2)。根据牛顿-莱布尼兹公式,立即推,第一个是用户命令,第二个是系统调用。系统调用里,函数的原型是这样的:
int chmod(const char *pathname, mode_t mode);
所以要实现的chmod命令,无非就是把用户的输入解释成对应的mode_t类型,然后交给chmod系统调用进行处理即可。
目标,支持符号和八进制数两种表示法。符号表示法仅支持
[ugoa...][+-=][rwxst...]。八进制表示法支持1-4位八制数,没有设置的位默认为0,同
man 1 chmod一致。
Usage: chmod mode file...
程序流程大概是这样的:
解析mode
对于每个文件调用chmod进行设置或修改
代码大概是这样的,用了一些位操作去减少代码的长度:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> void oops(const char* str); mode_t parse_mode(const char *mode); void xc_chmod(const char *path, mode_t mode); mode_t modify_mode(mode_t mode); #define USAGE "Usage: chmod mode file...\n" enum{ CW_ADD, CW_REMOVE, CW_SET, CW_COVER }chmod_way; enum{ MOD_READ = 0444, MOD_WRITE = 0222, MOD_EXEC = 0111, }; enum{ ER_ALL = 0777, ER_USR = 0700, ER_GRP = 070, ER_OTH = 07 }effect_range = 0; int mode_read = 0; int mode_write = 0; int mode_exec = 0; int mode_sgid = 0; int mode_sticky = 0; int main(int ac, char *av[]) { mode_t mode; if(ac < 3){ fprintf(stderr, USAGE); exit(1); } mode = parse_mode(*++av); ac -= 2; while(ac--) xc_chmod(*++av, mode); return 0; } void xc_chmod(const char *path, mode_t mode) { struct stat info; if(chmod_way != CW_COVER){ if(stat(path, &info) == -1) oops("chmod"); mode = info.st_mode; mode = modify_mode(mode); } if(chmod(path, mode) == -1) oops("chmod"); } mode_t modify_mode(mode_t mode) { mode_t amode = mode; int add_or_remove; if(chmod_way == CW_SET) { if(mode_read){ // printf("MODE_READ: %o & effect_range: %o = %o\n", MOD_READ, effect_range, MOD_READ& effect_range); amode |= MOD_READ & effect_range; } if(mode_write) amode |= MOD_WRITE & effect_range; if(mode_exec) amode |= MOD_EXEC & effect_range; if(mode_sgid){ if(effect_range & ER_USR) amode |= S_ISUID; if(effect_range & ER_GRP) amode |= S_ISGID; } if(mode_sticky && (effect_range & ER_OTH)) amode |= S_ISVTX; }else{ add_or_remove = chmod_way == CW_ADD; if(mode_read) if(add_or_remove) amode |= MOD_READ & effect_range; else amode &= ~(MOD_READ & effect_range); if(mode_write) if(add_or_remove) amode |= MOD_WRITE & effect_range; else amode &= ~(MOD_WRITE & effect_range); if(mode_exec) if(add_or_remove) amode |= MOD_EXEC & effect_range; else amode &= ~(MOD_EXEC & effect_range); if(mode_sgid){ if(effect_range & ER_USR) if(add_or_remove) amode |= S_ISUID; else amode &= ~S_ISUID; if(effect_range & ER_GRP) if(add_or_remove) amode |= S_ISGID; else amode &= ~S_ISGID; } if(mode_sticky && (effect_range & ER_OTH)) if(add_or_remove) amode |= S_ISVTX; else amode &= ~S_ISVTX; } return amode; } mode_t parse_mode(const char *mode) { char *p; mode_t amode; if(mode[0] >= '0' && mode[0] <= '9'){ /* parse use oct digits */ int len = 0; int base = 1; int tmp = 0; int i; int legal = 1; p = mode; while(*p){ if(!(*p >= '0' && *p <= '7')) legal = 0; p++; len++; } if(len > 4) legal = 0; if(!legal){ fprintf(stderr, USAGE); exit(1); } sscanf(mode, "%o", &tmp); amode = tmp; chmod_way = CW_COVER; }else{ /* parse use symbolic */ p = mode; while(*p != '+' && *p != '-' && *p != '='){ switch(*p){ case 'a': effect_range |= ER_ALL; break; case 'g': effect_range |= ER_GRP; break; case 'o': effect_range |= ER_OTH; break; case 'u': effect_range |= ER_USR; break; default: fprintf(stderr, USAGE); exit(1); break; } p++; } switch(*p){ case '+': chmod_way = CW_ADD; break; case '-': chmod_way = CW_REMOVE; break; case '=': chmod_way = CW_SET; break; default: fprintf(stderr, USAGE); exit(1); break; } p++; while(*p){ switch(*p){ case 'r': mode_read = 1; break; case 'w': mode_write = 1; break; case 'x': mode_exec = 1; break; case 's': mode_sgid = 1; break; case 't': mode_sticky = 1; break; default: fprintf(stderr, USAGE); exit(1); break; } ++p; } } return amode; } void oops(const char* str) { perror(str); exit(1); }
效果:
测试脚本:
gcc chmod.c ./a.out 7777 aaa ls -l aaa > bbb ./a.out 644 aaa ls -l aaa >> bbb ./a.out 0000 aaa ls -l aaa >> bbb ./a.out u=rwxst aaa ls -l aaa >> bbb ./a.out g=rwxst aaa ls -l aaa >> bbb ./a.out o=rwxst aaa ls -l aaa >> bbb ./a.out 0000 aaa ls -l aaa >> bbb ./a.out a=rwxst aaa ls -l aaa >> bbb ./a.out 0000 aaa ls -l aaa >> bbb ./a.out a=rw aaa ls -l aaa >> bbb ./a.out 0000 aaa ls -l aaa >> bbb ./a.out ug=rw aaa ls -l aaa >> bbb ./a.out o+rw aaa ls -l aaa >> bbb ./a.out u+x aaa ls -l aaa >> bbb ./a.out u+s aaa ls -l aaa >> bbb ./a.out u-x aaa ls -l aaa >> bbb ./a.out a-r aaa ls -l aaa >> bbb ./a.out a+t aaa ls -l aaa >> bbb chmod 7777 aaa ls -l aaa > ccc chmod 644 aaa ls -l aaa >> ccc chmod 0000 aaa ls -l aaa >> ccc chmod u=rwxst aaa ls -l aaa >> ccc chmod g=rwxst aaa ls -l aaa >> ccc chmod o=rwxst aaa ls -l aaa >> ccc chmod 0000 aaa ls -l aaa >> ccc chmod a=rwxst aaa ls -l aaa >> ccc chmod 0000 aaa ls -l aaa >> ccc chmod a=rw aaa ls -l aaa >> ccc chmod 0000 aaa ls -l aaa >> ccc chmod ug=rw aaa ls -l aaa >> ccc chmod o+rw aaa ls -l aaa >> ccc chmod u+x aaa ls -l aaa >> ccc chmod u+s aaa ls -l aaa >> ccc chmod u-x aaa ls -l aaa >> ccc chmod a-r aaa ls -l aaa >> ccc chmod a+t aaa ls -l aaa >> ccc diff bbb ccc
相关文章推荐
- Unix/Linux编程实践教程–ac在Ubuntu 14.04的实现
- Unix/Linux编程实践教程–cp在OS X的实现
- Unix/Linux编程实践教程--who在OS X的实现
- Unix/Linux编程实践教程–od在OS X的实现
- Unix/Linux编程实践教程–last在Ubuntu 14.04的实现
- Unix/Linux编程实践教程–head在OS X的实现
- Unix/Linux编程实践教程–cat在OS X的实现
- Unix/Linux编程实践教程–tail在OS X的实现
- CentOS 6.4 安装 Fcitx4.0(结合网上的教程自己实践做的总结)
- U盘安装centos6.5教程(两种实现方法)
- Unix/Linux编程实践教程参考答案-----第二章学习笔记
- unix/linux编程实践教程------学习笔记(三)
- unix/linux编程实践教程:who命令
- unix/linux编程实践教程:ls命令
- unix/linux编程实践教程------学习笔记(五)
- U盘安装centos6.5教程(两种实现方法)
- unix/linux编程实践教程------学习笔记
- unix/linux编程实践教程:学习stty
- unix/linux编程实践教程:pwd命令
- Linq实践教程(1):一行代码实现DataTable全文搜索(Full Text Search)