wok-next 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;