From 49510f10a5aad442483383adbe991da953bc2c42 Mon Sep 17 00:00:00 2001 From: Mateus Melchiades Date: Sun, 12 Nov 2023 12:09:49 +0000 Subject: [PATCH 1/5] Uncapizalize errors, add missing error checking --- core/disk.go | 26 ++++++++++++++---------- core/filesystem.go | 48 ++++++++++++++++++++++---------------------- core/grub.go | 20 +++++++++--------- core/luks.go | 14 ++++++------- core/partition.go | 34 +++++++++++++++---------------- core/post_install.go | 30 +++++++++++++-------------- core/util.go | 6 +++--- 7 files changed, 91 insertions(+), 87 deletions(-) diff --git a/core/disk.go b/core/disk.go index e5dccee6..afda8975 100644 --- a/core/disk.go +++ b/core/disk.go @@ -2,6 +2,7 @@ package albius import ( "encoding/json" + "errors" "fmt" "os/exec" "strconv" @@ -31,14 +32,14 @@ func (disk *Disk) AvailableSectors() ([]Sector, error) { for i, part := range disk.Partitions { endInt, err := strconv.Atoi(part.End[:len(part.End)-3]) if err != nil { - return []Sector{}, fmt.Errorf("Failed to retrieve end position of partition: %s", err) + return []Sector{}, fmt.Errorf("failed to retrieve end position of partition: %s", err) } if i < len(disk.Partitions)-1 { nextStart := disk.Partitions[i+1].Start nextStartInt, err := strconv.Atoi(nextStart[:len(nextStart)-3]) if err != nil { - return []Sector{}, fmt.Errorf("Failed to retrieve start position of next partition: %s", err) + return []Sector{}, fmt.Errorf("failed to retrieve start position of next partition: %s", err) } if endInt != nextStartInt { @@ -51,11 +52,11 @@ func (disk *Disk) AvailableSectors() ([]Sector, error) { lastPartitionEndStr := disk.Partitions[len(disk.Partitions)-1].End lastPartitionEnd, err := strconv.Atoi(lastPartitionEndStr[:len(lastPartitionEndStr)-3]) if err != nil { - return []Sector{}, fmt.Errorf("Failed to retrieve end position of last partition: %s", err) + return []Sector{}, fmt.Errorf("failed to retrieve end position of last partition: %s", err) } diskEnd, err := strconv.Atoi(disk.Size[:len(disk.Size)-3]) if err != nil { - return []Sector{}, fmt.Errorf("Failed to retrieve disk end") + return []Sector{}, fmt.Errorf("failed to retrieve disk end") } if lastPartitionEnd < diskEnd { sectors = append(sectors, Sector{lastPartitionEnd, diskEnd}) @@ -73,7 +74,7 @@ func LocateDisk(diskname string) (*Disk, error) { cmd := exec.Command("sh", "-c", fmt.Sprintf(findPartitionCmd, diskname)) output, err := cmd.Output() if err != nil { - return nil, fmt.Errorf("Failed to list disk: %s", err) + return nil, fmt.Errorf("failed to list disk: %s", err) } var device *Disk @@ -83,11 +84,14 @@ func LocateDisk(diskname string) (*Disk, error) { // Try a different approach suitable for when the disk is unformatted var decodedMap map[string]map[string]interface{} err = json.Unmarshal(output, &decodedMap) + if err != nil { + return nil, errors.New("parted output contains invalid json") + } device := new(Disk) for k, v := range decodedMap["Disk"] { err := setField(device, k, v) if err != nil { - return nil, fmt.Errorf("Failed to decode parted output: %s", err) + return nil, fmt.Errorf("failed to decode parted output: %s", err) } } } else { @@ -95,7 +99,7 @@ func LocateDisk(diskname string) (*Disk, error) { } if device == nil { - return nil, fmt.Errorf("Could not find device %s", diskname) + return nil, fmt.Errorf("could not find device %s", diskname) } for i := 0; i < len(device.Partitions); i++ { @@ -128,13 +132,13 @@ func (disk *Disk) LabelDisk(label DiskLabel) error { for _, part := range disk.Partitions { if err := part.UmountPartition(); err != nil { - return fmt.Errorf("Failed to unmount partition %s: %s", part.Path, err) + return fmt.Errorf("failed to unmount partition %s: %s", part.Path, err) } } err := RunCommand(fmt.Sprintf(labelDiskCmd, disk.Path, label)) if err != nil { - return fmt.Errorf("Failed to label disk: %s", err) + return fmt.Errorf("failed to label disk: %s", err) } return nil @@ -170,13 +174,13 @@ func (target *Disk) NewPartition(name string, fsType PartitionFs, start, end int err := RunCommand(fmt.Sprintf(createPartCmd, target.Path, partType, partName, fsType, start, endStr)) if err != nil { - return nil, fmt.Errorf("Failed to create partition: %s", err) + return nil, fmt.Errorf("failed to create partition: %s", err) } // Update partition list because we made changes to the disk err = target.Update() if err != nil { - return nil, fmt.Errorf("Failed to create partition: %s", err) + return nil, fmt.Errorf("failed to create partition: %s", err) } newPartition := &target.Partitions[len(target.Partitions)-1] diff --git a/core/filesystem.go b/core/filesystem.go index 71475c5e..eb8e001e 100644 --- a/core/filesystem.go +++ b/core/filesystem.go @@ -25,7 +25,7 @@ func Unsquashfs(filesystem, destination string, force bool) error { cmd.Stderr = os.Stderr err := cmd.Run() if err != nil { - return fmt.Errorf("Failed to run unsquashfs: %s", err) + return fmt.Errorf("failed to run unsquashfs: %s", err) } return nil @@ -47,14 +47,14 @@ func MakeFs(part *Partition) error { makefsCmd := "mkswap -f %s" err = RunCommand(fmt.Sprintf(makefsCmd, part.Path)) case HFS, HFS_PLUS, UDF: - return fmt.Errorf("Unsupported filesystem: %s", part.Filesystem) + return fmt.Errorf("unsupported filesystem: %s", part.Filesystem) default: makefsCmd := "mkfs.%s -f %s" err = RunCommand(fmt.Sprintf(makefsCmd, part.Filesystem, part.Path)) } if err != nil { - return fmt.Errorf("Failed to make %s filesystem for %s: %s", part.Filesystem, part.Path, err) + return fmt.Errorf("failed to make %s filesystem for %s: %s", part.Filesystem, part.Path, err) } return nil @@ -95,36 +95,36 @@ func GenFstab(targetRoot string, entries [][]string) error { func UpdateInitramfs(root string) error { // Setup mountpoints if err := RunCommand(fmt.Sprintf("mount --bind /dev %s/dev", root)); err != nil { - return fmt.Errorf("Error mounting /dev to chroot: %s", err) + return fmt.Errorf("error mounting /dev to chroot: %s", err) } if err := RunCommand(fmt.Sprintf("mount --bind /dev/pts %s/dev/pts", root)); err != nil { - return fmt.Errorf("Error mounting /dev/pts to chroot: %s", err) + return fmt.Errorf("error mounting /dev/pts to chroot: %s", err) } if err := RunCommand(fmt.Sprintf("mount --bind /proc %s/proc", root)); err != nil { - return fmt.Errorf("Error mounting /proc to chroot: %s", err) + return fmt.Errorf("error mounting /proc to chroot: %s", err) } if err := RunCommand(fmt.Sprintf("mount --bind /sys %s/sys", root)); err != nil { - return fmt.Errorf("Error mounting /sys to chroot: %s", err) + return fmt.Errorf("error mounting /sys to chroot: %s", err) } updInitramfsCmd := "update-initramfs -c -k all" err := RunInChroot(root, updInitramfsCmd) if err != nil { - return fmt.Errorf("Failed to run update-initramfs command: %s", err) + return fmt.Errorf("failed to run update-initramfs command: %s", err) } if err := RunCommand(fmt.Sprintf("umount %s/dev/pts", root)); err != nil { - return fmt.Errorf("Error unmounting /dev/pts fron chroot: %s", err) + return fmt.Errorf("error unmounting /dev/pts fron chroot: %s", err) } if err := RunCommand(fmt.Sprintf("umount %s/dev", root)); err != nil { - return fmt.Errorf("Error unmounting /dev from chroot: %s", err) + return fmt.Errorf("error unmounting /dev from chroot: %s", err) } if err := RunCommand(fmt.Sprintf("umount %s/proc", root)); err != nil { - return fmt.Errorf("Error unmounting /proc from chroot: %s", err) + return fmt.Errorf("error unmounting /proc from chroot: %s", err) } if err := RunCommand(fmt.Sprintf("umount %s/sys", root)); err != nil { - return fmt.Errorf("Error unmounting /sys from chroot: %s", err) + return fmt.Errorf("error unmounting /sys from chroot: %s", err) } return nil @@ -145,7 +145,7 @@ func RunInChroot(root, command string) error { func OCISetup(imageSource, storagePath, destination string, verbose bool) error { pmt, err := prometheus.NewPrometheus(filepath.Join(storagePath, "storage"), "overlay", 0) if err != nil { - return fmt.Errorf("Failed to create Prometheus instance: %s", err) + return fmt.Errorf("failed to create Prometheus instance: %s", err) } // Create tmp directory in root's /var to store podman's temp files, since /var/tmp in @@ -153,29 +153,29 @@ func OCISetup(imageSource, storagePath, destination string, verbose bool) error storageTmpDir := filepath.Join(storagePath, "tmp") err = os.Mkdir(storageTmpDir, 0644) if err != nil { - return fmt.Errorf("Failed to create storage tmp dir: %s", err) + return fmt.Errorf("failed to create storage tmp dir: %s", err) } err = RunCommand(fmt.Sprintf("mount --bind %s %s", storageTmpDir, "/var/tmp")) if err != nil { - return fmt.Errorf("Failed to mount bind storage tmp dir: %s", err) + return fmt.Errorf("failed to mount bind storage tmp dir: %s", err) } storedImageName := strings.ReplaceAll(imageSource, "/", "-") manifest, err := pmt.PullImage(imageSource, storedImageName) if err != nil { - return fmt.Errorf("Failed to pull OCI image: %s", err) + return fmt.Errorf("failed to pull OCI image: %s", err) } fmt.Printf("Image pulled with digest %s\n", manifest.Config.Digest) image, err := pmt.GetImageByDigest(manifest.Config.Digest) if err != nil { - return fmt.Errorf("Failed to get image from digest: %s", err) + return fmt.Errorf("failed to get image from digest: %s", err) } mountPoint, err := pmt.MountImage(image.TopLayer) if err != nil { - return fmt.Errorf("Failed to mount image at %s: %s", image.TopLayer, err) + return fmt.Errorf("failed to mount image at %s: %s", image.TopLayer, err) } fmt.Printf("Image mounted at %s\n", mountPoint) @@ -191,35 +191,35 @@ func OCISetup(imageSource, storagePath, destination string, verbose bool) error } err = RunCommand(fmt.Sprintf("rsync -a%sxHAX --numeric-ids %s/ %s/", verboseFlag, mountPoint, destination)) if err != nil { - return fmt.Errorf("Failed to sync image contents to %s: %s", destination, err) + return fmt.Errorf("failed to sync image contents to %s: %s", destination, err) } // Remove storage from destination err = RunCommand(fmt.Sprintf("umount -l %s/storage/graph/overlay", storagePath)) if err != nil { - return fmt.Errorf("Failed to unmount image: %s", err) + return fmt.Errorf("failed to unmount image: %s", err) } // Unmount tmp storage directory err = RunCommand("umount -l /var/tmp") if err != nil { - return fmt.Errorf("Failed to unmount storage tmp dir: %s", err) + return fmt.Errorf("failed to unmount storage tmp dir: %s", err) } entries, err := os.ReadDir(storageTmpDir) if err != nil { - return fmt.Errorf("Failed to read from storage tmp dir: %s", err) + return fmt.Errorf("failed to read from storage tmp dir: %s", err) } for _, entry := range entries { err = os.RemoveAll(filepath.Join(storageTmpDir, entry.Name())) if err != nil { - return fmt.Errorf("Failed to remove %s from storage tmp dir: %s", entry.Name(), err) + return fmt.Errorf("failed to remove %s from storage tmp dir: %s", entry.Name(), err) } } // Store the digest in destination as it may be used by the update manager err = os.WriteFile(filepath.Join(destination, ".oci_digest"), []byte(manifest.Config.Digest), 0644) if err != nil { - return fmt.Errorf("Failed to save digest in %s: %s", destination, err) + return fmt.Errorf("failed to save digest in %s: %s", destination, err) } return nil diff --git a/core/grub.go b/core/grub.go index f01de9c6..b51c82ba 100644 --- a/core/grub.go +++ b/core/grub.go @@ -28,7 +28,7 @@ func GetGrubConfig(targetRoot string) (GrubConfig, error) { content, err := os.ReadFile(targetRootGrubFile) if err != nil { - return nil, fmt.Errorf("Failed to read GRUB config file: %s", err) + return nil, fmt.Errorf("failed to read GRUB config file: %s", err) } config := GrubConfig{} @@ -54,7 +54,7 @@ func WriteGrubConfig(targetRoot string, config GrubConfig) error { targetRootGrubFile := filepath.Join(targetRoot, "/etc/default/grub") err := os.WriteFile(targetRootGrubFile, fileContents, 0644) if err != nil { - return fmt.Errorf("Failed to write GRUB config file: %s", err) + return fmt.Errorf("failed to write GRUB config file: %s", err) } return nil @@ -63,18 +63,18 @@ func WriteGrubConfig(targetRoot string, config GrubConfig) error { func AddGrubScript(targetRoot, scriptPath string) error { // Ensure script exists if _, err := os.Stat(scriptPath); os.IsNotExist(err) { - return fmt.Errorf("Error adding GRUB script: %s does not exist", scriptPath) + return fmt.Errorf("error adding GRUB script: %s does not exist", scriptPath) } contents, err := os.ReadFile(scriptPath) if err != nil { - return fmt.Errorf("Failed to read GRUB script at %s: %s", scriptPath, err) + return fmt.Errorf("failed to read GRUB script at %s: %s", scriptPath, err) } targetRootPath := filepath.Join(targetRoot, "/etc/grub.d", filepath.Base(scriptPath)) err = os.WriteFile(targetRootPath, contents, 0755) // Grub expects script to be executable if err != nil { - return fmt.Errorf("Failed to writing GRUB script to %s: %s", targetRootPath, err) + return fmt.Errorf("failed to writing GRUB script to %s: %s", targetRootPath, err) } return nil @@ -85,12 +85,12 @@ func RemoveGrubScript(targetRoot, scriptName string) error { // Ensure script exists if _, err := os.Stat(targetRootPath); os.IsNotExist(err) { - return fmt.Errorf("Error removing GRUB script: %s does not exist", targetRootPath) + return fmt.Errorf("error removing GRUB script: %s does not exist", targetRootPath) } err := os.Remove(targetRootPath) if err != nil { - return fmt.Errorf("Error removing GRUB script: %s", err) + return fmt.Errorf("error removing GRUB script: %s", err) } return nil @@ -104,7 +104,7 @@ func RunGrubInstall(targetRoot, bootDirectory, diskPath string, target FirmwareT targetBind := filepath.Join(targetRoot, bind) err := RunCommand(fmt.Sprintf("mount --bind %s %s", bind, targetBind)) if err != nil { - return fmt.Errorf("Failed to mount %s to %s: %s", bind, targetRoot, err) + return fmt.Errorf("failed to mount %s to %s: %s", bind, targetRoot, err) } } } @@ -118,7 +118,7 @@ func RunGrubInstall(targetRoot, bootDirectory, diskPath string, target FirmwareT err = RunCommand(fmt.Sprintf(grubInstallCmd, bootDirectory, target, diskPath)) } if err != nil { - return fmt.Errorf("Failed to run grub-install: %s", err) + return fmt.Errorf("failed to run grub-install: %s", err) } if targetRoot != "" { @@ -138,7 +138,7 @@ func RunGrubInstall(targetRoot, bootDirectory, diskPath string, target FirmwareT part := partExpr.FindString(efiDevice[0]) err = RunCommand(fmt.Sprintf(efibootmgrCmd, diskName, part)) if err != nil { - return fmt.Errorf("Failed to run grub-install: %s", err) + return fmt.Errorf("failed to run grub-install: %s", err) } } diff --git a/core/luks.go b/core/luks.go index 51d05a8d..9c6acce0 100644 --- a/core/luks.go +++ b/core/luks.go @@ -20,7 +20,7 @@ func IsLuks(part *Partition) (bool, error) { return false, nil } } - return false, fmt.Errorf("Failed to check if %s is LUKS-encrypted: %s", part.Path, err) + return false, fmt.Errorf("failed to check if %s is LUKS-encrypted: %s", part.Path, err) } return true, nil @@ -51,7 +51,7 @@ func LuksOpen(part *Partition, mapping, password string) error { err := RunCommand(fmt.Sprintf(luksOpenCmd, part.Path, mapping)) if err != nil { - return fmt.Errorf("Failed to open LUKS-encrypted partition: %s", err) + return fmt.Errorf("failed to open LUKS-encrypted partition: %s", err) } return nil @@ -70,7 +70,7 @@ func LuksTryOpen(part *Partition, mapping, password string) error { } else if os.IsNotExist(err) { return LuksOpen(part, mapping, password) } else { - return fmt.Errorf("Failed to try-open LUKS-encrypted partition: %s", err) + return fmt.Errorf("failed to try-open LUKS-encrypted partition: %s", err) } } @@ -79,7 +79,7 @@ func LuksClose(mapping string) error { err := RunCommand(fmt.Sprintf(luksCloseCmd, mapping)) if err != nil { - return fmt.Errorf("Failed to close LUKS-encrypted partition: %s", err) + return fmt.Errorf("failed to close LUKS-encrypted partition: %s", err) } return nil @@ -90,7 +90,7 @@ func LuksFormat(part *Partition, password string) error { err := RunCommand(fmt.Sprintf(luksFormatCmd, password, part.Path)) if err != nil { - return fmt.Errorf("Failed to create LUKS-encrypted partition: %s", err) + return fmt.Errorf("failed to create LUKS-encrypted partition: %s", err) } return nil @@ -121,7 +121,7 @@ func GetLUKSFilesystemByPath(path string) (string, error) { cmd := exec.Command("sh", "-c", fmt.Sprintf(lsblkCmd, path)) output, err := cmd.Output() if err != nil { - return "", fmt.Errorf("Failed to get encrypted partition FSTYPE: %s", err) + return "", fmt.Errorf("failed to get encrypted partition FSTYPE: %s", err) } return string(output[:len(output)-1]), nil @@ -155,4 +155,4 @@ func LUKSSetLabel(part *Partition, name string) error { innerPartition.Filesystem = part.Filesystem return innerPartition.SetLabel(name) -} \ No newline at end of file +} diff --git a/core/partition.go b/core/partition.go index 20de572c..fc41d1f9 100644 --- a/core/partition.go +++ b/core/partition.go @@ -65,7 +65,7 @@ func (part *Partition) Mount(location string) error { cmd := exec.Command("sh", "-c", fmt.Sprintf(checkPartCmd, mountPath)) output, err := cmd.Output() if err != nil { - return fmt.Errorf("Failed to locate partition %s: %s", mountPath, err) + return fmt.Errorf("failed to locate partition %s: %s", mountPath, err) } if strings.Contains(string(output), location) { return nil @@ -73,7 +73,7 @@ func (part *Partition) Mount(location string) error { err = RunCommand(fmt.Sprintf(mountCmd, mountPath, location)) if err != nil { - return fmt.Errorf("Failed to run mount command: %s", err) + return fmt.Errorf("failed to run mount command: %s", err) } return nil @@ -85,12 +85,12 @@ func (part *Partition) IsMounted() (bool, error) { cmd := exec.Command("sh", "-c", fmt.Sprintf(isMountedCmd, part.Path)) output, err := cmd.Output() if err != nil { - return false, fmt.Errorf("Failed to check if partition is mounted: %s", err) + return false, fmt.Errorf("failed to check if partition is mounted: %s", err) } mounts, err := strconv.Atoi(strings.TrimSpace(string(output))) if err != nil { - return false, fmt.Errorf("Failed to convert str to int: %s", err) + return false, fmt.Errorf("failed to convert str to int: %s", err) } if mounts > 0 { @@ -139,7 +139,7 @@ func (part *Partition) UmountPartition() error { err = RunCommand(fmt.Sprintf(umountCmd, mountTarget)) if err != nil { - return fmt.Errorf("Failed to run umount command: %s", err) + return fmt.Errorf("failed to run umount command: %s", err) } return nil @@ -150,7 +150,7 @@ func UmountDirectory(dir string) error { err := RunCommand(fmt.Sprintf(umountCmd, dir)) if err != nil { - return fmt.Errorf("Failed to run umount command: %s", err) + return fmt.Errorf("failed to run umount command: %s", err) } return nil @@ -166,7 +166,7 @@ func (target *Partition) RemovePartition() error { err := RunCommand(fmt.Sprintf(rmPartCmd, disk, part)) if err != nil { - return fmt.Errorf("Failed to remove partition: %s", err) + return fmt.Errorf("failed to remove partition: %s", err) } return nil @@ -182,7 +182,7 @@ func (target *Partition) ResizePartition(newEnd int) error { err := RunCommand(fmt.Sprintf(resizePartCmd, disk, part, newEnd)) if err != nil { - return fmt.Errorf("Failed to resize partition: %s", err) + return fmt.Errorf("failed to resize partition: %s", err) } return nil @@ -198,7 +198,7 @@ func (target *Partition) NamePartition(name string) error { err := RunCommand(fmt.Sprintf(namePartCmd, disk, part, name)) if err != nil { - return fmt.Errorf("Failed to name partition: %s", err) + return fmt.Errorf("failed to name partition: %s", err) } return nil @@ -221,7 +221,7 @@ func (target *Partition) SetPartitionFlag(flag string, state bool) error { err := RunCommand(fmt.Sprintf(setPartCmd, disk, part, flag, stateStr)) if err != nil { - return fmt.Errorf("Failed to name partition: %s", err) + return fmt.Errorf("failed to name partition: %s", err) } return nil @@ -243,7 +243,7 @@ func (target *Partition) GetUUID() (string, error) { cmd := exec.Command("sh", "-c", fmt.Sprintf(lsblkCmd, target.Path)) output, err := cmd.Output() if err != nil { - return "", fmt.Errorf("Failed to get partition UUID: %s", err) + return "", fmt.Errorf("failed to get partition UUID: %s", err) } return string(output[:len(output)-1]), nil @@ -255,7 +255,7 @@ func GetUUIDByPath(path string) (string, error) { cmd := exec.Command("sh", "-c", fmt.Sprintf(lsblkCmd, path)) output, err := cmd.Output() if err != nil { - return "", fmt.Errorf("Failed to get partition UUID: %s", err) + return "", fmt.Errorf("failed to get partition UUID: %s", err) } return string(output[:len(output)-1]), nil @@ -267,7 +267,7 @@ func GetFilesystemByPath(path string) (string, error) { cmd := exec.Command("sh", "-c", fmt.Sprintf(lsblkCmd, path)) output, err := cmd.Output() if err != nil { - return "", fmt.Errorf("Failed to get partition FSTYPE: %s", err) + return "", fmt.Errorf("failed to get partition FSTYPE: %s", err) } return string(output[:len(output)-1]), nil @@ -280,7 +280,7 @@ func (part *Partition) GetLUKSMapperPath() (string, error) { return "", err } if !luks { - return "", fmt.Errorf("Cannot get mapper path for %s. Partition is not LUKS-formatted", part.Path) + return "", fmt.Errorf("cannot get mapper path for %s. Partition is not LUKS-formatted", part.Path) } partUUID, err := part.GetUUID() @@ -300,7 +300,7 @@ func (part *Partition) SetLabel(label string) error { case BTRFS: labelCmd = fmt.Sprintf("btrfs filesystem label %s %s", part.Path, label) case REISERFS: - labelCmd = fmt.Sprintf("reiserfstune –l %s %s", label, part.Path) + labelCmd = fmt.Sprintf("reiserfstune -l %s %s", label, part.Path) case XFS: labelCmd = fmt.Sprintf("xfs_admin -L %s %s", label, part.Path) case LINUX_SWAP: @@ -308,12 +308,12 @@ func (part *Partition) SetLabel(label string) error { case NTFS: labelCmd = fmt.Sprintf("ntfslabel %s %s", part.Path, label) default: - return fmt.Errorf("Unsupported filesystem: %s", part.Filesystem) + return fmt.Errorf("unsupported filesystem: %s", part.Filesystem) } err := RunCommand(labelCmd) if err != nil { - return fmt.Errorf("Failed to label partition %s: %s", part.Path, err) + return fmt.Errorf("failed to label partition %s: %s", part.Path, err) } return nil diff --git a/core/post_install.go b/core/post_install.go index 8666eb02..eb901648 100644 --- a/core/post_install.go +++ b/core/post_install.go @@ -13,7 +13,7 @@ func SetTimezone(targetRoot, tz string) error { err := os.WriteFile(tzPath, []byte(tz), 0644) if err != nil { - return fmt.Errorf("Failed to set timezone: %s", err) + return fmt.Errorf("failed to set timezone: %s", err) } linkZoneinfoCmd := "ln -sf /usr/share/zoneinfo/%s /etc/localtime" @@ -23,7 +23,7 @@ func SetTimezone(targetRoot, tz string) error { err = RunCommand(fmt.Sprintf(linkZoneinfoCmd, tz)) } if err != nil { - return fmt.Errorf("Failed to set timezone: %s", err) + return fmt.Errorf("failed to set timezone: %s", err) } return nil @@ -39,13 +39,13 @@ func AddUser(targetRoot, username, fullname string, groups []string, withPasswor err = RunCommand(fmt.Sprintf(adduserCmd, username, fullname, username)) } if err != nil { - return fmt.Errorf("Failed to create user: %s", err) + return fmt.Errorf("failed to create user: %s", err) } if withPassword { passwdCmd := "echo \"%s:%s\" | chpasswd" if len(password) < 1 { - return fmt.Errorf("Password was not provided") + return fmt.Errorf("password was not provided") } if targetRoot != "" { @@ -54,7 +54,7 @@ func AddUser(targetRoot, username, fullname string, groups []string, withPasswor err = RunCommand(fmt.Sprintf(passwdCmd, username, password[0])) } if err != nil { - return fmt.Errorf("Failed to set password: %s", err) + return fmt.Errorf("failed to set password: %s", err) } } @@ -76,7 +76,7 @@ func AddUser(targetRoot, username, fullname string, groups []string, withPasswor err = RunCommand(fmt.Sprintf(addGroupCmd, groupList, username)) } if err != nil { - return fmt.Errorf("Failed to set password: %s", err) + return fmt.Errorf("failed to set password: %s", err) } return nil @@ -85,7 +85,7 @@ func AddUser(targetRoot, username, fullname string, groups []string, withPasswor func RemovePackages(targetRoot, pkgRemovePath, removeCmd string) error { pkgRemoveContent, err := os.ReadFile(pkgRemovePath) if err != nil { - return fmt.Errorf("Failed to read package removal file: %s", err) + return fmt.Errorf("failed to read package removal file: %s", err) } pkgList := strings.Replace(string(pkgRemoveContent), "\n", " ", -1) @@ -103,7 +103,7 @@ func ChangeHostname(targetRoot, hostname string) error { cmd := exec.Command("sh", "-c", fmt.Sprintf(replaceHostnameCmd, hostname, targetRoot)) err := cmd.Run() if err != nil { - return fmt.Errorf("Failed to change hostname: %s", err) + return fmt.Errorf("failed to change hostname: %s", err) } hostsContents := `127.0.0.1 localhost @@ -113,7 +113,7 @@ func ChangeHostname(targetRoot, hostname string) error { hostsPath := targetRoot + "/etc/hosts" err = os.WriteFile(hostsPath, []byte(fmt.Sprintf(hostsContents, hostname, hostname)), 0644) if err != nil { - return fmt.Errorf("Failed to change hosts file: %s", err) + return fmt.Errorf("failed to change hosts file: %s", err) } return nil @@ -122,12 +122,12 @@ func ChangeHostname(targetRoot, hostname string) error { func SetLocale(targetRoot, locale string) error { err := RunCommand(fmt.Sprintf("grep %s %s/usr/share/i18n/SUPPORTED", locale, targetRoot)) if err != nil { - return fmt.Errorf("Locale %s is invalid", locale) + return fmt.Errorf("locale %s is invalid", locale) } err = RunCommand(fmt.Sprintf("sed -i 's/^\\# \\(%s\\)/\\1/' %s/etc/locale.gen", regexp.QuoteMeta(locale), targetRoot)) if err != nil { - return fmt.Errorf("Failed to set locale: %s", err) + return fmt.Errorf("failed to set locale: %s", err) } localeGenCmd := "locale-gen" @@ -137,7 +137,7 @@ func SetLocale(targetRoot, locale string) error { err = RunCommand(localeGenCmd) } if err != nil { - return fmt.Errorf("Failed to set locale: %s", err) + return fmt.Errorf("failed to set locale: %s", err) } localeContents := `LANG=__lang__ @@ -154,7 +154,7 @@ LC_IDENTIFICATION=__lang__ localePath := targetRoot + "/etc/default/locale" err = os.WriteFile(localePath, []byte(strings.ReplaceAll(localeContents, "__lang__", locale)), 0644) if err != nil { - return fmt.Errorf("Failed to set locale: %s", err) + return fmt.Errorf("failed to set locale: %s", err) } return nil @@ -182,7 +182,7 @@ BACKSPACE="guess" keyboardPath := targetRoot + "/etc/default/keyboard" err := os.WriteFile(keyboardPath, []byte(fmt.Sprintf(keyboardContents, kbModel, kbLayout, kbVariant)), 0644) if err != nil { - return fmt.Errorf("Failed to set keyboard layout: %s", err) + return fmt.Errorf("failed to set keyboard layout: %s", err) } if targetRoot != "" { @@ -191,7 +191,7 @@ BACKSPACE="guess" err = RunCommand("setupcon --save-only") } if err != nil { - return fmt.Errorf("Failed to set keyboard layout: %s", err) + return fmt.Errorf("failed to set keyboard layout: %s", err) } return nil diff --git a/core/util.go b/core/util.go index eb056d2f..98556902 100644 --- a/core/util.go +++ b/core/util.go @@ -19,11 +19,11 @@ func setField(obj interface{}, name string, value interface{}) error { structFieldValue := structValue.FieldByName(name) if !structFieldValue.IsValid() { - return fmt.Errorf("No such field: %s in obj", name) + return fmt.Errorf("no such field: %s in obj", name) } if !structFieldValue.CanSet() { - return fmt.Errorf("Cannot set %s field value", name) + return fmt.Errorf("cannot set %s field value", name) } structFieldType := structFieldValue.Type() @@ -36,7 +36,7 @@ func setField(obj interface{}, name string, value interface{}) error { } else if structFieldType.Name() == "DiskLabel" && val.Type().Kind() == reflect.String { convertedVal = reflect.ValueOf(DiskLabel(val.Interface().(string))) } else { - return fmt.Errorf("Provided value type for %s did not match obj field type. Expected %v, got %v.", name, structFieldType, val.Type()) + return fmt.Errorf("provided value type for %s did not match obj field type. Expected %v, got %v", name, structFieldType, val.Type()) } } else { convertedVal = val From a02bba06253396d63cd758225ee9620379c1a07d Mon Sep 17 00:00:00 2001 From: Mateus Melchiades Date: Sun, 12 Nov 2023 09:18:43 -0300 Subject: [PATCH 2/5] Improve RunCommand error output --- core/util.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/core/util.go b/core/util.go index 98556902..6c12150b 100644 --- a/core/util.go +++ b/core/util.go @@ -1,17 +1,27 @@ package albius import ( + "errors" "fmt" "os" "os/exec" "reflect" ) +// RunCommand executes a command in a subshell. func RunCommand(command string) error { cmd := exec.Command("sh", "-c", command) cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - return cmd.Run() + err := cmd.Run() + + exitErr, ok := err.(*exec.ExitError) + if err != nil && ok { + return errors.New(string(exitErr.Stderr)) + } else if err != nil { + return err + } + + return nil } func setField(obj interface{}, name string, value interface{}) error { From a3ebb4061da4978778969939fbaa1d9b95021fe7 Mon Sep 17 00:00:00 2001 From: Mateus Melchiades Date: Sun, 12 Nov 2023 11:45:41 -0300 Subject: [PATCH 3/5] Code cleanup --- core/disk.go | 20 +++--- core/filesystem.go | 52 ++++---------- core/grub.go | 6 +- core/luks.go | 15 +++-- core/partition.go | 100 +++++++++------------------ core/post_install.go | 46 +++++-------- core/recipe.go | 157 +++++++++++++++++++++---------------------- core/util.go | 54 +++++++++++++-- 8 files changed, 205 insertions(+), 245 deletions(-) diff --git a/core/disk.go b/core/disk.go index afda8975..59ebe0d3 100644 --- a/core/disk.go +++ b/core/disk.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "os/exec" "strconv" ) @@ -65,25 +64,22 @@ func (disk *Disk) AvailableSectors() ([]Sector, error) { return sectors, nil } -type LocateDiskOutput struct { - Disk Disk -} - func LocateDisk(diskname string) (*Disk, error) { - findPartitionCmd := "parted -sj %s unit MiB print | sed -r 's/^(\\s*)\"(.)/\\1\"\\U\\2/g' | sed -r 's/(\\S)-(\\S)/\\1\\U\\2/g'" - cmd := exec.Command("sh", "-c", fmt.Sprintf(findPartitionCmd, diskname)) - output, err := cmd.Output() + findPartitionCmd := "parted -sj %s unit MiB print" + output, err := OutputCommand(fmt.Sprintf(findPartitionCmd, diskname)) if err != nil { return nil, fmt.Errorf("failed to list disk: %s", err) } var device *Disk - var decoded *LocateDiskOutput - err = json.Unmarshal(output, &decoded) + var decoded struct { + Disk Disk + } + err = json.Unmarshal([]byte(output), &decoded) if err != nil { // Try a different approach suitable for when the disk is unformatted var decodedMap map[string]map[string]interface{} - err = json.Unmarshal(output, &decodedMap) + err = json.Unmarshal([]byte(output), &decodedMap) if err != nil { return nil, errors.New("parted output contains invalid json") } @@ -131,7 +127,7 @@ func (disk *Disk) LabelDisk(label DiskLabel) error { labelDiskCmd := "parted -s %s mklabel %s" for _, part := range disk.Partitions { - if err := part.UmountPartition(); err != nil { + if err := part.UnmountPartition(); err != nil { return fmt.Errorf("failed to unmount partition %s: %s", part.Path, err) } } diff --git a/core/filesystem.go b/core/filesystem.go index eb8e001e..84289395 100644 --- a/core/filesystem.go +++ b/core/filesystem.go @@ -3,7 +3,6 @@ package albius import ( "fmt" "os" - "os/exec" "path/filepath" "strings" @@ -20,10 +19,7 @@ func Unsquashfs(filesystem, destination string, force bool) error { forceFlag = "" } - cmd := exec.Command("sh", "-c", fmt.Sprintf(unsquashfsCmd, forceFlag, destination, filesystem)) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - err := cmd.Run() + err := RunCommand(fmt.Sprintf(unsquashfsCmd, forceFlag, destination, filesystem)) if err != nil { return fmt.Errorf("failed to run unsquashfs: %s", err) } @@ -94,49 +90,25 @@ func GenFstab(targetRoot string, entries [][]string) error { func UpdateInitramfs(root string) error { // Setup mountpoints - if err := RunCommand(fmt.Sprintf("mount --bind /dev %s/dev", root)); err != nil { - return fmt.Errorf("error mounting /dev to chroot: %s", err) - } - if err := RunCommand(fmt.Sprintf("mount --bind /dev/pts %s/dev/pts", root)); err != nil { - return fmt.Errorf("error mounting /dev/pts to chroot: %s", err) - } - if err := RunCommand(fmt.Sprintf("mount --bind /proc %s/proc", root)); err != nil { - return fmt.Errorf("error mounting /proc to chroot: %s", err) - } - if err := RunCommand(fmt.Sprintf("mount --bind /sys %s/sys", root)); err != nil { - return fmt.Errorf("error mounting /sys to chroot: %s", err) + mountOrder := []string{"/dev", "/dev/pts", "/proc", "/sys"} + for _, mount := range mountOrder { + if err := RunCommand(fmt.Sprintf("mount --bind %s %s%s", mount, root, mount)); err != nil { + return fmt.Errorf("error mounting %s to chroot: %s", mount, err) + } } updInitramfsCmd := "update-initramfs -c -k all" - err := RunInChroot(root, updInitramfsCmd) if err != nil { return fmt.Errorf("failed to run update-initramfs command: %s", err) } - if err := RunCommand(fmt.Sprintf("umount %s/dev/pts", root)); err != nil { - return fmt.Errorf("error unmounting /dev/pts fron chroot: %s", err) - } - if err := RunCommand(fmt.Sprintf("umount %s/dev", root)); err != nil { - return fmt.Errorf("error unmounting /dev from chroot: %s", err) - } - if err := RunCommand(fmt.Sprintf("umount %s/proc", root)); err != nil { - return fmt.Errorf("error unmounting /proc from chroot: %s", err) - } - if err := RunCommand(fmt.Sprintf("umount %s/sys", root)); err != nil { - return fmt.Errorf("error unmounting /sys from chroot: %s", err) - } - - return nil -} - -func RunInChroot(root, command string) error { - cmd := exec.Command("chroot", root, "sh", "-c", command) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - err := cmd.Run() - if err != nil { - return err + // Cleanup mountpoints + unmountOrder := []string{"/dev/pts", "/dev", "/proc", "/sys"} + for _, mount := range unmountOrder { + if err := RunCommand(fmt.Sprintf("umount %s%s", root, mount)); err != nil { + return fmt.Errorf("error unmounting %s fron chroot: %s", mount, err) + } } return nil diff --git a/core/grub.go b/core/grub.go index b51c82ba..bd6385cf 100644 --- a/core/grub.go +++ b/core/grub.go @@ -5,7 +5,6 @@ import ( "fmt" "os" "path/filepath" - "regexp" "strings" ) @@ -129,13 +128,10 @@ func RunGrubInstall(targetRoot, bootDirectory, diskPath string, target FirmwareT // base, consider keeping it. if target == EFI { efibootmgrCmd := "efibootmgr --create --disk=%s --part=%s --label=vanilla --loader=\"\\EFI\\debian\\shimx64.efi\"" - diskExpr := regexp.MustCompile("^/dev/[a-zA-Z]+([0-9]+[a-z][0-9]+)?") - partExpr := regexp.MustCompile("[0-9]+$") if len(efiDevice) == 0 || efiDevice[0] == "" { return errors.New("EFI device was not specified") } - diskName := diskExpr.FindString(efiDevice[0]) - part := partExpr.FindString(efiDevice[0]) + diskName, part := SeparateDiskPart(efiDevice[0]) err = RunCommand(fmt.Sprintf(efibootmgrCmd, diskName, part)) if err != nil { return fmt.Errorf("failed to run grub-install: %s", err) diff --git a/core/luks.go b/core/luks.go index 9c6acce0..1ee6750e 100644 --- a/core/luks.go +++ b/core/luks.go @@ -13,11 +13,12 @@ func IsLuks(part *Partition) (bool, error) { cmd := exec.Command("sh", "-c", fmt.Sprintf(isLuksCmd, part.Path)) err := cmd.Run() if err != nil { - // We expect the command to return exit status 1 if partition isn't - // LUKS-encrypted + // We expect the command to return exit status 1 if partition isn't LUKS-encrypted if exitError, ok := err.(*exec.ExitError); ok { if exitError.ExitCode() == 1 { return false, nil + } else { + return false, fmt.Errorf("failed to check if %s is LUKS-encrypted: %s", part.Path, string(exitError.Stderr)) } } return false, fmt.Errorf("failed to check if %s is LUKS-encrypted: %s", part.Path, err) @@ -35,8 +36,10 @@ func IsPathLuks(path string) (bool, error) { // LuksOpen opens a LUKS-encrypted partition, mapping the unencrypted filesystem // to /dev/mapper/. +// // If password is an empty string, cryptsetup will prompt the password when // executed. +// // WARNING: This function will return an error if mapping already exists, use // LuksTryOpen() to open a device while ignoring existing mappings func LuksOpen(part *Partition, mapping, password string) error { @@ -59,9 +62,11 @@ func LuksOpen(part *Partition, mapping, password string) error { // LuksTryOpen opens a LUKS-encrypted partition, failing silently if mapping // already exists. +// // This is useful for when we pass a mapping like "luks-", which we are // certain is unique and the operation failing means that the device is already // open. +// // The function still returns other errors, however. func LuksTryOpen(part *Partition, mapping, password string) error { _, err := os.Stat(fmt.Sprintf("/dev/mapper/%s", mapping)) @@ -117,14 +122,12 @@ func GenCrypttab(targetRoot string, entries [][]string) error { func GetLUKSFilesystemByPath(path string) (string, error) { lsblkCmd := "lsblk -n -o FSTYPE %s | sed '/crypto_LUKS/d'" - - cmd := exec.Command("sh", "-c", fmt.Sprintf(lsblkCmd, path)) - output, err := cmd.Output() + output, err := OutputCommand(fmt.Sprintf(lsblkCmd, path)) if err != nil { return "", fmt.Errorf("failed to get encrypted partition FSTYPE: %s", err) } - return string(output[:len(output)-1]), nil + return output, nil } // LUKSMakeFs creates a filesystem inside of a LUKS-formatted partition. Use diff --git a/core/partition.go b/core/partition.go index fc41d1f9..21e84190 100644 --- a/core/partition.go +++ b/core/partition.go @@ -2,9 +2,7 @@ package albius import ( "fmt" - "os/exec" - "regexp" - "strconv" + "slices" "strings" ) @@ -58,19 +56,16 @@ func (part *Partition) Mount(location string) error { mountPath = part.Path } - mountCmd := "mount -m %s %s" - - // Check if device is already mounted at location - checkPartCmd := "lsblk -n -o MOUNTPOINTS %s" - cmd := exec.Command("sh", "-c", fmt.Sprintf(checkPartCmd, mountPath)) - output, err := cmd.Output() + // Check if partition is already mounted at location + mountpoints, err := part.Mountpoints() if err != nil { - return fmt.Errorf("failed to locate partition %s: %s", mountPath, err) + return err } - if strings.Contains(string(output), location) { + if slices.Contains(mountpoints, location) { return nil } + mountCmd := "mount -m %s %s" err = RunCommand(fmt.Sprintf(mountCmd, mountPath, location)) if err != nil { return fmt.Errorf("failed to run mount command: %s", err) @@ -79,28 +74,26 @@ func (part *Partition) Mount(location string) error { return nil } -func (part *Partition) IsMounted() (bool, error) { - isMountedCmd := "mount | grep %s | wc -l" - - cmd := exec.Command("sh", "-c", fmt.Sprintf(isMountedCmd, part.Path)) - output, err := cmd.Output() +func (part *Partition) Mountpoints() ([]string, error) { + mountpointsCmd := "lsblk -n -o MOUNTPOINTS %s" + output, err := OutputCommand(fmt.Sprintf(mountpointsCmd, part.Path)) if err != nil { - return false, fmt.Errorf("failed to check if partition is mounted: %s", err) + return []string{}, fmt.Errorf("failed to list mountpoints for %s: %s", part.Path, err) } - mounts, err := strconv.Atoi(strings.TrimSpace(string(output))) - if err != nil { - return false, fmt.Errorf("failed to convert str to int: %s", err) - } + return strings.Split(output, "\n"), nil +} - if mounts > 0 { - return true, nil +func (part *Partition) IsMounted() (bool, error) { + mountpoints, err := part.Mountpoints() + if err != nil { + return false, err } - return false, nil + return len(mountpoints) > 0, nil } -func (part *Partition) UmountPartition() error { +func (part *Partition) UnmountPartition() error { var mountTarget string // Check if partition is mounted first @@ -136,7 +129,6 @@ func (part *Partition) UmountPartition() error { } umountCmd := "umount %s" - err = RunCommand(fmt.Sprintf(umountCmd, mountTarget)) if err != nil { return fmt.Errorf("failed to run umount command: %s", err) @@ -145,7 +137,7 @@ func (part *Partition) UmountPartition() error { return nil } -func UmountDirectory(dir string) error { +func UnmountDirectory(dir string) error { umountCmd := "umount %s" err := RunCommand(fmt.Sprintf(umountCmd, dir)) @@ -157,13 +149,8 @@ func UmountDirectory(dir string) error { } func (target *Partition) RemovePartition() error { + disk, part := SeparateDiskPart(target.Path) rmPartCmd := "parted -s %s rm %s" - - diskExpr := regexp.MustCompile("^/dev/[a-zA-Z]+([0-9]+[a-z][0-9]+)?") - partExpr := regexp.MustCompile("[0-9]+$") - disk := diskExpr.FindString(target.Path) - part := partExpr.FindString(target.Path) - err := RunCommand(fmt.Sprintf(rmPartCmd, disk, part)) if err != nil { return fmt.Errorf("failed to remove partition: %s", err) @@ -173,13 +160,8 @@ func (target *Partition) RemovePartition() error { } func (target *Partition) ResizePartition(newEnd int) error { + disk, part := SeparateDiskPart(target.Path) resizePartCmd := "parted -s %s unit MiB resizepart %s %d" - - diskExpr := regexp.MustCompile("^/dev/[a-zA-Z]+([0-9]+[a-z][0-9]+)?") - partExpr := regexp.MustCompile("[0-9]+$") - disk := diskExpr.FindString(target.Path) - part := partExpr.FindString(target.Path) - err := RunCommand(fmt.Sprintf(resizePartCmd, disk, part, newEnd)) if err != nil { return fmt.Errorf("failed to resize partition: %s", err) @@ -189,13 +171,8 @@ func (target *Partition) ResizePartition(newEnd int) error { } func (target *Partition) NamePartition(name string) error { + disk, part := SeparateDiskPart(target.Path) namePartCmd := "parted -s %s name %s %s" - - diskExpr := regexp.MustCompile("^/dev/[a-zA-Z]+([0-9]+[a-z][0-9]+)?") - partExpr := regexp.MustCompile("[0-9]+$") - disk := diskExpr.FindString(target.Path) - part := partExpr.FindString(target.Path) - err := RunCommand(fmt.Sprintf(namePartCmd, disk, part, name)) if err != nil { return fmt.Errorf("failed to name partition: %s", err) @@ -205,20 +182,13 @@ func (target *Partition) NamePartition(name string) error { } func (target *Partition) SetPartitionFlag(flag string, state bool) error { - setPartCmd := "parted -s %s set %s %s %s" - - var stateStr string - if !state { - stateStr = "off" - } else { + stateStr := "off" + if state { stateStr = "on" } - diskExpr := regexp.MustCompile("^/dev/[a-zA-Z]+([0-9]+[a-z][0-9]+)?") - partExpr := regexp.MustCompile("[0-9]+$") - disk := diskExpr.FindString(target.Path) - part := partExpr.FindString(target.Path) - + disk, part := SeparateDiskPart(target.Path) + setPartCmd := "parted -s %s set %s %s %s" err := RunCommand(fmt.Sprintf(setPartCmd, disk, part, flag, stateStr)) if err != nil { return fmt.Errorf("failed to name partition: %s", err) @@ -229,8 +199,7 @@ func (target *Partition) SetPartitionFlag(flag string, state bool) error { func (target *Partition) FillPath(basePath string) { targetPathEnd := basePath[len(basePath)-1] - // "0" "9" - if targetPathEnd >= 48 && targetPathEnd <= 57 { + if targetPathEnd >= '0' && targetPathEnd <= '9' { target.Path = fmt.Sprintf("%sp%d", basePath, target.Number) } else { target.Path = fmt.Sprintf("%s%d", basePath, target.Number) @@ -240,37 +209,34 @@ func (target *Partition) FillPath(basePath string) { func (target *Partition) GetUUID() (string, error) { lsblkCmd := "lsblk -d -n -o UUID %s" - cmd := exec.Command("sh", "-c", fmt.Sprintf(lsblkCmd, target.Path)) - output, err := cmd.Output() + output, err := OutputCommand(fmt.Sprintf(lsblkCmd, target.Path)) if err != nil { return "", fmt.Errorf("failed to get partition UUID: %s", err) } - return string(output[:len(output)-1]), nil + return output, nil } func GetUUIDByPath(path string) (string, error) { lsblkCmd := "lsblk -d -n -o UUID %s" - cmd := exec.Command("sh", "-c", fmt.Sprintf(lsblkCmd, path)) - output, err := cmd.Output() + output, err := OutputCommand(fmt.Sprintf(lsblkCmd, path)) if err != nil { return "", fmt.Errorf("failed to get partition UUID: %s", err) } - return string(output[:len(output)-1]), nil + return output, nil } func GetFilesystemByPath(path string) (string, error) { lsblkCmd := "lsblk -d -n -o FSTYPE %s" - cmd := exec.Command("sh", "-c", fmt.Sprintf(lsblkCmd, path)) - output, err := cmd.Output() + output, err := OutputCommand(fmt.Sprintf(lsblkCmd, path)) if err != nil { return "", fmt.Errorf("failed to get partition FSTYPE: %s", err) } - return string(output[:len(output)-1]), nil + return output, nil } func (part *Partition) GetLUKSMapperPath() (string, error) { diff --git a/core/post_install.go b/core/post_install.go index eb901648..a071da9c 100644 --- a/core/post_install.go +++ b/core/post_install.go @@ -3,7 +3,6 @@ package albius import ( "fmt" "os" - "os/exec" "regexp" "strings" ) @@ -29,7 +28,7 @@ func SetTimezone(targetRoot, tz string) error { return nil } -func AddUser(targetRoot, username, fullname string, groups []string, withPassword bool, password ...string) error { +func AddUser(targetRoot, username, fullname string, groups []string, password ...string) error { adduserCmd := "useradd --shell /bin/bash %s && usermod -c \"%s\" %s" var err error @@ -42,12 +41,8 @@ func AddUser(targetRoot, username, fullname string, groups []string, withPasswor return fmt.Errorf("failed to create user: %s", err) } - if withPassword { + if len(password) == 1 { passwdCmd := "echo \"%s:%s\" | chpasswd" - if len(password) < 1 { - return fmt.Errorf("password was not provided") - } - if targetRoot != "" { err = RunInChroot(targetRoot, fmt.Sprintf(passwdCmd, username, password[0])) } else { @@ -58,25 +53,20 @@ func AddUser(targetRoot, username, fullname string, groups []string, withPasswor } } + // No groups were specified, we're done here if len(groups) == 0 { return nil } - addGroupCmd := "usermod -a -G %s %s" - groupList := "" - for i, group := range groups { - groupList += group - if i < len(groups)-1 { - groupList += "," - } - } + addGroupCmd := "usermod -a -G %s %s" + groupList := strings.Join(groups, ",") if targetRoot != "" { err = RunInChroot(targetRoot, fmt.Sprintf(addGroupCmd, groupList, username)) } else { err = RunCommand(fmt.Sprintf(addGroupCmd, groupList, username)) } if err != nil { - return fmt.Errorf("failed to set password: %s", err) + return fmt.Errorf("failed to add groups to user: %s", err) } return nil @@ -88,20 +78,23 @@ func RemovePackages(targetRoot, pkgRemovePath, removeCmd string) error { return fmt.Errorf("failed to read package removal file: %s", err) } - pkgList := strings.Replace(string(pkgRemoveContent), "\n", " ", -1) - + pkgList := strings.ReplaceAll(string(pkgRemoveContent), "\n", " ") completeCmd := fmt.Sprintf("%s %s", removeCmd, pkgList) if targetRoot != "" { - return RunInChroot(targetRoot, completeCmd) + err = RunInChroot(targetRoot, completeCmd) } else { - return RunCommand(completeCmd) + err = RunCommand(completeCmd) } + if err != nil { + return fmt.Errorf("failed to remove packages: %s", err) + } + + return nil } func ChangeHostname(targetRoot, hostname string) error { - replaceHostnameCmd := "echo %s > %s/etc/hostname" - cmd := exec.Command("sh", "-c", fmt.Sprintf(replaceHostnameCmd, hostname, targetRoot)) - err := cmd.Run() + hostnamePath := targetRoot + "/etc/hostname" + err := os.WriteFile(hostnamePath, []byte(hostname+"\n"), 0644) if err != nil { return fmt.Errorf("failed to change hostname: %s", err) } @@ -130,11 +123,10 @@ func SetLocale(targetRoot, locale string) error { return fmt.Errorf("failed to set locale: %s", err) } - localeGenCmd := "locale-gen" if targetRoot != "" { - err = RunInChroot(targetRoot, localeGenCmd) + err = RunInChroot(targetRoot, "locale-gen") } else { - err = RunCommand(localeGenCmd) + err = RunCommand("locale-gen") } if err != nil { return fmt.Errorf("failed to set locale: %s", err) @@ -162,7 +154,6 @@ LC_IDENTIFICATION=__lang__ func Swapon(targetRoot, swapPart string) error { swaponCmd := "swapon %s" - if targetRoot != "" { return RunInChroot(targetRoot, fmt.Sprintf(swaponCmd, swapPart)) } else { @@ -178,7 +169,6 @@ XKBLAYOUT="%s" XKBVARIANT="%s" BACKSPACE="guess" ` - keyboardPath := targetRoot + "/etc/default/keyboard" err := os.WriteFile(keyboardPath, []byte(fmt.Sprintf(keyboardContents, kbModel, kbLayout, kbVariant)), 0644) if err != nil { diff --git a/core/recipe.go b/core/recipe.go index 779b409c..8642baa5 100644 --- a/core/recipe.go +++ b/core/recipe.go @@ -87,7 +87,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { label := DiskLabel(args[0].(string)) err = disk.LabelDisk(label) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### mkpart * @@ -111,15 +111,15 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { fsType := PartitionFs(args[1].(string)) start := int(args[2].(float64)) end := int(args[3].(float64)) - if len(args) > 4 && strings.HasPrefix(string(fsType), "luks-") { + if len(args) > 4 && strings.HasPrefix(string(fsType), "luks-") { // Encrypted partition luksPassword := args[4].(string) part, err := disk.NewPartition(name, "", start, end) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } err = LuksFormat(part, luksPassword) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } // lsblk seems to take a few milliseconds to update the partition's // UUID, so we loop until it gives us one @@ -129,21 +129,21 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { } err = LuksOpen(part, fmt.Sprintf("luks-%s", uuid), luksPassword) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } part.Filesystem = PartitionFs(strings.TrimPrefix(string(fsType), "luks-")) err = LUKSMakeFs(part) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } err = LUKSSetLabel(part, name) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } - } else { + } else { // Unencrypted partition _, err := disk.NewPartition(name, fsType, start, end) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } } /* !! ### rm @@ -156,11 +156,11 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { case "rm": partNum, err := strconv.Atoi(args[0].(string)) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } err = disk.Partitions[partNum-1].RemovePartition() if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### resizepart * @@ -173,15 +173,15 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { case "resizepart": partNum, err := strconv.Atoi(args[0].(string)) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } partNewSize, err := strconv.Atoi(args[1].(string)) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } err = disk.Partitions[partNum-1].ResizePartition(partNewSize) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### namepart * @@ -194,19 +194,19 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { case "namepart": partNum, err := strconv.Atoi(args[0].(string)) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } partNewName := args[1].(string) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } err = disk.Partitions[partNum-1].SetLabel(partNewName) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } err = disk.Partitions[partNum-1].NamePartition(partNewName) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### setflag * @@ -221,11 +221,11 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { case "setflag": partNum, err := strconv.Atoi(args[0].(string)) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } err = disk.Partitions[partNum-1].SetPartitionFlag(args[1].(string), args[2].(bool)) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### format * @@ -239,19 +239,19 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { case "format": partNum, err := strconv.Atoi(args[0].(string)) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } filesystem := args[1].(string) disk.Partitions[partNum-1].Filesystem = PartitionFs(filesystem) err = MakeFs(&disk.Partitions[partNum-1]) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } if len(args) == 3 { label := args[2].(string) err := disk.Partitions[partNum-1].SetLabel(label) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } } /* !! ### luks-format @@ -267,7 +267,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { case "luks-format": partNum, err := strconv.Atoi(args[0].(string)) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } filesystem := args[1].(string) password := args[2].(string) @@ -275,7 +275,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { part.Filesystem = PartitionFs(filesystem) err = LuksFormat(&part, password) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } // lsblk seems to take a few milliseconds to update the partition's // UUID, so we loop until it gives us one @@ -285,17 +285,17 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { } err = LuksOpen(&part, fmt.Sprintf("luks-%s", uuid), password) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } err = LUKSMakeFs(&part) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } if len(args) == 4 { label := args[3].(string) err := LUKSSetLabel(&part, label) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } } /* !! ### pvcreate @@ -309,7 +309,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { part := args[0].(string) err := lvm.Pvcreate(part) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### pvresize * @@ -329,7 +329,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { err = lvm.Pvresize(part) } if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### pvremove * @@ -342,7 +342,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { part := args[0].(string) err := lvm.Pvremove(part) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### vgcreate * @@ -366,7 +366,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { } err := lvm.Vgcreate(name, pvList...) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### vgrename * @@ -381,7 +381,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { newName := args[1].(string) _, err := lvm.Vgrename(oldName, newName) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### vgextend * @@ -403,7 +403,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { } err := lvm.Vgextend(name, pvList...) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### vgreduce * @@ -425,7 +425,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { } err := lvm.Vgreduce(name, pvList...) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### vgremove * @@ -438,7 +438,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { name := args[0].(string) err := lvm.Vgremove(name) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### lvcreate * @@ -457,7 +457,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { vgSize := args[3] err := lvm.Lvcreate(name, vg, lvm.LVType(lvType), vgSize) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### lvrename * @@ -474,7 +474,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { vg := args[2].(string) _, err := lvm.Lvrename(oldName, newName, vg) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### lvremove * @@ -487,7 +487,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { name := args[0].(string) err := lvm.Lvremove(name) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### make-thin-pool * @@ -502,7 +502,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { thinMetaLV := args[1].(string) err := lvm.MakeThinPool(thinMetaLV, thinDataLV) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### lvcreate-thin * @@ -521,7 +521,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { thinPool := args[3].(string) err := lvm.LvThinCreate(name, vg, thinPool, vgSize) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } /* !! ### lvm-format * @@ -537,7 +537,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { filesystem := args[1].(string) lv, err := lvm.FindLv(name) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } dummyPart := Partition{ Path: "/dev/" + lv.VgName + "/" + lv.Name, @@ -545,13 +545,13 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { } err = MakeFs(&dummyPart) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } if len(args) == 3 { label := args[2].(string) err := dummyPart.SetLabel(label) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } } /* !! ### lvm-luks-format @@ -570,7 +570,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { password := args[2].(string) lv, err := lvm.FindLv(name) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } dummyPart := Partition{ Path: "/dev/" + lv.VgName + "/" + lv.Name, @@ -578,7 +578,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { } err = LuksFormat(&dummyPart, password) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } // lsblk seems to take a few milliseconds to update the partition's // UUID, so we loop until it gives us one @@ -588,17 +588,17 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { } err = LuksOpen(&dummyPart, fmt.Sprintf("luks-%s", uuid), password) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } err = LUKSMakeFs(&dummyPart) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } if len(args) == 4 { label := args[3].(string) err := LUKSSetLabel(&dummyPart, label) if err != nil { - return fmt.Errorf("failed to execute operation %s: %s", operation, err) + return err } } /* !! --- */ @@ -610,10 +610,11 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { } func (recipe *Recipe) RunSetup() error { - for _, step := range recipe.Setup { + for i, step := range recipe.Setup { + fmt.Printf("Setup [%d/%d]: %s", i, len(recipe.Setup), step.Operation) err := runSetupOperation(step.Disk, step.Operation, step.Params) if err != nil { - return err + return fmt.Errorf("failed to run setup operation %s: %s", step.Operation, err) } } @@ -646,13 +647,13 @@ func runPostInstallOperation(chroot bool, operation string, args []interface{}) groupStr := group.(string) groups = append(groups, groupStr) } - withPassword := false - password := "" + var err error if len(args) == 4 { - withPassword = true - password = args[3].(string) + password := args[3].(string) + err = AddUser(targetRoot, username, fullname, groups, password) + } else { + err = AddUser(targetRoot, username, fullname, groups) } - err := AddUser(targetRoot, username, fullname, groups, withPassword, password) if err != nil { return err } @@ -862,10 +863,11 @@ func runPostInstallOperation(chroot bool, operation string, args []interface{}) } func (recipe *Recipe) RunPostInstall() error { - for _, step := range recipe.PostInstallation { + for i, step := range recipe.PostInstallation { + fmt.Printf("Post-installation [%d/%d]: %s", i, len(recipe.PostInstallation), step.Operation) err := runPostInstallOperation(step.Chroot, step.Operation, step.Params) if err != nil { - return err + return fmt.Errorf("failed to run post-install operation %s: %s", step.Operation, err) } } @@ -898,8 +900,6 @@ func (recipe *Recipe) SetupMountpoints() error { } lvmExpr := regexp.MustCompile(`^/dev/(?P[\w-]+)/(?P[\w-]+)$`) - diskExpr := regexp.MustCompile("^/dev/[a-zA-Z]+([0-9]+[a-z][0-9]+)?") - partExpr := regexp.MustCompile("[0-9]+$") for _, mnt := range ordered_mountpoints { baseRoot := RootA @@ -923,8 +923,8 @@ func (recipe *Recipe) SetupMountpoints() error { } // Regular partition - diskName := diskExpr.FindString(mnt.Partition) - part, err := strconv.Atoi(partExpr.FindString(mnt.Partition)) + diskName, partName := SeparateDiskPart(mnt.Partition) + part, err := strconv.Atoi(partName) if err != nil { return err } @@ -993,13 +993,7 @@ func (recipe *Recipe) setupFstabEntries() ([][]string, error) { options = "defaults" } - entry = append(entry, fsName) - entry = append(entry, mnt.Target) - entry = append(entry, fstype) - entry = append(entry, options) - entry = append(entry, "0") - entry = append(entry, "0") - + entry = append(entry, fsName, mnt.Target, fstype, options, "0", "0") fstabEntries = append(fstabEntries, entry) } @@ -1024,11 +1018,12 @@ func (recipe *Recipe) setupCrypttabEntries() ([][]string, error) { return [][]string{}, err } - entry = append(entry, fmt.Sprintf("luks-%s", partUUID)) // target - entry = append(entry, fmt.Sprintf("UUID=%s", partUUID)) // device - entry = append(entry, "none") // keyfile - entry = append(entry, "luks,discard") // options - + entry = append(entry, + fmt.Sprintf("luks-%s", partUUID), // target + fmt.Sprintf("UUID=%s", partUUID), // device + "none", // keyfile + "luks,discard", // options + ) crypttabEntries = append(crypttabEntries, entry) } @@ -1036,20 +1031,18 @@ func (recipe *Recipe) setupCrypttabEntries() ([][]string, error) { } func (recipe *Recipe) Install() error { + var err error switch recipe.Installation.Method { case UNSQUASHFS: - err := Unsquashfs(recipe.Installation.Source, RootA, true) - if err != nil { - return err - } + err = Unsquashfs(recipe.Installation.Source, RootA, true) case OCI: - err := OCISetup(recipe.Installation.Source, filepath.Join(RootA, "var"), RootA, false) - if err != nil { - return err - } + err = OCISetup(recipe.Installation.Source, filepath.Join(RootA, "var"), RootA, false) default: return fmt.Errorf("unsupported installation method '%s'", recipe.Installation.Method) } + if err != nil { + return fmt.Errorf("failed to copy installation files: %s", err) + } // Setup crypttab (if needed) crypttabEntries, err := recipe.setupCrypttabEntries() diff --git a/core/util.go b/core/util.go index 6c12150b..adb43243 100644 --- a/core/util.go +++ b/core/util.go @@ -6,18 +6,51 @@ import ( "os" "os/exec" "reflect" + "regexp" + "strings" ) -// RunCommand executes a command in a subshell. +// RunCommand executes a command in a subshell func RunCommand(command string) error { cmd := exec.Command("sh", "-c", command) cmd.Stdout = os.Stdout err := cmd.Run() - exitErr, ok := err.(*exec.ExitError) - if err != nil && ok { - return errors.New(string(exitErr.Stderr)) - } else if err != nil { + if err != nil { + if exitErr, ok := err.(*exec.ExitError); ok { + return errors.New(string(exitErr.Stderr)) + } + return err + } + + return nil +} + +// OutputCommand executes a command in a subshell and returns its output +func OutputCommand(command string) (string, error) { + cmd := exec.Command("sh", "-c", command) + out, err := cmd.Output() + + if err != nil { + if exitErr, ok := err.(*exec.ExitError); ok { + return strings.TrimSpace(string(out)), errors.New(string(exitErr.Stderr)) + } + return strings.TrimSpace(string(out)), err + } + + return strings.TrimSpace(string(out)), err +} + +// RunInChroot executes a command in a subshell while chrooted into the specified root +func RunInChroot(root, command string) error { + cmd := exec.Command("chroot", root, "sh", "-c", command) + cmd.Stdout = os.Stdout + err := cmd.Run() + + if err != nil { + if exitErr, ok := err.(*exec.ExitError); ok { + return errors.New(string(exitErr.Stderr)) + } return err } @@ -55,3 +88,14 @@ func setField(obj interface{}, name string, value interface{}) error { structFieldValue.Set(convertedVal) return nil } + +// SeparateDiskPart receives a path (e.g. /dev/sda1) and separates it into +// the device root and partition number +func SeparateDiskPart(path string) (string, string) { + diskExpr := regexp.MustCompile("^/dev/[a-zA-Z]+([0-9]+[a-z][0-9]+)?") + partExpr := regexp.MustCompile("[0-9]+$") + disk := diskExpr.FindString(path) + part := partExpr.FindString(path) + + return disk, part +} From 4e144b0a65ea4f54bf71994ec4f73b7bd3b4ce3e Mon Sep 17 00:00:00 2001 From: Mateus Melchiades Date: Tue, 14 Nov 2023 13:30:52 -0300 Subject: [PATCH 4/5] Fix LocateDisk failing when reading unformatted disks --- core/disk.go | 40 ++++++++++++---------------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/core/disk.go b/core/disk.go index 59ebe0d3..2142701f 100644 --- a/core/disk.go +++ b/core/disk.go @@ -2,7 +2,6 @@ package albius import ( "encoding/json" - "errors" "fmt" "strconv" ) @@ -19,10 +18,12 @@ type Sector struct { } type Disk struct { - Path, Size, Model, Transport string - Label DiskLabel - LogicalSectorSize, PhysicalSectorSize, MaxPartitions int - Partitions []Partition + Path, Size, Model, Transport string + Label DiskLabel + LogicalSectorSize int `json:"logical-sector-size"` + PhysicalSectorSize int `json:"physical-sector-size"` + MaxPartitions int `json:"max-partitions"` + Partitions []Partition } func (disk *Disk) AvailableSectors() ([]Sector, error) { @@ -67,42 +68,25 @@ func (disk *Disk) AvailableSectors() ([]Sector, error) { func LocateDisk(diskname string) (*Disk, error) { findPartitionCmd := "parted -sj %s unit MiB print" output, err := OutputCommand(fmt.Sprintf(findPartitionCmd, diskname)) - if err != nil { + // If disk is unformatted, parted returns the expected json but also throws an error. + // We can assume we have all the necessary information if output isn't empty. + if err != nil && output == "" { return nil, fmt.Errorf("failed to list disk: %s", err) } - var device *Disk var decoded struct { Disk Disk } err = json.Unmarshal([]byte(output), &decoded) if err != nil { - // Try a different approach suitable for when the disk is unformatted - var decodedMap map[string]map[string]interface{} - err = json.Unmarshal([]byte(output), &decodedMap) - if err != nil { - return nil, errors.New("parted output contains invalid json") - } - device := new(Disk) - for k, v := range decodedMap["Disk"] { - err := setField(device, k, v) - if err != nil { - return nil, fmt.Errorf("failed to decode parted output: %s", err) - } - } - } else { - device = &decoded.Disk - } - - if device == nil { return nil, fmt.Errorf("could not find device %s", diskname) } - for i := 0; i < len(device.Partitions); i++ { - device.Partitions[i].FillPath(device.Path) + for i := 0; i < len(decoded.Disk.Partitions); i++ { + decoded.Disk.Partitions[i].FillPath(decoded.Disk.Path) } - return device, nil + return &decoded.Disk, nil } func (disk *Disk) Update() error { From 1a11fd3520837ca506e22e64d7fe5d9928a79ff5 Mon Sep 17 00:00:00 2001 From: Mateus Melchiades Date: Sat, 18 Nov 2023 16:23:45 -0300 Subject: [PATCH 5/5] Add missing newline --- core/recipe.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/recipe.go b/core/recipe.go index 8642baa5..f607c363 100644 --- a/core/recipe.go +++ b/core/recipe.go @@ -611,7 +611,7 @@ func runSetupOperation(diskLabel, operation string, args []interface{}) error { func (recipe *Recipe) RunSetup() error { for i, step := range recipe.Setup { - fmt.Printf("Setup [%d/%d]: %s", i, len(recipe.Setup), step.Operation) + fmt.Printf("Setup [%d/%d]: %s\n", i+1, len(recipe.Setup), step.Operation) err := runSetupOperation(step.Disk, step.Operation, step.Params) if err != nil { return fmt.Errorf("failed to run setup operation %s: %s", step.Operation, err) @@ -864,7 +864,7 @@ func runPostInstallOperation(chroot bool, operation string, args []interface{}) func (recipe *Recipe) RunPostInstall() error { for i, step := range recipe.PostInstallation { - fmt.Printf("Post-installation [%d/%d]: %s", i, len(recipe.PostInstallation), step.Operation) + fmt.Printf("Post-installation [%d/%d]: %s\n", i+1, len(recipe.PostInstallation), step.Operation) err := runPostInstallOperation(step.Chroot, step.Operation, step.Params) if err != nil { return fmt.Errorf("failed to run post-install operation %s: %s", step.Operation, err)