APUE第四章学习笔记

来源:互联网 发布:好看的电视剧 知乎 编辑:程序博客网 时间:2024/05/22 13:50
/****************************************************包含头文件:  #include <sys/stat.h>结构体   struct stat{    mode_t   st_mode;       // 文件模式及类型    ino_t       st_ino;     //inode节点号    dev_t      st_dev;          //设备号    dev_t      st_rdev;      //特殊设备号    nlink_t   st_nlink;       //文件的连接数    uid_t     st_uid;       //文件所有者用户ID    gid_t     st_gid;       //文件所有者用户组ID    off_t       st_size;      //普通文件对应的文件字节数    struct timespec st_atime;// 文件最后被访问的时间    struct timespec st_mtime;//文件内容最后被修改的时间    struct timespec st_ctime;//文件状态改变时间    blksize_t   st_blksize; //文件内容对应的块大小    blkcnt_t       st_blocks;  //文件被分配的块数量}*****************************************************/
/********************************************************文件类型信息包含在stat结构体成员st_mode中用下列宏(将st_mode作为参数)可确定文件类型:    宏                                  文件类型 S_ISREG()                              普通文件 S_ISDIR()                              目录文件 S_ISCHR()                              字符特殊文件 S_ISBLK()                              块特殊文件 S_ISFIFO()                             管道或FIFO S_ISLNK()                              符号链接 S_ISSOCK()                             套接字******************************************************/
/***************************************************包含头文件:  #include <sys/stat.h>函数原型:int stat(const char* restrict pathname,struct stat* restrict buf);函数说明: 返回pathname命名的文件的有关的信息结构返回值: 成功返回0出错返回-1**************************************************/
/*********************************************************包含头文件:  #include <sys/stat.h>函数原型:   int fstat(int fd,struct stat* restrict buf);函数说明: 获得已在描述符上打开文件的相关信息返回值:***************************************************/
/*************************************************包含头文件:  #include <sys/stat.h>函数原型:   int lstat(const char* restrict pathname,struct stat* buf);函数说明: 类似于stat,但当命名的文件是一个符号链接时,lstat返回该符号链接的有关信息,而不是由该符号链接引用的文件信息**************************************************/
/****************************************************包含头文件:  #include <sys/stat.h>函数原型:   int fstatat(int fd,const char* restrict pathname,struct stat* restrict buf,int flag);函数说明:flag参数为AT_SYSLINK_NOFOLLOW时,fstatat不会跟随符号链接,而是直接返回符号链接的信息*************************************************/

实例代码4.1.c

  1 #include <sys/stat.h>  2 #include <stdio.h>  3 #include <stdlib.h>  4   5 int main(int argc,char *argv[])  6 {  7     int i;  8     struct stat buf;  9     char *ptr; 10  11     for (i = 1; i < argc; ++i) 12     { 13         printf("%s: ",argv[i]); 14  15         if (lstat(argv[i],&buf) < 0) 16         { 17             printf("lstat error"); 18             continue; 19         } 20  21         if (S_ISREG(buf.st_mode)) 22             ptr = "普通文件"; 23  24         else if (S_ISDIR(buf.st_mode)) 25             ptr = "目录文件"; 26  27         else if (S_ISCHR(buf.st_mode)) 28             ptr = "字符特殊文件"; 29  30         else if (S_ISBLK(buf.st_mode)) 31             ptr = "块特殊文件"; 32  33         else if (S_ISFIFO(buf.st_mode)) 34             ptr = "管道或FIFO"; 35  36         else if (S_ISLNK(buf.st_mode)) 37             ptr = "符号链接"; 38  39         else if (S_ISSOCK(buf.st_mode)) 40             ptr = "套接字"; 41         else 42             ptr = "unknown type"; 43         printf("类型: %s\n",ptr); 44     } 45     exit(0); 46 }

运行:

这里写图片描述

