一.stat()&fstat()&lstat()
获取文件详细信息(文件大小,硬链接个数,ino编号,文件最近访问和修改时间,文件权限,文件类型,文件所有者ID和组ID)
#include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <time.h> int main(int argc, char *argv[]) { struct stat sb; if (argc != 2) { fprintf(stderr, "Usage: %s <pathname> ", argv[0]); exit(EXIT_FAILURE); } if (stat(argv[1], &sb) == -1) { perror("stat"); exit(EXIT_FAILURE); } printf("File type: "); switch (sb.st_mode & S_IFMT) { case S_IFBLK: printf("block device "); break; case S_IFCHR: printf("character device "); break; case S_IFDIR: printf("directory "); break; case S_IFIFO: printf("FIFO/pipe "); break; case S_IFLNK: printf("symlink "); break; case S_IFREG: printf("regular file "); break; case S_IFSOCK: printf("socket "); break; default: printf("unknow? "); break; } printf("I-node number: %ld ", (long)sb.st_ino); printf("Mode: %lo (octal) ", (unsigned long)sb.st_mode); printf("Link count: %ld ", (long)sb.st_nlink); printf("Ownership: UID=%ld GID=%ld ", (long)sb.st_uid, (long)sb.st_gid); printf("Preferred I/O block size: %ld bytes ", (long)sb.st_blksize); printf("File size: %lld bytes ", (long long)sb.st_size); printf("Blocks allocated: %lld ", (long long)sb.st_blocks); printf("Last status change: %s", ctime(&sb.st_ctime)); printf("Last file access: %s", ctime(&sb.st_atime)); printf("Last file modification: %s", ctime(&sb.st_mtime)); exit(EXIT_SUCCESS); }
运行结果:
yongdaimi@ubuntu:~/Documents/linux-sys/02-文件系统$ ./app empty.txt
File type: regular file
I-node number: 1101565
Mode: 100664 (octal)
Link count: 1
Ownership: UID=1000 GID=1000
Preferred I/O block size: 4096 bytes
File size: 9 bytes
Blocks allocated: 8
Last status change: Thu Feb 1 19:14:03 2018
Last file access: Thu Feb 1 22:26:46 2018
Last file modification: Thu Feb 1 19:14:03 2018
二.access()
检测文件是否存在,是否具有读写和执行权限
#include <unistd.h> #include <stdio.h> int main() { if (access("test.txt", F_OK|X_OK) < 0) { printf("FILE Not Exists or No Execute permission "); } else { printf("FILE Exists "); } return 0; }
三.chmod()&fchmod()
修改文件访问权限
#include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <stdio.h> int main() { int fd; if ((fd = open("empty.txt", O_RDWR)) < 0) { perror("open"); } fchmod(fd, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP); close(fd); return 0; }
四.truncate()&ftruncate()
该函数用于将文件截取为指定的长度,若要设置文件长度为0,可将第二个参数置为0
也可以使用open函数的O_TRUNC 标志来将文件长度截取为0
#include <unistd.h> #include <sys/types.h> #include <stdio.h> int main() { int ret; ret = truncate("empty.txt", 0); if (ret < 0) { perror("truncate"); } return 0; }
运行结果:
yongdaimi@ubuntu: stat empty.txt
File: ‘empty.txt’
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 801h/2049d Inode: 1103086 Links: 1
Access: (0740/-rwxr-----) Uid: ( 1000/yongdaimi) Gid: ( 1000/yongdaimi)
Access: 2018-02-05 17:10:07.617000418 -0800
Modify: 2018-02-05 17:09:49.485000637 -0800
Change: 2018-02-05 17:09:49.485000637 -0800
Birth: -
五.link()&symlink()&readlink()&unlink()
◆link()
#include <unistd.h> int link(const char *oldpath, const char *newpath);
创建一个硬链接。
当rm删除文件时,只是删除了目录下的记录项和把inode硬链接计数减1,当硬链接计数减为0时,当会真正删除文件。
* 硬链接通常要求位于同一文件系统中,POSIX允许夸文件系统
* 符号链接没有文件系统限制
* 通常不允许创建目录的硬链接,某些unix系统下超级用户可以创建目录的硬链
* 创建目录项以及增加硬链接计数应当是一个原子操作
◆symlink()
#include <unistd.h> int symlink(const char *oldpath, const char *newpath)
建立文件符号链接。
◆readlink()
#include <unistd.h> ssize_t readlink(const char *path, char *buf, size_t bufsiz)
读符号链接所指向的文件名字,不读文件内容。例如符号链接指向的文件名为“new.txt”, 则buf则存储的内容就为new.txt
◆unlink()
#include <unistd.h> int unlink(const char *pathname) 1. 如果是符号链接,删除符号链接 2. 如果是硬链接,硬链接数减1,当减为0时,释放数据块和inode 3. 如果文件硬链接数为0,但有进程已打开该文件,并持有文件描述符,则等该进程关闭该文件时,kernel才真正去删除该文件 4. 利用该特性创建临时文件,先open或creat创建一个文件,马上unlink此文件
#include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <stdlib.h> static const char *str = "www.baidu.com"; static const char *filename = "201321321313131313131313131313131.tmp"; int main() { int fd; if ((fd = open(filename, O_CREAT|O_RDWR, 0777)) < 0) { perror("open"); exit(1); } int ret = write(fd, str, strlen(str)); if (ret < 0) { perror("write"); exit(1); } sleep(30); close(fd); unlink(filename); return 0; }
当进程退出后,临时文件也会相应删除。
六.rename()&chdir()&getcwd()&pathconf()
◆rename()
重命名文件
#include <stdio.h> int rename(const char *oldpath, const char *newpath);
◆chdir()&getcwd
#include <unistd.h> int chdir(const char *path); int fchdir(int fd);
chdir()改变当前进程工作目录,类似于cd命令; getcwd()获取当前进程工作目录,类似于pwd指令
#include <unistd.h> char *getcwd(char *buf, size_t size);
例:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> int main() { char buf[4096] = {0}; int ret = chdir("/home/yongdaimi/ABC"); if (ret < 0) { perror("chdir"); exit(1); } char *pathname = getcwd(buf, sizeof(buf)); if (pathname != NULL) { printf("current working DIR is: %s ", pathname); } else { perror("getcwd"); exit(1); } if (access("apple.txt", F_OK) < 0) { printf("FILE not found "); } else { printf("FILE has found "); } return 0; }
运行结果:
current working DIR is: /home/yongdaimi/ABC
FILE has found
◆pathconf()&fpathconf()
#include <unistd.h> long fpathconf(int fd, int name); long pathconf(char *path, int name);
测试系统资源限制,可籍于此函数获得:
_PC_NAME_MAX 返回一个文件名的最大长度(linux下文件名的最大长度是255个字节)
_PC_LINK_MAX 最大硬链接数
_PC_PATH_MAX 最大路径长度
_PC_PIPE_BUF 最大管道的缓冲区
例:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> int main() { long ret = pathconf("google.txt", _PC_NAME_MAX); if (ret < 0) { perror("ret"); exit(1); } else { printf("cur value is: %ld ", ret); } return 0; }
运行结果:
cur value is: 255
七.mkdir()&rmdir()&opendir()&fdopendir()&closedir()
◆mkdir()
创建一个目录,类似于mkdir指令
#include <sys/stat.h> #include <sys/types.h> int mkdir(const char *pathname, mode_t mode);
◆rmdir()
删除目录,类似于rmdir指令
#include <unistd.h> int rmdir(const char *pathname);
◆opendir()&fdopendir
打开目录
#include <sys/types.h> #include <dirent.h> DIR *opendir(const char *name); DIR *fdopendir(int fd);
◆closedir()
关闭目录
#include <sys/types.h> #include <dirent.h> int closedir(DIR *dirp);
八.readdir()&rewinddir()&telldir()&seekdir()
◆readdir()
readdir每次返回一条记录项,DIR*指针指向下一条记录项
#include <dirent.h> struct dirent *readdir(DIR *dirp); 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 */ };
例:
#include <sys/types.h> #include <dirent.h> #include <stdio.h> #include <sys/stat.h> static void printFileType(int fileType) { printf("current fileType is: %d ", fileType); switch (fileType) { case DT_BLK: printf("File-type: block device "); break; case DT_CHR: printf("File-type: character device ");break; case DT_DIR: printf("File-type: directory "); break; case DT_FIFO: printf("File-type: FIFO/pipe "); break; case DT_LNK: printf("File-type: symlink "); break; case DT_REG: printf("File-type: regular file "); break; case DT_SOCK: printf("File-type: socket "); break; default: printf("File-type: unknow? "); break; } } int main() { const char *filePath = "ndk"; DIR *directory = opendir(filePath); struct dirent *p; while ((p = readdir(directory)) != NULL) { char *name = p->d_name; if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) continue; printf("File-ino: %ld ", p->d_ino); printf("File-off: %ld ", p->d_off); printf("File-reclen: %u ", p->d_reclen); printFileType(p->d_type); printf("File-name: %s ", name); printf("------------------------------------------ "); } closedir(directory); return 0; }
运行结果:
File-ino: 1122632
File-off: 572686190995098447
File-reclen: 24
current fileType is: 4
File-type: directory
File-name: obj
------------------------------------------
File-ino: 1122643
File-off: 3303630722307380472
File-reclen: 24
current fileType is: 4
File-type: directory
File-name: libs
------------------------------------------
File-ino: 1122647
File-off: 9223372036854775807
File-reclen: 24
current fileType is: 4
File-type: directory
File-name: jni
------------------------------------------
◆rewinddir()
移动目录指针到起始位置
#include <sys/types.h> #include <dirent.h> void rewinddir(DIR *dirp);
◆telldir()&seekdir()
telldir() 返回目录指针当前在什么位置
seekdir() 移动目录指针到什么位置
#include <dirent.h> long telldir(DIR *dirp);
#include <dirent.h> void seekdir(DIR *dirp, long offset);
例:
#include <sys/types.h> #include <dirent.h> #include <stdio.h> #include <sys/stat.h> static void printFileType(int fileType) { printf("current fileType is: %d ", fileType); switch (fileType) { case DT_BLK: printf("File-type: block device "); break; case DT_CHR: printf("File-type: character device ");break; case DT_DIR: printf("File-type: directory "); break; case DT_FIFO: printf("File-type: FIFO/pipe "); break; case DT_LNK: printf("File-type: symlink "); break; case DT_REG: printf("File-type: regular file "); break; case DT_SOCK: printf("File-type: socket "); break; default: printf("File-type: unknow? "); break; } } int main() { const char *filePath = "ndk"; DIR *directory = opendir(filePath); struct dirent *p; long dir_pos; while ((p = readdir(directory)) != NULL) { char *name = p->d_name; if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) continue; if (strcmp(name, "obj") == 0) { // record current dir point's position. dir_pos = telldir(directory); } printf("File-ino: %ld ", p->d_ino); printf("File-off: %ld ", p->d_off); printf("File-reclen: %u ", p->d_reclen); printFileType(p->d_type); printf("File-name: %s ", name); printf("------------------------------------------ "); } // Move dir pointer position to "obj" seekdir(directory, dir_pos); while ((p = readdir(directory)) != NULL) { char *name = p->d_name; if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) continue; if (strcmp(name, "obj") == 0) { dir_pos = telldir(directory); } printf("File-ino: %ld ", p->d_ino); printf("File-off: %ld ", p->d_off); printf("File-reclen: %u ", p->d_reclen); printFileType(p->d_type); printf("File-name: %s ", name); printf("------------------------------------------ "); } closedir(directory); return 0; }
运行结果:
File-ino: 1122632
File-off: 572686190995098447
File-reclen: 24
current fileType is: 4
File-type: directory
File-name: obj
------------------------------------------
File-ino: 1122643
File-off: 3303630722307380472
File-reclen: 24
current fileType is: 4
File-type: directory
File-name: libs
------------------------------------------
File-ino: 1122647
File-off: 9223372036854775807
File-reclen: 24
current fileType is: 4
File-type: directory
File-name: jni
------------------------------------------
File-ino: 1122643
File-off: 3303630722307380472
File-reclen: 24
current fileType is: 4
File-type: directory
File-name: libs
------------------------------------------
File-ino: 1122647
File-off: 9223372036854775807
File-reclen: 24
current fileType is: 4
File-type: directory
File-name: jni
------------------------------------------