func (kvdb *kvStore) CompleteRom(rom *types.Rom) error { if rom.Sha1 != nil { return nil } if rom.Md5 != nil { dBytes, err := kvdb.md5sha1DB.Get(rom.Md5) if err != nil { return err } if len(dBytes) >= sha1.Size { rom.Sha1 = dBytes } else { glog.Warningf("no mapping from MD5 %s to SHA1", hex.EncodeToString(rom.Md5)) } return nil } if rom.Crc != nil { dBytes, err := kvdb.crcsha1DB.Get(rom.Crc) if err != nil { return err } if len(dBytes) >= sha1.Size { rom.Sha1 = dBytes } else { glog.Warningf("no mapping from CRC %s to SHA1", hex.EncodeToString(rom.Crc)) } } return nil }
func (gw *gameWalker) visit(path string, f os.FileInfo, err error) error { if f == nil || f.Name() == ".DS_Store" { return nil } if f.IsDir() { return nil } hh, err := HashesForFile(path) if err != nil { return err } romName, err := filepath.Rel(gw.gamepath, path) if err != nil { return err } rom := new(types.Rom) rom.Name = romName rom.Size = f.Size() rom.Crc = hh.Crc rom.Md5 = hh.Md5 rom.Sha1 = hh.Sha1 gw.game.Roms = append(gw.game.Roms, rom) return nil }
func RomFromGZDepotFile(inpath string) (*types.Rom, error) { rom := new(types.Rom) fileName := filepath.Base(inpath) sha1Hex := strings.TrimSuffix(fileName, filepath.Ext(fileName)) sha1, err := hex.DecodeString(sha1Hex) if err != nil { return nil, err } rom.Sha1 = sha1 return rom, nil }
func fixHashes(rom *types.Rom) { if rom.Crc != nil { strV := string(rom.Crc) if strV != "" { v, err := hex.DecodeString(string(rom.Crc)) if err != nil { rom.Crc = nil } rom.Crc = v } else { rom.Crc = nil } } if rom.Md5 != nil { strV := string(rom.Md5) if strV != "" { v, err := hex.DecodeString(string(rom.Md5)) if err != nil { rom.Md5 = nil } rom.Md5 = v } else { rom.Md5 = nil } } if rom.Sha1 != nil { strV := string(rom.Sha1) if strV != "" { v, err := hex.DecodeString(string(rom.Sha1)) if err != nil { rom.Sha1 = nil } rom.Sha1 = v } else { rom.Sha1 = nil } } }
func (kvdb *kvStore) CompleteRom(rom *types.Rom) error { if rom.Sha1 != nil { return nil } if rom.Md5 != nil { dBytes, err := kvdb.md5sha1DB.GetKeySuffixesFor(rom.Md5WithSizeKey()) if err != nil { return err } rom.Sha1 = dBytes return nil } if rom.Crc != nil { dBytes, err := kvdb.crcsha1DB.GetKeySuffixesFor(rom.CrcWithSizeKey()) if err != nil { return err } rom.Sha1 = dBytes } return nil }
func (rs *RombaService) lookup(cmd *commander.Command, args []string) error { for _, arg := range args { hash, err := hex.DecodeString(arg) if err != nil { return err } if len(hash) == sha1.Size { dat, err := rs.romDB.GetDat(hash) if err != nil { return err } if dat != nil { fmt.Fprintf(cmd.Stdout, "dat with sha1 %s = %s\n", arg, types.PrintShortDat(dat)) } } r := new(types.Rom) switch len(hash) { case md5.Size: r.Md5 = hash case crc32.Size: r.Crc = hash case sha1.Size: r.Sha1 = hash default: return fmt.Errorf("found unknown hash size: %d", len(hash)) } dats, err := rs.romDB.DatsForRom(r) if err != nil { return err } err = rs.romDB.CompleteRom(r) if err != nil { return err } if len(dats) > 0 { fmt.Fprintf(cmd.Stdout, "rom in %s\n", types.PrintRomInDats(dats)) } } return nil }
func lookupByHash(hash []byte) (bool, error) { found := false if len(hash) == sha1.Size { dat, err := romDB.GetDat(hash) if err != nil { return false, err } if dat != nil { fmt.Printf("dat = %s\n", types.PrintDat(dat)) found = true } } r := new(types.Rom) switch len(hash) { case md5.Size: r.Md5 = hash case crc32.Size: r.Crc = hash case sha1.Size: r.Sha1 = hash default: return false, fmt.Errorf("found unknown hash size: %d", len(hash)) } dats, err := romDB.DatsForRom(r) if err != nil { return false, err } for _, dat := range dats { fmt.Printf("dat = %s\n", types.PrintDat(dat)) } found = found || len(dats) > 0 return found, nil }
func (w *archiveWorker) archive(ro readerOpener, name, path string, size int64, hh *Hashes, md5crcBuffer []byte) (int64, error) { r, err := ro() if err != nil { return 0, err } br := bufio.NewReader(r) err = hh.forReader(br) if err != nil { r.Close() return 0, err } err = r.Close() if err != nil { return 0, err } // if filestat size is different than size read then size read wins if size != hh.Size { size = hh.Size } copy(md5crcBuffer[0:md5.Size], hh.Md5) copy(md5crcBuffer[md5.Size:md5.Size+crc32.Size], hh.Crc) util.Int64ToBytes(size, md5crcBuffer[md5.Size+crc32.Size:]) rom := new(types.Rom) rom.Crc = make([]byte, crc32.Size) rom.Md5 = make([]byte, md5.Size) rom.Sha1 = make([]byte, sha1.Size) copy(rom.Crc, hh.Crc) copy(rom.Md5, hh.Md5) copy(rom.Sha1, hh.Sha1) rom.Name = name rom.Size = size rom.Path = path if !w.pm.noDB { if w.pm.onlyneeded { dats, err := w.depot.romDB.DatsForRom(rom) if err != nil { return 0, err } if len(dats) == 0 { return 0, nil } } err = w.depot.romDB.IndexRom(rom) if err != nil { return 0, err } } sha1Hex := hex.EncodeToString(hh.Sha1) exists, _, err := w.depot.RomInDepot(sha1Hex) if err != nil { return 0, err } if exists { glog.V(4).Infof("%s already in depot, skipping %s/%s", sha1Hex, path, name) return 0, nil } estimatedCompressedSize := size / 5 root, err := w.depot.reserveRoot(estimatedCompressedSize) if err != nil { return 0, err } outpath := pathFromSha1HexEncoding(w.depot.roots[root], sha1Hex, gzipSuffix) r, err = ro() if err != nil { return 0, err } defer r.Close() compressedSize, err := archive(outpath, r, md5crcBuffer) if err != nil { return 0, err } w.depot.adjustSize(root, compressedSize-estimatedCompressedSize) return compressedSize, nil }
func (rs *RombaService) lookup(cmd *commander.Command, args []string) error { size := cmd.Flag.Lookup("size").Value.Get().(int64) outpath := cmd.Flag.Lookup("out").Value.Get().(string) for _, arg := range args { fmt.Fprintf(cmd.Stdout, "----------------------------------------\n") fmt.Fprintf(cmd.Stdout, "key: %s\n", arg) if strings.HasPrefix(arg, "0x") { arg = arg[2:] } hash, err := hex.DecodeString(arg) if err != nil { return err } if len(hash) == sha1.Size { dat, err := rs.romDB.GetDat(hash) if err != nil { return err } if dat != nil { fmt.Fprintf(cmd.Stdout, "-----------------\n") fmt.Fprintf(cmd.Stdout, "dat with sha1 %s = %s\n", arg, types.PrintShortDat(dat)) } } if size != -1 || len(hash) == sha1.Size { r := new(types.Rom) r.Size = size switch len(hash) { case md5.Size: r.Md5 = hash case crc32.Size: r.Crc = hash case sha1.Size: r.Sha1 = hash default: return fmt.Errorf("found unknown hash size: %d", len(hash)) } err = rs.lookupRom(cmd, r, outpath) if err != nil { return err } fmt.Fprintf(cmd.Stdout, "-----------------\n") fmt.Fprintf(cmd.Stdout, "DebugGet:\n%s\n", rs.romDB.DebugGet(hash, size)) } else { suffixes, err := rs.romDB.ResolveHash(hash) if err != nil { return err } for i := 0; i < len(suffixes); i += sha1.Size + 8 { r := new(types.Rom) r.Size = util.BytesToInt64(suffixes[i : i+8]) switch len(hash) { case md5.Size: r.Md5 = hash case crc32.Size: r.Crc = hash default: return fmt.Errorf("found unknown hash size: %d", len(hash)) } r.Sha1 = suffixes[i+8 : i+8+sha1.Size] err = rs.lookupRom(cmd, r, outpath) if err != nil { return err } } } } return nil }
func (w *archiveWorker) archive(ro readerOpener, root int, name, path string, size int64) (int64, error) { r, err := ro() if err != nil { return 0, err } br := bufio.NewReader(r) err = w.hh.forReader(br) if err != nil { r.Close() return 0, err } err = r.Close() if err != nil { return 0, err } copy(w.md5crcBuffer[0:md5.Size], w.hh.Md5) copy(w.md5crcBuffer[md5.Size:], w.hh.Crc) rom := new(types.Rom) rom.Crc = make([]byte, crc32.Size) rom.Md5 = make([]byte, md5.Size) rom.Sha1 = make([]byte, sha1.Size) copy(rom.Crc, w.hh.Crc) copy(rom.Md5, w.hh.Md5) copy(rom.Sha1, w.hh.Sha1) rom.Name = name rom.Size = size rom.Path = path if w.pm.onlyneeded { dats, err := w.depot.romDB.DatsForRom(rom) if err != nil { return 0, err } needed := false for _, dat := range dats { if !dat.Artificial { needed = true break } } if !needed { return 0, nil } } err = w.depot.romDB.IndexRom(rom) if err != nil { return 0, err } sha1Hex := hex.EncodeToString(w.hh.Sha1) outpath := pathFromSha1HexEncoding(w.depot.roots[root], sha1Hex, gzipSuffix) exists, err := PathExists(outpath) if err != nil { return 0, err } if exists { return 0, nil } r, err = ro() if err != nil { return 0, err } defer r.Close() compressedSize, err := archive(outpath, r, w.md5crcBuffer) if err != nil { return 0, err } w.depot.adjustSize(root, compressedSize) return compressedSize, nil }
func TestDB(t *testing.T) { dbDir, err := ioutil.TempDir("", "rombadb") if err != nil { t.Fatalf("cannot create temp dir for test db: %v", err) } t.Logf("creating test db in %s\n", dbDir) krdb, err := db.New(dbDir) if err != nil { t.Fatalf("failed to open db: %v", err) } dat, sha1Bytes, err := parser.ParseDat(strings.NewReader(datText), "testing/dat") if err != nil { t.Fatalf("failed to parse test dat: %v", err) } err = krdb.IndexDat(dat, sha1Bytes) if err != nil { t.Fatalf("failed to index test dat: %v", err) } datFromDb, err := krdb.GetDat(sha1Bytes) if err != nil { t.Fatalf("failed to retrieve test dat: %v", err) } if !datFromDb.Equals(dat) { fmt.Printf("datFromDb=%s\n", string(types.PrintDat(datFromDb))) fmt.Printf("dat=%s\n", string(types.PrintDat(dat))) t.Fatalf("dat differs from db dat") } romSha1Bytes, err := hex.DecodeString("80353cb168dc5d7cc1dce57971f4ea2640a50ac4") if err != nil { t.Fatalf("failed to hex decode: %v", err) } rom := new(types.Rom) rom.Sha1 = romSha1Bytes dats, err := krdb.DatsForRom(rom) if err != nil { t.Fatalf("failed to retrieve dats for rom: %v", err) } if len(dats) != 1 { t.Fatalf("couldn't find dats for rom") } datFromDb = dats[0] if !datFromDb.Equals(dat) { fmt.Printf("datFromDb=%s\n", string(types.PrintDat(datFromDb))) fmt.Printf("dat=%s\n", string(types.PrintDat(dat))) t.Fatalf("dat differs from db dat") } err = krdb.Close() if err != nil { t.Fatalf("failed to close db: %v", err) } err = os.RemoveAll(dbDir) if err != nil { t.Fatalf("failed to remove test db dir %s: %v", dbDir, err) } }