forked from TrueCloudLab/restic
131 lines
2.3 KiB
Go
131 lines
2.3 KiB
Go
package dump
|
|
|
|
// Adapted from https://github.com/maxymania/go-system/blob/master/posix_acl/posix_acl.go
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
)
|
|
|
|
const (
|
|
aclUserOwner = 0x0001
|
|
aclUser = 0x0002
|
|
aclGroupOwner = 0x0004
|
|
aclGroup = 0x0008
|
|
aclMask = 0x0010
|
|
aclOthers = 0x0020
|
|
)
|
|
|
|
type aclSID uint64
|
|
|
|
type aclElem struct {
|
|
Tag uint16
|
|
Perm uint16
|
|
ID uint32
|
|
}
|
|
|
|
type acl struct {
|
|
Version uint32
|
|
List []aclElement
|
|
}
|
|
|
|
type aclElement struct {
|
|
aclSID
|
|
Perm uint16
|
|
}
|
|
|
|
func (a aclSID) getType() int {
|
|
return int(a >> 32)
|
|
}
|
|
func (a aclSID) getID() uint32 {
|
|
return uint32(a & 0xffffffff)
|
|
}
|
|
func (a aclSID) String() string {
|
|
switch a >> 32 {
|
|
case aclUserOwner:
|
|
return "user::"
|
|
case aclUser:
|
|
return fmt.Sprintf("user:%v:", a.getID())
|
|
case aclGroupOwner:
|
|
return "group::"
|
|
case aclGroup:
|
|
return fmt.Sprintf("group:%v:", a.getID())
|
|
case aclMask:
|
|
return "mask::"
|
|
case aclOthers:
|
|
return "other::"
|
|
}
|
|
return "?:"
|
|
}
|
|
|
|
func (a aclElement) String() string {
|
|
str := ""
|
|
if (a.Perm & 4) != 0 {
|
|
str += "r"
|
|
} else {
|
|
str += "-"
|
|
}
|
|
if (a.Perm & 2) != 0 {
|
|
str += "w"
|
|
} else {
|
|
str += "-"
|
|
}
|
|
if (a.Perm & 1) != 0 {
|
|
str += "x"
|
|
} else {
|
|
str += "-"
|
|
}
|
|
return fmt.Sprintf("%v%v", a.aclSID, str)
|
|
}
|
|
|
|
func (a *acl) decode(xattr []byte) {
|
|
var elem aclElement
|
|
ae := new(aclElem)
|
|
nr := bytes.NewReader(xattr)
|
|
e := binary.Read(nr, binary.LittleEndian, &a.Version)
|
|
if e != nil {
|
|
a.Version = 0
|
|
return
|
|
}
|
|
if len(a.List) > 0 {
|
|
a.List = a.List[:0]
|
|
}
|
|
for binary.Read(nr, binary.LittleEndian, ae) == nil {
|
|
elem.aclSID = (aclSID(ae.Tag) << 32) | aclSID(ae.ID)
|
|
elem.Perm = ae.Perm
|
|
a.List = append(a.List, elem)
|
|
}
|
|
}
|
|
|
|
func (a *acl) encode() []byte {
|
|
buf := new(bytes.Buffer)
|
|
ae := new(aclElem)
|
|
|
|
err := binary.Write(buf, binary.LittleEndian, &a.Version)
|
|
// write to a bytes.Buffer always returns a nil error
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
for _, elem := range a.List {
|
|
ae.Tag = uint16(elem.getType())
|
|
ae.Perm = elem.Perm
|
|
ae.ID = elem.getID()
|
|
|
|
err := binary.Write(buf, binary.LittleEndian, ae)
|
|
// write to a bytes.Buffer always returns a nil error
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
return buf.Bytes()
|
|
}
|
|
|
|
func (a *acl) String() string {
|
|
var finalacl string
|
|
for _, acl := range a.List {
|
|
finalacl += acl.String() + "\n"
|
|
}
|
|
return finalacl
|
|
}
|