专注收集记录技术开发学习笔记、技术难点、解决方案
网站信息搜索 >> 请输入关键词:
您当前的位置: 首页 > 编程

UNIX编程(四)-文件和目录

发布时间:2011-07-01 07:25:21 文章来源:www.iduyao.cn 采编人员:星星草
UNIX编程(4)-文件和目录
1.stat,fstat,lstat函数
#include <sys/stat.h>

int stat(const char *restrict pathname, struct
stat *restrict buf);

int fstat(int filedes, struct stat *buf);

int lstat(const char *restrict pathname, struct
stat *restrict buf);

当命名文件是一个符号链接时,lstat返回该符号链接的有关信息,而不是由该符号链接引用文件的信息。

stat 结构体说明
struct stat {
       mode_t    st_mode;      /* file type & mode (permissions) */
       ino_t     st_ino;       /* i-node number (serial number) */
       dev_t     st_dev;       /* device number (file system) */
       dev_t     st_rdev;      /* device number for special files */
       nlink_t   st_nlink;     /* number of links */
       uid_t     st_uid;       /* user ID of owner */
       gid_t     st_gid;       /* group ID of owner */
       off_t     st_size;      /* size in bytes, for regular files */
       time_t    st_atime;     /* time of last access */
       time_t    st_mtime;     /* time of last modification */
       time_t    st_ctime;     /* time of last file status change */
       blksize_t st_blksize;   /* best I/O block size */
       blkcnt_t  st_blocks;    /* number of disk blocks allocated */
     };

2.文件类型
文件类型包括:
普通文件
目录文件
块特殊文件
字符特殊文件
FIFO
套接字
符号链接

例:
打印文件类型
#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("%sn", ptr);
  }
   exit(0);
}
3.用户ID和设置组ID
与一个进程相关联的ID有6个或更多:
实际用户ID
实际组ID
有效用户ID
有效组ID
附件组ID
保存的设置用户组ID
保存的设置组ID


4.文件访问权限

st_mode包含了针对文件的访问权限位,每个文件有9个访问权限位,如下:
S_IRUSR  用户读
S_IWUSR  用户写
S_IXUSR  用户执行
S_IRGRP  组读
S_IWGRP  组写
S_IXGRP  组执行
S_IROTH  其他读
S_IWOTH  其他写
S_IXOTH  其他执行


5.access函数
access函数按实际用户ID和实际组ID进行访问权限测试
#include <unistd.h>

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


#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 OKn");
    if (open(argv[1], O_RDONLY) < 0)
        err_ret("open error for %s", argv[1]);
    else
        printf("open for reading OKn");
    exit(0);
}

6.umask函数

umask函数为进程设置文件模式创建屏蔽字,并返回以前的值

#include <sys/stat.h>

mode_t umask(mode_t cmask);

#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);
}

7.chmod和fchmod函数
修改文件的权限位。进程的有效用户ID必须等于文件所有者ID,或者该进程必须具有超级用户权限
#include <sys/stat.h>

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

int fchmod(int filedes, mode_t mode);


#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)
         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);
}

8.粘住位
S_ISVTX称为粘住位,对一个目录设置了粘住位以后,则只有对该目录具有写权限的用户在满足下列条件之一的情况下,才能删除或更名该目录下的文件:
拥有此文件
拥有此目录
是超级用户

9.chown,fchown和lchown函数
更改文件用户所有者ID 或组ID
#include <unistd.h>

int chown(const char *pathname, uid_t owner, gid_t
group);

int fchown(int filedes, uid_t owner, gid_t group);

int lchown(const char *pathname, uid_t owner,
gid_t group);

10.文件截短
将现有的文件长度截短为length字节
#include <unistd.h>

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

int ftruncate(int filedes, off_t length);

11.link,unlink,remove和rename函数
#include <unistd.h>

int link(const char *existingpath, const char
*newpath);

#include <unistd.h>

int unlink(const char *pathname);

#include "apue.h"
#include <fcntl.h>

