diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | Src/utils.c | 47 |
2 files changed, 37 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog index 38d0a21d3..16215ba37 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-03-23 Peter Stephenson <pws@csr.com> + + * 26767: Src/utils.c: 26763 created file descriptor leak. + 2009-03-20 Peter Stephenson <p.w.stephenson@ntlworld.com> * 26763: Src/utils.c: fix problem restoring directory @@ -11465,5 +11469,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.4630 $ +* $Revision: 1.4631 $ ***************************************************** diff --git a/Src/utils.c b/Src/utils.c index 9716e162c..b673c4739 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -5374,6 +5374,9 @@ lchdir(char const *path, struct dirsav *d, int hard) int err; struct stat st2; #endif +#ifdef HAVE_FCHDIR + int close_dir = 0; +#endif if (!d) { ds.ino = ds.dev = 0; @@ -5400,11 +5403,6 @@ lchdir(char const *path, struct dirsav *d, int hard) d->ino = st1.st_ino; } } -#ifdef HAVE_FCHDIR - if (d->dirfd < 0 && (d->dirfd = open(".", O_RDONLY | O_NOCTTY)) < 0 && - zgetdir(d) && *d->dirname != '/') - d->dirfd = open("..", O_RDONLY | O_NOCTTY); -#endif #ifdef HAVE_LSTAT if (!hard) @@ -5420,7 +5418,16 @@ lchdir(char const *path, struct dirsav *d, int hard) } return zchdir((char *) path); } + #ifdef HAVE_LSTAT +#ifdef HAVE_FCHDIR + if (d->dirfd < 0) { + close_dir = 1; + if ((d->dirfd = open(".", O_RDONLY | O_NOCTTY) < 0) && + zgetdir(d) && *d->dirname != '/') + d->dirfd = open("..", O_RDONLY | O_NOCTTY); + } +#endif if (*path == '/') if (chdir("/") < 0) zwarn("failed to chdir(/): %e", errno); @@ -5428,12 +5435,16 @@ lchdir(char const *path, struct dirsav *d, int hard) while(*path == '/') path++; if(!*path) { - if (d == &ds) { + if (d == &ds) zsfree(ds.dirname); - if (ds.dirfd >=0) - close(ds.dirfd); - } else + else d->level = level; +#ifdef HAVE_FCHDIR + if (d->dirfd >=0 && close_dir) { + close(d->dirfd); + d->dirfd = -1; + } +#endif return 0; } for(pptr = path; *++pptr && *pptr != '/'; ) ; @@ -5468,19 +5479,25 @@ lchdir(char const *path, struct dirsav *d, int hard) } } if (restoredir(d)) { - if (d == &ds) { + if (d == &ds) zsfree(ds.dirname); - if (ds.dirfd >=0) - close(ds.dirfd); +#ifdef HAVE_FCHDIR + if (d->dirfd >=0 && close_dir) { + close(d->dirfd); + d->dirfd = -1; } +#endif errno = err; return -2; } - if (d == &ds) { + if (d == &ds) zsfree(ds.dirname); - if (ds.dirfd >=0) - close(ds.dirfd); +#ifdef HAVE_FCHDIR + if (d->dirfd >=0 && close_dir) { + close(d->dirfd); + d->dirfd = -1; } +#endif errno = err; return -1; #endif /* HAVE_LSTAT */ |