mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-23 04:51:12 +02:00
46026: Add CLOBBER_EMPTY option.
This commit is contained in:
parent
172b646a6b
commit
3df604a4be
6 changed files with 59 additions and 5 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
2020-06-09 Peter Stephenson <p.stephenson@samsung.com>
|
||||||
|
|
||||||
|
* 46026: Doc/Zsh/options.yo, Src/exec.c, Src/options.c,
|
||||||
|
Src/zsh.h, Test/A04redirect.ztst: Add CLOBBER_EMPTY option.
|
||||||
|
|
||||||
2020-06-08 Peter Stephenson <p.w.stephenson@ntlworld.com>
|
2020-06-08 Peter Stephenson <p.w.stephenson@ntlworld.com>
|
||||||
|
|
||||||
* uwers/24909: Src/exec.c: Don't clean up files used for
|
* uwers/24909: Src/exec.c: Don't clean up files used for
|
||||||
|
|
|
@ -1168,6 +1168,22 @@ If the option is not set, and the option tt(APPEND_CREATE) is also
|
||||||
not set, `tt(>>!)' or `tt(>>|)' must be used to create a file.
|
not set, `tt(>>!)' or `tt(>>|)' must be used to create a file.
|
||||||
If either option is set, `tt(>>)' may be used.
|
If either option is set, `tt(>>)' may be used.
|
||||||
)
|
)
|
||||||
|
pindex(CLOBBER_EMPTY)
|
||||||
|
pindex(NO_CLOBBER_EMPTY)
|
||||||
|
pindex(CLOBBEREMPTY)
|
||||||
|
pindex(NOCLOBBEREMPTY)
|
||||||
|
cindex(clobbering, of empty files)
|
||||||
|
cindex(file clobbering, of empty files)
|
||||||
|
item(tt(CLOBBER_EMPTY))(
|
||||||
|
This option is only used if the option tt(CLOBBER) is not set: note that
|
||||||
|
it is set by default.
|
||||||
|
|
||||||
|
If this option is set, then regular files of zero length may be
|
||||||
|
ovewritten (`clobbered'). Note that it is possible another process
|
||||||
|
has written to the file between this test and use of the file by
|
||||||
|
the current process. This option should therefore not be used in
|
||||||
|
cases where files to be clobbered may be written to asynchronously.
|
||||||
|
)
|
||||||
pindex(CORRECT)
|
pindex(CORRECT)
|
||||||
pindex(NO_CORRECT)
|
pindex(NO_CORRECT)
|
||||||
pindex(NOCORRECT)
|
pindex(NOCORRECT)
|
||||||
|
|
27
Src/exec.c
27
Src/exec.c
|
@ -2143,14 +2143,15 @@ clobber_open(struct redir *f)
|
||||||
{
|
{
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
int fd, oerrno;
|
int fd, oerrno;
|
||||||
|
char *ufname = unmeta(f->name);
|
||||||
|
|
||||||
/* If clobbering, just open. */
|
/* If clobbering, just open. */
|
||||||
if (isset(CLOBBER) || IS_CLOBBER_REDIR(f->type))
|
if (isset(CLOBBER) || IS_CLOBBER_REDIR(f->type))
|
||||||
return open(unmeta(f->name),
|
return open(ufname,
|
||||||
O_WRONLY | O_CREAT | O_TRUNC | O_NOCTTY, 0666);
|
O_WRONLY | O_CREAT | O_TRUNC | O_NOCTTY, 0666);
|
||||||
|
|
||||||
/* If not clobbering, attempt to create file exclusively. */
|
/* If not clobbering, attempt to create file exclusively. */
|
||||||
if ((fd = open(unmeta(f->name),
|
if ((fd = open(ufname,
|
||||||
O_WRONLY | O_CREAT | O_EXCL | O_NOCTTY, 0666)) >= 0)
|
O_WRONLY | O_CREAT | O_EXCL | O_NOCTTY, 0666)) >= 0)
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
|
@ -2158,11 +2159,27 @@ clobber_open(struct redir *f)
|
||||||
* Try opening, and if it's a regular file then close it again *
|
* Try opening, and if it's a regular file then close it again *
|
||||||
* because we weren't supposed to open it. */
|
* because we weren't supposed to open it. */
|
||||||
oerrno = errno;
|
oerrno = errno;
|
||||||
if ((fd = open(unmeta(f->name), O_WRONLY | O_NOCTTY)) != -1) {
|
if ((fd = open(ufname, O_WRONLY | O_NOCTTY)) != -1) {
|
||||||
if(!fstat(fd, &buf) && !S_ISREG(buf.st_mode))
|
if(!fstat(fd, &buf)) {
|
||||||
return fd;
|
if (!S_ISREG(buf.st_mode))
|
||||||
|
return fd;
|
||||||
|
/*
|
||||||
|
* If CLOBBER_EMPTY is in effect and the file is empty,
|
||||||
|
* we are allowed to re-use it.
|
||||||
|
*
|
||||||
|
* Note: there is an intrinsic race here because another
|
||||||
|
* process can write to this file at any time. The only fix
|
||||||
|
* would be file locking, which we wish to avoid in basic
|
||||||
|
* file operations at this level. This would not be
|
||||||
|
* fixed. just additionally complicated, by re-opening the
|
||||||
|
* file and truncating.
|
||||||
|
*/
|
||||||
|
if (isset(CLOBBEREMPTY) && buf.st_size == 0)
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = oerrno;
|
errno = oerrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,6 +114,7 @@ static struct optname optns[] = {
|
||||||
{{NULL, "checkjobs", OPT_EMULATE|OPT_ZSH}, CHECKJOBS},
|
{{NULL, "checkjobs", OPT_EMULATE|OPT_ZSH}, CHECKJOBS},
|
||||||
{{NULL, "checkrunningjobs", OPT_EMULATE|OPT_ZSH}, CHECKRUNNINGJOBS},
|
{{NULL, "checkrunningjobs", OPT_EMULATE|OPT_ZSH}, CHECKRUNNINGJOBS},
|
||||||
{{NULL, "clobber", OPT_EMULATE|OPT_ALL}, CLOBBER},
|
{{NULL, "clobber", OPT_EMULATE|OPT_ALL}, CLOBBER},
|
||||||
|
{{NULL, "clobberempty", 0}, CLOBBEREMPTY},
|
||||||
{{NULL, "combiningchars", 0}, COMBININGCHARS},
|
{{NULL, "combiningchars", 0}, COMBININGCHARS},
|
||||||
{{NULL, "completealiases", 0}, COMPLETEALIASES},
|
{{NULL, "completealiases", 0}, COMPLETEALIASES},
|
||||||
{{NULL, "completeinword", 0}, COMPLETEINWORD},
|
{{NULL, "completeinword", 0}, COMPLETEINWORD},
|
||||||
|
|
|
@ -2378,6 +2378,7 @@ enum {
|
||||||
CHECKJOBS,
|
CHECKJOBS,
|
||||||
CHECKRUNNINGJOBS,
|
CHECKRUNNINGJOBS,
|
||||||
CLOBBER,
|
CLOBBER,
|
||||||
|
CLOBBEREMPTY,
|
||||||
APPENDCREATE,
|
APPENDCREATE,
|
||||||
COMBININGCHARS,
|
COMBININGCHARS,
|
||||||
COMPLETEALIASES,
|
COMPLETEALIASES,
|
||||||
|
|
|
@ -708,3 +708,17 @@
|
||||||
cat <&$testfd
|
cat <&$testfd
|
||||||
0:Regression test for here document with fd declarator
|
0:Regression test for here document with fd declarator
|
||||||
> This is, in some sense, a here document.
|
> This is, in some sense, a here document.
|
||||||
|
|
||||||
|
(setopt noclobber clobberempty
|
||||||
|
rm -f foo
|
||||||
|
touch foo
|
||||||
|
print Works >foo
|
||||||
|
cat foo
|
||||||
|
print Works not >foo
|
||||||
|
# Make sure the file was not harmed
|
||||||
|
cat foo
|
||||||
|
)
|
||||||
|
0:CLOBBER_EMPTY
|
||||||
|
>Works
|
||||||
|
>Works
|
||||||
|
?(eval):6: file exists: foo
|
||||||
|
|
Loading…
Reference in a new issue