UNIX环境高级编程 文件类型

 

 

 

相关函数列表

//stat获取文件的状态信息
//fstat 根据fd返回相关信息
//lstat 返回该符号链接有关信息
//fstatat为一个相当于当前打开目录的路径名返回文件统计信息
#include <sys/stat.h>
int stat(const char *restrict pathname, struct stat *restrict buf);
int fstat(int fd, struct stat *buf);
int fstat(const char *restrict pathname, struct stat *restrict buf);
int fstatat(int fd, const char *restrict pathname, struct stat *restrict buf,   int flag);


//stat 结构体
struct stat {
    mode_t       st_mode;   //文件类型和权限 
    ino_t        st_ino;    //i-node数量
    dev_t        st_dev;    //设备数量(文件系统)
    dev_t        st_rdev;   //设备数量
    nlink_t      st_nlink;  //链接数
    uid_t        st_uid;    //UID数
    gid_t        st_gid;    //GID数
    off_t        st_size;   //文件大小
    struct timespec   st_atime;   //上次访问时间
    struct timespec   st_mtime;   //修改时间
    struct timespec   st_ctime;   //文件状态修改时间,i-node
    blksize_t   st_bklsize;       //块数量
    blkcnt_t    st_blocks;        //被分配了多少磁盘块
};

//timespec结构体
struct timespec {
    time_t     tv_sec;  //秒
    long       tv_nsec; //纳秒
};


//测试文件是否打开,写入,执行正常
#include <unistd.h>
int access(const char *pathname, int mode);
int faccessat(int fd, const char *pathname, int mode, int flag);
//access函数的mode标志
R_OK       测试读权限
W_OK       测试写权限
X_OK       测试执行权限

//设置进程文件模式屏蔽字
//跟chmod不同,这里设置的S_IRUSR,S_IWUSR是屏蔽掉这个权限,也就是说umask(0)表示全部权限,
//而umask(S_IRUSR,S_IWUSR)是屏蔽掉当前用户的读写权限
//创建一个文件,目录默认的权限就来自于umask,umask设置的权限就是默认创建目录的权限
//文件权限略不同,会在目录权限的基础上去掉所有的执行权限
#include <sys/stat.h>
mode_t umask(mode_t cmask);

//更改现有文件的访问权限
#include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);
int fchmod(int fd, mode_t mode);
int fchmodeat(int fd, const char *pathname, mode_t mode, int flag);

