📄 ls.c
字号:
if ((nrows * ncols) < nfiles) nrows++; /* round up fractionals */ if (nrows > nfiles) nrows= nfiles; for (row=0; row<nrows; row++) { for (nc=0; nc<ncols; nc++) { /* reach into the array based on the column and row */ i= (nc * nrows) + row; /* assume display by column */ if (disp_opts & DISP_ROWS) i= (row * ncols) + nc; /* display across row */ if (i < nfiles) { nexttabstop(); list_single(dn[i]); } } newline(); }}/*----------------------------------------------------------------------*/static void showdirs(struct dnode **dn, int ndirs){ int i, nfiles; struct dnode **subdnp;#ifdef BB_FEATURE_LS_RECURSIVE int dndirs; struct dnode **dnd;#endif if (dn==NULL || ndirs < 1) return; for (i=0; i<ndirs; i++) { if (disp_opts & (DISP_DIRNAME | DISP_RECURSIVE)) { printf("\n%s:\n", dn[i]->fullname); } subdnp= list_dir(dn[i]->fullname); nfiles= countfiles(subdnp); if (nfiles > 0) { /* list all files at this level */#ifdef BB_FEATURE_LS_SORTFILES shellsort(subdnp, nfiles);#endif showfiles(subdnp, nfiles);#ifdef BB_FEATURE_LS_RECURSIVE if (disp_opts & DISP_RECURSIVE) { /* recursive- list the sub-dirs */ dnd= splitdnarray(subdnp, nfiles, SPLIT_SUBDIR); dndirs= countsubdirs(subdnp, nfiles); if (dndirs > 0) {#ifdef BB_FEATURE_LS_SORTFILES shellsort(dnd, dndirs);#endif showdirs(dnd, dndirs); free(dnd); /* free the array of dnode pointers to the dirs */ } } dfree(subdnp); /* free the dnodes and the fullname mem */#endif } }}/*----------------------------------------------------------------------*/static struct dnode **list_dir(char *path){ struct dnode *dn, *cur, **dnp; struct dirent *entry; DIR *dir; int i, nfiles; if (path==NULL) return(NULL); dn= NULL; nfiles= 0; dir = opendir(path); if (dir == NULL) { perror_msg("%s", path); status = EXIT_FAILURE; return(NULL); /* could not open the dir */ } while ((entry = readdir(dir)) != NULL) { /* are we going to list the file- it may be . or .. or a hidden file */ if ((strcmp(entry->d_name, ".")==0) && !(disp_opts & DISP_DOT)) continue; if ((strcmp(entry->d_name, "..")==0) && !(disp_opts & DISP_DOT)) continue; if ((entry->d_name[0] == '.') && !(disp_opts & DISP_HIDDEN)) continue; cur= (struct dnode *)xmalloc(sizeof(struct dnode)); cur->fullname = concat_path_file(path, entry->d_name); cur->name = cur->fullname + (strlen(cur->fullname) - strlen(entry->d_name)); if (my_stat(cur)) continue; cur->next= dn; dn= cur; nfiles++; } closedir(dir); /* now that we know how many files there are ** allocate memory for an array to hold dnode pointers */ if (nfiles < 1) return(NULL); dnp= dnalloc(nfiles); for (i=0, cur=dn; i<nfiles; i++) { dnp[i]= cur; /* save pointer to node in array */ cur= cur->next; } return(dnp);}/*----------------------------------------------------------------------*/static int list_single(struct dnode *dn){ int i;#ifdef BB_FEATURE_LS_USERNAME char scratch[BUFSIZ + 1];#endif#ifdef BB_FEATURE_LS_TIMESTAMPS char *filetime; time_t ttime, age;#endif#if defined (BB_FEATURE_LS_FILETYPES) || defined (BB_FEATURE_LS_COLOR) struct stat info; char append;#endif if (dn==NULL || dn->fullname==NULL) return(0);#ifdef BB_FEATURE_LS_TIMESTAMPS ttime= dn->dstat.st_mtime; /* the default time */ if (time_fmt & TIME_ACCESS) ttime= dn->dstat.st_atime; if (time_fmt & TIME_CHANGE) ttime= dn->dstat.st_ctime; filetime= ctime(&ttime);#endif#ifdef BB_FEATURE_LS_FILETYPES append = append_char(dn->dstat.st_mode);#endif for (i=0; i<=31; i++) { switch (list_fmt & (1<<i)) { case LIST_INO: printf("%7ld ", (long int)dn->dstat.st_ino); column += 8; break; case LIST_BLOCKS:#ifdef BB_FEATURE_HUMAN_READABLE fprintf(stdout, "%6s ", make_human_readable_str(dn->dstat.st_blocks>>1, KILOBYTE, (ls_disp_hr==TRUE)? 0: KILOBYTE));#else#if _FILE_OFFSET_BITS == 64 printf("%4lld ", dn->dstat.st_blocks>>1);#else printf("%4ld ", dn->dstat.st_blocks>>1);#endif#endif column += 5; break; case LIST_MODEBITS: printf("%-10s ", (char *)mode_string(dn->dstat.st_mode)); column += 10; break; case LIST_NLINKS: printf("%4ld ", (long)dn->dstat.st_nlink); column += 10; break; case LIST_ID_NAME:#ifdef BB_FEATURE_LS_USERNAME my_getpwuid(scratch, dn->dstat.st_uid); printf("%-8.8s ", scratch); my_getgrgid(scratch, dn->dstat.st_gid); printf("%-8.8s", scratch); column += 17; break;#endif case LIST_ID_NUMERIC: printf("%-8ld %-8ld", (long)dn->dstat.st_uid, (long)dn->dstat.st_gid); column += 17; break; case LIST_SIZE: case LIST_DEV: if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) { printf("%4d, %3d ", (int)MAJOR(dn->dstat.st_rdev), (int)MINOR(dn->dstat.st_rdev)); } else {#ifdef BB_FEATURE_HUMAN_READABLE if (ls_disp_hr==TRUE) { fprintf(stdout, "%8s ", make_human_readable_str(dn->dstat.st_size, 1, 0)); } else #endif {#if _FILE_OFFSET_BITS == 64 printf("%9lld ", (long long)dn->dstat.st_size);#else printf("%9ld ", dn->dstat.st_size);#endif } } column += 10; break;#ifdef BB_FEATURE_LS_TIMESTAMPS case LIST_FULLTIME: case LIST_DATE_TIME: if (list_fmt & LIST_FULLTIME) { printf("%24.24s ", filetime); column += 25; break; } age = time(NULL) - ttime; printf("%6.6s ", filetime+4); if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) { /* hh:mm if less than 6 months old */ printf("%5.5s ", filetime+11); } else { printf(" %4.4s ", filetime+20); } column += 13; break;#endif case LIST_FILENAME:#ifdef BB_FEATURE_LS_COLOR errno = 0; if (show_color && !lstat(dn->fullname, &info)) { printf( "\033[%d;%dm", bgcolor(info.st_mode), fgcolor(info.st_mode) ); }#endif printf("%s", dn->name);#ifdef BB_FEATURE_LS_COLOR if (show_color) { printf( "\033[0m" ); }#endif column += strlen(dn->name); break; case LIST_SYMLINK: if (S_ISLNK(dn->dstat.st_mode)) { char *lpath = xreadlink(dn->fullname); if (lpath) { printf(" -> ");#if defined(BB_FEATURE_LS_FILETYPES) || defined(BB_FEATURE_LS_COLOR) if (!stat(dn->fullname, &info)) { append = append_char(info.st_mode); }#endif#ifdef BB_FEATURE_LS_COLOR if (show_color) { errno = 0; printf( "\033[%d;%dm", bgcolor(info.st_mode), fgcolor(info.st_mode) ); }#endif printf("%s", lpath);#ifdef BB_FEATURE_LS_COLOR if (show_color) { printf( "\033[0m" ); }#endif column += strlen(lpath) + 4; free(lpath); } } break;#ifdef BB_FEATURE_LS_FILETYPES case LIST_FILETYPE: if (append != '\0') { printf("%1c", append); column++; } break;#endif } } return(0);}/*----------------------------------------------------------------------*/extern int ls_main(int argc, char **argv){ struct dnode **dnf, **dnd; int dnfiles, dndirs; struct dnode *dn, *cur, **dnp; int i, nfiles; int opt; int oi, ac; char **av;#ifdef BB_FEATURE_AUTOWIDTH struct winsize win = { 0, 0, 0, 0 };#endif disp_opts= DISP_NORMAL; style_fmt= STYLE_AUTO; list_fmt= LIST_SHORT;#ifdef BB_FEATURE_LS_SORTFILES sort_opts= SORT_NAME; sort_order= SORT_FORWARD;#endif#ifdef BB_FEATURE_LS_TIMESTAMPS time_fmt= TIME_MOD;#endif#ifdef BB_FEATURE_AUTOWIDTH ioctl(fileno(stdout), TIOCGWINSZ, &win); if (win.ws_row > 4) column_width = win.ws_row - 2; if (win.ws_col > 0) terminal_width = win.ws_col - 1;#endif nfiles=0;#ifdef BB_FEATURE_LS_COLOR if (isatty(fileno(stdout))) show_color = 1;#endif /* process options */ while ((opt = getopt(argc, argv, "1AaCdgilnsx"#ifdef BB_FEATURE_AUTOWIDTH"T:w:"#endif#ifdef BB_FEATURE_LS_FILETYPES"Fp"#endif#ifdef BB_FEATURE_LS_RECURSIVE"R"#endif#ifdef BB_FEATURE_LS_SORTFILES"rSvX"#endif#ifdef BB_FEATURE_LS_TIMESTAMPS"cetu"#endif#ifdef BB_FEATURE_LS_FOLLOWLINKS"L"#endif#ifdef BB_FEATURE_HUMAN_READABLE"h"#endif"k")) > 0) { switch (opt) { case '1': style_fmt = STYLE_SINGLE; break; case 'A': disp_opts |= DISP_HIDDEN; break; case 'a': disp_opts |= DISP_HIDDEN | DISP_DOT; break; case 'C': style_fmt = STYLE_COLUMNS; break; case 'd': disp_opts |= DISP_NOLIST; break; case 'g': /* ignore -- for ftp servers */ break; case 'i': list_fmt |= LIST_INO; break; case 'l': style_fmt = STYLE_LONG; list_fmt |= LIST_LONG;#ifdef BB_FEATURE_HUMAN_READABLE ls_disp_hr = FALSE;#endif break; case 'n': list_fmt |= LIST_ID_NUMERIC; break; case 's': list_fmt |= LIST_BLOCKS; break; case 'x': disp_opts = DISP_ROWS; break;#ifdef BB_FEATURE_LS_FILETYPES case 'F': list_fmt |= LIST_FILETYPE | LIST_EXEC; break; case 'p': list_fmt |= LIST_FILETYPE; break;#endif#ifdef BB_FEATURE_LS_RECURSIVE case 'R': disp_opts |= DISP_RECURSIVE; break;#endif#ifdef BB_FEATURE_LS_SORTFILES case 'r': sort_order |= SORT_REVERSE; break; case 'S': sort_opts= SORT_SIZE; break; case 'v': sort_opts= SORT_VERSION; break; case 'X': sort_opts= SORT_EXT; break;#endif#ifdef BB_FEATURE_LS_TIMESTAMPS case 'e': list_fmt |= LIST_FULLTIME; break; case 'c': time_fmt = TIME_CHANGE;#ifdef BB_FEATURE_LS_SORTFILES sort_opts= SORT_CTIME;#endif break; case 'u': time_fmt = TIME_ACCESS;#ifdef BB_FEATURE_LS_SORTFILES sort_opts= SORT_ATIME;#endif break; case 't':#ifdef BB_FEATURE_LS_SORTFILES sort_opts= SORT_MTIME;#endif break;#endif#ifdef BB_FEATURE_LS_FOLLOWLINKS case 'L': follow_links= TRUE; break;#endif#ifdef BB_FEATURE_AUTOWIDTH case 'T': tabstops= atoi(optarg); break; case 'w': terminal_width= atoi(optarg); break;#endif#ifdef BB_FEATURE_HUMAN_READABLE case 'h': ls_disp_hr = TRUE; break;#endif case 'k': break; default: goto print_usage_message; } } /* sort out which command line options take precedence */#ifdef BB_FEATURE_LS_RECURSIVE if (disp_opts & DISP_NOLIST) disp_opts &= ~DISP_RECURSIVE; /* no recurse if listing only dir */#endif#if defined (BB_FEATURE_LS_TIMESTAMPS) && defined (BB_FEATURE_LS_SORTFILES) if (time_fmt & TIME_CHANGE) sort_opts= SORT_CTIME; if (time_fmt & TIME_ACCESS) sort_opts= SORT_ATIME;#endif if (style_fmt != STYLE_LONG) list_fmt &= ~LIST_ID_NUMERIC; /* numeric uid only for long list */#ifdef BB_FEATURE_LS_USERNAME if (style_fmt == STYLE_LONG && (list_fmt & LIST_ID_NUMERIC)) list_fmt &= ~LIST_ID_NAME; /* don't list names if numeric uid */#endif /* choose a display format */ if (style_fmt == STYLE_AUTO) style_fmt = isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE; /* * when there are no cmd line args we have to supply a default "." arg. * we will create a second argv array, "av" that will hold either * our created "." arg, or the real cmd line args. The av array * just holds the pointers- we don't move the date the pointers * point to. */ ac= argc - optind; /* how many cmd line args are left */ if (ac < 1) { av= (char **)xcalloc((size_t)1, (size_t)(sizeof(char *))); av[0]= xstrdup("."); ac=1; } else { av= (char **)xcalloc((size_t)ac, (size_t)(sizeof(char *))); for (oi=0 ; oi < ac; oi++) { av[oi]= argv[optind++]; /* copy pointer to real cmd line arg */ } } /* now, everything is in the av array */ if (ac > 1) disp_opts |= DISP_DIRNAME; /* 2 or more items? label directories */ /* stuff the command line file names into an dnode array */ dn=NULL; for (oi=0 ; oi < ac; oi++) { cur= (struct dnode *)xmalloc(sizeof(struct dnode)); cur->fullname= xstrdup(av[oi]); cur->name= cur->fullname; if (my_stat(cur)) continue; cur->next= dn; dn= cur; nfiles++; } /* now that we know how many files there are ** allocate memory for an array to hold dnode pointers */ dnp= dnalloc(nfiles); for (i=0, cur=dn; i<nfiles; i++) { dnp[i]= cur; /* save pointer to node in array */ cur= cur->next; } if (disp_opts & DISP_NOLIST) {#ifdef BB_FEATURE_LS_SORTFILES shellsort(dnp, nfiles);#endif if (nfiles > 0) showfiles(dnp, nfiles); } else { dnd= splitdnarray(dnp, nfiles, SPLIT_DIR); dnf= splitdnarray(dnp, nfiles, SPLIT_FILE); dndirs= countdirs(dnp, nfiles); dnfiles= nfiles - dndirs; if (dnfiles > 0) {#ifdef BB_FEATURE_LS_SORTFILES shellsort(dnf, dnfiles);#endif showfiles(dnf, dnfiles); } if (dndirs > 0) {#ifdef BB_FEATURE_LS_SORTFILES shellsort(dnd, dndirs);#endif showdirs(dnd, dndirs); } } return(status); print_usage_message: show_usage();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -