* Copyright 2002-2009, 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>
#include <Directory.h>
#include <Entry.h>
#include <File.h>
#include <fs_interface.h>
#include <NodeMonitor.h>
#include "storage_support.h"
#include <syscalls.h>
#include <umask.h>
BFile::BFile()
:
fMode(0)
{
}
BFile::BFile(const BFile& file)
:
fMode(0)
{
*this = file;
}
BFile::BFile(const entry_ref* ref, uint32 openMode)
:
fMode(0)
{
SetTo(ref, openMode);
}
BFile::BFile(const BEntry* entry, uint32 openMode)
:
fMode(0)
{
SetTo(entry, openMode);
}
BFile::BFile(const char* path, uint32 openMode)
:
fMode(0)
{
SetTo(path, openMode);
}
BFile::BFile(const BDirectory *dir, const char* path, uint32 openMode)
:
fMode(0)
{
SetTo(dir, path, openMode);
}
BFile::~BFile()
{
close_fd();
}
status_t
BFile::SetTo(const entry_ref* ref, uint32 openMode)
{
Unset();
if (!ref)
return (fCStatus = B_BAD_VALUE);
if (BPrivate::Storage::is_absolute_path(ref->name))
return SetTo(ref->name, openMode);
openMode |= O_CLOEXEC;
int fd = _kern_open_entry_ref(ref->device, ref->directory, ref->name,
openMode, DEFFILEMODE & ~__gUmask);
if (fd >= 0) {
set_fd(fd);
fMode = openMode;
fCStatus = B_OK;
} else
fCStatus = fd;
return fCStatus;
}
status_t
BFile::SetTo(const BEntry* entry, uint32 openMode)
{
Unset();
if (!entry)
return (fCStatus = B_BAD_VALUE);
if (entry->InitCheck() != B_OK)
return (fCStatus = entry->InitCheck());
openMode |= O_CLOEXEC;
int fd = _kern_open(entry->fDirFd, entry->fName, openMode | O_CLOEXEC,
DEFFILEMODE & ~__gUmask);
if (fd >= 0) {
set_fd(fd);
fMode = openMode;
fCStatus = B_OK;
} else
fCStatus = fd;
return fCStatus;
}
status_t
BFile::SetTo(const char* path, uint32 openMode)
{
Unset();
if (!path)
return (fCStatus = B_BAD_VALUE);
openMode |= O_CLOEXEC;
int fd = _kern_open(AT_FDCWD, path, openMode, DEFFILEMODE & ~__gUmask);
if (fd >= 0) {
set_fd(fd);
fMode = openMode;
fCStatus = B_OK;
} else
fCStatus = fd;
return fCStatus;
}
status_t
BFile::SetTo(const BDirectory* dir, const char* path, uint32 openMode)
{
Unset();
if (!dir)
return (fCStatus = B_BAD_VALUE);
openMode |= O_CLOEXEC;
int fd = _kern_open(dir->fDirFd, path, openMode, DEFFILEMODE & ~__gUmask);
if (fd >= 0) {
set_fd(fd);
fMode = openMode;
fCStatus = B_OK;
} else
fCStatus = fd;
return fCStatus;
}
bool
BFile::IsReadable() const
{
return InitCheck() == B_OK
&& ((fMode & O_RWMASK) == O_RDONLY || (fMode & O_RWMASK) == O_RDWR);
}
bool
BFile::IsWritable() const
{
return InitCheck() == B_OK
&& ((fMode & O_RWMASK) == O_WRONLY || (fMode & O_RWMASK) == O_RDWR);
}
ssize_t
BFile::Read(void* buffer, size_t size)
{
if (InitCheck() != B_OK)
return InitCheck();
return _kern_read(get_fd(), -1, buffer, size);
}
ssize_t
BFile::ReadAt(off_t location, void* buffer, size_t size)
{
if (InitCheck() != B_OK)
return InitCheck();
if (location < 0)
return B_BAD_VALUE;
return _kern_read(get_fd(), location, buffer, size);
}
ssize_t
BFile::Write(const void* buffer, size_t size)
{
if (InitCheck() != B_OK)
return InitCheck();
return _kern_write(get_fd(), -1, buffer, size);
}
ssize_t
BFile::WriteAt(off_t location, const void* buffer, size_t size)
{
if (InitCheck() != B_OK)
return InitCheck();
if (location < 0)
return B_BAD_VALUE;
return _kern_write(get_fd(), location, buffer, size);
}
off_t
BFile::Seek(off_t offset, uint32 seekMode)
{
if (InitCheck() != B_OK)
return B_FILE_ERROR;
return _kern_seek(get_fd(), offset, seekMode);
}
off_t
BFile::Position() const
{
if (InitCheck() != B_OK)
return B_FILE_ERROR;
return _kern_seek(get_fd(), 0, SEEK_CUR);
}
status_t
BFile::SetSize(off_t size)
{
if (InitCheck() != B_OK)
return InitCheck();
if (size < 0)
return B_BAD_VALUE;
struct stat statData;
statData.st_size = size;
return set_stat(statData, B_STAT_SIZE | B_STAT_SIZE_INSECURE);
}
status_t
BFile::GetSize(off_t* size) const
{
return BStatable::GetSize(size);
}
BFile&
BFile::operator=(const BFile &file)
{
if (&file != this) {
Unset();
if (file.InitCheck() == B_OK) {
int fd = _kern_dup(file.get_fd());
if (fd >= 0) {
fFd = fd;
fMode = file.fMode;
fCStatus = B_OK;
} else
fCStatus = fd;
}
}
return *this;
}
void BFile::_PhiloFile1() {}
void BFile::_PhiloFile2() {}
void BFile::_PhiloFile3() {}
void BFile::_PhiloFile4() {}
void BFile::_PhiloFile5() {}
void BFile::_PhiloFile6() {}
To be used instead of accessing the BNode's private \c fFd member directly.
\returns The file descriptor, or -1 if not properly initialized.
*/
int
BFile::get_fd() const
{
return fFd;
}
void
BFile::close_fd()
{
BNode::close_fd();
}