在Linux下进行C/C++编程,主要通过以下三个系统调用来获取文件(普通文件,目录,管道,socket,字符,块等)属性。
头文件“#include <sys/stat.h>”
(1) //通过文件名称获取文件属性 int stat(const char *restrict pathname, struct stat *restrict buf);
(2) //通过文件描述符获取文件属性 int fstat(int filedes, struct stat *buf);
(3) //通过符号文件名称获取文件属性 int lstat(const char *restrict pathname, struct stat *restrict buf);
返回值(三个函数一样)成功:0 失败:-1
三个系统调用的区别:
1. fstat接受的第一个参数是“文件描述符”,stat和lstat是“文件全路径”,文件描述符需要用调用open之后才能得到,文件全路经直接写即可;
2. lstat获取的是该符号链接本身的信息;而stat获取的是该链接指向的文件的信息;
这三个系统调用都依赖一个重要的结构体struct stat
stat结构体:
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; //文件所有者
gid_t st_gid; //文件所有者对应的组
off_t st_size; //普通文件,对应的文件字节数
time_t st_atime; //文件最后被访问的时间
time_t st_mtime; //文件内容最后被修改的时间
time_t st_ctime; //文件状态改变时间
blksize_t st_blksize; //文件内容对应的块大小
blkcnt_t st_blocks; //伟建内容对应的块数量
};
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
int main(int argc,char *argv[])
{
if (argc < 2)
{
fprintf(stderr,"usage : %s\n",strerror(errno));
exit(1);
}
struct stat buf;
if(stat(argv[1],&buf) < 0)
{
fprintf(stderr,"stat failed : %s\n",strerror(errno));
exit(1);
}
printf("%s length :%ld\n",argv[1],buf.st_size);
return 0;
}
判断文件类型的函数:
Linux中七种文件和七种宏: 普通文件(regular file) S_ISREG()
目录文件(directory file) S_ISDIR()
块特殊文件(block special file) S_ISBLK()
字符特殊文件(charactor special file) S_ISCHR()
FIFO(named pipe) S_ISFIFO() //管道文件
套接字(socket) S_ISSOCK()
符号链接(symbolic link) S_ISLNK() //软链接文件
创建软链接文件$ln -s /etc/passwd ./123.so
创建硬链接文件$ln /etc/passwd a
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
//file_type.c
int main(int argc,char *argv[])
{
if (argc < 2)
{
fprintf(stderr,"usage : %s\n",strerror(errno));
exit(1);
}
struct stat buf;
if (lstat(argv[1],&buf) < 0)
{
fprintf(stderr,"stat failed %s\n",strerror(errno));
exit(1);
}
mode_t mode = buf.st_mode;
if (S_ISREG(mode))
{
printf("%s 是普通文件\n",argv[1]);
}
else if(S_ISDIR(mode))
{
printf("%s 是目录文件\n",argv[1]);
}
else if(S_ISBLK(mode))
{
printf("%s 是块设备文件\n",argv[1]);
}
else if(S_ISLNK(mode))
{
printf("%s 是符号链接文件\n",argv[1]);
}
return 0;
}
------------------------------------------------------------------------------------------------------------------------------------------------------------
文件权限 9种访问权限位:
S_IRUSR,S_IWUSR,S_IXUSR
S_IRGRP,S_IWGRP,S_IXGRP
S_IROTH,S_IWOTH,S_IXOTH
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc,char *argv[])
{
if(argc < 2)
{
fprintf(stderr,"usage : %s\n",strerror(errno));
exit(1);
}
struct stat st;
stat(argv[1],&st);
mode_t mode = st.st_mode;
if(mode & S_IRUSR)
{
printf("r");
}else
{
printf("-");
}
if(mode & S_IWUSR)
{
printf("w");
}else
{
printf("-");
}
if(mode & S_IXUSR)
{
printf("x");
}else
{
printf("-");
}
if(mode & S_IRGRP)
{
printf("r");
}else
{
printf("-");
}
if(mode & S_IWGRP)
{
printf("w");
}else
{
printf("-");
}
if(mode & S_IXUSR)
{
printf("x");
}else
{
printf("-");
}
if(mode & S_IROTH)
{
printf("r");
}else
{
printf("-");
}
if(mode & S_IWOTH)
{
printf("w");
}else
{
printf("-");
}
if(mode & S_IXGRP)
{
printf("x");
}else
{
printf("-");
}
printf("\n");
return 0;
}
access函数作用:用于验证实际用户能否访问一个给定的文件
#include <unistd.h>
Int access(const char *pathname,int mode);
返回:成功返回0,出错返回-1。
mode 取值:
R_OK测试读权限
W_OK测试写权限
X_OK测试执行权限
F_OK测试文件是否存在
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main(int argc,char *argv[])
{
if(argc < 2)
{
fprintf(stderr,"usage : %s\n",strerror(errno));
exit(1);
}
if(access(argv[1],R_OK) == 0)
{
printf("%s 该文件可读\n",argv[1]);
}
else
{
printf("%s 该文件不可读\n",argv[1]);
}
return 0;
}
权限位的由来
666 //创建文件的原始权限
002 //掩码值 $umask
000 000 010
111 111 101
& 110 110 110
-----------------
110 110 100
664
#include <fcntl.h>
//开辟进程,创建文件
int main(void)
{
creat("a.txt",0644);
return 0;
}
umask函数
#include <sys/stat.h>
mode_t umask(mode_t mode);
返回:以前的文件模式创建屏蔽字
chmod,fchmod函数
#include <sys/stat.h>
int chmod(const char *pathname,mode_t mode);
int fchmod(int fields,mode_t mode);
返回:成功返回0,出错返回-1。
想要改变一个文件的权限位,需满足条件:
进程的有效用户ID必须等于文件的所有者ID
进程具有超级用户权限
mode 取值:
S_ISUID,S_ISGID,S_ISVTX
S_IRWXU,S_IRUSR,S_IWUSR,S_IXUSR
S_IRWXG,S_IRGRP,S_IWGRP,S_IXGRP
S_IRWXO,S_IROTH,S_IWOTH,S_IXOTH
以上参数按位或
chown,fchown,lchown函数
#include <unistd.h>
Int chown(const char *pathname,uid_t owner,gid_t group);
Int fchown(int fieldes,uid_t owner,gid_t group);
Int lchown(const char *pathname,uid_t owner,gid_t group);
返回: 成功返回0,出错返回-1。
限制:
超级用户进程能更改该文件的用户ID
非超级用户满足如下条件可修改文件的组ID
进程拥有该文件
参数owner等于-1或文件的用户ID,并且参数group等于进程的有效组ID或进程 的附加组ID之一
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
system("id");
system("ls -l a.txt");
if(chown("a.txt",-1,108) < 0)
{
printf("change gid failed\n");
}
else
{
printf("chage gid success\n");
}
system("ls -l a.txt");
return 0;
}
文件截断函数
#include <unistd.h>
Int truncate(const char *pathname,off_t length);
Int ftruncate(int fieldes,off_t lenght);
返回:成功返回0,出错返回-1。
#include <stdio.h>
#include <unistd.h>
int main(void)
{
truncate("a.txt",10);
return 0;
}
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
文件系统结构;