forked from rosa/hakurei
ldd: remove deprecated API
Closes #25. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
21
ldd/exec.go
21
ldd/exec.go
@@ -18,14 +18,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// msgStaticSuffix is the suffix of message printed to stderr by musl on a statically linked program.
|
// msgStaticSuffix is the suffix of message printed to stderr by musl on a
|
||||||
|
// statically linked program.
|
||||||
msgStaticSuffix = ": Not a valid dynamic program"
|
msgStaticSuffix = ": Not a valid dynamic program"
|
||||||
// msgStaticGlibc is a substring of the message printed to stderr by glibc on a statically linked program.
|
// msgStaticGlibc is a substring of the message printed to stderr by glibc
|
||||||
|
// on a statically linked program.
|
||||||
msgStaticGlibc = "not a dynamic executable"
|
msgStaticGlibc = "not a dynamic executable"
|
||||||
|
|
||||||
// lddName is the file name of ldd(1) passed to exec.LookPath.
|
// lddName is the file name of ldd(1) passed to exec.LookPath.
|
||||||
lddName = "ldd"
|
lddName = "ldd"
|
||||||
// lddTimeout is the maximum duration ldd(1) is allowed to ran for before it is terminated.
|
// lddTimeout is the maximum duration ldd(1) is allowed to ran for before it
|
||||||
|
// is terminated.
|
||||||
lddTimeout = 4 * time.Second
|
lddTimeout = 4 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -104,15 +107,3 @@ func Resolve(
|
|||||||
}
|
}
|
||||||
return entries, decodeErr
|
return entries, decodeErr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec runs ldd(1) in a restrictive [container] and connects it to a [Decoder], returning resulting entries.
|
|
||||||
//
|
|
||||||
// Deprecated: this function takes an unchecked pathname string.
|
|
||||||
// Relative pathnames do not work in the container as working directory information is not sent.
|
|
||||||
func Exec(ctx context.Context, msg message.Msg, pathname string) ([]*Entry, error) {
|
|
||||||
if a, err := check.NewAbs(pathname); err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else {
|
|
||||||
return Resolve(ctx, msg, a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
63
ldd/ldd.go
63
ldd/ldd.go
@@ -1,9 +1,9 @@
|
|||||||
// Package ldd provides a robust parser for ldd(1) output, and a convenience function
|
// Package ldd provides a robust parser for ldd(1) output, and a convenience
|
||||||
// for running ldd(1) in a strict sandbox.
|
// function for running ldd(1) in a strict sandbox.
|
||||||
//
|
//
|
||||||
// Note: despite the additional hardening, great care must be taken when using ldd(1).
|
// Note: despite the additional hardening, great care must be taken when using
|
||||||
// As a general rule, you must never run ldd(1) against a file that you do not wish to
|
// ldd(1). As a general rule, you must never run ldd(1) against a file that you
|
||||||
// execute within the same context.
|
// do not wish to execute within the same context.
|
||||||
package ldd
|
package ldd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -27,8 +27,8 @@ var (
|
|||||||
ErrBadLocationFormat = errors.New("bad location format")
|
ErrBadLocationFormat = errors.New("bad location format")
|
||||||
)
|
)
|
||||||
|
|
||||||
// EntryUnexpectedSegmentsError is returned when encountering
|
// EntryUnexpectedSegmentsError is returned when encountering a line containing
|
||||||
// a line containing unexpected number of segments.
|
// unexpected number of segments.
|
||||||
type EntryUnexpectedSegmentsError string
|
type EntryUnexpectedSegmentsError string
|
||||||
|
|
||||||
func (e EntryUnexpectedSegmentsError) Error() string {
|
func (e EntryUnexpectedSegmentsError) Error() string {
|
||||||
@@ -51,26 +51,31 @@ const (
|
|||||||
// entrySegmentIndexPath is the index of the segment holding [Entry.Path],
|
// entrySegmentIndexPath is the index of the segment holding [Entry.Path],
|
||||||
// present only for a line describing a fully populated [Entry].
|
// present only for a line describing a fully populated [Entry].
|
||||||
entrySegmentIndexPath = 2
|
entrySegmentIndexPath = 2
|
||||||
// entrySegmentIndexSeparator is the index of the segment containing the magic bytes entrySegmentFullSeparator,
|
// entrySegmentIndexSeparator is the index of the segment containing the
|
||||||
// present only for a line describing a fully populated [Entry].
|
// magic bytes entrySegmentFullSeparator, present only for a line describing
|
||||||
|
// a fully populated [Entry].
|
||||||
entrySegmentIndexSeparator = 1
|
entrySegmentIndexSeparator = 1
|
||||||
// entrySegmentIndexLocation is the index of the segment holding [Entry.Location]
|
// entrySegmentIndexLocation is the index of the segment holding
|
||||||
// for a line describing a fully populated [Entry].
|
// [Entry.Location] for a line describing a fully populated [Entry].
|
||||||
entrySegmentIndexLocation = 3
|
entrySegmentIndexLocation = 3
|
||||||
// entrySegmentIndexLocationShort is the index of the segment holding [Entry.Location]
|
// entrySegmentIndexLocationShort is the index of the segment holding
|
||||||
// for a line describing only [Entry.Name].
|
// [Entry.Location] for a line describing only [Entry.Name].
|
||||||
entrySegmentIndexLocationShort = 1
|
entrySegmentIndexLocationShort = 1
|
||||||
|
|
||||||
// entrySegmentSep is the byte separating segments in an [Entry] line.
|
// entrySegmentSep is the byte separating segments in an [Entry] line.
|
||||||
entrySegmentSep = ' '
|
entrySegmentSep = ' '
|
||||||
// entrySegmentFullSeparator is the exact contents of the segment at index entrySegmentIndexSeparator.
|
// entrySegmentFullSeparator is the exact contents of the segment at index
|
||||||
|
// entrySegmentIndexSeparator.
|
||||||
entrySegmentFullSeparator = "=>"
|
entrySegmentFullSeparator = "=>"
|
||||||
|
|
||||||
// entrySegmentLocationLengthMin is the minimum possible length of a segment corresponding to [Entry.Location].
|
// entrySegmentLocationLengthMin is the minimum possible length of a segment
|
||||||
|
// corresponding to [Entry.Location].
|
||||||
entrySegmentLocationLengthMin = 4
|
entrySegmentLocationLengthMin = 4
|
||||||
// entrySegmentLocationPrefix are magic bytes prefixing a segment corresponding to [Entry.Location].
|
// entrySegmentLocationPrefix are magic bytes prefixing a segment
|
||||||
|
// corresponding to [Entry.Location].
|
||||||
entrySegmentLocationPrefix = "(0x"
|
entrySegmentLocationPrefix = "(0x"
|
||||||
// entrySegmentLocationSuffix is the magic byte suffixing a segment corresponding to [Entry.Location].
|
// entrySegmentLocationSuffix is the magic byte suffixing a segment
|
||||||
|
// corresponding to [Entry.Location].
|
||||||
entrySegmentLocationSuffix = ')'
|
entrySegmentLocationSuffix = ')'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -144,7 +149,9 @@ func (e *Entry) String() string {
|
|||||||
if e.Path != nil {
|
if e.Path != nil {
|
||||||
buf.WriteString(entrySegmentFullSeparator + " " + e.Path.String() + " ")
|
buf.WriteString(entrySegmentFullSeparator + " " + e.Path.String() + " ")
|
||||||
}
|
}
|
||||||
buf.WriteString(entrySegmentLocationPrefix + strconv.FormatUint(e.Location, 16) + string(entrySegmentLocationSuffix))
|
buf.WriteString(entrySegmentLocationPrefix +
|
||||||
|
strconv.FormatUint(e.Location, 16) +
|
||||||
|
string(entrySegmentLocationSuffix))
|
||||||
|
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
@@ -180,12 +187,12 @@ type Decoder struct {
|
|||||||
|
|
||||||
// NewDecoder returns a new decoder that reads from r.
|
// NewDecoder returns a new decoder that reads from r.
|
||||||
//
|
//
|
||||||
// The decoder introduces its own buffering and may read
|
// The decoder introduces its own buffering and may read data from r beyond the
|
||||||
// data from r beyond the [Entry] values requested.
|
// [Entry] values requested.
|
||||||
func NewDecoder(r io.Reader) *Decoder { return &Decoder{s: bufio.NewScanner(r)} }
|
func NewDecoder(r io.Reader) *Decoder { return &Decoder{s: bufio.NewScanner(r)} }
|
||||||
|
|
||||||
// Scan advances the [Decoder] to the next [Entry] and
|
// Scan advances the [Decoder] to the next [Entry] and stores the result in the
|
||||||
// stores the result in the value pointed to by v.
|
// value pointed to by v.
|
||||||
func (d *Decoder) Scan(v *Entry) bool {
|
func (d *Decoder) Scan(v *Entry) bool {
|
||||||
if d.s == nil || d.err != nil || d.depleted {
|
if d.s == nil || d.err != nil || d.depleted {
|
||||||
return false
|
return false
|
||||||
@@ -215,8 +222,8 @@ func (d *Decoder) Scan(v *Entry) bool {
|
|||||||
return d.err == nil
|
return d.err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Err returns the first non-EOF error that was encountered
|
// Err returns the first non-EOF error that was encountered by the underlying
|
||||||
// by the underlying [bufio.Scanner] or [Entry].
|
// [bufio.Scanner] or [Entry].
|
||||||
func (d *Decoder) Err() error {
|
func (d *Decoder) Err() error {
|
||||||
if d.err != nil || d.s == nil {
|
if d.err != nil || d.s == nil {
|
||||||
return d.err
|
return d.err
|
||||||
@@ -224,8 +231,8 @@ func (d *Decoder) Err() error {
|
|||||||
return d.s.Err()
|
return d.s.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode reads from the input stream until there are no more entries
|
// Decode reads from the input stream until there are no more entries and
|
||||||
// and returns the results in a slice.
|
// returns the results in a slice.
|
||||||
func (d *Decoder) Decode() ([]*Entry, error) {
|
func (d *Decoder) Decode() ([]*Entry, error) {
|
||||||
var entries []*Entry
|
var entries []*Entry
|
||||||
|
|
||||||
@@ -238,4 +245,6 @@ func (d *Decoder) Decode() ([]*Entry, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse returns a slice of addresses to [Entry] decoded from p.
|
// Parse returns a slice of addresses to [Entry] decoded from p.
|
||||||
func Parse(p []byte) ([]*Entry, error) { return NewDecoder(bytes.NewReader(p)).Decode() }
|
func Parse(p []byte) ([]*Entry, error) {
|
||||||
|
return NewDecoder(bytes.NewReader(p)).Decode()
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user