From f0ee02b25e02a7ba84efc541ab7b51f0e11ede9b Mon Sep 17 00:00:00 2001 From: PulkoMandy Date: Sun, 17 Jul 2022 22:58:12 +0200 Subject: [PATCH] userlandfs_fuse_lowlevel: fix opening directories in Tracker - It is possible to call open() on a directory, but FUSE lowlevel filesystems don't implement that and expect it to be re-routed to the opendir call. BRoster uses this to read the dir/file attributes to identify it, so it could not identify directories properly. - In ReadDir, make sure to not return more entries than asked, as this confuses the userlandfs protocol communication (the kernel does not acknowledge the readdir reply, and then the server hits an assert when receiving the next request instead of the ack). Change-Id: I9c4e9a3f0fc6e9879d4cfbc0d5402a4733d2218a Reviewed-on: https://review.haiku-os.org/c/haiku/+/5482 Tested-by: Commit checker robot Reviewed-by: waddlesplash --- headers/private/userlandfs/private/Requests.h | 38 +++++++++---------- .../userlandfs/server/fuse/FUSEFileSystem.cpp | 6 +-- .../userlandfs/server/fuse/FUSEVolume.cpp | 12 +++--- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/headers/private/userlandfs/private/Requests.h b/headers/private/userlandfs/private/Requests.h index 075c7408f3..16a45a66c6 100644 --- a/headers/private/userlandfs/private/Requests.h +++ b/headers/private/userlandfs/private/Requests.h @@ -38,7 +38,7 @@ enum { SYNC_VOLUME_REQUEST, SYNC_VOLUME_REPLY, READ_FS_INFO_REQUEST, - READ_FS_INFO_REPLY, + READ_FS_INFO_REPLY, // 10 WRITE_FS_INFO_REQUEST, WRITE_FS_INFO_REPLY, @@ -50,7 +50,7 @@ enum { READ_VNODE_REQUEST, READ_VNODE_REPLY, WRITE_VNODE_REQUEST, - WRITE_VNODE_REPLY, + WRITE_VNODE_REPLY, // 20 FS_REMOVE_VNODE_REQUEST, FS_REMOVE_VNODE_REPLY, @@ -62,7 +62,7 @@ enum { ITERATIVE_IO_GET_VECS_REQUEST, ITERATIVE_IO_GET_VECS_REPLY, ITERATIVE_IO_FINISHED_REQUEST, - ITERATIVE_IO_FINISHED_REPLY, + ITERATIVE_IO_FINISHED_REPLY, // 30 // nodes IOCTL_REQUEST, @@ -74,7 +74,7 @@ enum { DESELECT_REQUEST, DESELECT_REPLY, FSYNC_REQUEST, - FSYNC_REPLY, + FSYNC_REPLY, // 40 READ_SYMLINK_REQUEST, READ_SYMLINK_REPLY, @@ -85,7 +85,7 @@ enum { UNLINK_REQUEST, UNLINK_REPLY, RENAME_REQUEST, - RENAME_REPLY, + RENAME_REPLY, // 50 ACCESS_REQUEST, ACCESS_REPLY, @@ -98,7 +98,7 @@ enum { CREATE_REQUEST, CREATE_REPLY, OPEN_REQUEST, - OPEN_REPLY, + OPEN_REPLY, // 60 CLOSE_REQUEST, CLOSE_REPLY, FREE_COOKIE_REQUEST, @@ -110,7 +110,7 @@ enum { // directories CREATE_DIR_REQUEST, - CREATE_DIR_REPLY, + CREATE_DIR_REPLY, // 70 REMOVE_DIR_REQUEST, REMOVE_DIR_REPLY, OPEN_DIR_REQUEST, @@ -120,7 +120,7 @@ enum { FREE_DIR_COOKIE_REQUEST, FREE_DIR_COOKIE_REPLY, READ_DIR_REQUEST, - READ_DIR_REPLY, + READ_DIR_REPLY, // 80 REWIND_DIR_REQUEST, REWIND_DIR_REPLY, @@ -132,7 +132,7 @@ enum { FREE_ATTR_DIR_COOKIE_REQUEST, FREE_ATTR_DIR_COOKIE_REPLY, READ_ATTR_DIR_REQUEST, - READ_ATTR_DIR_REPLY, + READ_ATTR_DIR_REPLY, // 90 REWIND_ATTR_DIR_REQUEST, REWIND_ATTR_DIR_REPLY, @@ -144,7 +144,7 @@ enum { CLOSE_ATTR_REQUEST, CLOSE_ATTR_REPLY, FREE_ATTR_COOKIE_REQUEST, - FREE_ATTR_COOKIE_REPLY, + FREE_ATTR_COOKIE_REPLY, // 100 READ_ATTR_REQUEST, READ_ATTR_REPLY, WRITE_ATTR_REQUEST, @@ -154,7 +154,7 @@ enum { WRITE_ATTR_STAT_REQUEST, WRITE_ATTR_STAT_REPLY, RENAME_ATTR_REQUEST, - RENAME_ATTR_REPLY, + RENAME_ATTR_REPLY, // 110 REMOVE_ATTR_REQUEST, REMOVE_ATTR_REPLY, @@ -166,7 +166,7 @@ enum { FREE_INDEX_DIR_COOKIE_REQUEST, FREE_INDEX_DIR_COOKIE_REPLY, READ_INDEX_DIR_REQUEST, - READ_INDEX_DIR_REPLY, + READ_INDEX_DIR_REPLY, // 120 REWIND_INDEX_DIR_REQUEST, REWIND_INDEX_DIR_REPLY, CREATE_INDEX_REQUEST, @@ -178,7 +178,7 @@ enum { // queries OPEN_QUERY_REQUEST, - OPEN_QUERY_REPLY, + OPEN_QUERY_REPLY, // 130 CLOSE_QUERY_REQUEST, CLOSE_QUERY_REPLY, FREE_QUERY_COOKIE_REQUEST, @@ -190,7 +190,7 @@ enum { // node monitoring NODE_MONITORING_EVENT_REQUEST, - NODE_MONITORING_EVENT_REPLY, + NODE_MONITORING_EVENT_REPLY, // 140 // userland -> kernel requests // notifications @@ -205,7 +205,7 @@ enum { GET_VNODE_REQUEST, GET_VNODE_REPLY, PUT_VNODE_REQUEST, - PUT_VNODE_REPLY, + PUT_VNODE_REPLY, // 150 ACQUIRE_VNODE_REQUEST, ACQUIRE_VNODE_REPLY, NEW_VNODE_REQUEST, @@ -215,7 +215,7 @@ enum { REMOVE_VNODE_REQUEST, REMOVE_VNODE_REPLY, UNREMOVE_VNODE_REQUEST, - UNREMOVE_VNODE_REPLY, + UNREMOVE_VNODE_REPLY, // 160 GET_VNODE_REMOVED_REQUEST, GET_VNODE_REMOVED_REPLY, @@ -227,7 +227,7 @@ enum { FILE_CACHE_SET_ENABLED_REQUEST, FILE_CACHE_SET_ENABLED_REPLY, FILE_CACHE_SET_SIZE_REQUEST, - FILE_CACHE_SET_SIZE_REPLY, + FILE_CACHE_SET_SIZE_REPLY, // 170 FILE_CACHE_SYNC_REQUEST, FILE_CACHE_SYNC_REPLY, FILE_CACHE_READ_REQUEST, @@ -239,7 +239,7 @@ enum { DO_ITERATIVE_FD_IO_REQUEST, DO_ITERATIVE_FD_IO_REPLY, READ_FROM_IO_REQUEST_REQUEST, - READ_FROM_IO_REQUEST_REPLY, + READ_FROM_IO_REQUEST_REPLY, // 180 WRITE_TO_IO_REQUEST_REQUEST, WRITE_TO_IO_REQUEST_REPLY, NOTIFY_IO_REQUEST_REQUEST, @@ -255,7 +255,7 @@ enum { RECEIPT_ACK_REPLY, // invalid request ID (e.g. for request handlers) - NO_REQUEST, + NO_REQUEST, // 190 }; namespace UserlandFSUtil { diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.cpp index 86fa03d680..0564992823 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.cpp @@ -506,8 +506,7 @@ FUSEFileSystem::_InitCapabilities() bool hasAttributes = fLowLevelOps.listxattr != NULL; fNodeCapabilities.Set(FS_VNODE_CAPABILITY_OPEN_ATTR_DIR, hasAttributes); // not needed: FS_VNODE_CAPABILITY_CLOSE_ATTR_DIR - fNodeCapabilities.Set(FS_VNODE_CAPABILITY_FREE_ATTR_DIR_COOKIE, - hasAttributes); + fNodeCapabilities.Set(FS_VNODE_CAPABILITY_FREE_ATTR_DIR_COOKIE, hasAttributes); fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR_DIR, hasAttributes); fNodeCapabilities.Set(FS_VNODE_CAPABILITY_REWIND_ATTR_DIR, hasAttributes); @@ -521,8 +520,7 @@ FUSEFileSystem::_InitCapabilities() fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR, fLowLevelOps.getxattr); // fNodeCapabilities.Set(FS_VNODE_CAPABILITY_WRITE_ATTR, fLowLevelOps.write_attr); - fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR_STAT, - fLowLevelOps.getxattr); + fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR_STAT, fLowLevelOps.getxattr); // // missing: FS_VNODE_CAPABILITY_WRITE_ATTR_STAT // fNodeCapabilities.Set(FS_VNODE_CAPABILITY_RENAME_ATTR, fLowLevelOps.rename_attr); } else { diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp index 4175654e18..575cbf1c7e 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp @@ -1654,12 +1654,14 @@ FUSEVolume::Open(void* _node, int openMode, void** _cookie) size_t pathLen; int fuseError; - struct fuse_file_info llCookie; + struct fuse_file_info llCookie = { 0 }; // FIXME store this in the FileCookie for lowlevel streams, we'll need it in read, write... if (fOps != NULL) { llCookie.flags = openMode; - // TODO do we need to perform a conversion here? - fuseError = fuse_ll_open(fOps, node->id, &llCookie); + if (S_ISDIR(node->type)) + fuseError = fuse_ll_opendir(fOps, node->id, &llCookie); + else + fuseError = fuse_ll_open(fOps, node->id, &llCookie); } else { AutoLocker locker(fLock); @@ -2154,8 +2156,8 @@ FUSEVolume::ReadDir(void* _node, void* _cookie, void* buffer, size_t bufferSize, // currentEntryOffset. if (fuseError > 0) { struct dirent* dirent = (struct dirent*)buffer; - countRead = 0; - while ((char*)dirent + dirent->d_reclen <= (char*)buffer + fuseError) { + while (countRead < count + && (char*)dirent + dirent->d_reclen <= (char*)buffer + fuseError) { countRead++; dirent = (struct dirent*)(((char*)dirent) + dirent->d_reclen); if (dirent->d_reclen == 0)