ls.c revision 9feee025a09ace19b09dbb41d6ba87198c77cdf1
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h> 5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <dirent.h> 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h> 7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h> 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h> 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <time.h> 11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <pwd.h> 13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <grp.h> 14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/kdev_t.h> 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// bits for flags argument 18b33d3415b6c63f7b22e0863a2ac594feab9171cfAndy McFadden#define LIST_LONG (1 << 0) 19b33d3415b6c63f7b22e0863a2ac594feab9171cfAndy McFadden#define LIST_ALL (1 << 1) 20b33d3415b6c63f7b22e0863a2ac594feab9171cfAndy McFadden#define LIST_RECURSIVE (1 << 2) 21b33d3415b6c63f7b22e0863a2ac594feab9171cfAndy McFadden#define LIST_DIRECTORIES (1 << 3) 22327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden#define LIST_SIZE (1 << 4) 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// fwd 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int listpath(const char *name, int flags); 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic char mode2kind(unsigned mode) 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project switch(mode & S_IFMT){ 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFSOCK: return 's'; 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFLNK: return 'l'; 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFREG: return '-'; 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFDIR: return 'd'; 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFBLK: return 'b'; 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFCHR: return 'c'; 36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFIFO: return 'p'; 37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project default: return '?'; 38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void mode2str(unsigned mode, char *out) 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = mode2kind(mode); 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 0400) ? 'r' : '-'; 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 0200) ? 'w' : '-'; 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(mode & 04000) { 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 0100) ? 's' : 'S'; 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 0100) ? 'x' : '-'; 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 040) ? 'r' : '-'; 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 020) ? 'w' : '-'; 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(mode & 02000) { 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 010) ? 's' : 'S'; 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 010) ? 'x' : '-'; 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 04) ? 'r' : '-'; 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 02) ? 'w' : '-'; 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(mode & 01000) { 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 01) ? 't' : 'T'; 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 01) ? 'x' : '-'; 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out = 0; 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void user2str(unsigned uid, char *out) 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct passwd *pw = getpwuid(uid); 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(pw) { 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strcpy(out, pw->pw_name); 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sprintf(out, "%d", uid); 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void group2str(unsigned gid, char *out) 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct group *gr = getgrgid(gid); 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(gr) { 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strcpy(out, gr->gr_name); 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sprintf(out, "%d", gid); 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 899feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFaddenstatic int show_total_size(const char *dirname, DIR *d, int flags) 90327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden{ 919feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden struct dirent *de; 929feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden char tmp[1024]; 93327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden struct stat s; 949feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden int sum = 0; 959feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden 969feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden /* run through the directory and sum up the file block sizes */ 979feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden while ((de = readdir(d)) != 0) { 989feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) 999feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden continue; 1009feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden if (de->d_name[0] == '.' && (flags & LIST_ALL) == 0) 1019feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden continue; 1029feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden 1039feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden if (strcmp(dirname, "/") == 0) 1049feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden snprintf(tmp, sizeof(tmp), "/%s", de->d_name); 1059feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden else 1069feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden snprintf(tmp, sizeof(tmp), "%s/%s", dirname, de->d_name); 1079feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden 1089feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden if (lstat(tmp, &s) < 0) { 1099feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden fprintf(stderr, "stat failed on %s: %s\n", tmp, strerror(errno)); 1109feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden rewinddir(d); 1119feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden return -1; 1129feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden } 1139feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden 1149feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden sum += s.st_blocks / 2; 1159feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden } 116327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden 1179feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden printf("total %d\n", sum); 1189feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden rewinddir(d); 1199feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden return 0; 1209feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden} 1219feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden 1229feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFaddenstatic int listfile_size(const char *path, const char *filename, int flags) 1239feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden{ 1249feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden struct stat s; 1259feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden 1269feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden if (lstat(path, &s) < 0) { 1279feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden fprintf(stderr, "lstat '%s' failed: %s\n", path, strerror(errno)); 128327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden return -1; 1299feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden } 130327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden 131327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden /* blocks are 512 bytes, we want output to be KB */ 1329feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden printf("%lld %s\n", s.st_blocks / 2, filename); 133327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden return 0; 134327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden} 135327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden 136327e696808910f8e49370079f8d7f4db8cbe3820Andy McFaddenstatic int listfile_long(const char *path, int flags) 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct stat s; 139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char date[32]; 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char mode[16]; 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char user[16]; 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char group[16]; 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const char *name; 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* name is anything after the final '/', or the whole path if none*/ 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project name = strrchr(path, '/'); 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(name == 0) { 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project name = path; 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project name++; 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(lstat(path, &s) < 0) { 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mode2str(s.st_mode, mode); 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project user2str(s.st_uid, user); 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project group2str(s.st_gid, group); 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strftime(date, 32, "%Y-%m-%d %H:%M", localtime((const time_t*)&s.st_mtime)); 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project date[31] = 0; 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// 12345678901234567890123456789012345678901234567890123456789012345678901234567890 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// MMMMMMMM UUUUUUUU GGGGGGGGG XXXXXXXX YYYY-MM-DD HH:MM NAME (->LINK) 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project switch(s.st_mode & S_IFMT) { 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFBLK: 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFCHR: 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf("%s %-8s %-8s %3d, %3d %s %s\n", 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mode, user, group, 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project (int) MAJOR(s.st_rdev), (int) MINOR(s.st_rdev), 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project date, name); 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFREG: 176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf("%s %-8s %-8s %8d %s %s\n", 177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mode, user, group, (int) s.st_size, date, name); 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFLNK: { 180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char linkto[256]; 181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int len; 182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len = readlink(path, linkto, 256); 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(len < 0) return -1; 185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(len > 255) { 187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project linkto[252] = '.'; 188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project linkto[253] = '.'; 189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project linkto[254] = '.'; 190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project linkto[255] = 0; 191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project linkto[len] = 0; 193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf("%s %-8s %-8s %s %s -> %s\n", 196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mode, user, group, date, name, linkto); 197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project default: 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf("%s %-8s %-8s %s %s\n", 201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mode, user, group, date, name); 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 207327e696808910f8e49370079f8d7f4db8cbe3820Andy McFaddenstatic int listfile(const char *dirname, const char *filename, int flags) 208327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden{ 209327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden if ((flags & (LIST_LONG | LIST_SIZE)) == 0) { 210327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden printf("%s\n", filename); 211327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden return 0; 212327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden } 213327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden 214327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden char tmp[4096]; 215327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden const char* pathname = filename; 216327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden 217327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden if (dirname != NULL) { 218327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden snprintf(tmp, sizeof(tmp), "%s/%s", dirname, filename); 219327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden pathname = tmp; 220327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden } else { 221327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden pathname = filename; 222327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden } 223327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden 224327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden if ((flags & LIST_LONG) != 0) { 225327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden return listfile_long(pathname, flags); 226327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden } else /*((flags & LIST_SIZE) != 0)*/ { 2279feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden return listfile_size(pathname, filename, flags); 228327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden } 229327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden} 230327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden 231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int listdir(const char *name, int flags) 232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char tmp[4096]; 234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project DIR *d; 235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct dirent *de; 2369feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden 237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project d = opendir(name); 238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(d == 0) { 239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "opendir failed, %s\n", strerror(errno)); 240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 2439feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden if ((flags & LIST_SIZE) != 0) { 2449feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden show_total_size(name, d, flags); 2459feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden } 2469feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden 247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while((de = readdir(d)) != 0){ 248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue; 249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(de->d_name[0] == '.' && (flags & LIST_ALL) == 0) continue; 250327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden 251327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden listfile(name, de->d_name, flags); 252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (flags & LIST_RECURSIVE) { 255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rewinddir(d); 256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while ((de = readdir(d)) != 0) { 258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct stat s; 259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int err; 260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) 262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (de->d_name[0] == '.' && (flags & LIST_ALL) == 0) 264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 266327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden if (!strcmp(name, "/")) 267327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden snprintf(tmp, sizeof(tmp), "/%s", de->d_name); 268327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden else 269327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden snprintf(tmp, sizeof(tmp), "%s/%s", name, de->d_name); 270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* 272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * If the name ends in a '/', use stat() so we treat it like a 273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * directory even if it's a symlink. 274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (tmp[strlen(tmp)-1] == '/') 276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project err = stat(tmp, &s); 277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project else 278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project err = lstat(tmp, &s); 279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (err < 0) { 281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project perror(tmp); 282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project closedir(d); 283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (S_ISDIR(s.st_mode)) { 287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf("\n%s:\n", tmp); 288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project listdir(tmp, flags); 289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project closedir(d); 294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int listpath(const char *name, int flags) 298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct stat s; 300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int err; 301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* 303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * If the name ends in a '/', use stat() so we treat it like a 304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * directory even if it's a symlink. 305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (name[strlen(name)-1] == '/') 307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project err = stat(name, &s); 308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project else 309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project err = lstat(name, &s); 310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (err < 0) { 312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project perror(name); 313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 316b33d3415b6c63f7b22e0863a2ac594feab9171cfAndy McFadden if ((flags & LIST_DIRECTORIES) == 0 && S_ISDIR(s.st_mode)) { 317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (flags & LIST_RECURSIVE) 318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf("\n%s:\n", name); 319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return listdir(name, flags); 320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 321327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden /* yeah this calls stat() again*/ 322327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden return listfile(NULL, name, flags); 323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ls_main(int argc, char **argv) 327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int flags = 0; 329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int listed = 0; 330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(argc > 1) { 332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int i; 333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int err = 0; 334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for (i = 1; i < argc; i++) { 336327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden if (!strcmp(argv[i], "-l")) { 337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project flags |= LIST_LONG; 338327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden } else if (!strcmp(argv[i], "-s")) { 339327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden flags |= LIST_SIZE; 340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (!strcmp(argv[i], "-a")) { 341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project flags |= LIST_ALL; 342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (!strcmp(argv[i], "-R")) { 343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project flags |= LIST_RECURSIVE; 344b33d3415b6c63f7b22e0863a2ac594feab9171cfAndy McFadden } else if (!strcmp(argv[i], "-d")) { 345b33d3415b6c63f7b22e0863a2ac594feab9171cfAndy McFadden flags |= LIST_DIRECTORIES; 346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project listed++; 348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(listpath(argv[i], flags) != 0) { 349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project err = EXIT_FAILURE; 350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (listed > 0) return err; 355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // list working directory if no files or directories were specified 358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return listpath(".", flags); 359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 360