llfile.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:10k
源码类别:

游戏引擎

开发平台:

C++ Builder

  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=viewergpl$
  9.  * 
  10.  * Copyright (c) 2006-2010, Linden Research, Inc.
  11.  * 
  12.  * Second Life Viewer Source Code
  13.  * The source code in this file ("Source Code") is provided by Linden Lab
  14.  * to you under the terms of the GNU General Public License, version 2.0
  15.  * ("GPL"), unless you have obtained a separate licensing agreement
  16.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  17.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  18.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  19.  * 
  20.  * There are special exceptions to the terms and conditions of the GPL as
  21.  * it is applied to this Source Code. View the full text of the exception
  22.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  23.  * online at
  24.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  25.  * 
  26.  * By copying, modifying or distributing this software, you acknowledge
  27.  * that you have read and understood your obligations described above,
  28.  * and agree to abide by those obligations.
  29.  * 
  30.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  31.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  32.  * COMPLETENESS OR PERFORMANCE.
  33.  * $/LicenseInfo$
  34.  */
  35. #if LL_WINDOWS
  36. #include <windows.h>
  37. #endif
  38. #include "linden_common.h"
  39. #include "llfile.h"
  40. #include "llstring.h"
  41. #include "llerror.h"
  42. using namespace std;
  43. // static
  44. int LLFile::mkdir(const std::string& dirname, int perms)
  45. {
  46. #if LL_WINDOWS
  47. // permissions are ignored on Windows
  48. std::string utf8dirname = dirname;
  49. llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname);
  50. return _wmkdir(utf16dirname.c_str());
  51. #else
  52. return ::mkdir(dirname.c_str(), (mode_t)perms);
  53. #endif
  54. }
  55. // static
  56. int LLFile::rmdir(const std::string& dirname)
  57. {
  58. #if LL_WINDOWS
  59. // permissions are ignored on Windows
  60. std::string utf8dirname = dirname;
  61. llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname);
  62. return _wrmdir(utf16dirname.c_str());
  63. #else
  64. return ::rmdir(dirname.c_str());
  65. #endif
  66. }
  67. // static
  68. LLFILE* LLFile::fopen(const std::string& filename, const char* mode) /* Flawfinder: ignore */
  69. {
  70. #if LL_WINDOWS
  71. std::string utf8filename = filename;
  72. std::string utf8mode = std::string(mode);
  73. llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
  74. llutf16string utf16mode = utf8str_to_utf16str(utf8mode);
  75. return _wfopen(utf16filename.c_str(),utf16mode.c_str());
  76. #else
  77. return ::fopen(filename.c_str(),mode); /* Flawfinder: ignore */
  78. #endif
  79. }
  80. LLFILE* LLFile::_fsopen(const std::string& filename, const char* mode, int sharingFlag)
  81. {
  82. #if LL_WINDOWS
  83. std::string utf8filename = filename;
  84. std::string utf8mode = std::string(mode);
  85. llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
  86. llutf16string utf16mode = utf8str_to_utf16str(utf8mode);
  87. return _wfsopen(utf16filename.c_str(),utf16mode.c_str(),sharingFlag);
  88. #else
  89. llassert(0);//No corresponding function on non-windows
  90. return NULL;
  91. #endif
  92. }
  93. int LLFile::remove(const std::string& filename)
  94. {
  95. #if LL_WINDOWS
  96. std::string utf8filename = filename;
  97. llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
  98. return _wremove(utf16filename.c_str());
  99. #else
  100. return ::remove(filename.c_str());
  101. #endif
  102. }
  103. int LLFile::rename(const std::string& filename, const std::string& newname)
  104. {
  105. #if LL_WINDOWS
  106. std::string utf8filename = filename;
  107. std::string utf8newname = newname;
  108. llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
  109. llutf16string utf16newname = utf8str_to_utf16str(utf8newname);
  110. return _wrename(utf16filename.c_str(),utf16newname.c_str());
  111. #else
  112. return ::rename(filename.c_str(),newname.c_str());
  113. #endif
  114. }
  115. int LLFile::stat(const std::string& filename, llstat* filestatus)
  116. {
  117. #if LL_WINDOWS
  118. std::string utf8filename = filename;
  119. llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
  120. return _wstat(utf16filename.c_str(),filestatus);
  121. #else
  122. return ::stat(filename.c_str(),filestatus);
  123. #endif
  124. }
  125. bool LLFile::isdir(const std::string& filename)
  126. {
  127. llstat st;
  128. return stat(filename, &st) == 0 && S_ISDIR(st.st_mode);
  129. }
  130. bool LLFile::isfile(const std::string& filename)
  131. {
  132. llstat st;
  133. return stat(filename, &st) == 0 && S_ISREG(st.st_mode);
  134. }
  135. const char *LLFile::tmpdir()
  136. {
  137. static std::string utf8path;
  138. if (utf8path.empty())
  139. {
  140. char sep;
  141. #if LL_WINDOWS
  142. sep = '\';
  143. DWORD len = GetTempPathW(0, L"");
  144. llutf16string utf16path;
  145. utf16path.resize(len + 1);
  146. len = GetTempPathW(static_cast<DWORD>(utf16path.size()), &utf16path[0]);
  147. utf8path = utf16str_to_utf8str(utf16path);
  148. #else
  149. sep = '/';
  150. char *env = getenv("TMPDIR");
  151. utf8path = env ? env : "/tmp/";
  152. #endif
  153. if (utf8path[utf8path.size() - 1] != sep)
  154. {
  155. utf8path += sep;
  156. }
  157. }
  158. return utf8path.c_str();
  159. }
  160. /***************** Modified file stream created to overcome the incorrect behaviour of posix fopen in windows *******************/
  161. #if USE_LLFILESTREAMS
  162. LLFILE * LLFile::_Fiopen(const std::string& filename, std::ios::openmode mode,int) // protection currently unused
  163. { // open a file
  164. static const char *mods[] =
  165. { // fopen mode strings corresponding to valid[i]
  166. "r", "w", "w", "a", "rb", "wb", "wb", "ab",
  167. "r+", "w+", "a+", "r+b", "w+b", "a+b",
  168. 0};
  169. static const int valid[] =
  170. { // valid combinations of open flags
  171. ios_base::in,
  172. ios_base::out,
  173. ios_base::out | ios_base::trunc,
  174. ios_base::out | ios_base::app,
  175. ios_base::in | ios_base::binary,
  176. ios_base::out | ios_base::binary,
  177. ios_base::out | ios_base::trunc | ios_base::binary,
  178. ios_base::out | ios_base::app | ios_base::binary,
  179. ios_base::in | ios_base::out,
  180. ios_base::in | ios_base::out | ios_base::trunc,
  181. ios_base::in | ios_base::out | ios_base::app,
  182. ios_base::in | ios_base::out | ios_base::binary,
  183. ios_base::in | ios_base::out | ios_base::trunc
  184. | ios_base::binary,
  185. ios_base::in | ios_base::out | ios_base::app
  186. | ios_base::binary,
  187. 0};
  188. LLFILE *fp = 0;
  189. int n;
  190. ios_base::openmode atendflag = mode & ios_base::ate;
  191. ios_base::openmode norepflag = mode & ios_base::_Noreplace;
  192. if (mode & ios_base::_Nocreate)
  193. mode |= ios_base::in; // file must exist
  194. mode &= ~(ios_base::ate | ios_base::_Nocreate | ios_base::_Noreplace);
  195. for (n = 0; valid[n] != 0 && valid[n] != mode; ++n)
  196. ; // look for a valid mode
  197. if (valid[n] == 0)
  198. return (0); // no valid mode
  199. else if (norepflag && mode & (ios_base::out || ios_base::app)
  200. && (fp = LLFile::fopen(filename, "r")) != 0) /* Flawfinder: ignore */
  201. { // file must not exist, close and fail
  202. fclose(fp);
  203. return (0);
  204. }
  205. else if (fp != 0 && fclose(fp) != 0)
  206. return (0); // can't close after test open
  207. // should open with protection here, if other than default
  208. else if ((fp = LLFile::fopen(filename, mods[n])) == 0) /* Flawfinder: ignore */
  209. return (0); // open failed
  210. if (!atendflag || fseek(fp, 0, SEEK_END) == 0)
  211. return (fp); // no need to seek to end, or seek succeeded
  212. fclose(fp); // can't position at end
  213. return (0);
  214. }
  215. /************** input file stream ********************************/
  216. void llifstream::close()
  217. { // close the C stream
  218. if (_Filebuffer && _Filebuffer->close() == 0)
  219. {
  220. _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/
  221. }
  222. }
  223. void llifstream::open(const std::string& _Filename, /* Flawfinder: ignore */
  224. ios_base::openmode _Mode,
  225. int _Prot)
  226. { // open a C stream with specified mode
  227. LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::in, _Prot);
  228. if(filep == NULL)
  229. {
  230. _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/
  231. return;
  232. }
  233. llassert(_Filebuffer == NULL);
  234. _Filebuffer = new _Myfb(filep);
  235. _ShouldClose = true;
  236. _Myios::init(_Filebuffer);
  237. }
  238. bool llifstream::is_open() const
  239. { // test if C stream has been opened
  240. if(_Filebuffer)
  241. return (_Filebuffer->is_open());
  242. return false;
  243. }
  244. llifstream::~llifstream()
  245. {
  246. if (_ShouldClose)
  247. {
  248. close();
  249. }
  250. delete _Filebuffer;
  251. }
  252. llifstream::llifstream(const std::string& _Filename,
  253. ios_base::openmode _Mode,
  254. int _Prot)
  255. : std::basic_istream< char , std::char_traits< char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
  256. { // construct with named file and specified mode
  257. open(_Filename, _Mode | ios_base::in, _Prot); /* Flawfinder: ignore */
  258. }
  259. /************** output file stream ********************************/
  260. bool llofstream::is_open() const
  261. { // test if C stream has been opened
  262. if(_Filebuffer)
  263. return (_Filebuffer->is_open());
  264. return false;
  265. }
  266. void llofstream::open(const std::string& _Filename, /* Flawfinder: ignore */
  267. ios_base::openmode _Mode,
  268. int _Prot)
  269. { // open a C stream with specified mode
  270. LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::out, _Prot);
  271. if(filep == NULL)
  272. {
  273. _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/
  274. return;
  275. }
  276. llassert(_Filebuffer==NULL);
  277. _Filebuffer = new _Myfb(filep);
  278. _ShouldClose = true;
  279. _Myios::init(_Filebuffer);
  280. }
  281. void llofstream::close()
  282. { // close the C stream
  283. if(is_open())
  284. {
  285. if (_Filebuffer->close() == 0)
  286. _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/
  287. }
  288. }
  289. llofstream::llofstream(const std::string& _Filename,
  290. std::ios_base::openmode _Mode,
  291. int _Prot) 
  292. : std::basic_ostream<char,std::char_traits < char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
  293. { // construct with named file and specified mode
  294. open(_Filename, _Mode , _Prot); /* Flawfinder: ignore */
  295. }
  296. llofstream::~llofstream()
  297. {
  298. // destroy the object
  299. if (_ShouldClose)
  300. {
  301. close();
  302. }
  303. delete _Filebuffer;
  304. }
  305. #endif // #if USE_LLFILESTREAMS
  306. /************** helper functions ********************************/
  307. std::streamsize llifstream_size(llifstream& ifstr)
  308. {
  309. if(!ifstr.is_open()) return 0;
  310. std::streampos pos_old = ifstr.tellg();
  311. ifstr.seekg(0, ios_base::beg);
  312. std::streampos pos_beg = ifstr.tellg();
  313. ifstr.seekg(0, ios_base::end);
  314. std::streampos pos_end = ifstr.tellg();
  315. ifstr.seekg(pos_old, ios_base::beg);
  316. return pos_end - pos_beg;
  317. }
  318. std::streamsize llofstream_size(llofstream& ofstr)
  319. {
  320. if(!ofstr.is_open()) return 0;
  321. std::streampos pos_old = ofstr.tellp();
  322. ofstr.seekp(0, ios_base::beg);
  323. std::streampos pos_beg = ofstr.tellp();
  324. ofstr.seekp(0, ios_base::end);
  325. std::streampos pos_end = ofstr.tellp();
  326. ofstr.seekp(pos_old, ios_base::beg);
  327. return pos_end - pos_beg;
  328. }