From ae6440eecc4d6c018a3634c2c06052757bde962f Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 28 Jan 2015 15:55:18 -0500
Subject: [PATCH] MAINT-4744: Eliminate viewer dependency on (old) GNU
 libstdc++. To be more accurate, this changeset doesn't actually eliminate the
 dependency: it eliminates the use cases for the llifstream / llofstream
 feature that requires it. Currently you can construct an llifstream or
 llofstream from an open LLFILE* file handle (or, except on Windows, an int
 file descriptor). But rather than containing a streambuf implementation based
 on FILE*, llfile.h relies on the fact that the Windows std::filebuf happens
 to support that as a nonstandard extension; also on a nonstandard GNU
 extension __gnu_cxx::stdio_filebuf<char>. To move from GNU libstdc++ to
 clang's libc++ (the direction on Mac), we could code a streambuf that
 supports FILE*. But before doing that, it's worth asking whether anyone
 actually uses this questionable feature. In fact there were only two methods:
 LLWearable::exportFile() and importFile() -- and only one call to either, in
 LLViewerWearable::saveNewAsset(). The code in saveNewAsset() opened the
 LLFILE* immediately before calling exportFile(), meaning we could reasonably
 push the open operation down into exportFile(). That logic was complex anyway
 due to the need for the caller to close the LLFILE* regardless of the success
 of the exportFile(). Change LLWearable::exportFile() and importFile() to
 accept a std::string filename rather than an open LLFILE*. Change
 LLViewerWearable::saveNewAsset() to simply call exportFile(filename) rather
 than horsing around with an LLFILE* handle. (This improves the code in
 another way too: it encapsulates the need to open the relevant file in binary
 mode. Previously, each caller had to remember to do that.) To prevent
 inadvertent reintroduction of ll[io]fstream(LLFILE*) code, add
 llstream_LLFILE preprocessor macro (default 0) to control access to the
 relevant constructors. Also suppress rdbuf() override, the only method whose
 signature references llstdio_filebuf.

---
 indra/llappearance/llwearable.cpp  | 13 +++++++------
 indra/llappearance/llwearable.h    |  4 ++--
 indra/llcommon/llfile.cpp          |  4 ++++
 indra/llcommon/llfile.h            | 14 ++++++++++++++
 indra/newview/llviewerwearable.cpp | 13 +------------
 5 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp
index 4bce3f99ed8..41c06f43683 100755
--- a/indra/llappearance/llwearable.cpp
+++ b/indra/llappearance/llwearable.cpp
@@ -86,10 +86,10 @@ LLAssetType::EType LLWearable::getAssetType() const
 	return LLWearableType::getAssetType(mType);
 }
 
-BOOL LLWearable::exportFile(LLFILE* fp) const
+BOOL LLWearable::exportFile(const std::string& filename) const
 {
-	llofstream ofs(fp);
-	return exportStream(ofs);
+	llofstream ofs(filename, std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
+	return ofs.is_open() && exportStream(ofs);
 }
 
 // virtual
@@ -201,10 +201,11 @@ void LLWearable::createLayers(S32 te, LLAvatarAppearance *avatarp)
 	}
 }
 
-LLWearable::EImportResult LLWearable::importFile(LLFILE* fp, LLAvatarAppearance* avatarp )
+LLWearable::EImportResult LLWearable::importFile(const std::string& filename,
+												 LLAvatarAppearance* avatarp )
 {
-	llifstream ifs(fp);
-	return importStream(ifs, avatarp);
+	llifstream ifs(filename, std::ios_base::in | std::ios_base::binary);
+	return (! ifs.is_open())? FAILURE : importStream(ifs, avatarp);
 }
 
 // virtual
diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h
index 630eb1e3a5f..875c2932f15 100755
--- a/indra/llappearance/llwearable.h
+++ b/indra/llappearance/llwearable.h
@@ -81,8 +81,8 @@ class LLWearable
 		SUCCESS,
 		BAD_HEADER
 	};
