1 // Copyright 2009 Google LLC 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google LLC nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 #ifndef CLIENT_LINUX_MINIDUMP_WRITER_LINE_READER_H_ 30 #define CLIENT_LINUX_MINIDUMP_WRITER_LINE_READER_H_ 31 32 #include <stdint.h> 33 #include <assert.h> 34 #include <string.h> 35 36 #include "common/linux/linux_libc_support.h" 37 #include "third_party/lss/linux_syscall_support.h" 38 39 namespace google_breakpad { 40 41 // A class for reading a file, line by line, without using fopen/fgets or other 42 // functions which may allocate memory. 43 class LineReader { 44 public: LineReader(int fd)45 LineReader(int fd) 46 : fd_(fd), 47 hit_eof_(false), 48 buf_used_(0) { 49 } 50 51 // The maximum length of a line. 52 static const size_t kMaxLineLen = 512; 53 54 // Return the next line from the file. 55 // line: (output) a pointer to the start of the line. The line is NUL 56 // terminated. 57 // len: (output) the length of the line (not inc the NUL byte) 58 // 59 // Returns true iff successful (false on EOF). 60 // 61 // One must call |PopLine| after this function, otherwise you'll continue to 62 // get the same line over and over. GetNextLine(const char ** line,unsigned * len)63 bool GetNextLine(const char** line, unsigned* len) { 64 for (;;) { 65 if (buf_used_ == 0 && hit_eof_) 66 return false; 67 68 for (unsigned i = 0; i < buf_used_; ++i) { 69 if (buf_[i] == '\n' || buf_[i] == 0) { 70 buf_[i] = 0; 71 *len = i; 72 *line = buf_; 73 return true; 74 } 75 } 76 77 if (buf_used_ == sizeof(buf_)) { 78 // we scanned the whole buffer and didn't find an end-of-line marker. 79 // This line is too long to process. 80 return false; 81 } 82 83 // We didn't find any end-of-line terminators in the buffer. However, if 84 // this is the last line in the file it might not have one: 85 if (hit_eof_) { 86 assert(buf_used_); 87 // There's room for the NUL because of the buf_used_ == sizeof(buf_) 88 // check above. 89 buf_[buf_used_] = 0; 90 *len = buf_used_; 91 buf_used_ += 1; // since we appended the NUL. 92 *line = buf_; 93 return true; 94 } 95 96 // Otherwise, we should pull in more data from the file 97 const ssize_t n = sys_read(fd_, buf_ + buf_used_, 98 sizeof(buf_) - buf_used_); 99 if (n < 0) { 100 return false; 101 } else if (n == 0) { 102 hit_eof_ = true; 103 } else { 104 buf_used_ += n; 105 } 106 107 // At this point, we have either set the hit_eof_ flag, or we have more 108 // data to process... 109 } 110 } 111 PopLine(unsigned len)112 void PopLine(unsigned len) { 113 // len doesn't include the NUL byte at the end. 114 115 assert(buf_used_ >= len + 1); 116 buf_used_ -= len + 1; 117 my_memmove(buf_, buf_ + len + 1, buf_used_); 118 } 119 120 private: 121 const int fd_; 122 123 bool hit_eof_; 124 unsigned buf_used_; 125 char buf_[kMaxLineLen]; 126 }; 127 128 } // namespace google_breakpad 129 130 #endif // CLIENT_LINUX_MINIDUMP_WRITER_LINE_READER_H_ 131