mirror of
https://github.com/vbatts/dedupe-linker.git
synced 2024-12-27 00:56:31 +00:00
findbase: walk up tree to find a suitable base dir
Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
This commit is contained in:
parent
854f6bbccb
commit
aa4b5f4c39
2 changed files with 142 additions and 0 deletions
67
base/findbase.go
Normal file
67
base/findbase.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
package base
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// FindBase steps up the directory tree to find the top-level that is still on
|
||||
// the same device as the path provided
|
||||
func FindBase(path string) (string, error) {
|
||||
stat, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if stat.IsDir() {
|
||||
return findBaseInfo(stat)
|
||||
}
|
||||
|
||||
return FindBase(filepath.Dir(path))
|
||||
}
|
||||
|
||||
func findBaseInfo(stat os.FileInfo) (string, error) {
|
||||
dirstat, err := os.Lstat(filepath.Dir(stat.Name()))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if stat.Name() == dirstat.Name() {
|
||||
return stat.Name(), nil
|
||||
}
|
||||
|
||||
if sameDevice(stat, dirstat) {
|
||||
return findBaseInfo(dirstat)
|
||||
}
|
||||
return stat.Name(), nil
|
||||
}
|
||||
|
||||
func hasPermission(path string) bool {
|
||||
stat, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if !stat.IsDir() {
|
||||
path = filepath.Dir(path)
|
||||
}
|
||||
fh, err := ioutil.TempFile(path, "perm.test.")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
os.Remove(fh.Name())
|
||||
return true
|
||||
}
|
||||
|
||||
func sameDevice(file1, file2 os.FileInfo) bool {
|
||||
sys1 := file1.Sys().(*syscall.Stat_t)
|
||||
sys2 := file2.Sys().(*syscall.Stat_t)
|
||||
return ((major(sys1.Dev) == major(sys2.Dev)) && (minor(sys1.Dev) == minor(sys2.Dev)))
|
||||
}
|
||||
|
||||
func major(n uint64) uint64 {
|
||||
return uint64(n / 256)
|
||||
}
|
||||
|
||||
func minor(n uint64) uint64 {
|
||||
return uint64(n % 256)
|
||||
}
|
75
base/findbase_test.go
Normal file
75
base/findbase_test.go
Normal file
|
@ -0,0 +1,75 @@
|
|||
package base
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHasPermission(t *testing.T) {
|
||||
if !hasPermission("/tmp") {
|
||||
t.Error("expected to have permission to /tmp, but did not")
|
||||
}
|
||||
|
||||
if hasPermission("/") {
|
||||
t.Error("expected to not have permission to /, but did")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSameDev(t *testing.T) {
|
||||
file1, err := ioutil.TempFile("", "test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer file1.Close()
|
||||
file2, err := ioutil.TempFile("", "test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer file2.Close()
|
||||
|
||||
stat1, err := file1.Stat()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
stat2, err := file2.Stat()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !sameDevice(stat1, stat2) {
|
||||
t.Errorf("expected the two files to be on same device. But %q and %q are not", file1.Name(), file2.Name())
|
||||
} else {
|
||||
os.Remove(stat1.Name())
|
||||
os.Remove(stat2.Name())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNotSameDev(t *testing.T) {
|
||||
file1, err := ioutil.TempFile("/tmp", "test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer file1.Close()
|
||||
file2, err := ioutil.TempFile("/home/vbatts", "test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer file2.Close()
|
||||
|
||||
stat1, err := file1.Stat()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
stat2, err := file2.Stat()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if sameDevice(stat1, stat2) {
|
||||
t.Errorf("expected the two files _not_ to be on same device. But %q and %q are not", file1.Name(), file2.Name())
|
||||
} else {
|
||||
os.Remove(stat1.Name())
|
||||
os.Remove(stat2.Name())
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue