Project 2 Use C to implement the basic functions of LS

要求

成功要求

mustkown

struct __dirstream
   {
    void *__fd;
    char *__data;
    int __entry_data;
    char *__ptr;
    int __entry_ptr;
    size_t __allocation;
    size_t __size;
    __libc_lock_define (, __lock)
   };
typedef struct __dirstream DIR;

struct dirent
{
  long d_ino; /* inode number 索引节点号 */
    off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
    unsigned short d_reclen; /* length of this d_name 文件名长 */
    unsigned char d_type; /* the type of d_name 文件类型 */
    char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}

struct stat
{
    dev_t     st_dev;     /* ID of device containing file */  //文件使用的设备号
    ino_t     st_ino;     /* inode number */    //索引节点号 
    mode_t    st_mode;    /* protection */  //文件对应的模式,文件,目录等
    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 file system I/O */ //包含该文件的磁盘块的大小   
    blkcnt_t  st_blocks;  /* number of 512B blocks allocated */ //该文件所占的磁盘块  
    time_t    st_atime;   /* time of last access */ //最后一次访问该文件的时间   
    time_t    st_mtime;   /* time of last modification */ //最后一次修改该文件的时间   
    time_t    st_ctime;   /* time of last status change */ //最后一次改变该文件状态的时间   
};

最后,总结一下,想要获取某目录下(比如a目下)b文件的详细信息,我们应该怎样做?

首先,我们使用opendir函数打开目录a,返回指向目录a的DIR结构体c。

接着,我们调用readdir©函数读取目录a下所有文件(包括目录),返回指向目录a下所有文件的dirent结构体d。

然后,我们遍历d,调用stat(d->name,stat *e)来获取每个文件的详细信息,存储在stat结构体e中。

总体就是这样一种逐步细化的过程,在这一过程中,三种结构体扮演着不同的角色。

dir c =  opendir(a)
dirent d readdir(c)
stat e
stat(d->name,&e)
//通过上述四步即可在stat结构体e中得到a目录下的b文件的信息

废话不说了,直接上码!

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

//lstriRa 参数
#define l 1
#define s 2
#define t 3
#define r 4
#define i 5
#define R 6
#define a 7

struct info
{
    char filename[4096];
    struct stat otherinfo;
};

//ls
void myls(int arameter[], char* path);
void printfinfo(int arameter[], int filenum, struct info *temp, int count);


//ls -l
void myls_l(struct info *temp);
void uidtostring(gid_t uid);
void gittostring(gid_t gid);
void modetostring(struct stat otherinfo);//文件权限

//ls -r
static struct info *myls_r(struct info **temp, int num);

//ls -t
static struct info *myls_t(struct info **temp, int num);

//ls -R
void myls_R(struct info *temp, int num, int arameter[], char *path);

int main(int argc, char *argv[])
{
    int arameter[8] = {0}; // 存参数
    char path[4096];       // 目录
    int null[8] = {0};
    char pathname[4096]; // 多路径读取

    getcwd(pathname, sizeof(path)); // 获取文件路径

    if (argc == 1)
    {
        strcpy(path, "./");
        path[2] = '\0';
        myls(null, path);
        return 0;
    }
    for (int y = 1; y < argc; y++)
    {
        if (argv[y][0] != '-')
        {
            strcpy(path, argv[y]);
        }
    }
    int arameternum = 0;
    for (int x = 1; x < argc; x++)
    {
        arameternum += strlen(argv[x]); // 参数长度
    }
    while (arameternum > 1)
    {
        int x = getopt(argc, argv, "lstriRa");
        if (x < 0)
        {
            break;
        }
        else
        {
            if (x == 'l')
                arameter[l] |= 1;
            if (x == 's')
                arameter[s] |= 1;
            if (x == 't')
                arameter[t] |= 1;
            if (x == 'r')
                arameter[r] |= 1;
            if (x == 'i')
                arameter[i] |= 1;
            if (x == 'R')
                arameter[R] |= 1;
            if (x == 'a')
                arameter[a] |= 1;
        }
        arameternum--;
    }
    int flag = 0;
    for (int n = 1; n < argc; n++)
    {
        chdir(pathname);
        if (argv[n][0] != '-')
        {
            strcpy(path, argv[n]);

            printf("%s:\n", path);
            myls(arameter, path);
            printf("\n");

            flag++;
        }
    }
    if (flag == 0)
    {
        strcpy(path, pathname);
        myls(arameter, path);
    }
    return 0;
}

