fix(ingestion): close the PR #156 review findings on raw/ reads
- Reverting the ingest call sites to extract.Text(path) stayed green; a test now fails if anything outside internal/extract calls extract.Text( (only TextIn, through an os.Root, may be used). - The watcher symlink test passed for a watcher that ingested nothing, or stopped at the first symlink (SkipAll: one synced link halting all ingestion). It now plants a real note after the symlink and asserts exactly one ingest, and the symlinked-raw refusal has its own test. - A FIFO swapped in between Lstat and Open hung open(2) forever. extract.OpenRegular opens non-blocking and checks the type on the handle; readRawNote, TextIn and the watcher's archive copy use it. - The symlinked-root test covers pending, promote, reject, resolve and ReadIngestFile, and is named for exactly those. - The hard-link residual is documented where it is accepted. Out of scope, filed: #157 (symlinks elsewhere in the Syncthing-shared brain dir reach search and other readers), #158 (writes under raw/ follow symlinks). Refs #153 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,9 @@ package extract
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -34,3 +36,29 @@ func TestTextInReadsInsideTheRootAndRefusesEscapes(t *testing.T) {
|
||||
_, err = TextIn(r, "../"+filepath.Base(outside))
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
// PR #156 review: a regular file swapped for a FIFO between Lstat and Open
|
||||
// blocked open(2) forever. OpenRegular opens non-blocking and checks the type
|
||||
// on the opened handle, so a FIFO is refused promptly instead of hanging.
|
||||
func TestOpenRegularRefusesAFIFOWithoutBlocking(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.NoError(t, syscall.Mkfifo(filepath.Join(dir, "pipe.md"), 0o644))
|
||||
r, err := os.OpenRoot(dir)
|
||||
require.NoError(t, err)
|
||||
defer func() { _ = r.Close() }()
|
||||
|
||||
done := make(chan error, 1)
|
||||
go func() {
|
||||
f, _, err := OpenRegular(r, "pipe.md")
|
||||
if f != nil {
|
||||
_ = f.Close()
|
||||
}
|
||||
done <- err
|
||||
}()
|
||||
select {
|
||||
case err := <-done:
|
||||
assert.Error(t, err)
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("OpenRegular blocked on a FIFO")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user