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/>.
38 func (ent *Ent) IsDir() bool {
39 return IsDir(ent.name[len(ent.name)-1])
42 func dbCommit(dbPath string, tmp *os.File) {
43 umask := syscall.Umask(0)
45 if err := os.Chmod(tmp.Name(), os.FileMode(0666&^umask)); err != nil {
48 if err := os.Rename(tmp.Name(), dbPath); err != nil {
54 dbPath := flag.String("db", "glocate.db", "Path to database")
55 doIndex := flag.Bool("index", false, "Perform indexing")
56 doUpdate := flag.String("update", "", "Update database")
57 showMachine := flag.Bool("machine", false, "Show machine friendly")
58 showTree := flag.Bool("tree", false, "Show human-friendly tree")
59 dryRun := flag.Bool("n", false, "Dry run, do not overwrite database")
60 rootPath := flag.String("root", "", "Search only that part of tree")
62 log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds | log.Lshortfile)
65 TmpDir, err = filepath.Abs(*dbPath)
69 TmpDir = path.Dir(TmpDir)
75 dbCommit(*dbPath, tmp)
81 tmp := updateWithDiff(*dbPath, *doUpdate)
84 dbCommit(*dbPath, tmp)
89 db, err := os.Open(*dbPath)
93 entsReader := make(chan Ent, 1<<10)
94 go reader(db, entsReader)
96 entsPrinter := make(chan Ent, 1<<10)
97 printerJob := make(chan struct{})
100 printerMachine(entsPrinter)
101 } else if *showTree {
102 printerTree(entsPrinter)
104 printerSimple(entsPrinter)
111 root = strings.Split("./"+*rootPath, "/")
115 if len(flag.Args()) > 0 {
116 pat = "*" + flag.Arg(0) + "*"
121 var namePrev []string
123 for ent := range entsReader {
124 if hasPrefix(ent.name, root) {
130 for i = 0; i < len(ent.name); i++ {
131 if i == len(namePrev) || ent.name[i] != namePrev[i] {
135 for ; i < len(ent.name); i++ {
136 matched, err = path.Match(pat,
137 strings.ToLower(strings.TrimSuffix(ent.name[i], "/")))