Page MenuHomeFreeBSD

D28605.id83732.diff
No OneTemporary

D28605.id83732.diff

Index: sys/fs/fuse/fuse_internal.c
===================================================================
--- sys/fs/fuse/fuse_internal.c
+++ sys/fs/fuse/fuse_internal.c
@@ -638,6 +638,7 @@
de = (struct dirent *)cookediov->base;
de->d_fileno = fudge->ino;
+ de->d_off = fudge->off;
de->d_reclen = bytesavail;
de->d_type = fudge->type;
de->d_namlen = fudge->namelen;
Index: tests/sys/fs/fusefs/Makefile
===================================================================
--- tests/sys/fs/fusefs/Makefile
+++ tests/sys/fs/fusefs/Makefile
@@ -71,6 +71,9 @@
MOUNT= ${SRCTOP}/sbin/mount
# Suppress warnings that GCC generates for the libc++ and gtest headers.
CXXWARNFLAGS.gcc+= -Wno-placement-new -Wno-attributes
+# Suppress Wcast-align for readdir.cc, because it is unavoidable when using
+# getdirentries.
+CXXWARNFLAGS.readdir.cc+= -Wno-cast-align
.if ${COMPILER_TYPE} == "gcc" && ${COMPILER_VERSION} >= 80000
CXXWARNFLAGS+= -Wno-class-memaccess
.endif
Index: tests/sys/fs/fusefs/readdir.cc
===================================================================
--- tests/sys/fs/fusefs/readdir.cc
+++ tests/sys/fs/fusefs/readdir.cc
@@ -62,6 +62,9 @@
}
};
+const char dot[] = ".";
+const char dotdot[] = "..";
+
/* FUSE_READDIR returns nothing but "." and ".." */
TEST_F(Readdir, dots)
{
@@ -72,8 +75,6 @@
struct dirent *de;
vector<struct dirent> ents(2);
vector<struct dirent> empty_ents(0);
- const char dot[] = ".";
- const char dotdot[] = "..";
expect_lookup(RELPATH, ino);
expect_opendir(ino);
@@ -98,11 +99,6 @@
de = readdir(dir);
ASSERT_NE(nullptr, de) << strerror(errno);
EXPECT_EQ(2ul, de->d_fileno);
- /*
- * fuse(4) doesn't actually set d_off, which is ok for now because
- * nothing uses it.
- */
- //EXPECT_EQ(2000, de->d_off);
EXPECT_EQ(DT_DIR, de->d_type);
EXPECT_EQ(sizeof(dotdot), de->d_namlen);
EXPECT_EQ(0, strcmp(dotdot, de->d_name));
@@ -111,7 +107,6 @@
de = readdir(dir);
ASSERT_NE(nullptr, de) << strerror(errno);
EXPECT_EQ(3ul, de->d_fileno);
- //EXPECT_EQ(3000, de->d_off);
EXPECT_EQ(DT_DIR, de->d_type);
EXPECT_EQ(sizeof(dot), de->d_namlen);
EXPECT_EQ(0, strcmp(dot, de->d_name));
@@ -153,8 +148,11 @@
leakdir(dir);
}
-/* getdirentries(2) can use a larger buffer size than readdir(3) */
-TEST_F(Readdir, getdirentries)
+/*
+ * getdirentries(2) can use a larger buffer size than readdir(3). It also has
+ * some additional non-standardized fields in the returned dirent.
+ */
+TEST_F(Readdir, getdirentries_empty)
{
const char FULLPATH[] = "mountpoint/some_dir";
const char RELPATH[] = "some_dir";
@@ -186,6 +184,60 @@
leak(fd);
}
+/*
+ * The dirent.d_off field can be used with lseek to position the directory so
+ * that getdirentries will return the subsequent dirent.
+ */
+TEST_F(Readdir, getdirentries_seek)
+{
+ const char FULLPATH[] = "mountpoint/some_dir";
+ const char RELPATH[] = "some_dir";
+ vector<struct dirent> ents0(2);
+ vector<struct dirent> ents1(1);
+ uint64_t ino = 42;
+ int fd;
+ char buf[8192];
+ struct dirent *de0, *de1;
+ ssize_t r;
+
+ expect_lookup(RELPATH, ino);
+ expect_opendir(ino);
+
+ ents0[0].d_fileno = 2;
+ ents0[0].d_off = 2000;
+ ents0[0].d_namlen = sizeof(dotdot);
+ ents0[0].d_type = DT_DIR;
+ strncpy(ents0[0].d_name, dotdot, ents0[0].d_namlen);
+ expect_readdir(ino, 0, ents0);
+ ents0[1].d_fileno = 3;
+ ents0[1].d_off = 3000;
+ ents0[1].d_namlen = sizeof(dot);
+ ents0[1].d_type = DT_DIR;
+ ents1[0].d_fileno = 3;
+ ents1[0].d_off = 3000;
+ ents1[0].d_namlen = sizeof(dot);
+ ents1[0].d_type = DT_DIR;
+ strncpy(ents1[0].d_name, dot, ents1[0].d_namlen);
+ expect_readdir(ino, 0, ents0);
+ expect_readdir(ino, 2000, ents1);
+
+ fd = open(FULLPATH, O_DIRECTORY);
+ ASSERT_LE(0, fd) << strerror(errno);
+ r = getdirentries(fd, buf, sizeof(buf), 0);
+ ASSERT_LT(0, r) << strerror(errno);
+ de0 = (struct dirent*)&buf[0];
+ ASSERT_EQ(2000, de0->d_off);
+ de1 = (struct dirent*)(&(buf[de0->d_reclen]));
+ ASSERT_EQ(3ul, de1->d_fileno);
+
+ r = lseek(fd, de0->d_off, SEEK_SET);
+ ASSERT_LE(0, r);
+ r = getdirentries(fd, buf, sizeof(buf), 0);
+ ASSERT_LT(0, r) << strerror(errno);
+ de0 = (struct dirent*)&buf[0];
+ ASSERT_EQ(3000, de0->d_off);
+}
+
/*
* Nothing bad should happen if getdirentries is called on two file descriptors
* which were concurrently open, but one has already been closed.

File Metadata

Mime Type
text/plain
Expires
Thu, May 1, 1:01 PM (18 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17881681
Default Alt Text
D28605.id83732.diff (4 KB)

Event Timeline