summaryrefslogtreecommitdiff
path: root/user
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2020-07-16 11:38:08 -0400
committerFrans Kaashoek <[email protected]>2020-08-10 11:19:10 -0400
commitaf9eb9114c2f8700d4315eaa1e2d637c2aaaf210 (patch)
tree9e2e5cc663d2a3d56358121761755a4d3e878d6b /user
parent672217ae2a3d68b73b2229ab368979ef7790e28a (diff)
downloadxv6-labs-af9eb9114c2f8700d4315eaa1e2d637c2aaaf210.tar.gz
xv6-labs-af9eb9114c2f8700d4315eaa1e2d637c2aaaf210.tar.bz2
xv6-labs-af9eb9114c2f8700d4315eaa1e2d637c2aaaf210.zip
make "echo hello > x" truncate file x.
Diffstat (limited to 'user')
-rw-r--r--user/sh.c2
-rw-r--r--user/usertests.c138
2 files changed, 139 insertions, 1 deletions
diff --git a/user/sh.c b/user/sh.c
index a593bc0..83dd513 100644
--- a/user/sh.c
+++ b/user/sh.c
@@ -386,7 +386,7 @@ parseredirs(struct cmd *cmd, char **ps, char *es)
cmd = redircmd(cmd, q, eq, O_RDONLY, 0);
break;
case '>':
- cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1);
+ cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE|O_TRUNC, 1);
break;
case '+': // >>
cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1);
diff --git a/user/usertests.c b/user/usertests.c
index 9aa0ed4..f83a060 100644
--- a/user/usertests.c
+++ b/user/usertests.c
@@ -22,6 +22,141 @@
char buf[BUFSZ];
char name[3];
+// test O_TRUNC.
+void
+truncate1(char *s)
+{
+ char buf[32];
+
+ unlink("truncfile");
+ int fd1 = open("truncfile", O_CREATE|O_WRONLY|O_TRUNC);
+ write(fd1, "abcd", 4);
+ close(fd1);
+
+ int fd2 = open("truncfile", O_RDONLY);
+ int n = read(fd2, buf, sizeof(buf));
+ if(n != 4){
+ printf("%s: read %d bytes, wanted 4\n", s, n);
+ exit(1);
+ }
+
+ fd1 = open("truncfile", O_WRONLY|O_TRUNC);
+
+ int fd3 = open("truncfile", O_RDONLY);
+ n = read(fd3, buf, sizeof(buf));
+ if(n != 0){
+ printf("aaa fd3=%d\n", fd3);
+ printf("%s: read %d bytes, wanted 0\n", s, n);
+ exit(1);
+ }
+
+ n = read(fd2, buf, sizeof(buf));
+ if(n != 0){
+ printf("bbb fd2=%d\n", fd2);
+ printf("%s: read %d bytes, wanted 0\n", s, n);
+ exit(1);
+ }
+
+ write(fd1, "abcdef", 6);
+
+ n = read(fd3, buf, sizeof(buf));
+ if(n != 6){
+ printf("%s: read %d bytes, wanted 6\n", s, n);
+ exit(1);
+ }
+
+ n = read(fd2, buf, sizeof(buf));
+ if(n != 2){
+ printf("%s: read %d bytes, wanted 2\n", s, n);
+ exit(1);
+ }
+
+ unlink("truncfile");
+
+ close(fd1);
+ close(fd2);
+ close(fd3);
+}
+
+// write to an open FD whose file has just been truncated.
+// this causes a write at an offset beyond the end of the file.
+// such writes fail on xv6 (unlike POSIX) but at least
+// they don't crash.
+void
+truncate2(char *s)
+{
+ unlink("truncfile");
+
+ int fd1 = open("truncfile", O_CREATE|O_TRUNC|O_WRONLY);
+ write(fd1, "abcd", 4);
+
+ int fd2 = open("truncfile", O_TRUNC|O_WRONLY);
+
+ int n = write(fd1, "x", 1);
+ if(n != -1){
+ printf("%s: write returned %d, expected -1\n", s, n);
+ exit(1);
+ }
+
+ unlink("truncfile");
+ close(fd1);
+ close(fd2);
+}
+
+void
+truncate3(char *s)
+{
+ int pid, xstatus;
+
+ close(open("truncfile", O_CREATE|O_TRUNC|O_WRONLY));
+
+ pid = fork();
+ if(pid < 0){
+ printf("%s: fork failed\n", s);
+ exit(1);
+ }
+
+ if(pid == 0){
+ for(int i = 0; i < 100; i++){
+ char buf[32];
+ int fd = open("truncfile", O_WRONLY);
+ if(fd < 0){
+ printf("%s: open failed\n", s);
+ exit(1);
+ }
+ int n = write(fd, "1234567890", 10);
+ if(n != 10){
+ printf("%s: write got %d, expected 10\n", s, n);
+ exit(1);
+ }
+ close(fd);
+ fd = open("truncfile", O_RDONLY);
+ read(fd, buf, sizeof(buf));
+ close(fd);
+ }
+ exit(0);
+ }
+
+ for(int i = 0; i < 150; i++){
+ int fd = open("truncfile", O_CREATE|O_WRONLY|O_TRUNC);
+ if(fd < 0){
+ printf("%s: open failed\n", s);
+ exit(1);
+ }
+ int n = write(fd, "xxx", 3);
+ if(n != 3){
+ printf("%s: write got %d, expected 3\n", s, n);
+ exit(1);
+ }
+ close(fd);
+ }
+
+ wait(&xstatus);
+ unlink("truncfile");
+ exit(xstatus);
+}
+
+
// does chdir() call iput(p->cwd) in a transaction?
void
iputtest(char *s)
@@ -2169,6 +2304,9 @@ main(int argc, char *argv[])
void (*f)(char *);
char *s;
} tests[] = {
+ {truncate1, "truncate1"},
+ {truncate2, "truncate2"},
+ {truncate3, "truncate3"},
{reparent2, "reparent2"},
{pgbug, "pgbug" },
{sbrkbugs, "sbrkbugs" },