• R/O
  • SSH
  • HTTPS

yash: 提交


Commit MetaInfo

修訂4217 (tree)
時間2022-11-10 23:33:49
作者magicant

Log Message

Ensure noclobber redirection terminate (#46053)

Change Summary

差異

--- yash/trunk/NEWS (revision 4216)
+++ yash/trunk/NEWS (revision 4217)
@@ -23,6 +23,8 @@
2323 = The "array" built-in is now completely ignored in the POSIXly-
2424 correct mode. The built-in, formerly a regular built-in, is now
2525 categorized as an "extension" built-in.
26+ * The ">" redirection with the noclobber option no longer hangs
27+ when the operand names a symbolic link to a non-existing file.
2628
2729 ----------------------------------------------------------------------
2830 Yash 2.53 (2022-08-23)
--- yash/trunk/redir.c (revision 4216)
+++ yash/trunk/redir.c (revision 4217)
@@ -1,6 +1,6 @@
11 /* Yash: yet another shell */
22 /* redir.c: manages file descriptors and provides functions for redirections */
3-/* (C) 2007-2020 magicant */
3+/* (C) 2007-2022 magicant */
44
55 /* This program is free software: you can redistribute it and/or modify
66 * it under the terms of the GNU General Public License as published by
@@ -484,7 +484,6 @@
484484 const mode_t mode =
485485 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
486486
487-start:;
488487 int fd = open(path, oflag, mode);
489488
490489 // Support the no-clobber mode.
@@ -492,10 +491,15 @@
492491 fd = open(path, oflag & ~(O_CREAT | O_EXCL | O_TRUNC), mode);
493492 if (fd < 0) {
494493 if (errno == ENOENT) {
495- // A file existed on the first open but not on the second.
496- // Somebody must have removed it between the two opens.
497- // Start over as we might be able to create one this time.
498- goto start;
494+ // There are two possibilities now: One is that a file existed
495+ // on the first open call and had been removed before the
496+ // second. In this case, we might be able to create another if
497+ // we start over. The other is that there is a symbolic link
498+ // pointing to nothing, in which case retrying would only lead
499+ // to the same result. Since there is no reliable way to tell
500+ // the situations apart atomically, we give up and return the
501+ // initial error.
502+ errno = EEXIST;
499503 }
500504 } else {
501505 struct stat st;
Show on old repository browser