libzypp 17.32.5
zerocopystreams.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\----------------------------------------------------------------------/
9*
10* Some versions of protobuf lite do not export the simple zero copy streams,
11* so for those we copied them from upstream.
12*/
13
14#include "zerocopystreams.h"
15
16#ifdef PROTOBUFLITE_HAS_NO_ZEROCOPYSTREAM
17
18// Protocol Buffers - Google's data interchange format
19// Copyright 2008 Google Inc. All rights reserved.
20// https://developers.google.com/protocol-buffers/
21//
22// Redistribution and use in source and binary forms, with or without
23// modification, are permitted provided that the following conditions are
24// met:
25//
26// * Redistributions of source code must retain the above copyright
27// notice, this list of conditions and the following disclaimer.
28// * Redistributions in binary form must reproduce the above
29// copyright notice, this list of conditions and the following disclaimer
30// in the documentation and/or other materials provided with the
31// distribution.
32// * Neither the name of Google Inc. nor the names of its
33// contributors may be used to endorse or promote products derived from
34// this software without specific prior written permission.
35//
36// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
37// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
39// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
40// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
43// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
48// Author: kenton@google.com (Kenton Varda)
49// Based on original Protocol Buffers design by
50// Sanjay Ghemawat, Jeff Dean, and others.
51
52#include <unistd.h>
53#include <sys/types.h>
54#include <sys/stat.h>
55#include <fcntl.h>
56#include <errno.h>
57#include <iostream>
58#include <algorithm>
59#include <google/protobuf/io/zero_copy_stream_impl.h>
60#include <google/protobuf/stubs/common.h>
61#include <google/protobuf/stubs/logging.h>
62#include <google/protobuf/stubs/stl_util.h>
63
64namespace zyppng {
65
66namespace {
67
68// EINTR sucks.
69int close_no_eintr(int fd) {
70 int result;
71 do {
72 result = close(fd);
73 } while (result < 0 && errno == EINTR);
74 return result;
75}
76
77} // namespace
78
79
80// ===================================================================
81
82FileInputStream::FileInputStream(int file_descriptor, int block_size)
83 : copying_input_(file_descriptor),
84 impl_(&copying_input_, block_size) {
85}
86
87bool FileInputStream::Close() {
88 return copying_input_.Close();
89}
90
91bool FileInputStream::Next(const void** data, int* size) {
92 return impl_.Next(data, size);
93}
94
95void FileInputStream::BackUp(int count) {
96 impl_.BackUp(count);
97}
98
99bool FileInputStream::Skip(int count) {
100 return impl_.Skip(count);
101}
102
103google::protobuf::int64 FileInputStream::ByteCount() const {
104 return impl_.ByteCount();
105}
106
107FileInputStream::CopyingFileInputStream::CopyingFileInputStream(
108 int file_descriptor)
109 : file_(file_descriptor),
110 close_on_delete_(false),
111 is_closed_(false),
112 errno_(0),
113 previous_seek_failed_(false) {
114}
115
116FileInputStream::CopyingFileInputStream::~CopyingFileInputStream() {
117 if (close_on_delete_) {
118 if (!Close()) {
119 GOOGLE_LOG(ERROR) << "close() failed: " << strerror(errno_);
120 }
121 }
122}
123
124bool FileInputStream::CopyingFileInputStream::Close() {
125 GOOGLE_CHECK(!is_closed_);
126
127 is_closed_ = true;
128 if (close_no_eintr(file_) != 0) {
129 // The docs on close() do not specify whether a file descriptor is still
130 // open after close() fails with EIO. However, the glibc source code
131 // seems to indicate that it is not.
132 errno_ = errno;
133 return false;
134 }
135
136 return true;
137}
138
139int FileInputStream::CopyingFileInputStream::Read(void* buffer, int size) {
140 GOOGLE_CHECK(!is_closed_);
141
142 int result;
143 do {
144 result = read(file_, buffer, size);
145 } while (result < 0 && errno == EINTR);
146
147 if (result < 0) {
148 // Read error (not EOF).
149 errno_ = errno;
150 }
151
152 return result;
153}
154
155int FileInputStream::CopyingFileInputStream::Skip(int count) {
156 GOOGLE_CHECK(!is_closed_);
157
158 if (!previous_seek_failed_ &&
159 lseek(file_, count, SEEK_CUR) != (off_t)-1) {
160 // Seek succeeded.
161 return count;
162 } else {
163 // Failed to seek.
164
165 // Note to self: Don't seek again. This file descriptor doesn't
166 // support it.
167 previous_seek_failed_ = true;
168
169 // Use the default implementation.
170 return google::protobuf::io::CopyingInputStream::Skip(count);
171 }
172}
173
174// ===================================================================
175
176FileOutputStream::FileOutputStream(int file_descriptor, int block_size)
177 : copying_output_(file_descriptor),
178 impl_(&copying_output_, block_size) {
179}
180
181FileOutputStream::~FileOutputStream() {
182 impl_.Flush();
183}
184
185bool FileOutputStream::Close() {
186 bool flush_succeeded = impl_.Flush();
187 return copying_output_.Close() && flush_succeeded;
188}
189
190bool FileOutputStream::Flush() {
191 return impl_.Flush();
192}
193
194bool FileOutputStream::Next(void** data, int* size) {
195 return impl_.Next(data, size);
196}
197
198void FileOutputStream::BackUp(int count) {
199 impl_.BackUp(count);
200}
201
202google::protobuf::int64 FileOutputStream::ByteCount() const {
203 return impl_.ByteCount();
204}
205
206FileOutputStream::CopyingFileOutputStream::CopyingFileOutputStream(
207 int file_descriptor)
208 : file_(file_descriptor),
209 close_on_delete_(false),
210 is_closed_(false),
211 errno_(0) {
212}
213
214FileOutputStream::CopyingFileOutputStream::~CopyingFileOutputStream() {
215 if (close_on_delete_) {
216 if (!Close()) {
217 GOOGLE_LOG(ERROR) << "close() failed: " << strerror(errno_);
218 }
219 }
220}
221
222bool FileOutputStream::CopyingFileOutputStream::Close() {
223 GOOGLE_CHECK(!is_closed_);
224
225 is_closed_ = true;
226 if (close_no_eintr(file_) != 0) {
227 // The docs on close() do not specify whether a file descriptor is still
228 // open after close() fails with EIO. However, the glibc source code
229 // seems to indicate that it is not.
230 errno_ = errno;
231 return false;
232 }
233
234 return true;
235}
236
237bool FileOutputStream::CopyingFileOutputStream::Write(
238 const void* buffer, int size) {
239 GOOGLE_CHECK(!is_closed_);
240 int total_written = 0;
241
242 const google::protobuf::uint8* buffer_base = reinterpret_cast<const google::protobuf::uint8*>(buffer);
243
244 while (total_written < size) {
245 int bytes;
246 do {
247 bytes = write(file_, buffer_base + total_written, size - total_written);
248 } while (bytes < 0 && errno == EINTR);
249
250 if (bytes <= 0) {
251 // Write error.
252
253 // FIXME(kenton): According to the man page, if write() returns zero,
254 // there was no error; write() simply did not write anything. It's
255 // unclear under what circumstances this might happen, but presumably
256 // errno won't be set in this case. I am confused as to how such an
257 // event should be handled. For now I'm treating it as an error, since
258 // retrying seems like it could lead to an infinite loop. I suspect
259 // this never actually happens anyway.
260
261 if (bytes < 0) {
262 errno_ = errno;
263 }
264 return false;
265 }
266 total_written += bytes;
267 }
268
269 return true;
270}
271
272// ===================================================================
273
274} // namespace
275
276#endif
std::map< std::string, std::string > read(const Pathname &_path)
Read sysconfig file path_r and return (key,valye) pairs.
Definition sysconfig.cc:34
bool write(const Pathname &path_r, const std::string &key_r, const std::string &val_r, const std::string &newcomment_r)
Add or change a value in sysconfig file path_r.
Definition sysconfig.cc:80