Genimage struct

Configuration for generating an image

Fields:

  • Name (string) - json:"name"
  • Type (string) - json:"type"
  • GenimagePath (string) - json:"genimagepath"
  • Config (string) - json:"config"
  • Rootpath (string) - json:"rootpath"
  • Inputpath (string) - json:"inputpath"
  • Outputpath (string) - json:"outputpath"

PlugInfo function

Provide plugin information as a JSON string

Returns:

  • *C.char
Show/Hide Function Body
{
	plugininfo := &api.PluginInfo{Name: "genimage", Type: api.FinalizePlugin}
	pluginjson, err := json.Marshal(plugininfo)
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}
	return C.CString(string(pluginjson))
}

PluginScope function

Provide the plugin scope

Returns:

  • int32
Show/Hide Function Body
{ // int32 is defined as GoInt32 in cgo which is the same as a C int
	return api.IMAGENAME | api.FS | api.RECIPE
}

ParsePath function

Replace placeholders in the path with actual values from ScopeData

$PROJROOT -> Recipe.ParentPath

$FSROOT -> FS

Parameters:

  • path string
  • data *api.ScopeData

Returns:

  • string
Show/Hide Function Body
{
	path = strings.Replace(path, "$PROJROOT", data.Recipe.ParentPath, 1)
	path = strings.Replace(path, "$FSROOT", data.FS, 1)
	return path
}

FinalizeBuild function

Complete the build process for a generated image module.

Find the binary if not specified, replace path placeholders

in the module paths, and run the command

with the provided configuration

Parameters:

  • moduleInterface *C.char
  • extraData *C.char

Returns:

  • *C.char
Show/Hide Function Body
{
	var module *Genimage
	var data *api.ScopeData

	err := json.Unmarshal([]byte(C.GoString(moduleInterface)), &module)
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}

	err = json.Unmarshal([]byte(C.GoString(extraData)), &data)
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}

	genimage := module.GenimagePath
	if genimage == "" {
		genimage, err = exec.LookPath("genimage")
		if err != nil {
			return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
		}
	}

	cmd := exec.Command(
		genimage,
		"--config",
		ParsePath(module.Config, data),
		"--rootpath",
		ParsePath(module.Rootpath, data),
		"--outputpath",
		ParsePath(module.Outputpath, data),
		"--inputpath",
		ParsePath(module.Inputpath, data),
	)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Dir = data.Recipe.ParentPath

	err = cmd.Run()
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}

	return C.CString("")
}

main function

Show/Hide Function Body
{}

Shell struct

Configuration for a set of shell commands

Fields:

  • Name (string) - json:"name"
  • Type (string) - json:"type"
  • Commands ([]string) - json:"commands"
  • Cwd (string) - json:"cwd"

PlugInfo function

Provide plugin information as a JSON string

Returns:

  • *C.char
Show/Hide Function Body
{
	plugininfo := &api.PluginInfo{Name: "shell-final", Type: api.FinalizePlugin}
	pluginjson, err := json.Marshal(plugininfo)
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}
	return C.CString(string(pluginjson))
}

PluginScope function

Provide the plugin scope

Returns:

  • int32
Show/Hide Function Body
{ // int32 is defined as GoInt32 in cgo which is the same as a C int
	return api.IMAGENAME | api.FS | api.RECIPE
}

parsePath function

Replace placeholders in the path with actual values from ScopeData

$PROJROOT -> Recipe.ParentPath

$FSROOT -> FS

Parameters:

  • path string
  • data *api.ScopeData

Returns:

  • string
Show/Hide Function Body
{
	path = strings.ReplaceAll(path, "$PROJROOT", data.Recipe.ParentPath)
	path = strings.ReplaceAll(path, "$FSROOT", data.FS)
	return path
}

baseCommand function

Check if the command is in $PATH or includes a directory path.

Return the full path if found, otherwise return the command unchanged.

Parameters:

  • command string
  • data *api.ScopeData

Returns:

  • string
Show/Hide Function Body
{
	commandParts := strings.Split(command, " ")
	if strings.Contains(commandParts[0], "/") {
		return parsePath(commandParts[0], data)
	} else {
		command, err := exec.LookPath(commandParts[0])
		if err != nil {
			return commandParts[0]
		}
		return command
	}
}

