2 glocate -- ZFS-diff-friendly locate-like utility
3 Copyright (C) 2022-2023 Sergey Matveev <stargrave@stargrave.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, version 3 of the License.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 "github.com/klauspost/compress/zstd"
30 func dirSizer(dirSizes *[]int64, depth int, sinkBack, sinkIn, sinkOut chan Ent) (curSize int64) {
36 case ent = <-sinkBack:
40 ent, opened = <-sinkIn
45 if len(ent.name) < depth {
54 dirIdx = len(*dirSizes)
55 (*dirSizes) = append(*dirSizes, 0)
56 dirSize := dirSizer(dirSizes, depth+1, sinkBack, sinkIn, sinkOut)
57 (*dirSizes)[dirIdx] = dirSize
63 func applyDirSizes(src *os.File, dirSizes []int64) *os.File {
64 _, err := src.Seek(0, io.SeekStart)
68 tmp, err := os.CreateTemp(TmpDir, "glocate-idx")
73 compR, err := zstd.NewReader(src)
77 br := bufio.NewReaderSize(compR, 1<<17)
79 compW, err := zstd.NewWriter(tmp,
80 zstd.WithEncoderLevel(zstd.SpeedBestCompression))
84 bw := bufio.NewWriterSize(compW, 1<<17)
86 num := make([]byte, 8)
88 name := make([]byte, 0, 1<<16)
91 if _, err = io.ReadFull(br, num[:2]); err != nil {
97 mustWrite(bw, num[:2])
98 nameLen = int(binary.BigEndian.Uint16(num[:2]))
100 mustReadFull(br, name)
102 if _, err = io.CopyN(bw, br, 1+8); err != nil {
105 if name[len(name)-1] == byte('/') {
106 if _, err = br.Discard(8); err != nil {
109 binary.BigEndian.PutUint64(num, uint64(dirSizes[dirIdx]))
113 if _, err = io.CopyN(bw, br, 8); err != nil {
118 if err = bw.Flush(); err != nil {
121 if err = compW.Close(); err != nil {