Skip to content

Commit

Permalink
fix(libindex): temp files on non-linux
Browse files Browse the repository at this point in the history
Signed-off-by: RTann <rtannenb@redhat.com>
  • Loading branch information
RTann committed Nov 17, 2023
1 parent b15bdcb commit a35a66a
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 13 deletions.
17 changes: 4 additions & 13 deletions libindex/fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"go.opentelemetry.io/otel/trace"
"golang.org/x/sync/errgroup"
"golang.org/x/sync/singleflight"
"golang.org/x/sys/unix"

"github.com/quay/claircore"
"github.com/quay/claircore/indexer"
Expand Down Expand Up @@ -66,13 +65,13 @@ func NewRemoteFetchArena(wc *http.Client, root string) *RemoteFetchArena {
// Rc is a reference counter.
type rc struct {
sync.Mutex
val *os.File
val *tempFile
count int
done func()
}

// NewRc makes an rc.
func newRc(v *os.File, done func()) *rc {
func newRc(v *tempFile, done func()) *rc {
return &rc{
val: v,
done: done,
Expand Down Expand Up @@ -115,15 +114,7 @@ type ref struct {
func (r *ref) Val() (*os.File, error) {
r.rc.Lock()
defer r.rc.Unlock()
fd := int(r.rc.val.Fd())
if fd == -1 {
return nil, errStale
}
p := fmt.Sprintf(`/proc/self/fd/%d`, fd)
// Need to use OpenFile so that the symlink is not dereferenced.
// There's some proc magic so that opening that symlink itself copies the
// description.
return os.OpenFile(p, os.O_RDONLY, 0644)
return r.rc.val.Reopen()
}

// Close decrements the refcount.
Expand Down Expand Up @@ -250,7 +241,7 @@ func (a *RemoteFetchArena) fetchUnlinkedFile(ctx context.Context, key string, de
return v.(*rc), nil
}
// Otherwise, it needs to be populated.
f, err := os.OpenFile(a.root, os.O_WRONLY|unix.O_TMPFILE, 0644)
f, err := openTemp(a.root)
if err != nil {
return nil, err
}
Expand Down
31 changes: 31 additions & 0 deletions libindex/tempfile_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package libindex

import (
"fmt"
"os"

"golang.org/x/sys/unix"
)

type tempFile struct {
*os.File
}

func openTemp(dir string) (*tempFile, error) {
f, err := os.OpenFile(dir, os.O_WRONLY|unix.O_TMPFILE, 0644)
if err != nil {
return nil, err
}

Check warning on line 18 in libindex/tempfile_linux.go

View check run for this annotation

Codecov / codecov/patch

libindex/tempfile_linux.go#L17-L18

Added lines #L17 - L18 were not covered by tests
return &tempFile{
File: f,
}, nil
}

func (t *tempFile) Reopen() (*os.File, error) {
fd := int(t.Fd())
if fd == -1 {
return nil, errStale
}
p := fmt.Sprintf("/proc/self/fd/%d", fd)
return os.OpenFile(p, os.O_RDONLY, 0644)
}
30 changes: 30 additions & 0 deletions libindex/tempfile_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//go:build unix && !linux

package libindex

import (
"errors"
"os"
)

type tempFile struct {
*os.File
}

func openTemp(dir string) (*tempFile, error) {
f, err := os.CreateTemp(dir, "*.fetch")
if err != nil {
return nil, err
}
return &tempFile{
File: f,
}, nil
}

func (t *tempFile) Reopen() (*os.File, error) {
return os.OpenFile(t.Name(), os.O_RDONLY, 0644)
}

func (t *tempFile) Close() error {
return errors.Join(os.Remove(t.Name()), t.File.Close())
}
43 changes: 43 additions & 0 deletions libindex/tempfile_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package libindex

import (
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
_ "unsafe" // linker tricks
)

// This is a very rough port of src/os/tempfile.go that adds the magic
// autodelete flag.

//go:linkname fastrand runtime.fastrand
func fastrand() uint32

type tempFile struct {
*os.File
}

func openTemp(dir string) (*tempFile, error) {
// Copied out of golang.org/x/sys/windows
const FILE_FLAG_DELETE_ON_CLOSE = 0x04000000
for {
fn := fmt.Sprintf("fetch.%d", fastrand())
f, err := os.OpenFile(filepath.Join(dir, fn), os.O_WRONLY|FILE_FLAG_DELETE_ON_CLOSE, 0644)
switch {
case errors.Is(err, nil):
return &tempFile{
File: f,
}, nil
case errors.Is(err, fs.ErrExist):
// Continue
default:
return nil, err
}
}
}

func (t *tempFile) Reopen() (*os.File, error) {
return os.OpenFile(t.Name(), os.O_RDONLY, 0644)
}

0 comments on commit a35a66a

Please sign in to comment.