getArgs function

Extract and return arguments from a command string

Parameters:

  • command string
  • data *api.ScopeData

Returns:

  • []string
Show/Hide Function Body
{
	commandParts := strings.Split(parsePath(command, data), " ")
	return commandParts[1:]
}

genCommand function

Generate an executable command by resolving the base command and arguments

and wrapping them with appropriate syntax for execution.

Parameters:

  • command string
  • data *api.ScopeData

Returns:

  • []string
Show/Hide Function Body
{
	baseCommand := baseCommand(command, data)
	args := getArgs(command, data)
	return append(append(append([]string{"-c", "'"}, strings.Join(args, " ")), baseCommand), "'")
}

FinalizeBuild function

Execute shell commands from a Shell struct using the provided ScopeData.

It parses and runs each command in the context of the provided working directory,

or the recipe's parent path if no specific directory is given.

Parameters:

  • moduleInterface *C.char
  • extraData *C.char

Returns:

  • *C.char
Show/Hide Function Body
{
	var module *Shell
	var data *api.ScopeData

	err := json.Unmarshal([]byte(C.GoString(moduleInterface)), &module)
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}

	err = json.Unmarshal([]byte(C.GoString(extraData)), &data)
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}

	for _, command := range module.Commands {
		fmt.Println("shell-final:: bash ", "-c ", command)

		cmd := exec.Command(
			"bash", "-c", parsePath(command, data),
		)
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		cmd.Env = os.Environ()
		if len(strings.TrimSpace(module.Cwd)) == 0 {
			cmd.Dir = data.Recipe.ParentPath
		} else {
			cmd.Dir = parsePath(module.Cwd, data)
		}

		err = cmd.Run()
		if err != nil {
			return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
		}
	}

	return C.CString("")
}

main function

Show/Hide Function Body
{}

Sysext struct

Configuration for system extensions

Fields:

  • Name (string) - json:"name"
  • Type (string) - json:"type"
  • OSReleaseID (string) - json:"osreleaseid"
  • OSReleaseVersionID (string) - json:"osreleaseversionid"

PlugInfo function

Provide plugin information as a JSON string

Returns:

  • *C.char
Show/Hide Function Body
{
	plugininfo := &api.PluginInfo{Name: "sysext", Type: api.FinalizePlugin}
	pluginjson, err := json.Marshal(plugininfo)
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}
	return C.CString(string(pluginjson))
}

PluginScope function

Provide the plugin scope

Returns:

  • int32
Show/Hide Function Body
{ // int32 is defined as GoInt32 in cgo which is the same as a C int
	return api.IMAGENAME | api.FS | api.RECIPE
}

FinalizeBuild function

Process and finalize the build by creating an extension release file and

creating a SquashFS image from the filesystem

Parameters:

  • moduleInterface *C.char
  • extraData *C.char

Returns:

  • *C.char
Show/Hide Function Body
{
	var module *Sysext
	var data *api.ScopeData

	err := json.Unmarshal([]byte(C.GoString(moduleInterface)), &module)
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}

	err = json.Unmarshal([]byte(C.GoString(extraData)), &data)
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}

	var extensionRelease strings.Builder
	fmt.Fprintf(&extensionRelease, "ID=%s\n", module.OSReleaseID)
	fmt.Fprintf(&extensionRelease, "VERSION_ID=%s\n", module.OSReleaseVersionID)

	err = os.MkdirAll(filepath.Join(data.FS, "usr/lib/extension-release.d"), 0o777)
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}
	err = os.WriteFile(filepath.Join(data.FS, fmt.Sprintf("usr/lib/extension-release.d/extension-release.%s", data.Recipe.Id)), []byte(extensionRelease.String()), 0o777)
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}

	mksquashfs, err := exec.LookPath("mksquashfs")
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}
	cmd := exec.Command(
		mksquashfs, data.FS,
		filepath.Join(data.Recipe.ParentPath, fmt.Sprintf("%s.raw", data.Recipe.Id)),
	)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Dir = data.Recipe.ParentPath

	err = cmd.Run()
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}

	return C.CString("")
}

main function

Show/Hide Function Body
{}

SystemdRepart struct

