aboutsummaryrefslogtreecommitdiff
path: root/internal/openfiletable/inummap.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2019-11-16 21:35:26 +0100
committerJakob Unterwurzacher2019-11-16 21:35:26 +0100
commite5d5ab397384001566d573a13a142ed1bc2bc2aa (patch)
treed9b268f51a5cb33d8876a35d12b6c5c8ac9e17a5 /internal/openfiletable/inummap.go
parent31ff557f85cca54b935231668d382cfc0e61751a (diff)
openfiletable: add inummap
Generates unique inode numbers for files on different devices. https://github.com/rfjakob/gocryptfs/issues/435
Diffstat (limited to 'internal/openfiletable/inummap.go')
-rw-r--r--internal/openfiletable/inummap.go63
1 files changed, 63 insertions, 0 deletions
diff --git a/internal/openfiletable/inummap.go b/internal/openfiletable/inummap.go
new file mode 100644
index 0000000..d9f6862
--- /dev/null
+++ b/internal/openfiletable/inummap.go
@@ -0,0 +1,63 @@
+package openfiletable
+
+import (
+ "sync"
+ "syscall"
+)
+
+// UINT64_MAX = 18446744073709551615
+const inumTranslateBase = 10000000000000000000
+
+// InumMap ... see NewInumMap() for description.
+type InumMap struct {
+ sync.Mutex
+ baseDev uint64
+ translate map[QIno]uint64
+ translateNext uint64
+}
+
+// NewInumMap returns a new inumMap.
+//
+// inumMap translates (device uint64, inode uint64) pairs to unique uint64
+// inode numbers.
+// Inode numbers on the "baseDev" are passed through unchanged (as long as they
+// are not higher than inumTranslateBase).
+// Inode numbers on other devices are remapped to the number space above
+// 10000000000000000000. The mapping is stored in a simple Go map. Entries
+// can only be added and are never removed.
+func NewInumMap(baseDev uint64) *InumMap {
+ return &InumMap{
+ baseDev: baseDev,
+ translate: make(map[QIno]uint64),
+ translateNext: inumTranslateBase,
+ }
+}
+
+// Translate maps the passed-in (device, inode) pair to a unique inode number.
+func (m *InumMap) Translate(in QIno) (out uint64) {
+ if in.Dev == m.baseDev && in.Ino < inumTranslateBase {
+ return in.Ino
+ }
+ m.Lock()
+ defer m.Unlock()
+ out = m.translate[in]
+ if out != 0 {
+ return out
+ }
+ out = m.translateNext
+ m.translate[in] = m.translateNext
+ m.translateNext++
+ return out
+}
+
+// TranslateStat translates the inode number contained in "st" if neccessary.
+// Convience wrapper around Translate().
+func (m *InumMap) TranslateStat(st *syscall.Stat_t) {
+ in := QInoFromStat(st)
+ st.Ino = m.Translate(in)
+}
+
+// Count returns the number of entries in the translation table.
+func (m *InumMap) Count() int {
+ return len(m.translate)
+}