-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
108 lines (93 loc) · 3.03 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package main
import (
"errors"
"flag"
"fmt"
"os"
"os/signal"
"syscall"
"github.com/dbaumgarten/addfs/afs"
)
var usagestring = `Usage: addfs [flags] targetdir mountpoint
Mount a directory as read+append only. Inside the mountpoint new files and folders can be created, but existing files and folders can not be deleted, unlinked, renamed, moved or overwritten.
ATTENTION: If a user has write-access to the real directory (not only the mountpoint) he can circumvent the write-protection by writing directly to the real directory rather then the mountpoint. Use correct directory-permissions to prevent this!!!
Possible flags:
`
var allowRootMutation = flag.Bool("allowRootMutation", false, "Allow the root-user to mutate files and folders")
var ignoreWarnings = flag.Bool("ignoreWarnings", false, "Ignore all errors about file-ownership. ONLY USE IF YOU KNOW WHAT YOU ARE DOING!")
var keepMounted = flag.Bool("keepMounted", false, "Do not attempt to unmount on exiting")
var mutableFiles arrayFlags
func main() {
flag.Var(&mutableFiles, "mutableFiles", "Allow mutation of files that match the given regex. Can be specified multiple times.")
flag.Usage = func() {
fmt.Println(usagestring)
flag.PrintDefaults()
}
flag.Parse()
if flag.NArg() != 2 {
flag.Usage()
os.Exit(1)
}
if !*ignoreWarnings {
if os.Getegid() != 0 {
fmt.Println("WARNING!: Not running as root. Only directories that are write-accessible for the user can be mounted. This defeats addfs' write-protection. Aborting for safety-reasons.")
os.Exit(1)
}
err := checkSourceDirectory(flag.Arg(0))
if err != nil {
fmt.Println("WARNING!: " + err.Error() + ". Aborting for safety-reasons.")
os.Exit(1)
}
}
afsOpts := afs.AddFSOpts{
AllowRootMutation: *allowRootMutation,
MutableFiles: mutableFiles,
}
afs, err := afs.NewAddFS(flag.Arg(0), afsOpts)
if err != nil {
fmt.Println("Error: ", err)
os.Exit(1)
}
if !*keepMounted {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go unmountOnInterrupt(afs, c)
}
fmt.Println("Starting FUSE-Filesystem!")
err = afs.Mount(flag.Arg(1))
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func unmountOnInterrupt(afs *afs.AddFS, c chan os.Signal) {
for _ = range c {
fmt.Println("Unmounting...")
err := afs.Unmount()
if err != nil {
fmt.Println("Error when unmounting:", err)
os.Exit(1)
}
fmt.Println("Successfully unmounted!")
}
}
func checkSourceDirectory(path string) error {
stat, err := os.Stat(path)
if err != nil {
if os.IsExist(err) {
return errors.New("the source directory does not exists")
}
return err
}
sstat, ok := stat.Sys().(*syscall.Stat_t)
if !ok {
panic("Not a syscall.Stat_t")
}
if sstat.Uid != 0 {
return errors.New("the source directory is not owned by root. A regular user could write to it directly and therefore defeat addfs' write-protection")
}
if 02&stat.Mode() != 0 {
return errors.New("the source directory is world-writeable. A regular user could write to it directly and therefore defeat addfs' write-protection")
}
return nil
}