file_utils.cc
1 // Copyright 2011 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 // file_utils.cc: Implement utility functions for file manipulation. 30 // See file_utils.h for details. 31 32 #ifdef HAVE_CONFIG_H 33 #include <config.h> // Must come first 34 #endif 35 36 #include <fcntl.h> 37 #include <stdio.h> 38 #include <string.h> 39 #include <sys/stat.h> 40 #include <unistd.h> 41 42 #include "common/linux/eintr_wrapper.h" 43 #include "common/tests/file_utils.h" 44 45 namespace google_breakpad { 46 47 bool CopyFile(const char* from_path, const char* to_path) { 48 int infile = HANDLE_EINTR(open(from_path, O_RDONLY)); 49 if (infile < 0) { 50 perror("open"); 51 return false; 52 } 53 54 int outfile = HANDLE_EINTR(creat(to_path, 0666)); 55 if (outfile < 0) { 56 perror("creat"); 57 if (IGNORE_EINTR(close(infile)) < 0) { 58 perror("close"); 59 } 60 return false; 61 } 62 63 char buffer[1024]; 64 bool result = true; 65 66 while (result) { 67 ssize_t bytes_read = HANDLE_EINTR(read(infile, buffer, sizeof(buffer))); 68 if (bytes_read < 0) { 69 perror("read"); 70 result = false; 71 break; 72 } 73 if (bytes_read == 0) 74 break; 75 ssize_t bytes_written_per_read = 0; 76 do { 77 ssize_t bytes_written_partial = HANDLE_EINTR(write( 78 outfile, 79 &buffer[bytes_written_per_read], 80 bytes_read - bytes_written_per_read)); 81 if (bytes_written_partial < 0) { 82 perror("write"); 83 result = false; 84 break; 85 } 86 bytes_written_per_read += bytes_written_partial; 87 } while (bytes_written_per_read < bytes_read); 88 } 89 90 if (IGNORE_EINTR(close(infile)) == -1) { 91 perror("close"); 92 result = false; 93 } 94 if (IGNORE_EINTR(close(outfile)) == -1) { 95 perror("close"); 96 result = false; 97 } 98 99 return result; 100 } 101 102 bool CopyFile(const std::string& from_path, const std::string& to_path) { 103 return CopyFile(from_path.c_str(), to_path.c_str()); 104 } 105 106 bool ReadFile(const char* path, void* buffer, ssize_t* buffer_size) { 107 int fd = HANDLE_EINTR(open(path, O_RDONLY)); 108 if (fd == -1) { 109 perror("open"); 110 return false; 111 } 112 113 bool ok = true; 114 if (buffer && buffer_size && *buffer_size > 0) { 115 memset(buffer, 0, sizeof(*buffer_size)); 116 *buffer_size = HANDLE_EINTR(read(fd, buffer, *buffer_size)); 117 if (*buffer_size == -1) { 118 perror("read"); 119 ok = false; 120 } 121 } 122 if (IGNORE_EINTR(close(fd)) == -1) { 123 perror("close"); 124 ok = false; 125 } 126 return ok; 127 } 128 129 bool WriteFile(const char* path, const void* buffer, size_t buffer_size) { 130 int fd = HANDLE_EINTR(open(path, O_CREAT | O_TRUNC | O_WRONLY, S_IRWXU)); 131 if (fd == -1) { 132 perror("open"); 133 return false; 134 } 135 136 bool ok = true; 137 if (buffer) { 138 size_t bytes_written_total = 0; 139 ssize_t bytes_written_partial = 0; 140 const char* data = reinterpret_cast<const char*>(buffer); 141 while (bytes_written_total < buffer_size) { 142 bytes_written_partial = 143 HANDLE_EINTR(write(fd, data + bytes_written_total, 144 buffer_size - bytes_written_total)); 145 if (bytes_written_partial < 0) { 146 perror("write"); 147 ok = false; 148 break; 149 } 150 bytes_written_total += bytes_written_partial; 151 } 152 } 153 if (IGNORE_EINTR(close(fd)) == -1) { 154 perror("close"); 155 ok = false; 156 } 157 return ok; 158 } 159 160 } // namespace google_breakpad