Skip to content

Commit 8ab80e0

Browse files
SuperBukera3s7p
authored andcommitted
api socket.filemode
1 parent 57c9df6 commit 8ab80e0

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed

api/socket/filemode.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package socket
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
"fmt"
7+
"io/fs"
8+
"regexp"
9+
"strconv"
10+
)
11+
12+
var ErrUnsupportedBase = errors.New("unsuported base")
13+
var ErrInvalidNumber = errors.New("value doesn't correspond with base")
14+
var ErrInvalidPermissions = errors.New("invalid file permissions")
15+
16+
// Validate number corresponds with base
17+
func validateBase(s string, base uint32) error {
18+
// Only bases up to 10 are supported, this might chante in the future.
19+
if base == 0 || base > 10 {
20+
return ErrUnsupportedBase
21+
}
22+
23+
pattern := fmt.Sprintf("^[0-%v]{3}$", base-1)
24+
25+
if match, err := regexp.MatchString(pattern, s); err != nil {
26+
return err // Invalid pattern
27+
} else if !match {
28+
return ErrInvalidNumber
29+
}
30+
31+
return nil
32+
}
33+
34+
type FileMode fs.FileMode
35+
36+
// MarshalJSON implements json.Marshaler.
37+
func (fm FileMode) MarshalJSON() ([]byte, error) {
38+
39+
if fm > 511 {
40+
// Detect wrong permissions
41+
return nil, ErrInvalidPermissions
42+
}
43+
44+
value := strconv.FormatUint(uint64(fm), 8)
45+
b, err := json.Marshal(value)
46+
47+
l := len(b)
48+
if err != nil {
49+
return nil, err
50+
} else if l == 5 {
51+
// Prevent slice overflows in the following section
52+
return b, nil
53+
}
54+
55+
// Add leading zeros to the string
56+
data := []byte(`"000"`)
57+
for i, x := range b[1 : len(b)-1] {
58+
j := 6 - l + i
59+
data[j] = x
60+
}
61+
62+
return []byte(data), nil
63+
}
64+
65+
// UnmarshalJSON implements json.Unmarshaler.
66+
func (fm *FileMode) UnmarshalJSON(data []byte) (err error) {
67+
var value string
68+
var intVal uint64
69+
70+
if err = json.Unmarshal(data, &value); err != nil {
71+
// probably it's an valid json
72+
} else if err = validateBase(value, 8); err != nil {
73+
err = ErrInvalidPermissions // Validate permissions format
74+
} else if intVal, err = strconv.ParseUint(value, 8, 32); err != nil {
75+
err = ErrInvalidPermissions // This should never fail
76+
} else {
77+
*fm = FileMode(uint32(intVal))
78+
}
79+
80+
return
81+
}

api/socket/filemode_test.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package socket
2+
3+
import (
4+
"testing"
5+
)
6+
7+
/**
8+
func TestBaseConversion(t *testing.T) {
9+
result := baseConversion(10, 10, 8)
10+
if result != uint32(12) {
11+
t.Fatal("Invalid result")
12+
}
13+
14+
result = baseConversion(20, 8, 10)
15+
if result != uint32(16) {
16+
t.Fatal("Invalid result")
17+
}
18+
}
19+
20+
func TestValidateBase(t *testing.T) {
21+
err := validateBase(0, 11)
22+
if err == nil {
23+
t.Fatal("Must have failed")
24+
}
25+
26+
err = validateBase(2, 2)
27+
if err == nil {
28+
t.Fatal("Must have failed")
29+
}
30+
31+
err = validateBase(3, 4)
32+
if err != nil {
33+
t.Fatal(err)
34+
}
35+
}
36+
**/
37+
38+
func TestFileModeUnmarshal(t *testing.T) {
39+
var fm FileMode
40+
41+
err := fm.UnmarshalJSON([]byte(`"000"`))
42+
if err != nil {
43+
t.Fatal(err)
44+
} else if fm != 0 {
45+
t.Fatal("Wrong value")
46+
}
47+
48+
err = fm.UnmarshalJSON([]byte(`"0000"`))
49+
if err == nil {
50+
t.Fatal("Must have failed")
51+
}
52+
53+
err = fm.UnmarshalJSON([]byte(`"abc"`))
54+
if err == nil {
55+
t.Fatal("Must have failed")
56+
}
57+
58+
err = fm.UnmarshalJSON([]byte(`"800"`))
59+
if err == nil {
60+
t.Fatal("Must have failed")
61+
}
62+
63+
err = fm.UnmarshalJSON([]byte(`"066"`))
64+
if err != nil {
65+
t.Fatal(err)
66+
} else if fm != 54 {
67+
t.Fatal("Wrong value")
68+
}
69+
}
70+
71+
func TestFileModeMarshal(t *testing.T) {
72+
var fm FileMode
73+
74+
value, err := fm.MarshalJSON()
75+
if err != nil {
76+
t.Fatal(err)
77+
} else if string(value) != `"000"` {
78+
t.Fatal("Wrong value")
79+
}
80+
81+
fm = 0600
82+
value, err = fm.MarshalJSON()
83+
if err != nil {
84+
t.Fatal(err)
85+
} else if string(value) != `"600"` {
86+
t.Fatal("Wrong value")
87+
}
88+
89+
fm = 06000
90+
value, err = fm.MarshalJSON()
91+
if err == nil {
92+
t.Fatal("Must have failed")
93+
}
94+
}

0 commit comments

Comments
 (0)