2.文件系统

一.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
------------------------------------------

原文地址:https://www.cnblogs.com/yongdaimi/p/7806130.html