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:
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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() {}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user