文件和目录管理 - 文件和其元数据

2019-08-26  本文已影响0人  无无吴

文件和其元数据(metadata)

linux中每个file对应一个inode,它不仅代表磁盘上的物理对象,也是内核中的一个概念实体,并且由一个数据结构体表示。


linux中查看inode的方式

The Stat Family

Unix提供了一系列函数,用于获取文件的元数据。

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);

stat()返回由路径表示的文件的信息,而fstat()返回由文件描述符fd表示的文件的信息。lstat()与stat()相同, 除了在符号链接的情况下,lstat()返回有关链接本身的信息,而不是目标文件。

这些函数中的每一个都将信息存储在由用户提供的stat结构中。stat结构体定义在<bits/stat.h> 而这个由<sys/stat.h>包含。

struct stat{
        dev_t st_dev; /* ID of device containing file */
        ino_t st_ino; /* inode number */
        mode_t st_mode; /* permissions */
        nlink_t st_nlink; /* number of hard links */
        uid_t st_uid; /* user ID of owner */
        gid_t st_gid; /* group ID of owner */
        dev_t st_rdev; /* device ID (if special file) */
        off_t st_size; /* total size in bytes */
        blksize_t st_blksize; /* blocksize for filesystem I/O */
        blkcnt_t st_blocks; /* number of blocks allocated */
        time_t st_atime; /* last access time */
        time_t st_mtime; /* last modification time */
        time_t st_ctime; /* last status change time */
};

成功返回0,失败返回-1并且设置errno。

//example retrive the size of a file provided on the command line:
int getFileSize(int argc, char*argv[]) {
    struct stat sb;
    int ret;
    if(argc < 2){
        fprintf(stderr, "usage: %s <file>\n", argv[0]);
        return 1;
    }

    ret = stat(argv[1], &sb);
    if(ret){
        perror("stat");
        return 1;
    }

    printf("%s is %ld bytes\n",
            argv[1], sb.st_size);

    return 0;
}

int main(int argc, char*argv[])
{
    getFileSize(argc, argv);
    return 0;
}

test result
//example for reporting file tyoe(such as symbolick link or block device node)
int getFileType(int argc, char **argv) {
    struct stat sb;
    int ret;
    if(argc < 2){
        fprintf(stderr, "usage: %s <file>\n", argv[0]);
        return 1;
    }
    ret = stat(argv[1], &sb);
    if(ret){
        perror("stat");
        return 1;
    }

    printf("File type: ");
    switch(sb.st_mode & S_IFMT){
        case S_IFBLK:
            printf("block device node\n");
            break;
        case S_IFCHR:
            printf("character device node\n");
            break;
        case S_IFDIR:
            printf("directory\n");
            break;
        case S_IFIFO:
            printf("FIFO\n");
            break;
        case S_IFLNK:
            printf("symbolic link\n");
            break;
        case S_IFREG:
            printf("regular file\n");
            break;
        case S_IFSOCK:
            printf("socket\n");
            break;
        default:
            printf("unknown\n");
            break;
    }
    return 0;
}

int main(int argc, char*argv[])
{
    getFileType(argc, argv);
    return 0;
}
test result
/*
 * is_on_physical_device - returns a positive
 * integer if 'fd' resides on a physical device,
 * 0 if the file resides on a nonphysical or
 * virtual device (e.g., on an NFS mount), and
 * −1 on error.
 */
int is_on_physical_device (int fd) {
        struct stat sb;
        int ret;
        ret = fstat (fd, &sb);
        if (ret) {
              perror ("fstat");
              return −1;
         }
         return gnu_dev_major (sb.st_dev);
}

Permissions

通过stat能获得file的权限,另外两个系统调用可以设置权限

#include <sys/types.h>
#include <sys/stat.h>

