// YAML representation of a Siegfried struct. // This is the provenace block at the beginning of sf results and includes descriptions for each identifier. func (s *Siegfried) YAML() string { version := config.Version() str := fmt.Sprintf( "---\nsiegfried : %d.%d.%d\nscandate : %v\nsignature : %s\ncreated : %v\nidentifiers : \n", version[0], version[1], version[2], time.Now().Format(time.RFC3339), config.SignatureBase(), s.C.Format(time.RFC3339)) for _, id := range s.ids { d := id.Describe() str += fmt.Sprintf(" - name : '%v'\n details : '%v'\n", d[0], d[1]) } return str }
func TestMakeGob(t *testing.T) { s := siegfried.New() config.SetHome(*testhome) p, err := pronom.New() if err != nil { t.Fatal(err) } err = s.Add(p) if err != nil { t.Fatal(err) } sigs := filepath.Join("data", config.SignatureBase()) err = s.Save(sigs) if err != nil { t.Fatal(err) } }
// JSON representation of a Siegfried struct. // This is the provenace block at the beginning of sf results and includes descriptions for each identifier. func (s *Siegfried) JSON() string { version := config.Version() str := fmt.Sprintf( "{\"siegfried\":\"%d.%d.%d\",\"scandate\":\"%v\",\"signature\":\"%s\",\"created\":\"%v\",\"identifiers\":[", version[0], version[1], version[2], time.Now().Format(time.RFC3339), config.SignatureBase(), s.C.Format(time.RFC3339)) for i, id := range s.ids { if i > 0 { str += "," } d := id.Describe() str += fmt.Sprintf("{\"name\":\"%s\",\"details\":\"%s\"}", d[0], d[1]) } str += "]," return str }
func main() { flag.Parse() /*//UNCOMMENT TO RUN PROFILER go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }()*/ if *home != config.Home() { config.SetHome(*home) } if *sig != config.SignatureBase() { config.SetSignature(*sig) } if *version { version := config.Version() fmt.Printf("siegfried version: %d.%d.%d\n", version[0], version[1], version[2]) return } if *update { msg, err := updateSigs() if err != nil { log.Fatalf("Error: failed to update signature file, %v", err) } fmt.Println(msg) return } // during parallel scanning or in server mode, unsafe to access the last read buffer - so can't unzip or hash if *multi > 1 || *serve != "" { if *archive { log.Fatalln("Error: cannot scan archive formats when running in parallel mode") } if *hashf != "" { log.Fatalln("Error: cannot calculate file checksum when running in parallel mode") } } if err := setHash(); err != nil { log.Fatal(err) } if *serve != "" || *fprflag { s, err := siegfried.Load(config.Signature()) if err != nil { log.Fatalf("Error: error loading signature file, got: %v", err) } if *serve != "" { log.Printf("Starting server at %s. Use CTRL-C to quit.\n", *serve) listen(*serve, s) return } log.Printf("FPR server started at %s. Use CTRL-C to quit.\n", config.Fpr()) serveFpr(config.Fpr(), s) return } if flag.NArg() != 1 { log.Fatalln("Error: expecting a single file or directory argument") } s, err := siegfried.Load(config.Signature()) if err != nil { log.Fatalf("Error: error loading signature file, got: %v", err) } var w writer switch { case *debug: config.SetDebug() w = debugWriter{} case *slow: config.SetSlow() w = &slowWriter{os.Stdout} case *csvo: w = newCSV(os.Stdout) case *jsono: w = newJSON(os.Stdout) case *droido: w = newDroid(os.Stdout) case *knowno: w = &knownWriter{true, os.Stdout} case *unknowno: w = &knownWriter{false, os.Stdout} default: w = newYAML(os.Stdout) } // support reading list files from stdin if flag.Arg(0) == "-" { w.writeHead(s) scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { info, err := os.Stat(scanner.Text()) if err != nil || info.IsDir() { w.writeFile(scanner.Text(), 0, "", nil, fmt.Errorf("failed to identify %s (in scanning mode, inputs must all be files and not directories), got: %v", scanner.Text(), err), nil) } else { identifyFile(w, s, scanner.Text(), info.Size(), info.ModTime().Format(time.RFC3339)) } } w.writeTail() os.Exit(0) } info, err := os.Stat(flag.Arg(0)) if err != nil { log.Fatalf("Error: error getting info for %v, got: %v", flag.Arg(0), err) } if info.IsDir() { if config.Debug() { log.Fatalln("Error: when scanning in debug mode, give a file rather than a directory argument") } w.writeHead(s) if *multi > 16 { *multi = 16 } if *multi > 1 { multiIdentifyP(w, s, flag.Arg(0), *nr) } else { multiIdentifyS(w, s, flag.Arg(0), *nr) } w.writeTail() os.Exit(0) } w.writeHead(s) identifyFile(w, s, flag.Arg(0), info.Size(), info.ModTime().Format(time.RFC3339)) w.writeTail() os.Exit(0) }
const PROCS = -1 // flags var ( update = flag.Bool("update", false, "update or install the default signature file") version = flag.Bool("version", false, "display version information") debug = flag.Bool("debug", false, "scan in debug mode") slow = flag.Bool("slow", false, "scan and report slow signatures") nr = flag.Bool("nr", false, "prevent automatic directory recursion") csvo = flag.Bool("csv", false, "CSV output format") jsono = flag.Bool("json", false, "JSON output format") droido = flag.Bool("droid", false, "DROID CSV output format") knowno = flag.Bool("known", false, "Output list of known files") unknowno = flag.Bool("unknown", false, "Output list of unknown files") sig = flag.String("sig", config.SignatureBase(), "set the signature file") home = flag.String("home", config.Home(), "override the default home directory") serve = flag.String("serve", "", "start siegfried server e.g. -serve localhost:5138") multi = flag.Int("multi", 1, "set number of file ID processes") archive = flag.Bool("z", false, "scan archive formats (zip, tar, gzip)") hashf = flag.String("hash", "", "calculate file checksum with hash algorithm; options "+hashChoices) ) type res struct { path string sz int64 mod string c iterableID err error }
func main() { flag.Parse() /*//UNCOMMENT TO RUN PROFILER go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }()*/ if *version { version := config.Version() fmt.Printf("siegfried %d.%d.%d\n", version[0], version[1], version[2]) s, err := siegfried.Load(config.Signature()) if err != nil { fmt.Println(err) return } fmt.Print(s) return } if *home != config.Home() { config.SetHome(*home) } if *sig != config.SignatureBase() { config.SetSignature(*sig) } if *update { msg, err := updateSigs() if err != nil { log.Fatalf("[FATAL] failed to update signature file, %v", err) } fmt.Println(msg) return } // during parallel scanning or in server mode, unsafe to access the last read buffer - so can't unzip or hash if *multi > 1 || *serve != "" { if *archive { log.Fatalln("[FATAL] cannot scan archive formats when running in parallel or server mode") } if *hashf != "" { log.Fatalln("[FATAL] cannot calculate file checksum when running in parallel or server mode") } } if *logf != "" { if *multi > 1 && *logf != "error" { log.Fatalln("[FATAL] cannot log in parallel mode") } if err := newLogger(*logf); err != nil { log.Fatalln(err) } } if err := setHash(); err != nil { log.Fatal(err) } if *serve != "" || *fprflag { s, err := siegfried.Load(config.Signature()) if err != nil { log.Fatalf("[FATAL] error loading signature file, got: %v", err) } if *serve != "" { log.Printf("Starting server at %s. Use CTRL-C to quit.\n", *serve) listen(*serve, s) return } log.Printf("FPR server started at %s. Use CTRL-C to quit.\n", config.Fpr()) serveFpr(config.Fpr(), s) return } if flag.NArg() != 1 { log.Fatalln("[FATAL] expecting a single file or directory argument") } s, err := siegfried.Load(config.Signature()) if err != nil { log.Fatalf("[FATAL] error loading signature file, got: %v", err) } var w writer switch { case *csvo: w = newCSV(os.Stdout) case *jsono: w = newJSON(os.Stdout) case *droido: w = newDroid(os.Stdout) default: w = newYAML(os.Stdout) } if lg != nil && lg.w == os.Stdout { w = logWriter{} } // support reading list files from stdin if flag.Arg(0) == "-" { w.writeHead(s) scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { info, err := os.Stat(scanner.Text()) if err != nil { info, err = retryStat(scanner.Text(), err) } if err != nil || info.IsDir() { writeError(w, scanner.Text(), 0, "", fmt.Errorf("failed to identify %s (in scanning mode, inputs must all be files and not directories), got: %v", scanner.Text(), err)) } else { identifyFile(w, s, scanner.Text(), info.Size(), info.ModTime().Format(time.RFC3339)) } } w.writeTail() lg.printElapsed() os.Exit(0) } info, err := os.Stat(flag.Arg(0)) if err != nil { info, err = retryStat(flag.Arg(0), err) if err != nil { log.Fatalf("[FATAL] cannot get info for %v, got: %v", flag.Arg(0), err) } } if info.IsDir() { w.writeHead(s) if *multi > 16 { *multi = 16 } if *multi > 1 { err = multiIdentifyP(w, s, flag.Arg(0), *nr) } else { if *throttlef != 0 { throttle = time.NewTicker(*throttlef) defer throttle.Stop() } err = multiIdentifyS(w, s, flag.Arg(0), "", *nr) } w.writeTail() if err != nil { log.Fatalf("[FATAL] %v\n", err) } lg.printElapsed() os.Exit(0) } w.writeHead(s) identifyFile(w, s, flag.Arg(0), info.Size(), info.ModTime().Format(time.RFC3339)) w.writeTail() lg.printElapsed() os.Exit(0) }