/*****************************************包含头文件:  #include <unsitd.h>函数原型:   int access(const char* pathname,int mode);函数说明:   按照实际用户ID和实际组ID进行访问权限测试返回值:    若成功,返回0,若出错,返回-1---------------------------------------------------------------包含头文件:  #include <unistd.h>函数原型:int faccessat(int fd,const char* name,int mode,int flag);函数说明:按实际用户ID和实际组ID进行访问权限测试返回值:    若成功,返回0,若失败,返回-1;参数说明: mode :若测试文件是否存在 mode就为F_OK否则为下列值的或结果:   mode                 说明                        R_OK               测试读权限                        W_OK             测试写权限                        X_OK              测试执行权限flag参数可以用于改变faccessat的行为,若flag设置为AT_EACCESS,访问检查用的是有效ID和有效组ID,而不是实际ID和实际组ID注:若在这两种情况下:                1.pathname是绝对路径                2.fd为AT_FDCWD,pathname为相对路名access 和faccessat效果是相同的,否则faccessat计算打开目录(fd指向的)的相对路径pathname**********************************************************/

实例4.2.c

  1 #include <unistd.h>  2 #include <fcntl.h>  3 #include "apue.h"  4 int main(int argc,char *argv[])  5 {  6     if (argc != 2)  7      err_quit("usage: a.out <pathname>");  8     if (access(argv[1],R_OK) < 0)  9         err_ret("access error for %s",argv[1]); 10     else 11         printf("read access OK\n"); 12  13     if (open(argv[1],O_RDONLY) < 0) 14         err_ret("open error for %s",argv[1]); 15     else 16         printf("open for reading ok\n"); 17  18     exit(0); 19 }

这里写图片描述

实例:

#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <fcntl.h>int main(int argc,char* argv[]){    if (argc != 2)    {    printf("执行请加参数: <pathname>\n");    exit(0);    }    if (access(argv[1],F_OK) < 0)    {    printf("%s 文件不存在\n",argv[1]);    }    else    {     if (access(argv[1],R_OK) < 0)        printf("实际用户ID和实际组ID无读权限\n");    else        printf("实际用户ID和实际组ID有读权限\n");    if (access(argv[1],W_OK) < 0)        printf("实际用户ID和实际组ID无写权限\n");    else        printf("实际用户ID和实际组ID有写权限\n");    if (access(argv[1],X_OK) < 0)        printf("实际用户和实际组ID无执行权限\n");    else        printf("实际用户和实际组ID有执行权限\n");    }    if (faccessat(AT_FDCWD,argv[1],F_OK,AT_EACCESS) < 0)    {    printf("%s 文件不存在\n",argv[1]);    }    else    {    if (faccessat(AT_FDCWD,argv[1],R_OK,AT_EACCESS) < 0)        printf("有效用户ID和有效组ID无读权限\n");    else        printf("有效用户ID和有效组ID有读权限\n");    if (faccessat(AT_FDCWD,argv[1],W_OK,AT_EACCESS) < 0)        printf("有效用户ID和有效组ID无写权限\n");    else        printf("有效用户ID和有效组ID有写权限\n");    if (faccessat(AT_FDCWD,argv[1],X_OK,AT_EACCESS) < 0)        printf("有效用户ID和有效组ID无执行权限\n");    else        printf("有效用户ID和有效组ID有执行权限\n");    }    exit(0);}

运行:

这里写图片描述

这里写图片描述

