diff options
Diffstat (limited to 'pkg/util')
-rw-r--r-- | pkg/util/camelcase/LICENSE.md | 20 | ||||
-rw-r--r-- | pkg/util/camelcase/README.md | 58 | ||||
-rw-r--r-- | pkg/util/camelcase/camelcase.go | 91 | ||||
-rw-r--r-- | pkg/util/utils.go | 60 | ||||
-rw-r--r-- | pkg/util/utils_linux_test.go | 29 | ||||
-rw-r--r-- | pkg/util/utils_supported.go | 4 | ||||
-rw-r--r-- | pkg/util/utils_test.go | 31 |
7 files changed, 268 insertions, 25 deletions
diff --git a/pkg/util/camelcase/LICENSE.md b/pkg/util/camelcase/LICENSE.md new file mode 100644 index 000000000..aa4a536ca --- /dev/null +++ b/pkg/util/camelcase/LICENSE.md @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2015 Fatih Arslan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/pkg/util/camelcase/README.md b/pkg/util/camelcase/README.md new file mode 100644 index 000000000..105a6ae33 --- /dev/null +++ b/pkg/util/camelcase/README.md @@ -0,0 +1,58 @@ +# CamelCase [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/fatih/camelcase) [![Build Status](http://img.shields.io/travis/fatih/camelcase.svg?style=flat-square)](https://travis-ci.org/fatih/camelcase) + +CamelCase is a Golang (Go) package to split the words of a camelcase type +string into a slice of words. It can be used to convert a camelcase word (lower +or upper case) into any type of word. + +## Splitting rules: + +1. If string is not valid UTF-8, return it without splitting as + single item array. +2. Assign all unicode characters into one of 4 sets: lower case + letters, upper case letters, numbers, and all other characters. +3. Iterate through characters of string, introducing splits + between adjacent characters that belong to different sets. +4. Iterate through array of split strings, and if a given string + is upper case: + * if subsequent string is lower case: + * move last character of upper case string to beginning of + lower case string + +## Install + +```bash +go get github.com/fatih/camelcase +``` + +## Usage and examples + +```go +splitted := camelcase.Split("GolangPackage") + +fmt.Println(splitted[0], splitted[1]) // prints: "Golang", "Package" +``` + +Both lower camel case and upper camel case are supported. For more info please +check: [http://en.wikipedia.org/wiki/CamelCase](http://en.wikipedia.org/wiki/CamelCase) + +Below are some example cases: + +``` +"" => [] +"lowercase" => ["lowercase"] +"Class" => ["Class"] +"MyClass" => ["My", "Class"] +"MyC" => ["My", "C"] +"HTML" => ["HTML"] +"PDFLoader" => ["PDF", "Loader"] +"AString" => ["A", "String"] +"SimpleXMLParser" => ["Simple", "XML", "Parser"] +"vimRPCPlugin" => ["vim", "RPC", "Plugin"] +"GL11Version" => ["GL", "11", "Version"] +"99Bottles" => ["99", "Bottles"] +"May5" => ["May", "5"] +"BFG9000" => ["BFG", "9000"] +"BöseÜberraschung" => ["Böse", "Überraschung"] +"Two spaces" => ["Two", " ", "spaces"] +"BadUTF8\xe2\xe2\xa1" => ["BadUTF8\xe2\xe2\xa1"] +``` diff --git a/pkg/util/camelcase/camelcase.go b/pkg/util/camelcase/camelcase.go new file mode 100644 index 000000000..0a82d1005 --- /dev/null +++ b/pkg/util/camelcase/camelcase.go @@ -0,0 +1,91 @@ +// Package camelcase is a micro package to split the words of a camelcase type +// string into a slice of words. +package camelcase + +import ( + "unicode" + "unicode/utf8" +) + +// Split splits the camelcase word and returns a list of words. It also +// supports digits. Both lower camel case and upper camel case are supported. +// For more info please check: http://en.wikipedia.org/wiki/CamelCase +// +// Examples +// +// "" => [""] +// "lowercase" => ["lowercase"] +// "Class" => ["Class"] +// "MyClass" => ["My", "Class"] +// "MyC" => ["My", "C"] +// "HTML" => ["HTML"] +// "PDFLoader" => ["PDF", "Loader"] +// "AString" => ["A", "String"] +// "SimpleXMLParser" => ["Simple", "XML", "Parser"] +// "vimRPCPlugin" => ["vim", "RPC", "Plugin"] +// "GL11Version" => ["GL", "11", "Version"] +// "99Bottles" => ["99", "Bottles"] +// "May5" => ["May", "5"] +// "BFG9000" => ["BFG", "9000"] +// "BöseÜberraschung" => ["Böse", "Überraschung"] +// "Two spaces" => ["Two", " ", "spaces"] +// "BadUTF8\xe2\xe2\xa1" => ["BadUTF8\xe2\xe2\xa1"] +// +// Splitting rules +// +// 1) If string is not valid UTF-8, return it without splitting as +// single item array. +// 2) Assign all unicode characters into one of 4 sets: lower case +// letters, upper case letters, numbers, and all other characters. +// 3) Iterate through characters of string, introducing splits +// between adjacent characters that belong to different sets. +// 4) Iterate through array of split strings, and if a given string +// is upper case: +// if subsequent string is lower case: +// move last character of upper case string to beginning of +// lower case string +func Split(src string) (entries []string) { + // don't split invalid utf8 + if !utf8.ValidString(src) { + return []string{src} + } + entries = []string{} + var runes [][]rune + lastClass := 0 + class := 0 + // split into fields based on class of unicode character + for _, r := range src { + switch { + case unicode.IsLower(r): + class = 1 + case unicode.IsUpper(r): + class = 2 + case unicode.IsDigit(r): + class = 3 + default: + class = 4 + } + if class == lastClass { + runes[len(runes)-1] = append(runes[len(runes)-1], r) + } else { + runes = append(runes, []rune{r}) + } + lastClass = class + } + // handle upper case -> lower case sequences, e.g. + // "PDFL", "oader" -> "PDF", "Loader" + for i := 0; i < len(runes)-1; i++ { + if unicode.IsUpper(runes[i][0]) && unicode.IsLower(runes[i+1][0]) { + runes[i+1] = append([]rune{runes[i][len(runes[i])-1]}, runes[i+1]...) + runes[i] = runes[i][:len(runes[i])-1] + } + } + // construct []string from results + for _, s := range runes { + if len(s) > 0 { + entries = append(entries, string(s)) + } + } + + return entries +} diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 6aa3c221e..0c055745d 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -18,9 +18,9 @@ import ( "github.com/containers/libpod/pkg/errorhandling" "github.com/containers/libpod/pkg/namespaces" "github.com/containers/libpod/pkg/rootless" + "github.com/containers/libpod/pkg/signal" "github.com/containers/storage" "github.com/containers/storage/pkg/idtools" - "github.com/docker/docker/pkg/signal" v1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -309,15 +309,15 @@ func ParseSignal(rawSignal string) (syscall.Signal, error) { // Strip off leading dash, to allow -1 or -HUP basename := strings.TrimPrefix(rawSignal, "-") - signal, err := signal.ParseSignal(basename) + sig, err := signal.ParseSignal(basename) if err != nil { return -1, err } // 64 is SIGRTMAX; wish we could get this from a standard Go library - if signal < 1 || signal > 64 { + if sig < 1 || sig > 64 { return -1, errors.Errorf("valid signals are 1 through 64") } - return signal, nil + return sig, nil } // ParseIDMapping takes idmappings and subuid and subgid maps and returns a storage mapping @@ -600,3 +600,55 @@ func HomeDir() (string, error) { } return home, nil } + +func Tmpdir() string { + tmpdir := os.Getenv("TMPDIR") + if tmpdir == "" { + tmpdir = "/var/tmp" + } + + return tmpdir +} + +// ValidateSysctls validates a list of sysctl and returns it. +func ValidateSysctls(strSlice []string) (map[string]string, error) { + sysctl := make(map[string]string) + validSysctlMap := map[string]bool{ + "kernel.msgmax": true, + "kernel.msgmnb": true, + "kernel.msgmni": true, + "kernel.sem": true, + "kernel.shmall": true, + "kernel.shmmax": true, + "kernel.shmmni": true, + "kernel.shm_rmid_forced": true, + } + validSysctlPrefixes := []string{ + "net.", + "fs.mqueue.", + } + + for _, val := range strSlice { + foundMatch := false + arr := strings.Split(val, "=") + if len(arr) < 2 { + return nil, errors.Errorf("%s is invalid, sysctl values must be in the form of KEY=VALUE", val) + } + if validSysctlMap[arr[0]] { + sysctl[arr[0]] = arr[1] + continue + } + + for _, prefix := range validSysctlPrefixes { + if strings.HasPrefix(arr[0], prefix) { + sysctl[arr[0]] = arr[1] + foundMatch = true + break + } + } + if !foundMatch { + return nil, errors.Errorf("sysctl '%s' is not whitelisted", arr[0]) + } + } + return sysctl, nil +} diff --git a/pkg/util/utils_linux_test.go b/pkg/util/utils_linux_test.go new file mode 100644 index 000000000..38e6dbef9 --- /dev/null +++ b/pkg/util/utils_linux_test.go @@ -0,0 +1,29 @@ +package util + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGetImageConfigStopSignal(t *testing.T) { + // Linux-only beause parsing signal names is not supported on non-Linux systems by + // pkg/signal. + stopSignalValidInt, err := GetImageConfig([]string{"STOPSIGNAL 9"}) + require.Nil(t, err) + assert.Equal(t, stopSignalValidInt.StopSignal, "9") + + stopSignalValidString, err := GetImageConfig([]string{"STOPSIGNAL SIGKILL"}) + require.Nil(t, err) + assert.Equal(t, stopSignalValidString.StopSignal, "9") + + _, err = GetImageConfig([]string{"STOPSIGNAL 0"}) + assert.NotNil(t, err) + + _, err = GetImageConfig([]string{"STOPSIGNAL garbage"}) + assert.NotNil(t, err) + + _, err = GetImageConfig([]string{"STOPSIGNAL "}) + assert.NotNil(t, err) +} diff --git a/pkg/util/utils_supported.go b/pkg/util/utils_supported.go index 0b78a8150..c6aed9943 100644 --- a/pkg/util/utils_supported.go +++ b/pkg/util/utils_supported.go @@ -33,7 +33,7 @@ func GetRuntimeDir() (string, error) { logrus.Debugf("unable to make temp dir %s", tmpDir) } st, err := os.Stat(tmpDir) - if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 { + if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && (st.Mode().Perm()&0700 == 0700) { runtimeDir = tmpDir } } @@ -43,7 +43,7 @@ func GetRuntimeDir() (string, error) { logrus.Debugf("unable to make temp dir %s", tmpDir) } st, err := os.Stat(tmpDir) - if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 { + if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && (st.Mode().Perm()&0700 == 0700) { runtimeDir = tmpDir } } diff --git a/pkg/util/utils_test.go b/pkg/util/utils_test.go index f4b03599d..a9b37844e 100644 --- a/pkg/util/utils_test.go +++ b/pkg/util/utils_test.go @@ -219,25 +219,6 @@ func TestGetImageConfigLabel(t *testing.T) { assert.NotNil(t, err) } -func TestGetImageConfigStopSignal(t *testing.T) { - stopSignalValidInt, err := GetImageConfig([]string{"STOPSIGNAL 9"}) - require.Nil(t, err) - assert.Equal(t, stopSignalValidInt.StopSignal, "9") - - stopSignalValidString, err := GetImageConfig([]string{"STOPSIGNAL SIGKILL"}) - require.Nil(t, err) - assert.Equal(t, stopSignalValidString.StopSignal, "9") - - _, err = GetImageConfig([]string{"STOPSIGNAL 0"}) - assert.NotNil(t, err) - - _, err = GetImageConfig([]string{"STOPSIGNAL garbage"}) - assert.NotNil(t, err) - - _, err = GetImageConfig([]string{"STOPSIGNAL "}) - assert.NotNil(t, err) -} - func TestGetImageConfigOnBuild(t *testing.T) { onBuildOne, err := GetImageConfig([]string{"ONBUILD ADD /testdir1"}) require.Nil(t, err) @@ -264,3 +245,15 @@ func TestGetImageConfigMisc(t *testing.T) { _, err = GetImageConfig([]string{"BADINST testvalue"}) assert.NotNil(t, err) } + +func TestValidateSysctls(t *testing.T) { + strSlice := []string{"net.core.test1=4", "kernel.msgmax=2"} + result, _ := ValidateSysctls(strSlice) + assert.Equal(t, result["net.core.test1"], "4") +} + +func TestValidateSysctlBadSysctl(t *testing.T) { + strSlice := []string{"BLAU=BLUE", "GELB^YELLOW"} + _, err := ValidateSysctls(strSlice) + assert.Error(t, err) +} |