Got rid of the Storage Kit's kernel abstraction layer, which was

unfortunately quite slow and made some things more complicated than they
needed to be.
Implemented a few missing things (e.g. BSymLink and node locking).


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8694 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2004-08-28 20:14:46 +00:00
parent 233e6dadef
commit db10640de9
25 changed files with 1731 additions and 1137 deletions
+5 -2
View File
@@ -78,6 +78,8 @@ public:
BDirectory &operator=(const BDirectory &dir);
private:
friend class BNode;
virtual void _ErectorDirectory1();
virtual void _ErectorDirectory2();
virtual void _ErectorDirectory3();
@@ -87,13 +89,14 @@ private:
private:
virtual void close_fd();
BPrivate::Storage::FileDescriptor get_fd() const;
int get_fd() const;
private:
uint32 _reservedData[7];
BPrivate::Storage::FileDescriptor fDirFd;
int fDirFd;
friend class BEntry;
friend class BFile;
};
+9 -8
View File
@@ -14,7 +14,6 @@
#include <SupportDefs.h>
#include <Statable.h>
#include <StorageDefs.Private.h>
#ifdef USE_OPENBEOS_NAMESPACE
namespace OpenBeOS {
@@ -77,6 +76,11 @@ public:
BEntry &operator=(const BEntry &item);
private:
friend class BDirectory;
friend class BFile;
friend class BNode;
friend class BSymLink;
virtual void _PennyEntry1();
virtual void _PennyEntry2();
virtual void _PennyEntry3();
@@ -90,11 +94,10 @@ private:
/*! BEntry implementation of BStatable::set_stat() */
virtual status_t set_stat(struct stat &st, uint32 what);
status_t set(BPrivate::Storage::FileDescriptor dir, const char *path,
bool traverse);
status_t set(int dir, const char *path, bool traverse);
/*! File descriptor for the entry's parent directory. */
BPrivate::Storage::FileDescriptor fDirFd;
int fDirFd;
/*! Leaf name of the entry. */
char *fName;
@@ -104,6 +107,8 @@ private:
status_t set_name(const char *name);
status_t _Rename(BEntry& target, bool clobber);
void Dump(const char *name = NULL);
};
@@ -118,7 +123,3 @@ bool operator<(const entry_ref &a, const entry_ref &b);
#endif
#endif // _ENTRY_H
+1 -1
View File
@@ -71,7 +71,7 @@ private:
uint32 _reservedData[8];
private:
BPrivate::Storage::FileDescriptor get_fd() const;
int get_fd() const;
private:
//! The file's open mode.
+6 -4
View File
@@ -11,7 +11,6 @@
#define _NODE_H
#include <Statable.h>
#include <StorageDefs.Private.h>
#ifdef USE_OPENBEOS_NAMESPACE
namespace OpenBeOS {
@@ -115,14 +114,17 @@ private:
uint32 rudeData[4];
private:
status_t set_fd(BPrivate::Storage::FileDescriptor fd);
status_t set_fd(int fd);
virtual void close_fd();
void set_status(status_t newStatus);
status_t _SetTo(int fd, const char *path, bool traverse);
status_t _SetTo(const entry_ref *ref, bool traverse);
virtual status_t set_stat(struct stat &st, uint32 what);
BPrivate::Storage::FileDescriptor fFd;
BPrivate::Storage::FileDescriptor fAttrFd;
int fFd;
int fAttrFd;
status_t fCStatus;
status_t InitAttrDir();
+1 -5
View File
@@ -15,8 +15,6 @@
#include <OS.h>
#include <SupportDefs.h>
#include <StorageDefs.Private.h>
class BVolume;
struct entry_ref;
@@ -119,9 +117,7 @@ private:
bool fLive;
port_id fPort;
long fToken;
BPrivate::Storage::FileDescriptor fQueryFd;
int fQueryFd;
};
#endif // _QUERY_H
+2 -22
View File
@@ -39,15 +39,6 @@ public:
BSymLink(const BDirectory *dir, const char *path);
virtual ~BSymLink();
// WORKAROUND
// SetTo() methods: Part of a work around until someone has an idea how to
// get BPrivate::Storage::read_link(FileDescriptor,...) to work.
status_t SetTo(const entry_ref *ref);
status_t SetTo(const BEntry *entry);
status_t SetTo(const char *path);
status_t SetTo(const BDirectory *dir, const char *path);
void Unset();
ssize_t ReadLink(char *buf, size_t size);
ssize_t MakeLinkedPath(const char *dirPath, BPath *path);
@@ -55,11 +46,6 @@ public:
bool IsAbsolute();
// WORKAROUND
// operator=(): Part of a work around until someone has an idea how to
// get BPrivate::Storage::read_link(FileDescriptor,...) to work.
BSymLink &operator=(const BSymLink &link);
private:
virtual void _MissingSymLink1();
virtual void _MissingSymLink2();
@@ -68,15 +54,11 @@ private:
virtual void _MissingSymLink5();
virtual void _MissingSymLink6();
// WORKAROUND
// fSecretEntry: Part of a work around until someone has an idea how to
// get BPrivate::Storage::read_link(FileDescriptor,...) to work.
// uint32 _reservedData[4];
uint32 _reservedData[3];
uint32 _reservedData[4];
BEntry *fSecretEntry;
private:
BPrivate::Storage::FileDescriptor get_fd() const;
int get_fd() const;
};
#ifdef USE_OPENBEOS_NAMESPACE
@@ -84,5 +66,3 @@ private:
#endif
#endif // _SYM_LINK_H
+54
View File
@@ -11,14 +11,22 @@
#ifndef _STORAGE_SUPPORT_H
#define _STORAGE_SUPPORT_H
#include <dirent.h>
#include <string>
namespace BPrivate {
namespace Storage {
// For convenience:
struct LongDirEntry : dirent { char _buffer[B_FILE_NAME_LENGTH]; };
//! Returns whether the supplied path is absolute.
bool is_absolute_path(const char *path);
status_t parse_path(const char *fullPath, int &dirEnd, int &leafStart,
int &leafEnd);
status_t parse_path(const char *fullPath, char *dirPath, char *leaf);
//! splits a path name into directory path and leaf name
status_t split_path(const char *fullPath, char *&path, char *&leaf);
@@ -84,9 +92,55 @@ void escape_path(const char *str, char *result);
*/
void escape_path(char *str);
/*! \brief Returns whether the supplied device ID refers to the root FS.
*/
bool device_is_root_device(dev_t device);
// FDCloser
class FDCloser {
public:
FDCloser(int fd)
: fFD(fd)
{
}
~FDCloser()
{
Close();
}
void SetTo(int fd)
{
Close();
fFD = fd;
}
// implemented in the source file to not expose syscalls to the unit tests
// which include this file too
void Close();
// void Close()
// {
// if (fFD >= 0)
// _kern_close(fFD);
// fFD = -1;
// }
int Detach()
{
int fd = fFD;
fFD = -1;
return fd;
}
private:
int fFD;
};
}; // namespace Storage
}; // namespace BPrivate
using BPrivate::Storage::FDCloser;
#endif // _STORAGE_SUPPORT_H
+11
View File
@@ -427,6 +427,7 @@ BAppFileInfo::GetSupportedTypes(BMessage *types) const
- \c B_NO_INIT: The object is not properly initialized.
- other error codes
*/
#include <stdio.h>
status_t
BAppFileInfo::SetSupportedTypes(const BMessage *types, bool syncAll)
{
@@ -434,19 +435,23 @@ BAppFileInfo::SetSupportedTypes(const BMessage *types, bool syncAll)
status_t error = B_OK;
if (error == B_OK && InitCheck() != B_OK)
error = B_NO_INIT;
printf("check\n");
BMimeType mimeType;
if (error == B_OK)
error = GetMetaMime(&mimeType);
printf("check\n");
if (error == B_OK) {
if (types) {
// check param -- supported types must be valid
const char *type;
printf("check1\n");
for (int32 i = 0;
error == B_OK && types->FindString("types", i, &type) == B_OK;
i++) {
if (!BMimeType::IsValid(type))
error = B_BAD_VALUE;
}
printf("check1\n");
// get flattened size
ssize_t size = 0;
if (error == B_OK) {
@@ -454,6 +459,7 @@ BAppFileInfo::SetSupportedTypes(const BMessage *types, bool syncAll)
if (size < 0)
error = size;
}
printf("check1\n");
// allocate a buffer for the flattened data
char *buffer = NULL;
if (error == B_OK) {
@@ -461,23 +467,28 @@ BAppFileInfo::SetSupportedTypes(const BMessage *types, bool syncAll)
if (!buffer)
error = B_NO_MEMORY;
}
printf("check1\n");
// flatten the message
if (error == B_OK)
error = types->Flatten(buffer, size);
printf("check1\n");
// write the data
if (error == B_OK) {
error = _WriteData(kSupportedTypesAttribute,
kSupportedTypesResourceID, B_MESSAGE_TYPE,
buffer, size);
}
printf("check1\n");
// clean up
if (buffer)
delete[] buffer;
} else
error = _RemoveData(kSupportedTypesAttribute, B_MESSAGE_TYPE);
printf("check\n");
// update the MIME database, if the app signature is installed
if (error == B_OK && mimeType.IsInstalled())
error = mimeType.SetSupportedTypes(types, syncAll);
printf("check\n");
}
return error;
}
+198 -241
View File
@@ -15,8 +15,10 @@
#include <File.h>
#include <Path.h>
#include <SymLink.h>
#include <syscalls.h>
#include "storage_support.h"
#include "kernel_interface.h"
#ifdef USE_OPENBEOS_NAMESPACE
namespace OpenBeOS {
@@ -27,7 +29,7 @@ namespace OpenBeOS {
BDirectory::BDirectory()
: BNode(),
BEntryList(),
fDirFd(BPrivate::Storage::NullFd)
fDirFd(-1)
{
}
@@ -38,7 +40,7 @@ BDirectory::BDirectory()
BDirectory::BDirectory(const BDirectory &dir)
: BNode(),
BEntryList(),
fDirFd(BPrivate::Storage::NullFd)
fDirFd(-1)
{
*this = dir;
}
@@ -51,7 +53,7 @@ BDirectory::BDirectory(const BDirectory &dir)
BDirectory::BDirectory(const entry_ref *ref)
: BNode(),
BEntryList(),
fDirFd(BPrivate::Storage::NullFd)
fDirFd(-1)
{
SetTo(ref);
}
@@ -64,7 +66,7 @@ BDirectory::BDirectory(const entry_ref *ref)
BDirectory::BDirectory(const node_ref *nref)
: BNode(),
BEntryList(),
fDirFd(BPrivate::Storage::NullFd)
fDirFd(-1)
{
SetTo(nref);
}
@@ -77,7 +79,7 @@ BDirectory::BDirectory(const node_ref *nref)
BDirectory::BDirectory(const BEntry *entry)
: BNode(),
BEntryList(),
fDirFd(BPrivate::Storage::NullFd)
fDirFd(-1)
{
SetTo(entry);
}
@@ -90,7 +92,7 @@ BDirectory::BDirectory(const BEntry *entry)
BDirectory::BDirectory(const char *path)
: BNode(),
BEntryList(),
fDirFd(BPrivate::Storage::NullFd)
fDirFd(-1)
{
SetTo(path);
}
@@ -105,7 +107,7 @@ BDirectory::BDirectory(const char *path)
BDirectory::BDirectory(const BDirectory *dir, const char *path)
: BNode(),
BEntryList(),
fDirFd(BPrivate::Storage::NullFd)
fDirFd(-1)
{
SetTo(dir, path);
}
@@ -139,23 +141,22 @@ BDirectory::~BDirectory()
- \c B_BUSY: A node was busy.
- \c B_FILE_ERROR: A general file error.
- \c B_NO_MORE_FDS: The application has run out of file descriptors.
\todo Currently implemented using BPrivate::Storage::entry_ref_to_path().
Reimplement!
*/
status_t
BDirectory::SetTo(const entry_ref *ref)
{
Unset();
char path[B_PATH_NAME_LENGTH];
status_t error = (ref ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
error = BPrivate::Storage::entry_ref_to_path(ref, path,
B_PATH_NAME_LENGTH);
// open node
status_t error = _SetTo(ref, true);
if (error != B_OK)
return error;
// open dir
fDirFd = _kern_open_dir_entry_ref(ref->device, ref->directory, ref->name);
if (fDirFd < 0) {
status_t error = fDirFd;
Unset();
return (fCStatus = error);
}
if (error == B_OK)
error = SetTo(path);
set_status(error);
return error;
return B_OK;
}
// SetTo
@@ -200,23 +201,26 @@ BDirectory::SetTo(const node_ref *nref)
- \c B_BUSY: A node was busy.
- \c B_FILE_ERROR: A general file error.
- \c B_NO_MORE_FDS: The application has run out of file descriptors.
\todo Implemented using SetTo(entry_ref*). Check, if necessary to
reimplement!
*/
status_t
BDirectory::SetTo(const BEntry *entry)
{
Unset();
entry_ref ref;
status_t error = (entry ? B_OK : B_BAD_VALUE);
if (error == B_OK && entry->InitCheck() != B_OK)
error = B_BAD_VALUE;
if (error == B_OK)
error = entry->GetRef(&ref);
if (error == B_OK)
error = SetTo(&ref);
set_status(error);
return error;
if (!entry) {
Unset();
return (fCStatus = B_BAD_VALUE);
}
// open node
status_t error = _SetTo(entry->fDirFd, entry->fName, true);
if (error != B_OK)
return error;
// open dir
fDirFd = _kern_open_dir(entry->fDirFd, entry->fName);
if (fDirFd < 0) {
status_t error = fDirFd;
Unset();
return (fCStatus = error);
}
return B_OK;
}
// SetTo
@@ -239,30 +243,18 @@ BDirectory::SetTo(const BEntry *entry)
status_t
BDirectory::SetTo(const char *path)
{
Unset();
status_t result = (path ? B_OK : B_BAD_VALUE);
BPrivate::Storage::FileDescriptor newDirFd = BPrivate::Storage::NullFd;
if (result == B_OK)
result = BPrivate::Storage::open_dir(path, newDirFd);
if (result == B_OK) {
// We have to take care that BNode doesn't stick to a symbolic link.
// open_dir() does always traverse those. Therefore we open the FD for
// BNode (without the O_NOTRAVERSE flag).
BPrivate::Storage::FileDescriptor fd = BPrivate::Storage::NullFd;
result = BPrivate::Storage::open(path, O_RDWR, fd, true);
if (result == B_OK) {
result = set_fd(fd);
if (result != B_OK)
BPrivate::Storage::close(fd);
}
if (result == B_OK)
fDirFd = newDirFd;
else
BPrivate::Storage::close_dir(newDirFd);
// open node
status_t error = _SetTo(-1, path, true);
if (error != B_OK)
return error;
// open dir
fDirFd = _kern_open_dir(-1, path);
if (fDirFd < 0) {
status_t error = fDirFd;
Unset();
return (fCStatus = error);
}
// finally set the BNode status
set_status(result);
return result;
return B_OK;
}
// SetTo
@@ -283,22 +275,26 @@ BDirectory::SetTo(const char *path)
- \c B_FILE_ERROR: A general file error.
- \c B_NO_MORE_FDS: The application has run out of file descriptors.
- \c B_NOT_A_DIRECTORY: \a path includes a non-directory.
\todo Implemented using SetTo(BEntry*). Check, if necessary to reimplement!
*/
status_t
BDirectory::SetTo(const BDirectory *dir, const char *path)
{
Unset();
status_t error = (dir && path ? B_OK : B_BAD_VALUE);
if (error == B_OK && BPrivate::Storage::is_absolute_path(path))
error = B_BAD_VALUE;
BEntry entry;
if (error == B_OK)
error = entry.SetTo(dir, path);
if (error == B_OK)
error = SetTo(&entry);
set_status(error);
return error;
if (!dir || !path || BPrivate::Storage::is_absolute_path(path)) {
Unset();
return (fCStatus = B_BAD_VALUE);
}
// open node
status_t error = _SetTo(dir->fDirFd, path, true);
if (error != B_OK)
return error;
// open dir
fDirFd = _kern_open_dir(dir->fDirFd, path);
if (fDirFd < 0) {
status_t error = fDirFd;
Unset();
return (fCStatus = error);
}
return B_OK;
}
// GetEntry
@@ -316,23 +312,15 @@ BDirectory::SetTo(const BDirectory *dir, const char *path)
- \c B_BUSY: A node was busy.
- \c B_FILE_ERROR: A general file error.
- \c B_NO_MORE_FDS: The application has run out of file descriptors.
\todo Implemented using BPrivate::Storage::dir_to_self_entry_ref(). Check, if
there is a better alternative.
*/
status_t
BDirectory::GetEntry(BEntry *entry) const
{
status_t error = (entry ? B_OK : B_BAD_VALUE);
if (entry)
entry->Unset();
if (error == B_OK && InitCheck() != B_OK)
error = B_NO_INIT;
entry_ref ref;
if (error == B_OK)
error = BPrivate::Storage::dir_to_self_entry_ref(fDirFd, &ref);
if (error == B_OK)
error = entry->SetTo(&ref);
return error;
if (!entry)
return B_BAD_VALUE;
if (InitCheck() != B_OK)
return B_NO_INIT;
return entry->SetTo(this, ".", false);
}
// IsRootDirectory
@@ -492,20 +480,13 @@ BDirectory::Contains(const BEntry *entry, int32 nodeFlags) const
// If the directory is initialized, get the canonical paths of the dir and
// the entry and check, if the latter is a prefix of the first one.
if (result && InitCheck() == B_OK) {
char dirPath[B_PATH_NAME_LENGTH];
char entryPath[B_PATH_NAME_LENGTH];
result = (BPrivate::Storage::dir_to_path(fDirFd, dirPath,
B_PATH_NAME_LENGTH) == B_OK);
entry_ref ref;
if (result)
result = (entry->GetRef(&ref) == B_OK);
if (result) {
result = (BPrivate::Storage::entry_ref_to_path(&ref, entryPath,
B_PATH_NAME_LENGTH)
== B_OK);
}
if (result)
result = !strncmp(dirPath, entryPath, strlen(dirPath));
BPath dirPath(this, ".", true);
BPath entryPath(entry);
if (dirPath.InitCheck() == B_OK && entryPath.InitCheck() == B_OK) {
result = !strncmp(dirPath.Path(), entryPath.Path(),
strlen(dirPath.Path()));
} else
result = false;
}
return result;
}
@@ -532,22 +513,17 @@ BDirectory::Contains(const BEntry *entry, int32 nodeFlags) const
status_t
BDirectory::GetStatFor(const char *path, struct stat *st) const
{
status_t error = (st ? B_OK : B_BAD_VALUE);
if (error == B_OK && InitCheck() != B_OK)
error = B_NO_INIT;
if (error == B_OK) {
if (path) {
if (strlen(path) == 0)
error = B_ENTRY_NOT_FOUND;
else {
BEntry entry(this, path);
error = entry.InitCheck();
if (error == B_OK)
error = entry.GetStat(st);
}
} else
error = GetStat(st);
}
if (!st)
return B_BAD_VALUE;
if (InitCheck() != B_OK)
return B_NO_INIT;
status_t error = B_OK;
if (path) {
if (strlen(path) == 0)
return B_ENTRY_NOT_FOUND;
error = _kern_read_stat(fDirFd, path, false, st, sizeof(struct stat));
} else
error = GetStat(st);
return error;
}
@@ -613,15 +589,18 @@ BDirectory::GetNextRef(entry_ref *ref)
BPrivate::Storage::LongDirEntry entry;
bool next = true;
while (error == B_OK && next) {
if (BPrivate::Storage::read_dir(fDirFd, &entry, sizeof(entry), 1) != 1)
if (GetNextDirents(&entry, sizeof(entry), 1) != 1) {
error = B_ENTRY_NOT_FOUND;
if (error == B_OK) {
} else {
next = (!strcmp(entry.d_name, ".")
|| !strcmp(entry.d_name, ".."));
}
}
if (error == B_OK)
*ref = entry_ref(entry.d_pdev, entry.d_pino, entry.d_name);
if (error == B_OK) {
ref->device = entry.d_pdev;
ref->directory = entry.d_pino;
error = ref->set_name(entry.d_name);
}
}
return error;
}
@@ -650,12 +629,11 @@ BDirectory::GetNextRef(entry_ref *ref)
int32
BDirectory::GetNextDirents(dirent *buf, size_t bufSize, int32 count)
{
int32 result = (buf ? B_OK : B_BAD_VALUE);
if (result == B_OK && InitCheck() != B_OK)
result = B_FILE_ERROR;
if (result == B_OK)
result = BPrivate::Storage::read_dir(fDirFd, buf, bufSize, count);
return result;
if (!buf)
return B_BAD_VALUE;
if (InitCheck() != B_OK)
return B_FILE_ERROR;
return _kern_read_dir(fDirFd, buf, bufSize, count);
}
// Rewind
@@ -673,12 +651,9 @@ BDirectory::GetNextDirents(dirent *buf, size_t bufSize, int32 count)
status_t
BDirectory::Rewind()
{
status_t error = B_OK;
if (error == B_OK && InitCheck() != B_OK)
error = B_FILE_ERROR;
if (error == B_OK)
error = BPrivate::Storage::rewind_dir(fDirFd);
return error;
if (InitCheck() != B_OK)
return B_FILE_ERROR;
return _kern_rewind_dir(fDirFd);
}
// CountEntries
@@ -700,19 +675,15 @@ int32
BDirectory::CountEntries()
{
status_t error = Rewind();
if (error != B_OK)
return error;
int32 count = 0;
if (error == B_OK) {
BPrivate::Storage::LongDirEntry entry;
while (error == B_OK) {
if (BPrivate::Storage::read_dir(fDirFd, &entry, sizeof(entry), 1) != 1)
error = B_ENTRY_NOT_FOUND;
if (error == B_OK
&& strcmp(entry.d_name, ".") && strcmp(entry.d_name, "..")) {
count++;
}
}
if (error == B_ENTRY_NOT_FOUND)
error = B_OK;
BPrivate::Storage::LongDirEntry entry;
while (error == B_OK) {
if (GetNextDirents(&entry, sizeof(entry), 1) != 1)
break;
if (strcmp(entry.d_name, ".") != 0 && strcmp(entry.d_name, "..") != 0)
count++;
}
Rewind();
return (error == B_OK ? count : error);
@@ -740,24 +711,20 @@ BDirectory::CountEntries()
status_t
BDirectory::CreateDirectory(const char *path, BDirectory *dir)
{
status_t error = (path ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
// get the actual (absolute) path using BEntry's help
BEntry entry;
if (InitCheck() == B_OK && !BPrivate::Storage::is_absolute_path(path))
entry.SetTo(this, path);
else
entry.SetTo(path);
error = entry.InitCheck();
BPath realPath;
if (error == B_OK)
error = entry.GetPath(&realPath);
if (error == B_OK)
error = BPrivate::Storage::create_dir(realPath.Path());
if (error == B_OK && dir)
error = dir->SetTo(realPath.Path());
}
return error;
if (!path)
return B_BAD_VALUE;
// create the dir
status_t error = _kern_create_dir(fDirFd, path,
S_IRWXU | S_IRWXG | S_IRWXU);
if (error != B_OK)
return error;
if (!dir)
return B_OK;
// init the supplied BDirectory
if (InitCheck() != B_OK || BPrivate::Storage::is_absolute_path(path))
return dir->SetTo(path);
else
return dir->SetTo(this, path);
}
// CreateFile
@@ -790,20 +757,20 @@ BDirectory::CreateDirectory(const char *path, BDirectory *dir)
status_t
BDirectory::CreateFile(const char *path, BFile *file, bool failIfExists)
{
status_t error (path ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
// Let BFile do the dirty job.
uint32 openMode = B_READ_WRITE | B_CREATE_FILE
| (failIfExists ? B_FAIL_IF_EXISTS : 0);
BFile tmpFile;
BFile *realFile = (file ? file : &tmpFile);
if (InitCheck() == B_OK && !BPrivate::Storage::is_absolute_path(path))
error = realFile->SetTo(this, path, openMode);
else
error = realFile->SetTo(path, openMode);
if (error != B_OK)
realFile->Unset();
}
if (!path)
return B_BAD_VALUE;
// Let BFile do the dirty job.
uint32 openMode = B_READ_WRITE | B_CREATE_FILE
| (failIfExists ? B_FAIL_IF_EXISTS : 0);
BFile tmpFile;
BFile *realFile = (file ? file : &tmpFile);
status_t error = B_OK;
if (InitCheck() == B_OK && !BPrivate::Storage::is_absolute_path(path))
error = realFile->SetTo(this, path, openMode);
else
error = realFile->SetTo(path, openMode);
if (error != B_OK && file) // mimic R5 behavior
file->Unset();
return error;
}
@@ -831,29 +798,25 @@ status_t
BDirectory::CreateSymLink(const char *path, const char *linkToPath,
BSymLink *link)
{
status_t error = (path && linkToPath ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
// get the actual (absolute) path using BEntry's help
BEntry entry;
if (InitCheck() == B_OK && !BPrivate::Storage::is_absolute_path(path))
entry.SetTo(this, path);
else
entry.SetTo(path);
error = entry.InitCheck();
BPath realPath;
if (error == B_OK)
error = entry.GetPath(&realPath);
if (error == B_OK)
error = BPrivate::Storage::create_link(realPath.Path(), linkToPath);
if (error == B_OK && link)
error = link->SetTo(realPath.Path());
}
return error;
if (!path || !linkToPath)
return B_BAD_VALUE;
// create the symlink
status_t error = _kern_create_symlink(fDirFd, path, linkToPath,
S_IRWXU | S_IRWXG | S_IRWXU);
if (error != B_OK)
return error;
if (!link)
return B_OK;
// init the supplied BSymLink
if (InitCheck() != B_OK || BPrivate::Storage::is_absolute_path(path))
return link->SetTo(path);
else
return link->SetTo(this, path);
}
// =
//! Assigns another BDirectory to this BDirectory.
/*! If the other BDirectory is uninitialized, this one will be too. Otherwise
/*! If the other BDirectory is uninitialized, this one wi'll be too. Otherwise
it will refer to the same directory, unless an error occurs.
\param dir the original BDirectory
\return a reference to this BDirectory
@@ -863,16 +826,8 @@ BDirectory::operator=(const BDirectory &dir)
{
if (&dir != this) { // no need to assign us to ourselves
Unset();
if (dir.InitCheck() == B_OK) {
*((BNode*)this) = dir;
if (InitCheck() == B_OK) {
// duplicate the file descriptor
status_t status = BPrivate::Storage::dup_dir(dir.fDirFd, fDirFd);
if (status != B_OK)
Unset();
set_status(status);
}
}
if (dir.InitCheck() == B_OK)
SetTo(&dir, ".");
}
return *this;
}
@@ -891,9 +846,9 @@ void BDirectory::_ErectorDirectory6() {}
void
BDirectory::close_fd()
{
if (fDirFd != BPrivate::Storage::NullFd) {
BPrivate::Storage::close_dir(fDirFd);
fDirFd = BPrivate::Storage::NullFd;
if (fDirFd >= 0) {
_kern_close(fDirFd);
fDirFd = -1;
}
BNode::close_fd();
}
@@ -903,7 +858,7 @@ BDirectory::close_fd()
directly.
\return the file descriptor, or -1, if not properly initialized.
*/
BPrivate::Storage::FileDescriptor
int
BDirectory::get_fd() const
{
return fDirFd;
@@ -934,46 +889,50 @@ BDirectory::get_fd() const
status_t
create_directory(const char *path, mode_t mode)
{
if (!path)
return B_BAD_VALUE;
// That's the strategy: We start with the first component of the supplied
// path, create a BPath object from it and successively add the following
// components. Each time we get a new path, we check, if the entry it
// refers to exists and is a directory. If it doesn't exist, then we try
// refers to exists and is a directory. If it doesn't exist, we try
// to create it. This goes on, until we're done with the input path or
// an error occurs.
status_t error = (path ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
BPath dirPath;
char *component;
int32 nextComponent;
do {
// get the next path component
error = BPrivate::Storage::parse_first_path_component(path, component,
nextComponent);
if (error == B_OK) {
// append it to the BPath
if (dirPath.InitCheck() == B_NO_INIT) // first component
error = dirPath.SetTo(component);
else
error = dirPath.Append(component);
delete[] component;
path += nextComponent;
// create a BEntry from the BPath
BEntry entry;
if (error == B_OK)
error = entry.SetTo(dirPath.Path(), true);
// check, if it exists
if (error == B_OK) {
if (entry.Exists()) {
// yep, it exists
if (!entry.IsDirectory()) // but is no directory
error = B_NOT_A_DIRECTORY;
} else // it doesn't exists -- create it
error = BPrivate::Storage::create_dir(dirPath.Path(), mode);
}
}
} while (error == B_OK && nextComponent != 0);
}
return error;
BPath dirPath;
char *component;
int32 nextComponent;
do {
// get the next path component
status_t error = BPrivate::Storage::parse_first_path_component(path,
component, nextComponent);
if (error != B_OK)
return error;
// append it to the BPath
if (dirPath.InitCheck() == B_NO_INIT) // first component
error = dirPath.SetTo(component);
else
error = dirPath.Append(component);
delete[] component;
if (error != B_OK)
return error;
path += nextComponent;
// create a BEntry from the BPath
BEntry entry;
error = entry.SetTo(dirPath.Path(), true);
if (error != B_OK)
return error;
// check, if it exists
if (entry.Exists()) {
// yep, it exists
if (!entry.IsDirectory()) // but is no directory
return B_NOT_A_DIRECTORY;
} else {
// it doesn't exist -- create it
error = _kern_create_dir(-1, dirPath.Path(), mode);
if (error != B_OK)
return error;
}
} while (nextComponent != 0);
return B_OK;
}
@@ -981,5 +940,3 @@ create_directory(const char *path, mode_t mode)
}; // namespace OpenBeOS
#endif
+290 -347
View File
@@ -10,14 +10,17 @@
#include <Entry.h>
#include <new>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <Directory.h>
#include <Path.h>
#include <SymLink.h>
#include "kernel_interface.h"
#include "storage_support.h"
#include <syscalls.h>
#ifdef USE_OPENBEOS_NAMESPACE
using namespace OpenBeOS;
#endif
@@ -97,8 +100,7 @@ entry_ref::entry_ref(const entry_ref &ref)
//! Destroys the object and frees the storage allocated for the leaf name, if necessary.
entry_ref::~entry_ref()
{
if (name != NULL)
delete [] name;
free(name);
}
/*! \brief Set the entry_ref's leaf name, freeing the storage allocated for any previous
@@ -109,17 +111,14 @@ entry_ref::~entry_ref()
*/
status_t entry_ref::set_name(const char *name)
{
if (this->name != NULL) {
delete [] this->name;
}
free(this->name);
if (name == NULL) {
this->name = NULL;
} else {
this->name = new(nothrow) char[strlen(name)+1];
if (this->name == NULL)
this->name = strdup(name);
if (!this->name)
return B_NO_MEMORY;
strcpy(this->name, name);
}
return B_OK;
@@ -220,7 +219,7 @@ entry_ref::operator=(const entry_ref &ref)
- operator=(const BEntry&)
*/
BEntry::BEntry()
: fDirFd(BPrivate::Storage::NullFd),
: fDirFd(-1),
fName(NULL),
fCStatus(B_NO_INIT)
{
@@ -237,7 +236,7 @@ BEntry::BEntry()
*/
BEntry::BEntry(const BDirectory *dir, const char *path, bool traverse)
: fDirFd(BPrivate::Storage::NullFd),
: fDirFd(-1),
fName(NULL),
fCStatus(B_NO_INIT)
{
@@ -255,7 +254,7 @@ BEntry::BEntry(const BDirectory *dir, const char *path, bool traverse)
*/
BEntry::BEntry(const entry_ref *ref, bool traverse)
: fDirFd(BPrivate::Storage::NullFd),
: fDirFd(-1),
fName(NULL),
fCStatus(B_NO_INIT)
{
@@ -274,7 +273,7 @@ BEntry::BEntry(const entry_ref *ref, bool traverse)
*/
BEntry::BEntry(const char *path, bool traverse)
: fDirFd(BPrivate::Storage::NullFd),
: fDirFd(-1),
fName(NULL),
fCStatus(B_NO_INIT)
{
@@ -286,7 +285,7 @@ BEntry::BEntry(const char *path, bool traverse)
\see operator=(const BEntry&)
*/
BEntry::BEntry(const BEntry &entry)
: fDirFd(BPrivate::Storage::NullFd),
: fDirFd(-1),
fName(NULL),
fCStatus(B_NO_INIT)
{
@@ -321,12 +320,9 @@ BEntry::InitCheck() const
bool
BEntry::Exists() const
{
if (fCStatus != B_OK)
return false;
// Attempt to find the entry in our current directory
BPrivate::Storage::LongDirEntry entry;
return BPrivate::Storage::find_dir(fDirFd, fName, &entry, sizeof(entry)) == B_OK;
// just stat the beast
struct stat st;
return (GetStat(&st) == B_OK);
}
/*! \brief Fills in a stat structure for the entry. The information is copied into
@@ -345,13 +341,7 @@ BEntry::GetStat(struct stat *result) const
{
if (fCStatus != B_OK)
return B_NO_INIT;
entry_ref ref;
status_t status = GetRef(&ref);
if (status != B_OK)
return status;
return BPrivate::Storage::get_stat(ref, result);
return _kern_read_stat(fDirFd, fName, false, result, sizeof(struct stat));
}
/*! \brief Reinitializes the BEntry to the path or directory path combination,
@@ -360,45 +350,30 @@ BEntry::GetStat(struct stat *result) const
\return
- \c B_OK - Success
- "error code" - Failure
\todo Reimplement! Concatenating dir and leaf to an absolute path prevents
the user from accessing entries with longer absolute path.
R5 handles this without problems.
*/
status_t
BEntry::SetTo(const BDirectory *dir, const char *path, bool traverse)
{
Unset();
if (dir == NULL)
// check params
if (!dir)
return (fCStatus = B_BAD_VALUE);
if (path && path[0] == '\0') // R5 behaviour
path = NULL;
fCStatus = B_OK;
if (BPrivate::Storage::is_absolute_path(path)) {
SetTo(path, traverse);
} else {
if (dir->InitCheck() != B_OK)
fCStatus = B_BAD_VALUE;
// get the dir's path
char rootPath[B_PATH_NAME_LENGTH];
if (fCStatus == B_OK) {
fCStatus = BPrivate::Storage::dir_to_path(dir->get_fd(), rootPath,
B_PATH_NAME_LENGTH);
}
// Concatenate our two path strings together
if (fCStatus == B_OK && path) {
// The concatenated strings must fit into our buffer.
if (strlen(rootPath) + strlen(path) + 2 > B_PATH_NAME_LENGTH)
fCStatus = B_NAME_TOO_LONG;
else {
strcat(rootPath, "/");
strcat(rootPath, path);
}
}
// set the resulting path
if (fCStatus == B_OK)
SetTo(rootPath, traverse);
}
return fCStatus;
// if path is absolute, let the path-only SetTo() do the job
if (BPrivate::Storage::is_absolute_path(path))
return SetTo(path, traverse);
Unset();
if (dir->InitCheck() != B_OK)
fCStatus = B_BAD_VALUE;
// dup() the dir's FD and let set() do the rest
int dirFD = _kern_dup(dir->get_fd());
if (dirFD < 0)
return (fCStatus = dirFD);
return (fCStatus = set(dirFD, path, traverse));
}
/*! \brief Reinitializes the BEntry to the entry_ref, resolving symlinks if
@@ -407,22 +382,19 @@ BEntry::SetTo(const BDirectory *dir, const char *path, bool traverse)
\return
- \c B_OK - Success
- "error code" - Failure
\todo Implemented using entry_ref_to_path(). Reimplement!
*/
status_t
BEntry::SetTo(const entry_ref *ref, bool traverse)
{
Unset();
if (ref == NULL) {
if (ref == NULL)
return (fCStatus = B_BAD_VALUE);
}
char path[B_PATH_NAME_LENGTH];
fCStatus = BPrivate::Storage::entry_ref_to_path(ref, path,
B_PATH_NAME_LENGTH);
return (fCStatus == B_OK) ? SetTo(path, traverse) : fCStatus ;
// open the directory and let set() do the rest
int dirFD = _kern_open_dir_entry_ref(ref->device, ref->directory, NULL);
if (dirFD < 0)
return (fCStatus = dirFD);
return (fCStatus = set(dirFD, ref->name, traverse));
}
/*! \brief Reinitializes the BEntry object to the path, resolving symlinks if
@@ -431,35 +403,15 @@ BEntry::SetTo(const entry_ref *ref, bool traverse)
\return
- \c B_OK - Success
- "error code" - Failure
*/
status_t
BEntry::SetTo(const char *path, bool traverse)
{
Unset();
// check the argument
fCStatus = (path ? B_OK : B_BAD_VALUE);
if (fCStatus == B_OK)
fCStatus = BPrivate::Storage::check_path_name(path);
if (fCStatus == B_OK) {
// Get the path and leaf portions of the given path
char *pathStr, *leafStr;
pathStr = leafStr = NULL;
fCStatus = BPrivate::Storage::split_path(path, pathStr, leafStr);
if (fCStatus == B_OK) {
// Open the directory
BPrivate::Storage::FileDescriptor dirFd;
fCStatus = BPrivate::Storage::open_dir(pathStr, dirFd);
if (fCStatus == B_OK) {
fCStatus = set(dirFd, leafStr, traverse);
if (fCStatus != B_OK)
BPrivate::Storage::close_dir(dirFd);
}
}
delete [] pathStr;
delete [] leafStr;
}
return fCStatus;
if (!path)
return (fCStatus = B_BAD_VALUE);
return (fCStatus = set(-1, path, traverse));
}
/*! \brief Reinitializes the BEntry to an uninitialized BEntry object */
@@ -467,16 +419,15 @@ void
BEntry::Unset()
{
// Close the directory
if (fDirFd != BPrivate::Storage::NullFd) {
BPrivate::Storage::close_dir(fDirFd);
if (fDirFd >= 0) {
_kern_close(fDirFd);
// BPrivate::Storage::close_dir(fDirFd);
}
// Free our leaf name
if (fName != NULL) {
delete [] fName;
}
free(fName);
fDirFd = BPrivate::Storage::NullFd;
fDirFd = -1;
fName = NULL;
fCStatus = B_NO_INIT;
}
@@ -499,7 +450,8 @@ BEntry::GetRef(entry_ref *ref) const
return B_BAD_VALUE;
struct stat st;
status_t error = BPrivate::Storage::get_stat(fDirFd, &st);
status_t error = _kern_read_stat(fDirFd, NULL, false, &st,
sizeof(struct stat));
if (error == B_OK) {
ref->device = st.st_dev;
ref->directory = st.st_ino;
@@ -563,44 +515,30 @@ BEntry::GetPath(BPath *path) const
- \c B_OK - Success
- \c B_ENTRY_NOT_FOUND - Attempted to get the parent of the root directory \c "/"
- "error code" - Failure
*/
status_t BEntry::GetParent(BEntry *entry) const
{
// check parameter and initialization
if (fCStatus != B_OK)
return B_NO_INIT;
if (entry == NULL)
return B_BAD_VALUE;
// Convert ourselves to a entry_ref and change the
// leaf name to "."
entry_ref ref;
status_t status;
status = GetRef(&ref);
if (status == B_OK) {
// Verify we aren't an entry representing "/"
status = BPrivate::Storage::entry_ref_is_root_dir(&ref) ? (status_t)B_ENTRY_NOT_FOUND
: (status_t)B_OK ;
if (status == B_OK) {
status = ref.set_name(".");
if (status == B_OK) {
entry->SetTo(&ref);
return entry->InitCheck();
}
}
}
// If we get this far, an error occured, so we Unset() the
// argument as dictated by the BeBook
// check whether we are the root directory
// It is sufficient to check whether our leaf name is ".".
if (strcmp(fName, ".") == 0)
return B_ENTRY_NOT_FOUND;
// open the parent directory
char leafName[B_FILE_NAME_LENGTH];
int parentFD = _kern_open_parent_dir(fDirFd, leafName, B_FILE_NAME_LENGTH);
if (parentFD < 0)
return parentFD;
// init the entry
entry->Unset();
return status;
entry->fDirFd = parentFD;
entry->fCStatus = entry->set_name(leafName);
if (entry->fCStatus != B_OK)
entry->Unset();
return entry->fCStatus;
}
/*! \brief Gets the parent of the BEntry as a BDirectory.
@@ -612,40 +550,32 @@ status_t BEntry::GetParent(BEntry *entry) const
- \c B_OK - Success
- \c B_ENTRY_NOT_FOUND - Attempted to get the parent of the root directory \c "/"
- "error code" - Failure
*/
status_t
BEntry::GetParent(BDirectory *dir) const
{
// check initialization and parameter
if (fCStatus != B_OK)
return B_NO_INIT;
if (dir == NULL)
return B_BAD_VALUE;
entry_ref ref;
status_t status;
status = GetRef(&ref);
if (status == B_OK) {
// Verify we aren't an entry representing "/"
status = BPrivate::Storage::entry_ref_is_root_dir(&ref) ? (status_t)B_ENTRY_NOT_FOUND : (status_t)B_OK ;
if (status == B_OK) {
// Now point the entry_ref to the parent directory (instead of ourselves)
status = ref.set_name(".");
if (status == B_OK) {
dir->SetTo(&ref);
return dir->InitCheck();
}
}
}
// If we get this far, an error occured, so we Unset() the
// argument as dictated by the BeBook
dir->Unset();
return status;
// check whether we are the root directory
// It is sufficient to check whether our leaf name is ".".
if (strcmp(fName, ".") == 0)
return B_ENTRY_NOT_FOUND;
// get a node ref for the directory and init it
struct stat st;
status_t error = _kern_read_stat(fDirFd, NULL, false, &st,
sizeof(struct stat));
if (error != B_OK)
return error;
node_ref ref;
ref.device = st.st_dev;
ref.node = st.st_ino;
return dir->SetTo(&ref);
// TODO: This can be optimized: We already have a FD for the directory,
// so we could dup() it and set it on the directory. We just need a private
// API for being able to do that.
}
/*! \brief Gets the name of the entry's leaf.
@@ -657,7 +587,6 @@ BEntry::GetParent(BDirectory *dir) const
\return
- \c B_OK - Success
- "error code" - Failure
*/
status_t
BEntry::GetName(char *buffer) const
@@ -696,47 +625,26 @@ BEntry::GetName(char *buffer) const
status_t
BEntry::Rename(const char *path, bool clobber)
{
// check parameter and initialization
if (path == NULL)
return B_BAD_VALUE;
if (fCStatus != B_OK)
return B_NO_INIT;
status_t status = B_OK;
// Convert the given path to an absolute path, if it isn't already.
char fullPath[B_PATH_NAME_LENGTH];
if (!BPrivate::Storage::is_absolute_path(path)) {
// Convert our directory to an absolute pathname
status = BPrivate::Storage::dir_to_path(fDirFd, fullPath,
B_PATH_NAME_LENGTH);
if (status == B_OK) {
// Concatenate our pathname to it
strcat(fullPath, "/");
strcat(fullPath, path);
path = fullPath;
}
// get an entry representing the target location
BEntry target;
status_t error;
if (BPrivate::Storage::is_absolute_path(path)) {
error = target.SetTo(path);
} else {
int dirFD = _kern_dup(fDirFd);
if (dirFD < 0)
return dirFD;
// init the entry
error = target.fCStatus = target.set(dirFD, path, false);
}
// Check, whether the file does already exist, if clobber is false.
if (status == B_OK && !clobber) {
// We're not supposed to kill an already-existing file,
// so we'll try to figure out if it exists by stat()ing it.
BPrivate::Storage::Stat s;
status = BPrivate::Storage::get_stat(path, &s);
if (status == B_OK)
status = B_FILE_EXISTS;
else if (status == B_ENTRY_NOT_FOUND)
status = B_OK;
}
// Turn ourselves into a pathname, rename ourselves
if (status == B_OK) {
BPath oldPath;
status = GetPath(&oldPath);
if (status == B_OK) {
status = BPrivate::Storage::rename(oldPath.Path(), path);
if (status == B_OK)
status = SetTo(path, false);
}
}
return status;
if (error != B_OK)
return error;
return _Rename(target, clobber);
}
/*! \brief Moves the BEntry to directory or directory+path combination, replacing an existing entry if clobber is true.
@@ -755,41 +663,26 @@ BEntry::Rename(const char *path, bool clobber)
- \c B_ENTRY_EXISTS - The new location is already taken and \c clobber was \c false
- \c B_ENTRY_NOT_FOUND - Attempted to move an abstract entry
- "error code" - Failure
*/
status_t
BEntry::MoveTo(BDirectory *dir, const char *path, bool clobber)
{
// check parameters and initialization
if (fCStatus != B_OK)
return B_NO_INIT;
else if (dir == NULL)
if (dir == NULL)
return B_BAD_VALUE;
else if (dir->InitCheck() != B_OK)
if (dir->InitCheck() != B_OK)
return B_BAD_VALUE;
// NULL path simply means move without renaming
if (path == NULL)
path = fName;
status_t status = B_OK;
// Determine the absolute path of the target entry.
if (!BPrivate::Storage::is_absolute_path(path)) {
// Convert our directory to an absolute pathname
char fullPath[B_PATH_NAME_LENGTH];
status = BPrivate::Storage::dir_to_path(dir->get_fd(), fullPath,
B_PATH_NAME_LENGTH);
// Concatenate our pathname to it
if (status == B_OK) {
strcat(fullPath, "/");
strcat(fullPath, path);
path = fullPath;
}
}
// Now let rename do the dirty work
if (status == B_OK)
status = Rename(path, clobber);
return status;
// get an entry representing the target location
BEntry target;
status_t error = target.SetTo(dir, path);
if (error != B_OK)
return error;
return _Rename(target, clobber);
}
/*! \brief Removes the entry from the file system.
@@ -802,22 +695,13 @@ BEntry::MoveTo(BDirectory *dir, const char *path, bool clobber)
\return
- B_OK - Success
- "error code" - Failure
*/
status_t
BEntry::Remove()
{
if (fCStatus != B_OK)
return B_NO_INIT;
BPath path;
status_t status;
status = GetPath(&path);
if (status != B_OK)
return status;
return BPrivate::Storage::remove(path.Path());
return _kern_unlink(fDirFd, fName);
}
@@ -827,7 +711,6 @@ BEntry::Remove()
\return
- true - Both BEntry objects refer to the same entry or they are both uninitialzed
- false - The BEntry objects refer to different entries
*/
bool
BEntry::operator==(const BEntry &item) const
@@ -858,7 +741,6 @@ BEntry::operator==(const BEntry &item) const
\return
- true - The BEntry objects refer to different entries
- false - Both BEntry objects refer to the same entry or they are both uninitialzed
*/
bool
BEntry::operator!=(const BEntry &item) const
@@ -870,7 +752,6 @@ BEntry::operator!=(const BEntry &item) const
\return
- A reference to the copy
*/
BEntry&
BEntry::operator=(const BEntry &item)
@@ -880,10 +761,14 @@ BEntry::operator=(const BEntry &item)
Unset();
if (item.fCStatus == B_OK) {
fCStatus = BPrivate::Storage::dup_dir(item.fDirFd, fDirFd);
if (fCStatus == B_OK) {
fDirFd = _kern_dup(item.fDirFd);
if (fDirFd >= 0)
fCStatus = set_name(item.fName);
}
else
fCStatus = fDirFd;
if (fCStatus != B_OK)
Unset();
}
return *this;
@@ -909,121 +794,146 @@ BEntry::set_stat(struct stat &st, uint32 what)
{
if (fCStatus != B_OK)
return B_FILE_ERROR;
BPath path;
status_t status;
status = GetPath(&path);
if (status != B_OK)
return status;
return BPrivate::Storage::set_stat(path.Path(), st, what);
return _kern_write_stat(fDirFd, fName, false, &st, sizeof(struct stat),
what);
}
/*! Sets the Entry to point to the entry named by \c leaf in the given directory. If \c traverse
is \c true and the given entry is a symlink, the object is recursively set to point to the
entry pointed to by the symlink.
/*! Sets the Entry to point to the entry specified by the path \a path relative
to the given directory. If \a traverse is \c true and the given entry is a
symlink, the object is recursively set to point to the entry pointed to by
the symlink.
If \a path is an absolute path, \a dirFD is ignored.
If \a dirFD is -1, path is considered relative to the current directory
(unless it is an absolute path, that is).
\c leaf <b>must</b> be a leaf-name only (i.e. it must contain no '/' characters),
otherwise this function will return \c B_BAD_VALUE. If \c B_OK is returned,
the caller is no longer responsible for closing the directory file descriptor
with a call to BPrivate::Storage::close_dir.
\param dirFd File descriptor of the directory in which the entry resides
\param leaf Pointer to a string containing the entry's leaf name
\param traverse If \c true and the given entry is a symlink, the object is recursively
set to point to the entry linked to by the symlink.
The ownership of the file descriptor \a dirFD is transferred to the
function, regardless of whether it succeeds or fails. The caller must not
close the FD afterwards.
\param dirFD File descriptor of a directory relative to which path is to
be considered. May be -1, when the current directory shall be
considered.
\param path Pointer to a path relative to the given directory.
\param traverse If \c true and the given entry is a symlink, the object is
recursively set to point to the entry linked to by the symlink.
\return
- B_OK - Success
- "error code" - Failure
*/
status_t
BEntry::set(BPrivate::Storage::FileDescriptor dirFd, const char *leaf, bool traverse)
BEntry::set(int dirFD, const char *path, bool traverse)
{
// Verify that path is valid
status_t error = BPrivate::Storage::check_entry_name(leaf);
bool requireConcrete = false;
FDCloser fdCloser(dirFD);
char tmpPath[B_PATH_NAME_LENGTH];
char leafName[B_FILE_NAME_LENGTH];
int32 linkLimit = B_MAX_SYMLINKS;
while (true) {
if (!path || strcmp(path, ".") == 0) {
// "."
// if no dir FD is supplied, we need to open the current directory
// first
if (dirFD < 0) {
dirFD = _kern_open_dir(-1, ".");
if (dirFD < 0)
return dirFD;
fdCloser.SetTo(dirFD);
}
// get the parent directory
int parentFD = _kern_open_parent_dir(dirFD, leafName,
B_FILE_NAME_LENGTH);
if (parentFD < 0)
return parentFD;
dirFD = parentFD;
fdCloser.SetTo(dirFD);
break;
} else if (strcmp(path, "..") == 0) {
// ".."
// open the parent directory
int parentFD = _kern_open_dir(dirFD, "..");
if (parentFD < 0)
return parentFD;
dirFD = parentFD;
fdCloser.SetTo(dirFD);
// get the parent's parent directory
parentFD = _kern_open_parent_dir(dirFD, leafName,
B_FILE_NAME_LENGTH);
if (parentFD < 0)
return parentFD;
dirFD = parentFD;
fdCloser.SetTo(dirFD);
break;
} else {
// an ordinary path; analyze it
char dirPath[B_PATH_NAME_LENGTH];
status_t error = BPrivate::Storage::parse_path(path, dirPath,
leafName);
if (error != B_OK)
return error;
// special case: root directory ("/")
if (leafName[0] == '\0' && dirPath[0] == '/')
strcpy(leafName, ".");
if (leafName[0] == '\0') {
// the supplied path is already a leaf
error = BPrivate::Storage::check_entry_name(dirPath);
if (error != B_OK)
return error;
strcpy(leafName, dirPath);
// if no directory was given, we need to open the current dir
// now
if (dirFD < 0) {
char *cwd = getcwd(tmpPath, B_PATH_NAME_LENGTH);
if (!cwd)
return B_ERROR;
dirFD = _kern_open_dir(-1, cwd);
if (dirFD < 0)
return dirFD;
fdCloser.SetTo(dirFD);
}
} else {
int parentFD = _kern_open_dir(dirFD, dirPath);
if (parentFD < 0)
return parentFD;
dirFD = parentFD;
fdCloser.SetTo(dirFD);
}
// traverse symlinks, if desired
if (!traverse)
break;
struct stat st;
error = _kern_read_stat(dirFD, leafName, false, &st,
sizeof(struct stat));
if (error == B_ENTRY_NOT_FOUND && !requireConcrete) {
// that's fine -- the entry is abstract and was not target of
// a symlink we resolved
break;
}
if (error != B_OK)
return error;
// the entry is concrete
if (!S_ISLNK(st.st_mode))
break;
requireConcrete = true;
// we need to traverse the symlink
if (--linkLimit < 0)
return B_LINK_LIMIT;
ssize_t readBytes = _kern_read_link(dirFD, leafName, tmpPath,
B_PATH_NAME_LENGTH);
if (readBytes < 0)
return readBytes;
path = tmpPath;
// next round...
}
}
// set the result
status_t error = set_name(leafName);
if (error != B_OK)
return error;
// Check whether the entry is abstract or concrete.
// We try traversing concrete entries only.
BPrivate::Storage::LongDirEntry dirEntry;
bool isConcrete = (BPrivate::Storage::find_dir(dirFd, leaf, &dirEntry,
sizeof(dirEntry)) == B_OK);
if (traverse && isConcrete) {
// Though the link traversing strategy is iterative, we introduce
// some recursion, since we are using BSymLink, which may be
// (currently is) implemented using BEntry. Nevertheless this is
// harmless, because BSymLink does, of course, not want to traverse
// the link.
// convert the dir FD into a BPath
entry_ref ref;
error = BPrivate::Storage::dir_to_self_entry_ref(dirFd, &ref);
char dirPathname[B_PATH_NAME_LENGTH];
if (error == B_OK) {
error = BPrivate::Storage::entry_ref_to_path(&ref, dirPathname,
sizeof(dirPathname));
}
BPath dirPath(dirPathname);
if (error == B_OK)
error = dirPath.InitCheck();
BPath linkPath;
if (error == B_OK)
linkPath.SetTo(dirPath.Path(), leaf);
if (error == B_OK) {
// Here comes the link traversing loop: A BSymLink is created
// from the dir and the leaf name, the link target is determined,
// the target's dir and leaf name are got and so on.
bool isLink = true;
int32 linkLimit = B_MAX_SYMLINKS;
while (error == B_OK && isLink && linkLimit > 0) {
linkLimit--;
// that's OK with any node, even if it's not a symlink
BSymLink link(linkPath.Path());
error = link.InitCheck();
if (error == B_OK) {
isLink = link.IsSymLink();
if (isLink) {
// get the path to the link target
ssize_t linkSize = link.MakeLinkedPath(dirPath.Path(),
&linkPath);
if (linkSize < 0)
error = linkSize;
// get the link target's dir path
if (error == B_OK)
error = linkPath.GetParent(&dirPath);
}
}
}
// set the new values
if (error == B_OK) {
if (isLink)
error = B_LINK_LIMIT;
else {
BPrivate::Storage::FileDescriptor newDirFd = BPrivate::Storage::NullFd;
error = BPrivate::Storage::open_dir(dirPath.Path(), newDirFd);
if (error == B_OK) {
// If we are successful, we are responsible for the
// supplied FD. Thus we close it.
BPrivate::Storage::close_dir(dirFd);
dirFd = BPrivate::Storage::NullFd;
fDirFd = newDirFd;
// handle "/", which has a "" Leaf()
if (linkPath == "/")
set_name(".");
else
set_name(linkPath.Leaf());
}
}
}
} // getting the dir path for the FD
} else {
// don't traverse: either the flag is not set or the entry is abstract
fDirFd = dirFd;
set_name(leaf);
}
return error;
fdCloser.Detach();
fDirFd = dirFD;
return B_OK;
}
/*! \brief Handles string allocation, deallocation, and copying for the entry's leaf name.
@@ -1038,19 +948,51 @@ BEntry::set_name(const char *name)
if (name == NULL)
return B_BAD_VALUE;
if (fName != NULL) {
delete [] fName;
}
free(fName);
fName = new(nothrow) char[strlen(name)+1];
if (fName == NULL)
fName = strdup(name);
if (!fName)
return B_NO_MEMORY;
strcpy(fName, name);
return B_OK;
}
// _Rename
/*! \brief Renames the entry referred to by this object to the location
specified by \a target.
If an entry exists at the target location, the method fails, unless
\a clobber is \c true, in which case that entry is overwritten (doesn't
work for non-empty directories, though).
If the operation was successful, this entry is made a clone of the
supplied one and the supplied one is uninitialized.
\param target The entry specifying the target location.
\param clobber If \c true, the an entry existing at the target location
will be overwritten.
\return \c B_OK, if everything went fine, another error code otherwise.
*/
status_t
BEntry::_Rename(BEntry& target, bool clobber)
{
// check, if there's an entry in the way
if (!clobber && target.Exists())
return B_FILE_EXISTS;
// rename
status_t error = _kern_rename(fDirFd, fName, target.fDirFd, target.fName);
if (error == B_OK) {
Unset();
fCStatus = target.fCStatus;
fDirFd = target.fDirFd;
fName = target.fName;
target.fCStatus = B_NO_INIT;
target.fDirFd = -1;
target.fName = NULL;
}
return error;
}
/*! Debugging function, dumps the given entry to stdout. This function is not part of
the R5 implementation, and thus calls to it will mean you can't link with the
@@ -1071,11 +1013,12 @@ BEntry::Dump(const char *name)
printf("fCStatus == %ld\n", fCStatus);
BPrivate::Storage::LongDirEntry entry;
struct stat st;
if (fDirFd != -1
&& BPrivate::Storage::find_dir(fDirFd, ".", &entry, sizeof(entry)) == B_OK) {
printf("dir.device == %ld\n", entry.d_pdev);
printf("dir.inode == %lld\n", entry.d_pino);
&& _kern_read_stat(fDirFd, NULL, false, &st,
sizeof(struct stat)) == B_OK) {
printf("dir.device == %ld\n", st.st_dev);
printf("dir.inode == %lld\n", st.st_ino);
} else {
printf("dir == NullFd\n");
}
+81 -122
View File
@@ -9,9 +9,11 @@
#include <fsproto.h>
#include <Directory.h>
#include <Entry.h>
#include <File.h>
#include "kernel_interface.h"
#include <syscalls.h>
#ifdef USE_OPENBEOS_NAMESPACE
namespace OpenBeOS {
@@ -143,23 +145,22 @@ BFile::~BFile()
- \c B_BUSY: A node was busy.
- \c B_FILE_ERROR: A general file error.
- \c B_NO_MORE_FDS: The application has run out of file descriptors.
\todo Currently implemented using BPrivate::Storage::entry_ref_to_path().
Reimplement!
*/
status_t
BFile::SetTo(const entry_ref *ref, uint32 openMode)
{
Unset();
char path[B_PATH_NAME_LENGTH];
status_t error = (ref ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
error = BPrivate::Storage::entry_ref_to_path(ref, path,
B_PATH_NAME_LENGTH);
}
if (error == B_OK)
error = SetTo(path, openMode);
set_status(error);
return error;
if (!ref)
return (fCStatus = B_BAD_VALUE);
int fd = _kern_open_entry_ref(ref->device, ref->directory, ref->name,
openMode);
if (fd >= 0) {
set_fd(fd);
fMode = openMode;
fCStatus = B_OK;
} else
fCStatus = fd;
return fCStatus;
}
// SetTo
@@ -185,14 +186,18 @@ status_t
BFile::SetTo(const BEntry *entry, uint32 openMode)
{
Unset();
entry_ref ref;
status_t error = (entry ? B_OK : B_BAD_VALUE);
if (error == B_OK)
error = entry->GetRef(&ref);
if (error == B_OK)
error = SetTo(&ref, openMode);
set_status(error);
return error;
if (!entry)
return (fCStatus = B_BAD_VALUE);
if (entry->InitCheck() != B_OK)
return (fCStatus = entry->InitCheck());
int fd = _kern_open(entry->fDirFd, entry->fName, openMode);
if (fd >= 0) {
set_fd(fd);
fMode = openMode;
fCStatus = B_OK;
} else
fCStatus = fd;
return fCStatus;
}
// SetTo
@@ -216,54 +221,16 @@ status_t
BFile::SetTo(const char *path, uint32 openMode)
{
Unset();
status_t result = B_OK;
BPrivate::Storage::FileDescriptor newFd = BPrivate::Storage::NullFd;
if (path) {
// analyze openMode
// Well, it's a bit schizophrenic to convert the B_* style openMode
// to POSIX style openFlags, but to use O_RWMASK to filter openMode.
BPrivate::Storage::OpenFlags openFlags = 0;
switch (openMode & O_RWMASK) {
case B_READ_ONLY:
openFlags = O_RDONLY;
break;
case B_WRITE_ONLY:
openFlags = O_WRONLY;
break;
case B_READ_WRITE:
openFlags = O_RDWR;
break;
default:
result = B_BAD_VALUE;
break;
}
if (result == B_OK) {
if (openMode & B_ERASE_FILE)
openFlags |= O_TRUNC;
if (openMode & B_OPEN_AT_END)
openFlags |= O_APPEND;
if (openMode & B_CREATE_FILE) {
openFlags |= O_CREAT;
if (openMode & B_FAIL_IF_EXISTS)
openFlags |= O_EXCL;
result = BPrivate::Storage::open(path, openFlags, S_IREAD | S_IWRITE,
newFd);
} else
result = BPrivate::Storage::open(path, openFlags, newFd);
if (result == B_OK)
fMode = openFlags;
}
if (!path)
return (fCStatus = B_BAD_VALUE);
int fd = _kern_open(-1, path, openMode);
if (fd >= 0) {
set_fd(fd);
fMode = openMode;
fCStatus = B_OK;
} else
result = B_BAD_VALUE;
// set the new file descriptor
if (result == B_OK) {
result = set_fd(newFd);
if (result != B_OK)
BPrivate::Storage::close(newFd);
}
// finally set the BNode status
set_status(result);
return result;
fCStatus = fd;
return fCStatus;
}
// SetTo
@@ -291,14 +258,16 @@ status_t
BFile::SetTo(const BDirectory *dir, const char *path, uint32 openMode)
{
Unset();
status_t error = (dir && path ? B_OK : B_BAD_VALUE);
BEntry entry;
if (error == B_OK)
error = entry.SetTo(dir, path);
if (error == B_OK)
error = SetTo(&entry, openMode);
set_status(error);
return error;
if (!dir)
return (fCStatus = B_BAD_VALUE);
int fd = _kern_open(dir->fDirFd, path, openMode);
if (fd >= 0) {
set_fd(fd);
fMode = openMode;
fCStatus = B_OK;
} else
fCStatus = fd;
return fCStatus;
}
// IsReadable
@@ -340,10 +309,9 @@ BFile::IsWritable() const
ssize_t
BFile::Read(void *buffer, size_t size)
{
ssize_t result = InitCheck();
if (result == B_OK)
result = BPrivate::Storage::read(get_fd(), buffer, size);
return result;
if (InitCheck() != B_OK)
return InitCheck();
return _kern_read(get_fd(), -1, buffer, size);
}
// ReadAt
@@ -358,10 +326,11 @@ BFile::Read(void *buffer, size_t size)
ssize_t
BFile::ReadAt(off_t location, void *buffer, size_t size)
{
ssize_t result = InitCheck();
if (result == B_OK)
result = BPrivate::Storage::read(get_fd(), buffer, location, size);
return result;
if (InitCheck() != B_OK)
return InitCheck();
if (location < 0)
return B_BAD_VALUE;
return _kern_read(get_fd(), location, buffer, size);
}
// Write
@@ -373,10 +342,9 @@ BFile::ReadAt(off_t location, void *buffer, size_t size)
ssize_t
BFile::Write(const void *buffer, size_t size)
{
ssize_t result = InitCheck();
if (result == B_OK)
result = BPrivate::Storage::write(get_fd(), buffer, size);
return result;
if (InitCheck() != B_OK)
return InitCheck();
return _kern_write(get_fd(), -1, buffer, size);
}
// WriteAt
@@ -391,10 +359,11 @@ BFile::Write(const void *buffer, size_t size)
ssize_t
BFile::WriteAt(off_t location, const void *buffer, size_t size)
{
ssize_t result = InitCheck();
if (result == B_OK)
result = BPrivate::Storage::write(get_fd(), buffer, location, size);
return result;
if (InitCheck() != B_OK)
return InitCheck();
if (location < 0)
return B_BAD_VALUE;
return _kern_write(get_fd(), location, buffer, size);
}
// Seek
@@ -417,10 +386,9 @@ BFile::WriteAt(off_t location, const void *buffer, size_t size)
off_t
BFile::Seek(off_t offset, uint32 seekMode)
{
off_t result = (InitCheck() == B_OK ? (off_t)B_OK : (off_t)B_FILE_ERROR);
if (result == B_OK)
result = BPrivate::Storage::seek(get_fd(), offset, seekMode);
return result;
if (InitCheck() != B_OK)
return B_FILE_ERROR;
return _kern_seek(get_fd(), offset, seekMode);
}
// Position
@@ -433,10 +401,9 @@ BFile::Seek(off_t offset, uint32 seekMode)
off_t
BFile::Position() const
{
off_t result = (InitCheck() == B_OK ? (off_t)B_OK : (off_t)B_FILE_ERROR);
if (result == B_OK)
result = BPrivate::Storage::get_position(get_fd());
return result;
if (InitCheck() != B_OK)
return B_FILE_ERROR;
return _kern_seek(get_fd(), 0, SEEK_CUR);
}
// SetSize
@@ -456,15 +423,13 @@ BFile::Position() const
status_t
BFile::SetSize(off_t size)
{
status_t result = InitCheck();
if (result == B_OK && size < 0)
result = B_BAD_VALUE;
if (InitCheck() != B_OK)
return InitCheck();
if (size < 0)
return B_BAD_VALUE;
struct stat statData;
if (result == B_OK) {
statData.st_size = size;
result = set_stat(statData, WSTAT_SIZE);
}
return result;
statData.st_size = size;
return set_stat(statData, WSTAT_SIZE);
}
// =
@@ -481,17 +446,14 @@ BFile::operator=(const BFile &file)
Unset();
if (file.InitCheck() == B_OK) {
// duplicate the file descriptor
BPrivate::Storage::FileDescriptor fd = -1;
status_t status = BPrivate::Storage::dup(file.get_fd(), fd);
int fd = _kern_dup(file.get_fd());
// set it
if (status == B_OK) {
status = set_fd(fd);
if (status == B_OK)
fMode = file.fMode;
else
BPrivate::Storage::close(fd);
}
set_status(status);
if (fd >= 0) {
fFd = fd;
fMode = file.fMode;
fCStatus = B_OK;
} else
fCStatus = fd;
}
}
return *this;
@@ -512,7 +474,7 @@ void BFile::_PhiloFile6() {}
To be used instead of accessing the BNode's private \c fFd member directly.
\return the file descriptor, or -1, if not properly initialized.
*/
BPrivate::Storage::FileDescriptor
int
BFile::get_fd() const
{
return fFd;
@@ -523,6 +485,3 @@ BFile::get_fd() const
}; // namespace OpenBeOS
#endif
+644 -28
View File
@@ -1,41 +1,60 @@
// LibBeAdapter.cpp
#include <dirent.h>
#include <errno.h>
#include <new>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <Directory.h>
#include <Entry.h>
#include <fs_attr.h>
#include <fs_query.h>
#include <Path.h>
#include <string.h>
#include <syscalls.h>
enum {
FD_TYPE_UNKNOWN,
FD_TYPE_DIR,
FD_TYPE_ATTR_DIR,
FD_TYPE_QUERY,
};
extern "C" status_t
_kern_dir_node_ref_to_path(dev_t device, ino_t inode, char *buffer, size_t size)
{
if (buffer == NULL)
return B_BAD_VALUE;
static const int kFDTableSlotCount = 1024;
static uint8 sFDTable[kFDTableSlotCount];
node_ref nodeRef;
nodeRef.device = device;
nodeRef.node = inode;
BDirectory directory;
status_t error = directory.SetTo(&nodeRef);
BEntry entry;
if (error == B_OK)
error = directory.GetEntry(&entry);
BPath path;
if (error == B_OK)
error = entry.GetPath(&path);
if (error == B_OK) {
if (size >= strlen(path.Path()) + 1)
strcpy(buffer, path.Path());
else
error = B_BAD_VALUE;
static struct InitDirFDTable {
InitDirFDTable()
{
memset(sFDTable, FD_TYPE_UNKNOWN, sizeof(sFDTable));
}
return error;
} sInitDirFDTable;
// _kern_entry_ref_to_path
extern "C"
status_t
_kern_entry_ref_to_path(dev_t device, ino_t inode, const char *leaf,
char *userPath, size_t pathLength)
{
// check buffer
if (!userPath)
return B_BAD_VALUE;
// construct an entry_ref
if (!leaf)
leaf = ".";
entry_ref ref(device, inode, leaf);
// get the path
BPath path;
status_t error = path.SetTo(&ref);
if (error != B_OK)
return error;
// copy the path into the buffer
if (strlcpy(userPath, path.Path(), pathLength) >= pathLength)
return B_BUFFER_OVERFLOW;
return B_OK;
}
@@ -43,7 +62,27 @@ _kern_dir_node_ref_to_path(dev_t device, ino_t inode, char *buffer, size_t size)
// private libroot.so functions
extern "C" status_t _kwfsstat_(dev_t device, const struct fs_info *info, long mask);
extern "C" status_t _kclosedir_(int fd);
extern "C" status_t _kclose_attr_dir_(int fd);
extern "C" status_t _kclose_query_(int fd);
extern "C" ssize_t _kreadlink_(int fd, const char *path, char *buffer,
size_t bufferSize);
extern "C" status_t _krstat_(int fd, const char *path, struct stat *st,
int16 unknown);
extern "C" status_t _kwstat_(int fd, const char *path, const struct stat *st,
uint32 mask, uint16 unknown);
extern "C" status_t _kwfsstat_(dev_t device, const struct fs_info *info,
long mask);
extern "C" status_t _klock_node_(int fd);
extern "C" status_t _kunlock_node_(int fd);
extern "C" status_t _kstart_watching_vnode_(dev_t device, ino_t node,
uint32 flags, port_id port,
@@ -86,3 +125,580 @@ _kern_stop_watching(dev_t device, ino_t node, uint32 flags,
return _kstop_watching_vnode_(device, node, port, token);
}
// init_dir
static
status_t
init_dir(BDirectory &dir, int fd)
{
// get a node_ref for the dir
struct stat st;
if (fstat(fd, &st) < 0)
return errno;
node_ref ref;
ref.device = st.st_dev;
ref.node = st.st_ino;
// init the dir
return dir.SetTo(&ref);
}
// open_dir_hack
static
int
open_dir_hack(const char *path)
{
DIR *dirHandle = opendir(path);
if (!dirHandle)
return errno;
int dirFD = dirHandle->fd;
if (dirFD < 0 || dirFD >= kFDTableSlotCount) {
closedir(dirHandle);
return B_ERROR;
}
free(dirHandle);
sFDTable[dirFD] = FD_TYPE_DIR;
return dirFD;
}
// get_path
static
int
get_path(int fd, const char *relPath, BPath &path)
{
if (fd < 0 || relPath && relPath[0] == '/')
return path.SetTo(relPath);
BDirectory dir;
status_t error = init_dir(dir, fd);
if (error != B_OK)
return error;
return path.SetTo(&dir, relPath);
}
// _kern_open
int
_kern_open(int fd, const char *path, int omode)
{
status_t error;
BPath fullPath;
if (!path)
path = ".";
if (fd >= 0) {
// construct the full path
error = get_path(fd, path, fullPath);
if (error != B_OK)
return error;
path = fullPath.Path();
}
// open the file
int result = open(path, omode);
if (result < 0)
return errno;
return result;
}
// _kern_open_entry_ref
extern "C"
int
_kern_open_entry_ref(dev_t device, ino_t inode, const char *name, int omode)
{
BPath fullPath;
node_ref ref;
ref.device = device;
ref.node = inode;
// init the dir and get the path
BDirectory dir;
status_t error = dir.SetTo(&ref);
if (error != B_OK)
return error;
error = fullPath.SetTo(&dir, name);
if (error != B_OK)
return error;
// open the file
int fd = open(fullPath.Path(), omode);
if (fd < 0)
return errno;
return fd;
}
// _kern_open_dir
extern "C"
int
_kern_open_dir(int fd, const char *path)
{
status_t error;
BPath fullPath;
if (fd >= 0) {
if (!path)
return _kern_dup(fd);
// construct the full path
error = get_path(fd, path, fullPath);
if (error != B_OK)
return error;
path = fullPath.Path();
}
// open the dir
return open_dir_hack(path);
}
// _kern_open_dir_entry_ref
extern "C"
int
_kern_open_dir_entry_ref(dev_t device, ino_t inode, const char *path)
{
BPath fullPath;
node_ref ref;
ref.device = device;
ref.node = inode;
// init the dir and get the path
BDirectory dir;
status_t error = dir.SetTo(&ref);
if (error != B_OK)
return error;
error = fullPath.SetTo(&dir, path);
if (error != B_OK)
return error;
path = fullPath.Path();
// open the dir
return open_dir_hack(path);
}
// _kern_open_parent_dir
extern "C"
int
_kern_open_parent_dir(int fd, char *name, size_t pathLength)
{
if (fd < 0)
return B_BAD_VALUE;
// get the dir
BDirectory dir;
status_t error = init_dir(dir, fd);
if (error != B_OK)
return error;
// get an entry
BEntry entry;
error = entry.SetTo(&dir, NULL);
if (error != B_OK)
return error;
// copy back the path
if (name) {
char tmpName[B_FILE_NAME_LENGTH];
error = entry.GetName(tmpName);
if (error != B_OK)
return error;
if (strlcpy(name, tmpName, pathLength) >= pathLength)
return B_BUFFER_OVERFLOW;
}
// get the parent dir path
BPath path;
error = path.SetTo(&dir, "..");
if (error != B_OK)
return error;
// open the dir
return open_dir_hack(path.Path());
}
// _kern_open_query
extern "C"
int
_kern_open_query(dev_t device, const char *query, uint32 flags, port_id port,
int32 token)
{
// check params
if (!query || device < 0)
return B_BAD_VALUE;
if (flags & B_LIVE_QUERY && port < 0)
return B_BAD_VALUE;
// open query
DIR *dirHandle;
if (flags & B_LIVE_QUERY)
dirHandle = fs_open_live_query(device, query, flags, port, token);
else
dirHandle = fs_open_query(device, query, flags);
if (!dirHandle)
return errno;
// get FD and return result
int dirFD = dirHandle->fd;
if (dirFD < 0 || dirFD >= kFDTableSlotCount) {
fs_close_query(dirHandle);
return B_ERROR;
}
free(dirHandle);
sFDTable[dirFD] = FD_TYPE_QUERY;
return dirFD;
}
// _kern_create_dir
extern "C"
status_t
_kern_create_dir(int fd, const char *path, int perms)
{
if (!path)
return B_BAD_VALUE;
status_t error;
BPath fullPath;
if (fd >= 0) {
// construct the full path
error = get_path(fd, path, fullPath);
if (error != B_OK)
return error;
path = fullPath.Path();
}
// create the dir
return (mkdir(path, perms) < 0 ? errno : B_OK);
}
// _kern_create_symlink
extern "C"
status_t
_kern_create_symlink(int fd, const char *path, const char *toPath, int mode)
{
(void)mode;
if (!path)
return B_BAD_VALUE;
status_t error;
BPath fullPath;
if (fd >= 0) {
// construct the full path
error = get_path(fd, path, fullPath);
if (error != B_OK)
return error;
path = fullPath.Path();
}
// create the symlink
return (symlink(toPath, path) < 0 ? errno : B_OK);
}
// _kern_close
extern "C"
status_t
_kern_close(int fd)
{
if (fd >= 0 && fd < kFDTableSlotCount && sFDTable[fd] != FD_TYPE_UNKNOWN) {
status_t error;
switch (sFDTable[fd]) {
case FD_TYPE_DIR:
error = _kclosedir_(fd);
break;
case FD_TYPE_ATTR_DIR:
error = _kclose_attr_dir_(fd);
break;
case FD_TYPE_QUERY:
error = _kclose_query_(fd);
break;
default:
error = B_BAD_VALUE;
break;
}
sFDTable[fd] = FD_TYPE_UNKNOWN;
if (error != B_OK)
return error;
} else if (close(fd) < 0)
return errno;
return B_OK;
}
// _kern_dup
extern "C"
int
_kern_dup(int fd)
{
int clonedFD = dup(fd);
if (clonedFD < 0)
return errno;
if (fd >= 0 && fd < kFDTableSlotCount && sFDTable[fd] != FD_TYPE_UNKNOWN
&& clonedFD >= 0 && clonedFD < kFDTableSlotCount) {
sFDTable[clonedFD] = sFDTable[fd];
}
return clonedFD;
}
// _kern_read
extern "C"
ssize_t
_kern_read(int fd, off_t pos, void *buffer, size_t bufferSize)
{
if (!buffer)
return B_BAD_VALUE;
ssize_t result;
if (pos == -1)
result = read(fd, buffer, bufferSize);
else
result = read_pos(fd, pos, buffer, bufferSize);
return (result < 0 ? errno : result);
}
// _kern_write
extern "C"
ssize_t
_kern_write(int fd, off_t pos, const void *buffer, size_t bufferSize)
{
if (!buffer)
return B_BAD_VALUE;
ssize_t result;
if (pos == -1)
result = write(fd, buffer, bufferSize);
else
result = write_pos(fd, pos, buffer, bufferSize);
return (result < 0 ? errno : result);
}
// _kern_seek
extern "C"
off_t
_kern_seek(int fd, off_t pos, int seekType)
{
off_t result = lseek(fd, pos, seekType);
return (result < 0 ? errno : result);
}
// _kern_read_dir
extern "C"
ssize_t
_kern_read_dir(int fd, struct dirent *buffer, size_t bufferSize,
uint32 maxCount)
{
if (fd < 0 || !buffer)
return B_BAD_VALUE;
if (fd >= kFDTableSlotCount || sFDTable[fd] == FD_TYPE_UNKNOWN)
return B_BAD_VALUE;
if (maxCount < 1)
return 0;
char tmpBuffer[sizeof(struct dirent) + B_FILE_NAME_LENGTH];
DIR *dirDir = (DIR*)tmpBuffer;
dirDir->fd = fd;
dirent *entry = NULL;
switch (sFDTable[fd]) {
case FD_TYPE_DIR:
entry = readdir(dirDir);
break;
case FD_TYPE_ATTR_DIR:
entry = fs_read_attr_dir(dirDir);
break;
case FD_TYPE_QUERY:
entry = fs_read_query(dirDir);
break;
}
if (!entry)
return 0;
// Don't trust entry->d_reclen.
// Unlike stated in BeBook::BEntryList, the value is not the length
// of the whole structure, but only of the name. Some FSs count
// the terminating '\0', others don't.
// So we calculate the size ourselves (including the '\0'):
size_t entryLen = entry->d_name + strlen(entry->d_name) + 1
- (char*)entry;
if (bufferSize >= entryLen) {
memcpy(buffer, entry, entryLen);
return 1;
} else // buffer too small
return B_BUFFER_OVERFLOW;
}
// _kern_rewind_dir
extern "C"
status_t
_kern_rewind_dir(int fd)
{
if (fd < 0 || fd >= kFDTableSlotCount || sFDTable[fd] == FD_TYPE_UNKNOWN)
return B_BAD_VALUE;
char tmpBuffer[sizeof(struct dirent) + B_FILE_NAME_LENGTH];
DIR *dirDir = (DIR*)tmpBuffer;
dirDir->fd = fd;
switch (sFDTable[fd]) {
case FD_TYPE_DIR:
rewinddir(dirDir);
break;
case FD_TYPE_ATTR_DIR:
fs_rewind_attr_dir(dirDir);
break;
case FD_TYPE_QUERY:
return B_BAD_VALUE;
break;
}
return B_OK;
}
// _kern_read_link
extern "C"
ssize_t
_kern_read_link(int fd, const char *path, char *buffer, size_t bufferSize)
{
ssize_t result = _kreadlink_(fd, path, buffer, bufferSize);
if (result >= 0)
buffer[result] = '\0';
return result;
}
// _kern_unlink
extern "C"
status_t
_kern_unlink(int fd, const char *relPath)
{
BPath path;
status_t error = get_path(fd, relPath, path);
if (error != B_OK)
return error;
if (unlink(path.Path()) < 0) {
error = errno;
if (error == B_IS_A_DIRECTORY) {
if (rmdir(path.Path()) < 0)
return errno;
} else
return error;
}
return B_OK;
}
// _kern_rename
extern "C"
status_t
_kern_rename(int oldDir, const char *oldRelPath, int newDir,
const char *newRelPath)
{
// get old path
BPath oldPath;
status_t error = get_path(oldDir, oldRelPath, oldPath);
if (error != B_OK)
return error;
// get new path
BPath newPath;
error = get_path(newDir, newRelPath, newPath);
if (error != B_OK)
return error;
// rename
if (rename(oldPath.Path(), newPath.Path()) < 0)
return errno;
return B_OK;
}
// _kern_read_stat
extern "C"
status_t
_kern_read_stat(int fd, const char *path, bool traverseLink, struct stat *st,
size_t statSize)
{
if (traverseLink)
return B_ERROR; // unsupported
return _krstat_(fd, path, st, 0);
}
// _kern_write_stat
extern "C"
status_t
_kern_write_stat(int fd, const char *path, bool traverseLink,
const struct stat *st, size_t statSize, int statMask)
{
if (traverseLink)
return B_ERROR; // unsupported
return _kwstat_(fd, path, st, statMask, 0);
}
// _kern_lock_node
extern "C"
status_t
_kern_lock_node(int fd)
{
return _klock_node_(fd);
}
// _kern_unlock_node
extern "C"
status_t
_kern_unlock_node(int fd)
{
return _kunlock_node_(fd);
}
// _kern_fsync
extern "C"
status_t
_kern_fsync(int fd)
{
return (fsync(fd) < 0) ? errno : B_OK ;
}
// _kern_open_attr_dir
extern "C"
int
_kern_open_attr_dir(int fd, const char *path)
{
if (fd < 0 && !path)
return B_BAD_VALUE;
if (fd >= 0 && path)
return B_ERROR; // unsupported
DIR *dirHandle = (fd >= 0 ? fs_fopen_attr_dir(fd) : fs_open_attr_dir(path));
if (!dirHandle)
return errno;
int dirFD = dirHandle->fd;
if (dirFD < 0 || dirFD >= kFDTableSlotCount) {
fs_close_attr_dir(dirHandle);
return B_ERROR;
}
free(dirHandle);
sFDTable[dirFD] = FD_TYPE_ATTR_DIR;
return dirFD;
}
// _kern_remove_attr
extern "C"
status_t
_kern_remove_attr(int fd, const char *name)
{
return fs_remove_attr(fd, name) == -1 ? errno : B_OK ;
}
// _kern_rename_attr
extern "C"
status_t
_kern_rename_attr(int fromFile, const char *fromName, int toFile,
const char *toName)
{
status_t error = (fromName && toName ? B_OK : B_BAD_VALUE);
// Figure out how much data there is
attr_info info;
if (error == B_OK) {
if (fs_stat_attr(fromFile, fromName, &info) < 0)
error = B_BAD_VALUE; // This is what R5::BNode returns...
}
// Alloc a buffer
char *data = NULL;
if (error == B_OK) {
// alloc at least one byte
data = new(nothrow) char[info.size >= 1 ? info.size : 1];
if (data == NULL)
error = B_NO_MEMORY;
}
// Read in the data
if (error == B_OK) {
ssize_t size = fs_read_attr(fromFile, fromName, info.type, 0, data,
info.size);
if (size != info.size) {
if (size < 0)
error = errno;
else
error = B_ERROR;
}
}
// Write it to the new attribute
if (error == B_OK) {
ssize_t size = 0;
if (info.size > 0)
size = fs_write_attr(toFile, toName, info.type, 0, data, info.size);
if (size != info.size) {
if (size < 0)
error = errno;
else
error = B_ERROR;
}
}
// free the buffer
if (data)
delete[] data;
// Remove the old attribute
if (error == B_OK)
error = _kern_remove_attr(fromFile, fromName);
return error;
}
+163 -122
View File
@@ -7,15 +7,20 @@
BNode implementation.
*/
#include <errno.h>
#include <fs_attr.h> // for struct attr_info
#include <new>
#include <string.h>
#include <unistd.h>
#include <Node.h>
#include <Directory.h>
#include <Entry.h>
#include <Node.h>
#include <String.h>
#include <TypeConstants.h>
#include <syscalls.h>
#include "kernel_interface.h"
#include "storage_support.h"
//----------------------------------------------------------------------
@@ -84,8 +89,8 @@ node_ref::operator=(const node_ref &ref)
/*! \brief Creates an uninitialized BNode object
*/
BNode::BNode()
: fFd(BPrivate::Storage::NullFd),
fAttrFd(BPrivate::Storage::NullFd),
: fFd(-1),
fAttrFd(-1),
fCStatus(B_NO_INIT)
{
}
@@ -95,8 +100,8 @@ BNode::BNode()
\param ref the entry_ref referring to the entry
*/
BNode::BNode(const entry_ref *ref)
: fFd(BPrivate::Storage::NullFd),
fAttrFd(BPrivate::Storage::NullFd),
: fFd(-1),
fAttrFd(-1),
fCStatus(B_NO_INIT)
{
SetTo(ref);
@@ -107,8 +112,8 @@ BNode::BNode(const entry_ref *ref)
\param entry the BEntry representing the entry
*/
BNode::BNode(const BEntry *entry)
: fFd(BPrivate::Storage::NullFd),
fAttrFd(BPrivate::Storage::NullFd),
: fFd(-1),
fAttrFd(-1),
fCStatus(B_NO_INIT)
{
SetTo(entry);
@@ -119,8 +124,8 @@ BNode::BNode(const BEntry *entry)
\param path the path referring to the entry
*/
BNode::BNode(const char *path)
: fFd(BPrivate::Storage::NullFd),
fAttrFd(BPrivate::Storage::NullFd),
: fFd(-1),
fAttrFd(-1),
fCStatus(B_NO_INIT)
{
SetTo(path);
@@ -133,8 +138,8 @@ BNode::BNode(const char *path)
\param path the entry's path name relative to \a dir
*/
BNode::BNode(const BDirectory *dir, const char *path)
: fFd(BPrivate::Storage::NullFd),
fAttrFd(BPrivate::Storage::NullFd),
: fFd(-1),
fAttrFd(-1),
fCStatus(B_NO_INIT)
{
SetTo(dir, path);
@@ -144,8 +149,8 @@ BNode::BNode(const BDirectory *dir, const char *path)
\param node the BNode to be copied
*/
BNode::BNode(const BNode &node)
: fFd(BPrivate::Storage::NullFd),
fAttrFd(BPrivate::Storage::NullFd),
: fFd(-1),
fAttrFd(-1),
fCStatus(B_NO_INIT)
{
*this = node;
@@ -180,7 +185,9 @@ BNode::InitCheck() const
status_t
BNode::GetStat(struct stat *st) const
{
return (fCStatus != B_OK) ? fCStatus : BPrivate::Storage::get_stat(fFd, st) ;
return (fCStatus != B_OK)
? fCStatus
: _kern_read_stat(fFd, NULL, false, st, sizeof(struct stat));
}
/*! \brief Reinitializes the object to the specified entry_ref.
@@ -190,23 +197,11 @@ BNode::GetStat(struct stat *st) const
- \c B_BAD_VALUE: \c NULL \a ref.
- \c B_ENTRY_NOT_FOUND: The entry could not be found.
- \c B_BUSY: The entry is locked.
\todo Currently implemented using BPrivate::Storage::entry_ref_to_path().
Reimplement!
*/
status_t
BNode::SetTo(const entry_ref *ref)
{
Unset();
char path[B_PATH_NAME_LENGTH];
status_t error = (ref ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
error = BPrivate::Storage::entry_ref_to_path(ref, path,
B_PATH_NAME_LENGTH);
}
if (error == B_OK)
error = SetTo(path);
fCStatus = error;
return error;
return _SetTo(ref, false);
}
/*! \brief Reinitializes the object to the specified filesystem entry.
@@ -216,23 +211,15 @@ BNode::SetTo(const entry_ref *ref)
- \c B_BAD_VALUE: \c NULL \a entry.
- \c B_ENTRY_NOT_FOUND: The entry could not be found.
- \c B_BUSY: The entry is locked.
\todo Implemented using SetTo(entry_ref*). Check, if necessary to
reimplement!
*/
status_t
BNode::SetTo(const BEntry *entry)
{
Unset();
entry_ref ref;
status_t error = (entry ? B_OK : B_BAD_VALUE);
if (error == B_OK && entry->InitCheck() != B_OK)
error = B_BAD_VALUE;
if (error == B_OK)
error = entry->GetRef(&ref);
if (error == B_OK)
error = SetTo(&ref);
fCStatus = error;
return error;
if (!entry) {
Unset();
return (fCStatus = B_BAD_VALUE);
}
return _SetTo(entry->fDirFd, entry->fName, false);
}
/*! \brief Reinitializes the object to the entry referred to by the specified
@@ -247,12 +234,7 @@ BNode::SetTo(const BEntry *entry)
status_t
BNode::SetTo(const char *path)
{
Unset();
if (path != NULL) {
fCStatus = BPrivate::Storage::open(path, O_RDWR | O_NOTRAVERSE, fFd,
true);
}
return fCStatus;
return _SetTo(-1, path, false);
}
/*! \brief Reinitializes the object to the entry referred to by the specified
@@ -265,22 +247,15 @@ BNode::SetTo(const char *path)
- \c B_BAD_VALUE: \c NULL \a dir or \a path.
- \c B_ENTRY_NOT_FOUND: The entry could not be found.
- \c B_BUSY: The entry is locked.
\todo Implemented using SetTo(BEntry*). Check, if necessary to reimplement!
*/
status_t
BNode::SetTo(const BDirectory *dir, const char *path)
{
Unset();
status_t error = (dir && path ? B_OK : B_BAD_VALUE);
if (error == B_OK && BPrivate::Storage::is_absolute_path(path))
error = B_BAD_VALUE;
BEntry entry;
if (error == B_OK)
error = entry.SetTo(dir, path);
if (error == B_OK)
error = SetTo(&entry);
fCStatus = error;
return error;
if (!dir || !path || BPrivate::Storage::is_absolute_path(path)) {
Unset();
return (fCStatus = B_BAD_VALUE);
}
return _SetTo(dir->fDirFd, path, false);
}
/*! \brief Returns the object to an uninitialized state.
@@ -298,21 +273,13 @@ BNode::Unset()
- \c B_OK: Everything went fine.
- \c B_FILE_ERROR: The object is not initialized.
- \c B_BUSY: The node is already locked.
\todo Currently unimplemented; requires new kernel.
*/
status_t
BNode::Lock()
{
if (fCStatus != B_OK)
return fCStatus;
// This will have to wait for the new kenel
return B_FILE_ERROR;
// We'll need to keep lock around if the kernel function
// doesn't just work on file descriptors
// BPrivate::Storage::FileLock lock;
// return BPrivate::Storage::lock(fFd, BPrivate::Storage::READ_WRITE, &lock);
return _kern_lock_node(fFd);
}
/*! \brief Unlocks the node.
@@ -320,15 +287,13 @@ BNode::Lock()
- \c B_OK: Everything went fine.
- \c B_FILE_ERROR: The object is not initialized.
- \c B_BAD_VALUE: The node is not locked.
\todo Currently unimplemented; requires new kernel.
*/
status_t
BNode::Unlock()
{
if (fCStatus != B_OK)
return fCStatus;
// This will have to wait for the new kenel
return B_FILE_ERROR;
return _kern_unlock_node(fFd);
}
/*! \brief Immediately performs any pending disk actions on the node.
@@ -339,7 +304,7 @@ BNode::Unlock()
status_t
BNode::Sync()
{
return (fCStatus != B_OK) ? B_FILE_ERROR : BPrivate::Storage::sync(fFd) ;
return (fCStatus != B_OK) ? B_FILE_ERROR : _kern_fsync(fFd);
}
/*! \brief Writes data from a buffer to an attribute.
@@ -368,11 +333,10 @@ BNode::WriteAttr(const char *attr, type_code type, off_t offset,
{
if (fCStatus != B_OK)
return B_FILE_ERROR;
else {
ssize_t result = BPrivate::Storage::write_attr(fFd, attr, type, offset,
buffer, len);
return result;
}
if (!attr || !buffer)
return B_BAD_VALUE;
ssize_t result = fs_write_attr (fFd, attr, type, offset, buffer, len);
return (result < 0 ? errno : result);
}
/*! \brief Reads data from an attribute into a buffer.
@@ -396,11 +360,10 @@ BNode::ReadAttr(const char *attr, type_code type, off_t offset,
{
if (fCStatus != B_OK)
return B_FILE_ERROR;
else {
ssize_t result = BPrivate::Storage::read_attr(fFd, attr, type, offset, buffer,
len);
return result;
}
if (!attr || !buffer)
return B_BAD_VALUE;
ssize_t result = fs_read_attr(fFd, attr, type, offset, buffer, len );
return (result == -1 ? errno : result);
}
/*! \brief Deletes the attribute given by \a name.
@@ -415,8 +378,7 @@ BNode::ReadAttr(const char *attr, type_code type, off_t offset,
status_t
BNode::RemoveAttr(const char *name)
{
return (fCStatus != B_OK) ? B_FILE_ERROR
: BPrivate::Storage::remove_attr(fFd, name);
return (fCStatus != B_OK) ? B_FILE_ERROR : _kern_remove_attr(fFd, name);
}
/*! \brief Moves the attribute given by \a oldname to \a newname.
@@ -436,7 +398,7 @@ BNode::RenameAttr(const char *oldname, const char *newname)
{
if (fCStatus != B_OK)
return B_FILE_ERROR;
return BPrivate::Storage::rename_attr(fFd, oldname, newname);
return _kern_rename_attr(fFd, oldname, fFd, newname);
}
@@ -453,8 +415,11 @@ BNode::RenameAttr(const char *oldname, const char *newname)
status_t
BNode::GetAttrInfo(const char *name, struct attr_info *info) const
{
return (fCStatus != B_OK) ? B_FILE_ERROR
: BPrivate::Storage::stat_attr(fFd, name, info);
if (fCStatus != B_OK)
return B_FILE_ERROR;
if (!name || !info)
return B_BAD_VALUE;
return (fs_stat_attr(fFd, name, info) < 0) ? errno : B_OK ;
}
/*! \brief Returns the next attribute in the node's list of attributes.
@@ -486,12 +451,13 @@ BNode::GetNextAttrName(char *buffer)
return B_FILE_ERROR;
BPrivate::Storage::LongDirEntry entry;
status_t error = BPrivate::Storage::read_attr_dir(fAttrFd, entry);
if (error == B_OK) {
strncpy(buffer, entry.d_name, B_ATTR_NAME_LENGTH);
return B_OK;
}
return error;
ssize_t result = _kern_read_dir(fAttrFd, &entry, sizeof(entry), 1);
if (result < 0)
return result;
if (result == 0)
return B_ENTRY_NOT_FOUND;
strlcpy(buffer, entry.d_name, B_ATTR_NAME_LENGTH);
return B_OK;
}
/*! \brief Resets the object's attribute pointer to the first attribute in the
@@ -505,8 +471,7 @@ BNode::RewindAttrs()
{
if (InitAttrDir() != B_OK)
return B_FILE_ERROR;
BPrivate::Storage::rewind_attr_dir(fAttrFd);
return B_OK;
return _kern_rewind_dir(fAttrFd);
}
/*! Writes the specified string to the specified attribute, clobbering any
@@ -590,8 +555,8 @@ BNode::operator=(const BNode &node)
Unset();
// We have to manually dup the node, because R5::BNode::Dup()
// is not declared to be const (which IMO is retarded).
fFd = BPrivate::Storage::dup(node.fFd);
fCStatus = (fFd == BPrivate::Storage::NullFd) ? B_NO_INIT : B_OK ;
fFd = _kern_dup(node.fFd);
fCStatus = (fFd < 0) ? B_NO_INIT : B_OK ;
return *this;
}
@@ -607,13 +572,13 @@ BNode::operator==(const BNode &node) const
if (fCStatus == B_NO_INIT && node.InitCheck() == B_NO_INIT)
return true;
if (fCStatus == B_OK && node.InitCheck() == B_OK) {
// Check if they're identical
BPrivate::Storage::Stat s1, s2;
if (GetStat(&s1) != B_OK)
// compare the node_refs
node_ref ref1, ref2;
if (GetNodeRef(&ref1) != B_OK)
return false;
if (node.GetStat(&s2) != B_OK)
if (node.GetNodeRef(&ref2) != B_OK)
return false;
return (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino);
return (ref1 == ref2);
}
return false;
}
@@ -638,7 +603,8 @@ BNode::operator!=(const BNode &node) const
int
BNode::Dup()
{
return BPrivate::Storage::dup(fFd);
int fd = _kern_dup(fFd);
return (fd >= 0 ? fd : -1); // comply with R5 return value
}
@@ -662,7 +628,7 @@ void BNode::_RudeNode6() { }
thereafter.
*/
status_t
BNode::set_fd(BPrivate::Storage::FileDescriptor fd)
BNode::set_fd(int fd)
{
if (fFd != -1)
close_fd();
@@ -673,20 +639,19 @@ BNode::set_fd(BPrivate::Storage::FileDescriptor fd)
/*! \brief Closes the node's file descriptor(s).
To be implemented by subclasses to close the file descriptor using the
proper system call for the given file-type. This implementation calls
BPrivate::Storage::close(fFd) and also BPrivate::Storage::close_attr_dir(fAttrDir)
if necessary.
_kern_close(fFd) and also _kern_close(fAttrDir) if necessary.
*/
void
BNode::close_fd()
{
if (fAttrFd != BPrivate::Storage::NullFd)
if (fAttrFd >= 0)
{
BPrivate::Storage::close_attr_dir(fAttrFd);
fAttrFd = BPrivate::Storage::NullFd;
_kern_close(fAttrFd);
fAttrFd = -1;
}
if (fFd != BPrivate::Storage::NullFd) {
close(fFd);
fFd = BPrivate::Storage::NullFd;
if (fFd >= 0) {
_kern_close(fFd);
fFd = -1;
}
}
@@ -702,6 +667,84 @@ BNode::set_status(status_t newStatus)
fCStatus = newStatus;
}
// _SetTo
/*! \brief Initializes the BNode's file descriptor to the node referred to
by the given FD and path combo.
\a path must either be \c NULL, an absolute or a relative path.
In the first case, \a fd must not be \c NULL; the node it refers to will
be opened. If absolute, \a fd is ignored. If relative and \a fd is >= 0,
it will be reckoned off the directory identified by \a fd, otherwise off
the current working directory.
The method will first try to open the node with read and write permission.
If that fails due to a read-only FS or because the user has no write
permission for the node, it will re-try opening the node read-only.
The \a fCStatus member will be set to the return value of this method.
\param fd Either a directory FD or a value < 0. In the latter case \a path
must be specified.
\param path Either \a NULL in which case \a fd must be given, absolute, or
relative to the directory specified by \a fd (if given) or to the
current working directory.
\param traverse If the node identified by \a fd and \a path is a symlink
and \a traverse is \c true, the symlink will be resolved recursively.
\return \c B_OK, if everything went fine, another error code otherwise.
*/
status_t
BNode::_SetTo(int fd, const char *path, bool traverse)
{
Unset();
status_t error = (fd >= 0 || path ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
int traverseFlag = (traverse ? 0 : O_NOTRAVERSE);
fFd = _kern_open(fd, path, O_RDWR | traverseFlag);
if (fFd == B_READ_ONLY_DEVICE || fFd == B_PERMISSION_DENIED) {
// opening read-write failed, re-try read-only
fFd = _kern_open(fd, path, O_RDONLY | traverseFlag);
}
if (fFd < 0)
error = fFd;
}
return fCStatus = error;
}
// _SetTo
/*! \brief Initializes the BNode's file descriptor to the node referred to
by the given entry_ref.
The method will first try to open the node with read and write permission.
If that fails due to a read-only FS or because the user has no write
permission for the node, it will re-try opening the node read-only.
The \a fCStatus member will be set to the return value of this method.
\param ref An entry_ref identifying the node to be opened.
\param traverse If the node identified by \a ref is a symlink
and \a traverse is \c true, the symlink will be resolved recursively.
\return \c B_OK, if everything went fine, another error code otherwise.
*/
status_t
BNode::_SetTo(const entry_ref *ref, bool traverse)
{
Unset();
status_t error = (ref ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
int traverseFlag = (traverse ? 0 : O_NOTRAVERSE);
fFd = _kern_open_entry_ref(ref->device, ref->directory, ref->name,
O_RDWR | traverseFlag);
if (fFd == B_READ_ONLY_DEVICE || fFd == B_PERMISSION_DENIED) {
// opening read-write failed, re-try read-only
fFd = _kern_open_entry_ref(ref->device, ref->directory, ref->name,
O_RDONLY | traverseFlag);
}
if (fFd < 0)
error = fFd;
}
return fCStatus = error;
}
/*! \brief Modifies a certain setting for this node based on \a what and the
corresponding value in \a st.
Inherited from and called by BStatable.
@@ -714,7 +757,8 @@ BNode::set_stat(struct stat &st, uint32 what)
{
if (fCStatus != B_OK)
return B_FILE_ERROR;
return BPrivate::Storage::set_stat(fFd, st, what);
return _kern_write_stat(fFd, NULL, false, &st, sizeof(struct stat),
what);
}
/*! \brief Verifies that the BNode has been properly initialized, and then
@@ -725,8 +769,11 @@ BNode::set_stat(struct stat &st, uint32 what)
status_t
BNode::InitAttrDir()
{
if (fCStatus == B_OK && fAttrFd == BPrivate::Storage::NullFd)
return BPrivate::Storage::open_attr_dir(fFd, fAttrFd);
if (fCStatus == B_OK && fAttrFd < 0) {
fAttrFd = _kern_open_attr_dir(fFd, NULL);
if (fAttrFd < 0)
return fAttrFd;
}
return fCStatus;
}
@@ -735,16 +782,10 @@ BNode::InitAttrDir()
*/
/*! \var BNode::fAttrFd
This appears to be passed to the attribute directory functions
like a BPrivate::Storage::Dir would be, but it's actually a file descriptor.
Best I can figure, the R5 syscall for reading attributes must've
just taken a file descriptor. Depending on what our kernel ends up
providing, this may or may not be replaced with an Dir*
File descriptor for the attribute directory of the node. Initialized lazily.
*/
/*! \var BNode::fCStatus
The object's initialization status.
*/
+17 -14
View File
@@ -14,7 +14,9 @@
#include <Entry.h>
#include <StorageDefs.h>
#include <String.h>
#include "kernel_interface.h"
#include <syscalls.h>
#include "storage_support.h"
using namespace std;
@@ -125,15 +127,16 @@ status_t
BPath::SetTo(const entry_ref *ref)
{
Unset();
status_t error = (ref ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
char path[B_PATH_NAME_LENGTH];
error = BPrivate::Storage::entry_ref_to_path(ref, path, sizeof(path));
if (error == B_OK)
error = set_path(path); // the path is already normalized
}
fCStatus = error;
return error;
if (!ref)
return (fCStatus = B_BAD_VALUE);
char path[B_PATH_NAME_LENGTH];
status_t error = _kern_entry_ref_to_path(ref->device, ref->directory,
ref->name, path, sizeof(path));
if (error != B_OK)
return (fCStatus = error);
fCStatus = set_path(path); // the path is already normalized
return fCStatus;
}
/*! \brief Reinitializes the object to the specified filesystem entry.
@@ -214,11 +217,11 @@ BPath::SetTo(const char *path, const char *leaf, bool normalize)
// normalize the path, if necessary, otherwise just set it
if (error == B_OK) {
if (normalize) {
char normalizedPath[B_PATH_NAME_LENGTH];
error = BPrivate::Storage::get_canonical_path(newPath, normalizedPath,
sizeof(normalizedPath));
// create a BEntry and initialize us with this entry
BEntry entry;
error = entry.SetTo(newPath, false);
if (error == B_OK)
error = set_path(normalizedPath);
return SetTo(&entry);
} else
error = set_path(newPath);
}
+48 -46
View File
@@ -6,7 +6,6 @@
\file Query.cpp
BQuery implementation.
*/
#include <Query.h>
#include <fs_query.h>
#include <new>
@@ -14,18 +13,17 @@
#include <time.h>
#include <Entry.h>
#include <Query.h>
#include <Volume.h>
#include "kernel_interface.h"
#include <MessengerPrivate.h>
#include <syscalls.h>
#include "QueryPredicate.h"
#include "storage_support.h"
using namespace BPrivate::Storage;
using namespace std;
enum {
NOT_IMPLEMENTED = B_ERROR,
};
using namespace BPrivate::Storage;
// BQuery
@@ -40,7 +38,7 @@ BQuery::BQuery()
fLive(false),
fPort(B_ERROR),
fToken(0),
fQueryFd(NullFd)
fQueryFd(-1)
{
}
@@ -61,9 +59,9 @@ BQuery::Clear()
{
// close the currently open query
status_t error = B_OK;
if (fQueryFd != NullFd) {
error = close_query(fQueryFd);
fQueryFd = NullFd;
if (fQueryFd >= 0) {
error = _kern_close(fQueryFd);
fQueryFd = -1;
}
// delete the predicate stack and the predicate
delete fStack;
@@ -314,10 +312,8 @@ BQuery::PushDate(const char *date)
time_t t;
time(&t);
t = parsedate(date, t);
if (t < 0) {
// error = t;
if (t < 0)
error = B_BAD_VALUE;
}
}
if (error == B_OK)
error = _PushNode(new(nothrow) DateNode(date), true);
@@ -391,8 +387,10 @@ BQuery::SetTarget(BMessenger messenger)
if (error == B_OK && _HasFetched())
error = B_NOT_ALLOWED;
if (error == B_OK) {
fPort = messenger.fPort;
fToken = messenger.fHandlerToken;
BMessenger::Private messengerPrivate(messenger);
fPort = messengerPrivate.Port();
fToken = (messengerPrivate.IsPreferredTarget()
? -1 : messengerPrivate.Token());
fLive = true;
}
return error;
@@ -428,7 +426,6 @@ BQuery::GetPredicate(char *buffer, size_t length)
{
status_t error = (buffer ? B_OK : B_BAD_VALUE);
if (error == B_OK)
// error = _EvaluateStack();
_EvaluateStack();
if (error == B_OK && !fPredicate)
error = B_NO_INIT;
@@ -458,7 +455,6 @@ BQuery::GetPredicate(BString *predicate)
{
status_t error = (predicate ? B_OK : B_BAD_VALUE);
if (error == B_OK)
// error = _EvaluateStack();
_EvaluateStack();
if (error == B_OK && !fPredicate)
error = B_NO_INIT;
@@ -518,20 +514,19 @@ BQuery::TargetDevice() const
status_t
BQuery::Fetch()
{
status_t error = (_HasFetched() ? B_NOT_ALLOWED : B_OK);
if (error == B_OK)
// error = _EvaluateStack();
_EvaluateStack();
if (error == B_OK && (!fPredicate || fDevice < 0))
error = B_NO_INIT;
if (error == B_OK) {
if (fLive) {
error = open_live_query(fDevice, fPredicate, B_LIVE_QUERY, fPort,
fToken, fQueryFd);
} else
error = open_query(fDevice, fPredicate, 0, fQueryFd);
}
return error;
if (_HasFetched())
return B_NOT_ALLOWED;
_EvaluateStack();
if (!fPredicate || fDevice < 0)
return B_NO_INIT;
if (fLive) {
fQueryFd = _kern_open_query(fDevice, fPredicate, B_LIVE_QUERY,
fPort, fToken);
} else
fQueryFd = _kern_open_query(fDevice, fPredicate, 0, -1, -1);
if (fQueryFd < 0)
return fQueryFd;
return B_OK;
}
@@ -586,10 +581,20 @@ BQuery::GetNextRef(entry_ref *ref)
error = B_FILE_ERROR;
if (error == B_OK) {
BPrivate::Storage::LongDirEntry entry;
if (BPrivate::Storage::read_query(fQueryFd, &entry, sizeof(entry), 1) != 1)
error = B_ENTRY_NOT_FOUND;
if (error == B_OK)
*ref = entry_ref(entry.d_pdev, entry.d_pino, entry.d_name);
bool next = true;
while (error == B_OK && next) {
if (GetNextDirents(&entry, sizeof(entry), 1) != 1) {
error = B_ENTRY_NOT_FOUND;
} else {
next = (!strcmp(entry.d_name, ".")
|| !strcmp(entry.d_name, ".."));
}
}
if (error == B_OK) {
ref->device = entry.d_pdev;
ref->directory = entry.d_pino;
error = ref->set_name(entry.d_name);
}
}
return error;
}
@@ -614,12 +619,11 @@ BQuery::GetNextRef(entry_ref *ref)
int32
BQuery::GetNextDirents(struct dirent *buf, size_t length, int32 count)
{
int32 result = (buf ? B_OK : B_BAD_VALUE);
if (result == B_OK && !_HasFetched())
result = B_FILE_ERROR;
if (result == B_OK)
result = read_query(fQueryFd, buf, length, count);
return result;
if (!buf)
return B_BAD_VALUE;
if (!_HasFetched())
return B_FILE_ERROR;
return _kern_read_dir(fQueryFd, buf, length, count);
}
// Rewind
@@ -650,7 +654,7 @@ BQuery::CountEntries()
bool
BQuery::_HasFetched() const
{
return (fQueryFd != NullFd);
return (fQueryFd >= 0);
}
// _PushNode
@@ -758,5 +762,3 @@ void BQuery::_QwertyQuery4() {}
void BQuery::_QwertyQuery5() {}
void BQuery::_QwertyQuery6() {}
+4 -7
View File
@@ -10,6 +10,7 @@
#include <ResourceStrings.h>
#include <new>
#include <stdlib.h>
#include <string.h>
#include <Entry.h>
@@ -17,7 +18,7 @@
#include <Resources.h>
#include <String.h>
#include "kernel_interface.h"
#include <AppMisc.h>
using namespace std;
@@ -139,12 +140,8 @@ BResourceStrings::SetStringFile(const entry_ref *ref)
if (ref) {
fileRef = *ref;
fFileRef = *ref;
} else {
char appPath[B_PATH_NAME_LENGTH];
error = BPrivate::Storage::get_app_path(appPath);
if (error == B_OK)
error = get_ref_for_path(appPath, &fileRef);
}
} else
error = BPrivate::get_app_ref(&fileRef);
// get the BResources
if (error == B_OK) {
BFile file(&fileRef, B_READ_ONLY);
-1
View File
@@ -14,7 +14,6 @@
#include <sys/stat.h>
#include "fsproto.h"
#include "kernel_interface.h"
/*! \fn status_t GetStat(struct stat *st) const
\brief Returns the stat stucture for the node.
+23 -141
View File
@@ -13,7 +13,9 @@
#include <Directory.h>
#include <Entry.h>
#include <Path.h>
#include "kernel_interface.h"
#include <syscalls.h>
#include "storage_support.h"
using namespace std;
@@ -26,8 +28,6 @@ namespace OpenBeOS {
//! Creates an uninitialized BSymLink object.
BSymLink::BSymLink()
: BNode()
// WORKAROUND
, fSecretEntry(new(nothrow) BEntry)
{
}
@@ -36,11 +36,8 @@ BSymLink::BSymLink()
/*! \param link the BSymLink object to be copied
*/
BSymLink::BSymLink(const BSymLink &link)
: BNode()
// WORKAROUND
, fSecretEntry(new(nothrow) BEntry)
: BNode(link)
{
*this = link;
}
// constructor
@@ -49,11 +46,8 @@ BSymLink::BSymLink(const BSymLink &link)
\param ref the entry_ref referring to the symbolic link
*/
BSymLink::BSymLink(const entry_ref *ref)
: BNode()
// WORKAROUND
, fSecretEntry(new(nothrow) BEntry)
: BNode(ref)
{
SetTo(ref);
}
// constructor
@@ -62,11 +56,8 @@ BSymLink::BSymLink(const entry_ref *ref)
\param entry the BEntry referring to the symbolic link
*/
BSymLink::BSymLink(const BEntry *entry)
: BNode()
// WORKAROUND
, fSecretEntry(new(nothrow) BEntry)
: BNode(entry)
{
SetTo(entry);
}
// constructor
@@ -75,11 +66,8 @@ BSymLink::BSymLink(const BEntry *entry)
\param path the symbolic link's path name
*/
BSymLink::BSymLink(const char *path)
: BNode()
// WORKAROUND
, fSecretEntry(new(nothrow) BEntry)
: BNode(path)
{
SetTo(path);
}
// constructor
@@ -90,11 +78,8 @@ BSymLink::BSymLink(const char *path)
\param path the symbolic link's path name relative to \a dir
*/
BSymLink::BSymLink(const BDirectory *dir, const char *path)
: BNode()
// WORKAROUND
, fSecretEntry(new(nothrow) BEntry)
: BNode(dir, path)
{
SetTo(dir, path);
}
// destructor
@@ -104,76 +89,8 @@ BSymLink::BSymLink(const BDirectory *dir, const char *path)
*/
BSymLink::~BSymLink()
{
// WORKAROUND
delete fSecretEntry;
}
// WORKAROUND
status_t
BSymLink::SetTo(const entry_ref *ref)
{
status_t error = BNode::SetTo(ref);
if (fSecretEntry) {
fSecretEntry->Unset();
if (error == B_OK)
fSecretEntry->SetTo(ref);
} else
error = B_NO_MEMORY;
return error;
}
// WORKAROUND
status_t
BSymLink::SetTo(const BEntry *entry)
{
status_t error = BNode::SetTo(entry);
if (fSecretEntry) {
fSecretEntry->Unset();
if (error == B_OK)
*fSecretEntry = *entry;
} else
error = B_NO_MEMORY;
return error;
}
// WORKAROUND
status_t
BSymLink::SetTo(const char *path)
{
status_t error = BNode::SetTo(path);
if (fSecretEntry) {
fSecretEntry->Unset();
if (error == B_OK)
fSecretEntry->SetTo(path);
} else
error = B_NO_MEMORY;
return error;
}
// WORKAROUND
status_t
BSymLink::SetTo(const BDirectory *dir, const char *path)
{
status_t error = BNode::SetTo(dir, path);
if (fSecretEntry) {
fSecretEntry->Unset();
if (error == B_OK)
fSecretEntry->SetTo(dir, path);
} else
error = B_NO_MEMORY;
return error;
}
// WORKAROUND
void
BSymLink::Unset()
{
BNode::Unset();
if (fSecretEntry)
fSecretEntry->Unset();
}
// ReadLink
//! Reads the contents of the symbolic link into a buffer.
/*! \param buf the buffer
@@ -188,30 +105,11 @@ BSymLink::Unset()
ssize_t
BSymLink::ReadLink(char *buf, size_t size)
{
/*
status_t error = (buf ? B_OK : B_BAD_VALUE);
if (error == B_OK && InitCheck() != B_OK)
error = B_FILE_ERROR;
if (error == B_OK)
error = BPrivate::Storage::read_link(get_fd(), buf, size);
return error;
*/
// WORKAROUND
status_t error = (buf ? B_OK : B_BAD_VALUE);
if (error == B_OK && (InitCheck() != B_OK
|| !fSecretEntry
|| fSecretEntry->InitCheck() != B_OK)) {
error = B_FILE_ERROR;
}
entry_ref ref;
if (error == B_OK)
error = fSecretEntry->GetRef(&ref);
char path[B_PATH_NAME_LENGTH];
if (error == B_OK)
error = BPrivate::Storage::entry_ref_to_path(&ref, path, sizeof(path));
if (error == B_OK)
error = BPrivate::Storage::read_link(path, buf, size);
return error;
if (!buf)
return B_BAD_VALUE;
if (InitCheck() != B_OK)
return B_FILE_ERROR;
return _kern_read_link(get_fd(), NULL, buf, size);
}
// MakeLinkedPath
@@ -233,13 +131,12 @@ BSymLink::MakeLinkedPath(const char *dirPath, BPath *path)
// R5 seems to convert the dirPath to a BDirectory, which causes links to
// be resolved, i.e. a "/tmp" dirPath expands to "/boot/var/tmp".
// That does also mean, that the dirPath must exists!
ssize_t result = (dirPath && path ? B_OK : B_BAD_VALUE);
if (result == B_OK) {
BDirectory dir(dirPath);
result = dir.InitCheck();
if (result == B_OK)
result = MakeLinkedPath(&dir, path);
}
if (!dirPath || !path)
return B_BAD_VALUE;
BDirectory dir(dirPath);
ssize_t result = dir.InitCheck();
if (result == B_OK)
result = MakeLinkedPath(&dir, path);
return result;
}
@@ -259,10 +156,10 @@ BSymLink::MakeLinkedPath(const char *dirPath, BPath *path)
ssize_t
BSymLink::MakeLinkedPath(const BDirectory *dir, BPath *path)
{
ssize_t result = (dir && path ? 0 : B_BAD_VALUE);
if (!dir || !path)
return B_BAD_VALUE;
char contents[B_PATH_NAME_LENGTH];
if (result == 0)
result = ReadLink(contents, sizeof(contents));
ssize_t result = ReadLink(contents, sizeof(contents));
if (result >= 0) {
if (BPrivate::Storage::is_absolute_path(contents))
result = path->SetTo(contents);
@@ -291,19 +188,6 @@ BSymLink::IsAbsolute()
return result;
}
// WORKAROUND
BSymLink &
BSymLink::operator=(const BSymLink &link)
{
if (&link != this) { // no need to assign us to ourselves
Unset();
static_cast<BNode&>(*this) = link;
if (fSecretEntry && link.fSecretEntry)
*fSecretEntry = *link.fSecretEntry;
}
return *this;
}
void BSymLink::_MissingSymLink1() {}
void BSymLink::_MissingSymLink2() {}
@@ -316,7 +200,7 @@ void BSymLink::_MissingSymLink6() {}
/*! To be used instead of accessing the BNode's private \c fFd member directly.
\return the file descriptor, or -1, if not properly initialized.
*/
BPrivate::Storage::FileDescriptor
int
BSymLink::get_fd() const
{
return fFd;
@@ -327,5 +211,3 @@ BSymLink::get_fd() const
}; // namespace OpenBeOS
#endif
+45 -8
View File
@@ -12,14 +12,18 @@
*/
#include <errno.h>
#include <string.h>
#include <Bitmap.h>
#include <Directory.h>
#include <fs_info.h>
#include <kernel_interface.h>
#include <fs_interface.h>
#include <Node.h>
#include <Path.h>
#include <Volume.h>
#include <storage_support.h>
#include <syscalls.h>
#ifdef USE_OPENBEOS_NAMESPACE
namespace OpenBeOS {
@@ -272,13 +276,46 @@ status_t
BVolume::SetName(const char *name)
{
// check initialization
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
if (error == B_OK)
error = BPrivate::Storage::set_volume_name(fDevice, name);
// ToDo: change the name of the mount point, too
// (or the link to the boot volume, if that name has been changed)
if (!name || InitCheck() != B_OK)
return B_BAD_VALUE;
if (strlen(name) >= B_FILE_NAME_LENGTH)
return B_NAME_TOO_LONG;
// get the FS stat (including the old name) first
fs_info oldInfo;
if (fs_stat_dev(fDevice, &oldInfo) != 0)
return errno;
if (strcmp(name, oldInfo.volume_name) == 0)
return B_OK;
// set the volume name
fs_info newInfo;
strlcpy(newInfo.volume_name, name, sizeof(newInfo.volume_name));
status_t error = _kern_write_fs_info(fDevice, &newInfo,
FS_WRITE_FSINFO_NAME);
if (error != B_OK)
return error;
// change the name of the mount point
// R5 implementation checks, if an entry with the volume's old name
// exists in the root directory and renames that entry, if it is indeed
// the mount point of the volume (or a link referring to it). In all other
// cases, nothing is done (even if the mount point is named like the
// volume, but lives in a different directory).
// We follow suit for the time being.
// create the entry
BPath entryPath;
BEntry entry;
BEntry traversedEntry;
node_ref entryNodeRef;
if (BPrivate::Storage::check_entry_name(name) == B_OK
&& BPrivate::Storage::check_entry_name(oldInfo.volume_name) == B_OK
&& entryPath.SetTo("/", oldInfo.volume_name) == B_OK
&& entry.SetTo(entryPath.Path(), false) == B_OK
&& entry.Exists()
&& traversedEntry.SetTo(entryPath.Path(), true) == B_OK
&& traversedEntry.GetNodeRef(&entryNodeRef) == B_OK
&& entryNodeRef.device == fDevice
&& entryNodeRef.node == oldInfo.root) {
traversedEntry.Rename(name, false);
}
return error;
}
-1
View File
@@ -17,7 +17,6 @@
#include <Bitmap.h>
#include <Directory.h>
#include <fs_info.h>
#include <kernel_interface.h>
#include <Node.h>
#include <NodeMonitor.h>
#include <VolumeRoster.h>
+5 -5
View File
@@ -15,7 +15,6 @@
#include <MimeType.h>
#include <Path.h>
#include <String.h>
#include <kernel_interface.h>
#include <mime/database_support.h>
#include <storage_support.h>
@@ -144,11 +143,12 @@ status_t
AssociatedTypes::GuessMimeType(const entry_ref *ref, BString *result)
{
// Convert the entry_ref to a filename and then do the check
/*! \todo If the ref is invalid, */
char path[B_PATH_NAME_LENGTH];
status_t err = entry_ref_to_path(ref, path, B_PATH_NAME_LENGTH);
if (!ref)
return B_BAD_VALUE;
BPath path;
status_t err = path.SetTo(ref);
if (!err)
err = GuessMimeType(path, result);
err = GuessMimeType(path.Path(), result);
return err;
}
+3 -3
View File
@@ -7,16 +7,16 @@
MimeUpdateThread implementation
*/
#include "mime/MimeUpdateThread.h"
#include <stdio.h>
#include <Directory.h>
#include <kernel_interface.h>
#include <Message.h>
#include <Path.h>
#include <RegistrarDefs.h>
#include <Volume.h>
#include <stdio.h>
#include <storage_support.h>
#include "mime/MimeUpdateThread.h"
//#define DBG(x) x
#define DBG(x)
-2
View File
@@ -2,7 +2,6 @@ STORAGE_KIT_SOURCE =
# storage
AppFileInfo.cpp
Directory.cpp
# DiskScannerAddOn.cpp
Entry.cpp
EntryList.cpp
File.cpp
@@ -25,7 +24,6 @@ STORAGE_KIT_SOURCE =
SymLink.cpp
Volume.cpp
VolumeRoster.cpp
kernel_interface.POSIX.cpp
storage_support.cpp
# storage/mime
+117 -2
View File
@@ -13,6 +13,9 @@
#include <StorageDefs.h>
#include <SupportDefs.h>
#include <syscalls.h>
#include "storage_support.h"
using namespace std;
@@ -30,9 +33,105 @@ is_absolute_path(const char *path)
}
// parse_path
/*! \brief Parses the supplied path and returns the position of the leaf name
part of the path and the length of its directory path part.
The value returned in \a fullPath is guaranteed to be > 0, i.e. the
function always returns a non-empty directory path part. The leaf name
part may be empty though (i.e. \code leafStart == leafEnd \endcode), which
will happen, if the supplied path consists only of one component.
\param fullPath The path to be parsed.
\param dirEnd Reference to a variable into which the end index of the
directory part shall be written. The index is exclusive.
\param leafStart Reference to a variable into which the start index of
the leaf name part shall be written. The index is inclusive.
\param leafEnd Reference to a variable into which the end index of
the leaf name part shall be written. The index is exclusive.
\return \c B_OK, if everything went fine, B_BAD_VALUE, if the supplied
path is invalid.
*/
status_t
parse_path(const char *fullPath, int &dirEnd, int &leafStart, int &leafEnd)
{
// check path and get length
if (!fullPath)
return B_BAD_VALUE;
int pathLen = strlen(fullPath);
if (pathLen == 0)
return B_BAD_VALUE;
// find then end of the leaf name (skip trailing '/')
int i = pathLen - 1;
while (i >= 0 && fullPath[i] == '/')
i--;
leafEnd = i + 1;
if (leafEnd == 0) {
// fullPath consists of slashes only
dirEnd = leafStart = leafEnd = 1;
return B_OK;
}
// find the start of the leaf name
while (i >= 0 && fullPath[i] != '/')
i--;
leafStart = i + 1;
if (leafStart == 0) {
// fullPath contains only one component
dirEnd = leafStart = leafEnd;
return B_OK;
}
// find the end of the dir path
while (i >= 0 && fullPath[i] == '/')
i--;
dirEnd = i + 1;
if (dirEnd == 0) // => fullPath[0] == '/' (an absolute path)
dirEnd = 1;
return B_OK;
}
// parse_path
/*! \brief Parses the supplied path and returns the leaf name part of the path
and its directory path part.
The value returned in \a fullPath is guaranteed to be > 0, i.e. the
function always returns a non-empty directory path part. The leaf name
part may be empty though (i.e. \code leafStart == leafEnd \endcode), which
will happen, if the supplied path consists only of one component.
\param fullPath The path to be parsed.
\param dirPath Pointer to a character array of size \c B_PATH_NAME_LENGTH
or greater, into which the directory part shall be written.
May be \c NULL.
\param leaf Pointer to a character array of size \c B_FILE_NAME_LENGTH
or greater, into which the leaf name part shall be written.
May be \c NULL.
\return \c B_OK, if everything went fine, B_BAD_VALUE, if the supplied
path is invalid.
*/
status_t
parse_path(const char *fullPath, char *dirPath, char *leaf)
{
// parse the path and check the lengths
int leafStart, leafEnd, dirEnd;
status_t error = parse_path(fullPath, dirEnd, leafStart, leafEnd);
if (error != B_OK)
return error;
if (dirEnd >= B_PATH_NAME_LENGTH
|| leafEnd - leafStart >= B_FILE_NAME_LENGTH) {
return B_NAME_TOO_LONG;
}
// copy the result strings
if (dirPath)
strlcpy(dirPath, fullPath, dirEnd + 1);
if (leaf)
strlcpy(leaf, fullPath + leafStart, leafEnd - leafStart + 1);
return B_OK;
}
// internal_parse_path
static
void
parse_path(const char *fullPath, int &leafStart, int &leafEnd, int &pathEnd)
internal_parse_path(const char *fullPath, int &leafStart, int &leafEnd,
int &pathEnd)
{
if (fullPath == NULL)
return;
@@ -109,7 +208,7 @@ split_path(const char *fullPath, char **path, char **leaf)
return B_BAD_VALUE;
int leafStart, leafEnd, pathEnd, len;
parse_path(fullPath, leafStart, leafEnd, pathEnd);
internal_parse_path(fullPath, leafStart, leafEnd, pathEnd);
try {
// Tidy up/handle special cases
@@ -387,6 +486,22 @@ void escape_path(char *str)
}
}
// device_is_root_device
bool
device_is_root_device(dev_t device)
{
return device == 1;
}
// Close
void
FDCloser::Close()
{
if (fFD >= 0)
_kern_close(fFD);
fFD = -1;
}
}; // namespace Storage
}; // namespace BPrivate
+4 -5
View File
@@ -32,9 +32,9 @@
#include <AppFileInfo.h>
#include <Entry.h>
#include <File.h>
#include <kernel_interface.h> // From the Storage Kit
#include <Message.h>
#include <Mime.h>
#include <Path.h>
#include <Roster.h>
#include <String.h>
#include <storage_support.h>
@@ -309,12 +309,11 @@ RecentEntries::Save(FILE* file, const char *description, const char *tag)
// We're going to need to properly escape the path name we
// get, which will at absolute worst double the length of
// the string.
char path[B_PATH_NAME_LENGTH];
BPath path;
char escapedPath[B_PATH_NAME_LENGTH*2];
status_t outputError = BPrivate::Storage::entry_ref_to_path(&mapItem->first,
path, B_PATH_NAME_LENGTH);
status_t outputError = path.SetTo(&mapItem->first);
if (!outputError) {
BPrivate::Storage::escape_path(path, escapedPath);
BPrivate::Storage::escape_path(path.Path(), escapedPath);
fprintf(file, "%s %s", tag, escapedPath);
std::list<recent_entry*> &list = mapItem->second;
int32 i = 0;