1 // 2 // Copyright (C) 2014 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 "shill/protobuf_lite_streams.h" 18 19 #include <fcntl.h> 20 #include <sys/types.h> 21 22 #include <base/files/file_util.h> 23 #include <base/posix/eintr_wrapper.h> 24 25 using google::protobuf::io::CopyingInputStream; 26 using google::protobuf::io::CopyingInputStreamAdaptor; 27 using std::string; 28 29 namespace shill { 30 31 CopyingInputStreamAdaptor* protobuf_lite_file_input_stream( 32 const string& file_path) { 33 int fd = HANDLE_EINTR(open(file_path.c_str(), O_RDONLY)); 34 if (fd == -1) { 35 PLOG(ERROR) << __func__ << ": " 36 << "Could not load protobuf file [" << file_path << "] "; 37 return nullptr; 38 } 39 40 auto* file_stream(new ProtobufLiteCopyingFileInputStream(fd)); 41 auto* adaptor(new CopyingInputStreamAdaptor( 42 static_cast<CopyingInputStream*>(file_stream))); 43 // Pass ownership of |file_stream|. 44 adaptor->SetOwnsCopyingStream(true); 45 return adaptor; 46 } 47 48 49 ProtobufLiteCopyingFileInputStream::ProtobufLiteCopyingFileInputStream(int fd) 50 : fd_(fd), 51 scoped_fd_closer_(fd_), 52 previous_seek_failed_(false) {} 53 54 ProtobufLiteCopyingFileInputStream::~ProtobufLiteCopyingFileInputStream() {} 55 56 int ProtobufLiteCopyingFileInputStream::Read(void* buffer, int size) { 57 return HANDLE_EINTR(read(fd_, buffer, size)); 58 } 59 60 int ProtobufLiteCopyingFileInputStream::Skip(int count) { 61 if (!previous_seek_failed_ && 62 lseek(fd_, count, SEEK_CUR) != static_cast<off_t>(-1)) { 63 // seek succeeded. 64 return count; 65 } 66 // Let's not attempt to seek again later. 67 previous_seek_failed_ = true; 68 return CopyingInputStream::Skip(count); 69 } 70 71 } // namespace shill 72