ls.c revision 40106
1130803Smarcel/* 2130803Smarcel * $Id: ls.c,v 1.4 1998/10/07 02:38:26 msmith Exp $ 3130803Smarcel * From: $NetBSD: ls.c,v 1.3 1997/06/13 13:48:47 drochner Exp $ 4130803Smarcel */ 598944Sobrien 698944Sobrien/* 798944Sobrien * Copyright (c) 1993 898944Sobrien * The Regents of the University of California. All rights reserved. 998944Sobrien * Copyright (c) 1996 1098944Sobrien * Matthias Drochner. All rights reserved. 1198944Sobrien * 1298944Sobrien * Redistribution and use in source and binary forms, with or without 1398944Sobrien * modification, are permitted provided that the following conditions 1498944Sobrien * are met: 1598944Sobrien * 1. Redistributions of source code must retain the above copyright 1698944Sobrien * notice, this list of conditions and the following disclaimer. 1798944Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1898944Sobrien * notice, this list of conditions and the following disclaimer in the 1998944Sobrien * documentation and/or other materials provided with the distribution. 2098944Sobrien * 3. All advertising materials mentioning features or use of this software 2198944Sobrien * must display the following acknowledgement: 2298944Sobrien * This product includes software developed by the University of 2398944Sobrien * California, Berkeley and its contributors. 2498944Sobrien * 4. Neither the name of the University nor the names of its contributors 2598944Sobrien * may be used to endorse or promote products derived from this software 2698944Sobrien * without specific prior written permission. 2798944Sobrien * 2898944Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2998944Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3098944Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3198944Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3298944Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3398944Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3498944Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3598944Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3698944Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3798944Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3898944Sobrien * SUCH DAMAGE. 3998944Sobrien */ 4098944Sobrien 4198944Sobrien 4298944Sobrien#include <sys/param.h> 4398944Sobrien#include <ufs/ufs/dinode.h> 4498944Sobrien#include <ufs/ufs/dir.h> 4598944Sobrien 4698944Sobrien#include <stand.h> 4798944Sobrien#include <string.h> 4898944Sobrien 4998944Sobrien#include "bootstrap.h" 5098944Sobrien 51130803Smarcelstatic char typestr[] = "?fc?d?b? ?l?s?w"; 52130803Smarcel 53130803Smarcelstatic int ls_getdir(char **pathp); 54130803Smarcel 55130803SmarcelCOMMAND_SET(ls, "ls", "list files", command_ls); 56130803Smarcel 5798944Sobrienstatic int 5898944Sobriencommand_ls(int argc, char *argv[]) 5998944Sobrien{ 6098944Sobrien int fd; 6198944Sobrien size_t size; 6298944Sobrien struct stat sb; 6398944Sobrien static char dirbuf[DIRBLKSIZ]; 6498944Sobrien char *buf, *path; 6598944Sobrien char lbuf[128]; /* one line */ 6698944Sobrien int result, ch; 6798944Sobrien int verbose; 6898944Sobrien 6998944Sobrien result = CMD_OK; 7098944Sobrien fd = -1; 7198944Sobrien verbose = 0; 7298944Sobrien optind = 1; 7398944Sobrien while ((ch = getopt(argc, argv, "l")) != -1) { 7498944Sobrien switch(ch) { 75130803Smarcel case 'l': 76130803Smarcel verbose = 1; 77130803Smarcel break; 78130803Smarcel case '?': 7998944Sobrien default: 8098944Sobrien /* getopt has already reported an error */ 8198944Sobrien return(CMD_OK); 8298944Sobrien } 8398944Sobrien } 8498944Sobrien argv += (optind - 1); 8598944Sobrien argc -= (optind - 1); 8698944Sobrien 8798944Sobrien if (argc < 2) { 8898944Sobrien path = ""; 89130803Smarcel } else { 9098944Sobrien path = argv[1]; 91130803Smarcel } 9298944Sobrien 9398944Sobrien fd = ls_getdir(&path); 9498944Sobrien if (fd == -1) { 9598944Sobrien result = CMD_ERROR; 9698944Sobrien goto out; 97130803Smarcel } 9898944Sobrien pager_open(); 9998944Sobrien pager_output(path); 10098944Sobrien pager_output("\n"); 10198944Sobrien 10298944Sobrien 10398944Sobrien while ((size = read(fd, dirbuf, DIRBLKSIZ)) == DIRBLKSIZ) { 10498944Sobrien struct direct *dp, *edp; 10598944Sobrien 10698944Sobrien dp = (struct direct *) dirbuf; 10798944Sobrien edp = (struct direct *) (dirbuf + size); 10898944Sobrien 10998944Sobrien while (dp < edp) { 11098944Sobrien if (dp->d_ino != (ino_t) 0) { 11198944Sobrien 11298944Sobrien if ((dp->d_namlen > MAXNAMLEN + 1) || (dp->d_type > sizeof(typestr))) { 11398944Sobrien /* 11498944Sobrien * This does not handle "old" 11598944Sobrien * filesystems properly. On little 11698944Sobrien * endian machines, we get a bogus 117130803Smarcel * type name if the namlen matches a 118130803Smarcel * valid type identifier. We could 119130803Smarcel * check if we read namlen "0" and 120130803Smarcel * handle this case specially, if 121130803Smarcel * there were a pressing need... 122130803Smarcel */ 123130803Smarcel command_errmsg = "bad dir entry"; 124130803Smarcel result = CMD_ERROR; 12598944Sobrien goto out; 126130803Smarcel } 127130803Smarcel 128130803Smarcel if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) { 129130803Smarcel if (verbose) { 130130803Smarcel /* stat the file, if possible */ 131130803Smarcel sb.st_size = 0; 132130803Smarcel buf = malloc(strlen(path) + strlen(dp->d_name) + 2); 133130803Smarcel sprintf(buf, "%s/%s", path, dp->d_name); 134130803Smarcel /* ignore return, could be symlink, etc. */ 135130803Smarcel if (stat(buf, &sb)) 136130803Smarcel sb.st_size = 0; 13798944Sobrien free(buf); 13898944Sobrien sprintf(lbuf, " %c %8d %s\n", typestr[dp->d_type], (int)sb.st_size, dp->d_name); 13998944Sobrien } else 14098944Sobrien sprintf(lbuf, " %c %s\n", typestr[dp->d_type], dp->d_name); 14198944Sobrien if (pager_output(lbuf)) 14298944Sobrien goto out; 14398944Sobrien } 14498944Sobrien } 14598944Sobrien dp = (struct direct *) ((char *) dp + dp->d_reclen); 14698944Sobrien } 14798944Sobrien } 148130803Smarcel out: 149130803Smarcel pager_close(); 150130803Smarcel if (fd != -1) 151130803Smarcel close(fd); 15298944Sobrien if (path != NULL) 153 free(path); 154 return(result); 155} 156 157/* 158 * Given (path) containing a vaguely reasonable path specification, return an fd 159 * on the directory, and an allocated copy of the path to the directory. 160 */ 161static int 162ls_getdir(char **pathp) 163{ 164 struct stat sb; 165 int fd; 166 char *cp; 167 char *path, *tail; 168 169 tail = NULL; 170 fd = -1; 171 172 /* one extra byte for a possible trailing slash required */ 173 path = malloc(strlen(*pathp) + 2); 174 strcpy(path, *pathp); 175 176 /* Make sure the path is respectable to begin with */ 177 if (archsw.arch_getdev(NULL, path, &cp)) { 178 sprintf(command_errbuf, "bad path '%s'", path); 179 goto out; 180 } 181 182 /* If there's no path on the device, assume '/' */ 183 if (*cp == 0) 184 strcat(path, "/"); 185 186 fd = open(path, O_RDONLY); 187 if (fd < 0) { 188 sprintf(command_errbuf, "open '%s' failed: %s", path, strerror(errno)); 189 goto out; 190 } 191 if (fstat(fd, &sb) < 0) { 192 sprintf(command_errbuf, "stat failed: %s", strerror(errno)); 193 goto out; 194 } 195 if (!S_ISDIR(sb.st_mode)) { 196 sprintf(command_errbuf, "%s: %s", path, strerror(ENOTDIR)); 197 goto out; 198 } 199 200 *pathp = path; 201 return(fd); 202 203 out: 204 free(path); 205 *pathp = NULL; 206 if (fd != -1) 207 close(fd); 208 return(-1); 209} 210