
#include <unistd.h>
#include<stdio.h>
#inlcude<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
//int open(char*name,mode)
//如果返回值小于0,则表示打开文件或者创建文件失败
int maim(){
int num=3; //系统默认打开stdin,stdout,stderr;所以打开的文件的下标从3开始
char filename[128]={0}//定义文件名
while(1){
sprinft(filename,"temp_%04d",num++);
int fd=open(filename,O_RDNOLY|O_CREAT,0666);
if(fd<0){
perror("open err"); //打印警告
break;
}
}
printf("num==%d\n",num);
return 0;
}
//输出: num==1023
//需要在程序结束后再关闭所有的文件,否则程序会出现死循环
获取文件信息的函数,文化信息存放在参数buf中
#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);

hello.hard是hello的硬链接,两者指向同一个块。
vim ../ #查看目录文件

目录项存放了该目录下的文件名,inode,读条大小
参数:
pathname :文件名
struct stat *buf(传入参数):struct stat sb;&sb
传入类型参数:需要我们传入参数,由函数完成参数的内容填充
返回值:
成功返回0,失败返回-1;
#teststat.c
#include <unistd.h>
#include<stdio.h>
#inlcude<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
int main(int agrc,char*argv[]){
struct stat sb;
stat(argv[1],&sb);//sb的值由函数填充
return 0;
}
int main(int argc,char*argv[]){
struct stat sb;
stat(argv[1],&sb);
return 0;
}
gcc teststat -o teststat.out
./teststat.out 文件名 #获得该文件的信息(主要信息存放在struct stat*sb中);
int stat(const char *path, struct stat *buf);
stat结构体的内容
st_mode中包含了文件的主要信息,st_ino包含了文件连接数
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
//获取文件数据
struct stat sb; //struct stat*sb;
//传入型数据类型
stat(argv[1],&sb); //文件信息都存储在sb中。
//输出文件信息,解析属性信st_mode,st_uid,st_gid,st_atime,st_ino
char stmode[11]={0}; //文件类型--用户权限---用户组权限---其他人权限,最后一个位置为\n
memset(stmode,'-',sizeof(stmmode)); //初始化
文件类型相关的宏(st_mode)

文件权限宏
if(S_ISREG(sb.st_mode)) stmode[0]='-'; //is it a regular file?
if(S_ISDIR(sb.st_mode)) stmode[0]='d'; //directory?
if(S_ISCHR(sb.st_mode)) stmode[0]='c'; //character device?
if(S_ISBLK(sb.st_mode)) stdmode[0]='b'; //block device?
if(S_ISFIFO(sb.st_mode)) stdmode[0]='p'; //FIFO (named pipe)?
if(S_ISLNK(sb.st_mode)) stdmode[0]='l';//symbolic link? (Not in POSIX.1-1996.)
if(S_ISSOCK(sb.st_mode)) stdmode[0]='s';//socket? (Not in POSIX.1-1996.)
//解析文件权限
//解析文件拥有者权限位
if(sb.st_mode&S_IRUSR) stdmode[1]='r';
if(sb.st_mode&S_IWUSR) stdmode[2]='w';
if(sb.st_mode&S_IXUSR) stdmode[3]='x';
//解析文件所有组权限位
if(sb.st_mode&S_IRGRP) stdmode[4]='r';
if(sb.st_mode&S_IWGRP) stdmode[5]='w';
if(sb.st_mode&S_IXGRP) stdmode[6]='x';
if(sb.st_mode&S_IROTH) stdmode[7]='r';
if(sb.st_mode&S_IWOTH) stdmode[8]='w';
if(sb.st_mode&S_IXOTH) stdmode[9]='x';
stdmode[10]='\0';
int num=sb.st_nlink;
//使用struct passwd* getpwuid(uid_t uid) 获得用户名,需要传入uid
//使用struct group* getgrgid(gid_t gid) 获得组名,需要传入gid
//stat结构体已经包含了两者
struct passwd*sbwd=(struct passwd*)getpwuid(sb.st_uid);
struct group* sbgrp=(struct group*)getgrgid(sb.st_git);


