1 /* 2 * $NetBSD: ls.c,v 1.3 1997/06/13 13:48:47 drochner Exp $ 3 */ 4 5 /*- 6 * Copyright (c) 1993 7 * The Regents of the University of California. All rights reserved. 8 * Copyright (c) 1996 9 * Matthias Drochner. All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 */ 39 40 #include <sys/param.h> 41 #include <ufs/ufs/dinode.h> 42 #include <ufs/ufs/dir.h> 43 44 #include <stand.h> 45 #include <string.h> 46 47 #include "bootstrap.h" 48 49 static char typestr[] = "?fc?d?b? ?l?s?w"; 50 51 static int ls_getdir(char **pathp); 52 53 COMMAND_SET(ls, "ls", "list files", command_ls); 54 55 static int 56 command_ls(int argc, char *argv[]) 57 { 58 int fd; 59 struct stat sb; 60 struct dirent *d; 61 char *buf, *path; 62 char lbuf[128]; /* one line */ 63 int result, ch; 64 int verbose; 65 66 result = CMD_OK; 67 fd = -1; 68 verbose = 0; 69 optind = 1; 70 optreset = 1; 71 while ((ch = getopt(argc, argv, "l")) != -1) { 72 switch (ch) { 73 case 'l': 74 verbose = 1; 75 break; 76 case '?': 77 default: 78 /* getopt has already reported an error */ 79 return (CMD_OK); 80 } 81 } 82 argv += (optind - 1); 83 argc -= (optind - 1); 84 85 if (argc < 2) { 86 path = ""; 87 } else { 88 path = argv[1]; 89 } 90 91 if (stat(path, &sb) == 0 && !S_ISDIR(sb.st_mode)) { 92 if (verbose) { 93 printf(" %c %8d %s\n", 94 typestr[sb.st_mode >> 12], 95 (int)sb.st_size, path); 96 } else { 97 printf(" %c %s\n", 98 typestr[sb.st_mode >> 12], path); 99 } 100 return (CMD_OK); 101 } 102 103 fd = ls_getdir(&path); 104 if (fd == -1) { 105 result = CMD_ERROR; 106 goto out; 107 } 108 pager_open(); 109 pager_output(path); 110 pager_output("\n"); 111 112 while ((d = readdirfd(fd)) != NULL) { 113 if (strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) { 114 if (d->d_type == 0 || verbose) { 115 /* stat the file, if possible */ 116 sb.st_size = 0; 117 sb.st_mode = 0; 118 buf = malloc(strlen(path) + strlen(d->d_name) + 2); 119 if (buf != NULL) { 120 sprintf(buf, "%s/%s", path, d->d_name); 121 /* ignore return, could be symlink, etc. */ 122 if (stat(buf, &sb)) { 123 sb.st_size = 0; 124 sb.st_mode = 0; 125 } 126 free(buf); 127 } 128 } 129 if (verbose) { 130 snprintf(lbuf, sizeof(lbuf), " %c %8d %s\n", 131 typestr[d->d_type? d->d_type:sb.st_mode >> 12], 132 (int)sb.st_size, d->d_name); 133 } else { 134 snprintf(lbuf, sizeof(lbuf), " %c %s\n", 135 typestr[d->d_type? d->d_type:sb.st_mode >> 12], d->d_name); 136 } 137 if (pager_output(lbuf)) 138 goto out; 139 } 140 } 141 out: 142 pager_close(); 143 if (fd != -1) 144 close(fd); 145 free(path); /* ls_getdir() did allocate path */ 146 return (result); 147 } 148 149 /* 150 * Given (path) containing a vaguely reasonable path specification, return an fd 151 * on the directory, and an allocated copy of the path to the directory. 152 */ 153 static int 154 ls_getdir(char **pathp) 155 { 156 struct stat sb; 157 int fd; 158 const char *cp; 159 char *path; 160 161 fd = -1; 162 163 /* one extra byte for a possible trailing slash required */ 164 path = malloc(strlen(*pathp) + 2); 165 if (path == NULL) { 166 snprintf(command_errbuf, sizeof (command_errbuf), 167 "out of memory"); 168 goto out; 169 } 170 strcpy(path, *pathp); 171 172 /* Make sure the path is respectable to begin with */ 173 if (archsw.arch_getdev(NULL, path, &cp)) { 174 snprintf(command_errbuf, sizeof(command_errbuf), 175 "bad path '%s'", path); 176 goto out; 177 } 178 179 /* If there's no path on the device, assume '/' */ 180 if (*cp == 0) 181 strcat(path, "/"); 182 183 fd = open(path, O_RDONLY); 184 if (fd < 0) { 185 snprintf(command_errbuf, sizeof(command_errbuf), 186 "open '%s' failed: %s", path, strerror(errno)); 187 goto out; 188 } 189 if (fstat(fd, &sb) < 0) { 190 snprintf(command_errbuf, sizeof(command_errbuf), 191 "stat failed: %s", strerror(errno)); 192 goto out; 193 } 194 if (!S_ISDIR(sb.st_mode)) { 195 snprintf(command_errbuf, sizeof(command_errbuf), 196 "%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