linux下ls命令的实现

Linux系统ls命令的实现

     7	#include <stdio.h>
     8	#include <unistd.h>
     9	#include <stdlib.h>
    10	#include <math.h>
    11	#include <dirent.h>
    12	#include <sys/types.h>
    13	#include <string.h>
    14	#include <sys/ioctl.h>
    15	#include <sys/stat.h>
    16	#include <grp.h>
    17	#include <pwd.h>
    18	#include <time.h>
    19	
    20	#define FILEMAX 1024
    21	#define NAMEMAX 256
    22	
    23	int flag_a = 0;
    24	int flag_l = 0;
    25	int dir_num = 0;
    26	int fg_c, bg_c;
    27	
    28	void size_window(char filename[][NAMEMAX], int cnt, int* row, int* col){
    29	    struct winsize size;
    30	    int len[cnt], max = 0, total = 0;
    31	    memset(len, 0, sizeof(int) * cnt);
    32	    if (isatty(STDOUT_FILENO) == 0) {
    33	        exit(1);
    34	    }
    35	
    36	    if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &size) < 0) {
    37	        perror("ioctl");
    38	        exit(1);
    39	    }
    40	
    41	    for (int i= 0; i < cnt; i++){
    42	        len[i] = strlen(filename[i]);
    43	        if (max < len[i]) max = len[i];
    44	        total += len[i] + 1;
    45	    }
    46	    if (max + 1 >= size.ws_col) {
    47	        *row = cnt;
    48	        *col = 1;
    49	        return ;
    50	    }
    51	    if (total <= size.ws_col) {
    52	        *row = 1;
    53	        *col = cnt;
    54	        return ;
    55	    }
    56	
    57	    int try_begin = 0;
    58	    for (int i = 0, tmp = 0; i < cnt; i++) {
    59	        tmp += (len[i] + 1);
    60	        if (tmp >= size.ws_col) {
    61	            try_begin = i;
    62	            break;
    63	        }
    64	    }
    65	
    66	    for (int i = try_begin; ;i--) {
    67	        int *wide = (int *)malloc(sizeof(int) * i);
    68	        memset(wide, 0, sizeof(int) * i);
    69	        *row = (int)ceil(cnt / i);
    70	        int try_sum = 0;
    71	        for (int x = 0; x < i; x++) {
    72	            for (int y = x * *row; y < (x + 1) * *row && y < cnt; y++) {
    73	                if (wide[x] < len[y]) wide[x] = len[y];
    74	            }
    75	            try_sum += (wide[x] + 1);
    76	        }
    77	
    78	        if (try_sum > size.ws_col) continue;
    79	        if (try_sum <= size.ws_col) {
    80	            *col = i;
    81	            break;
    82	        }
    83	    }
    84	}
    85	
    86	void update_color(mode_t mode) {
    87	    bg_c = 0;
    88	    fg_c = 37;
    89	    if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) fg_c = 32;
    90	    if (mode & 0111) fg_c = 32;
    91	    switch (mode & S_IFMT) {
    92	        case S_IFDIR:
    93	            fg_c = 34;
    94	            break;
    95	        case S_IFLNK:
    96	            fg_c = 36;
    97	            break;
    98	    }
    99	}
   100	
   101	void show_files(char filename[][NAMEMAX], int cnt, int row, int col) {
   102	    int wide_file[cnt];
   103	    struct stat tmp_st;
   104	    memset(wide_file, 0, sizeof(int) * cnt);
   105	    for(int i = 0; i < col; i++) {
   106	        for (int j = (i * row); j < (i + 1) * row && j < cnt; j++) {
   107	            if (wide_file[i] < strlen(filename[j])) wide_file[i] = strlen(filename[j]) ;
   108	
   109	        }
   110	    }
   111	
   112	    for (int i = 0; i < row; i++) {
   113	        for (int j = i; j < i + (row * col) && j < cnt; j = j + row) {
   114	            int tmp = j / row;
   115	            stat(filename[j], &tmp_st);
   116	            update_color(tmp_st.st_mode);
   117	            printf("\033[%d;%dm%-*s\033[0m", bg_c, fg_c, wide_file[tmp] + 1, filename[j]);
   118	        }
   119	            printf("\n");
   120	        }
   121	}
   122	
   123	
   124	void mode_to_str(mode_t mode, char *str) {
   125	    if (S_ISREG(mode)) str[0] = '-';
   126	    if (S_ISDIR(mode)) str[0] = 'd';
   127	    if (S_ISCHR(mode)) str[0] = 'c';
   128	    if (S_ISBLK(mode)) str[0] = 'b';
   129	    if (S_ISSOCK(mode)) str[0] = 's';
   130	    if (S_ISLNK(mode)) str[0] = 'l';
   131	    if (S_ISFIFO(mode)) str[0] = 'p';
   132	
   133	    if (mode & S_IRUSR) str[1] = 'r';
   134	    if (mode & S_IWUSR) str[2] = 'w';
   135	    if (mode & S_IXUSR) str[3] = 'x';
   136	    if (mode & S_IRGRP) str[4] = 'r';
   137	    if (mode & S_IWGRP) str[5] = 'w';
   138	    if (mode & S_IXGRP) str[6] = 'x';
   139	
   140	    if (mode & S_IROTH) str[7] = 'r';
   141	    if (mode & S_IWOTH) str[8] = 'w';
   142	    if (mode & S_IXOTH) str[9] = 'x';
   143	
   144	    if ((mode & S_IXUSR) && (mode & S_ISUID)) str[3] = 's';
   145	    update_color(mode);
   146	}
   147	
   148	char *uid_to_name(uid_t uid){
   149	    struct passwd *pw_ptr;
   150	    static char tmpstr[10] = {0};
   151	    if ((pw_ptr = getpwuid(uid)) == NULL) {
   152	        sprintf(tmpstr, "%d", uid);
   153	        return tmpstr;
   154	    } else {
   155	        return pw_ptr->pw_name;
   156	    }
   157	}
   158	
   159	char *gid_to_name(gid_t gid) {
   160	    struct group *gr_ptr;
   161	    static char tmpstr[10] = {0};
   162	    if ((gr_ptr = getgrgid(gid)) == NULL) {
   163	        sprintf(tmpstr, "%d", gid);
   164	        return tmpstr;
   165	    } else {
   166	        return gr_ptr->gr_name;
   167	    }
   168	}
   169	
   170	void show_info(char *filename, struct stat *info) {
   171	    char modestr[11] = "----------";
   172	    mode_to_str(info->st_mode, modestr);
   173	    printf("%s ", modestr);
   174	    printf("%4ld ", info->st_nlink);
   175	    printf("%8s ", uid_to_name(info->st_uid));
   176	    printf("%8s ", gid_to_name(info->st_gid));
   177	    printf("%8ld ", info->st_size);
   178	    printf("%.15s ",  4 + ctime(&info->st_mtime));
   179	    printf("\033[%d;%dm%s\033[0m ", bg_c, fg_c, filename);
   180	    if (modestr[0] == 'l') {
   181	        int cnt;
   182	        char buf[NAMEMAX] = {0};
   183	        if (cnt == readlink(filename, buf, 256) < 0) {
   184	            perror("readlink");
   185	        }
   186	        printf("-> \033[%d;%dm%s\033[0m", bg_c, fg_c, buf);
   187	    }
   188	    printf("\n");
   189	}
   190	
   191	void do_stat(char *filename) {
   192	    struct stat st;
   193	    if (stat(filename, &st) < 0) {
   194	        perror(filename);
   195	    } else {
   196	        show_info(filename, &st);
   197	    }
   198	}
   199	
   200	int cmp_name(const void* _a, const void* _b) {
   201	    char *a = (char *)_a;
   202	    char *b = (char *)_b;
   203	    return strcmp(a, b);
   204	}
   205	
   206	void do_ls(char *dirname) {
   207	    DIR *dirp = NULL;
   208	    struct dirent *direntp;
   209	    char names[FILEMAX][NAMEMAX] = {0};
   210	    if ((dirp = opendir(dirname)) == NULL) {
   211	        if (access(dirname, R_OK) == 0) {
   212	            if (flag_l == 0) {
   213	                dir_num--;
   214	                struct stat tmp_st;
   215	                stat(dirname, &tmp_st);
   216	                update_color(tmp_st.st_mode);
   217	                printf("\033[%d;%dm%s\033[0m\n",bg_c, fg_c, dirname);
   218	                return;
   219	            } else {
   220	                dir_num--;
   221	                do_stat(dirname);
   222	                return;
   223	            }
   224	        } else {
   225	            perror(dirname);
   226	            return ;
   227	        }
   228	    } else {
   229	        if (dir_num)
   230	            printf("%s:\n", dirname);
   231	        chdir(dirname);
   232	        int cnt = 0;
   233	        while((direntp = readdir(dirp)) != NULL) {
   234	            if (direntp->d_name[0] == '.' && (flag_a == 0)) continue;
   235	            strcpy(names[cnt++], direntp->d_name);
   236	        }
   237	        qsort(names, cnt, NAMEMAX, cmp_name);
   238	
   239	        if (flag_l == 1) {
   240	            for (int i = 0; i < cnt; i++) {
   241	                do_stat(names[i]);
   242	            }
   243	        } else {
   244	            int row, col;
   245	            size_window(names, cnt, &row, &col);
   246	            show_files(names, cnt, row, col);
   247	        }
   248	
   249	    }
   250	}
   251	
   252	
   253	int main(int argc, char **argv) {
   254	    int opt;
   255	    while((opt = getopt(argc, argv, "al")) != -1) {
   256	        switch (opt) {
   257	            case 'a':
   258	            flag_a = 1;
   259	                break;
   260	            case 'l':
   261	                flag_l = 1;
   262	                break;
   263	            default:
   264	                fprintf(stderr, "Usage: %s [-al] [filename]\n", argv[0]);
   265	                exit(1);
   266	        }
   267	    }
   268	    argc -= (optind - 1);
   269	    argv += (optind - 1);
   270	
   271	    if (argc == 1) {
   272	        dir_num = 0;
   273	        do_ls(".");
   274	    } else {
   275	        dir_num = argc - 2;
   276	        while(--argc) {
   277	            do_ls(*(++argv));
   278	        }
   279	    }
   280	    return 0;
   281	}
   282
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值