-	BOOL				exportFile(LLFILE* file) const;
-	EImportResult		importFile(LLFILE* file, LLAvatarAppearance* avatarp );
+	BOOL				exportFile(const std::string& filename) const;
+	EImportResult		importFile(const std::string& filename, LLAvatarAppearance* avatarp );
 	virtual BOOL				exportStream( std::ostream& output_stream ) const;
 	virtual EImportResult		importStream( std::istream& input_stream, LLAvatarAppearance* avatarp );
 
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index aabc195ba8e..304d702979c 100755
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -919,6 +919,7 @@ llifstream::llifstream(const char* _Filename,
 #endif
 
 
+#if llstream_LLFILE
 // explicit
 llifstream::llifstream(_Filet *_File,
 		ios_base::openmode _Mode, size_t _Size) :
@@ -942,6 +943,7 @@ llifstream::llifstream(int __fd,
 	this->init(&_M_filebuf);
 }
 #endif
+#endif // llstream_LLFILE
 
 bool llifstream::is_open() const
 {	// test if C stream has been opened
@@ -1039,6 +1041,7 @@ llofstream::llofstream(const char* _Filename,
 }
 #endif
 
+#if llstream_LLFILE
 // explicit
 llofstream::llofstream(_Filet *_File,
 			ios_base::openmode _Mode, size_t _Size) :
@@ -1062,6 +1065,7 @@ llofstream::llofstream(int __fd,
 	this->init(&_M_filebuf);
 }
 #endif
+#endif // llstream_LLFILE
 
 bool llofstream::is_open() const
 {	// test if C stream has been opened
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index 0612071d674..44a1e42fa5a 100755
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -86,6 +86,12 @@ class LL_COMMON_API LLFile
 	static  const char * tmpdir();
 };
 
+// Remove ll[io]fstream support for [LL]FILE*, preparing to remove dependency
+// on GNU's standard library.
+#if ! defined(llstream_LLFILE)
+#define llstream_LLFILE 0
+#endif
+
 /**
  *  @brief Provides a layer of compatibility for C/POSIX.
  *
@@ -228,6 +234,7 @@ class LL_COMMON_API llifstream	:	public	std::istream
 	explicit llifstream(const char* _Filename,
 			ios_base::openmode _Mode = ios_base::in);
 
+#if llstream_LLFILE
 	/**
 	 *  @brief  Create a stream using an open c file stream.
 	 *  @param  File  An open @c FILE*.
@@ -253,6 +260,7 @@ class LL_COMMON_API llifstream	:	public	std::istream
 			//size_t _Size = static_cast<size_t>(BUFSIZ));
 			size_t _Size = static_cast<size_t>(1));
 #endif
+#endif // llstream_LLFILE
 
 	/**
 	 *  @brief  The destructor does nothing.
@@ -263,6 +271,7 @@ class LL_COMMON_API llifstream	:	public	std::istream
 	virtual ~llifstream() {}
 
 	// Members:
+#if llstream_LLFILE
 	/**
 	 *  @brief  Accessing the underlying buffer.
 	 *  @return  The current basic_filebuf buffer.
@@ -271,6 +280,7 @@ class LL_COMMON_API llifstream	:	public	std::istream
 	*/
 	llstdio_filebuf* rdbuf() const
 	{ return const_cast<llstdio_filebuf*>(&_M_filebuf); }
+#endif // llstream_LLFILE
 
 	/**
 	 *  @brief  Wrapper to test for an open file.
@@ -340,6 +350,7 @@ class LL_COMMON_API llofstream	:	public	std::ostream
 	explicit llofstream(const char* _Filename,
 			ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
 
+#if llstream_LLFILE
 	/**
 	 *  @brief  Create a stream using an open c file stream.
 	 *  @param  File  An open @c FILE*.
@@ -365,6 +376,7 @@ class LL_COMMON_API llofstream	:	public	std::ostream
 			//size_t _Size = static_cast<size_t>(BUFSIZ));
 			size_t _Size = static_cast<size_t>(1));
 #endif
+#endif // llstream_LLFILE
 
 	/**
 	 *  @brief  The destructor does nothing.
@@ -375,6 +387,7 @@ class LL_COMMON_API llofstream	:	public	std::ostream
 	virtual ~llofstream() {}
 
 	// Members:
+#if llstream_LLFILE
 	/**
 	 *  @brief  Accessing the underlying buffer.
 	 *  @return  The current basic_filebuf buffer.
@@ -383,6 +396,7 @@ class LL_COMMON_API llofstream	:	public	std::ostream
 	*/
 	llstdio_filebuf* rdbuf() const
 	{ return const_cast<llstdio_filebuf*>(&_M_filebuf); }
+#endif // llstream_LLFILE
 
 	/**
 	 *  @brief  Wrapper to test for an open file.
diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp
index 7de82a47108..0f73515b5d8 100755
--- a/indra/newview/llviewerwearable.cpp
+++ b/indra/newview/llviewerwearable.cpp
@@ -509,18 +509,7 @@ void LLViewerWearable::saveNewAsset() const
 	//LL_INFOS() << *this << LL_ENDL;
 
 	const std::string filename = asset_id_to_filename(mAssetID);
-	LLFILE* fp = LLFile::fopen(filename, "wb");		/* Flawfinder: ignore */
-	BOOL successful_save = FALSE;
-	if(fp && exportFile(fp))
-	{
-		successful_save = TRUE;
-	}
-	if(fp)
-	{
-		fclose(fp);
-		fp = NULL;
-	}
-	if(!successful_save)
+	if(! exportFile(filename))
 	{
 		std::string buffer = llformat("Unable to save '%s' to wearable file.", mName.c_str());
 		LL_WARNS() << buffer << LL_ENDL;
-- 
GitLab