llfile.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /**
  2. * @file llfile.h
  3. * @author Michael Schlachter
  4. * @date 2006-03-23
  5. * @brief Declaration of cross-platform POSIX file buffer and c++
  6. * stream classes.
  7. *
  8. * $LicenseInfo:firstyear=2006&license=viewergpl$
  9. *
  10. * Copyright (c) 2006-2009, 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. #ifndef LL_LLFILE_H
  36. #define LL_LLFILE_H
  37. typedef FILE LLFILE;
  38. #include <algorithm>
  39. #include <fstream>
  40. #include <sys/stat.h>
  41. #include <time.h>
  42. // Safe char* -> std::string conversion. Also indirectly includes
  43. // llpreprocessor.h (for LL_INLINE).
  44. #include "llstring.h"
  45. // This replaces advantageously gDirUtil.getDirDelimiter() and saves us the
  46. // costly use of a std::string (and quite a few std::string/const char* strings
  47. // concatenations) for the directory delimiter, which is known at compile
  48. // time... HB
  49. #if LL_WINDOWS
  50. # define LL_DIR_DELIM_STR "\\"
  51. # define LL_DIR_DELIM_CHR '\\'
  52. #else
  53. # define LL_DIR_DELIM_STR "/"
  54. # define LL_DIR_DELIM_CHR '/'
  55. #endif
  56. #if LL_WINDOWS
  57. // Windows version of stat function and stat data structure are called _stat
  58. typedef struct _stat llstat;
  59. #elif LL_DARWIN
  60. typedef struct stat llstat;
  61. #else
  62. typedef struct stat llstat;
  63. # include <ext/stdio_filebuf.h>
  64. # include <bits/postypes.h>
  65. #endif
  66. #ifndef S_ISREG
  67. # define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
  68. #endif
  69. #ifndef S_ISDIR
  70. # define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR)
  71. #endif
  72. // This class provides a cross platform interface to the filesystem. Attempts
  73. // to mostly mirror the POSIX style IO functions.
  74. class LLFile
  75. {
  76. protected:
  77. LOG_CLASS(LLFile);
  78. public:
  79. // All the methods below take UTF-8 path/filenames.
  80. // These non-static methods have been implemented to get rid of LLAPRFile.
  81. // They implement the equivalent of what could be found in the latter, with
  82. // the open() method (implicit in constructor) and close() method (implicit
  83. // in destructor) removed. They also replace LLUniqueFile (which was only
  84. // used in llerror.cpp). HB
  85. // Empty constructor (used in llerror.cpp)
  86. LL_INLINE LLFile()
  87. : mFile(NULL)
  88. {
  89. }
  90. // Normal constructor
  91. LLFile(const std::string& filename, const char* mode, S64* size = NULL);
  92. // Wrap constructor. E.g. result of LLFile::open() (used in llerror.cpp)
  93. LL_INLINE LLFile(LLFILE* f)
  94. : mFile(f)
  95. {
  96. }
  97. // Move constructor
  98. LL_INLINE LLFile(LLFile&& other)
  99. {
  100. mFile = other.mFile;
  101. other.mFile = NULL;
  102. }
  103. // Forbid copy constructor usage
  104. LLFile(const LLFile&) = delete;
  105. ~LLFile();
  106. // Simple assignment
  107. LLFile& operator=(LLFILE* f);
  108. // Move assignment
  109. LLFile& operator=(LLFile&& other);
  110. // Forbid copy assignment usage
  111. LLFile& operator=(const LLFile&) = delete;
  112. // Detect whether the wrapped LLFILE is open or not
  113. LL_INLINE explicit operator bool() const { return bool(mFile); }
  114. LL_INLINE bool operator!() { return !mFile; }
  115. // LLFile should be usable for any operation that accepts LLFILE* (or FILE*
  116. // for that matter).
  117. LL_INLINE operator LLFILE*() const { return mFile; }
  118. // Explicit method, handier/clearer when using a pointer on an LLFile.
  119. LL_INLINE LLFILE* getStream() { return mFile; }
  120. S64 read(U8* buffer, S64 bytes);
  121. S64 write(const U8* buffer, S64 bytes);
  122. // Returns true on success.
  123. bool flush();
  124. // Use true for 'delta' when seeking at offset from current file position.
  125. S64 seek(S64 position, bool delta = false);
  126. // Returns true on EOF marker set.
  127. bool eof();
  128. // Returns false if a non-blocking file lock could not be obtained. Note
  129. // that the 'exclusive' boolean is only actually used under Windows where
  130. // shared locks prevent any writing by the lock holder, while exclusive
  131. // locks allow it but prevent any other process to read the locked file !
  132. // On POSIX OSes, a write lock is always used, which still allows the lock
  133. // holder to write to the file and any other process to read it. HB
  134. bool lock(bool exclusive = false);
  135. // Windows is stupid: you cannot change the contents of a locked file, when
  136. // you own a shared lock on it, and you cannot read it from another process
  137. // if you take an exclusive lock on it. This is unlike POSIX systems where
  138. // a write-locked file can still be read by everyone... So under Windoze,
  139. // we need to be able to unlock our file to change its contents and re-lock
  140. // it afterwards. HB
  141. bool unlock();
  142. // These two methods (which used to be in the now removed LLAPRFile) return
  143. // the number of bytes read/written, or 0 if read/write failed. They are
  144. // limited to 2GB files. HB
  145. static S32 readEx(const std::string& filename, void* buf, S32 offset,
  146. S32 nbytes);
  147. // Note: 'offset' < 0 means append.
  148. static S32 writeEx(const std::string& filename, void* buf, S32 offset,
  149. S32 nbytes);
  150. // Gets the contents of the file. Returns an empty string when the file
  151. // cannot be opened for reading.
  152. static std::string getContents(const std::string& filename);
  153. // For all these methods, returned booleans are true on success to perform
  154. // the requested operation, false on failure. This is unlike LL's original
  155. // code that usually returns an error code which is 0 to denote a success.
  156. // HB
  157. static LLFILE* open(const std::string& filename, const char* accessmode);
  158. static LLFILE* open(const char* filename, const char* accessmode);
  159. static void close(LLFILE* file);
  160. // 'perms' is a permissions mask (in octal) like 0777 or 0700. In most
  161. // cases it will be overridden by the user's umask. It is ignored on
  162. // Windows.
  163. static bool mkdir(const std::string& filename, U16 perms = 0700);
  164. static bool rmdir(const std::string& filename);
  165. static bool remove(const std::string& filename);
  166. static bool rename(const std::string& filename, const std::string& newname,
  167. bool ignore_cross_linking = false);
  168. static bool copy(const std::string from, const std::string to);
  169. // Note: this method returns the error code from the OS stat() call:
  170. // 0 denotes a success (i.e. file exists and its metadata could be read).
  171. static S32 stat(const std::string& filename, llstat* file_status);
  172. static bool exists(const std::string& filename);
  173. static bool isdir(const std::string& filename);
  174. static bool isfile(const std::string& filename);
  175. static size_t getFileSize(const std::string& filename);
  176. static time_t lastModidied(const std::string& filename);
  177. // Tries and creates a symbolic 'link' for regular file 'filename'. When
  178. // 'filename' does not correspond to an existing file, this method tries to
  179. // create an empty file for it. Returns true on success, or false when
  180. // 'filename' is not an existing regular file and could not be created as
  181. // an empty file, or'link' is empty, or the link creation failed (warnings
  182. // are also logged as appropriate). HB
  183. static bool createFileSymlink(const std::string& filename,
  184. const std::string& link);
  185. static const char* tmpdir();
  186. // Used to be gzip_file() and gunzip_file() and are defined in llsys.h/cpp
  187. // in LL's sources, but best moved here, since they make use of LLFile
  188. // operations and have *strictly* nothing to do llsys stuff !... HB
  189. // These methods return true on success or false otherwise.
  190. static bool gzip(const std::string& srcfile, const std::string& dstfile);
  191. static bool gunzip(const std::string& srcfile, const std::string& dstfile);
  192. LL_INLINE static bool hadWriteErrors()
  193. {
  194. bool error = sWriteError;
  195. sWriteError = false;
  196. return error;
  197. }
  198. LL_INLINE static void setWriteError() { sWriteError = true; }
  199. private:
  200. LLFILE* mFile;
  201. static bool sWriteError;
  202. public:
  203. // This is to work around a bug in Wine (*) which reports a wrong file
  204. // position after non flushed writes. (*) This is for people perverted
  205. // enough to run a Windows build under Wine under Linux instead of a Linux
  206. // native build: yes, I am perverted since I do it to test Windows builds
  207. // under Linux... :-P HB
  208. static bool sFlushOnWrite;
  209. };
  210. #if !LL_WINDOWS
  211. typedef std::ifstream llifstream;
  212. typedef std::ofstream llofstream;
  213. #else
  214. // Controlling input for files.
  215. //
  216. // This class supports writing to named files, using the inherited methods from
  217. // std::ifstream. The only added value is that our constructor Does The Right
  218. // Thing when passed a non-ASCII pathname. Sadly, that is not true of
  219. // Microsoft's std::ofstream.
  220. class llifstream : public std::ifstream
  221. {
  222. public:
  223. // Default constructor.
  224. // Initializes sb using its default constructor, and passes &sb to the base
  225. // class initializer. Does not open any files (you have not given it a
  226. // filename to open).
  227. llifstream();
  228. // Creates an input file stream, opening file 'filename' in specified
  229. // 'mode' (see std::ios_base). ios_base::in is automatically included in
  230. // 'mode'.
  231. explicit llifstream(const std::string& filename,
  232. ios_base::openmode mode = ios_base::in);
  233. // Opens an external file named 'filename' in specified 'mode'.
  234. // Calls llstdio_filebuf::open(s,mode|in). If that method
  235. // fails, @c failbit is set in the stream's error state.
  236. void open(const std::string& filename,
  237. ios_base::openmode mode = ios_base::in);
  238. };
  239. // Controlling output for files.
  240. //
  241. // This class supports writing to named files, using the inherited methods from
  242. // std::ofstream. The only added value is that our constructor Does The Right
  243. // Thing when passed a non-ASCII pathname. Sadly, that is not true of
  244. // Microsoft's std::ofstream.
  245. class llofstream : public std::ofstream
  246. {
  247. public:
  248. // Default constructor.
  249. // Initializes sb using its default constructor, and passes &sb to the base
  250. // class initializer. Does not open any file (you have not given it a
  251. // filename to open).
  252. llofstream();
  253. // Creates an output file stream, opening file 'filename' in specified
  254. // 'mode' (see std::ios_base). ios_base::out is automatically included in
  255. // 'mode'.
  256. explicit llofstream(const std::string& filename,
  257. ios_base::openmode mode = ios_base::out|ios_base::trunc);
  258. // Opens an external file named 'filename' in specified 'mode'.
  259. // ios_base::out is automatically included in 'mode'.
  260. void open(const std::string& filename,
  261. ios_base::openmode mode = ios_base::out|ios_base::trunc);
  262. };
  263. #endif // LL_WINDOWS
  264. #endif // LL_LLFILE_H