*/
typedef bool (*rgw_readdir_cb)(const char *name, void *arg, uint64_t offset);
+#define RGW_READDIR_FLAG_NONE 0x0000
+#define RGW_READDIR_FLAG_DOTDOT 0x0001 /* send dot names */
+
int rgw_readdir(struct rgw_fs *rgw_fs,
struct rgw_file_handle *parent_fh, uint64_t *offset,
- rgw_readdir_cb rcb, void *cb_arg, bool *eof);
+ rgw_readdir_cb rcb, void *cb_arg, bool *eof,
+ uint32_t flags);
/* XXX (get|set)attr mask bits */
#define RGW_SETATTR_MODE 1
} /* RGWFileHandle::reclaim */
int RGWFileHandle::readdir(rgw_readdir_cb rcb, void *cb_arg, uint64_t *offset,
- bool *eof)
+ bool *eof, uint32_t flags)
{
using event = RGWLibFS::event;
int rc = 0;
(void) clock_gettime(CLOCK_MONOTONIC_COARSE, &now); /* !LOCKED */
+ if (flags & RGW_READDIR_FLAG_DOTDOT) {
+ /* send '.' and '..' with their NFS-defined offsets */
+ rcb(".", cb_arg, 1);
+ rcb("..", cb_arg, 2);
+ }
+
if (is_root()) {
RGWListBucketsRequest req(cct, fs->get_user(), this, rcb, cb_arg,
offset);
int rgw_readdir(struct rgw_fs *rgw_fs,
struct rgw_file_handle *parent_fh, uint64_t *offset,
- rgw_readdir_cb rcb, void *cb_arg, bool *eof)
+ rgw_readdir_cb rcb, void *cb_arg, bool *eof,
+ uint32_t flags)
{
RGWFileHandle* parent = get_rgwfh(parent_fh);
if (! parent) {
/* bad parent */
return -EINVAL;
}
- int rc = parent->readdir(rcb, cb_arg, offset, eof);
+ int rc = parent->readdir(rcb, cb_arg, offset, eof, flags);
return -rc;
}
return EPERM;
}
- int readdir(rgw_readdir_cb rcb, void *cb_arg, uint64_t *offset, bool *eof);
+ int readdir(rgw_readdir_cb rcb, void *cb_arg, uint64_t *offset, bool *eof,
+ uint32_t flags);
int write(uint64_t off, size_t len, size_t *nbytes, void *buffer);
int write_finish();
int close();
bool eof = false;
uint64_t offset = 0;
- int ret = rgw_readdir(fs, fs->root_fh, &offset, r1_cb, &fids1, &eof);
+ int ret = rgw_readdir(fs, fs->root_fh, &offset, r1_cb, &fids1, &eof,
+ RGW_READDIR_FLAG_NONE);
for (auto& fid : fids1) {
std::cout << "fname: " << get<0>(fid) << " fid: " << get<1>(fid)
<< std::endl;
bool eof = false;
uint64_t offset = 0;
- int ret = rgw_readdir(fs, bucket_fh, &offset, r2_cb, &obj_vector, &eof);
+ int ret = rgw_readdir(fs, bucket_fh, &offset, r2_cb, &obj_vector, &eof,
+ RGW_READDIR_FLAG_NONE);
for (auto& obj : obj_vector) {
std::cout << "fname: " << get<0>(obj) << " fid: " << get<1>(obj)
<< std::endl;
bool eof = false;
uint64_t offset = 0;
int ret = rgw_readdir(fs, bucket_fh, &offset, r2_cb, &fids,
- &eof);
+ &eof, RGW_READDIR_FLAG_NONE);
for (auto& fid : fids) {
std::cout << "fname: " << get<0>(fid) << " fid: " << get<1>(fid)
<< std::endl;
<< " dir=" << rgw_fh->full_object_name()
<< " called back name=" << name
<< dendl;
- obj_stack.push(
- obj_rec{name, nullptr, parent_fh, nullptr});
+ string name_str{name};
+ if (! ((name_str == ".") ||
+ (name_str == ".."))) {
+ obj_stack.push(
+ obj_rec{std::move(name_str), nullptr, parent_fh, nullptr});
+ }
return true; /* XXX */
}
}
<< " object_name: " << elt.rgw_fh->object_name()
<< " full_name: " << elt.rgw_fh->full_object_name()
<< dendl;
- rc = rgw_readdir(fs, elt.fh, &offset, r1_cb, elt.fh, &eof);
+ rc = rgw_readdir(fs, elt.fh, &offset, r1_cb, elt.fh, &eof,
+ RGW_READDIR_FLAG_DOTDOT);
elt.state.readdir = true;
ASSERT_EQ(rc, 0);
// ASSERT_TRUE(eof); // XXXX working incorrectly w/single readdir
<< " iv count=" << dvec.count
<< " called back name=" << name
<< dendl;
- dvec.obj_names.push_back(dirent_t{name, offset});
+ string name_str{name};
+ if (! ((name_str == ".") ||
+ (name_str == ".."))) {
+ dvec.obj_names.push_back(dirent_t{std::move(name_str), offset});
+ }
return true; /* XXX */
}
}
do {
ASSERT_TRUE(dvec.count <= max_iterations);
- int ret = rgw_readdir(fs, marker_fh, &offset, r2_cb, &dvec, &eof);
+ int ret = rgw_readdir(fs, marker_fh, &offset, r2_cb, &dvec, &eof,
+ RGW_READDIR_FLAG_DOTDOT);
ASSERT_EQ(ret, 0);
ASSERT_EQ(offset, get<1>(dvec.obj_names.back())); // cookie check
++dvec.count;