package main import ( "encoding/binary" "errors" "flag" "fmt" "io" "io/ioutil" "log" "os" "path/filepath" "strings" "syscall" ) 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 string 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, err = findPartUUID(partUUID) if err != nil { return fmt.Errorf("error mounting datadir: %w", err) } err = syscall.Mount(dev, 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 }