From 425ff8818dcc440e619e21a63287fb4882cd042f Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Tue, 25 Jul 2023 01:44:20 +0000 Subject: [PATCH] Add . and .. in NFS directory listings MC, for example, hangs with infinite listing retries without them --- src/nfs_conn.cpp | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/nfs_conn.cpp b/src/nfs_conn.cpp index 002e5644..9e3b276e 100644 --- a/src/nfs_conn.cpp +++ b/src/nfs_conn.cpp @@ -882,6 +882,27 @@ static int nfs3_link_proc(void *opaque, rpc_op_t *rop) return 0; } +static void fill_dir_entry(nfs_client_t *self, rpc_op_t *rop, + std::map::iterator dir_id_it, struct entryplus3 *entry, bool is_plus) +{ + if (dir_id_it == self->parent->dir_info.end()) + { + return; + } + entry->fileid = dir_id_it->second.id; + if (is_plus) + { + entry->name_attributes = (post_op_attr){ + .attributes_follow = 1, + .attributes = get_dir_attributes(self, dir_id_it->first), + }; + entry->name_handle = (post_op_fh3){ + .handle_follows = 1, + .handle = xdr_copy_string(rop->xdrs, "S"+base64_encode(sha256(dir_id_it->first))), + }; + } +} + static void nfs3_readdir_common(void *opaque, rpc_op_t *rop, bool is_plus) { nfs_client_t *self = (nfs_client_t*)opaque; @@ -959,17 +980,17 @@ static void nfs3_readdir_common(void *opaque, rpc_op_t *rop, bool is_plus) continue; std::string subname = dir_id_it->first.substr(prefix.size()); // for directories, fileid changes when the user restarts proxy - entries[subname].fileid = dir_id_it->second.id; - if (is_plus) + fill_dir_entry(self, rop, dir_id_it, &entries[subname], is_plus); + } + // Add . and .. + { + auto dir_id_it = self->parent->dir_info.find(dir); + fill_dir_entry(self, rop, dir_id_it, &entries["."], is_plus); + auto sl = dir.rfind("/"); + if (sl != std::string::npos) { - entries[subname].name_attributes = (post_op_attr){ - .attributes_follow = 1, - .attributes = get_dir_attributes(self, dir_id_it->first), - }; - entries[subname].name_handle = (post_op_fh3){ - .handle_follows = 1, - .handle = xdr_copy_string(rop->xdrs, "S"+base64_encode(sha256(dir_id_it->first))), - }; + auto dir_id_it = self->parent->dir_info.find(dir.substr(0, sl)); + fill_dir_entry(self, rop, dir_id_it, &entries[".."], is_plus); } } // Offset results by the continuation cookie (equal to index in the listing)