zsh-workers
 help / color / mirror / code / Atom feed
From: Zoltan Hidvegi <hzoli@cs.elte.hu>
To: zefram@dcs.warwick.ac.uk (Zefram)
Cc: zsh-workers@math.gatech.edu
Subject: Re: files module improvements
Date: Thu, 2 Jan 1997 04:52:58 +0100 (MET)	[thread overview]
Message-ID: <199701020352.EAA05348@hzoli.ppp.cs.elte.hu> (raw)
In-Reply-To: <29389.199612311251@stone.dcs.warwick.ac.uk> from Zefram at "Dec 31, 96 12:51:43 pm"

Zefram wrote:
> * rm -r can run out of file descriptors in deep trees.  Fixing this would
>   require going back up the tree with chdir("..") and then checking that
>   the tree wasn't moved while we were deleting it; it makes it easier for
>   rm to fail.  I think this needs to be done, but I don't like it.

If chdir("..") succeeds it always go back where you started so it is as
safe to use as fchdir.  chdir(..) fails only if the current directory has
been unlinked or if there is a non-executable directory in the chain of
parents.  The patch below uses chdir("..") if possible.

It fixes an other more serious bug: the output of zreaddir was passed to
dorm (calling unmeta first).  But readdir (and zreaddir) uses a static
buffer which may be overwritten by subsequent calls.

And a less serious bug: rm -r non_readable_dir did not remove that
directory.

Zoltan


*** Src/utils.c	1997/01/02 01:48:28	3.1.1.9
--- Src/utils.c	1997/01/02 03:49:21
***************
*** 3306,3311 ****
--- 3306,3328 ----
      return r;
  }
  
+ /**/
+ int
+ upchdir(int n)
+ {
+     char buf[PATH_MAX];
+     char *s;
+ 
+     while (n > 0) {
+ 	for (s = buf; s < buf + PATH_MAX - 4 && n--; )
+ 	    *s++ = '.', *s++ = '.', *s++ = '/';
+ 	s[-1] = '\0';
+ 	if (chdir(buf))
+ 	    return -1;
+     }
+     return 0;
+ }
+ 
  /* 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 *
***************
*** 3320,3330 ****
  #else /* HAVE_LSTAT */
      char buf[PATH_MAX + 1], *ptr;
      char const *pptr;
!     int olddir = open(".", O_RDONLY), err;
      struct stat st1, st2;
  
!     if(*path == '/')
  	chdir("/");
      for(;;) {
  	while(*path == '/')
  	    path++;
--- 3337,3350 ----
  #else /* HAVE_LSTAT */
      char buf[PATH_MAX + 1], *ptr;
      char const *pptr;
!     int olddir = open(".", O_RDONLY), level, err;
      struct stat st1, st2;
  
!     if(*path == '/') {
  	chdir("/");
+ 	level = -1;
+     } else
+ 	level = 0;
      for(;;) {
  	while(*path == '/')
  	    path++;
***************
*** 3348,3354 ****
  	    err = ENOTDIR;
  	    break;
  	}
! 	if(chdir(buf) || lstat(".", &st2)) {
  	    err = errno;
  	    break;
  	}
--- 3368,3380 ----
  	    err = ENOTDIR;
  	    break;
  	}
! 	if(chdir(buf)) {
! 	    err = errno;
! 	    break;
! 	}
! 	if (level >= 0)
! 	    level++;
! 	if(lstat(".", &st2)) {
  	    err = errno;
  	    break;
  	}
***************
*** 3357,3364 ****
  	    break;
  	}
      }
!     fchdir(olddir);
!     close(olddir);
      errno = err;
      return -1;
  #endif /* HAVE_LSTAT */
--- 3383,3393 ----
  	    break;
  	}
      }
!     if (olddir >= 0) {
! 	fchdir(olddir);
! 	close(olddir);
!     } else
! 	upchdir(level);
      errno = err;
      return -1;
  #endif /* HAVE_LSTAT */
