diff options
author | jilles <jilles@FreeBSD.org> | 2009-06-20 20:44:27 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2009-06-20 20:44:27 +0000 |
commit | e3cb9d1015e8283f4f9d116cf50f510741f8c0dd (patch) | |
tree | 2ece574b3d59a8e84626752587e1eb579a3c0428 /bin/sh | |
parent | 5125e5db2794d27b9f32c23a7439b1c456b334f5 (diff) | |
download | FreeBSD-src-e3cb9d1015e8283f4f9d116cf50f510741f8c0dd.zip FreeBSD-src-e3cb9d1015e8283f4f9d116cf50f510741f8c0dd.tar.gz |
Fix race condition in noclobber option.
Formerly, it was possible for the file to be created between the check if it
existed and the open; the contents would then be lost.
Because this must use O_EXCL, noclobber > will not create a file through a
symlink anymore. This agrees with behaviour of other shells.
Approved by: ed (mentor) (implicit)
Diffstat (limited to 'bin/sh')
-rw-r--r-- | bin/sh/redir.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/bin/sh/redir.c b/bin/sh/redir.c index bc18975..695e150 100644 --- a/bin/sh/redir.c +++ b/bin/sh/redir.c @@ -188,13 +188,25 @@ movefd: error("cannot create %s: %s", fname, strerror(errno)); goto movefd; case NTO: - fname = redir->nfile.expfname; - if (Cflag && stat(fname, &sb) != -1 && S_ISREG(sb.st_mode)) - error("cannot create %s: %s", fname, - strerror(EEXIST)); - if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) - error("cannot create %s: %s", fname, strerror(errno)); - goto movefd; + if (Cflag) { + fname = redir->nfile.expfname; + if (stat(fname, &sb) == -1) { + if ((f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) + error("cannot create %s: %s", fname, strerror(errno)); + } else if (!S_ISREG(sb.st_mode)) { + if ((f = open(fname, O_WRONLY, 0666)) < 0) + error("cannot create %s: %s", fname, strerror(errno)); + if (fstat(f, &sb) != -1 && S_ISREG(sb.st_mode)) { + close(f); + error("cannot create %s: %s", fname, + strerror(EEXIST)); + } + } else + error("cannot create %s: %s", fname, + strerror(EEXIST)); + goto movefd; + } + /* FALLTHROUGH */ case NCLOBBER: fname = redir->nfile.expfname; if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) |