// netfs.cpp #include #include #include #include "DebugSupport.h" #include "Node.h" #include "ObjectTracker.h" #include "QueryManager.h" #include "RootVolume.h" #include "VolumeManager.h" // #pragma mark - // #pragma mark ----- prototypes ----- extern "C" { // fs static int netfs_mount(nspace_id nsid, const char *device, ulong flags, void *parameters, size_t len, void **data, vnode_id *rootID); static int netfs_unmount(void *ns); //static int netfs_sync(void *ns); static int netfs_read_fs_stat(void *ns, struct fs_info *info); //static int netfs_write_fs_stat(void *ns, struct fs_info *info, long mask); // vnodes static int netfs_read_vnode(void *ns, vnode_id vnid, char reenter, void **node); static int netfs_write_vnode(void *ns, void *node, char reenter); static int netfs_remove_vnode(void *ns, void *node, char reenter); // nodes //static int netfs_fsync(void *ns, void *node); static int netfs_read_stat(void *ns, void *node, struct stat *st); static int netfs_write_stat(void *ns, void *node, struct stat *st, long mask); static int netfs_access(void *ns, void *node, int mode); // files static int netfs_create(void *ns, void *dir, const char *name, int openMode, int mode, vnode_id *vnid, void **cookie); static int netfs_open(void *ns, void *node, int openMode, void **cookie); static int netfs_close(void *ns, void *node, void *cookie); static int netfs_free_cookie(void *ns, void *node, void *cookie); static int netfs_read(void *ns, void *node, void *cookie, off_t pos, void *buffer, size_t *bufferSize); static int netfs_write(void *ns, void *node, void *cookie, off_t pos, const void *buffer, size_t *bufferSize); static int netfs_ioctl(void *ns, void *node, void *cookie, int cmd, void *buffer, size_t bufferSize); //static int netfs_setflags(void *ns, void *node, void *cookie, int flags); // hard links / symlinks static int netfs_link(void *ns, void *dir, const char *name, void *node); static int netfs_unlink(void *ns, void *dir, const char *name); static int netfs_symlink(void *ns, void *dir, const char *name, const char *path); static int netfs_read_link(void *ns, void *node, char *buffer, size_t *bufferSize); static int netfs_rename(void *ns, void *oldDir, const char *oldName, void *newDir, const char *newName); // directories static int netfs_mkdir(void *ns, void *dir, const char *name, int mode); static int netfs_rmdir(void *ns, void *dir, const char *name); static int netfs_open_dir(void *ns, void *node, void **cookie); static int netfs_close_dir(void *ns, void *node, void *cookie); static int netfs_free_dir_cookie(void *ns, void *node, void *cookie); static int netfs_read_dir(void *ns, void *node, void *cookie, long *count, struct dirent *buffer, size_t bufferSize); static int netfs_rewind_dir(void *ns, void *node, void *cookie); static int netfs_walk(void *ns, void *dir, const char *entryName, char **resolvedPath, vnode_id *vnid); // attributes static int netfs_open_attrdir(void *ns, void *node, void **cookie); static int netfs_close_attrdir(void *ns, void *node, void *cookie); static int netfs_free_attrdir_cookie(void *ns, void *node, void *cookie); static int netfs_read_attrdir(void *ns, void *node, void *cookie, long *count, struct dirent *buffer, size_t bufferSize); static int netfs_read_attr(void *ns, void *node, const char *name, int type, void *buffer, size_t *bufferSize, off_t pos); static int netfs_rewind_attrdir(void *ns, void *node, void *cookie); static int netfs_write_attr(void *ns, void *node, const char *name, int type, const void *buffer, size_t *bufferSize, off_t pos); static int netfs_remove_attr(void *ns, void *node, const char *name); static int netfs_rename_attr(void *ns, void *node, const char *oldName, const char *newName); static int netfs_stat_attr(void *ns, void *node, const char *name, struct attr_info *attrInfo); // queries static int netfs_open_query(void *ns, const char *queryString, ulong flags, port_id port, long token, void **cookie); static int netfs_close_query(void *ns, void *cookie); static int netfs_free_query_cookie(void *ns, void *node, void *cookie); static int netfs_read_query(void *ns, void *cookie, long *count, struct dirent *buffer, size_t bufferSize); } // extern "C" /* vnode_ops struct. Fill this in to tell the kernel how to call functions in your driver. */ vnode_ops fs_entry = { &netfs_read_vnode, // read_vnode &netfs_write_vnode, // write_vnode &netfs_remove_vnode, // remove_vnode NULL, // secure_vnode (not needed) &netfs_walk, // walk &netfs_access, // access &netfs_create, // create &netfs_mkdir, // mkdir &netfs_symlink, // symlink &netfs_link, // link &netfs_rename, // rename &netfs_unlink, // unlink &netfs_rmdir, // rmdir &netfs_read_link, // readlink &netfs_open_dir, // opendir &netfs_close_dir, // closedir &netfs_free_dir_cookie, // free_dircookie &netfs_rewind_dir, // rewinddir &netfs_read_dir, // readdir &netfs_open, // open file &netfs_close, // close file &netfs_free_cookie, // free cookie &netfs_read, // read file &netfs_write, // write file NULL, // readv NULL, // writev &netfs_ioctl, // ioctl NULL, // setflags file &netfs_read_stat, // read stat &netfs_write_stat, // write stat NULL, // fsync NULL, // initialize &netfs_mount, // mount &netfs_unmount, // unmount NULL, // sync &netfs_read_fs_stat, // read fs stat NULL, // write fs stat NULL, // select NULL, // deselect NULL, // open index dir NULL, // close index dir NULL, // free index dir cookie NULL, // rewind index dir NULL, // read index dir NULL, // create index NULL, // remove index NULL, // rename index NULL, // stat index &netfs_open_attrdir, // open attr dir &netfs_close_attrdir, // close attr dir &netfs_free_attrdir_cookie, // free attr dir cookie &netfs_rewind_attrdir, // rewind attr dir &netfs_read_attrdir, // read attr dir &netfs_write_attr, // write attr &netfs_read_attr, // read attr &netfs_remove_attr, // remove attr &netfs_rename_attr, // rename attr &netfs_stat_attr, // stat attr &netfs_open_query, // open query &netfs_close_query, // close query &netfs_free_query_cookie, // free query cookie &netfs_read_query, // read query }; int32 api_version = B_CUR_FS_API_VERSION; // #pragma mark - // #pragma mark ----- fs ----- // netfs_mount static int netfs_mount(nspace_id nsid, const char *device, ulong flags, void *parameters, size_t len, void **data, vnode_id *rootID) { status_t error = B_OK; init_debugging(); #ifdef DEBUG_OBJECT_TRACKING ObjectTracker::InitDefault(); #endif // create and init the volume manager VolumeManager* volumeManager = new(std::nothrow) VolumeManager(nsid, flags); Volume* rootVolume = NULL; if (volumeManager) { error = volumeManager->MountRootVolume(device, (const char*)parameters, len, &rootVolume); if (error != B_OK) { delete volumeManager; volumeManager = NULL; } } else error = B_NO_MEMORY; VolumePutter _(rootVolume); // set results if (error == B_OK) { *data = volumeManager; *rootID = rootVolume->GetRootID(); } else { #ifdef DEBUG_OBJECT_TRACKING ObjectTracker::ExitDefault(); #endif exit_debugging(); } return error; } // netfs_unmount static int netfs_unmount(void *ns) { VolumeManager* volumeManager = (VolumeManager*)ns; PRINT("netfs_unmount()\n"); volumeManager->UnmountRootVolume(); delete volumeManager; #ifdef DEBUG_OBJECT_TRACKING ObjectTracker::ExitDefault(); #endif PRINT("netfs_unmount() done\n"); exit_debugging(); return B_OK; } #if 0 // not used // netfs_sync static int netfs_sync(void *ns) { VolumeManager* volumeManager = (VolumeManager*)ns; Volume* volume = volumeManager->GetRootVolume(); VolumePutter _(volume); PRINT("netfs_sync(%p)\n", ns); status_t error = B_BAD_VALUE; if (volume) error = volume->Sync(); PRINT("netfs_sync() done: %" B_PRIx32 " \n", error); return error; } #endif // netfs_read_fs_stat static int netfs_read_fs_stat(void *ns, struct fs_info *info) { VolumeManager* volumeManager = (VolumeManager*)ns; Volume* volume = volumeManager->GetRootVolume(); VolumePutter _(volume); PRINT("netfs_read_fs_stat(%p, %p)\n", ns, info); status_t error = B_BAD_VALUE; if (volume) error = volume->ReadFSStat(info); PRINT("netfs_read_fs_stat() done: %" B_PRIx32 " \n", error); return error; } #if 0 // not used // netfs_write_fs_stat static int netfs_write_fs_stat(void *ns, struct fs_info *info, long mask) { VolumeManager* volumeManager = (VolumeManager*)ns; Volume* volume = volumeManager->GetRootVolume(); VolumePutter _(volume); PRINT("netfs_write_fs_stat(%p, %p, %ld)\n", ns, info, mask); status_t error = B_BAD_VALUE; if (volume) error = volume->WriteFSStat(info, mask); PRINT("netfs_write_fs_stat() done: %" B_PRIx32 " \n", error); return error; } #endif // #pragma mark - // #pragma mark ----- vnodes ----- // netfs_read_vnode static int netfs_read_vnode(void *ns, vnode_id vnid, char reenter, void **node) { VolumeManager* volumeManager = (VolumeManager*)ns; Volume* volume = volumeManager->GetVolume(vnid); VolumePutter _(volume); PRINT("netfs_read_vnode(%p, %" B_PRIdINO ", %d, %p)\n", ns, vnid, reenter, node); status_t error = B_BAD_VALUE; if (volume) error = volume->ReadVNode(vnid, reenter, (Node**)node); PRINT("netfs_read_vnode() done: (%" B_PRIx32 ", %p)\n", error, *node); return error; } // netfs_write_vnode static int netfs_write_vnode(void *ns, void *_node, char reenter) { Node* node = (Node*)_node; // DANGER: If dbg_printf() is used, this thread will enter another FS and // even perform a write operation. The is dangerous here, since this hook // may be called out of the other FSs, since, for instance a put_vnode() // called from another FS may cause the VFS layer to free vnodes and thus // invoke this hook. // PRINT(("netfs_write_vnode(%p, %p, %d)\n", ns, node, reenter)); status_t error = node->GetVolume()->WriteVNode(node, reenter); // PRINT(("netfs_write_vnode() done: %" B_PRIx32 "\n", error)); return error; } // netfs_remove_vnode static int netfs_remove_vnode(void *ns, void *_node, char reenter) { Node* node = (Node*)_node; // DANGER: See netfs_write_vnode(). // PRINT(("netfs_remove_vnode(%p, %p, %d)\n", ns, node, reenter)); status_t error = node->GetVolume()->RemoveVNode(node, reenter); // PRINT(("netfs_remove_vnode() done: %" B_PRIx32 "\n", error)); return error; } // #pragma mark - // #pragma mark ----- nodes ----- #if 0 // not used // netfs_fsync static int netfs_fsync(void *ns, void *_node) { Node* node = (Node*)_node; PRINT("netfs_fsync(%p, %p)\n", ns, node); status_t error = node->GetVolume()->FSync(node); PRINT("netfs_fsync() done: %" B_PRIx32 "\n", error); return error; } #endif // netfs_read_stat static int netfs_read_stat(void *ns, void *_node, struct stat *st) { Node* node = (Node*)_node; PRINT("netfs_read_stat(%p, %p, %p)\n", ns, node, st); status_t error = node->GetVolume()->ReadStat(node, st); PRINT("netfs_read_stat() done: %" B_PRIx32 "\n", error); return error; } // netfs_write_stat static int netfs_write_stat(void *ns, void *_node, struct stat *st, long mask) { Node* node = (Node*)_node; PRINT("netfs_write_stat(%p, %p, %p, %ld)\n", ns, node, st, mask); status_t error = node->GetVolume()->WriteStat(node, st, mask); PRINT("netfs_write_stat() done: %" B_PRIx32 "\n", error); return error; } // netfs_access static int netfs_access(void *ns, void *_node, int mode) { Node* node = (Node*)_node; PRINT("netfs_access(%p, %p, %d)\n", ns, node, mode); status_t error = node->GetVolume()->Access(node, mode); PRINT("netfs_access() done: %" B_PRIx32 "\n", error); return error; } // #pragma mark - // #pragma mark ----- files ----- // netfs_create static int netfs_create(void *ns, void *_dir, const char *name, int openMode, int mode, vnode_id *vnid, void **cookie) { Node* dir = (Node*)_dir; PRINT("netfs_create(%p, %p, `%s', %d, %d, %p, %p)\n", ns, dir, name, openMode, mode, vnid, cookie); status_t error = dir->GetVolume()->Create(dir, name, openMode, mode, vnid, cookie); PRINT("netfs_create() done: (%" B_PRIx32 ", %" B_PRIdINO ", %p)\n", error, *vnid, *cookie); return error; } // netfs_open static int netfs_open(void *ns, void *_node, int openMode, void **cookie) { Node* node = (Node*)_node; PRINT("netfs_open(%p, %p, %d)\n", ns, node, openMode); status_t error = node->GetVolume()->Open(node, openMode, cookie); PRINT("netfs_open() done: (%" B_PRIx32 ", %p)\n", error, *cookie); return error; } // netfs_close static int netfs_close(void *ns, void *_node, void *cookie) { Node* node = (Node*)_node; PRINT("netfs_close(%p, %p, %p)\n", ns, node, cookie); status_t error = node->GetVolume()->Close(node, cookie); PRINT("netfs_close() done: %" B_PRIx32 "\n", error); return error; } // netfs_free_cookie static int netfs_free_cookie(void *ns, void *_node, void *cookie) { Node* node = (Node*)_node; PRINT("netfs_free_cookie(%p, %p, %p)\n", ns, node, cookie); status_t error = node->GetVolume()->FreeCookie(node, cookie); PRINT("netfs_free_cookie() done: %" B_PRIx32 "\n", error); return error; } // netfs_read static int netfs_read(void *ns, void *_node, void *cookie, off_t pos, void *buffer, size_t *bufferSize) { Node* node = (Node*)_node; PRINT("netfs_read(%p, %p, %p, %" B_PRIdOFF ", %p, %lu)\n", ns, node, cookie, pos, buffer, *bufferSize); status_t error = node->GetVolume()->Read(node, cookie, pos, buffer, *bufferSize, bufferSize); PRINT("netfs_read() done: (%" B_PRIx32 ", %lu)\n", error, *bufferSize); return error; } // netfs_write static int netfs_write(void *ns, void *_node, void *cookie, off_t pos, const void *buffer, size_t *bufferSize) { Node* node = (Node*)_node; PRINT("netfs_write(%p, %p, %p, %" B_PRIdOFF ", %p, %lu)\n", ns, node, cookie, pos, buffer, *bufferSize); status_t error = node->GetVolume()->Write(node, cookie, pos, buffer, *bufferSize, bufferSize); PRINT("netfs_write() done: (%" B_PRIx32 ", %lu)\n", error, *bufferSize); return error; } // netfs_ioctl static int netfs_ioctl(void *ns, void *_node, void *cookie, int cmd, void *buffer, size_t bufferSize) { Node* node = (Node*)_node; PRINT("netfs_ioctl(%p, %p, %p, %d, %p, %lu)\n", ns, node, cookie, cmd, buffer, bufferSize); status_t error = node->GetVolume()->IOCtl(node, cookie, cmd, buffer, bufferSize); PRINT("netfs_ioctl() done: (%" B_PRIx32 ")\n", error); return error; } // netfs_setflags //static //int //netfs_setflags(void *ns, void *_node, void *cookie, int flags) //{ // Node* node = (Node*)_node; // PRINT(("netfs_setflags(%p, %p, %p, %d)\n", ns, node, cookie, flags)); // status_t error = node->GetVolume()->SetFlags(node, cookie, flags); // PRINT(("netfs_setflags() done: (%lx)\n", error)); // return error; //} // #pragma mark - // #pragma mark ----- hard links / symlinks ----- // netfs_link static int netfs_link(void *ns, void *_dir, const char *name, void *_node) { Node* dir = (Node*)_dir; Node* node = (Node*)_node; PRINT("netfs_link(%p, %p, `%s', %p)\n", ns, dir, name, node); status_t error = dir->GetVolume()->Link(dir, name, node); PRINT("netfs_link() done: (%" B_PRIx32 ")\n", error); return error; } // netfs_unlink static int netfs_unlink(void *ns, void *_dir, const char *name) { Node* dir = (Node*)_dir; PRINT("netfs_unlink(%p, %p, `%s')\n", ns, dir, name); status_t error = dir->GetVolume()->Unlink(dir, name); PRINT("netfs_unlink() done: (%" B_PRIx32 ")\n", error); return error; } // netfs_symlink static int netfs_symlink(void *ns, void *_dir, const char *name, const char *path) { Node* dir = (Node*)_dir; PRINT("netfs_symlink(%p, %p, `%s', `%s')\n", ns, dir, name, path); status_t error = dir->GetVolume()->Symlink(dir, name, path); PRINT("netfs_symlink() done: (%" B_PRIx32 ")\n", error); return error; } // netfs_read_link static int netfs_read_link(void *ns, void *_node, char *buffer, size_t *bufferSize) { Node* node = (Node*)_node; PRINT("netfs_read_link(%p, %p, %p, %lu)\n", ns, node, buffer, *bufferSize); // TODO: If this were to be implemented (which it isn't, it currently just // returns B_BAD_VALUE) then this will need to be changed to return the // length of the node and not the number of bytes read into buffer. status_t error = node->GetVolume()->ReadLink(node, buffer, *bufferSize, bufferSize); PRINT("netfs_read_link() done: (%" B_PRIx32 ", %lu)\n", error, *bufferSize); return error; } // netfs_rename static int netfs_rename(void *ns, void *_oldDir, const char *oldName, void *_newDir, const char *newName) { Node* oldDir = (Node*)_oldDir; Node* newDir = (Node*)_newDir; PRINT("netfs_rename(%p, %p, `%s', %p, `%s')\n", ns, oldDir, oldName, newDir, newName); status_t error = oldDir->GetVolume()->Rename(oldDir, oldName, newDir, newName); PRINT("netfs_rename() done: (%" B_PRIx32 ")\n", error); return error; } // #pragma mark - // #pragma mark ----- directories ----- // netfs_mkdir static int netfs_mkdir(void *ns, void *_dir, const char *name, int mode) { Node* dir = (Node*)_dir; PRINT("netfs_mkdir(%p, %p, `%s', %d)\n", ns, dir, name, mode); status_t error = dir->GetVolume()->MkDir(dir, name, mode); PRINT("netfs_mkdir() done: (%" B_PRIx32 ")\n", error); return error; } // netfs_rmdir static int netfs_rmdir(void *ns, void *_dir, const char *name) { Node* dir = (Node*)_dir; PRINT("netfs_rmdir(%p, %p, `%s')\n", ns, dir, name); status_t error = dir->GetVolume()->RmDir(dir, name); PRINT("netfs_rmdir() done: (%" B_PRIx32 ")\n", error); return error; } // netfs_open_dir static int netfs_open_dir(void *ns, void *_node, void **cookie) { Node* node = (Node*)_node; PRINT("netfs_open_dir(%p, %p)\n", ns, node); status_t error = node->GetVolume()->OpenDir(node, cookie); PRINT("netfs_open_dir() done: (%" B_PRIx32 ", %p)\n", error, *cookie); return error; } // netfs_close_dir static int netfs_close_dir(void *ns, void *_node, void *cookie) { Node* node = (Node*)_node; PRINT("netfs_close_dir(%p, %p, %p)\n", ns, node, cookie); status_t error = node->GetVolume()->CloseDir(node, cookie); PRINT("netfs_close_dir() done: %" B_PRIx32 "\n", error); return error; } // netfs_free_dir_cookie static int netfs_free_dir_cookie(void *ns, void *_node, void *cookie) { Node* node = (Node*)_node; PRINT("netfs_free_dir_cookie(%p, %p, %p)\n", ns, node, cookie); status_t error = node->GetVolume()->FreeDirCookie(node, cookie); PRINT("netfs_free_dir_cookie() done: %" B_PRIx32 " \n", error); return error; } // netfs_read_dir static int netfs_read_dir(void *ns, void *_node, void *cookie, long *count, struct dirent *buffer, size_t bufferSize) { Node* node = (Node*)_node; PRINT("netfs_read_dir(%p, %p, %p, %ld, %p, %lu)\n", ns, node, cookie, *count, buffer, bufferSize); int32 _count = *count; status_t error = node->GetVolume()->ReadDir(node, cookie, buffer, bufferSize, _count, &_count); *count = _count; PRINT("netfs_read_dir() done: (%" B_PRIx32 ", %ld)\n", error, *count); #if DEBUG dirent* entry = buffer; for (int32 i = 0; i < *count; i++) { // R5's kernel vsprintf() doesn't seem to know `%.s', so // we need to work around. char name[B_FILE_NAME_LENGTH]; int nameLen = strnlen(entry->d_name, B_FILE_NAME_LENGTH - 1); strncpy(name, entry->d_name, nameLen); name[nameLen] = '\0'; PRINT(" entry: d_dev: %" B_PRIdDEV ", d_pdev: %" B_PRIdDEV ", d_ino: %" B_PRIdINO ", d_pino: %" B_PRIdINO ", d_reclen: %hu, d_name: `%s'\n", entry->d_dev, entry->d_pdev, entry->d_ino, entry->d_pino, entry->d_reclen, name); entry = (dirent*)((char*)entry + entry->d_reclen); } #endif return error; } // netfs_rewind_dir static int netfs_rewind_dir(void *ns, void *_node, void *cookie) { Node* node = (Node*)_node; PRINT("netfs_rewind_dir(%p, %p, %p)\n", ns, node, cookie); status_t error = node->GetVolume()->RewindDir(node, cookie); PRINT("netfs_rewind_dir() done: %" B_PRIx32 "\n", error); return error; } // netfs_walk static int netfs_walk(void *ns, void *_dir, const char *entryName, char **resolvedPath, vnode_id *vnid) { Node* dir = (Node*)_dir; PRINT("netfs_walk(%p, %p, `%s', %p, %p)\n", ns, dir, entryName, resolvedPath, vnid); status_t error = dir->GetVolume()->Walk(dir, entryName, resolvedPath, vnid); PRINT("netfs_walk() done: (%" B_PRIx32 ", `%s', %" B_PRIdINO ")\n", error, (resolvedPath ? *resolvedPath : NULL), *vnid); return error; } // #pragma mark - // #pragma mark ----- attributes ----- // netfs_open_attrdir static int netfs_open_attrdir(void *ns, void *_node, void **cookie) { Node* node = (Node*)_node; PRINT("netfs_open_attrdir(%p, %p)\n", ns, node); status_t error = node->GetVolume()->OpenAttrDir(node, cookie); PRINT("netfs_open_attrdir() done: (%" B_PRIx32 ", %p)\n", error, *cookie); return error; } // netfs_close_attrdir static int netfs_close_attrdir(void *ns, void *_node, void *cookie) { Node* node = (Node*)_node; PRINT("netfs_close_attrdir(%p, %p, %p)\n", ns, node, cookie); status_t error = node->GetVolume()->CloseAttrDir(node, cookie); PRINT("netfs_close_attrdir() done: (%" B_PRIx32 ")\n", error); return error; } // netfs_free_attrdir_cookie static int netfs_free_attrdir_cookie(void *ns, void *_node, void *cookie) { Node* node = (Node*)_node; PRINT("netfs_free_attrdir_cookie(%p, %p, %p)\n", ns, node, cookie); status_t error = node->GetVolume()->FreeAttrDirCookie(node, cookie); PRINT("netfs_free_attrdir_cookie() done: (%" B_PRIx32 ")\n", error); return error; } // netfs_read_attrdir static int netfs_read_attrdir(void *ns, void *_node, void *cookie, long *count, struct dirent *buffer, size_t bufferSize) { Node* node = (Node*)_node; PRINT("netfs_read_attrdir(%p, %p, %p, %ld, %p, %lu)\n", ns, node, cookie, *count, buffer, bufferSize); int32 _count = *count; status_t error = node->GetVolume()->ReadAttrDir(node, cookie, buffer, bufferSize, _count, &_count); *count = _count; PRINT("netfs_read_attrdir() done: (%" B_PRIx32 ", %ld)\n", error, *count); return error; } // netfs_rewind_attrdir static int netfs_rewind_attrdir(void *ns, void *_node, void *cookie) { Node* node = (Node*)_node; PRINT("netfs_rewind_attrdir(%p, %p, %p)\n", ns, node, cookie); status_t error = node->GetVolume()->RewindAttrDir(node, cookie); PRINT("netfs_rewind_attrdir() done: (%" B_PRIx32 ")\n", error); return error; } // netfs_read_attr static int netfs_read_attr(void *ns, void *_node, const char *name, int type, void *buffer, size_t *bufferSize, off_t pos) { Node* node = (Node*)_node; PRINT("netfs_read_attr(%p, %p, `%s', %d, %p, %lu, %" B_PRIdOFF ")\n", ns, node, name, type, buffer, *bufferSize, pos); status_t error = node->GetVolume()->ReadAttr(node, name, type, pos, buffer, *bufferSize, bufferSize); PRINT("netfs_read_attr() done: (%" B_PRIx32 ", %ld)\n", error, *bufferSize); return error; } // netfs_write_attr static int netfs_write_attr(void *ns, void *_node, const char *name, int type, const void *buffer, size_t *bufferSize, off_t pos) { Node* node = (Node*)_node; PRINT("netfs_write_attr(%p, %p, `%s', %d, %p, %lu, %" B_PRIdOFF ")\n", ns, node, name, type, buffer, *bufferSize, pos); status_t error = node->GetVolume()->WriteAttr(node, name, type, pos, buffer, *bufferSize, bufferSize); PRINT("netfs_write_attr() done: (%" B_PRIx32 ", %ld)\n", error, *bufferSize); return error; } // netfs_remove_attr static int netfs_remove_attr(void *ns, void *_node, const char *name) { Node* node = (Node*)_node; PRINT("netfs_remove_attr(%p, %p, `%s')\n", ns, node, name); status_t error = node->GetVolume()->RemoveAttr(node, name); PRINT("netfs_remove_attr() done: (%" B_PRIx32 ")\n", error); return error; } // netfs_rename_attr static int netfs_rename_attr(void *ns, void *_node, const char *oldName, const char *newName) { Node* node = (Node*)_node; PRINT("netfs_rename_attr(%p, %p, `%s', `%s')\n", ns, node, oldName, newName); status_t error = node->GetVolume()->RenameAttr(node, oldName, newName); PRINT("netfs_rename_attr() done: (%" B_PRIx32 ")\n", error); return error; } // netfs_stat_attr static int netfs_stat_attr(void *ns, void *_node, const char *name, struct attr_info *attrInfo) { Node* node = (Node*)_node; PRINT("netfs_stat_attr(%p, %p, `%s', %p)\n", ns, node, name, attrInfo); status_t error = node->GetVolume()->StatAttr(node, name, attrInfo); PRINT("netfs_stat_attr() done: (%" B_PRIx32 ")\n", error); return error; } // #pragma mark - // #pragma mark ----- queries ----- // netfs_open_query static int netfs_open_query(void *ns, const char *queryString, ulong flags, port_id port, long token, void **cookie) { VolumeManager* volumeManager = (VolumeManager*)ns; Volume* volume = volumeManager->GetRootVolume(); VolumePutter _(volume); PRINT("netfs_open_query(%p, `%s', %lu, %" B_PRId32 ", %ld, %p)\n", ns, queryString, flags, port, token, cookie); status_t error = B_BAD_VALUE; if (volume) { error = volume->OpenQuery(queryString, flags, port, token, (QueryIterator**)cookie); } PRINT("netfs_open_query() done: (%" B_PRIx32 ", %p)\n", error, *cookie); return error; } // netfs_close_query static int netfs_close_query(void *ns, void *cookie) { PRINT("netfs_close_query(%p, %p)\n", ns, cookie); status_t error = B_OK; // no-op: we don't use this hook PRINT("netfs_close_query() done: (%" B_PRIx32 ")\n", error); return error; } // netfs_free_query_cookie static int netfs_free_query_cookie(void *ns, void *node, void *cookie) { VolumeManager* volumeManager = (VolumeManager*)ns; QueryIterator* iterator = (QueryIterator*)cookie; PRINT("netfs_free_query_cookie(%p, %p)\n", ns, cookie); status_t error = B_OK; volumeManager->GetQueryManager()->PutIterator(iterator); PRINT("netfs_free_query_cookie() done: (%" B_PRIx32 ")\n", error); return error; } // netfs_read_query static int netfs_read_query(void *ns, void *cookie, long *count, struct dirent *buffer, size_t bufferSize) { VolumeManager* volumeManager = (VolumeManager*)ns; Volume* volume = volumeManager->GetRootVolume(); QueryIterator* iterator = (QueryIterator*)cookie; VolumePutter _(volume); PRINT("netfs_read_query(%p, %p, %ld, %p, %lu)\n", ns, cookie, *count, buffer, bufferSize); status_t error = B_BAD_VALUE; if (volume) { int32 _count = *count; error = volume->ReadQuery(iterator, buffer, bufferSize, _count, &_count); *count = _count; } PRINT("netfs_read_query() done: (%" B_PRIx32 ", %ld)\n", error, *count); return error; }