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
|
||||
fs.cpp
|
||||
fs_attr.cpp
|
||||
fs_descriptors.cpp
|
||||
misc.cpp
|
||||
sem.cpp
|
||||
thread.cpp
|
||||
|
||||
+7
-399
@@ -1,6 +1,8 @@
|
||||
|
||||
#include <BeOSBuildCompatibility.h>
|
||||
|
||||
#include "fs_impl.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -17,296 +19,21 @@
|
||||
#include <NodeMonitor.h> // for B_STAT_* flags
|
||||
#include <syscalls.h>
|
||||
|
||||
#include "fs_attr_impl.h"
|
||||
#include "fs_descriptors.h"
|
||||
#include "NodeRef.h"
|
||||
|
||||
using namespace std;
|
||||
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
|
||||
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
|
||||
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 -
|
||||
|
||||
// read_pos
|
||||
|
||||
+142
-116
@@ -9,11 +9,6 @@
|
||||
# include <syscalls.h>
|
||||
#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 <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -26,13 +21,9 @@
|
||||
|
||||
#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 BPrivate;
|
||||
@@ -133,87 +124,6 @@ get_attribute_dir_path(NodeRef ref)
|
||||
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
|
||||
static status_t
|
||||
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;
|
||||
}
|
||||
|
||||
// already exists: Check whether the file is marked. If not, this
|
||||
// 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);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// doesn't exist yet: create it
|
||||
if (mkdir(attrDirPath.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) < 0)
|
||||
return errno;
|
||||
|
||||
// mark the file
|
||||
return set_attribute_dir_mark(path, fd);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// open_attr_dir
|
||||
DIR *
|
||||
BPrivate::open_attr_dir(NodeRef ref, const char *path, int fd)
|
||||
static DIR *
|
||||
open_attr_dir(NodeRef ref, const char *path, int fd)
|
||||
{
|
||||
// make sure the directory exists
|
||||
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
|
||||
status_t
|
||||
BPrivate::get_attribute_path(NodeRef ref, const char *path, int fd,
|
||||
static status_t
|
||||
get_attribute_path(NodeRef ref, const char *path, int fd,
|
||||
const char *attribute, string &attrPath, string &typePath)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
#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
|
||||
DIR *
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// #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