diff options
author | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 21:25:21 +0200 |
---|---|---|
committer | Andrey Lihatskiy <alihatskiy@productengine.com> | 2024-05-22 22:40:26 +0300 |
commit | e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 (patch) | |
tree | 1bb897489ce524986f6196201c10ac0d8861aa5f /indra/llmessage/llxfer_file.cpp | |
parent | 069ea06848f766466f1a281144c82a0f2bd79f3a (diff) |
Fix line endlings
Diffstat (limited to 'indra/llmessage/llxfer_file.cpp')
-rw-r--r-- | indra/llmessage/llxfer_file.cpp | 950 |
1 files changed, 475 insertions, 475 deletions
diff --git a/indra/llmessage/llxfer_file.cpp b/indra/llmessage/llxfer_file.cpp index a9450f725b..ad15d5969b 100644 --- a/indra/llmessage/llxfer_file.cpp +++ b/indra/llmessage/llxfer_file.cpp @@ -1,475 +1,475 @@ -/**
- * @file llxfer_file.cpp
- * @brief implementation of LLXfer_File class for a single xfer (file)
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#if !LL_WINDOWS
-#include <errno.h>
-#include <unistd.h>
-#endif
-
-#include "llxfer_file.h"
-#include "lluuid.h"
-#include "llerror.h"
-#include "llmath.h"
-#include "llstring.h"
-#include "lldir.h"
-
-// size of chunks read from/written to disk
-const U32 LL_MAX_XFER_FILE_BUFFER = 65536;
-
-// local function to copy a file
-S32 copy_file(const std::string& from, const std::string& to);
-
-///////////////////////////////////////////////////////////
-
-LLXfer_File::LLXfer_File (S32 chunk_size)
-: LLXfer(chunk_size)
-{
- init(LLStringUtil::null, false, chunk_size);
-}
-
-LLXfer_File::LLXfer_File (const std::string& local_filename, bool delete_local_on_completion, S32 chunk_size)
-: LLXfer(chunk_size)
-{
- init(local_filename, delete_local_on_completion, chunk_size);
-}
-
-///////////////////////////////////////////////////////////
-
-LLXfer_File::~LLXfer_File ()
-{
- cleanup();
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer_File::init (const std::string& local_filename, bool delete_local_on_completion, S32 chunk_size)
-{
-
- mFp = NULL;
- mLocalFilename.clear();
- mRemoteFilename.clear();
- mRemotePath = LL_PATH_NONE;
- mTempFilename.clear();
- mDeleteLocalOnCompletion = false;
- mDeleteRemoteOnCompletion = false;
-
- if (!local_filename.empty())
- {
- mLocalFilename = local_filename.substr(0,LL_MAX_PATH-1);
-
- // You can only automatically delete .tmp file as a safeguard against nasty messages.
- std::string exten = mLocalFilename.substr(mLocalFilename.length()-4, 4);
- mDeleteLocalOnCompletion = (delete_local_on_completion && exten == ".tmp");
- }
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer_File::cleanup ()
-{
- if (mFp)
- {
- fclose(mFp);
- mFp = NULL;
- }
-
- LLFile::remove(mTempFilename, ENOENT);
-
- if (mDeleteLocalOnCompletion)
- {
- LL_DEBUGS("Xfer") << "Removing file: " << mLocalFilename << LL_ENDL;
- LLFile::remove(mLocalFilename, ENOENT);
- }
- else
- {
- LL_DEBUGS("Xfer") << "Keeping local file: " << mLocalFilename << LL_ENDL;
- }
-
- LLXfer::cleanup();
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_File::initializeRequest(U64 xfer_id,
- const std::string& local_filename,
- const std::string& remote_filename,
- ELLPath remote_path,
- const LLHost& remote_host,
- bool delete_remote_on_completion,
- void (*callback)(void**,S32,LLExtStat),
- void** user_data)
-{
- S32 retval = 0; // presume success
-
- mID = xfer_id;
- mLocalFilename = local_filename;
- mRemoteFilename = remote_filename;
- mRemotePath = remote_path;
- mRemoteHost = remote_host;
- mDeleteRemoteOnCompletion = delete_remote_on_completion;
-
- mTempFilename = gDirUtilp->getTempFilename();
-
- mCallback = callback;
- mCallbackDataHandle = user_data;
- mCallbackResult = LL_ERR_NOERR;
-
- LL_INFOS("Xfer") << "Requesting xfer from " << remote_host << " for file: " << mLocalFilename << LL_ENDL;
-
- if (mBuffer)
- {
- delete(mBuffer);
- mBuffer = NULL;
- }
-
- mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
- mBufferLength = 0;
-
- mPacketNum = 0;
-
- mStatus = e_LL_XFER_PENDING;
- return retval;
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_File::startDownload()
-{
- S32 retval = 0; // presume success
- mFp = LLFile::fopen(mTempFilename,"w+b"); /* Flawfinder : ignore */
- if (mFp)
- {
- fclose(mFp);
- mFp = NULL;
-
- // tbd - is it premature to send this message if the queue is backed up?
- gMessageSystem->newMessageFast(_PREHASH_RequestXfer);
- gMessageSystem->nextBlockFast(_PREHASH_XferID);
- gMessageSystem->addU64Fast(_PREHASH_ID, mID);
- gMessageSystem->addStringFast(_PREHASH_Filename, mRemoteFilename);
- gMessageSystem->addU8("FilePath", (U8) mRemotePath);
- gMessageSystem->addBOOL("DeleteOnCompletion", mDeleteRemoteOnCompletion);
- gMessageSystem->addBOOL("UseBigPackets", mChunkSize == LL_XFER_LARGE_PAYLOAD);
- gMessageSystem->addUUIDFast(_PREHASH_VFileID, LLUUID::null);
- gMessageSystem->addS16Fast(_PREHASH_VFileType, -1);
-
- gMessageSystem->sendReliable(mRemoteHost);
- mStatus = e_LL_XFER_IN_PROGRESS;
- }
- else
- {
- LL_WARNS("Xfer") << "Couldn't create file to be received!" << LL_ENDL;
- retval = -1;
- }
-
- return (retval);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_File::startSend (U64 xfer_id, const LLHost &remote_host)
-{
- S32 retval = LL_ERR_NOERR; // presume success
-
- mRemoteHost = remote_host;
- mID = xfer_id;
- mPacketNum = -1;
-
-// cout << "Sending file: " << mLocalFilename << endl;
-
- delete [] mBuffer;
- mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
-
- mBufferLength = 0;
- mBufferStartOffset = 0;
-
- // We leave the file open, assuming we'll start reading and sending soon
- mFp = LLFile::fopen(mLocalFilename,"rb"); /* Flawfinder : ignore */
- if (mFp)
- {
- fseek(mFp,0,SEEK_END);
-
- S32 file_size = ftell(mFp);
- if (file_size <= 0)
- {
- return LL_ERR_FILE_EMPTY;
- }
- setXferSize(file_size);
-
- fseek(mFp,0,SEEK_SET);
- }
- else
- {
- LL_INFOS("Xfer") << "Warning: " << mLocalFilename << " not found." << LL_ENDL;
- return (LL_ERR_FILE_NOT_FOUND);
- }
-
- mStatus = e_LL_XFER_PENDING;
-
- return (retval);
-}
-
-///////////////////////////////////////////////////////////
-void LLXfer_File::closeFileHandle()
-{
- if (mFp)
- {
- fclose(mFp);
- mFp = NULL;
- }
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_File::reopenFileHandle()
-{
- S32 retval = LL_ERR_NOERR; // presume success
-
- if (mFp == NULL)
- {
- mFp = LLFile::fopen(mLocalFilename,"rb"); /* Flawfinder : ignore */
- if (mFp == NULL)
- {
- LL_INFOS("Xfer") << "Warning: " << mLocalFilename << " not found when re-opening file" << LL_ENDL;
- retval = LL_ERR_FILE_NOT_FOUND;
- }
- }
-
- return retval;
-}
-
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_File::getMaxBufferSize ()
-{
- return(LL_MAX_XFER_FILE_BUFFER);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_File::suck(S32 start_position)
-{
- S32 retval = 0;
-
- if (mFp)
- {
- // grab a buffer from the right place in the file
- fseek (mFp,start_position,SEEK_SET);
-
- mBufferLength = (U32)fread(mBuffer,1,LL_MAX_XFER_FILE_BUFFER,mFp);
- mBufferStartOffset = start_position;
-
- if (feof(mFp))
- {
- mBufferContainsEOF = true;
- }
- else
- {
- mBufferContainsEOF = false;
- }
- }
- else
- {
- retval = -1;
- }
-
- return (retval);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_File::flush()
-{
- S32 retval = 0;
- if (mBufferLength)
- {
- if (mFp)
- {
- LL_ERRS("Xfer") << "Overwriting open file pointer!" << LL_ENDL;
- }
- mFp = LLFile::fopen(mTempFilename,"a+b"); /* Flawfinder : ignore */
-
- if (mFp)
- {
- S32 write_size = fwrite(mBuffer,1,mBufferLength,mFp);
- if (write_size != mBufferLength)
- {
- LL_WARNS("Xfer") << "Non-matching write size, requested " << mBufferLength
- << " but wrote " << write_size
- << LL_ENDL;
- }
-
-// LL_INFOS("Xfer") << "******* wrote " << mBufferLength << " bytes of file xfer" << LL_ENDL;
- fclose(mFp);
- mFp = NULL;
-
- mBufferLength = 0;
- }
- else
- {
- LL_WARNS("Xfer") << "LLXfer_File::flush() unable to open " << mTempFilename << " for writing!" << LL_ENDL;
- retval = LL_ERR_CANNOT_OPEN_FILE;
- }
- }
- return (retval);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_File::processEOF()
-{
- S32 retval = 0;
- mStatus = e_LL_XFER_COMPLETE;
-
- S32 flushval = flush();
-
- // If we have no other errors, our error becomes the error generated by
- // flush.
- if (!mCallbackResult)
- {
- mCallbackResult = flushval;
- }
-
- LLFile::remove(mLocalFilename, ENOENT);
-
- if (!mCallbackResult)
- {
- if (LLFile::rename(mTempFilename,mLocalFilename))
- {
-#if !LL_WINDOWS
- S32 error_number = errno;
- LL_INFOS("Xfer") << "Rename failure (" << error_number << ") - "
- << mTempFilename << " to " << mLocalFilename << LL_ENDL;
- if(EXDEV == error_number)
- {
- if(copy_file(mTempFilename, mLocalFilename) == 0)
- {
- LL_INFOS("Xfer") << "Rename across mounts; copying+unlinking the file instead." << LL_ENDL;
- unlink(mTempFilename.c_str());
- }
- else
- {
- LL_WARNS("Xfer") << "Copy failure - " << mTempFilename << " to "
- << mLocalFilename << LL_ENDL;
- }
- }
- else
- {
- //LLFILE* fp = LLFile::fopen(mTempFilename, "r");
- //LL_WARNS() << "File " << mTempFilename << " does "
- // << (!fp ? "not" : "" ) << " exit." << LL_ENDL;
- //if(fp) fclose(fp);
- //fp = LLFile::fopen(mLocalFilename, "r");
- //LL_WARNS() << "File " << mLocalFilename << " does "
- // << (!fp ? "not" : "" ) << " exit." << LL_ENDL;
- //if(fp) fclose(fp);
- LL_WARNS("Xfer") << "Rename fatally failed, can only handle EXDEV ("
- << EXDEV << ")" << LL_ENDL;
- }
-#else
- LL_WARNS("Xfer") << "Rename failure - " << mTempFilename << " to "
- << mLocalFilename << LL_ENDL;
-#endif
- }
- }
-
- if (mFp)
- {
- fclose(mFp);
- mFp = NULL;
- }
-
- retval = LLXfer::processEOF();
-
- return(retval);
-}
-
-///////////////////////////////////////////////////////////
-
-bool LLXfer_File::matchesLocalFilename(const std::string& filename)
-{
- return (filename == mLocalFilename);
-}
-
-///////////////////////////////////////////////////////////
-
-bool LLXfer_File::matchesRemoteFilename(const std::string& filename, ELLPath remote_path)
-{
- return ((filename == mRemoteFilename) && (remote_path == mRemotePath));
-}
-
-
-///////////////////////////////////////////////////////////
-
-std::string LLXfer_File::getFileName()
-{
- return mLocalFilename;
-}
-
-///////////////////////////////////////////////////////////
-
-// hacky - doesn't matter what this is
-// as long as it's different from the other classes
-U32 LLXfer_File::getXferTypeTag()
-{
- return LLXfer::XFER_FILE;
-}
-
-///////////////////////////////////////////////////////////
-
-#if !LL_WINDOWS
-
-// This is really close to, but not quite a general purpose copy
-// function. It does not really spam enough information, but is useful
-// for this cpp file, because this should never be called in a
-// production environment.
-S32 copy_file(const std::string& from, const std::string& to)
-{
- S32 rv = 0;
- LLFILE* in = LLFile::fopen(from, "rb"); /*Flawfinder: ignore*/
- LLFILE* out = LLFile::fopen(to, "wb"); /*Flawfinder: ignore*/
- if(in && out)
- {
- S32 read = 0;
- const S32 COPY_BUFFER_SIZE = 16384;
- U8 buffer[COPY_BUFFER_SIZE];
- while(((read = fread(buffer, 1, sizeof(buffer), in)) > 0)
- && (fwrite(buffer, 1, read, out) == (U32)read)); /* Flawfinder : ignore */
- if(ferror(in) || ferror(out)) rv = -2;
- }
- else
- {
- rv = -1;
- }
- if(in) fclose(in);
- if(out) fclose(out);
- return rv;
-}
-#endif
-
+/** + * @file llxfer_file.cpp + * @brief implementation of LLXfer_File class for a single xfer (file) + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#if !LL_WINDOWS +#include <errno.h> +#include <unistd.h> +#endif + +#include "llxfer_file.h" +#include "lluuid.h" +#include "llerror.h" +#include "llmath.h" +#include "llstring.h" +#include "lldir.h" + +// size of chunks read from/written to disk +const U32 LL_MAX_XFER_FILE_BUFFER = 65536; + +// local function to copy a file +S32 copy_file(const std::string& from, const std::string& to); + +/////////////////////////////////////////////////////////// + +LLXfer_File::LLXfer_File (S32 chunk_size) +: LLXfer(chunk_size) +{ + init(LLStringUtil::null, false, chunk_size); +} + +LLXfer_File::LLXfer_File (const std::string& local_filename, bool delete_local_on_completion, S32 chunk_size) +: LLXfer(chunk_size) +{ + init(local_filename, delete_local_on_completion, chunk_size); +} + +/////////////////////////////////////////////////////////// + +LLXfer_File::~LLXfer_File () +{ + cleanup(); +} + +/////////////////////////////////////////////////////////// + +void LLXfer_File::init (const std::string& local_filename, bool delete_local_on_completion, S32 chunk_size) +{ + + mFp = NULL; + mLocalFilename.clear(); + mRemoteFilename.clear(); + mRemotePath = LL_PATH_NONE; + mTempFilename.clear(); + mDeleteLocalOnCompletion = false; + mDeleteRemoteOnCompletion = false; + + if (!local_filename.empty()) + { + mLocalFilename = local_filename.substr(0,LL_MAX_PATH-1); + + // You can only automatically delete .tmp file as a safeguard against nasty messages. + std::string exten = mLocalFilename.substr(mLocalFilename.length()-4, 4); + mDeleteLocalOnCompletion = (delete_local_on_completion && exten == ".tmp"); + } +} + +/////////////////////////////////////////////////////////// + +void LLXfer_File::cleanup () +{ + if (mFp) + { + fclose(mFp); + mFp = NULL; + } + + LLFile::remove(mTempFilename, ENOENT); + + if (mDeleteLocalOnCompletion) + { + LL_DEBUGS("Xfer") << "Removing file: " << mLocalFilename << LL_ENDL; + LLFile::remove(mLocalFilename, ENOENT); + } + else + { + LL_DEBUGS("Xfer") << "Keeping local file: " << mLocalFilename << LL_ENDL; + } + + LLXfer::cleanup(); +} + +/////////////////////////////////////////////////////////// + +S32 LLXfer_File::initializeRequest(U64 xfer_id, + const std::string& local_filename, + const std::string& remote_filename, + ELLPath remote_path, + const LLHost& remote_host, + bool delete_remote_on_completion, + void (*callback)(void**,S32,LLExtStat), + void** user_data) +{ + S32 retval = 0; // presume success + + mID = xfer_id; + mLocalFilename = local_filename; + mRemoteFilename = remote_filename; + mRemotePath = remote_path; + mRemoteHost = remote_host; + mDeleteRemoteOnCompletion = delete_remote_on_completion; + + mTempFilename = gDirUtilp->getTempFilename(); + + mCallback = callback; + mCallbackDataHandle = user_data; + mCallbackResult = LL_ERR_NOERR; + + LL_INFOS("Xfer") << "Requesting xfer from " << remote_host << " for file: " << mLocalFilename << LL_ENDL; + + if (mBuffer) + { + delete(mBuffer); + mBuffer = NULL; + } + + mBuffer = new char[LL_MAX_XFER_FILE_BUFFER]; + mBufferLength = 0; + + mPacketNum = 0; + + mStatus = e_LL_XFER_PENDING; + return retval; +} + +/////////////////////////////////////////////////////////// + +S32 LLXfer_File::startDownload() +{ + S32 retval = 0; // presume success + mFp = LLFile::fopen(mTempFilename,"w+b"); /* Flawfinder : ignore */ + if (mFp) + { + fclose(mFp); + mFp = NULL; + + // tbd - is it premature to send this message if the queue is backed up? + gMessageSystem->newMessageFast(_PREHASH_RequestXfer); + gMessageSystem->nextBlockFast(_PREHASH_XferID); + gMessageSystem->addU64Fast(_PREHASH_ID, mID); + gMessageSystem->addStringFast(_PREHASH_Filename, mRemoteFilename); + gMessageSystem->addU8("FilePath", (U8) mRemotePath); + gMessageSystem->addBOOL("DeleteOnCompletion", mDeleteRemoteOnCompletion); + gMessageSystem->addBOOL("UseBigPackets", mChunkSize == LL_XFER_LARGE_PAYLOAD); + gMessageSystem->addUUIDFast(_PREHASH_VFileID, LLUUID::null); + gMessageSystem->addS16Fast(_PREHASH_VFileType, -1); + + gMessageSystem->sendReliable(mRemoteHost); + mStatus = e_LL_XFER_IN_PROGRESS; + } + else + { + LL_WARNS("Xfer") << "Couldn't create file to be received!" << LL_ENDL; + retval = -1; + } + + return (retval); +} + +/////////////////////////////////////////////////////////// + +S32 LLXfer_File::startSend (U64 xfer_id, const LLHost &remote_host) +{ + S32 retval = LL_ERR_NOERR; // presume success + + mRemoteHost = remote_host; + mID = xfer_id; + mPacketNum = -1; + +// cout << "Sending file: " << mLocalFilename << endl; + + delete [] mBuffer; + mBuffer = new char[LL_MAX_XFER_FILE_BUFFER]; + + mBufferLength = 0; + mBufferStartOffset = 0; + + // We leave the file open, assuming we'll start reading and sending soon + mFp = LLFile::fopen(mLocalFilename,"rb"); /* Flawfinder : ignore */ + if (mFp) + { + fseek(mFp,0,SEEK_END); + + S32 file_size = ftell(mFp); + if (file_size <= 0) + { + return LL_ERR_FILE_EMPTY; + } + setXferSize(file_size); + + fseek(mFp,0,SEEK_SET); + } + else + { + LL_INFOS("Xfer") << "Warning: " << mLocalFilename << " not found." << LL_ENDL; + return (LL_ERR_FILE_NOT_FOUND); + } + + mStatus = e_LL_XFER_PENDING; + + return (retval); +} + +/////////////////////////////////////////////////////////// +void LLXfer_File::closeFileHandle() +{ + if (mFp) + { + fclose(mFp); + mFp = NULL; + } +} + +/////////////////////////////////////////////////////////// + +S32 LLXfer_File::reopenFileHandle() +{ + S32 retval = LL_ERR_NOERR; // presume success + + if (mFp == NULL) + { + mFp = LLFile::fopen(mLocalFilename,"rb"); /* Flawfinder : ignore */ + if (mFp == NULL) + { + LL_INFOS("Xfer") << "Warning: " << mLocalFilename << " not found when re-opening file" << LL_ENDL; + retval = LL_ERR_FILE_NOT_FOUND; + } + } + + return retval; +} + + +/////////////////////////////////////////////////////////// + +S32 LLXfer_File::getMaxBufferSize () +{ + return(LL_MAX_XFER_FILE_BUFFER); +} + +/////////////////////////////////////////////////////////// + +S32 LLXfer_File::suck(S32 start_position) +{ + S32 retval = 0; + + if (mFp) + { + // grab a buffer from the right place in the file + fseek (mFp,start_position,SEEK_SET); + + mBufferLength = (U32)fread(mBuffer,1,LL_MAX_XFER_FILE_BUFFER,mFp); + mBufferStartOffset = start_position; + + if (feof(mFp)) + { + mBufferContainsEOF = true; + } + else + { + mBufferContainsEOF = false; + } + } + else + { + retval = -1; + } + + return (retval); +} + +/////////////////////////////////////////////////////////// + +S32 LLXfer_File::flush() +{ + S32 retval = 0; + if (mBufferLength) + { + if (mFp) + { + LL_ERRS("Xfer") << "Overwriting open file pointer!" << LL_ENDL; + } + mFp = LLFile::fopen(mTempFilename,"a+b"); /* Flawfinder : ignore */ + + if (mFp) + { + S32 write_size = fwrite(mBuffer,1,mBufferLength,mFp); + if (write_size != mBufferLength) + { + LL_WARNS("Xfer") << "Non-matching write size, requested " << mBufferLength + << " but wrote " << write_size + << LL_ENDL; + } + +// LL_INFOS("Xfer") << "******* wrote " << mBufferLength << " bytes of file xfer" << LL_ENDL; + fclose(mFp); + mFp = NULL; + + mBufferLength = 0; + } + else + { + LL_WARNS("Xfer") << "LLXfer_File::flush() unable to open " << mTempFilename << " for writing!" << LL_ENDL; + retval = LL_ERR_CANNOT_OPEN_FILE; + } + } + return (retval); +} + +/////////////////////////////////////////////////////////// + +S32 LLXfer_File::processEOF() +{ + S32 retval = 0; + mStatus = e_LL_XFER_COMPLETE; + + S32 flushval = flush(); + + // If we have no other errors, our error becomes the error generated by + // flush. + if (!mCallbackResult) + { + mCallbackResult = flushval; + } + + LLFile::remove(mLocalFilename, ENOENT); + + if (!mCallbackResult) + { + if (LLFile::rename(mTempFilename,mLocalFilename)) + { +#if !LL_WINDOWS + S32 error_number = errno; + LL_INFOS("Xfer") << "Rename failure (" << error_number << ") - " + << mTempFilename << " to " << mLocalFilename << LL_ENDL; + if(EXDEV == error_number) + { + if(copy_file(mTempFilename, mLocalFilename) == 0) + { + LL_INFOS("Xfer") << "Rename across mounts; copying+unlinking the file instead." << LL_ENDL; + unlink(mTempFilename.c_str()); + } + else + { + LL_WARNS("Xfer") << "Copy failure - " << mTempFilename << " to " + << mLocalFilename << LL_ENDL; + } + } + else + { + //LLFILE* fp = LLFile::fopen(mTempFilename, "r"); + //LL_WARNS() << "File " << mTempFilename << " does " + // << (!fp ? "not" : "" ) << " exit." << LL_ENDL; + //if(fp) fclose(fp); + //fp = LLFile::fopen(mLocalFilename, "r"); + //LL_WARNS() << "File " << mLocalFilename << " does " + // << (!fp ? "not" : "" ) << " exit." << LL_ENDL; + //if(fp) fclose(fp); + LL_WARNS("Xfer") << "Rename fatally failed, can only handle EXDEV (" + << EXDEV << ")" << LL_ENDL; + } +#else + LL_WARNS("Xfer") << "Rename failure - " << mTempFilename << " to " + << mLocalFilename << LL_ENDL; +#endif + } + } + + if (mFp) + { + fclose(mFp); + mFp = NULL; + } + + retval = LLXfer::processEOF(); + + return(retval); +} + +/////////////////////////////////////////////////////////// + +bool LLXfer_File::matchesLocalFilename(const std::string& filename) +{ + return (filename == mLocalFilename); +} + +/////////////////////////////////////////////////////////// + +bool LLXfer_File::matchesRemoteFilename(const std::string& filename, ELLPath remote_path) +{ + return ((filename == mRemoteFilename) && (remote_path == mRemotePath)); +} + + +/////////////////////////////////////////////////////////// + +std::string LLXfer_File::getFileName() +{ + return mLocalFilename; +} + +/////////////////////////////////////////////////////////// + +// hacky - doesn't matter what this is +// as long as it's different from the other classes +U32 LLXfer_File::getXferTypeTag() +{ + return LLXfer::XFER_FILE; +} + +/////////////////////////////////////////////////////////// + +#if !LL_WINDOWS + +// This is really close to, but not quite a general purpose copy +// function. It does not really spam enough information, but is useful +// for this cpp file, because this should never be called in a +// production environment. +S32 copy_file(const std::string& from, const std::string& to) +{ + S32 rv = 0; + LLFILE* in = LLFile::fopen(from, "rb"); /*Flawfinder: ignore*/ + LLFILE* out = LLFile::fopen(to, "wb"); /*Flawfinder: ignore*/ + if(in && out) + { + S32 read = 0; + const S32 COPY_BUFFER_SIZE = 16384; + U8 buffer[COPY_BUFFER_SIZE]; + while(((read = fread(buffer, 1, sizeof(buffer), in)) > 0) + && (fwrite(buffer, 1, read, out) == (U32)read)); /* Flawfinder : ignore */ + if(ferror(in) || ferror(out)) rv = -2; + } + else + { + rv = -1; + } + if(in) fclose(in); + if(out) fclose(out); + return rv; +} +#endif + |