2016-07-06 21:51:25 +02:00
|
|
|
// Package syscallcompat wraps Linux-specific syscalls.
|
2016-07-03 17:51:40 +02:00
|
|
|
package syscallcompat
|
2016-01-07 21:39:41 +01:00
|
|
|
|
2016-04-20 22:47:31 +02:00
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
"syscall"
|
2016-07-03 17:51:40 +02:00
|
|
|
|
|
|
|
"github.com/rfjakob/gocryptfs/internal/tlog"
|
2016-04-20 22:47:31 +02:00
|
|
|
)
|
|
|
|
|
2016-10-04 23:30:05 +02:00
|
|
|
const _FALLOC_FL_KEEP_SIZE = 0x01
|
2016-04-20 22:47:31 +02:00
|
|
|
|
|
|
|
var preallocWarn sync.Once
|
2016-01-07 21:39:41 +01:00
|
|
|
|
2016-07-03 19:14:12 +02:00
|
|
|
// EnospcPrealloc preallocates ciphertext space without changing the file
|
|
|
|
// size. This guarantees that we don't run out of space while writing a
|
|
|
|
// ciphertext block (that would corrupt the block).
|
|
|
|
func EnospcPrealloc(fd int, off int64, len int64) (err error) {
|
2016-01-07 21:39:41 +01:00
|
|
|
for {
|
2016-10-04 23:30:05 +02:00
|
|
|
err = syscall.Fallocate(fd, _FALLOC_FL_KEEP_SIZE, off, len)
|
2016-01-07 21:39:41 +01:00
|
|
|
if err == syscall.EINTR {
|
|
|
|
// fallocate, like many syscalls, can return EINTR. This is not an
|
|
|
|
// error and just signifies that the operation was interrupted by a
|
|
|
|
// signal and we should try again.
|
|
|
|
continue
|
|
|
|
}
|
2016-04-20 22:47:31 +02:00
|
|
|
if err == syscall.EOPNOTSUPP {
|
2016-07-03 19:14:12 +02:00
|
|
|
// ZFS and ext3 do not support fallocate. Warn but continue anyway.
|
|
|
|
// https://github.com/rfjakob/gocryptfs/issues/22
|
2016-04-20 22:47:31 +02:00
|
|
|
preallocWarn.Do(func() {
|
2016-06-15 23:30:44 +02:00
|
|
|
tlog.Warn.Printf("Warning: The underlying filesystem " +
|
2016-04-20 22:47:31 +02:00
|
|
|
"does not support fallocate(2). gocryptfs will continue working " +
|
|
|
|
"but is no longer resistant against out-of-space errors.\n")
|
|
|
|
})
|
|
|
|
return nil
|
|
|
|
}
|
2016-01-07 21:39:41 +01:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2016-07-03 19:14:12 +02:00
|
|
|
|
2016-10-02 06:14:18 +02:00
|
|
|
// Fallocate wraps the Fallocate syscall.
|
2016-07-03 20:05:32 +02:00
|
|
|
func Fallocate(fd int, mode uint32, off int64, len int64) (err error) {
|
|
|
|
return syscall.Fallocate(fd, mode, off, len)
|
|
|
|
}
|
|
|
|
|
2016-10-02 06:14:18 +02:00
|
|
|
// Openat wraps the Openat syscall.
|
2016-07-03 19:14:12 +02:00
|
|
|
func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
|
|
|
|
return syscall.Openat(dirfd, path, flags, mode)
|
|
|
|
}
|
|
|
|
|
2016-10-02 06:14:18 +02:00
|
|
|
// Renameat wraps the Renameat syscall.
|
2016-07-03 20:05:32 +02:00
|
|
|
func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
|
|
|
|
return syscall.Renameat(olddirfd, oldpath, newdirfd, newpath)
|
2016-07-03 19:14:12 +02:00
|
|
|
}
|
2016-07-03 20:17:40 +02:00
|
|
|
|
2016-10-02 06:14:18 +02:00
|
|
|
// Unlinkat wraps the Unlinkat syscall.
|
2016-07-03 20:17:40 +02:00
|
|
|
func Unlinkat(dirfd int, path string) error {
|
|
|
|
return syscall.Unlinkat(dirfd, path)
|
|
|
|
}
|
2016-07-03 20:21:29 +02:00
|
|
|
|
2016-10-02 06:14:18 +02:00
|
|
|
// Mknodat wraps the Mknodat syscall.
|
2016-07-03 20:21:29 +02:00
|
|
|
func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
|
|
|
|
return syscall.Mknodat(dirfd, path, mode, dev)
|
|
|
|
}
|
2017-06-18 15:40:38 +02:00
|
|
|
|
|
|
|
// Dup3 wraps the Dup3 syscall. We want to use Dup3 rather than Dup2 because Dup2
|
|
|
|
// is not implemented on arm64.
|
|
|
|
func Dup3(oldfd int, newfd int, flags int) (err error) {
|
|
|
|
return syscall.Dup3(oldfd, newfd, flags)
|
|
|
|
}
|