PageRenderTime 37ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/llcommon/llfile.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 387 lines | 297 code | 51 blank | 39 comment | 49 complexity | a50abb6daed2014b61b1abdefaa8176d MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llfile.cpp
  3. * @author Michael Schlachter
  4. * @date 2006-03-23
  5. * @brief Implementation of cross-platform POSIX file buffer and c++
  6. * stream classes.
  7. *
  8. * $LicenseInfo:firstyear=2006&license=viewerlgpl$
  9. * Second Life Viewer Source Code
  10. * Copyright (C) 2010, Linden Research, Inc.
  11. *
  12. * This library is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU Lesser General Public
  14. * License as published by the Free Software Foundation;
  15. * version 2.1 of the License only.
  16. *
  17. * This library is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20. * Lesser General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Lesser General Public
  23. * License along with this library; if not, write to the Free Software
  24. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  25. *
  26. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  27. * $/LicenseInfo$
  28. */
  29. #if LL_WINDOWS
  30. #include <windows.h>
  31. #endif
  32. #include "linden_common.h"
  33. #include "llfile.h"
  34. #include "llstring.h"
  35. #include "llerror.h"
  36. using namespace std;
  37. // static
  38. int LLFile::mkdir(const std::string& dirname, int perms)
  39. {
  40. #if LL_WINDOWS
  41. // permissions are ignored on Windows
  42. std::string utf8dirname = dirname;
  43. llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname);
  44. return _wmkdir(utf16dirname.c_str());
  45. #else
  46. return ::mkdir(dirname.c_str(), (mode_t)perms);
  47. #endif
  48. }
  49. // static
  50. int LLFile::rmdir(const std::string& dirname)
  51. {
  52. #if LL_WINDOWS
  53. // permissions are ignored on Windows
  54. std::string utf8dirname = dirname;
  55. llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname);
  56. return _wrmdir(utf16dirname.c_str());
  57. #else
  58. return ::rmdir(dirname.c_str());
  59. #endif
  60. }
  61. // static
  62. LLFILE* LLFile::fopen(const std::string& filename, const char* mode) /* Flawfinder: ignore */
  63. {
  64. #if LL_WINDOWS
  65. std::string utf8filename = filename;
  66. std::string utf8mode = std::string(mode);
  67. llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
  68. llutf16string utf16mode = utf8str_to_utf16str(utf8mode);
  69. return _wfopen(utf16filename.c_str(),utf16mode.c_str());
  70. #else
  71. return ::fopen(filename.c_str(),mode); /* Flawfinder: ignore */
  72. #endif
  73. }
  74. LLFILE* LLFile::_fsopen(const std::string& filename, const char* mode, int sharingFlag)
  75. {
  76. #if LL_WINDOWS
  77. std::string utf8filename = filename;
  78. std::string utf8mode = std::string(mode);
  79. llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
  80. llutf16string utf16mode = utf8str_to_utf16str(utf8mode);
  81. return _wfsopen(utf16filename.c_str(),utf16mode.c_str(),sharingFlag);
  82. #else
  83. llassert(0);//No corresponding function on non-windows
  84. return NULL;
  85. #endif
  86. }
  87. int LLFile::close(LLFILE * file)
  88. {
  89. int ret_value = 0;
  90. if (file)
  91. {
  92. ret_value = fclose(file);
  93. }
  94. return ret_value;
  95. }
  96. int LLFile::remove(const std::string& filename)
  97. {
  98. #if LL_WINDOWS
  99. std::string utf8filename = filename;
  100. llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
  101. return _wremove(utf16filename.c_str());
  102. #else
  103. return ::remove(filename.c_str());
  104. #endif
  105. }
  106. int LLFile::rename(const std::string& filename, const std::string& newname)
  107. {
  108. #if LL_WINDOWS
  109. std::string utf8filename = filename;
  110. std::string utf8newname = newname;
  111. llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
  112. llutf16string utf16newname = utf8str_to_utf16str(utf8newname);
  113. return _wrename(utf16filename.c_str(),utf16newname.c_str());
  114. #else
  115. return ::rename(filename.c_str(),newname.c_str());
  116. #endif
  117. }
  118. int LLFile::stat(const std::string& filename, llstat* filestatus)
  119. {
  120. #if LL_WINDOWS
  121. std::string utf8filename = filename;
  122. llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
  123. return _wstat(utf16filename.c_str(),filestatus);
  124. #else
  125. return ::stat(filename.c_str(),filestatus);
  126. #endif
  127. }
  128. bool LLFile::isdir(const std::string& filename)
  129. {
  130. llstat st;
  131. return stat(filename, &st) == 0 && S_ISDIR(st.st_mode);
  132. }
  133. bool LLFile::isfile(const std::string& filename)
  134. {
  135. llstat st;
  136. return stat(filename, &st) == 0 && S_ISREG(st.st_mode);
  137. }
  138. const char *LLFile::tmpdir()
  139. {
  140. static std::string utf8path;
  141. if (utf8path.empty())
  142. {
  143. char sep;
  144. #if LL_WINDOWS
  145. sep = '\\';
  146. DWORD len = GetTempPathW(0, L"");
  147. llutf16string utf16path;
  148. utf16path.resize(len + 1);
  149. len = GetTempPathW(static_cast<DWORD>(utf16path.size()), &utf16path[0]);
  150. utf8path = utf16str_to_utf8str(utf16path);
  151. #else
  152. sep = '/';
  153. char *env = getenv("TMPDIR");
  154. utf8path = env ? env : "/tmp/";
  155. #endif
  156. if (utf8path[utf8path.size() - 1] != sep)
  157. {
  158. utf8path += sep;
  159. }
  160. }
  161. return utf8path.c_str();
  162. }
  163. /***************** Modified file stream created to overcome the incorrect behaviour of posix fopen in windows *******************/
  164. #if USE_LLFILESTREAMS
  165. LLFILE * LLFile::_Fiopen(const std::string& filename, std::ios::openmode mode,int) // protection currently unused
  166. { // open a file
  167. static const char *mods[] =
  168. { // fopen mode strings corresponding to valid[i]
  169. "r", "w", "w", "a", "rb", "wb", "wb", "ab",
  170. "r+", "w+", "a+", "r+b", "w+b", "a+b",
  171. 0};
  172. static const int valid[] =
  173. { // valid combinations of open flags
  174. ios_base::in,
  175. ios_base::out,
  176. ios_base::out | ios_base::trunc,
  177. ios_base::out | ios_base::app,
  178. ios_base::in | ios_base::binary,
  179. ios_base::out | ios_base::binary,
  180. ios_base::out | ios_base::trunc | ios_base::binary,
  181. ios_base::out | ios_base::app | ios_base::binary,
  182. ios_base::in | ios_base::out,
  183. ios_base::in | ios_base::out | ios_base::trunc,
  184. ios_base::in | ios_base::out | ios_base::app,
  185. ios_base::in | ios_base::out | ios_base::binary,
  186. ios_base::in | ios_base::out | ios_base::trunc
  187. | ios_base::binary,
  188. ios_base::in | ios_base::out | ios_base::app
  189. | ios_base::binary,
  190. 0};
  191. LLFILE *fp = 0;
  192. int n;
  193. ios_base::openmode atendflag = mode & ios_base::ate;
  194. ios_base::openmode norepflag = mode & ios_base::_Noreplace;
  195. if (mode & ios_base::_Nocreate)
  196. mode |= ios_base::in; // file must exist
  197. mode &= ~(ios_base::ate | ios_base::_Nocreate | ios_base::_Noreplace);
  198. for (n = 0; valid[n] != 0 && valid[n] != mode; ++n)
  199. ; // look for a valid mode
  200. if (valid[n] == 0)
  201. return (0); // no valid mode
  202. else if (norepflag && mode & (ios_base::out || ios_base::app)
  203. && (fp = LLFile::fopen(filename, "r")) != 0) /* Flawfinder: ignore */
  204. { // file must not exist, close and fail
  205. fclose(fp);
  206. return (0);
  207. }
  208. else if (fp != 0 && fclose(fp) != 0)
  209. return (0); // can't close after test open
  210. // should open with protection here, if other than default
  211. else if ((fp = LLFile::fopen(filename, mods[n])) == 0) /* Flawfinder: ignore */
  212. return (0); // open failed
  213. if (!atendflag || fseek(fp, 0, SEEK_END) == 0)
  214. return (fp); // no need to seek to end, or seek succeeded
  215. fclose(fp); // can't position at end
  216. return (0);
  217. }
  218. /************** input file stream ********************************/
  219. void llifstream::close()
  220. { // close the C stream
  221. if (_Filebuffer && _Filebuffer->close() == 0)
  222. {
  223. _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/
  224. }
  225. }
  226. void llifstream::open(const std::string& _Filename, /* Flawfinder: ignore */
  227. ios_base::openmode _Mode,
  228. int _Prot)
  229. { // open a C stream with specified mode
  230. LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::in, _Prot);
  231. if(filep == NULL)
  232. {
  233. _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/
  234. return;
  235. }
  236. llassert(_Filebuffer == NULL);
  237. _Filebuffer = new _Myfb(filep);
  238. _ShouldClose = true;
  239. _Myios::init(_Filebuffer);
  240. }
  241. bool llifstream::is_open() const
  242. { // test if C stream has been opened
  243. if(_Filebuffer)
  244. return (_Filebuffer->is_open());
  245. return false;
  246. }
  247. llifstream::~llifstream()
  248. {
  249. if (_ShouldClose)
  250. {
  251. close();
  252. }
  253. delete _Filebuffer;
  254. }
  255. llifstream::llifstream(const std::string& _Filename,
  256. ios_base::openmode _Mode,
  257. int _Prot)
  258. : std::basic_istream< char , std::char_traits< char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
  259. { // construct with named file and specified mode
  260. open(_Filename, _Mode | ios_base::in, _Prot); /* Flawfinder: ignore */
  261. }
  262. /************** output file stream ********************************/
  263. bool llofstream::is_open() const
  264. { // test if C stream has been opened
  265. if(_Filebuffer)
  266. return (_Filebuffer->is_open());
  267. return false;
  268. }
  269. void llofstream::open(const std::string& _Filename, /* Flawfinder: ignore */
  270. ios_base::openmode _Mode,
  271. int _Prot)
  272. { // open a C stream with specified mode
  273. LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::out, _Prot);
  274. if(filep == NULL)
  275. {
  276. _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/
  277. return;
  278. }
  279. llassert(_Filebuffer==NULL);
  280. _Filebuffer = new _Myfb(filep);
  281. _ShouldClose = true;
  282. _Myios::init(_Filebuffer);
  283. }
  284. void llofstream::close()
  285. { // close the C stream
  286. if(is_open())
  287. {
  288. if (_Filebuffer->close() == 0)
  289. {
  290. _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/
  291. }
  292. delete _Filebuffer;
  293. _Filebuffer = NULL;
  294. _ShouldClose = false;
  295. }
  296. }
  297. llofstream::llofstream(const std::string& _Filename,
  298. std::ios_base::openmode _Mode,
  299. int _Prot)
  300. : std::basic_ostream<char,std::char_traits < char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
  301. { // construct with named file and specified mode
  302. open(_Filename, _Mode , _Prot); /* Flawfinder: ignore */
  303. }
  304. llofstream::~llofstream()
  305. {
  306. // destroy the object
  307. if (_ShouldClose)
  308. {
  309. close();
  310. }
  311. delete _Filebuffer;
  312. }
  313. #endif // #if USE_LLFILESTREAMS
  314. /************** helper functions ********************************/
  315. std::streamsize llifstream_size(llifstream& ifstr)
  316. {
  317. if(!ifstr.is_open()) return 0;
  318. std::streampos pos_old = ifstr.tellg();
  319. ifstr.seekg(0, ios_base::beg);
  320. std::streampos pos_beg = ifstr.tellg();
  321. ifstr.seekg(0, ios_base::end);
  322. std::streampos pos_end = ifstr.tellg();
  323. ifstr.seekg(pos_old, ios_base::beg);
  324. return pos_end - pos_beg;
  325. }
  326. std::streamsize llofstream_size(llofstream& ofstr)
  327. {
  328. if(!ofstr.is_open()) return 0;
  329. std::streampos pos_old = ofstr.tellp();
  330. ofstr.seekp(0, ios_base::beg);
  331. std::streampos pos_beg = ofstr.tellp();
  332. ofstr.seekp(0, ios_base::end);
  333. std::streampos pos_end = ofstr.tellp();
  334. ofstr.seekp(pos_old, ios_base::beg);
  335. return pos_end - pos_beg;
  336. }