* Fixed _{kern|user}_{read|write}[v]() functions to not move the descriptor's

file position in case an offset was specified.
* Reverted r23828-r23830 in File.cpp: don't fix the symptoms but the cause
  of the problem (hey, that has to be in the kernel, right? :))
* Cleanup of File.cpp, removed OpenBeOS namespace.
* Moved user_fd_kernel_ioctl() to the section where it belongs to (that
  function should be renamed, though).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23832 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-02-02 23:50:51 +00:00
parent ff5defe060
commit 5905a0ae34
2 changed files with 126 additions and 113 deletions

View File

@ -1,11 +1,12 @@
//----------------------------------------------------------------------
// This software is part of the Haiku distribution and is covered
// by the MIT license.
//---------------------------------------------------------------------
/*!
\file File.cpp
BFile implementation.
*/
/*
* Copyright 2002-2008, Haiku Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Tyler Dauwalder
* Ingo Weinhold, bonefish@users.sf.net
*/
#include <fcntl.h>
#include <unistd.h>
@ -22,11 +23,6 @@ extern mode_t __gUmask;
// declared in sys/umask.c
#ifdef USE_OPENBEOS_NAMESPACE
namespace OpenBeOS {
#endif
// constructor
//! Creates an uninitialized BFile.
BFile::BFile()
: BNode(),
@ -35,7 +31,7 @@ BFile::BFile()
{
}
// copy constructor
//! Creates a copy of the supplied BFile.
/*! If \a file is uninitialized, the newly constructed BFile will be, too.
\param file the BFile object to be copied
@ -48,7 +44,7 @@ BFile::BFile(const BFile &file)
*this = file;
}
// constructor
/*! \brief Creates a BFile and initializes it to the file referred to by
the supplied entry_ref and according to the specified open mode.
\param ref the entry_ref referring to the file
@ -63,7 +59,7 @@ BFile::BFile(const entry_ref *ref, uint32 openMode)
SetTo(ref, openMode);
}
// constructor
/*! \brief Creates a BFile and initializes it to the file referred to by
the supplied BEntry and according to the specified open mode.
\param entry the BEntry referring to the file
@ -78,7 +74,7 @@ BFile::BFile(const BEntry *entry, uint32 openMode)
SetTo(entry, openMode);
}
// constructor
/*! \brief Creates a BFile and initializes it to the file referred to by
the supplied path name and according to the specified open mode.
\param path the file's path name
@ -93,7 +89,7 @@ BFile::BFile(const char *path, uint32 openMode)
SetTo(path, openMode);
}
// constructor
/*! \brief Creates a BFile and initializes it to the file referred to by
the supplied path name relative to the specified BDirectory and
according to the specified open mode.
@ -111,9 +107,9 @@ BFile::BFile(const BDirectory *dir, const char *path, uint32 openMode)
SetTo(dir, path, openMode);
}
// destructor
//! Frees all allocated resources.
/*! If the file is properly initialized, the file's file descriptor is closed.
/*! \brief Frees all allocated resources.
If the file is properly initialized, the file's file descriptor is closed.
*/
BFile::~BFile()
{
@ -125,7 +121,7 @@ BFile::~BFile()
close_fd();
}
// SetTo
/*! \brief Re-initializes the BFile to the file referred to by the
supplied entry_ref and according to the specified open mode.
\param ref the entry_ref referring to the file
@ -175,7 +171,7 @@ BFile::SetTo(const entry_ref *ref, uint32 openMode)
return fCStatus;
}
// SetTo
/*! \brief Re-initializes the BFile to the file referred to by the
supplied BEntry and according to the specified open mode.
\param entry the BEntry referring to the file
@ -218,7 +214,7 @@ BFile::SetTo(const BEntry *entry, uint32 openMode)
return fCStatus;
}
// SetTo
/*! \brief Re-initializes the BFile to the file referred to by the
supplied path name and according to the specified open mode.
\param path the file's path name
@ -256,7 +252,7 @@ BFile::SetTo(const char *path, uint32 openMode)
return fCStatus;
}
// SetTo
/*! \brief Re-initializes the BFile to the file referred to by the
supplied path name relative to the specified BDirectory and
according to the specified open mode.
@ -298,9 +294,9 @@ BFile::SetTo(const BDirectory *dir, const char *path, uint32 openMode)
return fCStatus;
}
// IsReadable
//! Returns whether the file is readable.
/*! \return
/*! \brief Returns whether the file is readable.
\return
- \c true, if the BFile has been initialized properly and the file has
been been opened for reading,
- \c false, otherwise.
@ -308,14 +304,13 @@ BFile::SetTo(const BDirectory *dir, const char *path, uint32 openMode)
bool
BFile::IsReadable() const
{
return (InitCheck() == B_OK
&& ((fMode & O_RWMASK) == O_RDONLY
|| (fMode & O_RWMASK) == O_RDWR));
return InitCheck() == B_OK
&& ((fMode & O_RWMASK) == O_RDONLY || (fMode & O_RWMASK) == O_RDWR);
}
// IsWritable
//! Returns whether the file is writable.
/*! \return
/*! \brief Returns whether the file is writable.
\return
- \c true, if the BFile has been initialized properly and the file has
been opened for writing,
- \c false, otherwise.
@ -323,14 +318,13 @@ BFile::IsReadable() const
bool
BFile::IsWritable() const
{
return (InitCheck() == B_OK
&& ((fMode & O_RWMASK) == O_WRONLY
|| (fMode & O_RWMASK) == O_RDWR));
return InitCheck() == B_OK
&& ((fMode & O_RWMASK) == O_WRONLY || (fMode & O_RWMASK) == O_RDWR);
}
// Read
//! Reads a number of bytes from the file into a buffer.
/*! \param buffer the buffer the data from the file shall be written to
/*! \brief Reads a number of bytes from the file into a buffer.
\param buffer the buffer the data from the file shall be written to
\param size the number of bytes that shall be read
\return the number of bytes actually read or an error code
*/
@ -342,7 +336,7 @@ BFile::Read(void *buffer, size_t size)
return _kern_read(get_fd(), -1, buffer, size);
}
// ReadAt
/*! \brief Reads a number of bytes from a certain position within the file
into a buffer.
\param location the position (in bytes) within the file from which the
@ -359,18 +353,12 @@ BFile::ReadAt(off_t location, void *buffer, size_t size)
if (location < 0)
return B_BAD_VALUE;
// ReadAt() is not supposed to move the current position on the file.
// Tested on BeOS R5 and Zeta.
off_t curPos = Position(); // Cache current position.
ssize_t result = _kern_read(get_fd(), location, buffer, size);
Seek(curPos, SEEK_SET); // Resets file position.
return result;
return _kern_read(get_fd(), location, buffer, size);
}
// Write
//! Writes a number of bytes from a buffer into the file.
/*! \param buffer the buffer containing the data to be written to the file
/*! \brief Writes a number of bytes from a buffer into the file.
\param buffer the buffer containing the data to be written to the file
\param size the number of bytes that shall be written
\return the number of bytes actually written or an error code
*/
@ -382,7 +370,7 @@ BFile::Write(const void *buffer, size_t size)
return _kern_write(get_fd(), -1, buffer, size);
}
// WriteAt
/*! \brief Writes a number of bytes from a buffer at a certain position
into the file.
\param location the position (in bytes) within the file at which the data
@ -399,17 +387,12 @@ BFile::WriteAt(off_t location, const void *buffer, size_t size)
if (location < 0)
return B_BAD_VALUE;
// WriteAt() is not supposed to move the current position on the file.
off_t curPos = Position(); // Cache current position.
ssize_t result = _kern_write(get_fd(), location, buffer, size);
Seek(curPos, SEEK_SET); // Resets file position.
return result;
return _kern_write(get_fd(), location, buffer, size);
}
// Seek
//! Seeks to another read/write position within the file.
/*! It is allowed to seek past the end of the file. A subsequent call to
/*! \brief Seeks to another read/write position within the file.
It is allowed to seek past the end of the file. A subsequent call to
Write() will pad the file with undefined data. Seeking before the
beginning of the file will fail and the behavior of subsequent Read()
or Write() invocations will be undefined.
@ -432,9 +415,9 @@ BFile::Seek(off_t offset, uint32 seekMode)
return _kern_seek(get_fd(), offset, seekMode);
}
// Position
//! Returns the current read/write position within the file.
/*! \return
/*! \brief Returns the current read/write position within the file.
\return
- the current read/write position relative to the beginning of the file
- \c B_ERROR, after a Seek() before the beginning of the file
- \c B_FILE_ERROR, if the file has not been initialized
@ -447,9 +430,9 @@ BFile::Position() const
return _kern_seek(get_fd(), 0, SEEK_CUR);
}
// SetSize
//! Sets the size of the file.
/*! If the file is shorter than \a size bytes it will be padded with
/*! \brief Sets the size of the file.
If the file is shorter than \a size bytes it will be padded with
unspecified data to the requested size. If it is larger, it will be
truncated.
Note: There's no problem with setting the size of a BFile opened in
@ -473,16 +456,16 @@ BFile::SetSize(off_t size)
return set_stat(statData, B_STAT_SIZE);
}
// GetSize TODO: doxygen comment
status_t
BFile::GetSize(off_t* size) const
{
return BStatable::GetSize(size);
}
// =
//! Assigns another BFile to this BFile.
/*! If the other BFile is uninitialized, this one will be too. Otherwise it
/*! \brief Assigns another BFile to this BFile.
If the other BFile is uninitialized, this one will be too. Otherwise it
will refer to the same file using the same mode, unless an error occurs.
\param file the original BFile
\return a reference to this BFile
@ -517,7 +500,6 @@ void BFile::_PhiloFile5() {}
void BFile::_PhiloFile6() {}
// get_fd
/*! Returns the file descriptor.
To be used instead of accessing the BNode's private \c fFd member directly.
\return the file descriptor, or -1, if not properly initialized.
@ -528,7 +510,7 @@ BFile::get_fd() const
return fFd;
}
// close_fd
/*! Overrides BNode::close_fd() solely for R5 binary compatibility.
*/
void
@ -537,8 +519,3 @@ BFile::close_fd()
BNode::close_fd();
}
#ifdef USE_OPENBEOS_NAMESPACE
}; // namespace OpenBeOS
#endif

