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