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"
"os"
"sync"
"time"
"github.com/pojntfx/stfs/internal/ioext"
"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
gid := 0
uid := 0
modTime := f.info.ModTime()
accessTime := f.info.ModTime()
changeTime := f.info.ModTime()
sys, ok := f.info.Sys().(*Stat)
if ok {
gid = int(sys.Gid)
uid = int(sys.Uid)
accessTime = time.Unix(0, sys.Atim.Nano())
changeTime = time.Unix(0, sys.Ctim.Nano())
}
f.info = NewFileInfo(
f.info.Name(),
size,
f.info.Mode(),
f.info.ModTime(),
modTime,
accessTime,
changeTime,
gid,
uid,
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

@@ -16,6 +16,8 @@ type FileInfo struct {
size int64
mode fs.FileMode
modTime time.Time
accessTime time.Time
changeTime time.Time
gid int
uid int
isDir bool
@@ -28,6 +30,8 @@ func NewFileInfo(
size int64,
mode fs.FileMode,
modTime time.Time,
accessTime time.Time,
changeTime time.Time,
gid int,
uid int,
isDir bool,
@@ -39,6 +43,8 @@ func NewFileInfo(
size: size,
mode: mode,
modTime: modTime,
accessTime: accessTime,
changeTime: changeTime,
gid: gid,
uid: uid,
isDir: isDir,
@@ -57,6 +63,8 @@ func NewFileInfoFromTarHeader(
size: hdr.FileInfo().Size(),
mode: hdr.FileInfo().Mode(),
modTime: hdr.FileInfo().ModTime(),
accessTime: hdr.AccessTime,
changeTime: hdr.ChangeTime,
gid: hdr.Gid,
uid: hdr.Uid,
isDir: hdr.FileInfo().IsDir(),
@@ -110,8 +118,11 @@ func (f *FileInfo) Sys() interface{} {
"name": f.name,
})
return &Stat{
Uid: uint32(f.uid),
Gid: uint32(f.gid),
}
return NewStat(
uint32(f.uid),
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),
}
}