/************************************************************包含头文件:  #include <sys/stat.h>函数原型:   int chmod(const char* pathname,mode_t mode);函数说明:   更改现有文件的访问权限返回值:    若成功返回0,若出错返回-1注:  为了改变一个文件的权限位,进程的有效ID必须等于文件所有者ID,或者该进程必须具有超级用户权限************************************************************/
/****************************************************包含头文件:  #include <sys/stat.h>函数原型:   int fchmod(const char* pathname,mode_t mode);函数说明:   对已打开的文件进行操作返回值: 若成功,返回0,若失败返回-1*****************************************************/
/***********************************************************二、设置用户ID位和设置组ID位。在文件模式字(st_mode)中,有两个位(bit10和bit11)分别称为设置用户组ID位和设置用户ID位,分别有两个测试常量S_ISGID和S_ISUID与其对应。若此文件为可执行文件:(1)当设置用户组ID位为1,则文件执行时,内核将其进程的有效用户组ID设置为文件的所有组ID。(2)当设置用户ID位为1,则文件执行时,内核将其进程的有效用户ID设置为文件所有者的用户ID。*****************************************************/
/***************************************************包含头文件:  #include <sys/stat.h>函数原型:  int  fchmodat(int fd,const char* pathname,mode_t mode,int flag);函数说明:   在下面两种情况:        1.pathname参数为绝对路径        2.fd取值为AT_FDCWD,pathname为相对路径fchmodat和chmod和效果相同否则,fchmodat相对于打开目录(由fd指向)pathname参数flag可该fchmodat函数的行为,当设置了AT_SYMLINK_NOFOLLOW标志时,fchmodat并不会跟随符号链接**********************************************/
/*****************************************包含头文件:  #include <unistd.h>函数原型:int chown(const char* pathname,uid_t owner,gid_t group);函数说明: 用于更改文件的用户ID和组ID,如果两个参数owner或group任意一个是-1,则对应ID不变返回值: 若成功,返回0,若失败-1*****************************************//****************************************包含头文件:  #include <unistd.h>函数原型:   int fchown(int fd,uid_t owner,gid_t group);函数说明:   fchown用于由fd指向的已打开文件,改变其所有者(既然它作用于已打开文件,那么此函数就不能用于改变符号链接的所有者)*****************************************************//****************************************************包含头文件:  #include<unistd.h>函数原型: int fchownat(int fd,const char* pathname,uid_t owner,gid_t group);函数说明:fchownat在下列两种情况:    1.pathname为绝对路径    2.fd取值为AT_FDCWD,pathname为相对路径 和chown,lchown功能相同如果参数flag设置了AT_SYSLINK_NOFOLLOW,则lchown和fchownat行为相同如果清除了AT_SYSLINK_NOFOLLOW标志,则fchownat和chown行为相同否则,fd指向打开目录,pathname为相对路径名,fchownat函数计算相对于打开目录的pathname*******************************************************//*****************************************************包含头文件:  #include <unistd.h>函数原型:   int lchown(const char* pathname,uid_t owner,gid_t group);函数说明:   更改文件的所有者,在文件是符号链接的情况下,会修改符号链接的所有者,而不是修改符号链接所引用文件的所有者******************************************************//****************************************************注: 如果这些函数由非超级用户调用,则在成功返回时,该文件的设置用户ID位和设置组ID位会被清除***************************************************/

测试代码(注意设置用户ID位和设置ID位被清除)

4.6.c

#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <sys/stat.h>int main(int argc,char* argv[]){    struct stat statbuf;    if (argc != 2)    {    printf("add <pathname>");    exit(0);    }    if (stat(argv[1],&statbuf) < 0)    {    printf("get stat error\n");    exit(0);    }    if (chmod(argv[1],statbuf.st_mode | S_ISUID | S_ISGID) < 0)    {    printf("chmod error\n");    exit(0);    }    if (lchown(argv[1],27,1000) < 0)    {    printf("lchown error\n");    exit(0);    }    exit(0);}

4.7.c

#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <sys/stat.h>int main(int argc,char* argv[]){    if (argc != 2)    {    printf("add <pathname>");    }    struct stat statbuf;    if (stat(argv[1],&statbuf) < 0)    {    printf("stat error\n");    exit(0);    }    if (statbuf.st_mode & S_ISUID)    {    printf("文件有设置用户ID权限\n");    }    else    printf("文件无设置用户ID权限\n");    if (statbuf.st_mode & S_ISGID)    printf("文件有设置用户组ID权限\n");    else    printf("文件无设置用户组ID权限\n");    printf("用户ID:%d\n",statbuf.st_uid);    printf("用户组ID: %d\n",statbuf.st_gid);    exit(0);}

