Compare commits

..

No commits in common. "74868ab2d3ab71b88ef30c73806fc7b07b9707a6" and "3cc35fa7ffa0d754434e286e6231bbfeac713b1f" have entirely different histories.

7 changed files with 51 additions and 241 deletions

View File

@ -2,4 +2,7 @@ module ectl
go 1.23.4 go 1.23.4
require gopkg.in/yaml.v3 v3.0.1 require (
gopkg.in/yaml.v3 v3.0.1 // indirect
rsc.io/getopt v0.0.0-20170811000552-20be20937449 // indirect
)

View File

@ -1,4 +1,5 @@
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
rsc.io/getopt v0.0.0-20170811000552-20be20937449 h1:UukjJOsjQH0DIuyyrcod6CXHS6cdaMMuJmrt+SN1j4A=
rsc.io/getopt v0.0.0-20170811000552-20be20937449/go.mod h1:dhCdeqAxkyt5u3/sKRkUXuHaMXUu1Pt13GTQAM2xnig=

View File

@ -59,28 +59,7 @@ func main() {
fmt.Println("Usage: ectl service <start/stop/enable/disable/status/list> [service]") fmt.Println("Usage: ectl service <start/stop/enable/disable/status/list> [service]")
return return
} else if flag.Args()[1] == "list" { } else if flag.Args()[1] == "list" {
if _, err := os.Stat(path.Join(runstatedir, "esvm")); err != nil { fmt.Println("list")
log.Fatalf("Could not list services! Error: %s\n", err)
}
entries, err := os.ReadDir(path.Join(runstatedir, "esvm"))
if err != nil {
log.Fatalf("Could not list services! Error: %s\n", err)
}
for _, entry := range entries {
if !entry.IsDir() {
continue
}
state := getServiceState(entry.Name())
enabled := strconv.FormatBool(isServiceEnabled(entry.Name()))
enabled = strings.ToUpper(enabled[:1]) + strings.ToLower(enabled[1:])
fmt.Println("Service name: " + entry.Name())
fmt.Printf(" State: %s\n", state)
fmt.Printf(" Enabled: %s\n", enabled)
}
return return
} else if len(flag.Args()) <= 2 { } else if len(flag.Args()) <= 2 {
fmt.Printf("Usage: ectl service %s <service>\n", flag.Args()[1]) fmt.Printf("Usage: ectl service %s <service>\n", flag.Args()[1])
@ -247,13 +226,26 @@ func main() {
log.Fatalf("Could not get service status! Error: %s\n", err) log.Fatalf("Could not get service status! Error: %s\n", err)
} }
state := getServiceState(flag.Args()[2]) var state uint64
enabled := strconv.FormatBool(isServiceEnabled(flag.Args()[2])) bytes, err := os.ReadFile(path.Join(runstatedir, "esvm", flag.Args()[2], "state"))
enabled = strings.ToUpper(enabled[:1]) + strings.ToLower(enabled[1:]) if err != nil {
state = 0
}
state, err = strconv.ParseUint(string(bytes), 10, 8)
fmt.Println("Service name: " + flag.Args()[2]) fmt.Println("Service name: " + flag.Args()[2])
fmt.Printf(" State: %s\n", state) switch state {
fmt.Printf(" Enabled: %s\n", enabled) case 0:
fmt.Println("Service state: Unknown")
case 1:
fmt.Println("Service state: Unloaded")
case 2:
fmt.Println("Service state: Running")
case 3:
fmt.Println("Service state: Stopped")
case 4:
fmt.Println("Service state: Crashed")
}
return return
} }
} }
@ -262,53 +254,6 @@ func main() {
os.Exit(1) os.Exit(1)
} }
func getServiceState(serviceName string) string {
if _, err := os.Stat(path.Join(runstatedir, "esvm", serviceName)); err != nil {
return ""
}
var state uint64
bytes, err := os.ReadFile(path.Join(runstatedir, "esvm", serviceName, "state"))
if err != nil {
state = 0
}
state, err = strconv.ParseUint(string(bytes), 10, 8)
switch state {
case 1:
return "Unloaded"
case 2:
return "Running"
case 3:
return "Stopped"
case 4:
return "Crashed"
case 5:
return "Completed"
default:
return "Unknown"
}
}
func isServiceEnabled(serviceName string) bool {
if _, err := os.Stat(path.Join(sysconfdir, "esvm/enabled_services")); err != nil {
return false
}
file, err := os.ReadFile(path.Join(sysconfdir, "esvm/enabled_services"))
if err != nil {
return false
}
for _, line := range strings.Split(string(file), "\n") {
if strings.TrimSpace(line) == serviceName {
return true
}
}
return false
}
func printUsage() { func printUsage() {
fmt.Println("Available sucommands:") fmt.Println("Available sucommands:")
fmt.Println("ectl version | Show enit version") fmt.Println("ectl version | Show enit version")

View File

@ -1,5 +1,3 @@
module enit module enit
go 1.23.4 go 1.23.4
require golang.org/x/sys v0.31.0

View File

@ -1,2 +1,4 @@
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"errors"
"flag" "flag"
"fmt" "fmt"
"log" "log"
@ -74,45 +75,43 @@ func setProcessName() error {
func mountVirtualFilesystems() { func mountVirtualFilesystems() {
fmt.Print("Mounting virtual filesystems... ") fmt.Print("Mounting virtual filesystems... ")
commonOptions := "rw,nosuid,relatime" commonFlags := uintptr(0 | syscall.MS_NOSUID | syscall.MS_RELATIME)
// Mount /proc // Mount /proc
if err := mount("proc", "/proc", "proc", commonOptions+",nodev,noexec", false); err != nil { if err := syscall.Mount("proc", "/proc", "proc", commonFlags|syscall.MS_NODEV|syscall.MS_NOEXEC|syscall.MS_REMOUNT, ""); err != nil {
panic(err) panic(err)
} }
// Mount /sys // Mount /sys
if err := mount("sys", "/sys", "sysfs", commonOptions+",nodev,noexec", false); err != nil { if err := syscall.Mount("sys", "/sys", "sysfs", commonFlags|syscall.MS_NODEV|syscall.MS_NOEXEC|syscall.MS_REMOUNT, ""); err != nil {
panic(err) panic(err)
} }
// Mount /dev // Mount /dev
if err := mount("dev", "/dev", "devtmpfs", commonOptions+",mode=755,inode64", false); err != nil { if err := syscall.Mount("dev", "/dev", "devtmpfs", commonFlags|syscall.MS_REMOUNT, "mode=755,inode64"); err != nil {
panic(err) panic(err)
} }
// Mount /run // Mount /run
if err := mount("run", "/run", "tmpfs", commonOptions+",nodev,mode=755,inode64", false); err != nil { if err := syscall.Mount("run", "/run", "tmpfs", commonFlags|syscall.MS_NODEV|syscall.MS_REMOUNT, "mode=755,inode64"); err != nil {
panic(err) panic(err)
} }
// Mount /dev/pts // Mount /dev/pts
if err := mount("devpts", "/dev/pts", "devpts", commonOptions+",gid=5,mode=620,ptmxmode=000", true); err != nil { if err := os.Mkdir("/dev/pts", 0755); err != nil && !errors.Is(err, os.ErrExist) {
panic(err)
}
if err := syscall.Mount("devpts", "/dev/pts", "devpts", commonFlags, "gid=5,mode=620,ptmxmode=000"); err != nil {
panic(err) panic(err)
} }
// Mount /dev/shm // Mount /dev/shm
if err := mount("shm", "/dev/shm", "tmpfs", commonOptions+",nodev,inode64", true); err != nil { if err := os.Mkdir("/dev/shm", 0755); err != nil && !errors.Is(err, os.ErrExist) {
panic(err)
}
if err := syscall.Mount("shm", "/dev/shm", "tmpfs", commonFlags|syscall.MS_NODEV, "inode64"); err != nil {
panic(err) panic(err)
} }
// Mount securityfs // Mount securityfs
if err := mount("securityfs", "/sys/kernel/security", "securityfs", commonOptions, false); err != nil { if err := syscall.Mount("securityfs", "/sys/kernel/security", "securityfs", commonFlags, ""); err != nil {
panic(err) panic(err)
} }
// Mount cgroups v2 // Mount cgroups v2
if err := mount("cgroup2", "/sys/fs/cgroup", "cgroup2", commonOptions+",noexec,nsdelegate,memory_recursiveprot", false); err != nil { if err := syscall.Mount("cgroup2", "/sys/fs/cgroup", "cgroup2", commonFlags|syscall.MS_NOEXEC, ""); err != nil {
panic(err) panic(err)
} }
@ -120,9 +119,12 @@ func mountVirtualFilesystems() {
} }
func mountFilesystems() { func mountFilesystems() {
fmt.Print("Mounting fstab entries... ") fmt.Print("Mounting filesystems... ")
if err := mountFstabEntries(); err != nil { cmd := exec.Command("/bin/mount", "-a")
err := cmd.Run()
if err != nil {
log.Println("Could not mount fstab entries!") log.Println("Could not mount fstab entries!")
panic(err) panic(err)
} }

View File

@ -1,141 +0,0 @@
package main
import (
"golang.org/x/sys/unix"
"os"
"slices"
"strings"
)
var flagsEquivalence = map[string]uintptr{
"dirsync": unix.MS_DIRSYNC,
"lazytime": unix.MS_LAZYTIME,
"noatime": unix.MS_NOATIME,
"nodev": unix.MS_NODEV,
"nodiratime": unix.MS_NODIRATIME,
"noexec": unix.MS_NOEXEC,
"nosuid": unix.MS_NOSUID,
"ro": unix.MS_RDONLY,
"rw": 0,
"relatime": unix.MS_RELATIME,
"silent": unix.MS_SILENT,
"strictatime": unix.MS_STRICTATIME,
"sync": unix.MS_SYNCHRONOUS,
"defaults": 0,
}
// Split string flags to mount flags and mount data
func convertMountOptions(options string) (flags []uintptr, data string) {
for _, flag := range strings.Split(options, ",") {
if unixFlag, ok := flagsEquivalence[flag]; ok {
flags = append(flags, unixFlag)
} else {
if data == "" {
data = flag
} else {
data += "," + flag
}
}
}
return flags, data
}
// Combine a unix flag slice or array into a single uintptr
func combineUnixFlags(flagsSlice []uintptr) (flags uintptr) {
flags = 0
for _, flag := range flagsSlice {
flags |= flag
}
return flags
}
// Check whether a certain path is a mountpoint
func isMountpoint(mountpoint string) bool {
if mountpoint != "/" {
mountpoint = strings.TrimRight(mountpoint, "/")
}
if _, err := os.Stat("/proc/mounts"); err != nil {
return false
}
bytes, err := os.ReadFile("/proc/mounts")
if err != nil {
return false
}
for _, line := range strings.Split(string(bytes), "\n") {
line = strings.TrimSpace(line)
if line == "" {
continue
}
if strings.Split(line, " ")[1] == mountpoint {
return true
}
}
return false
}
func mount(source, target, fstype string, options string, mkdir bool) error {
flags, data := convertMountOptions(options)
if isMountpoint(target) && !slices.Contains(flags, unix.MS_REMOUNT) {
flags = append(flags, unix.MS_REMOUNT)
}
if mkdir {
err := os.MkdirAll(target, 0755)
if err != nil {
return err
}
}
if err := unix.Mount(source, target, fstype, combineUnixFlags(flags), data); err != nil {
return err
}
return nil
}
func mountFstabEntries() error {
if _, err := os.Stat("/etc/fstab"); err != nil {
return err
}
bytes, err := os.ReadFile("/etc/fstab")
if err != nil {
return err
}
for _, line := range strings.Split(string(bytes), "\n") {
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "#") || line == "" {
continue
}
source := strings.Split(line, " ")[0]
target := strings.Split(line, " ")[1]
fstype := strings.Split(line, " ")[2]
options := strings.Split(line, " ")[3]
flags, data := convertMountOptions(options)
if slices.Contains(strings.Split(data, ","), "noauto") {
continue
}
if isMountpoint(target) && !slices.Contains(flags, unix.MS_REMOUNT) {
flags = append(flags, unix.MS_REMOUNT)
}
if err := unix.Mount(source, target, fstype, combineUnixFlags(flags), data); err != nil {
return err
}
}
return nil
}