//更改文件的用户ID和组ID
//fchown和lchown更改符号链接本身的所有者,而不是符号链接指向的文件所有者
//uid 和 gid参考/etc/passwd文件
#include <unistd.h>
int chown(const char *pathname, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int fchownat(int fd, const char *pathname, uid_t owner, gid_t group);
int lchown(const char *pathname, uid_t owner, gid_t group);


//文件截断
#include <unistd.h>
int truncate(const char *pathname, off_t length);
int ftruncate(int fd, off_t length);


//任何一个文件可以有多个目录项指向其 i节点,link函数用来创建指向现有文件的链接
#include <unistd.h>
int link(const char *existingpath, const char *newpath);
int linkat(int efd, const char *existingpath, int nfd, const char *newpath, int flag);

//删除一个现有的目录项
#include <unistd.h>
int unlink(const char *pathname);
int unlinkat(int fd, const char *pathname, int flag);

//可以用remove函数删除对一个文件或目录的链接,对于文件remove和unlink相同,对于目录remove和
//rmdir相同
#include <stdio.h>
int remove(const char *pathname);

//对目录和文件重命名
#include <stdio.h>
int rename(const char *pathname, const char *newname);
int renameat(int oldfd, const char *oldname, int newfd, const char *newname);

//创建符号链接
#include <unistd.h>
int symlink(const char *actualpath, const char *sympath);
int symlikdat(const char *actualpath, int fd, const char *sympath);

//打开符号链接
#include <unistd.h>
ssize_t readlink(const char *restrict pathname, char *restrict buf, size_t bufsize);
ssize_t readlinkat(int fd, const char *restrict pathname, char *restrict buf,size bufsize);


//更改文件的访问时间和修改时间
#include <sys/stat.h>
int futimens(int fd, const struct timespec times[2]);
int utimensat(int fd, const char *path, const struct timespec times[2], int flag);

//timespec结构体如下
struct timeval {
    time_t tv_sec;  //秒
    long  tv_usec;  //毫秒
};

//创建目录
#include <sys/stat.h>
int mkdir(const char *pathname, mode_t mode);
int mkdirat(int fd, const char *pathname, mode_t mode);

//删除一个空目录
#include <unistd.h>
int rmdir(const char *pathname);


//更改当前工作目录,获取当前工作目录的完成路径
#include <unistd.h>
int chdir(const char *pathname);
int fchdir(int fd);
char *getcwd(char *buf, size_t size);

//读目录
#include <dirent.h>
DIR  *opendir(const char *pathname);
DIR  *fdopendir(int *fd);              //这两个函数成功返回指针,出错返回NULL
struct dirent  *readdir(DIR *dp);      //成功返回指针,出错返回NULL
void rewinddir(DIR *dp);               
int  closedir(DIR *dp);                //成功返回0,出错返回-1
long telldir(DIR *dp);                 //返回值与dp关联的目录中的当前位置
void seekdir(DIR *dp, long loc);

//DIR结构体如下
struct DIR {
    ino_t  d_ino;
    char   d_name[];
};

 

 

UNIX中的文件类型

类型 说明
普通文件(regular file)

最常用的文件类型,这种文件包含了某些形式的数据,至于是二进制还是文本

类型,对于UNIX内核而已并无区别,对普通文件的内容解释是由处理该文件

的应用程序进行

目录文件(directory file)

这种文件包含了其他文件的名字以及指向与这些玩呢间有关信息的指针。对于

一个目录文件具有读权限的人已进场都可以读该目录的内容,但只有内核可以

直接写目录文件。

块特殊文件

(block special file)

这种类型的文件提供对设备(如磁盘)带缓冲的访问,每次访问以固定长度单位

进行

字符特殊文件

(character special file)

这种类型的文件提供对设备不带缓冲的访问,每次访问长度可变。系统中的

所有设备那么是字符特殊文件,那么是块特殊文件。

FIFO 这种类型的文件用于进程间通信,有时也沉默命名管道(named pipe)
套接字(socket)

这种类型的文件用于进程间的网络通讯。套接字也可用于一台宿主机上进程

之间的非网络通信

符号链接

(symbolic link)

这种类型的文件指向另一个文件

 

 

stat结构中的st_mode成员 <sys/stat.h>中的文件类型宏

文件类型
S_ISREG() 普通文件
S_ISDIR() 目录文件
S_ISCHR() 字符特殊文件
S_ISBLK() 块特殊文件
S_ISFIFO() 管道或FIFO
S_ISLNK() 符号链接
S_ISSOCK() 套接字

 

POSIX.1允许实现将进场通讯(IPC)对象(如消息队列和信号量等)说明为文件。下列类型参数并非st_mode,

而是指向stat结构的指针

对象的类型
S_TYPEISMQ() 消息队列
S_TYPEISSEM() 信号量
S_TYPEISSHM() 共享存储对象

 

文件访问权限

st_mode屏蔽 含义 对普通文件的影响 对目录的影响
S_IRUSR 用户读 许可用户读文件 许可用户读目录项
S_IWUSR 用户写 许可用户写文件 许可用户在目录中删除和创建文件
S_IXUSR 用户执行 许可用户执行文件 许可用户在目录中搜索给定路径名
S_IRGRP 组读 许可组读文件 许可组读目录项
S_IWGRP 组写 许可组写文件 许可组在目录中删除和创建文件
S_IXGRP 组执行 许可组执行文件 许可组在目录中搜索给定路径名
S_IROTH 其他读 许可其他读文件 许可其他读目录项
S_IWOTH 其他写 许可其他写文件 许可其他在目录中删除和创建目录
S_IXOTH 其他执行 许可其他执行文件 许可其他在目录中搜索给定路径名

S_ISUID

S_ISGID

设置用户ID

设置组ID

执行时设置有效用户ID

若组执行位设置,则执行时设置

有效组ID,否则强制性锁起作用

(未使用)

将在目录中创建的新文件的组ID设置为

目录的组ID

S_ISVTX

粘着位

在交换区缓存程序正文(若支持)

限制在目录中删除和重命名文件

 

 

每次打开创建删除文件内核都会进程文件访问权限测试,具体如下:

1.若进程的有小用户ID是0(超级用户)则允许访问,这给予超级用户对整个文件系统进程处理的最充分权利

2.若进程的有小用户ID等于文件的所有者ID(也就是进程拥有此文件),那么如果所有者适当的访问权限位被

   设置,则允许访问,否则拒绝。

3.若进程的有小组ID或进程的附属组ID之一等于文件的组ID,那么如果组适当的访问权限位被设置则允许

   访问,否则拒绝。

4.若其他用户适当的访问权限位被设置则允许访问,否则拒绝。

 

较详细的柱面组的i 节点和数据块


 

 

 

 

查看文件类型的列子:

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
int main(int argc, char *argv[]) {
        int i;
        struct stat buf;
        char *ptr;
        for(i=1;i<argc;i++) {
            printf("%s : ",argv[i]);
            if( lstat(argv[i], &buf) < 0 ) {
                printf("lstat error\r\n");
                continue;
            }

            if( S_ISREG(buf.st_mode) ) {
                ptr = "regular file";
            }
            else if( S_ISDIR(buf.st_mode) ) {
                ptr = "directory file";
            }
            else if( S_ISCHR(buf.st_mode) ) {
                ptr = "character special file";
            }
            else if( S_ISBLK(buf.st_mode) ) {
                ptr = "block special file";
            }
            else if( S_ISFIFO(buf.st_mode) ) {
                ptr = "file file";
            }
            else if( S_ISLNK(buf.st_mode) ) {
                ptr = "synbolic line file";
            }
            else if( S_ISSOCK(buf.st_mode) ) {
                ptr = "socket file";
            }
            else {
                ptr = "unkonwn mode";
           }
            printf("%s\r\n",ptr);
        }//end for
        return 0;
}

 

测试文件是否可以正常打开(可以测试是否可读,可执行)

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
int main(int argc, char *argv[]) {

        if(argc < 2) {
                printf("input path\r\n");
                return 1;
        }

        if( access(argv[1], R_OK) < 0 ) {
                printf("access error for %s",argv[1]);
                printf("\r\n");
        } else {
                printf("read access ok\r\n");
        }

        if( open(argv[1],O_RDONLY) < 0 ) {
                printf("open error for %s",argv[1]);
                printf("\r\n");
        } else {
                printf("open for reading ok\r\n");
        }
        return 0;
}

 

umask

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
int main(int argc, char *argv[]) {
        umask(0);
        if( creat("aaa",RWRWRW) < 0 ) {
                printf("create error aaa\r\n");
        }
        umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
        if( creat("bbb",RWRWRW) < 0 ) {
                printf("create error for bbb\r\n");
        }
        return 0;
}

 

改变文件权限和所有者,文件截断

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
        struct stat buf;
        if(stat("bbb",&buf) < 0) {
                printf("stat error\r\n");
        }
        if( chmod("bbb", (buf.st_mode | S_IRGRP | S_IWGRP | S_IXGRP)) < 0 ) {
                printf("chmod error\r\n");
        }
        if( chown("bbb", 0, 0) < 0 ) {
                printf("chown error\r\n");
        }
        if(truncate("hehe.txt",10) < 0) {
                printf("truncate error\r\n");
        }
        return 0;
}

 

