diff --git a/cmd/gomtree/main.go b/cmd/gomtree/main.go index 6563cbc..8af7f55 100644 --- a/cmd/gomtree/main.go +++ b/cmd/gomtree/main.go @@ -23,6 +23,7 @@ var ( flListKeywords = flag.Bool("list-keywords", false, "List the keywords available") flResultFormat = flag.String("result-format", "bsd", "output the validation results using the given format (bsd, json, path)") flTar = flag.String("T", "", "use tar archive to create or validate a directory hierarchy spec") + flBsdKeywords = flag.Bool("bsd-keywords", false, "only operate on keywords that are supported by upstream mtree(8)") flDebug = flag.Bool("debug", false, "output debug info to STDERR") ) @@ -71,20 +72,24 @@ func main() { } }() - // -l + // -list-keywords if *flListKeywords { fmt.Println("Available keywords:") for k := range mtree.KeywordFuncs { - if inSlice(k, mtree.DefaultKeywords) { - fmt.Println(" ", k, " (default)") - } else { - fmt.Println(" ", k) + fmt.Print(" ") + fmt.Print(k) + if mtree.Keyword(k).Default() { + fmt.Print(" (default)") } + if !mtree.Keyword(k).Bsd() { + fmt.Print(" (not upstream)") + } + fmt.Print("\n") } return } - // --output + // --result-format formatFunc, ok := formats[*flResultFormat] if !ok { log.Printf("invalid output format: %s", *flResultFormat) @@ -92,29 +97,46 @@ func main() { return } - var currentKeywords []string + var ( + tmpKeywords []string + currentKeywords []string + ) // -k if *flUseKeywords != "" { - currentKeywords = splitKeywordsArg(*flUseKeywords) - if !inSlice("type", currentKeywords) { - currentKeywords = append([]string{"type"}, currentKeywords...) + tmpKeywords = splitKeywordsArg(*flUseKeywords) + if !inSlice("type", tmpKeywords) { + tmpKeywords = append([]string{"type"}, tmpKeywords...) } } else { if *flTar != "" { - currentKeywords = mtree.DefaultTarKeywords[:] + tmpKeywords = mtree.DefaultTarKeywords[:] } else { - currentKeywords = mtree.DefaultKeywords[:] + tmpKeywords = mtree.DefaultKeywords[:] } } + // -K if *flAddKeywords != "" { for _, kw := range splitKeywordsArg(*flAddKeywords) { - if !inSlice(kw, currentKeywords) { - currentKeywords = append(currentKeywords, kw) + if !inSlice(kw, tmpKeywords) { + tmpKeywords = append(tmpKeywords, kw) } } } + // -bsd-keywords + if *flBsdKeywords { + for _, k := range tmpKeywords { + if mtree.Keyword(k).Bsd() { + currentKeywords = append(currentKeywords, k) + } else { + fmt.Fprintf(os.Stderr, "INFO: ignoring %q as it is not an upstream keyword\n", k) + } + } + } else { + currentKeywords = tmpKeywords + } + // -f var dh *mtree.DirectoryHierarchy if *flFile != "" && !*flCreate { @@ -169,6 +191,7 @@ func main() { return } } + // -c if *flCreate { // create a directory hierarchy diff --git a/keywords.go b/keywords.go index 136f679..2228aca 100644 --- a/keywords.go +++ b/keywords.go @@ -23,6 +23,20 @@ import ( // for each new KeywordFunc type KeywordFunc func(path string, info os.FileInfo, r io.Reader) (string, error) +// Keyword is the string name of a keyword, with some convenience functions for +// determining whether it is a default or bsd standard keyword. +type Keyword string + +// Default returns whether this keyword is in the default set of keywords +func (k Keyword) Default() bool { + return inSlice(string(k), DefaultKeywords) +} + +// Bsd returns whether this keyword is in the upstream FreeBSD mtree(8) +func (k Keyword) Bsd() bool { + return inSlice(string(k), BsdKeywords) +} + // KeyVal is a "keyword=value" type KeyVal string @@ -134,6 +148,7 @@ var ( "nlink", "time", } + // DefaultTarKeywords has keywords that should be used when creating a manifest from // an archive. Currently, evaluating the # of hardlinks has not been implemented yet DefaultTarKeywords = []string{ @@ -145,6 +160,41 @@ var ( "link", "tar_time", } + + // BsdKeywords is the set of keywords that is only in the upstream FreeBSD mtree + BsdKeywords = []string{ + "cksum", + "device", + "flags", + "ignore", + "gid", + "gname", + "link", + "md5", + "md5digest", + "mode", + "nlink", + "nochange", + "optional", + "ripemd160digest", + "rmd160", + "rmd160digest", + "sha1", + "sha1digest", + "sha256", + "sha256digest", + "sha384", + "sha384digest", + "sha512", + "sha512digest", + "size", + "tags", + "time", + "type", + "uid", + "uname", + } + // SetKeywords is the default set of keywords calculated for a `/set` SpecialType SetKeywords = []string{ "uid",