aboutsummaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/boltdb_state.go167
-rw-r--r--libpod/container_internal.go20
-rw-r--r--libpod/container_internal_test.go48
-rw-r--r--libpod/oci.go6
4 files changed, 172 insertions, 69 deletions
diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go
index c226a0617..92a7b1538 100644
--- a/libpod/boltdb_state.go
+++ b/libpod/boltdb_state.go
@@ -382,6 +382,11 @@ func (s *BoltState) LookupContainer(idOrName string) (*Container, error) {
return err
}
+ namesBucket, err := getNamesBucket(tx)
+ if err != nil {
+ return err
+ }
+
nsBucket, err := getNSBucket(tx)
if err != nil {
return err
@@ -395,41 +400,59 @@ func (s *BoltState) LookupContainer(idOrName string) (*Container, error) {
// It might not be in our namespace, but
// getContainerFromDB() will handle that case.
id = []byte(idOrName)
- } else {
- // They did not give us a full container ID.
- // Search for partial ID or full name matches
- // Use else-if in case the name is set to a partial ID
- exists := false
- err = idBucket.ForEach(func(checkID, checkName []byte) error {
- // If the container isn't in our namespace, we
- // can't match it
- if s.namespaceBytes != nil {
- ns := nsBucket.Get(checkID)
- if !bytes.Equal(ns, s.namespaceBytes) {
- return nil
- }
+ return s.getContainerFromDB(id, ctr, ctrBucket)
+ }
+
+ // Next, check if the full name was given
+ isPod := false
+ fullID := namesBucket.Get([]byte(idOrName))
+ if fullID != nil {
+ // The name exists and maps to an ID.
+ // However, we are not yet certain the ID is a
+ // container.
+ ctrExists = ctrBucket.Bucket(fullID)
+ if ctrExists != nil {
+ // A container bucket matching the full ID was
+ // found.
+ return s.getContainerFromDB(fullID, ctr, ctrBucket)
+ }
+ // Don't error if we have a name match but it's not a
+ // container - there's a chance we have a container with
+ // an ID starting with those characters.
+ // However, so we can return a good error, note whether
+ // this is a pod.
+ isPod = true
+ }
+
+ // We were not given a full container ID or name.
+ // Search for partial ID matches.
+ exists := false
+ err = idBucket.ForEach(func(checkID, checkName []byte) error {
+ // If the container isn't in our namespace, we
+ // can't match it
+ if s.namespaceBytes != nil {
+ ns := nsBucket.Get(checkID)
+ if !bytes.Equal(ns, s.namespaceBytes) {
+ return nil
}
- if string(checkName) == idOrName {
- if exists {
- return errors.Wrapf(ErrCtrExists, "more than one result for ID or name %s", idOrName)
- }
- id = checkID
- exists = true
- } else if strings.HasPrefix(string(checkID), idOrName) {
- if exists {
- return errors.Wrapf(ErrCtrExists, "more than one result for ID or name %s", idOrName)
- }
- id = checkID
- exists = true
+ }
+ if strings.HasPrefix(string(checkID), idOrName) {
+ if exists {
+ return errors.Wrapf(ErrCtrExists, "more than one result for container ID %s", idOrName)
}
+ id = checkID
+ exists = true
+ }
- return nil
- })
- if err != nil {
- return err
- } else if !exists {
- return errors.Wrapf(ErrNoSuchCtr, "no container with name or ID %s found", idOrName)
+ return nil
+ })
+ if err != nil {
+ return err
+ } else if !exists {
+ if isPod {
+ return errors.Wrapf(ErrNoSuchCtr, "%s is a pod, not a container", idOrName)
}
+ return errors.Wrapf(ErrNoSuchCtr, "no container with name or ID %s found", idOrName)
}
return s.getContainerFromDB(id, ctr, ctrBucket)
@@ -941,6 +964,11 @@ func (s *BoltState) LookupPod(idOrName string) (*Pod, error) {
return err
}
+ namesBkt, err := getNamesBucket(tx)
+ if err != nil {
+ return err
+ }
+
nsBkt, err := getNSBucket(tx)
if err != nil {
return err
@@ -954,41 +982,56 @@ func (s *BoltState) LookupPod(idOrName string) (*Pod, error) {
// It might not be in our namespace, but getPodFromDB()
// will handle that case.
id = []byte(idOrName)
- } else {
- // They did not give us a full pod ID.
- // Search for partial ID or full name matches
- // Use else-if in case the name is set to a partial ID
- exists := false
- err = idBucket.ForEach(func(checkID, checkName []byte) error {
- // If the pod isn't in our namespace, we
- // can't match it
- if s.namespaceBytes != nil {
- ns := nsBkt.Get(checkID)
- if !bytes.Equal(ns, s.namespaceBytes) {
- return nil
- }
+ return s.getPodFromDB(id, pod, podBkt)
+ }
+
+ // Next, check if the full name was given
+ isCtr := false
+ fullID := namesBkt.Get([]byte(idOrName))
+ if fullID != nil {
+ // The name exists and maps to an ID.
+ // However, we aren't yet sure if the ID is a pod.
+ podExists = podBkt.Bucket(fullID)
+ if podExists != nil {
+ // A pod bucket matching the full ID was found.
+ return s.getPodFromDB(fullID, pod, podBkt)
+ }
+ // Don't error if we have a name match but it's not a
+ // pod - there's a chance we have a pod with an ID
+ // starting with those characters.
+ // However, so we can return a good error, note whether
+ // this is a container.
+ isCtr = true
+ }
+ // They did not give us a full pod name or ID.
+ // Search for partial ID matches.
+ exists := false
+ err = idBucket.ForEach(func(checkID, checkName []byte) error {
+ // If the pod isn't in our namespace, we
+ // can't match it
+ if s.namespaceBytes != nil {
+ ns := nsBkt.Get(checkID)
+ if !bytes.Equal(ns, s.namespaceBytes) {
+ return nil
}
- if string(checkName) == idOrName {
- if exists {
- return errors.Wrapf(ErrPodExists, "more than one result for ID or name %s", idOrName)
- }
- id = checkID
- exists = true
- } else if strings.HasPrefix(string(checkID), idOrName) {
- if exists {
- return errors.Wrapf(ErrPodExists, "more than one result for ID or name %s", idOrName)
- }
- id = checkID
- exists = true
+ }
+ if strings.HasPrefix(string(checkID), idOrName) {
+ if exists {
+ return errors.Wrapf(ErrPodExists, "more than one result for ID or name %s", idOrName)
}
+ id = checkID
+ exists = true
+ }
- return nil
- })
- if err != nil {
- return err
- } else if !exists {
- return errors.Wrapf(ErrNoSuchPod, "no pod with name or ID %s found", idOrName)
+ return nil
+ })
+ if err != nil {
+ return err
+ } else if !exists {
+ if isCtr {
+ return errors.Wrapf(ErrNoSuchPod, "%s is a container, not a pod", idOrName)
}
+ return errors.Wrapf(ErrNoSuchPod, "no pod with name or ID %s found", idOrName)
}
// We might have found a container ID, but it's OK
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 08945c410..d86062e38 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -34,8 +34,8 @@ const (
)
var (
- // localeToLanguage maps from locale values to language tags.
- localeToLanguage = map[string]string{
+ // localeToLanguageMap maps from locale values to language tags.
+ localeToLanguageMap = map[string]string{
"": "und-u-va-posix",
"c": "und-u-va-posix",
"posix": "und-u-va-posix",
@@ -1281,6 +1281,16 @@ func (c *Container) saveSpec(spec *spec.Spec) error {
return nil
}
+// localeToLanguage translates POSIX locale strings to BCP 47 language tags.
+func localeToLanguage(locale string) string {
+ locale = strings.Replace(strings.SplitN(locale, ".", 2)[0], "_", "-", 1)
+ langString, ok := localeToLanguageMap[strings.ToLower(locale)]
+ if !ok {
+ langString = locale
+ }
+ return langString
+}
+
// Warning: precreate hooks may alter 'config' in place.
func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (extensionStageHooks map[string][]spec.Hook, err error) {
var locale string
@@ -1296,11 +1306,7 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (exten
}
}
- langString, ok := localeToLanguage[strings.ToLower(locale)]
- if !ok {
- langString = locale
- }
-
+ langString := localeToLanguage(locale)
lang, err := language.Parse(langString)
if err != nil {
logrus.Warnf("failed to parse language %q: %s", langString, err)
diff --git a/libpod/container_internal_test.go b/libpod/container_internal_test.go
index f1e2b70a7..1654af929 100644
--- a/libpod/container_internal_test.go
+++ b/libpod/container_internal_test.go
@@ -17,6 +17,54 @@ import (
// hookPath is the path to an example hook executable.
var hookPath string
+func TestLocaleToLanguage(t *testing.T) {
+ for _, testCase := range []struct {
+ locale string
+ language string
+ }{
+ {
+ locale: "",
+ language: "und-u-va-posix",
+ },
+ {
+ locale: "C",
+ language: "und-u-va-posix",
+ },
+ {
+ locale: "POSIX",
+ language: "und-u-va-posix",
+ },
+ {
+ locale: "c",
+ language: "und-u-va-posix",
+ },
+ {
+ locale: "en",
+ language: "en",
+ },
+ {
+ locale: "en_US",
+ language: "en-US",
+ },
+ {
+ locale: "en.UTF-8",
+ language: "en",
+ },
+ {
+ locale: "en_US.UTF-8",
+ language: "en-US",
+ },
+ {
+ locale: "does-not-exist",
+ language: "does-not-exist",
+ },
+ } {
+ t.Run(testCase.locale, func(t *testing.T) {
+ assert.Equal(t, testCase.language, localeToLanguage(testCase.locale))
+ })
+ }
+}
+
func TestPostDeleteHooks(t *testing.T) {
ctx := context.Background()
dir, err := ioutil.TempDir("", "libpod_test_")
diff --git a/libpod/oci.go b/libpod/oci.go
index 2cbf25699..c3b5f9af2 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -805,6 +805,12 @@ func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty
execCmd.Env = append(execCmd.Env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir))
+ if preserveFDs > 0 {
+ for fd := 3; fd < 3+preserveFDs; fd++ {
+ execCmd.ExtraFiles = append(execCmd.ExtraFiles, os.NewFile(uintptr(fd), fmt.Sprintf("fd-%d", fd)))
+ }
+ }
+
if err := execCmd.Start(); err != nil {
return nil, errors.Wrapf(err, "cannot start container %s", c.ID())
}