aboutsummaryrefslogtreecommitdiff
path: root/statement.go
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2023-10-20 23:14:03 +0700
committerShulhan <ms@kilabit.info>2023-10-20 23:45:00 +0700
commitcda5c7c31a84b01e2231bed579d7f4bb6212a272 (patch)
tree996ff00e15bcc7c683c223cbff020cd40d78290b /statement.go
parent6c99e66401ce06889b0d8fd46a0e073402b359f0 (diff)
downloadawwan-cda5c7c31a84b01e2231bed579d7f4bb6212a272.tar.xz
all: add parser for magic command "#get" or "#put" with owner and mode
The owner and mode is defined after the magic command with the following syntax, [ USER [ ":" GROUP ]] ["+" MODE] The USER and/or GROUP is optional, its accept the value as in "chown". The MODE also optional, its value must be an octal.
Diffstat (limited to 'statement.go')
-rw-r--r--statement.go76
1 files changed, 71 insertions, 5 deletions
diff --git a/statement.go b/statement.go
index 288399c..2bfc36c 100644
--- a/statement.go
+++ b/statement.go
@@ -7,6 +7,8 @@ import (
"bytes"
"errors"
"fmt"
+ "io/fs"
+ "strconv"
"strings"
libexec "github.com/shuLhan/share/lib/os/exec"
@@ -42,9 +44,12 @@ var magicCmdGetPut = map[int][]byte{
// Statement contains parsed raw line from the script.
type Statement struct {
+ owner string
+
cmd string
args []string
raw []byte
+ mode fs.FileMode
kind int
}
@@ -122,6 +127,21 @@ func parseStatementGetPut(kind int, raw []byte) (stmt *Statement, err error) {
args []string
)
+ if len(raw) == 0 {
+ return nil, errors.New(`missing arguments`)
+ }
+
+ stmt = &Statement{
+ kind: kind,
+ }
+
+ if raw[0] != ' ' && raw[0] != '\t' {
+ raw, err = stmt.parseOwnerMode(raw)
+ if err != nil {
+ return nil, err
+ }
+ }
+
cmd, args = libexec.ParseCommandArgs(string(raw))
if len(cmd) == 0 {
return nil, errors.New(`missing arguments`)
@@ -132,10 +152,56 @@ func parseStatementGetPut(kind int, raw []byte) (stmt *Statement, err error) {
if len(args) > 1 {
return nil, errors.New(`too many arguments`)
}
- stmt = &Statement{
- kind: kind,
- args: []string{cmd, args[0]},
- raw: raw,
- }
+
+ stmt.args = []string{cmd, args[0]}
+ stmt.raw = raw
+
return stmt, nil
}
+
+// parseOwnerMode parse the owner and optionally the file mode for
+// destination file.
+// The owner and mode has the following syntax,
+//
+// [ USER [ ":" GROUP ]][ "+" MODE ]
+//
+// The USER and/or GROUP is optional, its accept the value as in "chown".
+// The MODE also optional, its value must be an octal.
+func (stmt *Statement) parseOwnerMode(in []byte) (out []byte, err error) {
+ var (
+ sepSpace = " \t"
+ sepMode = "+"
+
+ tmp []byte
+ idx int
+ )
+
+ idx = bytes.IndexAny(in, sepSpace)
+ if idx < 0 {
+ return nil, nil
+ }
+
+ tmp = in[:idx]
+ out = in[idx+1:]
+
+ idx = bytes.IndexAny(tmp, sepMode)
+ if idx < 0 {
+ stmt.owner = string(tmp)
+ } else {
+ stmt.owner = string(tmp[:idx])
+
+ var (
+ modeString = string(tmp[idx+1:])
+ mode uint64
+ )
+
+ mode, err = strconv.ParseUint(modeString, 8, 32)
+ if err != nil {
+ return nil, err
+ }
+
+ stmt.mode = fs.FileMode(mode)
+ }
+
+ return out, nil
+}