// ls
void myls(int arameter[], char *path)
{
    chdir(path); // 跳转至path指定的目录'

    DIR *dir = NULL;
    struct dirent *ptr = NULL;
    int size = 0;
    int sizehavea = 0;
    int filenum = 0;
    int num = 0;

    struct info *temp = (struct info *)malloc(sizeof(struct info) * 4096);
    memset(temp, 0, sizeof(struct info) * 4096); // 分配内存+置0
    struct info *inception = temp;

    if ((dir = opendir(path)) == NULL)
    {
        perror("fail:");
        exit(1);
    }

    while ((ptr = readdir(dir)) != NULL)
    {
        strcpy(temp->filename, ptr->d_name);
        stat(ptr->d_name, &(temp->otherinfo));
        sizehavea += (temp->otherinfo.st_size);
        if ((temp->filename[0]) != '.')
        {
            size += temp->otherinfo.st_size;
        }
        temp++;
        filenum++;
    }
    num = filenum;
    temp = inception;
    if (arameter[R] == 1)
    {
        printf("%s:\n", path);
        myls_R(temp, num, arameter, path);
    }
    if (arameter[R] != 1)
    {
        printfinfo(arameter, num, temp, filenum);
    }
    free(temp);
    closedir(dir);
}

// ls -l
void myls_l(struct info *temp)
{
    modetostring(temp->otherinfo);
    printf("%5ld", temp->otherinfo.st_nlink);
    uidtostring(temp->otherinfo.st_uid);
    gittostring(temp->otherinfo.st_gid);
    printf("%ld\t", temp->otherinfo.st_blksize / 2);
    char *time = ctime(&(temp->otherinfo.st_mtime));
    if (time[strlen(time) - 1] == '\n')
        time[strlen(time) - 1] = '\0';
    printf("%-12s\t", time);
}

// ls -r
static struct info *myls_r(struct info **temp, int num)
{
    for (int x = 0; x <= (num - 1) / 2; x++)
    {
        struct info tmp = (*temp)[num - 1 - x];
        (*temp)[num - x - 1] = (*temp)[x];
        (*temp)[x] = tmp;
    }
    return *temp;
}

// ls -t
static struct info *myls_t(struct info **temp, int num)
{
    for (int x = 1; x < num; x++)
    {
        for (int j = 0; j < num - x; j++)
        {
            if ((*temp + j)->otherinfo.st_mtime < (*temp + j + 1)->otherinfo.st_mtime)
            {
                struct info tmp = (*temp)[j + 1];
                (*temp)[j + 1] = (*temp)[j];
                (*temp)[j] = tmp;
            }
        }
    }
    return *temp;
}

// ls -R
void myls_R(struct info *temp, int num, int arameter[], char *path)
{
    if (arameter[t] == 1)
    {
        temp = myls_t(&temp, num);
    }
    if (arameter[r] == 1)
    {
        temp = myls_r(&temp, num);
    }
    for (int m = 0; m < num; m++)
    {
        char *tmp = (temp + m)->filename;
        if (arameter[a] != 1)
        {
            if (arameter[i] == 1 && tmp[0] != '.')
                printf("%-10ld ", (temp + m)->otherinfo.st_ino);
            if (arameter[s] == 1 && tmp[0] != '.')
                printf("%-4ld ", (temp + m)->otherinfo.st_blocks / 2);
            if (arameter[l] == 1 && tmp[0] != '.')
                myls_l((temp + m));
            if (tmp[0] != '.')
                printf("%s ", (temp + m)->filename);
            if (arameter[l] == 1 && tmp[0] != '.')
                printf("\n");
        }
        if (arameter[a] == 1)
        {
            if (arameter[i] == 1)
                printf("%-10ld ", (temp + m)->otherinfo.st_ino);
            if (arameter[s] == 1)
                printf("%-4ld ", (temp + m)->otherinfo.st_blocks / 2);
            if (arameter[l] == 1)
                myls_l((temp + m));
            printf("%s ", (temp + m)->filename);
            if (arameter[l] == 1)
                printf("\n");
        }
    }
    printf("\n");
    for (int m = 0; m < num; m++)
    {
        char *tmp = (temp + m)->filename;
        if (S_ISDIR((temp + m)->otherinfo.st_mode) && tmp[0] != '.')
        {
            char path1[1024];
            char path2[1024];
            strcpy(path1, path);
            strcpy(path2, path1);
            strcat(path2, "/");
            strcat(path2, (temp + m)->filename);
            myls(arameter, path2);
        }
    }
}

