am e5cabca5: Merge "implement missing seekdir and telldir"
* commit 'e5cabca516252addb5e305c8e1e0f35cafbcafbe': implement missing seekdir and telldir
This commit is contained in:
commit
1b6b274a4b
@ -43,6 +43,7 @@ struct DIR {
|
||||
int fd_;
|
||||
size_t available_bytes_;
|
||||
dirent* next_;
|
||||
long current_pos_;
|
||||
pthread_mutex_t mutex_;
|
||||
dirent buff_[15];
|
||||
};
|
||||
@ -55,6 +56,7 @@ static DIR* __allocate_DIR(int fd) {
|
||||
d->fd_ = fd;
|
||||
d->available_bytes_ = 0;
|
||||
d->next_ = NULL;
|
||||
d->current_pos_ = 0L;
|
||||
pthread_mutex_init(&d->mutex_, NULL);
|
||||
return d;
|
||||
}
|
||||
@ -100,6 +102,9 @@ static dirent* __readdir_locked(DIR* 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;
|
||||
}
|
||||
|
||||
@ -146,6 +151,20 @@ void rewinddir(DIR* d) {
|
||||
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) {
|
||||
|
@ -76,6 +76,8 @@ extern int readdir_r(DIR*, struct dirent*, struct dirent**);
|
||||
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**);
|
||||
|
@ -231,3 +231,50 @@ TEST(dirent, rewinddir) {
|
||||
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));
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ TEST(stdio, dprintf) {
|
||||
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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user