package main import ( "errors" "flag" "fmt" "io" "io/ioutil" "log" "os" "path/filepath" "strconv" "strings" "syscall" "github.com/u-root/u-root/pkg/mount/gpt" ) var ( perm = flag.String("perm", "/perm", "new val for perm") gloaderHome = "/perm/gloader" ) func main() { flag.Parse() gloaderHome = filepath.Join(*perm, "gloader") os.MkdirAll(gloaderHome, 0777) err := mount() if err != nil { log.Println(err) os.Exit(1) } d := newDownloader() d.DataDir = filepath.Join(gloaderHome, "data") d.Start("tcp", ":8844") } func mount() error { var ( partUUIDb []byte partUUID string dev part err error dataStat os.FileInfo dataDir = filepath.Join(gloaderHome, "data") ) partUUIDb, err = ioutil.ReadFile(filepath.Join(gloaderHome, "partition")) partUUID = strings.TrimSpace(string(partUUIDb)) if err != nil || partUUID == "" { return nil } dataStat, err = os.Stat(dataDir) if err != nil { if errors.Is(err, os.ErrNotExist) { err = os.MkdirAll(dataDir, 0o755) if err != nil { return fmt.Errorf("error creating datadir: %w", err) } dataStat, err = os.Stat(dataDir) if err != nil { return fmt.Errorf("error mounting datadir: %w", err) } } else { return fmt.Errorf("error mounting datadir: %w", err) } } if dataStat.IsDir() { var folder *os.File folder, err = os.Open(dataDir) if err != nil { return fmt.Errorf("error mounting datadir: %w", err) } _, err = folder.Readdir(1) if errors.Is(err, io.EOF) { fmt.Printf("mount %s %s", partUUID, dataDir) dev = findPartUUID(partUUID) if err != nil { return fmt.Errorf("error mounting datadir: %w", err) } err = syscall.Mount(dev.Path, dataDir, "ext4", 0, "") if err != nil { return fmt.Errorf("error mounting datadir: %w", err) } return nil } return fmt.Errorf("error mounting datadir: %w", err) } return fmt.Errorf("error mounting datadir: data dir %s is not a directory", dataDir) } // func findPartUUID(uuid string) (string, error) { // var dev string // err := filepath.Walk("/sys/block", func(path string, info os.FileInfo, err error) error { // if err != nil { // log.Printf("findPartUUID: %v", err) // return nil // } // if info.Mode()&os.ModeSymlink == 0 { // return nil // } // devname := "/dev/" + filepath.Base(path) // f, err := os.Open(devname) // if err != nil { // log.Printf("findPartUUID: %v", err) // return nil // } // defer f.Close() // if _, err := f.Seek(440, io.SeekStart); err != nil { // var se syscall.Errno // if errors.As(err, &se) && se == syscall.EINVAL { // // Seek()ing empty loop devices results in EINVAL. // return nil // } // log.Printf("findPartUUID: %v(%T)", err, err.(*os.PathError).Err) // return nil // } // var diskSig struct { // ID uint32 // Trailer uint16 // } // if err := binary.Read(f, binary.LittleEndian, &diskSig); err != nil { // log.Printf("findPartUUID: %v", err) // return nil // } // if fmt.Sprintf("%08x", diskSig.ID) == uuid && diskSig.Trailer == 0 { // dev = devname // // TODO: abort early with sentinel error code // return nil // } // return nil // }) // if err != nil { // return "", err // } // if dev == "" { // return "", fmt.Errorf("PARTUUID=%s not found", uuid) // } // return dev, nil // } type part struct { UUID string Path string } func findPartUUID(UUID string) part { var dev part err := filepath.Walk("/sys/block", func(path string, info os.FileInfo, err error) error { if err != nil { log.Printf("listPartUUID: %v", err) return nil } if info.Mode()&os.ModeSymlink == 0 { return nil } devname := "/dev/" + filepath.Base(path) f, err := os.Open(devname) if err != nil { log.Printf("listPartUUID: %v", err) return nil } defer f.Close() parttable, _ := gpt.New(f) if parttable.Primary != nil { for i, partition := range parttable.Primary.Parts { if partition.UniqueGUID.String() == UUID { dev = part{UUID: partition.UniqueGUID.String(), Path: devname + strconv.Itoa(i+1)} } } } return nil }) if err != nil { return part{} } return dev }