/*1* $NetBSD: ls.c,v 1.3 1997/06/13 13:48:47 drochner Exp $2*/34/*-5* Copyright (c) 19936* The Regents of the University of California. All rights reserved.7* Copyright (c) 19968* Matthias Drochner. All rights reserved.9*10* Redistribution and use in source and binary forms, with or without11* modification, are permitted provided that the following conditions12* are met:13* 1. Redistributions of source code must retain the above copyright14* notice, this list of conditions and the following disclaimer.15* 2. Redistributions in binary form must reproduce the above copyright16* notice, this list of conditions and the following disclaimer in the17* documentation and/or other materials provided with the distribution.18* 3. All advertising materials mentioning features or use of this software19* must display the following acknowledgement:20* This product includes software developed by the University of21* California, Berkeley and its contributors.22* 4. Neither the name of the University nor the names of its contributors23* may be used to endorse or promote products derived from this software24* without specific prior written permission.25*26* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND27* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE28* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE29* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE30* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL31* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS32* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)33* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT34* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY35* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF36* SUCH DAMAGE.37*/3839#include <sys/param.h>40#include <ufs/ufs/dinode.h>41#include <ufs/ufs/dir.h>4243#include <stand.h>44#include <string.h>4546#include "bootstrap.h"4748static char typestr[] = "?fc?d?b? ?l?s?w";4950static int ls_getdir(char **pathp);5152COMMAND_SET(ls, "ls", "list files", command_ls);5354static int55command_ls(int argc, char *argv[])56{57int fd;58struct stat sb;59struct dirent *d;60char *buf, *path;61char lbuf[128]; /* one line */62int result, ch;63int verbose;6465result = CMD_OK;66fd = -1;67verbose = 0;68optind = 1;69optreset = 1;70while ((ch = getopt(argc, argv, "l")) != -1) {71switch (ch) {72case 'l':73verbose = 1;74break;75case '?':76default:77/* getopt has already reported an error */78return (CMD_OK);79}80}81argv += (optind - 1);82argc -= (optind - 1);8384if (argc < 2) {85path = "";86} else {87path = argv[1];88}8990if (stat(path, &sb) == 0 && !S_ISDIR(sb.st_mode)) {91if (verbose) {92printf(" %c %8d %s\n",93typestr[sb.st_mode >> 12],94(int)sb.st_size, path);95} else {96printf(" %c %s\n",97typestr[sb.st_mode >> 12], path);98}99return (CMD_OK);100}101102fd = ls_getdir(&path);103if (fd == -1) {104result = CMD_ERROR;105goto out;106}107pager_open();108pager_output(path);109pager_output("\n");110111while ((d = readdirfd(fd)) != NULL) {112if (strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) {113if (d->d_type == 0 || verbose) {114/* stat the file, if possible */115sb.st_size = 0;116sb.st_mode = 0;117buf = malloc(strlen(path) + strlen(d->d_name) + 2);118if (buf != NULL) {119sprintf(buf, "%s/%s", path, d->d_name);120/* ignore return, could be symlink, etc. */121if (stat(buf, &sb)) {122sb.st_size = 0;123sb.st_mode = 0;124}125free(buf);126}127}128if (verbose) {129snprintf(lbuf, sizeof(lbuf), " %c %8d %s\n",130typestr[d->d_type? d->d_type:sb.st_mode >> 12],131(int)sb.st_size, d->d_name);132} else {133snprintf(lbuf, sizeof(lbuf), " %c %s\n",134typestr[d->d_type? d->d_type:sb.st_mode >> 12], d->d_name);135}136if (pager_output(lbuf))137goto out;138}139}140out:141pager_close();142if (fd != -1)143close(fd);144free(path); /* ls_getdir() did allocate path */145return (result);146}147148/*149* Given (path) containing a vaguely reasonable path specification, return an fd150* on the directory, and an allocated copy of the path to the directory.151*/152static int153ls_getdir(char **pathp)154{155struct stat sb;156int fd;157const char *cp;158char *path;159160fd = -1;161162/* one extra byte for a possible trailing slash required */163path = malloc(strlen(*pathp) + 2);164if (path == NULL) {165snprintf(command_errbuf, sizeof (command_errbuf),166"out of memory");167goto out;168}169strcpy(path, *pathp);170171/* Make sure the path is respectable to begin with */172if (archsw.arch_getdev(NULL, path, &cp)) {173snprintf(command_errbuf, sizeof(command_errbuf),174"bad path '%s'", path);175goto out;176}177178/* If there's no path on the device, assume '/' */179if (*cp == 0)180strcat(path, "/");181182fd = open(path, O_RDONLY);183if (fd < 0) {184snprintf(command_errbuf, sizeof(command_errbuf),185"open '%s' failed: %s", path, strerror(errno));186goto out;187}188if (fstat(fd, &sb) < 0) {189snprintf(command_errbuf, sizeof(command_errbuf),190"stat failed: %s", strerror(errno));191goto out;192}193if (!S_ISDIR(sb.st_mode)) {194snprintf(command_errbuf, sizeof(command_errbuf),195"%s: %s", path, strerror(ENOTDIR));196goto out;197}198199*pathp = path;200return (fd);201202out:203free(path);204*pathp = NULL;205if (fd != -1)206close(fd);207return (-1);208}209210211