Skip to content

Commit c2313ea

Browse files
authored
Fix write() truncation with ext-uv and ext-eio (#76)
1 parent 1c9f0eb commit c2313ea

File tree

4 files changed

+58
-4
lines changed

4 files changed

+58
-4
lines changed

src/Driver/EioFilesystemDriver.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ public function read(string $path): string
346346

347347
public function write(string $path, string $contents): void
348348
{
349-
$flags = \EIO_O_RDWR | \EIO_O_CREAT;
349+
$flags = \EIO_O_RDWR | \EIO_O_CREAT | \EIO_O_TRUNC;
350350
$mode = \EIO_S_IRUSR | \EIO_S_IWUSR | \EIO_S_IXUSR;
351351
$priority = \EIO_PRI_DEFAULT;
352352

src/Driver/UvFilesystemDriver.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ public function read(string $path): string
418418

419419
public function write(string $path, string $contents): void
420420
{
421-
$flags = \UV::O_WRONLY | \UV::O_CREAT;
421+
$flags = \UV::O_WRONLY | \UV::O_CREAT | \UV::O_TRUNC;
422422
$mode = \UV::S_IRWXU | \UV::S_IRUSR;
423423

424424
$this->poll->listen();
@@ -454,8 +454,10 @@ private function parseMode(string $mode): int
454454
return match ($mode) {
455455
"r" => \UV::O_RDONLY,
456456
"r+" => \UV::O_RDWR,
457-
"c", "w" => \UV::O_WRONLY | \UV::O_CREAT,
458-
"c+", "w+" => \UV::O_RDWR | \UV::O_CREAT,
457+
"c" => \UV::O_WRONLY | \UV::O_CREAT,
458+
"w" => \UV::O_WRONLY | \UV::O_CREAT | \UV::O_TRUNC,
459+
"c+" => \UV::O_RDWR | \UV::O_CREAT,
460+
"w+" => \UV::O_RDWR | \UV::O_CREAT | \UV::O_TRUNC,
459461
"a" => \UV::O_WRONLY | \UV::O_CREAT | \UV::O_APPEND,
460462
"a+" => \UV::O_RDWR | \UV::O_CREAT | \UV::O_APPEND,
461463
"x" => \UV::O_WRONLY | \UV::O_CREAT | \UV::O_EXCL,

test/FileTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use Amp\ByteStream\ClosedException;
66
use Amp\File;
7+
use Amp\File\Whence;
8+
79
use function Amp\async;
810

911
abstract class FileTest extends FilesystemTest
@@ -25,6 +27,35 @@ public function testWrite(): void
2527
$this->assertSame("foobar", $contents);
2628

2729
$handle->close();
30+
31+
$handle = $this->driver->openFile($path, "c+");
32+
$handle->seek(0, Whence::End);
33+
$this->assertSame(6, $handle->tell());
34+
35+
$handle->close();
36+
}
37+
38+
public function testWriteTruncate(): void
39+
{
40+
$path = Fixture::path() . "/write";
41+
$handle = $this->driver->openFile($path, "c+");
42+
$this->assertSame(0, $handle->tell());
43+
44+
$handle->write("foo");
45+
$handle->write("bar");
46+
$handle->seek(0);
47+
$contents = $handle->read();
48+
$this->assertSame(6, $handle->tell());
49+
$this->assertTrue($handle->eof());
50+
$this->assertSame("foobar", $contents);
51+
52+
$handle->close();
53+
54+
$handle = $this->driver->openFile($path, "w+");
55+
$handle->seek(0, Whence::End);
56+
$this->assertSame(0, $handle->tell());
57+
58+
$handle->close();
2859
}
2960

3061
public function testEmptyWrite(): void

test/FilesystemDriverTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,27 @@ public function testTouch(): void
506506
$this->assertTrue($newStat["mtime"] > $oldStat["mtime"]);
507507
}
508508

509+
/**
510+
* @group slow
511+
*/
512+
public function testWrite(): void
513+
{
514+
$fixtureDir = Fixture::path();
515+
516+
$contents1 = "write test longer";
517+
$contents2 = "write test";
518+
$path = "{$fixtureDir}/write.txt";
519+
520+
$this->driver->write($path, $contents1);
521+
$this->assertSame($contents1, $this->driver->read($path));
522+
523+
$this->driver->write($path, $contents2);
524+
$this->assertSame($contents2, $this->driver->read($path));
525+
526+
$this->driver->write($path, $contents1);
527+
$this->assertSame($contents1, $this->driver->read($path));
528+
}
529+
509530
public function testTouchFailsOnNonexistentPath(): void
510531
{
511532
$fixtureDir = Fixture::path();

0 commit comments

Comments
 (0)