int
main(void)
{
    if (open("tempfile", O_RDWR) < 0)
        err_sys("open error");
    if (unlink("tempfile") < 0)
        err_sys("unlink error");
    printf("file unlinkedn");
    sleep(15);
    printf("donen");
    exit(0);
}


#include <stdio.h>

int remove(const char *pathname);

重命名文件
#include <stdio.h>

int rename(const char *oldname, const char *newname);

12.symlink和readlink函数
symlink创建一个符号链接
#include <unistd.h>
int symlink(const char *actualpath, const char
*sympath);

readlink 打开符号链接文件本身
#include <unistd.h>
ssize_t readlink(const char* restrict pathname,
char *restrict buf,
                 size_t bufsize);

13.utime函数
#include <utime.h>

int utime(const char *pathname, const struct
utimbuf *times);
函数使用的结构体为:
  struct utimbuf {
      time_t actime;    /* access time */
      time_t modtime;   /* modification time */
    }

#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);
}

14.mkdir和rmdir函数
mkdir函数创建目录,rmdir删除目录

#include <sys/stat.h>

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

#include <unistd.h>

int rmdir(const char *pathname);

15.读目录




#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;
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);
}

/*
* Descend through the hierarchy, starting at "pathname".
* The caller's func() is called for every file.
*/
#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                  /* we return whatever func() returns */
myftw(char *pathname, Myfunc *func)
{

    int len;
    fullpath = path_alloc(&len);    /* malloc's for PATH_MAX+1 bytes */
                                        /* (Figure 2.15) */
    strncpy(fullpath, pathname, len);       /* protect against */
    fullpath[len-1] = 0;                    /* buffer overrun */

    return(dopath(func));
}
/*
* Descend through the hierarchy, starting at "fullpath".
* If "fullpath" is anything other than a directory, we lstat() it,
* call func(), and return. For a directory, we call ourself
* recursively for each name in the directory.
*/
static int                  /* we return whatever func() returns */
dopath(Myfunc* func)
{
    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));

     /*
      * It's a directory. First call func() for the directory,
      * then process each filename in the directory.
      */
    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);
}

16.chdir,fchdir和getcwd函数
chdir和fchdir 改变当前工作目录

#include <unistd.h>

int chdir(const char *pathname);

int fchdir(int filedes);

#include "apue.h"

int
main(void)
{

     if (chdir("/tmp") < 0)
         err_sys("chdir failed");
     printf("chdir to /tmp succeededn");
     exit(0);
}

getcwd获得当前的全路径
#include <unistd.h>

char *getcwd(char *buf, size_t size);



#include "apue.h"

  int
  main(void)
  {

      char    *ptr;
      int     size;

      if (chdir("/usr/spool/uucppublic") < 0)
          err_sys("chdir failed");

      ptr = path_alloc(&size); /* our own function */
      if (getcwd(ptr, size) == NULL)
          err_sys("getcwd failed");

      printf("cwd = %sn", ptr);
      exit(0);
  }


17.设备特殊文件

设备号所用的存储类型是dev_t,通常用major和minor这两个宏来访问主次设备号。
系统中于每个文件名关联的st_dev值是文件系统的设备号,只有字符特殊文件和块特殊文件才有st_rdev值.
例:打印st_dev和st_rdev值
#include "apue.h"
#ifdef SOLARIS
#include <sys/mkdev.h>
#endif

int
main(int argc, char *argv[])
{

    int         i;
    struct stat buf;

    for (i = 1; i < argc; i++) {
        printf("%s: ", argv[i]);
        if (stat(argv[i], &buf) < 0) {
            err_ret("stat error");
            continue;
         }

         printf("dev = %d/%d", major(buf.st_dev), minor(buf.st_dev));
         if (S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode)) {
             printf(" (%s) rdev = %d/%d",
                     (S_ISCHR(buf.st_mode)) ? "character" : "block",
                     major(buf.st_rdev), minor(buf.st_rdev));

         }
         printf("n");
    }

    exit(0);

}





友情提示:
信息收集于互联网,如果您发现错误或造成侵权,请及时通知本站更正或删除,具体联系方式见页面底部联系我们,谢谢。

其他相似内容:

热门推荐: