首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >4(文件和目录)

4(文件和目录)

作者头像
提莫队长
发布2019-02-21 10:47:04
5560
发布2019-02-21 10:47:04
举报
文章被收录于专栏:刘晓杰刘晓杰

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 permission
W_OK    test for write permission
X_OK    test for execute permission
F_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
这里写图片描述
这里写图片描述

6 link, unlink, remove, rename函数

#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 error
struct dirent *readdir(DIR *dp);
        Returns: pointer if OK, NULL at end of directory or error
void rewinddir(DIR *dp);
int closedir(DIR *dp);
        Returns: 0 if OK, 1 on error
long 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
$ mycd
chdir to /tmp succeeded
$ pwd
/usr/lib

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

10 文件访问权限位小结

这里写图片描述
这里写图片描述
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年04月21日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 查看文件类型
  • 2 access函数–测试访问权限
  • 3 umask函数(为进程创建屏蔽字,并返回以前的值)
  • 4 chomd和fchomd函数
  • 5 文件截短函数
  • 6 link, unlink, remove, rename函数
  • 7 utime函数(一个文件的访问和修改时间可用它更改)
  • 8 读目录
  • 9 chdir, fchdir, getcwd函数
  • 10 文件访问权限位小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档