wok rev 13969

syslinux: add 5.0 searchdir resource leak fix
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Feb 03 17:35:36 2013 +0100 (2013-02-03)
parents 108b6ea76839
children 42f782f44a5e
files syslinux/receipt syslinux/stuff/extra/fs.u
line diff
     1.1 --- a/syslinux/receipt	Fri Feb 01 17:38:08 2013 -0200
     1.2 +++ b/syslinux/receipt	Sun Feb 03 17:35:36 2013 +0100
     1.3 @@ -16,8 +16,9 @@
     1.4  compile_rules()
     1.5  {
     1.6      cd $src
     1.7 -    #patch -p 0 < $stuff/extra/iso9660.u
     1.8 +    patch -p 0 < $stuff/extra/iso9660.u
     1.9      patch -p 0 < $stuff/extra/readconfig.u
    1.10 +    patch -p 0 < $stuff/extra/fs.u
    1.11      cp -a $stuff/iso2exe .
    1.12      make -C iso2exe
    1.13      cp $stuff/tools/isohybrid.sh .
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/syslinux/stuff/extra/fs.u	Sun Feb 03 17:35:36 2013 +0100
     2.3 @@ -0,0 +1,347 @@
     2.4 +--- core/fs/fs.c
     2.5 ++++ core/fs/fs.c
     2.6 +@@ -1,10 +1,16 @@
     2.7 ++#include <sys/file.h>
     2.8 + #include <stdio.h>
     2.9 + #include <stdbool.h>
    2.10 + #include <string.h>
    2.11 ++#include <unistd.h>
    2.12 + #include <dprintf.h>
    2.13 ++#include "core.h"
    2.14 ++#include "dev.h"
    2.15 + #include "fs.h"
    2.16 + #include "cache.h"
    2.17 + 
    2.18 ++char *PATH;
    2.19 ++
    2.20 + /* The currently mounted filesystem */
    2.21 + struct fs_info *this_fs = NULL;		/* Root filesystem */
    2.22 + 
    2.23 +@@ -76,19 +82,30 @@
    2.24 + }
    2.25 + 
    2.26 + /*
    2.27 +- * Convert between a 16-bit file handle and a file structure
    2.28 ++ * Find and open the configuration file
    2.29 +  */
    2.30 +-
    2.31 +-void pm_load_config(com32sys_t *regs)
    2.32 ++int open_config(void)
    2.33 + {
    2.34 +-    int err;
    2.35 ++    int fd, handle;
    2.36 ++    struct file_info *fp;
    2.37 + 
    2.38 +-    err = this_fs->fs_ops->load_config();
    2.39 ++    fd = opendev(&__file_dev, NULL, O_RDONLY);
    2.40 ++    if (fd < 0)
    2.41 ++	return -1;
    2.42 + 
    2.43 +-    if (err)
    2.44 +-	printf("ERROR: No configuration file found\n");
    2.45 ++    fp = &__file_info[fd];
    2.46 + 
    2.47 +-    set_flags(regs, err ? EFLAGS_ZF : 0);
    2.48 ++    handle = this_fs->fs_ops->open_config(&fp->i.fd);
    2.49 ++    if (handle < 0) {
    2.50 ++	close(fd);
    2.51 ++	errno = ENOENT;
    2.52 ++	return -1;
    2.53 ++    }
    2.54 ++
    2.55 ++    fp->i.offset = 0;
    2.56 ++    fp->i.nbytes = 0;
    2.57 ++
    2.58 ++    return fd;
    2.59 + }
    2.60 + 
    2.61 + void pm_mangle_name(com32sys_t *regs)
    2.62 +@@ -202,11 +219,10 @@
    2.63 + 
    2.64 + int searchdir(const char *name)
    2.65 + {
    2.66 +-    struct inode *inode = NULL;
    2.67 +-    struct inode *parent = NULL;
    2.68 ++    static char root_name[] = "/";
    2.69 +     struct file *file;
    2.70 +-    char *pathbuf = NULL;
    2.71 +-    char *part, *p, echar;
    2.72 ++    char *path, *inode_name, *next_inode_name;
    2.73 ++    struct inode *tmp, *inode = NULL;
    2.74 +     int symlink_count = MAX_SYMLINK_CNT;
    2.75 + 
    2.76 +     dprintf("searchdir: %s  root: %p  cwd: %p\n",
    2.77 +@@ -228,113 +244,165 @@
    2.78 + 
    2.79 +     /* else, try the generic-path-lookup method */
    2.80 + 
    2.81 +-    parent = get_inode(this_fs->cwd);
    2.82 +-    p = pathbuf = strdup(name);
    2.83 +-    if (!pathbuf)
    2.84 +-	goto err;
    2.85 ++    /* Copy the path */
    2.86 ++    path = strdup(name);
    2.87 ++    if (!path) {
    2.88 ++	dprintf("searchdir: Couldn't copy path\n");
    2.89 ++	goto err_path;
    2.90 ++    }
    2.91 + 
    2.92 +-    do {
    2.93 +-    got_link:
    2.94 +-	if (*p == '/') {
    2.95 +-	    put_inode(parent);
    2.96 +-	    parent = get_inode(this_fs->root);
    2.97 ++    /* Work with the current directory, by default */
    2.98 ++    inode = get_inode(this_fs->cwd);
    2.99 ++    if (!inode) {
   2.100 ++	dprintf("searchdir: Couldn't use current directory\n");
   2.101 ++	goto err_curdir;
   2.102 ++    }
   2.103 ++
   2.104 ++    for (inode_name = path; inode_name; inode_name = next_inode_name) {
   2.105 ++	/* Root directory? */
   2.106 ++	if (inode_name[0] == '/') {
   2.107 ++	    next_inode_name = inode_name + 1;
   2.108 ++	    inode_name = root_name;
   2.109 ++	} else {
   2.110 ++	    /* Find the next inode name */
   2.111 ++	    next_inode_name = strchr(inode_name + 1, '/');
   2.112 ++	    if (next_inode_name) {
   2.113 ++		/* Terminate the current inode name and point to next */
   2.114 ++		*next_inode_name++ = '\0';
   2.115 ++	    }
   2.116 + 	}
   2.117 ++	if (next_inode_name) {
   2.118 ++	    /* Advance beyond redundant slashes */
   2.119 ++	    while (*next_inode_name == '/')
   2.120 ++		next_inode_name++;
   2.121 + 
   2.122 +-	do {
   2.123 +-	    inode = get_inode(parent);
   2.124 ++	    /* Check if we're at the end */
   2.125 ++	    if (*next_inode_name == '\0')
   2.126 ++		next_inode_name = NULL;
   2.127 ++	}
   2.128 ++	dprintf("searchdir: inode_name: %s\n", inode_name);
   2.129 ++	if (next_inode_name)
   2.130 ++	    dprintf("searchdir: Remaining: %s\n", next_inode_name);
   2.131 + 
   2.132 +-	    while (*p == '/')
   2.133 +-		p++;
   2.134 ++	/* Root directory? */
   2.135 ++	if (inode_name[0] == '/') {
   2.136 ++	    /* Release any chain that's already been established */
   2.137 ++	    put_inode(inode);
   2.138 ++	    inode = get_inode(this_fs->root);
   2.139 ++	    continue;
   2.140 ++	}
   2.141 + 
   2.142 +-	    if (!*p)
   2.143 +-		break;
   2.144 ++	/* Current directory? */
   2.145 ++	if (!strncmp(inode_name, ".", sizeof "."))
   2.146 ++	    continue;
   2.147 + 
   2.148 +-	    part = p;
   2.149 +-	    while ((echar = *p) && echar != '/')
   2.150 +-		p++;
   2.151 +-	    *p++ = '\0';
   2.152 ++	/* Parent directory? */
   2.153 ++	if (!strncmp(inode_name, "..", sizeof "..")) {
   2.154 ++	    /* If there is no parent, just ignore it */
   2.155 ++	    if (!inode->parent)
   2.156 ++		continue;
   2.157 + 
   2.158 +-	    if (part[0] == '.' && part[1] == '.' && part[2] == '\0') {
   2.159 +-		if (inode->parent) {
   2.160 +-		    put_inode(parent);
   2.161 +-		    parent = get_inode(inode->parent);
   2.162 +-		    put_inode(inode);
   2.163 +-		    inode = NULL;
   2.164 +-		    if (!echar) {
   2.165 +-			/* Terminal double dots */
   2.166 +-			inode = parent;
   2.167 +-			parent = inode->parent ?
   2.168 +-			    get_inode(inode->parent) : NULL;
   2.169 +-		    }
   2.170 +-		}
   2.171 +-	    } else if (part[0] != '.' || part[1] != '\0') {
   2.172 +-		inode = this_fs->fs_ops->iget(part, parent);
   2.173 +-		if (!inode)
   2.174 +-		    goto err;
   2.175 +-		if (inode->mode == DT_LNK) {
   2.176 +-		    char *linkbuf, *q;
   2.177 +-		    int name_len = echar ? strlen(p) : 0;
   2.178 +-		    int total_len = inode->size + name_len + 2;
   2.179 +-		    int link_len;
   2.180 ++	    /* Add a reference to the parent so we can release the child */
   2.181 ++	    tmp = get_inode(inode->parent);
   2.182 + 
   2.183 +-		    if (!this_fs->fs_ops->readlink ||
   2.184 +-			--symlink_count == 0       ||      /* limit check */
   2.185 +-			total_len > MAX_SYMLINK_BUF)
   2.186 +-			goto err;
   2.187 ++	    /* Releasing the child will drop the parent back down to 1 */
   2.188 ++	    put_inode(inode);
   2.189 + 
   2.190 +-		    linkbuf = malloc(total_len);
   2.191 +-		    if (!linkbuf)
   2.192 +-			goto err;
   2.193 ++	    inode = tmp;
   2.194 ++	    continue;
   2.195 ++	}
   2.196 + 
   2.197 +-		    link_len = this_fs->fs_ops->readlink(inode, linkbuf);
   2.198 +-		    if (link_len <= 0) {
   2.199 +-			free(linkbuf);
   2.200 +-			goto err;
   2.201 +-		    }
   2.202 ++	/* Anything else */
   2.203 ++	tmp = inode;
   2.204 ++	inode = this_fs->fs_ops->iget(inode_name, inode);
   2.205 ++	if (!inode) {
   2.206 ++	    /* Failure.  Release the chain */
   2.207 ++	    put_inode(tmp);
   2.208 ++	    break;
   2.209 ++	}
   2.210 + 
   2.211 +-		    q = linkbuf + link_len;
   2.212 ++	/* Sanity-check */
   2.213 ++	if (inode->parent && inode->parent != tmp) {
   2.214 ++	    dprintf("searchdir: iget returned a different parent\n");
   2.215 ++	    put_inode(inode);
   2.216 ++	    inode = NULL;
   2.217 ++	    put_inode(tmp);
   2.218 ++	    break;
   2.219 ++	}
   2.220 ++	inode->parent = tmp;
   2.221 ++	inode->name = strdup(inode_name);
   2.222 ++	dprintf("searchdir: path component: %s\n", inode->name);
   2.223 + 
   2.224 +-		    if (echar) {
   2.225 +-			if (link_len > 0 && q[-1] != '/')
   2.226 +-			    *q++ = '/';
   2.227 ++	/* Symlink handling */
   2.228 ++	if (inode->mode == DT_LNK) {
   2.229 ++	    char *new_path;
   2.230 ++	    int new_len, copied;
   2.231 + 
   2.232 +-			memcpy(q, p, name_len+1);
   2.233 +-		    } else {
   2.234 +-			*q = '\0';
   2.235 +-		    }
   2.236 ++	    /* target path + NUL */
   2.237 ++	    new_len = inode->size + 1;
   2.238 + 
   2.239 +-		    free(pathbuf);
   2.240 +-		    p = pathbuf = linkbuf;
   2.241 +-		    put_inode(inode);
   2.242 +-		    inode = NULL;
   2.243 +-		    goto got_link;
   2.244 +-		}
   2.245 ++	    if (next_inode_name) {
   2.246 ++		/* target path + slash + remaining + NUL */
   2.247 ++		new_len += strlen(next_inode_name) + 1;
   2.248 ++	    }
   2.249 + 
   2.250 +-		inode->name = strdup(part);
   2.251 +-		dprintf("path component: %s\n", inode->name);
   2.252 ++	    if (!this_fs->fs_ops->readlink ||
   2.253 ++		/* limit checks */
   2.254 ++		--symlink_count == 0 ||
   2.255 ++		new_len > MAX_SYMLINK_BUF)
   2.256 ++		goto err_new_len;
   2.257 + 
   2.258 +-		inode->parent = parent;
   2.259 +-		parent = NULL;
   2.260 ++	    new_path = malloc(new_len);
   2.261 ++	    if (!new_path)
   2.262 ++		goto err_new_path;
   2.263 + 
   2.264 +-		if (!echar)
   2.265 +-		    break;
   2.266 ++	    copied = this_fs->fs_ops->readlink(inode, new_path);
   2.267 ++	    if (copied <= 0)
   2.268 ++		goto err_copied;
   2.269 ++	    new_path[copied] = '\0';
   2.270 ++	    dprintf("searchdir: Symlink: %s\n", new_path);
   2.271 + 
   2.272 +-		if (inode->mode != DT_DIR)
   2.273 +-		    goto err;
   2.274 +-
   2.275 +-		parent = inode;
   2.276 +-		inode = NULL;
   2.277 ++	    if (next_inode_name) {
   2.278 ++		new_path[copied] = '/';
   2.279 ++		strcpy(new_path + copied + 1, next_inode_name);
   2.280 ++		dprintf("searchdir: New path: %s\n", new_path);
   2.281 + 	    }
   2.282 +-	} while (echar);
   2.283 +-    } while (0);
   2.284 + 
   2.285 +-    free(pathbuf);
   2.286 +-    pathbuf = NULL;
   2.287 +-    put_inode(parent);
   2.288 +-    parent = NULL;
   2.289 ++	    free(path);
   2.290 ++	    path = next_inode_name = new_path;
   2.291 + 
   2.292 +-    if (!inode)
   2.293 ++            /* Add a reference to the parent so we can release the child */
   2.294 ++            tmp = get_inode(inode->parent);
   2.295 ++
   2.296 ++            /* Releasing the child will drop the parent back down to 1 */
   2.297 ++            put_inode(inode);
   2.298 ++
   2.299 ++            inode = tmp;
   2.300 ++	    continue;
   2.301 ++err_copied:
   2.302 ++	    free(new_path);
   2.303 ++err_new_path:
   2.304 ++err_new_len:
   2.305 ++	    put_inode(inode);
   2.306 ++	    inode = NULL;
   2.307 ++	    break;
   2.308 ++	}
   2.309 ++
   2.310 ++	/* If there's more to process, this should be a directory */
   2.311 ++	if (next_inode_name && inode->mode != DT_DIR) {
   2.312 ++	    dprintf("searchdir: Expected a directory\n");
   2.313 ++	    put_inode(inode);
   2.314 ++	    inode = NULL;
   2.315 ++	    break;
   2.316 ++	}
   2.317 ++    }
   2.318 ++err_curdir:
   2.319 ++    free(path);
   2.320 ++err_path:
   2.321 ++    if (!inode) {
   2.322 ++	dprintf("searchdir: Not found\n");
   2.323 + 	goto err;
   2.324 ++    }
   2.325 + 
   2.326 +     file->inode  = inode;
   2.327 +     file->offset = 0;
   2.328 +@@ -342,10 +410,6 @@
   2.329 +     return file_to_handle(file);
   2.330 + 
   2.331 + err:
   2.332 +-    put_inode(inode);
   2.333 +-    put_inode(parent);
   2.334 +-    if (pathbuf)
   2.335 +-	free(pathbuf);
   2.336 +     _close_file(file);
   2.337 + err_no_close:
   2.338 +     return -1;
   2.339 +@@ -483,6 +547,11 @@
   2.340 + 	fs.root = fs.fs_ops->iget_root(&fs);
   2.341 + 	fs.cwd = get_inode(fs.root);
   2.342 + 	dprintf("init: root inode %p, cwd inode %p\n", fs.root, fs.cwd);
   2.343 ++    }
   2.344 ++
   2.345 ++    if (fs.fs_ops->chdir_start) {
   2.346 ++	    if (fs.fs_ops->chdir_start() < 0)
   2.347 ++		    printf("Failed to chdir to start directory\n");
   2.348 +     }
   2.349 + 
   2.350 +     SectorShift = fs.sector_shift;