Fix open(2) allowing opening directories invalidly and check O_TRUNC errors.
Among other things, redirecting to a directory will now display an error as it should. Also fix a bug when opening /dev/pts: O_WRITE on a directory is a POSIX violation.
This commit is contained in:
parent
b767063c9a
commit
9d29e96c3b
|
@ -645,7 +645,11 @@ static bool IsSaneFlagModeCombination(int flags, mode_t /*mode*/)
|
||||||
// opening a directory, attempting to truncate it, and then aborting with an
|
// opening a directory, attempting to truncate it, and then aborting with an
|
||||||
// error because a directory was opened.
|
// error because a directory was opened.
|
||||||
if ( (flags & (O_CREATE | O_TRUNC)) && (flags & (O_DIRECTORY)) )
|
if ( (flags & (O_CREATE | O_TRUNC)) && (flags & (O_DIRECTORY)) )
|
||||||
return errno = EINVAL, false;
|
return false;
|
||||||
|
// POSIX: "The result of using O_TRUNC without either O_RDWR or
|
||||||
|
// O_WRONLY is undefined."
|
||||||
|
if ( (flags & O_TRUNC) && !(flags & O_WRITE) )
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,6 +774,21 @@ Ref<Descriptor> Descriptor::open(ioctx_t* ctx, const char* filename, int flags,
|
||||||
|
|
||||||
delete[] filename_mine;
|
delete[] filename_mine;
|
||||||
|
|
||||||
|
// Abort if the user tries to write to an existing directory.
|
||||||
|
if ( S_ISDIR(desc->type) )
|
||||||
|
{
|
||||||
|
if ( flags & (O_CREATE | O_TRUNC | O_WRITE) )
|
||||||
|
return errno = EISDIR, Ref<Descriptor>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truncate the file if requested.
|
||||||
|
if ( (flags & O_TRUNC) && S_ISREG(desc->type) )
|
||||||
|
{
|
||||||
|
assert(flags & O_WRITE); // IsSaneFlagModeCombination
|
||||||
|
if ( desc->truncate(ctx, 0) < 0 )
|
||||||
|
return Ref<Descriptor>();
|
||||||
|
}
|
||||||
|
|
||||||
// Abort the open if the user wanted a directory but this wasn't.
|
// Abort the open if the user wanted a directory but this wasn't.
|
||||||
if ( flags & O_DIRECTORY && !S_ISDIR(desc->type) )
|
if ( flags & O_DIRECTORY && !S_ISDIR(desc->type) )
|
||||||
return errno = ENOTDIR, Ref<Descriptor>();
|
return errno = ENOTDIR, Ref<Descriptor>();
|
||||||
|
@ -802,13 +821,6 @@ Ref<Descriptor> Descriptor::open_elem(ioctx_t* ctx, const char* filename,
|
||||||
if ( !ret )
|
if ( !ret )
|
||||||
return Ref<Descriptor>();
|
return Ref<Descriptor>();
|
||||||
|
|
||||||
// Truncate the file if requested.
|
|
||||||
// TODO: This is a bit dodgy, should this be moved to the inode open method
|
|
||||||
// or something? And how should error handling be done here?
|
|
||||||
if ( (flags & O_TRUNC) && S_ISREG(ret->type) )
|
|
||||||
if ( flags & O_WRITE )
|
|
||||||
ret->truncate(ctx, 0);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -520,7 +520,7 @@ static void BootThread(void* /*user*/)
|
||||||
if ( slashdev->mkdir(&ctx, "pts", 0755) < 0 )
|
if ( slashdev->mkdir(&ctx, "pts", 0755) < 0 )
|
||||||
Panic("Could not mkdir /dev/pts");
|
Panic("Could not mkdir /dev/pts");
|
||||||
Ref<Descriptor> ptsdir =
|
Ref<Descriptor> ptsdir =
|
||||||
slashdev->open(&ctx, "pts", O_DIRECTORY | O_READ | O_WRITE);
|
slashdev->open(&ctx, "pts", O_DIRECTORY | O_READ);
|
||||||
if ( !ptsdir )
|
if ( !ptsdir )
|
||||||
Panic("Could not open /dev/pts");
|
Panic("Could not open /dev/pts");
|
||||||
if ( !mtable->AddMount(ptsdir->ino, ptsdir->dev, pts, true) )
|
if ( !mtable->AddMount(ptsdir->ino, ptsdir->dev, pts, true) )
|
||||||
|
|
Loading…
Reference in New Issue