go: portability work
Compiles and mostly works on osx and freebsd. Pull in gopsutil to fill in recon info. Change-Id: I13c77f77cf99abbc275496edb254915ad9012181
This commit is contained in:
parent
f6834ae97f
commit
7ebda1bdfb
@ -29,6 +29,11 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/disk"
|
||||
"github.com/shirou/gopsutil/load"
|
||||
"github.com/shirou/gopsutil/mem"
|
||||
"github.com/shirou/gopsutil/process"
|
||||
)
|
||||
|
||||
func DumpReconCache(reconCachePath string, source string, cacheData map[string]interface{}) error {
|
||||
@ -79,22 +84,44 @@ func DumpReconCache(reconCachePath string, source string, cacheData map[string]i
|
||||
return WriteFileAtomic(reconFile, newdata, 0600)
|
||||
}
|
||||
|
||||
// getMem dumps the contents of /proc/meminfo if it's available, otherwise it pulls what it can from gopsutil/mem
|
||||
func getMem() interface{} {
|
||||
results := make(map[string]string)
|
||||
fp, _ := os.Open("/proc/meminfo")
|
||||
defer fp.Close()
|
||||
scanner := bufio.NewScanner(fp)
|
||||
for scanner.Scan() {
|
||||
vals := strings.Split(scanner.Text(), ":")
|
||||
results[strings.TrimSpace(vals[0])] = strings.TrimSpace(vals[1])
|
||||
if fp, err := os.Open("/proc/meminfo"); err == nil {
|
||||
defer fp.Close()
|
||||
results := make(map[string]string)
|
||||
scanner := bufio.NewScanner(fp)
|
||||
for scanner.Scan() {
|
||||
vals := strings.Split(scanner.Text(), ":")
|
||||
results[strings.TrimSpace(vals[0])] = strings.TrimSpace(vals[1])
|
||||
}
|
||||
return results
|
||||
} else {
|
||||
vmem, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
swap, err := mem.SwapMemory()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return map[string]string{
|
||||
"MemTotal": strconv.FormatUint(vmem.Total, 10),
|
||||
"MemFree": strconv.FormatUint(vmem.Available, 10),
|
||||
"Buffers": strconv.FormatUint(vmem.Buffers, 10),
|
||||
"Cached": strconv.FormatUint(vmem.Cached, 10),
|
||||
"SwapTotal": strconv.FormatUint(swap.Total, 10),
|
||||
"SwapFree": strconv.FormatUint(swap.Free, 10),
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
func getSockstats() interface{} {
|
||||
results := make(map[string]int64)
|
||||
|
||||
fp, _ := os.Open("/proc/net/sockstat")
|
||||
fp, err := os.Open("/proc/net/sockstat")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer fp.Close()
|
||||
scanner := bufio.NewScanner(fp)
|
||||
for scanner.Scan() {
|
||||
@ -109,7 +136,10 @@ func getSockstats() interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
fp, _ = os.Open("/proc/net/sockstat6")
|
||||
fp, err = os.Open("/proc/net/sockstat6")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer fp.Close()
|
||||
scanner = bufio.NewScanner(fp)
|
||||
for scanner.Scan() {
|
||||
@ -125,26 +155,39 @@ func getSockstats() interface{} {
|
||||
|
||||
func getLoad() interface{} {
|
||||
results := make(map[string]interface{})
|
||||
fp, _ := os.Open("/proc/loadavg")
|
||||
defer fp.Close()
|
||||
data, _ := ioutil.ReadAll(fp)
|
||||
parts := strings.Split(strings.TrimSpace(string(data)), " ")
|
||||
results["1m"], _ = strconv.ParseFloat(parts[0], 64)
|
||||
results["5m"], _ = strconv.ParseFloat(parts[1], 64)
|
||||
results["15m"], _ = strconv.ParseFloat(parts[2], 64)
|
||||
results["tasks"] = parts[3]
|
||||
results["processes"], _ = strconv.ParseInt(parts[4], 10, 64)
|
||||
avg, err := load.Avg()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
misc, err := load.Misc()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
pids, err := process.Pids()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
results["1m"] = avg.Load1
|
||||
results["5m"] = avg.Load5
|
||||
results["15m"] = avg.Load15
|
||||
results["tasks"] = fmt.Sprintf("%d/%d", misc.ProcsRunning, len(pids))
|
||||
// swift's recon puts the pid of the last created process in this field, which seems kind of useless.
|
||||
// I'm making it the number of processes, which seems like what it was meant to be.
|
||||
results["processes"] = len(pids)
|
||||
// also adding these two fields, since they might be useful.
|
||||
results["running"] = misc.ProcsRunning
|
||||
results["blocked"] = misc.ProcsBlocked
|
||||
return results
|
||||
}
|
||||
|
||||
func getMounts() interface{} {
|
||||
results := make([]map[string]string, 0)
|
||||
fp, _ := os.Open("/proc/mounts")
|
||||
defer fp.Close()
|
||||
scanner := bufio.NewScanner(fp)
|
||||
for scanner.Scan() {
|
||||
vals := strings.Split(scanner.Text(), " ")
|
||||
results = append(results, map[string]string{"device": vals[0], "path": vals[1]})
|
||||
partitions, err := disk.Partitions(true)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, part := range partitions {
|
||||
results = append(results, map[string]string{"device": part.Device, "path": part.Mountpoint})
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ func TestGetMem(t *testing.T) {
|
||||
var v map[string]string
|
||||
err := json.Unmarshal(output, &v)
|
||||
require.Nil(t, err)
|
||||
_, ok := v["Active"]
|
||||
_, ok := v["MemTotal"]
|
||||
require.True(t, ok)
|
||||
}
|
||||
|
||||
|
@ -359,7 +359,7 @@ func StandardizeTimestamp(timestamp string) (string, error) {
|
||||
|
||||
func IsNotDir(err error) bool {
|
||||
if se, ok := err.(*os.SyscallError); ok {
|
||||
return se.Err == syscall.ENOTDIR
|
||||
return se.Err == syscall.ENOTDIR || se.Err == syscall.EINVAL
|
||||
}
|
||||
if se, ok := err.(*os.PathError); ok {
|
||||
return os.IsNotExist(se)
|
||||
|
@ -216,7 +216,7 @@ func TestUrlencode(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIsMount(t *testing.T) {
|
||||
isMount, err := IsMount("/proc")
|
||||
isMount, err := IsMount("/dev")
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, isMount)
|
||||
isMount, err = IsMount(".")
|
||||
|
@ -1,55 +0,0 @@
|
||||
// Copyright (c) 2015 Rackspace
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package hummingbird
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func FGetXattr(fd uintptr, attr string, value []byte) (int, error) {
|
||||
attrp, err := syscall.BytePtrFromString(attr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(value) == 0 {
|
||||
if r0, _, e1 := syscall.Syscall6(syscall.SYS_FGETXATTR, fd, uintptr(unsafe.Pointer(attrp)), 0, 0, 0, 0); e1 == 0 {
|
||||
return int(r0), nil
|
||||
} else {
|
||||
return 0, e1
|
||||
}
|
||||
} else {
|
||||
valuep := unsafe.Pointer(&value[0])
|
||||
if r0, _, e1 := syscall.Syscall6(syscall.SYS_FGETXATTR, fd, uintptr(unsafe.Pointer(attrp)), uintptr(valuep), uintptr(len(value)), 0, 0); e1 == 0 {
|
||||
return int(r0), nil
|
||||
} else {
|
||||
return int(r0), e1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func FSetXattr(fd uintptr, attr string, value []byte) (int, error) {
|
||||
attrp, err := syscall.BytePtrFromString(attr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
valuep := unsafe.Pointer(&value[0])
|
||||
r0, _, e1 := syscall.Syscall6(syscall.SYS_FSETXATTR, fd, uintptr(unsafe.Pointer(attrp)), uintptr(valuep), uintptr(len(value)), 0, 0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
}
|
||||
return int(r0), nil
|
||||
}
|
@ -19,7 +19,6 @@ import (
|
||||
"bufio"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@ -28,10 +27,10 @@ import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/openstack/swift/go/hummingbird"
|
||||
"github.com/openstack/swift/go/xattr"
|
||||
)
|
||||
|
||||
const METADATA_CHUNK_SIZE = 65536
|
||||
@ -50,16 +49,6 @@ type AtomicFileWriter interface {
|
||||
Preallocate(int64, int64) error
|
||||
}
|
||||
|
||||
func GetXAttr(fileNameOrFd interface{}, attr string, value []byte) (int, error) {
|
||||
switch v := fileNameOrFd.(type) {
|
||||
case string:
|
||||
return syscall.Getxattr(v, attr, value)
|
||||
case uintptr:
|
||||
return hummingbird.FGetXattr(v, attr, value)
|
||||
}
|
||||
return 0, &hummingbird.BackendError{Err: errors.New("Invalid fileNameOrFd"), Code: hummingbird.UnhandledError}
|
||||
}
|
||||
|
||||
func RawReadMetadata(fileNameOrFd interface{}) ([]byte, error) {
|
||||
var pickledMetadata []byte
|
||||
offset := 0
|
||||
@ -72,7 +61,7 @@ func RawReadMetadata(fileNameOrFd interface{}) ([]byte, error) {
|
||||
metadataName = "user.swift.metadata" + strconv.Itoa(index)
|
||||
}
|
||||
// get size of xattr
|
||||
length, err := GetXAttr(fileNameOrFd, metadataName, nil)
|
||||
length, err := xattr.Getxattr(fileNameOrFd, metadataName, nil)
|
||||
if err != nil || length <= 0 {
|
||||
break
|
||||
}
|
||||
@ -81,7 +70,7 @@ func RawReadMetadata(fileNameOrFd interface{}) ([]byte, error) {
|
||||
pickledMetadata = append(pickledMetadata, 0)
|
||||
}
|
||||
pickledMetadata = pickledMetadata[0 : offset+length]
|
||||
if _, err := GetXAttr(fileNameOrFd, metadataName, pickledMetadata[offset:]); err != nil {
|
||||
if _, err := xattr.Getxattr(fileNameOrFd, metadataName, pickledMetadata[offset:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offset += length
|
||||
@ -126,7 +115,7 @@ func RawWriteMetadata(fd uintptr, buf []byte) error {
|
||||
if len(buf) < writelen {
|
||||
writelen = len(buf)
|
||||
}
|
||||
if _, err := hummingbird.FSetXattr(fd, metadataName, buf[0:writelen]); err != nil {
|
||||
if _, err := xattr.Setxattr(fd, metadataName, buf[0:writelen]); err != nil {
|
||||
return err
|
||||
}
|
||||
buf = buf[writelen:len(buf)]
|
||||
|
@ -55,8 +55,9 @@ func (o *TempFile) Save(dst string) error {
|
||||
}
|
||||
|
||||
// Preallocate pre-allocates space for the file.
|
||||
func (o *TempFile) Preallocate(size int64, reserve int64) {
|
||||
func (o *TempFile) Preallocate(size int64, reserve int64) error {
|
||||
// TODO: this could be done for most non-linux operating systems, but it hasn't been important.
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewAtomicFileWriter returns an AtomicFileWriter, which handles atomically writing files.
|
||||
|
46
go/xattr/xattr.go
Normal file
46
go/xattr/xattr.go
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2015 Rackspace
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package xattr
|
||||
|
||||
import "errors"
|
||||
|
||||
// Setxattr sets xattrs for a file, given a file descriptor, attribute name, and value buffer.
|
||||
func Setxattr(fileNameOrFd interface{}, attr string, value []byte) (int, error) {
|
||||
switch v := fileNameOrFd.(type) {
|
||||
case string:
|
||||
return setxattr(v, attr, value)
|
||||
case uintptr:
|
||||
return fsetxattr(v, attr, value)
|
||||
case int:
|
||||
return fsetxattr(uintptr(v), attr, value)
|
||||
default:
|
||||
return 0, errors.New("Invalid fileNameOrFd")
|
||||
}
|
||||
}
|
||||
|
||||
// Getxattr gets xattrs from a file, given a filename(string) or file descriptor(uintptr), an attribute name, and value buffer to store it to.
|
||||
func Getxattr(fileNameOrFd interface{}, attr string, value []byte) (int, error) {
|
||||
switch v := fileNameOrFd.(type) {
|
||||
case string:
|
||||
return getxattr(v, attr, value)
|
||||
case uintptr:
|
||||
return fgetxattr(v, attr, value)
|
||||
case int:
|
||||
return fgetxattr(uintptr(v), attr, value)
|
||||
default:
|
||||
return 0, errors.New("Invalid fileNameOrFd")
|
||||
}
|
||||
}
|
103
go/xattr/xattr_bsd.go
Normal file
103
go/xattr/xattr_bsd.go
Normal file
@ -0,0 +1,103 @@
|
||||
// Copyright (c) 2015 Rackspace
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build freebsd openbsd netbsd dragonfly
|
||||
|
||||
package xattr
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
/*
|
||||
#include <sys/types.h>
|
||||
#include <sys/extattr.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func fsetxattr(fd uintptr, attr string, value []byte) (int, error) {
|
||||
attrp, err := syscall.BytePtrFromString(attr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
valuep := unsafe.Pointer(&value[0])
|
||||
if r0, _, e1 := syscall.Syscall6(syscall.SYS_EXTATTR_SET_FD, fd, uintptr(C.EXTATTR_NAMESPACE_USER), uintptr(unsafe.Pointer(attrp)), uintptr(valuep), uintptr(len(value)), 0); e1 == 0 {
|
||||
return int(r0), nil
|
||||
} else {
|
||||
return 0, e1
|
||||
}
|
||||
}
|
||||
|
||||
func setxattr(path string, attr string, value []byte) (int, error) {
|
||||
attrp, err := syscall.BytePtrFromString(attr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
pathp, err := syscall.BytePtrFromString(path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
valuep := unsafe.Pointer(&value[0])
|
||||
if r0, _, e1 := syscall.Syscall6(syscall.SYS_EXTATTR_SET_FILE, uintptr(unsafe.Pointer(pathp)), uintptr(C.EXTATTR_NAMESPACE_USER), uintptr(unsafe.Pointer(attrp)), uintptr(valuep), uintptr(len(value)), 0); e1 == 0 {
|
||||
return int(r0), nil
|
||||
} else {
|
||||
return 0, e1
|
||||
}
|
||||
}
|
||||
|
||||
func fgetxattr(fd uintptr, attr string, value []byte) (int, error) {
|
||||
attrp, err := syscall.BytePtrFromString(attr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var r0 uintptr
|
||||
var e1 syscall.Errno
|
||||
if value == nil {
|
||||
r0, _, e1 = syscall.Syscall6(syscall.SYS_EXTATTR_GET_FD, fd, uintptr(C.EXTATTR_NAMESPACE_USER), uintptr(unsafe.Pointer(attrp)), 0, 0, 0)
|
||||
} else {
|
||||
valuep := unsafe.Pointer(&value[0])
|
||||
r0, _, e1 = syscall.Syscall6(syscall.SYS_EXTATTR_GET_FD, fd, uintptr(C.EXTATTR_NAMESPACE_USER), uintptr(unsafe.Pointer(attrp)), uintptr(valuep), uintptr(len(value)), 0)
|
||||
}
|
||||
if e1 == 0 {
|
||||
return int(r0), nil
|
||||
} else {
|
||||
return 0, e1
|
||||
}
|
||||
}
|
||||
|
||||
func getxattr(path string, attr string, value []byte) (int, error) {
|
||||
attrp, err := syscall.BytePtrFromString(attr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
pathp, err := syscall.BytePtrFromString(path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var r0 uintptr
|
||||
var e1 syscall.Errno
|
||||
if value == nil {
|
||||
r0, _, e1 = syscall.Syscall6(syscall.SYS_EXTATTR_GET_FILE, uintptr(unsafe.Pointer(pathp)), uintptr(C.EXTATTR_NAMESPACE_USER), uintptr(unsafe.Pointer(attrp)), 0, 0, 0)
|
||||
} else {
|
||||
valuep := unsafe.Pointer(&value[0])
|
||||
r0, _, e1 = syscall.Syscall6(syscall.SYS_EXTATTR_GET_FILE, uintptr(unsafe.Pointer(pathp)), uintptr(C.EXTATTR_NAMESPACE_USER), uintptr(unsafe.Pointer(attrp)), uintptr(valuep), uintptr(len(value)), 0)
|
||||
}
|
||||
if e1 == 0 {
|
||||
return int(r0), nil
|
||||
} else {
|
||||
return 0, e1
|
||||
}
|
||||
}
|
97
go/xattr/xattr_darwinlinux.go
Normal file
97
go/xattr/xattr_darwinlinux.go
Normal file
@ -0,0 +1,97 @@
|
||||
// Copyright (c) 2015 Rackspace
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build linux darwin
|
||||
|
||||
package xattr
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func fsetxattr(fd uintptr, attr string, value []byte) (int, error) {
|
||||
attrp, err := syscall.BytePtrFromString(attr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
valuep := unsafe.Pointer(&value[0])
|
||||
if r0, _, e1 := syscall.Syscall6(syscall.SYS_FSETXATTR, fd, uintptr(unsafe.Pointer(attrp)), uintptr(valuep), uintptr(len(value)), 0, 0); e1 == 0 {
|
||||
return int(r0), nil
|
||||
} else {
|
||||
return 0, e1
|
||||
}
|
||||
}
|
||||
|
||||
func setxattr(path string, attr string, value []byte) (int, error) {
|
||||
attrp, err := syscall.BytePtrFromString(attr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
pathp, err := syscall.BytePtrFromString(path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
valuep := unsafe.Pointer(&value[0])
|
||||
if r0, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(pathp)), uintptr(unsafe.Pointer(attrp)), uintptr(valuep), uintptr(len(value)), 0, 0); e1 == 0 {
|
||||
return int(r0), nil
|
||||
} else {
|
||||
return 0, e1
|
||||
}
|
||||
}
|
||||
|
||||
func fgetxattr(fd uintptr, attr string, value []byte) (int, error) {
|
||||
attrp, err := syscall.BytePtrFromString(attr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var r0 uintptr
|
||||
var e1 syscall.Errno
|
||||
if len(value) == 0 {
|
||||
r0, _, e1 = syscall.Syscall6(syscall.SYS_FGETXATTR, fd, uintptr(unsafe.Pointer(attrp)), 0, 0, 0, 0)
|
||||
} else {
|
||||
valuep := unsafe.Pointer(&value[0])
|
||||
r0, _, e1 = syscall.Syscall6(syscall.SYS_FGETXATTR, fd, uintptr(unsafe.Pointer(attrp)), uintptr(valuep), uintptr(len(value)), 0, 0)
|
||||
}
|
||||
if e1 == 0 {
|
||||
return int(r0), nil
|
||||
} else {
|
||||
return 0, e1
|
||||
}
|
||||
}
|
||||
|
||||
func getxattr(path string, attr string, value []byte) (int, error) {
|
||||
attrp, err := syscall.BytePtrFromString(attr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
pathp, err := syscall.BytePtrFromString(path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var r0 uintptr
|
||||
var e1 syscall.Errno
|
||||
if len(value) == 0 {
|
||||
r0, _, e1 = syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(pathp)), uintptr(unsafe.Pointer(attrp)), 0, 0, 0, 0)
|
||||
} else {
|
||||
valuep := unsafe.Pointer(&value[0])
|
||||
r0, _, e1 = syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(pathp)), uintptr(unsafe.Pointer(attrp)), uintptr(valuep), uintptr(len(value)), 0, 0)
|
||||
}
|
||||
if e1 == 0 {
|
||||
return int(r0), nil
|
||||
} else {
|
||||
return 0, e1
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package hummingbird
|
||||
package xattr
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
@ -23,8 +23,22 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// func FGetXattr(fd uintptr, attr string, value []byte) (int, error)
|
||||
// func FSetXattr(fd uintptr, attr string, value []byte) (int, error)
|
||||
func TestFXattr(t *testing.T) {
|
||||
fp, err := ioutil.TempFile("", "")
|
||||
require.Nil(t, err)
|
||||
defer fp.Close()
|
||||
defer os.RemoveAll(fp.Name())
|
||||
|
||||
_, err = Setxattr(fp.Fd(), "user.swift.metadata", []byte("somevalue"))
|
||||
require.Nil(t, err)
|
||||
|
||||
count, err := Getxattr(fp.Fd(), "user.swift.metadata", nil)
|
||||
require.Nil(t, err)
|
||||
value := make([]byte, count)
|
||||
count, err = Getxattr(fp.Fd(), "user.swift.metadata", value)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, "somevalue", string(value))
|
||||
}
|
||||
|
||||
func TestXattr(t *testing.T) {
|
||||
fp, err := ioutil.TempFile("", "")
|
||||
@ -32,13 +46,13 @@ func TestXattr(t *testing.T) {
|
||||
defer fp.Close()
|
||||
defer os.RemoveAll(fp.Name())
|
||||
|
||||
_, err = FSetXattr(fp.Fd(), "user.swift.metadata", []byte("somevalue"))
|
||||
_, err = Setxattr(fp.Name(), "user.swift.metadata", []byte("somevalue"))
|
||||
require.Nil(t, err)
|
||||
|
||||
count, err := FGetXattr(fp.Fd(), "user.swift.metadata", nil)
|
||||
count, err := Getxattr(fp.Name(), "user.swift.metadata", nil)
|
||||
require.Nil(t, err)
|
||||
value := make([]byte, count)
|
||||
count, err = FGetXattr(fp.Fd(), "user.swift.metadata", value)
|
||||
count, err = Getxattr(fp.Name(), "user.swift.metadata", value)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, "somevalue", string(value))
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user