int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);
//mode 参数
- S_IRWXU 所有者具有读取、写入和执行权限。
- S_IRUSR 所有这具有读取的权限
- S_IWUSR 所有者具有写入的权限
- S_IXUSR 所有者具有执行的权限
- S_IRWXG 组具有读取、写入和执行权限
- S_IRGRP 组具有读取的权限
- S_IWGRP 组具有写入的权限
- S_IXGRP 组具有执行的权限
- S_IRWXO 每个人都可以写入、读取和执行
- S_IROTH 每个人都可以读取
- S_IWOTH 每个人都可以写入
- S_IXOTH 每个人都可以执行

成功返回0,失败返回-1,并设置errno

//eample
int ret = chmod("./map.png", S_IRUSR | S_IWUSR);
if(ret)
        perror("chmod");
int ret = fchmod(fd, S_IRUSR|S_IWUSR);
if(ret)
        perror("fchmod");

Ownership

stat中st_uid和st_gid分别提供了文件的拥有者和组。下面这三个调用可以改变这两个值。

#include <sys/types.h>
#include <unistd.h>
int chown(const char*path, uid_t owner, gid_t group);
int lchown(const char*path, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);

成功返回0,失败返回-1,并设置errno。
只有拥有CAP_CHOWN属性(通常是root进程)的进程才可以改变文件的owner。
如果owner和group参数值是-1的话,那么这个值将不被设置。

int ret;
/*
 * getgrnam() returns information on a group
 * given its name.
 */
gr = getgrnam ("officers");
if (!gr) {
/* likely an invalid group */
            perror ("getgrnam");
            return 1;
 }
/* set manifest.txt's group to 'officers' */
ret = chown("manifest.txt", -1, gr->gr_gid);
if (ret)
            perror ("chown");
/*
 * make_root_owner - changes the owner and group of the file
 * given by 'fd' to root. Returns 0 on success and −1 on
 * failure.
 */
int make_root_owner (int fd) {
int ret;
/* 0 is both the gid and the uid for root */
ret = fchown (fd, 0, 0);
if (ret)
      perror ("fchown");
      return ret;
 }

Extended Attributes

Linux 目前定义了四个扩展的属性命名空间,将来可能会定义更多。 目前的四个项目如下:

Extended Attribute Operations

POSIX定义了应用程序可以对给定文件的扩展属性执行的四个操作:

检索扩展属性

#include <sys/types.h>
#include <attr/xattr.h>
ssize_t getxattr (const char *path, const char *key,
void *value, size_t size);
ssize_t lgetxattr (const char *path, const char *key,
void *value, size_t size);
ssize_t fgetxattr (int fd, const char *key,
void *value, size_t size);

成功的调用将会把key相对应的值存储在buffer value中,size是buffer的size。
函数成功调用的话返回实际value对应的size。
如果size是零,函数会返回value的size,但不会存储金buffer value中。所以传0可以额让应用知道存储key的valued的buffer的实际大小。
失败返回-1并设置errno。

设置扩展属性

#include <sys/types.h>
#include <attr/xattr.h>
int setxattr (const char *path, const char *key,
                      const void *value, size_t size, int flags);
int lsetxattr (const char *path, const char *key,
                    const void *value, size_t size, int flags);
int fsetxattr (int fd, const char *key,
                    const void *value, size_t size, int flags);
#### 列出文件上的扩展属性
#include <sys/types.h>
#include <attr/xattr.h>
ssize_t listxattr (const char *path,
          char *list, size_t size);
ssize_t llistxattr (const char *path,
          char *list, size_t size);
ssize_t flistxattr (int fd,
          char *list, size_t size);
注解

如果size传入0的话,就可以知道实际buffer list需要的大小。
成功返回0,失败返回-1,并且设置errno。

移除一个扩展属性

#include <sys/types.h>
#include <attr/xattr.h>
int removexattr (const char *path, const char *key);
int lremovexattr (const char *path, const char *key);
int fremovexattr (int fd, const char *key);

成功返回0,失败返回-1。

上一篇 下一篇

猜你喜欢

热点阅读