github.com/criyle/go-sandbox@v0.10.3/runner/ptrace/filehandler/fileset.go (about) 1 package filehandler 2 3 import ( 4 "path/filepath" 5 "strings" 6 ) 7 8 // FileSet stores the file permissions in the hierarchical set 9 type FileSet struct { 10 Set map[string]bool 11 SystemRoot bool 12 } 13 14 // FilePerm stores the permission apply to the file 15 type FilePerm int 16 17 // FilePermWrite / Read / Stat are permissions 18 const ( 19 FilePermWrite = iota + 1 20 FilePermRead 21 FilePermStat 22 ) 23 24 // NewFileSet creates the new file set 25 func NewFileSet() FileSet { 26 return FileSet{make(map[string]bool), false} 27 } 28 29 // IsInSetSmart same from uoj-judger 30 func (s *FileSet) IsInSetSmart(name string) bool { 31 if s.Set[name] { 32 return true 33 } 34 if name == "/" && s.SystemRoot { 35 return true 36 } 37 // check ... 38 level := 0 39 for level = 0; name != ""; level++ { 40 if level == 1 && s.Set[name+"/*"] { 41 return true 42 } 43 if s.Set[name+"/"] { 44 return true 45 } 46 name = dirname(name) 47 } 48 if level == 1 && s.Set["/*"] { 49 return true 50 } 51 if s.Set["/"] { 52 return true 53 } 54 return false 55 } 56 57 // Add adds a single file path into the FileSet 58 func (s *FileSet) Add(name string) { 59 if name == "/" { 60 s.SystemRoot = true 61 } else { 62 s.Set[name] = true 63 } 64 } 65 66 // AddRange adds multiple files into the FileSet 67 // If path is relative path, add according to the workPath 68 func (s *FileSet) AddRange(names []string, workPath string) { 69 for _, n := range names { 70 if filepath.IsAbs(n) { 71 if n == "/" { 72 s.SystemRoot = true 73 } else { 74 s.Set[n] = true 75 } 76 } else { 77 s.Set[filepath.Join(workPath, n)+"/"] = true 78 } 79 } 80 } 81 82 // FileSets aggregates multiple permissions including write / read / stat / soft ban 83 type FileSets struct { 84 Writable, Readable, Statable, SoftBan FileSet 85 } 86 87 // NewFileSets creates new FileSets struct 88 func NewFileSets() *FileSets { 89 return &FileSets{NewFileSet(), NewFileSet(), NewFileSet(), NewFileSet()} 90 } 91 92 // IsWritableFile determines whether the file path inside the write set 93 func (s *FileSets) IsWritableFile(name string) bool { 94 return s.Writable.IsInSetSmart(name) || s.Writable.IsInSetSmart(realPath(name)) 95 } 96 97 // IsReadableFile determines whether the file path inside the read / write set 98 func (s *FileSets) IsReadableFile(name string) bool { 99 return s.IsWritableFile(name) || s.Readable.IsInSetSmart(name) || s.Readable.IsInSetSmart(realPath(name)) 100 } 101 102 // IsStatableFile determines whether the file path inside the stat / read / write set 103 func (s *FileSets) IsStatableFile(name string) bool { 104 return s.IsReadableFile(name) || s.Statable.IsInSetSmart(name) || s.Statable.IsInSetSmart(realPath(name)) 105 } 106 107 // IsSoftBanFile determines whether the file path inside the softban set 108 func (s *FileSets) IsSoftBanFile(name string) bool { 109 return s.SoftBan.IsInSetSmart(name) || s.SoftBan.IsInSetSmart(realPath(name)) 110 } 111 112 // AddFilePermission adds the file into fileSets according to the given permission 113 func (s *FileSets) AddFilePermission(name string, mode FilePerm) { 114 if mode == FilePermWrite { 115 s.Writable.Add(name) 116 } else if mode == FilePermRead { 117 s.Readable.Add(name) 118 } else if mode == FilePermStat { 119 s.Statable.Add(name) 120 } 121 for name = dirname(name); name != ""; name = dirname(name) { 122 s.Statable.Add(name) 123 } 124 } 125 126 // GetExtraSet evaluates the concatenated file set according to real path or raw path 127 func GetExtraSet(extra, raw []string) []string { 128 rt := make([]string, 0, len(extra)+len(raw)) 129 rt = append(rt, raw...) 130 for _, v := range extra { 131 rt = append(rt, realPath(v)) 132 } 133 return rt 134 } 135 136 // dirname return path without last "/" 137 func dirname(path string) string { 138 if p := strings.LastIndex(path, "/"); p >= 0 { 139 return path[:p] 140 } 141 return "" 142 } 143 144 func realPath(p string) string { 145 f, err := filepath.EvalSymlinks(p) 146 if err != nil { 147 return "" 148 } 149 return f 150 }