Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion distrobuilder/main_incus.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,35 @@ func (c *cmdIncus) run(cmd *cobra.Command, args []string, overlayDir string) err
imageTargets |= shared.ImageTargetContainer
}

for _, file := range c.global.definition.Files {
// Maps symbolic user/group names to their numeric IDs using information from passwd and group files.
userMap, groupMap, err := parsePasswdAndGroupFiles(overlayDir)
if err != nil {
c.global.logger.WithField("overlay", overlayDir).Warn("Could not parse passwd/group file: %w", err)
}

for i, file := range c.global.definition.Files {
if !shared.ApplyFilter(&file, c.global.definition.Image.Release, c.global.definition.Image.ArchitectureMapped, c.global.definition.Image.Variant, c.global.definition.Targets.Type, imageTargets) {
continue
}

if file.UID != "" && !isNumeric(file.UID) {
uid, exists := userMap[file.UID]
if exists {
c.global.definition.Files[i].UID = uid
} else {
c.global.logger.WithField("generator", file.Generator).Warnf("Could not find UID for user %q", file.UID)
}
}

if file.UID != "" && !isNumeric(file.GID) {
gid, exists := groupMap[file.GID]
if exists {
c.global.definition.Files[i].GID = gid
} else {
c.global.logger.WithField("generator", file.Generator).Warnf("Could not find GID for group %q", file.GID)
}
}

generator, err := generators.Load(file.Generator, c.global.logger, c.global.flagCacheDir, overlayDir, file, *c.global.definition)
if err != nil {
return fmt.Errorf("Failed to load generator %q: %w", file.Generator, err)
Expand Down
56 changes: 56 additions & 0 deletions distrobuilder/passwd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package main

import (
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
)

// parsePasswdAndGroupFiles reads passwd and group files from the given root directory
// and returns mappings of names to IDs for both users and groups.
func parsePasswdAndGroupFiles(rootDir string) (map[string]string, map[string]string, error) {
userMap, err := parsePasswdFile(filepath.Join(rootDir, "/etc/passwd"))
if err != nil {
return nil, nil, fmt.Errorf("parsing passwd file: %w", err)
}

groupMap, err := parsePasswdFile(filepath.Join(rootDir, "/etc/group"))
if err != nil {
return nil, nil, fmt.Errorf("parsing group file: %w", err)
}

return userMap, groupMap, nil
}

// parsePasswdFile reads a passwd-format file and returns a map of names to IDs.
func parsePasswdFile(path string) (map[string]string, error) {
idMap := make(map[string]string)

data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("reading file %s: %w", path, err)
}

for _, line := range strings.Split(string(data), "\n") {
if line == "" {
continue
}

fields := strings.Split(line, ":")
if len(fields) < 3 {
continue
}

idMap[fields[0]] = fields[2]
}

return idMap, nil
}

// isNumeric is a helper function to check if a string is numeric.
func isNumeric(s string) bool {
_, err := strconv.Atoi(s)
return err == nil
}
2 changes: 2 additions & 0 deletions shared/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ func GetLogger(debug bool) (*logrus.Logger, error) {
PadLevelText: true,
}

formatter.EnvironmentOverrideColors = true

logger.Formatter = &formatter

if debug {
Expand Down