| 31 | namespace brpc { |
| 32 | |
| 33 | void DirService::default_method(::google::protobuf::RpcController* cntl_base, |
| 34 | const ::brpc::DirRequest*, |
| 35 | ::brpc::DirResponse*, |
| 36 | ::google::protobuf::Closure* done) { |
| 37 | ClosureGuard done_guard(done); |
| 38 | Controller *cntl = static_cast<Controller*>(cntl_base); |
| 39 | std::string open_path; |
| 40 | |
| 41 | const std::string& path_str = |
| 42 | cntl->http_request().unresolved_path(); |
| 43 | if (!path_str.empty()) { |
| 44 | open_path.reserve(path_str.size() + 2); |
| 45 | open_path.push_back('/'); |
| 46 | open_path.append(path_str); |
| 47 | } else { |
| 48 | open_path = "/"; |
| 49 | } |
| 50 | DIR* dir = opendir(open_path.c_str()); |
| 51 | if (NULL == dir) { |
| 52 | butil::fd_guard fd(open(open_path.c_str(), O_RDONLY)); |
| 53 | if (fd < 0) { |
| 54 | cntl->SetFailed(errno, "Cannot open `%s'", open_path.c_str()); |
| 55 | return; |
| 56 | } |
| 57 | butil::make_non_blocking(fd); |
| 58 | butil::make_close_on_exec(fd); |
| 59 | |
| 60 | butil::IOPortal read_portal; |
| 61 | size_t total_read = 0; |
| 62 | do { |
| 63 | const ssize_t nr = read_portal.append_from_file_descriptor( |
| 64 | fd, MAX_READ); |
| 65 | if (nr < 0) { |
| 66 | cntl->SetFailed(errno, "Cannot read `%s'", open_path.c_str()); |
| 67 | return; |
| 68 | } |
| 69 | if (nr == 0) { |
| 70 | break; |
| 71 | } |
| 72 | total_read += nr; |
| 73 | } while (total_read < MAX_READ); |
| 74 | butil::IOBuf& resp = cntl->response_attachment(); |
| 75 | resp.swap(read_portal); |
| 76 | if (total_read >= MAX_READ) { |
| 77 | std::ostringstream oss; |
| 78 | oss << " <" << lseek(fd, 0, SEEK_END) - total_read << " more bytes>"; |
| 79 | resp.append(oss.str()); |
| 80 | } |
| 81 | cntl->http_response().set_content_type("text/plain"); |
| 82 | } else { |
| 83 | const bool use_html = UseHTML(cntl->http_request()); |
| 84 | const butil::EndPoint* const html_addr = (use_html ? Path::LOCAL : NULL); |
| 85 | cntl->http_response().set_content_type( |
| 86 | use_html ? "text/html" : "text/plain"); |
| 87 | |
| 88 | std::vector<std::string> files; |
| 89 | files.reserve(32); |
| 90 | // readdir_r is marked as deprecated since glibc 2.24. |
nothing calls this directly
no test coverage detected