第四章 文件和目录

来源:互联网 发布:上市公司网络投票规则 编辑:程序博客网 时间:2024/05/29 08:59

4.2 stat fstat lstat函数

#include <sys/stat.h>

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

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

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

三个函数的返回值:若成功则返回0 若出错则返回-1

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 */
     };

 说明:st_mode:文件权限, 文件类型,设置用户ID,设置用户组ID都在里边。

      <sys/stat.h>
Macro           Type of file
S_ISREG()       regular file
S_ISDIR()       directory file
S_ISCHR()       character special file
S_ISBLK()       block special file
S_ISFIFO()      pipe or FIFO
S_ISLNK()       symbolic link
S_ISSOCK()      socket

 

      <sys/stat.h>
Macro           Type of object
S_TYPEISMQ()    message queue
S_TYPEISSEM()   semaphore
S_TYPEISSHM()   shared memory object

 

eg:测试文件类型:

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

 

4.4  设置用户ID和设置组ID

real user ID
real group ID

who we really are

effective user ID
effective group ID
supplementary group IDs

used for file access permission checks

saved set-user-ID
saved set-group-ID

saved by exec functions

实际用户ID和实际组ID标识我们究竟是谁。这两个字段在登录时取自口令文件中的登录项

有效用户ID,有效组ID及附加组ID决定了我们的文件访问权限。

保存的设置用户ID和保存的设置组ID在执行一个程序时包含了有效用户ID和有效组ID的副本

 

每个文件都有一个所有者和组所有者,所有者由stat结构中的st_uid成员表示,组成原者则由st_gid成员表示。

设置用户ID位及设置组ID位都包含在st_mode值中。

如果设置了用户ID位则表示当执行此文件时将进程的有效用户ID设置为文件所有者的用户ID(st_uid),设置了组ID位以此类推。

 

 

4.5 文件访问权限

st_mode mask

Meaning

S_IRUSR

user-read

S_IWUSR

user-write

S_IXUSR

user-execute

S_IRGRP

group-read

S_IWGRP

group-write

S_IXGRP

group-execute

S_IROTH

other-read

S_IWOTH

other-write

S_IXOTH

other-execute

内核进行权限的测试是:

1.若进程的有效用户ID是0,则允许访问。

2.若进程的有效用户ID等于文件的所有者ID,那么若所有者适当的访问权限位被设置,则允许访问,否则拒绝访问。

3.若进程的有效组ID或进程的附加组ID之一等于文件的组ID,那么:若组适当的访问权限位被设置,则允许访问,否则拒绝访问。

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

补充:对linux  一般来说:如果它所在的目录设置了组ID,则新文件的组ID设置为目录的组ID,否则将新文件的组ID设置为进程的有效组ID。

 

4.6 新文件和目录的所有权

新文件的用户ID设置为进程的有效用户ID,关于组ID,分下列两种情况:

1.新文件的组ID可以是进程的有效组ID。

2.新文件的组ID可以是它所在目录的组ID。

 

 

 

4.7 access函数

access函数是按实际用户ID和实际组ID进行访问权限测试的。而不管setUID, 和 setGID

#include <unistd.h>

int access(const char * pathname, in mode); 返回值:若成功则返回0, 若出错则返回-1

mode

Description

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

eg:

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

4.8 umask函数

#include <sys/stat.h>

mode_t umask(mode_t cmask);

 

eg:umask函数的例子

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

说明:f00 RWRWRW  bar rw-------,create受umask的影响!!!

 

 

 

4.9 chmod fchmod函数

     #include <sys/stat.h>

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

    int fchmod (int fileds, mode_t mode);  两个函数的返回值,若成功则返回0,若出错则返回-1

    说明:为了改变一个文件的权限位, 进程的有效用户ID必须等于文件的所有者ID,或者该进程必须具有超级用户权限。

 

 

4.10粘帖位

如果对一个目录设置了粘住位,则只有对该目录具有写权限的用户在满足下列条件之一的情况下,才能删除或更名该目录下的文件:

1.拥有此文件 2.拥有此目录 3.超级用户

 

4.10 chown fchown lchown函数

#include <unistd.h>

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

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

int lcown (const char * pathname, uid_t owner, gid_t group);  三个函数 成功返回0 ,出错返回-1

如果这些函数由非超级用户进程调用,则在成功返回时,该文件的设置用户ID位和设置组ID位都会被清除

 

 

4.12 文件长度

stat结构成员st_size表示以字节为单位的文件长度。此字段只对普通文件,目录文件和符号链接有意义。

对于普通文件,其文件长度可以是0,再读这种文件时,将得到文件结束标志

对于目录,文件长度通常是一个数(例如 16 或512 )的倍数.

对于符号链接,文件长度是文件名中的实际字节数。(因为符号链接文件长度是由st_size指示,所以它并不包含通常C语言用作名字结尾的null字符)

 

文件空洞:如果使用实用程序复制这种文件,那么所有这些空洞都会被填满,其中所有实际数据字节皆填为0.

 

 

4.13文件截短

#include <unistd.h>

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

int ftruncate(int filedes, off_t length); 两个函数的返回值:若成功则返回0 若出错则返回-1

说明:如果该文件以前的长度大于length,则超过length以外的数据就不能再访问。如果以前的长度短于length ,则其效果与系统有关。

