commit 6e30de9c53aba4a0729a70ffd3268b9ab9354f4c
parent c32ff091e2e26bb67eb6d635fd567a8f9a89ef1a
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Thu, 11 Jan 2024 07:13:28 +0900
delete the file when an fid with ORCLOSE set is clunked
Diffstat:
2 files changed, 45 insertions(+), 0 deletions(-)
diff --git a/server.go b/server.go
@@ -917,6 +917,17 @@ func sClunk(ctx context.Context, c *conn, rc <-chan *request) {
 					r.err = fmt.Errorf("close: %v", err)
 					goto resp
 				}
+				if r.fid.omode&ORCLOSE != 0 {
+					rfs, ok := r.fid.fs.(RemoverFS)
+					if !ok {
+						r.err = ErrOperation
+						goto resp
+					}
+					if err := rfs.Remove(r.fid.path); err != nil {
+						r.err = err
+						goto resp
+					}
+				}
 			}
 			r.ofcall = &RClunk{}
 		resp:
diff --git a/server_test.go b/server_test.go
@@ -714,6 +714,40 @@ func TestSClunk(t *testing.T) {
 	}
 }
 
+func TestORCLOSE(t *testing.T) {
+	c, rc := setupConn(testfs)
+	tc0, tc1 := make(chan *request), make(chan *request)
+	ctx, cancel := context.WithCancel(context.Background())
+	defer cancel()
+	go sCreate(ctx, c, tc0)
+	go sClunk(ctx, c, tc1)
+	fid, err := c.fPool.add(0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	fid.path = "."
+	fid.fs = testfs
+	fid.uid = "glenda"
+	tc0 <- &request{
+		ifcall: &TCreate{Fid: 0, Name: "tmp", Perm: 0777, Mode: ORCLOSE|OREAD},
+	}
+	ofcall := (<-rc).ofcall
+	if rerr, ok := ofcall.(*RError); ok {
+		t.Fatal(rerr.Ename)
+	}
+	if _, err = testfs.walkPath("tmp"); err != nil {
+		t.Fatal(err)
+	}
+	tc1 <- &request{ifcall: &TClunk{Fid: 0}}
+	ofcall = (<-rc).ofcall
+	if rerr, ok := ofcall.(*RError); ok {
+		t.Fatal(rerr.Ename)
+	}
+	if _, err = testfs.walkPath("tmp"); err == nil {
+		t.Fatal("file not removed after closing it")
+	}
+}
+
 func TestSRemove(t *testing.T) {
 	tests := []struct {
 		fid      uint32