//获取时间:struct tm *localtime(const time_t *timep);对应stat结构体中的st_atime
struct tm*sttime=localtime(&sb.st_atim.tv_sec);

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#include<pwd.h>
#include<time.h>
#include<string.h>
int main(int argc,char*argv[]){
if(argc!=2){
printf("./a.out filename\n");
return -1;
}
//获取文件数据
struct stat sb;
//传入型数据类型
stat(argv[1],&sb); //文件信息都存储在sb中。
//输出文件信息,解析属性信息stat_mode,uid,gid,tim
//获取文件类型
char stmode[11]={0}; //文件类型--用户权限---用户组权限---其他人权限---连接数
//通过宏判断文件的类型
memset(stmode,'-',sizeof(stmode));
if(S_ISREG(sb.st_mode)) stmode[0]='-'; //is it a regular file?
if(S_ISDIR(sb.st_mode)) stmode[0]='d'; //directory?
if(S_ISCHR(sb.st_mode)) stmode[0]='c'; //character device?
if(S_ISBLK(sb.st_mode)) stmode[0]='b'; //block device?
if(S_ISFIFO(sb.st_mode)) stmode[0]='p'; //FIFO (named pipe)?
if(S_ISLNK(sb.st_mode)) stmode[0]='l';//symbolic link? (Not in POSIX.1-1996.)
if(S_ISSOCK(sb.st_mode)) stmode[0]='s';//socket? (Not in POSIX.1-1996.)
//解析文件权限
//解析文件拥有者权限位
if(sb.st_mode&S_IRUSR) stmode[1]='r';
if(sb.st_mode&S_IWUSR) stmode[2]='w';
if(sb.st_mode&S_IXUSR) stmode[3]='x';
//解析文件所有组权限位
if(sb.st_mode&S_IRGRP) stmode[4]='r';
if(sb.st_mode&S_IWGRP) stmode[5]='w';
if(sb.st_mode&S_IXGRP) stmode[6]='x';
if(sb.st_mode&S_IROTH) stmode[7]='r';
if(sb.st_mode&S_IWOTH) stmode[8]='w';
if(sb.st_mode&S_IXOTH) stmode[9]='x';
stmode[10]='\0';
//解析连接数
//使用struct passwd* getpwuid(uid_t uid) 获得用户名,需要传入uid
//使用struct group* getgrgid(gid_t gid) 获得组名,需要传入gid
//获取时间:struct tm *localtime(const time_t *timep);对应stat结构体中的st_atime
struct tm*sttime=localtime(&sb.st_atim.tv_sec);
char timebuf[20]={0};
sprintf(timebuf,"%d月 %d %02d:%02d",sttime->tm_mon,sttime->tm_yday,sttime->tm_hour,sttime->tm_min);
//结构体体类型:指针使用->访问成员;非指针使用.访问成员
printf("%s %2ld %s %s %4ld %s %s\n ",stmode,sb.st_nlink,getpwuid(sb.st_uid)->pw_name,getgrgid(sb.st_gid)->gr_name,sb.st_size,timebuf,argv[1]);
return 0;
}
stat可以穿透链接,找到链接对应的文件;而lstat无法穿透。
//通过stat获取文件大小 也可以使用fseek获取文件大小
struct stat* sb;
stat(filename,sb);
printf("文件大小是:%d",sb->st_size);
作用:判读用户是否具有r,w,x权限;
#include <unistd.h>
int access(const char *pathname, int mode);
/*
参数:
pathname:文件名
mode:R_OK读权限, W_OK写权限,X_OK:执行权限,F_OK:是否存在
返回值:
成功:有权限或者文件存在返回0
失败:返回-1
*/
EXAMPLE:
int main(int argc,char*argv[]){
if(!access(argv[1],W_OK)) printf("有可写权限");
if(!access(argv[1],R_OK)) printf("有可读权限");
return 0;
}
文件截断函数
#include <unistd.h>
#include <sys/types.h>
int truncate(const char *path, off_t length);
/*
参数:
path:文件名
length:文件大小 长度大于原文件就扩展y
返回值:
成功:返回0
失败:返回-1
*/
#include <unistd.h>
int chown(const char *path, uid_t owner, gid_t group);
/*
参数:
path:文件名
owner:用户ID 在文件/etc/passwd可以查询
group:组ID 在文件/etc/group可以查询
返回值:
成功:返回0
失败:返回-1
*/
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
/*
参数:
oldpath:旧文件名
newpath:新文件名
返回值:
成功:0
失败:-1
*/
#include<unistd.h>
char* getcwd(char*buf,size_t size);
/*
buf:传处参数,缓冲区中存放的就是路径
size:缓冲区大小
返回值:
成功:返回目录指针
失败:返回NULL
*/
mypwd.c
#include<stdio.h>
#include<unistd.h>
int main(int argc,char*argv[]){
char buf[128];
getcwd(buf,sizeof(buf));
printf("%s",buf);
return 0;
}
gcc mypwd.c
./a.out
/home/west/dr2
#include<unistd.h>
int chdir(const char*path);
/*
path:进入目录路径指针
返回值:
成功:0
失败:-1
*/
#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *pathname, mode_t mode);
/*
参数:
pathname:创建的目录名
mode:权限 0777|umask 或者 0777&~umask
这里的0777是目录创建的默认初始权限,umask表示权限掩码,最后创建的默认权限位0777|umask
返回值:
成功:0
失败:-1
*/
#include<sys/stat.h>
#include<sys/types.h>
#include<stdio.h>
int main(int argc,char*argv[]){
if(argc!=2){
printf("a.out filename\n");
}
//umask权限掩码
//int mkdir(const char *pathname, mode_t mode)的mode参数是权限
//而目录的默认权限参数是0777,而umask一般是0002
//所以目录的默认参数是0777|umask=0775(八进制数)
mkdir(argv[1],0775);
return 0;
}
gcc mydir.c
./a.out mydir
ls -l
drwxrwxr-x -------------- mydir
#include <unistd.h>
int rmdir(const char *pathname);
/*
pathname:目录名
返回值:
成功:返回0;
失败:返回-1;
*/
模拟实现rmdir指令
//删除空目录
#include<stdio.h>
#include<unistd.h>
int main(int argc,char*argv[]){
if(argc!=2){
printf("a.out filename\n");
return -1;
}
rmdir(argv[1]);
return 0;
}
gcc myrmdir.c
./a.out mydir
#结果为成功删除mydic目录
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
/*
name:目录名
返回值:The opendir() and fdopendir() functions return a pointer to the directory stream.
意思是返回一个目录项信息的的指针,指向目录项信息,主要作为readdir和closedir的参数传入
*/
调用readdir函数时,目录指针自动向下移动
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
//如果读到EOF或者发生错误就返回NULL

