4(文件和目录)

来源:互联网 发布:pk10预测软件 编辑:程序博客网 时间:2024/04/29 10:53

1 查看文件类型

#include <sys/stat.h>int stat(const char *pathname, struct stat *buf);int fstat(int filedes, struct stat *buf);int lstat(const char * pathname, struct stat *buf);            All three return: 0 if OK, -1 on error

这里写图片描述
struct stat结构如下
这里写图片描述

unix 的文件类型(包含在st_mode中)
1> 普通文件,包含了某种类型的数据,可以是二进制的也可以是文本
2>目录文件,目录文件时包含了其他文件的文件名和链接的文件。
3>字符设备文件,对文件的读写以字符为单位的,没有缓冲区
4>块设备文件,对文件的读写以某个大小的块为单位,有缓冲区,写入与读出都是从缓冲区的读写
5>FIFO文件 也就是命名管道文件
6>符号连结:指向另一个文件的文件
这里写图片描述
示例:

#include "apue.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) {            err_ret("lstat error");            continue;         }         if (S_ISREG(buf.st_mode))            ptr = "regular";         else if (S_ISDIR(buf.st_mode))            ptr = "directory";         else if (S_ISCHR(buf.st_mode))            ptr = "character special";         else if (S_ISBLK(buf.st_mode))            ptr = "block special";         else if (S_ISFIFO(buf.st_mode))            ptr = "fifo";         else if (S_ISLNK(buf.st_mode))            ptr = "symbolic link";         else if (S_ISSOCK(buf.st_mode))            ptr = "socket";         else            ptr = "** unknown mode **";         printf("%s\n", ptr);  }   exit(0);}

这里写图片描述

2 access函数–测试访问权限

#include <unistd.h>int access(const char *pathname, int mode);        Returns: 0 if OK, -1 on error

mode取值

R_OK    test for read permissionW_OK    test for write permissionX_OK    test for execute permissionF_OK    test for existence of file

示例

#include "apue.h"#include <fcntl.h>Int main(int argc, char *argv[]){    if (argc != 2)        err_quit("usage: a.out <pathname>");    if (access(argv[1], R_OK) < 0)        err_ret("access error for %s", argv[1]);    else        printf("read access OK\n");    if (open(argv[1], O_RDONLY) < 0)        err_ret("open error for %s", argv[1]);    else        printf("open for reading OK\n");    exit(0);}

这里写图片描述

3 umask函数(为进程创建屏蔽字,并返回以前的值)

#include <sys/stat.h>mode_t umask(mode_t cmask);    Returns: previous file mode creation mask

示例

#include "apue.h"#include <fcntl.h>#define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)Int main(void){    umask(0);    if (creat("foo", RWRWRW) < 0)        err_sys("creat error for foo");    umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);    if (creat("bar", RWRWRW) < 0)        err_sys("creat error for bar");    exit(0);}

这里写图片描述
可以修改代码如下:拿走bar文件user的read和write权限
这里写图片描述
结果如下:
这里写图片描述

umask是从权限中“拿走”相应的位,且文件创建时不能赋予执行权限
umask 命令允许你设定文件创建时的缺省模式,对应每一类用户(文件属主、同组用户、其他用户)存在一个相应的umask值中的数字。对于文件来说,这一数字的最大值是6。系统不允许你在创建一个文本文件时就赋予它执行权限,必须在创建后用chmod命令增加这一权限。目录则允许设置执行权限,这样针对目录来说,umask中各个数字最大可以到7。
假设这次u m a s k值为0 2 2:
1) 文件的最大权限 rwx rwx rwx (777)
2 ) u m a s k值为0 2 2 — -w- -w-
3) 目录权限 rwx r-x r-x (755) 这就是目录创建缺省权限
4) 文件权限 rw- r– r– (644) 这就是文件创建缺省权限

4 chomd和fchomd函数

更改现有文件的访问权限

#include <sys/stat.h>int chmod(const char *pathname, mode_t mode);int fchmod(int filedes, mode_t mode);        Both return: 0 if OK, -1 on error

Chomd在指定文件上操作,fchomd在已打开的文件上操作
示例:

#include "apue.h"Int main(void){     struct stat      statbuf;     /* turn on set-group-ID and turn off group-execute */     if (stat("foo", &statbuf) < 0)         err_sys("stat error for foo");     if (chmod("foo", (statbuf.st_mode & ~S_IXGRP) | S_ISGID) < 0)//修改group的x权限         err_sys("chmod error for foo");     /* set absolute mode to "rw-r--r--" */     if (chmod("bar", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0)         err_sys("chmod error for bar");     exit(0);}

