efifs_ls.c revision 1.2.2.3 1 1.2.2.3 kardel /* $NetBSD: efifs_ls.c,v 1.2.2.3 2006/06/01 22:34:54 kardel 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.3 kardel /* Based on libsa/ufs_ls.c */
58 1.2.2.2 simonb
59 1.2.2.2 simonb #include <dirent.h>
60 1.2.2.2 simonb #include <sys/param.h>
61 1.2.2.2 simonb #include <sys/stat.h>
62 1.2.2.2 simonb
63 1.2.2.2 simonb #include <lib/libkern/libkern.h>
64 1.2.2.2 simonb
65 1.2.2.2 simonb #include "stand.h"
66 1.2.2.2 simonb
67 1.2.2.2 simonb #include <efi.h>
68 1.2.2.2 simonb #include <efilib.h>
69 1.2.2.2 simonb
70 1.2.2.2 simonb #include "efifs.h"
71 1.2.2.2 simonb
72 1.2.2.2 simonb #define NELEM(x) (sizeof (x) / sizeof(*x))
73 1.2.2.2 simonb
74 1.2.2.2 simonb typedef struct entry_t entry_t;
75 1.2.2.2 simonb struct entry_t {
76 1.2.2.2 simonb entry_t *e_next;
77 1.2.2.2 simonb ino_t e_ino;
78 1.2.2.2 simonb uint8_t e_type;
79 1.2.2.2 simonb char e_name[1];
80 1.2.2.2 simonb };
81 1.2.2.2 simonb
82 1.2.2.2 simonb static const char *const typestr[] = {
83 1.2.2.2 simonb "unknown",
84 1.2.2.2 simonb "FIFO",
85 1.2.2.2 simonb "CHR",
86 1.2.2.2 simonb 0,
87 1.2.2.2 simonb "DIR",
88 1.2.2.2 simonb 0,
89 1.2.2.2 simonb "BLK",
90 1.2.2.2 simonb 0,
91 1.2.2.2 simonb "REG",
92 1.2.2.2 simonb 0,
93 1.2.2.2 simonb "LNK",
94 1.2.2.2 simonb 0,
95 1.2.2.2 simonb "SOCK",
96 1.2.2.2 simonb 0,
97 1.2.2.2 simonb "WHT"
98 1.2.2.2 simonb };
99 1.2.2.2 simonb
100 1.2.2.2 simonb static int
101 1.2.2.2 simonb fn_match(const char *fname, const char *pattern)
102 1.2.2.2 simonb {
103 1.2.2.2 simonb char fc, pc;
104 1.2.2.2 simonb
105 1.2.2.2 simonb do {
106 1.2.2.2 simonb fc = *fname++;
107 1.2.2.2 simonb pc = *pattern++;
108 1.2.2.2 simonb if (!fc && !pc)
109 1.2.2.2 simonb return 1;
110 1.2.2.2 simonb if (pc == '?' && fc)
111 1.2.2.2 simonb pc = fc;
112 1.2.2.2 simonb } while (fc == pc);
113 1.2.2.2 simonb
114 1.2.2.2 simonb if (pc != '*')
115 1.2.2.2 simonb return 0;
116 1.2.2.2 simonb /* Too hard (and unnecessary really) too check for "*?name" etc....
117 1.2.2.2 simonb "**" will look for a '*' and "*?" a '?' */
118 1.2.2.2 simonb pc = *pattern++;
119 1.2.2.2 simonb if (!pc)
120 1.2.2.2 simonb return 1;
121 1.2.2.2 simonb while ((fname = strchr(fname, pc)))
122 1.2.2.2 simonb if (fn_match(++fname, pattern))
123 1.2.2.2 simonb return 1;
124 1.2.2.2 simonb return 0;
125 1.2.2.2 simonb }
126 1.2.2.2 simonb
127 1.2.2.2 simonb void
128 1.2.2.2 simonb efifs_ls(const char *path)
129 1.2.2.2 simonb {
130 1.2.2.2 simonb int fd;
131 1.2.2.2 simonb struct stat sb;
132 1.2.2.2 simonb size_t size;
133 1.2.2.2 simonb char dirbuf[DIRBLKSIZ];
134 1.2.2.2 simonb const char *fname = 0;
135 1.2.2.2 simonb char *p;
136 1.2.2.2 simonb entry_t *names = 0, *n, **np;
137 1.2.2.2 simonb
138 1.2.2.2 simonb if ((fd = open(path, 0)) < 0
139 1.2.2.2 simonb || fstat(fd, &sb) < 0
140 1.2.2.2 simonb || (sb.st_mode & S_IFMT) != S_IFDIR) {
141 1.2.2.2 simonb /* Path supplied isn't a directory, open parent
142 1.2.2.2 simonb directory and list matching files. */
143 1.2.2.2 simonb if (fd >= 0)
144 1.2.2.2 simonb close(fd);
145 1.2.2.2 simonb fname = strrchr(path, '/');
146 1.2.2.2 simonb if (fname) {
147 1.2.2.2 simonb size = fname - path;
148 1.2.2.2 simonb p = alloc(size + 1);
149 1.2.2.2 simonb if (!p)
150 1.2.2.2 simonb goto out;
151 1.2.2.2 simonb memcpy(p, path, size);
152 1.2.2.2 simonb p[size] = 0;
153 1.2.2.2 simonb fd = open(p, 0);
154 1.2.2.2 simonb free(p, size + 1);
155 1.2.2.2 simonb } else {
156 1.2.2.2 simonb fd = open("", 0);
157 1.2.2.2 simonb fname = path;
158 1.2.2.2 simonb }
159 1.2.2.2 simonb
160 1.2.2.2 simonb if (fd < 0) {
161 1.2.2.2 simonb printf("ls: %s\n", strerror(errno));
162 1.2.2.2 simonb return;
163 1.2.2.2 simonb }
164 1.2.2.2 simonb if (fstat(fd, &sb) < 0) {
165 1.2.2.2 simonb printf("stat: %s\n", strerror(errno));
166 1.2.2.2 simonb goto out;
167 1.2.2.2 simonb }
168 1.2.2.2 simonb if ((sb.st_mode & S_IFMT) != S_IFDIR) {
169 1.2.2.2 simonb printf("%s: %s\n", path, strerror(ENOTDIR));
170 1.2.2.2 simonb goto out;
171 1.2.2.2 simonb }
172 1.2.2.2 simonb }
173 1.2.2.2 simonb
174 1.2.2.2 simonb while ((size = read(fd, dirbuf, DIRBLKSIZ)) == DIRBLKSIZ) {
175 1.2.2.2 simonb struct dirent *dp, *edp;
176 1.2.2.2 simonb
177 1.2.2.2 simonb dp = (struct dirent *) dirbuf;
178 1.2.2.2 simonb edp = (struct dirent *) (dirbuf + size);
179 1.2.2.2 simonb
180 1.2.2.2 simonb for (; dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) {
181 1.2.2.2 simonb const char *t;
182 1.2.2.2 simonb if (dp->d_ino == 0)
183 1.2.2.2 simonb continue;
184 1.2.2.2 simonb
185 1.2.2.2 simonb if (dp->d_type >= NELEM(typestr) ||
186 1.2.2.2 simonb !(t = typestr[dp->d_type])) {
187 1.2.2.2 simonb /*
188 1.2.2.2 simonb * This does not handle "old"
189 1.2.2.2 simonb * filesystems properly. On little
190 1.2.2.2 simonb * endian machines, we get a bogus
191 1.2.2.2 simonb * type name if the namlen matches a
192 1.2.2.2 simonb * valid type identifier. We could
193 1.2.2.2 simonb * check if we read namlen "0" and
194 1.2.2.2 simonb * handle this case specially, if
195 1.2.2.2 simonb * there were a pressing need...
196 1.2.2.2 simonb */
197 1.2.2.2 simonb printf("bad dir entry\n");
198 1.2.2.2 simonb goto out;
199 1.2.2.2 simonb }
200 1.2.2.2 simonb if (fname && !fn_match(dp->d_name, fname))
201 1.2.2.2 simonb continue;
202 1.2.2.2 simonb n = alloc(sizeof *n + strlen(dp->d_name));
203 1.2.2.2 simonb if (!n) {
204 1.2.2.2 simonb printf("%d: %s (%s)\n",
205 1.2.2.2 simonb dp->d_ino, dp->d_name, t);
206 1.2.2.2 simonb continue;
207 1.2.2.2 simonb }
208 1.2.2.2 simonb n->e_ino = dp->d_ino;
209 1.2.2.2 simonb n->e_type = dp->d_type;
210 1.2.2.2 simonb strcpy(n->e_name, dp->d_name);
211 1.2.2.2 simonb for (np = &names; *np; np = &(*np)->e_next) {
212 1.2.2.2 simonb if (strcmp(n->e_name, (*np)->e_name) < 0)
213 1.2.2.2 simonb break;
214 1.2.2.2 simonb }
215 1.2.2.2 simonb n->e_next = *np;
216 1.2.2.2 simonb *np = n;
217 1.2.2.2 simonb }
218 1.2.2.2 simonb }
219 1.2.2.2 simonb
220 1.2.2.2 simonb if (names) {
221 1.2.2.2 simonb do {
222 1.2.2.2 simonb n = names;
223 1.2.2.2 simonb printf("%d: %s (%s)\n",
224 1.2.2.2 simonb n->e_ino, n->e_name, typestr[n->e_type]);
225 1.2.2.2 simonb names = n->e_next;
226 1.2.2.2 simonb free(n, 0);
227 1.2.2.2 simonb } while (names);
228 1.2.2.2 simonb } else {
229 1.2.2.2 simonb printf( "%s not found\n", path );
230 1.2.2.2 simonb }
231 1.2.2.2 simonb out:
232 1.2.2.2 simonb close(fd);
233 1.2.2.2 simonb }
234