From 9defc9850d0d73742856165f595899f0d8a87c6d Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 24 Mar 2009 12:52:07 +0000 Subject: 26772: better error handling and fix runaway chdir on failed cd --- ChangeLog | 8 +++++++- Src/Modules/files.c | 8 ++------ Src/glob.c | 4 +--- Src/utils.c | 30 +++++++++++++++++++++++++++--- Src/zsh.h | 1 + 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index b5deadc77..e1f014314 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-03-24 Peter Stephenson + + * 26772: Src/glob.c, Src/utils.c, Src/zsh.h, Src/Modules/files.c: + more failed cd handling: fix possible runaway series of chdirs; + better error handling. + 2009-03-23 Peter Stephenson * 26769: Src/utils.c: 26767 created an even worse problem. @@ -11474,5 +11480,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.4633 $ +* $Revision: 1.4634 $ ***************************************************** diff --git a/Src/Modules/files.c b/Src/Modules/files.c index 0b991c556..3fbccf576 100644 --- a/Src/Modules/files.c +++ b/Src/Modules/files.c @@ -382,9 +382,7 @@ recursivecmd(char *nam, int opt_noerr, int opt_recurse, int opt_safe, reccmd.dirpost_func = dirpost_func; reccmd.leaf_func = leaf_func; reccmd.magic = magic; - ds.ino = ds.dev = 0; - ds.dirname = NULL; - ds.dirfd = ds.level = -1; + init_dirsav(&ds); if (opt_recurse || opt_safe) { if ((ds.dirfd = open(".", O_RDONLY|O_NOCTTY)) < 0 && zgetdir(&ds) && *ds.dirname != '/') @@ -476,9 +474,7 @@ recursivecmd_dorec(struct recursivecmd const *reccmd, } err = err1; - dsav.ino = dsav.dev = 0; - dsav.dirname = NULL; - dsav.dirfd = dsav.level = -1; + init_dirsav(&dsav); d = opendir("."); if(!d) { if(!reccmd->opt_noerr) diff --git a/Src/glob.c b/Src/glob.c index 5000ff457..46a0ce9c0 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -492,9 +492,7 @@ scanner(Complist q) int errssofar = errsfound; struct dirsav ds; - ds.ino = ds.dev = 0; - ds.dirname = NULL; - ds.dirfd = ds.level = -1; + init_dirsav(&ds); if (!q) return; diff --git a/Src/utils.c b/Src/utils.c index 969f2cf09..9bf7878e0 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -5356,6 +5356,21 @@ upchdir(int n) return 0; } +/* + * Initialize a "struct dirsav". + * The structure will be set to the directory we want to save + * the first time we change to a different directory. + */ + +/**/ +mod_export void +init_dirsav(Dirsav d) +{ + d->ino = d->dev = 0; + d->dirname = NULL; + d->dirfd = d->level = -1; +} + /* Change directory, without following symlinks. Returns 0 on success, -1 * * on failure. Sets errno to ENOTDIR if any symlinks are encountered. If * * fchdir() fails, or the current directory is unreadable, we might end up * @@ -5379,9 +5394,7 @@ lchdir(char const *path, struct dirsav *d, int hard) #endif if (!d) { - ds.ino = ds.dev = 0; - ds.dirname = NULL; - ds.dirfd = -1; + init_dirsav(&ds); d = &ds; } #ifdef HAVE_LSTAT @@ -5479,6 +5492,17 @@ lchdir(char const *path, struct dirsav *d, int hard) } } if (restoredir(d)) { + int restoreerr = errno; + /* + * Failed to restore the directory. + * Just be definite, cd to root and report the result. + */ + zsfree(pwd); + pwd = ztrdup("/"); + if (chdir(pwd) < 0) + zerr("lost current directory, failed to cd to /: %e", errno); + else + zerr("lost current directory: %e: changed to /", restoreerr); if (d == &ds) zsfree(ds.dirname); #ifdef HAVE_FCHDIR diff --git a/Src/zsh.h b/Src/zsh.h index 8d2deec6c..3c1623c1f 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -382,6 +382,7 @@ typedef struct builtin *Builtin; typedef struct cmdnam *Cmdnam; typedef struct complist *Complist; typedef struct conddef *Conddef; +typedef struct dirsav *Dirsav; typedef struct features *Features; typedef struct feature_enables *Feature_enables; typedef struct funcstack *Funcstack; -- cgit 1.4.1