Пример #1
0
func (st *State) Sync(name string, add [][]byte, del []string) ([][]byte, error) {
	mgr := st.Managers[name]
	if mgr == nil || mgr.Connected.IsZero() {
		return nil, fmt.Errorf("unconnected manager %v", name)
	}
	if len(del) != 0 {
		for _, h := range del {
			sig, err := hash.FromString(h)
			if err != nil {
				Logf(0, "manager %v: bad hash: %v", mgr.name, h)
				continue
			}
			delete(mgr.Corpus, sig)
		}
		st.purgeCorpus()
	}
	if len(add) != 0 {
		st.seq++
		for _, prog := range add {
			st.addInput(mgr, prog)
		}
	}
	inputs, err := st.pendingInputs(mgr)
	mgr.Added += len(add)
	mgr.Deleted += len(del)
	mgr.New += len(inputs)
	return inputs, err
}
Пример #2
0
func newPersistentSet(dir string, verify func(data []byte) bool) *PersistentSet {
	ps := &PersistentSet{
		dir: dir,
		m:   make(map[hash.Sig][]byte),
	}
	os.MkdirAll(dir, 0770)
	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			Fatalf("error during dir walk: %v\n", err)
		}
		if info.IsDir() {
			if info.Name() == ".git" {
				return filepath.SkipDir // in case corpus is checked in
			}
			return nil
		}
		data, err := ioutil.ReadFile(path)
		if err != nil {
			Fatalf("error during file read: %v\n", err)
			return nil
		}
		sig := hash.Hash(data)
		if _, ok := ps.m[sig]; ok {
			return nil
		}
		name := info.Name()
		if len(data) == 0 {
			// This can happen is master runs on machine-under-test,
			// and it has crashed midway.
			Logf(0, "removing empty file %v", name)
			os.Remove(path)
			return nil
		}
		if _, err := hash.FromString(name); err != nil {
			Logf(0, "unknown file in persistent dir %v: %v", dir, name)
			return nil
		}
		if verify != nil && !verify(data) {
			os.Remove(path)
			return nil
		}
		if name != sig.String() {
			Logf(0, "bad hash in persistent dir %v for file %v, expect %v", dir, name, sig.String())
			if err := ioutil.WriteFile(filepath.Join(ps.dir, sig.String()), data, 0660); err != nil {
				Fatalf("failed to write file: %v", err)
			}
			os.Remove(path)
		}
		ps.m[sig] = data
		ps.a = append(ps.a, data)
		return nil
	})
	return ps
}
Пример #3
0
// Make creates State and initializes it from dir.
func Make(dir string) (*State, error) {
	st := &State{
		dir:      dir,
		Corpus:   make(map[hash.Sig]*Input),
		Managers: make(map[string]*Manager),
	}

	corpusDir := filepath.Join(st.dir, "corpus")
	os.MkdirAll(corpusDir, 0700)
	inputs, err := ioutil.ReadDir(corpusDir)
	if err != nil {
		return nil, fmt.Errorf("failed to read %v dir: %v", corpusDir, err)
	}
	for _, inp := range inputs {
		data, err := ioutil.ReadFile(filepath.Join(corpusDir, inp.Name()))
		if err != nil {
			return nil, err
		}
		if _, err := prog.CallSet(data); err != nil {
			return nil, err
		}
		parts := strings.Split(inp.Name(), "-")
		if len(parts) != 2 {
			return nil, fmt.Errorf("bad file in corpus: %v", inp.Name())
		}
		seq, err := strconv.ParseUint(parts[1], 10, 64)
		if err != nil {
			return nil, fmt.Errorf("bad file in corpus: %v", inp.Name())
		}
		sig := hash.Hash(data)
		if sig.String() != parts[0] {
			return nil, fmt.Errorf("bad file in corpus: %v, want hash %v", inp.Name(), sig.String())
		}
		st.Corpus[sig] = &Input{
			seq:  seq,
			prog: data,
		}
		if st.seq < seq {
			st.seq = seq
		}
	}

	managersDir := filepath.Join(st.dir, "manager")
	os.MkdirAll(managersDir, 0700)
	managers, err := ioutil.ReadDir(managersDir)
	if err != nil {
		return nil, fmt.Errorf("failed to read %v dir: %v", managersDir, err)
	}
	for _, manager := range managers {
		mgr := &Manager{
			name: manager.Name(),
		}
		st.Managers[mgr.name] = mgr
		mgr.dir = filepath.Join(managersDir, mgr.name)
		seqStr, _ := ioutil.ReadFile(filepath.Join(mgr.dir, "seq"))
		mgr.seq, _ = strconv.ParseUint(string(seqStr), 10, 64)
		if st.seq < mgr.seq {
			st.seq = mgr.seq
		}

		mgr.Corpus = make(map[hash.Sig]bool)
		corpusDir := filepath.Join(mgr.dir, "corpus")
		os.MkdirAll(corpusDir, 0700)
		corpus, err := ioutil.ReadDir(corpusDir)
		if err != nil {
			return nil, fmt.Errorf("failed to read %v dir: %v", corpusDir, err)
		}
		for _, input := range corpus {
			sig, err := hash.FromString(input.Name())
			if err != nil {
				return nil, fmt.Errorf("bad file in corpus: %v", input.Name())
			}
			mgr.Corpus[sig] = true
		}
	}

	return st, err
}