boxdd: Implement linux http proxy
This commit is contained in:
@@ -16,15 +16,31 @@ import (
|
||||
)
|
||||
|
||||
type LinuxSystemProxy struct {
|
||||
execute func(name string, args ...string) error
|
||||
hasGSettings bool
|
||||
kWriteConfigCmd string
|
||||
sudoUser string
|
||||
serverAddr M.Socksaddr
|
||||
supportSOCKS bool
|
||||
isEnabled bool
|
||||
}
|
||||
|
||||
func NewSystemProxy(ctx context.Context, serverAddr M.Socksaddr, supportSOCKS bool, bypassDomain []string) (*LinuxSystemProxy, error) {
|
||||
var sudoUser string
|
||||
if os.Getuid() == 0 {
|
||||
sudoUser = os.Getenv("SUDO_USER")
|
||||
}
|
||||
return NewLinuxSystemProxy(serverAddr, supportSOCKS, func(name string, args ...string) error {
|
||||
if os.Getuid() != 0 {
|
||||
return shell.Exec(name, args...).Attach().Run()
|
||||
} else if sudoUser != "" {
|
||||
return shell.Exec("su", "-", sudoUser, "-c", F.ToString(name, " ", strings.Join(args, " "))).Attach().Run()
|
||||
} else {
|
||||
return E.New("set system proxy: unable to set as root")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func NewLinuxSystemProxy(serverAddr M.Socksaddr, supportSOCKS bool, execute func(name string, args ...string) error) (*LinuxSystemProxy, error) {
|
||||
hasGSettings := common.Error(exec.LookPath("gsettings")) == nil
|
||||
kWriteConfigCmds := []string{
|
||||
"kwriteconfig5",
|
||||
@@ -37,17 +53,13 @@ func NewSystemProxy(ctx context.Context, serverAddr M.Socksaddr, supportSOCKS bo
|
||||
break
|
||||
}
|
||||
}
|
||||
var sudoUser string
|
||||
if os.Getuid() == 0 {
|
||||
sudoUser = os.Getenv("SUDO_USER")
|
||||
}
|
||||
if !hasGSettings && kWriteConfigCmd == "" {
|
||||
return nil, E.New("unsupported desktop environment")
|
||||
}
|
||||
return &LinuxSystemProxy{
|
||||
execute: execute,
|
||||
hasGSettings: hasGSettings,
|
||||
kWriteConfigCmd: kWriteConfigCmd,
|
||||
sudoUser: sudoUser,
|
||||
serverAddr: serverAddr,
|
||||
supportSOCKS: supportSOCKS,
|
||||
}, nil
|
||||
@@ -59,7 +71,7 @@ func (p *LinuxSystemProxy) IsEnabled() bool {
|
||||
|
||||
func (p *LinuxSystemProxy) Enable() error {
|
||||
if p.hasGSettings {
|
||||
err := p.runAsUser("gsettings", "set", "org.gnome.system.proxy.http", "enabled", "true")
|
||||
err := p.execute("gsettings", "set", "org.gnome.system.proxy.http", "enabled", "true")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -71,17 +83,17 @@ func (p *LinuxSystemProxy) Enable() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = p.runAsUser("gsettings", "set", "org.gnome.system.proxy", "use-same-proxy", F.ToString(p.supportSOCKS))
|
||||
err = p.execute("gsettings", "set", "org.gnome.system.proxy", "use-same-proxy", F.ToString(p.supportSOCKS))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = p.runAsUser("gsettings", "set", "org.gnome.system.proxy", "mode", "manual")
|
||||
err = p.execute("gsettings", "set", "org.gnome.system.proxy", "mode", "manual")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if p.kWriteConfigCmd != "" {
|
||||
err := p.runAsUser(p.kWriteConfigCmd, "--file", "kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "1")
|
||||
err := p.execute(p.kWriteConfigCmd, "--file", "kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -93,11 +105,11 @@ func (p *LinuxSystemProxy) Enable() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = p.runAsUser(p.kWriteConfigCmd, "--file", "kioslaverc", "--group", "Proxy Settings", "--key", "Authmode", "0")
|
||||
err = p.execute(p.kWriteConfigCmd, "--file", "kioslaverc", "--group", "Proxy Settings", "--key", "Authmode", "0")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = p.runAsUser("dbus-send", "--type=signal", "/KIO/Scheduler", "org.kde.KIO.Scheduler.reparseSlaveConfiguration", "string:''")
|
||||
err = p.execute("dbus-send", "--type=signal", "/KIO/Scheduler", "org.kde.KIO.Scheduler.reparseSlaveConfiguration", "string:''")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -108,17 +120,17 @@ func (p *LinuxSystemProxy) Enable() error {
|
||||
|
||||
func (p *LinuxSystemProxy) Disable() error {
|
||||
if p.hasGSettings {
|
||||
err := p.runAsUser("gsettings", "set", "org.gnome.system.proxy", "mode", "none")
|
||||
err := p.execute("gsettings", "set", "org.gnome.system.proxy", "mode", "none")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if p.kWriteConfigCmd != "" {
|
||||
err := p.runAsUser(p.kWriteConfigCmd, "--file", "kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "0")
|
||||
err := p.execute(p.kWriteConfigCmd, "--file", "kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "0")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = p.runAsUser("dbus-send", "--type=signal", "/KIO/Scheduler", "org.kde.KIO.Scheduler.reparseSlaveConfiguration", "string:''")
|
||||
err = p.execute("dbus-send", "--type=signal", "/KIO/Scheduler", "org.kde.KIO.Scheduler.reparseSlaveConfiguration", "string:''")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -127,23 +139,13 @@ func (p *LinuxSystemProxy) Disable() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *LinuxSystemProxy) runAsUser(name string, args ...string) error {
|
||||
if os.Getuid() != 0 {
|
||||
return shell.Exec(name, args...).Attach().Run()
|
||||
} else if p.sudoUser != "" {
|
||||
return shell.Exec("su", "-", p.sudoUser, "-c", F.ToString(name, " ", strings.Join(args, " "))).Attach().Run()
|
||||
} else {
|
||||
return E.New("set system proxy: unable to set as root")
|
||||
}
|
||||
}
|
||||
|
||||
func (p *LinuxSystemProxy) setGnomeProxy(proxyTypes ...string) error {
|
||||
for _, proxyType := range proxyTypes {
|
||||
err := p.runAsUser("gsettings", "set", "org.gnome.system.proxy."+proxyType, "host", p.serverAddr.AddrString())
|
||||
err := p.execute("gsettings", "set", "org.gnome.system.proxy."+proxyType, "host", p.serverAddr.AddrString())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = p.runAsUser("gsettings", "set", "org.gnome.system.proxy."+proxyType, "port", F.ToString(p.serverAddr.Port))
|
||||
err = p.execute("gsettings", "set", "org.gnome.system.proxy."+proxyType, "port", F.ToString(p.serverAddr.Port))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -159,7 +161,7 @@ func (p *LinuxSystemProxy) setKDEProxy(proxyTypes ...string) error {
|
||||
} else {
|
||||
proxyUrl = "http://" + p.serverAddr.String()
|
||||
}
|
||||
err := p.runAsUser(
|
||||
err := p.execute(
|
||||
p.kWriteConfigCmd,
|
||||
"--file",
|
||||
"kioslaverc",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//nolint:unused
|
||||
package main
|
||||
|
||||
import (
|
||||
|
||||
@@ -0,0 +1,394 @@
|
||||
//go:build linux && !android
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/settings"
|
||||
"github.com/sagernet/sing-box/daemon"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-tun"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
"github.com/sagernet/sing/common/shell"
|
||||
)
|
||||
|
||||
type linuxPlatformInterface struct {
|
||||
daemon *Daemon
|
||||
access sync.Mutex
|
||||
ownerUser *user.User
|
||||
systemProxy *settings.LinuxSystemProxy
|
||||
systemProxyEnabled bool
|
||||
}
|
||||
|
||||
func newPlatformInterface(daemonInstance *Daemon) (daemonPlatform, error) {
|
||||
return &linuxPlatformInterface{
|
||||
daemon: daemonInstance,
|
||||
systemProxyEnabled: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) Initialize(networkManager adapter.NetworkManager) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) UsePlatformAutoDetectInterfaceControl() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) AutoDetectInterfaceControl(fd int) error {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) UsePlatformInterface() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) OpenInterface(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) ProcessPlatformOptions(options option.TunPlatformOptions) error {
|
||||
if options.HTTPProxy == nil || !options.HTTPProxy.Enabled {
|
||||
return nil
|
||||
}
|
||||
httpProxyOptions := options.HTTPProxy
|
||||
systemProxy, err := settings.NewLinuxSystemProxy(
|
||||
M.ParseSocksaddrHostPort(httpProxyOptions.Server, httpProxyOptions.ServerPort),
|
||||
false,
|
||||
p.executeAsOwner,
|
||||
)
|
||||
if err != nil {
|
||||
p.daemon.logger.Warn("initialize system proxy: ", err)
|
||||
return nil
|
||||
}
|
||||
p.access.Lock()
|
||||
if p.systemProxy != nil {
|
||||
p.access.Unlock()
|
||||
return E.New("only one enabled `tun.platform.http_proxy` is supported")
|
||||
}
|
||||
p.systemProxy = systemProxy
|
||||
err = p.applySystemProxyLocked()
|
||||
if err != nil {
|
||||
rollbackError := p.disableSystemProxyLocked()
|
||||
p.systemProxy = nil
|
||||
p.access.Unlock()
|
||||
return E.Errors(E.Cause(err, "set system proxy"), rollbackError)
|
||||
}
|
||||
p.access.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) UsePlatformDefaultInterfaceMonitor() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) CreateDefaultInterfaceMonitor(logger logger.Logger) tun.DefaultInterfaceMonitor {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) UsePlatformNetworkInterfaces() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) NetworkInterfaces() ([]adapter.NetworkInterface, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) UnderNetworkExtension() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) NetworkExtensionIncludeAllNetworks() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) ClearDNSCache() {
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) RequestPermissionForWIFIState() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) ReadWIFIState() adapter.WIFIState {
|
||||
return adapter.WIFIState{}
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) UsePlatformConnectionOwnerFinder() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) FindConnectionOwner(request *adapter.FindConnectionOwnerRequest) (*adapter.ConnectionOwner, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) UsePlatformWIFIMonitor() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) UsePlatformNotification() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) SendNotification(notification *adapter.Notification) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) MyInterfaceAddress() []netip.Addr {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) UsePlatformNeighborResolver() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) StartNeighborMonitor(listener adapter.NeighborUpdateListener) error {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) CloseNeighborMonitor(listener adapter.NeighborUpdateListener) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) UsePlatformShell() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) CheckPlatformShell() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) OpenShellSession(user *adapter.PlatformUser, command string, environ []string, term string, rows int32, cols int32) (adapter.ShellSession, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) LookupUser(username string) (*adapter.PlatformUser, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) LookupSFTPServer() (string, error) {
|
||||
return "", os.ErrInvalid
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) ReadSystemSSHHostKey() ([]byte, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) TailscaleHostname() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) UsePlatformBridge() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) CreateBridge(options adapter.BridgeOptions) (adapter.BridgeSession, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) PrepareOwner(identity peerIdentity) error {
|
||||
p.access.Lock()
|
||||
defer p.access.Unlock()
|
||||
if listenAddress != "" {
|
||||
return p.applySystemProxyLocked()
|
||||
}
|
||||
if p.ownerUser != nil && p.ownerUser.Uid == identity.UserID {
|
||||
return p.applySystemProxyLocked()
|
||||
}
|
||||
ownerUser, err := user.LookupId(identity.UserID)
|
||||
if err != nil {
|
||||
return E.Cause(err, "lookup owner user")
|
||||
}
|
||||
return p.replaceOwnerLocked(ownerUser)
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) RestoreOwner(state ownerState) error {
|
||||
p.access.Lock()
|
||||
defer p.access.Unlock()
|
||||
if listenAddress != "" {
|
||||
return nil
|
||||
}
|
||||
ownerUser, err := user.LookupId(state.UserID)
|
||||
if err != nil {
|
||||
return E.Cause(err, "lookup owner user")
|
||||
}
|
||||
p.ownerUser = ownerUser
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) ReleaseOwner() error {
|
||||
p.access.Lock()
|
||||
defer p.access.Unlock()
|
||||
err := p.disableSystemProxyLocked()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.ownerUser = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) ResetPlatformOptions() error {
|
||||
p.access.Lock()
|
||||
defer p.access.Unlock()
|
||||
err := p.disableSystemProxyLocked()
|
||||
if err == nil {
|
||||
p.systemProxy = nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) SetSystemProxyPreference(enabled bool) {
|
||||
p.access.Lock()
|
||||
p.systemProxyEnabled = enabled
|
||||
p.access.Unlock()
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) SystemProxyStatus() (*daemon.SystemProxyStatus, error) {
|
||||
p.access.Lock()
|
||||
defer p.access.Unlock()
|
||||
available := p.systemProxy != nil
|
||||
return &daemon.SystemProxyStatus{
|
||||
Available: available,
|
||||
Enabled: available && p.systemProxyEnabled,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) SetSystemProxyEnabled(enabled bool) error {
|
||||
p.access.Lock()
|
||||
defer p.access.Unlock()
|
||||
if p.systemProxy == nil {
|
||||
if !enabled {
|
||||
p.systemProxyEnabled = false
|
||||
return nil
|
||||
}
|
||||
return E.New("the system proxy is not available")
|
||||
}
|
||||
previousEnabled := p.systemProxyEnabled
|
||||
p.systemProxyEnabled = enabled
|
||||
err := p.applySystemProxyLocked()
|
||||
if err != nil {
|
||||
p.systemProxyEnabled = previousEnabled
|
||||
rollbackError := p.applySystemProxyLocked()
|
||||
return E.Errors(err, rollbackError)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) HandleSessionChange(eventType uint32, sessionID uint32, state ownerState) (uint32, bool, error) {
|
||||
return 0, false, nil
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) Close() error {
|
||||
p.access.Lock()
|
||||
defer p.access.Unlock()
|
||||
err := p.disableSystemProxyLocked()
|
||||
p.systemProxy = nil
|
||||
p.ownerUser = nil
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) applySystemProxyLocked() error {
|
||||
if p.systemProxy == nil {
|
||||
return nil
|
||||
}
|
||||
if p.systemProxyEnabled {
|
||||
if p.systemProxy.IsEnabled() || !p.ownerSessionActiveLocked() {
|
||||
return nil
|
||||
}
|
||||
return p.systemProxy.Enable()
|
||||
}
|
||||
return p.disableSystemProxyLocked()
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) disableSystemProxyLocked() error {
|
||||
if p.systemProxy == nil || !p.systemProxy.IsEnabled() || !p.ownerSessionActiveLocked() {
|
||||
return nil
|
||||
}
|
||||
return p.systemProxy.Disable()
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) ownerSessionActiveLocked() bool {
|
||||
if listenAddress != "" {
|
||||
return true
|
||||
}
|
||||
if p.ownerUser == nil {
|
||||
return false
|
||||
}
|
||||
_, err := os.Stat(ownerSessionBusPath(p.ownerUser))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) executeAsOwner(name string, args ...string) error {
|
||||
if listenAddress != "" {
|
||||
return shell.Exec(name, args...).Attach().Run()
|
||||
}
|
||||
ownerUser := p.ownerUser
|
||||
if ownerUser == nil {
|
||||
return E.New("missing owner session")
|
||||
}
|
||||
uid, err := strconv.ParseUint(ownerUser.Uid, 10, 32)
|
||||
if err != nil {
|
||||
return E.Cause(err, "parse owner user ID")
|
||||
}
|
||||
gid, err := strconv.ParseUint(ownerUser.Gid, 10, 32)
|
||||
if err != nil {
|
||||
return E.Cause(err, "parse owner group ID")
|
||||
}
|
||||
searchPath := os.Getenv("PATH")
|
||||
if searchPath == "" {
|
||||
searchPath = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
}
|
||||
command := exec.Command(name, args...)
|
||||
command.SysProcAttr = &syscall.SysProcAttr{
|
||||
Credential: &syscall.Credential{
|
||||
Uid: uint32(uid),
|
||||
Gid: uint32(gid),
|
||||
},
|
||||
}
|
||||
command.Env = []string{
|
||||
"HOME=" + ownerUser.HomeDir,
|
||||
"USER=" + ownerUser.Username,
|
||||
"LOGNAME=" + ownerUser.Username,
|
||||
"PATH=" + searchPath,
|
||||
"XDG_RUNTIME_DIR=" + ownerRuntimeDirectory(ownerUser),
|
||||
"DBUS_SESSION_BUS_ADDRESS=unix:path=" + ownerSessionBusPath(ownerUser),
|
||||
}
|
||||
output, err := command.CombinedOutput()
|
||||
if err != nil {
|
||||
outputText := strings.TrimSpace(string(output))
|
||||
if outputText != "" {
|
||||
return E.Cause(err, "execute (", name, ") ", strings.Join(args, " "), ": ", outputText)
|
||||
}
|
||||
return E.Cause(err, "execute (", name, ") ", strings.Join(args, " "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *linuxPlatformInterface) replaceOwnerLocked(ownerUser *user.User) error {
|
||||
err := p.disableSystemProxyLocked()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.ownerUser = ownerUser
|
||||
return p.applySystemProxyLocked()
|
||||
}
|
||||
|
||||
func ownerRuntimeDirectory(ownerUser *user.User) string {
|
||||
return "/run/user/" + ownerUser.Uid
|
||||
}
|
||||
|
||||
func ownerSessionBusPath(ownerUser *user.User) string {
|
||||
return ownerRuntimeDirectory(ownerUser) + "/bus"
|
||||
}
|
||||
|
||||
var _ daemonPlatform = (*linuxPlatformInterface)(nil)
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build !windows
|
||||
//go:build !windows && !(linux && !android)
|
||||
|
||||
package main
|
||||
|
||||
|
||||
Reference in New Issue
Block a user