Date: Thu, 16 Apr 2020 15:48:00 +0200 From: Joerg Sonnenberger <jo...@bec.de> Message-ID: <20200416134800.gc21...@bec.de>
| It strikes me as a lot of complexity for a limited use case. That argument (almost identically, but with more verbosity) was made back when the discussions on this were held (before my time watching what was happening there). I believe the complexity is almost 0 - the updates to the man page would probably take more lines than the code. Whether the use case is as limited as it seems was the subject of some dispute - with some believing that if available, it would be used, perhaps replacing many if not all uses of O_EXCL. I'm not advocating this one way or the other (if I were, I'd just implement it) but O_EXCL is referenced exactly 5 times in sys/kern/*.c Two of those are for semaphores and message queues, and are irrelevant. One is to stop following (if the final component) a symbolic link when O_EXCL is set (O_NOCLOBBER specifically would not do that), which is one of the problems with using O_EXCL for noclobber mode in sh - in any case, no change is needed there. The remaining two handle the cases where the path name does not, and does, exist. The does not case: if (fmode & O_EXCL) va.va_vaflags |= VA_EXCLUSIVE; error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd, &va); would I think become if (fmode & (O_EXCL|O_NOCLOBER)) va.va_vaflags |= VA_EXCLUSIVE; error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd, &va); Where more of a change is needed is in the does exist case, which is currently ... if (fmode & O_EXCL) { error = EEXIST; goto bad; } which would need a new block added something like if ((mode & O_NOCLOBBER) && vp->v_type == VREG) { error = EEXIST; goto bad; } (the two blocks could be combined with a more complex test, but I prefer to allow the compiler to make that optimisation). I believe that's almost all there is to it. Complex it isn't. Elsewhere in the kernel, there's obviously the definition of O_EXCL (and O_NOCLOBBER would need to be added) there's some device driver use of O_EXCL (DRM and maybe more) none of which is relevant to O_NOCLOBBER, as none of those is making regular files, there's some mention in procfs which might need some investigation (I wooudn't have expected to be able to create files there at all, but maybe some can be - whether files in procfs count as regular files for this purpose I'm not sure), and related references in union mounts and unionfs (where in both cases I'd expect O_EXCL and O_NOCLOBBER to be treated the same for whatever special handling they need). There's also some linux compat mode fiddling (relevant only if linux adds O_NOCLOBBER and we need to emulate it) and in coda and NFS which need looking at (the big issue is what one does when the client supports O_NOCLOBBER and the server doesn't). Finally O_EXCL is used as an arg when external attributes are created - that clearly doesn't need any mods. O_NOCLOBBER is really just intended to be O_EXCL with the two minor variations - it only applies to regular files, and follows the symlink if the path named is an existing symlink. | PS: I would find something like O_NOATIME to be much more useful, when | talking about special purpose flags with non-trivial impact. I would also find that useful, even O_NOMTIME sometimes, and if someone would like to implement either of those (which would, I suspect, take some real work, unlike the above) there would certainly be no objection here. kre ps: If you looked at the POSIX bug report, you'll see there are two options - one of them will appear in the next edition. Option 2 is the one discussed here, where O_NOCLOBBER is required (which won't happen unless there is at least one implementation - perhaps more than one would be needed). The other option (Option 1) is to recommend implementing O_NOCLOBBER with a view to requiring it in the next version of the standard. That is, they would add in the future directions section: A future version of this standard may add an O_NOCLOBBER flag, specified as follows, for use by shells when the noclobber option is set (see [xref to XRAT C.2.7.2]): O_NOCLOBBER If O_CREAT and O_NOCLOBBER are set, open() shall fail if the file exists and is either a regular file or a symbolic link that resolves to [....] (the rest of it is the same text I posted last time). That is, that text is going to appear in the standard, either as a future direction for the next standard, or a requirement of the coming one. That one of those two options be included has already been approved.