blob: c740f847ed1fbd24247ad807364bd9a5818cd23b [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <sys/types.h>
5#include <dirent.h>
6#include <errno.h>
7
Stephen Smalley8290d102012-01-13 08:53:56 -05008#include <selinux/selinux.h>
Stephen Smalley8290d102012-01-13 08:53:56 -05009
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080010#include <sys/stat.h>
11#include <unistd.h>
12#include <time.h>
13
14#include <pwd.h>
15#include <grp.h>
16
17#include <linux/kdev_t.h>
David 'Digit' Turneraa2106b2010-06-04 10:44:56 -070018#include <limits.h>
19
David 'Digit' Turnera8d1afb2011-01-06 08:39:44 +010020#include "dynarray.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080021
22// bits for flags argument
Andy McFaddenb33d3412009-04-08 19:25:35 -070023#define LIST_LONG (1 << 0)
24#define LIST_ALL (1 << 1)
25#define LIST_RECURSIVE (1 << 2)
26#define LIST_DIRECTORIES (1 << 3)
Andy McFadden327e6962009-08-18 11:10:03 -070027#define LIST_SIZE (1 << 4)
Brad Fitzpatricke7fe5bf2010-10-25 13:29:53 -070028#define LIST_LONG_NUMERIC (1 << 5)
Kenny Root40dac652011-07-13 09:14:33 -070029#define LIST_CLASSIFY (1 << 6)
Stephen Smalley8290d102012-01-13 08:53:56 -050030#define LIST_MACLABEL (1 << 7)
William Roberts403b1952013-04-03 16:01:30 -070031#define LIST_INODE (1 << 8)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080032
33// fwd
34static int listpath(const char *name, int flags);
35
36static char mode2kind(unsigned mode)
37{
38 switch(mode & S_IFMT){
39 case S_IFSOCK: return 's';
40 case S_IFLNK: return 'l';
41 case S_IFREG: return '-';
42 case S_IFDIR: return 'd';
43 case S_IFBLK: return 'b';
44 case S_IFCHR: return 'c';
45 case S_IFIFO: return 'p';
46 default: return '?';
47 }
48}
49
50static void mode2str(unsigned mode, char *out)
51{
52 *out++ = mode2kind(mode);
David 'Digit' Turnera8d1afb2011-01-06 08:39:44 +010053
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080054 *out++ = (mode & 0400) ? 'r' : '-';
55 *out++ = (mode & 0200) ? 'w' : '-';
56 if(mode & 04000) {
57 *out++ = (mode & 0100) ? 's' : 'S';
58 } else {
59 *out++ = (mode & 0100) ? 'x' : '-';
60 }
61 *out++ = (mode & 040) ? 'r' : '-';
62 *out++ = (mode & 020) ? 'w' : '-';
63 if(mode & 02000) {
64 *out++ = (mode & 010) ? 's' : 'S';
65 } else {
66 *out++ = (mode & 010) ? 'x' : '-';
67 }
68 *out++ = (mode & 04) ? 'r' : '-';
69 *out++ = (mode & 02) ? 'w' : '-';
70 if(mode & 01000) {
71 *out++ = (mode & 01) ? 't' : 'T';
72 } else {
73 *out++ = (mode & 01) ? 'x' : '-';
74 }
75 *out = 0;
76}
77
Nick Kralevich4ec29102013-11-27 15:09:43 -080078static void user2str(uid_t uid, char *out, size_t out_size)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080079{
80 struct passwd *pw = getpwuid(uid);
81 if(pw) {
Nick Kralevich4ec29102013-11-27 15:09:43 -080082 strlcpy(out, pw->pw_name, out_size);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080083 } else {
Nick Kralevich4ec29102013-11-27 15:09:43 -080084 snprintf(out, out_size, "%d", uid);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080085 }
86}
87
Nick Kralevich4ec29102013-11-27 15:09:43 -080088static void group2str(gid_t gid, char *out, size_t out_size)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080089{
90 struct group *gr = getgrgid(gid);
91 if(gr) {
Nick Kralevich4ec29102013-11-27 15:09:43 -080092 strlcpy(out, gr->gr_name, out_size);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080093 } else {
Nick Kralevich4ec29102013-11-27 15:09:43 -080094 snprintf(out, out_size, "%d", gid);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080095 }
96}
97
Andy McFadden9feee022009-09-27 15:13:56 -070098static int show_total_size(const char *dirname, DIR *d, int flags)
99{
100 struct dirent *de;
101 char tmp[1024];
102 struct stat s;
103 int sum = 0;
104
105 /* run through the directory and sum up the file block sizes */
106 while ((de = readdir(d)) != 0) {
107 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
108 continue;
109 if (de->d_name[0] == '.' && (flags & LIST_ALL) == 0)
110 continue;
111
112 if (strcmp(dirname, "/") == 0)
113 snprintf(tmp, sizeof(tmp), "/%s", de->d_name);
114 else
115 snprintf(tmp, sizeof(tmp), "%s/%s", dirname, de->d_name);
116
117 if (lstat(tmp, &s) < 0) {
118 fprintf(stderr, "stat failed on %s: %s\n", tmp, strerror(errno));
119 rewinddir(d);
120 return -1;
121 }
122
123 sum += s.st_blocks / 2;
124 }
125
126 printf("total %d\n", sum);
127 rewinddir(d);
128 return 0;
129}
130
William Roberts403b1952013-04-03 16:01:30 -0700131static int listfile_size(const char *path, const char *filename, struct stat *s,
132 int flags)
Andy McFadden327e6962009-08-18 11:10:03 -0700133{
William Roberts403b1952013-04-03 16:01:30 -0700134 if(!s || !path) {
Andy McFadden327e6962009-08-18 11:10:03 -0700135 return -1;
Andy McFadden9feee022009-09-27 15:13:56 -0700136 }
Andy McFadden327e6962009-08-18 11:10:03 -0700137
138 /* blocks are 512 bytes, we want output to be KB */
Kenny Root40dac652011-07-13 09:14:33 -0700139 if ((flags & LIST_SIZE) != 0) {
William Roberts403b1952013-04-03 16:01:30 -0700140 printf("%lld ", s->st_blocks / 2);
Kenny Root40dac652011-07-13 09:14:33 -0700141 }
142
143 if ((flags & LIST_CLASSIFY) != 0) {
William Roberts403b1952013-04-03 16:01:30 -0700144 char filetype = mode2kind(s->st_mode);
Kenny Root40dac652011-07-13 09:14:33 -0700145 if (filetype != 'l') {
146 printf("%c ", filetype);
147 } else {
148 struct stat link_dest;
149 if (!stat(path, &link_dest)) {
150 printf("l%c ", mode2kind(link_dest.st_mode));
151 } else {
152 fprintf(stderr, "stat '%s' failed: %s\n", path, strerror(errno));
153 printf("l? ");
154 }
155 }
156 }
157
158 printf("%s\n", filename);
159
Andy McFadden327e6962009-08-18 11:10:03 -0700160 return 0;
161}
162
William Roberts403b1952013-04-03 16:01:30 -0700163static int listfile_long(const char *path, struct stat *s, int flags)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800164{
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800165 char date[32];
166 char mode[16];
Nick Kralevich4ec29102013-11-27 15:09:43 -0800167 char user[32];
168 char group[32];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800169 const char *name;
170
William Roberts403b1952013-04-03 16:01:30 -0700171 if(!s || !path) {
172 return -1;
173 }
174
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800175 /* name is anything after the final '/', or the whole path if none*/
176 name = strrchr(path, '/');
177 if(name == 0) {
178 name = path;
179 } else {
180 name++;
181 }
182
William Roberts403b1952013-04-03 16:01:30 -0700183 mode2str(s->st_mode, mode);
Brad Fitzpatricke7fe5bf2010-10-25 13:29:53 -0700184 if (flags & LIST_LONG_NUMERIC) {
Nick Kralevich4ec29102013-11-27 15:09:43 -0800185 snprintf(user, sizeof(user), "%ld", s->st_uid);
186 snprintf(group, sizeof(group), "%ld", s->st_gid);
Brad Fitzpatricke7fe5bf2010-10-25 13:29:53 -0700187 } else {
Nick Kralevich4ec29102013-11-27 15:09:43 -0800188 user2str(s->st_uid, user, sizeof(user));
189 group2str(s->st_gid, group, sizeof(group));
Brad Fitzpatricke7fe5bf2010-10-25 13:29:53 -0700190 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800191
William Roberts403b1952013-04-03 16:01:30 -0700192 strftime(date, 32, "%Y-%m-%d %H:%M", localtime((const time_t*)&s->st_mtime));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800193 date[31] = 0;
David 'Digit' Turnera8d1afb2011-01-06 08:39:44 +0100194
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800195// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
196// MMMMMMMM UUUUUUUU GGGGGGGGG XXXXXXXX YYYY-MM-DD HH:MM NAME (->LINK)
197
William Roberts403b1952013-04-03 16:01:30 -0700198 switch(s->st_mode & S_IFMT) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800199 case S_IFBLK:
200 case S_IFCHR:
201 printf("%s %-8s %-8s %3d, %3d %s %s\n",
David 'Digit' Turnera8d1afb2011-01-06 08:39:44 +0100202 mode, user, group,
William Roberts403b1952013-04-03 16:01:30 -0700203 (int) MAJOR(s->st_rdev), (int) MINOR(s->st_rdev),
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800204 date, name);
205 break;
206 case S_IFREG:
Kenny Rooteb421702010-06-25 09:08:05 -0700207 printf("%s %-8s %-8s %8lld %s %s\n",
William Roberts403b1952013-04-03 16:01:30 -0700208 mode, user, group, s->st_size, date, name);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800209 break;
210 case S_IFLNK: {
211 char linkto[256];
Nick Kralevich8dfdf652013-11-27 16:12:48 -0800212 ssize_t len;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800213
214 len = readlink(path, linkto, 256);
215 if(len < 0) return -1;
David 'Digit' Turnera8d1afb2011-01-06 08:39:44 +0100216
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800217 if(len > 255) {
218 linkto[252] = '.';
219 linkto[253] = '.';
220 linkto[254] = '.';
221 linkto[255] = 0;
222 } else {
223 linkto[len] = 0;
224 }
David 'Digit' Turnera8d1afb2011-01-06 08:39:44 +0100225
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800226 printf("%s %-8s %-8s %s %s -> %s\n",
227 mode, user, group, date, name, linkto);
228 break;
229 }
230 default:
231 printf("%s %-8s %-8s %s %s\n",
232 mode, user, group, date, name);
233
234 }
235 return 0;
236}
237
Nick Kralevich8dfdf652013-11-27 16:12:48 -0800238static int listfile_maclabel(const char *path, struct stat *s)
Stephen Smalley8290d102012-01-13 08:53:56 -0500239{
Stephen Smalley8290d102012-01-13 08:53:56 -0500240 char mode[16];
Nick Kralevich4ec29102013-11-27 15:09:43 -0800241 char user[32];
242 char group[32];
Stephen Smalley8290d102012-01-13 08:53:56 -0500243 char *maclabel = NULL;
244 const char *name;
245
William Roberts403b1952013-04-03 16:01:30 -0700246 if(!s || !path) {
247 return -1;
248 }
249
Stephen Smalley8290d102012-01-13 08:53:56 -0500250 /* name is anything after the final '/', or the whole path if none*/
251 name = strrchr(path, '/');
252 if(name == 0) {
253 name = path;
254 } else {
255 name++;
256 }
257
Stephen Smalley8290d102012-01-13 08:53:56 -0500258 lgetfilecon(path, &maclabel);
Stephen Smalley8290d102012-01-13 08:53:56 -0500259 if (!maclabel) {
260 return -1;
261 }
262
William Roberts403b1952013-04-03 16:01:30 -0700263 mode2str(s->st_mode, mode);
Nick Kralevich4ec29102013-11-27 15:09:43 -0800264 user2str(s->st_uid, user, sizeof(user));
265 group2str(s->st_gid, group, sizeof(group));
Stephen Smalley8290d102012-01-13 08:53:56 -0500266
William Roberts403b1952013-04-03 16:01:30 -0700267 switch(s->st_mode & S_IFMT) {
Stephen Smalley8290d102012-01-13 08:53:56 -0500268 case S_IFLNK: {
269 char linkto[256];
Kenny Rootef5d0342012-10-10 11:26:54 -0700270 ssize_t len;
Stephen Smalley8290d102012-01-13 08:53:56 -0500271
272 len = readlink(path, linkto, sizeof(linkto));
273 if(len < 0) return -1;
274
Kenny Rootef5d0342012-10-10 11:26:54 -0700275 if((size_t)len > sizeof(linkto)-1) {
Stephen Smalley8290d102012-01-13 08:53:56 -0500276 linkto[sizeof(linkto)-4] = '.';
277 linkto[sizeof(linkto)-3] = '.';
278 linkto[sizeof(linkto)-2] = '.';
279 linkto[sizeof(linkto)-1] = 0;
280 } else {
281 linkto[len] = 0;
282 }
283
284 printf("%s %-8s %-8s %s %s -> %s\n",
285 mode, user, group, maclabel, name, linkto);
286 break;
287 }
288 default:
289 printf("%s %-8s %-8s %s %s\n",
290 mode, user, group, maclabel, name);
291
292 }
293
294 free(maclabel);
295
296 return 0;
297}
298
Andy McFadden327e6962009-08-18 11:10:03 -0700299static int listfile(const char *dirname, const char *filename, int flags)
300{
William Roberts403b1952013-04-03 16:01:30 -0700301 struct stat s;
302
303 if ((flags & (LIST_LONG | LIST_SIZE | LIST_CLASSIFY | LIST_MACLABEL | LIST_INODE)) == 0) {
Andy McFadden327e6962009-08-18 11:10:03 -0700304 printf("%s\n", filename);
305 return 0;
306 }
307
308 char tmp[4096];
309 const char* pathname = filename;
310
311 if (dirname != NULL) {
312 snprintf(tmp, sizeof(tmp), "%s/%s", dirname, filename);
313 pathname = tmp;
314 } else {
315 pathname = filename;
316 }
317
William Roberts403b1952013-04-03 16:01:30 -0700318 if(lstat(pathname, &s) < 0) {
William Robertsded34642014-01-02 14:34:54 -0800319 fprintf(stderr, "lstat '%s' failed: %s\n", pathname, strerror(errno));
William Roberts403b1952013-04-03 16:01:30 -0700320 return -1;
321 }
322
323 if(flags & LIST_INODE) {
324 printf("%8llu ", s.st_ino);
325 }
326
Stephen Smalley8290d102012-01-13 08:53:56 -0500327 if ((flags & LIST_MACLABEL) != 0) {
Nick Kralevich8dfdf652013-11-27 16:12:48 -0800328 return listfile_maclabel(pathname, &s);
Stephen Smalley8290d102012-01-13 08:53:56 -0500329 } else if ((flags & LIST_LONG) != 0) {
William Roberts403b1952013-04-03 16:01:30 -0700330 return listfile_long(pathname, &s, flags);
Andy McFadden327e6962009-08-18 11:10:03 -0700331 } else /*((flags & LIST_SIZE) != 0)*/ {
William Roberts403b1952013-04-03 16:01:30 -0700332 return listfile_size(pathname, filename, &s, flags);
Andy McFadden327e6962009-08-18 11:10:03 -0700333 }
334}
335
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800336static int listdir(const char *name, int flags)
337{
338 char tmp[4096];
339 DIR *d;
340 struct dirent *de;
David 'Digit' Turneraa2106b2010-06-04 10:44:56 -0700341 strlist_t files = STRLIST_INITIALIZER;
David 'Digit' Turnera8d1afb2011-01-06 08:39:44 +0100342
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800343 d = opendir(name);
344 if(d == 0) {
345 fprintf(stderr, "opendir failed, %s\n", strerror(errno));
346 return -1;
347 }
348
Andy McFadden9feee022009-09-27 15:13:56 -0700349 if ((flags & LIST_SIZE) != 0) {
350 show_total_size(name, d, flags);
351 }
352
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800353 while((de = readdir(d)) != 0){
354 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue;
355 if(de->d_name[0] == '.' && (flags & LIST_ALL) == 0) continue;
Andy McFadden327e6962009-08-18 11:10:03 -0700356
David 'Digit' Turneraa2106b2010-06-04 10:44:56 -0700357 strlist_append_dup(&files, de->d_name);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800358 }
359
David 'Digit' Turneraa2106b2010-06-04 10:44:56 -0700360 strlist_sort(&files);
361 STRLIST_FOREACH(&files, filename, listfile(name, filename, flags));
362 strlist_done(&files);
363
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800364 if (flags & LIST_RECURSIVE) {
David 'Digit' Turneraa2106b2010-06-04 10:44:56 -0700365 strlist_t subdirs = STRLIST_INITIALIZER;
366
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800367 rewinddir(d);
368
369 while ((de = readdir(d)) != 0) {
370 struct stat s;
371 int err;
372
373 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
374 continue;
375 if (de->d_name[0] == '.' && (flags & LIST_ALL) == 0)
376 continue;
377
Andy McFadden327e6962009-08-18 11:10:03 -0700378 if (!strcmp(name, "/"))
379 snprintf(tmp, sizeof(tmp), "/%s", de->d_name);
380 else
381 snprintf(tmp, sizeof(tmp), "%s/%s", name, de->d_name);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800382
383 /*
384 * If the name ends in a '/', use stat() so we treat it like a
385 * directory even if it's a symlink.
386 */
387 if (tmp[strlen(tmp)-1] == '/')
388 err = stat(tmp, &s);
389 else
390 err = lstat(tmp, &s);
391
392 if (err < 0) {
393 perror(tmp);
394 closedir(d);
395 return -1;
396 }
397
398 if (S_ISDIR(s.st_mode)) {
David 'Digit' Turneraa2106b2010-06-04 10:44:56 -0700399 strlist_append_dup(&subdirs, tmp);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800400 }
401 }
David 'Digit' Turneraa2106b2010-06-04 10:44:56 -0700402 strlist_sort(&subdirs);
403 STRLIST_FOREACH(&subdirs, path, {
404 printf("\n%s:\n", path);
405 listdir(path, flags);
406 });
407 strlist_done(&subdirs);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800408 }
409
410 closedir(d);
411 return 0;
412}
413
414static int listpath(const char *name, int flags)
415{
416 struct stat s;
417 int err;
418
419 /*
420 * If the name ends in a '/', use stat() so we treat it like a
421 * directory even if it's a symlink.
422 */
423 if (name[strlen(name)-1] == '/')
424 err = stat(name, &s);
425 else
426 err = lstat(name, &s);
427
428 if (err < 0) {
429 perror(name);
430 return -1;
431 }
432
Andy McFaddenb33d3412009-04-08 19:25:35 -0700433 if ((flags & LIST_DIRECTORIES) == 0 && S_ISDIR(s.st_mode)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800434 if (flags & LIST_RECURSIVE)
435 printf("\n%s:\n", name);
436 return listdir(name, flags);
437 } else {
Andy McFadden327e6962009-08-18 11:10:03 -0700438 /* yeah this calls stat() again*/
439 return listfile(NULL, name, flags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800440 }
441}
442
443int ls_main(int argc, char **argv)
444{
445 int flags = 0;
446 int listed = 0;
David 'Digit' Turnera8d1afb2011-01-06 08:39:44 +0100447
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800448 if(argc > 1) {
449 int i;
450 int err = 0;
David 'Digit' Turneraa2106b2010-06-04 10:44:56 -0700451 strlist_t files = STRLIST_INITIALIZER;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800452
453 for (i = 1; i < argc; i++) {
David 'Digit' Turneraa2106b2010-06-04 10:44:56 -0700454 if (argv[i][0] == '-') {
455 /* an option ? */
456 const char *arg = argv[i]+1;
457 while (arg[0]) {
458 switch (arg[0]) {
459 case 'l': flags |= LIST_LONG; break;
Brad Fitzpatricke7fe5bf2010-10-25 13:29:53 -0700460 case 'n': flags |= LIST_LONG | LIST_LONG_NUMERIC; break;
David 'Digit' Turneraa2106b2010-06-04 10:44:56 -0700461 case 's': flags |= LIST_SIZE; break;
462 case 'R': flags |= LIST_RECURSIVE; break;
463 case 'd': flags |= LIST_DIRECTORIES; break;
Stephen Smalley8290d102012-01-13 08:53:56 -0500464 case 'Z': flags |= LIST_MACLABEL; break;
David 'Digit' Turneraa2106b2010-06-04 10:44:56 -0700465 case 'a': flags |= LIST_ALL; break;
Kenny Root40dac652011-07-13 09:14:33 -0700466 case 'F': flags |= LIST_CLASSIFY; break;
William Roberts403b1952013-04-03 16:01:30 -0700467 case 'i': flags |= LIST_INODE; break;
David 'Digit' Turneraa2106b2010-06-04 10:44:56 -0700468 default:
469 fprintf(stderr, "%s: Unknown option '-%c'. Aborting.\n", "ls", arg[0]);
470 exit(1);
471 }
472 arg++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800473 }
David 'Digit' Turneraa2106b2010-06-04 10:44:56 -0700474 } else {
475 /* not an option ? */
476 strlist_append_dup(&files, argv[i]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800477 }
478 }
479
David 'Digit' Turneraa2106b2010-06-04 10:44:56 -0700480 if (files.count > 0) {
481 STRLIST_FOREACH(&files, path, {
482 if (listpath(path, flags) != 0) {
483 err = EXIT_FAILURE;
484 }
485 });
486 strlist_done(&files);
487 return err;
488 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800489 }
David 'Digit' Turnera8d1afb2011-01-06 08:39:44 +0100490
491 // list working directory if no files or directories were specified
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800492 return listpath(".", flags);
493}