PageRenderTime 51ms CodeModel.GetById 21ms app.highlight 26ms RepoModel.GetById 2ms app.codeStats 0ms

/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
  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
 30#if LL_WINDOWS
 31#include <windows.h>
 32#endif
 33
 34#include "linden_common.h"
 35#include "llfile.h"
 36#include "llstring.h"
 37#include "llerror.h"
 38
 39using namespace std;
 40
 41// static
 42int	LLFile::mkdir(const std::string& dirname, int perms)
 43{
 44#if LL_WINDOWS	
 45	// permissions are ignored on Windows
 46	std::string utf8dirname = dirname;
 47	llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname);
 48	return _wmkdir(utf16dirname.c_str());
 49#else
 50	return ::mkdir(dirname.c_str(), (mode_t)perms);
 51#endif
 52}
 53
 54// static
 55int	LLFile::rmdir(const std::string& dirname)
 56{
 57#if LL_WINDOWS	
 58	// permissions are ignored on Windows
 59	std::string utf8dirname = dirname;
 60	llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname);
 61	return _wrmdir(utf16dirname.c_str());
 62#else
 63	return ::rmdir(dirname.c_str());
 64#endif
 65}
 66
 67// static
 68LLFILE*	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
 81LLFILE*	LLFile::_fsopen(const std::string& filename, const char* mode, int sharingFlag)
 82{
 83#if	LL_WINDOWS
 84	std::string utf8filename = filename;
 85	std::string utf8mode = std::string(mode);
 86	llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
 87	llutf16string utf16mode = utf8str_to_utf16str(utf8mode);
 88	return _wfsopen(utf16filename.c_str(),utf16mode.c_str(),sharingFlag);
 89#else
 90	llassert(0);//No corresponding function on non-windows
 91	return NULL;
 92#endif
 93}
 94
 95int	LLFile::close(LLFILE * file)
 96{
 97	int ret_value = 0;
 98	if (file)
 99	{
100		ret_value = fclose(file);
101	}
102	return ret_value;
103}
104
105
106int	LLFile::remove(const std::string& filename)
107{
108#if	LL_WINDOWS
109	std::string utf8filename = filename;
110	llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
111	return _wremove(utf16filename.c_str());
112#else
113	return ::remove(filename.c_str());
114#endif
115}
116
117int	LLFile::rename(const std::string& filename, const std::string& newname)
118{
119#if	LL_WINDOWS
120	std::string utf8filename = filename;
121	std::string utf8newname = newname;
122	llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
123	llutf16string utf16newname = utf8str_to_utf16str(utf8newname);
124	return _wrename(utf16filename.c_str(),utf16newname.c_str());
125#else
126	return ::rename(filename.c_str(),newname.c_str());
127#endif
128}
129
130int	LLFile::stat(const std::string& filename, llstat* filestatus)
131{
132#if LL_WINDOWS
133	std::string utf8filename = filename;
134	llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
135	return _wstat(utf16filename.c_str(),filestatus);
136#else
137	return ::stat(filename.c_str(),filestatus);
138#endif
139}
140
141bool LLFile::isdir(const std::string& filename)
142{
143	llstat st;
144	
145	return stat(filename, &st) == 0 && S_ISDIR(st.st_mode);
146}
147
148bool LLFile::isfile(const std::string& filename)
149{
150	llstat st;
151	
152	return stat(filename, &st) == 0 && S_ISREG(st.st_mode);
153}
154
155const char *LLFile::tmpdir()
156{
157	static std::string utf8path;
158
159	if (utf8path.empty())
160	{
161		char sep;
162#if LL_WINDOWS
163		sep = '\\';
164
165		DWORD len = GetTempPathW(0, L"");
166		llutf16string utf16path;
167		utf16path.resize(len + 1);
168		len = GetTempPathW(static_cast<DWORD>(utf16path.size()), &utf16path[0]);
169		utf8path = utf16str_to_utf8str(utf16path);
170#else
171		sep = '/';
172
173		char *env = getenv("TMPDIR");
174
175		utf8path = env ? env : "/tmp/";
176#endif
177		if (utf8path[utf8path.size() - 1] != sep)
178		{
179			utf8path += sep;
180		}
181	}
182	return utf8path.c_str();
183}
184
185
186/***************** Modified file stream created to overcome the incorrect behaviour of posix fopen in windows *******************/
187
188#if USE_LLFILESTREAMS
189
190LLFILE *	LLFile::_Fiopen(const std::string& filename, std::ios::openmode mode,int)	// protection currently unused
191{	// open a file
192	static const char *mods[] =
193	{	// fopen mode strings corresponding to valid[i]
194	"r", "w", "w", "a", "rb", "wb", "wb", "ab",
195	"r+", "w+", "a+", "r+b", "w+b", "a+b",
196	0};
197	static const int valid[] =
198	{	// valid combinations of open flags
199		ios_base::in,
200		ios_base::out,
201		ios_base::out | ios_base::trunc,
202		ios_base::out | ios_base::app,
203		ios_base::in | ios_base::binary,
204		ios_base::out | ios_base::binary,
205		ios_base::out | ios_base::trunc | ios_base::binary,
206		ios_base::out | ios_base::app | ios_base::binary,
207		ios_base::in | ios_base::out,
208		ios_base::in | ios_base::out | ios_base::trunc,
209		ios_base::in | ios_base::out | ios_base::app,
210		ios_base::in | ios_base::out | ios_base::binary,
211		ios_base::in | ios_base::out | ios_base::trunc
212			| ios_base::binary,
213		ios_base::in | ios_base::out | ios_base::app
214			| ios_base::binary,
215	0};
216
217	LLFILE *fp = 0;
218	int n;
219	ios_base::openmode atendflag = mode & ios_base::ate;
220	ios_base::openmode norepflag = mode & ios_base::_Noreplace;
221
222	if (mode & ios_base::_Nocreate)
223		mode |= ios_base::in;	// file must exist
224	mode &= ~(ios_base::ate | ios_base::_Nocreate | ios_base::_Noreplace);
225	for (n = 0; valid[n] != 0 && valid[n] != mode; ++n)
226		;	// look for a valid mode
227
228	if (valid[n] == 0)
229		return (0);	// no valid mode
230	else if (norepflag && mode & (ios_base::out || ios_base::app)
231		&& (fp = LLFile::fopen(filename, "r")) != 0)	/* Flawfinder: ignore */
232		{	// file must not exist, close and fail
233		fclose(fp);
234		return (0);
235		}
236	else if (fp != 0 && fclose(fp) != 0)
237		return (0);	// can't close after test open
238// should open with protection here, if other than default
239	else if ((fp = LLFile::fopen(filename, mods[n])) == 0)	/* Flawfinder: ignore */
240		return (0);	// open failed
241
242	if (!atendflag || fseek(fp, 0, SEEK_END) == 0)
243		return (fp);	// no need to seek to end, or seek succeeded
244
245	fclose(fp);	// can't position at end
246	return (0);
247}
248
249/************** input file stream ********************************/
250
251void llifstream::close()
252{	// close the C stream
253	if (_Filebuffer && _Filebuffer->close() == 0)
254	{
255		_Myios::setstate(ios_base::failbit);	/*Flawfinder: ignore*/
256	}
257}
258
259void llifstream::open(const std::string& _Filename,	/* Flawfinder: ignore */
260	ios_base::openmode _Mode,
261	int _Prot)
262{	// open a C stream with specified mode
263	
264	LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::in, _Prot);
265	if(filep == NULL)
266	{
267		_Myios::setstate(ios_base::failbit);	/*Flawfinder: ignore*/
268		return;
269	}
270	llassert(_Filebuffer == NULL);
271	_Filebuffer = new _Myfb(filep);
272	_ShouldClose = true;
273	_Myios::init(_Filebuffer);
274}
275
276bool llifstream::is_open() const
277{	// test if C stream has been opened
278	if(_Filebuffer)
279		return (_Filebuffer->is_open());
280	return false;
281}
282llifstream::~llifstream()
283{	
284	if (_ShouldClose)
285	{
286		close();
287	}
288	delete _Filebuffer;
289}
290
291llifstream::llifstream(const std::string& _Filename,
292	ios_base::openmode _Mode,
293	int _Prot)
294	: std::basic_istream< char , std::char_traits< char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
295
296{	// construct with named file and specified mode
297	open(_Filename, _Mode | ios_base::in, _Prot);	/* Flawfinder: ignore */
298}
299
300
301/************** output file stream ********************************/
302
303bool llofstream::is_open() const
304{	// test if C stream has been opened
305	if(_Filebuffer)
306		return (_Filebuffer->is_open());
307	return false;
308}
309
310void llofstream::open(const std::string& _Filename,	/* Flawfinder: ignore */
311	ios_base::openmode _Mode,
312	int _Prot)	
313{	// open a C stream with specified mode
314
315	LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::out, _Prot);
316	if(filep == NULL)
317	{
318		_Myios::setstate(ios_base::failbit);	/*Flawfinder: ignore*/
319		return;
320	}
321	llassert(_Filebuffer==NULL);
322	_Filebuffer = new _Myfb(filep);
323	_ShouldClose = true;
324	_Myios::init(_Filebuffer);
325}
326
327void llofstream::close()
328{	// close the C stream
329	if(is_open())
330	{
331		if (_Filebuffer->close() == 0)
332		{
333			_Myios::setstate(ios_base::failbit);	/*Flawfinder: ignore*/
334		}
335		delete _Filebuffer;
336		_Filebuffer = NULL;
337		_ShouldClose = false;
338	}
339}
340
341llofstream::llofstream(const std::string& _Filename,
342	std::ios_base::openmode _Mode,
343	int _Prot) 
344		: std::basic_ostream<char,std::char_traits < char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
345{	// construct with named file and specified mode
346	open(_Filename, _Mode , _Prot);	/* Flawfinder: ignore */
347}
348
349llofstream::~llofstream()
350{	
351	// destroy the object
352	if (_ShouldClose)
353	{
354		close();
355	}
356	delete _Filebuffer;
357}
358
359#endif // #if USE_LLFILESTREAMS
360
361/************** helper functions ********************************/
362
363std::streamsize llifstream_size(llifstream& ifstr)
364{
365	if(!ifstr.is_open()) return 0;
366	std::streampos pos_old = ifstr.tellg();
367	ifstr.seekg(0, ios_base::beg);
368	std::streampos pos_beg = ifstr.tellg();
369	ifstr.seekg(0, ios_base::end);
370	std::streampos pos_end = ifstr.tellg();
371	ifstr.seekg(pos_old, ios_base::beg);
372	return pos_end - pos_beg;
373}
374
375std::streamsize llofstream_size(llofstream& ofstr)
376{
377	if(!ofstr.is_open()) return 0;
378	std::streampos pos_old = ofstr.tellp();
379	ofstr.seekp(0, ios_base::beg);
380	std::streampos pos_beg = ofstr.tellp();
381	ofstr.seekp(0, ios_base::end);
382	std::streampos pos_end = ofstr.tellp();
383	ofstr.seekp(pos_old, ios_base::beg);
384	return pos_end - pos_beg;
385}
386
387