1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <sstream>
18 #include <string>
19 #include <thread>
20 #include <vector>
21
22 #include "common/libs/fs/shared_buf.h"
23 #include "common/libs/fs/shared_fd.h"
24
25 namespace cuttlefish {
26
27 namespace {
28
29 const size_t BUFF_SIZE = 1 << 14;
30
31 } // namespace
32
WriteAll(SharedFD fd,const char * buf,size_t size)33 ssize_t WriteAll(SharedFD fd, const char* buf, size_t size) {
34 size_t total_written = 0;
35 ssize_t written = 0;
36 do {
37 written = fd->Write((void*)&(buf[total_written]), size - total_written);
38 if (written <= 0) {
39 if (written < 0) {
40 errno = fd->GetErrno();
41 return written;
42 }
43 return total_written;
44 }
45 total_written += written;
46 } while (total_written < size);
47 return total_written;
48 }
49
ReadExact(SharedFD fd,char * buf,size_t size)50 ssize_t ReadExact(SharedFD fd, char* buf, size_t size) {
51 size_t total_read = 0;
52 ssize_t read = 0;
53 do {
54 read = fd->Read((void*)&(buf[total_read]), size - total_read);
55 if (read <= 0) {
56 if (read < 0) {
57 errno = fd->GetErrno();
58 return read;
59 }
60 return total_read;
61 }
62 total_read += read;
63 } while (total_read < size);
64 return total_read;
65 }
66
ReadAll(SharedFD fd,std::string * buf)67 ssize_t ReadAll(SharedFD fd, std::string* buf) {
68 char buff[BUFF_SIZE];
69 std::stringstream ss;
70 ssize_t read;
71 while ((read = fd->Read(buff, BUFF_SIZE - 1)) > 0) {
72 // this is necessary to avoid problems with having a '\0' in the middle of the buffer
73 ss << std::string(buff, read);
74 }
75 if (read < 0) {
76 errno = fd->GetErrno();
77 return read;
78 }
79 *buf = ss.str();
80 return buf->size();
81 }
82
ReadExact(SharedFD fd,std::string * buf)83 ssize_t ReadExact(SharedFD fd, std::string* buf) {
84 return ReadExact(fd, buf->data(), buf->size());
85 }
86
ReadExact(SharedFD fd,std::vector<char> * buf)87 ssize_t ReadExact(SharedFD fd, std::vector<char>* buf) {
88 return ReadExact(fd, buf->data(), buf->size());
89 }
90
WriteAll(SharedFD fd,std::string_view buf)91 ssize_t WriteAll(SharedFD fd, std::string_view buf) {
92 return WriteAll(fd, buf.data(), buf.size());
93 }
94
WriteAll(SharedFD fd,const std::vector<char> & buf)95 ssize_t WriteAll(SharedFD fd, const std::vector<char>& buf) {
96 return WriteAll(fd, buf.data(), buf.size());
97 }
98
SendAll(SharedFD sock,std::string_view msg)99 bool SendAll(SharedFD sock, std::string_view msg) {
100 ssize_t total_written{};
101 if (!sock->IsOpen()) {
102 return false;
103 }
104 while (total_written < static_cast<ssize_t>(msg.size())) {
105 auto just_written = sock->Send(msg.data() + total_written,
106 msg.size() - total_written, MSG_NOSIGNAL);
107 if (just_written <= 0) {
108 return false;
109 }
110 total_written += just_written;
111 }
112 return true;
113 }
114
RecvAll(SharedFD sock,const size_t count)115 std::string RecvAll(SharedFD sock, const size_t count) {
116 size_t total_read{};
117 if (!sock->IsOpen()) {
118 return {};
119 }
120 std::unique_ptr<char[]> data(new char[count]);
121 while (total_read < count) {
122 auto just_read = sock->Read(data.get() + total_read, count - total_read);
123 if (just_read <= 0) {
124 return {};
125 }
126 total_read += just_read;
127 }
128 return {data.get(), count};
129 }
130
131 } // namespace cuttlefish
132