From c36cf9511a29cea032c54c6dfe4c4f3434a86945 Mon Sep 17 00:00:00 2001 From: yo Date: Mon, 20 Dec 2021 22:10:38 +0100 Subject: [PATCH] Add sort support, can use every field --- cmd/list.go | 44 +++ cmd/root.go | 10 +- cmd/struct.go | 306 ++++++++++++++++ cmd/utils.go | 942 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1299 insertions(+), 3 deletions(-) diff --git a/cmd/list.go b/cmd/list.go index fc713c5..85a493a 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -357,6 +357,50 @@ func ListJails(args []string, display bool) { jails = js } + /************************************************************************************ + / Sort jails + / We support 3 sort criteria max + /***********************************************************************************/ + if len(gSortFields) > 0 { + js := initSortStruct() + + // The way we manage criteria quantity is not very elegant... + var fct1, fct2, fct3 reflect.Value + for i, c := range strings.Split(gSortFields, ",") { + var fctName string + if strings.HasPrefix(c, "-") { + fctName = fmt.Sprintf("%sDec", strings.Replace(c, "-", "", 1)) + } else { // Par defaut (pas de prefix +/-) on considere un tri incremental + fctName = fmt.Sprintf("%sInc", strings.Replace(c, "+", "", 1)) + } + + // Get function by its name + fct, _, err := getStructFieldValue(js, fctName) + if err != nil { + fieldName := strings.Replace(strings.Replace(c, "-", "", 1), "+", "", 1) + fmt.Printf("ERROR getting JailSort struct field %s. Please check the field name: %s\n", fctName, fieldName) + return + } + switch i+1 { + case 1: fct1 = fct + case 2: fct2 = fct + case 3: fct3 = fct + } + } + + switch len(strings.Split(gSortFields, ",")) { + case 1: + OrderedBy(fct1.Interface().(lessFunc)).Sort(jails) + case 2: + OrderedBy(fct1.Interface().(lessFunc), fct2.Interface().(lessFunc)).Sort(jails) + case 3: + OrderedBy(fct1.Interface().(lessFunc), fct2.Interface().(lessFunc), fct3.Interface().(lessFunc)).Sort(jails) + } + } + + /************************************************************************************ + / Finally, display jails + /***********************************************************************************/ if display { displayStructFields(jails, fields) } diff --git a/cmd/root.go b/cmd/root.go index 9d2987e..425e531 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -3,14 +3,14 @@ package cmd import ( "os" "fmt" -// "strings" + "strings" "github.com/spf13/cobra" "github.com/spf13/viper" ) const ( - version = "0.001" + version = "0.02" ) var ( @@ -81,7 +81,7 @@ func init() { listCmd.PersistentFlags().StringVarP(&gDisplayColumns, "outcol", "o", "JID,Name,Config.Release,Config.Ip4_addr,Running", "Show these columns in output") listCmd.PersistentFlags().BoolVarP(&gNoLineSep, "nolinesep", "l", false, "Do not display line separator between jails") listCmd.PersistentFlags().StringVarP(&gFilterJails, "filter", "f", "none", "Only display jails with these values. Ex: \"gocage list -f Config.Boot=1\" will only list started on boot jails") - listCmd.PersistentFlags().StringVarP(&gSortFields, "sort", "s", "none", "Display jails sorted by field values. Ex: \"gocage list -s Config.Priority\" will sort jails by their start priority. NOT IMPLEMENTED YET") + listCmd.PersistentFlags().StringVarP(&gSortFields, "sort", "s", "none", "Display jails sorted by field values. Ex: \"gocage list -s +Name,-Config.Priority\" will sort jails by their decreasing name, then increasing start priority. 3 critera max supported.") // Now declare commands rootCmd.AddCommand(versionCmd) @@ -124,6 +124,10 @@ func initConfig() { if listCmd.Flags().Lookup("sort") != nil && false == listCmd.Flags().Lookup("sort").Changed { gSortFields = viper.GetString("sort") } + if len(strings.Split(gSortFields, ",")) > 3 { + fmt.Printf("More than 3 sort criteria, this is not supported!\n") + os.Exit(1) + } } func Execute() { diff --git a/cmd/struct.go b/cmd/struct.go index 4299da7..9815048 100644 --- a/cmd/struct.go +++ b/cmd/struct.go @@ -1,5 +1,7 @@ package cmd + +// To allow sorting, just duplicate fields in JailSort below type Jail struct { Name string InternalName string @@ -15,6 +17,11 @@ type Jail struct { // iocage struct as stored in config.json // CONFIG_VERSION = 27 +// +// Fields in this struct are acquired by their name using reflection +// So these char are forbidden for field name: -+. +// +// To allow sorting, just duplicate fields in JailConfigSort below type JailConfig struct { Config_version string `json:"CONFIG_VERSION"` Allow_chflags int `json:"allow_chflags"` @@ -155,3 +162,302 @@ type JailConfig struct { Writeiops string `json:"writeiops"` } +// This struct hold "sort by jail fields" functions +type lessFunc func(j1 *Jail, j2 *Jail) bool + +// Fields in this struct are acquired by their name using reflection +// So these char are forbidden for field name: -+. +// +type JailSort struct { + NameInc lessFunc + NameDec lessFunc + InternalNameInc lessFunc + InternalNameDec lessFunc + JIDInc lessFunc + JIDDec lessFunc + RootPathInc lessFunc + RootPathDec lessFunc + ConfigPathInc lessFunc + ConfigPathDec lessFunc + RunningInc lessFunc + RunningDec lessFunc + ZpoolInc lessFunc + ZpoolDec lessFunc + Config JailConfigSort +} + + +type JailConfigSort struct { + Config_versionInc lessFunc + Config_versionDec lessFunc + Allow_chflagsInc lessFunc + Allow_chflagsDec lessFunc + Allow_mlockInc lessFunc + Allow_mlockDec lessFunc + Allow_mountInc lessFunc + Allow_mountDec lessFunc + Allow_mount_devfsInc lessFunc + Allow_mount_devfsDec lessFunc + Allow_mount_fusefsInc lessFunc + Allow_mount_fusefsDec lessFunc + Allow_mount_nullfsInc lessFunc + Allow_mount_nullfsDec lessFunc + Allow_mount_procfsInc lessFunc + Allow_mount_procfsDec lessFunc + Allow_mount_tmpfsInc lessFunc + Allow_mount_tmpfsDec lessFunc + Allow_mount_zfsInc lessFunc + Allow_mount_zfsDec lessFunc + Allow_quotasInc lessFunc + Allow_quotasDec lessFunc + Allow_raw_socketsInc lessFunc + Allow_raw_socketsDec lessFunc + Allow_set_hostnameInc lessFunc + Allow_set_hostnameDec lessFunc + Allow_socket_afInc lessFunc + Allow_socket_afDec lessFunc + Allow_sysvipcInc lessFunc + Allow_sysvipcDec lessFunc + Allow_tunInc lessFunc + Allow_tunDec lessFunc + Allow_vmmInc lessFunc + Allow_vmmDec lessFunc + Assign_localhostInc lessFunc + Assign_localhostDec lessFunc + AvailableInc lessFunc + AvailableDec lessFunc + BasejailInc lessFunc + BasejailDec lessFunc + BootInc lessFunc + BootDec lessFunc + BpfInc lessFunc + BpfDec lessFunc + Children_maxInc lessFunc + Children_maxDec lessFunc + Cloned_releaseInc lessFunc + Cloned_releaseDec lessFunc + CommentInc lessFunc + CommentDec lessFunc + CompressionInc lessFunc + CompressionDec lessFunc + CompressratioInc lessFunc + CompressratioDec lessFunc + CoredumpsizeInc lessFunc + CoredumpsizeDec lessFunc + CountInc lessFunc + CountDec lessFunc + CpusetInc lessFunc + CpusetDec lessFunc + CputimeInc lessFunc + CputimeDec lessFunc + DatasizeInc lessFunc + DatasizeDec lessFunc + DedupInc lessFunc + DedupDec lessFunc + DefaultrouterInc lessFunc + DefaultrouterDec lessFunc + Defaultrouter6Inc lessFunc + Defaultrouter6Dec lessFunc + DependsInc lessFunc + DependsDec lessFunc + Devfs_rulesetInc lessFunc + Devfs_rulesetDec lessFunc + DhcpInc lessFunc + DhcpDec lessFunc + Enforce_statfsInc lessFunc + Enforce_statfsDec lessFunc + Exec_cleanInc lessFunc + Exec_cleanDec lessFunc + Exec_createdInc lessFunc + Exec_createdDec lessFunc + Exec_fibInc lessFunc + Exec_fibDec lessFunc + Exec_jail_userInc lessFunc + Exec_jail_userDec lessFunc + Exec_poststartInc lessFunc + Exec_poststartDec lessFunc + Exec_poststopInc lessFunc + Exec_poststopDec lessFunc + Exec_prestartInc lessFunc + Exec_prestartDec lessFunc + Exec_prestopInc lessFunc + Exec_prestopDec lessFunc + Exec_startInc lessFunc + Exec_startDec lessFunc + Exec_stopInc lessFunc + Exec_stopDec lessFunc + Exec_system_jail_userInc lessFunc + Exec_system_jail_userDec lessFunc + Exec_system_userInc lessFunc + Exec_system_userDec lessFunc + Exec_timeoutInc lessFunc + Exec_timeoutDec lessFunc + Host_domainnameInc lessFunc + Host_domainnameDec lessFunc + Host_hostnameInc lessFunc + Host_hostnameDec lessFunc + Host_hostuuidInc lessFunc + Host_hostuuidDec lessFunc + Host_timeInc lessFunc + Host_timeDec lessFunc + HostidInc lessFunc + HostidDec lessFunc + Hostid_strict_checkInc lessFunc + Hostid_strict_checkDec lessFunc + InterfacesInc lessFunc + InterfacesDec lessFunc + Ip4Inc lessFunc + Ip4Dec lessFunc + Ip4_addrInc lessFunc + Ip4_addrDec lessFunc + Ip4_saddrselInc lessFunc + Ip4_saddrselDec lessFunc + Ip6Inc lessFunc + Ip6Dec lessFunc + Ip6_addrInc lessFunc + Ip6_addrDec lessFunc + Ip6_saddrselInc lessFunc + Ip6_saddrselDec lessFunc + Ip_hostnameInc lessFunc + Ip_hostnameDec lessFunc + Jail_zfsInc lessFunc + Jail_zfsDec lessFunc + Jail_zfs_datasetInc lessFunc + Jail_zfs_datasetDec lessFunc + Jail_zfs_mountpointInc lessFunc + Jail_zfs_mountpointDec lessFunc + Last_startedInc lessFunc + Last_startedDec lessFunc + Localhost_ipInc lessFunc + Localhost_ipDec lessFunc + Login_flagsInc lessFunc + Login_flagsDec lessFunc + Mac_prefixInc lessFunc + Mac_prefixDec lessFunc + MaxprocInc lessFunc + MaxprocDec lessFunc + MemorylockedInc lessFunc + MemorylockedDec lessFunc + MemoryuseInc lessFunc + MemoryuseDec lessFunc + Min_dyn_devfs_rulesetInc lessFunc + Min_dyn_devfs_rulesetDec lessFunc + Mount_devfsInc lessFunc + Mount_devfsDec lessFunc + Mount_fdescfsInc lessFunc + Mount_fdescfsDec lessFunc + Mount_linprocfsInc lessFunc + Mount_linprocfsDec lessFunc + Mount_procfsInc lessFunc + Mount_procfsDec lessFunc + MountpointInc lessFunc + MountpointDec lessFunc + MsgqqueuedInc lessFunc + MsgqqueuedDec lessFunc + MsgqsizeInc lessFunc + MsgqsizeDec lessFunc + NatInc lessFunc + NatDec lessFunc + Nat_backendInc lessFunc + Nat_backendDec lessFunc + Nat_forwardsInc lessFunc + Nat_forwardsDec lessFunc + Nat_interfaceInc lessFunc + Nat_interfaceDec lessFunc + Nat_prefixInc lessFunc + Nat_prefixDec lessFunc + NmsgqInc lessFunc + NmsgqDec lessFunc + NotesInc lessFunc + NotesDec lessFunc + NsemInc lessFunc + NsemDec lessFunc + NsemopInc lessFunc + NsemopDec lessFunc + NshmInc lessFunc + NshmDec lessFunc + NthrInc lessFunc + NthrDec lessFunc + OpenfilesInc lessFunc + OpenfilesDec lessFunc + OriginInc lessFunc + OriginDec lessFunc + OwnerInc lessFunc + OwnerDec lessFunc + PcpuInc lessFunc + PcpuDec lessFunc + Plugin_nameInc lessFunc + Plugin_nameDec lessFunc + Plugin_repositoryInc lessFunc + Plugin_repositoryDec lessFunc + PriorityInc lessFunc + PriorityDec lessFunc + PseudoterminalsInc lessFunc + PseudoterminalsDec lessFunc + QuotaInc lessFunc + QuotaDec lessFunc + ReadbpsInc lessFunc + ReadbpsDec lessFunc + ReadiopsInc lessFunc + ReadiopsDec lessFunc + ReleaseInc lessFunc + ReleaseDec lessFunc + ReservationInc lessFunc + ReservationDec lessFunc + ResolverInc lessFunc + ResolverDec lessFunc + RlimitsInc lessFunc + RlimitsDec lessFunc + RtsoldInc lessFunc + RtsoldDec lessFunc + SecurelevelInc lessFunc + SecurelevelDec lessFunc + ShmsizeInc lessFunc + ShmsizeDec lessFunc + StacksizeInc lessFunc + StacksizeDec lessFunc + Stop_timeoutInc lessFunc + Stop_timeoutDec lessFunc + SwapuseInc lessFunc + SwapuseDec lessFunc + Sync_stateInc lessFunc + Sync_stateDec lessFunc + Sync_targetInc lessFunc + Sync_targetDec lessFunc + Sync_tgt_zpoolInc lessFunc + Sync_tgt_zpoolDec lessFunc + SysvmsgInc lessFunc + SysvmsgDec lessFunc + SysvsemInc lessFunc + SysvsemDec lessFunc + SysvshmInc lessFunc + SysvshmDec lessFunc + TemplateInc lessFunc + TemplateDec lessFunc + JailtypeInc lessFunc + JailtypeDec lessFunc + UsedInc lessFunc + UsedDec lessFunc + VmemoryuseInc lessFunc + VmemoryuseDec lessFunc + VnetInc lessFunc + VnetDec lessFunc + Vnet0_macInc lessFunc + Vnet0_macDec lessFunc + Vnet1_macInc lessFunc + Vnet1_macDec lessFunc + Vnet2_macInc lessFunc + Vnet2_macDec lessFunc + Vnet3_macInc lessFunc + Vnet3_macDec lessFunc + Vnet_default_interfaceInc lessFunc + Vnet_default_interfaceDec lessFunc + Vnet_interfacesInc lessFunc + Vnet_interfacesDec lessFunc + WallclockInc lessFunc + WallclockDec lessFunc + WritebpsInc lessFunc + WritebpsDec lessFunc + WriteiopsInc lessFunc + WriteiopsDec lessFunc +} diff --git a/cmd/utils.go b/cmd/utils.go index 8f86f36..01f1a88 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -1,10 +1,16 @@ package cmd import ( + "sort" "os/exec" "strings" ) +/***************************************************************************** +* +* Command execution +* +*****************************************************************************/ func executeCommand(cmdline string) (string, error) { var cmd []string var out []byte @@ -51,3 +57,939 @@ func executeCommandInJail(jail *Jail, cmdline string) (string, error) { return string(out), err } + +/***************************************************************************** +* +* Sorting jails +* +*****************************************************************************/ + +// already defined in cmd/struct.go +//type lessFunc func(j1 *Jail, j2 *Jail) bool +func initSortStruct() JailSort { + jcs := JailConfigSort{ + Allow_chflagsInc: func(j1, j2 *Jail) bool { + return j1.Config.Allow_chflags < j2.Config.Allow_chflags + }, + Allow_chflagsDec: func(j1, j2 *Jail) bool { + return j1.Config.Allow_chflags > j2.Config.Allow_chflags + }, + Allow_mlockInc: func(j1, j2 *Jail) bool { + return j1.Config.Allow_mlock < j2.Config.Allow_mlock + }, + Allow_mlockDec: func(j1, j2 *Jail) bool { + return j1.Config.Allow_mlock > j2.Config.Allow_mlock + }, + Allow_mountInc: func(j1, j2 *Jail) bool { + return j1.Config.Allow_mount < j2.Config.Allow_mount + }, + Allow_mountDec: func(j1, j2 *Jail) bool { + return j1.Config.Allow_mount > j2.Config.Allow_mount + }, + Allow_mount_devfsInc: func(j1, j2 *Jail) bool { + return j1.Config.Allow_mount_devfs < j2.Config.Allow_mount_devfs + }, + Allow_mount_devfsDec: func(j1, j2 *Jail) bool { + return j1.Config.Allow_mount_devfs > j2.Config.Allow_mount_devfs + }, + Allow_mount_fusefsInc: func(j1, j2 *Jail) bool { + return j1.Config.Allow_mount_fusefs < j2.Config.Allow_mount_fusefs + }, + Allow_mount_fusefsDec: func(j1, j2 *Jail) bool { + return j1.Config.Allow_mount_fusefs > j2.Config.Allow_mount_fusefs + }, + Allow_mount_nullfsInc: func(j1, j2 *Jail) bool { + return j1.Config.Allow_mount_nullfs < j2.Config.Allow_mount_nullfs + }, + Allow_mount_nullfsDec: func(j1, j2 *Jail) bool { + return j1.Config.Allow_mount_nullfs > j2.Config.Allow_mount_nullfs + }, + Allow_mount_procfsInc: func(j1, j2 *Jail) bool { + return j1.Config.Allow_mount_procfs < j2.Config.Allow_mount_procfs + }, + Allow_mount_procfsDec: func(j1, j2 *Jail) bool { + return j1.Config.Allow_mount_procfs > j2.Config.Allow_mount_procfs + }, + Allow_mount_tmpfsInc: func(j1, j2 *Jail) bool { + return j1.Config.Allow_mount_tmpfs < j2.Config.Allow_mount_tmpfs + }, + Allow_mount_tmpfsDec: func(j1, j2 *Jail) bool { + return j1.Config.Allow_mount_tmpfs > j2.Config.Allow_mount_tmpfs + }, + Allow_mount_zfsInc: func(j1, j2 *Jail) bool { + return j1.Config.Allow_mount_zfs < j2.Config.Allow_mount_zfs + }, + Allow_mount_zfsDec: func(j1, j2 *Jail) bool { + return j1.Config.Allow_mount_zfs > j2.Config.Allow_mount_zfs + }, + Allow_quotasInc: func(j1, j2 *Jail) bool { + return j1.Config.Allow_quotas < j2.Config.Allow_quotas + }, + Allow_quotasDec: func(j1, j2 *Jail) bool { + return j1.Config.Allow_quotas > j2.Config.Allow_quotas + }, + Allow_raw_socketsInc: func(j1, j2 *Jail) bool { + return j1.Config.Allow_raw_sockets < j2.Config.Allow_raw_sockets + }, + Allow_raw_socketsDec: func(j1, j2 *Jail) bool { + return j1.Config.Allow_raw_sockets > j2.Config.Allow_raw_sockets + }, + Allow_set_hostnameInc: func(j1, j2 *Jail) bool { + return j1.Config.Allow_set_hostname < j2.Config.Allow_set_hostname + }, + Allow_set_hostnameDec: func(j1, j2 *Jail) bool { + return j1.Config.Allow_set_hostname > j2.Config.Allow_set_hostname + }, + Allow_socket_afInc: func(j1, j2 *Jail) bool { + return j1.Config.Allow_socket_af < j2.Config.Allow_socket_af + }, + Allow_socket_afDec: func(j1, j2 *Jail) bool { + return j1.Config.Allow_socket_af > j2.Config.Allow_socket_af + }, + Allow_sysvipcInc: func(j1, j2 *Jail) bool { + return j1.Config.Allow_sysvipc < j2.Config.Allow_sysvipc + }, + Allow_sysvipcDec: func(j1, j2 *Jail) bool { + return j1.Config.Allow_sysvipc > j2.Config.Allow_sysvipc + }, + Allow_tunInc: func(j1, j2 *Jail) bool { + return j1.Config.Allow_tun < j2.Config.Allow_tun + }, + Allow_tunDec: func(j1, j2 *Jail) bool { + return j1.Config.Allow_tun > j2.Config.Allow_tun + }, + Allow_vmmInc: func(j1, j2 *Jail) bool { + return j1.Config.Allow_vmm < j2.Config.Allow_vmm + }, + Allow_vmmDec: func(j1, j2 *Jail) bool { + return j1.Config.Allow_vmm > j2.Config.Allow_vmm + }, + Assign_localhostInc: func(j1, j2 *Jail) bool { + return j1.Config.Assign_localhost < j2.Config.Assign_localhost + }, + Assign_localhostDec: func(j1, j2 *Jail) bool { + return j1.Config.Assign_localhost > j2.Config.Assign_localhost + }, + AvailableInc: func(j1, j2 *Jail) bool { + return j1.Config.Available < j2.Config.Available + }, + AvailableDec: func(j1, j2 *Jail) bool { + return j1.Config.Available > j2.Config.Available + }, + BasejailInc: func(j1, j2 *Jail) bool { + return j1.Config.Basejail < j2.Config.Basejail + }, + BasejailDec: func(j1, j2 *Jail) bool { + return j1.Config.Basejail > j2.Config.Basejail + }, + BootInc: func(j1, j2 *Jail) bool { + return j1.Config.Boot < j2.Config.Boot + }, + BootDec: func(j1, j2 *Jail) bool { + return j1.Config.Boot > j2.Config.Boot + }, + BpfInc: func(j1, j2 *Jail) bool { + return j1.Config.Bpf < j2.Config.Bpf + }, + BpfDec: func(j1, j2 *Jail) bool { + return j1.Config.Bpf > j2.Config.Bpf + }, + Children_maxInc: func(j1, j2 *Jail) bool { + return j1.Config.Children_max < j2.Config.Children_max + }, + Children_maxDec: func(j1, j2 *Jail) bool { + return j1.Config.Children_max > j2.Config.Children_max + }, + Cloned_releaseInc: func(j1, j2 *Jail) bool { + return j1.Config.Cloned_release < j2.Config.Cloned_release + }, + Cloned_releaseDec: func(j1, j2 *Jail) bool { + return j1.Config.Cloned_release > j2.Config.Cloned_release + }, + CommentInc: func(j1, j2 *Jail) bool { + return j1.Config.Comment < j2.Config.Comment + }, + CommentDec: func(j1, j2 *Jail) bool { + return j1.Config.Comment > j2.Config.Comment + }, + CompressionInc: func(j1, j2 *Jail) bool { + return j1.Config.Compression < j2.Config.Compression + }, + CompressionDec: func(j1, j2 *Jail) bool { + return j1.Config.Compression > j2.Config.Compression + }, + CompressratioInc: func(j1, j2 *Jail) bool { + return j1.Config.Compressratio < j2.Config.Compressratio + }, + CompressratioDec: func(j1, j2 *Jail) bool { + return j1.Config.Compressratio > j2.Config.Compressratio + }, + Config_versionInc: func(j1, j2 *Jail) bool { + return j1.Config.Config_version < j2.Config.Config_version + }, + Config_versionDec: func(j1, j2 *Jail) bool { + return j1.Config.Config_version > j2.Config.Config_version + }, + CoredumpsizeInc: func(j1, j2 *Jail) bool { + return j1.Config.Coredumpsize < j2.Config.Coredumpsize + }, + CoredumpsizeDec: func(j1, j2 *Jail) bool { + return j1.Config.Coredumpsize > j2.Config.Coredumpsize + }, + CountInc: func(j1, j2 *Jail) bool { + return j1.Config.Count < j2.Config.Count + }, + CountDec: func(j1, j2 *Jail) bool { + return j1.Config.Count > j2.Config.Count + }, + CpusetInc: func(j1, j2 *Jail) bool { + return j1.Config.Cpuset < j2.Config.Cpuset + }, + CpusetDec: func(j1, j2 *Jail) bool { + return j1.Config.Cpuset > j2.Config.Cpuset + }, + CputimeInc: func(j1, j2 *Jail) bool { + return j1.Config.Cputime < j2.Config.Cputime + }, + CputimeDec: func(j1, j2 *Jail) bool { + return j1.Config.Cputime > j2.Config.Cputime + }, + DatasizeInc: func(j1, j2 *Jail) bool { + return j1.Config.Datasize < j2.Config.Datasize + }, + DatasizeDec: func(j1, j2 *Jail) bool { + return j1.Config.Datasize > j2.Config.Datasize + }, + DedupInc: func(j1, j2 *Jail) bool { + return j1.Config.Dedup < j2.Config.Dedup + }, + DedupDec: func(j1, j2 *Jail) bool { + return j1.Config.Dedup > j2.Config.Dedup + }, + DefaultrouterInc: func(j1, j2 *Jail) bool { + return j1.Config.Defaultrouter < j2.Config.Defaultrouter + }, + DefaultrouterDec: func(j1, j2 *Jail) bool { + return j1.Config.Defaultrouter > j2.Config.Defaultrouter + }, + Defaultrouter6Inc: func(j1, j2 *Jail) bool { + return j1.Config.Defaultrouter6 < j2.Config.Defaultrouter6 + }, + Defaultrouter6Dec: func(j1, j2 *Jail) bool { + return j1.Config.Defaultrouter6 > j2.Config.Defaultrouter6 + }, + DependsInc: func(j1, j2 *Jail) bool { + return j1.Config.Depends < j2.Config.Depends + }, + DependsDec: func(j1, j2 *Jail) bool { + return j1.Config.Depends > j2.Config.Depends + }, + Devfs_rulesetInc: func(j1, j2 *Jail) bool { + return j1.Config.Devfs_ruleset < j2.Config.Devfs_ruleset + }, + Devfs_rulesetDec: func(j1, j2 *Jail) bool { + return j1.Config.Devfs_ruleset > j2.Config.Devfs_ruleset + }, + DhcpInc: func(j1, j2 *Jail) bool { + return j1.Config.Dhcp < j2.Config.Dhcp + }, + DhcpDec: func(j1, j2 *Jail) bool { + return j1.Config.Dhcp > j2.Config.Dhcp + }, + Enforce_statfsInc: func(j1, j2 *Jail) bool { + return j1.Config.Enforce_statfs < j2.Config.Enforce_statfs + }, + Enforce_statfsDec: func(j1, j2 *Jail) bool { + return j1.Config.Enforce_statfs > j2.Config.Enforce_statfs + }, + Exec_cleanInc: func(j1, j2 *Jail) bool { + return j1.Config.Exec_clean < j2.Config.Exec_clean + }, + Exec_cleanDec: func(j1, j2 *Jail) bool { + return j1.Config.Exec_clean > j2.Config.Exec_clean + }, + Exec_createdInc: func(j1, j2 *Jail) bool { + return j1.Config.Exec_created < j2.Config.Exec_created + }, + Exec_createdDec: func(j1, j2 *Jail) bool { + return j1.Config.Exec_created > j2.Config.Exec_created + }, + Exec_fibInc: func(j1, j2 *Jail) bool { + return j1.Config.Exec_fib < j2.Config.Exec_fib + }, + Exec_fibDec: func(j1, j2 *Jail) bool { + return j1.Config.Exec_fib > j2.Config.Exec_fib + }, + Exec_jail_userInc: func(j1, j2 *Jail) bool { + return j1.Config.Exec_jail_user < j2.Config.Exec_jail_user + }, + Exec_jail_userDec: func(j1, j2 *Jail) bool { + return j1.Config.Exec_jail_user > j2.Config.Exec_jail_user + }, + Exec_poststartInc: func(j1, j2 *Jail) bool { + return j1.Config.Exec_poststart < j2.Config.Exec_poststart + }, + Exec_poststartDec: func(j1, j2 *Jail) bool { + return j1.Config.Exec_poststart > j2.Config.Exec_poststart + }, + Exec_poststopInc: func(j1, j2 *Jail) bool { + return j1.Config.Exec_poststop < j2.Config.Exec_poststop + }, + Exec_poststopDec: func(j1, j2 *Jail) bool { + return j1.Config.Exec_poststop > j2.Config.Exec_poststop + }, + Exec_prestartInc: func(j1, j2 *Jail) bool { + return j1.Config.Exec_prestart < j2.Config.Exec_prestart + }, + Exec_prestartDec: func(j1, j2 *Jail) bool { + return j1.Config.Exec_prestart > j2.Config.Exec_prestart + }, + Exec_prestopInc: func(j1, j2 *Jail) bool { + return j1.Config.Exec_prestop < j2.Config.Exec_prestop + }, + Exec_prestopDec: func(j1, j2 *Jail) bool { + return j1.Config.Exec_prestop > j2.Config.Exec_prestop + }, + Exec_startInc: func(j1, j2 *Jail) bool { + return j1.Config.Exec_start < j2.Config.Exec_start + }, + Exec_startDec: func(j1, j2 *Jail) bool { + return j1.Config.Exec_start > j2.Config.Exec_start + }, + Exec_stopInc: func(j1, j2 *Jail) bool { + return j1.Config.Exec_stop < j2.Config.Exec_stop + }, + Exec_stopDec: func(j1, j2 *Jail) bool { + return j1.Config.Exec_stop > j2.Config.Exec_stop + }, + Exec_system_jail_userInc: func(j1, j2 *Jail) bool { + return j1.Config.Exec_system_jail_user < j2.Config.Exec_system_jail_user + }, + Exec_system_jail_userDec: func(j1, j2 *Jail) bool { + return j1.Config.Exec_system_jail_user > j2.Config.Exec_system_jail_user + }, + Exec_system_userInc: func(j1, j2 *Jail) bool { + return j1.Config.Exec_system_user < j2.Config.Exec_system_user + }, + Exec_system_userDec: func(j1, j2 *Jail) bool { + return j1.Config.Exec_system_user > j2.Config.Exec_system_user + }, + Exec_timeoutInc: func(j1, j2 *Jail) bool { + return j1.Config.Exec_timeout < j2.Config.Exec_timeout + }, + Exec_timeoutDec: func(j1, j2 *Jail) bool { + return j1.Config.Exec_timeout > j2.Config.Exec_timeout + }, + Host_domainnameInc: func(j1, j2 *Jail) bool { + return j1.Config.Host_domainname < j2.Config.Host_domainname + }, + Host_domainnameDec: func(j1, j2 *Jail) bool { + return j1.Config.Host_domainname > j2.Config.Host_domainname + }, + Host_hostnameInc: func(j1, j2 *Jail) bool { + return j1.Config.Host_hostname < j2.Config.Host_hostname + }, + Host_hostnameDec: func(j1, j2 *Jail) bool { + return j1.Config.Host_hostname > j2.Config.Host_hostname + }, + Host_hostuuidInc: func(j1, j2 *Jail) bool { + return j1.Config.Host_hostuuid < j2.Config.Host_hostuuid + }, + Host_hostuuidDec: func(j1, j2 *Jail) bool { + return j1.Config.Host_hostuuid > j2.Config.Host_hostuuid + }, + Host_timeInc: func(j1, j2 *Jail) bool { + return j1.Config.Host_time < j2.Config.Host_time + }, + Host_timeDec: func(j1, j2 *Jail) bool { + return j1.Config.Host_time > j2.Config.Host_time + }, + HostidInc: func(j1, j2 *Jail) bool { + return j1.Config.Hostid < j2.Config.Hostid + }, + HostidDec: func(j1, j2 *Jail) bool { + return j1.Config.Hostid > j2.Config.Hostid + }, + Hostid_strict_checkInc: func(j1, j2 *Jail) bool { + return j1.Config.Hostid_strict_check < j2.Config.Hostid_strict_check + }, + Hostid_strict_checkDec: func(j1, j2 *Jail) bool { + return j1.Config.Hostid_strict_check > j2.Config.Hostid_strict_check + }, + InterfacesInc: func(j1, j2 *Jail) bool { + return j1.Config.Interfaces < j2.Config.Interfaces + }, + InterfacesDec: func(j1, j2 *Jail) bool { + return j1.Config.Interfaces > j2.Config.Interfaces + }, + Ip_hostnameInc: func(j1, j2 *Jail) bool { + return j1.Config.Ip_hostname < j2.Config.Ip_hostname + }, + Ip_hostnameDec: func(j1, j2 *Jail) bool { + return j1.Config.Ip_hostname > j2.Config.Ip_hostname + }, + Ip4Inc: func(j1, j2 *Jail) bool { + return j1.Config.Ip4 < j2.Config.Ip4 + }, + Ip4Dec: func(j1, j2 *Jail) bool { + return j1.Config.Ip4 > j2.Config.Ip4 + }, + Ip4_addrInc: func(j1, j2 *Jail) bool { + return j1.Config.Ip4_addr < j2.Config.Ip4_addr + }, + Ip4_addrDec: func(j1, j2 *Jail) bool { + return j1.Config.Ip4_addr > j2.Config.Ip4_addr + }, + Ip4_saddrselInc: func(j1, j2 *Jail) bool { + return j1.Config.Ip4_saddrsel < j2.Config.Ip4_saddrsel + }, + Ip4_saddrselDec: func(j1, j2 *Jail) bool { + return j1.Config.Ip4_saddrsel > j2.Config.Ip4_saddrsel + }, + Ip6Inc: func(j1, j2 *Jail) bool { + return j1.Config.Ip6 < j2.Config.Ip6 + }, + Ip6Dec: func(j1, j2 *Jail) bool { + return j1.Config.Ip6 > j2.Config.Ip6 + }, + Ip6_addrInc: func(j1, j2 *Jail) bool { + return j1.Config.Ip6_addr < j2.Config.Ip6_addr + }, + Ip6_addrDec: func(j1, j2 *Jail) bool { + return j1.Config.Ip6_addr > j2.Config.Ip6_addr + }, + Ip6_saddrselInc: func(j1, j2 *Jail) bool { + return j1.Config.Ip6_saddrsel < j2.Config.Ip6_saddrsel + }, + Ip6_saddrselDec: func(j1, j2 *Jail) bool { + return j1.Config.Ip6_saddrsel > j2.Config.Ip6_saddrsel + }, + Jail_zfsInc: func(j1, j2 *Jail) bool { + return j1.Config.Jail_zfs < j2.Config.Jail_zfs + }, + Jail_zfsDec: func(j1, j2 *Jail) bool { + return j1.Config.Jail_zfs > j2.Config.Jail_zfs + }, + Jail_zfs_datasetInc: func(j1, j2 *Jail) bool { + return j1.Config.Jail_zfs_dataset < j2.Config.Jail_zfs_dataset + }, + Jail_zfs_datasetDec: func(j1, j2 *Jail) bool { + return j1.Config.Jail_zfs_dataset > j2.Config.Jail_zfs_dataset + }, + Jail_zfs_mountpointInc: func(j1, j2 *Jail) bool { + return j1.Config.Jail_zfs_mountpoint < j2.Config.Jail_zfs_mountpoint + }, + Jail_zfs_mountpointDec: func(j1, j2 *Jail) bool { + return j1.Config.Jail_zfs_mountpoint > j2.Config.Jail_zfs_mountpoint + }, + JailtypeInc: func(j1, j2 *Jail) bool { + return j1.Config.Jailtype < j2.Config.Jailtype + }, + JailtypeDec: func(j1, j2 *Jail) bool { + return j1.Config.Jailtype > j2.Config.Jailtype + }, + Last_startedInc: func(j1, j2 *Jail) bool { + return j1.Config.Last_started < j2.Config.Last_started + }, + Last_startedDec: func(j1, j2 *Jail) bool { + return j1.Config.Last_started > j2.Config.Last_started + }, + Localhost_ipInc: func(j1, j2 *Jail) bool { + return j1.Config.Localhost_ip < j2.Config.Localhost_ip + }, + Localhost_ipDec: func(j1, j2 *Jail) bool { + return j1.Config.Localhost_ip > j2.Config.Localhost_ip + }, + Login_flagsInc: func(j1, j2 *Jail) bool { + return j1.Config.Login_flags < j2.Config.Login_flags + }, + Login_flagsDec: func(j1, j2 *Jail) bool { + return j1.Config.Login_flags > j2.Config.Login_flags + }, + Mac_prefixInc: func(j1, j2 *Jail) bool { + return j1.Config.Mac_prefix < j2.Config.Mac_prefix + }, + Mac_prefixDec: func(j1, j2 *Jail) bool { + return j1.Config.Mac_prefix > j2.Config.Mac_prefix + }, + MaxprocInc: func(j1, j2 *Jail) bool { + return j1.Config.Maxproc < j2.Config.Maxproc + }, + MaxprocDec: func(j1, j2 *Jail) bool { + return j1.Config.Maxproc > j2.Config.Maxproc + }, + MemorylockedInc: func(j1, j2 *Jail) bool { + return j1.Config.Memorylocked < j2.Config.Memorylocked + }, + MemorylockedDec: func(j1, j2 *Jail) bool { + return j1.Config.Memorylocked > j2.Config.Memorylocked + }, + MemoryuseInc: func(j1, j2 *Jail) bool { + return j1.Config.Memoryuse < j2.Config.Memoryuse + }, + MemoryuseDec: func(j1, j2 *Jail) bool { + return j1.Config.Memoryuse > j2.Config.Memoryuse + }, + Min_dyn_devfs_rulesetInc: func(j1, j2 *Jail) bool { + return j1.Config.Min_dyn_devfs_ruleset < j2.Config.Min_dyn_devfs_ruleset + }, + Min_dyn_devfs_rulesetDec: func(j1, j2 *Jail) bool { + return j1.Config.Min_dyn_devfs_ruleset > j2.Config.Min_dyn_devfs_ruleset + }, + Mount_devfsInc: func(j1, j2 *Jail) bool { + return j1.Config.Mount_devfs < j2.Config.Mount_devfs + }, + Mount_devfsDec: func(j1, j2 *Jail) bool { + return j1.Config.Mount_devfs > j2.Config.Mount_devfs + }, + Mount_fdescfsInc: func(j1, j2 *Jail) bool { + return j1.Config.Mount_fdescfs < j2.Config.Mount_fdescfs + }, + Mount_fdescfsDec: func(j1, j2 *Jail) bool { + return j1.Config.Mount_fdescfs > j2.Config.Mount_fdescfs + }, + Mount_linprocfsInc: func(j1, j2 *Jail) bool { + return j1.Config.Mount_linprocfs < j2.Config.Mount_linprocfs + }, + Mount_linprocfsDec: func(j1, j2 *Jail) bool { + return j1.Config.Mount_linprocfs > j2.Config.Mount_linprocfs + }, + Mount_procfsInc: func(j1, j2 *Jail) bool { + return j1.Config.Mount_procfs < j2.Config.Mount_procfs + }, + Mount_procfsDec: func(j1, j2 *Jail) bool { + return j1.Config.Mount_procfs > j2.Config.Mount_procfs + }, + MountpointInc: func(j1, j2 *Jail) bool { + return j1.Config.Mountpoint < j2.Config.Mountpoint + }, + MountpointDec: func(j1, j2 *Jail) bool { + return j1.Config.Mountpoint > j2.Config.Mountpoint + }, + MsgqqueuedInc: func(j1, j2 *Jail) bool { + return j1.Config.Msgqqueued < j2.Config.Msgqqueued + }, + MsgqqueuedDec: func(j1, j2 *Jail) bool { + return j1.Config.Msgqqueued > j2.Config.Msgqqueued + }, + MsgqsizeInc: func(j1, j2 *Jail) bool { + return j1.Config.Msgqsize < j2.Config.Msgqsize + }, + MsgqsizeDec: func(j1, j2 *Jail) bool { + return j1.Config.Msgqsize > j2.Config.Msgqsize + }, + NatInc: func(j1, j2 *Jail) bool { + return j1.Config.Nat < j2.Config.Nat + }, + NatDec: func(j1, j2 *Jail) bool { + return j1.Config.Nat > j2.Config.Nat + }, + Nat_backendInc: func(j1, j2 *Jail) bool { + return j1.Config.Nat_backend < j2.Config.Nat_backend + }, + Nat_backendDec: func(j1, j2 *Jail) bool { + return j1.Config.Nat_backend > j2.Config.Nat_backend + }, + Nat_forwardsInc: func(j1, j2 *Jail) bool { + return j1.Config.Nat_forwards < j2.Config.Nat_forwards + }, + Nat_forwardsDec: func(j1, j2 *Jail) bool { + return j1.Config.Nat_forwards > j2.Config.Nat_forwards + }, + Nat_interfaceInc: func(j1, j2 *Jail) bool { + return j1.Config.Nat_interface < j2.Config.Nat_interface + }, + Nat_interfaceDec: func(j1, j2 *Jail) bool { + return j1.Config.Nat_interface > j2.Config.Nat_interface + }, + Nat_prefixInc: func(j1, j2 *Jail) bool { + return j1.Config.Nat_prefix < j2.Config.Nat_prefix + }, + Nat_prefixDec: func(j1, j2 *Jail) bool { + return j1.Config.Nat_prefix > j2.Config.Nat_prefix + }, + NmsgqInc: func(j1, j2 *Jail) bool { + return j1.Config.Nmsgq < j2.Config.Nmsgq + }, + NmsgqDec: func(j1, j2 *Jail) bool { + return j1.Config.Nmsgq > j2.Config.Nmsgq + }, + NotesInc: func(j1, j2 *Jail) bool { + return j1.Config.Notes < j2.Config.Notes + }, + NotesDec: func(j1, j2 *Jail) bool { + return j1.Config.Notes > j2.Config.Notes + }, + NsemInc: func(j1, j2 *Jail) bool { + return j1.Config.Nsem < j2.Config.Nsem + }, + NsemDec: func(j1, j2 *Jail) bool { + return j1.Config.Nsem > j2.Config.Nsem + }, + NsemopInc: func(j1, j2 *Jail) bool { + return j1.Config.Nsemop < j2.Config.Nsemop + }, + NsemopDec: func(j1, j2 *Jail) bool { + return j1.Config.Nsemop > j2.Config.Nsemop + }, + NshmInc: func(j1, j2 *Jail) bool { + return j1.Config.Nshm < j2.Config.Nshm + }, + NshmDec: func(j1, j2 *Jail) bool { + return j1.Config.Nshm > j2.Config.Nshm + }, + NthrInc: func(j1, j2 *Jail) bool { + return j1.Config.Nthr < j2.Config.Nthr + }, + NthrDec: func(j1, j2 *Jail) bool { + return j1.Config.Nthr > j2.Config.Nthr + }, + OpenfilesInc: func(j1, j2 *Jail) bool { + return j1.Config.Openfiles < j2.Config.Openfiles + }, + OpenfilesDec: func(j1, j2 *Jail) bool { + return j1.Config.Openfiles > j2.Config.Openfiles + }, + OriginInc: func(j1, j2 *Jail) bool { + return j1.Config.Origin < j2.Config.Origin + }, + OriginDec: func(j1, j2 *Jail) bool { + return j1.Config.Origin > j2.Config.Origin + }, + OwnerInc: func(j1, j2 *Jail) bool { + return j1.Config.Owner < j2.Config.Owner + }, + OwnerDec: func(j1, j2 *Jail) bool { + return j1.Config.Owner > j2.Config.Owner + }, + PcpuInc: func(j1, j2 *Jail) bool { + return j1.Config.Pcpu < j2.Config.Pcpu + }, + PcpuDec: func(j1, j2 *Jail) bool { + return j1.Config.Pcpu > j2.Config.Pcpu + }, + Plugin_nameInc: func(j1, j2 *Jail) bool { + return j1.Config.Plugin_name < j2.Config.Plugin_name + }, + Plugin_nameDec: func(j1, j2 *Jail) bool { + return j1.Config.Plugin_name > j2.Config.Plugin_name + }, + Plugin_repositoryInc: func(j1, j2 *Jail) bool { + return j1.Config.Plugin_repository < j2.Config.Plugin_repository + }, + Plugin_repositoryDec: func(j1, j2 *Jail) bool { + return j1.Config.Plugin_repository > j2.Config.Plugin_repository + }, + PriorityInc: func(j1, j2 *Jail) bool { + return j1.Config.Priority < j2.Config.Priority + }, + PriorityDec: func(j1, j2 *Jail) bool { + return j1.Config.Priority > j2.Config.Priority + }, + PseudoterminalsInc: func(j1, j2 *Jail) bool { + return j1.Config.Pseudoterminals < j2.Config.Pseudoterminals + }, + PseudoterminalsDec: func(j1, j2 *Jail) bool { + return j1.Config.Pseudoterminals > j2.Config.Pseudoterminals + }, + QuotaInc: func(j1, j2 *Jail) bool { + return j1.Config.Quota < j2.Config.Quota + }, + QuotaDec: func(j1, j2 *Jail) bool { + return j1.Config.Quota > j2.Config.Quota + }, + ReadbpsInc: func(j1, j2 *Jail) bool { + return j1.Config.Readbps < j2.Config.Readbps + }, + ReadbpsDec: func(j1, j2 *Jail) bool { + return j1.Config.Readbps > j2.Config.Readbps + }, + ReadiopsInc: func(j1, j2 *Jail) bool { + return j1.Config.Readiops < j2.Config.Readiops + }, + ReadiopsDec: func(j1, j2 *Jail) bool { + return j1.Config.Readiops > j2.Config.Readiops + }, + ReleaseInc: func(j1, j2 *Jail) bool { + return j1.Config.Release < j2.Config.Release + }, + ReleaseDec: func(j1, j2 *Jail) bool { + return j1.Config.Release > j2.Config.Release + }, + ReservationInc: func(j1, j2 *Jail) bool { + return j1.Config.Reservation < j2.Config.Reservation + }, + ReservationDec: func(j1, j2 *Jail) bool { + return j1.Config.Reservation > j2.Config.Reservation + }, + ResolverInc: func(j1, j2 *Jail) bool { + return j1.Config.Resolver < j2.Config.Resolver + }, + ResolverDec: func(j1, j2 *Jail) bool { + return j1.Config.Resolver > j2.Config.Resolver + }, + RlimitsInc: func(j1, j2 *Jail) bool { + return j1.Config.Rlimits < j2.Config.Rlimits + }, + RlimitsDec: func(j1, j2 *Jail) bool { + return j1.Config.Rlimits > j2.Config.Rlimits + }, + RtsoldInc: func(j1, j2 *Jail) bool { + return j1.Config.Rtsold < j2.Config.Rtsold + }, + RtsoldDec: func(j1, j2 *Jail) bool { + return j1.Config.Rtsold > j2.Config.Rtsold + }, + SecurelevelInc: func(j1, j2 *Jail) bool { + return j1.Config.Securelevel < j2.Config.Securelevel + }, + SecurelevelDec: func(j1, j2 *Jail) bool { + return j1.Config.Securelevel > j2.Config.Securelevel + }, + ShmsizeInc: func(j1, j2 *Jail) bool { + return j1.Config.Shmsize < j2.Config.Shmsize + }, + ShmsizeDec: func(j1, j2 *Jail) bool { + return j1.Config.Shmsize > j2.Config.Shmsize + }, + StacksizeInc: func(j1, j2 *Jail) bool { + return j1.Config.Stacksize < j2.Config.Stacksize + }, + StacksizeDec: func(j1, j2 *Jail) bool { + return j1.Config.Stacksize > j2.Config.Stacksize + }, + Stop_timeoutInc: func(j1, j2 *Jail) bool { + return j1.Config.Stop_timeout < j2.Config.Stop_timeout + }, + Stop_timeoutDec: func(j1, j2 *Jail) bool { + return j1.Config.Stop_timeout > j2.Config.Stop_timeout + }, + SwapuseInc: func(j1, j2 *Jail) bool { + return j1.Config.Swapuse < j2.Config.Swapuse + }, + SwapuseDec: func(j1, j2 *Jail) bool { + return j1.Config.Swapuse > j2.Config.Swapuse + }, + Sync_stateInc: func(j1, j2 *Jail) bool { + return j1.Config.Sync_state < j2.Config.Sync_state + }, + Sync_stateDec: func(j1, j2 *Jail) bool { + return j1.Config.Sync_state > j2.Config.Sync_state + }, + Sync_targetInc: func(j1, j2 *Jail) bool { + return j1.Config.Sync_target < j2.Config.Sync_target + }, + Sync_targetDec: func(j1, j2 *Jail) bool { + return j1.Config.Sync_target > j2.Config.Sync_target + }, + Sync_tgt_zpoolInc: func(j1, j2 *Jail) bool { + return j1.Config.Sync_tgt_zpool < j2.Config.Sync_tgt_zpool + }, + Sync_tgt_zpoolDec: func(j1, j2 *Jail) bool { + return j1.Config.Sync_tgt_zpool > j2.Config.Sync_tgt_zpool + }, + SysvmsgInc: func(j1, j2 *Jail) bool { + return j1.Config.Sysvmsg < j2.Config.Sysvmsg + }, + SysvmsgDec: func(j1, j2 *Jail) bool { + return j1.Config.Sysvmsg > j2.Config.Sysvmsg + }, + SysvsemInc: func(j1, j2 *Jail) bool { + return j1.Config.Sysvsem < j2.Config.Sysvsem + }, + SysvsemDec: func(j1, j2 *Jail) bool { + return j1.Config.Sysvsem > j2.Config.Sysvsem + }, + SysvshmInc: func(j1, j2 *Jail) bool { + return j1.Config.Sysvshm < j2.Config.Sysvshm + }, + SysvshmDec: func(j1, j2 *Jail) bool { + return j1.Config.Sysvshm > j2.Config.Sysvshm + }, + TemplateInc: func(j1, j2 *Jail) bool { + return j1.Config.Template < j2.Config.Template + }, + TemplateDec: func(j1, j2 *Jail) bool { + return j1.Config.Template > j2.Config.Template + }, + UsedInc: func(j1, j2 *Jail) bool { + return j1.Config.Used < j2.Config.Used + }, + UsedDec: func(j1, j2 *Jail) bool { + return j1.Config.Used > j2.Config.Used + }, + VmemoryuseInc: func(j1, j2 *Jail) bool { + return j1.Config.Vmemoryuse < j2.Config.Vmemoryuse + }, + VmemoryuseDec: func(j1, j2 *Jail) bool { + return j1.Config.Vmemoryuse > j2.Config.Vmemoryuse + }, + VnetInc: func(j1, j2 *Jail) bool { + return j1.Config.Vnet < j2.Config.Vnet + }, + VnetDec: func(j1, j2 *Jail) bool { + return j1.Config.Vnet > j2.Config.Vnet + }, + Vnet_default_interfaceInc: func(j1, j2 *Jail) bool { + return j1.Config.Vnet_default_interface < j2.Config.Vnet_default_interface + }, + Vnet_default_interfaceDec: func(j1, j2 *Jail) bool { + return j1.Config.Vnet_default_interface > j2.Config.Vnet_default_interface + }, + Vnet_interfacesInc: func(j1, j2 *Jail) bool { + return j1.Config.Vnet_interfaces < j2.Config.Vnet_interfaces + }, + Vnet_interfacesDec: func(j1, j2 *Jail) bool { + return j1.Config.Vnet_interfaces > j2.Config.Vnet_interfaces + }, + Vnet0_macInc: func(j1, j2 *Jail) bool { + return j1.Config.Vnet0_mac < j2.Config.Vnet0_mac + }, + Vnet0_macDec: func(j1, j2 *Jail) bool { + return j1.Config.Vnet0_mac > j2.Config.Vnet0_mac + }, + Vnet1_macInc: func(j1, j2 *Jail) bool { + return j1.Config.Vnet1_mac < j2.Config.Vnet1_mac + }, + Vnet1_macDec: func(j1, j2 *Jail) bool { + return j1.Config.Vnet1_mac > j2.Config.Vnet1_mac + }, + Vnet2_macInc: func(j1, j2 *Jail) bool { + return j1.Config.Vnet2_mac < j2.Config.Vnet2_mac + }, + Vnet2_macDec: func(j1, j2 *Jail) bool { + return j1.Config.Vnet2_mac > j2.Config.Vnet2_mac + }, + Vnet3_macInc: func(j1, j2 *Jail) bool { + return j1.Config.Vnet3_mac < j2.Config.Vnet3_mac + }, + Vnet3_macDec: func(j1, j2 *Jail) bool { + return j1.Config.Vnet3_mac > j2.Config.Vnet3_mac + }, + WallclockInc: func(j1, j2 *Jail) bool { + return j1.Config.Wallclock < j2.Config.Wallclock + }, + WallclockDec: func(j1, j2 *Jail) bool { + return j1.Config.Wallclock > j2.Config.Wallclock + }, + WritebpsInc: func(j1, j2 *Jail) bool { + return j1.Config.Writebps < j2.Config.Writebps + }, + WritebpsDec: func(j1, j2 *Jail) bool { + return j1.Config.Writebps > j2.Config.Writebps + }, + WriteiopsInc: func(j1, j2 *Jail) bool { + return j1.Config.Writeiops < j2.Config.Writeiops + }, + WriteiopsDec: func(j1, j2 *Jail) bool { + return j1.Config.Writeiops > j2.Config.Writeiops + }, + } + + js := JailSort{ + ConfigPathInc: func(j1, j2 *Jail) bool { + return j1.ConfigPath < j2.ConfigPath + }, + ConfigPathDec: func(j1, j2 *Jail) bool { + return j1.ConfigPath > j2.ConfigPath + }, + InternalNameInc: func(j1, j2 *Jail) bool { + return j1.InternalName < j2.InternalName + }, + InternalNameDec: func(j1, j2 *Jail) bool { + return j1.InternalName > j2.InternalName + }, + JIDInc: func(j1, j2 *Jail) bool { + return j1.JID < j2.JID + }, + JIDDec: func(j1, j2 *Jail) bool { + return j1.JID > j2.JID + }, + NameInc: func(j1, j2 *Jail) bool { + return j1.Name < j2.Name + }, + NameDec: func(j1, j2 *Jail) bool { + return j1.Name > j2.Name + }, + RootPathInc: func(j1, j2 *Jail) bool { + return j1.RootPath < j2.RootPath + }, + RootPathDec: func(j1, j2 *Jail) bool { + return j1.RootPath > j2.RootPath + }, + RunningInc: func(j1, j2 *Jail) bool { + return !j1.Running && j2.Running + }, + RunningDec: func(j1, j2 *Jail) bool { + return j1.Running && !j2.Running + }, + ZpoolInc: func(j1, j2 *Jail) bool { + return j1.Zpool < j2.Zpool + }, + ZpoolDec: func(j1, j2 *Jail) bool { + return j1.Zpool > j2.Zpool + }, + Config: jcs, + } + + return js +} + +// multiSorter implements the Sort interface, sorting the jails within. +type multiSorter struct { + jails []Jail + less []lessFunc +} + +// Sort sorts the argument slice according to the less functions passed to OrderedBy. +func (ms *multiSorter) Sort(jails []Jail) { + ms.jails = jails + sort.Sort(ms) +} + +// OrderedBy returns a Sorter that sorts using the less functions, in order. +// Call its Sort method to sort the data. +func OrderedBy(less ...lessFunc) *multiSorter { + return &multiSorter{ + less: less, + } +} + +// Len is part of sort.Interface. +func (ms *multiSorter) Len() int { + return len(ms.jails) +} + +// Swap is part of sort.Interface. +func (ms *multiSorter) Swap(i, j int) { + ms.jails[i], ms.jails[j] = ms.jails[j], ms.jails[i] +} + +// Less is part of sort.Interface. It is implemented by looping along the +// less functions until it finds a comparison that discriminates between +// the two items (one is less than the other). Note that it can call the +// less functions twice per call. We could change the functions to return +// -1, 0, 1 and reduce the number of calls for greater efficiency: an +// exercise for the reader. +func (ms *multiSorter) Less(i, j int) bool { + p, q := &ms.jails[i], &ms.jails[j] + // Try all but the last comparison. + var k int + for k = 0; k < len(ms.less)-1; k++ { + less := ms.less[k] + switch { + case less(p, q): + // p < q, so we have a decision. + return true + case less(q, p): + // p > q, so we have a decision. + return false + } + // p == q; try the next comparison. + } + // All comparisons to here said "equal", so just return whatever + // the final comparison reports. + return ms.less[k](p, q) +} + +