wok-6.x view syslinux/stuff/extra/fs.u @ rev 17077
QtWeb: /suggests/suggested/, move to deps
author | Xander Ziiryanoff <psychomaniak@xakep.ru> |
---|---|
date | Sun Aug 24 09:53:06 2014 +0200 (2014-08-24) |
parents | |
children |
line source
1 --- core/fs/fs.c
2 +++ core/fs/fs.c
3 @@ -1,10 +1,16 @@
4 +#include <sys/file.h>
5 #include <stdio.h>
6 #include <stdbool.h>
7 #include <string.h>
8 +#include <unistd.h>
9 #include <dprintf.h>
10 +#include "core.h"
11 +#include "dev.h"
12 #include "fs.h"
13 #include "cache.h"
15 +char *PATH;
16 +
17 /* The currently mounted filesystem */
18 struct fs_info *this_fs = NULL; /* Root filesystem */
20 @@ -76,19 +82,30 @@
21 }
23 /*
24 - * Convert between a 16-bit file handle and a file structure
25 + * Find and open the configuration file
26 */
27 -
28 -void pm_load_config(com32sys_t *regs)
29 +int open_config(void)
30 {
31 - int err;
32 + int fd, handle;
33 + struct file_info *fp;
35 - err = this_fs->fs_ops->load_config();
36 + fd = opendev(&__file_dev, NULL, O_RDONLY);
37 + if (fd < 0)
38 + return -1;
40 - if (err)
41 - printf("ERROR: No configuration file found\n");
42 + fp = &__file_info[fd];
44 - set_flags(regs, err ? EFLAGS_ZF : 0);
45 + handle = this_fs->fs_ops->open_config(&fp->i.fd);
46 + if (handle < 0) {
47 + close(fd);
48 + errno = ENOENT;
49 + return -1;
50 + }
51 +
52 + fp->i.offset = 0;
53 + fp->i.nbytes = 0;
54 +
55 + return fd;
56 }
58 void pm_mangle_name(com32sys_t *regs)
59 @@ -202,11 +219,10 @@
61 int searchdir(const char *name)
62 {
63 - struct inode *inode = NULL;
64 - struct inode *parent = NULL;
65 + static char root_name[] = "/";
66 struct file *file;
67 - char *pathbuf = NULL;
68 - char *part, *p, echar;
69 + char *path, *inode_name, *next_inode_name;
70 + struct inode *tmp, *inode = NULL;
71 int symlink_count = MAX_SYMLINK_CNT;
73 dprintf("searchdir: %s root: %p cwd: %p\n",
74 @@ -228,113 +244,165 @@
76 /* else, try the generic-path-lookup method */
78 - parent = get_inode(this_fs->cwd);
79 - p = pathbuf = strdup(name);
80 - if (!pathbuf)
81 - goto err;
82 + /* Copy the path */
83 + path = strdup(name);
84 + if (!path) {
85 + dprintf("searchdir: Couldn't copy path\n");
86 + goto err_path;
87 + }
89 - do {
90 - got_link:
91 - if (*p == '/') {
92 - put_inode(parent);
93 - parent = get_inode(this_fs->root);
94 + /* Work with the current directory, by default */
95 + inode = get_inode(this_fs->cwd);
96 + if (!inode) {
97 + dprintf("searchdir: Couldn't use current directory\n");
98 + goto err_curdir;
99 + }
100 +
101 + for (inode_name = path; inode_name; inode_name = next_inode_name) {
102 + /* Root directory? */
103 + if (inode_name[0] == '/') {
104 + next_inode_name = inode_name + 1;
105 + inode_name = root_name;
106 + } else {
107 + /* Find the next inode name */
108 + next_inode_name = strchr(inode_name + 1, '/');
109 + if (next_inode_name) {
110 + /* Terminate the current inode name and point to next */
111 + *next_inode_name++ = '\0';
112 + }
113 }
114 + if (next_inode_name) {
115 + /* Advance beyond redundant slashes */
116 + while (*next_inode_name == '/')
117 + next_inode_name++;
119 - do {
120 - inode = get_inode(parent);
121 + /* Check if we're at the end */
122 + if (*next_inode_name == '\0')
123 + next_inode_name = NULL;
124 + }
125 + dprintf("searchdir: inode_name: %s\n", inode_name);
126 + if (next_inode_name)
127 + dprintf("searchdir: Remaining: %s\n", next_inode_name);
129 - while (*p == '/')
130 - p++;
131 + /* Root directory? */
132 + if (inode_name[0] == '/') {
133 + /* Release any chain that's already been established */
134 + put_inode(inode);
135 + inode = get_inode(this_fs->root);
136 + continue;
137 + }
139 - if (!*p)
140 - break;
141 + /* Current directory? */
142 + if (!strncmp(inode_name, ".", sizeof "."))
143 + continue;
145 - part = p;
146 - while ((echar = *p) && echar != '/')
147 - p++;
148 - *p++ = '\0';
149 + /* Parent directory? */
150 + if (!strncmp(inode_name, "..", sizeof "..")) {
151 + /* If there is no parent, just ignore it */
152 + if (!inode->parent)
153 + continue;
155 - if (part[0] == '.' && part[1] == '.' && part[2] == '\0') {
156 - if (inode->parent) {
157 - put_inode(parent);
158 - parent = get_inode(inode->parent);
159 - put_inode(inode);
160 - inode = NULL;
161 - if (!echar) {
162 - /* Terminal double dots */
163 - inode = parent;
164 - parent = inode->parent ?
165 - get_inode(inode->parent) : NULL;
166 - }
167 - }
168 - } else if (part[0] != '.' || part[1] != '\0') {
169 - inode = this_fs->fs_ops->iget(part, parent);
170 - if (!inode)
171 - goto err;
172 - if (inode->mode == DT_LNK) {
173 - char *linkbuf, *q;
174 - int name_len = echar ? strlen(p) : 0;
175 - int total_len = inode->size + name_len + 2;
176 - int link_len;
177 + /* Add a reference to the parent so we can release the child */
178 + tmp = get_inode(inode->parent);
180 - if (!this_fs->fs_ops->readlink ||
181 - --symlink_count == 0 || /* limit check */
182 - total_len > MAX_SYMLINK_BUF)
183 - goto err;
184 + /* Releasing the child will drop the parent back down to 1 */
185 + put_inode(inode);
187 - linkbuf = malloc(total_len);
188 - if (!linkbuf)
189 - goto err;
190 + inode = tmp;
191 + continue;
192 + }
194 - link_len = this_fs->fs_ops->readlink(inode, linkbuf);
195 - if (link_len <= 0) {
196 - free(linkbuf);
197 - goto err;
198 - }
199 + /* Anything else */
200 + tmp = inode;
201 + inode = this_fs->fs_ops->iget(inode_name, inode);
202 + if (!inode) {
203 + /* Failure. Release the chain */
204 + put_inode(tmp);
205 + break;
206 + }
208 - q = linkbuf + link_len;
209 + /* Sanity-check */
210 + if (inode->parent && inode->parent != tmp) {
211 + dprintf("searchdir: iget returned a different parent\n");
212 + put_inode(inode);
213 + inode = NULL;
214 + put_inode(tmp);
215 + break;
216 + }
217 + inode->parent = tmp;
218 + inode->name = strdup(inode_name);
219 + dprintf("searchdir: path component: %s\n", inode->name);
221 - if (echar) {
222 - if (link_len > 0 && q[-1] != '/')
223 - *q++ = '/';
224 + /* Symlink handling */
225 + if (inode->mode == DT_LNK) {
226 + char *new_path;
227 + int new_len, copied;
229 - memcpy(q, p, name_len+1);
230 - } else {
231 - *q = '\0';
232 - }
233 + /* target path + NUL */
234 + new_len = inode->size + 1;
236 - free(pathbuf);
237 - p = pathbuf = linkbuf;
238 - put_inode(inode);
239 - inode = NULL;
240 - goto got_link;
241 - }
242 + if (next_inode_name) {
243 + /* target path + slash + remaining + NUL */
244 + new_len += strlen(next_inode_name) + 1;
245 + }
247 - inode->name = strdup(part);
248 - dprintf("path component: %s\n", inode->name);
249 + if (!this_fs->fs_ops->readlink ||
250 + /* limit checks */
251 + --symlink_count == 0 ||
252 + new_len > MAX_SYMLINK_BUF)
253 + goto err_new_len;
255 - inode->parent = parent;
256 - parent = NULL;
257 + new_path = malloc(new_len);
258 + if (!new_path)
259 + goto err_new_path;
261 - if (!echar)
262 - break;
263 + copied = this_fs->fs_ops->readlink(inode, new_path);
264 + if (copied <= 0)
265 + goto err_copied;
266 + new_path[copied] = '\0';
267 + dprintf("searchdir: Symlink: %s\n", new_path);
269 - if (inode->mode != DT_DIR)
270 - goto err;
271 -
272 - parent = inode;
273 - inode = NULL;
274 + if (next_inode_name) {
275 + new_path[copied] = '/';
276 + strcpy(new_path + copied + 1, next_inode_name);
277 + dprintf("searchdir: New path: %s\n", new_path);
278 }
279 - } while (echar);
280 - } while (0);
282 - free(pathbuf);
283 - pathbuf = NULL;
284 - put_inode(parent);
285 - parent = NULL;
286 + free(path);
287 + path = next_inode_name = new_path;
289 - if (!inode)
290 + /* Add a reference to the parent so we can release the child */
291 + tmp = get_inode(inode->parent);
292 +
293 + /* Releasing the child will drop the parent back down to 1 */
294 + put_inode(inode);
295 +
296 + inode = tmp;
297 + continue;
298 +err_copied:
299 + free(new_path);
300 +err_new_path:
301 +err_new_len:
302 + put_inode(inode);
303 + inode = NULL;
304 + break;
305 + }
306 +
307 + /* If there's more to process, this should be a directory */
308 + if (next_inode_name && inode->mode != DT_DIR) {
309 + dprintf("searchdir: Expected a directory\n");
310 + put_inode(inode);
311 + inode = NULL;
312 + break;
313 + }
314 + }
315 +err_curdir:
316 + free(path);
317 +err_path:
318 + if (!inode) {
319 + dprintf("searchdir: Not found\n");
320 goto err;
321 + }
323 file->inode = inode;
324 file->offset = 0;
325 @@ -342,10 +410,6 @@
326 return file_to_handle(file);
328 err:
329 - put_inode(inode);
330 - put_inode(parent);
331 - if (pathbuf)
332 - free(pathbuf);
333 _close_file(file);
334 err_no_close:
335 return -1;
336 @@ -483,6 +547,11 @@
337 fs.root = fs.fs_ops->iget_root(&fs);
338 fs.cwd = get_inode(fs.root);
339 dprintf("init: root inode %p, cwd inode %p\n", fs.root, fs.cwd);
340 + }
341 +
342 + if (fs.fs_ops->chdir_start) {
343 + if (fs.fs_ops->chdir_start() < 0)
344 + printf("Failed to chdir to start directory\n");
345 }
347 SectorShift = fs.sector_shift;