mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
[vfs2][gofer] Return appropriate errors when opening and creating files.
Fixes php test ext/standard/tests/file/touch_variation5.phpt on vfs2. Updates #3516 Also spotted a bug with O_EXCL, where we did not return EEXIST when we tried to open the root of the filesystem with O_EXCL | O_CREAT. Added some more tests for open() corner cases. PiperOrigin-RevId: 326346863
This commit is contained in:
@@ -844,6 +844,13 @@ func (fs *filesystem) OpenAt(ctx context.Context, rp *vfs.ResolvingPath, opts vf
|
||||
}
|
||||
}
|
||||
if rp.Done() {
|
||||
// Reject attempts to open mount root directory with O_CREAT.
|
||||
if mayCreate && rp.MustBeDir() {
|
||||
return nil, syserror.EISDIR
|
||||
}
|
||||
if mustCreate {
|
||||
return nil, syserror.EEXIST
|
||||
}
|
||||
return start.openLocked(ctx, rp, &opts)
|
||||
}
|
||||
|
||||
@@ -856,6 +863,10 @@ afterTrailingSymlink:
|
||||
if err := parent.checkPermissions(rp.Credentials(), vfs.MayExec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Reject attempts to open directories with O_CREAT.
|
||||
if mayCreate && rp.MustBeDir() {
|
||||
return nil, syserror.EISDIR
|
||||
}
|
||||
// Determine whether or not we need to create a file.
|
||||
parent.dirMu.Lock()
|
||||
child, err := fs.stepLocked(ctx, rp, parent, false /* mayFollowSymlinks */, &ds)
|
||||
|
||||
@@ -320,7 +320,7 @@ func (fs *filesystem) OpenAt(ctx context.Context, rp *vfs.ResolvingPath, opts vf
|
||||
fs.mu.Lock()
|
||||
defer fs.mu.Unlock()
|
||||
if rp.Done() {
|
||||
// Reject attempts to open directories with O_CREAT.
|
||||
// Reject attempts to open mount root directory with O_CREAT.
|
||||
if rp.MustBeDir() {
|
||||
return nil, syserror.EISDIR
|
||||
}
|
||||
|
||||
@@ -95,6 +95,38 @@ TEST_F(OpenTest, OTruncAndReadOnlyFile) {
|
||||
Open(dirpath.c_str(), O_TRUNC | O_RDONLY, 0666));
|
||||
}
|
||||
|
||||
TEST_F(OpenTest, OCreateDirectory) {
|
||||
SKIP_IF(IsRunningWithVFS1());
|
||||
auto dirpath = GetAbsoluteTestTmpdir();
|
||||
|
||||
// Normal case: existing directory.
|
||||
ASSERT_THAT(open(dirpath.c_str(), O_RDWR | O_CREAT, 0666),
|
||||
SyscallFailsWithErrno(EISDIR));
|
||||
// Trailing separator on existing directory.
|
||||
ASSERT_THAT(open(dirpath.append("/").c_str(), O_RDWR | O_CREAT, 0666),
|
||||
SyscallFailsWithErrno(EISDIR));
|
||||
// Trailing separator on non-existing directory.
|
||||
ASSERT_THAT(open(JoinPath(dirpath, "non-existent").append("/").c_str(),
|
||||
O_RDWR | O_CREAT, 0666),
|
||||
SyscallFailsWithErrno(EISDIR));
|
||||
// "." special case.
|
||||
ASSERT_THAT(open(JoinPath(dirpath, ".").c_str(), O_RDWR | O_CREAT, 0666),
|
||||
SyscallFailsWithErrno(EISDIR));
|
||||
}
|
||||
|
||||
TEST_F(OpenTest, MustCreateExisting) {
|
||||
auto dirPath = GetAbsoluteTestTmpdir();
|
||||
|
||||
// Existing directory.
|
||||
ASSERT_THAT(open(dirPath.c_str(), O_RDWR | O_CREAT | O_EXCL, 0666),
|
||||
SyscallFailsWithErrno(EEXIST));
|
||||
|
||||
// Existing file.
|
||||
auto newFile = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileIn(dirPath));
|
||||
ASSERT_THAT(open(newFile.path().c_str(), O_RDWR | O_CREAT | O_EXCL, 0666),
|
||||
SyscallFailsWithErrno(EEXIST));
|
||||
}
|
||||
|
||||
TEST_F(OpenTest, ReadOnly) {
|
||||
char buf;
|
||||
const FileDescriptor ro_file =
|
||||
|
||||
Reference in New Issue
Block a user