wok annotate syslinux/stuff/extra/fs.u @ rev 17902

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