硬链接,软链接,重命名,创建删除目录

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
int main(int argc, char *argv[]) {
        //hard link
        if(link("aaa","aaa_hard") < 0) {
                printf("link error\r\n");
        }
        if(unlink("bbb") < 0) {
                printf("unlink error\r\n");
        }
        if(remove("mask") < 0) {
                printf("remove error\r\n");
        }

        //rename
        if(rename("xx","rename_xx") < 0) {
                printf("rename xx error\r\n");
        }
        if(rename("xx2","rename_xx2") < 0) {
                printf("rename xx2 error\r\n");
        }

        //symbol link
        if(symlink("aaa","aaa_symlink") < 0) {
                printf("symlink error\r\n");
        }
        char buf[1024];
        int result = readlink("aaa_mylink",buf,1024);
        if(result > 0) {
                int i;
                for(i=0;i<result;i++) {
                    printf("buf[%d]--%c\r\n",i,buf[i]);
                }
        }

        //test dir
        if(mkdir("aaa_dir",S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
                printf("create aaa_dir error\r\n");
        }
        if(rmdir("test_dir") < 0) {
                printf("remove dir error\r\n");
        }
        return 0;
}

 

修改文件访问时间和创建时间,当前工作目录

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
int main(int argc, char *argv[]) {
        int i,fd;
        struct stat buf;
        struct timespec time[2];
        char *path ="/data0/test/test.log";
        if(stat(path,&buf) < 0) {
                printf("stat error\r\n");
        }
        if((fd=open(path, O_RDWR|O_TRUNC)) < 0) {
                printf("open error\r\n");
        }
        time[0] = buf.st_atim;
        time[1] = buf.st_mtim;
        if(futimens(fd,time) < 0) {
                printf("futimens error\r\n");
        }
        close(fd);

        if(chdir("/tmp") < 0) {
                printf("chdir error\r\n");
        }
        char buffer[1024];
        char *dir = getcwd(buffer,1024); 
        printf("path=%s\r\n",dir);
        return 0;
}

 

 

 

 

 

参考

umask

硬链接和符号链接的区别

文件和目录

Linux磁盘分区和文件系统

关于linux中的软链接和硬链接

linux关于readlink函数获取运行路径的小程序  

 

 

 

猜你喜欢

转载自xxniao.iteye.com/blog/2109076