feat: Add portable Timespec implementation for FileInfo

This commit is contained in:
Felicitas Pojtinger
2022-01-16 01:18:45 +01:00
parent e32d0d16c6
commit 2f8e6e8875
6 changed files with 120 additions and 41 deletions

View File

@@ -7,6 +7,7 @@ import (
"io/fs" "io/fs"
"os" "os"
"sync" "sync"
"time"
"github.com/pojntfx/stfs/internal/ioext" "github.com/pojntfx/stfs/internal/ioext"
"github.com/pojntfx/stfs/pkg/cache" "github.com/pojntfx/stfs/pkg/cache"
@@ -124,17 +125,24 @@ func (f *File) syncWithoutLocking() error {
// Some OSes like i.e. Windows don't support numeric GIDs and UIDs, so use 0 instead // Some OSes like i.e. Windows don't support numeric GIDs and UIDs, so use 0 instead
gid := 0 gid := 0
uid := 0 uid := 0
modTime := f.info.ModTime()
accessTime := f.info.ModTime()
changeTime := f.info.ModTime()
sys, ok := f.info.Sys().(*Stat) sys, ok := f.info.Sys().(*Stat)
if ok { if ok {
gid = int(sys.Gid) gid = int(sys.Gid)
uid = int(sys.Uid) uid = int(sys.Uid)
accessTime = time.Unix(0, sys.Atim.Nano())
changeTime = time.Unix(0, sys.Ctim.Nano())
} }
f.info = NewFileInfo( f.info = NewFileInfo(
f.info.Name(), f.info.Name(),
size, size,
f.info.Mode(), f.info.Mode(),
f.info.ModTime(), modTime,
accessTime,
changeTime,
gid, gid,
uid, uid,
f.info.IsDir(), f.info.IsDir(),

View File

@@ -1,8 +0,0 @@
//go:build windows
package fs
type Stat struct {
Uid uint32
Gid uint32
}

View File

@@ -1,7 +0,0 @@
//go:build !windows
package fs
import "syscall"
type Stat syscall.Stat_t

View File

@@ -12,13 +12,15 @@ import (
type FileInfo struct { type FileInfo struct {
os.FileInfo os.FileInfo
name string name string
size int64 size int64
mode fs.FileMode mode fs.FileMode
modTime time.Time modTime time.Time
gid int accessTime time.Time
uid int changeTime time.Time
isDir bool gid int
uid int
isDir bool
log logging.StructuredLogger log logging.StructuredLogger
} }
@@ -28,6 +30,8 @@ func NewFileInfo(
size int64, size int64,
mode fs.FileMode, mode fs.FileMode,
modTime time.Time, modTime time.Time,
accessTime time.Time,
changeTime time.Time,
gid int, gid int,
uid int, uid int,
isDir bool, isDir bool,
@@ -35,13 +39,15 @@ func NewFileInfo(
log logging.StructuredLogger, log logging.StructuredLogger,
) *FileInfo { ) *FileInfo {
return &FileInfo{ return &FileInfo{
name: name, name: name,
size: size, size: size,
mode: mode, mode: mode,
modTime: modTime, modTime: modTime,
gid: gid, accessTime: accessTime,
uid: uid, changeTime: changeTime,
isDir: isDir, gid: gid,
uid: uid,
isDir: isDir,
log: log, log: log,
} }
@@ -53,13 +59,15 @@ func NewFileInfoFromTarHeader(
log logging.StructuredLogger, log logging.StructuredLogger,
) *FileInfo { ) *FileInfo {
return &FileInfo{ return &FileInfo{
name: hdr.FileInfo().Name(), name: hdr.FileInfo().Name(),
size: hdr.FileInfo().Size(), size: hdr.FileInfo().Size(),
mode: hdr.FileInfo().Mode(), mode: hdr.FileInfo().Mode(),
modTime: hdr.FileInfo().ModTime(), modTime: hdr.FileInfo().ModTime(),
gid: hdr.Gid, accessTime: hdr.AccessTime,
uid: hdr.Uid, changeTime: hdr.ChangeTime,
isDir: hdr.FileInfo().IsDir(), gid: hdr.Gid,
uid: hdr.Uid,
isDir: hdr.FileInfo().IsDir(),
log: log, log: log,
} }
@@ -110,8 +118,11 @@ func (f *FileInfo) Sys() interface{} {
"name": f.name, "name": f.name,
}) })
return &Stat{ return NewStat(
Uid: uint32(f.uid), uint32(f.uid),
Gid: uint32(f.gid), uint32(f.gid),
} f.modTime.UnixNano(),
f.accessTime.UnixNano(),
f.changeTime.UnixNano(),
)
} }

View File

@@ -0,0 +1,52 @@
//go:build !linux
package fs
// From the Go stdlib for linux/amd64
type Timespec struct {
Sec int64
Nsec int64
}
func (ts *Timespec) Unix() (sec int64, nsec int64) {
return int64(ts.Sec), int64(ts.Nsec)
}
func (ts *Timespec) Nano() int64 {
return int64(ts.Sec)*1e9 + int64(ts.Nsec)
}
func NsecToTimespec(nsec int64) Timespec {
sec := nsec / 1e9
nsec = nsec % 1e9
if nsec < 0 {
nsec += 1e9
sec--
}
return Timespec{Sec: sec, Nsec: nsec}
}
type Stat struct {
Uid uint32
Gid uint32
Mtim Timespec
Atim Timespec
Ctim Timespec
}
func NewStat(
uid uint32,
gid uint32,
mtim int64,
atim int64,
ctim int64,
) *Stat {
return &Stat{
Uid: uid,
Gid: gid,
Mtim: NsecToTimespec(mtim),
Atim: NsecToTimespec(atim),
Ctim: NsecToTimespec(ctim),
}
}

View File

@@ -0,0 +1,23 @@
//go:build linux
package fs
import "syscall"
type Stat syscall.Stat_t
func NewStat(
uid uint32,
gid uint32,
mtim int64,
atim int64,
ctim int64,
) *Stat {
return &Stat{
Uid: uid,
Gid: gid,
Mtim: syscall.NsecToTimespec(mtim),
Atim: syscall.NsecToTimespec(atim),
Ctim: syscall.NsecToTimespec(ctim),
}
}