Add untested plugin support
This commit is contained in:
parent
9a6607494f
commit
209270a179
@ -5,7 +5,9 @@ import "io"
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
import "time"
|
import "time"
|
||||||
import "io/fs"
|
import "io/fs"
|
||||||
|
import "plugin"
|
||||||
import "errors"
|
import "errors"
|
||||||
|
import "syscall"
|
||||||
import "context"
|
import "context"
|
||||||
import "path/filepath"
|
import "path/filepath"
|
||||||
import "html/template"
|
import "html/template"
|
||||||
@ -103,6 +105,55 @@ func (this *Environment) Unload (name string) {
|
|||||||
delete(documents, name)
|
delete(documents, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadProviderPlugin loads a plugin given its file path. The file must:
|
||||||
|
//
|
||||||
|
// - Be a shared library
|
||||||
|
// - Be built with go -buildmode=plugin
|
||||||
|
// - Be built with the same version of Go
|
||||||
|
// - Be built with the same version of STEP
|
||||||
|
// - Be owned by root
|
||||||
|
//
|
||||||
|
// Plugins cannot be unloaded from the current program once they are loaded.
|
||||||
|
// Sorgy :( its Go's fault.
|
||||||
|
func (this *Environment) LoadProviderPlugin (name string) (Provider, error) {
|
||||||
|
return this.loadProviderPlugin(name, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadProviderPluginUnsafe is like LoadProviderPlugin, but does not check to
|
||||||
|
// see that the file is owned by root, thereby making it easier to run a random
|
||||||
|
// plugin you just compiled. This should not be used otherwise.
|
||||||
|
func (this *Environment) LoadProviderPluginUnsafe (name string) (Provider, error) {
|
||||||
|
return this.loadProviderPlugin(name, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Environment) loadProviderPlugin (name string, checkRoot bool) (Provider, error) {
|
||||||
|
plugin, err := this.loadPlugin(name, checkRoot)
|
||||||
|
if err != nil { return nil, err }
|
||||||
|
providerSymbol, err := plugin.Lookup("Provider")
|
||||||
|
if err != nil { return nil, err }
|
||||||
|
providerFactory, ok := providerSymbol.(func () Provider)
|
||||||
|
if !ok { return nil, ErrPluginBadSymbol }
|
||||||
|
provider := providerFactory()
|
||||||
|
this.Providers = append(this.Providers, provider)
|
||||||
|
return provider, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Environment) loadPlugin (name string, checkRoot bool) (*plugin.Plugin, error) {
|
||||||
|
name = filepath.Clean(name)
|
||||||
|
if checkRoot {
|
||||||
|
info, err := os.Stat(name)
|
||||||
|
if err != nil { return nil, err }
|
||||||
|
if info, ok := info.Sys().(*syscall.Stat_t); ok {
|
||||||
|
if info.Uid != 0 {
|
||||||
|
return nil, ErrPluginNotOwnedByRoot
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, ErrInsufficientSystem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return plugin.Open(name)
|
||||||
|
}
|
||||||
|
|
||||||
func (this *Environment) parse (name string, modTime time.Time, input io.Reader) (*Document, error) {
|
func (this *Environment) parse (name string, modTime time.Time, input io.Reader) (*Document, error) {
|
||||||
documents, done := this.documents.Borrow()
|
documents, done := this.documents.Borrow()
|
||||||
defer done()
|
defer done()
|
||||||
|
3
error.go
3
error.go
@ -6,6 +6,9 @@ type Error string; const (
|
|||||||
ErrMetaMalformed Error = "metadata is malformed"
|
ErrMetaMalformed Error = "metadata is malformed"
|
||||||
ErrMetaNeverClosed Error = "metadata is never closed"
|
ErrMetaNeverClosed Error = "metadata is never closed"
|
||||||
ErrTypeMismatch Error = "type mismatch"
|
ErrTypeMismatch Error = "type mismatch"
|
||||||
|
ErrPluginBadSymbol Error = "plugin has an incorrect symbol"
|
||||||
|
ErrPluginNotOwnedByRoot Error = "plugin is not owned by the root user"
|
||||||
|
ErrInsufficientSystem Error = "the system cannot perform this action"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Error fulfills the error interface.
|
// Error fulfills the error interface.
|
||||||
|
Loading…
Reference in New Issue
Block a user