FileWriter.cc 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright (C) 2011 Michael McMaster <michael@codesrc.com>
  2. //
  3. // This file is part of libzipper.
  4. //
  5. // libzipper is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // libzipper is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with libzipper. If not, see <http://www.gnu.org/licenses/>.
  17. #include "zipper.hh"
  18. #include "strerror.hh"
  19. #include <algorithm>
  20. #include <cassert>
  21. #include <sstream>
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. #include <fcntl.h>
  25. #include <unistd.h>
  26. #include <utime.h>
  27. #include <errno.h>
  28. using namespace zipper;
  29. class FileWriter::FileWriterImpl
  30. {
  31. public:
  32. FileWriterImpl(
  33. const std::string& filename,
  34. mode_t createPermissions,
  35. const timeval& modTime
  36. ) :
  37. m_filename(filename),
  38. m_modTime(modTime),
  39. m_fd(-1),
  40. m_closeOnExit(true),
  41. m_setModTimeOnExit(true)
  42. {
  43. m_fd =
  44. ::open(
  45. filename.c_str(),
  46. O_WRONLY | O_TRUNC | O_CREAT,
  47. createPermissions);
  48. if (m_fd < 0)
  49. {
  50. std::string errMsg(zipper::strerror(errno));
  51. std::stringstream message;
  52. message << "Could not open file \"" << filename << "\": " <<
  53. errMsg;
  54. throw IOException(message.str());
  55. }
  56. }
  57. FileWriterImpl(const std::string& filename, int fd, bool closeFd) :
  58. m_filename(filename),
  59. m_fd(fd),
  60. m_closeOnExit(closeFd),
  61. m_setModTimeOnExit(false)
  62. {
  63. }
  64. ~FileWriterImpl()
  65. {
  66. close();
  67. if (m_setModTimeOnExit)
  68. {
  69. struct timeval times[2];
  70. if (s_now.tv_sec == m_modTime.tv_sec)
  71. {
  72. gettimeofday(&times[0], NULL);
  73. times[1] = times[0];
  74. }
  75. else
  76. {
  77. times[0] = m_modTime;
  78. times[1] = m_modTime;
  79. }
  80. utimes(m_filename.c_str(), times);
  81. }
  82. }
  83. virtual void writeData(
  84. zsize_t offset, zsize_t bytes, const uint8_t* data
  85. ) const
  86. {
  87. assert(m_fd >= 0);
  88. zsize_t bytesWritten(0);
  89. while(bytesWritten < bytes)
  90. {
  91. ssize_t currentBytes(
  92. pwrite(
  93. m_fd,
  94. data + bytesWritten,
  95. bytes - bytesWritten,
  96. offset + bytesWritten)
  97. );
  98. if (currentBytes >= 0)
  99. {
  100. bytesWritten += static_cast<zsize_t>(currentBytes);
  101. }
  102. else if ((currentBytes < 0) && (errno != EINTR))
  103. {
  104. std::string errMsg(zipper::strerror(errno));
  105. throw IOException(errMsg);
  106. }
  107. }
  108. }
  109. zsize_t getSize() const
  110. {
  111. assert(m_fd >= 0);
  112. zsize_t result(lseek(m_fd, 0, SEEK_END));
  113. return result;
  114. }
  115. private:
  116. void close()
  117. {
  118. if ((m_fd >= 0) && m_closeOnExit)
  119. {
  120. ::close(m_fd);
  121. m_fd = -1;
  122. }
  123. }
  124. std::string m_filename;
  125. timeval m_modTime;
  126. int m_fd;
  127. bool m_closeOnExit;
  128. bool m_setModTimeOnExit;
  129. };
  130. FileWriter::FileWriter(
  131. const std::string& filename,
  132. mode_t createPermissions,
  133. const timeval& modTime) :
  134. m_impl(new FileWriterImpl(filename, createPermissions, modTime))
  135. {
  136. }
  137. FileWriter::FileWriter(const std::string& filename, int fd, bool closeFd) :
  138. m_impl(new FileWriterImpl(filename, fd, closeFd))
  139. {
  140. }
  141. FileWriter::~FileWriter()
  142. {
  143. delete m_impl;
  144. }
  145. void
  146. FileWriter::writeData(zsize_t offset, zsize_t bytes, const uint8_t* data)
  147. {
  148. m_impl->writeData(offset, bytes, data);
  149. }
  150. zsize_t
  151. FileWriter::getSize() const
  152. {
  153. return m_impl->getSize();
  154. }