ref: 18dbc24cdfd2f6b1105589fbf261b528e7d35035
parent: b44945b79ee0413d93bedc0dfb3f569d028bc6c2
parent: e1964307f2d3ca6cd9e31ed3299c2ab42bfb7a4e
author: Sigrid <[email protected]>
date: Fri Jun 19 12:19:42 EDT 2020
merge
--- a/kern/devfs-posix.c
+++ b/kern/devfs-posix.c
@@ -397,6 +397,13 @@
char strs[NAME_MAX*3];
Ufsinfo *uif;
+ /*
+ * wstat is supposed to be atomic.
+ * we check all the things we can before trying anything.
+ * still, if we are told to truncate a file and rename it and only
+ * one works, we're screwed. in such cases we leave things
+ * half broken and return an error. it's hardly perfect.
+ */
if(convM2D(buf, n, &d, strs) != n)
error(Ebadstat);
@@ -404,6 +411,13 @@
if(stat(uif->path, &stbuf) < 0)
error(strerror(errno));
+ /*
+ * try things in increasing order of harm to the file.
+ * mtime should come after truncate so that if you
+ * do both the mtime actually takes effect, but i'd rather
+ * leave truncate until last.
+ * (see above comment about atomicity).
+ */
if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) {
if(chmod(uif->path, d.mode&0777) < 0)
error(strerror(errno));
@@ -450,6 +464,10 @@
uif->gid = p->id;
}
*/
+
+ if((uvlong)d.length != (uvlong)~0 && truncate(uif->path, d.length) < 0)
+ error(strerror(errno));
+
return n;
}