1// Copyright 2016 the Go-FUSE Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package test
6
7import (
8	"fmt"
9	"os"
10	"os/exec"
11	"testing"
12
13	"github.com/hanwen/go-fuse/v2/fuse"
14	"github.com/hanwen/go-fuse/v2/fuse/nodefs"
15	"github.com/hanwen/go-fuse/v2/fuse/pathfs"
16	"github.com/hanwen/go-fuse/v2/internal/testutil"
17)
18
19type umaskFS struct {
20	pathfs.FileSystem
21
22	mkdirMode  uint32
23	createMode uint32
24}
25
26func (fs *umaskFS) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
27	fs.createMode = mode
28	return fs.FileSystem.Create(name, flags, mode, context)
29}
30
31func (fs *umaskFS) Mkdir(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
32	fs.mkdirMode = mode
33	return fs.FileSystem.Mkdir(name, mode, context)
34}
35
36func TestUmask(t *testing.T) {
37	tmpDir := testutil.TempDir()
38	orig := tmpDir + "/orig"
39	mnt := tmpDir + "/mnt"
40
41	os.Mkdir(orig, 0700)
42	os.Mkdir(mnt, 0700)
43
44	var pfs pathfs.FileSystem
45	pfs = pathfs.NewLoopbackFileSystem(orig)
46	pfs = pathfs.NewLockingFileSystem(pfs)
47	ufs := &umaskFS{FileSystem: pfs}
48
49	pathFs := pathfs.NewPathNodeFs(ufs, &pathfs.PathNodeFsOptions{
50		ClientInodes: true})
51	connector := nodefs.NewFileSystemConnector(pathFs.Root(),
52		&nodefs.Options{
53			EntryTimeout:        testTTL,
54			AttrTimeout:         testTTL,
55			NegativeTimeout:     0.0,
56			Debug:               testutil.VerboseTest(),
57			LookupKnownChildren: true,
58		})
59	server, err := fuse.NewServer(
60		connector.RawFS(), mnt, &fuse.MountOptions{
61			SingleThreaded: true,
62			Debug:          testutil.VerboseTest(),
63		})
64	if err != nil {
65		t.Fatal("NewServer:", err)
66	}
67
68	go server.Serve()
69	if err := server.WaitMount(); err != nil {
70		t.Fatal("WaitMount", err)
71	}
72
73	// Make sure system setting does not affect test.
74	mask := 020
75	cmd := exec.Command("/bin/sh", "-c",
76		fmt.Sprintf("umask %o && cd %s && mkdir x && touch y", mask, mnt))
77	if err := cmd.Run(); err != nil {
78		t.Fatalf("cmd.Run: %v", err)
79	}
80
81	if err := server.Unmount(); err != nil {
82		t.Fatalf("Unmount %v", err)
83	}
84
85	if got, want := ufs.mkdirMode&0777, uint32(0757); got != want {
86		t.Errorf("got dirMode %o want %o", got, want)
87	}
88	if got, want := ufs.createMode&0666, uint32(0646); got != want {
89		t.Errorf("got createMode %o want %o", got, want)
90	}
91}
92