diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-25 17:47:48 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-25 17:47:48 +0200 |
commit | f1a5cb0548f647e628032ea8645c0d0d2d07b02f (patch) | |
tree | 6063135a5059b3f137322726699e33e91c6ba095 | |
parent | 2990aa45d188b1d9814c89dd44658f068eb37e83 (diff) | |
download | busybox-w32-f1a5cb0548f647e628032ea8645c0d0d2d07b02f.tar.gz busybox-w32-f1a5cb0548f647e628032ea8645c0d0d2d07b02f.tar.bz2 busybox-w32-f1a5cb0548f647e628032ea8645c0d0d2d07b02f.zip |
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 c353834a4..b4b0d5253 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -5175,68 +5175,6 @@ stoppedjobs(void) | |||
5175 | #define CLOSED -3 /* marks a slot of previously-closed fd */ | 5175 | #define CLOSED -3 /* marks a slot of previously-closed fd */ |
5176 | 5176 | ||
5177 | /* | 5177 | /* |
5178 | * Open a file in noclobber mode. | ||
5179 | * The code was copied from bash. | ||
5180 | */ | ||
5181 | static int | ||
5182 | noclobberopen(const char *fname) | ||
5183 | { | ||
5184 | int r, fd; | ||
5185 | struct stat finfo, finfo2; | ||
5186 | |||
5187 | /* | ||
5188 | * If the file exists and is a regular file, return an error | ||
5189 | * immediately. | ||
5190 | */ | ||
5191 | r = stat(fname, &finfo); | ||
5192 | if (r == 0 && S_ISREG(finfo.st_mode)) { | ||
5193 | errno = EEXIST; | ||
5194 | return -1; | ||
5195 | } | ||
5196 | |||
5197 | /* | ||
5198 | * If the file was not present (r != 0), make sure we open it | ||
5199 | * exclusively so that if it is created before we open it, our open | ||
5200 | * will fail. Make sure that we do not truncate an existing file. | ||
5201 | * Note that we don't turn on O_EXCL unless the stat failed -- if the | ||
5202 | * file was not a regular file, we leave O_EXCL off. | ||
5203 | */ | ||
5204 | if (r != 0) | ||
5205 | return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666); | ||
5206 | fd = open(fname, O_WRONLY|O_CREAT, 0666); | ||
5207 | |||
5208 | /* If the open failed, return the file descriptor right away. */ | ||
5209 | if (fd < 0) | ||
5210 | return fd; | ||
5211 | |||
5212 | /* | ||
5213 | * OK, the open succeeded, but the file may have been changed from a | ||
5214 | * non-regular file to a regular file between the stat and the open. | ||
5215 | * We are assuming that the O_EXCL open handles the case where FILENAME | ||
5216 | * did not exist and is symlinked to an existing file between the stat | ||
5217 | * and open. | ||
5218 | */ | ||
5219 | |||
5220 | /* | ||
5221 | * If we can open it and fstat the file descriptor, and neither check | ||
5222 | * revealed that it was a regular file, and the file has not been | ||
5223 | * replaced, return the file descriptor. | ||
5224 | */ | ||
5225 | if (fstat(fd, &finfo2) == 0 | ||
5226 | && !S_ISREG(finfo2.st_mode) | ||
5227 | && finfo.st_dev == finfo2.st_dev | ||
5228 | && finfo.st_ino == finfo2.st_ino | ||
5229 | ) { | ||
5230 | return fd; | ||
5231 | } | ||
5232 | |||
5233 | /* The file has been replaced. badness. */ | ||
5234 | close(fd); | ||
5235 | errno = EEXIST; | ||
5236 | return -1; | ||
5237 | } | ||
5238 | |||
5239 | /* | ||
5240 | * Handle here documents. Normally we fork off a process to write the | 5178 | * Handle here documents. Normally we fork off a process to write the |
5241 | * data to a pipe. If the document is short, we can stuff the data in | 5179 | * data to a pipe. If the document is short, we can stuff the data in |
5242 | * the pipe without forking. | 5180 | * the pipe without forking. |
@@ -5280,6 +5218,7 @@ openhere(union node *redir) | |||
5280 | static int | 5218 | static int |
5281 | openredirect(union node *redir) | 5219 | openredirect(union node *redir) |
5282 | { | 5220 | { |
5221 | struct stat sb; | ||
5283 | char *fname; | 5222 | char *fname; |
5284 | int f; | 5223 | int f; |
5285 | 5224 | ||
@@ -5319,9 +5258,23 @@ openredirect(union node *redir) | |||
5319 | #endif | 5258 | #endif |
5320 | /* Take care of noclobber mode. */ | 5259 | /* Take care of noclobber mode. */ |
5321 | if (Cflag) { | 5260 | if (Cflag) { |
5322 | f = noclobberopen(fname); | 5261 | if (stat(fname, &sb) < 0) { |
5323 | if (f < 0) | 5262 | f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666); |
5263 | if (f < 0) | ||
5264 | goto ecreate; | ||
5265 | } else if (!S_ISREG(sb.st_mode)) { | ||
5266 | f = open(fname, O_WRONLY, 0666); | ||
5267 | if (f < 0) | ||
5268 | goto ecreate; | ||
5269 | if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) { | ||
5270 | close(f); | ||
5271 | errno = EEXIST; | ||
5272 | goto ecreate; | ||
5273 | } | ||
5274 | } else { | ||
5275 | errno = EEXIST; | ||
5324 | goto ecreate; | 5276 | goto ecreate; |
5277 | } | ||
5325 | break; | 5278 | break; |
5326 | } | 5279 | } |
5327 | /* FALLTHROUGH */ | 5280 | /* FALLTHROUGH */ |