运行:

这里写图片描述

/*****************************************文件长度:   stat结构成员st_size表示以字节为单位的文件长度,此字段只对普通文件,目录文件和符号链接有意义。注: 对于符号链接,文件长度是在文件名的实际字节数(因为符号链接文件长度总是由st_size指示,所以它并不包含通常C语言用作名字结尾的null字节)**********************************************************/文件截断/*********************************************************包含头文件:  #include <unistd.h>函数原型:   int truncate(const char* pathname,off_t length);            int ftruncate(int fd,off_t length);函数说明:   将一个现有文件长度截断为length,如果该文件以前长度大于length,则length以后的字节都不可访问,如果小于length,以前文件尾和新文件尾之间之间的数据读做0(也就是在文件里创建了个空洞)******************************************************/

实例代码:

#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main(int argc,char* argv[]){    if (argc != 3)    {    printf("add <pathname> <length>\n");    exit(0);    }    off_t length = atoi(argv[2]);    if (truncate(argv[1],length) < 0)    {    printf("truncate error\n");    exit(0);    }    exit(0);}

运行:

这里写图片描述

这里写图片描述

/********************************************************包含头文件:  #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);函数说明:   创建一个新目录项newpath,它引用现有文件existingpath.如果newpath已存在,则返回出错.只创建newpath中的最后一个分量,路径中的其他部分应当已经存在注:  当现有文件是符号链接时,可通过flag参数指定来控制linkat是创建指向符号链接的链接,还是创建指向符号链接所指向文件的链接返回值:    若成功,返回0,若出错,返回-1*******************************************************/
/********************************************************包含头文件:#include <unistd.h>函数原型:   int unlink(const char* pathname);            int unlinkat(int fd,const char* pathname,int flag);函数说明:   删除目录项,并将由pathname所引用文件的链接计数减一注:为了解除对文件的链接,必须对包含该目录项的目录具有写和执行权限。如果对该目录设置了粘帖位,则对该目录必须具有写权限,并且具备下面三个条件之一:    1.拥有该文件    2.拥有该目录    3.具有超级用户权限当flag设置为AT_REMOVEDIR,unlinkat函数可以类似于rmdir一样删除目录,如果这个标志被清除,unlinkat与unlink执行相同操作********************************************************/

实例:
4.9.1.c

#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main(int argc,char* argv[]){    if (argc != 3)    {    printf("add <pathname> <pathname>\n");    exit(0);    }    if (link(argv[1],argv[2]) < 0)    {    printf("link error");    exit(0);    }    exit(0);}

4.9.2.c

#include <unistd.h>#include <stdio.h>#include <stdlib.h>int main(int argc,char* argv[]){    if (argc != 2)    {    printf("add <pathname>\n");    exit(0);    }    if (unlink(argv[1]) < 0)    {    printf("unlink error");    exit(0);    }    exit(0);

运行:

这里写图片描述

/********************************************************包含头文件:  #include <stdio.h>函数原型:   int rename(const char* oldname,const char* newname);    int renameat(int oldfd,const char* oldname,int newfd,const char* newname);函数说明:(1)如果oldname指的是一个文件而不是目录,那么为该文件或符号链接重命名。在这种情况下,如果newname已存在,则它不能引用一个目录,此时,则现将该目录项删除,然后将oldname命名为newname(对包含oldname和newname的目录,调用进程必须具有写权限)(2)如果oldname指的是一个目录,那么为该目录重命名,如果newname已存在,则newname必须引用一个目录,并且该目录应当是空目录(空目录指的是该目录只有.和..项,如果newname已存在(而且引用一个空目录),则现将其删除,然后将oldname重命名为newname.注: 当为一个目录重命名时,newname不能包含oldname作为其路径前缀(3)如若oldname或newname引用符号链接,则处理符号链接本身,而不是符号链接所引用的文件******************************************************/

