Commit 224440cb authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

nodefs: port utimens and allocate from fuse/nodefs

parent 9c331316
// Copyright 2019 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package nodefs
import (
"context"
"syscall"
"time"
)
func (f *loopbackFile) Allocate(ctx context.Context, off uint64, sz uint64, mode uint32) syscall.Errno {
return syscall.ENOSYS
}
func (f *loopbackFile) Utimens(ctx context.Context, a *time.Time, m *time.Time) syscall.Errno {
return syscall.ENOSYS
}
......@@ -8,6 +8,10 @@ import (
"context"
"syscall"
"time"
"unsafe"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/internal/utimens"
)
func (n *loopbackNode) GetXAttr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) {
......@@ -30,6 +34,77 @@ func (n *loopbackNode) renameExchange(name string, newparent *loopbackNode, newN
return syscall.ENOSYS
}
func (f *loopbackFile) Allocate(ctx context.Context, off uint64, sz uint64, mode uint32) syscall.Errno {
// TODO: Handle `mode` parameter.
// From `man fcntl` on OSX:
// The F_PREALLOCATE command operates on the following structure:
//
// typedef struct fstore {
// u_int32_t fst_flags; /* IN: flags word */
// int fst_posmode; /* IN: indicates offset field */
// off_t fst_offset; /* IN: start of the region */
// off_t fst_length; /* IN: size of the region */
// off_t fst_bytesalloc; /* OUT: number of bytes allocated */
// } fstore_t;
//
// The flags (fst_flags) for the F_PREALLOCATE command are as follows:
//
// F_ALLOCATECONTIG Allocate contiguous space.
//
// F_ALLOCATEALL Allocate all requested space or no space at all.
//
// The position modes (fst_posmode) for the F_PREALLOCATE command indicate how to use the offset field. The modes are as fol-
// lows:
//
// F_PEOFPOSMODE Allocate from the physical end of file.
//
// F_VOLPOSMODE Allocate from the volume offset.
k := struct {
Flags uint32 // u_int32_t
Posmode int64 // int
Offset int64 // off_t
Length int64 // off_t
Bytesalloc int64 // off_t
}{
0,
0,
int64(off),
int64(sz),
0,
}
// Linux version for reference:
// err := syscall.Fallocate(int(f.File.Fd()), mode, int64(off), int64(sz))
_, _, errno := syscall.Syscall(syscall.SYS_FCNTL, uintptr(f.fd), uintptr(syscall.F_PREALLOCATE), uintptr(unsafe.Pointer(&k)))
return errno
}
// timeToTimeval - Convert time.Time to syscall.Timeval
//
// Note: This does not use syscall.NsecToTimespec because
// that does not work properly for times before 1970,
// see https://github.com/golang/go/issues/12777
func timeToTimeval(t *time.Time) syscall.Timeval {
var tv syscall.Timeval
tv.Usec = int32(t.Nanosecond() / 1000)
tv.Sec = t.Unix()
return tv
}
// MacOS before High Sierra lacks utimensat() and UTIME_OMIT.
// We emulate using utimes() and extra GetAttr() calls.
func (f *loopbackFile) utimens(a *time.Time, m *time.Time) syscall.Errno {
return syscall.ENOSYS // XXX
var attr fuse.AttrOut
if a == nil || m == nil {
errno := f.GetAttr(context.Background(), &attr)
if errno != 0 {
return errno
}
}
tv := utimens.Fill(a, m, &attr.Attr)
err := syscall.Futimes(int(f.fd), tv)
return ToErrno(err)
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment