138465Smsmith/* 2119483Sobrien * $NetBSD: ls.c,v 1.3 1997/06/13 13:48:47 drochner Exp $ 338465Smsmith */ 438465Smsmith 5119483Sobrien/*- 638465Smsmith * Copyright (c) 1993 738465Smsmith * The Regents of the University of California. All rights reserved. 838465Smsmith * Copyright (c) 1996 938465Smsmith * Matthias Drochner. All rights reserved. 1038465Smsmith * 1138465Smsmith * Redistribution and use in source and binary forms, with or without 1238465Smsmith * modification, are permitted provided that the following conditions 1338465Smsmith * are met: 1438465Smsmith * 1. Redistributions of source code must retain the above copyright 1538465Smsmith * notice, this list of conditions and the following disclaimer. 1638465Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1738465Smsmith * notice, this list of conditions and the following disclaimer in the 1838465Smsmith * documentation and/or other materials provided with the distribution. 1938465Smsmith * 3. All advertising materials mentioning features or use of this software 2038465Smsmith * must display the following acknowledgement: 2138465Smsmith * This product includes software developed by the University of 2238465Smsmith * California, Berkeley and its contributors. 2338465Smsmith * 4. Neither the name of the University nor the names of its contributors 2438465Smsmith * may be used to endorse or promote products derived from this software 2538465Smsmith * without specific prior written permission. 2638465Smsmith * 2738465Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2838465Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2938465Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3038465Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3138465Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3238465Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3338465Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3438465Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3538465Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3638465Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3738465Smsmith * SUCH DAMAGE. 3838465Smsmith */ 3938465Smsmith 40119483Sobrien#include <sys/cdefs.h> 41119483Sobrien__FBSDID("$FreeBSD: stable/11/stand/common/ls.c 329099 2018-02-10 04:37:44Z kevans $"); 4238465Smsmith 4338465Smsmith#include <sys/param.h> 4438465Smsmith#include <ufs/ufs/dinode.h> 4538465Smsmith#include <ufs/ufs/dir.h> 4638465Smsmith 4738465Smsmith#include <stand.h> 4840106Smsmith#include <string.h> 4938465Smsmith 5038465Smsmith#include "bootstrap.h" 5138465Smsmith 5238465Smsmithstatic char typestr[] = "?fc?d?b? ?l?s?w"; 5338465Smsmith 5440106Smsmithstatic int ls_getdir(char **pathp); 5540106Smsmith 5638465SmsmithCOMMAND_SET(ls, "ls", "list files", command_ls); 5738465Smsmith 5838465Smsmithstatic int 5938465Smsmithcommand_ls(int argc, char *argv[]) 6038465Smsmith{ 6138465Smsmith int fd; 6238465Smsmith struct stat sb; 63329099Skevans struct dirent *d; 6440106Smsmith char *buf, *path; 6540106Smsmith char lbuf[128]; /* one line */ 6638465Smsmith int result, ch; 6738465Smsmith int verbose; 68329099Skevans 6940106Smsmith result = CMD_OK; 7040106Smsmith fd = -1; 7138465Smsmith verbose = 0; 7238465Smsmith optind = 1; 7342512Smsmith optreset = 1; 7438465Smsmith while ((ch = getopt(argc, argv, "l")) != -1) { 75329099Skevans switch (ch) { 7638465Smsmith case 'l': 7738465Smsmith verbose = 1; 7838465Smsmith break; 7938465Smsmith case '?': 8038465Smsmith default: 8138465Smsmith /* getopt has already reported an error */ 82329099Skevans return (CMD_OK); 8338465Smsmith } 8438465Smsmith } 8538465Smsmith argv += (optind - 1); 8638465Smsmith argc -= (optind - 1); 8738465Smsmith 8838465Smsmith if (argc < 2) { 8940106Smsmith path = ""; 9038465Smsmith } else { 9138465Smsmith path = argv[1]; 9238465Smsmith } 9338465Smsmith 94329099Skevans if (stat(path, &sb) == 0 && !S_ISDIR(sb.st_mode)) { 95329099Skevans if (verbose) { 96329099Skevans printf(" %c %8d %s\n", 97329099Skevans typestr[sb.st_mode >> 12], 98329099Skevans (int)sb.st_size, path); 99329099Skevans } else { 100329099Skevans printf(" %c %s\n", 101329099Skevans typestr[sb.st_mode >> 12], path); 102329099Skevans } 103329099Skevans return (CMD_OK); 104329099Skevans } 105329099Skevans 10640106Smsmith fd = ls_getdir(&path); 10740106Smsmith if (fd == -1) { 10840106Smsmith result = CMD_ERROR; 10940106Smsmith goto out; 11040106Smsmith } 11138465Smsmith pager_open(); 11238465Smsmith pager_output(path); 11338465Smsmith pager_output("\n"); 11438465Smsmith 11559767Sjlemon while ((d = readdirfd(fd)) != NULL) { 11659767Sjlemon if (strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) { 117329099Skevans if (d->d_type == 0 || verbose) { 11859767Sjlemon /* stat the file, if possible */ 11959767Sjlemon sb.st_size = 0; 120329099Skevans sb.st_mode = 0; 12159767Sjlemon buf = malloc(strlen(path) + strlen(d->d_name) + 2); 122329099Skevans if (buf != NULL) { 123329099Skevans sprintf(buf, "%s/%s", path, d->d_name); 124329099Skevans /* ignore return, could be symlink, etc. */ 125329099Skevans if (stat(buf, &sb)) { 126329099Skevans sb.st_size = 0; 127329099Skevans sb.st_mode = 0; 128329099Skevans } 129329099Skevans free(buf); 130329099Skevans } 131329099Skevans } 132329099Skevans if (verbose) { 133329099Skevans snprintf(lbuf, sizeof(lbuf), " %c %8d %s\n", 134329099Skevans typestr[d->d_type? d->d_type:sb.st_mode >> 12], 13559767Sjlemon (int)sb.st_size, d->d_name); 13659767Sjlemon } else { 137329099Skevans snprintf(lbuf, sizeof(lbuf), " %c %s\n", 138329099Skevans typestr[d->d_type? d->d_type:sb.st_mode >> 12], d->d_name); 13938465Smsmith } 14059767Sjlemon if (pager_output(lbuf)) 14159767Sjlemon goto out; 14238465Smsmith } 14338465Smsmith } 14438465Smsmith out: 14538465Smsmith pager_close(); 14640106Smsmith if (fd != -1) 14740106Smsmith close(fd); 148329099Skevans free(path); /* ls_getdir() did allocate path */ 149329099Skevans return (result); 15038465Smsmith} 15140106Smsmith 15240106Smsmith/* 15340106Smsmith * Given (path) containing a vaguely reasonable path specification, return an fd 15440106Smsmith * on the directory, and an allocated copy of the path to the directory. 15540106Smsmith */ 15640106Smsmithstatic int 15740106Smsmithls_getdir(char **pathp) 15840106Smsmith{ 15940106Smsmith struct stat sb; 16040106Smsmith int fd; 16140215Speter const char *cp; 162316318Sngie char *path; 16340106Smsmith 16440106Smsmith fd = -1; 16540106Smsmith 16640106Smsmith /* one extra byte for a possible trailing slash required */ 16740106Smsmith path = malloc(strlen(*pathp) + 2); 168329099Skevans if (path == NULL) { 169329099Skevans snprintf(command_errbuf, sizeof (command_errbuf), 170329099Skevans "out of memory"); 171329099Skevans goto out; 172329099Skevans } 17340106Smsmith strcpy(path, *pathp); 17440106Smsmith 17540106Smsmith /* Make sure the path is respectable to begin with */ 17640106Smsmith if (archsw.arch_getdev(NULL, path, &cp)) { 177329010Skevans snprintf(command_errbuf, sizeof(command_errbuf), 178329010Skevans "bad path '%s'", path); 17940106Smsmith goto out; 18040106Smsmith } 181329099Skevans 18240106Smsmith /* If there's no path on the device, assume '/' */ 18340106Smsmith if (*cp == 0) 18440106Smsmith strcat(path, "/"); 18540106Smsmith 18640106Smsmith fd = open(path, O_RDONLY); 18740106Smsmith if (fd < 0) { 188329010Skevans snprintf(command_errbuf, sizeof(command_errbuf), 189329010Skevans "open '%s' failed: %s", path, strerror(errno)); 19040106Smsmith goto out; 19140106Smsmith } 19240106Smsmith if (fstat(fd, &sb) < 0) { 193329010Skevans snprintf(command_errbuf, sizeof(command_errbuf), 194329010Skevans "stat failed: %s", strerror(errno)); 19540106Smsmith goto out; 19640106Smsmith } 19740106Smsmith if (!S_ISDIR(sb.st_mode)) { 198329010Skevans snprintf(command_errbuf, sizeof(command_errbuf), 199329010Skevans "%s: %s", path, strerror(ENOTDIR)); 20040106Smsmith goto out; 20140106Smsmith } 20240106Smsmith 20340106Smsmith *pathp = path; 204329099Skevans return (fd); 20540106Smsmith 20640106Smsmith out: 20740106Smsmith free(path); 20840106Smsmith *pathp = NULL; 20940106Smsmith if (fd != -1) 21040106Smsmith close(fd); 211329099Skevans return (-1); 21240106Smsmith} 213