文件类型d_type的宏定义

#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
void rewinddir(DIR* dirp); //把目录指针恢复到起始位置
long telldir(DIR*dirp); //获取目录读写位置 返回值为返回当前在目录中的位置
void seekdir(DIR*dirp,long loc); //修改目录读写位置
coutdir.c
#include<stdio.h>
#include<unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include<string.h>
int num=0;
void Dircount(char*dirname){
//打开目录
DIR* dirp=opendir(dirname);
//如果为空
if(dirp==NULL){
printf("opendir err\n");
return ;
}
//循环读目录,如果是普通文件++,如果是目录,递归统计个数
struct dirent*dentp=NULL;
while((dentp=readdir(dirp))!=NULL){ //调用依次readdir函数,目录指针就移动一次。
//如果是目录文件
if(dentp->d_type==DT_DIR){
//如果是.或者是..目录就跳过这两个目录
if(strcmp(".",dentp->d_name)==0||strcmp("..",dentp->d_name)==0){
continue;
}
//如果是其他目录,就递归调用
//进程的工作路径无法直接打开
//使用dirname拼接下一级目录
char tmpname[256]={0};
sprintf(tmpname,"%s/%s",dirname,dentp->d_name);
Dircount(tmpaname);
}
if(dentp->d_type==DT_REG){
num++;
}
}
closedir(dirp);
}
int main(int argc,char*argv[]){
if(argc!=2){
printf("a.out filename\n");
return -1;
}
Dircount(argv[1]);
printf("文件数为:%d",num);
return 0;
}
gcc coutdir.c
./a.out mk
文件数为 4
复制文件描述符,用于备份
#include <unistd.h>
int dup(int oldfd); //返回当前最小可用的文件描述符,并指向oldfd指向的文件
int dup2(int oldfd, int newfd); //输出重定向函数
dup(oldfd):

dup2(oldfd,newfd):

案例
//在代码中执行2次printf("hello world\n");第一次输出到hello文件中,后一次输出到屏幕上
#include<stdio.h>
#include <unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(){
//备份标准输出stdout的描述符
int outfd=dup(1);
//printf默认打开stdin,stdout,stderr
//打开文件hello,返回open文件的文件描述符
int fd=open("hello",O_WRONLY|O_CREAT,0666);
//重定向
dup2(fd,1);//这里的1指的是stdout,把标准输出重定向为hello文件
//这样hello world就输出到hello文件中
printf("hello world\n");
fflush(stdout);
//恢复标准输出指向
dup2(outfd,1);
//输出到屏幕上
printf("hello world\n");
}