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会被移动到上层目录,并重命名,无上层目录,则出错且此上层目录不能为/
/*****************************************包含头文件: #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);}
运行:
阅读全文
1 0
- APUE 学习笔记(第四章)
- APUE第四章学习笔记
- APUE-第四章-习题笔记
- APUE学习笔记——第四章 文件和目录
- apue学习笔记(第四章 文件和目录)
- apue第四章<文件和类型> 笔记
- 《APUE》第四章笔记(1)
- 《APUE》第四章笔记(2)
- 《APUE》第四章笔记(3)
- 《APUE》笔记-第四章-文件和目录
- 《APUE》笔记-第四章-函数总结
- APUE学习: 第四章, 文件和目录
- APUE学习笔记2——第四章——文件和目录
- APUE 学习笔记(第三章)
- APUE学习笔记(第九章)
- APUE第三章学习笔记
- APUE第五章学习笔记
- APUE第六章学习笔记
- jmeter性能测试第一篇(安装)
- HDU1166:敌兵布阵(线段树单点修改)
- 深入理解前端移动开发中的viewport概念
- SQL之利用操作系统
- java IO笔记(SequenceInputStream)
- APUE第四章学习笔记
- UESTC 929Post office(贪心)
- 一个免费的内网穿透工具-sunny-ngrok
- javascripts参考手册(含es6)
- hdu1863(水)
- 数据结构实验之图论二:基于邻接表的广度优先搜索遍历
- ThreadLocal源码解读
- 坑:在angular内使用DOM操作添加元素,被添加的元素不再具有使用ng指令的能力
- Jstorm 简介