View File

@ -1,9 +1,10 @@
/* Operations on file descriptors
*
* Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de.
/*
* Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
//! Operations on file descriptors
#include <fd.h>
#include <stdlib.h>
@ -611,8 +612,16 @@ common_close(int fd, bool kernel)
}
// #pragma mark -
// User syscalls
status_t
user_fd_kernel_ioctl(int fd, ulong op, void *buffer, size_t length)
{
TRACE(("user_fd_kernel_ioctl: fd %d\n", fd));
return fd_ioctl(false, fd, op, buffer, length);
}
// #pragma mark - User syscalls
ssize_t
@ -636,8 +645,11 @@ _user_read(int fd, off_t pos, void *buffer, size_t length)
return B_FILE_ERROR;
}
if (pos == -1)
bool movePosition = false;
if (pos == -1) {
pos = descriptor->pos;
movePosition = true;
}
if (descriptor->ops->fd_read) {
bytesRead = descriptor->ops->fd_read(descriptor, pos, buffer, &length);
@ -647,7 +659,8 @@ _user_read(int fd, off_t pos, void *buffer, size_t length)
else
bytesRead = (ssize_t)length;
descriptor->pos = pos + length;
if (movePosition)
descriptor->pos = pos + length;
}
} else
bytesRead = B_BAD_VALUE;
@ -661,6 +674,7 @@ ssize_t
_user_readv(int fd, off_t pos, const iovec *userVecs, size_t count)
{
struct file_descriptor *descriptor;
bool movePosition = false;
ssize_t bytesRead = 0;
status_t status;
iovec *vecs;
@ -696,8 +710,10 @@ _user_readv(int fd, off_t pos, const iovec *userVecs, size_t count)
goto err2;
}
if (pos == -1)
if (pos == -1) {
pos = descriptor->pos;
movePosition = true;
}
if (descriptor->ops->fd_read) {
for (i = 0; i < count; i++) {
@ -719,7 +735,8 @@ _user_readv(int fd, off_t pos, const iovec *userVecs, size_t count)
bytesRead = B_BAD_VALUE;
status = bytesRead;
descriptor->pos = pos;
if (movePosition)
descriptor->pos = pos;
err2:
free(vecs);
@ -749,8 +766,11 @@ _user_write(int fd, off_t pos, const void *buffer, size_t length)
return B_FILE_ERROR;
}
if (pos == -1)
bool movePosition = false;
if (pos == -1) {
pos = descriptor->pos;
movePosition = true;
}
if (descriptor->ops->fd_write) {
bytesWritten = descriptor->ops->fd_write(descriptor, pos, buffer, &length);
@ -760,7 +780,8 @@ _user_write(int fd, off_t pos, const void *buffer, size_t length)
else
bytesWritten = (ssize_t)length;
descriptor->pos = pos + length;
if (movePosition)
descriptor->pos = pos + length;
}
} else
bytesWritten = B_BAD_VALUE;
@ -774,6 +795,7 @@ ssize_t
_user_writev(int fd, off_t pos, const iovec *userVecs, size_t count)
{
struct file_descriptor *descriptor;
bool movePosition = false;
ssize_t bytesWritten = 0;
status_t status;
iovec *vecs;
@ -809,8 +831,10 @@ _user_writev(int fd, off_t pos, const iovec *userVecs, size_t count)
goto err2;
}
if (pos == -1)
if (pos == -1) {
pos = descriptor->pos;
movePosition = true;
}
if (descriptor->ops->fd_write) {
for (i = 0; i < count; i++) {
@ -832,7 +856,8 @@ _user_writev(int fd, off_t pos, const iovec *userVecs, size_t count)
bytesWritten = B_BAD_VALUE;
status = bytesWritten;
descriptor->pos = pos;
if (movePosition)
descriptor->pos = pos;
err2:
free(vecs);
@ -951,8 +976,7 @@ _user_dup2(int ofd, int nfd)
}
// #pragma mark -
// Kernel calls
// #pragma mark - Kernel calls
ssize_t
@ -972,8 +996,11 @@ _kern_read(int fd, off_t pos, void *buffer, size_t length)
return B_FILE_ERROR;
}
if (pos == -1)
bool movePosition = false;
if (pos == -1) {
pos = descriptor->pos;
movePosition = true;
}
if (descriptor->ops->fd_read) {
bytesRead = descriptor->ops->fd_read(descriptor, pos, buffer, &length);
@ -983,7 +1010,8 @@ _kern_read(int fd, off_t pos, void *buffer, size_t length)
else
bytesRead = (ssize_t)length;
descriptor->pos = pos + length;
if (movePosition)
descriptor->pos = pos + length;
}
} else
bytesRead = B_BAD_VALUE;
@ -997,6 +1025,7 @@ ssize_t
_kern_readv(int fd, off_t pos, const iovec *vecs, size_t count)
{
struct file_descriptor *descriptor;
bool movePosition = false;
ssize_t bytesRead = 0;
status_t status;
uint32 i;
@ -1012,13 +1041,16 @@ _kern_readv(int fd, off_t pos, const iovec *vecs, size_t count)
return B_FILE_ERROR;
}
if (pos == -1)
if (pos == -1) {
pos = descriptor->pos;
movePosition = true;
}
if (descriptor->ops->fd_read) {
for (i = 0; i < count; i++) {
size_t length = vecs[i].iov_len;
status = descriptor->ops->fd_read(descriptor, pos, vecs[i].iov_base, &length);
status = descriptor->ops->fd_read(descriptor, pos, vecs[i].iov_base,
&length);
if (status < B_OK) {
bytesRead = status;
break;
@ -1034,7 +1066,9 @@ _kern_readv(int fd, off_t pos, const iovec *vecs, size_t count)
} else
bytesRead = B_BAD_VALUE;
descriptor->pos = pos;
if (movePosition)
descriptor->pos = pos;
put_fd(descriptor);
return bytesRead;
}
@ -1057,18 +1091,23 @@ _kern_write(int fd, off_t pos, const void *buffer, size_t length)
return B_FILE_ERROR;
}
if (pos == -1)
bool movePosition = false;
if (pos == -1) {
pos = descriptor->pos;
movePosition = true;
}
if (descriptor->ops->fd_write) {
bytesWritten = descriptor->ops->fd_write(descriptor, pos, buffer, &length);
bytesWritten = descriptor->ops->fd_write(descriptor, pos, buffer,
&length);
if (bytesWritten >= B_OK) {
if (length > SSIZE_MAX)
bytesWritten = SSIZE_MAX;
else
bytesWritten = (ssize_t)length;
descriptor->pos = pos + length;
if (movePosition)
descriptor->pos = pos + length;
}
} else
bytesWritten = B_BAD_VALUE;
@ -1082,6 +1121,7 @@ ssize_t
_kern_writev(int fd, off_t pos, const iovec *vecs, size_t count)
{
struct file_descriptor *descriptor;
bool movePosition = false;
ssize_t bytesWritten = 0;
status_t status;
uint32 i;
@ -1097,13 +1137,16 @@ _kern_writev(int fd, off_t pos, const iovec *vecs, size_t count)
return B_FILE_ERROR;
}
if (pos == -1)
if (pos == -1) {
pos = descriptor->pos;
movePosition = true;
}
if (descriptor->ops->fd_write) {
for (i = 0; i < count; i++) {
size_t length = vecs[i].iov_len;
status = descriptor->ops->fd_write(descriptor, pos, vecs[i].iov_base, &length);
status = descriptor->ops->fd_write(descriptor, pos,
vecs[i].iov_base, &length);
if (status < B_OK) {
bytesWritten = status;
break;
@ -1119,7 +1162,9 @@ _kern_writev(int fd, off_t pos, const iovec *vecs, size_t count)
} else
bytesWritten = B_BAD_VALUE;
descriptor->pos = pos;
if (movePosition)
descriptor->pos = pos;
put_fd(descriptor);
return bytesWritten;
}
@ -1153,15 +1198,6 @@ _kern_ioctl(int fd, ulong op, void *buffer, size_t length)
}
status_t
user_fd_kernel_ioctl(int fd, ulong op, void *buffer, size_t length)
{
TRACE(("user_fd_kernel_ioctl: fd %d\n", fd));
return fd_ioctl(false, fd, op, buffer, length);
}
ssize_t
_kern_read_dir(int fd, struct dirent *buffer, size_t bufferSize, uint32 maxCount)
{