/
playground.go
140 lines (128 loc) · 3.51 KB
/
playground.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright 2020 Alexey Krivonogov. All rights reserved.
// Use of this source code is governed by a MIT license
// that can be found in the LICENSE file.
package vm
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/gentee/gentee/core"
)
const (
NoLimit = -1
ClearSize = -2
DeleteSize = -3
DeleteAllSize = -4
)
type Playground struct {
Path string // path to the temporary folder if it's empty then TempDir is used.
AllSizeLimit int64 // all files size limit. By default, 10MB
FilesLimit int // count of files limit. By default, 100
SizeLimit int64 // file size limit. By default, 5MB
}
/*type FSFile struct {
IsDir bool
Size int
}*/
type PlaygroundFS struct {
Size int64 // summary of files size
Files map[string]int64
}
// InitPlayground inits playground settings
func InitPlayground(settings *Settings) (err error) {
if len(settings.Playground.Path) == 0 {
settings.Playground.Path = TempDir()
}
if settings.Playground.Path, err = filepath.Abs(settings.Playground.Path); err != nil {
return
}
settings.Playground.Path = filepath.Join(settings.Playground.Path, strings.ToLower(core.RandName()))
if err = os.MkdirAll(settings.Playground.Path, os.ModePerm); err != nil {
return
}
if settings.Playground.AllSizeLimit == 0 {
settings.Playground.AllSizeLimit = 10 << 20 // 10MB
}
if settings.Playground.FilesLimit == 0 {
settings.Playground.FilesLimit = 100
}
if settings.Playground.SizeLimit == 0 {
settings.Playground.SizeLimit = 5 << 20 // 5MB
}
return os.Chdir(settings.Playground.Path)
}
// DeinitPlayground removes playground files
func DeinitPlayground(vm *VM) {
os.RemoveAll(vm.Settings.Playground.Path)
}
func PlaygroundAbsPath(vm *VM, fname string) (ret string, err error) {
ret, err = filepath.Abs(fname)
if err == nil {
if !strings.HasPrefix(strings.ToLower(ret), strings.ToLower(vm.Settings.Playground.Path)) {
return ``, fmt.Errorf(`%s [%s]`, ErrorText(ErrPlayAccess), fname)
}
}
return
}
func PlaygroundSize(vm *VM, fname string) (int64, error) {
ret, err := PlaygroundAbsPath(vm, fname)
if err != nil {
return 0, err
}
return vm.Playground.Files[ret[len(vm.Settings.Playground.Path):]], nil
}
func CheckPlaygroundLimits(vm *VM, fname string, size int64) error {
var (
curSize int64
ok bool
)
ret, err := PlaygroundAbsPath(vm, fname)
if err != nil {
return err
}
if size == NoLimit {
return nil
}
name := ret[len(vm.Settings.Playground.Path):]
curSize, ok = vm.Playground.Files[name]
if size == DeleteSize {
if ok {
vm.Playground.Size -= curSize
delete(vm.Playground.Files, name)
}
return nil
}
if size == DeleteAllSize {
for key, val := range vm.Playground.Files {
if strings.HasPrefix(key, name) {
vm.Playground.Size -= val
delete(vm.Playground.Files, key)
}
}
return nil
}
if size == ClearSize {
if ok {
vm.Playground.Size -= curSize
vm.Playground.Files[name] = 0
}
size = 0
}
if !ok {
vm.Playground.Files[name] = size
} else {
vm.Playground.Files[name] += size
}
if len(vm.Playground.Files) > vm.Settings.Playground.FilesLimit {
return fmt.Errorf(`%s [%d]`, ErrorText(ErrPlayCount), vm.Settings.Playground.FilesLimit)
}
vm.Playground.Size += size
if curSize+size > vm.Settings.Playground.SizeLimit {
return fmt.Errorf(`%s [%d MB]`, ErrorText(ErrPlaySize), vm.Settings.Playground.SizeLimit>>20)
}
if vm.Playground.Size > vm.Settings.Playground.AllSizeLimit {
return fmt.Errorf(`%s [%d MB]`, ErrorText(ErrPlayAllSize), vm.Settings.Playground.AllSizeLimit>>20)
}
return nil
}