From 4c1e7a4310caea79e4f2df8d9bd18fe856960d93 Mon Sep 17 00:00:00 2001 From: lordwelch Date: Wed, 9 Dec 2020 13:25:44 -0800 Subject: [PATCH] Add code for partition mounting --- main.go | 166 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 123 insertions(+), 43 deletions(-) diff --git a/main.go b/main.go index 5ae3fe6..8769399 100644 --- a/main.go +++ b/main.go @@ -1,57 +1,137 @@ 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") + perm = flag.String("perm", "/perm", "new val for perm") + gloaderHome = "/perm/gloader" ) func main() { - os.MkdirAll("/home/timmy/dltest", 0777) + 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 = "/home/timmy/dltest" - d.Start("tcp", ":8080") + d.DataDir = filepath.Join(gloaderHome, "data") + d.Start("tcp", ":8844") } -// func mount() error { -// var ( -// partUUID string -// partUUIDb []byte -// err error -// dataStat os.FileInfo -// dataDir = filepath.Join(*perm, "downloader/data") -// ) -// partUUIDb, err = ioutil.ReadFile(filepath.Join(*perm, "downloader/partition")) -// if err != nil || string(partUUIDb) == "" { -// return nil -// } -// partUUID = string(partUUIDb) -// 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) -// } -// } 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) -// 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 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 +}