这里写图片描述
解释一下chmod(“foo”, (statbuf.st_mode & ~S_IXGRP) | S_ISGID) 这句话:
S_IXGRP=1(执行权限设定为1),取反为0.那么就是将组执行权限置空。
再“或”上S_ISGID,就是讲组执行权限置为S
S_ISGID表示(set group-id on execution),对应解释在(http://zhidao.baidu.com/link?url=04hmDw4WdWfPzD1oKNaFoK_0GgtZq4DO8wJ756h5W0Ml2c7GkeyhPpBwjU1AYUZbicJ74uRoiAriiIDvEr38rjp1tV0KnI1HMjJZU1OY_C3)

5 文件截短函数

#include <unistd.h>int truncate(const char *pathname, off_t length);int ftruncate(int filedes, off_t length);        Both return: 0 if OK, 1 on error

这里写图片描述

#include <unistd.h>int link(const char *existingpath, const char *newpath);        Returns: 0 if OK, -1 on error

此函数创建一个newpath,引用现有的文件existingpath。如果newpath存在,返回-1。只创建newpath中的最后一个分量,路径中的其它部分应该存在

#include <unistd.h>int unlink(const char *pathname);        Returns: 0 if OK, -1 on error

此函数删除目录项,并将pathname所引用的文件链接计数减1.如果该文件还有其他链接,可以通过其他链接访问该数据

#include <stdio.h>int remove(const char *pathname);        Returns: 0 if OK, 1 on error

移除链接。对于文件,相当于unlink;对于目录,相当于rmdir

#include <stdio.h>int rename(const char *oldname, const char *newname);        Returns: 0 if OK, 1 on error

给文件或者目录更名

7 utime函数(一个文件的访问和修改时间可用它更改)

#include <utime.h>int utime(const char *pathname, const struct utimbuf *times);        Returns: 0 if OK, 1 on error

struct utimbuf数据结构如下:

struct utimbuf {    time_t actime;    /* access time */    time_t modtime;   /* modification time */}

下面的代码使用带O_TRUNC选项的open函数将文件长度截短为0,但不更改访问和修改时间。为了做到这一点,先用stat获取文件当前状态(包括时间),然后截短,最后用utime复位

#include "apue.h"#include <fcntl.h>#include <utime.h>Int main(int argc, char *argv[]){    int             i, fd;    struct stat     statbuf;    struct utimbuf  timebuf;    for (i = 1; i < argc; i++) {        if (stat(argv[i], &statbuf) < 0) { /* fetch current times */            err_ret("%s: stat error", argv[i]);            continue;        }        if ((fd = open(argv[i], O_RDWR | O_TRUNC)) < 0) { /* truncate */            err_ret("%s: open error", argv[i]);            continue;        }         close(fd);        timebuf.actime  =  statbuf.st_atime;        timebuf.modtime =  statbuf.st_mtime;        if (utime(argv[i], &timebuf) < 0) {     /* reset times */            err_ret("%s: utime error", argv[i]);            continue;        }    }    exit(0);}

8 读目录

#include <dirent.h>DIR *opendir(const char *pathname);        Returns: pointer if OK, NULL on errorstruct dirent *readdir(DIR *dp);        Returns: pointer if OK, NULL at end of directory or errorvoid rewinddir(DIR *dp);int closedir(DIR *dp);        Returns: 0 if OK, 1 on errorlong telldir(DIR *dp);        Returns: current location in directory associated with dp void seekdir(DIR *dp, long loc);

用法如下:

#include "apue.h"#include <dirent.h>#include <limits.h>/* function type that is called for each filename */typedef int Myfunc(const char *, const struct stat *, int);static Myfunc myfunc;//相当于myfunc(const char *, const struct stat *, int);统计各种类型的文件的数量static int myftw(char *, Myfunc *);static int dopath(Myfunc *);static long nreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot;int main(int argc, char *argv[]){    int ret;    if (argc != 2)        err_quit("usage:  ftw  <starting-pathname>");    ret = myftw(argv[1], myfunc);       /* does it all */    ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock;    if (ntot == 0)        ntot = 1;       /* avoid divide by 0; print 0 for all counts */    printf("regular files  = %7ld, %5.2f %%\n", nreg,  nreg*100.0/ntot);    printf("directories    = %7ld, %5.2f %%\n", ndir, ndir*100.0/ntot);    printf("block special  = %7ld, %5.2f %%\n", nblk, nblk*100.0/ntot);    printf("char special   = %7ld, %5.2f %%\n", nchr, nchr*100.0/ntot);    printf("FIFOs          = %7ld, %5.2f %%\n", nfifo, nfifo*100.0/ntot);    printf("symbolic links = %7ld, %5.2f %%\n", nslink, nslink*100.0/ntot);    printf("sockets        = %7ld, %5.2f %%\n", nsock, nsock*100.0/ntot);    exit(ret);}#define FTW_F   1       /* file other than directory */#define FTW_D   2       /* directory */#define FTW_DNR 3       /* directory that can't be read */#define FTW_NS  4       /* file that we can't stat */static char *fullpath;      /* contains full pathname for every file */static int myftw(char *pathname, Myfunc *func){    int len;    fullpath = path_alloc(&len);    /* malloc's for PATH_MAX+1 bytes */    strncpy(fullpath, pathname, len);   /* protect against */    fullpath[len-1] = 0;            /* buffer overrun */    return(dopath(func));}//path_alloc在网上有详细的解释http://www.docin.com/p-634598991.html//注意里面的size=PATH_MAX+1//所以才有了fullpath[len-1] = 0;这句static int dopath(Myfunc* func)//遍历fullpath下的每个文件并统计,包括stat error和directory这两种情况{    struct stat     statbuf;    struct dirent   *dirp;    DIR     *dp;    int     ret;    char        *ptr;    if (lstat(fullpath, &statbuf) < 0)  /* stat error */        return(func(fullpath, &statbuf, FTW_NS));    if (S_ISDIR(statbuf.st_mode) == 0)  /* not a directory */        return(func(fullpath, &statbuf, FTW_F));    if ((ret = func(fullpath, &statbuf, FTW_D)) != 0)        return(ret);    ptr = fullpath + strlen(fullpath);  /* point to end of fullpath */    *ptr++ = '/';    *ptr = 0;    if ((dp = opendir(fullpath)) == NULL)   /* can't read directory */        return(func(fullpath, &statbuf, FTW_DNR));    while ((dirp = readdir(dp)) != NULL)    {        if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0)            continue;       /* ignore dot and dot-dot */        strcpy(ptr, dirp->d_name);  /* append name after slash */        if ((ret = dopath(func)) != 0)      /* recursive */             break;  /* time to leave */    }    ptr[-1] = 0;    /* erase everything from slash onwards */    if (closedir(dp) < 0)        err_ret("can't close directory %s", fullpath);    return(ret);}static int myfunc(const char *pathname, const struct stat *statptr, int type)//统计各种类型的文件的数量{    switch (type) {        case FTW_F:            switch (statptr->st_mode & S_IFMT) {            case S_IFREG:   nreg++;     break;            case S_IFBLK:   nblk++;     break;            case S_IFCHR:   nchr++;     break;            case S_IFIFO:   nfifo++;    break;            case S_IFLNK:   nslink++;   break;            case S_IFSOCK:  nsock++;    break;            case S_IFDIR:                err_dump("for S_IFDIR for %s", pathname);                /* directories should have type = FTW_D */            }            break;        case FTW_D:                 ndir++;             break;        case FTW_DNR:                   err_ret("can't read directory %s", pathname);                   break;        case FTW_NS:                err_ret("stat error for %s", pathname);             break;        default:            err_dump("unknown type %d for pathname %s", type, pathname);        }    return(0);}

9 chdir, fchdir, getcwd函数

可以更改目录

#include <unistd.h>int chdir(const char *pathname);int fchdir(int filedes);        Both return: 0 if OK, 1 on error

因为当前目录是进程的一个属性,所以只影响chdir本身。这就意味着下面这段代码不会产生我们希望的结果

#include "apue.h"int main(void){     if (chdir("/tmp") < 0)         err_sys("chdir failed");     printf("chdir to /tmp succeeded\n");     exit(0);}

编译程序会得到下列结果:

$ pwd/usr/lib$ mycdchdir to /tmp succeeded$ pwd/usr/lib

由此可见当前目录并没有改变,是因为shell创建了一个子进程来执行这个程序。要想改变目录,必须要让shell去执行,cd命令的执行程序直接包含在shell里面。

10 文件访问权限位小结

这里写图片描述

0 0
原创粉丝点击