stat命令的实现-mystat

stat命令的实现-mystat

任务内容

学习使用stat(1),并用C语言实现

  1. 提交学习stat(1)的截图。
  2. man -k ,grep -r的使用。
  3. 伪代码。
  4. 产品代码 mystate.c,提交码云链接。
  5. 测试代码,mystat 与stat(1)对比,提交截图 。

    任务步骤

    查询stat命令

  • 使用手册查询stat命令man stat

我们可以看到,stat命令的解释是“展示文件或文件系统的状态”

  • 实际使用stat命令,观察实现效果

  • 我们继续在手册中通过man -k stat | grep 2查询stat命令的系统调用,如图所示

  • man 2 stat查看stat()函数的使用方法

  • 我们发现如下的结构体,文字介绍意为“所有的系统调用最后都会返回一个stat结构体,包含下列信息”
struct stat {
    dev_t         st_dev;       //文件的设备编号
    ino_t         st_ino;       //节点
    mode_t        st_mode;      //文件的类型和存取的权限
    nlink_t       st_nlink;     //连到该文件的硬连接数目,刚建立的文件值为1
    uid_t         st_uid;       //用户ID
    gid_t         st_gid;       //组ID
    dev_t         st_rdev;      //(设备类型)若此文件为设备文件,则为其设备编号
    off_t         st_size;      //文件字节数(文件大小)
    unsigned long st_blksize;   //块大小(文件系统的I/O 缓冲区大小)
    unsigned long st_blocks;    //块数
    time_t        st_atime;     //最后一次访问时间
    time_t        st_mtime;     //最后一次修改时间
    time_t        st_ctime;     //最后一次改变时间(指属性)
};
  • 于是我们了解到,只要调用stat()函数获取结构体信息即可实现stat命令的功能
  • 但是我们注意到,文件类型的输出我们直接用st_mode输出会显示一个整型数,但实际上使用stat命令显示的是文件的具体类型
  • 再次查看stat(),在结构体介绍的下面还有如下描述

  • 在手册中查看inode,获得如下信息:

  • 我们发现系统会根据这个标志,来判断具体的文件类型,因此我们需要再用switch加以判断

    伪代码实现

1.判断输入中是否包含文件参数,如果有则继续,没有则提示用户输入错误
2.声明结构体,并调用stat()函数给结构体赋值
3.逐个取出结构体中的数据并输出即可
4.注意文件的mode需要switch来判断

代码实现

#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    struct stat sb;
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    if (stat(argv[1], &sb) == -1) {
        perror("stat");
        exit(EXIT_FAILURE);
    }
    printf("文件: %s\n",argv[1]);
    printf("I-node:            %ld\n", (long) sb.st_ino);
    printf("硬连接:               %ld\n", (long) sb.st_nlink);
    printf("权限:                UID=%ld   GID=%ld\n",(long) sb.st_uid, (long) sb.st_gid);
    printf("IO块: %ld ",(long) sb.st_blksize);
    switch (sb.st_mode & S_IFMT) {
        case S_IFBLK:   printf("块设备\n");
            break;
    case S_IFCHR:   printf("character device\n");
            break;
    case S_IFDIR:   printf("目录\n");
            break;
    case S_IFIFO:   printf("FIFO/管道\n");
            break;
    case S_IFLNK:   printf("符号链接\n");
            break;
    case S_IFREG:   printf("普通文件\n");
            break;
    case S_IFSOCK:  printf("socket\n");
            break;
    default:        printf("未知?\n");
            break;
    }
    printf("大小:                %lld bytes\n",(long long) sb.st_size);
    printf("块:         %lld\n",(long long) sb.st_blocks);
    printf("最近访问:         %s", ctime(&sb.st_atime));
    printf("最近更改:   %s", ctime(&sb.st_mtime));
    printf("最近改动:       %s", ctime(&sb.st_ctime));
    exit(EXIT_SUCCESS);
}

运行结果

码云链接

猜你喜欢

转载自www.cnblogs.com/darklord0604/p/12111147.html