-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
Co-authored-by: greatroar <@>
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
package xattr | ||
|
||
import ( | ||
"errors" | ||
"os" | ||
"syscall" | ||
|
||
|
@@ -22,52 +23,109 @@ const ( | |
ENOATTR = syscall.ENODATA | ||
) | ||
|
||
// On Linux, FUSE and CIFS filesystems can return EINTR for interrupted system | ||
// calls. This function works around this by retrying system calls until they | ||
// stop returning EINTR. | ||
// | ||
// See https://github.com/golang/go/commit/6b420169d798c7ebe733487b56ea5c3fa4aab5ce. | ||
func ignoringEINTR(fn func() error) (err error) { | ||
for { | ||
err = fn() | ||
if !errors.Is(err, unix.EINTR) { | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
kuba--
Member
|
||
break | ||
} | ||
} | ||
return err | ||
} | ||
|
||
func getxattr(path string, name string, data []byte) (int, error) { | ||
return unix.Getxattr(path, name, data) | ||
var r int | ||
err := ignoringEINTR(func() (err error) { | ||
r, err = unix.Getxattr(path, name, data) | ||
return err | ||
}) | ||
return r, err | ||
} | ||
|
||
func lgetxattr(path string, name string, data []byte) (int, error) { | ||
return unix.Lgetxattr(path, name, data) | ||
var r int | ||
err := ignoringEINTR(func() (err error) { | ||
r, err = unix.Lgetxattr(path, name, data) | ||
return err | ||
}) | ||
return r, err | ||
} | ||
|
||
func fgetxattr(f *os.File, name string, data []byte) (int, error) { | ||
return unix.Fgetxattr(int(f.Fd()), name, data) | ||
var r int | ||
err := ignoringEINTR(func() (err error) { | ||
r, err = unix.Fgetxattr(int(f.Fd()), name, data) | ||
return err | ||
}) | ||
return r, err | ||
} | ||
|
||
func setxattr(path string, name string, data []byte, flags int) error { | ||
return unix.Setxattr(path, name, data, flags) | ||
return ignoringEINTR(func() (err error) { | ||
return unix.Setxattr(path, name, data, flags) | ||
}) | ||
} | ||
|
||
func lsetxattr(path string, name string, data []byte, flags int) error { | ||
return unix.Lsetxattr(path, name, data, flags) | ||
return ignoringEINTR(func() (err error) { | ||
return unix.Lsetxattr(path, name, data, flags) | ||
}) | ||
} | ||
|
||
func fsetxattr(f *os.File, name string, data []byte, flags int) error { | ||
return unix.Fsetxattr(int(f.Fd()), name, data, flags) | ||
return ignoringEINTR(func() (err error) { | ||
return unix.Fsetxattr(int(f.Fd()), name, data, flags) | ||
}) | ||
} | ||
|
||
func removexattr(path string, name string) error { | ||
return unix.Removexattr(path, name) | ||
return ignoringEINTR(func() (err error) { | ||
return unix.Removexattr(path, name) | ||
}) | ||
} | ||
|
||
func lremovexattr(path string, name string) error { | ||
return unix.Lremovexattr(path, name) | ||
return ignoringEINTR(func() (err error) { | ||
return unix.Lremovexattr(path, name) | ||
}) | ||
} | ||
|
||
func fremovexattr(f *os.File, name string) error { | ||
return unix.Fremovexattr(int(f.Fd()), name) | ||
return ignoringEINTR(func() (err error) { | ||
return unix.Fremovexattr(int(f.Fd()), name) | ||
}) | ||
} | ||
|
||
func listxattr(path string, data []byte) (int, error) { | ||
return unix.Listxattr(path, data) | ||
var r int | ||
err := ignoringEINTR(func() (err error) { | ||
r, err = unix.Listxattr(path, data) | ||
return err | ||
}) | ||
return r, err | ||
} | ||
|
||
func llistxattr(path string, data []byte) (int, error) { | ||
return unix.Llistxattr(path, data) | ||
var r int | ||
err := ignoringEINTR(func() (err error) { | ||
r, err = unix.Llistxattr(path, data) | ||
return err | ||
}) | ||
return r, err | ||
} | ||
|
||
func flistxattr(f *os.File, data []byte) (int, error) { | ||
return unix.Flistxattr(int(f.Fd()), data) | ||
var r int | ||
err := ignoringEINTR(func() (err error) { | ||
r, err = unix.Flistxattr(int(f.Fd()), data) | ||
return err | ||
}) | ||
return r, err | ||
} | ||
|
||
// stringsFromByteSlice converts a sequence of attributes to a []string. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package xattr | ||
|
||
import ( | ||
"syscall" | ||
"testing" | ||
) | ||
|
||
func TestIgnoringEINTR(t *testing.T) { | ||
eintrs := 100 | ||
err := ignoringEINTR(func() error { | ||
if eintrs == 0 { | ||
return nil | ||
} | ||
eintrs-- | ||
return syscall.EINTR | ||
}) | ||
|
||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
} |
The breaks Go 1.10: https://travis-ci.org/github/rfjakob/cshatag/builds/743651578#L216