*** Src/Modules/files.c	1997/01/02 01:49:56	3.1.1.2
--- Src/Modules/files.c	1997/01/02 03:15:42
***************
*** 311,320 ****
  
      for(; !(err & 2) && *args; args++) {
  	rp = ztrdup(*args);
! 	len = strlen(rp + 1);
! 	unmetafy(rp, NULL);
  	err |= dorm(nam, *args, rp, ops, 1);
! 	zfree(rp, len);
      }
      return ops['f'] ? 0 : !!err;
  }
--- 311,319 ----
  
      for(; !(err & 2) && *args; args++) {
  	rp = ztrdup(*args);
! 	unmetafy(rp, &len);
  	err |= dorm(nam, *args, rp, ops, 1);
! 	zfree(rp, len + 1);
      }
      return ops['f'] ? 0 : !!err;
  }
***************
*** 365,371 ****
      char *fn;
      DIR *d;
      int err = 0;
!     int pwd = open(".", O_RDONLY);
  
      if(first ? zchdir(rp) : lchdir(rp)) {
  	if(!ops['f'])
--- 364,370 ----
      char *fn;
      DIR *d;
      int err = 0;
!     int pwd = *rp == '/' ? open(".", O_RDONLY) : -1;
  
      if(first ? zchdir(rp) : lchdir(rp)) {
  	if(!ops['f'])
***************
*** 377,404 ****
      if(!d) {
  	if(!ops['f'])
  	    zwarnnam(nam, "%s: %e", arg, errno);
! 	return 1 - fchdir(pwd);
      }
!     while((fn = zreaddir(d, 1))) {
! 	char *narg = tricat(arg, "/", fn);
  
! 	err |= dorm(nam, narg, unmeta(fn), ops, 0);
! 	zsfree(narg);
! 	if(err & 2) {
! 	    closedir(d);
  	    close(pwd);
  	    return 2;
  	}
!     }
!     closedir(d);
!     if(fchdir(pwd)) {
  	close(pwd);
- 	if(!ops['f'])
- 	    zwarnnam(nam, "failed to return to previous directory: %e",
- 		NULL, errno);
- 	return 2;
-     }
-     close(pwd);
      if(!ops['f'] && ops['i']) {
  	nicezputs(nam, stderr);
  	fputs(": remove `", stderr);
--- 376,420 ----
      if(!d) {
  	if(!ops['f'])
  	    zwarnnam(nam, "%s: %e", arg, errno);
! 	err = 1;
!     } else {
! 	while((fn = zreaddir(d, 1))) {
! 	    char *narg = tricat(arg, "/", fn);
! 	    int len;
! 
! 	    fn = ztrdup(unmetafy(fn, &len));
! 	    err |= dorm(nam, narg, fn, ops, 0);
! 	    zsfree(narg);
! 	    zfree(fn, len + 1);
! 	    if(err & 2) {
! 		closedir(d);
! 		close(pwd);
! 		return 2;
! 	    }
! 	}
! 	closedir(d);
      }
!     if (pwd < 0 || fchdir(pwd)) {
! 	int level = 0;
  
! 	if (pwd >= 0)
  	    close(pwd);
+ 	if (*rp != '/') {
+ 	    for (fn = rp; *fn; level++) {
+ 		while (*fn && *fn++ != '/');
+ 		while (*fn == '/')
+ 		    fn++;
+ 	    }
+ 	    level = !upchdir(level);
+ 	}
+ 	if (!level) {
+ 	    if(!ops['f'])
+ 		zwarnnam(nam, "failed to return to previous directory: %e",
+ 			 NULL, errno);
  	    return 2;
  	}
!     } else
  	close(pwd);
      if(!ops['f'] && ops['i']) {
  	nicezputs(nam, stderr);
  	fputs(": remove `", stderr);


  reply	other threads:[~1997-01-02  4:39 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1996-12-31 12:51 Zefram
1997-01-02  3:52 ` Zoltan Hidvegi [this message]
1997-01-02 11:16   ` Zefram

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=199701020352.EAA05348@hzoli.ppp.cs.elte.hu \
    --to=hzoli@cs.elte.hu \
    --cc=zefram@dcs.warwick.ac.uk \
    --cc=zsh-workers@math.gatech.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).