目录与文件
获取文件属性
- stat 通过文件路径获取属性
- fstat 通过文件描述符获取属性
- lstat 面对符号链接文件时,获取的是符号链接文件的属性,而stat获取的是所指目标文件的属性
- int stat(const char *pathname, struct stat *statbuf);
- int fstat(int fd, struct stat *statbuf);
- int lstat(const char *pathname, struct stat *statbuf);
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* Inode number */
mode_t st_mode; /* File type and mode 权限 */
nlink_t st_nlink; /* Number of hard links */
uid_t st_uid; /* User ID of owner */
off_t st_size; /* Total size, in bytes */
blksize_t st_blksize; /* Block size for filesystem I/O 一块扇区的大小*/
blkcnt_t st_blocks; /* Number of 512B blocks allocated 所占扇区的个数*/
...
}
文件所占磁盘大小= st_blksize * st_blocks (不等于st_size)
static off_t flen(const char *fname){
struct stat statres;
if (stat(fname,&statres) < 0) {
perror("tata()");
exit(1);
}
return statres.st_size;
}
int main(int argc,char **argv)
{
if (argc < 2) {
fprintf(stderr,"Usage...\n");
exit(1);
}
long len = flen(argv[1]);
printf("st_size = %ld\n",len);
exit(0);
}
空洞文件
5G大小
int main(int argc,char **argv)
{
if (argc < 2) {
fprintf(stderr,"Usage...\n");
exit(1);
}
int fd = open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0600);
if (fd < 0) {
perror("open()");
exit(1);
}
long err = lseek(fd,5LL*1024LL*1024LL*1024LL-1LL,SEEK_SET);
if (err == -1) {
perror("lseek");
exit(1);
}
write(fd,"",1);
return 0;
}
文件属性
7种文件类型 `
- b 块设备文件
- c 字符设备文件
- d 目录
- - 常规文件
- l 符号链接文件
- s socket文件(网络套接字文件)
- p 匿名管道文件(不可见)
宏:S_ISREG、S_ISDIR、S_ISSOCK…
static int ftype(const char* fname) {
if (stat(fname,&statres) < 0) {
perror("rstat()");
exit(1);
}
if (S_ISREG(statres.st_mode)) {
return '-';
}else if (S_ISDIR(statres.st_mode)) {
return 'd';
}else{
return '?';
}
文件访问权限
-
st_mode
16位位图,用于表示文件类型、文件访问权限、特殊权限位
_ _ _ (7种文件类型) _ t(粘住位) _ g+s _ u+s _ _ _ user _ _ _ group _ _ _ other共15位 -
umask:防止产生权限过松的文件
文件权限的更改与管理
- int chmod(const char *pathname, mode_t mode);
- int fchmod(int fd, mode_t mode); 修改一个已经成功打开的文件
- chmod (命令)
- chmod a+x ??x ??x ??x
- chmod u+x ??x ??? ???
- chmod g+x ??? ??x ???
- chmod o+x ??? ??? ??x
文件系统
(文件或数据的存储格式)FAT、UFS
FAT
(实质)静态单链表
UFS
…|磁盘分区|…
/ \
…|柱面组|…
/ \
| 描述性信息 | inode位图 | 数据块位图 | inode | 数据块 |
inode 结构体包括:stat、亚数据信息、隐藏内容、数据库指针
数据块指针:直接数据块指针、1级、2级、3级间接数据块指针
缺陷:不善于管理小文件、大量小文件时inode满了,数据块可能大量空白
硬链接 符号连接
-
目录文件:文件名保存在目录文件中
| 目录项 | 目录项 | 目录项 |…
/inode 、filename…\ -
int link(const char *oldpath, const char *newpath);
创建硬链接
其实就是在目录文件中创建个目录项
限制:与源文件名不同,inode相同。不能给分区建立硬链接、不能给目录建立硬链接 -
符号链接:相当于windows下的快捷方式,block=0
优点:可以跨分区、可以给目录建立 -
int unlink(const char *pathname);
删除一个文件的硬连接 但并不是删除文件
只有当一个文件的硬链接数为0 且没有进程占用该文件时一个文件才有被删除的可能(数据可被随意改写)
分析目录/读取目录内容
- int glob(const char *pattern, int flags, int (*errfunc) (const char *epath, int eerrno), glob_t *pglob);
- void globfree(glob_t *pglob);
- glob 解析模式/通配符
errfunc 保存当前出错路径和原因
errno GLOB_NOSPACE 、GLOB_ABORTED、GLOB_NOMATCH
typedef struct {
size_t gl_pathc; /* Count of paths matched so far 数量 */
char **gl_pathv; /* List of matched pathnames. 路径名,类似与main argv 字符指针数组的首地址 */
size_t gl_offs; /* Slots to reserve in gl_pathv. */
} glob_t;
glob解析路径
static void Glob(){
glob_t globres;
int err = glob(PAT,0,&errfunc,&globres);
if (err) {
printf("Error code = %d\n",err);
}
for (i = 0; i < globres.gl_pathc; i++) {
puts(globres.gl_pathv[i]);
}
globfree(&globres);
}
其他目录操作函数
- opendir()
- closedir()
- readdir()
- seekdir()
- telldir()
解析路径
static void PathParse(char *Path) {
DIR *dp;
struct dirent *cur;
dp = opendir(Path);
if (dp == NULL) {
perror("opendir");
exit(1);
}
while((cur = readdir(dp)) != NULL) {
fprintf(stdout,"%s ",cur->d_name);
fprintf(stdout,"type:%d ",cur->d_type);
}
closedir(dp);
}
时间戳
-
time()
time_t time(time_t *tloc); 从kernel中取出时间戳(以秒为单位) -
localtime()
struct tm *localtime(const time_t *timep); 将时间戳转换为struct_tm
本地时间
struct tm {
int tm_sec; /* Seconds (0-60) */
int tm_min; /* Minutes (0-59) */
int tm_hour; /* Hours (0-23) */
...
};
-
mktime()
time_t mktime(struct tm *tm); 指定一块缓冲区,将 struct_tm结构体转换为时间戳,还可以检查是否溢出 -
strftime()
size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);格式化时间字符串
time_t stamp;
time(&stamp);
//stamp = time(NULL);
struct tm *tm;
tm = localtime(&stamp);
strftime(buf,BUFSIZE,"%Y-%m-%d",tm);
puts(buf);
实现每秒钟打印一行时间戳
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#define BUFSIZE 1024
int main()
{
char fmttime[BUFSIZ];
char buf[BUFSIZE];
char res[BUFSIZE];
int count = 0;
FILE *fptr;
fptr = fopen("./log","a+");
if (fptr == NULL) {
perror("fopen()");
exit(1);
}
while(fgets(buf, BUFSIZE, fptr) != NULL) {
count++;
}
while (1){
time_t stamp;
stamp = time(NULL);
struct tm *struct_tm;
struct_tm = localtime(&stamp);
strftime(fmttime,BUFSIZE,"%Y-%m-%d %H:%M:%S",struct_tm);
fprintf(fptr,"%d %s\n",++count,fmttime);
fflush(fptr);
sleep(1);
}
fclose(fptr);
exit(0);
}