遵循XSI的系统将增加该文件的长度。若unix系统实现扩展了该文件,则在以前的文件尾端和新的文件尾端之间的数据将读作0.也就是可能在文件中创建一个空洞。

 

 

 

4.14 文件系统

第四章  文件和目录 - night person - 夜归人

 第四章  文件和目录 - night person - 夜归人

1.在stat结构中,链接计数包含在st_nlink成员中,其基本系统数据类型是nlink_t,这种链接类型成为硬链接。

2.I节点包含了大多数与文件有关的信息: 文件类型那个,文件访问权限位,文件长度和指向该文件所占用的数据库的指针等等。只有两项数据存放在目录项中:文件名和I节点编号。I节点编号的数据类型为ino_t。

3.每个文件系统各自对他们的I节点进行编号,因此目录中I节点编号数指向同一文件系中的相应I节点,不能使一个目录项指向另一个文件系统的I节点。这就是为什么ln(1)命令不能跨越文件系统的原因。

 

4.15 link unlink remove 和 rename函数

#include <unistd.h>

int link(const char * existingpath,const char * newpath);  返回值:若成功则返回0,若出错则返回-1

#include <unistd.h>

int unlink(const char * pathname); 返回值:若成功则返回0, 若出错则返回-1

此函数删除目录项,并将由pathname所应用文件的连接数减一。如果该目录设置了粘住位,则对该目录必须具有写权限,并且具备下面三个条件之一:1.拥有该文件  2.拥有该目录 3.具有超级用户特权。

只有当链接计数达到0时,该文件的内容才可被删除。另一个条件也会组织删除文件的内容---只要有进程打开了该文件,其内容也不能删除。关闭一个文件时,内核首先检查打开该文件的进程数,如果数达到0,然后内核检查其连接数,如果这个数也是0,那么就删除该文件的内容。

eg :打开一个文件,然后unlink它

 #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 unlinked\n");
    sleep(15);
    printf("done\n");
    exit(0);
}

如果 pathname是符号链接,那么unlink删除该符号链接,而不会删除该链接所引用的文件。给出符号链接名情况下,没有一个函数能删除该链接所引用的文件。

超级用户可以调用unlink,其参数pathname制定一个目录,当时通常应该使用rmdir函数,而不使用这种方式。

 

我们也可以用remove函数接触对一个文件或目录的链接。对于文件,remove的功能与unlink相同。对于目录remove的功能与rmdir相同。

#include <stdio.h>

int remove(const char * pathname); 返回值:成功返回0 出错返回-1;

 

#include < stdio.h>

int rename(const char * oldname, const char * newname); 返回值:成功返回0 ,出错返回-1

 

 

4.16 符号链接

 

4.17 symlink 和 readlink函数

       #include <unistd.h>

      int symlink(const char * actualpath, const char * sympath);  //若成功则返回0  若出错则返回-1

     因为open函数跟随符号链接,所以需要有一种方法打开该链接本身,并读该链接中的名字。readlink函数提供了这种功能

     #include<unistd.h>

    sssize_t readlink (const char * restrict pathname ,char * restrict buf , size_t bufsize);成功返回读到的字节数,出错返回-1

 

 

4.18 文件的时间

  

第四章  文件和目录 - night person - 夜归人

     系统并不保存对一个I节点的最后一次访问时间,所以access和stat函数并不更改这三个时间中的任一个。

     ls命令按这三个时间值中的一个排序进行显示。-u选项使其用访问的时间排序, -c 选项则使其用更改状态时间排序。

 

 

4.19 utime函数

#include<utime.h>

int utime(const char * pathname, const struct utimbuf *times); 若成功返回0 若出错返回-1

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

如果times是一个空指针,则返回时间和修改时间两者都设置为当前时间。为了执行此操作必须满足下列两条件之一:进程的有效用户ID必须等于该文件的所有者ID;或者进程对该文件必须具有写权限。

如果times是非空指针,则访问时间和修改时间被设置为times所指向结构中的值。此时进程有效用户ID必须等于该文件的所有者ID,或者进程必须是一个超级用户进程。对文件只具有写权限是不够的。

我们不能对更改状态时间st_ctime制定一个值,当调用utime函数时,此字段将自动更新。

以下程序使用带O_TRUNC选项的open函数将文件长度截短卫0,但并不更改其访问时间及修改时间

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

 

 

4.20 mkdir 和 rmdir函数

#include <sys/stat.h>

int mkdir(const char * pathname , mode_t mode); 返回值:成功返回0  出错则返回-1

#include <unistd.h>

int rmdir(const char * pathname); 返回值:成功则返回0  出错则返回-1;

 

4.21读目录

第四章  文件和目录 - night person - 夜归人
 
 
4.22 chdir fchdir 和 getcwd函数
#include <unistd.h>
int chdir(const char * pathname);
int fchdir(int filedes); 两个函数的返回值:若成功则返回0 若出错则返回-1;
因为当前工作目录是进程的一个属性,所以它只影响调用chdir的进程本身,而不影响其他进程。
 
#include <unistd.h>
char * getcwd(char * buf , size_t size); 返回值:若成功则返回buf, 若出错则返回null
向此函数传递两个参数,一个是缓冲地址buf ,另一个是缓冲区的长度size。该缓冲必须有足够的长度以容纳绝对路径名再加上一个null.否则返回错误。
 
 
4.23设备特殊文件
#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);    }  

第四章  文件和目录 - night person - 夜归人
0 0
原创粉丝点击