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>
This commit is contained in:
parent
2990aa45d1
commit
f1a5cb0548
81
shell/ash.c
81
shell/ash.c
@ -5174,68 +5174,6 @@ stoppedjobs(void)
|
|||||||
#define EMPTY -2 /* marks an unused slot in redirtab */
|
#define EMPTY -2 /* marks an unused slot in redirtab */
|
||||||
#define CLOSED -3 /* marks a slot of previously-closed fd */
|
#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
|
* 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
|
* data to a pipe. If the document is short, we can stuff the data in
|
||||||
@ -5280,6 +5218,7 @@ openhere(union node *redir)
|
|||||||
static int
|
static int
|
||||||
openredirect(union node *redir)
|
openredirect(union node *redir)
|
||||||
{
|
{
|
||||||
|
struct stat sb;
|
||||||
char *fname;
|
char *fname;
|
||||||
int f;
|
int f;
|
||||||
|
|
||||||
@ -5319,9 +5258,23 @@ openredirect(union node *redir)
|
|||||||
#endif
|
#endif
|
||||||
/* Take care of noclobber mode. */
|
/* Take care of noclobber mode. */
|
||||||
if (Cflag) {
|
if (Cflag) {
|
||||||
f = noclobberopen(fname);
|
if (stat(fname, &sb) < 0) {
|
||||||
if (f < 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;
|
goto ecreate;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user