diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba077a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +bin diff --git a/Makefile b/Makefile index a1d92b3..9eda553 100644 --- a/Makefile +++ b/Makefile @@ -1,21 +1,63 @@ # Go parameters GOCMD=go +GOMOD=$(GOCMD) mod GOBUILD=$(GOCMD) build +GOINSTALL=$(GOCMD) install GOCLEAN=$(GOCMD) clean GOTEST=$(GOCMD) test -GOGET=$(GOCMD) get -STATIC_FLAGS=-a -ldflags '-s -w -extldflags "-static"' +GOVET=$(GOCMD) vet -all: build-all-static +current_dir := $(dir $(abspath $(firstword $(MAKEFILE_LIST)))) +GOBIN ?= $(current_dir)/bin + +prefix = /usr +exec_prefix = $(prefix) +bindir = $(exec_prefix)/bin + +PKGBASE := github.com/openxt/openxt-go +PKGS := argo db ioctl +CMDS := argo-nc dbdcmd dbus-send +VERSION := 0.1.0 + +# FIPS is not available until Go 1.24 +#FIPS = GOFIPS140=v1.0.0 + +ifeq (1,${STATIC}) +ENV = CGO_ENABLED=0 GOOS=linux ${FIPS} +FLAGS = -a -ldflags '-s -w -extldflags "-static"' +else +ENV = ${FIPS} +FLAGS = -ldflags="-s -w" +endif + +all: ${CMDS} clean: - $(GOCLEAN) - rm -f argo-nc + @$(GOCLEAN) + rm -rf $(GOBIN) + +install: all + @- $(foreach CMD, $(CMDS), \ + install -Dpm 0755 $(GOBIN)/$(CMD) $(DESTDIR)$(bindir)/$(CMD); \ + ) + +dep: + $(GOMOD) download + +vet: + @- $(foreach PKG, $(PKGS), \ + $(GOVET) $(PKGBASE)/$(PKG); \ + ) + @- $(foreach CMD, $(CMDS), \ + $(GOVET) $(PKGBASE)/cmd/$(CMD); \ + ) + +gobin: + [ -e "$(GOBIN)" ] || mkdir $(GOBIN) -build-all-static: build-argo-nc-static +pkgsite: gobin + GOBIN=$(GOBIN) $(GOINSTALL) golang.org/x/pkgsite/cmd/pkgsite@latest -build-argo-nc-static: - CGO_ENABLED=0 GOOS=linux $(GOBUILD) $(STATIC_FLAGS) github.com/openxt/openxt-go/cmd/argo-nc -build-dbus-send-static: - CGO_ENABLED=0 GOOS=linux $(GOBUILD) $(STATIC_FLAGS) github.com/openxt/openxt-go/cmd/dbus-send +${CMDS}: gobin dep + $(ENV) $(GOBUILD) -o $(GOBIN)/$@ $(FLAGS) $(PKGBASE)/cmd/$@ diff --git a/pkg/argo/argo-libargo.go b/argo/argo-libargo.go similarity index 94% rename from pkg/argo/argo-libargo.go rename to argo/argo-libargo.go index 8c16509..2332239 100644 --- a/pkg/argo/argo-libargo.go +++ b/argo/argo-libargo.go @@ -1,10 +1,8 @@ // +build libargo +// SPDX-License-Identifier: BSD-3-Clause // -// Copyright 2020 Apertus Soutions, LLC -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file +// Copyright 2026 Apertus Soutions, LLC // package argo diff --git a/pkg/argo/argo-native.go b/argo/argo-native.go similarity index 84% rename from pkg/argo/argo-native.go rename to argo/argo-native.go index 60af18b..6829d94 100644 --- a/pkg/argo/argo-native.go +++ b/argo/argo-native.go @@ -1,10 +1,8 @@ // +build !libargo +// SPDX-License-Identifier: BSD-3-Clause // -// Copyright 2020 Apertus Soutions, LLC -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file +// Copyright 2026 Apertus Soutions, LLC // package argo @@ -17,6 +15,8 @@ import ( "os" "syscall" "unsafe" + + "github.com/openxt/openxt-go/ioctl" ) const ( @@ -33,18 +33,18 @@ const ( ) var ( - argoIocSetRingSize = iow(typArgo, 1, u32Size) - argoIocBind = iow(typArgo, 2, argoRingIdSize) - argoIocGetSockName = iow(typArgo, 3, argoRingIdSize) - argoIocGetPeerName = iow(typArgo, 4, xenArgoAddrSize) - argoIocConnect = iow(typArgo, 5, xenArgoAddrSize) - argoIocGetConnectErr = iow(typArgo, 6, intSize) - argoIocListen = iow(typArgo, 7, u32Size) - argoIocAccept = iow(typArgo, 8, xenArgoAddrSize) - argoIocGetSockType = iow(typArgo, 11, intSize) - argoIocViptablesAdd = iow(typArgo, 12, vIpTablesRulePos) - argoIocViptablesDel = iow(typArgo, 13, vIpTablesRulePos) - argoIocViptablesList = iow(typArgo, 14, u32Size) + argoIocSetRingSize = ioctl.Iow(typArgo, 1, u32Size) + argoIocBind = ioctl.Iow(typArgo, 2, argoRingIdSize) + argoIocGetSockName = ioctl.Iow(typArgo, 3, argoRingIdSize) + argoIocGetPeerName = ioctl.Iow(typArgo, 4, xenArgoAddrSize) + argoIocConnect = ioctl.Iow(typArgo, 5, xenArgoAddrSize) + argoIocGetConnectErr = ioctl.Iow(typArgo, 6, intSize) + argoIocListen = ioctl.Iow(typArgo, 7, u32Size) + argoIocAccept = ioctl.Iow(typArgo, 8, xenArgoAddrSize) + argoIocGetSockType = ioctl.Iow(typArgo, 11, intSize) + argoIocViptablesAdd = ioctl.Iow(typArgo, 12, vIpTablesRulePos) + argoIocViptablesDel = ioctl.Iow(typArgo, 13, vIpTablesRulePos) + argoIocViptablesList = ioctl.Iow(typArgo, 14, u32Size) ) func addrFromC(r io.Reader, a *Addr) error { diff --git a/pkg/argo/argo.go b/argo/argo.go similarity index 87% rename from pkg/argo/argo.go rename to argo/argo.go index b3cdc67..8bc34d4 100644 --- a/pkg/argo/argo.go +++ b/argo/argo.go @@ -1,8 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause // -// Copyright 2020 Apertus Soutions, LLC -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file +// Copyright 2026 Apertus Soutions, LLC // // Package argo provides a Go interface for interacting with the Argo character diff --git a/pkg/argo/dbus/argo.go b/argo/dbus/argo.go similarity index 90% rename from pkg/argo/dbus/argo.go rename to argo/dbus/argo.go index 623fd5e..3462f90 100644 --- a/pkg/argo/dbus/argo.go +++ b/argo/dbus/argo.go @@ -1,8 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause // -// Copyright 2020 Apertus Soutions, LLC -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file +// Copyright 2026 Apertus Soutions, LLC // package dbus @@ -14,7 +12,7 @@ import ( "strings" "syscall" - "github.com/openxt/openxt-go/pkg/argo" + "github.com/openxt/openxt-go/argo" godbus "github.com/godbus/dbus/v5" ) diff --git a/pkg/argo/structures.go b/argo/structures.go similarity index 84% rename from pkg/argo/structures.go rename to argo/structures.go index f89fd0e..272909d 100644 --- a/pkg/argo/structures.go +++ b/argo/structures.go @@ -1,8 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause // -// Copyright 2020 Apertus Soutions, LLC -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file +// Copyright 2026 Apertus Soutions, LLC // package argo diff --git a/cmd/argo-nc/main.go b/cmd/argo-nc/main.go index 0091521..5bef8f6 100644 --- a/cmd/argo-nc/main.go +++ b/cmd/argo-nc/main.go @@ -1,5 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause // -// Copyright 2020 Apertus Soutions, LLC +// Copyright 2026 Apertus Soutions, LLC // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file @@ -14,7 +15,7 @@ import ( "syscall" flag "github.com/spf13/pflag" - "github.com/openxt/openxt-go/pkg/argo" + "github.com/openxt/openxt-go/argo" ) var ( diff --git a/cmd/dbdcmd/main.go b/cmd/dbdcmd/main.go index 1975007..5f206e7 100644 --- a/cmd/dbdcmd/main.go +++ b/cmd/dbdcmd/main.go @@ -1,8 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause // -// Copyright 2015 Apertus Soutions, LLC -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file +// Copyright 2026 Apertus Soutions, LLC // package main @@ -11,7 +9,7 @@ import ( "fmt" "os" - "github.com/openxt/openxt-go/pkg/dbd" + "github.com/openxt/openxt-go/db" ) func die(format string, a ...interface{}) { diff --git a/cmd/dbus-send/main.go b/cmd/dbus-send/main.go index 4f23442..c262d93 100644 --- a/cmd/dbus-send/main.go +++ b/cmd/dbus-send/main.go @@ -1,8 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause // -// Copyright 2020 Apertus Soutions, LLC -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file +// Copyright 2026 Apertus Soutions, LLC // package main @@ -16,7 +14,7 @@ import ( "strings" flag "github.com/spf13/pflag" - "github.com/openxt/openxt-go/pkg/argo/dbus" + "github.com/openxt/openxt-go/argo/dbus" godbus "github.com/godbus/dbus/v5" ) diff --git a/cmd/xenstore/main.go b/cmd/xenstore/main.go deleted file mode 100644 index 94da8b6..0000000 --- a/cmd/xenstore/main.go +++ /dev/null @@ -1,135 +0,0 @@ -// -// Copyright 2015 Apertus Soutions, LLC -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file -// - -package main - -import ( - "fmt" - "os" - "strings" - - "github.com/openxt/openxt-go/pkg/xenstore" -) - -func die(format string, a ...interface{}) { - fmt.Fprintf(os.Stderr, format, a...) - fmt.Fprintln(os.Stderr) - os.Exit(1) -} - -func usage() { - die( - `Usage: xenstore [] - -Available commands are: - read [ ... ] Retrieve from store - write [ ... ] Store for in the store - rm [ ... ] Delete from store - exists [ ... ] Check if exist in the store - help Print this help`) -} - -func new_xs() xenstore.Client { - xs, err := xenstore.NewClient(0) - if err != nil { - die("xenstore.Open error: %v", err) - } - - return xs -} - -func xs_read(script_name string, args []string) { - if len(args) == 0 || args[0] == "-h" { - die("Usage: %s key [ key ... ]", script_name) - } - - xs := new_xs() - for _, key := range args[:] { - result, err := xs.Read(key) - if err != nil { - die("%s error: %v", script_name, err) - } - - fmt.Println(result) - } -} - -func xs_write(script_name string, args []string) { - if len(args) == 0 || args[0] == "-h" || len(args)%2 != 0 { - die("Usage: %s key value [ key value ... ]", script_name) - } - - xs := new_xs() - for i := 0; i < len(args); i += 2 { - key := args[i] - value := args[i+1] - - err := xs.Write(key, value) - if err != nil { - die("%s error: %v", script_name, err) - } - } -} - -func xs_rm(script_name string, args []string) { - if len(args) == 0 || args[0] == "-h" { - die("Usage: %s key [ key ... ]", script_name) - } - - xs := new_xs() - for _, key := range args[:] { - err := xs.Rm(key) - if err != nil { - die("%s error: %v", script_name, err) - } - } -} - -func xs_exists(script_name string, args []string) { - if len(args) == 0 || args[0] == "-h" { - die("Usage: %s key [ key ... ]", script_name) - } - - xs := new_xs() - for _, key := range args[:] { - _, err := xs.Read(key) - if err != nil { - die("%s error: %v", script_name, err) - } - } -} - -func main() { - var operation string - var args []string - - script_name := os.Args[0] - if strings.Contains(script_name, "-") { - operation = script_name[strings.LastIndex(script_name, "-")+1:] - args = os.Args[1:] - } else { - if len(os.Args) < 2 { - usage() - } - operation = os.Args[1] - script_name = script_name + " " + operation - args = os.Args[2:] - } - - switch operation { - case "read": - xs_read(script_name, args) - case "write": - xs_write(script_name, args) - case "rm": - xs_rm(script_name, args) - case "exists": - xs_exists(script_name, args) - default: - usage() - } -} diff --git a/pkg/dbd/dbd.go b/db/dbd.go similarity index 95% rename from pkg/dbd/dbd.go rename to db/dbd.go index 4fe1e0a..c0bdb46 100644 --- a/pkg/dbd/dbd.go +++ b/db/dbd.go @@ -1,8 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause // -// Copyright 2015 Apertus Soutions, LLC -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file +// Copyright 2026 Apertus Soutions, LLC // diff --git a/pkg/argo/ioctl.go b/ioctl/ioctl.go similarity index 50% rename from pkg/argo/ioctl.go rename to ioctl/ioctl.go index ee33414..19f7e05 100644 --- a/pkg/argo/ioctl.go +++ b/ioctl/ioctl.go @@ -1,11 +1,9 @@ +// SPDX-License-Identifier: BSD-3-Clause // -// Copyright 2020 Apertus Soutions, LLC -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file +// Copyright 2026 Apertus Soutions, LLC // -package argo +package ioctl const ( typBits = 8 @@ -28,18 +26,18 @@ const ( dirShift = sizShift + sizBits ) -func ioc(dir, t, nr, size uintptr) uintptr { +func Ioc(dir, t, nr, size uintptr) uintptr { return (dir << dirShift) | (t << typShift) | (nr << numShift) | (size << sizShift) } -func ior(t, nr, size uintptr) uintptr { - return ioc(dirRead, t, nr, size) +func Ior(t, nr, size uintptr) uintptr { + return Ioc(dirRead, t, nr, size) } -func iow(t, nr, size uintptr) uintptr { - return ioc(dirWrite, t, nr, size) +func Iow(t, nr, size uintptr) uintptr { + return Ioc(dirWrite, t, nr, size) } -func iowr(t, nr, size uintptr) uintptr { - return ioc(dirRead|dirWrite, t, nr, size) +func Iowr(t, nr, size uintptr) uintptr { + return Ioc(dirRead|dirWrite, t, nr, size) } diff --git a/pkg/xenstore/xenstore.go b/pkg/xenstore/xenstore.go deleted file mode 100644 index 035add2..0000000 --- a/pkg/xenstore/xenstore.go +++ /dev/null @@ -1,444 +0,0 @@ -// Copyright (c) 2015, Citrix Systems -// All rights reserved. -// -// Copyright 2015 Apertus Soutions, LLC -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file -// -// File originated from github.com/xenserver/xe-guest-utilities and has -// been horribly modified. - -package xenstore - -import ( - "bufio" - "bytes" - "encoding/binary" - "errors" - "fmt" - "io" - "os" - "strconv" - "strings" - "sync" - "time" -) - -type Permission int - -const ( - PERM_NONE Permission = iota - PERM_READ - PERM_WRITE - PERM_READWRITE -) - -type Operation uint32 - -const ( - XS_READ Operation = 2 - XS_GET_PERMS Operation = 3 - XS_WATCH Operation = 4 - XS_UNWATCH Operation = 5 - XS_TRANSACTION_START Operation = 6 - XS_TRANSACTION_END Operation = 7 - XS_WRITE Operation = 11 - XS_MKDIR Operation = 12 - XS_RM Operation = 13 - XS_SET_PERMS Operation = 14 - XS_WATCH_EVENT Operation = 15 - XS_ERROR Operation = 16 -) - -type Packet struct { - OpCode Operation - Req uint32 - TxID uint32 - Length uint32 - Value []byte -} - -type Event struct { - Token string - Data []byte -} - -type Client interface { - Close() error - DO(packet *Packet) (*Packet, error) - Read(path string) (string, error) - Mkdir(path string) error - Rm(path string) error - Write(path string, value string) error - GetPermission(path string) (map[int]Permission, error) - Watch(path string) (<-chan Event, error) - StopWatch() error -} - -func ReadPacket(r io.Reader) (packet *Packet, err error) { - - packet = &Packet{} - - err = binary.Read(r, binary.LittleEndian, &packet.OpCode) - if err != nil { - return nil, err - } - err = binary.Read(r, binary.LittleEndian, &packet.Req) - if err != nil { - return nil, err - } - err = binary.Read(r, binary.LittleEndian, &packet.TxID) - if err != nil { - return nil, err - } - err = binary.Read(r, binary.LittleEndian, &packet.Length) - if err != nil { - return nil, err - } - - if packet.Length > 0 { - packet.Value = make([]byte, packet.Length) - _, err = io.ReadFull(r, packet.Value) - if err != nil { - return nil, err - } - if packet.OpCode == XS_ERROR { - return nil, errors.New(strings.Split(string(packet.Value), "\x00")[0]) - } - } - - return packet, nil -} - -func (p *Packet) Write(w io.Writer) (err error) { - var bw *bufio.Writer - - if w1, ok := w.(*bufio.Writer); ok { - bw = w1 - } else { - bw = bufio.NewWriter(w) - } - defer bw.Flush() - - err = binary.Write(bw, binary.LittleEndian, p.OpCode) - if err != nil { - return err - } - err = binary.Write(bw, binary.LittleEndian, p.Req) - if err != nil { - return err - } - err = binary.Write(bw, binary.LittleEndian, p.TxID) - if err != nil { - return err - } - err = binary.Write(bw, binary.LittleEndian, p.Length) - if err != nil { - return err - } - if p.Length > 0 { - _, err = bw.Write(p.Value) - if err != nil { - return err - } - } - return nil -} - -type XenStore struct { - tx uint32 - xbFile io.ReadWriteCloser - xbFileReader *bufio.Reader - muWatch *sync.Mutex - onceWatch *sync.Once - watchQueues map[string]chan Event - watchStopChan chan struct{} - watchStoppedChan chan struct{} - nonWatchQueue chan []byte -} - -func NewClient(tx uint32) (Client, error) { - devPath, err := getDevPath() - if err != nil { - return nil, err - } - - xbFile, err := os.OpenFile(devPath, os.O_RDWR, 0666) - if err != nil { - return nil, err - } - return newXenstore(tx, xbFile) -} - -func newXenstore(tx uint32, rwc io.ReadWriteCloser) (Client, error) { - return &XenStore{ - tx: tx, - xbFile: rwc, - xbFileReader: bufio.NewReader(rwc), - watchQueues: make(map[string]chan Event, 0), - nonWatchQueue: nil, - watchStopChan: make(chan struct{}, 1), - watchStoppedChan: make(chan struct{}, 1), - onceWatch: &sync.Once{}, - muWatch: &sync.Mutex{}, - }, nil -} - -func (xs *XenStore) Close() error { - return xs.xbFile.Close() -} - -func (xs *XenStore) DO(req *Packet) (resp *Packet, err error) { - err = req.Write(xs.xbFile) - if err != nil { - return nil, err - } - - var r io.Reader - if xs.nonWatchQueue != nil { - data := <-xs.nonWatchQueue - r = bytes.NewReader(data) - } else { - r = xs.xbFileReader - } - - resp, err = ReadPacket(r) - return resp, err -} - -func (xs *XenStore) Read(path string) (string, error) { - v := []byte(path + "\x00") - req := &Packet{ - OpCode: XS_READ, - Req: 0, - TxID: xs.tx, - Length: uint32(len(v)), - Value: v, - } - resp, err := xs.DO(req) - if err != nil { - return "", err - } - return string(resp.Value), nil -} - -func (xs *XenStore) Mkdir(path string) error { - v := []byte(path + "\x00") - req := &Packet{ - OpCode: XS_WRITE, - Req: 0, - TxID: xs.tx, - Length: uint32(len(v)), - Value: v, - } - _, err := xs.DO(req) - return err -} - -func (xs *XenStore) Rm(path string) error { - v := []byte(path + "\x00") - req := &Packet{ - OpCode: XS_RM, - Req: 0, - TxID: xs.tx, - Length: uint32(len(v)), - Value: v, - } - _, err := xs.DO(req) - return err -} - -func (xs *XenStore) Write(path string, value string) error { - v := []byte(path + "\x00" + value) - req := &Packet{ - OpCode: XS_WRITE, - Req: 0, - TxID: xs.tx, - Length: uint32(len(v)), - Value: v, - } - _, err := xs.DO(req) - return err -} - -func (xs *XenStore) GetPermission(path string) (map[int]Permission, error) { - perm := make(map[int]Permission, 0) - - v := []byte(path + "\x00") - req := &Packet{ - OpCode: XS_GET_PERMS, - Req: 0, - TxID: xs.tx, - Length: uint32(len(v)), - Value: v, - } - resp, err := xs.DO(req) - if err != nil { - return nil, err - } - - for _, e := range strings.Split(string(resp.Value[:len(resp.Value)-1]), "\x00") { - k, err := strconv.Atoi(e[1:]) - if err != nil { - return nil, err - } - var p Permission - switch e[0] { - case 'n': - p = PERM_NONE - case 'r': - p = PERM_READ - case 'w': - p = PERM_WRITE - case 'b': - p = PERM_READWRITE - } - perm[k] = p - } - return perm, nil -} - -func (xs *XenStore) Watch(path string) (<-chan Event, error) { - watcher := func() { - - type XSData struct { - *Packet - Error error - } - - xsDataChan := make(chan XSData, 100) - go func(r io.Reader, out chan<- XSData) { - for { - p, err := ReadPacket(r) - out <- XSData{Packet: p, Error: err} - } - }(xs.xbFileReader, xsDataChan) - - xs.nonWatchQueue = make(chan []byte, 100) - for { - select { - case <-xs.watchStopChan: - fmt.Printf("watch receive stop signal, quit.") - xs.watchStopChan <- struct{}{} - return - case xsdata := <-xsDataChan: - if xsdata.Error != nil { - fmt.Printf("watch receive error: %#v", xsdata.Error) - return - } - switch xsdata.Packet.OpCode { - case XS_WATCH_EVENT: - parts := strings.SplitN(string(xsdata.Value), "\x00", 2) - path := parts[0] - token := parts[1] - data := []byte(parts[2]) - if c, ok := xs.watchQueues[path]; ok { - c <- Event{token, data} - } - default: - var b bytes.Buffer - xsdata.Packet.Write(&b) - xs.nonWatchQueue <- b.Bytes() - } - } - } - } - xs.onceWatch.Do(watcher) - xs.muWatch.Lock() - defer xs.muWatch.Unlock() - if _, ok := xs.watchQueues[path]; !ok { - xs.watchQueues[path] = make(chan Event, 100) - } - return xs.watchQueues[path], nil -} - -func (xs *XenStore) StopWatch() error { - xs.watchStopChan <- struct{}{} - <-xs.watchStoppedChan - xs.nonWatchQueue = nil - return nil -} - -type CachedXenStore struct { - xs Client - writeCache map[string]string - lastCommit map[string]time.Time -} - -func NewCachedClient(tx uint32) (Client, error) { - xs, err := NewClient(tx) - if err != nil { - return nil, err - } - return &CachedXenStore{ - xs: xs, - writeCache: make(map[string]string, 0), - lastCommit: make(map[string]time.Time, 0), - }, nil -} - -func (xs *CachedXenStore) Write(path string, value string) error { - if v, ok := xs.writeCache[path]; ok && v == value { - if t, ok := xs.lastCommit[path]; ok && t.After(time.Now().Add(-2*time.Minute)) { - return nil - } - } - err := xs.xs.Write(path, value) - if err != nil { - xs.writeCache[path] = value - xs.lastCommit[path] = time.Now() - } - return err -} - -func (xs *CachedXenStore) Close() error { - return xs.xs.Close() -} - -func (xs *CachedXenStore) DO(req *Packet) (resp *Packet, err error) { - return xs.xs.DO(req) -} - -func (xs *CachedXenStore) Read(path string) (string, error) { - return xs.xs.Read(path) -} - -func (xs *CachedXenStore) Mkdir(path string) error { - return xs.xs.Mkdir(path) -} - -func (xs *CachedXenStore) Rm(path string) error { - return xs.xs.Rm(path) -} - -func (xs *CachedXenStore) GetPermission(path string) (map[int]Permission, error) { - return xs.xs.GetPermission(path) -} - -func (xs *CachedXenStore) Watch(path string) (<-chan Event, error) { - return xs.xs.Watch(path) -} - -func (xs *CachedXenStore) StopWatch() error { - return xs.xs.StopWatch() -} - -func (xs *CachedXenStore) Clear() { - xs.writeCache = make(map[string]string, 0) - xs.lastCommit = make(map[string]time.Time, 0) -} - -func getDevPath() (devPath string, err error) { - devPaths := []string{ - "/proc/xen/xenbus", - "/dev/xen/xenbus", - "/kern/xen/xenbus", - } - for _, devPath = range devPaths { - if _, err = os.Stat(devPath); err == nil { - return devPath, err - } - } - return "", fmt.Errorf("Cannot locate xenbus dev path in %v", devPaths) -} diff --git a/pkg/xenstore/xenstore_test.go b/pkg/xenstore/xenstore_test.go deleted file mode 100644 index 824f1a1..0000000 --- a/pkg/xenstore/xenstore_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright 2020 Apertus Soutions, LLC -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file -// - -package xenstore - -import ( - "bytes" - "testing" -) - -type mockFile struct { - t *testing.T -} - -func (f *mockFile) Read(b []byte) (n int, err error) { - value := "i am value" - p := &Packet{ - OpCode: XS_READ, - Req: 0, - TxID: 0, - Length: uint32(len(value)), - Value: []byte(value), - } - var buf bytes.Buffer - if err = p.Write(&buf); err != nil { - return 0, err - } - copy(b, buf.Bytes()) - n = buf.Len() - f.t.Logf("Read %d bytes", n) - return n, nil -} - -func (f *mockFile) Write(b []byte) (n int, err error) { - buf := bytes.NewBuffer(b) - if _, err := ReadPacket(buf); err != nil { - return 0, err - } - n = len(b) - f.t.Logf("Write %d bytes", n) - return n, nil -} - -func (f *mockFile) Close() error { - f.t.Logf("Close()") - return nil -} - -func TestXenStore(t *testing.T) { - xs, err := newXenstore(0, &mockFile{t}) - if err != nil { - t.Errorf("newXenstore error: %#v\n", err) - } - defer xs.Close() - - if _, err := xs.Read("foo"); err != nil { - t.Errorf("xs.Read error: %#v\n", err) - } - - if err := xs.Write("foo", "bar"); err != nil { - t.Errorf("xs.Read error: %#v\n", err) - } -}