//go:build !remote package util import ( "fmt" "strings" "github.com/containers/podman/v6/pkg/rootless" "github.com/docker/go-units" "github.com/opencontainers/runtime-spec/specs-go" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) // FormatRlimits formats the rlimits to the runtime spec format func FormatRlimits(rlimits []specs.POSIXRlimit) []specs.POSIXRlimit { formatted := make([]specs.POSIXRlimit, len(rlimits)) for i, rlimit := range rlimits { typ := strings.ToUpper(rlimit.Type) if !strings.HasPrefix(typ, "RLIMIT_") { typ = "RLIMIT_" + typ } rlimit.Type = typ formatted[i] = ClampRlimitToHost(rlimit) } return formatted } // ClampRlimitToHost translates Hard or soft limits of -1 to the current // processes Max limit func ClampRlimitToHost(u specs.POSIXRlimit) specs.POSIXRlimit { if !rootless.IsRootless() || (int64(u.Hard) != -1 && int64(u.Soft) != -1) { return u } rlimitName := strings.TrimPrefix(strings.ToLower(u.Type), "rlimit_") ul, err := units.ParseUlimit(fmt.Sprintf("%s=%d:%d", rlimitName, int64(u.Soft), int64(u.Hard))) if err != nil { logrus.Warnf("Failed to check %s ulimit %q", u.Type, err) return u } rl, err := ul.GetRlimit() if err != nil { logrus.Warnf("Failed to check %s ulimit %q", u.Type, err) return u } var rlimit unix.Rlimit if err := unix.Getrlimit(rl.Type, &rlimit); err != nil { logrus.Warnf("Failed to return %s ulimit %q", u.Type, err) return u } maxLimit := rlimitMaxToUint64(rlimit.Max) if int64(u.Hard) == -1 { u.Hard = maxLimit } if int64(u.Soft) == -1 { u.Soft = maxLimit } return u } // rlimitMaxToUint64 converts unix.Rlimit.Max to uint64. // On Linux, Max is uint64; on Darwin/BSD, Max is int64. func rlimitMaxToUint64(max any) uint64 { switch v := max.(type) { case uint64: return v case int64: return uint64(v) default: panic(fmt.Sprintf("unexpected type for rlimit.Max: %T (expected uint64 or int64)", v)) } }