From 74230d93e223e482bdcc07fe7a2d87e7049a9375 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 3 Aug 2019 03:59:35 -0600 Subject: [PATCH] copy directory via tar --- build-all.go | 156 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 147 insertions(+), 9 deletions(-) diff --git a/build-all.go b/build-all.go index 7341282..0cc5d30 100644 --- a/build-all.go +++ b/build-all.go @@ -85,6 +85,7 @@ func main() { // Get a copy of all the node modules npmdir := "tmp-package-modules" + // TODO save bits /* err = os.RemoveAll(npmdir) if nil != err { panic(err) @@ -118,6 +119,7 @@ func main() { if nil != err { panic(err) } + //*/ for i := range pkgs { pkg := pkgs[i] @@ -168,15 +170,23 @@ func main() { panic(err) } case "tar.gz": + // SAVE ON BITS /* tgz, err := os.Open(nfile) if nil != err { panic(err) } - strip := 1 - err = untar(tgz, outdir, strip) + defer tgz.Close() + tarfile, err := gzip.NewReader(tgz) if nil != err { panic(err) } + // TODOD XXX turn back on + strip := 1 + err = untar(tarfile, outdir, strip) + if nil != err { + panic(err) + } + //*/ default: panic(fmt.Errorf("%s", "Liar!!")) } @@ -199,6 +209,29 @@ func main() { panic(err) } + // TODO we'll use this when tar-ing + //tzw := gzip.NewWriter(tw) + pr, pw := io.Pipe() + go func() { + tw := tar.NewWriter(pw) + defer tw.Close() + //fis, err := ioutil.ReadDir(npmdir) + fi, err := os.Stat(npmdir) + if nil != err { + panic("stat:" + err.Error()) + } + //err = tarDir(tw, npmdir, fis, "") + err = tarEntry(tw, "", fi, "") + if nil != err { + panic("tarError:" + err.Error()) + } + }() + + err = untar(pr, outdir, 1) + if nil != err { + panic("untarError:" + err.Error()) + } + // Get pathman for the platform pathmanURL := fmt.Sprintf( "https://rootprojects.org/pathman/dist/%s/%s/pathman"+pkg.exe, @@ -256,12 +289,7 @@ func download(title string, nurl string, nfile string, exec bool) error { return nf.Sync() } -func untar(tgz io.Reader, outdir string, strip int) error { - t, err := gzip.NewReader(tgz) - if nil != err { - return err - } - defer t.Close() +func untar(t io.Reader, outdir string, strip int) error { tr := tar.NewReader(t) for { header, err := tr.Next() @@ -278,6 +306,7 @@ func untar(tgz io.Reader, outdir string, strip int) error { case tar.TypeLink: // ignore hard links case tar.TypeSymlink: + //fmt.Println("untarSym:", fpath) // Note: the link itself is always a file, even when it represents a directory lpath := filepath.Join(filepath.Dir(fpath), header.Linkname) if !strings.HasPrefix(lpath+string(os.PathSeparator), outdir+string(os.PathSeparator)) { @@ -287,6 +316,13 @@ func untar(tgz io.Reader, outdir string, strip int) error { return err } case tar.TypeDir: + //fmt.Println("untarDir:", fpath) + /* + // TODO + if err := os.Lchown(dst); err != nil { + return err + } + */ // gonna use the same perms as were set previously here // should be fine (i.e. we want 755 for execs on *nix) _, err := safeOpen(header.FileInfo(), os.FileMode(header.Mode), fpath, outdir) @@ -294,6 +330,13 @@ func untar(tgz io.Reader, outdir string, strip int) error { return err } case tar.TypeReg: + //fmt.Println("untarReg:", fpath) + /* + // TODO + if err := os.Lchown(dst); err != nil { + return err + } + */ // gonna use the same perms as were set previously here // should be fine (i.e. we want 755 for execs on *nix) out, err := safeOpen(header.FileInfo(), os.FileMode(header.Mode), fpath, outdir) @@ -409,9 +452,104 @@ func safeOpen(fi os.FileInfo, fm os.FileMode, fpath string, outdir string) (io.W } out, err := os.OpenFile(fpath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, fm) - if err != nil { + if nil != err { return nil, err } return out, nil } + +// simpler to tar and untar than to have separate code to copy and to tar +func tarDir(tw *tar.Writer, src string, fis []os.FileInfo, trim string) error { + //fmt.Println("tarDir:", src) + for i := range fis { + fi := fis[i] + + //fmt.Println("tarEntry:", src) + if err := tarEntry(tw, src, fi, trim); nil != err { + return err + } + } + + return nil +} + +func tarEntry(tw *tar.Writer, src string, fi os.FileInfo, trim string) error { + // gotta get perms + /* + stat, ok := info.Sys().(*syscall.Stat_t) + if !ok { + return fmt.Errorf("syscall failed for %q", src) + } + // TODO uid, username + Uid: int(stat.Uid), + Gid: int(stat.Gid), + */ + + src = filepath.Join(src, fi.Name()) + h := &tar.Header{ + Name: strings.TrimPrefix(strings.TrimPrefix(src, trim), "/"), + Mode: int64(fi.Mode()), + ModTime: fi.ModTime(), + } + //fmt.Printf("tarHeader: %s %s\n", src, h.Name) + + switch fi.Mode() & os.ModeType { + case os.ModeSymlink: + //fmt.Println("tarSym:", src) + // TODO make sure that this is within the directory + targetpath, err := os.Readlink(src) + if nil != err { + return err + } + h.Linkname = targetpath + + err = tw.WriteHeader(h) + if nil != err { + return err + } + + // return to skip chmod + return nil + case os.ModeDir: + // directories must end in / for tar + h.Name = strings.TrimPrefix(h.Name+"/", "/") + //fmt.Printf("tarIsDir: %q %q\n", src, h.Name) + if "" != h.Name { + if err := tw.WriteHeader(h); nil != err { + return err + } + } + + //fmt.Println("tarReadDir:", src) + fis, err := ioutil.ReadDir(src) + if nil != err { + return err + } + + return tarDir(tw, src, fis, trim) + default: + //fmt.Println("tarDefault:", src) + if !fi.Mode().IsRegular() { + return fmt.Errorf("Unsupported file type: %s", src) + } + + h.Size = fi.Size() + err := tw.WriteHeader(h) + if nil != err { + return err + } + + r, err := os.Open(src) + defer r.Close() + if nil != err { + return err + } + + if _, err := io.Copy(tw, r); nil != err { + return err + } + } + + return nil +}