github.com/sevki/docker@v1.7.1/pkg/ulimit/ulimit.go (about)

     1  package ulimit
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  )
     8  
     9  // Human friendly version of Rlimit
    10  type Ulimit struct {
    11  	Name string
    12  	Hard int64
    13  	Soft int64
    14  }
    15  
    16  type Rlimit struct {
    17  	Type int    `json:"type,omitempty"`
    18  	Hard uint64 `json:"hard,omitempty"`
    19  	Soft uint64 `json:"soft,omitempty"`
    20  }
    21  
    22  const (
    23  	// magic numbers for making the syscall
    24  	// some of these are defined in the syscall package, but not all.
    25  	// Also since Windows client doesn't get access to the syscall package, need to
    26  	//	define these here
    27  	RLIMIT_AS         = 9
    28  	RLIMIT_CORE       = 4
    29  	RLIMIT_CPU        = 0
    30  	RLIMIT_DATA       = 2
    31  	RLIMIT_FSIZE      = 1
    32  	RLIMIT_LOCKS      = 10
    33  	RLIMIT_MEMLOCK    = 8
    34  	RLIMIT_MSGQUEUE   = 12
    35  	RLIMIT_NICE       = 13
    36  	RLIMIT_NOFILE     = 7
    37  	RLIMIT_NPROC      = 6
    38  	RLIMIT_RSS        = 5
    39  	RLIMIT_RTPRIO     = 14
    40  	RLIMIT_RTTIME     = 15
    41  	RLIMIT_SIGPENDING = 11
    42  	RLIMIT_STACK      = 3
    43  )
    44  
    45  var ulimitNameMapping = map[string]int{
    46  	//"as":         RLIMIT_AS, // Disbaled since this doesn't seem usable with the way Docker inits a container.
    47  	"core":       RLIMIT_CORE,
    48  	"cpu":        RLIMIT_CPU,
    49  	"data":       RLIMIT_DATA,
    50  	"fsize":      RLIMIT_FSIZE,
    51  	"locks":      RLIMIT_LOCKS,
    52  	"memlock":    RLIMIT_MEMLOCK,
    53  	"msgqueue":   RLIMIT_MSGQUEUE,
    54  	"nice":       RLIMIT_NICE,
    55  	"nofile":     RLIMIT_NOFILE,
    56  	"nproc":      RLIMIT_NPROC,
    57  	"rss":        RLIMIT_RSS,
    58  	"rtprio":     RLIMIT_RTPRIO,
    59  	"rttime":     RLIMIT_RTTIME,
    60  	"sigpending": RLIMIT_SIGPENDING,
    61  	"stack":      RLIMIT_STACK,
    62  }
    63  
    64  func Parse(val string) (*Ulimit, error) {
    65  	parts := strings.SplitN(val, "=", 2)
    66  	if len(parts) != 2 {
    67  		return nil, fmt.Errorf("invalid ulimit argument: %s", val)
    68  	}
    69  
    70  	if _, exists := ulimitNameMapping[parts[0]]; !exists {
    71  		return nil, fmt.Errorf("invalid ulimit type: %s", parts[0])
    72  	}
    73  
    74  	limitVals := strings.SplitN(parts[1], ":", 2)
    75  	if len(limitVals) > 2 {
    76  		return nil, fmt.Errorf("too many limit value arguments - %s, can only have up to two, `soft[:hard]`", parts[1])
    77  	}
    78  
    79  	soft, err := strconv.ParseInt(limitVals[0], 10, 64)
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  
    84  	hard := soft // in case no hard was set
    85  	if len(limitVals) == 2 {
    86  		hard, err = strconv.ParseInt(limitVals[1], 10, 64)
    87  	}
    88  	if soft > hard {
    89  		return nil, fmt.Errorf("ulimit soft limit must be less than or equal to hard limit: %d > %d", soft, hard)
    90  	}
    91  
    92  	return &Ulimit{Name: parts[0], Soft: soft, Hard: hard}, nil
    93  }
    94  
    95  func (u *Ulimit) GetRlimit() (*Rlimit, error) {
    96  	t, exists := ulimitNameMapping[u.Name]
    97  	if !exists {
    98  		return nil, fmt.Errorf("invalid ulimit name %s", u.Name)
    99  	}
   100  
   101  	return &Rlimit{Type: t, Soft: uint64(u.Soft), Hard: uint64(u.Hard)}, nil
   102  }
   103  
   104  func (u *Ulimit) String() string {
   105  	return fmt.Sprintf("%s=%d:%d", u.Name, u.Soft, u.Hard)
   106  }