实例:

#include <stdio.h>#include <stdlib.h>int main(int argc,char* argv[]){    if (argc != 3)    {    printf("add <oldname> <newname>\n");    exit(0);    }    if (rename(argv[1],argv[2]) < 0)    {    printf("rename error\n");    exit(0);    }    exit(0);}

若newdir里有文件,那么olddir会被移动到上层目录,并重命名,无上层目录,则出错且此上层目录不能为/
若newdir里有文件,那么olddir会被移动到上层目录,并重命名,无上层目录,则出错且此上层目录不能为/

/*****************************************包含头文件:  #include <unistd.h>函数原型:   int symlink(const char* actualpath,constchar* sympath);    int symlinkat(const char* actualpath,int fd,const char*sympath);函数说明:   创建一个符号链接注:  在创建此符号链接时,并不要求actualpath已经存在,并且,并不要求actualpath和sympath并不需要位于同一文件系统中。返回值:若成功,返回0,若失败,返回-1*****************************************//***********************************************************包含头文件:  #include <unistd.h>函数说明: ssize_t readlink(const char* restrict pathname,const char* restrict buf,size_t bufsize);    ssize_t readlinkat(int fd,const char* restrict pathname,char *restrict buf,size_t   bufsize);函数说明:   打开该链接本身,并读该链接中的名字(如果函数成功执行,则返回读入buf的字节数,在buf中返回的符号链接的内容不以null字节终止)返回值: 若成功,返回读取的字节数,若失败返回-1**********************************************************/

实例:
4.11.c

#include <unistd.h>#include <stdio.h>#include <stdlib.h>int main(int argc,char* argv[]){    if (argc != 3)    {    printf("add <actualpath> <sympath>\n");    exit(0);    }    if (symlink(argv[1],argv[2]) < 0)    {    printf("symlink error\n");    exit(0);    }    exit(0);}

4.12.c

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#define BUFFERSIZE 4096int main(int argc,char* argv[]){    if (argc != 2)    {    printf("add <sympath>\n");    exit(0);    }    char buf[BUFFERSIZE];    int n;    if ((n = readlink(argv[1],buf,BUFFERSIZE)) < 0)    {    printf("readlink error\n");    exit(0);    }    printf("sympath actual content: %s\n",buf);    exit(0);}

这里写图片描述

/******************************************************包含头文件:  #include <sys/stat.h>函数原型:   int futimens(int fd,const struct timespec[2]);int utimensat(int fd,const char* path,const struct timespec times[2],int flag);函数说明:   更改文件的访问和修改时间注:  (1)如果times参数是空指针,则访问时间和修改时间都设置为当前时间(2)如果times是非空指针,并且任一tv_nsec字段的值既不是UTIME_NOW也不是UTIME_OMIT,则进程的有效用户ID必须等于该文件所有者的ID,或者进程必须是一个超级用户进程,对文件只具有写权限是不够的(3) futimens函数需要打开文件来更改它的时间,utimensat的flag参数如果设置了AT_SYMLINK_NOFOLLOW,则符号链接本身会被修改,否则默认下跟随符号链接,并把文件的时间改成符号链接的时间*********************************************************/

这里写图片描述

/**********************************************************包含头文件:  #include <sys/stat.h>函数原型:   int mkdir(const char* pathname,mode_tmode);int mkdirat(int fd,const char* pathname,mode_t mode);函数说明:   创建一个空目录,其中.和..目录项是自动创建的,所指定的文件访问权限mode由进程的文件模式创建屏蔽字修改注:对于目录通常至少要设置一个执行权限位,以访问该目录中的文件名返回值:若成功,返回0,若失败,返回-1***********************************************************//**********************************************************包含头文件:  #include <unistd.h>函数原型:   int rmdir(const char* pathname);函数说明:   删除空目录,空目录是指只包含.和..这两项的目录返回值:    若成功,返回0,若出错,返回-1**********************************************************/

