linux开发之ls -l命令实现

发布时间 2023-04-17 18:43:58作者: 1v7w

效果

实现

大致思路

首先,程序需要通过参数接受一个文件名。接着通过stat函数获取文件的信息,通过处理,进行合适的输出。

转换时间戳可以用localtime函数来进行。

判断文件类型时候要按位与S_IFMT。判断权限时候,也要按位与对应的宏。

具体流程

  1. 判断程序用法是否正确
  2. 通过stas函数获取文件信息
  3. 将信息依次存到最终结果中

代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>

int main(int argc, char *argv[]) {
    if(argc < 2) {
        printf("usage: %s filename\n", argv[0]);
        return -1;
    }

    // 获取文件信息
    struct stat st;
    int ret = stat(argv[1], &st);
    if(ret == -1) {
        perror(argv[1]);
        return -1;
    }

    // 记录文件类型以及权限
    char prime[11] = {0};
    // 文件类型
    switch(st.st_mode & S_IFMT) {
        case S_IFSOCK:
            prime[0] = 's';
            break;
        case S_IFLNK:
            prime[0] = 'l';
            break;
        case S_IFREG:
            prime[0] = '-';
            break;
        case S_IFBLK:
            prime[0] = 'b';
            break;
        case S_IFDIR:
            prime[0] = 'd';
            break;
        case S_IFCHR:
            prime[0] = 'c';
            break;
        case S_IFIFO:
            prime[0] = 'p';
            break;
        case S_IFMT:
            break;
        default:
            prime[0] = '?';
    }

    // 所有者权限
    prime[1] = st.st_mode & S_IRUSR ? 'r' : '-';
    prime[2] = st.st_mode & S_IWUSR ? 'w' : '-';
    prime[3] = st.st_mode & S_IXUSR ? 'x' : '-';
    // 所在组权限
    prime[4] = st.st_mode & S_IRGRP ? 'r' : '-';
    prime[5] = st.st_mode & S_IWGRP ? 'w' : '-';
    prime[6] = st.st_mode & S_IXGRP ? 'x' : '-';
    // 其他人权限
    prime[7] = st.st_mode & S_IROTH ? 'r' : '-';
    prime[8] = st.st_mode & S_IWOTH ? 'w' : '-';
    prime[9] = st.st_mode & S_IXOTH ? 'x' : '-';

    // 硬链接数量
    unsigned long int linknum = st.st_nlink;

    // 所有者
    char *file_user = getpwuid(st.st_uid)->pw_name;

    // 所在组
    char *file_group = getgrgid(st.st_gid)->gr_name;

    // 文件大小
    long int file_size = st.st_size;

    // 获取时间
    struct tm *time = localtime(&st.st_mtim.tv_sec);
    char time1[256] = {0};
    const char * months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sepr", "Oct", "Nov", "Dec"};
    sprintf(time1, "%s %d %d:%d", months[time->tm_mon], time->tm_mday, time->tm_hour, time->tm_min);

    char buf[1024];
    sprintf(buf, "%s %lu %s %s %ld %s %s", prime, linknum, file_user, file_group, file_size, time1, argv[1]);
    puts(buf);

    return 0;
}