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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llxfer_file.cpp
  3.  * @brief implementation of LLXfer_File class for a single xfer (file)
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #if !LL_WINDOWS
  34. #include <errno.h>
  35. #include <unistd.h>
  36. #endif
  37. #include "llxfer_file.h"
  38. #include "lluuid.h"
  39. #include "llerror.h"
  40. #include "llmath.h"
  41. #include "llstring.h"
  42. #include "lldir.h"
  43. // size of chunks read from/written to disk
  44. const U32 LL_MAX_XFER_FILE_BUFFER = 65536;
  45. // local function to copy a file
  46. S32 copy_file(const std::string& from, const std::string& to);
  47. ///////////////////////////////////////////////////////////
  48. LLXfer_File::LLXfer_File (S32 chunk_size)
  49. : LLXfer(chunk_size)
  50. {
  51. init(LLStringUtil::null, FALSE, chunk_size);
  52. }
  53. LLXfer_File::LLXfer_File (const std::string& local_filename, BOOL delete_local_on_completion, S32 chunk_size)
  54. : LLXfer(chunk_size)
  55. {
  56. init(local_filename, delete_local_on_completion, chunk_size);
  57. }
  58. ///////////////////////////////////////////////////////////
  59. LLXfer_File::~LLXfer_File ()
  60. {
  61. cleanup();
  62. }
  63. ///////////////////////////////////////////////////////////
  64. void LLXfer_File::init (const std::string& local_filename, BOOL delete_local_on_completion, S32 chunk_size)
  65. {
  66. mFp = NULL;
  67. mLocalFilename.clear();
  68. mRemoteFilename.clear();
  69. mRemotePath = LL_PATH_NONE;
  70. mTempFilename.clear();
  71. mDeleteLocalOnCompletion = FALSE;
  72. mDeleteRemoteOnCompletion = FALSE;
  73. if (!local_filename.empty())
  74. {
  75. mLocalFilename =  local_filename.substr(0,LL_MAX_PATH-1);
  76. // You can only automatically delete .tmp file as a safeguard against nasty messages.
  77. std::string exten = mLocalFilename.substr(mLocalFilename.length()-4, 4);
  78. mDeleteLocalOnCompletion = (delete_local_on_completion && exten == ".tmp");
  79. }
  80. }
  81. ///////////////////////////////////////////////////////////
  82. void LLXfer_File::cleanup ()
  83. {
  84. if (mFp)
  85. {
  86. fclose(mFp);
  87. mFp = NULL;
  88. }
  89. LLFile::remove(mTempFilename);
  90. if (mDeleteLocalOnCompletion)
  91. {
  92. lldebugs << "Removing file: " << mLocalFilename << llendl;
  93. LLFile::remove(mLocalFilename);
  94. }
  95. else
  96. {
  97. lldebugs << "Keeping local file: " << mLocalFilename << llendl;
  98. }
  99. LLXfer::cleanup();
  100. }
  101. ///////////////////////////////////////////////////////////
  102. S32 LLXfer_File::initializeRequest(U64 xfer_id,
  103.    const std::string& local_filename,
  104.    const std::string& remote_filename,
  105.    ELLPath remote_path,
  106.    const LLHost& remote_host,
  107.    BOOL delete_remote_on_completion,
  108.    void (*callback)(void**,S32,LLExtStat),
  109.    void** user_data)
  110. {
  111.   S32 retval = 0;  // presume success
  112. mID = xfer_id;
  113. mLocalFilename = local_filename;
  114. mRemoteFilename = remote_filename;
  115. mRemotePath = remote_path;
  116. mRemoteHost = remote_host;
  117. mDeleteRemoteOnCompletion = delete_remote_on_completion;
  118. mTempFilename = gDirUtilp->getTempFilename();
  119. mCallback = callback;
  120. mCallbackDataHandle = user_data;
  121. mCallbackResult = LL_ERR_NOERR;
  122. llinfos << "Requesting xfer from " << remote_host << " for file: " << mLocalFilename << llendl;
  123. if (mBuffer)
  124. {
  125. delete(mBuffer);
  126. mBuffer = NULL;
  127. }
  128. mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
  129. mBufferLength = 0;
  130. mPacketNum = 0;
  131.   mStatus = e_LL_XFER_PENDING;
  132. return retval;
  133. }
  134. ///////////////////////////////////////////////////////////
  135. S32 LLXfer_File::startDownload()
  136. {
  137.   S32 retval = 0;  // presume success
  138. mFp = LLFile::fopen(mTempFilename,"w+b"); /* Flawfinder : ignore */
  139. if (mFp)
  140. {
  141. fclose(mFp);
  142. mFp = NULL;
  143. gMessageSystem->newMessageFast(_PREHASH_RequestXfer);
  144. gMessageSystem->nextBlockFast(_PREHASH_XferID);
  145. gMessageSystem->addU64Fast(_PREHASH_ID, mID);
  146. gMessageSystem->addStringFast(_PREHASH_Filename, mRemoteFilename);
  147. gMessageSystem->addU8("FilePath", (U8) mRemotePath);
  148. gMessageSystem->addBOOL("DeleteOnCompletion", mDeleteRemoteOnCompletion);
  149. gMessageSystem->addBOOL("UseBigPackets", BOOL(mChunkSize == LL_XFER_LARGE_PAYLOAD));
  150. gMessageSystem->addUUIDFast(_PREHASH_VFileID, LLUUID::null);
  151. gMessageSystem->addS16Fast(_PREHASH_VFileType, -1);
  152. gMessageSystem->sendReliable(mRemoteHost);
  153. mStatus = e_LL_XFER_IN_PROGRESS;
  154. }
  155. else
  156. {
  157. llwarns << "Couldn't create file to be received!" << llendl;
  158. retval = -1;
  159. }
  160. return (retval);
  161. }
  162. ///////////////////////////////////////////////////////////
  163. S32 LLXfer_File::startSend (U64 xfer_id, const LLHost &remote_host)
  164. {
  165. S32 retval = LL_ERR_NOERR;  // presume success
  166.     mRemoteHost = remote_host;
  167. mID = xfer_id;
  168.     mPacketNum = -1;
  169. // cout << "Sending file: " << mLocalFilename << endl;
  170. delete [] mBuffer;
  171. mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
  172. mBufferLength = 0;
  173. mBufferStartOffset = 0;
  174. mFp = LLFile::fopen(mLocalFilename,"rb"); /* Flawfinder : ignore */
  175. if (mFp)
  176. {
  177. fseek(mFp,0,SEEK_END);
  178. S32 file_size = ftell(mFp);
  179. if (file_size <= 0)
  180. {
  181. return LL_ERR_FILE_EMPTY;
  182. }
  183. setXferSize(file_size);
  184. fseek(mFp,0,SEEK_SET);
  185. }
  186. else
  187. {
  188. llinfos << "Warning: " << mLocalFilename << " not found." << llendl;
  189. return (LL_ERR_FILE_NOT_FOUND);
  190. }
  191. mStatus = e_LL_XFER_PENDING;
  192. return (retval);
  193. }
  194. ///////////////////////////////////////////////////////////
  195. S32 LLXfer_File::getMaxBufferSize ()
  196. {
  197. return(LL_MAX_XFER_FILE_BUFFER);
  198. }
  199. ///////////////////////////////////////////////////////////
  200. S32 LLXfer_File::suck(S32 start_position)
  201. {
  202. S32 retval = 0;
  203. if (mFp)
  204. {
  205. // grab a buffer from the right place in the file
  206. fseek (mFp,start_position,SEEK_SET);
  207. mBufferLength = (U32)fread(mBuffer,1,LL_MAX_XFER_FILE_BUFFER,mFp);
  208. mBufferStartOffset = start_position;
  209. if (feof(mFp))
  210. {
  211. mBufferContainsEOF = TRUE;
  212. }
  213. else
  214. {
  215. mBufferContainsEOF = FALSE;
  216. }
  217. }
  218. else
  219. {
  220. retval = -1;
  221. }
  222. return (retval);
  223. }
  224. ///////////////////////////////////////////////////////////
  225. S32 LLXfer_File::flush()
  226. {
  227. S32 retval = 0;
  228. if (mBufferLength)
  229. {
  230. if (mFp)
  231. {
  232. llerrs << "Overwriting open file pointer!" << llendl;
  233. }
  234. mFp = LLFile::fopen(mTempFilename,"a+b"); /* Flawfinder : ignore */
  235. if (mFp)
  236. {
  237. if (fwrite(mBuffer,1,mBufferLength,mFp) != mBufferLength)
  238. {
  239. llwarns << "Short write" << llendl;
  240. }
  241. // llinfos << "******* wrote " << mBufferLength << " bytes of file xfer" << llendl;
  242. fclose(mFp);
  243. mFp = NULL;
  244. mBufferLength = 0;
  245. }
  246. else
  247. {
  248. llwarns << "LLXfer_File::flush() unable to open " << mTempFilename << " for writing!" << llendl;
  249. retval = LL_ERR_CANNOT_OPEN_FILE;
  250. }
  251. }
  252. return (retval);
  253. }
  254. ///////////////////////////////////////////////////////////
  255. S32 LLXfer_File::processEOF()
  256. {
  257. S32 retval = 0;
  258. mStatus = e_LL_XFER_COMPLETE;
  259. S32 flushval = flush();
  260. // If we have no other errors, our error becomes the error generated by
  261. // flush.
  262. if (!mCallbackResult)
  263. {
  264. mCallbackResult = flushval;
  265. }
  266. LLFile::remove(mLocalFilename);
  267. if (!mCallbackResult)
  268. {
  269. if (LLFile::rename(mTempFilename,mLocalFilename))
  270. {
  271. #if !LL_WINDOWS
  272. S32 error_number = errno;
  273. llinfos << "Rename failure (" << error_number << ") - "
  274. << mTempFilename << " to " << mLocalFilename << llendl;
  275. if(EXDEV == error_number)
  276. {
  277. if(copy_file(mTempFilename, mLocalFilename) == 0)
  278. {
  279. llinfos << "Rename across mounts; copying+unlinking the file instead." << llendl;
  280. unlink(mTempFilename.c_str());
  281. }
  282. else
  283. {
  284. llwarns << "Copy failure - " << mTempFilename << " to "
  285. << mLocalFilename << llendl;
  286. }
  287. }
  288. else
  289. {
  290. //LLFILE* fp = LLFile::fopen(mTempFilename, "r");
  291. //llwarns << "File " << mTempFilename << " does "
  292. // << (!fp ? "not" : "" ) << " exit." << llendl;
  293. //if(fp) fclose(fp);
  294. //fp = LLFile::fopen(mLocalFilename, "r");
  295. //llwarns << "File " << mLocalFilename << " does "
  296. // << (!fp ? "not" : "" ) << " exit." << llendl;
  297. //if(fp) fclose(fp);
  298. llwarns << "Rename fatally failed, can only handle EXDEV ("
  299. << EXDEV << ")" << llendl;
  300. }
  301. #else
  302. llwarns << "Rename failure - " << mTempFilename << " to "
  303. << mLocalFilename << llendl;
  304. #endif
  305. }
  306. }
  307. if (mFp)
  308. {
  309. fclose(mFp);
  310. mFp = NULL;
  311. }
  312. retval = LLXfer::processEOF();
  313. return(retval);
  314. }
  315. ///////////////////////////////////////////////////////////
  316. BOOL LLXfer_File::matchesLocalFilename(const std::string& filename) 
  317. {
  318. return (filename == mLocalFilename);
  319. }
  320. ///////////////////////////////////////////////////////////
  321. BOOL LLXfer_File::matchesRemoteFilename(const std::string& filename, ELLPath remote_path) 
  322. {
  323. return ((filename == mRemoteFilename) && (remote_path == mRemotePath));
  324. }
  325. ///////////////////////////////////////////////////////////
  326. std::string LLXfer_File::getFileName() 
  327. {
  328. return mLocalFilename;
  329. }
  330. ///////////////////////////////////////////////////////////
  331. // hacky - doesn't matter what this is
  332. // as long as it's different from the other classes
  333. U32 LLXfer_File::getXferTypeTag()
  334. {
  335. return LLXfer::XFER_FILE;
  336. }
  337. ///////////////////////////////////////////////////////////
  338. #if !LL_WINDOWS
  339. // This is really close to, but not quite a general purpose copy
  340. // function. It does not really spam enough information, but is useful
  341. // for this cpp file, because this should never be called in a
  342. // production environment.
  343. S32 copy_file(const std::string& from, const std::string& to)
  344. {
  345. S32 rv = 0;
  346. LLFILE* in = LLFile::fopen(from, "rb"); /*Flawfinder: ignore*/
  347. LLFILE* out = LLFile::fopen(to, "wb"); /*Flawfinder: ignore*/
  348. if(in && out)
  349. {
  350. S32 read = 0;
  351. const S32 COPY_BUFFER_SIZE = 16384;
  352. U8 buffer[COPY_BUFFER_SIZE];
  353. while(((read = fread(buffer, 1, sizeof(buffer), in)) > 0)
  354.   && (fwrite(buffer, 1, read, out) == (U32)read)); /* Flawfinder : ignore */
  355. if(ferror(in) || ferror(out)) rv = -2;
  356. }
  357. else
  358. {
  359. rv = -1;
  360. }
  361. if(in) fclose(in);
  362. if(out) fclose(out);
  363. return rv;
  364. }
  365. #endif