1 // glocate -- ZFS-diff-friendly locate-like utility
2 // Copyright (C) 2022-2024 Sergey Matveev <stargrave@stargrave.org>
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, version 3 of the License.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program. If not, see <http://www.gnu.org/licenses/>.
25 "github.com/klauspost/compress/zstd"
28 func dirSizer(dirSizes *[]int64, depth int, sinkBack, sinkIn, sinkOut chan Ent) (curSize int64) {
34 case ent = <-sinkBack:
38 ent, opened = <-sinkIn
43 if len(ent.name) < depth {
52 dirIdx = len(*dirSizes)
53 (*dirSizes) = append(*dirSizes, 0)
54 dirSize := dirSizer(dirSizes, depth+1, sinkBack, sinkIn, sinkOut)
55 (*dirSizes)[dirIdx] = dirSize
61 func applyDirSizes(src *os.File, dirSizes []int64) *os.File {
62 _, err := src.Seek(0, io.SeekStart)
66 tmp, err := os.CreateTemp(TmpDir, "glocate-idx")
71 compR, err := zstd.NewReader(src)
75 br := bufio.NewReaderSize(compR, 1<<17)
77 compW, err := zstd.NewWriter(tmp,
78 zstd.WithEncoderLevel(zstd.SpeedBestCompression))
82 bw := bufio.NewWriterSize(compW, 1<<17)
84 num := make([]byte, 8)
86 name := make([]byte, 0, 1<<16)
89 if _, err = io.ReadFull(br, num[:2]); err != nil {
95 mustWrite(bw, num[:2])
96 nameLen = int(binary.BigEndian.Uint16(num[:2]))
98 mustReadFull(br, name)
100 if _, err = io.CopyN(bw, br, 1+8); err != nil {
103 if name[len(name)-1] == byte('/') {
104 if _, err = br.Discard(8); err != nil {
107 binary.BigEndian.PutUint64(num, uint64(dirSizes[dirIdx]))
111 if _, err = io.CopyN(bw, br, 8); err != nil {
116 if err = bw.Flush(); err != nil {
119 if err = compW.Close(); err != nil {