* Fixed the directory filler callbacks. It is possible that it is passed a NULL
struct stat (new callback) or a 0 type. So if we don't have a node type, we need to stat the node. * Added simple opening/closing of files (no reading/writing yet). It's now possible to browse sshfs volumes. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29634 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c029607ba8
commit
fe24dc3df4
@ -413,9 +413,9 @@ FUSEFileSystem::_InitCapabilities()
|
||||
//
|
||||
// // file operations
|
||||
// fNodeCapabilities.Set(FS_VNODE_CAPABILITY_CREATE, fFS->ops.create);
|
||||
// fNodeCapabilities.Set(FS_VNODE_CAPABILITY_OPEN, fFS->ops.open);
|
||||
// fNodeCapabilities.Set(FS_VNODE_CAPABILITY_CLOSE, fFS->ops.close);
|
||||
// fNodeCapabilities.Set(FS_VNODE_CAPABILITY_FREE_COOKIE, fFS->ops.free_cookie);
|
||||
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_OPEN, fFS->ops.open);
|
||||
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_CLOSE, fFS->ops.flush);
|
||||
fNodeCapabilities.Set(FS_VNODE_CAPABILITY_FREE_COOKIE, fFS->ops.release);
|
||||
// fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ, fFS->ops.read);
|
||||
// fNodeCapabilities.Set(FS_VNODE_CAPABILITY_WRITE, fFS->ops.write);
|
||||
//
|
||||
|
@ -170,6 +170,21 @@ struct FUSEVolume::DirCookie : fuse_file_info {
|
||||
};
|
||||
|
||||
|
||||
struct FUSEVolume::FileCookie : fuse_file_info {
|
||||
FileCookie(int openMode)
|
||||
{
|
||||
flags = openMode;
|
||||
fh_old = 0;
|
||||
writepage = 0;
|
||||
direct_io = 0;
|
||||
keep_cache = 0;
|
||||
flush = 0;
|
||||
fh = 0;
|
||||
lock_owner = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct FUSEVolume::ReadDirBuffer {
|
||||
FUSEVolume* volume;
|
||||
FUSENode* directory;
|
||||
@ -398,6 +413,7 @@ FUSEVolume::ReadVNode(ino_t vnid, bool reenter, void** _node, int* type,
|
||||
RETURN_ERROR(B_ENTRY_NOT_FOUND);
|
||||
|
||||
node->refCount++;
|
||||
|
||||
*_node = node;
|
||||
*type = node->type;
|
||||
*flags = 0;
|
||||
@ -607,26 +623,98 @@ FUSEVolume::Create(void* dir, const char* name, int openMode, int mode,
|
||||
|
||||
|
||||
status_t
|
||||
FUSEVolume::Open(void* node, int openMode, void** cookie)
|
||||
FUSEVolume::Open(void* _node, int openMode, void** _cookie)
|
||||
{
|
||||
// TODO: Implement!
|
||||
return B_UNSUPPORTED;
|
||||
FUSENode* node = (FUSENode*)_node;
|
||||
PRINT(("FUSEVolume::Open(%p (%lld), %#x)\n", node, node->id, openMode));
|
||||
|
||||
bool truncate = (openMode & O_TRUNC) != 0;
|
||||
openMode &= ~O_TRUNC;
|
||||
|
||||
// TODO: Support truncation!
|
||||
if (truncate)
|
||||
RETURN_ERROR(B_NOT_ALLOWED);
|
||||
|
||||
// allocate a file cookie
|
||||
FileCookie* cookie = new(std::nothrow) FileCookie(openMode);
|
||||
if (cookie == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
ObjectDeleter<FileCookie> cookieDeleter(cookie);
|
||||
|
||||
AutoLocker<Locker> locker(fLock);
|
||||
|
||||
// get a path for the node
|
||||
char path[B_PATH_NAME_LENGTH];
|
||||
size_t pathLen;
|
||||
status_t error = _BuildPath(node, path, pathLen);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
// open the dir
|
||||
int fuseError = fuse_fs_open(fFS, path, cookie);
|
||||
if (fuseError != 0)
|
||||
return from_fuse_error(fuseError);
|
||||
|
||||
cookieDeleter.Detach();
|
||||
*_cookie = cookie;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
FUSEVolume::Close(void* node, void* cookie)
|
||||
FUSEVolume::Close(void* _node, void* _cookie)
|
||||
{
|
||||
// TODO: Implement!
|
||||
return B_UNSUPPORTED;
|
||||
FUSENode* node = (FUSENode*)_node;
|
||||
FileCookie* cookie = (FileCookie*)_cookie;
|
||||
|
||||
AutoLocker<Locker> locker(fLock);
|
||||
|
||||
// get a path for the node
|
||||
char path[B_PATH_NAME_LENGTH];
|
||||
size_t pathLen;
|
||||
status_t error = _BuildPath(node, path, pathLen);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
// flush the file
|
||||
int fuseError = fuse_fs_flush(fFS, path, cookie);
|
||||
if (fuseError != 0)
|
||||
return from_fuse_error(fuseError);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
FUSEVolume::FreeCookie(void* node, void* cookie)
|
||||
FUSEVolume::FreeCookie(void* _node, void* _cookie)
|
||||
{
|
||||
// TODO: Implement!
|
||||
return B_UNSUPPORTED;
|
||||
FUSENode* node = (FUSENode*)_node;
|
||||
FileCookie* cookie = (FileCookie*)_cookie;
|
||||
|
||||
ObjectDeleter<FileCookie> cookieDeleter(cookie);
|
||||
|
||||
AutoLocker<Locker> locker(fLock);
|
||||
|
||||
// get a path for the node
|
||||
char path[B_PATH_NAME_LENGTH];
|
||||
size_t pathLen;
|
||||
status_t error = _BuildPath(node, path, pathLen);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
// release the file
|
||||
int fuseError = fuse_fs_release(fFS, path, cookie);
|
||||
if (fuseError != 0)
|
||||
return from_fuse_error(fuseError);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -1068,8 +1156,10 @@ FUSEVolume::_AddReadDirEntry(void* _buffer, const char* name,
|
||||
const struct stat* st, off_t offset)
|
||||
{
|
||||
ReadDirBuffer* buffer = (ReadDirBuffer*)_buffer;
|
||||
return buffer->volume->_AddReadDirEntry(buffer, name, st->st_mode & S_IFMT,
|
||||
st->st_ino, offset);
|
||||
|
||||
ino_t nodeID = st != NULL ? st->st_ino : 0;
|
||||
int type = st != NULL ? st->st_mode & S_IFMT : 0;
|
||||
return buffer->volume->_AddReadDirEntry(buffer, name, type, nodeID, offset);
|
||||
}
|
||||
|
||||
|
||||
@ -1078,7 +1168,7 @@ FUSEVolume::_AddReadDirEntryGetDir(fuse_dirh_t handle, const char* name,
|
||||
int type, ino_t nodeID)
|
||||
{
|
||||
ReadDirBuffer* buffer = (ReadDirBuffer*)handle;
|
||||
return buffer->volume->_AddReadDirEntry(buffer, name, type & S_IFMT, nodeID,
|
||||
return buffer->volume->_AddReadDirEntry(buffer, name, type << 12, nodeID,
|
||||
0);
|
||||
}
|
||||
|
||||
@ -1090,7 +1180,7 @@ FUSEVolume::_AddReadDirEntry(ReadDirBuffer* buffer, const char* name, int type,
|
||||
PRINT(("FUSEVolume::_AddReadDirEntry(%p, \"%s\", %#x, %lld, %lld\n", buffer,
|
||||
name, type, nodeID, offset));
|
||||
|
||||
AutoLocker<Locker> _(fLock);
|
||||
AutoLocker<Locker> locker(fLock);
|
||||
|
||||
size_t entryLen;
|
||||
if (offset != 0) {
|
||||
@ -1110,6 +1200,7 @@ name, type, nodeID, offset));
|
||||
if (strcmp(name, ".") == 0) {
|
||||
// current dir entry
|
||||
nodeID = dirID;
|
||||
type = S_IFDIR;
|
||||
} else if (strcmp(name, "..") == 0) {
|
||||
// parent dir entry
|
||||
FUSEEntry* parentEntry = buffer->directory->entries.Head();
|
||||
@ -1119,6 +1210,7 @@ name, type, nodeID, offset));
|
||||
return 0;
|
||||
}
|
||||
nodeID = parentEntry->parent->id;
|
||||
type = S_IFDIR;
|
||||
} else if ((entry = fEntries.Lookup(FUSEEntryRef(dirID, name))) == NULL) {
|
||||
// get the node
|
||||
FUSENode* node = NULL;
|
||||
@ -1129,6 +1221,34 @@ name, type, nodeID, offset));
|
||||
|
||||
if (node == NULL) {
|
||||
// no node yet -- create one
|
||||
|
||||
// If we don't have a valid type, we need to stat the node first.
|
||||
if (type == 0) {
|
||||
char path[B_PATH_NAME_LENGTH];
|
||||
size_t pathLen;
|
||||
status_t error = _BuildPath(buffer->directory, name, path,
|
||||
pathLen);
|
||||
if (error != B_OK) {
|
||||
buffer->error = error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
// stat the path
|
||||
struct stat st;
|
||||
int fuseError = fuse_fs_getattr(fFS, path, &st);
|
||||
|
||||
locker.Lock();
|
||||
|
||||
if (fuseError != 0) {
|
||||
buffer->error = from_fuse_error(fuseError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
type = st.st_mode & S_IFMT;
|
||||
}
|
||||
|
||||
node = new(std::nothrow) FUSENode(nodeID, type);
|
||||
if (node == NULL) {
|
||||
buffer->error = B_NO_MEMORY;
|
||||
@ -1153,7 +1273,9 @@ PRINT((" -> create node: %p, id: %lld\n", node, nodeID));
|
||||
fEntries.Insert(entry);
|
||||
node->entries.Add(entry);
|
||||
} else {
|
||||
// TODO: Check whether the node's ID matches the one we got!
|
||||
// TODO: Check whether the node's ID matches the one we got (if any)!
|
||||
nodeID = entry->node->id;
|
||||
type = entry->node->type;
|
||||
}
|
||||
|
||||
if (offset == 0) {
|
||||
|
@ -121,6 +121,7 @@ public:
|
||||
private:
|
||||
struct DirEntryCache;
|
||||
struct DirCookie;
|
||||
struct FileCookie;
|
||||
struct ReadDirBuffer;
|
||||
|
||||
private:
|
||||
|
Loading…
Reference in New Issue
Block a user