Unix/Linux编程实践教程–chmod在Centos7.3的实现
来源:互联网 发布:淘宝返现卡片 编辑:程序博客网 时间:2024/06/01 08:18
环境:centos 7.3 x86_64
如果搜一下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 aaals -l aaa > bbb./a.out 644 aaals -l aaa >> bbb./a.out 0000 aaals -l aaa >> bbb./a.out u=rwxst aaals -l aaa >> bbb./a.out g=rwxst aaals -l aaa >> bbb./a.out o=rwxst aaals -l aaa >> bbb./a.out 0000 aaals -l aaa >> bbb./a.out a=rwxst aaals -l aaa >> bbb./a.out 0000 aaals -l aaa >> bbb./a.out a=rw aaals -l aaa >> bbb./a.out 0000 aaals -l aaa >> bbb./a.out ug=rw aaals -l aaa >> bbb./a.out o+rw aaals -l aaa >> bbb./a.out u+x aaals -l aaa >> bbb./a.out u+s aaals -l aaa >> bbb./a.out u-x aaals -l aaa >> bbb./a.out a-r aaals -l aaa >> bbb./a.out a+t aaals -l aaa >> bbbchmod 7777 aaals -l aaa > cccchmod 644 aaals -l aaa >> cccchmod 0000 aaals -l aaa >> cccchmod u=rwxst aaals -l aaa >> cccchmod g=rwxst aaals -l aaa >> cccchmod o=rwxst aaals -l aaa >> cccchmod 0000 aaals -l aaa >> cccchmod a=rwxst aaals -l aaa >> cccchmod 0000 aaals -l aaa >> cccchmod a=rw aaals -l aaa >> cccchmod 0000 aaals -l aaa >> cccchmod ug=rw aaals -l aaa >> cccchmod o+rw aaals -l aaa >> cccchmod u+x aaals -l aaa >> cccchmod u+s aaals -l aaa >> cccchmod u-x aaals -l aaa >> cccchmod a-r aaals -l aaa >> cccchmod a+t aaals -l aaa >> cccdiff bbb ccc
阅读全文
0 0
- Unix/Linux编程实践教程–chmod在Centos7.3的实现
- Unix/Linux编程实践教程–cp在OS X的实现
- Unix/Linux编程实践教程–ac在Ubuntu 14.04的实现
- Unix/Linux编程实践教程–last在Ubuntu 14.04的实现
- Unix/Linux编程实践教程–cat在OS X的实现
- Unix/Linux编程实践教程–head在OS X的实现
- Unix/Linux编程实践教程–tail在OS X的实现
- Unix/Linux编程实践教程–od在OS X的实现
- Unix/Linux编程实践教程--who在OS X的实现
- Unix/Linux编程实践教程–书评
- Unix/Linux编程实践教程
- Unix/Linux编程实践教程
- Unix-linux编程实践教程
- unix/linux编程实践教程---sscanf函数的用法
- 《unix/linux编程实践教程》之管道
- unix/linux编程实践教程--more命令
- unix/linux编程实践教程:who命令
- unix/linux编程实践教程:ls命令
- 开发实现C++ RTMP直播推流sdk
- union
- 算法map简单用法
- 栈 介绍及简单实现
- 转换函数
- Unix/Linux编程实践教程–chmod在Centos7.3的实现
- JVM内存划分
- Eclipse防止定义变量名时后面追加类型后缀
- iOS 运用Runtime机制扩大UIButton的响应区域
- Android利用activity-alias动态更新图标icon,标题label
- 在Java中如何遍历Map对象
- android传输图片数据给java后台(HTML)原始封装
- IntelliJ IDEA Tomcat配置 详解
- 开发实现C++ RTMP直播拉流播放器