浅墨浓香

想要天亮进城,就得天黑赶路。

导航

第4章 文件和目录(2)_文件权限及操作函数

Posted on 2017-01-25 17:35  浅墨浓香  阅读(796)  评论(0编辑  收藏  举报

2. 文件权限及操作函数

(1)9种文件访问权限位

权限

权限常量(宏)

用户权限

S_IRUSR、S_IWUSR和S_IXUSR

组权限

S_IRGRP、S_IWGRP和S_IXGRP

其它权限

S_IROTH、S_IWOTH和S_IXOTH

备注

文件权限通过按位或的方式构造。如:

int fd=open("test.txt", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH),相当于0644权限

【编程实验】显示文件权限

//file_perm.c

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <memory.h>

/*查看给定文件的权限*/

//显示权限信息
void showPerm(mode_t mode)
{

    //User permission
    if(S_IRUSR & mode){
        printf("r");
    }else{
        printf("-");
    }
    if(S_IWUSR & mode){
        printf("w");
    }else{
        printf("-");
    }
    if(S_IXUSR & mode){
        printf("x");
    }else{
        printf("-");
    }

    //Group permission
    if(S_IRGRP & mode){
        printf("r");
    }else{
        printf("-");
    }
    if(S_IRGRP & mode){
        printf("w");
    }else{
        printf("-");
    }
    if(S_IXGRP & mode){
        printf("x");
    }else{
        printf("-");
    }

    //Other permission
    if(S_IROTH & mode){
        printf("r");
    }else{
        printf("-");
    }
    if(S_IROTH & mode){
        printf("w");
    }else{
        printf("-");
    }
    if(S_IXOTH & mode){
        printf("x");
    }else{
        printf("-");
    }
}

int main(int argc, char* argv[])
{
    if (argc < 2) {
        fprintf(stderr, "usage: %s files\n", argv[0]);
        exit(1);
    }

    struct stat buff;
    int i=0;
    for(i=1; i<argc; i++){
        memset(&buff, 0, sizeof(buff));
        if(lstat(argv[i], &buff) < 0 )
        {
            perror("lstat error");
            continue;
        }
       
        //获得文件的权限信息
        mode_t mode = buff.st_mode;
        printf("%-20s", argv[i]);
        
        //显示权限信息
        showPerm(mode);

        printf("\n");
    } 
    
    return 0;
}

(2)accept函数

头文件

#include<unistd.h>

函数

int access(const char* pathname, int mode);

返回值

若成功则为0,若出错则为-1

功能

查看调用进程(所有者或所属组)是否可以对指定的文件执行某种操作

参数

(1)pathname:文件路径

(2)mode:文件的访问权限

  ①R_OK:判断文件是否有读权限

  ②W_OK:判断文件是否有写权限

  ③X_OK:判断文件是否有可执行权限

  ④F_OK:判断文件是否存在

备注

(1)Linux内核总是根据进程的有效用户ID和有效组ID来决定一个进程是否有权访问某个文件。但有时希望按实际用户ID和实际组ID 来测试其访问能力

(2)access检查用户对一个文件的权限情况,根据mode的值检查调用进程对文件pathname是否具有读、写、或执行的权限。若进程实际用户具有mode所指出的权限,access返回0.否则返回-1

(3)Linux系统中某个可执行文件所有者为root并且有SetUID当一个普通用户mike运行这个程序时,则产生的进程的有效用户为root实际用户为mike

【编程实验】判断当前进程对指定文件是否具有某种权限

//file_access.c

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

/*判断进程对某个文件是否具有指定的权限*/

int main(int argc, char* argv[])
{
    if (argc < 2){
        fprintf(stderr, "usage: %s files\n", argv[0]);
        exit(1);
    }

    int i=0;
    for(i=1; i<argc; i++){
        //判断指定文件是否存在
        if(access(argv[i], F_OK)){
            printf("%s is not exist\n", argv[i]);
            continue;
        }
        
        //判断当前进程(所有者或所属组)对指定文件是否具有读权限
        if(access(argv[i], R_OK)){
            printf("%d can not read %s\n", getpid(), argv[i]);
        }else{
            printf("%d can read %s\n", getpid(), argv[i]);
        }

        //判断当前进程(所有者或所属组)对指定文件是否具有写权限
        if(access(argv[i], W_OK)){
            printf("%d can not write %s\n", getpid(), argv[i]);
        }else{
            printf("%d can write %s\n", getpid(), argv[i]);
        }
        
        //判断当前进程(所有者或用户组)对指定文件是否具有执行权限
        if(access(argv[i], X_OK)){
            printf("%d can not execute %s\n", getpid(), argv[i]);
        }else{
            printf("%d can execute %s\n", getpid(), argv[i]);
        }

        printf("\n");
    }

    return 0;
}

(3)umask函数

头文件

#include<sys/types.h>

#include<sys/stat.h>

函数

mode_t umask(mode_t mode);

返回值

返回以前的设置的掩码。这个函数不会出错。

功能

指定在建立文件或目录时预设的权限掩码,并返回以前的值。

补充说明:umask可用来设定权限掩码。将要设定的文件权限减去权限掩码,即为新建文件的实际权限

参数

mode:文件权限常量(如:S_IRGRP、S_IWGRP等)

备注

(1)umask设置的权限掩码不能影响己创建的文件权限

(2)umask只影响当前进程新建文件的默认权限并不影响其父进程(常常是shell)的掩码

(4)chmod和fchmod函数

头文件

#include<sys/stat.h>

函数

int chmod(const char* pathname, mode_t mode);

int fchmod(int fd, mode_t mode);

返回值

成功返回0,出错返回-1

功能

更改现存文件的权限chmod函数在指定的文件上进行操作。而fchmod函数则对己打开的文件进行操作。

参数

(1)pathname:文件路径名字

(2)mode:文件权限(按位或操作)

  ①S_ISUID、S_ISGID和S_ISVTX  //SetUID、SetGID和SetBID

  ②S_IRWXU、S_IRUSR、S_IWUSR和S_IXUSR

  ③S_IRWXG、S_IRGRP、S_IWGRP和S_IXGRP

  ④S_IRWXO、S_IROTH、S_IWOTH和S_IXOTH

备注

更改一个文件的权限位,需要满足的条件

  ①进程的有效用户ID必须等于文件的所有者ID可用id命令查看当前用户ID及其组ID等信息

  ②或者进程具有超级用户权限

【编程实验】更改文件权限

//file_chmod.c

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

/*更改指定文件的权限*/

#define MODE S_IRWXU | S_IRWXG | S_IRWXO
#define UMASK S_IXUSR | S_IWGRP | S_IRWXO   //0127

int main(int argc, char* argv[])
{
    if(argc < 2){
        fprintf(stderr, "usage: %s file\n", argv[0]);
        exit(1);
    }

    //设置掩码
    /*
    umask(UMASK);
    
    int fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, MODE);
    if (fd < 0){
        perror("open error");
        exit(1);
    }
    */
    
    //更改文件的权限
    int fd = open(argv[1], O_RDWR);
    if(fd < 0){
        perror("open error");
        exit(1);
    }

    fchmod(fd, MODE); //将己经存在的文件权限改为0777

    close(fd);

    return 0;
}

(4)文件截短函数:truncate和ftruncate函数

头文件

#include<sys/types.h>

#include <unistd.h>

函数

int truncate(const char* pathname, off_t length);

int ftruncate(int fd, off_t length);

返回值

成功返回0,出错返回-1

功能

文件截短

参数

(1)pathname:文件路径名字

(2)length:文件截短后的长度

备注

(1)在文件尾端处截去一些数据以缩短文件

(2)将一个文件的长度截短为0是一个特例,用O_TRUNC标志可以做到这一点。

(3)如果该文件以前的长度大于length,则超过length以外的数据就不再能存取如果以前的长度短于length则其后果与系统有关

【编程实验】文件截短

//file_truncate.c

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    if(argc < 3){
        fprintf(stderr, "usage: %s file length\n", argv[0]);
        exit(1);
    }

    //判断进程对文件是否有写权限
    if(access(argv[1], W_OK) < 0){
        perror("write permission error");
        exit(1);
    }

    //将文件截短为指定长度
    if(truncate(argv[1], atoi(argv[2]))){  //atoi函数指字符串转为数字
        perror("truncate error");
        exit(1);
    }
    
    int fd = open(argv[1], O_RDONLY);
    if(fd < 0){
        perror("open error");
        exit(1);
    }

    //显示截短后的文件长度
    long len = lseek(fd, 0L, SEEK_END);
    printf("file length: %ld\n", len);

    close(fd);

    return 0;
}