summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 9df7040)
raw | patch | inline | side by side (parent: 9df7040)
author | Yabin Cui <yabinc@google.com> | |
Fri, 7 Nov 2014 03:55:09 +0000 (19:55 -0800) | ||
committer | Yabin Cui <yabinc@google.com> | |
Fri, 7 Nov 2014 18:20:32 +0000 (10:20 -0800) |
libc/bionic/dirent.cpp | patch | blob | history | |
libc/include/dirent.h | patch | blob | history | |
tests/dirent_test.cpp | patch | blob | history | |
tests/stdio_test.cpp | patch | blob | history |
diff --git a/libc/bionic/dirent.cpp b/libc/bionic/dirent.cpp
index 5e1c7a5658bfea75e0a8fe8aa14abb8b3771ac4d..6d870978506d2272d00b83d0cbe64900c33ab13b 100644 (file)
--- a/libc/bionic/dirent.cpp
+++ b/libc/bionic/dirent.cpp
int fd_;
size_t available_bytes_;
dirent* next_;
+ long current_pos_;
pthread_mutex_t mutex_;
dirent buff_[15];
};
d->fd_ = fd;
d->available_bytes_ = 0;
d->next_ = NULL;
+ d->current_pos_ = 0L;
pthread_mutex_init(&d->mutex_, NULL);
return d;
}
dirent* entry = d->next_;
d->next_ = reinterpret_cast<dirent*>(reinterpret_cast<char*>(entry) + entry->d_reclen);
d->available_bytes_ -= entry->d_reclen;
+ // The directory entry offset uses 0, 1, 2 instead of real file offset,
+ // so the value range of long type is enough.
+ d->current_pos_ = static_cast<long>(entry->d_off);
return entry;
}
ScopedPthreadMutexLocker locker(&d->mutex_);
lseek(d->fd_, 0, SEEK_SET);
d->available_bytes_ = 0;
+ d->current_pos_ = 0L;
+}
+
+void seekdir(DIR* d, long offset) {
+ ScopedPthreadMutexLocker locker(&d->mutex_);
+ off_t ret = lseek(d->fd_, offset, SEEK_SET);
+ if (ret != -1L) {
+ d->available_bytes_ = 0;
+ d->current_pos_ = ret;
+ }
+}
+
+long telldir(DIR* d) {
+ return d->current_pos_;
}
int alphasort(const dirent** a, const dirent** b) {
diff --git a/libc/include/dirent.h b/libc/include/dirent.h
index a849a61f152d527ab585d2661f17aa7b28f5cdd8..820558a77e285be08733689a17a28e3512aef47a 100644 (file)
--- a/libc/include/dirent.h
+++ b/libc/include/dirent.h
extern int readdir64_r(DIR*, struct dirent64*, struct dirent64**);
extern int closedir(DIR*);
extern void rewinddir(DIR*);
+extern void seekdir(DIR*, long);
+extern long telldir(DIR*);
extern int dirfd(DIR*);
extern int alphasort(const struct dirent**, const struct dirent**);
extern int alphasort64(const struct dirent64**, const struct dirent64**);
diff --git a/tests/dirent_test.cpp b/tests/dirent_test.cpp
index 6aadb3768766f172e629019ad226a2481939300c..214dd78c803391239f29705d1a8c942bbc0ee4d6 100644 (file)
--- a/tests/dirent_test.cpp
+++ b/tests/dirent_test.cpp
ASSERT_EQ(pass1[i], pass2[i]);
}
}
+
+TEST(dirent, seekdir_telldir) {
+ DIR* d = opendir("/proc/self");
+ ASSERT_TRUE(d != NULL);
+ std::vector<long> offset_list;
+ std::vector<std::string> name_list;
+ dirent* e = NULL;
+
+ offset_list.push_back(telldir(d));
+ ASSERT_EQ(0L, offset_list.back());
+
+ while ((e = readdir(d)) != NULL) {
+ name_list.push_back(e->d_name);
+ offset_list.push_back(telldir(d));
+ // Make sure telldir() point to the next entry.
+ ASSERT_EQ(e->d_off, offset_list.back());
+ }
+
+ long end_offset = telldir(d);
+ // telldir() should not pass the end of the file.
+ ASSERT_EQ(offset_list.back(), end_offset);
+ offset_list.pop_back();
+
+ for (size_t i = 0; i < offset_list.size(); ++i) {
+ seekdir(d, offset_list[i]);
+ ASSERT_EQ(offset_list[i], telldir(d));
+ e = readdir(d);
+ ASSERT_TRUE(e != NULL);
+ ASSERT_STREQ(name_list[i].c_str(), e->d_name);
+ }
+ for (int i = static_cast<int>(offset_list.size()) - 1; i >= 0; --i) {
+ seekdir(d, offset_list[i]);
+ ASSERT_EQ(offset_list[i], telldir(d));
+ e = readdir(d);
+ ASSERT_TRUE(e != NULL);
+ ASSERT_STREQ(name_list[i].c_str(), e->d_name);
+ }
+
+ // Seek to the end, read NULL.
+ seekdir(d, end_offset);
+ ASSERT_EQ(end_offset, telldir(d));
+ errno = 0;
+ ASSERT_EQ(NULL, readdir(d));
+ ASSERT_EQ(0, errno);
+
+ ASSERT_EQ(0, closedir(d));
+}
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 549792efbf3f7bc866a4a135f7bdae22b9a1de72..6be372c52cf6a59d328a7dfdfea6cb4f807bf31f 100644 (file)
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
int rc = dprintf(tf.fd, "hello\n");
ASSERT_EQ(rc, 6);
- lseek(tf.fd, SEEK_SET, 0);
+ lseek(tf.fd, 0, SEEK_SET);
FILE* tfile = fdopen(tf.fd, "r");
ASSERT_TRUE(tfile != NULL);