github.com/hanwen/go-fuse@v1.0.0/fuse/nodefs/files_darwin.go (about) 1 // Copyright 2016 the Go-FUSE Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package nodefs 6 7 import ( 8 "syscall" 9 "time" 10 "unsafe" 11 12 "github.com/hanwen/go-fuse/fuse" 13 "github.com/hanwen/go-fuse/internal/utimens" 14 ) 15 16 func (f *loopbackFile) Allocate(off uint64, sz uint64, mode uint32) fuse.Status { 17 // TODO: Handle `mode` parameter. 18 19 // From `man fcntl` on OSX: 20 // The F_PREALLOCATE command operates on the following structure: 21 // 22 // typedef struct fstore { 23 // u_int32_t fst_flags; /* IN: flags word */ 24 // int fst_posmode; /* IN: indicates offset field */ 25 // off_t fst_offset; /* IN: start of the region */ 26 // off_t fst_length; /* IN: size of the region */ 27 // off_t fst_bytesalloc; /* OUT: number of bytes allocated */ 28 // } fstore_t; 29 // 30 // The flags (fst_flags) for the F_PREALLOCATE command are as follows: 31 // 32 // F_ALLOCATECONTIG Allocate contiguous space. 33 // 34 // F_ALLOCATEALL Allocate all requested space or no space at all. 35 // 36 // The position modes (fst_posmode) for the F_PREALLOCATE command indicate how to use the offset field. The modes are as fol- 37 // lows: 38 // 39 // F_PEOFPOSMODE Allocate from the physical end of file. 40 // 41 // F_VOLPOSMODE Allocate from the volume offset. 42 43 k := struct { 44 Flags uint32 // u_int32_t 45 Posmode int64 // int 46 Offset int64 // off_t 47 Length int64 // off_t 48 Bytesalloc int64 // off_t 49 }{ 50 0, 51 0, 52 int64(off), 53 int64(sz), 54 0, 55 } 56 57 // Linux version for reference: 58 // err := syscall.Fallocate(int(f.File.Fd()), mode, int64(off), int64(sz)) 59 60 f.lock.Lock() 61 _, _, errno := syscall.Syscall(syscall.SYS_FCNTL, f.File.Fd(), uintptr(syscall.F_PREALLOCATE), uintptr(unsafe.Pointer(&k))) 62 f.lock.Unlock() 63 if errno != 0 { 64 return fuse.ToStatus(errno) 65 } 66 return fuse.OK 67 } 68 69 // timeToTimeval - Convert time.Time to syscall.Timeval 70 // 71 // Note: This does not use syscall.NsecToTimespec because 72 // that does not work properly for times before 1970, 73 // see https://github.com/golang/go/issues/12777 74 func timeToTimeval(t *time.Time) syscall.Timeval { 75 var tv syscall.Timeval 76 tv.Usec = int32(t.Nanosecond() / 1000) 77 tv.Sec = t.Unix() 78 return tv 79 } 80 81 // MacOS before High Sierra lacks utimensat() and UTIME_OMIT. 82 // We emulate using utimes() and extra GetAttr() calls. 83 func (f *loopbackFile) Utimens(a *time.Time, m *time.Time) fuse.Status { 84 var attr fuse.Attr 85 if a == nil || m == nil { 86 var status fuse.Status 87 status = f.GetAttr(&attr) 88 if !status.Ok() { 89 return status 90 } 91 } 92 tv := utimens.Fill(a, m, &attr) 93 f.lock.Lock() 94 err := syscall.Futimes(int(f.File.Fd()), tv) 95 f.lock.Unlock() 96 return fuse.ToStatus(err) 97 }