1 1.2 cherry /* $NetBSD: efifs_ls.c,v 1.2 2006/04/22 07:58:53 cherry Exp $ */ 2 1.1 cherry 3 1.1 cherry /* 4 1.1 cherry * Copyright (c) 1993 5 1.1 cherry * The Regents of the University of California. All rights reserved. 6 1.1 cherry * 7 1.1 cherry * Redistribution and use in source and binary forms, with or without 8 1.1 cherry * modification, are permitted provided that the following conditions 9 1.1 cherry * are met: 10 1.1 cherry * 1. Redistributions of source code must retain the above copyright 11 1.1 cherry * notice, this list of conditions and the following disclaimer. 12 1.1 cherry * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cherry * notice, this list of conditions and the following disclaimer in the 14 1.1 cherry * documentation and/or other materials provided with the distribution. 15 1.1 cherry * 3. Neither the name of the University nor the names of its contributors 16 1.1 cherry * may be used to endorse or promote products derived from this software 17 1.1 cherry * without specific prior written permission. 18 1.1 cherry * 19 1.1 cherry * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cherry * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cherry * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cherry * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cherry * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cherry * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cherry * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cherry * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cherry * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cherry * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cherry * SUCH DAMAGE. 30 1.1 cherry */ 31 1.1 cherry 32 1.1 cherry /* 33 1.1 cherry * Copyright (c) 1996 34 1.1 cherry * Matthias Drochner. All rights reserved. 35 1.1 cherry * 36 1.1 cherry * Redistribution and use in source and binary forms, with or without 37 1.1 cherry * modification, are permitted provided that the following conditions 38 1.1 cherry * are met: 39 1.1 cherry * 1. Redistributions of source code must retain the above copyright 40 1.1 cherry * notice, this list of conditions and the following disclaimer. 41 1.1 cherry * 2. Redistributions in binary form must reproduce the above copyright 42 1.1 cherry * notice, this list of conditions and the following disclaimer in the 43 1.1 cherry * documentation and/or other materials provided with the distribution. 44 1.1 cherry * 45 1.1 cherry * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 46 1.1 cherry * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 47 1.1 cherry * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 48 1.1 cherry * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 49 1.1 cherry * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 50 1.1 cherry * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 51 1.1 cherry * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 52 1.1 cherry * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 53 1.1 cherry * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 54 1.1 cherry * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55 1.1 cherry */ 56 1.1 cherry 57 1.2 cherry /* Based on libsa/ufs_ls.c */ 58 1.1 cherry 59 1.1 cherry #include <dirent.h> 60 1.1 cherry #include <sys/param.h> 61 1.1 cherry #include <sys/stat.h> 62 1.1 cherry 63 1.1 cherry #include <lib/libkern/libkern.h> 64 1.1 cherry 65 1.1 cherry #include "stand.h" 66 1.1 cherry 67 1.1 cherry #include <efi.h> 68 1.1 cherry #include <efilib.h> 69 1.1 cherry 70 1.1 cherry #include "efifs.h" 71 1.1 cherry 72 1.1 cherry #define NELEM(x) (sizeof (x) / sizeof(*x)) 73 1.1 cherry 74 1.1 cherry typedef struct entry_t entry_t; 75 1.1 cherry struct entry_t { 76 1.1 cherry entry_t *e_next; 77 1.1 cherry ino_t e_ino; 78 1.1 cherry uint8_t e_type; 79 1.1 cherry char e_name[1]; 80 1.1 cherry }; 81 1.1 cherry 82 1.1 cherry static const char *const typestr[] = { 83 1.1 cherry "unknown", 84 1.1 cherry "FIFO", 85 1.1 cherry "CHR", 86 1.1 cherry 0, 87 1.1 cherry "DIR", 88 1.1 cherry 0, 89 1.1 cherry "BLK", 90 1.1 cherry 0, 91 1.1 cherry "REG", 92 1.1 cherry 0, 93 1.1 cherry "LNK", 94 1.1 cherry 0, 95 1.1 cherry "SOCK", 96 1.1 cherry 0, 97 1.1 cherry "WHT" 98 1.1 cherry }; 99 1.1 cherry 100 1.1 cherry static int 101 1.1 cherry fn_match(const char *fname, const char *pattern) 102 1.1 cherry { 103 1.1 cherry char fc, pc; 104 1.1 cherry 105 1.1 cherry do { 106 1.1 cherry fc = *fname++; 107 1.1 cherry pc = *pattern++; 108 1.1 cherry if (!fc && !pc) 109 1.1 cherry return 1; 110 1.1 cherry if (pc == '?' && fc) 111 1.1 cherry pc = fc; 112 1.1 cherry } while (fc == pc); 113 1.1 cherry 114 1.1 cherry if (pc != '*') 115 1.1 cherry return 0; 116 1.1 cherry /* Too hard (and unnecessary really) too check for "*?name" etc.... 117 1.1 cherry "**" will look for a '*' and "*?" a '?' */ 118 1.1 cherry pc = *pattern++; 119 1.1 cherry if (!pc) 120 1.1 cherry return 1; 121 1.1 cherry while ((fname = strchr(fname, pc))) 122 1.1 cherry if (fn_match(++fname, pattern)) 123 1.1 cherry return 1; 124 1.1 cherry return 0; 125 1.1 cherry } 126 1.1 cherry 127 1.1 cherry void 128 1.1 cherry efifs_ls(const char *path) 129 1.1 cherry { 130 1.1 cherry int fd; 131 1.1 cherry struct stat sb; 132 1.1 cherry size_t size; 133 1.1 cherry char dirbuf[DIRBLKSIZ]; 134 1.1 cherry const char *fname = 0; 135 1.1 cherry char *p; 136 1.1 cherry entry_t *names = 0, *n, **np; 137 1.1 cherry 138 1.1 cherry if ((fd = open(path, 0)) < 0 139 1.1 cherry || fstat(fd, &sb) < 0 140 1.1 cherry || (sb.st_mode & S_IFMT) != S_IFDIR) { 141 1.1 cherry /* Path supplied isn't a directory, open parent 142 1.1 cherry directory and list matching files. */ 143 1.1 cherry if (fd >= 0) 144 1.1 cherry close(fd); 145 1.1 cherry fname = strrchr(path, '/'); 146 1.1 cherry if (fname) { 147 1.1 cherry size = fname - path; 148 1.1 cherry p = alloc(size + 1); 149 1.1 cherry if (!p) 150 1.1 cherry goto out; 151 1.1 cherry memcpy(p, path, size); 152 1.1 cherry p[size] = 0; 153 1.1 cherry fd = open(p, 0); 154 1.1 cherry free(p, size + 1); 155 1.1 cherry } else { 156 1.1 cherry fd = open("", 0); 157 1.1 cherry fname = path; 158 1.1 cherry } 159 1.1 cherry 160 1.1 cherry if (fd < 0) { 161 1.1 cherry printf("ls: %s\n", strerror(errno)); 162 1.1 cherry return; 163 1.1 cherry } 164 1.1 cherry if (fstat(fd, &sb) < 0) { 165 1.1 cherry printf("stat: %s\n", strerror(errno)); 166 1.1 cherry goto out; 167 1.1 cherry } 168 1.1 cherry if ((sb.st_mode & S_IFMT) != S_IFDIR) { 169 1.1 cherry printf("%s: %s\n", path, strerror(ENOTDIR)); 170 1.1 cherry goto out; 171 1.1 cherry } 172 1.1 cherry } 173 1.1 cherry 174 1.1 cherry while ((size = read(fd, dirbuf, DIRBLKSIZ)) == DIRBLKSIZ) { 175 1.1 cherry struct dirent *dp, *edp; 176 1.1 cherry 177 1.1 cherry dp = (struct dirent *) dirbuf; 178 1.1 cherry edp = (struct dirent *) (dirbuf + size); 179 1.1 cherry 180 1.1 cherry for (; dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) { 181 1.1 cherry const char *t; 182 1.1 cherry if (dp->d_ino == 0) 183 1.1 cherry continue; 184 1.1 cherry 185 1.1 cherry if (dp->d_type >= NELEM(typestr) || 186 1.1 cherry !(t = typestr[dp->d_type])) { 187 1.1 cherry /* 188 1.1 cherry * This does not handle "old" 189 1.1 cherry * filesystems properly. On little 190 1.1 cherry * endian machines, we get a bogus 191 1.1 cherry * type name if the namlen matches a 192 1.1 cherry * valid type identifier. We could 193 1.1 cherry * check if we read namlen "0" and 194 1.1 cherry * handle this case specially, if 195 1.1 cherry * there were a pressing need... 196 1.1 cherry */ 197 1.1 cherry printf("bad dir entry\n"); 198 1.1 cherry goto out; 199 1.1 cherry } 200 1.1 cherry if (fname && !fn_match(dp->d_name, fname)) 201 1.1 cherry continue; 202 1.1 cherry n = alloc(sizeof *n + strlen(dp->d_name)); 203 1.1 cherry if (!n) { 204 1.1 cherry printf("%d: %s (%s)\n", 205 1.1 cherry dp->d_ino, dp->d_name, t); 206 1.1 cherry continue; 207 1.1 cherry } 208 1.1 cherry n->e_ino = dp->d_ino; 209 1.1 cherry n->e_type = dp->d_type; 210 1.1 cherry strcpy(n->e_name, dp->d_name); 211 1.1 cherry for (np = &names; *np; np = &(*np)->e_next) { 212 1.1 cherry if (strcmp(n->e_name, (*np)->e_name) < 0) 213 1.1 cherry break; 214 1.1 cherry } 215 1.1 cherry n->e_next = *np; 216 1.1 cherry *np = n; 217 1.1 cherry } 218 1.1 cherry } 219 1.1 cherry 220 1.1 cherry if (names) { 221 1.1 cherry do { 222 1.1 cherry n = names; 223 1.1 cherry printf("%d: %s (%s)\n", 224 1.1 cherry n->e_ino, n->e_name, typestr[n->e_type]); 225 1.1 cherry names = n->e_next; 226 1.1 cherry free(n, 0); 227 1.1 cherry } while (names); 228 1.1 cherry } else { 229 1.1 cherry printf( "%s not found\n", path ); 230 1.1 cherry } 231 1.1 cherry out: 232 1.1 cherry close(fd); 233 1.1 cherry } 234