Open/close attribute support for xattrs backend
For the xattr/BSD (untyped) attribute backend implement fs_fopen_attr() and fs_close_attr(). A new AttributeDescriptor is created. It is currently used in write_pos() only.
This commit is contained in:
+62
-49
@@ -130,17 +130,17 @@ normalize_dir_path(string path, NodeRef ref, string &normalizedPath)
|
||||
status_t error = find_dir_entry(path.c_str(), ref, name, true) ;
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
|
||||
// recurse to get the parent dir path, if found
|
||||
error = normalize_dir_path(path, parentRef, normalizedPath);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
// construct the normalizedPath
|
||||
// construct the normalizedPath
|
||||
if (normalizedPath.length() > 1) // don't append "/", if parent is root
|
||||
normalizedPath += '/';
|
||||
normalizedPath += name;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ normalize_dir_path(const char *path, string &normalizedPath)
|
||||
struct stat st;
|
||||
if (stat(path, &st) < 0)
|
||||
return errno;
|
||||
|
||||
|
||||
return normalize_dir_path(path, NodeRef(st), normalizedPath);
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ normalize_entry_path(const char *path, string &normalizedPath)
|
||||
{
|
||||
const char *dirPath = NULL;
|
||||
const char *leafName = NULL;
|
||||
|
||||
|
||||
string dirPathString;
|
||||
if (const char *lastSlash = strrchr(path, '/')) {
|
||||
// found a slash: decompose into dir path and leaf name
|
||||
@@ -184,7 +184,7 @@ normalize_entry_path(const char *path, string &normalizedPath)
|
||||
// catch special case: no leaf, or leaf is a directory
|
||||
if (!leafName || strcmp(leafName, ".") == 0 || strcmp(leafName, "..") == 0)
|
||||
return normalize_dir_path(path, normalizedPath);
|
||||
|
||||
|
||||
// normalize the dir path
|
||||
status_t error = normalize_dir_path(dirPath, normalizedPath);
|
||||
if (error != B_OK)
|
||||
@@ -222,7 +222,7 @@ get_path(const NodeRef *ref, const char *name, string &path)
|
||||
DirPathMap::iterator it = sDirPathMap.find(*ref);
|
||||
if (it == sDirPathMap.end())
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
|
||||
path = it->second;
|
||||
|
||||
// stat the path to check, if it is still valid
|
||||
@@ -250,7 +250,7 @@ get_path(const NodeRef *ref, const char *name, string &path)
|
||||
path += '/';
|
||||
path += name;
|
||||
}
|
||||
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -272,7 +272,7 @@ BPrivate::get_path(int fd, const char *name, string &path)
|
||||
return error;
|
||||
|
||||
return ::get_path(&ref, name, path);
|
||||
|
||||
|
||||
} else // no descriptor or absolute path
|
||||
return ::get_path((NodeRef*)NULL, name, path);
|
||||
}
|
||||
@@ -284,7 +284,7 @@ get_path(dev_t device, ino_t directory, const char *name, string &path)
|
||||
NodeRef ref;
|
||||
ref.device = device;
|
||||
ref.node = directory;
|
||||
|
||||
|
||||
return get_path(&ref, name, path);
|
||||
}
|
||||
|
||||
@@ -315,7 +315,7 @@ _kern_entry_ref_to_path(dev_t device, ino_t node, const char *leaf,
|
||||
// copy it back to the user buffer
|
||||
if (strlcpy(userPath, path.c_str(), pathLength) >= pathLength)
|
||||
return B_BUFFER_OVERFLOW;
|
||||
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -334,8 +334,8 @@ _kern_create_dir(int fd, const char *path, int perms)
|
||||
|
||||
// mkdir
|
||||
if (mkdir(realPath.c_str(), perms) < 0)
|
||||
return errno;
|
||||
|
||||
return errno;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -352,8 +352,8 @@ _kern_create_dir_entry_ref(dev_t device, ino_t node, const char *name,
|
||||
|
||||
// mkdir
|
||||
if (mkdir(realPath.c_str(), perms) < 0)
|
||||
return errno;
|
||||
|
||||
return errno;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -382,7 +382,7 @@ open_dir(const char *path)
|
||||
NodeRef ref(st);
|
||||
add_dir_path(path, ref);
|
||||
|
||||
// create descriptor
|
||||
// create descriptor
|
||||
DirectoryDescriptor *descriptor = new DirectoryDescriptor(dir, ref);
|
||||
return add_descriptor(descriptor);
|
||||
}
|
||||
@@ -443,7 +443,7 @@ _kern_open_parent_dir(int fd, char *name, size_t nameLength)
|
||||
return B_BUFFER_OVERFLOW;
|
||||
|
||||
// open the parent directory
|
||||
|
||||
|
||||
return open_dir(realPath.c_str());
|
||||
}
|
||||
|
||||
@@ -455,7 +455,7 @@ _kern_read_dir(int fd, struct dirent *buffer, size_t bufferSize,
|
||||
if (maxCount <= 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// get the descriptor
|
||||
// get the descriptor
|
||||
DirectoryDescriptor *descriptor
|
||||
= dynamic_cast<DirectoryDescriptor*>(get_descriptor(fd));
|
||||
if (!descriptor)
|
||||
@@ -484,7 +484,7 @@ _kern_read_dir(int fd, struct dirent *buffer, size_t bufferSize,
|
||||
status_t
|
||||
_kern_rewind_dir(int fd)
|
||||
{
|
||||
// get the descriptor
|
||||
// get the descriptor
|
||||
DirectoryDescriptor *descriptor
|
||||
= dynamic_cast<DirectoryDescriptor*>(get_descriptor(fd));
|
||||
if (!descriptor)
|
||||
@@ -523,7 +523,7 @@ open_file(const char *path, int openMode, int perms)
|
||||
status_t error = normalize_entry_path(path, normalizedPath);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
|
||||
descriptor = new SymlinkDescriptor(normalizedPath.c_str());
|
||||
} else {
|
||||
// open the file
|
||||
@@ -534,11 +534,11 @@ open_file(const char *path, int openMode, int perms)
|
||||
|
||||
descriptor = new FileDescriptor(newFD);
|
||||
}
|
||||
|
||||
|
||||
// cache path, if this is a directory
|
||||
if (exists && S_ISDIR(st.st_mode))
|
||||
add_dir_path(path, NodeRef(st));
|
||||
|
||||
|
||||
return add_descriptor(descriptor);
|
||||
}
|
||||
|
||||
@@ -603,7 +603,7 @@ _kern_read(int fd, off_t pos, void *buffer, size_t bufferSize)
|
||||
if (result < 0)
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
||||
// read
|
||||
ssize_t bytesRead = haiku_host_platform_read(descriptor->fd, buffer,
|
||||
bufferSize);
|
||||
@@ -629,7 +629,7 @@ _kern_write(int fd, off_t pos, const void *buffer, size_t bufferSize)
|
||||
if (result < 0)
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
||||
// read
|
||||
ssize_t bytesWritten = haiku_host_platform_write(descriptor->fd, buffer,
|
||||
bufferSize);
|
||||
@@ -706,10 +706,10 @@ _kern_read_stat(int fd, const char *path, bool traverseLink,
|
||||
Descriptor *descriptor = get_descriptor(fd);
|
||||
if (!descriptor)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
|
||||
return descriptor->GetStat(traverseLink, st);
|
||||
}
|
||||
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -734,7 +734,7 @@ _kern_write_stat(int fd, const char *path, bool traverseLink,
|
||||
return errno;
|
||||
|
||||
isSymlink = S_ISLNK(tmpStat.st_mode);
|
||||
|
||||
|
||||
} else {
|
||||
Descriptor *descriptor = get_descriptor(fd);
|
||||
if (!descriptor)
|
||||
@@ -743,17 +743,17 @@ _kern_write_stat(int fd, const char *path, bool traverseLink,
|
||||
if (FileDescriptor *fileFD
|
||||
= dynamic_cast<FileDescriptor*>(descriptor)) {
|
||||
realFD = fileFD->fd;
|
||||
|
||||
|
||||
} else if (dynamic_cast<DirectoryDescriptor*>(descriptor)) {
|
||||
error = get_path(fd, NULL, realPath);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
|
||||
} else if (SymlinkDescriptor *linkFD
|
||||
= dynamic_cast<SymlinkDescriptor*>(descriptor)) {
|
||||
realPath = linkFD->path;
|
||||
isSymlink = true;
|
||||
|
||||
|
||||
} else
|
||||
return B_FILE_ERROR;
|
||||
}
|
||||
@@ -762,23 +762,23 @@ _kern_write_stat(int fd, const char *path, bool traverseLink,
|
||||
// available functions traverse symlinks.
|
||||
if (isSymlink && !traverseLink)
|
||||
return B_ERROR;
|
||||
|
||||
|
||||
if (realFD >= 0) {
|
||||
if (statMask & B_STAT_MODE) {
|
||||
if (fchmod(realFD, st->st_mode) < 0)
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
||||
if (statMask & B_STAT_UID) {
|
||||
if (fchown(realFD, st->st_uid, (gid_t)-1) < 0)
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
||||
if (statMask & B_STAT_GID) {
|
||||
if (fchown(realFD, (uid_t)-1, st->st_gid) < 0)
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
||||
if (statMask & B_STAT_SIZE) {
|
||||
if (ftruncate(realFD, st->st_size) < 0)
|
||||
return errno;
|
||||
@@ -790,25 +790,25 @@ _kern_write_stat(int fd, const char *path, bool traverseLink,
|
||||
| B_STAT_CREATION_TIME | B_STAT_CHANGE_TIME)) {
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
} else {
|
||||
if (statMask & B_STAT_MODE) {
|
||||
if (chmod(realPath.c_str(), st->st_mode) < 0)
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
||||
if (statMask & B_STAT_UID) {
|
||||
if (chown(realPath.c_str(), st->st_uid, (gid_t)-1) < 0)
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
||||
if (statMask & B_STAT_GID) {
|
||||
if (chown(realPath.c_str(), (uid_t)-1, st->st_gid) < 0)
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
||||
if (statMask & B_STAT_SIZE) {
|
||||
if (truncate(realPath.c_str(), st->st_size) < 0)
|
||||
return errno;
|
||||
@@ -822,18 +822,18 @@ _kern_write_stat(int fd, const char *path, bool traverseLink,
|
||||
if (stat(realPath.c_str(), &oldStat) < 0)
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
||||
utimbuf buffer;
|
||||
buffer.actime = (statMask & B_STAT_ACCESS_TIME) ? st->st_atime : oldStat.st_atime;
|
||||
buffer.modtime = (statMask & B_STAT_MODIFICATION_TIME) ? st->st_mtime : oldStat.st_mtime;
|
||||
if (utime(realPath.c_str(), &buffer) < 0)
|
||||
return errno;
|
||||
}
|
||||
|
||||
// not supported
|
||||
|
||||
// not supported
|
||||
if (statMask & (B_STAT_CREATION_TIME | B_STAT_CHANGE_TIME))
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -878,7 +878,7 @@ _kern_read_link(int fd, const char *path, char *buffer, size_t *_bufferSize)
|
||||
if (*_bufferSize > 0) {
|
||||
if ((size_t)bytesRead == *_bufferSize)
|
||||
bytesRead--;
|
||||
|
||||
|
||||
buffer[bytesRead] = '\0';
|
||||
}
|
||||
|
||||
@@ -918,7 +918,7 @@ _kern_rename(int oldDir, const char *oldPath, int newDir, const char *newPath)
|
||||
error = get_path(newDir, newPath, realNewPath);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
|
||||
// rename
|
||||
if (rename(realOldPath.c_str(), realNewPath.c_str()) < 0)
|
||||
return errno;
|
||||
@@ -954,7 +954,7 @@ read_pos(int fd, off_t pos, void *buffer, size_t bufferSize)
|
||||
off_t result = lseek(fd, pos, SEEK_SET);
|
||||
if (result < 0)
|
||||
return errno;
|
||||
|
||||
|
||||
// read
|
||||
ssize_t bytesRead = haiku_host_platform_read(fd, buffer, bufferSize);
|
||||
if (bytesRead < 0) {
|
||||
@@ -969,12 +969,25 @@ read_pos(int fd, off_t pos, void *buffer, size_t bufferSize)
|
||||
ssize_t
|
||||
write_pos(int fd, off_t pos, const void *buffer, size_t bufferSize)
|
||||
{
|
||||
// If this is an attribute descriptor, let it do the job.
|
||||
AttributeDescriptor* descriptor
|
||||
= dynamic_cast<AttributeDescriptor*>(get_descriptor(fd));
|
||||
if (descriptor != NULL) {
|
||||
status_t error = descriptor->Write(pos, buffer, bufferSize);
|
||||
if (error != B_OK) {
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// seek
|
||||
off_t result = lseek(fd, pos, SEEK_SET);
|
||||
if (result < 0)
|
||||
return errno;
|
||||
|
||||
// read
|
||||
// write
|
||||
ssize_t bytesWritten = haiku_host_platform_write(fd, buffer, bufferSize);
|
||||
if (bytesWritten < 0) {
|
||||
errno = bytesWritten;
|
||||
@@ -992,7 +1005,7 @@ readv_pos(int fd, off_t pos, const struct iovec *vec, size_t count)
|
||||
off_t result = lseek(fd, pos, SEEK_SET);
|
||||
if (result < 0)
|
||||
return errno;
|
||||
|
||||
|
||||
// read
|
||||
ssize_t bytesRead = haiku_host_platform_readv(fd, vec, count);
|
||||
if (bytesRead < 0) {
|
||||
@@ -1011,7 +1024,7 @@ writev_pos(int fd, off_t pos, const struct iovec *vec, size_t count)
|
||||
off_t result = lseek(fd, pos, SEEK_SET);
|
||||
if (result < 0)
|
||||
return errno;
|
||||
|
||||
|
||||
// read
|
||||
ssize_t bytesWritten = haiku_host_platform_writev(fd, vec, count);
|
||||
if (bytesWritten < 0) {
|
||||
|
||||
@@ -33,7 +33,7 @@ init_attribute_dir_base_dir()
|
||||
|
||||
if (initialized)
|
||||
return initError;
|
||||
|
||||
|
||||
// stat the dir
|
||||
struct stat st;
|
||||
initError = B_OK;
|
||||
@@ -44,7 +44,7 @@ init_attribute_dir_base_dir()
|
||||
"directory base directory exists, but is no directory!\n");
|
||||
initError = B_FILE_ERROR;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
// doesn't exist yet: create it
|
||||
if (mkdir(sAttributeDirBasePath, S_IRWXU | S_IRWXG | S_IRWXO) < 0)
|
||||
@@ -68,7 +68,7 @@ escape_attr_name(const char *name)
|
||||
escapedName += "__";
|
||||
else
|
||||
escapedName += *name;
|
||||
|
||||
|
||||
name++;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ deescape_attr_name(const char *name)
|
||||
return "___";
|
||||
}
|
||||
name++;
|
||||
|
||||
|
||||
string deescapedName;
|
||||
while (*name != '\0') {
|
||||
if (*name == '_') {
|
||||
@@ -100,11 +100,11 @@ deescape_attr_name(const char *name)
|
||||
}
|
||||
} else
|
||||
deescapedName += *name;
|
||||
|
||||
|
||||
name++;
|
||||
}
|
||||
|
||||
return deescapedName;
|
||||
return deescapedName;
|
||||
}
|
||||
|
||||
// get_attribute_dir_path
|
||||
@@ -179,7 +179,7 @@ get_attribute_path(NodeRef ref, const char *path, int fd,
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// construct the attribute path
|
||||
attrPath = get_attribute_dir_path(ref) + '/';
|
||||
string attrName(escape_attr_name(attribute));
|
||||
@@ -206,7 +206,7 @@ get_attribute_path_virtual_fd(int fd, const char *attribute, string &attrPath,
|
||||
// (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);
|
||||
@@ -269,7 +269,7 @@ fs_fopen_attr_dir(int fd)
|
||||
// (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 open_attr_dir(NodeRef(st), (pathValid ? path.c_str() : NULL),
|
||||
(pathValid ? -1 : fd));
|
||||
@@ -292,8 +292,8 @@ fs_read_attr_dir(DIR *dir)
|
||||
entry = readdir(dir);
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
// ignore administrative entries; the
|
||||
|
||||
// ignore administrative entries; the
|
||||
if (entry->d_name[0] == '_') {
|
||||
string attrName = deescape_attr_name(entry->d_name);
|
||||
strcpy(entry->d_name, attrName.c_str());
|
||||
@@ -309,15 +309,15 @@ fs_rewind_attr_dir(DIR *dir)
|
||||
rewinddir(dir);
|
||||
}
|
||||
|
||||
// fs_open_attr
|
||||
// fs_fopen_attr
|
||||
int
|
||||
fs_open_attr(int fd, const char *attribute, uint32 type, int openMode)
|
||||
fs_fopen_attr(int fd, const char *attribute, uint32 type, int openMode)
|
||||
{
|
||||
if (!attribute) {
|
||||
errno = B_BAD_VALUE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// get the attribute path
|
||||
string attrPath;
|
||||
string typePath;
|
||||
@@ -344,7 +344,7 @@ fs_open_attr(int fd, const char *attribute, uint32 type, int openMode)
|
||||
// write the type into the file
|
||||
if (write(typeFD, &type, sizeof(type)) < 0)
|
||||
error = errno;
|
||||
|
||||
|
||||
close(typeFD);
|
||||
|
||||
} else
|
||||
@@ -355,10 +355,10 @@ fs_open_attr(int fd, const char *attribute, uint32 type, int openMode)
|
||||
if (typeFD > 0) {
|
||||
unlink(typePath.c_str());
|
||||
}
|
||||
|
||||
|
||||
close(attrFD);
|
||||
unlink(attrPath.c_str());
|
||||
|
||||
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
@@ -395,7 +395,7 @@ fs_read_attr(int fd, const char *attribute, uint32 type, off_t pos,
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
@@ -421,7 +421,7 @@ fs_write_attr(int fd, const char *attribute, uint32 type, off_t pos,
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ fs_remove_attr(int fd, const char *attribute)
|
||||
errno = B_BAD_VALUE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// get the attribute path
|
||||
string attrPath;
|
||||
string typePath;
|
||||
@@ -446,9 +446,9 @@ fs_remove_attr(int fd, const char *attribute)
|
||||
// remove the attribute
|
||||
if (unlink(attrPath.c_str()) < 0)
|
||||
return -1;
|
||||
|
||||
|
||||
unlink(typePath.c_str());
|
||||
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -474,7 +474,7 @@ fs_stat_attr(int fd, const char *attribute, struct attr_info *attrInfo)
|
||||
struct stat st;
|
||||
if (lstat(attrPath.c_str(), &st) < 0)
|
||||
return -1;
|
||||
|
||||
|
||||
attrInfo->size = st.st_size;
|
||||
|
||||
// now open the attribute type file and read the attribute's type
|
||||
@@ -496,7 +496,7 @@ fs_stat_attr(int fd, const char *attribute, struct attr_info *attrInfo)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -524,14 +524,14 @@ _kern_open_attr_dir(int fd, const char *path)
|
||||
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
|
||||
// create descriptor
|
||||
AttrDirDescriptor *descriptor = new AttrDirDescriptor(dir, ref);
|
||||
return add_descriptor(descriptor);
|
||||
}
|
||||
@@ -571,7 +571,7 @@ _kern_rename_attr(int fromFile, const char *fromName, int toFile,
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -452,22 +452,50 @@ fs_rewind_attr_dir(DIR *dir)
|
||||
attrDir->RewindDir();
|
||||
}
|
||||
|
||||
// fs_open_attr
|
||||
// fs_fopen_attr
|
||||
int
|
||||
fs_open_attr(int fd, const char *attribute, uint32 type, int openMode)
|
||||
fs_fopen_attr(int fd, const char *attribute, uint32 type, int openMode)
|
||||
{
|
||||
// not supported ATM
|
||||
errno = B_BAD_VALUE;
|
||||
return -1;
|
||||
if (fd < 0) {
|
||||
errno = B_BAD_VALUE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
AttributeDescriptor* descriptor = new(std::nothrow) AttributeDescriptor(fd,
|
||||
attribute, type, openMode);
|
||||
if (descriptor == NULL) {
|
||||
errno = B_NO_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
status_t error = descriptor->Init();
|
||||
if (error != B_OK) {
|
||||
delete descriptor;
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int attributeFD = add_descriptor(descriptor);
|
||||
if (attributeFD < 0) {
|
||||
delete descriptor;
|
||||
errno = B_NO_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return attributeFD;
|
||||
}
|
||||
|
||||
// fs_close_attr
|
||||
int
|
||||
fs_close_attr(int fd)
|
||||
{
|
||||
// not supported ATM
|
||||
errno = B_BAD_VALUE;
|
||||
return -1;
|
||||
status_t error = delete_descriptor(fd);
|
||||
if (error != 0) {
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// fs_read_attr
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <fs_attr.h>
|
||||
@@ -250,6 +252,151 @@ SymlinkDescriptor::GetPath(string& path) const
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - AttributeDescriptor
|
||||
|
||||
|
||||
AttributeDescriptor::AttributeDescriptor(int fileFD, const char* attribute,
|
||||
uint32 type, int openMode)
|
||||
:
|
||||
fFileFD(dup(fileFD)),
|
||||
fType(type),
|
||||
fOpenMode(openMode),
|
||||
fData(NULL),
|
||||
fDataSize(0)
|
||||
|
||||
{
|
||||
strlcpy(fAttribute, attribute, sizeof(fAttribute));
|
||||
}
|
||||
|
||||
|
||||
AttributeDescriptor::~AttributeDescriptor()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AttributeDescriptor::Init()
|
||||
{
|
||||
if (fFileFD < 0)
|
||||
return B_IO_ERROR;
|
||||
|
||||
// stat the attribute
|
||||
attr_info info;
|
||||
if (fs_stat_attr(fFileFD, fAttribute, &info) < 0) {
|
||||
if (errno == B_ENTRY_NOT_FOUND) {
|
||||
if ((fOpenMode & O_CREAT) == 0)
|
||||
return errno;
|
||||
|
||||
// create the attribute
|
||||
if (fs_write_attr(fFileFD, fAttribute, fType, 0, NULL, 0) < 0)
|
||||
return errno;
|
||||
return B_OK;
|
||||
}
|
||||
return errno;
|
||||
}
|
||||
|
||||
if ((fOpenMode & O_TRUNC) == 0) {
|
||||
// truncate the attribute
|
||||
if (fs_write_attr(fFileFD, fAttribute, fType, 0, NULL, 0) < 0)
|
||||
return errno;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// we have to read in the attribute data
|
||||
if (info.size == 0)
|
||||
return B_OK;
|
||||
|
||||
fData = (uint8*)malloc(info.size);
|
||||
if (fData == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fDataSize = info.size;
|
||||
|
||||
ssize_t bytesRead = fs_read_attr(fFileFD, fAttribute, fType, 0, fData,
|
||||
fDataSize);
|
||||
if (bytesRead < 0)
|
||||
return errno;
|
||||
if ((size_t)bytesRead != fDataSize)
|
||||
return B_IO_ERROR;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AttributeDescriptor::Write(off_t offset, const void* buffer, size_t bufferSize)
|
||||
{
|
||||
if (offset < 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if ((fOpenMode & O_ACCMODE) != O_WRONLY
|
||||
&& (fOpenMode & O_ACCMODE) != O_RDWR) {
|
||||
return B_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
// we may need to resize the buffer
|
||||
size_t minSize = (size_t)offset + bufferSize;
|
||||
if (minSize > fDataSize) {
|
||||
uint8* data = (uint8*)realloc(fData, minSize);
|
||||
if (data == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if ((size_t)offset > fDataSize)
|
||||
memset(data + offset, 0, offset - fDataSize);
|
||||
|
||||
fData = data;
|
||||
fDataSize = minSize;
|
||||
}
|
||||
|
||||
// copy the data and write all of it
|
||||
if (bufferSize == 0)
|
||||
return B_OK;
|
||||
|
||||
memcpy((uint8*)fData + offset, buffer, bufferSize);
|
||||
|
||||
ssize_t bytesWritten = fs_write_attr(fFileFD, fAttribute, fType, 0,
|
||||
fData, fDataSize);
|
||||
if (bytesWritten < 0)
|
||||
return errno;
|
||||
if ((size_t)bytesWritten != fDataSize)
|
||||
return B_IO_ERROR;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AttributeDescriptor::Close()
|
||||
{
|
||||
if (fFileFD < 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
close(fFileFD);
|
||||
fFileFD = -1;
|
||||
|
||||
free(fData);
|
||||
fData = NULL;
|
||||
fDataSize = 0;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AttributeDescriptor::Dup(Descriptor*& clone)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AttributeDescriptor::GetStat(bool traverseLink, struct stat* st)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - AttrDirDescriptor
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <StorageDefs.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include "NodeRef.h"
|
||||
@@ -35,7 +36,7 @@ struct Descriptor {
|
||||
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);
|
||||
@@ -50,7 +51,7 @@ struct DirectoryDescriptor : Descriptor {
|
||||
|
||||
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);
|
||||
@@ -71,12 +72,41 @@ struct SymlinkDescriptor : Descriptor {
|
||||
virtual status_t GetPath(string& path) const;
|
||||
};
|
||||
|
||||
// AttributeDescriptor
|
||||
struct AttributeDescriptor : Descriptor {
|
||||
AttributeDescriptor(int fileFD,
|
||||
const char* attribute, uint32 type,
|
||||
int openMode);
|
||||
virtual ~AttributeDescriptor();
|
||||
|
||||
status_t Init();
|
||||
status_t Write(off_t offset, const void* buffer,
|
||||
size_t bufferSize);
|
||||
|
||||
int FileFD() const { return fFileFD; }
|
||||
const char* Attribute() const { return fAttribute; }
|
||||
uint32 Type() const { return fType; }
|
||||
int OpenMode() const { return fOpenMode; }
|
||||
|
||||
virtual status_t Close();
|
||||
virtual status_t Dup(Descriptor*& clone);
|
||||
virtual status_t GetStat(bool traverseLink, struct stat* st);
|
||||
|
||||
private:
|
||||
int fFileFD;
|
||||
char fAttribute[B_ATTR_NAME_LENGTH];
|
||||
uint32 fType;
|
||||
int fOpenMode;
|
||||
uint8* fData;
|
||||
size_t fDataSize;
|
||||
};
|
||||
|
||||
// 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);
|
||||
|
||||
Reference in New Issue
Block a user