/ src / common / tests / file_utils.cc
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