1214077Sgibbs/* 2214077Sgibbs * $NetBSD: ls.c,v 1.3 2009/07/20 04:59:03 kiyohara Exp $ 3214077Sgibbs */ 4214077Sgibbs 5214077Sgibbs/*- 6214077Sgibbs * Copyright (c) 1993 7214077Sgibbs * The Regents of the University of California. All rights reserved. 8214077Sgibbs * Copyright (c) 1996 9214077Sgibbs * Matthias Drochner. All rights reserved. 10214077Sgibbs * 11214077Sgibbs * Redistribution and use in source and binary forms, with or without 12214077Sgibbs * modification, are permitted provided that the following conditions 13214077Sgibbs * are met: 14214077Sgibbs * 1. Redistributions of source code must retain the above copyright 15214077Sgibbs * notice, this list of conditions and the following disclaimer. 16214077Sgibbs * 2. Redistributions in binary form must reproduce the above copyright 17214077Sgibbs * notice, this list of conditions and the following disclaimer in the 18214077Sgibbs * documentation and/or other materials provided with the distribution. 19214077Sgibbs * 3. All advertising materials mentioning features or use of this software 20214077Sgibbs * must display the following acknowledgement: 21214077Sgibbs * This product includes software developed by the University of 22214077Sgibbs * California, Berkeley and its contributors. 23214077Sgibbs * 4. Neither the name of the University nor the names of its contributors 24214077Sgibbs * may be used to endorse or promote products derived from this software 25214077Sgibbs * without specific prior written permission. 26214077Sgibbs * 27214077Sgibbs * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28214077Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29214077Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30214077Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31214077Sgibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32214077Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33214077Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34214077Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35214077Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36214077Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37214077Sgibbs * SUCH DAMAGE. 38214077Sgibbs */ 39214077Sgibbs 40214077Sgibbs#include <sys/cdefs.h> 41214077Sgibbs/* __FBSDID("$FreeBSD: src/sys/boot/common/ls.c,v 1.11 2003/08/25 23:30:41 obrien Exp $"); */ 42214077Sgibbs 43214077Sgibbs 44214077Sgibbs#include <sys/param.h> 45214077Sgibbs#include <ufs/ufs/dinode.h> 46214077Sgibbs#include <ufs/ufs/dir.h> 47214077Sgibbs#include <sys/dirent.h> 48214077Sgibbs 49214077Sgibbs#include <lib/libsa/stand.h> 50214077Sgibbs#include <lib/libsa/loadfile.h> 51214077Sgibbs 52214077Sgibbs#include "bootstrap.h" 53214077Sgibbs 54214077Sgibbsstatic char typestr[] = "?fc?d?b? ?l?s?w"; 55214077Sgibbs 56214077Sgibbsstatic int ls_getdir(char **pathp); 57214077Sgibbs 58214077Sgibbsint 59214077Sgibbscommand_ls(int argc, char *argv[]) 60214077Sgibbs{ 61214077Sgibbs int fd; 62214077Sgibbs struct stat sb; 63214077Sgibbs struct dirent *d; 64214077Sgibbs char *buf, *path; 65214077Sgibbs char lbuf[128]; /* one line */ 66214077Sgibbs int result, ch; 67214077Sgibbs int verbose; 68214077Sgibbs 69214077Sgibbs result = CMD_OK; 70214077Sgibbs fd = -1; 71214077Sgibbs verbose = 0; 72214077Sgibbs optind = 1; 73214077Sgibbs optreset = 1; 74214077Sgibbs while ((ch = getopt(argc, argv, "l")) != -1) { 75214077Sgibbs switch(ch) { 76214077Sgibbs case 'l': 77214077Sgibbs verbose = 1; 78214077Sgibbs break; 79214077Sgibbs case '?': 80214077Sgibbs default: 81214077Sgibbs /* getopt has already reported an error */ 82214077Sgibbs return(CMD_OK); 83214077Sgibbs } 84214077Sgibbs } 85214077Sgibbs argv += (optind - 1); 86214077Sgibbs argc -= (optind - 1); 87214077Sgibbs 88214077Sgibbs if (argc < 2) { 89214077Sgibbs path = ""; 90214077Sgibbs } else { 91214077Sgibbs path = argv[1]; 92214077Sgibbs } 93214077Sgibbs 94214077Sgibbs fd = ls_getdir(&path); 95214077Sgibbs if (fd == -1) { 96214077Sgibbs result = CMD_ERROR; 97214077Sgibbs goto out; 98214077Sgibbs } 99214077Sgibbs 100214077Sgibbs pager_open(); 101214077Sgibbs pager_output(path); 102214077Sgibbs pager_output("\n"); 103214077Sgibbs 104214077Sgibbs while ((d = readdirfd(fd)) != NULL) { 105214077Sgibbs/* if (strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) { */ 106214077Sgibbs if (verbose) { 107214077Sgibbs size_t buflen; 108214077Sgibbs /* stat the file, if possible */ 109214077Sgibbs sb.st_size = 0; 110214077Sgibbs buflen = strlen(path) + strlen(d->d_name) + 2; 111214077Sgibbs buf = alloc(buflen); 112214077Sgibbs snprintf(buf, buflen, "%s/%s", path, d->d_name); 113214077Sgibbs /* ignore return, could be symlink, etc. */ 114214077Sgibbs if (stat(buf, &sb)) 115214077Sgibbs sb.st_size = 0; 116214077Sgibbs free(buf); 117214077Sgibbs snprintf(lbuf, sizeof(lbuf), " %c %8d %s\n", typestr[d->d_type], 118214077Sgibbs (int)sb.st_size, d->d_name); 119214077Sgibbs } else { 120214077Sgibbs snprintf(lbuf, sizeof(lbuf), " %c %s\n", typestr[d->d_type], 121214077Sgibbs d->d_name); 122214077Sgibbs } 123214077Sgibbs if (pager_output(lbuf)) 124214077Sgibbs goto out; 125214077Sgibbs /* } */ 126214077Sgibbs } 127214077Sgibbs out: 128214077Sgibbs pager_close(); 129214077Sgibbs if (fd != -1) 130214077Sgibbs close(fd); 131214077Sgibbs if (path != NULL) 132214077Sgibbs free(path); 133214077Sgibbs return(result); 134214077Sgibbs} 135214077Sgibbs 136214077Sgibbs/* 137214077Sgibbs * Given (path) containing a vaguely reasonable path specification, return an fd 138214077Sgibbs * on the directory, and an allocated copy of the path to the directory. 139214077Sgibbs */ 140214077Sgibbsstatic int 141214077Sgibbsls_getdir(char **pathp) 142214077Sgibbs{ 143214077Sgibbs struct stat sb; 144214077Sgibbs int fd; 145214077Sgibbs const char *cp; 146214077Sgibbs char *path, *tail; 147214077Sgibbs 148214077Sgibbs tail = NULL; 149214077Sgibbs fd = -1; 150214077Sgibbs 151214077Sgibbs /* one extra byte for a possible trailing slash required */ 152214077Sgibbs path = alloc(strlen(*pathp) + 2); 153214077Sgibbs strcpy(path, *pathp); 154214077Sgibbs 155214077Sgibbs /* Make sure the path is respectable to begin with */ 156214077Sgibbs if (archsw.arch_getdev(NULL, path, &cp)) { 157214077Sgibbs command_seterr("bad path '%s'", path); 158214077Sgibbs goto out; 159214077Sgibbs } 160214077Sgibbs 161214077Sgibbs /* If there's no path on the device, assume '/' */ 162214077Sgibbs if (*cp == 0) 163214077Sgibbs strcat(path, "/"); 164214077Sgibbs fd = open(path, O_RDONLY); 165214077Sgibbs if (fd < 0) { 166214077Sgibbs command_seterr("open '%s' failed: %s", path, strerror(errno)); 167214077Sgibbs goto out; 168214077Sgibbs } 169214077Sgibbs if (fstat(fd, &sb) < 0) { 170214077Sgibbs command_seterr("stat failed: %s", strerror(errno)); 171214077Sgibbs goto out; 172214077Sgibbs } 173214077Sgibbs if (!S_ISDIR(sb.st_mode)) { 174214077Sgibbs command_seterr("%s: %s", path, strerror(ENOTDIR)); 175214077Sgibbs goto out; 176214077Sgibbs } 177214077Sgibbs 178214077Sgibbs *pathp = path; 179214077Sgibbs return(fd); 180214077Sgibbs 181214077Sgibbs out: 182214077Sgibbs free(path); 183214077Sgibbs *pathp = NULL; 184214077Sgibbs if (fd != -1) 185214077Sgibbs close(fd); 186214077Sgibbs return(-1); 187214077Sgibbs} 188214077Sgibbs