fix(snapshot): support darwin filesystem syscalls
- commit
- 5f10d2ee28e3ce3d4069aaaf90998551ef9f1201
- author
- brice · · 2026-07-22 05:29 UTC
- parent
- 6efb8f5
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
9 files · +65 -34
M go.mod +4 -1
| @@ -2,7 +2,10 @@ module github.com/bnema/vev | |||
| 2 | 2 | ||
| 3 | 3 | go 1.26 | |
| 4 | 4 | ||
| 5 | - | require github.com/stretchr/testify v1.11.1 | |
| 5 | + | require ( | |
| 6 | + | github.com/stretchr/testify v1.11.1 | |
| 7 | + | golang.org/x/sys v0.47.0 | |
| 8 | + | ) | |
| 6 | 9 | ||
| 7 | 10 | require ( | |
| 8 | 11 | github.com/davecgh/go-spew v1.1.1 // indirect | |
| @@ -2,7 +2,10 @@ module github.com/bnema/vev | |||||
| 2 | 2 | ||||
| 3 | go 1.26 | 3 | go 1.26 | ||
| 4 | 4 | ||||
| 5 | - | require github.com/stretchr/testify v1.11.1 | 5 | + | require ( |
| 6 | + | github.com/stretchr/testify v1.11.1 | |||
| 7 | + | golang.org/x/sys v0.47.0 | |||
| 8 | + | ) | |||
| 6 | 9 | ||||
| 7 | require ( | 10 | require ( | ||
| 8 | github.com/davecgh/go-spew v1.1.1 // indirect | 11 | github.com/davecgh/go-spew v1.1.1 // indirect | ||
M go.sum +2 -0 generated file: collapsed
M internal/adapters/snapshot/atomic.go +6 -26
| @@ -7,9 +7,9 @@ import ( | |||
| 7 | 7 | "os" | |
| 8 | 8 | "path/filepath" | |
| 9 | 9 | "syscall" | |
| 10 | - | "unsafe" | |
| 11 | 10 | ||
| 12 | 11 | "github.com/bnema/vev/pkg/safedir" | |
| 12 | + | "golang.org/x/sys/unix" | |
| 13 | 13 | ) | |
| 14 | 14 | ||
| 15 | 15 | func (r *Repository) ensureSession(key string) error { | |
| @@ -67,7 +67,7 @@ func (r *Repository) ensurePrivateDirectoryPhase(dir, phase string) error { | |||
| 67 | 67 | return err | |
| 68 | 68 | } | |
| 69 | 69 | created := false | |
| 70 | - | mkdirErr := syscall.Mkdirat(parent, name, 0o700) | |
| 70 | + | mkdirErr := unix.Mkdirat(parent, name, 0o700) | |
| 71 | 71 | if mkdirErr == nil { | |
| 72 | 72 | created = true | |
| 73 | 73 | } | |
| @@ -277,19 +277,7 @@ func (r *Repository) installImmutable(oldPath, newPath string) (err error) { | |||
| 277 | 277 | defer func() { | |
| 278 | 278 | joinCloseError(&err, "close destination snapshot parent directory", r.closeDescriptor(newFD, "close destination snapshot parent directory")) | |
| 279 | 279 | }() | |
| 280 | - | oldPtr, err := syscall.BytePtrFromString(oldName) | |
| 281 | - | if err != nil { | |
| 282 | - | return err | |
| 283 | - | } | |
| 284 | - | newPtr, err := syscall.BytePtrFromString(newName) | |
| 285 | - | if err != nil { | |
| 286 | - | return err | |
| 287 | - | } | |
| 288 | - | _, _, errno := syscall.Syscall6(syscall.SYS_LINKAT, uintptr(oldFD), uintptr(unsafe.Pointer(oldPtr)), uintptr(newFD), uintptr(unsafe.Pointer(newPtr)), 0, 0) | |
| 289 | - | if errno != 0 { | |
| 290 | - | return errno | |
| 291 | - | } | |
| 292 | - | return nil | |
| 280 | + | return unix.Linkat(oldFD, oldName, newFD, newName, 0) | |
| 293 | 281 | } | |
| 294 | 282 | func (r *Repository) rename(oldPath, newPath string) (err error) { | |
| 295 | 283 | if r.hooks.rename != nil { | |
| @@ -311,7 +299,7 @@ func (r *Repository) rename(oldPath, newPath string) (err error) { | |||
| 311 | 299 | defer func() { | |
| 312 | 300 | joinCloseError(&err, "close destination snapshot parent directory", r.closeDescriptor(newFD, "close destination snapshot parent directory")) | |
| 313 | 301 | }() | |
| 314 | - | return syscall.Renameat(oldFD, oldName, newFD, newName) | |
| 302 | + | return unix.Renameat(oldFD, oldName, newFD, newName) | |
| 315 | 303 | } | |
| 316 | 304 | func (r *Repository) remove(path string) (err error) { | |
| 317 | 305 | if r.hooks.remove != nil { | |
| @@ -326,18 +314,10 @@ func (r *Repository) remove(path string) (err error) { | |||
| 326 | 314 | defer func() { | |
| 327 | 315 | joinCloseError(&err, "close snapshot parent directory", r.closeDescriptor(fd, "close snapshot parent directory")) | |
| 328 | 316 | }() | |
| 329 | - | if err := syscall.Unlinkat(fd, name); !errors.Is(err, syscall.EISDIR) { | |
| 330 | - | return err | |
| 331 | - | } | |
| 332 | - | namePtr, err := syscall.BytePtrFromString(name) | |
| 333 | - | if err != nil { | |
| 317 | + | if err := unix.Unlinkat(fd, name, 0); !errors.Is(err, unix.EISDIR) { | |
| 334 | 318 | return err | |
| 335 | 319 | } | |
| 336 | - | _, _, errno := syscall.Syscall(syscall.SYS_UNLINKAT, uintptr(fd), uintptr(unsafe.Pointer(namePtr)), uintptr(0x200)) // AT_REMOVEDIR | |
| 337 | - | if errno != 0 { | |
| 338 | - | return errno | |
| 339 | - | } | |
| 340 | - | return nil | |
| 320 | + | return unix.Unlinkat(fd, name, unix.AT_REMOVEDIR) | |
| 341 | 321 | } | |
| 342 | 322 | func (r *Repository) syncDirectory(dir string) error { | |
| 343 | 323 | if r.hooks.syncDirectory != nil { | |
| @@ -7,9 +7,9 @@ import ( | |||||
| 7 | "os" | 7 | "os" | ||
| 8 | "path/filepath" | 8 | "path/filepath" | ||
| 9 | "syscall" | 9 | "syscall" | ||
| 10 | - | "unsafe" | |||
| 11 | 10 | ||||
| 12 | "github.com/bnema/vev/pkg/safedir" | 11 | "github.com/bnema/vev/pkg/safedir" | ||
| 12 | + | "golang.org/x/sys/unix" | |||
| 13 | ) | 13 | ) | ||
| 14 | 14 | ||||
| 15 | func (r *Repository) ensureSession(key string) error { | 15 | func (r *Repository) ensureSession(key string) error { | ||
| @@ -67,7 +67,7 @@ func (r *Repository) ensurePrivateDirectoryPhase(dir, phase string) error { | |||||
| 67 | return err | 67 | return err | ||
| 68 | } | 68 | } | ||
| 69 | created := false | 69 | created := false | ||
| 70 | - | mkdirErr := syscall.Mkdirat(parent, name, 0o700) | 70 | + | mkdirErr := unix.Mkdirat(parent, name, 0o700) |
| 71 | if mkdirErr == nil { | 71 | if mkdirErr == nil { | ||
| 72 | created = true | 72 | created = true | ||
| 73 | } | 73 | } | ||
| @@ -277,19 +277,7 @@ func (r *Repository) installImmutable(oldPath, newPath string) (err error) { | |||||
| 277 | defer func() { | 277 | defer func() { | ||
| 278 | joinCloseError(&err, "close destination snapshot parent directory", r.closeDescriptor(newFD, "close destination snapshot parent directory")) | 278 | joinCloseError(&err, "close destination snapshot parent directory", r.closeDescriptor(newFD, "close destination snapshot parent directory")) | ||
| 279 | }() | 279 | }() | ||
| 280 | - | oldPtr, err := syscall.BytePtrFromString(oldName) | 280 | + | return unix.Linkat(oldFD, oldName, newFD, newName, 0) |
| 281 | - | if err != nil { | |||
| 282 | - | return err | |||
| 283 | - | } | |||
| 284 | - | newPtr, err := syscall.BytePtrFromString(newName) | |||
| 285 | - | if err != nil { | |||
| 286 | - | return err | |||
| 287 | - | } | |||
| 288 | - | _, _, errno := syscall.Syscall6(syscall.SYS_LINKAT, uintptr(oldFD), uintptr(unsafe.Pointer(oldPtr)), uintptr(newFD), uintptr(unsafe.Pointer(newPtr)), 0, 0) | |||
| 289 | - | if errno != 0 { | |||
| 290 | - | return errno | |||
| 291 | - | } | |||
| 292 | - | return nil | |||
| 293 | } | 281 | } | ||
| 294 | func (r *Repository) rename(oldPath, newPath string) (err error) { | 282 | func (r *Repository) rename(oldPath, newPath string) (err error) { | ||
| 295 | if r.hooks.rename != nil { | 283 | if r.hooks.rename != nil { | ||
| @@ -311,7 +299,7 @@ func (r *Repository) rename(oldPath, newPath string) (err error) { | |||||
| 311 | defer func() { | 299 | defer func() { | ||
| 312 | joinCloseError(&err, "close destination snapshot parent directory", r.closeDescriptor(newFD, "close destination snapshot parent directory")) | 300 | joinCloseError(&err, "close destination snapshot parent directory", r.closeDescriptor(newFD, "close destination snapshot parent directory")) | ||
| 313 | }() | 301 | }() | ||
| 314 | - | return syscall.Renameat(oldFD, oldName, newFD, newName) | 302 | + | return unix.Renameat(oldFD, oldName, newFD, newName) |
| 315 | } | 303 | } | ||
| 316 | func (r *Repository) remove(path string) (err error) { | 304 | func (r *Repository) remove(path string) (err error) { | ||
| 317 | if r.hooks.remove != nil { | 305 | if r.hooks.remove != nil { | ||
| @@ -326,18 +314,10 @@ func (r *Repository) remove(path string) (err error) { | |||||
| 326 | defer func() { | 314 | defer func() { | ||
| 327 | joinCloseError(&err, "close snapshot parent directory", r.closeDescriptor(fd, "close snapshot parent directory")) | 315 | joinCloseError(&err, "close snapshot parent directory", r.closeDescriptor(fd, "close snapshot parent directory")) | ||
| 328 | }() | 316 | }() | ||
| 329 | - | if err := syscall.Unlinkat(fd, name); !errors.Is(err, syscall.EISDIR) { | 317 | + | if err := unix.Unlinkat(fd, name, 0); !errors.Is(err, unix.EISDIR) { |
| 330 | - | return err | |||
| 331 | - | } | |||
| 332 | - | namePtr, err := syscall.BytePtrFromString(name) | |||
| 333 | - | if err != nil { | |||
| 334 | return err | 318 | return err | ||
| 335 | } | 319 | } | ||
| 336 | - | _, _, errno := syscall.Syscall(syscall.SYS_UNLINKAT, uintptr(fd), uintptr(unsafe.Pointer(namePtr)), uintptr(0x200)) // AT_REMOVEDIR | 320 | + | return unix.Unlinkat(fd, name, unix.AT_REMOVEDIR) |
| 337 | - | if errno != 0 { | |||
| 338 | - | return errno | |||
| 339 | - | } | |||
| 340 | - | return nil | |||
| 341 | } | 321 | } | ||
| 342 | func (r *Repository) syncDirectory(dir string) error { | 322 | func (r *Repository) syncDirectory(dir string) error { | ||
| 343 | if r.hooks.syncDirectory != nil { | 323 | if r.hooks.syncDirectory != nil { | ||
A internal/adapters/snapshot/dirent_cookie_darwin.go +7 -0
| @@ -0,0 +1,7 @@ | |||
| 1 | + | //go:build darwin | |
| 2 | + | ||
| 3 | + | package snapshot | |
| 4 | + | ||
| 5 | + | import "syscall" | |
| 6 | + | ||
| 7 | + | func directoryCookie(dirent *syscall.Dirent) int64 { return int64(dirent.Seekoff) } | |
| @@ -0,0 +1,7 @@ | |||||
| 1 | + | //go:build darwin | |||
| 2 | + | ||||
| 3 | + | package snapshot | |||
| 4 | + | ||||
| 5 | + | import "syscall" | |||
| 6 | + | ||||
| 7 | + | func directoryCookie(dirent *syscall.Dirent) int64 { return int64(dirent.Seekoff) } | |||
A internal/adapters/snapshot/dirent_cookie_darwin_test.go +15 -0
| @@ -0,0 +1,15 @@ | |||
| 1 | + | //go:build darwin | |
| 2 | + | ||
| 3 | + | package snapshot | |
| 4 | + | ||
| 5 | + | import ( | |
| 6 | + | "syscall" | |
| 7 | + | "testing" | |
| 8 | + | ) | |
| 9 | + | ||
| 10 | + | func TestDirectoryCookieUsesDarwinSeekOffset(t *testing.T) { | |
| 11 | + | dirent := syscall.Dirent{Seekoff: 42} | |
| 12 | + | if got := directoryCookie(&dirent); got != 42 { | |
| 13 | + | t.Fatalf("directoryCookie() = %d, want 42", got) | |
| 14 | + | } | |
| 15 | + | } | |
| @@ -0,0 +1,15 @@ | |||||
| 1 | + | //go:build darwin | |||
| 2 | + | ||||
| 3 | + | package snapshot | |||
| 4 | + | ||||
| 5 | + | import ( | |||
| 6 | + | "syscall" | |||
| 7 | + | "testing" | |||
| 8 | + | ) | |||
| 9 | + | ||||
| 10 | + | func TestDirectoryCookieUsesDarwinSeekOffset(t *testing.T) { | |||
| 11 | + | dirent := syscall.Dirent{Seekoff: 42} | |||
| 12 | + | if got := directoryCookie(&dirent); got != 42 { | |||
| 13 | + | t.Fatalf("directoryCookie() = %d, want 42", got) | |||
| 14 | + | } | |||
| 15 | + | } | |||
A internal/adapters/snapshot/dirent_cookie_linux.go +7 -0
| @@ -0,0 +1,7 @@ | |||
| 1 | + | //go:build linux | |
| 2 | + | ||
| 3 | + | package snapshot | |
| 4 | + | ||
| 5 | + | import "syscall" | |
| 6 | + | ||
| 7 | + | func directoryCookie(dirent *syscall.Dirent) int64 { return dirent.Off } | |
| @@ -0,0 +1,7 @@ | |||||
| 1 | + | //go:build linux | |||
| 2 | + | ||||
| 3 | + | package snapshot | |||
| 4 | + | ||||
| 5 | + | import "syscall" | |||
| 6 | + | ||||
| 7 | + | func directoryCookie(dirent *syscall.Dirent) int64 { return dirent.Off } | |||
A internal/adapters/snapshot/dirent_cookie_linux_test.go +15 -0
| @@ -0,0 +1,15 @@ | |||
| 1 | + | //go:build linux | |
| 2 | + | ||
| 3 | + | package snapshot | |
| 4 | + | ||
| 5 | + | import ( | |
| 6 | + | "syscall" | |
| 7 | + | "testing" | |
| 8 | + | ) | |
| 9 | + | ||
| 10 | + | func TestDirectoryCookieUsesLinuxOffset(t *testing.T) { | |
| 11 | + | dirent := syscall.Dirent{Off: 42} | |
| 12 | + | if got := directoryCookie(&dirent); got != 42 { | |
| 13 | + | t.Fatalf("directoryCookie() = %d, want 42", got) | |
| 14 | + | } | |
| 15 | + | } | |
| @@ -0,0 +1,15 @@ | |||||
| 1 | + | //go:build linux | |||
| 2 | + | ||||
| 3 | + | package snapshot | |||
| 4 | + | ||||
| 5 | + | import ( | |||
| 6 | + | "syscall" | |||
| 7 | + | "testing" | |||
| 8 | + | ) | |||
| 9 | + | ||||
| 10 | + | func TestDirectoryCookieUsesLinuxOffset(t *testing.T) { | |||
| 11 | + | dirent := syscall.Dirent{Off: 42} | |||
| 12 | + | if got := directoryCookie(&dirent); got != 42 { | |||
| 13 | + | t.Fatalf("directoryCookie() = %d, want 42", got) | |||
| 14 | + | } | |||
| 15 | + | } | |||
M internal/adapters/snapshot/maintenance_cursor.go +4 -4
| @@ -114,9 +114,9 @@ func maintenanceDirectoryError(operation string, err error) error { | |||
| 114 | 114 | return fmt.Errorf("%s: %w", operation, safeFilesystemError(err)) | |
| 115 | 115 | } | |
| 116 | 116 | ||
| 117 | - | // readMaintenanceDirent uses the Linux getdents seek cookie from each record. | |
| 118 | - | // syscall.Dirent's Off field is the d_off member of linux_dirent64 and | |
| 119 | - | // syscall.Seek is lseek(2), as defined by Go's syscall Linux sources. | |
| 117 | + | // readMaintenanceDirent saves the OS-provided seek cookie from each record. | |
| 118 | + | // The field differs by platform; directoryCookie abstracts that layout while | |
| 119 | + | // syscall.Seek resumes the descriptor at the saved directory position. | |
| 120 | 120 | func (r *Repository) readMaintenanceDirent(dir string, limit int, cursor *maintenanceCursor) (entries []maintenanceDirEntry, done bool, err error) { | |
| 121 | 121 | file, err := r.openMaintenanceDirectory(dir) | |
| 122 | 122 | if err != nil { | |
| @@ -162,7 +162,7 @@ func (r *Repository) readMaintenanceDirent(dir string, limit int, cursor *mainte | |||
| 162 | 162 | } | |
| 163 | 163 | data = data[reclen:] | |
| 164 | 164 | // Advance past every raw record, including dot and disappeared entries. | |
| 165 | - | cursor.offset = record.Off | |
| 165 | + | cursor.offset = directoryCookie(record) | |
| 166 | 166 | nameBytes := unsafe.Slice((*byte)(unsafe.Pointer(&record.Name[0])), reclen-nameOffset) | |
| 167 | 167 | if end := strings.IndexByte(string(nameBytes), 0); end >= 0 { | |
| 168 | 168 | nameBytes = nameBytes[:end] | |
| @@ -114,9 +114,9 @@ func maintenanceDirectoryError(operation string, err error) error { | |||||
| 114 | return fmt.Errorf("%s: %w", operation, safeFilesystemError(err)) | 114 | return fmt.Errorf("%s: %w", operation, safeFilesystemError(err)) | ||
| 115 | } | 115 | } | ||
| 116 | 116 | ||||
| 117 | - | // readMaintenanceDirent uses the Linux getdents seek cookie from each record. | 117 | + | // readMaintenanceDirent saves the OS-provided seek cookie from each record. |
| 118 | - | // syscall.Dirent's Off field is the d_off member of linux_dirent64 and | 118 | + | // The field differs by platform; directoryCookie abstracts that layout while |
| 119 | - | // syscall.Seek is lseek(2), as defined by Go's syscall Linux sources. | 119 | + | // syscall.Seek resumes the descriptor at the saved directory position. |
| 120 | func (r *Repository) readMaintenanceDirent(dir string, limit int, cursor *maintenanceCursor) (entries []maintenanceDirEntry, done bool, err error) { | 120 | func (r *Repository) readMaintenanceDirent(dir string, limit int, cursor *maintenanceCursor) (entries []maintenanceDirEntry, done bool, err error) { | ||
| 121 | file, err := r.openMaintenanceDirectory(dir) | 121 | file, err := r.openMaintenanceDirectory(dir) | ||
| 122 | if err != nil { | 122 | if err != nil { | ||
| @@ -162,7 +162,7 @@ func (r *Repository) readMaintenanceDirent(dir string, limit int, cursor *mainte | |||||
| 162 | } | 162 | } | ||
| 163 | data = data[reclen:] | 163 | data = data[reclen:] | ||
| 164 | // Advance past every raw record, including dot and disappeared entries. | 164 | // Advance past every raw record, including dot and disappeared entries. | ||
| 165 | - | cursor.offset = record.Off | 165 | + | cursor.offset = directoryCookie(record) |
| 166 | nameBytes := unsafe.Slice((*byte)(unsafe.Pointer(&record.Name[0])), reclen-nameOffset) | 166 | nameBytes := unsafe.Slice((*byte)(unsafe.Pointer(&record.Name[0])), reclen-nameOffset) | ||
| 167 | if end := strings.IndexByte(string(nameBytes), 0); end >= 0 { | 167 | if end := strings.IndexByte(string(nameBytes), 0); end >= 0 { | ||
| 168 | nameBytes = nameBytes[:end] | 168 | nameBytes = nameBytes[:end] | ||
M internal/adapters/snapshot/safe_path.go +5 -3
| @@ -9,6 +9,8 @@ import ( | |||
| 9 | 9 | "path/filepath" | |
| 10 | 10 | "strings" | |
| 11 | 11 | "syscall" | |
| 12 | + | ||
| 13 | + | "golang.org/x/sys/unix" | |
| 12 | 14 | ) | |
| 13 | 15 | ||
| 14 | 16 | // repositoryFD opens a repository-relative path one component at a time. Each | |
| @@ -52,7 +54,7 @@ func (r *Repository) repositoryFD(path string, finalFlags int, mode uint32) (*os | |||
| 52 | 54 | } else { | |
| 53 | 55 | flags = finalFlags | syscall.O_CLOEXEC | syscall.O_NOFOLLOW | |
| 54 | 56 | } | |
| 55 | - | next, openErr := syscall.Openat(fd, part, flags, mode) | |
| 57 | + | next, openErr := unix.Openat(fd, part, flags, mode) | |
| 56 | 58 | closeErr := r.closeDescriptor(fd, "close snapshot path parent directory") | |
| 57 | 59 | if openErr != nil { | |
| 58 | 60 | err = openErr | |
| @@ -94,7 +96,7 @@ func (r *Repository) repositoryParent(path string) (int, string, error) { | |||
| 94 | 96 | joinCloseError(&err, "close snapshot parent directory", r.closeDescriptor(fd, "close snapshot parent directory")) | |
| 95 | 97 | return -1, "", err | |
| 96 | 98 | } | |
| 97 | - | next, openErr := syscall.Openat(fd, part, syscall.O_RDONLY|syscall.O_DIRECTORY|syscall.O_NOFOLLOW|syscall.O_CLOEXEC, 0) | |
| 99 | + | next, openErr := unix.Openat(fd, part, syscall.O_RDONLY|syscall.O_DIRECTORY|syscall.O_NOFOLLOW|syscall.O_CLOEXEC, 0) | |
| 98 | 100 | closeErr := r.closeDescriptor(fd, "close snapshot parent directory") | |
| 99 | 101 | if openErr != nil { | |
| 100 | 102 | err = openErr | |
| @@ -166,7 +168,7 @@ func (r *Repository) createTempAt(dir string) (temp *os.File, err error) { | |||
| 166 | 168 | return nil, err | |
| 167 | 169 | } | |
| 168 | 170 | name := ".tmp-" + hex.EncodeToString(random[:]) | |
| 169 | - | tempFD, err := syscall.Openat(int(fd.Fd()), name, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_EXCL|syscall.O_NOFOLLOW|syscall.O_CLOEXEC, 0o600) | |
| 171 | + | tempFD, err := unix.Openat(int(fd.Fd()), name, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_EXCL|syscall.O_NOFOLLOW|syscall.O_CLOEXEC, 0o600) | |
| 170 | 172 | if errors.Is(err, syscall.EEXIST) { | |
| 171 | 173 | continue | |
| 172 | 174 | } | |
| @@ -9,6 +9,8 @@ import ( | |||||
| 9 | "path/filepath" | 9 | "path/filepath" | ||
| 10 | "strings" | 10 | "strings" | ||
| 11 | "syscall" | 11 | "syscall" | ||
| 12 | + | ||||
| 13 | + | "golang.org/x/sys/unix" | |||
| 12 | ) | 14 | ) | ||
| 13 | 15 | ||||
| 14 | // repositoryFD opens a repository-relative path one component at a time. Each | 16 | // repositoryFD opens a repository-relative path one component at a time. Each | ||
| @@ -52,7 +54,7 @@ func (r *Repository) repositoryFD(path string, finalFlags int, mode uint32) (*os | |||||
| 52 | } else { | 54 | } else { | ||
| 53 | flags = finalFlags | syscall.O_CLOEXEC | syscall.O_NOFOLLOW | 55 | flags = finalFlags | syscall.O_CLOEXEC | syscall.O_NOFOLLOW | ||
| 54 | } | 56 | } | ||
| 55 | - | next, openErr := syscall.Openat(fd, part, flags, mode) | 57 | + | next, openErr := unix.Openat(fd, part, flags, mode) |
| 56 | closeErr := r.closeDescriptor(fd, "close snapshot path parent directory") | 58 | closeErr := r.closeDescriptor(fd, "close snapshot path parent directory") | ||
| 57 | if openErr != nil { | 59 | if openErr != nil { | ||
| 58 | err = openErr | 60 | err = openErr | ||
| @@ -94,7 +96,7 @@ func (r *Repository) repositoryParent(path string) (int, string, error) { | |||||
| 94 | joinCloseError(&err, "close snapshot parent directory", r.closeDescriptor(fd, "close snapshot parent directory")) | 96 | joinCloseError(&err, "close snapshot parent directory", r.closeDescriptor(fd, "close snapshot parent directory")) | ||
| 95 | return -1, "", err | 97 | return -1, "", err | ||
| 96 | } | 98 | } | ||
| 97 | - | next, openErr := syscall.Openat(fd, part, syscall.O_RDONLY|syscall.O_DIRECTORY|syscall.O_NOFOLLOW|syscall.O_CLOEXEC, 0) | 99 | + | next, openErr := unix.Openat(fd, part, syscall.O_RDONLY|syscall.O_DIRECTORY|syscall.O_NOFOLLOW|syscall.O_CLOEXEC, 0) |
| 98 | closeErr := r.closeDescriptor(fd, "close snapshot parent directory") | 100 | closeErr := r.closeDescriptor(fd, "close snapshot parent directory") | ||
| 99 | if openErr != nil { | 101 | if openErr != nil { | ||
| 100 | err = openErr | 102 | err = openErr | ||
| @@ -166,7 +168,7 @@ func (r *Repository) createTempAt(dir string) (temp *os.File, err error) { | |||||
| 166 | return nil, err | 168 | return nil, err | ||
| 167 | } | 169 | } | ||
| 168 | name := ".tmp-" + hex.EncodeToString(random[:]) | 170 | name := ".tmp-" + hex.EncodeToString(random[:]) | ||
| 169 | - | tempFD, err := syscall.Openat(int(fd.Fd()), name, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_EXCL|syscall.O_NOFOLLOW|syscall.O_CLOEXEC, 0o600) | 171 | + | tempFD, err := unix.Openat(int(fd.Fd()), name, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_EXCL|syscall.O_NOFOLLOW|syscall.O_CLOEXEC, 0o600) |
| 170 | if errors.Is(err, syscall.EEXIST) { | 172 | if errors.Is(err, syscall.EEXIST) { | ||
| 171 | continue | 173 | continue | ||
| 172 | } | 174 | } | ||