1// +build darwin
2
3// Copyright 2019 the Go-FUSE Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7package fs
8
9import (
10	"context"
11	"syscall"
12	"time"
13	"unsafe"
14
15	"github.com/hanwen/go-fuse/v2/fuse"
16	"github.com/hanwen/go-fuse/v2/internal/utimens"
17)
18
19func (n *LoopbackNode) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) {
20	return 0, syscall.ENOSYS
21}
22
23func (n *LoopbackNode) Setxattr(ctx context.Context, attr string, data []byte, flags uint32) syscall.Errno {
24	return syscall.ENOSYS
25}
26
27func (n *LoopbackNode) Removexattr(ctx context.Context, attr string) syscall.Errno {
28	return syscall.ENOSYS
29}
30
31func (n *LoopbackNode) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errno) {
32	return 0, syscall.ENOSYS
33}
34
35func (n *LoopbackNode) renameExchange(name string, newparent InodeEmbedder, newName string) syscall.Errno {
36	return syscall.ENOSYS
37}
38
39func (f *loopbackFile) Allocate(ctx context.Context, off uint64, sz uint64, mode uint32) syscall.Errno {
40	// TODO: Handle `mode` parameter.
41
42	// From `man fcntl` on OSX:
43	//     The F_PREALLOCATE command operates on the following structure:
44	//
45	//             typedef struct fstore {
46	//                 u_int32_t fst_flags;      /* IN: flags word */
47	//                 int       fst_posmode;    /* IN: indicates offset field */
48	//                 off_t     fst_offset;     /* IN: start of the region */
49	//                 off_t     fst_length;     /* IN: size of the region */
50	//                 off_t     fst_bytesalloc; /* OUT: number of bytes allocated */
51	//             } fstore_t;
52	//
53	//     The flags (fst_flags) for the F_PREALLOCATE command are as follows:
54	//
55	//           F_ALLOCATECONTIG   Allocate contiguous space.
56	//
57	//           F_ALLOCATEALL      Allocate all requested space or no space at all.
58	//
59	//     The position modes (fst_posmode) for the F_PREALLOCATE command indicate how to use the offset field.  The modes are as fol-
60	//     lows:
61	//
62	//           F_PEOFPOSMODE   Allocate from the physical end of file.
63	//
64	//           F_VOLPOSMODE    Allocate from the volume offset.
65
66	k := struct {
67		Flags      uint32 // u_int32_t
68		Posmode    int64  // int
69		Offset     int64  // off_t
70		Length     int64  // off_t
71		Bytesalloc int64  // off_t
72	}{
73		0,
74		0,
75		int64(off),
76		int64(sz),
77		0,
78	}
79
80	// Linux version for reference:
81	// err := syscall.Fallocate(int(f.File.Fd()), mode, int64(off), int64(sz))
82	_, _, errno := syscall.Syscall(syscall.SYS_FCNTL, uintptr(f.fd), uintptr(syscall.F_PREALLOCATE), uintptr(unsafe.Pointer(&k)))
83
84	return errno
85}
86
87// timeToTimeval - Convert time.Time to syscall.Timeval
88//
89// Note: This does not use syscall.NsecToTimespec because
90// that does not work properly for times before 1970,
91// see https://github.com/golang/go/issues/12777
92func timeToTimeval(t *time.Time) syscall.Timeval {
93	var tv syscall.Timeval
94	tv.Usec = int32(t.Nanosecond() / 1000)
95	tv.Sec = t.Unix()
96	return tv
97}
98
99// MacOS before High Sierra lacks utimensat() and UTIME_OMIT.
100// We emulate using utimes() and extra Getattr() calls.
101func (f *loopbackFile) utimens(a *time.Time, m *time.Time) syscall.Errno {
102	var attr fuse.AttrOut
103	if a == nil || m == nil {
104		errno := f.Getattr(context.Background(), &attr)
105		if errno != 0 {
106			return errno
107		}
108	}
109	tv := utimens.Fill(a, m, &attr.Attr)
110	err := syscall.Futimes(int(f.fd), tv)
111	return ToErrno(err)
112}
113
114func (n *LoopbackNode) CopyFileRange(ctx context.Context, fhIn FileHandle,
115	offIn uint64, out *Inode, fhOut FileHandle, offOut uint64,
116	len uint64, flags uint64) (uint32, syscall.Errno) {
117	return 0, syscall.ENOSYS
118}
119