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:
Ingo Weinhold
2011-07-17 16:54:09 +02:00
parent 62fef8b3fc
commit e781b1b5a8
5 changed files with 305 additions and 87 deletions
+62 -49
View File
@@ -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) ; status_t error = find_dir_entry(path.c_str(), ref, name, true) ;
if (error != B_OK) if (error != B_OK)
return error; return error;
// recurse to get the parent dir path, if found // recurse to get the parent dir path, if found
error = normalize_dir_path(path, parentRef, normalizedPath); error = normalize_dir_path(path, parentRef, normalizedPath);
if (error != 0) if (error != 0)
return error; return error;
// construct the normalizedPath // construct the normalizedPath
if (normalizedPath.length() > 1) // don't append "/", if parent is root if (normalizedPath.length() > 1) // don't append "/", if parent is root
normalizedPath += '/'; normalizedPath += '/';
normalizedPath += name; normalizedPath += name;
return 0; return 0;
} }
@@ -152,7 +152,7 @@ normalize_dir_path(const char *path, string &normalizedPath)
struct stat st; struct stat st;
if (stat(path, &st) < 0) if (stat(path, &st) < 0)
return errno; return errno;
return normalize_dir_path(path, NodeRef(st), normalizedPath); 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 *dirPath = NULL;
const char *leafName = NULL; const char *leafName = NULL;
string dirPathString; string dirPathString;
if (const char *lastSlash = strrchr(path, '/')) { if (const char *lastSlash = strrchr(path, '/')) {
// found a slash: decompose into dir path and leaf name // 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 // catch special case: no leaf, or leaf is a directory
if (!leafName || strcmp(leafName, ".") == 0 || strcmp(leafName, "..") == 0) if (!leafName || strcmp(leafName, ".") == 0 || strcmp(leafName, "..") == 0)
return normalize_dir_path(path, normalizedPath); return normalize_dir_path(path, normalizedPath);
// normalize the dir path // normalize the dir path
status_t error = normalize_dir_path(dirPath, normalizedPath); status_t error = normalize_dir_path(dirPath, normalizedPath);
if (error != B_OK) if (error != B_OK)
@@ -222,7 +222,7 @@ get_path(const NodeRef *ref, const char *name, string &path)
DirPathMap::iterator it = sDirPathMap.find(*ref); DirPathMap::iterator it = sDirPathMap.find(*ref);
if (it == sDirPathMap.end()) if (it == sDirPathMap.end())
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
path = it->second; path = it->second;
// stat the path to check, if it is still valid // 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 += '/';
path += name; path += name;
} }
return B_OK; return B_OK;
} }
@@ -272,7 +272,7 @@ BPrivate::get_path(int fd, const char *name, string &path)
return error; return error;
return ::get_path(&ref, name, path); return ::get_path(&ref, name, path);
} else // no descriptor or absolute path } else // no descriptor or absolute path
return ::get_path((NodeRef*)NULL, name, 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; NodeRef ref;
ref.device = device; ref.device = device;
ref.node = directory; ref.node = directory;
return get_path(&ref, name, path); 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 // copy it back to the user buffer
if (strlcpy(userPath, path.c_str(), pathLength) >= pathLength) if (strlcpy(userPath, path.c_str(), pathLength) >= pathLength)
return B_BUFFER_OVERFLOW; return B_BUFFER_OVERFLOW;
return B_OK; return B_OK;
} }
@@ -334,8 +334,8 @@ _kern_create_dir(int fd, const char *path, int perms)
// mkdir // mkdir
if (mkdir(realPath.c_str(), perms) < 0) if (mkdir(realPath.c_str(), perms) < 0)
return errno; return errno;
return B_OK; return B_OK;
} }
@@ -352,8 +352,8 @@ _kern_create_dir_entry_ref(dev_t device, ino_t node, const char *name,
// mkdir // mkdir
if (mkdir(realPath.c_str(), perms) < 0) if (mkdir(realPath.c_str(), perms) < 0)
return errno; return errno;
return B_OK; return B_OK;
} }
@@ -382,7 +382,7 @@ open_dir(const char *path)
NodeRef ref(st); NodeRef ref(st);
add_dir_path(path, ref); add_dir_path(path, ref);
// create descriptor // create descriptor
DirectoryDescriptor *descriptor = new DirectoryDescriptor(dir, ref); DirectoryDescriptor *descriptor = new DirectoryDescriptor(dir, ref);
return add_descriptor(descriptor); return add_descriptor(descriptor);
} }
@@ -443,7 +443,7 @@ _kern_open_parent_dir(int fd, char *name, size_t nameLength)
return B_BUFFER_OVERFLOW; return B_BUFFER_OVERFLOW;
// open the parent directory // open the parent directory
return open_dir(realPath.c_str()); return open_dir(realPath.c_str());
} }
@@ -455,7 +455,7 @@ _kern_read_dir(int fd, struct dirent *buffer, size_t bufferSize,
if (maxCount <= 0) if (maxCount <= 0)
return B_BAD_VALUE; return B_BAD_VALUE;
// get the descriptor // get the descriptor
DirectoryDescriptor *descriptor DirectoryDescriptor *descriptor
= dynamic_cast<DirectoryDescriptor*>(get_descriptor(fd)); = dynamic_cast<DirectoryDescriptor*>(get_descriptor(fd));
if (!descriptor) if (!descriptor)
@@ -484,7 +484,7 @@ _kern_read_dir(int fd, struct dirent *buffer, size_t bufferSize,
status_t status_t
_kern_rewind_dir(int fd) _kern_rewind_dir(int fd)
{ {
// get the descriptor // get the descriptor
DirectoryDescriptor *descriptor DirectoryDescriptor *descriptor
= dynamic_cast<DirectoryDescriptor*>(get_descriptor(fd)); = dynamic_cast<DirectoryDescriptor*>(get_descriptor(fd));
if (!descriptor) if (!descriptor)
@@ -523,7 +523,7 @@ open_file(const char *path, int openMode, int perms)
status_t error = normalize_entry_path(path, normalizedPath); status_t error = normalize_entry_path(path, normalizedPath);
if (error != B_OK) if (error != B_OK)
return error; return error;
descriptor = new SymlinkDescriptor(normalizedPath.c_str()); descriptor = new SymlinkDescriptor(normalizedPath.c_str());
} else { } else {
// open the file // open the file
@@ -534,11 +534,11 @@ open_file(const char *path, int openMode, int perms)
descriptor = new FileDescriptor(newFD); descriptor = new FileDescriptor(newFD);
} }
// cache path, if this is a directory // cache path, if this is a directory
if (exists && S_ISDIR(st.st_mode)) if (exists && S_ISDIR(st.st_mode))
add_dir_path(path, NodeRef(st)); add_dir_path(path, NodeRef(st));
return add_descriptor(descriptor); return add_descriptor(descriptor);
} }
@@ -603,7 +603,7 @@ _kern_read(int fd, off_t pos, void *buffer, size_t bufferSize)
if (result < 0) if (result < 0)
return errno; return errno;
} }
// read // read
ssize_t bytesRead = haiku_host_platform_read(descriptor->fd, buffer, ssize_t bytesRead = haiku_host_platform_read(descriptor->fd, buffer,
bufferSize); bufferSize);
@@ -629,7 +629,7 @@ _kern_write(int fd, off_t pos, const void *buffer, size_t bufferSize)
if (result < 0) if (result < 0)
return errno; return errno;
} }
// read // read
ssize_t bytesWritten = haiku_host_platform_write(descriptor->fd, buffer, ssize_t bytesWritten = haiku_host_platform_write(descriptor->fd, buffer,
bufferSize); bufferSize);
@@ -706,10 +706,10 @@ _kern_read_stat(int fd, const char *path, bool traverseLink,
Descriptor *descriptor = get_descriptor(fd); Descriptor *descriptor = get_descriptor(fd);
if (!descriptor) if (!descriptor)
return B_FILE_ERROR; return B_FILE_ERROR;
return descriptor->GetStat(traverseLink, st); return descriptor->GetStat(traverseLink, st);
} }
return B_OK; return B_OK;
} }
@@ -734,7 +734,7 @@ _kern_write_stat(int fd, const char *path, bool traverseLink,
return errno; return errno;
isSymlink = S_ISLNK(tmpStat.st_mode); isSymlink = S_ISLNK(tmpStat.st_mode);
} else { } else {
Descriptor *descriptor = get_descriptor(fd); Descriptor *descriptor = get_descriptor(fd);
if (!descriptor) if (!descriptor)
@@ -743,17 +743,17 @@ _kern_write_stat(int fd, const char *path, bool traverseLink,
if (FileDescriptor *fileFD if (FileDescriptor *fileFD
= dynamic_cast<FileDescriptor*>(descriptor)) { = dynamic_cast<FileDescriptor*>(descriptor)) {
realFD = fileFD->fd; realFD = fileFD->fd;
} else if (dynamic_cast<DirectoryDescriptor*>(descriptor)) { } else if (dynamic_cast<DirectoryDescriptor*>(descriptor)) {
error = get_path(fd, NULL, realPath); error = get_path(fd, NULL, realPath);
if (error != B_OK) if (error != B_OK)
return error; return error;
} else if (SymlinkDescriptor *linkFD } else if (SymlinkDescriptor *linkFD
= dynamic_cast<SymlinkDescriptor*>(descriptor)) { = dynamic_cast<SymlinkDescriptor*>(descriptor)) {
realPath = linkFD->path; realPath = linkFD->path;
isSymlink = true; isSymlink = true;
} else } else
return B_FILE_ERROR; return B_FILE_ERROR;
} }
@@ -762,23 +762,23 @@ _kern_write_stat(int fd, const char *path, bool traverseLink,
// available functions traverse symlinks. // available functions traverse symlinks.
if (isSymlink && !traverseLink) if (isSymlink && !traverseLink)
return B_ERROR; return B_ERROR;
if (realFD >= 0) { if (realFD >= 0) {
if (statMask & B_STAT_MODE) { if (statMask & B_STAT_MODE) {
if (fchmod(realFD, st->st_mode) < 0) if (fchmod(realFD, st->st_mode) < 0)
return errno; return errno;
} }
if (statMask & B_STAT_UID) { if (statMask & B_STAT_UID) {
if (fchown(realFD, st->st_uid, (gid_t)-1) < 0) if (fchown(realFD, st->st_uid, (gid_t)-1) < 0)
return errno; return errno;
} }
if (statMask & B_STAT_GID) { if (statMask & B_STAT_GID) {
if (fchown(realFD, (uid_t)-1, st->st_gid) < 0) if (fchown(realFD, (uid_t)-1, st->st_gid) < 0)
return errno; return errno;
} }
if (statMask & B_STAT_SIZE) { if (statMask & B_STAT_SIZE) {
if (ftruncate(realFD, st->st_size) < 0) if (ftruncate(realFD, st->st_size) < 0)
return errno; return errno;
@@ -790,25 +790,25 @@ _kern_write_stat(int fd, const char *path, bool traverseLink,
| B_STAT_CREATION_TIME | B_STAT_CHANGE_TIME)) { | B_STAT_CREATION_TIME | B_STAT_CHANGE_TIME)) {
return B_ERROR; return B_ERROR;
} }
return 0; return 0;
} else { } else {
if (statMask & B_STAT_MODE) { if (statMask & B_STAT_MODE) {
if (chmod(realPath.c_str(), st->st_mode) < 0) if (chmod(realPath.c_str(), st->st_mode) < 0)
return errno; return errno;
} }
if (statMask & B_STAT_UID) { if (statMask & B_STAT_UID) {
if (chown(realPath.c_str(), st->st_uid, (gid_t)-1) < 0) if (chown(realPath.c_str(), st->st_uid, (gid_t)-1) < 0)
return errno; return errno;
} }
if (statMask & B_STAT_GID) { if (statMask & B_STAT_GID) {
if (chown(realPath.c_str(), (uid_t)-1, st->st_gid) < 0) if (chown(realPath.c_str(), (uid_t)-1, st->st_gid) < 0)
return errno; return errno;
} }
if (statMask & B_STAT_SIZE) { if (statMask & B_STAT_SIZE) {
if (truncate(realPath.c_str(), st->st_size) < 0) if (truncate(realPath.c_str(), st->st_size) < 0)
return errno; return errno;
@@ -822,18 +822,18 @@ _kern_write_stat(int fd, const char *path, bool traverseLink,
if (stat(realPath.c_str(), &oldStat) < 0) if (stat(realPath.c_str(), &oldStat) < 0)
return errno; return errno;
} }
utimbuf buffer; utimbuf buffer;
buffer.actime = (statMask & B_STAT_ACCESS_TIME) ? st->st_atime : oldStat.st_atime; 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; buffer.modtime = (statMask & B_STAT_MODIFICATION_TIME) ? st->st_mtime : oldStat.st_mtime;
if (utime(realPath.c_str(), &buffer) < 0) if (utime(realPath.c_str(), &buffer) < 0)
return errno; return errno;
} }
// not supported // not supported
if (statMask & (B_STAT_CREATION_TIME | B_STAT_CHANGE_TIME)) if (statMask & (B_STAT_CREATION_TIME | B_STAT_CHANGE_TIME))
return B_ERROR; return B_ERROR;
} }
return B_OK; return B_OK;
} }
@@ -878,7 +878,7 @@ _kern_read_link(int fd, const char *path, char *buffer, size_t *_bufferSize)
if (*_bufferSize > 0) { if (*_bufferSize > 0) {
if ((size_t)bytesRead == *_bufferSize) if ((size_t)bytesRead == *_bufferSize)
bytesRead--; bytesRead--;
buffer[bytesRead] = '\0'; 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); error = get_path(newDir, newPath, realNewPath);
if (error != B_OK) if (error != B_OK)
return error; return error;
// rename // rename
if (rename(realOldPath.c_str(), realNewPath.c_str()) < 0) if (rename(realOldPath.c_str(), realNewPath.c_str()) < 0)
return errno; 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); off_t result = lseek(fd, pos, SEEK_SET);
if (result < 0) if (result < 0)
return errno; return errno;
// read // read
ssize_t bytesRead = haiku_host_platform_read(fd, buffer, bufferSize); ssize_t bytesRead = haiku_host_platform_read(fd, buffer, bufferSize);
if (bytesRead < 0) { if (bytesRead < 0) {
@@ -969,12 +969,25 @@ read_pos(int fd, off_t pos, void *buffer, size_t bufferSize)
ssize_t ssize_t
write_pos(int fd, off_t pos, const void *buffer, size_t bufferSize) 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 // seek
off_t result = lseek(fd, pos, SEEK_SET); off_t result = lseek(fd, pos, SEEK_SET);
if (result < 0) if (result < 0)
return errno; return errno;
// read // write
ssize_t bytesWritten = haiku_host_platform_write(fd, buffer, bufferSize); ssize_t bytesWritten = haiku_host_platform_write(fd, buffer, bufferSize);
if (bytesWritten < 0) { if (bytesWritten < 0) {
errno = bytesWritten; 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); off_t result = lseek(fd, pos, SEEK_SET);
if (result < 0) if (result < 0)
return errno; return errno;
// read // read
ssize_t bytesRead = haiku_host_platform_readv(fd, vec, count); ssize_t bytesRead = haiku_host_platform_readv(fd, vec, count);
if (bytesRead < 0) { 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); off_t result = lseek(fd, pos, SEEK_SET);
if (result < 0) if (result < 0)
return errno; return errno;
// read // read
ssize_t bytesWritten = haiku_host_platform_writev(fd, vec, count); ssize_t bytesWritten = haiku_host_platform_writev(fd, vec, count);
if (bytesWritten < 0) { if (bytesWritten < 0) {
+27 -27
View File
@@ -33,7 +33,7 @@ init_attribute_dir_base_dir()
if (initialized) if (initialized)
return initError; return initError;
// stat the dir // stat the dir
struct stat st; struct stat st;
initError = B_OK; initError = B_OK;
@@ -44,7 +44,7 @@ init_attribute_dir_base_dir()
"directory base directory exists, but is no directory!\n"); "directory base directory exists, but is no directory!\n");
initError = B_FILE_ERROR; initError = B_FILE_ERROR;
} }
} else { } else {
// doesn't exist yet: create it // doesn't exist yet: create it
if (mkdir(sAttributeDirBasePath, S_IRWXU | S_IRWXG | S_IRWXO) < 0) if (mkdir(sAttributeDirBasePath, S_IRWXU | S_IRWXG | S_IRWXO) < 0)
@@ -68,7 +68,7 @@ escape_attr_name(const char *name)
escapedName += "__"; escapedName += "__";
else else
escapedName += *name; escapedName += *name;
name++; name++;
} }
@@ -84,7 +84,7 @@ deescape_attr_name(const char *name)
return "___"; return "___";
} }
name++; name++;
string deescapedName; string deescapedName;
while (*name != '\0') { while (*name != '\0') {
if (*name == '_') { if (*name == '_') {
@@ -100,11 +100,11 @@ deescape_attr_name(const char *name)
} }
} else } else
deescapedName += *name; deescapedName += *name;
name++; name++;
} }
return deescapedName; return deescapedName;
} }
// get_attribute_dir_path // get_attribute_dir_path
@@ -179,7 +179,7 @@ get_attribute_path(NodeRef ref, const char *path, int fd,
errno = error; errno = error;
return -1; return -1;
} }
// construct the attribute path // construct the attribute path
attrPath = get_attribute_dir_path(ref) + '/'; attrPath = get_attribute_dir_path(ref) + '/';
string attrName(escape_attr_name(attribute)); 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. // (i.e. system) file descriptor, which is just as well.
string path; string path;
bool pathValid = (get_path(fd, NULL, path) == B_OK); bool pathValid = (get_path(fd, NULL, path) == B_OK);
// get the attribute path // get the attribute path
return get_attribute_path(ref, (pathValid ? path.c_str() : NULL), return get_attribute_path(ref, (pathValid ? path.c_str() : NULL),
(pathValid ? -1 : fd), attribute, attrPath, typePath); (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. // (i.e. system) file descriptor, which is just as well.
string path; string path;
bool pathValid = (get_path(fd, NULL, path) == B_OK); bool pathValid = (get_path(fd, NULL, path) == B_OK);
// get the attribute path // get the attribute path
return open_attr_dir(NodeRef(st), (pathValid ? path.c_str() : NULL), return open_attr_dir(NodeRef(st), (pathValid ? path.c_str() : NULL),
(pathValid ? -1 : fd)); (pathValid ? -1 : fd));
@@ -292,8 +292,8 @@ fs_read_attr_dir(DIR *dir)
entry = readdir(dir); entry = readdir(dir);
if (!entry) if (!entry)
return NULL; return NULL;
// ignore administrative entries; the // ignore administrative entries; the
if (entry->d_name[0] == '_') { if (entry->d_name[0] == '_') {
string attrName = deescape_attr_name(entry->d_name); string attrName = deescape_attr_name(entry->d_name);
strcpy(entry->d_name, attrName.c_str()); strcpy(entry->d_name, attrName.c_str());
@@ -309,15 +309,15 @@ fs_rewind_attr_dir(DIR *dir)
rewinddir(dir); rewinddir(dir);
} }
// fs_open_attr // fs_fopen_attr
int 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) { if (!attribute) {
errno = B_BAD_VALUE; errno = B_BAD_VALUE;
return -1; return -1;
} }
// get the attribute path // get the attribute path
string attrPath; string attrPath;
string typePath; string typePath;
@@ -344,7 +344,7 @@ fs_open_attr(int fd, const char *attribute, uint32 type, int openMode)
// write the type into the file // write the type into the file
if (write(typeFD, &type, sizeof(type)) < 0) if (write(typeFD, &type, sizeof(type)) < 0)
error = errno; error = errno;
close(typeFD); close(typeFD);
} else } else
@@ -355,10 +355,10 @@ fs_open_attr(int fd, const char *attribute, uint32 type, int openMode)
if (typeFD > 0) { if (typeFD > 0) {
unlink(typePath.c_str()); unlink(typePath.c_str());
} }
close(attrFD); close(attrFD);
unlink(attrPath.c_str()); unlink(attrPath.c_str());
errno = error; errno = error;
return -1; return -1;
} }
@@ -395,7 +395,7 @@ fs_read_attr(int fd, const char *attribute, uint32 type, off_t pos,
errno = error; errno = error;
return -1; return -1;
} }
return bytesRead; return bytesRead;
} }
@@ -421,7 +421,7 @@ fs_write_attr(int fd, const char *attribute, uint32 type, off_t pos,
errno = error; errno = error;
return -1; return -1;
} }
return bytesWritten; return bytesWritten;
} }
@@ -433,7 +433,7 @@ fs_remove_attr(int fd, const char *attribute)
errno = B_BAD_VALUE; errno = B_BAD_VALUE;
return -1; return -1;
} }
// get the attribute path // get the attribute path
string attrPath; string attrPath;
string typePath; string typePath;
@@ -446,9 +446,9 @@ fs_remove_attr(int fd, const char *attribute)
// remove the attribute // remove the attribute
if (unlink(attrPath.c_str()) < 0) if (unlink(attrPath.c_str()) < 0)
return -1; return -1;
unlink(typePath.c_str()); unlink(typePath.c_str());
return B_OK; return B_OK;
} }
@@ -474,7 +474,7 @@ fs_stat_attr(int fd, const char *attribute, struct attr_info *attrInfo)
struct stat st; struct stat st;
if (lstat(attrPath.c_str(), &st) < 0) if (lstat(attrPath.c_str(), &st) < 0)
return -1; return -1;
attrInfo->size = st.st_size; attrInfo->size = st.st_size;
// now open the attribute type file and read the attribute's type // 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 -1;
} }
return 0; return 0;
} }
@@ -524,14 +524,14 @@ _kern_open_attr_dir(int fd, const char *path)
if (error != B_OK) if (error != B_OK)
return error; return error;
} }
// open the attr dir // open the attr dir
DIR *dir = open_attr_dir(ref, (path ? realPath.c_str() : NULL), DIR *dir = open_attr_dir(ref, (path ? realPath.c_str() : NULL),
(path ? -1 : fd)); (path ? -1 : fd));
if (!dir) if (!dir)
return errno; return errno;
// create descriptor // create descriptor
AttrDirDescriptor *descriptor = new AttrDirDescriptor(dir, ref); AttrDirDescriptor *descriptor = new AttrDirDescriptor(dir, ref);
return add_descriptor(descriptor); return add_descriptor(descriptor);
} }
@@ -571,7 +571,7 @@ _kern_rename_attr(int fromFile, const char *fromName, int toFile,
return error; return error;
} }
return B_OK; return B_OK;
} }
+36 -8
View File
@@ -452,22 +452,50 @@ fs_rewind_attr_dir(DIR *dir)
attrDir->RewindDir(); attrDir->RewindDir();
} }
// fs_open_attr // fs_fopen_attr
int 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 if (fd < 0) {
errno = B_BAD_VALUE; errno = B_BAD_VALUE;
return -1; 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 // fs_close_attr
int int
fs_close_attr(int fd) fs_close_attr(int fd)
{ {
// not supported ATM status_t error = delete_descriptor(fd);
errno = B_BAD_VALUE; if (error != 0) {
return -1; errno = error;
return -1;
}
return 0;
} }
// fs_read_attr // fs_read_attr
+147
View File
@@ -11,7 +11,9 @@
#include <map> #include <map>
#include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <fs_attr.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 // #pragma mark - AttrDirDescriptor
+33 -3
View File
@@ -5,6 +5,7 @@
#include <string> #include <string>
#include <StorageDefs.h>
#include <SupportDefs.h> #include <SupportDefs.h>
#include "NodeRef.h" #include "NodeRef.h"
@@ -35,7 +36,7 @@ struct Descriptor {
struct FileDescriptor : Descriptor { struct FileDescriptor : Descriptor {
FileDescriptor(int fd); FileDescriptor(int fd);
virtual ~FileDescriptor(); virtual ~FileDescriptor();
virtual status_t Close(); virtual status_t Close();
virtual status_t Dup(Descriptor *&clone); virtual status_t Dup(Descriptor *&clone);
virtual status_t GetStat(bool traverseLink, struct stat *st); virtual status_t GetStat(bool traverseLink, struct stat *st);
@@ -50,7 +51,7 @@ struct DirectoryDescriptor : Descriptor {
DirectoryDescriptor(DIR *dir, const NodeRef &ref); DirectoryDescriptor(DIR *dir, const NodeRef &ref);
virtual ~DirectoryDescriptor(); virtual ~DirectoryDescriptor();
virtual status_t Close(); virtual status_t Close();
virtual status_t Dup(Descriptor *&clone); virtual status_t Dup(Descriptor *&clone);
virtual status_t GetStat(bool traverseLink, struct stat *st); virtual status_t GetStat(bool traverseLink, struct stat *st);
@@ -71,12 +72,41 @@ struct SymlinkDescriptor : Descriptor {
virtual status_t GetPath(string& path) const; 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 // AttrDirDescriptor
struct AttrDirDescriptor : DirectoryDescriptor { struct AttrDirDescriptor : DirectoryDescriptor {
AttrDirDescriptor(DIR *dir, const NodeRef &ref); AttrDirDescriptor(DIR *dir, const NodeRef &ref);
virtual ~AttrDirDescriptor(); virtual ~AttrDirDescriptor();
virtual status_t Close(); virtual status_t Close();
virtual status_t Dup(Descriptor *&clone); virtual status_t Dup(Descriptor *&clone);
virtual status_t GetStat(bool traverseLink, struct stat *st); virtual status_t GetStat(bool traverseLink, struct stat *st);