实例:

#include <stdio.h>#include <stdlib.h>#include <sys/stat.h>#define MODE (S_IRWXU | S_IRWXG | S_IRWXO)int main(int argc,char* argv[]){    if (argc != 2)    {    printf("add <dirname>\n");    exit(0);    }    umask(0);    if (mkdir(argv[1],MODE) < 0)    {    printf("mkdir error\n");    exit(0);    }    exit(0);}

运行:

这里写图片描述

/********************************************************包含头文件:  #include <dirent.h>函数原型:   DIR *opendir(const char pathname);            DIR *fdopendir(int fd);函数说明:   打开目录返回值:    若成功,返回DIR指针,若出错,返回NULL********************************************************//********************************************************包含头文件:  #include <dirent.h>函数原型:   struct dirent* readdir(DIR *dp);函数说明: 读取目录返回值:    返回参数dp目录流的下个目录项进入点(指针),到达目录项结尾返回NULL*******************************************************//******************************************************包含头文件:  #include <dirent.h>函数原型:   void rewinddir(DIR *dp);函数说明: 设置参数dp目前读取的位置为原来开头的读取位置*******************************************************//*********************************************************包含头文件:  #include <dirent.h>函数原型:   int closedir(DIR* dp);函数说明: 关闭目录返回值:    若成功,返回0,若失败,返回-1*********************************************************//*******************************************************包含头文件:  #include <dirent.h>函数原型:   long telldir(DIR *dp);函数说明:与dp关联目录的当前位置******************************************************//**********************************************************包含头文件:  #include <dirent.h>函数原型:   void seekdir(DIR *dp,long loc);函数说明:   设置读取目录参数dp当前位置,loc为偏移量,则下次readdir从新当前位置开始***********************************************************/

实例: 4.15.cpp

#include <iostream>#include <dirent.h>#include <stdlib.h>#include <stdexcept>using namespace std;int main(int argc,char* argv[]){    try    {    if (argc != 2)        throw domain_error("add <dirname>\n");    DIR *dp;    if ((dp = opendir(argv[1])) == NULL)        throw domain_error("dirname is no sense\n");    struct dirent* dt;    long offset;    while ((dt = readdir(dp)) != NULL)    {        offset = telldir(dp);        cout <<"目录第" << offset << "项" << dt->d_name << endl;    }    }    catch(const exception& e)    {    cout << e.what() << endl;    }}

这里写图片描述

/***********************************************************包含头文件:  #include <unistd.h>函数原型:   int chdir(const char* pathname);            int fchdir(int fd);函数说明:   分别用pathname或打开文件描述符来指定新的当前工作目录返回值:    若成功,返回0,若失败,返回-1***********************************************************//***********************************************************包含头文件:  #include <unistd.h>函数原型:   char* getcwd(char* buf,size_t size);函数说明:   得到当前工作目录路径名返回值: 若成功,返回buf,若失败,返回NULL***********************************************************/

实例:

4.17.c

#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main(){    if (chdir("/home/marco/o") < 0)    {    printf("chdir error\n");    exit(0);    }    printf("chdir to /home/marco/o\n");    exit(0);}

这里写图片描述

4.18.c

#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main(){    char *ptr;    size_t size;    if (chdir("/home/marco/o") < 0)    {    printf("chdir error \n");    exit(0);    }    ptr = (char*)malloc(50);    size = 50;    if (getcwd(ptr,size) == NULL)    {    printf("getcwd failed\n");    exit(0);    }    printf("cwd = %s\n",ptr);    exit(0);}

运行:
这里写图片描述

原创粉丝点击