ls.c revision 40dac659418f84551a5637a9edee03764c570f3c
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> 16aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner#include <limits.h> 17aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 18aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner// dynamic arrays 19aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turnertypedef struct { 20aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner int count; 21aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner int capacity; 22aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner void** items; 23aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner} dynarray_t; 24aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 25aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner#define DYNARRAY_INITIALIZER { 0, 0, NULL } 26aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 27aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turnerstatic void dynarray_init( dynarray_t *a ) 28aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner{ 29aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner a->count = a->capacity = 0; 30aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner a->items = NULL; 31aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner} 32aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 33aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turnerstatic void dynarray_reserve_more( dynarray_t *a, int count ) 34aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner{ 35aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner int old_cap = a->capacity; 36aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner int new_cap = old_cap; 37aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner const int max_cap = INT_MAX/sizeof(void*); 38aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner void** new_items; 39aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner int new_count = a->count + count; 40aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 41aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner if (count <= 0) 42aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner return; 43aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 44aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner if (count > max_cap - a->count) 45aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner abort(); 46aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 47aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner new_count = a->count + count; 48aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 49aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner while (new_cap < new_count) { 50aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner old_cap = new_cap; 51aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner new_cap += (new_cap >> 2) + 4; 52aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner if (new_cap < old_cap || new_cap > max_cap) { 53aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner new_cap = max_cap; 54aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner } 55aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner } 56aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner new_items = realloc(a->items, new_cap*sizeof(void*)); 57aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner if (new_items == NULL) 58aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner abort(); 59aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 60aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner a->items = new_items; 61aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner a->capacity = new_cap; 62aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner} 63aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 64aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turnerstatic void dynarray_append( dynarray_t *a, void* item ) 65aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner{ 66aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner if (a->count >= a->capacity) 67aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner dynarray_reserve_more(a, 1); 68aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 69aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner a->items[a->count++] = item; 70aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner} 71aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 72aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turnerstatic void dynarray_done( dynarray_t *a ) 73aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner{ 74aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner free(a->items); 75aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner a->items = NULL; 76aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner a->count = a->capacity = 0; 77aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner} 78aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 79aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner#define DYNARRAY_FOREACH_TYPE(_array,_item_type,_item,_stmnt) \ 80aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner do { \ 81aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner int _nn_##__LINE__ = 0; \ 82aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner for (;_nn_##__LINE__ < (_array)->count; ++ _nn_##__LINE__) { \ 83aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner _item_type _item = (_item_type)(_array)->items[_nn_##__LINE__]; \ 84aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner _stmnt; \ 85aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner } \ 86aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner } while (0) 87aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 88aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner#define DYNARRAY_FOREACH(_array,_item,_stmnt) \ 89aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner DYNARRAY_FOREACH_TYPE(_array,void *,_item,_stmnt) 90aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 91aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner// string arrays 92aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 93aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turnertypedef dynarray_t strlist_t; 94aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 95aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner#define STRLIST_INITIALIZER DYNARRAY_INITIALIZER 96aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 97aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner#define STRLIST_FOREACH(_list,_string,_stmnt) \ 98aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner DYNARRAY_FOREACH_TYPE(_list,char *,_string,_stmnt) 99aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 100aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turnerstatic void strlist_init( strlist_t *list ) 101aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner{ 102aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner dynarray_init(list); 103aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner} 104aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 105aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turnerstatic void strlist_append_b( strlist_t *list, const void* str, size_t slen ) 106aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner{ 107aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner char *copy = malloc(slen+1); 108aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner memcpy(copy, str, slen); 109aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner copy[slen] = '\0'; 110aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner dynarray_append(list, copy); 111aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner} 112aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 113aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turnerstatic void strlist_append_dup( strlist_t *list, const char *str) 114aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner{ 115aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner strlist_append_b(list, str, strlen(str)); 116aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner} 117aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 118aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turnerstatic void strlist_done( strlist_t *list ) 119aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner{ 120aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner STRLIST_FOREACH(list, string, free(string)); 121aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner dynarray_done(list); 122aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner} 123aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 124aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turnerstatic int strlist_compare_strings(const void* a, const void* b) 125aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner{ 126aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner const char *sa = *(const char **)a; 127aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner const char *sb = *(const char **)b; 128aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner return strcmp(sa, sb); 129aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner} 130aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 131aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turnerstatic void strlist_sort( strlist_t *list ) 132aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner{ 133aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner if (list->count > 0) { 134aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner qsort(list->items, 135aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner (size_t)list->count, 136aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner sizeof(void*), 137aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner strlist_compare_strings); 138aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner } 139aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner} 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// bits for flags argument 142b33d3415b6c63f7b22e0863a2ac594feab9171cfAndy McFadden#define LIST_LONG (1 << 0) 143b33d3415b6c63f7b22e0863a2ac594feab9171cfAndy McFadden#define LIST_ALL (1 << 1) 144b33d3415b6c63f7b22e0863a2ac594feab9171cfAndy McFadden#define LIST_RECURSIVE (1 << 2) 145b33d3415b6c63f7b22e0863a2ac594feab9171cfAndy McFadden#define LIST_DIRECTORIES (1 << 3) 146327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden#define LIST_SIZE (1 << 4) 14740dac659418f84551a5637a9edee03764c570f3cKenny Root#define LIST_CLASSIFY (1 << 6) 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// fwd 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int listpath(const char *name, int flags); 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic char mode2kind(unsigned mode) 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project switch(mode & S_IFMT){ 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFSOCK: return 's'; 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFLNK: return 'l'; 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFREG: return '-'; 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFDIR: return 'd'; 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFBLK: return 'b'; 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFCHR: return 'c'; 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFIFO: return 'p'; 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project default: return '?'; 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void mode2str(unsigned mode, char *out) 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = mode2kind(mode); 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 0400) ? 'r' : '-'; 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 0200) ? 'w' : '-'; 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(mode & 04000) { 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 0100) ? 's' : 'S'; 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 0100) ? 'x' : '-'; 176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 040) ? 'r' : '-'; 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 020) ? 'w' : '-'; 179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(mode & 02000) { 180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 010) ? 's' : 'S'; 181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 010) ? 'x' : '-'; 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 04) ? 'r' : '-'; 185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 02) ? 'w' : '-'; 186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(mode & 01000) { 187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 01) ? 't' : 'T'; 188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out++ = (mode & 01) ? 'x' : '-'; 190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *out = 0; 192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void user2str(unsigned uid, char *out) 195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct passwd *pw = getpwuid(uid); 197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(pw) { 198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strcpy(out, pw->pw_name); 199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sprintf(out, "%d", uid); 201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void group2str(unsigned gid, char *out) 205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct group *gr = getgrgid(gid); 207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(gr) { 208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strcpy(out, gr->gr_name); 209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sprintf(out, "%d", gid); 211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 2149feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFaddenstatic int show_total_size(const char *dirname, DIR *d, int flags) 215327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden{ 2169feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden struct dirent *de; 2179feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden char tmp[1024]; 218327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden struct stat s; 2199feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden int sum = 0; 2209feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden 2219feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden /* run through the directory and sum up the file block sizes */ 2229feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden while ((de = readdir(d)) != 0) { 2239feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) 2249feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden continue; 2259feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden if (de->d_name[0] == '.' && (flags & LIST_ALL) == 0) 2269feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden continue; 2279feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden 2289feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden if (strcmp(dirname, "/") == 0) 2299feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden snprintf(tmp, sizeof(tmp), "/%s", de->d_name); 2309feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden else 2319feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden snprintf(tmp, sizeof(tmp), "%s/%s", dirname, de->d_name); 2329feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden 2339feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden if (lstat(tmp, &s) < 0) { 2349feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden fprintf(stderr, "stat failed on %s: %s\n", tmp, strerror(errno)); 2359feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden rewinddir(d); 2369feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden return -1; 2379feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden } 2389feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden 2399feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden sum += s.st_blocks / 2; 2409feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden } 241327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden 2429feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden printf("total %d\n", sum); 2439feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden rewinddir(d); 2449feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden return 0; 2459feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden} 2469feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden 2479feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFaddenstatic int listfile_size(const char *path, const char *filename, int flags) 2489feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden{ 2499feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden struct stat s; 2509feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden 2519feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden if (lstat(path, &s) < 0) { 2529feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden fprintf(stderr, "lstat '%s' failed: %s\n", path, strerror(errno)); 253327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden return -1; 2549feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden } 255327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden 256327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden /* blocks are 512 bytes, we want output to be KB */ 25740dac659418f84551a5637a9edee03764c570f3cKenny Root if ((flags & LIST_SIZE) != 0) { 25840dac659418f84551a5637a9edee03764c570f3cKenny Root printf("%lld ", s.st_blocks / 2); 25940dac659418f84551a5637a9edee03764c570f3cKenny Root } 26040dac659418f84551a5637a9edee03764c570f3cKenny Root 26140dac659418f84551a5637a9edee03764c570f3cKenny Root if ((flags & LIST_CLASSIFY) != 0) { 26240dac659418f84551a5637a9edee03764c570f3cKenny Root char filetype = mode2kind(s.st_mode); 26340dac659418f84551a5637a9edee03764c570f3cKenny Root if (filetype != 'l') { 26440dac659418f84551a5637a9edee03764c570f3cKenny Root printf("%c ", filetype); 26540dac659418f84551a5637a9edee03764c570f3cKenny Root } else { 26640dac659418f84551a5637a9edee03764c570f3cKenny Root struct stat link_dest; 26740dac659418f84551a5637a9edee03764c570f3cKenny Root if (!stat(path, &link_dest)) { 26840dac659418f84551a5637a9edee03764c570f3cKenny Root printf("l%c ", mode2kind(link_dest.st_mode)); 26940dac659418f84551a5637a9edee03764c570f3cKenny Root } else { 27040dac659418f84551a5637a9edee03764c570f3cKenny Root fprintf(stderr, "stat '%s' failed: %s\n", path, strerror(errno)); 27140dac659418f84551a5637a9edee03764c570f3cKenny Root printf("l? "); 27240dac659418f84551a5637a9edee03764c570f3cKenny Root } 27340dac659418f84551a5637a9edee03764c570f3cKenny Root } 27440dac659418f84551a5637a9edee03764c570f3cKenny Root } 27540dac659418f84551a5637a9edee03764c570f3cKenny Root 27640dac659418f84551a5637a9edee03764c570f3cKenny Root printf("%s\n", filename); 27740dac659418f84551a5637a9edee03764c570f3cKenny Root 278327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden return 0; 279327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden} 280327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden 281327e696808910f8e49370079f8d7f4db8cbe3820Andy McFaddenstatic int listfile_long(const char *path, int flags) 282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct stat s; 284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char date[32]; 285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char mode[16]; 286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char user[16]; 287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char group[16]; 288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const char *name; 289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* name is anything after the final '/', or the whole path if none*/ 291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project name = strrchr(path, '/'); 292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(name == 0) { 293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project name = path; 294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project name++; 296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(lstat(path, &s) < 0) { 299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mode2str(s.st_mode, mode); 303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project user2str(s.st_uid, user); 304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project group2str(s.st_gid, group); 305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strftime(date, 32, "%Y-%m-%d %H:%M", localtime((const time_t*)&s.st_mtime)); 307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project date[31] = 0; 308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// 12345678901234567890123456789012345678901234567890123456789012345678901234567890 310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// MMMMMMMM UUUUUUUU GGGGGGGGG XXXXXXXX YYYY-MM-DD HH:MM NAME (->LINK) 311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project switch(s.st_mode & S_IFMT) { 313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFBLK: 314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFCHR: 315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf("%s %-8s %-8s %3d, %3d %s %s\n", 316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mode, user, group, 317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project (int) MAJOR(s.st_rdev), (int) MINOR(s.st_rdev), 318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project date, name); 319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFREG: 321eb42170e6c8b70f11dca9965785aa04a80290c72Kenny Root printf("%s %-8s %-8s %8lld %s %s\n", 322eb42170e6c8b70f11dca9965785aa04a80290c72Kenny Root mode, user, group, s.st_size, date, name); 323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case S_IFLNK: { 325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char linkto[256]; 326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int len; 327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len = readlink(path, linkto, 256); 329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(len < 0) return -1; 330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(len > 255) { 332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project linkto[252] = '.'; 333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project linkto[253] = '.'; 334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project linkto[254] = '.'; 335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project linkto[255] = 0; 336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project linkto[len] = 0; 338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf("%s %-8s %-8s %s %s -> %s\n", 341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mode, user, group, date, name, linkto); 342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project default: 345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf("%s %-8s %-8s %s %s\n", 346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mode, user, group, date, name); 347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 352327e696808910f8e49370079f8d7f4db8cbe3820Andy McFaddenstatic int listfile(const char *dirname, const char *filename, int flags) 353327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden{ 35440dac659418f84551a5637a9edee03764c570f3cKenny Root if ((flags & (LIST_LONG | LIST_SIZE | LIST_CLASSIFY)) == 0) { 355327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden printf("%s\n", filename); 356327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden return 0; 357327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden } 358327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden 359327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden char tmp[4096]; 360327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden const char* pathname = filename; 361327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden 362327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden if (dirname != NULL) { 363327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden snprintf(tmp, sizeof(tmp), "%s/%s", dirname, filename); 364327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden pathname = tmp; 365327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden } else { 366327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden pathname = filename; 367327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden } 368327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden 369327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden if ((flags & LIST_LONG) != 0) { 370327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden return listfile_long(pathname, flags); 371327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden } else /*((flags & LIST_SIZE) != 0)*/ { 3729feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden return listfile_size(pathname, filename, flags); 373327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden } 374327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden} 375327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden 376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int listdir(const char *name, int flags) 377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char tmp[4096]; 379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project DIR *d; 380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct dirent *de; 381aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner strlist_t files = STRLIST_INITIALIZER; 382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project d = opendir(name); 384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(d == 0) { 385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "opendir failed, %s\n", strerror(errno)); 386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 3899feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden if ((flags & LIST_SIZE) != 0) { 3909feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden show_total_size(name, d, flags); 3919feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden } 3929feee025a09ace19b09dbb41d6ba87198c77cdf1Andy McFadden 393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while((de = readdir(d)) != 0){ 394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue; 395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(de->d_name[0] == '.' && (flags & LIST_ALL) == 0) continue; 396327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden 397aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner strlist_append_dup(&files, de->d_name); 398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 400aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner strlist_sort(&files); 401aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner STRLIST_FOREACH(&files, filename, listfile(name, filename, flags)); 402aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner strlist_done(&files); 403aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (flags & LIST_RECURSIVE) { 405aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner strlist_t subdirs = STRLIST_INITIALIZER; 406aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner 407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rewinddir(d); 408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while ((de = readdir(d)) != 0) { 410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct stat s; 411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int err; 412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) 414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (de->d_name[0] == '.' && (flags & LIST_ALL) == 0) 416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 418327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden if (!strcmp(name, "/")) 419327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden snprintf(tmp, sizeof(tmp), "/%s", de->d_name); 420327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden else 421327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden snprintf(tmp, sizeof(tmp), "%s/%s", name, de->d_name); 422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* 424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * If the name ends in a '/', use stat() so we treat it like a 425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * directory even if it's a symlink. 426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (tmp[strlen(tmp)-1] == '/') 428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project err = stat(tmp, &s); 429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project else 430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project err = lstat(tmp, &s); 431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (err < 0) { 433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project perror(tmp); 434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project closedir(d); 435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (S_ISDIR(s.st_mode)) { 439aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner strlist_append_dup(&subdirs, tmp); 440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 442aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner strlist_sort(&subdirs); 443aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner STRLIST_FOREACH(&subdirs, path, { 444aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner printf("\n%s:\n", path); 445aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner listdir(path, flags); 446aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner }); 447aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner strlist_done(&subdirs); 448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project closedir(d); 451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int listpath(const char *name, int flags) 455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct stat s; 457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int err; 458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* 460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * If the name ends in a '/', use stat() so we treat it like a 461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * directory even if it's a symlink. 462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (name[strlen(name)-1] == '/') 464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project err = stat(name, &s); 465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project else 466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project err = lstat(name, &s); 467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (err < 0) { 469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project perror(name); 470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 473b33d3415b6c63f7b22e0863a2ac594feab9171cfAndy McFadden if ((flags & LIST_DIRECTORIES) == 0 && S_ISDIR(s.st_mode)) { 474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (flags & LIST_RECURSIVE) 475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf("\n%s:\n", name); 476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return listdir(name, flags); 477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 478327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden /* yeah this calls stat() again*/ 479327e696808910f8e49370079f8d7f4db8cbe3820Andy McFadden return listfile(NULL, name, flags); 480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ls_main(int argc, char **argv) 484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int flags = 0; 486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int listed = 0; 487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(argc > 1) { 489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int i; 490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int err = 0; 491aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner strlist_t files = STRLIST_INITIALIZER; 492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for (i = 1; i < argc; i++) { 494aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner if (argv[i][0] == '-') { 495aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner /* an option ? */ 496aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner const char *arg = argv[i]+1; 497aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner while (arg[0]) { 498aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner switch (arg[0]) { 499aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner case 'l': flags |= LIST_LONG; break; 500aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner case 's': flags |= LIST_SIZE; break; 501aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner case 'R': flags |= LIST_RECURSIVE; break; 502aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner case 'd': flags |= LIST_DIRECTORIES; break; 503aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner case 'a': flags |= LIST_ALL; break; 50440dac659418f84551a5637a9edee03764c570f3cKenny Root case 'F': flags |= LIST_CLASSIFY; break; 505aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner default: 506aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner fprintf(stderr, "%s: Unknown option '-%c'. Aborting.\n", "ls", arg[0]); 507aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner exit(1); 508aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner } 509aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner arg++; 510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 511aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner } else { 512aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner /* not an option ? */ 513aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner strlist_append_dup(&files, argv[i]); 514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 515dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 517aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner if (files.count > 0) { 518aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner STRLIST_FOREACH(&files, path, { 519aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner if (listpath(path, flags) != 0) { 520aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner err = EXIT_FAILURE; 521aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner } 522aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner }); 523aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner strlist_done(&files); 524aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner return err; 525aa2106b008921ed8f33ee14ee70fb1b944f547ecDavid 'Digit' Turner } 526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // list working directory if no files or directories were specified 529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return listpath(".", flags); 530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 531