17aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley/* ls.c - list files 23d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley * 33d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley * Copyright 2012 Andre Renaud <andre@bluewatersys.com> 4eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley * Copyright 2012 Rob Landley <rob@landley.net> 53d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley * 6f91b7c89bc852868692b9518185421ebb52d67b3Rob Landley * See http://opengroup.org/onlinepubs/9699919799/utilities/ls.html 73d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley 88565668d785d25f6dfd2dd19cece502cedf178b6Elliott HughesUSE_LS(NEWTOY(ls, USE_LS_COLOR("(color):;")USE_LS_Z("Z")"goACFHLRSacdfiklmnpqrstux1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL]", TOYFLAG_BIN|TOYFLAG_LOCALE)) 93d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley 103d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landleyconfig LS 117aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley bool "ls" 127aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley default y 137aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley help 147aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley usage: ls [-ACFHLRSacdfiklmnpqrstux1] [directory...] 157aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley list files 167aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 177aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley what to show: 1853b47708a7852dd9dc15b981888afec42cd0d591Rob Landley -a all files including .hidden -c use ctime for timestamps 1953b47708a7852dd9dc15b981888afec42cd0d591Rob Landley -d directory, not contents -i inode number 2053b47708a7852dd9dc15b981888afec42cd0d591Rob Landley -k block sizes in kilobytes -p put a '/' after dir names 2153b47708a7852dd9dc15b981888afec42cd0d591Rob Landley -q unprintable chars as '?' -s size (in blocks) 2253b47708a7852dd9dc15b981888afec42cd0d591Rob Landley -u use access time for timestamps -A list all files but . and .. 2353b47708a7852dd9dc15b981888afec42cd0d591Rob Landley -H follow command line symlinks -L follow symlinks 2453b47708a7852dd9dc15b981888afec42cd0d591Rob Landley -R recursively list files in subdirs -F append /dir *exe @sym |FIFO 257aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 267aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley output formats: 2753b47708a7852dd9dc15b981888afec42cd0d591Rob Landley -1 list one file per line -C columns (sorted vertically) 2853b47708a7852dd9dc15b981888afec42cd0d591Rob Landley -g like -l but no owner -l long (show full details) 2953b47708a7852dd9dc15b981888afec42cd0d591Rob Landley -m comma separated -n like -l but numeric uid/gid 3053b47708a7852dd9dc15b981888afec42cd0d591Rob Landley -o like -l but no group -x columns (horizontal sort) 317aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 327aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley sorting (default is alphabetical): 3353b47708a7852dd9dc15b981888afec42cd0d591Rob Landley -f unsorted -r reverse -t timestamp -S size 3412a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley 358565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughesconfig LS_Z 36491e3e3f1c654f689de0f8cbd3b05559fd65c568Rob Landley bool 37e94931034578707958fecb7f34dcd3a0a175eaf7Jan Cybulski default y 388565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes depends on LS && (TOYBOX_SELINUX || TOYBOX_SMACK) 39e94931034578707958fecb7f34dcd3a0a175eaf7Jan Cybulski help 40e94931034578707958fecb7f34dcd3a0a175eaf7Jan Cybulski usage: ls [-Z] 41e94931034578707958fecb7f34dcd3a0a175eaf7Jan Cybulski 42e94931034578707958fecb7f34dcd3a0a175eaf7Jan Cybulski -Z security context 43e94931034578707958fecb7f34dcd3a0a175eaf7Jan Cybulski 4412a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landleyconfig LS_COLOR 4512a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley bool "ls --color" 4612a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley default y 47b2bc38289143c52dee88ce3b0187aba091f668c6Rob Landley depends on LS 4812a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley help 49408d4f2670df910180988747f11b6290551ddaa7Rob Landley usage: ls --color[=auto] 5012a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley 5112a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley --color device=yellow symlink=turquoise/red dir=blue socket=purple 5212a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley files: exe=green suid=red suidfile=redback stickydir=greenback 53408d4f2670df910180988747f11b6290551ddaa7Rob Landley =auto means detect if output is a tty. 543d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley*/ 553d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley 56c0e56edaf256adb6c60c5a052525a1ffbb927901Rob Landley#define FOR_ls 573d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley#include "toys.h" 583d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley 59eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley// test sst output (suid/sticky in ls flaglist) 60eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 61eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley// ls -lR starts .: then ./subdir: 62eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 63c0e56edaf256adb6c60c5a052525a1ffbb927901Rob LandleyGLOBALS( 64408d4f2670df910180988747f11b6290551ddaa7Rob Landley char *color; 65408d4f2670df910180988747f11b6290551ddaa7Rob Landley 667aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley struct dirtree *files; 67eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 687aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley unsigned screen_width; 697aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley int nl_title; 7001f828d9d80ce2ad80e21638fece083f924318a9Rob Landley char uid_buf[12], gid_buf[12]; 71eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley) 72eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 738fb779954829f923ee2935d81cd4446973aaa01fRob Landley// Does two things: 1) Returns wcwidth(utf8) version of strlen, 748fb779954829f923ee2935d81cd4446973aaa01fRob Landley// 2) replaces unprintable characters input string with '?' wildcard char. 758fb779954829f923ee2935d81cd4446973aaa01fRob Landleyint strwidth(char *s) 768fb779954829f923ee2935d81cd4446973aaa01fRob Landley{ 778fb779954829f923ee2935d81cd4446973aaa01fRob Landley int total = 0, width, len; 788fb779954829f923ee2935d81cd4446973aaa01fRob Landley wchar_t c; 798fb779954829f923ee2935d81cd4446973aaa01fRob Landley 808fb779954829f923ee2935d81cd4446973aaa01fRob Landley if (!CFG_TOYBOX_I18N) { 818fb779954829f923ee2935d81cd4446973aaa01fRob Landley total = strlen(s); 828fb779954829f923ee2935d81cd4446973aaa01fRob Landley if (toys.optflags & FLAG_q) for (; *s; s++) if (!isprint(*s)) *s = '?'; 838fb779954829f923ee2935d81cd4446973aaa01fRob Landley } else while (*s) { 848fb779954829f923ee2935d81cd4446973aaa01fRob Landley len = mbrtowc(&c, s, MB_CUR_MAX, 0); 858fb779954829f923ee2935d81cd4446973aaa01fRob Landley if (len < 1 || (width = wcwidth(c)) < 0) { 868fb779954829f923ee2935d81cd4446973aaa01fRob Landley total++; 8731db579265fa9e0acea036faa486be26f508e67aRob Landley if (toys.optflags & FLAG_q) *s = '?'; 8831db579265fa9e0acea036faa486be26f508e67aRob Landley s++; 8931db579265fa9e0acea036faa486be26f508e67aRob Landley } else { 9031db579265fa9e0acea036faa486be26f508e67aRob Landley s += len; 9131db579265fa9e0acea036faa486be26f508e67aRob Landley total += width; 928fb779954829f923ee2935d81cd4446973aaa01fRob Landley } 938fb779954829f923ee2935d81cd4446973aaa01fRob Landley } 948fb779954829f923ee2935d81cd4446973aaa01fRob Landley 958fb779954829f923ee2935d81cd4446973aaa01fRob Landley return total; 968fb779954829f923ee2935d81cd4446973aaa01fRob Landley} 978fb779954829f923ee2935d81cd4446973aaa01fRob Landley 98eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landleystatic char endtype(struct stat *st) 993d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley{ 1007aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley mode_t mode = st->st_mode; 1017aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if ((toys.optflags&(FLAG_F|FLAG_p)) && S_ISDIR(mode)) return '/'; 1027aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (toys.optflags & FLAG_F) { 1037aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (S_ISLNK(mode)) return '@'; 1047aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (S_ISREG(mode) && (mode&0111)) return '*'; 1057aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (S_ISFIFO(mode)) return '|'; 1067aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (S_ISSOCK(mode)) return '='; 1077aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 1087aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley return 0; 109eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley} 110eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 111eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landleystatic char *getusername(uid_t uid) 112eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley{ 1137aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley struct passwd *pw = getpwuid(uid); 11401f828d9d80ce2ad80e21638fece083f924318a9Rob Landley 11501f828d9d80ce2ad80e21638fece083f924318a9Rob Landley sprintf(TT.uid_buf, "%u", (unsigned)uid); 1167aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley return pw ? pw->pw_name : TT.uid_buf; 117eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley} 118eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 119eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landleystatic char *getgroupname(gid_t gid) 120eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley{ 1217aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley struct group *gr = getgrgid(gid); 12201f828d9d80ce2ad80e21638fece083f924318a9Rob Landley 12301f828d9d80ce2ad80e21638fece083f924318a9Rob Landley sprintf(TT.gid_buf, "%u", (unsigned)gid); 12401f828d9d80ce2ad80e21638fece083f924318a9Rob Landley return gr ? gr->gr_name : TT.gid_buf; 1253d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley} 1263d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley 1272b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landleystatic int numlen(long long ll) 1282b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley{ 1292b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley return snprintf(0, 0, "%llu", ll); 1302b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley} 1312b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley 1328565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes// measure/print SELinux/smack security label. (If pad=0, just measure.) 1338565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughesstatic unsigned seclabel(struct dirtree *dt, int pad) 134491e3e3f1c654f689de0f8cbd3b05559fd65c568Rob Landley{ 1358565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes if (CFG_TOYBOX_SELINUX) { 1368565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes char* path = dirtree_path(dt, 0); 1378565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes char* label = 0; 1388565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes size_t len; 1398565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes 1408565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes lgetfilecon(path, &label); 1418565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes if (!label) { 1428565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes label = strdup("?"); 1438565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes } 144491e3e3f1c654f689de0f8cbd3b05559fd65c568Rob Landley 1458565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes len = strlen(label); 1468565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes if (pad) printf(" %*s "+(pad>0), pad, label); 147491e3e3f1c654f689de0f8cbd3b05559fd65c568Rob Landley 1488565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes free(label); 1498565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes free(path); 1508565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes return len; 1518565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes } else if (CFG_TOYBOX_SMACK) { 1528565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes int fd = openat(dirtree_parentfd(dt), dt->name, O_PATH|O_NOFOLLOW); 1538565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes char buf[SMACK_LABEL_LEN+1]; 1548565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes ssize_t len = 1; 1558565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes 1568565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes strcpy(buf, "?"); 1578565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes if (fd != -1) { 1588565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes len = fgetxattr(fd, XATTR_NAME_SMACK, pad?buf:0, pad?SMACK_LABEL_LEN:0); 1598565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes close(fd); 1608565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes 1618565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes if (len<1 || len>SMACK_LABEL_LEN) len = 0; 1628565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes else buf[len] = 0; 1638565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes } 1648565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes if (pad) printf(" %*s "+(pad>0), pad, buf); 165491e3e3f1c654f689de0f8cbd3b05559fd65c568Rob Landley 1668565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes return len; 1678565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes } 168491e3e3f1c654f689de0f8cbd3b05559fd65c568Rob Landley} 169491e3e3f1c654f689de0f8cbd3b05559fd65c568Rob Landley 170eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley// Figure out size of printable entry fields for display indent/wrap 171eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 172eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landleystatic void entrylen(struct dirtree *dt, unsigned *len) 1733d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley{ 1747aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley struct stat *st = &(dt->st); 1757aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley unsigned flags = toys.optflags; 1767aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 1778fb779954829f923ee2935d81cd4446973aaa01fRob Landley *len = strwidth(dt->name); 1787aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (endtype(st)) ++*len; 1797aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (flags & FLAG_m) ++*len; 1807aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 1812b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley len[1] = (flags & FLAG_i) ? numlen(st->st_ino) : 0; 1827aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) { 1837aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley unsigned fn = flags & FLAG_n; 1847aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley len[2] = numlen(st->st_nlink); 1852b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley len[3] = fn ? numlen(st->st_uid) : strwidth(getusername(st->st_uid)); 1862b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley len[4] = fn ? numlen(st->st_gid) : strwidth(getgroupname(st->st_gid)); 187876903c5e063431091fd3f9a2e01b496e88950d4Rob Landley if (S_ISBLK(st->st_mode) || S_ISCHR(st->st_mode)) { 188876903c5e063431091fd3f9a2e01b496e88950d4Rob Landley // cheating slightly here: assuming minor is always 3 digits to avoid 189876903c5e063431091fd3f9a2e01b496e88950d4Rob Landley // tracking another column 190876903c5e063431091fd3f9a2e01b496e88950d4Rob Landley len[5] = numlen(major(st->st_rdev))+5; 191876903c5e063431091fd3f9a2e01b496e88950d4Rob Landley } else len[5] = numlen(st->st_size); 1927aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 1932b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley 1942b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley len[6] = (flags & FLAG_s) ? numlen(st->st_blocks) : 0; 195b18c7e8a59e61b8ec49e2d0f8cb2dda19b8f6a82Rob Landley len[7] = (CFG_LS_Z && (flags & FLAG_Z)) ? seclabel(dt, 0) : 0; 196eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley} 197eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 198eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landleystatic int compare(void *a, void *b) 199eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley{ 2007aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley struct dirtree *dta = *(struct dirtree **)a; 2017aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley struct dirtree *dtb = *(struct dirtree **)b; 2027aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley int ret = 0, reverse = (toys.optflags & FLAG_r) ? -1 : 1; 2037aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 2047aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (toys.optflags & FLAG_S) { 2057aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (dta->st.st_size > dtb->st.st_size) ret = -1; 2067aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley else if (dta->st.st_size < dtb->st.st_size) ret = 1; 2077aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 2087aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (toys.optflags & FLAG_t) { 2097aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (dta->st.st_mtime > dtb->st.st_mtime) ret = -1; 2107aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley else if (dta->st.st_mtime < dtb->st.st_mtime) ret = 1; 2117aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 2127aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (!ret) ret = strcmp(dta->name, dtb->name); 2137aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley return ret * reverse; 214eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley} 2153d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley 2169b3af46b888a57c2183545455e2de1cb457d9f2aRob Landley// callback from dirtree_recurse() determining how to handle this entry. 2179b3af46b888a57c2183545455e2de1cb457d9f2aRob Landley 218eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landleystatic int filter(struct dirtree *new) 219eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley{ 2207aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley int flags = toys.optflags; 221eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 2227aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Special case to handle enormous dirs without running out of memory. 2237aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (flags == (FLAG_1|FLAG_f)) { 2247aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley xprintf("%s\n", new->name); 2257aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley return 0; 2267aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 227eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 2287aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (flags & FLAG_u) new->st.st_mtime = new->st.st_atime; 2297aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (flags & FLAG_c) new->st.st_mtime = new->st.st_ctime; 2307aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (flags & FLAG_k) new->st.st_blocks = (new->st.st_blocks + 1) / 2; 23185dd282b08eb378b4b8cc275f96226dc2c151216Rob Landley 2327aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (flags & (FLAG_a|FLAG_f)) return DIRTREE_SAVE; 2337aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (!(flags & FLAG_A) && new->name[0]=='.') return 0; 23485dd282b08eb378b4b8cc275f96226dc2c151216Rob Landley 2357aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley return dirtree_notdotdot(new) & DIRTREE_SAVE; 236eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley} 237eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 23844785cd0821e909b1086c2368fe5d5bf742eca6fRob Landley// For column view, calculate horizontal position (for padding) and return 23944785cd0821e909b1086c2368fe5d5bf742eca6fRob Landley// index of next entry to display. 24044785cd0821e909b1086c2368fe5d5bf742eca6fRob Landley 24144785cd0821e909b1086c2368fe5d5bf742eca6fRob Landleystatic unsigned long next_column(unsigned long ul, unsigned long dtlen, 2427aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley unsigned columns, unsigned *xpos) 24344785cd0821e909b1086c2368fe5d5bf742eca6fRob Landley{ 2447aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley unsigned long transition; 2457aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley unsigned height, widecols; 24644785cd0821e909b1086c2368fe5d5bf742eca6fRob Landley 2477aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Horizontal sort is easy 2487aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (!(toys.optflags & FLAG_C)) { 2497aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley *xpos = ul % columns; 2507aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley return ul; 2517aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 25244785cd0821e909b1086c2368fe5d5bf742eca6fRob Landley 2537aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // vertical sort 25444785cd0821e909b1086c2368fe5d5bf742eca6fRob Landley 2557aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // For -x, calculate height of display, rounded up 2567aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley height = (dtlen+columns-1)/columns; 25744785cd0821e909b1086c2368fe5d5bf742eca6fRob Landley 2587aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Sanity check: does wrapping render this column count impossible 2597aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // due to the right edge wrapping eating a whole row? 2607aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (height*columns - dtlen >= height) { 2617aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley *xpos = columns; 2627aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley return 0; 2637aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 26444785cd0821e909b1086c2368fe5d5bf742eca6fRob Landley 2657aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Uneven rounding goes along right edge 2667aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley widecols = dtlen % height; 2677aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (!widecols) widecols = height; 2687aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley transition = widecols * columns; 2697aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (ul < transition) { 2707aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley *xpos = ul % columns; 2717aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley return (*xpos*height) + (ul/columns); 2727aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 27344785cd0821e909b1086c2368fe5d5bf742eca6fRob Landley 2747aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley ul -= transition; 2757aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley *xpos = ul % (columns-1); 27644785cd0821e909b1086c2368fe5d5bf742eca6fRob Landley 2777aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley return (*xpos*height) + widecols + (ul/(columns-1)); 27844785cd0821e909b1086c2368fe5d5bf742eca6fRob Landley} 27944785cd0821e909b1086c2368fe5d5bf742eca6fRob Landley 28012a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landleyint color_from_mode(mode_t mode) 28112a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley{ 28212a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley int color = 0; 28312a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley 28412a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley if (S_ISDIR(mode)) color = 256+34; 28512a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley else if (S_ISLNK(mode)) color = 256+36; 28612a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley else if (S_ISBLK(mode) || S_ISCHR(mode)) color = 256+33; 28712a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley else if (S_ISREG(mode) && (mode&0111)) color = 256+32; 28812a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley else if (S_ISFIFO(mode)) color = 33; 28912a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley else if (S_ISSOCK(mode)) color = 256+35; 29012a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley 29112a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley return color; 29212a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley} 29312a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley 294eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley// Display a list of dirtree entries, according to current format 295eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley// Output types -1, -l, -C, or stream 2963d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley 297f3b4a916525c6658e71def23ee37532b0313b663Rob Landleystatic void listfiles(int dirfd, struct dirtree *indir) 298eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley{ 2995e18bae30a80d6149e47d9adb1acb3a64bac7c08Rob Landley struct dirtree *dt, **sort; 3005e18bae30a80d6149e47d9adb1acb3a64bac7c08Rob Landley unsigned long dtlen, ul = 0; 301e94931034578707958fecb7f34dcd3a0a175eaf7Jan Cybulski unsigned width, flags = toys.optflags, totals[8], len[8], totpad = 0, 3027aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley *colsizes = (unsigned *)(toybuf+260), columns = (sizeof(toybuf)-260)/4; 3037aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 3047aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley memset(totals, 0, sizeof(totals)); 3057aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 3067aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Silently descend into single directory listed by itself on command line. 3077aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // In this case only show dirname/total header when given -R. 3087aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (!indir->parent) { 3097aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (!(dt = indir->child)) return; 3107aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (S_ISDIR(dt->st.st_mode) && !dt->next && !(flags & FLAG_d)) { 3117aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley dt->extra = 1; 3127aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley listfiles(open(dt->name, 0), dt); 313b18c7e8a59e61b8ec49e2d0f8cb2dda19b8f6a82Rob Landley 3147aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley return; 315eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley } 3167aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } else { 3177aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Read directory contents. We dup() the fd because this will close it. 3187aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley indir->data = dup(dirfd); 3191f5f436826505df6dfabe1de9724424fc40fae23Rob Landley dirtree_recurse(indir, filter, DIRTREE_SYMFOLLOW*!!(flags&FLAG_L)); 3207aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 3217aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 3227aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Copy linked list to array and sort it. Directories go in array because 3235e18bae30a80d6149e47d9adb1acb3a64bac7c08Rob Landley // we visit them in sorted order too. (The nested loops let us measure and 3245e18bae30a80d6149e47d9adb1acb3a64bac7c08Rob Landley // fill with the same inner loop.) 325b18c7e8a59e61b8ec49e2d0f8cb2dda19b8f6a82Rob Landley for (sort = 0;;sort = xmalloc(dtlen*sizeof(void *))) { 3265e18bae30a80d6149e47d9adb1acb3a64bac7c08Rob Landley for (dtlen = 0, dt = indir->child; dt; dt = dt->next, dtlen++) 3277aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (sort) sort[dtlen] = dt; 3287aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (sort) break; 3297aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 3307aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 3317aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Label directory if not top of tree, or if -R 3327aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (indir->parent && (!indir->extra || (flags & FLAG_R))) 3337aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley { 3347aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley char *path = dirtree_path(indir, 0); 3357aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 3367aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (TT.nl_title++) xputc('\n'); 3377aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley xprintf("%s:\n", path); 3387aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley free(path); 3397aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 3407aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 3415e18bae30a80d6149e47d9adb1acb3a64bac7c08Rob Landley // Measure each entry to work out whitespace padding and total blocks 3422b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley if (!(flags & FLAG_f)) { 3432b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley unsigned long long blocks = 0; 3442b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley 3452b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley qsort(sort, dtlen, sizeof(void *), (void *)compare); 3462b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley for (ul = 0; ul<dtlen; ul++) { 3472b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley entrylen(sort[ul], len); 348e94931034578707958fecb7f34dcd3a0a175eaf7Jan Cybulski for (width = 0; width<8; width++) 3492b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley if (len[width]>totals[width]) totals[width] = len[width]; 3502b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley blocks += sort[ul]->st.st_blocks; 3512b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley } 3525e18bae30a80d6149e47d9adb1acb3a64bac7c08Rob Landley totpad = totals[1]+!!totals[1]+totals[6]+!!totals[6]+totals[7]+!!totals[7]; 3532b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g|FLAG_s) && indir->parent) 3542b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley xprintf("total %llu\n", blocks); 3552b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley } 3567aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 3577aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Find largest entry in each field for display alignment 3587aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (flags & (FLAG_C|FLAG_x)) { 3597aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 3607aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // columns can't be more than toybuf can hold, or more than files, 3617aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // or > 1/2 screen width (one char filename, one space). 3627aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (columns > TT.screen_width/2) columns = TT.screen_width/2; 3637aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (columns > dtlen) columns = dtlen; 3647aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 3657aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Try to fit as many columns as we can, dropping down by one each time 3667aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley for (;columns > 1; columns--) { 3677aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley unsigned c, totlen = columns; 3687aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 3697aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley memset(colsizes, 0, columns*sizeof(unsigned)); 3707aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley for (ul=0; ul<dtlen; ul++) { 3717aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley entrylen(sort[next_column(ul, dtlen, columns, &c)], len); 3722b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley *len += totpad; 3737aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (c == columns) break; 3742b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley // Expand this column if necessary, break if that puts us over budget 3757aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (*len > colsizes[c]) { 3762b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley totlen += (*len)-colsizes[c]; 3777aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley colsizes[c] = *len; 3787aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (totlen > TT.screen_width) break; 3793d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley } 3807aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 3812b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley // If everything fit, stop here 3827aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (ul == dtlen) break; 3833d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley } 3847aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 385da5aa3a09667a84779f3af077e725daa747737fdRob Landley 3867aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Loop through again to produce output. 3877aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley memset(toybuf, ' ', 256); 3887aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley width = 0; 3897aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley for (ul = 0; ul<dtlen; ul++) { 39012a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley unsigned curcol, color = 0; 3917aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley unsigned long next = next_column(ul, dtlen, columns, &curcol); 3927aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley struct stat *st = &(sort[next]->st); 3937aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley mode_t mode = st->st_mode; 3947aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley char et = endtype(st); 3957aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 3967aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Skip directories at the top of the tree when -d isn't set 3977aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (S_ISDIR(mode) && !indir->parent && !(flags & FLAG_d)) continue; 3987aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley TT.nl_title=1; 3997aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 4007aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Handle padding and wrapping for display purposes 4017aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley entrylen(sort[next], len); 4027aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (ul) { 4037aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (flags & FLAG_m) xputc(','); 4047aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (flags & (FLAG_C|FLAG_x)) { 4057aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (!curcol) xputc('\n'); 4067aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } else if ((flags & FLAG_1) || width+1+*len > TT.screen_width) { 4077aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley xputc('\n'); 4087aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley width = 0; 4097aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } else { 4107aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley xputc(' '); 4117aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley width++; 4127aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 4137aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 4147aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley width += *len; 41544785cd0821e909b1086c2368fe5d5bf742eca6fRob Landley 4162b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley if (flags & FLAG_i) 4172b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley xprintf("%*lu ", totals[1], (unsigned long)st->st_ino); 4182b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley if (flags & FLAG_s) 4192b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley xprintf("%*lu ", totals[6], (unsigned long)st->st_blocks); 420f3b4a916525c6658e71def23ee37532b0313b663Rob Landley 4217aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) { 4227aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley struct tm *tm; 4235a221e6b84e9eab02e24ca541530e28eb7cfddacFelix Janda char perm[11], thyme[64], *usr, *upad, *grp, *grpad; 4247aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 4255a26a86cec424d728d43523988ca70aa56ee76c9Rob Landley mode_to_string(mode, perm); 4267aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 4277aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (flags&FLAG_o) grp = grpad = toybuf+256; 4287aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley else { 4298fb779954829f923ee2935d81cd4446973aaa01fRob Landley if (flags&FLAG_n) sprintf(grp = thyme, "%u", (unsigned)st->st_gid); 4308fb779954829f923ee2935d81cd4446973aaa01fRob Landley else strwidth(grp = getgroupname(st->st_gid)); 4317aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley grpad = toybuf+256-(totals[4]-len[4]); 4327aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 4337aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 4347aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (flags&FLAG_g) usr = upad = toybuf+256; 4357aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley else { 4367aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley upad = toybuf+255-(totals[3]-len[3]); 43701f828d9d80ce2ad80e21638fece083f924318a9Rob Landley if (flags&FLAG_n) sprintf(usr = TT.uid_buf, "%u", (unsigned)st->st_uid); 4388fb779954829f923ee2935d81cd4446973aaa01fRob Landley else strwidth(usr = getusername(st->st_uid)); 4397aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 4407aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 4417aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Coerce the st types into something we know we can print. 442876903c5e063431091fd3f9a2e01b496e88950d4Rob Landley printf("%s% *ld %s%s%s%s", perm, totals[2]+1, (long)st->st_nlink, 443876903c5e063431091fd3f9a2e01b496e88950d4Rob Landley usr, upad, grp, grpad); 444876903c5e063431091fd3f9a2e01b496e88950d4Rob Landley 4458565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes if (CFG_LS_Z && (flags & FLAG_Z)) seclabel(sort[next], -(int)totals[7]); 446e94931034578707958fecb7f34dcd3a0a175eaf7Jan Cybulski 447876903c5e063431091fd3f9a2e01b496e88950d4Rob Landley if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) 448876903c5e063431091fd3f9a2e01b496e88950d4Rob Landley printf("% *d,% 4d", totals[5]-4, major(st->st_rdev),minor(st->st_rdev)); 4495e18bae30a80d6149e47d9adb1acb3a64bac7c08Rob Landley else printf("% *lld", totals[5]+1, (long long)st->st_size); 45001f828d9d80ce2ad80e21638fece083f924318a9Rob Landley 45101f828d9d80ce2ad80e21638fece083f924318a9Rob Landley tm = localtime(&(st->st_mtime)); 45201f828d9d80ce2ad80e21638fece083f924318a9Rob Landley strftime(thyme, sizeof(thyme), "%F %H:%M", tm); 453876903c5e063431091fd3f9a2e01b496e88950d4Rob Landley xprintf(" %s ", thyme); 4548565668d785d25f6dfd2dd19cece502cedf178b6Elliott Hughes } else if (CFG_LS_Z && (flags & FLAG_Z)) seclabel(sort[next], totals[7]); 455f3b4a916525c6658e71def23ee37532b0313b663Rob Landley 456408d4f2670df910180988747f11b6290551ddaa7Rob Landley if (flags & FLAG_color) { 45712a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley color = color_from_mode(st->st_mode); 45812a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley if (color) printf("\033[%d;%dm", color>>8, color&255); 45912a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley } 46012a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley 4617aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (flags & FLAG_q) { 4627aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley char *p; 4638fb779954829f923ee2935d81cd4446973aaa01fRob Landley for (p=sort[next]->name; *p; p++) fputc(isprint(*p) ? *p : '?', stdout); 4647aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } else xprintf("%s", sort[next]->name); 46512a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley if (color) xprintf("\033[0m"); 46612a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley 46712a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley if ((flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) && S_ISLNK(mode)) { 46812a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley printf(" -> "); 469408d4f2670df910180988747f11b6290551ddaa7Rob Landley if (flags & FLAG_color) { 47012a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley struct stat st2; 47112a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley 47212a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley if (fstatat(dirfd, sort[next]->symlink, &st2, 0)) color = 256+31; 47312a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley else color = color_from_mode(st2.st_mode); 47412a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley 47512a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley if (color) printf("\033[%d;%dm", color>>8, color&255); 47612a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley } 47712a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley 47812a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley printf("%s", sort[next]->symlink); 47912a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley if (color) printf("\033[0m"); 48012a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley } 481eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 4827aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (et) xputc(et); 483eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 4847aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Pad columns 4857aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (flags & (FLAG_C|FLAG_x)) { 4862b8a6f636854e2b07c7ba9bedcbbd275e27b69bdRob Landley curcol = colsizes[curcol]-(*len)-totpad; 487302d9d3e5138e950487dd22ab9e8b1d32a67456cRob Landley if (curcol < 255) xprintf("%s", toybuf+255-curcol); 4883d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley } 4897aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 490eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 4917aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (width) xputc('\n'); 492eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 4937aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Free directory entries, recursing first if necessary. 4947792f8f65310f5eecac79df8ce0a0cb5e0d83ea8Rob Landley 4957aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley for (ul = 0; ul<dtlen; free(sort[ul++])) { 4967aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if ((flags & FLAG_d) || !S_ISDIR(sort[ul]->st.st_mode) 4977aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley || !dirtree_notdotdot(sort[ul])) continue; 4987792f8f65310f5eecac79df8ce0a0cb5e0d83ea8Rob Landley 4997aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Recurse into dirs if at top of the tree or given -R 5007aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (!indir->parent || (flags & FLAG_R)) 5017aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley listfiles(openat(dirfd, sort[ul]->name, 0), sort[ul]); 5027aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 5037aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley free(sort); 50412a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley if (dirfd != AT_FDCWD) close(dirfd); 5053d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley} 5063d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley 5073d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landleyvoid ls_main(void) 5083d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley{ 5097aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley char **s, *noargs[] = {".", 0}; 5107aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley struct dirtree *dt; 5117aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 51212a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley TT.screen_width = 80; 51312a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley terminal_size(&TT.screen_width, NULL); 51412a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley if (TT.screen_width<2) TT.screen_width = 2; 51512a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley 5167aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Do we have an implied -1 517408d4f2670df910180988747f11b6290551ddaa7Rob Landley if (!isatty(1)) { 518408d4f2670df910180988747f11b6290551ddaa7Rob Landley toys.optflags |= FLAG_1; 519408d4f2670df910180988747f11b6290551ddaa7Rob Landley if (TT.color) toys.optflags ^= FLAG_color; 520408d4f2670df910180988747f11b6290551ddaa7Rob Landley } else if (toys.optflags&(FLAG_l|FLAG_o|FLAG_n|FLAG_g)) 5217aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley toys.optflags |= FLAG_1; 52212a4d74fb8813ad17a480732415d8ffc478d3ab3Rob Landley else if (!(toys.optflags&(FLAG_1|FLAG_x|FLAG_m))) toys.optflags |= FLAG_C; 5237aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // The optflags parsing infrastructure should really do this for us, 5247aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // but currently it has "switch off when this is set", so "-dR" and "-Rd" 5257aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // behave differently 5267aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (toys.optflags & FLAG_d) toys.optflags &= ~FLAG_R; 5277aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 5287aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Iterate through command line arguments, collecting directories and files. 5297aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Non-absolute paths are relative to current directory. 530aab9164df395a4b0878b0ad930a5ec8a806a58e9Rob Landley TT.files = dirtree_start(0, 0); 5317aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley for (s = *toys.optargs ? toys.optargs : noargs; *s; s++) { 532aab9164df395a4b0878b0ad930a5ec8a806a58e9Rob Landley dt = dirtree_start(*s, !(toys.optflags&(FLAG_l|FLAG_d|FLAG_F)) || 533aab9164df395a4b0878b0ad930a5ec8a806a58e9Rob Landley (toys.optflags&(FLAG_L|FLAG_H))); 5347aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 535b18c7e8a59e61b8ec49e2d0f8cb2dda19b8f6a82Rob Landley // note: double_list->prev temporarirly goes in dirtree->parent 536b18c7e8a59e61b8ec49e2d0f8cb2dda19b8f6a82Rob Landley if (dt) dlist_add_nomalloc((void *)&TT.files->child, (void *)dt); 537b18c7e8a59e61b8ec49e2d0f8cb2dda19b8f6a82Rob Landley else toys.exitval = 1; 5387aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 539eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 540b18c7e8a59e61b8ec49e2d0f8cb2dda19b8f6a82Rob Landley // Convert double_list into dirtree. 541b18c7e8a59e61b8ec49e2d0f8cb2dda19b8f6a82Rob Landley dlist_terminate(TT.files->child); 542b18c7e8a59e61b8ec49e2d0f8cb2dda19b8f6a82Rob Landley for (dt = TT.files->child; dt; dt = dt->next) dt->parent = TT.files; 543eb7ea22c7505f10928e104a9df39edc70a8f7036Rob Landley 5447aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Display the files we collected 5457aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley listfiles(AT_FDCWD, TT.files); 5469b3af46b888a57c2183545455e2de1cb457d9f2aRob Landley 5477aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (CFG_TOYBOX_FREE) free(TT.files); 5483d8685b61d858a1fb3ade581129e3cc4e2efc94cRob Landley} 549