Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : // Copyright (c) 2010 The Chromium Authors. All rights reserved.
4 : // Use of this source code is governed by a BSD-style license that can be
5 : // found in the LICENSE file.
6 :
7 : #ifndef BASE_DIR_READER_LINUX_H_
8 : #define BASE_DIR_READER_LINUX_H_
9 : #pragma once
10 :
11 : #include <errno.h>
12 : #include <fcntl.h>
13 : #include <stdint.h>
14 : #include <sys/syscall.h>
15 : #include <unistd.h>
16 :
17 : #include "base/logging.h"
18 : #include "base/eintr_wrapper.h"
19 :
20 : // See the comments in dir_reader_posix.h about this.
21 :
22 : namespace base {
23 :
24 : struct linux_dirent {
25 : uint64_t d_ino;
26 : int64_t d_off;
27 : unsigned short d_reclen;
28 : unsigned char d_type;
29 : char d_name[0];
30 : };
31 :
32 : class DirReaderLinux {
33 : public:
34 0 : explicit DirReaderLinux(const char* directory_path)
35 0 : : fd_(open(directory_path, O_RDONLY | O_DIRECTORY)),
36 : offset_(0),
37 0 : size_(0) {
38 0 : memset(buf_, 0, sizeof(buf_));
39 0 : }
40 :
41 0 : ~DirReaderLinux() {
42 0 : if (fd_ >= 0) {
43 0 : if (HANDLE_EINTR(close(fd_)))
44 0 : DLOG(ERROR) << "Failed to close directory handle";
45 : }
46 0 : }
47 :
48 0 : bool IsValid() const {
49 0 : return fd_ >= 0;
50 : }
51 :
52 : // Move to the next entry returning false if the iteration is complete.
53 0 : bool Next() {
54 0 : if (size_) {
55 0 : linux_dirent* dirent = reinterpret_cast<linux_dirent*>(&buf_[offset_]);
56 0 : offset_ += dirent->d_reclen;
57 : }
58 :
59 0 : if (offset_ != size_)
60 0 : return true;
61 :
62 0 : const int r = syscall(__NR_getdents64, fd_, buf_, sizeof(buf_));
63 0 : if (r == 0)
64 0 : return false;
65 0 : if (r == -1) {
66 0 : DLOG(ERROR) << "getdents64 returned an error: " << errno;
67 0 : return false;
68 : }
69 0 : size_ = r;
70 0 : offset_ = 0;
71 0 : return true;
72 : }
73 :
74 0 : const char* name() const {
75 0 : if (!size_)
76 0 : return NULL;
77 :
78 : const linux_dirent* dirent =
79 0 : reinterpret_cast<const linux_dirent*>(&buf_[offset_]);
80 0 : return dirent->d_name;
81 : }
82 :
83 0 : int fd() const {
84 0 : return fd_;
85 : }
86 :
87 : static bool IsFallback() {
88 : return false;
89 : }
90 :
91 : private:
92 : const int fd_;
93 : unsigned char buf_[512];
94 : size_t offset_, size_;
95 :
96 : DISALLOW_COPY_AND_ASSIGN(DirReaderLinux);
97 : };
98 :
99 : } // namespace base
100 :
101 : #endif // BASE_DIR_READER_LINUX_H_
|