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);
|
BDirectory &operator=(const BDirectory &dir);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class BNode;
|
||||||
|
|
||||||
virtual void _ErectorDirectory1();
|
virtual void _ErectorDirectory1();
|
||||||
virtual void _ErectorDirectory2();
|
virtual void _ErectorDirectory2();
|
||||||
virtual void _ErectorDirectory3();
|
virtual void _ErectorDirectory3();
|
||||||
@@ -87,13 +89,14 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void close_fd();
|
virtual void close_fd();
|
||||||
BPrivate::Storage::FileDescriptor get_fd() const;
|
int get_fd() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32 _reservedData[7];
|
uint32 _reservedData[7];
|
||||||
BPrivate::Storage::FileDescriptor fDirFd;
|
int fDirFd;
|
||||||
|
|
||||||
friend class BEntry;
|
friend class BEntry;
|
||||||
|
friend class BFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
#include <Statable.h>
|
#include <Statable.h>
|
||||||
#include <StorageDefs.Private.h>
|
|
||||||
|
|
||||||
#ifdef USE_OPENBEOS_NAMESPACE
|
#ifdef USE_OPENBEOS_NAMESPACE
|
||||||
namespace OpenBeOS {
|
namespace OpenBeOS {
|
||||||
@@ -77,6 +76,11 @@ public:
|
|||||||
BEntry &operator=(const BEntry &item);
|
BEntry &operator=(const BEntry &item);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class BDirectory;
|
||||||
|
friend class BFile;
|
||||||
|
friend class BNode;
|
||||||
|
friend class BSymLink;
|
||||||
|
|
||||||
virtual void _PennyEntry1();
|
virtual void _PennyEntry1();
|
||||||
virtual void _PennyEntry2();
|
virtual void _PennyEntry2();
|
||||||
virtual void _PennyEntry3();
|
virtual void _PennyEntry3();
|
||||||
@@ -90,11 +94,10 @@ private:
|
|||||||
/*! BEntry implementation of BStatable::set_stat() */
|
/*! BEntry implementation of BStatable::set_stat() */
|
||||||
virtual status_t set_stat(struct stat &st, uint32 what);
|
virtual status_t set_stat(struct stat &st, uint32 what);
|
||||||
|
|
||||||
status_t set(BPrivate::Storage::FileDescriptor dir, const char *path,
|
status_t set(int dir, const char *path, bool traverse);
|
||||||
bool traverse);
|
|
||||||
|
|
||||||
/*! File descriptor for the entry's parent directory. */
|
/*! File descriptor for the entry's parent directory. */
|
||||||
BPrivate::Storage::FileDescriptor fDirFd;
|
int fDirFd;
|
||||||
|
|
||||||
/*! Leaf name of the entry. */
|
/*! Leaf name of the entry. */
|
||||||
char *fName;
|
char *fName;
|
||||||
@@ -104,6 +107,8 @@ private:
|
|||||||
|
|
||||||
status_t set_name(const char *name);
|
status_t set_name(const char *name);
|
||||||
|
|
||||||
|
status_t _Rename(BEntry& target, bool clobber);
|
||||||
|
|
||||||
void Dump(const char *name = NULL);
|
void Dump(const char *name = NULL);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -118,7 +123,3 @@ bool operator<(const entry_ref &a, const entry_ref &b);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // _ENTRY_H
|
#endif // _ENTRY_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ private:
|
|||||||
uint32 _reservedData[8];
|
uint32 _reservedData[8];
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BPrivate::Storage::FileDescriptor get_fd() const;
|
int get_fd() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! The file's open mode.
|
//! The file's open mode.
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
#define _NODE_H
|
#define _NODE_H
|
||||||
|
|
||||||
#include <Statable.h>
|
#include <Statable.h>
|
||||||
#include <StorageDefs.Private.h>
|
|
||||||
|
|
||||||
#ifdef USE_OPENBEOS_NAMESPACE
|
#ifdef USE_OPENBEOS_NAMESPACE
|
||||||
namespace OpenBeOS {
|
namespace OpenBeOS {
|
||||||
@@ -115,14 +114,17 @@ private:
|
|||||||
uint32 rudeData[4];
|
uint32 rudeData[4];
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t set_fd(BPrivate::Storage::FileDescriptor fd);
|
status_t set_fd(int fd);
|
||||||
virtual void close_fd();
|
virtual void close_fd();
|
||||||
void set_status(status_t newStatus);
|
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);
|
virtual status_t set_stat(struct stat &st, uint32 what);
|
||||||
|
|
||||||
BPrivate::Storage::FileDescriptor fFd;
|
int fFd;
|
||||||
BPrivate::Storage::FileDescriptor fAttrFd;
|
int fAttrFd;
|
||||||
status_t fCStatus;
|
status_t fCStatus;
|
||||||
|
|
||||||
status_t InitAttrDir();
|
status_t InitAttrDir();
|
||||||
|
|||||||
@@ -15,8 +15,6 @@
|
|||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
#include <StorageDefs.Private.h>
|
|
||||||
|
|
||||||
class BVolume;
|
class BVolume;
|
||||||
struct entry_ref;
|
struct entry_ref;
|
||||||
|
|
||||||
@@ -119,9 +117,7 @@ private:
|
|||||||
bool fLive;
|
bool fLive;
|
||||||
port_id fPort;
|
port_id fPort;
|
||||||
long fToken;
|
long fToken;
|
||||||
BPrivate::Storage::FileDescriptor fQueryFd;
|
int fQueryFd;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _QUERY_H
|
#endif // _QUERY_H
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -39,15 +39,6 @@ public:
|
|||||||
BSymLink(const BDirectory *dir, const char *path);
|
BSymLink(const BDirectory *dir, const char *path);
|
||||||
virtual ~BSymLink();
|
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 ReadLink(char *buf, size_t size);
|
||||||
|
|
||||||
ssize_t MakeLinkedPath(const char *dirPath, BPath *path);
|
ssize_t MakeLinkedPath(const char *dirPath, BPath *path);
|
||||||
@@ -55,11 +46,6 @@ public:
|
|||||||
|
|
||||||
bool IsAbsolute();
|
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:
|
private:
|
||||||
virtual void _MissingSymLink1();
|
virtual void _MissingSymLink1();
|
||||||
virtual void _MissingSymLink2();
|
virtual void _MissingSymLink2();
|
||||||
@@ -68,15 +54,11 @@ private:
|
|||||||
virtual void _MissingSymLink5();
|
virtual void _MissingSymLink5();
|
||||||
virtual void _MissingSymLink6();
|
virtual void _MissingSymLink6();
|
||||||
|
|
||||||
// WORKAROUND
|
uint32 _reservedData[4];
|
||||||
// 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];
|
|
||||||
BEntry *fSecretEntry;
|
BEntry *fSecretEntry;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BPrivate::Storage::FileDescriptor get_fd() const;
|
int get_fd() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef USE_OPENBEOS_NAMESPACE
|
#ifdef USE_OPENBEOS_NAMESPACE
|
||||||
@@ -84,5 +66,3 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // _SYM_LINK_H
|
#endif // _SYM_LINK_H
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,14 +11,22 @@
|
|||||||
#ifndef _STORAGE_SUPPORT_H
|
#ifndef _STORAGE_SUPPORT_H
|
||||||
#define _STORAGE_SUPPORT_H
|
#define _STORAGE_SUPPORT_H
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
namespace Storage {
|
namespace Storage {
|
||||||
|
|
||||||
|
// For convenience:
|
||||||
|
struct LongDirEntry : dirent { char _buffer[B_FILE_NAME_LENGTH]; };
|
||||||
|
|
||||||
//! Returns whether the supplied path is absolute.
|
//! Returns whether the supplied path is absolute.
|
||||||
bool is_absolute_path(const char *path);
|
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
|
//! splits a path name into directory path and leaf name
|
||||||
status_t split_path(const char *fullPath, char *&path, char *&leaf);
|
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);
|
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 Storage
|
||||||
}; // namespace BPrivate
|
}; // namespace BPrivate
|
||||||
|
|
||||||
|
using BPrivate::Storage::FDCloser;
|
||||||
|
|
||||||
#endif // _STORAGE_SUPPORT_H
|
#endif // _STORAGE_SUPPORT_H
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -427,6 +427,7 @@ BAppFileInfo::GetSupportedTypes(BMessage *types) const
|
|||||||
- \c B_NO_INIT: The object is not properly initialized.
|
- \c B_NO_INIT: The object is not properly initialized.
|
||||||
- other error codes
|
- other error codes
|
||||||
*/
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
status_t
|
status_t
|
||||||
BAppFileInfo::SetSupportedTypes(const BMessage *types, bool syncAll)
|
BAppFileInfo::SetSupportedTypes(const BMessage *types, bool syncAll)
|
||||||
{
|
{
|
||||||
@@ -434,19 +435,23 @@ BAppFileInfo::SetSupportedTypes(const BMessage *types, bool syncAll)
|
|||||||
status_t error = B_OK;
|
status_t error = B_OK;
|
||||||
if (error == B_OK && InitCheck() != B_OK)
|
if (error == B_OK && InitCheck() != B_OK)
|
||||||
error = B_NO_INIT;
|
error = B_NO_INIT;
|
||||||
|
printf("check\n");
|
||||||
BMimeType mimeType;
|
BMimeType mimeType;
|
||||||
if (error == B_OK)
|
if (error == B_OK)
|
||||||
error = GetMetaMime(&mimeType);
|
error = GetMetaMime(&mimeType);
|
||||||
|
printf("check\n");
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
if (types) {
|
if (types) {
|
||||||
// check param -- supported types must be valid
|
// check param -- supported types must be valid
|
||||||
const char *type;
|
const char *type;
|
||||||
|
printf("check1\n");
|
||||||
for (int32 i = 0;
|
for (int32 i = 0;
|
||||||
error == B_OK && types->FindString("types", i, &type) == B_OK;
|
error == B_OK && types->FindString("types", i, &type) == B_OK;
|
||||||
i++) {
|
i++) {
|
||||||
if (!BMimeType::IsValid(type))
|
if (!BMimeType::IsValid(type))
|
||||||
error = B_BAD_VALUE;
|
error = B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
printf("check1\n");
|
||||||
// get flattened size
|
// get flattened size
|
||||||
ssize_t size = 0;
|
ssize_t size = 0;
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
@@ -454,6 +459,7 @@ BAppFileInfo::SetSupportedTypes(const BMessage *types, bool syncAll)
|
|||||||
if (size < 0)
|
if (size < 0)
|
||||||
error = size;
|
error = size;
|
||||||
}
|
}
|
||||||
|
printf("check1\n");
|
||||||
// allocate a buffer for the flattened data
|
// allocate a buffer for the flattened data
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
@@ -461,23 +467,28 @@ BAppFileInfo::SetSupportedTypes(const BMessage *types, bool syncAll)
|
|||||||
if (!buffer)
|
if (!buffer)
|
||||||
error = B_NO_MEMORY;
|
error = B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
printf("check1\n");
|
||||||
// flatten the message
|
// flatten the message
|
||||||
if (error == B_OK)
|
if (error == B_OK)
|
||||||
error = types->Flatten(buffer, size);
|
error = types->Flatten(buffer, size);
|
||||||
|
printf("check1\n");
|
||||||
// write the data
|
// write the data
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
error = _WriteData(kSupportedTypesAttribute,
|
error = _WriteData(kSupportedTypesAttribute,
|
||||||
kSupportedTypesResourceID, B_MESSAGE_TYPE,
|
kSupportedTypesResourceID, B_MESSAGE_TYPE,
|
||||||
buffer, size);
|
buffer, size);
|
||||||
}
|
}
|
||||||
|
printf("check1\n");
|
||||||
// clean up
|
// clean up
|
||||||
if (buffer)
|
if (buffer)
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
} else
|
} else
|
||||||
error = _RemoveData(kSupportedTypesAttribute, B_MESSAGE_TYPE);
|
error = _RemoveData(kSupportedTypesAttribute, B_MESSAGE_TYPE);
|
||||||
|
printf("check\n");
|
||||||
// update the MIME database, if the app signature is installed
|
// update the MIME database, if the app signature is installed
|
||||||
if (error == B_OK && mimeType.IsInstalled())
|
if (error == B_OK && mimeType.IsInstalled())
|
||||||
error = mimeType.SetSupportedTypes(types, syncAll);
|
error = mimeType.SetSupportedTypes(types, syncAll);
|
||||||
|
printf("check\n");
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|||||||
+155
-198
@@ -15,8 +15,10 @@
|
|||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include <SymLink.h>
|
#include <SymLink.h>
|
||||||
|
|
||||||
|
#include <syscalls.h>
|
||||||
|
|
||||||
#include "storage_support.h"
|
#include "storage_support.h"
|
||||||
#include "kernel_interface.h"
|
|
||||||
|
|
||||||
#ifdef USE_OPENBEOS_NAMESPACE
|
#ifdef USE_OPENBEOS_NAMESPACE
|
||||||
namespace OpenBeOS {
|
namespace OpenBeOS {
|
||||||
@@ -27,7 +29,7 @@ namespace OpenBeOS {
|
|||||||
BDirectory::BDirectory()
|
BDirectory::BDirectory()
|
||||||
: BNode(),
|
: BNode(),
|
||||||
BEntryList(),
|
BEntryList(),
|
||||||
fDirFd(BPrivate::Storage::NullFd)
|
fDirFd(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +40,7 @@ BDirectory::BDirectory()
|
|||||||
BDirectory::BDirectory(const BDirectory &dir)
|
BDirectory::BDirectory(const BDirectory &dir)
|
||||||
: BNode(),
|
: BNode(),
|
||||||
BEntryList(),
|
BEntryList(),
|
||||||
fDirFd(BPrivate::Storage::NullFd)
|
fDirFd(-1)
|
||||||
{
|
{
|
||||||
*this = dir;
|
*this = dir;
|
||||||
}
|
}
|
||||||
@@ -51,7 +53,7 @@ BDirectory::BDirectory(const BDirectory &dir)
|
|||||||
BDirectory::BDirectory(const entry_ref *ref)
|
BDirectory::BDirectory(const entry_ref *ref)
|
||||||
: BNode(),
|
: BNode(),
|
||||||
BEntryList(),
|
BEntryList(),
|
||||||
fDirFd(BPrivate::Storage::NullFd)
|
fDirFd(-1)
|
||||||
{
|
{
|
||||||
SetTo(ref);
|
SetTo(ref);
|
||||||
}
|
}
|
||||||
@@ -64,7 +66,7 @@ BDirectory::BDirectory(const entry_ref *ref)
|
|||||||
BDirectory::BDirectory(const node_ref *nref)
|
BDirectory::BDirectory(const node_ref *nref)
|
||||||
: BNode(),
|
: BNode(),
|
||||||
BEntryList(),
|
BEntryList(),
|
||||||
fDirFd(BPrivate::Storage::NullFd)
|
fDirFd(-1)
|
||||||
{
|
{
|
||||||
SetTo(nref);
|
SetTo(nref);
|
||||||
}
|
}
|
||||||
@@ -77,7 +79,7 @@ BDirectory::BDirectory(const node_ref *nref)
|
|||||||
BDirectory::BDirectory(const BEntry *entry)
|
BDirectory::BDirectory(const BEntry *entry)
|
||||||
: BNode(),
|
: BNode(),
|
||||||
BEntryList(),
|
BEntryList(),
|
||||||
fDirFd(BPrivate::Storage::NullFd)
|
fDirFd(-1)
|
||||||
{
|
{
|
||||||
SetTo(entry);
|
SetTo(entry);
|
||||||
}
|
}
|
||||||
@@ -90,7 +92,7 @@ BDirectory::BDirectory(const BEntry *entry)
|
|||||||
BDirectory::BDirectory(const char *path)
|
BDirectory::BDirectory(const char *path)
|
||||||
: BNode(),
|
: BNode(),
|
||||||
BEntryList(),
|
BEntryList(),
|
||||||
fDirFd(BPrivate::Storage::NullFd)
|
fDirFd(-1)
|
||||||
{
|
{
|
||||||
SetTo(path);
|
SetTo(path);
|
||||||
}
|
}
|
||||||
@@ -105,7 +107,7 @@ BDirectory::BDirectory(const char *path)
|
|||||||
BDirectory::BDirectory(const BDirectory *dir, const char *path)
|
BDirectory::BDirectory(const BDirectory *dir, const char *path)
|
||||||
: BNode(),
|
: BNode(),
|
||||||
BEntryList(),
|
BEntryList(),
|
||||||
fDirFd(BPrivate::Storage::NullFd)
|
fDirFd(-1)
|
||||||
{
|
{
|
||||||
SetTo(dir, path);
|
SetTo(dir, path);
|
||||||
}
|
}
|
||||||
@@ -139,23 +141,22 @@ BDirectory::~BDirectory()
|
|||||||
- \c B_BUSY: A node was busy.
|
- \c B_BUSY: A node was busy.
|
||||||
- \c B_FILE_ERROR: A general file error.
|
- \c B_FILE_ERROR: A general file error.
|
||||||
- \c B_NO_MORE_FDS: The application has run out of file descriptors.
|
- \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
|
status_t
|
||||||
BDirectory::SetTo(const entry_ref *ref)
|
BDirectory::SetTo(const entry_ref *ref)
|
||||||
{
|
{
|
||||||
Unset();
|
// open node
|
||||||
char path[B_PATH_NAME_LENGTH];
|
status_t error = _SetTo(ref, true);
|
||||||
status_t error = (ref ? B_OK : B_BAD_VALUE);
|
if (error != B_OK)
|
||||||
if (error == B_OK) {
|
|
||||||
error = BPrivate::Storage::entry_ref_to_path(ref, path,
|
|
||||||
B_PATH_NAME_LENGTH);
|
|
||||||
}
|
|
||||||
if (error == B_OK)
|
|
||||||
error = SetTo(path);
|
|
||||||
set_status(error);
|
|
||||||
return error;
|
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);
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTo
|
// SetTo
|
||||||
@@ -200,23 +201,26 @@ BDirectory::SetTo(const node_ref *nref)
|
|||||||
- \c B_BUSY: A node was busy.
|
- \c B_BUSY: A node was busy.
|
||||||
- \c B_FILE_ERROR: A general file error.
|
- \c B_FILE_ERROR: A general file error.
|
||||||
- \c B_NO_MORE_FDS: The application has run out of file descriptors.
|
- \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
|
status_t
|
||||||
BDirectory::SetTo(const BEntry *entry)
|
BDirectory::SetTo(const BEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
Unset();
|
Unset();
|
||||||
entry_ref ref;
|
return (fCStatus = B_BAD_VALUE);
|
||||||
status_t error = (entry ? B_OK : B_BAD_VALUE);
|
}
|
||||||
if (error == B_OK && entry->InitCheck() != B_OK)
|
// open node
|
||||||
error = B_BAD_VALUE;
|
status_t error = _SetTo(entry->fDirFd, entry->fName, true);
|
||||||
if (error == B_OK)
|
if (error != B_OK)
|
||||||
error = entry->GetRef(&ref);
|
|
||||||
if (error == B_OK)
|
|
||||||
error = SetTo(&ref);
|
|
||||||
set_status(error);
|
|
||||||
return error;
|
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
|
// SetTo
|
||||||
@@ -239,30 +243,18 @@ BDirectory::SetTo(const BEntry *entry)
|
|||||||
status_t
|
status_t
|
||||||
BDirectory::SetTo(const char *path)
|
BDirectory::SetTo(const char *path)
|
||||||
{
|
{
|
||||||
|
// 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();
|
Unset();
|
||||||
status_t result = (path ? B_OK : B_BAD_VALUE);
|
return (fCStatus = error);
|
||||||
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)
|
return B_OK;
|
||||||
fDirFd = newDirFd;
|
|
||||||
else
|
|
||||||
BPrivate::Storage::close_dir(newDirFd);
|
|
||||||
}
|
|
||||||
// finally set the BNode status
|
|
||||||
set_status(result);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTo
|
// SetTo
|
||||||
@@ -283,22 +275,26 @@ BDirectory::SetTo(const char *path)
|
|||||||
- \c B_FILE_ERROR: A general file error.
|
- \c B_FILE_ERROR: A general file error.
|
||||||
- \c B_NO_MORE_FDS: The application has run out of file descriptors.
|
- \c B_NO_MORE_FDS: The application has run out of file descriptors.
|
||||||
- \c B_NOT_A_DIRECTORY: \a path includes a non-directory.
|
- \c B_NOT_A_DIRECTORY: \a path includes a non-directory.
|
||||||
\todo Implemented using SetTo(BEntry*). Check, if necessary to reimplement!
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BDirectory::SetTo(const BDirectory *dir, const char *path)
|
BDirectory::SetTo(const BDirectory *dir, const char *path)
|
||||||
{
|
{
|
||||||
|
if (!dir || !path || BPrivate::Storage::is_absolute_path(path)) {
|
||||||
Unset();
|
Unset();
|
||||||
status_t error = (dir && path ? B_OK : B_BAD_VALUE);
|
return (fCStatus = B_BAD_VALUE);
|
||||||
if (error == B_OK && BPrivate::Storage::is_absolute_path(path))
|
}
|
||||||
error = B_BAD_VALUE;
|
// open node
|
||||||
BEntry entry;
|
status_t error = _SetTo(dir->fDirFd, path, true);
|
||||||
if (error == B_OK)
|
if (error != B_OK)
|
||||||
error = entry.SetTo(dir, path);
|
|
||||||
if (error == B_OK)
|
|
||||||
error = SetTo(&entry);
|
|
||||||
set_status(error);
|
|
||||||
return error;
|
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
|
// GetEntry
|
||||||
@@ -316,23 +312,15 @@ BDirectory::SetTo(const BDirectory *dir, const char *path)
|
|||||||
- \c B_BUSY: A node was busy.
|
- \c B_BUSY: A node was busy.
|
||||||
- \c B_FILE_ERROR: A general file error.
|
- \c B_FILE_ERROR: A general file error.
|
||||||
- \c B_NO_MORE_FDS: The application has run out of file descriptors.
|
- \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
|
status_t
|
||||||
BDirectory::GetEntry(BEntry *entry) const
|
BDirectory::GetEntry(BEntry *entry) const
|
||||||
{
|
{
|
||||||
status_t error = (entry ? B_OK : B_BAD_VALUE);
|
if (!entry)
|
||||||
if (entry)
|
return B_BAD_VALUE;
|
||||||
entry->Unset();
|
if (InitCheck() != B_OK)
|
||||||
if (error == B_OK && InitCheck() != B_OK)
|
return B_NO_INIT;
|
||||||
error = B_NO_INIT;
|
return entry->SetTo(this, ".", false);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRootDirectory
|
// 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
|
// 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.
|
// the entry and check, if the latter is a prefix of the first one.
|
||||||
if (result && InitCheck() == B_OK) {
|
if (result && InitCheck() == B_OK) {
|
||||||
char dirPath[B_PATH_NAME_LENGTH];
|
BPath dirPath(this, ".", true);
|
||||||
char entryPath[B_PATH_NAME_LENGTH];
|
BPath entryPath(entry);
|
||||||
result = (BPrivate::Storage::dir_to_path(fDirFd, dirPath,
|
if (dirPath.InitCheck() == B_OK && entryPath.InitCheck() == B_OK) {
|
||||||
B_PATH_NAME_LENGTH) == B_OK);
|
result = !strncmp(dirPath.Path(), entryPath.Path(),
|
||||||
entry_ref ref;
|
strlen(dirPath.Path()));
|
||||||
if (result)
|
} else
|
||||||
result = (entry->GetRef(&ref) == B_OK);
|
result = false;
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -532,22 +513,17 @@ BDirectory::Contains(const BEntry *entry, int32 nodeFlags) const
|
|||||||
status_t
|
status_t
|
||||||
BDirectory::GetStatFor(const char *path, struct stat *st) const
|
BDirectory::GetStatFor(const char *path, struct stat *st) const
|
||||||
{
|
{
|
||||||
status_t error = (st ? B_OK : B_BAD_VALUE);
|
if (!st)
|
||||||
if (error == B_OK && InitCheck() != B_OK)
|
return B_BAD_VALUE;
|
||||||
error = B_NO_INIT;
|
if (InitCheck() != B_OK)
|
||||||
if (error == B_OK) {
|
return B_NO_INIT;
|
||||||
|
status_t error = B_OK;
|
||||||
if (path) {
|
if (path) {
|
||||||
if (strlen(path) == 0)
|
if (strlen(path) == 0)
|
||||||
error = B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
else {
|
error = _kern_read_stat(fDirFd, path, false, st, sizeof(struct stat));
|
||||||
BEntry entry(this, path);
|
|
||||||
error = entry.InitCheck();
|
|
||||||
if (error == B_OK)
|
|
||||||
error = entry.GetStat(st);
|
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
error = GetStat(st);
|
error = GetStat(st);
|
||||||
}
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,15 +589,18 @@ BDirectory::GetNextRef(entry_ref *ref)
|
|||||||
BPrivate::Storage::LongDirEntry entry;
|
BPrivate::Storage::LongDirEntry entry;
|
||||||
bool next = true;
|
bool next = true;
|
||||||
while (error == B_OK && next) {
|
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;
|
error = B_ENTRY_NOT_FOUND;
|
||||||
if (error == B_OK) {
|
} else {
|
||||||
next = (!strcmp(entry.d_name, ".")
|
next = (!strcmp(entry.d_name, ".")
|
||||||
|| !strcmp(entry.d_name, ".."));
|
|| !strcmp(entry.d_name, ".."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (error == B_OK)
|
if (error == B_OK) {
|
||||||
*ref = entry_ref(entry.d_pdev, entry.d_pino, entry.d_name);
|
ref->device = entry.d_pdev;
|
||||||
|
ref->directory = entry.d_pino;
|
||||||
|
error = ref->set_name(entry.d_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -650,12 +629,11 @@ BDirectory::GetNextRef(entry_ref *ref)
|
|||||||
int32
|
int32
|
||||||
BDirectory::GetNextDirents(dirent *buf, size_t bufSize, int32 count)
|
BDirectory::GetNextDirents(dirent *buf, size_t bufSize, int32 count)
|
||||||
{
|
{
|
||||||
int32 result = (buf ? B_OK : B_BAD_VALUE);
|
if (!buf)
|
||||||
if (result == B_OK && InitCheck() != B_OK)
|
return B_BAD_VALUE;
|
||||||
result = B_FILE_ERROR;
|
if (InitCheck() != B_OK)
|
||||||
if (result == B_OK)
|
return B_FILE_ERROR;
|
||||||
result = BPrivate::Storage::read_dir(fDirFd, buf, bufSize, count);
|
return _kern_read_dir(fDirFd, buf, bufSize, count);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewind
|
// Rewind
|
||||||
@@ -673,12 +651,9 @@ BDirectory::GetNextDirents(dirent *buf, size_t bufSize, int32 count)
|
|||||||
status_t
|
status_t
|
||||||
BDirectory::Rewind()
|
BDirectory::Rewind()
|
||||||
{
|
{
|
||||||
status_t error = B_OK;
|
if (InitCheck() != B_OK)
|
||||||
if (error == B_OK && InitCheck() != B_OK)
|
return B_FILE_ERROR;
|
||||||
error = B_FILE_ERROR;
|
return _kern_rewind_dir(fDirFd);
|
||||||
if (error == B_OK)
|
|
||||||
error = BPrivate::Storage::rewind_dir(fDirFd);
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CountEntries
|
// CountEntries
|
||||||
@@ -700,20 +675,16 @@ int32
|
|||||||
BDirectory::CountEntries()
|
BDirectory::CountEntries()
|
||||||
{
|
{
|
||||||
status_t error = Rewind();
|
status_t error = Rewind();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
int32 count = 0;
|
int32 count = 0;
|
||||||
if (error == B_OK) {
|
|
||||||
BPrivate::Storage::LongDirEntry entry;
|
BPrivate::Storage::LongDirEntry entry;
|
||||||
while (error == B_OK) {
|
while (error == B_OK) {
|
||||||
if (BPrivate::Storage::read_dir(fDirFd, &entry, sizeof(entry), 1) != 1)
|
if (GetNextDirents(&entry, sizeof(entry), 1) != 1)
|
||||||
error = B_ENTRY_NOT_FOUND;
|
break;
|
||||||
if (error == B_OK
|
if (strcmp(entry.d_name, ".") != 0 && strcmp(entry.d_name, "..") != 0)
|
||||||
&& strcmp(entry.d_name, ".") && strcmp(entry.d_name, "..")) {
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (error == B_ENTRY_NOT_FOUND)
|
|
||||||
error = B_OK;
|
|
||||||
}
|
|
||||||
Rewind();
|
Rewind();
|
||||||
return (error == B_OK ? count : error);
|
return (error == B_OK ? count : error);
|
||||||
}
|
}
|
||||||
@@ -740,24 +711,20 @@ BDirectory::CountEntries()
|
|||||||
status_t
|
status_t
|
||||||
BDirectory::CreateDirectory(const char *path, BDirectory *dir)
|
BDirectory::CreateDirectory(const char *path, BDirectory *dir)
|
||||||
{
|
{
|
||||||
status_t error = (path ? B_OK : B_BAD_VALUE);
|
if (!path)
|
||||||
if (error == B_OK) {
|
return B_BAD_VALUE;
|
||||||
// get the actual (absolute) path using BEntry's help
|
// create the dir
|
||||||
BEntry entry;
|
status_t error = _kern_create_dir(fDirFd, path,
|
||||||
if (InitCheck() == B_OK && !BPrivate::Storage::is_absolute_path(path))
|
S_IRWXU | S_IRWXG | S_IRWXU);
|
||||||
entry.SetTo(this, path);
|
if (error != B_OK)
|
||||||
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;
|
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
|
// CreateFile
|
||||||
@@ -790,20 +757,20 @@ BDirectory::CreateDirectory(const char *path, BDirectory *dir)
|
|||||||
status_t
|
status_t
|
||||||
BDirectory::CreateFile(const char *path, BFile *file, bool failIfExists)
|
BDirectory::CreateFile(const char *path, BFile *file, bool failIfExists)
|
||||||
{
|
{
|
||||||
status_t error (path ? B_OK : B_BAD_VALUE);
|
if (!path)
|
||||||
if (error == B_OK) {
|
return B_BAD_VALUE;
|
||||||
// Let BFile do the dirty job.
|
// Let BFile do the dirty job.
|
||||||
uint32 openMode = B_READ_WRITE | B_CREATE_FILE
|
uint32 openMode = B_READ_WRITE | B_CREATE_FILE
|
||||||
| (failIfExists ? B_FAIL_IF_EXISTS : 0);
|
| (failIfExists ? B_FAIL_IF_EXISTS : 0);
|
||||||
BFile tmpFile;
|
BFile tmpFile;
|
||||||
BFile *realFile = (file ? file : &tmpFile);
|
BFile *realFile = (file ? file : &tmpFile);
|
||||||
|
status_t error = B_OK;
|
||||||
if (InitCheck() == B_OK && !BPrivate::Storage::is_absolute_path(path))
|
if (InitCheck() == B_OK && !BPrivate::Storage::is_absolute_path(path))
|
||||||
error = realFile->SetTo(this, path, openMode);
|
error = realFile->SetTo(this, path, openMode);
|
||||||
else
|
else
|
||||||
error = realFile->SetTo(path, openMode);
|
error = realFile->SetTo(path, openMode);
|
||||||
if (error != B_OK)
|
if (error != B_OK && file) // mimic R5 behavior
|
||||||
realFile->Unset();
|
file->Unset();
|
||||||
}
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -831,29 +798,25 @@ status_t
|
|||||||
BDirectory::CreateSymLink(const char *path, const char *linkToPath,
|
BDirectory::CreateSymLink(const char *path, const char *linkToPath,
|
||||||
BSymLink *link)
|
BSymLink *link)
|
||||||
{
|
{
|
||||||
status_t error = (path && linkToPath ? B_OK : B_BAD_VALUE);
|
if (!path || !linkToPath)
|
||||||
if (error == B_OK) {
|
return B_BAD_VALUE;
|
||||||
// get the actual (absolute) path using BEntry's help
|
// create the symlink
|
||||||
BEntry entry;
|
status_t error = _kern_create_symlink(fDirFd, path, linkToPath,
|
||||||
if (InitCheck() == B_OK && !BPrivate::Storage::is_absolute_path(path))
|
S_IRWXU | S_IRWXG | S_IRWXU);
|
||||||
entry.SetTo(this, path);
|
if (error != B_OK)
|
||||||
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;
|
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.
|
//! 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.
|
it will refer to the same directory, unless an error occurs.
|
||||||
\param dir the original BDirectory
|
\param dir the original BDirectory
|
||||||
\return a reference to this 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
|
if (&dir != this) { // no need to assign us to ourselves
|
||||||
Unset();
|
Unset();
|
||||||
if (dir.InitCheck() == B_OK) {
|
if (dir.InitCheck() == B_OK)
|
||||||
*((BNode*)this) = dir;
|
SetTo(&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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -891,9 +846,9 @@ void BDirectory::_ErectorDirectory6() {}
|
|||||||
void
|
void
|
||||||
BDirectory::close_fd()
|
BDirectory::close_fd()
|
||||||
{
|
{
|
||||||
if (fDirFd != BPrivate::Storage::NullFd) {
|
if (fDirFd >= 0) {
|
||||||
BPrivate::Storage::close_dir(fDirFd);
|
_kern_close(fDirFd);
|
||||||
fDirFd = BPrivate::Storage::NullFd;
|
fDirFd = -1;
|
||||||
}
|
}
|
||||||
BNode::close_fd();
|
BNode::close_fd();
|
||||||
}
|
}
|
||||||
@@ -903,7 +858,7 @@ BDirectory::close_fd()
|
|||||||
directly.
|
directly.
|
||||||
\return the file descriptor, or -1, if not properly initialized.
|
\return the file descriptor, or -1, if not properly initialized.
|
||||||
*/
|
*/
|
||||||
BPrivate::Storage::FileDescriptor
|
int
|
||||||
BDirectory::get_fd() const
|
BDirectory::get_fd() const
|
||||||
{
|
{
|
||||||
return fDirFd;
|
return fDirFd;
|
||||||
@@ -934,52 +889,54 @@ BDirectory::get_fd() const
|
|||||||
status_t
|
status_t
|
||||||
create_directory(const char *path, mode_t mode)
|
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
|
// 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
|
// 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
|
// 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
|
// to create it. This goes on, until we're done with the input path or
|
||||||
// an error occurs.
|
// an error occurs.
|
||||||
status_t error = (path ? B_OK : B_BAD_VALUE);
|
|
||||||
if (error == B_OK) {
|
|
||||||
BPath dirPath;
|
BPath dirPath;
|
||||||
char *component;
|
char *component;
|
||||||
int32 nextComponent;
|
int32 nextComponent;
|
||||||
do {
|
do {
|
||||||
// get the next path component
|
// get the next path component
|
||||||
error = BPrivate::Storage::parse_first_path_component(path, component,
|
status_t error = BPrivate::Storage::parse_first_path_component(path,
|
||||||
nextComponent);
|
component, nextComponent);
|
||||||
if (error == B_OK) {
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
// append it to the BPath
|
// append it to the BPath
|
||||||
if (dirPath.InitCheck() == B_NO_INIT) // first component
|
if (dirPath.InitCheck() == B_NO_INIT) // first component
|
||||||
error = dirPath.SetTo(component);
|
error = dirPath.SetTo(component);
|
||||||
else
|
else
|
||||||
error = dirPath.Append(component);
|
error = dirPath.Append(component);
|
||||||
delete[] component;
|
delete[] component;
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
path += nextComponent;
|
path += nextComponent;
|
||||||
// create a BEntry from the BPath
|
// create a BEntry from the BPath
|
||||||
BEntry entry;
|
BEntry entry;
|
||||||
if (error == B_OK)
|
|
||||||
error = entry.SetTo(dirPath.Path(), true);
|
error = entry.SetTo(dirPath.Path(), true);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
// check, if it exists
|
// check, if it exists
|
||||||
if (error == B_OK) {
|
|
||||||
if (entry.Exists()) {
|
if (entry.Exists()) {
|
||||||
// yep, it exists
|
// yep, it exists
|
||||||
if (!entry.IsDirectory()) // but is no directory
|
if (!entry.IsDirectory()) // but is no directory
|
||||||
error = B_NOT_A_DIRECTORY;
|
return B_NOT_A_DIRECTORY;
|
||||||
} else // it doesn't exists -- create it
|
} else {
|
||||||
error = BPrivate::Storage::create_dir(dirPath.Path(), mode);
|
// it doesn't exist -- create it
|
||||||
}
|
error = _kern_create_dir(-1, dirPath.Path(), mode);
|
||||||
}
|
if (error != B_OK)
|
||||||
} while (error == B_OK && nextComponent != 0);
|
|
||||||
}
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
} while (nextComponent != 0);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_OPENBEOS_NAMESPACE
|
#ifdef USE_OPENBEOS_NAMESPACE
|
||||||
}; // namespace OpenBeOS
|
}; // namespace OpenBeOS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+285
-342
@@ -10,14 +10,17 @@
|
|||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include <SymLink.h>
|
#include <SymLink.h>
|
||||||
#include "kernel_interface.h"
|
|
||||||
#include "storage_support.h"
|
#include "storage_support.h"
|
||||||
|
|
||||||
|
#include <syscalls.h>
|
||||||
|
|
||||||
#ifdef USE_OPENBEOS_NAMESPACE
|
#ifdef USE_OPENBEOS_NAMESPACE
|
||||||
using namespace OpenBeOS;
|
using namespace OpenBeOS;
|
||||||
#endif
|
#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.
|
//! Destroys the object and frees the storage allocated for the leaf name, if necessary.
|
||||||
entry_ref::~entry_ref()
|
entry_ref::~entry_ref()
|
||||||
{
|
{
|
||||||
if (name != NULL)
|
free(name);
|
||||||
delete [] name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Set the entry_ref's leaf name, freeing the storage allocated for any previous
|
/*! \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)
|
status_t entry_ref::set_name(const char *name)
|
||||||
{
|
{
|
||||||
if (this->name != NULL) {
|
free(this->name);
|
||||||
delete [] this->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
this->name = NULL;
|
this->name = NULL;
|
||||||
} else {
|
} else {
|
||||||
this->name = new(nothrow) char[strlen(name)+1];
|
this->name = strdup(name);
|
||||||
if (this->name == NULL)
|
if (!this->name)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
strcpy(this->name, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -220,7 +219,7 @@ entry_ref::operator=(const entry_ref &ref)
|
|||||||
- operator=(const BEntry&)
|
- operator=(const BEntry&)
|
||||||
*/
|
*/
|
||||||
BEntry::BEntry()
|
BEntry::BEntry()
|
||||||
: fDirFd(BPrivate::Storage::NullFd),
|
: fDirFd(-1),
|
||||||
fName(NULL),
|
fName(NULL),
|
||||||
fCStatus(B_NO_INIT)
|
fCStatus(B_NO_INIT)
|
||||||
{
|
{
|
||||||
@@ -237,7 +236,7 @@ BEntry::BEntry()
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
BEntry::BEntry(const BDirectory *dir, const char *path, bool traverse)
|
BEntry::BEntry(const BDirectory *dir, const char *path, bool traverse)
|
||||||
: fDirFd(BPrivate::Storage::NullFd),
|
: fDirFd(-1),
|
||||||
fName(NULL),
|
fName(NULL),
|
||||||
fCStatus(B_NO_INIT)
|
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)
|
BEntry::BEntry(const entry_ref *ref, bool traverse)
|
||||||
: fDirFd(BPrivate::Storage::NullFd),
|
: fDirFd(-1),
|
||||||
fName(NULL),
|
fName(NULL),
|
||||||
fCStatus(B_NO_INIT)
|
fCStatus(B_NO_INIT)
|
||||||
{
|
{
|
||||||
@@ -274,7 +273,7 @@ BEntry::BEntry(const entry_ref *ref, bool traverse)
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
BEntry::BEntry(const char *path, bool traverse)
|
BEntry::BEntry(const char *path, bool traverse)
|
||||||
: fDirFd(BPrivate::Storage::NullFd),
|
: fDirFd(-1),
|
||||||
fName(NULL),
|
fName(NULL),
|
||||||
fCStatus(B_NO_INIT)
|
fCStatus(B_NO_INIT)
|
||||||
{
|
{
|
||||||
@@ -286,7 +285,7 @@ BEntry::BEntry(const char *path, bool traverse)
|
|||||||
\see operator=(const BEntry&)
|
\see operator=(const BEntry&)
|
||||||
*/
|
*/
|
||||||
BEntry::BEntry(const BEntry &entry)
|
BEntry::BEntry(const BEntry &entry)
|
||||||
: fDirFd(BPrivate::Storage::NullFd),
|
: fDirFd(-1),
|
||||||
fName(NULL),
|
fName(NULL),
|
||||||
fCStatus(B_NO_INIT)
|
fCStatus(B_NO_INIT)
|
||||||
{
|
{
|
||||||
@@ -321,12 +320,9 @@ BEntry::InitCheck() const
|
|||||||
bool
|
bool
|
||||||
BEntry::Exists() const
|
BEntry::Exists() const
|
||||||
{
|
{
|
||||||
if (fCStatus != B_OK)
|
// just stat the beast
|
||||||
return false;
|
struct stat st;
|
||||||
|
return (GetStat(&st) == B_OK);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Fills in a stat structure for the entry. The information is copied into
|
/*! \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)
|
if (fCStatus != B_OK)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
return _kern_read_stat(fDirFd, fName, false, result, sizeof(struct stat));
|
||||||
entry_ref ref;
|
|
||||||
status_t status = GetRef(&ref);
|
|
||||||
if (status != B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
return BPrivate::Storage::get_stat(ref, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Reinitializes the BEntry to the path or directory path combination,
|
/*! \brief Reinitializes the BEntry to the path or directory path combination,
|
||||||
@@ -360,45 +350,30 @@ BEntry::GetStat(struct stat *result) const
|
|||||||
\return
|
\return
|
||||||
- \c B_OK - Success
|
- \c B_OK - Success
|
||||||
- "error code" - Failure
|
- "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
|
status_t
|
||||||
BEntry::SetTo(const BDirectory *dir, const char *path, bool traverse)
|
BEntry::SetTo(const BDirectory *dir, const char *path, bool traverse)
|
||||||
{
|
{
|
||||||
Unset();
|
// check params
|
||||||
if (dir == NULL)
|
if (!dir)
|
||||||
return (fCStatus = B_BAD_VALUE);
|
return (fCStatus = B_BAD_VALUE);
|
||||||
|
if (path && path[0] == '\0') // R5 behaviour
|
||||||
|
path = NULL;
|
||||||
|
|
||||||
|
// if path is absolute, let the path-only SetTo() do the job
|
||||||
|
if (BPrivate::Storage::is_absolute_path(path))
|
||||||
|
return SetTo(path, traverse);
|
||||||
|
|
||||||
|
Unset();
|
||||||
|
|
||||||
fCStatus = B_OK;
|
|
||||||
if (BPrivate::Storage::is_absolute_path(path)) {
|
|
||||||
SetTo(path, traverse);
|
|
||||||
} else {
|
|
||||||
if (dir->InitCheck() != B_OK)
|
if (dir->InitCheck() != B_OK)
|
||||||
fCStatus = B_BAD_VALUE;
|
fCStatus = B_BAD_VALUE;
|
||||||
// get the dir's path
|
|
||||||
char rootPath[B_PATH_NAME_LENGTH];
|
// dup() the dir's FD and let set() do the rest
|
||||||
if (fCStatus == B_OK) {
|
int dirFD = _kern_dup(dir->get_fd());
|
||||||
fCStatus = BPrivate::Storage::dir_to_path(dir->get_fd(), rootPath,
|
if (dirFD < 0)
|
||||||
B_PATH_NAME_LENGTH);
|
return (fCStatus = dirFD);
|
||||||
}
|
return (fCStatus = set(dirFD, path, traverse));
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Reinitializes the BEntry to the entry_ref, resolving symlinks if
|
/*! \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
|
\return
|
||||||
- \c B_OK - Success
|
- \c B_OK - Success
|
||||||
- "error code" - Failure
|
- "error code" - Failure
|
||||||
|
|
||||||
\todo Implemented using entry_ref_to_path(). Reimplement!
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BEntry::SetTo(const entry_ref *ref, bool traverse)
|
BEntry::SetTo(const entry_ref *ref, bool traverse)
|
||||||
{
|
{
|
||||||
Unset();
|
Unset();
|
||||||
if (ref == NULL) {
|
if (ref == NULL)
|
||||||
return (fCStatus = B_BAD_VALUE);
|
return (fCStatus = B_BAD_VALUE);
|
||||||
}
|
|
||||||
|
|
||||||
char path[B_PATH_NAME_LENGTH];
|
// open the directory and let set() do the rest
|
||||||
|
int dirFD = _kern_open_dir_entry_ref(ref->device, ref->directory, NULL);
|
||||||
fCStatus = BPrivate::Storage::entry_ref_to_path(ref, path,
|
if (dirFD < 0)
|
||||||
B_PATH_NAME_LENGTH);
|
return (fCStatus = dirFD);
|
||||||
return (fCStatus == B_OK) ? SetTo(path, traverse) : fCStatus ;
|
return (fCStatus = set(dirFD, ref->name, traverse));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Reinitializes the BEntry object to the path, resolving symlinks if
|
/*! \brief Reinitializes the BEntry object to the path, resolving symlinks if
|
||||||
@@ -431,35 +403,15 @@ BEntry::SetTo(const entry_ref *ref, bool traverse)
|
|||||||
\return
|
\return
|
||||||
- \c B_OK - Success
|
- \c B_OK - Success
|
||||||
- "error code" - Failure
|
- "error code" - Failure
|
||||||
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BEntry::SetTo(const char *path, bool traverse)
|
BEntry::SetTo(const char *path, bool traverse)
|
||||||
{
|
{
|
||||||
Unset();
|
Unset();
|
||||||
// check the argument
|
// check the argument
|
||||||
fCStatus = (path ? B_OK : B_BAD_VALUE);
|
if (!path)
|
||||||
if (fCStatus == B_OK)
|
return (fCStatus = B_BAD_VALUE);
|
||||||
fCStatus = BPrivate::Storage::check_path_name(path);
|
return (fCStatus = set(-1, path, traverse));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Reinitializes the BEntry to an uninitialized BEntry object */
|
/*! \brief Reinitializes the BEntry to an uninitialized BEntry object */
|
||||||
@@ -467,16 +419,15 @@ void
|
|||||||
BEntry::Unset()
|
BEntry::Unset()
|
||||||
{
|
{
|
||||||
// Close the directory
|
// Close the directory
|
||||||
if (fDirFd != BPrivate::Storage::NullFd) {
|
if (fDirFd >= 0) {
|
||||||
BPrivate::Storage::close_dir(fDirFd);
|
_kern_close(fDirFd);
|
||||||
|
// BPrivate::Storage::close_dir(fDirFd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free our leaf name
|
// Free our leaf name
|
||||||
if (fName != NULL) {
|
free(fName);
|
||||||
delete [] fName;
|
|
||||||
}
|
|
||||||
|
|
||||||
fDirFd = BPrivate::Storage::NullFd;
|
fDirFd = -1;
|
||||||
fName = NULL;
|
fName = NULL;
|
||||||
fCStatus = B_NO_INIT;
|
fCStatus = B_NO_INIT;
|
||||||
}
|
}
|
||||||
@@ -499,7 +450,8 @@ BEntry::GetRef(entry_ref *ref) const
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
struct stat st;
|
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) {
|
if (error == B_OK) {
|
||||||
ref->device = st.st_dev;
|
ref->device = st.st_dev;
|
||||||
ref->directory = st.st_ino;
|
ref->directory = st.st_ino;
|
||||||
@@ -563,44 +515,30 @@ BEntry::GetPath(BPath *path) const
|
|||||||
- \c B_OK - Success
|
- \c B_OK - Success
|
||||||
- \c B_ENTRY_NOT_FOUND - Attempted to get the parent of the root directory \c "/"
|
- \c B_ENTRY_NOT_FOUND - Attempted to get the parent of the root directory \c "/"
|
||||||
- "error code" - Failure
|
- "error code" - Failure
|
||||||
|
|
||||||
*/
|
*/
|
||||||
status_t BEntry::GetParent(BEntry *entry) const
|
status_t BEntry::GetParent(BEntry *entry) const
|
||||||
{
|
{
|
||||||
|
// check parameter and initialization
|
||||||
if (fCStatus != B_OK)
|
if (fCStatus != B_OK)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
// check whether we are the root directory
|
||||||
// Convert ourselves to a entry_ref and change the
|
// It is sufficient to check whether our leaf name is ".".
|
||||||
// leaf name to "."
|
if (strcmp(fName, ".") == 0)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
entry_ref ref;
|
// open the parent directory
|
||||||
status_t status;
|
char leafName[B_FILE_NAME_LENGTH];
|
||||||
|
int parentFD = _kern_open_parent_dir(fDirFd, leafName, B_FILE_NAME_LENGTH);
|
||||||
status = GetRef(&ref);
|
if (parentFD < 0)
|
||||||
if (status == B_OK) {
|
return parentFD;
|
||||||
|
// init the entry
|
||||||
// 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
|
|
||||||
entry->Unset();
|
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.
|
/*! \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_OK - Success
|
||||||
- \c B_ENTRY_NOT_FOUND - Attempted to get the parent of the root directory \c "/"
|
- \c B_ENTRY_NOT_FOUND - Attempted to get the parent of the root directory \c "/"
|
||||||
- "error code" - Failure
|
- "error code" - Failure
|
||||||
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BEntry::GetParent(BDirectory *dir) const
|
BEntry::GetParent(BDirectory *dir) const
|
||||||
{
|
{
|
||||||
|
// check initialization and parameter
|
||||||
if (fCStatus != B_OK)
|
if (fCStatus != B_OK)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
|
||||||
if (dir == NULL)
|
if (dir == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
// check whether we are the root directory
|
||||||
entry_ref ref;
|
// It is sufficient to check whether our leaf name is ".".
|
||||||
status_t status;
|
if (strcmp(fName, ".") == 0)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
status = GetRef(&ref);
|
// get a node ref for the directory and init it
|
||||||
if (status == B_OK) {
|
struct stat st;
|
||||||
|
status_t error = _kern_read_stat(fDirFd, NULL, false, &st,
|
||||||
// Verify we aren't an entry representing "/"
|
sizeof(struct stat));
|
||||||
status = BPrivate::Storage::entry_ref_is_root_dir(&ref) ? (status_t)B_ENTRY_NOT_FOUND : (status_t)B_OK ;
|
if (error != B_OK)
|
||||||
if (status == B_OK) {
|
return error;
|
||||||
|
node_ref ref;
|
||||||
// Now point the entry_ref to the parent directory (instead of ourselves)
|
ref.device = st.st_dev;
|
||||||
status = ref.set_name(".");
|
ref.node = st.st_ino;
|
||||||
if (status == B_OK) {
|
return dir->SetTo(&ref);
|
||||||
dir->SetTo(&ref);
|
// TODO: This can be optimized: We already have a FD for the directory,
|
||||||
return dir->InitCheck();
|
// so we could dup() it and set it on the directory. We just need a private
|
||||||
}
|
// API for being able to do that.
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we get this far, an error occured, so we Unset() the
|
|
||||||
// argument as dictated by the BeBook
|
|
||||||
dir->Unset();
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Gets the name of the entry's leaf.
|
/*! \brief Gets the name of the entry's leaf.
|
||||||
@@ -657,7 +587,6 @@ BEntry::GetParent(BDirectory *dir) const
|
|||||||
\return
|
\return
|
||||||
- \c B_OK - Success
|
- \c B_OK - Success
|
||||||
- "error code" - Failure
|
- "error code" - Failure
|
||||||
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BEntry::GetName(char *buffer) const
|
BEntry::GetName(char *buffer) const
|
||||||
@@ -696,47 +625,26 @@ BEntry::GetName(char *buffer) const
|
|||||||
status_t
|
status_t
|
||||||
BEntry::Rename(const char *path, bool clobber)
|
BEntry::Rename(const char *path, bool clobber)
|
||||||
{
|
{
|
||||||
|
// check parameter and initialization
|
||||||
if (path == NULL)
|
if (path == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
if (fCStatus != B_OK)
|
if (fCStatus != B_OK)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
// get an entry representing the target location
|
||||||
status_t status = B_OK;
|
BEntry target;
|
||||||
// Convert the given path to an absolute path, if it isn't already.
|
status_t error;
|
||||||
char fullPath[B_PATH_NAME_LENGTH];
|
if (BPrivate::Storage::is_absolute_path(path)) {
|
||||||
if (!BPrivate::Storage::is_absolute_path(path)) {
|
error = target.SetTo(path);
|
||||||
// Convert our directory to an absolute pathname
|
} else {
|
||||||
status = BPrivate::Storage::dir_to_path(fDirFd, fullPath,
|
int dirFD = _kern_dup(fDirFd);
|
||||||
B_PATH_NAME_LENGTH);
|
if (dirFD < 0)
|
||||||
if (status == B_OK) {
|
return dirFD;
|
||||||
// Concatenate our pathname to it
|
// init the entry
|
||||||
strcat(fullPath, "/");
|
error = target.fCStatus = target.set(dirFD, path, false);
|
||||||
strcat(fullPath, path);
|
|
||||||
path = fullPath;
|
|
||||||
}
|
}
|
||||||
}
|
if (error != B_OK)
|
||||||
// Check, whether the file does already exist, if clobber is false.
|
return error;
|
||||||
if (status == B_OK && !clobber) {
|
return _Rename(target, 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Moves the BEntry to directory or directory+path combination, replacing an existing entry if clobber is true.
|
/*! \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_EXISTS - The new location is already taken and \c clobber was \c false
|
||||||
- \c B_ENTRY_NOT_FOUND - Attempted to move an abstract entry
|
- \c B_ENTRY_NOT_FOUND - Attempted to move an abstract entry
|
||||||
- "error code" - Failure
|
- "error code" - Failure
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BEntry::MoveTo(BDirectory *dir, const char *path, bool clobber)
|
BEntry::MoveTo(BDirectory *dir, const char *path, bool clobber)
|
||||||
{
|
{
|
||||||
|
// check parameters and initialization
|
||||||
if (fCStatus != B_OK)
|
if (fCStatus != B_OK)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
else if (dir == NULL)
|
if (dir == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
else if (dir->InitCheck() != B_OK)
|
if (dir->InitCheck() != B_OK)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
// NULL path simply means move without renaming
|
// NULL path simply means move without renaming
|
||||||
if (path == NULL)
|
if (path == NULL)
|
||||||
path = fName;
|
path = fName;
|
||||||
|
// get an entry representing the target location
|
||||||
status_t status = B_OK;
|
BEntry target;
|
||||||
// Determine the absolute path of the target entry.
|
status_t error = target.SetTo(dir, path);
|
||||||
if (!BPrivate::Storage::is_absolute_path(path)) {
|
if (error != B_OK)
|
||||||
// Convert our directory to an absolute pathname
|
return error;
|
||||||
char fullPath[B_PATH_NAME_LENGTH];
|
return _Rename(target, clobber);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Removes the entry from the file system.
|
/*! \brief Removes the entry from the file system.
|
||||||
@@ -802,22 +695,13 @@ BEntry::MoveTo(BDirectory *dir, const char *path, bool clobber)
|
|||||||
\return
|
\return
|
||||||
- B_OK - Success
|
- B_OK - Success
|
||||||
- "error code" - Failure
|
- "error code" - Failure
|
||||||
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BEntry::Remove()
|
BEntry::Remove()
|
||||||
{
|
{
|
||||||
if (fCStatus != B_OK)
|
if (fCStatus != B_OK)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
return _kern_unlink(fDirFd, fName);
|
||||||
BPath path;
|
|
||||||
status_t status;
|
|
||||||
|
|
||||||
status = GetPath(&path);
|
|
||||||
if (status != B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
return BPrivate::Storage::remove(path.Path());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -827,7 +711,6 @@ BEntry::Remove()
|
|||||||
\return
|
\return
|
||||||
- true - Both BEntry objects refer to the same entry or they are both uninitialzed
|
- true - Both BEntry objects refer to the same entry or they are both uninitialzed
|
||||||
- false - The BEntry objects refer to different entries
|
- false - The BEntry objects refer to different entries
|
||||||
|
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
BEntry::operator==(const BEntry &item) const
|
BEntry::operator==(const BEntry &item) const
|
||||||
@@ -858,7 +741,6 @@ BEntry::operator==(const BEntry &item) const
|
|||||||
\return
|
\return
|
||||||
- true - The BEntry objects refer to different entries
|
- true - The BEntry objects refer to different entries
|
||||||
- false - Both BEntry objects refer to the same entry or they are both uninitialzed
|
- false - Both BEntry objects refer to the same entry or they are both uninitialzed
|
||||||
|
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
BEntry::operator!=(const BEntry &item) const
|
BEntry::operator!=(const BEntry &item) const
|
||||||
@@ -870,7 +752,6 @@ BEntry::operator!=(const BEntry &item) const
|
|||||||
|
|
||||||
\return
|
\return
|
||||||
- A reference to the copy
|
- A reference to the copy
|
||||||
|
|
||||||
*/
|
*/
|
||||||
BEntry&
|
BEntry&
|
||||||
BEntry::operator=(const BEntry &item)
|
BEntry::operator=(const BEntry &item)
|
||||||
@@ -880,10 +761,14 @@ BEntry::operator=(const BEntry &item)
|
|||||||
|
|
||||||
Unset();
|
Unset();
|
||||||
if (item.fCStatus == B_OK) {
|
if (item.fCStatus == B_OK) {
|
||||||
fCStatus = BPrivate::Storage::dup_dir(item.fDirFd, fDirFd);
|
fDirFd = _kern_dup(item.fDirFd);
|
||||||
if (fCStatus == B_OK) {
|
if (fDirFd >= 0)
|
||||||
fCStatus = set_name(item.fName);
|
fCStatus = set_name(item.fName);
|
||||||
}
|
else
|
||||||
|
fCStatus = fDirFd;
|
||||||
|
|
||||||
|
if (fCStatus != B_OK)
|
||||||
|
Unset();
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@@ -910,120 +795,145 @@ BEntry::set_stat(struct stat &st, uint32 what)
|
|||||||
if (fCStatus != B_OK)
|
if (fCStatus != B_OK)
|
||||||
return B_FILE_ERROR;
|
return B_FILE_ERROR;
|
||||||
|
|
||||||
BPath path;
|
return _kern_write_stat(fDirFd, fName, false, &st, sizeof(struct stat),
|
||||||
status_t status;
|
what);
|
||||||
|
|
||||||
status = GetPath(&path);
|
|
||||||
if (status != B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
return BPrivate::Storage::set_stat(path.Path(), st, what);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Sets the Entry to point to the entry named by \c leaf in the given directory. If \c traverse
|
/*! Sets the Entry to point to the entry specified by the path \a path relative
|
||||||
is \c true and the given entry is a symlink, the object is recursively set to point to the
|
to the given directory. If \a traverse is \c true and the given entry is a
|
||||||
entry pointed to by the symlink.
|
symlink, the object is recursively set to point to the entry pointed to by
|
||||||
|
the symlink.
|
||||||
|
|
||||||
\c leaf <b>must</b> be a leaf-name only (i.e. it must contain no '/' characters),
|
If \a path is an absolute path, \a dirFD is ignored.
|
||||||
otherwise this function will return \c B_BAD_VALUE. If \c B_OK is returned,
|
If \a dirFD is -1, path is considered relative to the current directory
|
||||||
the caller is no longer responsible for closing the directory file descriptor
|
(unless it is an absolute path, that is).
|
||||||
with a call to BPrivate::Storage::close_dir.
|
|
||||||
|
|
||||||
\param dirFd File descriptor of the directory in which the entry resides
|
The ownership of the file descriptor \a dirFD is transferred to the
|
||||||
\param leaf Pointer to a string containing the entry's leaf name
|
function, regardless of whether it succeeds or fails. The caller must not
|
||||||
\param traverse If \c true and the given entry is a symlink, the object is recursively
|
close the FD afterwards.
|
||||||
set to point to the entry linked to by the symlink.
|
|
||||||
|
\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
|
\return
|
||||||
- B_OK - Success
|
- B_OK - Success
|
||||||
- "error code" - Failure
|
- "error code" - Failure
|
||||||
|
|
||||||
*/
|
*/
|
||||||
status_t
|
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
|
bool requireConcrete = false;
|
||||||
status_t error = BPrivate::Storage::check_entry_name(leaf);
|
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)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
// Check whether the entry is abstract or concrete.
|
// special case: root directory ("/")
|
||||||
// We try traversing concrete entries only.
|
if (leafName[0] == '\0' && dirPath[0] == '/')
|
||||||
BPrivate::Storage::LongDirEntry dirEntry;
|
strcpy(leafName, ".");
|
||||||
bool isConcrete = (BPrivate::Storage::find_dir(dirFd, leaf, &dirEntry,
|
if (leafName[0] == '\0') {
|
||||||
sizeof(dirEntry)) == B_OK);
|
// the supplied path is already a leaf
|
||||||
if (traverse && isConcrete) {
|
error = BPrivate::Storage::check_entry_name(dirPath);
|
||||||
// Though the link traversing strategy is iterative, we introduce
|
if (error != B_OK)
|
||||||
// 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;
|
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;
|
||||||
|
fdCloser.Detach();
|
||||||
|
fDirFd = dirFD;
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Handles string allocation, deallocation, and copying for the entry's leaf name.
|
/*! \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)
|
if (name == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
if (fName != NULL) {
|
free(fName);
|
||||||
delete [] fName;
|
|
||||||
}
|
|
||||||
|
|
||||||
fName = new(nothrow) char[strlen(name)+1];
|
fName = strdup(name);
|
||||||
if (fName == NULL)
|
if (!fName)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
strcpy(fName, name);
|
|
||||||
|
|
||||||
return B_OK;
|
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
|
/*! 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
|
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);
|
printf("fCStatus == %ld\n", fCStatus);
|
||||||
|
|
||||||
BPrivate::Storage::LongDirEntry entry;
|
struct stat st;
|
||||||
if (fDirFd != -1
|
if (fDirFd != -1
|
||||||
&& BPrivate::Storage::find_dir(fDirFd, ".", &entry, sizeof(entry)) == B_OK) {
|
&& _kern_read_stat(fDirFd, NULL, false, &st,
|
||||||
printf("dir.device == %ld\n", entry.d_pdev);
|
sizeof(struct stat)) == B_OK) {
|
||||||
printf("dir.inode == %lld\n", entry.d_pino);
|
printf("dir.device == %ld\n", st.st_dev);
|
||||||
|
printf("dir.inode == %lld\n", st.st_ino);
|
||||||
} else {
|
} else {
|
||||||
printf("dir == NullFd\n");
|
printf("dir == NullFd\n");
|
||||||
}
|
}
|
||||||
|
|||||||
+79
-120
@@ -9,9 +9,11 @@
|
|||||||
|
|
||||||
#include <fsproto.h>
|
#include <fsproto.h>
|
||||||
|
|
||||||
|
#include <Directory.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include "kernel_interface.h"
|
|
||||||
|
#include <syscalls.h>
|
||||||
|
|
||||||
#ifdef USE_OPENBEOS_NAMESPACE
|
#ifdef USE_OPENBEOS_NAMESPACE
|
||||||
namespace OpenBeOS {
|
namespace OpenBeOS {
|
||||||
@@ -143,23 +145,22 @@ BFile::~BFile()
|
|||||||
- \c B_BUSY: A node was busy.
|
- \c B_BUSY: A node was busy.
|
||||||
- \c B_FILE_ERROR: A general file error.
|
- \c B_FILE_ERROR: A general file error.
|
||||||
- \c B_NO_MORE_FDS: The application has run out of file descriptors.
|
- \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
|
status_t
|
||||||
BFile::SetTo(const entry_ref *ref, uint32 openMode)
|
BFile::SetTo(const entry_ref *ref, uint32 openMode)
|
||||||
{
|
{
|
||||||
Unset();
|
Unset();
|
||||||
char path[B_PATH_NAME_LENGTH];
|
if (!ref)
|
||||||
status_t error = (ref ? B_OK : B_BAD_VALUE);
|
return (fCStatus = B_BAD_VALUE);
|
||||||
if (error == B_OK) {
|
int fd = _kern_open_entry_ref(ref->device, ref->directory, ref->name,
|
||||||
error = BPrivate::Storage::entry_ref_to_path(ref, path,
|
openMode);
|
||||||
B_PATH_NAME_LENGTH);
|
if (fd >= 0) {
|
||||||
}
|
set_fd(fd);
|
||||||
if (error == B_OK)
|
fMode = openMode;
|
||||||
error = SetTo(path, openMode);
|
fCStatus = B_OK;
|
||||||
set_status(error);
|
} else
|
||||||
return error;
|
fCStatus = fd;
|
||||||
|
return fCStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTo
|
// SetTo
|
||||||
@@ -185,14 +186,18 @@ status_t
|
|||||||
BFile::SetTo(const BEntry *entry, uint32 openMode)
|
BFile::SetTo(const BEntry *entry, uint32 openMode)
|
||||||
{
|
{
|
||||||
Unset();
|
Unset();
|
||||||
entry_ref ref;
|
if (!entry)
|
||||||
status_t error = (entry ? B_OK : B_BAD_VALUE);
|
return (fCStatus = B_BAD_VALUE);
|
||||||
if (error == B_OK)
|
if (entry->InitCheck() != B_OK)
|
||||||
error = entry->GetRef(&ref);
|
return (fCStatus = entry->InitCheck());
|
||||||
if (error == B_OK)
|
int fd = _kern_open(entry->fDirFd, entry->fName, openMode);
|
||||||
error = SetTo(&ref, openMode);
|
if (fd >= 0) {
|
||||||
set_status(error);
|
set_fd(fd);
|
||||||
return error;
|
fMode = openMode;
|
||||||
|
fCStatus = B_OK;
|
||||||
|
} else
|
||||||
|
fCStatus = fd;
|
||||||
|
return fCStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTo
|
// SetTo
|
||||||
@@ -216,54 +221,16 @@ status_t
|
|||||||
BFile::SetTo(const char *path, uint32 openMode)
|
BFile::SetTo(const char *path, uint32 openMode)
|
||||||
{
|
{
|
||||||
Unset();
|
Unset();
|
||||||
status_t result = B_OK;
|
if (!path)
|
||||||
BPrivate::Storage::FileDescriptor newFd = BPrivate::Storage::NullFd;
|
return (fCStatus = B_BAD_VALUE);
|
||||||
if (path) {
|
int fd = _kern_open(-1, path, openMode);
|
||||||
// analyze openMode
|
if (fd >= 0) {
|
||||||
// Well, it's a bit schizophrenic to convert the B_* style openMode
|
set_fd(fd);
|
||||||
// to POSIX style openFlags, but to use O_RWMASK to filter openMode.
|
fMode = openMode;
|
||||||
BPrivate::Storage::OpenFlags openFlags = 0;
|
fCStatus = B_OK;
|
||||||
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
|
} else
|
||||||
result = BPrivate::Storage::open(path, openFlags, newFd);
|
fCStatus = fd;
|
||||||
if (result == B_OK)
|
return fCStatus;
|
||||||
fMode = openFlags;
|
|
||||||
}
|
|
||||||
} 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTo
|
// SetTo
|
||||||
@@ -291,14 +258,16 @@ status_t
|
|||||||
BFile::SetTo(const BDirectory *dir, const char *path, uint32 openMode)
|
BFile::SetTo(const BDirectory *dir, const char *path, uint32 openMode)
|
||||||
{
|
{
|
||||||
Unset();
|
Unset();
|
||||||
status_t error = (dir && path ? B_OK : B_BAD_VALUE);
|
if (!dir)
|
||||||
BEntry entry;
|
return (fCStatus = B_BAD_VALUE);
|
||||||
if (error == B_OK)
|
int fd = _kern_open(dir->fDirFd, path, openMode);
|
||||||
error = entry.SetTo(dir, path);
|
if (fd >= 0) {
|
||||||
if (error == B_OK)
|
set_fd(fd);
|
||||||
error = SetTo(&entry, openMode);
|
fMode = openMode;
|
||||||
set_status(error);
|
fCStatus = B_OK;
|
||||||
return error;
|
} else
|
||||||
|
fCStatus = fd;
|
||||||
|
return fCStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsReadable
|
// IsReadable
|
||||||
@@ -340,10 +309,9 @@ BFile::IsWritable() const
|
|||||||
ssize_t
|
ssize_t
|
||||||
BFile::Read(void *buffer, size_t size)
|
BFile::Read(void *buffer, size_t size)
|
||||||
{
|
{
|
||||||
ssize_t result = InitCheck();
|
if (InitCheck() != B_OK)
|
||||||
if (result == B_OK)
|
return InitCheck();
|
||||||
result = BPrivate::Storage::read(get_fd(), buffer, size);
|
return _kern_read(get_fd(), -1, buffer, size);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadAt
|
// ReadAt
|
||||||
@@ -358,10 +326,11 @@ BFile::Read(void *buffer, size_t size)
|
|||||||
ssize_t
|
ssize_t
|
||||||
BFile::ReadAt(off_t location, void *buffer, size_t size)
|
BFile::ReadAt(off_t location, void *buffer, size_t size)
|
||||||
{
|
{
|
||||||
ssize_t result = InitCheck();
|
if (InitCheck() != B_OK)
|
||||||
if (result == B_OK)
|
return InitCheck();
|
||||||
result = BPrivate::Storage::read(get_fd(), buffer, location, size);
|
if (location < 0)
|
||||||
return result;
|
return B_BAD_VALUE;
|
||||||
|
return _kern_read(get_fd(), location, buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write
|
// Write
|
||||||
@@ -373,10 +342,9 @@ BFile::ReadAt(off_t location, void *buffer, size_t size)
|
|||||||
ssize_t
|
ssize_t
|
||||||
BFile::Write(const void *buffer, size_t size)
|
BFile::Write(const void *buffer, size_t size)
|
||||||
{
|
{
|
||||||
ssize_t result = InitCheck();
|
if (InitCheck() != B_OK)
|
||||||
if (result == B_OK)
|
return InitCheck();
|
||||||
result = BPrivate::Storage::write(get_fd(), buffer, size);
|
return _kern_write(get_fd(), -1, buffer, size);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteAt
|
// WriteAt
|
||||||
@@ -391,10 +359,11 @@ BFile::Write(const void *buffer, size_t size)
|
|||||||
ssize_t
|
ssize_t
|
||||||
BFile::WriteAt(off_t location, const void *buffer, size_t size)
|
BFile::WriteAt(off_t location, const void *buffer, size_t size)
|
||||||
{
|
{
|
||||||
ssize_t result = InitCheck();
|
if (InitCheck() != B_OK)
|
||||||
if (result == B_OK)
|
return InitCheck();
|
||||||
result = BPrivate::Storage::write(get_fd(), buffer, location, size);
|
if (location < 0)
|
||||||
return result;
|
return B_BAD_VALUE;
|
||||||
|
return _kern_write(get_fd(), location, buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seek
|
// Seek
|
||||||
@@ -417,10 +386,9 @@ BFile::WriteAt(off_t location, const void *buffer, size_t size)
|
|||||||
off_t
|
off_t
|
||||||
BFile::Seek(off_t offset, uint32 seekMode)
|
BFile::Seek(off_t offset, uint32 seekMode)
|
||||||
{
|
{
|
||||||
off_t result = (InitCheck() == B_OK ? (off_t)B_OK : (off_t)B_FILE_ERROR);
|
if (InitCheck() != B_OK)
|
||||||
if (result == B_OK)
|
return B_FILE_ERROR;
|
||||||
result = BPrivate::Storage::seek(get_fd(), offset, seekMode);
|
return _kern_seek(get_fd(), offset, seekMode);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Position
|
// Position
|
||||||
@@ -433,10 +401,9 @@ BFile::Seek(off_t offset, uint32 seekMode)
|
|||||||
off_t
|
off_t
|
||||||
BFile::Position() const
|
BFile::Position() const
|
||||||
{
|
{
|
||||||
off_t result = (InitCheck() == B_OK ? (off_t)B_OK : (off_t)B_FILE_ERROR);
|
if (InitCheck() != B_OK)
|
||||||
if (result == B_OK)
|
return B_FILE_ERROR;
|
||||||
result = BPrivate::Storage::get_position(get_fd());
|
return _kern_seek(get_fd(), 0, SEEK_CUR);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetSize
|
// SetSize
|
||||||
@@ -456,15 +423,13 @@ BFile::Position() const
|
|||||||
status_t
|
status_t
|
||||||
BFile::SetSize(off_t size)
|
BFile::SetSize(off_t size)
|
||||||
{
|
{
|
||||||
status_t result = InitCheck();
|
if (InitCheck() != B_OK)
|
||||||
if (result == B_OK && size < 0)
|
return InitCheck();
|
||||||
result = B_BAD_VALUE;
|
if (size < 0)
|
||||||
|
return B_BAD_VALUE;
|
||||||
struct stat statData;
|
struct stat statData;
|
||||||
if (result == B_OK) {
|
|
||||||
statData.st_size = size;
|
statData.st_size = size;
|
||||||
result = set_stat(statData, WSTAT_SIZE);
|
return set_stat(statData, WSTAT_SIZE);
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// =
|
// =
|
||||||
@@ -481,17 +446,14 @@ BFile::operator=(const BFile &file)
|
|||||||
Unset();
|
Unset();
|
||||||
if (file.InitCheck() == B_OK) {
|
if (file.InitCheck() == B_OK) {
|
||||||
// duplicate the file descriptor
|
// duplicate the file descriptor
|
||||||
BPrivate::Storage::FileDescriptor fd = -1;
|
int fd = _kern_dup(file.get_fd());
|
||||||
status_t status = BPrivate::Storage::dup(file.get_fd(), fd);
|
|
||||||
// set it
|
// set it
|
||||||
if (status == B_OK) {
|
if (fd >= 0) {
|
||||||
status = set_fd(fd);
|
fFd = fd;
|
||||||
if (status == B_OK)
|
|
||||||
fMode = file.fMode;
|
fMode = file.fMode;
|
||||||
else
|
fCStatus = B_OK;
|
||||||
BPrivate::Storage::close(fd);
|
} else
|
||||||
}
|
fCStatus = fd;
|
||||||
set_status(status);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@@ -512,7 +474,7 @@ void BFile::_PhiloFile6() {}
|
|||||||
To be used instead of accessing the BNode's private \c fFd member directly.
|
To be used instead of accessing the BNode's private \c fFd member directly.
|
||||||
\return the file descriptor, or -1, if not properly initialized.
|
\return the file descriptor, or -1, if not properly initialized.
|
||||||
*/
|
*/
|
||||||
BPrivate::Storage::FileDescriptor
|
int
|
||||||
BFile::get_fd() const
|
BFile::get_fd() const
|
||||||
{
|
{
|
||||||
return fFd;
|
return fFd;
|
||||||
@@ -523,6 +485,3 @@ BFile::get_fd() const
|
|||||||
}; // namespace OpenBeOS
|
}; // namespace OpenBeOS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,41 +1,60 @@
|
|||||||
// LibBeAdapter.cpp
|
// 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 <Directory.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
|
#include <fs_attr.h>
|
||||||
|
#include <fs_query.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
FD_TYPE_UNKNOWN,
|
||||||
|
FD_TYPE_DIR,
|
||||||
|
FD_TYPE_ATTR_DIR,
|
||||||
|
FD_TYPE_QUERY,
|
||||||
|
};
|
||||||
|
|
||||||
extern "C" status_t
|
static const int kFDTableSlotCount = 1024;
|
||||||
_kern_dir_node_ref_to_path(dev_t device, ino_t inode, char *buffer, size_t size)
|
static uint8 sFDTable[kFDTableSlotCount];
|
||||||
|
|
||||||
|
static struct InitDirFDTable {
|
||||||
|
InitDirFDTable()
|
||||||
{
|
{
|
||||||
if (buffer == NULL)
|
memset(sFDTable, FD_TYPE_UNKNOWN, sizeof(sFDTable));
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
} 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;
|
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
|
// 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,
|
extern "C" status_t _kstart_watching_vnode_(dev_t device, ino_t node,
|
||||||
uint32 flags, port_id port,
|
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);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+160
-119
@@ -7,15 +7,20 @@
|
|||||||
BNode implementation.
|
BNode implementation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <fs_attr.h> // for struct attr_info
|
#include <fs_attr.h> // for struct attr_info
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <Node.h>
|
#include <Directory.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
|
#include <Node.h>
|
||||||
|
#include <String.h>
|
||||||
|
#include <TypeConstants.h>
|
||||||
|
|
||||||
|
#include <syscalls.h>
|
||||||
|
|
||||||
#include "kernel_interface.h"
|
|
||||||
#include "storage_support.h"
|
#include "storage_support.h"
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
@@ -84,8 +89,8 @@ node_ref::operator=(const node_ref &ref)
|
|||||||
/*! \brief Creates an uninitialized BNode object
|
/*! \brief Creates an uninitialized BNode object
|
||||||
*/
|
*/
|
||||||
BNode::BNode()
|
BNode::BNode()
|
||||||
: fFd(BPrivate::Storage::NullFd),
|
: fFd(-1),
|
||||||
fAttrFd(BPrivate::Storage::NullFd),
|
fAttrFd(-1),
|
||||||
fCStatus(B_NO_INIT)
|
fCStatus(B_NO_INIT)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -95,8 +100,8 @@ BNode::BNode()
|
|||||||
\param ref the entry_ref referring to the entry
|
\param ref the entry_ref referring to the entry
|
||||||
*/
|
*/
|
||||||
BNode::BNode(const entry_ref *ref)
|
BNode::BNode(const entry_ref *ref)
|
||||||
: fFd(BPrivate::Storage::NullFd),
|
: fFd(-1),
|
||||||
fAttrFd(BPrivate::Storage::NullFd),
|
fAttrFd(-1),
|
||||||
fCStatus(B_NO_INIT)
|
fCStatus(B_NO_INIT)
|
||||||
{
|
{
|
||||||
SetTo(ref);
|
SetTo(ref);
|
||||||
@@ -107,8 +112,8 @@ BNode::BNode(const entry_ref *ref)
|
|||||||
\param entry the BEntry representing the entry
|
\param entry the BEntry representing the entry
|
||||||
*/
|
*/
|
||||||
BNode::BNode(const BEntry *entry)
|
BNode::BNode(const BEntry *entry)
|
||||||
: fFd(BPrivate::Storage::NullFd),
|
: fFd(-1),
|
||||||
fAttrFd(BPrivate::Storage::NullFd),
|
fAttrFd(-1),
|
||||||
fCStatus(B_NO_INIT)
|
fCStatus(B_NO_INIT)
|
||||||
{
|
{
|
||||||
SetTo(entry);
|
SetTo(entry);
|
||||||
@@ -119,8 +124,8 @@ BNode::BNode(const BEntry *entry)
|
|||||||
\param path the path referring to the entry
|
\param path the path referring to the entry
|
||||||
*/
|
*/
|
||||||
BNode::BNode(const char *path)
|
BNode::BNode(const char *path)
|
||||||
: fFd(BPrivate::Storage::NullFd),
|
: fFd(-1),
|
||||||
fAttrFd(BPrivate::Storage::NullFd),
|
fAttrFd(-1),
|
||||||
fCStatus(B_NO_INIT)
|
fCStatus(B_NO_INIT)
|
||||||
{
|
{
|
||||||
SetTo(path);
|
SetTo(path);
|
||||||
@@ -133,8 +138,8 @@ BNode::BNode(const char *path)
|
|||||||
\param path the entry's path name relative to \a dir
|
\param path the entry's path name relative to \a dir
|
||||||
*/
|
*/
|
||||||
BNode::BNode(const BDirectory *dir, const char *path)
|
BNode::BNode(const BDirectory *dir, const char *path)
|
||||||
: fFd(BPrivate::Storage::NullFd),
|
: fFd(-1),
|
||||||
fAttrFd(BPrivate::Storage::NullFd),
|
fAttrFd(-1),
|
||||||
fCStatus(B_NO_INIT)
|
fCStatus(B_NO_INIT)
|
||||||
{
|
{
|
||||||
SetTo(dir, path);
|
SetTo(dir, path);
|
||||||
@@ -144,8 +149,8 @@ BNode::BNode(const BDirectory *dir, const char *path)
|
|||||||
\param node the BNode to be copied
|
\param node the BNode to be copied
|
||||||
*/
|
*/
|
||||||
BNode::BNode(const BNode &node)
|
BNode::BNode(const BNode &node)
|
||||||
: fFd(BPrivate::Storage::NullFd),
|
: fFd(-1),
|
||||||
fAttrFd(BPrivate::Storage::NullFd),
|
fAttrFd(-1),
|
||||||
fCStatus(B_NO_INIT)
|
fCStatus(B_NO_INIT)
|
||||||
{
|
{
|
||||||
*this = node;
|
*this = node;
|
||||||
@@ -180,7 +185,9 @@ BNode::InitCheck() const
|
|||||||
status_t
|
status_t
|
||||||
BNode::GetStat(struct stat *st) const
|
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.
|
/*! \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_BAD_VALUE: \c NULL \a ref.
|
||||||
- \c B_ENTRY_NOT_FOUND: The entry could not be found.
|
- \c B_ENTRY_NOT_FOUND: The entry could not be found.
|
||||||
- \c B_BUSY: The entry is locked.
|
- \c B_BUSY: The entry is locked.
|
||||||
\todo Currently implemented using BPrivate::Storage::entry_ref_to_path().
|
|
||||||
Reimplement!
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BNode::SetTo(const entry_ref *ref)
|
BNode::SetTo(const entry_ref *ref)
|
||||||
{
|
{
|
||||||
Unset();
|
return _SetTo(ref, false);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Reinitializes the object to the specified filesystem entry.
|
/*! \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_BAD_VALUE: \c NULL \a entry.
|
||||||
- \c B_ENTRY_NOT_FOUND: The entry could not be found.
|
- \c B_ENTRY_NOT_FOUND: The entry could not be found.
|
||||||
- \c B_BUSY: The entry is locked.
|
- \c B_BUSY: The entry is locked.
|
||||||
\todo Implemented using SetTo(entry_ref*). Check, if necessary to
|
|
||||||
reimplement!
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BNode::SetTo(const BEntry *entry)
|
BNode::SetTo(const BEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
Unset();
|
Unset();
|
||||||
entry_ref ref;
|
return (fCStatus = B_BAD_VALUE);
|
||||||
status_t error = (entry ? B_OK : B_BAD_VALUE);
|
}
|
||||||
if (error == B_OK && entry->InitCheck() != B_OK)
|
return _SetTo(entry->fDirFd, entry->fName, false);
|
||||||
error = B_BAD_VALUE;
|
|
||||||
if (error == B_OK)
|
|
||||||
error = entry->GetRef(&ref);
|
|
||||||
if (error == B_OK)
|
|
||||||
error = SetTo(&ref);
|
|
||||||
fCStatus = error;
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Reinitializes the object to the entry referred to by the specified
|
/*! \brief Reinitializes the object to the entry referred to by the specified
|
||||||
@@ -247,12 +234,7 @@ BNode::SetTo(const BEntry *entry)
|
|||||||
status_t
|
status_t
|
||||||
BNode::SetTo(const char *path)
|
BNode::SetTo(const char *path)
|
||||||
{
|
{
|
||||||
Unset();
|
return _SetTo(-1, path, false);
|
||||||
if (path != NULL) {
|
|
||||||
fCStatus = BPrivate::Storage::open(path, O_RDWR | O_NOTRAVERSE, fFd,
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
return fCStatus;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Reinitializes the object to the entry referred to by the specified
|
/*! \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_BAD_VALUE: \c NULL \a dir or \a path.
|
||||||
- \c B_ENTRY_NOT_FOUND: The entry could not be found.
|
- \c B_ENTRY_NOT_FOUND: The entry could not be found.
|
||||||
- \c B_BUSY: The entry is locked.
|
- \c B_BUSY: The entry is locked.
|
||||||
\todo Implemented using SetTo(BEntry*). Check, if necessary to reimplement!
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BNode::SetTo(const BDirectory *dir, const char *path)
|
BNode::SetTo(const BDirectory *dir, const char *path)
|
||||||
{
|
{
|
||||||
|
if (!dir || !path || BPrivate::Storage::is_absolute_path(path)) {
|
||||||
Unset();
|
Unset();
|
||||||
status_t error = (dir && path ? B_OK : B_BAD_VALUE);
|
return (fCStatus = B_BAD_VALUE);
|
||||||
if (error == B_OK && BPrivate::Storage::is_absolute_path(path))
|
}
|
||||||
error = B_BAD_VALUE;
|
return _SetTo(dir->fDirFd, path, false);
|
||||||
BEntry entry;
|
|
||||||
if (error == B_OK)
|
|
||||||
error = entry.SetTo(dir, path);
|
|
||||||
if (error == B_OK)
|
|
||||||
error = SetTo(&entry);
|
|
||||||
fCStatus = error;
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Returns the object to an uninitialized state.
|
/*! \brief Returns the object to an uninitialized state.
|
||||||
@@ -298,21 +273,13 @@ BNode::Unset()
|
|||||||
- \c B_OK: Everything went fine.
|
- \c B_OK: Everything went fine.
|
||||||
- \c B_FILE_ERROR: The object is not initialized.
|
- \c B_FILE_ERROR: The object is not initialized.
|
||||||
- \c B_BUSY: The node is already locked.
|
- \c B_BUSY: The node is already locked.
|
||||||
\todo Currently unimplemented; requires new kernel.
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BNode::Lock()
|
BNode::Lock()
|
||||||
{
|
{
|
||||||
if (fCStatus != B_OK)
|
if (fCStatus != B_OK)
|
||||||
return fCStatus;
|
return fCStatus;
|
||||||
|
return _kern_lock_node(fFd);
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Unlocks the node.
|
/*! \brief Unlocks the node.
|
||||||
@@ -320,15 +287,13 @@ BNode::Lock()
|
|||||||
- \c B_OK: Everything went fine.
|
- \c B_OK: Everything went fine.
|
||||||
- \c B_FILE_ERROR: The object is not initialized.
|
- \c B_FILE_ERROR: The object is not initialized.
|
||||||
- \c B_BAD_VALUE: The node is not locked.
|
- \c B_BAD_VALUE: The node is not locked.
|
||||||
\todo Currently unimplemented; requires new kernel.
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BNode::Unlock()
|
BNode::Unlock()
|
||||||
{
|
{
|
||||||
if (fCStatus != B_OK)
|
if (fCStatus != B_OK)
|
||||||
return fCStatus;
|
return fCStatus;
|
||||||
// This will have to wait for the new kenel
|
return _kern_unlock_node(fFd);
|
||||||
return B_FILE_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Immediately performs any pending disk actions on the node.
|
/*! \brief Immediately performs any pending disk actions on the node.
|
||||||
@@ -339,7 +304,7 @@ BNode::Unlock()
|
|||||||
status_t
|
status_t
|
||||||
BNode::Sync()
|
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.
|
/*! \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)
|
if (fCStatus != B_OK)
|
||||||
return B_FILE_ERROR;
|
return B_FILE_ERROR;
|
||||||
else {
|
if (!attr || !buffer)
|
||||||
ssize_t result = BPrivate::Storage::write_attr(fFd, attr, type, offset,
|
return B_BAD_VALUE;
|
||||||
buffer, len);
|
ssize_t result = fs_write_attr (fFd, attr, type, offset, buffer, len);
|
||||||
return result;
|
return (result < 0 ? errno : result);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Reads data from an attribute into a buffer.
|
/*! \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)
|
if (fCStatus != B_OK)
|
||||||
return B_FILE_ERROR;
|
return B_FILE_ERROR;
|
||||||
else {
|
if (!attr || !buffer)
|
||||||
ssize_t result = BPrivate::Storage::read_attr(fFd, attr, type, offset, buffer,
|
return B_BAD_VALUE;
|
||||||
len);
|
ssize_t result = fs_read_attr(fFd, attr, type, offset, buffer, len );
|
||||||
return result;
|
return (result == -1 ? errno : result);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Deletes the attribute given by \a name.
|
/*! \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
|
status_t
|
||||||
BNode::RemoveAttr(const char *name)
|
BNode::RemoveAttr(const char *name)
|
||||||
{
|
{
|
||||||
return (fCStatus != B_OK) ? B_FILE_ERROR
|
return (fCStatus != B_OK) ? B_FILE_ERROR : _kern_remove_attr(fFd, name);
|
||||||
: BPrivate::Storage::remove_attr(fFd, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Moves the attribute given by \a oldname to \a newname.
|
/*! \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)
|
if (fCStatus != B_OK)
|
||||||
return B_FILE_ERROR;
|
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
|
status_t
|
||||||
BNode::GetAttrInfo(const char *name, struct attr_info *info) const
|
BNode::GetAttrInfo(const char *name, struct attr_info *info) const
|
||||||
{
|
{
|
||||||
return (fCStatus != B_OK) ? B_FILE_ERROR
|
if (fCStatus != B_OK)
|
||||||
: BPrivate::Storage::stat_attr(fFd, name, info);
|
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.
|
/*! \brief Returns the next attribute in the node's list of attributes.
|
||||||
@@ -486,13 +451,14 @@ BNode::GetNextAttrName(char *buffer)
|
|||||||
return B_FILE_ERROR;
|
return B_FILE_ERROR;
|
||||||
|
|
||||||
BPrivate::Storage::LongDirEntry entry;
|
BPrivate::Storage::LongDirEntry entry;
|
||||||
status_t error = BPrivate::Storage::read_attr_dir(fAttrFd, entry);
|
ssize_t result = _kern_read_dir(fAttrFd, &entry, sizeof(entry), 1);
|
||||||
if (error == B_OK) {
|
if (result < 0)
|
||||||
strncpy(buffer, entry.d_name, B_ATTR_NAME_LENGTH);
|
return result;
|
||||||
|
if (result == 0)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
strlcpy(buffer, entry.d_name, B_ATTR_NAME_LENGTH);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \brief Resets the object's attribute pointer to the first attribute in the
|
/*! \brief Resets the object's attribute pointer to the first attribute in the
|
||||||
list.
|
list.
|
||||||
@@ -505,8 +471,7 @@ BNode::RewindAttrs()
|
|||||||
{
|
{
|
||||||
if (InitAttrDir() != B_OK)
|
if (InitAttrDir() != B_OK)
|
||||||
return B_FILE_ERROR;
|
return B_FILE_ERROR;
|
||||||
BPrivate::Storage::rewind_attr_dir(fAttrFd);
|
return _kern_rewind_dir(fAttrFd);
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Writes the specified string to the specified attribute, clobbering any
|
/*! Writes the specified string to the specified attribute, clobbering any
|
||||||
@@ -590,8 +555,8 @@ BNode::operator=(const BNode &node)
|
|||||||
Unset();
|
Unset();
|
||||||
// We have to manually dup the node, because R5::BNode::Dup()
|
// We have to manually dup the node, because R5::BNode::Dup()
|
||||||
// is not declared to be const (which IMO is retarded).
|
// is not declared to be const (which IMO is retarded).
|
||||||
fFd = BPrivate::Storage::dup(node.fFd);
|
fFd = _kern_dup(node.fFd);
|
||||||
fCStatus = (fFd == BPrivate::Storage::NullFd) ? B_NO_INIT : B_OK ;
|
fCStatus = (fFd < 0) ? B_NO_INIT : B_OK ;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,13 +572,13 @@ BNode::operator==(const BNode &node) const
|
|||||||
if (fCStatus == B_NO_INIT && node.InitCheck() == B_NO_INIT)
|
if (fCStatus == B_NO_INIT && node.InitCheck() == B_NO_INIT)
|
||||||
return true;
|
return true;
|
||||||
if (fCStatus == B_OK && node.InitCheck() == B_OK) {
|
if (fCStatus == B_OK && node.InitCheck() == B_OK) {
|
||||||
// Check if they're identical
|
// compare the node_refs
|
||||||
BPrivate::Storage::Stat s1, s2;
|
node_ref ref1, ref2;
|
||||||
if (GetStat(&s1) != B_OK)
|
if (GetNodeRef(&ref1) != B_OK)
|
||||||
return false;
|
return false;
|
||||||
if (node.GetStat(&s2) != B_OK)
|
if (node.GetNodeRef(&ref2) != B_OK)
|
||||||
return false;
|
return false;
|
||||||
return (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino);
|
return (ref1 == ref2);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -638,7 +603,8 @@ BNode::operator!=(const BNode &node) const
|
|||||||
int
|
int
|
||||||
BNode::Dup()
|
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.
|
thereafter.
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BNode::set_fd(BPrivate::Storage::FileDescriptor fd)
|
BNode::set_fd(int fd)
|
||||||
{
|
{
|
||||||
if (fFd != -1)
|
if (fFd != -1)
|
||||||
close_fd();
|
close_fd();
|
||||||
@@ -673,20 +639,19 @@ BNode::set_fd(BPrivate::Storage::FileDescriptor fd)
|
|||||||
/*! \brief Closes the node's file descriptor(s).
|
/*! \brief Closes the node's file descriptor(s).
|
||||||
To be implemented by subclasses to close the file descriptor using the
|
To be implemented by subclasses to close the file descriptor using the
|
||||||
proper system call for the given file-type. This implementation calls
|
proper system call for the given file-type. This implementation calls
|
||||||
BPrivate::Storage::close(fFd) and also BPrivate::Storage::close_attr_dir(fAttrDir)
|
_kern_close(fFd) and also _kern_close(fAttrDir) if necessary.
|
||||||
if necessary.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
BNode::close_fd()
|
BNode::close_fd()
|
||||||
{
|
{
|
||||||
if (fAttrFd != BPrivate::Storage::NullFd)
|
if (fAttrFd >= 0)
|
||||||
{
|
{
|
||||||
BPrivate::Storage::close_attr_dir(fAttrFd);
|
_kern_close(fAttrFd);
|
||||||
fAttrFd = BPrivate::Storage::NullFd;
|
fAttrFd = -1;
|
||||||
}
|
}
|
||||||
if (fFd != BPrivate::Storage::NullFd) {
|
if (fFd >= 0) {
|
||||||
close(fFd);
|
_kern_close(fFd);
|
||||||
fFd = BPrivate::Storage::NullFd;
|
fFd = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -702,6 +667,84 @@ BNode::set_status(status_t newStatus)
|
|||||||
fCStatus = 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
|
/*! \brief Modifies a certain setting for this node based on \a what and the
|
||||||
corresponding value in \a st.
|
corresponding value in \a st.
|
||||||
Inherited from and called by BStatable.
|
Inherited from and called by BStatable.
|
||||||
@@ -714,7 +757,8 @@ BNode::set_stat(struct stat &st, uint32 what)
|
|||||||
{
|
{
|
||||||
if (fCStatus != B_OK)
|
if (fCStatus != B_OK)
|
||||||
return B_FILE_ERROR;
|
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
|
/*! \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
|
status_t
|
||||||
BNode::InitAttrDir()
|
BNode::InitAttrDir()
|
||||||
{
|
{
|
||||||
if (fCStatus == B_OK && fAttrFd == BPrivate::Storage::NullFd)
|
if (fCStatus == B_OK && fAttrFd < 0) {
|
||||||
return BPrivate::Storage::open_attr_dir(fFd, fAttrFd);
|
fAttrFd = _kern_open_attr_dir(fFd, NULL);
|
||||||
|
if (fAttrFd < 0)
|
||||||
|
return fAttrFd;
|
||||||
|
}
|
||||||
return fCStatus;
|
return fCStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -735,16 +782,10 @@ BNode::InitAttrDir()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*! \var BNode::fAttrFd
|
/*! \var BNode::fAttrFd
|
||||||
This appears to be passed to the attribute directory functions
|
File descriptor for the attribute directory of the node. Initialized lazily.
|
||||||
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*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*! \var BNode::fCStatus
|
/*! \var BNode::fCStatus
|
||||||
The object's initialization status.
|
The object's initialization status.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+16
-13
@@ -14,7 +14,9 @@
|
|||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
#include <StorageDefs.h>
|
#include <StorageDefs.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
#include "kernel_interface.h"
|
|
||||||
|
#include <syscalls.h>
|
||||||
|
|
||||||
#include "storage_support.h"
|
#include "storage_support.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -125,15 +127,16 @@ status_t
|
|||||||
BPath::SetTo(const entry_ref *ref)
|
BPath::SetTo(const entry_ref *ref)
|
||||||
{
|
{
|
||||||
Unset();
|
Unset();
|
||||||
status_t error = (ref ? B_OK : B_BAD_VALUE);
|
if (!ref)
|
||||||
if (error == B_OK) {
|
return (fCStatus = B_BAD_VALUE);
|
||||||
|
|
||||||
char path[B_PATH_NAME_LENGTH];
|
char path[B_PATH_NAME_LENGTH];
|
||||||
error = BPrivate::Storage::entry_ref_to_path(ref, path, sizeof(path));
|
status_t error = _kern_entry_ref_to_path(ref->device, ref->directory,
|
||||||
if (error == B_OK)
|
ref->name, path, sizeof(path));
|
||||||
error = set_path(path); // the path is already normalized
|
if (error != B_OK)
|
||||||
}
|
return (fCStatus = error);
|
||||||
fCStatus = error;
|
fCStatus = set_path(path); // the path is already normalized
|
||||||
return error;
|
return fCStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Reinitializes the object to the specified filesystem entry.
|
/*! \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
|
// normalize the path, if necessary, otherwise just set it
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
if (normalize) {
|
if (normalize) {
|
||||||
char normalizedPath[B_PATH_NAME_LENGTH];
|
// create a BEntry and initialize us with this entry
|
||||||
error = BPrivate::Storage::get_canonical_path(newPath, normalizedPath,
|
BEntry entry;
|
||||||
sizeof(normalizedPath));
|
error = entry.SetTo(newPath, false);
|
||||||
if (error == B_OK)
|
if (error == B_OK)
|
||||||
error = set_path(normalizedPath);
|
return SetTo(&entry);
|
||||||
} else
|
} else
|
||||||
error = set_path(newPath);
|
error = set_path(newPath);
|
||||||
}
|
}
|
||||||
|
|||||||
+44
-42
@@ -6,7 +6,6 @@
|
|||||||
\file Query.cpp
|
\file Query.cpp
|
||||||
BQuery implementation.
|
BQuery implementation.
|
||||||
*/
|
*/
|
||||||
#include <Query.h>
|
|
||||||
|
|
||||||
#include <fs_query.h>
|
#include <fs_query.h>
|
||||||
#include <new>
|
#include <new>
|
||||||
@@ -14,18 +13,17 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
|
#include <Query.h>
|
||||||
#include <Volume.h>
|
#include <Volume.h>
|
||||||
|
|
||||||
#include "kernel_interface.h"
|
#include <MessengerPrivate.h>
|
||||||
|
#include <syscalls.h>
|
||||||
|
|
||||||
#include "QueryPredicate.h"
|
#include "QueryPredicate.h"
|
||||||
|
#include "storage_support.h"
|
||||||
|
|
||||||
using namespace BPrivate::Storage;
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
using namespace BPrivate::Storage;
|
||||||
|
|
||||||
enum {
|
|
||||||
NOT_IMPLEMENTED = B_ERROR,
|
|
||||||
};
|
|
||||||
|
|
||||||
// BQuery
|
// BQuery
|
||||||
|
|
||||||
@@ -40,7 +38,7 @@ BQuery::BQuery()
|
|||||||
fLive(false),
|
fLive(false),
|
||||||
fPort(B_ERROR),
|
fPort(B_ERROR),
|
||||||
fToken(0),
|
fToken(0),
|
||||||
fQueryFd(NullFd)
|
fQueryFd(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,9 +59,9 @@ BQuery::Clear()
|
|||||||
{
|
{
|
||||||
// close the currently open query
|
// close the currently open query
|
||||||
status_t error = B_OK;
|
status_t error = B_OK;
|
||||||
if (fQueryFd != NullFd) {
|
if (fQueryFd >= 0) {
|
||||||
error = close_query(fQueryFd);
|
error = _kern_close(fQueryFd);
|
||||||
fQueryFd = NullFd;
|
fQueryFd = -1;
|
||||||
}
|
}
|
||||||
// delete the predicate stack and the predicate
|
// delete the predicate stack and the predicate
|
||||||
delete fStack;
|
delete fStack;
|
||||||
@@ -314,11 +312,9 @@ BQuery::PushDate(const char *date)
|
|||||||
time_t t;
|
time_t t;
|
||||||
time(&t);
|
time(&t);
|
||||||
t = parsedate(date, t);
|
t = parsedate(date, t);
|
||||||
if (t < 0) {
|
if (t < 0)
|
||||||
// error = t;
|
|
||||||
error = B_BAD_VALUE;
|
error = B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (error == B_OK)
|
if (error == B_OK)
|
||||||
error = _PushNode(new(nothrow) DateNode(date), true);
|
error = _PushNode(new(nothrow) DateNode(date), true);
|
||||||
return error;
|
return error;
|
||||||
@@ -391,8 +387,10 @@ BQuery::SetTarget(BMessenger messenger)
|
|||||||
if (error == B_OK && _HasFetched())
|
if (error == B_OK && _HasFetched())
|
||||||
error = B_NOT_ALLOWED;
|
error = B_NOT_ALLOWED;
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
fPort = messenger.fPort;
|
BMessenger::Private messengerPrivate(messenger);
|
||||||
fToken = messenger.fHandlerToken;
|
fPort = messengerPrivate.Port();
|
||||||
|
fToken = (messengerPrivate.IsPreferredTarget()
|
||||||
|
? -1 : messengerPrivate.Token());
|
||||||
fLive = true;
|
fLive = true;
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
@@ -428,7 +426,6 @@ BQuery::GetPredicate(char *buffer, size_t length)
|
|||||||
{
|
{
|
||||||
status_t error = (buffer ? B_OK : B_BAD_VALUE);
|
status_t error = (buffer ? B_OK : B_BAD_VALUE);
|
||||||
if (error == B_OK)
|
if (error == B_OK)
|
||||||
// error = _EvaluateStack();
|
|
||||||
_EvaluateStack();
|
_EvaluateStack();
|
||||||
if (error == B_OK && !fPredicate)
|
if (error == B_OK && !fPredicate)
|
||||||
error = B_NO_INIT;
|
error = B_NO_INIT;
|
||||||
@@ -458,7 +455,6 @@ BQuery::GetPredicate(BString *predicate)
|
|||||||
{
|
{
|
||||||
status_t error = (predicate ? B_OK : B_BAD_VALUE);
|
status_t error = (predicate ? B_OK : B_BAD_VALUE);
|
||||||
if (error == B_OK)
|
if (error == B_OK)
|
||||||
// error = _EvaluateStack();
|
|
||||||
_EvaluateStack();
|
_EvaluateStack();
|
||||||
if (error == B_OK && !fPredicate)
|
if (error == B_OK && !fPredicate)
|
||||||
error = B_NO_INIT;
|
error = B_NO_INIT;
|
||||||
@@ -518,20 +514,19 @@ BQuery::TargetDevice() const
|
|||||||
status_t
|
status_t
|
||||||
BQuery::Fetch()
|
BQuery::Fetch()
|
||||||
{
|
{
|
||||||
status_t error = (_HasFetched() ? B_NOT_ALLOWED : B_OK);
|
if (_HasFetched())
|
||||||
if (error == B_OK)
|
return B_NOT_ALLOWED;
|
||||||
// error = _EvaluateStack();
|
|
||||||
_EvaluateStack();
|
_EvaluateStack();
|
||||||
if (error == B_OK && (!fPredicate || fDevice < 0))
|
if (!fPredicate || fDevice < 0)
|
||||||
error = B_NO_INIT;
|
return B_NO_INIT;
|
||||||
if (error == B_OK) {
|
|
||||||
if (fLive) {
|
if (fLive) {
|
||||||
error = open_live_query(fDevice, fPredicate, B_LIVE_QUERY, fPort,
|
fQueryFd = _kern_open_query(fDevice, fPredicate, B_LIVE_QUERY,
|
||||||
fToken, fQueryFd);
|
fPort, fToken);
|
||||||
} else
|
} else
|
||||||
error = open_query(fDevice, fPredicate, 0, fQueryFd);
|
fQueryFd = _kern_open_query(fDevice, fPredicate, 0, -1, -1);
|
||||||
}
|
if (fQueryFd < 0)
|
||||||
return error;
|
return fQueryFd;
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -586,10 +581,20 @@ BQuery::GetNextRef(entry_ref *ref)
|
|||||||
error = B_FILE_ERROR;
|
error = B_FILE_ERROR;
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
BPrivate::Storage::LongDirEntry entry;
|
BPrivate::Storage::LongDirEntry entry;
|
||||||
if (BPrivate::Storage::read_query(fQueryFd, &entry, sizeof(entry), 1) != 1)
|
bool next = true;
|
||||||
|
while (error == B_OK && next) {
|
||||||
|
if (GetNextDirents(&entry, sizeof(entry), 1) != 1) {
|
||||||
error = B_ENTRY_NOT_FOUND;
|
error = B_ENTRY_NOT_FOUND;
|
||||||
if (error == B_OK)
|
} else {
|
||||||
*ref = entry_ref(entry.d_pdev, entry.d_pino, entry.d_name);
|
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;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -614,12 +619,11 @@ BQuery::GetNextRef(entry_ref *ref)
|
|||||||
int32
|
int32
|
||||||
BQuery::GetNextDirents(struct dirent *buf, size_t length, int32 count)
|
BQuery::GetNextDirents(struct dirent *buf, size_t length, int32 count)
|
||||||
{
|
{
|
||||||
int32 result = (buf ? B_OK : B_BAD_VALUE);
|
if (!buf)
|
||||||
if (result == B_OK && !_HasFetched())
|
return B_BAD_VALUE;
|
||||||
result = B_FILE_ERROR;
|
if (!_HasFetched())
|
||||||
if (result == B_OK)
|
return B_FILE_ERROR;
|
||||||
result = read_query(fQueryFd, buf, length, count);
|
return _kern_read_dir(fQueryFd, buf, length, count);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewind
|
// Rewind
|
||||||
@@ -650,7 +654,7 @@ BQuery::CountEntries()
|
|||||||
bool
|
bool
|
||||||
BQuery::_HasFetched() const
|
BQuery::_HasFetched() const
|
||||||
{
|
{
|
||||||
return (fQueryFd != NullFd);
|
return (fQueryFd >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// _PushNode
|
// _PushNode
|
||||||
@@ -758,5 +762,3 @@ void BQuery::_QwertyQuery4() {}
|
|||||||
void BQuery::_QwertyQuery5() {}
|
void BQuery::_QwertyQuery5() {}
|
||||||
void BQuery::_QwertyQuery6() {}
|
void BQuery::_QwertyQuery6() {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <ResourceStrings.h>
|
#include <ResourceStrings.h>
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
@@ -17,7 +18,7 @@
|
|||||||
#include <Resources.h>
|
#include <Resources.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
#include "kernel_interface.h"
|
#include <AppMisc.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@@ -139,12 +140,8 @@ BResourceStrings::SetStringFile(const entry_ref *ref)
|
|||||||
if (ref) {
|
if (ref) {
|
||||||
fileRef = *ref;
|
fileRef = *ref;
|
||||||
fFileRef = *ref;
|
fFileRef = *ref;
|
||||||
} else {
|
} else
|
||||||
char appPath[B_PATH_NAME_LENGTH];
|
error = BPrivate::get_app_ref(&fileRef);
|
||||||
error = BPrivate::Storage::get_app_path(appPath);
|
|
||||||
if (error == B_OK)
|
|
||||||
error = get_ref_for_path(appPath, &fileRef);
|
|
||||||
}
|
|
||||||
// get the BResources
|
// get the BResources
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
BFile file(&fileRef, B_READ_ONLY);
|
BFile file(&fileRef, B_READ_ONLY);
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "fsproto.h"
|
#include "fsproto.h"
|
||||||
#include "kernel_interface.h"
|
|
||||||
|
|
||||||
/*! \fn status_t GetStat(struct stat *st) const
|
/*! \fn status_t GetStat(struct stat *st) const
|
||||||
\brief Returns the stat stucture for the node.
|
\brief Returns the stat stucture for the node.
|
||||||
|
|||||||
+20
-138
@@ -13,7 +13,9 @@
|
|||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include "kernel_interface.h"
|
|
||||||
|
#include <syscalls.h>
|
||||||
|
|
||||||
#include "storage_support.h"
|
#include "storage_support.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -26,8 +28,6 @@ namespace OpenBeOS {
|
|||||||
//! Creates an uninitialized BSymLink object.
|
//! Creates an uninitialized BSymLink object.
|
||||||
BSymLink::BSymLink()
|
BSymLink::BSymLink()
|
||||||
: BNode()
|
: BNode()
|
||||||
// WORKAROUND
|
|
||||||
, fSecretEntry(new(nothrow) BEntry)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,11 +36,8 @@ BSymLink::BSymLink()
|
|||||||
/*! \param link the BSymLink object to be copied
|
/*! \param link the BSymLink object to be copied
|
||||||
*/
|
*/
|
||||||
BSymLink::BSymLink(const BSymLink &link)
|
BSymLink::BSymLink(const BSymLink &link)
|
||||||
: BNode()
|
: BNode(link)
|
||||||
// WORKAROUND
|
|
||||||
, fSecretEntry(new(nothrow) BEntry)
|
|
||||||
{
|
{
|
||||||
*this = link;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
@@ -49,11 +46,8 @@ BSymLink::BSymLink(const BSymLink &link)
|
|||||||
\param ref the entry_ref referring to the symbolic link
|
\param ref the entry_ref referring to the symbolic link
|
||||||
*/
|
*/
|
||||||
BSymLink::BSymLink(const entry_ref *ref)
|
BSymLink::BSymLink(const entry_ref *ref)
|
||||||
: BNode()
|
: BNode(ref)
|
||||||
// WORKAROUND
|
|
||||||
, fSecretEntry(new(nothrow) BEntry)
|
|
||||||
{
|
{
|
||||||
SetTo(ref);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
@@ -62,11 +56,8 @@ BSymLink::BSymLink(const entry_ref *ref)
|
|||||||
\param entry the BEntry referring to the symbolic link
|
\param entry the BEntry referring to the symbolic link
|
||||||
*/
|
*/
|
||||||
BSymLink::BSymLink(const BEntry *entry)
|
BSymLink::BSymLink(const BEntry *entry)
|
||||||
: BNode()
|
: BNode(entry)
|
||||||
// WORKAROUND
|
|
||||||
, fSecretEntry(new(nothrow) BEntry)
|
|
||||||
{
|
{
|
||||||
SetTo(entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
@@ -75,11 +66,8 @@ BSymLink::BSymLink(const BEntry *entry)
|
|||||||
\param path the symbolic link's path name
|
\param path the symbolic link's path name
|
||||||
*/
|
*/
|
||||||
BSymLink::BSymLink(const char *path)
|
BSymLink::BSymLink(const char *path)
|
||||||
: BNode()
|
: BNode(path)
|
||||||
// WORKAROUND
|
|
||||||
, fSecretEntry(new(nothrow) BEntry)
|
|
||||||
{
|
{
|
||||||
SetTo(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
@@ -90,11 +78,8 @@ BSymLink::BSymLink(const char *path)
|
|||||||
\param path the symbolic link's path name relative to \a dir
|
\param path the symbolic link's path name relative to \a dir
|
||||||
*/
|
*/
|
||||||
BSymLink::BSymLink(const BDirectory *dir, const char *path)
|
BSymLink::BSymLink(const BDirectory *dir, const char *path)
|
||||||
: BNode()
|
: BNode(dir, path)
|
||||||
// WORKAROUND
|
|
||||||
, fSecretEntry(new(nothrow) BEntry)
|
|
||||||
{
|
{
|
||||||
SetTo(dir, path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
@@ -104,76 +89,8 @@ BSymLink::BSymLink(const BDirectory *dir, const char *path)
|
|||||||
*/
|
*/
|
||||||
BSymLink::~BSymLink()
|
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
|
// ReadLink
|
||||||
//! Reads the contents of the symbolic link into a buffer.
|
//! Reads the contents of the symbolic link into a buffer.
|
||||||
/*! \param buf the buffer
|
/*! \param buf the buffer
|
||||||
@@ -188,30 +105,11 @@ BSymLink::Unset()
|
|||||||
ssize_t
|
ssize_t
|
||||||
BSymLink::ReadLink(char *buf, size_t size)
|
BSymLink::ReadLink(char *buf, size_t size)
|
||||||
{
|
{
|
||||||
/*
|
if (!buf)
|
||||||
status_t error = (buf ? B_OK : B_BAD_VALUE);
|
return B_BAD_VALUE;
|
||||||
if (error == B_OK && InitCheck() != B_OK)
|
if (InitCheck() != B_OK)
|
||||||
error = B_FILE_ERROR;
|
return B_FILE_ERROR;
|
||||||
if (error == B_OK)
|
return _kern_read_link(get_fd(), NULL, buf, size);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeLinkedPath
|
// 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
|
// 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".
|
// be resolved, i.e. a "/tmp" dirPath expands to "/boot/var/tmp".
|
||||||
// That does also mean, that the dirPath must exists!
|
// That does also mean, that the dirPath must exists!
|
||||||
ssize_t result = (dirPath && path ? B_OK : B_BAD_VALUE);
|
if (!dirPath || !path)
|
||||||
if (result == B_OK) {
|
return B_BAD_VALUE;
|
||||||
BDirectory dir(dirPath);
|
BDirectory dir(dirPath);
|
||||||
result = dir.InitCheck();
|
ssize_t result = dir.InitCheck();
|
||||||
if (result == B_OK)
|
if (result == B_OK)
|
||||||
result = MakeLinkedPath(&dir, path);
|
result = MakeLinkedPath(&dir, path);
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,10 +156,10 @@ BSymLink::MakeLinkedPath(const char *dirPath, BPath *path)
|
|||||||
ssize_t
|
ssize_t
|
||||||
BSymLink::MakeLinkedPath(const BDirectory *dir, BPath *path)
|
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];
|
char contents[B_PATH_NAME_LENGTH];
|
||||||
if (result == 0)
|
ssize_t result = ReadLink(contents, sizeof(contents));
|
||||||
result = ReadLink(contents, sizeof(contents));
|
|
||||||
if (result >= 0) {
|
if (result >= 0) {
|
||||||
if (BPrivate::Storage::is_absolute_path(contents))
|
if (BPrivate::Storage::is_absolute_path(contents))
|
||||||
result = path->SetTo(contents);
|
result = path->SetTo(contents);
|
||||||
@@ -291,19 +188,6 @@ BSymLink::IsAbsolute()
|
|||||||
return result;
|
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::_MissingSymLink1() {}
|
||||||
void BSymLink::_MissingSymLink2() {}
|
void BSymLink::_MissingSymLink2() {}
|
||||||
@@ -316,7 +200,7 @@ void BSymLink::_MissingSymLink6() {}
|
|||||||
/*! To be used instead of accessing the BNode's private \c fFd member directly.
|
/*! To be used instead of accessing the BNode's private \c fFd member directly.
|
||||||
\return the file descriptor, or -1, if not properly initialized.
|
\return the file descriptor, or -1, if not properly initialized.
|
||||||
*/
|
*/
|
||||||
BPrivate::Storage::FileDescriptor
|
int
|
||||||
BSymLink::get_fd() const
|
BSymLink::get_fd() const
|
||||||
{
|
{
|
||||||
return fFd;
|
return fFd;
|
||||||
@@ -327,5 +211,3 @@ BSymLink::get_fd() const
|
|||||||
}; // namespace OpenBeOS
|
}; // namespace OpenBeOS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,14 +12,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <Bitmap.h>
|
#include <Bitmap.h>
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <fs_info.h>
|
#include <fs_info.h>
|
||||||
#include <kernel_interface.h>
|
#include <fs_interface.h>
|
||||||
#include <Node.h>
|
#include <Node.h>
|
||||||
|
#include <Path.h>
|
||||||
#include <Volume.h>
|
#include <Volume.h>
|
||||||
|
|
||||||
|
#include <storage_support.h>
|
||||||
|
#include <syscalls.h>
|
||||||
|
|
||||||
#ifdef USE_OPENBEOS_NAMESPACE
|
#ifdef USE_OPENBEOS_NAMESPACE
|
||||||
namespace OpenBeOS {
|
namespace OpenBeOS {
|
||||||
@@ -272,13 +276,46 @@ status_t
|
|||||||
BVolume::SetName(const char *name)
|
BVolume::SetName(const char *name)
|
||||||
{
|
{
|
||||||
// check initialization
|
// check initialization
|
||||||
status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
|
if (!name || InitCheck() != B_OK)
|
||||||
if (error == B_OK)
|
return B_BAD_VALUE;
|
||||||
error = BPrivate::Storage::set_volume_name(fDevice, name);
|
if (strlen(name) >= B_FILE_NAME_LENGTH)
|
||||||
|
return B_NAME_TOO_LONG;
|
||||||
// ToDo: change the name of the mount point, too
|
// get the FS stat (including the old name) first
|
||||||
// (or the link to the boot volume, if that name has been changed)
|
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;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
#include <Bitmap.h>
|
#include <Bitmap.h>
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <fs_info.h>
|
#include <fs_info.h>
|
||||||
#include <kernel_interface.h>
|
|
||||||
#include <Node.h>
|
#include <Node.h>
|
||||||
#include <NodeMonitor.h>
|
#include <NodeMonitor.h>
|
||||||
#include <VolumeRoster.h>
|
#include <VolumeRoster.h>
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include <MimeType.h>
|
#include <MimeType.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
#include <kernel_interface.h>
|
|
||||||
#include <mime/database_support.h>
|
#include <mime/database_support.h>
|
||||||
#include <storage_support.h>
|
#include <storage_support.h>
|
||||||
|
|
||||||
@@ -144,11 +143,12 @@ status_t
|
|||||||
AssociatedTypes::GuessMimeType(const entry_ref *ref, BString *result)
|
AssociatedTypes::GuessMimeType(const entry_ref *ref, BString *result)
|
||||||
{
|
{
|
||||||
// Convert the entry_ref to a filename and then do the check
|
// Convert the entry_ref to a filename and then do the check
|
||||||
/*! \todo If the ref is invalid, */
|
if (!ref)
|
||||||
char path[B_PATH_NAME_LENGTH];
|
return B_BAD_VALUE;
|
||||||
status_t err = entry_ref_to_path(ref, path, B_PATH_NAME_LENGTH);
|
BPath path;
|
||||||
|
status_t err = path.SetTo(ref);
|
||||||
if (!err)
|
if (!err)
|
||||||
err = GuessMimeType(path, result);
|
err = GuessMimeType(path.Path(), result);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,16 +7,16 @@
|
|||||||
MimeUpdateThread implementation
|
MimeUpdateThread implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mime/MimeUpdateThread.h"
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <kernel_interface.h>
|
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include <RegistrarDefs.h>
|
#include <RegistrarDefs.h>
|
||||||
#include <Volume.h>
|
#include <Volume.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <storage_support.h>
|
||||||
|
#include "mime/MimeUpdateThread.h"
|
||||||
|
|
||||||
//#define DBG(x) x
|
//#define DBG(x) x
|
||||||
#define DBG(x)
|
#define DBG(x)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ STORAGE_KIT_SOURCE =
|
|||||||
# storage
|
# storage
|
||||||
AppFileInfo.cpp
|
AppFileInfo.cpp
|
||||||
Directory.cpp
|
Directory.cpp
|
||||||
# DiskScannerAddOn.cpp
|
|
||||||
Entry.cpp
|
Entry.cpp
|
||||||
EntryList.cpp
|
EntryList.cpp
|
||||||
File.cpp
|
File.cpp
|
||||||
@@ -25,7 +24,6 @@ STORAGE_KIT_SOURCE =
|
|||||||
SymLink.cpp
|
SymLink.cpp
|
||||||
Volume.cpp
|
Volume.cpp
|
||||||
VolumeRoster.cpp
|
VolumeRoster.cpp
|
||||||
kernel_interface.POSIX.cpp
|
|
||||||
storage_support.cpp
|
storage_support.cpp
|
||||||
|
|
||||||
# storage/mime
|
# storage/mime
|
||||||
|
|||||||
@@ -13,6 +13,9 @@
|
|||||||
|
|
||||||
#include <StorageDefs.h>
|
#include <StorageDefs.h>
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
#include <syscalls.h>
|
||||||
|
|
||||||
#include "storage_support.h"
|
#include "storage_support.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -30,9 +33,105 @@ is_absolute_path(const char *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse_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
|
static
|
||||||
void
|
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)
|
if (fullPath == NULL)
|
||||||
return;
|
return;
|
||||||
@@ -109,7 +208,7 @@ split_path(const char *fullPath, char **path, char **leaf)
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
int leafStart, leafEnd, pathEnd, len;
|
int leafStart, leafEnd, pathEnd, len;
|
||||||
parse_path(fullPath, leafStart, leafEnd, pathEnd);
|
internal_parse_path(fullPath, leafStart, leafEnd, pathEnd);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Tidy up/handle special cases
|
// 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 Storage
|
||||||
}; // namespace BPrivate
|
}; // namespace BPrivate
|
||||||
|
|
||||||
|
|||||||
@@ -32,9 +32,9 @@
|
|||||||
#include <AppFileInfo.h>
|
#include <AppFileInfo.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include <kernel_interface.h> // From the Storage Kit
|
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
#include <Mime.h>
|
#include <Mime.h>
|
||||||
|
#include <Path.h>
|
||||||
#include <Roster.h>
|
#include <Roster.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
#include <storage_support.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
|
// We're going to need to properly escape the path name we
|
||||||
// get, which will at absolute worst double the length of
|
// get, which will at absolute worst double the length of
|
||||||
// the string.
|
// the string.
|
||||||
char path[B_PATH_NAME_LENGTH];
|
BPath path;
|
||||||
char escapedPath[B_PATH_NAME_LENGTH*2];
|
char escapedPath[B_PATH_NAME_LENGTH*2];
|
||||||
status_t outputError = BPrivate::Storage::entry_ref_to_path(&mapItem->first,
|
status_t outputError = path.SetTo(&mapItem->first);
|
||||||
path, B_PATH_NAME_LENGTH);
|
|
||||||
if (!outputError) {
|
if (!outputError) {
|
||||||
BPrivate::Storage::escape_path(path, escapedPath);
|
BPrivate::Storage::escape_path(path.Path(), escapedPath);
|
||||||
fprintf(file, "%s %s", tag, escapedPath);
|
fprintf(file, "%s %s", tag, escapedPath);
|
||||||
std::list<recent_entry*> &list = mapItem->second;
|
std::list<recent_entry*> &list = mapItem->second;
|
||||||
int32 i = 0;
|
int32 i = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user