diff --git a/Gopkg.toml b/Gopkg.toml index eab5bae7..8d3cb550 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -1,7 +1,3 @@ -[[constraint]] - name = "github.com/coreos/pkg" - version = "4.0.0" - [[constraint]] name = "github.com/godbus/dbus" version = "5.0" diff --git a/internal/dlopen/dlopen.go b/internal/dlopen/dlopen.go new file mode 100644 index 00000000..23774f61 --- /dev/null +++ b/internal/dlopen/dlopen.go @@ -0,0 +1,82 @@ +// Copyright 2016 CoreOS, Inc. +// +// 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 dlopen provides some convenience functions to dlopen a library and +// get its symbols. +package dlopen + +// #cgo LDFLAGS: -ldl +// #include +// #include +import "C" +import ( + "errors" + "fmt" + "unsafe" +) + +var ErrSoNotFound = errors.New("unable to open a handle to the library") + +// LibHandle represents an open handle to a library (.so) +type LibHandle struct { + Handle unsafe.Pointer + Libname string +} + +// GetHandle tries to get a handle to a library (.so), attempting to access it +// by the names specified in libs and returning the first that is successfully +// opened. Callers are responsible for closing the handler. If no library can +// be successfully opened, an error is returned. +func GetHandle(libs []string) (*LibHandle, error) { + for _, name := range libs { + libname := C.CString(name) + defer C.free(unsafe.Pointer(libname)) + handle := C.dlopen(libname, C.RTLD_LAZY) + if handle != nil { + h := &LibHandle{ + Handle: handle, + Libname: name, + } + return h, nil + } + } + return nil, ErrSoNotFound +} + +// GetSymbolPointer takes a symbol name and returns a pointer to the symbol. +func (l *LibHandle) GetSymbolPointer(symbol string) (unsafe.Pointer, error) { + sym := C.CString(symbol) + defer C.free(unsafe.Pointer(sym)) + + C.dlerror() + p := C.dlsym(l.Handle, sym) + e := C.dlerror() + if e != nil { + return nil, fmt.Errorf("error resolving symbol %q: %v", symbol, errors.New(C.GoString(e))) + } + + return p, nil +} + +// Close closes a LibHandle. +func (l *LibHandle) Close() error { + C.dlerror() + C.dlclose(l.Handle) + e := C.dlerror() + if e != nil { + return fmt.Errorf("error closing %v: %v", l.Libname, errors.New(C.GoString(e))) + } + + return nil +} diff --git a/internal/dlopen/dlopen_test.go b/internal/dlopen/dlopen_test.go new file mode 100644 index 00000000..60d88fa4 --- /dev/null +++ b/internal/dlopen/dlopen_test.go @@ -0,0 +1,63 @@ +// Copyright 2015 CoreOS, Inc. +// +// 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 dlopen + +import ( + "fmt" + "testing" +) + +func checkFailure(shouldSucceed bool, err error) (rErr error) { + switch { + case err != nil && shouldSucceed: + rErr = fmt.Errorf("expected test to succeed, failed unexpectedly: %v", err) + case err == nil && !shouldSucceed: + rErr = fmt.Errorf("expected test to fail, succeeded unexpectedly") + } + + return +} + +func TestDlopen(t *testing.T) { + tests := []struct { + libs []string + shouldSucceed bool + }{ + { + libs: []string{ + "libc.so.6", + "libc.so", + }, + shouldSucceed: true, + }, + { + libs: []string{ + "libstrange.so", + }, + shouldSucceed: false, + }, + } + + for i, tt := range tests { + expLen := 4 + len, err := strlen(tt.libs, "test") + if checkFailure(tt.shouldSucceed, err) != nil { + t.Errorf("case %d: %v", i, err) + } + + if tt.shouldSucceed && len != expLen { + t.Errorf("case %d: expected length %d, got %d", i, expLen, len) + } + } +} diff --git a/scripts/jenkins/periodic-go-systemd-builder.sh b/scripts/jenkins/periodic-go-systemd-builder.sh index 05089f72..89e32ed1 100755 --- a/scripts/jenkins/periodic-go-systemd-builder.sh +++ b/scripts/jenkins/periodic-go-systemd-builder.sh @@ -19,6 +19,5 @@ if [ ! -h gopath/src/github.com/coreos/go-systemd ]; then fi export GOPATH=${PWD}/gopath go get -u github.com/godbus/dbus -go get github.com/coreos/pkg/dlopen sudo -E ./test diff --git a/sdjournal/functions.go b/sdjournal/functions.go index e132369c..06aaca14 100644 --- a/sdjournal/functions.go +++ b/sdjournal/functions.go @@ -16,7 +16,7 @@ package sdjournal import ( - "github.com/coreos/pkg/dlopen" + "github.com/coreos/go-systemd/internal/dlopen" "sync" "unsafe" ) diff --git a/test b/test index 2ffd6117..e43fa6e3 100755 --- a/test +++ b/test @@ -24,7 +24,6 @@ if [ -z "$GOPATH" ]; then fi export GOPATH=${PWD}/gopath go get -u github.com/godbus/dbus - go get -u github.com/coreos/pkg/dlopen fi TESTABLE="activation daemon journal login1 unit" diff --git a/util/util_cgo.go b/util/util_cgo.go index 6269bc73..b683b168 100644 --- a/util/util_cgo.go +++ b/util/util_cgo.go @@ -58,7 +58,7 @@ import ( "syscall" "unsafe" - "github.com/coreos/pkg/dlopen" + "github.com/coreos/go-systemd/internal/dlopen" ) var libsystemdNames = []string{