File_VX.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. //
  2. // File_VX.cpp
  3. //
  4. // $Id: //poco/1.4/Foundation/src/File_VX.cpp#1 $
  5. //
  6. // Library: Foundation
  7. // Package: Filesystem
  8. // Module: File
  9. //
  10. // Copyright (c) 2004-2011, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #include "Poco/File_VX.h"
  16. #include "Poco/Buffer.h"
  17. #include "Poco/Exception.h"
  18. #include <algorithm>
  19. #include <sys/stat.h>
  20. #include <sys/types.h>
  21. #include <fcntl.h>
  22. #include <errno.h>
  23. #include <unistd.h>
  24. #include <stdio.h>
  25. #include <utime.h>
  26. #include <cstring>
  27. namespace Poco {
  28. FileImpl::FileImpl()
  29. {
  30. }
  31. FileImpl::FileImpl(const std::string& path): _path(path)
  32. {
  33. std::string::size_type n = _path.size();
  34. if (n > 1 && _path[n - 1] == '/')
  35. _path.resize(n - 1);
  36. }
  37. FileImpl::~FileImpl()
  38. {
  39. }
  40. void FileImpl::swapImpl(FileImpl& file)
  41. {
  42. std::swap(_path, file._path);
  43. }
  44. void FileImpl::setPathImpl(const std::string& path)
  45. {
  46. _path = path;
  47. std::string::size_type n = _path.size();
  48. if (n > 1 && _path[n - 1] == '/')
  49. _path.resize(n - 1);
  50. }
  51. bool FileImpl::existsImpl() const
  52. {
  53. poco_assert (!_path.empty());
  54. struct stat st;
  55. return stat(const_cast<char*>(_path.c_str()), &st) == 0;
  56. }
  57. bool FileImpl::canReadImpl() const
  58. {
  59. poco_assert (!_path.empty());
  60. return true;
  61. }
  62. bool FileImpl::canWriteImpl() const
  63. {
  64. poco_assert (!_path.empty());
  65. return true;
  66. }
  67. bool FileImpl::canExecuteImpl() const
  68. {
  69. return false;
  70. }
  71. bool FileImpl::isFileImpl() const
  72. {
  73. poco_assert (!_path.empty());
  74. struct stat st;
  75. if (stat(const_cast<char*>(_path.c_str()), &st) == 0)
  76. return S_ISREG(st.st_mode);
  77. else
  78. handleLastErrorImpl(_path);
  79. return false;
  80. }
  81. bool FileImpl::isDirectoryImpl() const
  82. {
  83. poco_assert (!_path.empty());
  84. struct stat st;
  85. if (stat(const_cast<char*>(_path.c_str()), &st) == 0)
  86. return S_ISDIR(st.st_mode);
  87. else
  88. handleLastErrorImpl(_path);
  89. return false;
  90. }
  91. bool FileImpl::isLinkImpl() const
  92. {
  93. return false;
  94. }
  95. bool FileImpl::isDeviceImpl() const
  96. {
  97. poco_assert (!_path.empty());
  98. struct stat st;
  99. if (stat(const_cast<char*>(_path.c_str()), &st) == 0)
  100. return S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode);
  101. else
  102. handleLastErrorImpl(_path);
  103. return false;
  104. }
  105. bool FileImpl::isHiddenImpl() const
  106. {
  107. poco_assert (!_path.empty());
  108. Path p(_path);
  109. p.makeFile();
  110. return p.getFileName()[0] == '.';
  111. }
  112. Timestamp FileImpl::createdImpl() const
  113. {
  114. poco_assert (!_path.empty());
  115. struct stat st;
  116. if (stat(const_cast<char*>(_path.c_str()), &st) == 0)
  117. return Timestamp::fromEpochTime(st.st_ctime);
  118. else
  119. handleLastErrorImpl(_path);
  120. return 0;
  121. }
  122. Timestamp FileImpl::getLastModifiedImpl() const
  123. {
  124. poco_assert (!_path.empty());
  125. struct stat st;
  126. if (stat(const_cast<char*>(_path.c_str()), &st) == 0)
  127. return Timestamp::fromEpochTime(st.st_mtime);
  128. else
  129. handleLastErrorImpl(_path);
  130. return 0;
  131. }
  132. void FileImpl::setLastModifiedImpl(const Timestamp& ts)
  133. {
  134. poco_assert (!_path.empty());
  135. struct utimbuf tb;
  136. tb.actime = ts.epochTime();
  137. tb.modtime = ts.epochTime();
  138. if (utime(const_cast<char*>(_path.c_str()), &tb) != 0)
  139. handleLastErrorImpl(_path);
  140. }
  141. FileImpl::FileSizeImpl FileImpl::getSizeImpl() const
  142. {
  143. poco_assert (!_path.empty());
  144. struct stat st;
  145. if (stat(const_cast<char*>(_path.c_str()), &st) == 0)
  146. return st.st_size;
  147. else
  148. handleLastErrorImpl(_path);
  149. return 0;
  150. }
  151. void FileImpl::setSizeImpl(FileSizeImpl size)
  152. {
  153. poco_assert (!_path.empty());
  154. int fd = open(_path.c_str(), O_WRONLY, S_IRWXU);
  155. if (fd != -1)
  156. {
  157. try
  158. {
  159. if (ftruncate(fd, size) != 0)
  160. handleLastErrorImpl(_path);
  161. }
  162. catch (...)
  163. {
  164. close(fd);
  165. throw;
  166. }
  167. }
  168. }
  169. void FileImpl::setWriteableImpl(bool flag)
  170. {
  171. poco_assert (!_path.empty());
  172. }
  173. void FileImpl::setExecutableImpl(bool flag)
  174. {
  175. poco_assert (!_path.empty());
  176. }
  177. void FileImpl::copyToImpl(const std::string& path) const
  178. {
  179. poco_assert (!_path.empty());
  180. int sd = open(_path.c_str(), O_RDONLY, 0);
  181. if (sd == -1) handleLastErrorImpl(_path);
  182. struct stat st;
  183. if (fstat(sd, &st) != 0)
  184. {
  185. close(sd);
  186. handleLastErrorImpl(_path);
  187. }
  188. const long blockSize = st.st_blksize;
  189. int dd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, st.st_mode & S_IRWXU);
  190. if (dd == -1)
  191. {
  192. close(sd);
  193. handleLastErrorImpl(path);
  194. }
  195. Buffer<char> buffer(blockSize);
  196. try
  197. {
  198. int n;
  199. while ((n = read(sd, buffer.begin(), blockSize)) > 0)
  200. {
  201. if (write(dd, buffer.begin(), n) != n)
  202. handleLastErrorImpl(path);
  203. }
  204. if (n < 0)
  205. handleLastErrorImpl(_path);
  206. }
  207. catch (...)
  208. {
  209. close(sd);
  210. close(dd);
  211. throw;
  212. }
  213. close(sd);
  214. close(dd);
  215. }
  216. void FileImpl::renameToImpl(const std::string& path)
  217. {
  218. poco_assert (!_path.empty());
  219. if (rename(_path.c_str(), path.c_str()) != 0)
  220. handleLastErrorImpl(_path);
  221. }
  222. void FileImpl::removeImpl()
  223. {
  224. poco_assert (!_path.empty());
  225. int rc;
  226. if (!isLinkImpl() && isDirectoryImpl())
  227. rc = rmdir(_path.c_str());
  228. else
  229. rc = unlink(const_cast<char*>(_path.c_str()));
  230. if (rc) handleLastErrorImpl(_path);
  231. }
  232. bool FileImpl::createFileImpl()
  233. {
  234. poco_assert (!_path.empty());
  235. int n = open(_path.c_str(), O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
  236. if (n != -1)
  237. {
  238. close(n);
  239. return true;
  240. }
  241. if (n == -1 && errno == EEXIST)
  242. return false;
  243. else
  244. handleLastErrorImpl(_path);
  245. return false;
  246. }
  247. bool FileImpl::createDirectoryImpl()
  248. {
  249. poco_assert (!_path.empty());
  250. if (existsImpl() && isDirectoryImpl())
  251. return false;
  252. if (mkdir(_path.c_str()) != 0)
  253. handleLastErrorImpl(_path);
  254. return true;
  255. }
  256. void FileImpl::handleLastErrorImpl(const std::string& path)
  257. {
  258. switch (errno)
  259. {
  260. case EIO:
  261. throw IOException(path);
  262. case EPERM:
  263. throw FileAccessDeniedException("insufficient permissions", path);
  264. case EACCES:
  265. throw FileAccessDeniedException(path);
  266. case ENOENT:
  267. throw FileNotFoundException(path);
  268. case ENOTDIR:
  269. throw OpenFileException("not a directory", path);
  270. case EISDIR:
  271. throw OpenFileException("not a file", path);
  272. case EROFS:
  273. throw FileReadOnlyException(path);
  274. case EEXIST:
  275. throw FileExistsException(path);
  276. case ENOSPC:
  277. throw FileException("no space left on device", path);
  278. case ENOTEMPTY:
  279. throw FileException("directory not empty", path);
  280. case ENAMETOOLONG:
  281. throw PathSyntaxException(path);
  282. case ENFILE:
  283. case EMFILE:
  284. throw FileException("too many open files", path);
  285. default:
  286. throw FileException(std::strerror(errno), path);
  287. }
  288. }
  289. } // namespace Poco