libroot_build.so:
* Reorganized sources a bit: - The descriptor support is in a separate file now. - Disentangled the attribute support from the other stuff. * Removed broken xattr use for attribute support. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20606 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -26,6 +26,7 @@ BuildPlatformSharedLibrary libroot_build.so :
|
|||||||
errors.cpp
|
errors.cpp
|
||||||
fs.cpp
|
fs.cpp
|
||||||
fs_attr.cpp
|
fs_attr.cpp
|
||||||
|
fs_descriptors.cpp
|
||||||
misc.cpp
|
misc.cpp
|
||||||
sem.cpp
|
sem.cpp
|
||||||
thread.cpp
|
thread.cpp
|
||||||
|
|||||||
+7
-399
@@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
#include <BeOSBuildCompatibility.h>
|
#include <BeOSBuildCompatibility.h>
|
||||||
|
|
||||||
|
#include "fs_impl.h"
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -17,296 +19,21 @@
|
|||||||
#include <NodeMonitor.h> // for B_STAT_* flags
|
#include <NodeMonitor.h> // for B_STAT_* flags
|
||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
|
|
||||||
#include "fs_attr_impl.h"
|
#include "fs_descriptors.h"
|
||||||
#include "NodeRef.h"
|
#include "NodeRef.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace BPrivate;
|
using namespace BPrivate;
|
||||||
|
|
||||||
static const int kVirtualDescriptorStart = 10000;
|
|
||||||
|
|
||||||
static status_t get_path(dev_t device, ino_t node, const char *name, string &path);
|
static status_t get_path(dev_t device, ino_t node, const char *name,
|
||||||
|
string &path);
|
||||||
|
|
||||||
namespace BPrivate {
|
|
||||||
class Descriptor;
|
|
||||||
}
|
|
||||||
using namespace BPrivate;
|
|
||||||
|
|
||||||
typedef map<int, Descriptor*> DescriptorMap;
|
|
||||||
static DescriptorMap sDescriptors;
|
|
||||||
|
|
||||||
namespace BPrivate {
|
|
||||||
|
|
||||||
// Descriptor
|
|
||||||
struct Descriptor {
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
virtual ~Descriptor()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t Close() = 0;
|
|
||||||
virtual status_t Dup(Descriptor *&clone) = 0;
|
|
||||||
virtual status_t GetStat(bool traverseLink, struct stat *st) = 0;
|
|
||||||
|
|
||||||
virtual status_t GetNodeRef(NodeRef &ref)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
status_t error = GetStat(false, &st);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
ref = NodeRef(st);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// FileDescriptor
|
|
||||||
struct FileDescriptor : Descriptor {
|
|
||||||
FileDescriptor(int fd)
|
|
||||||
{
|
|
||||||
this->fd = fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~FileDescriptor()
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t Close()
|
|
||||||
{
|
|
||||||
if (fd >= 0) {
|
|
||||||
int oldFD = fd;
|
|
||||||
fd = -1;
|
|
||||||
if (close(oldFD) < 0)
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t Dup(Descriptor *&clone)
|
|
||||||
{
|
|
||||||
int dupFD = dup(fd);
|
|
||||||
if (dupFD < 0)
|
|
||||||
return errno;
|
|
||||||
|
|
||||||
clone = new FileDescriptor(dupFD);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t GetStat(bool traverseLink, struct stat *st)
|
|
||||||
{
|
|
||||||
if (fstat(fd, st) < 0)
|
|
||||||
return errno;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// DirectoryDescriptor
|
|
||||||
struct DirectoryDescriptor : Descriptor {
|
|
||||||
DIR *dir;
|
|
||||||
NodeRef ref;
|
|
||||||
|
|
||||||
DirectoryDescriptor(DIR *dir, const NodeRef &ref)
|
|
||||||
{
|
|
||||||
this->dir = dir;
|
|
||||||
this->ref = ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~DirectoryDescriptor()
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t Close()
|
|
||||||
{
|
|
||||||
if (dir) {
|
|
||||||
DIR *oldDir = dir;
|
|
||||||
dir = NULL;
|
|
||||||
if (closedir(oldDir) < 0)
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t Dup(Descriptor *&clone)
|
|
||||||
{
|
|
||||||
string path;
|
|
||||||
status_t error = get_path(fd, NULL, path);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
DIR *dupDir = opendir(path.c_str());
|
|
||||||
if (!dupDir)
|
|
||||||
return errno;
|
|
||||||
|
|
||||||
clone = new DirectoryDescriptor(dupDir, ref);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t GetStat(bool traverseLink, struct stat *st)
|
|
||||||
{
|
|
||||||
// get a usable path
|
|
||||||
string realPath;
|
|
||||||
status_t error = get_path(fd, NULL, realPath);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
// stat
|
|
||||||
int result;
|
|
||||||
result = stat(realPath.c_str(), st);
|
|
||||||
|
|
||||||
if (result < 0)
|
|
||||||
return errno;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t GetNodeRef(NodeRef &ref)
|
|
||||||
{
|
|
||||||
ref = this->ref;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// SymlinkDescriptor
|
|
||||||
struct SymlinkDescriptor : Descriptor {
|
|
||||||
string path;
|
|
||||||
|
|
||||||
SymlinkDescriptor(const char *path)
|
|
||||||
{
|
|
||||||
this->path = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t Close()
|
|
||||||
{
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t Dup(Descriptor *&clone)
|
|
||||||
{
|
|
||||||
clone = new SymlinkDescriptor(path.c_str());
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t GetStat(bool traverseLink, struct stat *st)
|
|
||||||
{
|
|
||||||
// stat
|
|
||||||
int result;
|
|
||||||
if (traverseLink)
|
|
||||||
result = stat(path.c_str(), st);
|
|
||||||
else
|
|
||||||
result = lstat(path.c_str(), st);
|
|
||||||
|
|
||||||
if (result < 0)
|
|
||||||
return errno;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// AttrDirDescriptor
|
|
||||||
struct AttrDirDescriptor : DirectoryDescriptor {
|
|
||||||
|
|
||||||
AttrDirDescriptor(DIR *dir, const NodeRef &ref)
|
|
||||||
: DirectoryDescriptor(dir, ref)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~AttrDirDescriptor()
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t Close()
|
|
||||||
{
|
|
||||||
if (dir) {
|
|
||||||
DIR *oldDir = dir;
|
|
||||||
dir = NULL;
|
|
||||||
if (fs_close_attr_dir(oldDir) < 0)
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t Dup(Descriptor *&clone)
|
|
||||||
{
|
|
||||||
// we don't allow dup()int attr dir descriptors
|
|
||||||
return B_FILE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t GetStat(bool traverseLink, struct stat *st)
|
|
||||||
{
|
|
||||||
// we don't allow stat()int attr dir descriptors
|
|
||||||
return B_FILE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t GetNodeRef(NodeRef &ref)
|
|
||||||
{
|
|
||||||
ref = this->ref;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace BPrivate
|
|
||||||
|
|
||||||
// get_descriptor
|
|
||||||
static Descriptor *
|
|
||||||
get_descriptor(int fd)
|
|
||||||
{
|
|
||||||
DescriptorMap::iterator it = sDescriptors.find(fd);
|
|
||||||
if (it == sDescriptors.end())
|
|
||||||
return NULL;
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
add_descriptor(Descriptor *descriptor)
|
|
||||||
{
|
|
||||||
int fd = -1;
|
|
||||||
if (FileDescriptor *file = dynamic_cast<FileDescriptor*>(descriptor)) {
|
|
||||||
fd = file->fd;
|
|
||||||
} else {
|
|
||||||
// find a free slot
|
|
||||||
for (fd = kVirtualDescriptorStart;
|
|
||||||
sDescriptors.find(fd) != sDescriptors.end();
|
|
||||||
fd++) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sDescriptors[fd] = descriptor;
|
|
||||||
descriptor->fd = fd;
|
|
||||||
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete_descriptor
|
|
||||||
static status_t
|
|
||||||
delete_descriptor(int fd)
|
|
||||||
{
|
|
||||||
DescriptorMap::iterator it = sDescriptors.find(fd);
|
|
||||||
if (it == sDescriptors.end())
|
|
||||||
return B_FILE_ERROR;
|
|
||||||
|
|
||||||
status_t error = it->second->Close();
|
|
||||||
delete it->second;
|
|
||||||
sDescriptors.erase(it);
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
// find_dir_entry
|
// find_dir_entry
|
||||||
static status_t
|
static status_t
|
||||||
find_dir_entry(DIR *dir, const char *path, NodeRef ref, string &name, bool skipDot)
|
find_dir_entry(DIR *dir, const char *path, NodeRef ref, string &name,
|
||||||
|
bool skipDot)
|
||||||
{
|
{
|
||||||
// find the entry
|
// find the entry
|
||||||
bool found = false;
|
bool found = false;
|
||||||
@@ -1193,125 +920,6 @@ _kern_unlock_node(int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
// _kern_open_attr_dir
|
|
||||||
int
|
|
||||||
_kern_open_attr_dir(int fd, const char *path)
|
|
||||||
{
|
|
||||||
// get node ref for the node
|
|
||||||
struct stat st;
|
|
||||||
status_t error = _kern_read_stat(fd, path, false, &st,
|
|
||||||
sizeof(struct stat));
|
|
||||||
if (error != B_OK) {
|
|
||||||
errno = error;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
NodeRef ref(st);
|
|
||||||
|
|
||||||
// If a path was given, get a usable path.
|
|
||||||
string realPath;
|
|
||||||
if (path) {
|
|
||||||
error = get_path(fd, path, realPath);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// open the attr dir
|
|
||||||
DIR *dir = open_attr_dir(ref, (path ? realPath.c_str() : NULL),
|
|
||||||
(path ? -1 : fd));
|
|
||||||
if (!dir)
|
|
||||||
return errno;
|
|
||||||
|
|
||||||
// create descriptor
|
|
||||||
AttrDirDescriptor *descriptor = new AttrDirDescriptor(dir, ref);
|
|
||||||
return add_descriptor(descriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get_attribute_path
|
|
||||||
static status_t
|
|
||||||
get_attribute_path(int fd, const char *attribute, string &attrPath,
|
|
||||||
string &typePath)
|
|
||||||
{
|
|
||||||
// stat the file to get a NodeRef
|
|
||||||
struct stat st;
|
|
||||||
status_t error = _kern_read_stat(fd, NULL, false, &st, sizeof(st));
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
NodeRef ref(st);
|
|
||||||
|
|
||||||
// Try to get a path. If we can't get a path, this is must be a "real"
|
|
||||||
// (i.e. system) file descriptor, which is just as well.
|
|
||||||
string path;
|
|
||||||
bool pathValid = (get_path(fd, NULL, path) == B_OK);
|
|
||||||
|
|
||||||
// get the attribute path
|
|
||||||
return get_attribute_path(ref, (pathValid ? path.c_str() : NULL),
|
|
||||||
(pathValid ? -1 : fd), attribute, attrPath, typePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// _kern_rename_attr
|
|
||||||
status_t
|
|
||||||
_kern_rename_attr(int fromFile, const char *fromName, int toFile,
|
|
||||||
const char *toName)
|
|
||||||
{
|
|
||||||
if (!fromName || !toName)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
// get the attribute paths
|
|
||||||
string fromAttrPath;
|
|
||||||
string fromTypePath;
|
|
||||||
status_t error = get_attribute_path(fromFile, fromName, fromAttrPath,
|
|
||||||
fromTypePath);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
string toAttrPath;
|
|
||||||
string toTypePath;
|
|
||||||
error = get_attribute_path(toFile, toName, toAttrPath, toTypePath);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
// rename the attribute and type files
|
|
||||||
if (rename(fromAttrPath.c_str(), toAttrPath.c_str()) < 0)
|
|
||||||
return errno;
|
|
||||||
|
|
||||||
if (rename(fromTypePath.c_str(), toTypePath.c_str()) < 0) {
|
|
||||||
// renaming the type file failed: try to rename back the attribute file
|
|
||||||
error = errno;
|
|
||||||
|
|
||||||
rename(toAttrPath.c_str(), fromAttrPath.c_str());
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// _kern_remove_attr
|
|
||||||
status_t
|
|
||||||
_kern_remove_attr(int fd, const char *name)
|
|
||||||
{
|
|
||||||
if (!name)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
// get the attribute path
|
|
||||||
string attrPath;
|
|
||||||
string typePath;
|
|
||||||
status_t error = get_attribute_path(fd, name, attrPath, typePath);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
// remove the attribute
|
|
||||||
if (unlink(attrPath.c_str()) < 0)
|
|
||||||
return errno;
|
|
||||||
|
|
||||||
unlink(typePath.c_str());
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
// read_pos
|
// read_pos
|
||||||
|
|||||||
+142
-116
@@ -9,11 +9,6 @@
|
|||||||
# include <syscalls.h>
|
# include <syscalls.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Defined, if the host platform has extended attribute support.
|
|
||||||
// Unfortunately I don't seem to have extended attribute support under
|
|
||||||
// SuSE Linux 9.2 (kernel 2.6.8-...) with ReiserFS 3.6.
|
|
||||||
//#define HAS_EXTENDED_ATTRIBUTE_SUPPORT 1
|
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -26,13 +21,9 @@
|
|||||||
|
|
||||||
#include <fs_attr.h>
|
#include <fs_attr.h>
|
||||||
|
|
||||||
#include "fs_attr_impl.h"
|
#include "fs_impl.h"
|
||||||
|
#include "fs_descriptors.h"
|
||||||
|
|
||||||
#ifdef HAS_EXTENDED_ATTRIBUTE_SUPPORT
|
|
||||||
#include <sys/xattr.h>
|
|
||||||
|
|
||||||
static const char *kAttributeDirMarkAttributeName = "_has_haiku_attr_dir";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace BPrivate;
|
using namespace BPrivate;
|
||||||
@@ -133,87 +124,6 @@ get_attribute_dir_path(NodeRef ref)
|
|||||||
return attrDirPath;
|
return attrDirPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// has_attribute_dir_mark
|
|
||||||
static bool
|
|
||||||
has_attribute_dir_mark(const char *path, int fd)
|
|
||||||
{
|
|
||||||
#ifdef HAS_EXTENDED_ATTRIBUTE_SUPPORT
|
|
||||||
|
|
||||||
uint8 value;
|
|
||||||
if (path) {
|
|
||||||
return (lgetxattr(path, kAttributeDirMarkAttributeName, &value, 1)
|
|
||||||
> 0);
|
|
||||||
} else {
|
|
||||||
return (fgetxattr(fd, kAttributeDirMarkAttributeName, &value, 1)
|
|
||||||
> 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else // !HAS_EXTENDED_ATTRIBUTE_SUPPORT
|
|
||||||
|
|
||||||
// No extended attribute support. We can't mark the file and thus
|
|
||||||
// have to handle it as marked.
|
|
||||||
return true;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// set_attribute_dir_mark
|
|
||||||
static status_t
|
|
||||||
set_attribute_dir_mark(const char *path, int fd)
|
|
||||||
{
|
|
||||||
#ifdef HAS_EXTENDED_ATTRIBUTE_SUPPORT
|
|
||||||
|
|
||||||
uint8 value = 1;
|
|
||||||
if (path) {
|
|
||||||
if (lsetxattr(path, kAttributeDirMarkAttributeName, &value, 1, 0)
|
|
||||||
< 0) {
|
|
||||||
fprintf(stderr, "set_attribute_dir_mark(): lsetxattr() "
|
|
||||||
"failed on \"%s\"\n", path);
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (fsetxattr(fd, kAttributeDirMarkAttributeName, &value, 1, 0)
|
|
||||||
< 0) {
|
|
||||||
fprintf(stderr, "set_attribute_dir_mark(): fsetxattr() "
|
|
||||||
"failed on FD \"%d\"\n", fd);
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// empty_attribute_dir
|
|
||||||
static status_t
|
|
||||||
empty_attribute_dir(const char *path)
|
|
||||||
{
|
|
||||||
DIR *dir = opendir(path);
|
|
||||||
if (!dir)
|
|
||||||
return errno;
|
|
||||||
|
|
||||||
while (dirent *entry = readdir(dir)) {
|
|
||||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
string entryPath(path);
|
|
||||||
entryPath += '/';
|
|
||||||
entryPath += entry->d_name;
|
|
||||||
|
|
||||||
// We assume the attribute dir contains files only (we only create
|
|
||||||
// files) and thus use unlink().
|
|
||||||
if (unlink(entryPath.c_str()) < 0) {
|
|
||||||
status_t error = errno;
|
|
||||||
closedir(dir);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(dir);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure_attribute_dir_exists
|
// ensure_attribute_dir_exists
|
||||||
static status_t
|
static status_t
|
||||||
ensure_attribute_dir_exists(NodeRef ref, const char *path, int fd)
|
ensure_attribute_dir_exists(NodeRef ref, const char *path, int fd)
|
||||||
@@ -235,37 +145,19 @@ ensure_attribute_dir_exists(NodeRef ref, const char *path, int fd)
|
|||||||
return B_FILE_ERROR;
|
return B_FILE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// already exists: Check whether the file is marked. If not, this
|
return B_OK;
|
||||||
// is a stale attribute directory from a deleted node that had the
|
|
||||||
// same node ID as this one.
|
|
||||||
if (has_attribute_dir_mark(path, fd))
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
// empty the attribute dir
|
|
||||||
error = empty_attribute_dir(attrDirPath.c_str());
|
|
||||||
if (error != B_OK) {
|
|
||||||
fprintf(stderr, "ensure_attribute_dir_exists(): Attribute "
|
|
||||||
"directory for node %lld exists, the node has no mark, and "
|
|
||||||
"emptying the attribute directory failed\n",
|
|
||||||
ref.node);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// mark the file
|
|
||||||
return set_attribute_dir_mark(path, fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// doesn't exist yet: create it
|
// doesn't exist yet: create it
|
||||||
if (mkdir(attrDirPath.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) < 0)
|
if (mkdir(attrDirPath.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) < 0)
|
||||||
return errno;
|
return errno;
|
||||||
|
|
||||||
// mark the file
|
return B_OK;
|
||||||
return set_attribute_dir_mark(path, fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// open_attr_dir
|
// open_attr_dir
|
||||||
DIR *
|
static DIR *
|
||||||
BPrivate::open_attr_dir(NodeRef ref, const char *path, int fd)
|
open_attr_dir(NodeRef ref, const char *path, int fd)
|
||||||
{
|
{
|
||||||
// make sure the directory exists
|
// make sure the directory exists
|
||||||
status_t error = ensure_attribute_dir_exists(ref, path, fd);
|
status_t error = ensure_attribute_dir_exists(ref, path, fd);
|
||||||
@@ -280,8 +172,8 @@ BPrivate::open_attr_dir(NodeRef ref, const char *path, int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get_attribute_path
|
// get_attribute_path
|
||||||
status_t
|
static status_t
|
||||||
BPrivate::get_attribute_path(NodeRef ref, const char *path, int fd,
|
get_attribute_path(NodeRef ref, const char *path, int fd,
|
||||||
const char *attribute, string &attrPath, string &typePath)
|
const char *attribute, string &attrPath, string &typePath)
|
||||||
{
|
{
|
||||||
if (!attribute || strlen(attribute) == 0)
|
if (!attribute || strlen(attribute) == 0)
|
||||||
@@ -317,6 +209,37 @@ get_attribute_path(int fd, const char *attribute, string &attrPath,
|
|||||||
return get_attribute_path(ref, NULL, fd, attribute, attrPath, typePath);
|
return get_attribute_path(ref, NULL, fd, attribute, attrPath, typePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef BUILDING_FS_SHELL
|
||||||
|
|
||||||
|
// get_attribute_path_virtual_fd
|
||||||
|
static status_t
|
||||||
|
get_attribute_path_virtual_fd(int fd, const char *attribute, string &attrPath,
|
||||||
|
string &typePath)
|
||||||
|
{
|
||||||
|
// stat the file to get a NodeRef
|
||||||
|
struct stat st;
|
||||||
|
status_t error = _kern_read_stat(fd, NULL, false, &st, sizeof(st));
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
NodeRef ref(st);
|
||||||
|
|
||||||
|
// Try to get a path. If we can't get a path, this is must be a "real"
|
||||||
|
// (i.e. system) file descriptor, which is just as well.
|
||||||
|
string path;
|
||||||
|
bool pathValid = (get_path(fd, NULL, path) == B_OK);
|
||||||
|
|
||||||
|
// get the attribute path
|
||||||
|
return get_attribute_path(ref, (pathValid ? path.c_str() : NULL),
|
||||||
|
(pathValid ? -1 : fd), attribute, attrPath, typePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ! BUILDING_FS_SHELL
|
||||||
|
|
||||||
|
|
||||||
|
// # pragma mark - Public API
|
||||||
|
|
||||||
|
|
||||||
// fs_open_attr_dir
|
// fs_open_attr_dir
|
||||||
DIR *
|
DIR *
|
||||||
fs_open_attr_dir(const char *path)
|
fs_open_attr_dir(const char *path)
|
||||||
@@ -586,3 +509,106 @@ fs_stat_attr(int fd, const char *attribute, struct attr_info *attrInfo)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Private Syscalls
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef BUILDING_FS_SHELL
|
||||||
|
|
||||||
|
// _kern_open_attr_dir
|
||||||
|
int
|
||||||
|
_kern_open_attr_dir(int fd, const char *path)
|
||||||
|
{
|
||||||
|
// get node ref for the node
|
||||||
|
struct stat st;
|
||||||
|
status_t error = _kern_read_stat(fd, path, false, &st,
|
||||||
|
sizeof(struct stat));
|
||||||
|
if (error != B_OK) {
|
||||||
|
errno = error;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
NodeRef ref(st);
|
||||||
|
|
||||||
|
// If a path was given, get a usable path.
|
||||||
|
string realPath;
|
||||||
|
if (path) {
|
||||||
|
error = get_path(fd, path, realPath);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open the attr dir
|
||||||
|
DIR *dir = open_attr_dir(ref, (path ? realPath.c_str() : NULL),
|
||||||
|
(path ? -1 : fd));
|
||||||
|
if (!dir)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
// create descriptor
|
||||||
|
AttrDirDescriptor *descriptor = new AttrDirDescriptor(dir, ref);
|
||||||
|
return add_descriptor(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// _kern_rename_attr
|
||||||
|
status_t
|
||||||
|
_kern_rename_attr(int fromFile, const char *fromName, int toFile,
|
||||||
|
const char *toName)
|
||||||
|
{
|
||||||
|
if (!fromName || !toName)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// get the attribute paths
|
||||||
|
string fromAttrPath;
|
||||||
|
string fromTypePath;
|
||||||
|
status_t error = get_attribute_path_virtual_fd(fromFile, fromName,
|
||||||
|
fromAttrPath, fromTypePath);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
string toAttrPath;
|
||||||
|
string toTypePath;
|
||||||
|
error = get_attribute_path_virtual_fd(toFile, toName, toAttrPath,
|
||||||
|
toTypePath);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// rename the attribute and type files
|
||||||
|
if (rename(fromAttrPath.c_str(), toAttrPath.c_str()) < 0)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
if (rename(fromTypePath.c_str(), toTypePath.c_str()) < 0) {
|
||||||
|
// renaming the type file failed: try to rename back the attribute file
|
||||||
|
error = errno;
|
||||||
|
|
||||||
|
rename(toAttrPath.c_str(), fromAttrPath.c_str());
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _kern_remove_attr
|
||||||
|
status_t
|
||||||
|
_kern_remove_attr(int fd, const char *name)
|
||||||
|
{
|
||||||
|
if (!name)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// get the attribute path
|
||||||
|
string attrPath;
|
||||||
|
string typePath;
|
||||||
|
status_t error = get_attribute_path_virtual_fd(fd, name, attrPath,
|
||||||
|
typePath);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// remove the attribute
|
||||||
|
if (unlink(attrPath.c_str()) < 0)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
unlink(typePath.c_str());
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ! BUILDING_FS_SHELL
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
#ifndef FS_ATTR_IMPL_H
|
|
||||||
#define FS_ATTR_IMPL_H
|
|
||||||
|
|
||||||
#include <dirent.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "NodeRef.h"
|
|
||||||
|
|
||||||
namespace BPrivate {
|
|
||||||
|
|
||||||
// defined in fs_attr.cpp
|
|
||||||
|
|
||||||
// Note: Only one of path or fd can be supplied.
|
|
||||||
DIR *open_attr_dir(NodeRef ref, const char *path, int fd);
|
|
||||||
|
|
||||||
// Note: Only one of path or fd can be supplied.
|
|
||||||
status_t get_attribute_path(NodeRef ref, const char *path, int fd,
|
|
||||||
const char *attribute, std::string &attrPath, std::string &typePath);
|
|
||||||
|
|
||||||
|
|
||||||
// defined in fs.cpp
|
|
||||||
|
|
||||||
status_t get_path(int fd, const char *name, std::string &path);
|
|
||||||
|
|
||||||
} // namespace BPrivate
|
|
||||||
|
|
||||||
#endif // FS_ATTR_IMPL_H
|
|
||||||
@@ -0,0 +1,319 @@
|
|||||||
|
|
||||||
|
#include <BeOSBuildCompatibility.h>
|
||||||
|
|
||||||
|
#include "fs_descriptors.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <fs_attr.h>
|
||||||
|
|
||||||
|
#include "fs_impl.h"
|
||||||
|
|
||||||
|
using std::map;
|
||||||
|
|
||||||
|
static const int kVirtualDescriptorStart = 10000;
|
||||||
|
|
||||||
|
typedef map<int, BPrivate::Descriptor*> DescriptorMap;
|
||||||
|
static DescriptorMap sDescriptors;
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Descriptor
|
||||||
|
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
Descriptor::~Descriptor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNodeRef
|
||||||
|
status_t
|
||||||
|
Descriptor::GetNodeRef(NodeRef &ref)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
status_t error = GetStat(false, &st);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
ref = NodeRef(st);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - FileDescriptor
|
||||||
|
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
FileDescriptor::FileDescriptor(int fd)
|
||||||
|
{
|
||||||
|
this->fd = fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
FileDescriptor::~FileDescriptor()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close
|
||||||
|
status_t
|
||||||
|
FileDescriptor::Close()
|
||||||
|
{
|
||||||
|
if (fd >= 0) {
|
||||||
|
int oldFD = fd;
|
||||||
|
fd = -1;
|
||||||
|
if (close(oldFD) < 0)
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dup
|
||||||
|
status_t
|
||||||
|
FileDescriptor::Dup(Descriptor *&clone)
|
||||||
|
{
|
||||||
|
int dupFD = dup(fd);
|
||||||
|
if (dupFD < 0)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
clone = new FileDescriptor(dupFD);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStat
|
||||||
|
status_t
|
||||||
|
FileDescriptor::GetStat(bool traverseLink, struct stat *st)
|
||||||
|
{
|
||||||
|
if (fstat(fd, st) < 0)
|
||||||
|
return errno;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - DirectoryDescriptor
|
||||||
|
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
DirectoryDescriptor::DirectoryDescriptor(DIR *dir, const NodeRef &ref)
|
||||||
|
{
|
||||||
|
this->dir = dir;
|
||||||
|
this->ref = ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
DirectoryDescriptor::~DirectoryDescriptor()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close
|
||||||
|
status_t
|
||||||
|
DirectoryDescriptor::Close()
|
||||||
|
{
|
||||||
|
if (dir) {
|
||||||
|
DIR *oldDir = dir;
|
||||||
|
dir = NULL;
|
||||||
|
if (closedir(oldDir) < 0)
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dup
|
||||||
|
status_t
|
||||||
|
DirectoryDescriptor::Dup(Descriptor *&clone)
|
||||||
|
{
|
||||||
|
string path;
|
||||||
|
status_t error = get_path(fd, NULL, path);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
DIR *dupDir = opendir(path.c_str());
|
||||||
|
if (!dupDir)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
clone = new DirectoryDescriptor(dupDir, ref);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStat
|
||||||
|
status_t
|
||||||
|
DirectoryDescriptor::GetStat(bool traverseLink, struct stat *st)
|
||||||
|
{
|
||||||
|
// get a usable path
|
||||||
|
string realPath;
|
||||||
|
status_t error = get_path(fd, NULL, realPath);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// stat
|
||||||
|
int result;
|
||||||
|
result = stat(realPath.c_str(), st);
|
||||||
|
|
||||||
|
if (result < 0)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNodeRef
|
||||||
|
status_t
|
||||||
|
DirectoryDescriptor::GetNodeRef(NodeRef &ref)
|
||||||
|
{
|
||||||
|
ref = this->ref;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - SymlinkDescriptor
|
||||||
|
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
SymlinkDescriptor::SymlinkDescriptor(const char *path)
|
||||||
|
{
|
||||||
|
this->path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close
|
||||||
|
status_t
|
||||||
|
SymlinkDescriptor::Close()
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dup
|
||||||
|
status_t
|
||||||
|
SymlinkDescriptor::Dup(Descriptor *&clone)
|
||||||
|
{
|
||||||
|
clone = new SymlinkDescriptor(path.c_str());
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStat
|
||||||
|
status_t
|
||||||
|
SymlinkDescriptor::GetStat(bool traverseLink, struct stat *st)
|
||||||
|
{
|
||||||
|
// stat
|
||||||
|
int result;
|
||||||
|
if (traverseLink)
|
||||||
|
result = stat(path.c_str(), st);
|
||||||
|
else
|
||||||
|
result = lstat(path.c_str(), st);
|
||||||
|
|
||||||
|
if (result < 0)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - AttrDirDescriptor
|
||||||
|
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
AttrDirDescriptor::AttrDirDescriptor(DIR *dir, const NodeRef &ref)
|
||||||
|
: DirectoryDescriptor(dir, ref)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
AttrDirDescriptor::~AttrDirDescriptor()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close
|
||||||
|
status_t
|
||||||
|
AttrDirDescriptor::Close()
|
||||||
|
{
|
||||||
|
if (dir) {
|
||||||
|
DIR *oldDir = dir;
|
||||||
|
dir = NULL;
|
||||||
|
if (fs_close_attr_dir(oldDir) < 0)
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dup
|
||||||
|
status_t
|
||||||
|
AttrDirDescriptor::Dup(Descriptor *&clone)
|
||||||
|
{
|
||||||
|
// we don't allow dup()int attr dir descriptors
|
||||||
|
return B_FILE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStat
|
||||||
|
status_t
|
||||||
|
AttrDirDescriptor::GetStat(bool traverseLink, struct stat *st)
|
||||||
|
{
|
||||||
|
// we don't allow stat()int attr dir descriptors
|
||||||
|
return B_FILE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNodeRef
|
||||||
|
status_t
|
||||||
|
AttrDirDescriptor::GetNodeRef(NodeRef &ref)
|
||||||
|
{
|
||||||
|
ref = this->ref;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// get_descriptor
|
||||||
|
Descriptor *
|
||||||
|
get_descriptor(int fd)
|
||||||
|
{
|
||||||
|
DescriptorMap::iterator it = sDescriptors.find(fd);
|
||||||
|
if (it == sDescriptors.end())
|
||||||
|
return NULL;
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add_descriptor
|
||||||
|
int
|
||||||
|
add_descriptor(Descriptor *descriptor)
|
||||||
|
{
|
||||||
|
int fd = -1;
|
||||||
|
if (FileDescriptor *file = dynamic_cast<FileDescriptor*>(descriptor)) {
|
||||||
|
fd = file->fd;
|
||||||
|
} else {
|
||||||
|
// find a free slot
|
||||||
|
for (fd = kVirtualDescriptorStart;
|
||||||
|
sDescriptors.find(fd) != sDescriptors.end();
|
||||||
|
fd++) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sDescriptors[fd] = descriptor;
|
||||||
|
descriptor->fd = fd;
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete_descriptor
|
||||||
|
status_t
|
||||||
|
delete_descriptor(int fd)
|
||||||
|
{
|
||||||
|
DescriptorMap::iterator it = sDescriptors.find(fd);
|
||||||
|
if (it == sDescriptors.end())
|
||||||
|
return B_FILE_ERROR;
|
||||||
|
|
||||||
|
status_t error = it->second->Close();
|
||||||
|
delete it->second;
|
||||||
|
sDescriptors.erase(it);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace BPrivate
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
#ifndef FS_DESCRIPTORS_H
|
||||||
|
#define FS_DESCRIPTORS_H
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
#include "NodeRef.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
struct stat;
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
|
||||||
|
// Descriptor
|
||||||
|
struct Descriptor {
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
virtual ~Descriptor();
|
||||||
|
|
||||||
|
virtual status_t Close() = 0;
|
||||||
|
virtual status_t Dup(Descriptor *&clone) = 0;
|
||||||
|
virtual status_t GetStat(bool traverseLink, struct stat *st) = 0;
|
||||||
|
|
||||||
|
virtual status_t GetNodeRef(NodeRef &ref);
|
||||||
|
};
|
||||||
|
|
||||||
|
// FileDescriptor
|
||||||
|
struct FileDescriptor : Descriptor {
|
||||||
|
FileDescriptor(int fd);
|
||||||
|
virtual ~FileDescriptor();
|
||||||
|
|
||||||
|
virtual status_t Close();
|
||||||
|
virtual status_t Dup(Descriptor *&clone);
|
||||||
|
virtual status_t GetStat(bool traverseLink, struct stat *st);
|
||||||
|
};
|
||||||
|
|
||||||
|
// DirectoryDescriptor
|
||||||
|
struct DirectoryDescriptor : Descriptor {
|
||||||
|
DIR *dir;
|
||||||
|
NodeRef ref;
|
||||||
|
|
||||||
|
DirectoryDescriptor(DIR *dir, const NodeRef &ref);
|
||||||
|
virtual ~DirectoryDescriptor();
|
||||||
|
|
||||||
|
virtual status_t Close();
|
||||||
|
virtual status_t Dup(Descriptor *&clone);
|
||||||
|
virtual status_t GetStat(bool traverseLink, struct stat *st);
|
||||||
|
|
||||||
|
virtual status_t GetNodeRef(NodeRef &ref);
|
||||||
|
};
|
||||||
|
|
||||||
|
// SymlinkDescriptor
|
||||||
|
struct SymlinkDescriptor : Descriptor {
|
||||||
|
string path;
|
||||||
|
|
||||||
|
SymlinkDescriptor(const char *path);
|
||||||
|
|
||||||
|
virtual status_t Close();
|
||||||
|
virtual status_t Dup(Descriptor *&clone);
|
||||||
|
virtual status_t GetStat(bool traverseLink, struct stat *st);
|
||||||
|
};
|
||||||
|
|
||||||
|
// AttrDirDescriptor
|
||||||
|
struct AttrDirDescriptor : DirectoryDescriptor {
|
||||||
|
|
||||||
|
AttrDirDescriptor(DIR *dir, const NodeRef &ref);
|
||||||
|
virtual ~AttrDirDescriptor();
|
||||||
|
|
||||||
|
virtual status_t Close();
|
||||||
|
virtual status_t Dup(Descriptor *&clone);
|
||||||
|
virtual status_t GetStat(bool traverseLink, struct stat *st);
|
||||||
|
|
||||||
|
virtual status_t GetNodeRef(NodeRef &ref);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Descriptor* get_descriptor(int fd);
|
||||||
|
int add_descriptor(Descriptor *descriptor);
|
||||||
|
status_t delete_descriptor(int fd);
|
||||||
|
|
||||||
|
} // namespace BPrivate
|
||||||
|
|
||||||
|
#endif // FS_DESCRIPTORS_H
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef FS_IMPL_H
|
||||||
|
#define FS_IMPL_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
|
||||||
|
// defined in fs.cpp
|
||||||
|
|
||||||
|
status_t get_path(int fd, const char *name, std::string &path);
|
||||||
|
|
||||||
|
} // namespace BPrivate
|
||||||
|
|
||||||
|
#endif // FS_IMPL_H
|
||||||
Reference in New Issue
Block a user