// 格式打印
void printfinfo(int arameter[], int filenum, struct info *temp, int count)
{
    if (arameter[t] == 1)
    {
        temp = myls_t(&temp, count);
    }
    if (arameter[r] == 1)
    {
        temp = myls_r(&temp, count);
    }

    while (filenum > 0)
    {
        char *tmp = temp->filename;
        if (arameter[a] != 1)
        {
            if (arameter[i] == 1 && tmp[0] != '.')
                printf("%-10ld ", temp->otherinfo.st_ino);
            if (arameter[s] == 1 && tmp[0] != '.')
                printf("%-4ld ", temp->otherinfo.st_blocks / 2);
            if (arameter[l] == 1 && tmp[0] != '.')
                myls_l(temp);
            if (tmp[0] != '.')
                printf("%-12s\t ", temp->filename);
            if (arameter[l] == 1 && tmp[0] != '.')
                printf("\n");
        }
        if (arameter[a] == 1)
        {
            if (arameter[i] == 1)
                printf("%-10ld ", temp->otherinfo.st_ino);
            if (arameter[s] == 1)
                printf("%-4ld ", temp->otherinfo.st_blocks / 2);
            if (arameter[l] == 1)
                myls_l(temp);
            printf("%-12s\t ", temp->filename);
            if (arameter[l] == 1)
                printf("\n");
        }
        filenum--;
        temp++;
    }
}

// uid
void uidtostring(uid_t uid)
{
    struct passwd *pw_ptr;
    static char numstr[10];
    if ((pw_ptr = getpwuid(uid)) == NULL)
    {
        printf("%8d", uid);
    }
    else
    {
        printf("%8s", pw_ptr->pw_name);
    }
}

// gid
void gittostring(gid_t gid)
{
    struct group *grp_ptr;
    static char numstr[10];
    if ((grp_ptr = getgrgid(gid)) == NULL)
    {
        printf("%8d", gid);
    }
    else
    {
        printf("%8s", grp_ptr->gr_name);
    }
}

// 文件权限
void modetostring(struct stat otherinfo)
{
    int mode = otherinfo.st_mode;
    char str[4096] = {0};
    strcpy(str, "----------");

    if (S_ISDIR(mode))
        str[0] = 'd';
    if (S_ISCHR(mode))
        str[0] = 'c';
    if (S_ISBLK(mode))
        str[0] = 'b';

    if (mode & S_IRUSR)
        str[1] = 'r';
    if (mode & S_IWUSR)
        str[2] = 'w';
    if (mode & S_IXUSR)
        str[3] = 'x';

    if (mode & S_IRGRP)
        str[4] = 'r';
    if (mode & S_IWGRP)
        str[5] = 'w';
    if (mode & S_IXGRP)
        str[6] = 'x';

    if (mode & S_IROTH)
        str[7] = 'r';
    if (mode & S_IWOTH)
        str[8] = 'w';
    if (mode & S_IXOTH)
        str[9] = 'x';

    printf("%12s", str);
}
//此为鄙人的拙见,如有不正,请指正,该代码未实现颜色展示,颜色展示可以用``printf()`` 中的``033[``命令,别问我为啥没写,问就是懒,哼!
//该代码在ArchLinux系统中适配,其他系统未尝试,别问我为啥没测,问就是懒,哼!
//如有其他问题,请私信联系我。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值