Configuration for systemd repartitioning

Fields:

  • Name (string) - json:"name"
  • Type (string) - json:"type"
  • Output (string) - json:"output"
  • Json (string) - json:"json"
  • SpecOutput (string) - json:"spec_output"
  • Size (string) - json:"size"
  • Seed (string) - json:"seed"
  • Split (bool) - json:"split"
  • DeferPartitions ([]string) - json:"defer_partitions"

PlugInfo function

Provide plugin information as a JSON string

Returns:

  • *C.char
Show/Hide Function Body
{
	plugininfo := &api.PluginInfo{Name: "systemd-repart", Type: api.FinalizePlugin}
	pluginjson, err := json.Marshal(plugininfo)
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}
	return C.CString(string(pluginjson))
}

PluginScope function

Provide the plugin scope

Returns:

  • int32
Show/Hide Function Body
{ // int32 is defined as GoInt32 in cgo which is the same as a C int
	return api.IMAGENAME | api.FS | api.RECIPE
}

FinalizeBuild function

Finalize the build by executing systemd-repart with the provided configuration

to generate and apply partitioning specifications and output results

Parameters:

  • moduleInterface *C.char
  • extraData *C.char

Returns:

  • *C.char
Show/Hide Function Body
{
	var module *SystemdRepart
	var data *api.ScopeData

	err := json.Unmarshal([]byte(C.GoString(moduleInterface)), &module)
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}

	err = json.Unmarshal([]byte(C.GoString(extraData)), &data)
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}

	repart, err := exec.LookPath("systemd-repart")
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}

	if len(strings.TrimSpace(module.Json)) == 0 {
		module.Json = "off"
	}

	args := []string{
		"--definitions=definitions",
		"--empty=create",
		fmt.Sprintf("--size=%s", module.Size),
		"--dry-run=no",
		"--discard=no",
		"--offline=true",
		"--no-pager",
		fmt.Sprintf("--split=%t", module.Split),
		fmt.Sprintf("--seed=%s", module.Seed),
		fmt.Sprintf("--root=%s", data.FS),
		module.Output,
		fmt.Sprintf("--json=%s", module.Json),
	}

	if len(module.DeferPartitions) > 0 {
		args = append(args, fmt.Sprintf("--defer-partitions=%s", strings.Join(module.DeferPartitions, ",")))
	}

	cmd := exec.Command(
		repart,
		args...,
	)
	jsonFile, err := os.Create(module.SpecOutput)
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}
	defer jsonFile.Close()
	cmd.Stdout = jsonFile
	cmd.Stderr = os.Stderr
	cmd.Dir = data.Recipe.ParentPath

	err = cmd.Run()
	if err != nil {
		return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
	}

	return C.CString("")
}

main function

Show/Hide Function Body
{}

C import

Import example:

import "C"

encoding/json import

Import example:

import "encoding/json"

fmt import

Import example:

import "fmt"

github.com/vanilla-os/vib/api import

Import example:

import "github.com/vanilla-os/vib/api"

os import

Import example:

import "os"

os/exec import

Import example:

import "os/exec"

strings import

Import example:

import "strings"

C import

Import example:

import "C"

encoding/json import

Import example:

import "encoding/json"

fmt import

Import example:

import "fmt"

github.com/vanilla-os/vib/api import

Import example:

import "github.com/vanilla-os/vib/api"

os import

Import example:

import "os"

os/exec import

Import example:

import "os/exec"

strings import

Import example:

import "strings"

C import

Import example:

import "C"

encoding/json import

Import example:

import "encoding/json"

fmt import

Import example:

import "fmt"

os import

Import example:

import "os"

os/exec import

Import example:

import "os/exec"

path/filepath import

Import example:

import "path/filepath"

strings import

Import example:

import "strings"

github.com/vanilla-os/vib/api import

Import example:

import "github.com/vanilla-os/vib/api"

C import

Import example:

import "C"

encoding/json import

Import example:

import "encoding/json"

fmt import

Import example:

import "fmt"

github.com/vanilla-os/vib/api import

Import example:

import "github.com/vanilla-os/vib/api"

os import

Import example:

import "os"

os/exec import

Import example:

import "os/exec"

strings import

Import example:

import "strings"