func hashForFile(buildDir, path string, info os.FileInfo) (h *fileHash, err error) { sha512sum := "" // pointer so that omitempty works (we don't want size for // directories or symlinks) var size *int64 if info.Mode().IsRegular() { sha512sum, err = helpers.Sha512sum(path) if err != nil { return nil, err } fsize := info.Size() size = &fsize } // major/minor handling device := "" major, minor, err := helpers.MajorMinor(info) if err == nil { device = fmt.Sprintf("%v,%v", major, minor) } if buildDir != "" { path = path[len(buildDir)+1:] } return &fileHash{ Name: path, Size: size, Sha512: sha512sum, Device: device, // FIXME: not portable, this output is different on // windows, macos Mode: newYamlFileMode(info.Mode()), }, nil }
// tarCreate creates a tarfile for a clickdeb, all files in the archive // belong to root (same as dpkg-deb) func tarCreate(tarname string, sourceDir string, fn tarExcludeFunc) error { w, err := os.Create(tarname) if err != nil { return err } defer w.Close() var compressor io.WriteCloser switch { case strings.HasSuffix(tarname, ".gz"): compressor, err = gzip.NewWriterLevel(w, 9) case strings.HasSuffix(tarname, ".xz"): compressor = newXZPipeWriter(w) default: return fmt.Errorf("unknown compression extension %s", tarname) } if err != nil { return err } defer compressor.Close() tarWriter := tar.NewWriter(compressor) defer tarWriter.Close() err = filepath.Walk(sourceDir, func(path string, info os.FileInfo, err error) error { st, err := os.Lstat(path) if err != nil { return err } // check if we support this type if !st.Mode().IsRegular() && !helpers.IsSymlink(st.Mode()) && !st.Mode().IsDir() && !helpers.IsDevice(st.Mode()) { return fmt.Errorf("unsupported file type for %s", path) } // check our exclude function if fn != nil { if !fn(path) { return nil } } // huh? golang, come on! the symlink stuff is a bit complicated target, _ := os.Readlink(path) hdr, err := tar.FileInfoHeader(info, target) if err != nil { return err } // tar.FileInfoHeader does include the fact that its a // char/block device, but does not set major/minor :/ if helpers.IsDevice(st.Mode()) { major, minor, err := helpers.MajorMinor(st) if err != nil { return err } hdr.Devmajor = int64(major) hdr.Devminor = int64(minor) } // exclude "." relativePath := "." + path[len(sourceDir):] if relativePath == "." { return nil } // add header, note that all files belong to root hdr.Name = relativePath hdr.Uid = 0 hdr.Gid = 0 hdr.Uname = "root" hdr.Gname = "root" if err := tarWriter.WriteHeader(hdr); err != nil { return err } // add content if st.Mode().IsRegular() { f, err := os.Open(path) if err != nil { return err } defer f.Close() _, err = io.Copy(tarWriter, f) if err != nil { return err } } return nil }) return err }