/* glocate -- ZFS-diff-friendly locate-like utility Copyright (C) 2022-2023 Sergey Matveev This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package main import ( "bufio" "encoding/binary" "io" "log" "github.com/klauspost/compress/zstd" ) func mustReadFull(r io.Reader, buf []byte) { if _, err := io.ReadFull(r, buf); err != nil { log.Fatalln(err) } } func reader(src io.Reader, sink chan Ent) { comp, err := zstd.NewReader(src) if err != nil { log.Fatalln(err) } br := bufio.NewReaderSize(comp, 1<<17) num := make([]byte, 8) var cols []string var namePrev string var nameLen uint16 var depth, depthPrev uint8 for { _, err = io.ReadFull(br, num[:2]) if err != nil { if err == io.EOF { break } log.Fatalln(err) } nameLen = binary.BigEndian.Uint16(num[:2]) nameRaw := make([]byte, nameLen) mustReadFull(br, nameRaw) name := string(nameRaw) mustReadFull(br, num[:1]) depth = uint8(num[0]) mustReadFull(br, num) ent := Ent{mtime: int64(binary.BigEndian.Uint64(num))} mustReadFull(br, num) ent.size = int64(binary.BigEndian.Uint64(num)) if depth > depthPrev { cols = append(cols, namePrev[:len(namePrev)-1]) } else if depth < depthPrev { cols = cols[:len(cols)-int(depthPrev-depth)] } ent.name = append([]string{}, append(cols, name)...) sink <- ent namePrev = name depthPrev = depth } close(sink) comp.Close() }