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/cdefs.h> 41 #include <sys/param.h> 42 #include <ufs/ufs/dinode.h> 43 #include <ufs/ufs/dir.h> 44 45 #include <stand.h> 46 #include <string.h> 47 48 #include "bootstrap.h" 49 50 static char typestr[] = "?fc?d?b? ?l?s?w"; 51 52 static int ls_getdir(char **pathp); 53 54 COMMAND_SET(ls, "ls", "list files", command_ls); 55 56 static int 57 command_ls(int argc, char *argv[]) 58 { 59 int fd; 60 struct stat sb; 61 struct dirent *d; 62 char *buf, *path; 63 char lbuf[128]; /* one line */ 64 int result, ch; 65 int verbose; 66 67 result = CMD_OK; 68 fd = -1; 69 verbose = 0; 70 optind = 1; 71 optreset = 1; 72 while ((ch = getopt(argc, argv, "l")) != -1) { 73 switch (ch) { 74 case 'l': 75 verbose = 1; 76 break; 77 case '?': 78 default: 79 /* getopt has already reported an error */ 80 return (CMD_OK); 81 } 82 } 83 argv += (optind - 1); 84 argc -= (optind - 1); 85 86 if (argc < 2) { 87 path = ""; 88 } else { 89 path = argv[1]; 90 } 91 92 if (stat(path, &sb) == 0 && !S_ISDIR(sb.st_mode)) { 93 if (verbose) { 94 printf(" %c %8d %s\n", 95 typestr[sb.st_mode >> 12], 96 (int)sb.st_size, path); 97 } else { 98 printf(" %c %s\n", 99 typestr[sb.st_mode >> 12], path); 100 } 101 return (CMD_OK); 102 } 103 104 fd = ls_getdir(&path); 105 if (fd == -1) { 106 result = CMD_ERROR; 107 goto out; 108 } 109 pager_open(); 110 pager_output(path); 111 pager_output("\n"); 112 113 while ((d = readdirfd(fd)) != NULL) { 114 if (strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) { 115 if (d->d_type == 0 || verbose) { 116 /* stat the file, if possible */ 117 sb.st_size = 0; 118 sb.st_mode = 0; 119 buf = malloc(strlen(path) + strlen(d->d_name) + 2); 120 if (buf != NULL) { 121 sprintf(buf, "%s/%s", path, d->d_name); 122 /* ignore return, could be symlink, etc. */ 123 if (stat(buf, &sb)) { 124 sb.st_size = 0; 125 sb.st_mode = 0; 126 } 127 free(buf); 128 } 129 } 130 if (verbose) { 131 snprintf(lbuf, sizeof(lbuf), " %c %8d %s\n", 132 typestr[d->d_type? d->d_type:sb.st_mode >> 12], 133 (int)sb.st_size, d->d_name); 134 } else { 135 snprintf(lbuf, sizeof(lbuf), " %c %s\n", 136 typestr[d->d_type? d->d_type:sb.st_mode >> 12], d->d_name); 137 } 138 if (pager_output(lbuf)) 139 goto out; 140 } 141 } 142 out: 143 pager_close(); 144 if (fd != -1) 145 close(fd); 146 free(path); /* ls_getdir() did allocate path */ 147 return (result); 148 } 149 150 /* 151 * Given (path) containing a vaguely reasonable path specification, return an fd 152 * on the directory, and an allocated copy of the path to the directory. 153 */ 154 static int 155 ls_getdir(char **pathp) 156 { 157 struct stat sb; 158 int fd; 159 const char *cp; 160 char *path; 161 162 fd = -1; 163 164 /* one extra byte for a possible trailing slash required */ 165 path = malloc(strlen(*pathp) + 2); 166 if (path == NULL) { 167 snprintf(command_errbuf, sizeof (command_errbuf), 168 "out of memory"); 169 goto out; 170 } 171 strcpy(path, *pathp); 172 173 /* Make sure the path is respectable to begin with */ 174 if (archsw.arch_getdev(NULL, path, &cp)) { 175 snprintf(command_errbuf, sizeof(command_errbuf), 176 "bad path '%s'", path); 177 goto out; 178 } 179 180 /* If there's no path on the device, assume '/' */ 181 if (*cp == 0) 182 strcat(path, "/"); 183 184 fd = open(path, O_RDONLY); 185 if (fd < 0) { 186 snprintf(command_errbuf, sizeof(command_errbuf), 187 "open '%s' failed: %s", path, strerror(errno)); 188 goto out; 189 } 190 if (fstat(fd, &sb) < 0) { 191 snprintf(command_errbuf, sizeof(command_errbuf), 192 "stat failed: %s", strerror(errno)); 193 goto out; 194 } 195 if (!S_ISDIR(sb.st_mode)) { 196 snprintf(command_errbuf, sizeof(command_errbuf), 197 "%s: %s", path, strerror(ENOTDIR)); 198 goto out; 199 } 200 201 *pathp = path; 202 return (fd); 203 204 out: 205 free(path); 206 *pathp = NULL; 207 if (fd != -1) 208 close(fd); 209 return (-1); 210 } 211