Skip to content

Commit e9c53c6

Browse files
Added local transaction execution for BeeGFS like systems
1 parent f23a4fb commit e9c53c6

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package transprocessor
2+
3+
import (
4+
"fmt"
5+
"os/exec"
6+
"strings"
7+
"sync"
8+
"time"
9+
10+
"github.com/PythonHacker24/linux-acl-management-backend/internal/types"
11+
"go.uber.org/zap"
12+
)
13+
14+
/* maintains locks on file which are actively under ACL modifications */
15+
var pathLocks sync.Map
16+
17+
/* locks a given file path */
18+
func getPathLock(path string) *sync.Mutex {
19+
mtx, _ := pathLocks.LoadOrStore(path, &sync.Mutex{})
20+
return mtx.(*sync.Mutex)
21+
}
22+
23+
/* handles local transaction execution (change permissions via mounts) */
24+
func (p *PermProcessor) HandleLocalTransaction(txn *types.Transaction, absolutePath string) error {
25+
aclEntry := BuildACLEntry(txn.Entries)
26+
27+
/* REMOVE THIS */
28+
zap.L().Info("ACL Request recieved",
29+
zap.String("Transaction ID", txn.ID.String()),
30+
zap.String("Action", txn.Entries.Action),
31+
zap.String("Entry", aclEntry),
32+
zap.String("Path", txn.TargetPath),
33+
)
34+
35+
/* lock the file path for thread safety (ensure unlock even on panic) */
36+
lock := getPathLock(txn.TargetPath)
37+
lock.Lock()
38+
defer lock.Unlock()
39+
40+
/* execute the ACL modifications with acl commands */
41+
var cmd *exec.Cmd
42+
switch txn.Entries.Action {
43+
case "add", "modify":
44+
cmd = exec.Command("setfacl", "-m", aclEntry, txn.TargetPath)
45+
case "remove":
46+
cmd = exec.Command("setfacl", "-x", aclEntry, txn.TargetPath)
47+
default:
48+
// sendResponse(conn, false, "Unsupported action: "+req.Action)
49+
txn.ErrorMsg = fmt.Sprintf("unsupported ACL action: %s", txn.Entries.Action)
50+
}
51+
52+
start := time.Now()
53+
54+
output, err := cmd.CombinedOutput()
55+
56+
duration := time.Since(start).Milliseconds()
57+
58+
txn.Output = string(output)
59+
txn.DurationMs = duration
60+
61+
if err != nil {
62+
/* status of transaction is successful but execution failed */
63+
txn.Status = types.StatusSuccess
64+
txn.ExecStatus = false
65+
txn.ErrorMsg = err.Error()
66+
67+
/* REMOVE THIS */
68+
zap.L().Error("ACL command failed",
69+
zap.String("Transaction ID", txn.ID.String()),
70+
zap.String("Output", string(output)),
71+
zap.Error(err),
72+
)
73+
74+
txn.ErrorMsg = fmt.Sprintf("setfacl failed: %w, output: %s", err, output)
75+
}
76+
77+
txn.Status = types.StatusSuccess
78+
txn.ExecStatus = true
79+
80+
/* REMOVE THIS */
81+
zap.L().Info("ACL command executed successfully",
82+
zap.String("Transaction ID", txn.ID.String()),
83+
zap.String("Output", string(output)),
84+
)
85+
86+
return nil
87+
}
88+
89+
/* builds the ACL entry string for setfacl */
90+
func BuildACLEntry(entry types.ACLEntry) string {
91+
var sb strings.Builder
92+
93+
if entry.IsDefault {
94+
sb.WriteString("default:")
95+
}
96+
97+
sb.WriteString(entry.EntityType)
98+
sb.WriteString(":")
99+
sb.WriteString(entry.Entity)
100+
sb.WriteString(":")
101+
sb.WriteString(entry.Permissions)
102+
103+
return sb.String()
104+
}

0 commit comments

Comments
 (0)