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