Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ bindir = $(exec_prefix)/bin

PKGBASE := github.com/openxt/openxt-go
PKGS := argo db ioctl
CMDS := argo-nc dbdcmd dbus-send
CMDS := argo-nc db-cmd dbus-send
VERSION := 0.1.0

# FIPS is not available until Go 1.24
Expand Down
199 changes: 199 additions & 0 deletions cmd/db-cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright 2026 Apertus Soutions, LLC
//

package main

import (
"encoding/binary"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/godbus/dbus/v5"
argoDbus "github.com/openxt/openxt-go/argo/dbus"
"github.com/openxt/openxt-go/db"
flag "github.com/spf13/pflag"
)

func die(format string, a ...interface{}) {
fmt.Fprintf(os.Stderr, format, a...)
fmt.Fprintln(os.Stderr)
os.Exit(1)
}

func usage() {
fmt.Fprintf(os.Stderr, "Usage of %s <command> [<args>]:\n", os.Args[0])
flag.PrintDefaults()
die(`
Available commands are:
cat <key> Dump raw value for <key>
exists <key> Check if <key> exist
ls <key> List tree start at <key>
nodes <key> List immediate childtren of <key>
read <key> Retrieve string value for <key>
rm <key> Delete <key>
write <key> <value> Store <value> for <key>`)
}

func list(c *db.DbClient, fullPath bool, indent int, path string) (string, error) {
path = strings.TrimRight(path, db.PathDelimiter)
result, err := c.List(path)
if err != nil {
return "", err
}

var key string
if fullPath {
key = path
} else {
key = strings.Repeat(" ", indent)
if path != "" {
key += filepath.Base(path)
}
}

if len(result) == 0 {
value, err := c.Read(path)
if err != nil {
return "", fmt.Errorf("failed reading %s: %v\n", path, err)
}
return fmt.Sprintf("%s = \"%s\"", key, value), nil
}

out := key + " ="
for _, elem := range result {
r, err := list(c, fullPath, indent+1, path+"/"+elem)
if err != nil {
return "", err
}

out += "\n" + r
}

return out, nil
}

func main() {
var conn *dbus.Conn

helpFlag := flag.BoolP("help", "h", false, "Print help")
fullPathFlag := flag.BoolP("full", "f", false, "Full path")
platBusFlag := flag.BoolP("platform", "p", false, "Connect to the platform bus")
flag.CommandLine.MarkHidden("full")
flag.Parse()

if *helpFlag {
usage()
}

if *platBusFlag {
var err error
conn, err = argoDbus.ConnectPlatformBus()
if err != nil {
die("Error connecting to platform bus: %v\n", err)
}
} else {
var err error
conn, err = dbus.SystemBus()
if err != nil {
die("Error connecting to system bus: %v\n", err)
}
}
defer conn.Close()

args := flag.Args()
if len(args) < 1 {
usage()
}

client := db.NewDbClient(conn, db.DbServiceName, "/")

operation := args[0]

args = args[1:]
arglen := len(args)

switch operation {
case "cat":
if arglen != 1 {
fmt.Fprintf(os.Stderr,
"Error: incorrect number of arguments.\n")
usage()
}
result, err := client.ReadBinary(args[1])
if err != nil {
die("DB read binary error: %v", err)
}
binary.Write(os.Stdout, binary.LittleEndian, result)

case "exists":
if arglen != 1 {
fmt.Fprintf(os.Stderr,
"Error: incorrect number of arguments.\n")
usage()
}
result, err := client.Exists(os.Args[0])
if err != nil {
die("DB exists error: %v", err)
}
fmt.Printf("%t", result)
case "ls":
path := "/"
if len(args) != 0 {
path = args[0]
}
result, err := list(client, *fullPathFlag, 0, path)
if err != nil {
die("DB list error: %v", err)
}
fmt.Printf("%s\n", result)

case "nodes":
if arglen != 1 {
fmt.Fprintf(os.Stderr,
"Error: incorrect number of arguments.\n")
usage()
}
result, err := client.List(args[0])
if err != nil {
die("DB read error: %v", err)
}
fmt.Printf("%s\n", strings.Join(result, " "))
case "read":
if arglen != 1 {
fmt.Fprintf(os.Stderr,
"Error: incorrect number of arguments.\n")
usage()
}
result, err := client.Read(args[0])
if err != nil {
die("DB read error: %v", err)
}
fmt.Printf("%s\n", result)
case "rm":
if arglen != 1 {
fmt.Fprintf(os.Stderr,
"Error: incorrect number of arguments.\n")
usage()
}
err := client.Rm(args[0])
if err != nil {
die("DB rm error: %v", err)
}
case "write":
if arglen != 2 {
fmt.Fprintf(os.Stderr,
"Error: incorrect number of arguments.\n")
usage()
}
err := client.Write(args[0], args[1])
if err != nil {
die("DB write error: %v", err)
}
default:
usage()
}
}
93 changes: 0 additions & 93 deletions cmd/dbdcmd/main.go

This file was deleted.

77 changes: 77 additions & 0 deletions db/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright 2026 Apertus Soutions, LLC
//

package db

import (
"github.com/godbus/dbus/v5"
)

const DbServiceName = "com.citrix.xenclient.db"

type DbClient struct {
dbus.BusObject
}

func NewDbClient(conn *dbus.Conn, dest, path string) *DbClient {
return &DbClient{conn.Object(dest, dbus.ObjectPath(path))}
}

/* Interface com.citrix.xenclient.db */
func (d *DbClient) Dump(path string) (value string, err error) {

err = d.Call("com.citrix.xenclient.db.dump", 0, path).Store(&value)

return
}

func (d *DbClient) Exists(path string) (ex bool, err error) {

err = d.Call("com.citrix.xenclient.db.exists", 0, path).Store(&ex)

return
}

func (d *DbClient) Inject(path string, value string) error {

call := d.Call("com.citrix.xenclient.db.inject", 0, path, value)

return call.Err
}

func (d *DbClient) List(path string) (value []string, err error) {

err = d.Call("com.citrix.xenclient.db.list", 0, path).Store(&value)

return
}

func (d *DbClient) Read(path string) (value string, err error) {

err = d.Call("com.citrix.xenclient.db.read", 0, path).Store(&value)

return
}

func (d *DbClient) ReadBinary(path string) (value []byte, err error) {

err = d.Call("com.citrix.xenclient.db.read_binary", 0, path).Store(&value)

return
}

func (d *DbClient) Rm(path string) error {

call := d.Call("com.citrix.xenclient.db.rm", 0, path)

return call.Err
}

func (d *DbClient) Write(path string, value string) error {

call := d.Call("com.citrix.xenclient.db.write", 0, path, value)

return call.Err
}
13 changes: 13 additions & 0 deletions db/db.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright 2026 Apertus Soutions, LLC
//

/*
Package db implements an client and server for OpenXT db.
*/
package db

// PathDelimiter allows specifying the delimiter used for path element
// separation.
var PathDelimiter string = "/"
Loading
Loading