·有道云笔记地址,详细戳这:http://note.youdao.com/noteshare?id=c3acd730a7443727b1db74d2d44e9ac9&sub=BAD34E04DC5A4AC8AF1FB1F6F149D42D
目录
4、测试stat函数部分功能(具体函数头文件包含,用man命令)
5、stat函数的应用案例 E:\Linux\3.AppNet\2.fileproperty\3.2.2
access函数检查权限设置E:\Linux\3.AppNet\2.fileproperty\3.2.3
chown修改文件/目录所属拥有者和组。(改文件的属主与属组)
chmod修改文件的各种权限属性。chmod命令只有root用户才有权利去执行修改。
三、目录文件函数 E:\Linux\3.AppNet\2.fileproperty\3.2.4
一、linux中各种文件类型
Linux—— 一切皆是文件,linux将文件分为7个种类
- 普通文件 (-) :
文本文件 和 二进制文件
- 目录文件 (d) :
能vi打开,但是需要特殊api来读写的文件
- 字符设备文件 (c)
- 块设备文件 (b) :
文件系统虚拟出来的文件,如/dev /sys /proc,大多数不 直接读写,用特殊api,驱动时用
- 管道文件 (p) :
管道通信
- 套接字文件 (s) :
socket
- 符号链接文件 (l):
软链接、硬链接
二、文件属性
1、文件属性概述
Linux 文件的属性主要包括:文件的节点、种类、权限模式、链接数量、所归属的用户和用户组、最近访问或修改的时间等内容。文件属性示例如下:
第一字段:文件类型和权限
第二字段:硬链接数
第三字段:所属用户
第四字段:所属用户组
第五字段:文件大小
第六字段:最后访问或修改时间
第七字段:文件名
2、文件属性函数
Linux 命令: stat xxx.c获取文件属性
stat指令是根据stat这个api得到的应用
-
2.1、stat
int stat(const char *path, struct stat *buf);
path:文件的路径,buf:指向存储文件信息的数据结构的指针
-
2.2、fstat
int fstat(int fd, struct stat *buf);
fd:文件描述符,buf:指向存储文件信息的数据结构的指针
-
2.3、lstat
int lstat(const char *path, struct stat *buf);
path:文件的路径,buf:指向存储文件信息的数据结构的指针
用于查阅链接文件的文件属性
-
2.4stat函数三种形态:
stat : 不打开文件,读文件属性(在磁盘中读)
fstat : 若文件打开,读已经打开的文件属性(效率更高,在内存读)
lstat : 读符号链接文件本身的属性(stat、fstat会追溯指向文件的属性)
3、函数原型和头文件
#include <sys/types.h> #include <sys/stat.h> #include <unistd.h>
int stat(const char *path, struct stat *buf); int fstat(int fd, struct stat *buf); int lstat(const char *path, struct stat *buf); 成功返回0,错误返回-1,并设置errno全局变量 |
- 举例详解结构体stat原型
struct stat { dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* inode number */ mode_t st_mode; /* protection */ nlink_t st_nlink; /* number of hard links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ dev_t st_rdev; /* device ID (if special file) */ off_t st_size; /* total size, in bytes */ blksize_t st_blksize; /* blocksize for file system I/O */ blkcnt_t st_blocks; /* number of 512B blocks allocated */ time_t st_atime; /* time of last access */ time_t st_mtime; /* time of last modification */ time_t st_ctime; /* time of last status change */ }; |
结构体各个成员表示含义:
st_dev:文件所在磁盘的磁盘的ID号
st_ino:节点编号
st_mode:描述文件的类型和权限
st_nlink:硬链接的数量
st_uid:文件属于用户的ID
st_gid:文件所属用户组ID
st_rdev:如果是设备文件则是设备ID号
st_size:文件大小
st_blksize:文件内容对应的块的大小
st_blocks:文件内容对应得块数量
time_t st_atime; //文件最后被访问的时间
time_t st_mtime; //文件内容最后被修改的时间
time_t st_ctime; //文件状态改变时间
4、测试stat函数部分功能(具体函数头文件包含,用man命令)
E:\Linux\3.AppNet\2.fileproperty\3.2.1
#define Name "1.txt" int main(void) { int dout=-1; struct stat buf; memset(&buf,0,sizeof(buf));//memset后buf中全是0 dout=stat(Name,&buf);//stat后buf就有内容了 if(dout<0)//失败 { perror("stat error"); exit(-1); } //成功获取了stat结构体,从中打印出各种文件属性信息 printf("st_nlink=%d.\n",buf.st_nlink); printf("st_size=%d.\n",buf.st_size); printf("st_mode=%d.\n",buf.st_mode); return 0; } |
测试程序中调用stat函数和直接在ubuntu中使用stat命令打印信息相同。
5、stat函数的应用案例 E:\Linux\3.AppNet\2.fileproperty\3.2.2
-
用代码判断文件类型
文件的文件类型和文件权限存在于文件属性数据结构中的st_mode成员。为了使用st_mode检查文件类型,POSIX标准定义了如下的宏:
S_ISREG(m) is it a regular file? S_ISDIR(m) directory? S_ISCHR(m) character device? S_ISBLK(m) block device? S_ISFIFO(m) FIFO (named pipe)? S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.) S_ISSOCK(m) socket? (Not in POSIX.1-1996.) |
譬如S_ISREG宏返回值是1表示这个文件是一个普通文件,如果文件不是普通文件则返回值是0.
具体用法如下:
#if 1 // 判断这个文件类型 char result; if(S_ISREG(buf.st_mode))//普通文件 (-) { result='-'; printf("result = %c\n", result); } else if(S_ISDIR(buf.st_mode))//目录文件 (d) { result='d'; printf("result = %c\n", result); } else if(S_ISCHR(buf.st_mode))//字符设备文件 (c) { result='c'; printf("result = %c\n", result); } else if(S_ISBLK(buf.st_mode))//块设备文件 (b) : { result='b'; printf("result = %c\n", result); } else if(S_ISFIFO(buf.st_mode))//管道文件 (p) : { result='p'; printf("result = %c\n", result); } else if(S_ISLNK(buf.st_mode))//符号链接文件 (l): { result='l'; printf("result = %c\n", result); } else if(S_ISSOCK(buf.st_mode))//套接字文件 (s) : { result='s'; printf("result = %c\n", result); }
#endif |
-
用代码判断文件权限设置
st_mode中还包含了文件的权限信息
S_IFMT 0170000 bit mask for the file type bit fields S_IFSOCK 0140000 socket S_IFLNK 0120000 symbolic link S_IFREG 0100000 regular file S_IFBLK 0060000 block device S_IFDIR 0040000 directory S_IFCHR 0020000 character device S_IFIFO 0010000 FIFO S_ISUID 0004000 set UID bit S_ISGID 0002000 set-group-ID bit (see below) S_ISVTX 0001000 sticky bit (see below) S_IRWXU 00700 mask for file owner permissions//用户权限掩码 S_IRUSR 00400 owner has read permission S_IWUSR 00200 owner has write permission S_IXUSR 00100 owner has execute permission S_IRWXG 00070 mask for group permissions//组权限掩码 S_IRGRP 00040 group has read permission S_IWGRP 00020 group has write permission S_IXGRP 00010 group has execute permission S_IRWXO 00007 mask for permissions for others //掩码 S_IROTH 00004 others have read permission S_IWOTH 00002 others have write permission S_IXOTH 00001 others have execute permission |
具体用法如下:
#if 1 // 文件权限测试 unsigned char ownrd,ownwt,ownet,grprd,grpwt,grpet,othrd,othet,othwt; if(buf.st_mode & S_IRUSR) ownrd='r'; printf("result = %c\n", ownrd); if(buf.st_mode & S_IWUSR) ownwt='w'; printf("result = %c\n", ownwt); if(buf.st_mode & S_IXUSR) ownet='x'; printf("result = %c\n", ownet); if(buf.st_mode & S_IRGRP) grprd='r'; printf("result = %c\n", grprd); if(buf.st_mode & S_IWGRP) grpwt='w'; printf("result = %c\n", grpwt); if(buf.st_mode & S_IXGRP) grpet='x'; printf("result = %c\n", grpet); if(buf.st_mode & S_IROTH) othrd='r'; printf("result = %c\n", othrd); if(buf.st_mode & S_IWOTH) othwt='w'; printf("result = %c\n", othwt); if(buf.st_mode & S_IXOTH) othet='x'; printf("result = %c\n", othet); #endif |
-
access函数检查权限设置E:\Linux\3.AppNet\2.fileproperty\3.2.3
ccess函数可以测试得到当前执行程序的那个用户在当前那个环境下对目标文件是否具有某种操作权限。
#define name "2.txt" int main(void) { int ret=-1; ret=access(name,F_OK); if(ret<0) { printf("文件不存在\n"); return -1; } else { printf("文件存在 "); } ret=access(name,R_OK); if(ret<0) { printf("不可读\n"); return -1; } else { printf("可读 "); } ret=access(name,X_OK); if(ret<0) { printf("不可写\n"); return -1; } else { printf("可写\n"); } return 0; } |
-
chown修改文件/目录所属拥有者和组。(改文件的属主与属组)
#chown guest:guest a.txt
#chown -R guest /home/berry (把berry文件下的所有文件都改成guest这个组)
-
chgrp是修改文件或目录所属组。(只是更改文件的属组)
#chgrp -R guest /var/tmp/f.txt
#chgrp - R root /home/berry/file/a.txt
-
chmod修改文件的各种权限属性。chmod命令只有root用户才有权利去执行修改。
#chmod 777 /home/berry
#chmod u+x /home/berry
操作对象who可是下述字母中的任一个或者它们的组合:
- u 表示“用户(user)”,即文件或目录的所有者。
- g 表示“同组(group)用户”,即与文件属主有相同组ID的所有用户。
- o 表示“其他(others)用户”。
- a 表示“所有(all)用户”。它是系统默认值。
三、目录文件函数 E:\Linux\3.AppNet\2.fileproperty\3.2.4
Linux中目录也是文件,目录操作函数为标准IO库函数。
1、opendir与readdir函数
-
主要函数如下:
#include <sys/types.h> #include <dirent.h>
DIR *opendir(const char *name); DIR *fdopendir(int fd);
成功返回一个指向目录流的指针,失败返回NULL,并且设置errno全局变量。 |
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
成功返回一个指向目录 dirent结构的指针,如果到达目录流结尾或错误返回NULL。 |
读取目录文件 opendir函数打开一个目录后,得到一个DIR指针给readdir使用 readdir返回一个struct dirent(dir entry)类型的指针,指向一个结构体变量,记录着目录中的一个子文件
readdir调用一次,只能读取一个文件。要读取n个文件必须n次调用。
readdir函数内部会记忆哪个目录项已经被读过了哪个还没读,所以多次调用后不会重复返回已经返回过的目录项。
当readdir函数返回NULL时就表示目录中所有的目录项已经读完了
-
目录文件信息结构体dirent:
struct dirent { ino_t d_ino; /* inode number */ off_t d_off; /* offset to the next dirent */ unsigned short d_reclen; /* length of this record */ unsigned char d_type; /* type of file; not supported by all file system types */ char d_name[256]; /* filename */ }; |
-
具体用法如下:
int main(int argc, char **argv) { DIR *pDir = NULL; struct dirent * pEnt = NULL; unsigned int cnt = 0; if (argc != 2) { printf("usage: %s dirname\n", argv[0]); return -1; } pDir = opendir(argv[1]); if (NULL == pDir) { perror("opendir"); return -1; } while (1) { pEnt = readdir(pDir); if(pEnt != NULL) { // 还有子文件,在此处理子文件 printf("name:[%s] ,", pEnt->d_name); cnt++; if (pEnt->d_type == DT_REG) { printf("是普通文件\n"); } else { printf("不是普通文件\n"); } } else //没有子文件,跳出循环 { break; } }; printf("总文件数为:%d\n", cnt); return 0; } |
sudo apt-get install gparted
2、目录操作函数scandir
-
函数原型
#include <dirent.h>
int scandir(const char *dirp,//目录名 struct dirent ***namelist,//返回目录列表 int (*filter)(const struct dirent *),//过滤目录,NULL不过滤 int (*compar)(const struct dirent **,const struct dirent **));//排序返回目录,NULL不排序 成功返回目录内文件的数量,失败返回-1。 |
-
遍历目录函数:
int traverse_dir(const char *path)
{ unsigned int cnt = 0; struct dirent **dent;
unsigned int i = 0;
i = scandir(path, &dent, NULL, NULL);
while(*dent)
{
printf("name:[%s] \n", (*dent)->d_name);
dent++; cnt++;
} printf("总文件数为:%d\n", cnt); return 0;
} |
int main(int argc, char **argv) { if (argc != 2) { printf("usage: %s dirname\n", argv[0]); return -1; } traverse_dir(argv[1]); } |