| /* |
| * ls.c - list files and directories |
| * |
| * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix |
| * |
| * See file CREDITS for list of people who contributed to this |
| * project. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 |
| * as published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| #include <common.h> |
| #include <command.h> |
| #include <fs.h> |
| #include <linux/stat.h> |
| #include <errno.h> |
| #include <malloc.h> |
| #include <getopt.h> |
| #include <stringlist.h> |
| |
| static void ls_one(const char *path, struct stat *s) |
| { |
| char modestr[11]; |
| unsigned int namelen = strlen(path); |
| |
| mkmodestr(s->st_mode, modestr); |
| printf("%s %10lu %*.*s\n", modestr, s->st_size, namelen, namelen, path); |
| } |
| |
| int ls(const char *path, ulong flags) |
| { |
| DIR *dir; |
| struct dirent *d; |
| char tmp[PATH_MAX]; |
| struct stat s; |
| struct string_list sl; |
| |
| string_list_init(&sl); |
| |
| if (stat(path, &s)) |
| return errno; |
| |
| if (flags & LS_SHOWARG && s.st_mode & S_IFDIR) |
| printf("%s:\n", path); |
| |
| if (!(s.st_mode & S_IFDIR)) { |
| ls_one(path, &s); |
| return 0; |
| } |
| |
| dir = opendir(path); |
| if (!dir) |
| return errno; |
| |
| while ((d = readdir(dir))) { |
| sprintf(tmp, "%s/%s", path, d->d_name); |
| if (stat(tmp, &s)) |
| goto out; |
| if (flags & LS_COLUMN) |
| string_list_add(&sl, d->d_name); |
| else |
| ls_one(d->d_name, &s); |
| } |
| |
| closedir(dir); |
| |
| if (flags & LS_COLUMN) { |
| string_list_print_by_column(&sl); |
| string_list_free(&sl); |
| } |
| |
| if (!(flags & LS_RECURSIVE)) |
| return 0; |
| |
| dir = opendir(path); |
| if (!dir) { |
| errno = -ENOENT; |
| return -ENOENT; |
| } |
| |
| while ((d = readdir(dir))) { |
| |
| if (!strcmp(d->d_name, ".")) |
| continue; |
| if (!strcmp(d->d_name, "..")) |
| continue; |
| sprintf(tmp, "%s/%s", path, d->d_name); |
| |
| if (stat(tmp, &s)) |
| goto out; |
| if (s.st_mode & S_IFDIR) { |
| char *norm = normalise_path(tmp); |
| ls(norm, flags); |
| free(norm); |
| } |
| } |
| out: |
| closedir(dir); |
| |
| return 0; |
| } |
| |
| static int do_ls(struct command *cmdtp, int argc, char *argv[]) |
| { |
| int ret, opt, o; |
| struct stat s; |
| ulong flags = LS_COLUMN; |
| struct string_list sl; |
| |
| while((opt = getopt(argc, argv, "RCl")) > 0) { |
| switch(opt) { |
| case 'R': |
| flags |= LS_RECURSIVE | LS_SHOWARG; |
| break; |
| case 'C': |
| flags |= LS_COLUMN; |
| break; |
| case 'l': |
| flags &= ~LS_COLUMN; |
| break; |
| } |
| } |
| |
| if (argc - optind > 1) |
| flags |= LS_SHOWARG; |
| |
| if (optind == argc) { |
| ret = ls(getcwd(), flags); |
| return ret ? 1 : 0; |
| } |
| |
| string_list_init(&sl); |
| |
| o = optind; |
| |
| /* first pass: all files */ |
| while (o < argc) { |
| ret = stat(argv[o], &s); |
| if (ret) { |
| printf("%s: %s: %s\n", argv[0], |
| argv[o], errno_str()); |
| o++; |
| continue; |
| } |
| |
| if (!(s.st_mode & S_IFDIR)) { |
| if (flags & LS_COLUMN) |
| string_list_add(&sl, argv[o]); |
| else |
| ls_one(argv[o], &s); |
| } |
| |
| o++; |
| } |
| |
| if (flags & LS_COLUMN) |
| string_list_print_by_column(&sl); |
| |
| string_list_free(&sl); |
| |
| o = optind; |
| |
| /* second pass: directories */ |
| while (o < argc) { |
| ret = stat(argv[o], &s); |
| if (ret) { |
| o++; |
| continue; |
| } |
| |
| if (s.st_mode & S_IFDIR) { |
| ret = ls(argv[o], flags); |
| if (ret) { |
| perror("ls"); |
| o++; |
| continue; |
| } |
| } |
| |
| o++; |
| } |
| |
| return 0; |
| } |
| |
| BAREBOX_CMD_HELP_START(ls) |
| BAREBOX_CMD_HELP_USAGE("ls [OPTIONS] [FILES]\n") |
| BAREBOX_CMD_HELP_SHORT("List information about the FILEs (the current directory by default).\n") |
| BAREBOX_CMD_HELP_OPT ("-R", "list subdirectories recursively\n") |
| BAREBOX_CMD_HELP_END |
| |
| BAREBOX_CMD_START(ls) |
| .cmd = do_ls, |
| .usage = "list a file or directory", |
| BAREBOX_CMD_HELP(cmd_ls_help) |
| BAREBOX_CMD_END |