diff options
author | Denys Vlasenko | 2017-07-25 17:47:48 +0200 |
---|---|---|
committer | Denys Vlasenko | 2017-07-25 17:47:48 +0200 |
commit | f1a5cb0548f647e628032ea8645c0d0d2d07b02f (patch) | |
tree | 6063135a5059b3f137322726699e33e91c6ba095 | |
parent | 2990aa45d188b1d9814c89dd44658f068eb37e83 (diff) | |
download | busybox-f1a5cb0548f647e628032ea8645c0d0d2d07b02f.zip busybox-f1a5cb0548f647e628032ea8645c0d0d2d07b02f.tar.gz |
ash: [REDIR] Replace GPL noclobberopen code with the FreeBSD version
Upstream commit:
Date: Thu, 10 Mar 2011 16:52:13 +0800
[REDIR] Replace GPL noclobberopen code with the FreeBSD version
Replace noclobberopen() from bash with the FreeBSD code for noclobber
opens.
This also reduces code size by eliminating an unnecessary check.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
function old new delta
changepath 192 194 +2
localcmd 366 364 -2
expmeta 521 517 -4
redirect 1210 1135 -75
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/3 up/down: 2/-81) Total: -79 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/ash.c | 81 |
1 files changed, 17 insertions, 64 deletions
diff --git a/shell/ash.c b/shell/ash.c index c353834..b4b0d52 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5175,68 +5175,6 @@ stoppedjobs(void) #define CLOSED -3 /* marks a slot of previously-closed fd */ /* - * Open a file in noclobber mode. - * The code was copied from bash. - */ -static int -noclobberopen(const char *fname) -{ - int r, fd; - struct stat finfo, finfo2; - - /* - * If the file exists and is a regular file, return an error - * immediately. - */ - r = stat(fname, &finfo); - if (r == 0 && S_ISREG(finfo.st_mode)) { - errno = EEXIST; - return -1; - } - - /* - * If the file was not present (r != 0), make sure we open it - * exclusively so that if it is created before we open it, our open - * will fail. Make sure that we do not truncate an existing file. - * Note that we don't turn on O_EXCL unless the stat failed -- if the - * file was not a regular file, we leave O_EXCL off. - */ - if (r != 0) - return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666); - fd = open(fname, O_WRONLY|O_CREAT, 0666); - - /* If the open failed, return the file descriptor right away. */ - if (fd < 0) - return fd; - - /* - * OK, the open succeeded, but the file may have been changed from a - * non-regular file to a regular file between the stat and the open. - * We are assuming that the O_EXCL open handles the case where FILENAME - * did not exist and is symlinked to an existing file between the stat - * and open. - */ - - /* - * If we can open it and fstat the file descriptor, and neither check - * revealed that it was a regular file, and the file has not been - * replaced, return the file descriptor. - */ - if (fstat(fd, &finfo2) == 0 - && !S_ISREG(finfo2.st_mode) - && finfo.st_dev == finfo2.st_dev - && finfo.st_ino == finfo2.st_ino - ) { - return fd; - } - - /* The file has been replaced. badness. */ - close(fd); - errno = EEXIST; - return -1; -} - -/* * Handle here documents. Normally we fork off a process to write the * data to a pipe. If the document is short, we can stuff the data in * the pipe without forking. @@ -5280,6 +5218,7 @@ openhere(union node *redir) static int openredirect(union node *redir) { + struct stat sb; char *fname; int f; @@ -5319,9 +5258,23 @@ openredirect(union node *redir) #endif /* Take care of noclobber mode. */ if (Cflag) { - f = noclobberopen(fname); - if (f < 0) + if (stat(fname, &sb) < 0) { + f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666); + if (f < 0) + goto ecreate; + } else if (!S_ISREG(sb.st_mode)) { + f = open(fname, O_WRONLY, 0666); + if (f < 0) + goto ecreate; + if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) { + close(f); + errno = EEXIST; + goto ecreate; + } + } else { + errno = EEXIST; goto ecreate; + } break; } /* FALLTHROUGH */ |