1.获取文件属性
创建一个名为-a的文件,touch -a是创建不了的,因为系统会把-a当作一个选项。任何命令+--表示当前命令选项完毕。touch -- -a成功。touch ./a也是可以的,rm -a不行但是rm ./-a可以。
stat();fstat();lstat();
int stat(const char *path,struct stat *buf);通过路径
面对符号链接时获取的是所指向目标文件的属性
int fstat(int fd,struct stat *buf);通过文件描述符
int lstat(const char *path,struct stat *buf);通过路径
面对符号链接时,获取的是符号链接文件的属性
将属性信息传到结构体buf中去。成功返回0,失败返回-1并生成errno。
struct stat{
dev_t st_dev; //包含当前设备ID名
ino_t st_ino; //inde号,一个文件一个唯一的标号
mode_t st_mode; //权限信息 (16位整形数)基本位9位(777*3)粘住位 U+s位 g+s位
nlink_t st_nlink; //硬连接数
uid_t st_uid; //userID
gid_t st_gid;//groupID
dev_t st_rdev;//当前拿到的是device,则是设备号
off_t st_size; //文件大小 (以字节为单位)
blksize_t st_blksize;//block的大小
blkcnt_t st_blocks;//当前文件占了多少512b的快
time_t st_atimes;//最后一次读的时间
time_t st_mtime;//最后一次写的时间
time_t st_ctime;//最后一次亚数据修改的时间
};
注意 st_size!=st_blksize*st_blocks;
st_size只是文件属性,并不是在磁盘上所占空间。空洞文件就是文件属性很大但是磁盘上所占空间非常小。st_blksize*st_blocks是文件真正在磁盘上占的空间。
下面我们创建一个空洞文件
#include "main.h"
#define _FILE_OFFSET_BITS 64
int main(int argc,char ** argv)
{
if(argc<2)
{
fprintf(stderr,"Usage:%s,<destfile>",argv[0]);
exit(1);
}
int fd;
off_t len;
fd=open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0600);
if(fd<0)
{
perror("open()");
exit(1);
}
len=lseek(fd,5LL*1024*1024*1024-1LL,SEEK_SET);
if(len<0)
{
perror("lseek()");
exit(1);
}
write(fd,"",1);
close(fd);
exit(0);
}
从这里我们可以看到文件大小为5G但是在磁盘上面的空间其实是8K
lseek(fd,5LL*1024*1024*1024-1LL);为什么要加单位呢,因为没有单位的值是没有意义的,当什么单位也没有,系统会默认给一个单位,当前默认为32位的有符号整数。如果不加单位会有溢出Waring但是已经是err,gcc编译器里面大部分waring就是err。我们要调试到除了一些我们能解释通的警告,没有其他警告。
cp命令也可证明这一点,我们使用cp命令复制上面程序生成的文件,只需要几秒,但是我们都知道你复制个几个G的文件是需要十几秒或者几十秒的。
执行过程:读一块,写一块,但是在写之间要进行检查,检查是不是空字符,如果是,那就记录不下,不写,再读一块写一块,写之前检查一下。如果还是那就还记录,直到读完,到现在还没有写一次,最后一下子在文件中一下子扯了你记录那么大的空间。
在linux中并不是文件有多大,在磁盘里面就有这么大的空间。window下是这样的。
有一个命令叫stat
#include "main.h"
#define _FILE_OFFSET_BITS 64
static off_t flen(const char* fname)
{
struct stat statres;
if(stat(fname,&statres)<0)
{
perror("stat()");
exit(1);
}
return statres.st_size;
}
int main(int argc,char ** argv)
{
if(argc<2)
{
fprintf(stderr,"Usage : %s,<destfile>",argv[0]);
exit(1);
}
long long len;
len=flen(argv[1]);
printf("文件大小为:%lld\n",len);
exit(0);
}
-rwxrwxrwx
第一个位置表示文件类型,dcb-lsp
d direction目录文件
c charcter special file字符设备文件
b block special file块设备文件
- regular file常规文件
l symbol link链接文件(符号链接文件)
s socket网络套接字socket文件
p pipe管道(特指命名管道,匿名管道在磁盘上看不到)
程序:识别文件类型
#include "main.h"
static int fType(const char *Fname);
static char *ftype(const char* FNAME)
{
struct stat *statres=NULL;
char* mode=NULL;
mode=malloc(sizeof(char));
*mode='-';
static char mode1='0';
statres=malloc(sizeof(struct stat));
if(stat(FNAME,statres)<0)
{
perror("stat()");
exit(1);
}
if(S_ISREG(statres->st_mode))
{
return mode ;
}
return &mode1;
}
/*
返回值类型可以是char 我这样写是变复杂了。
*/
int main(int argc,char **argv)
{
if(argc<2)
{
fprintf(stderr,"Usage : %s <destfile>",argv[0]);
exit(1);
}
printf("文件类型为:%c\n",*ftype(argv[1]));
printf("文件类型位:%c\n",fType(argv[1]));
exit(0);
}
static int fType(const char *Fname)
{
struct stat statres;
if(stat(Fname,&statres)<0)
{
perror("stat()");
exit(1);
}
if(S_ISREG(statres.st_mode))
return '-';
else
return '?';
}
得到文件权限的方法有两种,一种是通过宏来判断,也就是上面这种,虽然S_ISREG看着是一个函数但是它是通过带参宏来定义的。
另外一种是通过位图或和与来判断,其实就是S_ISREG的原型。
2.文件的访问权限
文件的范文权限是一个16位的位图,用于表示文件类型,文件的访问权限,及特殊权限位。
3.umask
在你创建文件时,给一个权限,把你给出的权限跟&~umsk,如果没给就是0666&~umask。
umask可以进行修改,命令输入umask +你想修改成什么样的权限。
其实umask命令使用umask函数封装的。在进程中可以用umask函数调整权限,作用是防止产生权限过松的文件。
4.文件权限的更改/管理
chmod chmod 权限 文件名
fchmod
int chmod(const char *path,mode_t mode);
int fchmod(int fd,mode_t mode);
5.粘住位:t位
原本时给某一个可执行的二进制命令设置当前t位,设置t位是为了把某一个命令的使用痕迹进行保留,为了下次转载这个模块比较快。
现在常用数据块就会留在内存里面。
现在常用给目录设置t位。