diff options
| author | flu0r1ne <flu0r1ne@flu0r1ne.net> | 2021-07-22 17:18:21 -0500 | 
|---|---|---|
| committer | flu0r1ne <flu0r1ne@flu0r1ne.net> | 2021-07-22 17:18:21 -0500 | 
| commit | 34d7d612dd376258248ee6cae07b839951fccf32 (patch) | |
| tree | 6d637a04f5cbbd285c89331a3b9fb58b5e605e52 /snap | |
| parent | af8f52e2e4c879935656dd93c2fb564c6e2ce515 (diff) | |
| download | zsu-34d7d612dd376258248ee6cae07b839951fccf32.tar.xz zsu-34d7d612dd376258248ee6cae07b839951fccf32.zip | |
List command, diff command, and snapshot search infrastructure
Diffstat (limited to 'snap')
| -rw-r--r-- | snap/fs.go | 147 | ||||
| -rw-r--r-- | snap/parsing.go | 3 | 
2 files changed, 148 insertions, 2 deletions
| diff --git a/snap/fs.go b/snap/fs.go new file mode 100644 index 0000000..d0dc83d --- /dev/null +++ b/snap/fs.go @@ -0,0 +1,147 @@ +package snap + +import ( +	"time" +	"path/filepath" +	"os" +	"sort" +) + +type Snapshot struct { +	Name      string +	ModTime   time.Time +	Reference string +} + +func getZFSRoot(reference string) string { +	cursor := filepath.Dir(reference) +	zfsNotFound := false + +	for !zfsNotFound { +		zfsDir := filepath.Join(cursor, ".zfs") +		 +		if _, err := os.Stat(zfsDir); !os.IsNotExist(err) { +			break +		}  + +		cursor = filepath.Join(cursor, "..") + +		zfsNotFound = filepath.ToSlash(cursor) == "/" +	} + +	if(zfsNotFound) { +		die.Fatal("Could not find a .zfs directory. Are you within a zfs dataset?") +	} + +	return cursor +} + +func getSnapshots(reference string) []*Snapshot { +	zfsRoot := getZFSRoot(reference) + +	snapshotDir := filepath.Join(zfsRoot, ".zfs", "snapshot"); + +	files, err := os.ReadDir(snapshotDir) +	if err != nil { +		die.Fatalf("Could not find the snapshots directory inside %s", snapshotDir); +	} + +	relPath, err := filepath.Rel(zfsRoot, reference) +	if err != nil { +		die.Fatal("Could not find relative path to reference file: %v", err) +	} + +	snaps := make([]*Snapshot, len(files)) + +	for i, file := range files { + +		info, err := file.Info() +		if(err != nil) { +			die.Fatalf("Could not read file %v", err) +		} + +		name := file.Name() +		snaps[i] = &Snapshot{ +			Name: name, +			ModTime: info.ModTime(), +		} + +		pathInSnap := filepath.Join(snapshotDir, name, relPath) + +		if _, err := os.Stat(pathInSnap); err != nil { +			if !os.IsNotExist(err) { +				die.Fatalf("Error encountered while attempting to read reference file in snapshot:\n%v", err) +			} +		} else { +			snaps[i].Reference = pathInSnap +		} + +	} + +	return snaps +} + +func GetTimeseries(reference string) []*Snapshot { +	reference, err := filepath.Abs(reference) + +	if err != nil { +	  die.Fatal(err) +	} +	 +	snaps := getSnapshots(reference) + +	sort.Slice(snaps, func(i, j int) bool { +		return snaps[i].ModTime.Before(snaps[j].ModTime) +	}) + +	return snaps +} + +func buildNameMap(snapTs []*Snapshot) map[string] int { +	namemap := make(map[string] int) + +	for i, snap := range snapTs { +		namemap[snap.Name] = i +	} + +	return namemap +} + +type SnapshotOracle struct { +	timeseries []*Snapshot +	namemap    map[string] int +}; + +func GetOracle(reference string) *SnapshotOracle { +	timeseries := GetTimeseries(reference) +	namemap := buildNameMap(timeseries) + + +	return &SnapshotOracle { +		timeseries, +		namemap, +	} +} + +func (oracle *SnapshotOracle) ResolveRelative(ref *Relative) string { +	n_ts := len(oracle.timeseries) +	wanted := n_ts - 1 + +	if ref.snapshot != "" { +		id, ok := oracle.namemap[ref.snapshot] + +		if !ok { +			die.Fatal("Could not find the snapshot %s", ref.snapshot) +		} + +		wanted = id +	} + +	wanted += ref.offset + +	if wanted < 0 || wanted >= n_ts { +		die.Fatal("The snapshot you requested is out of range.") +	} + +	return oracle.timeseries[wanted].Reference +}
\ No newline at end of file diff --git a/snap/parsing.go b/snap/parsing.go index e878077..fcacec9 100644 --- a/snap/parsing.go +++ b/snap/parsing.go @@ -78,7 +78,7 @@ func ToRelative(snapish string) * Relative {  		return ref;  	} -	if ref := parseRelativeSyntax(snapish, "~"); ref != nil { +	if ref := parseRelativeSyntax(snapish, "^"); ref != nil {  		ref.offset = -ref.offset;  		return ref;  	} @@ -88,7 +88,6 @@ func ToRelative(snapish string) * Relative {  	};  } -// FROM, TO  func ParseDiff(snapdiff string) (fromRel, toRel *Relative) {  	snapishes := strings.Split(snapdiff, "..") | 
