From 1ca268e36a2ddcbcf075b4a426f0678bafabfded Mon Sep 17 00:00:00 2001 From: Andrey Prygunkov Date: Thu, 7 Feb 2008 18:23:59 +0000 Subject: [PATCH] refactored: moved global functions in unit to new class to prevent possible conflicts with system functions; added error-reporting by moving completed files from tmp- to dst-directory and added code to move files across drives if renaming fails --- ArticleDownloader.cpp | 59 ++++++++++++------ BinRpc.cpp | 12 ++-- DiskState.cpp | 4 +- DownloadInfo.cpp | 15 ++--- Frontend.cpp | 8 +-- Log.cpp | 9 ++- Options.cpp | 16 +++-- ParChecker.cpp | 6 +- PrePostProcessor.cpp | 24 ++++---- QueueCoordinator.cpp | 2 +- RemoteClient.cpp | 8 +-- Util.cpp | 136 ++++++++++++++++++++++++++++++------------ Util.h | 71 ++++++++++++---------- XmlRpc.cpp | 58 +++++++++--------- 14 files changed, 256 insertions(+), 172 deletions(-) diff --git a/ArticleDownloader.cpp b/ArticleDownloader.cpp index 5019731f..198840d2 100644 --- a/ArticleDownloader.cpp +++ b/ArticleDownloader.cpp @@ -41,6 +41,7 @@ #include #endif #include +#include #include "nzbget.h" #include "ArticleDownloader.h" @@ -123,9 +124,7 @@ void ArticleDownloader::Run() if (g_pOptions->GetContinuePartial()) { - struct stat buffer; - bool fileExists = !stat(m_szResultFilename, &buffer); - if (fileExists) + if (Util::FileExists(m_szResultFilename)) { // file exists from previous program's start info("Article %s already downloaded, skipping", m_szInfoName); @@ -536,7 +535,7 @@ bool ArticleDownloader::PrepareFile(char* szLine) { pb += 5; //=strlen("size=") long iArticleFilesize = atol(pb); - if (!SetFileSize(m_szOutputFilename, iArticleFilesize)) + if (!Util::SetFileSize(m_szOutputFilename, iArticleFilesize)) { error("Could not create file %s!", m_szOutputFilename); return false; @@ -613,7 +612,10 @@ ArticleDownloader::EStatus ArticleDownloader::Decode() { if (bOK) { - rename(szDecoderTempFilename, m_szResultFilename); + if (!Util::MoveFile(szDecoderTempFilename, m_szResultFilename)) + { + error("Could not rename file %s to %s! Errcode: %i", szDecoderTempFilename, m_szResultFilename, errno); + } } else if (g_pOptions->GetDecoder() == Options::dcUulib) { @@ -673,8 +675,14 @@ ArticleDownloader::EStatus ArticleDownloader::Decode() else if (g_pOptions->GetDecoder() == Options::dcNone) { // rawmode - rename(m_szTempFilename, m_szResultFilename); - info("Article %s successfully downloaded", m_szInfoName); + if (Util::MoveFile(m_szTempFilename, m_szResultFilename)) + { + info("Article %s successfully downloaded", m_szInfoName); + } + else + { + error("Could not move file %s to %s! Errcode: %i", m_szTempFilename, m_szResultFilename, errno); + } return adFinished; } else @@ -694,7 +702,7 @@ void ArticleDownloader::LogDebugInfo() ctime_r(&m_tLastUpdateTime, szTime); #endif - debug(" Download: status=%s, LastUpdateTime=%s, filename=%s", GetStatusText(), szTime, BaseFileName(GetTempFilename())); + debug(" Download: status=%s, LastUpdateTime=%s, filename=%s", GetStatusText(), szTime, Util::BaseFileName(GetTempFilename())); } void ArticleDownloader::Stop() @@ -772,12 +780,16 @@ void ArticleDownloader::CompleteFileParts() ofn[1024-1] = '\0'; // Ensure the DstDir is created - mkdir(m_pFileInfo->GetNZBInfo()->GetDestDir(), S_DIRMODE); + if (!Util::CreateDirectory(m_pFileInfo->GetNZBInfo()->GetDestDir())) + { + error("Could not create directory %s! Errcode: %i", m_pFileInfo->GetNZBInfo()->GetDestDir(), errno); + SetStatus(adFinished); + return; + } // prevent overwriting existing files - struct stat statbuf; int dupcount = 0; - while (!stat(ofn, &statbuf)) + while (Util::FileExists(ofn)) { dupcount++; snprintf(ofn, 1024, "%s%c%s_duplicate%d", m_pFileInfo->GetNZBInfo()->GetDestDir(), (int)PATH_SEPARATOR, m_pFileInfo->GetFilename(), dupcount); @@ -813,7 +825,12 @@ void ArticleDownloader::CompleteFileParts() else if (g_pOptions->GetDecoder() == Options::dcNone) { remove(tmpdestfile); - mkdir(ofn, S_DIRMODE); + if (!Util::CreateDirectory(ofn)) + { + error("Could not create directory %s! Errcode: %i", ofn, errno); + SetStatus(adFinished); + return; + } } bool complete = true; @@ -870,7 +887,10 @@ void ArticleDownloader::CompleteFileParts() char dstFileName[1024]; snprintf(dstFileName, 1024, "%s%c%03i", ofn, (int)PATH_SEPARATOR, pa->GetPartNumber()); dstFileName[1024-1] = '\0'; - rename(fn, dstFileName); + if (!Util::MoveFile(fn, dstFileName)) + { + error("Could not move file %s to %s! Errcode: %i", fn, dstFileName, errno); + } } } @@ -882,12 +902,18 @@ void ArticleDownloader::CompleteFileParts() if (outfile) { fclose(outfile); - rename(tmpdestfile, ofn); + if (!Util::MoveFile(tmpdestfile, ofn)) + { + error("Could not move file %s to %s! Errcode: %i", tmpdestfile, ofn, errno); + } } if (g_pOptions->GetDirectWrite()) { - rename(m_szOutputFilename, ofn); + if (!Util::MoveFile(m_szOutputFilename, ofn)) + { + error("Could not move file %s to %s! Errcode: %i", m_szOutputFilename, ofn, errno); + } } if (!g_pOptions->GetDirectWrite() || g_pOptions->GetContinuePartial()) @@ -912,8 +938,7 @@ void ArticleDownloader::CompleteFileParts() char brokenfn[1024]; snprintf(brokenfn, 1024, "%s_broken", ofn); brokenfn[1024-1] = '\0'; - bool OK = rename(ofn, brokenfn) == 0; - if (OK) + if (Util::MoveFile(ofn, brokenfn)) { info("Renaming broken file from %s to %s", ofn, brokenfn); } diff --git a/BinRpc.cpp b/BinRpc.cpp index 5fef4103..d66983ac 100644 --- a/BinRpc.cpp +++ b/BinRpc.cpp @@ -317,14 +317,14 @@ void DownloadBinCommand::Execute() delete pNZBFile; char tmp[1024]; - snprintf(tmp, 1024, "Collection %s added to queue", BaseFileName(DownloadRequest.m_szFilename)); + snprintf(tmp, 1024, "Collection %s added to queue", Util::BaseFileName(DownloadRequest.m_szFilename)); tmp[1024-1] = '\0'; SendBoolResponse(true, tmp); } else { char tmp[1024]; - snprintf(tmp, 1024, "Download Request failed for %s", BaseFileName(DownloadRequest.m_szFilename)); + snprintf(tmp, 1024, "Download Request failed for %s", Util::BaseFileName(DownloadRequest.m_szFilename)); tmp[1024-1] = '\0'; SendBoolResponse(false, tmp); } @@ -376,10 +376,10 @@ void ListBinCommand::Execute() FileInfo* pFileInfo = *it; SNZBListResponseEntry* pListAnswer = (SNZBListResponseEntry*) bufptr; pListAnswer->m_iID = htonl(pFileInfo->GetID()); - SplitInt64(pFileInfo->GetSize(), &iSizeHi, &iSizeLo); + Util::SplitInt64(pFileInfo->GetSize(), &iSizeHi, &iSizeLo); pListAnswer->m_iFileSizeLo = htonl(iSizeLo); pListAnswer->m_iFileSizeHi = htonl(iSizeHi); - SplitInt64(pFileInfo->GetRemainingSize(), &iSizeHi, &iSizeLo); + Util::SplitInt64(pFileInfo->GetRemainingSize(), &iSizeHi, &iSizeLo); pListAnswer->m_iRemainingSizeLo = htonl(iSizeLo); pListAnswer->m_iRemainingSizeHi = htonl(iSizeHi); pListAnswer->m_bFilenameConfirmed = htonl(pFileInfo->GetFilenameConfirmed()); @@ -409,7 +409,7 @@ void ListBinCommand::Execute() { unsigned int iSizeHi, iSizeLo; ListResponse.m_iDownloadRate = htonl((int)(g_pQueueCoordinator->CalcCurrentDownloadSpeed() * 1024)); - SplitInt64(g_pQueueCoordinator->CalcRemainingSize(), &iSizeHi, &iSizeLo); + Util::SplitInt64(g_pQueueCoordinator->CalcRemainingSize(), &iSizeHi, &iSizeLo); ListResponse.m_iRemainingSizeHi = htonl(iSizeHi); ListResponse.m_iRemainingSizeLo = htonl(iSizeLo); ListResponse.m_iDownloadLimit = htonl((int)(g_pOptions->GetDownloadRate() * 1024)); @@ -426,7 +426,7 @@ void ListBinCommand::Execute() ListResponse.m_iUpTimeSec = htonl(iUpTimeSec); ListResponse.m_iDownloadTimeSec = htonl(iDnTimeSec); ListResponse.m_bServerStandBy = htonl(bStandBy); - SplitInt64(iAllBytes, &iSizeHi, &iSizeLo); + Util::SplitInt64(iAllBytes, &iSizeHi, &iSizeLo); ListResponse.m_iDownloadedBytesHi = htonl(iSizeHi); ListResponse.m_iDownloadedBytesLo = htonl(iSizeLo); } diff --git a/DiskState.cpp b/DiskState.cpp index 73d43edf..a6243507 100644 --- a/DiskState.cpp +++ b/DiskState.cpp @@ -404,9 +404,7 @@ bool DiskState::Exists() char fileName[1024]; snprintf(fileName, 1024, "%s%s", g_pOptions->GetQueueDir(), "queue"); fileName[1024-1] = '\0'; - struct stat buffer; - bool fileExists = !stat(fileName, &buffer); - return fileExists; + return Util::FileExists(fileName); } bool DiskState::DiscardFile(DownloadQueue* pDownloadQueue, FileInfo* pFileInfo) diff --git a/DownloadInfo.cpp b/DownloadInfo.cpp index 270b2fca..0403eb89 100644 --- a/DownloadInfo.cpp +++ b/DownloadInfo.cpp @@ -100,7 +100,7 @@ void NZBInfo::GetNiceNZBName(char* szBuffer, int iSize) void NZBInfo::MakeNiceNZBName(const char * szNZBFilename, char * szBuffer, int iSize) { char postname[1024]; - const char* szBaseName = BaseFileName(szNZBFilename); + const char* szBaseName = Util::BaseFileName(szNZBFilename); // if .nzb file has a certain structure, try to strip out certain elements if (sscanf(szBaseName, "msgid_%*d_%1023s", postname) == 1) @@ -117,7 +117,7 @@ void NZBInfo::MakeNiceNZBName(const char * szNZBFilename, char * szBuffer, int i // wipe out ".nzb" if (char* p = strrchr(postname, '.')) *p = '\0'; - ::MakeValidFilename(postname, '_'); + Util::MakeValidFilename(postname, '_'); // if the resulting name is empty, use basename without cleaning up "msgid_" if (strlen(postname) == 0) @@ -129,7 +129,7 @@ void NZBInfo::MakeNiceNZBName(const char * szNZBFilename, char * szBuffer, int i // wipe out ".nzb" if (char* p = strrchr(postname, '.')) *p = '\0'; - ::MakeValidFilename(postname, '_'); + Util::MakeValidFilename(postname, '_'); // if the resulting name is STILL empty, use "noname" if (strlen(postname) == 0) @@ -262,7 +262,7 @@ void FileInfo::SetFilename(const char* szFilename) void FileInfo::MakeValidFilename() { - ::MakeValidFilename(m_szFilename, '_'); + Util::MakeValidFilename(m_szFilename, '_'); } void FileInfo::LockOutputFile() @@ -277,19 +277,16 @@ void FileInfo::UnlockOutputFile() bool FileInfo::IsDupe(const char* szFilename) { - struct stat buffer; char fileName[1024]; snprintf(fileName, 1024, "%s%c%s", m_pNZBInfo->GetDestDir(), (int)PATH_SEPARATOR, szFilename); fileName[1024-1] = '\0'; - bool exists = !stat(fileName, &buffer); - if (exists) + if (Util::FileExists(fileName)) { return true; } snprintf(fileName, 1024, "%s%c%s_broken", m_pNZBInfo->GetDestDir(), (int)PATH_SEPARATOR, szFilename); fileName[1024-1] = '\0'; - exists = !stat(fileName, &buffer); - if (exists) + if (Util::FileExists(fileName)) { return true; } diff --git a/Frontend.cpp b/Frontend.cpp index 6663655a..6f6e43f0 100644 --- a/Frontend.cpp +++ b/Frontend.cpp @@ -351,7 +351,7 @@ bool Frontend::RequestFileList() if (m_bSummary) { m_bPause = ntohl(ListResponse.m_bServerPaused); - m_lRemainingSize = JoinInt64(ntohl(ListResponse.m_iRemainingSizeHi), ntohl(ListResponse.m_iRemainingSizeLo)); + m_lRemainingSize = Util::JoinInt64(ntohl(ListResponse.m_iRemainingSizeHi), ntohl(ListResponse.m_iRemainingSizeLo)); m_fCurrentDownloadSpeed = ntohl(ListResponse.m_iDownloadRate) / 1024.0; m_fDownloadLimit = ntohl(ListResponse.m_iDownloadLimit) / 1024.0; m_iThreadCount = ntohl(ListResponse.m_iThreadCount); @@ -359,7 +359,7 @@ bool Frontend::RequestFileList() m_iUpTimeSec = ntohl(ListResponse.m_iUpTimeSec); m_iDnTimeSec = ntohl(ListResponse.m_iDownloadTimeSec); m_bStandBy = ntohl(ListResponse.m_bServerStandBy); - m_iAllBytes = JoinInt64(ntohl(ListResponse.m_iDownloadedBytesHi), ntohl(ListResponse.m_iDownloadedBytesLo)); + m_iAllBytes = Util::JoinInt64(ntohl(ListResponse.m_iDownloadedBytesHi), ntohl(ListResponse.m_iDownloadedBytesLo)); } if (m_bFileList && ntohl(ListResponse.m_iTrailingDataLength) > 0) @@ -379,8 +379,8 @@ bool Frontend::RequestFileList() FileInfo* pFileInfo = new FileInfo(); pFileInfo->SetID(ntohl(pListAnswer->m_iID)); - pFileInfo->SetSize(JoinInt64(ntohl(pListAnswer->m_iFileSizeHi), ntohl(pListAnswer->m_iFileSizeLo))); - pFileInfo->SetRemainingSize(JoinInt64(ntohl(pListAnswer->m_iRemainingSizeHi), ntohl(pListAnswer->m_iRemainingSizeLo))); + pFileInfo->SetSize(Util::JoinInt64(ntohl(pListAnswer->m_iFileSizeHi), ntohl(pListAnswer->m_iFileSizeLo))); + pFileInfo->SetRemainingSize(Util::JoinInt64(ntohl(pListAnswer->m_iRemainingSizeHi), ntohl(pListAnswer->m_iRemainingSizeLo))); pFileInfo->SetPaused(ntohl(pListAnswer->m_bPaused)); pFileInfo->SetSubject(szSubject); pFileInfo->SetFilename(szFileName); diff --git a/Log.cpp b/Log.cpp index 9b6b6c15..5d477216 100644 --- a/Log.cpp +++ b/Log.cpp @@ -1,5 +1,5 @@ /* - * This file if part of nzbget + * This file is part of nzbget * * Copyright (C) 2004 Sven Henkel * Copyright (C) 2007 Andrei Prygounkov @@ -50,8 +50,7 @@ Log::Log() m_iIDGen = 0; m_szLogFilename = NULL; #ifdef DEBUG - struct stat buffer; - m_bExtraDebug = !stat("extradebug", &buffer); + m_bExtraDebug = Util::FileExists("extradebug"); #endif } @@ -144,11 +143,11 @@ void debug(const char* msg, ...) #ifdef HAVE_VARIADIC_MACROS if (szFuncname) { - snprintf(tmp2, 1024, "%s (%s:%i:%s)", tmp1, BaseFileName(szFilename), iLineNr, szFuncname); + snprintf(tmp2, 1024, "%s (%s:%i:%s)", tmp1, Util::BaseFileName(szFilename), iLineNr, szFuncname); } else { - snprintf(tmp2, 1024, "%s (%s:%i)", tmp1, BaseFileName(szFilename), iLineNr); + snprintf(tmp2, 1024, "%s (%s:%i)", tmp1, Util::BaseFileName(szFilename), iLineNr); } #else snprintf(tmp2, 1024, "%s", tmp1); diff --git a/Options.cpp b/Options.cpp index 1896fc62..dff79c1c 100644 --- a/Options.cpp +++ b/Options.cpp @@ -222,7 +222,7 @@ Options::Options(int argc, char* argv[]) strncpy(szFilename, argv[0], MAX_PATH + 1); #endif szFilename[MAX_PATH] = '\0'; - NormalizePathSeparators(szFilename); + Util::NormalizePathSeparators(szFilename); char* end = strrchr(szFilename, PATH_SEPARATOR); if (end) *end = '\0'; SetOption("APPDIR", szFilename); @@ -422,13 +422,12 @@ void Options::InitOptFile() char szFilename[MAX_PATH + 1]; GetModuleFileName(NULL, szFilename, MAX_PATH + 1); szFilename[MAX_PATH] = '\0'; - NormalizePathSeparators(szFilename); + Util::NormalizePathSeparators(szFilename); char* end = strrchr(szFilename, PATH_SEPARATOR); if (end) end[1] = '\0'; strcat(szFilename, "nzbget.conf"); - struct stat buffer; - if (!stat(szFilename, &buffer) && S_ISREG(buffer.st_mode)) + if (Util::FileExists(szFilename)) { m_szConfigFilename = strdup(szFilename); } @@ -440,8 +439,7 @@ void Options::InitOptFile() SetOption("$CONFIGFILENAME", szFilename); szFilename = GetOption("$CONFIGFILENAME"); - struct stat buffer; - if (!stat(szFilename, &buffer) && S_ISREG(buffer.st_mode)) + if (Util::FileExists(szFilename)) { m_szConfigFilename = strdup(szFilename); DelOption("$CONFIGFILENAME"); @@ -479,14 +477,14 @@ void Options::CheckDir(char** dir, const char* szOptionName) usedir[len] = PATH_SEPARATOR; usedir[len + 1] = '\0'; } - NormalizePathSeparators(usedir); + Util::NormalizePathSeparators(usedir); } else { abort("FATAL ERROR: Wrong value for option \"%s\"\n", szOptionName); } // Ensure the dir is created - if (!ForceDirectories(usedir)) + if (!Util::ForceDirectories(usedir)) { abort("FATAL ERROR: Directory \"%s\" (option \"%s\") does not exist and could not be created\n", usedir, szOptionName); } @@ -788,7 +786,7 @@ void Options::PrintUsage(char* com) " D Delete file(s)\n" " Comma-separated list of file-ids or ranges\n" " of file-ids, e. g.: 1-5,3,10-22\n", - BaseFileName(com)); + Util::BaseFileName(com)); } void Options::InitFileArg(int argc, char* argv[]) diff --git a/ParChecker.cpp b/ParChecker.cpp index 62790efa..530c82e3 100644 --- a/ParChecker.cpp +++ b/ParChecker.cpp @@ -425,7 +425,7 @@ void ParChecker::FindPars(DownloadQueue * pDownloadQueue, Blocks * pBlocks, bool *pBlockFound = 0; // extract base name from m_szParFilename (trim .par2-extension and possible .vol-part) - char* szBaseParFilename = BaseFileName(m_szParFilename); + char* szBaseParFilename = Util::BaseFileName(m_szParFilename); char szMainBaseFilename[1024]; int iMainBaseLen = 0; if (!ParseParFilename(szBaseParFilename, &iMainBaseLen, NULL)) @@ -497,11 +497,11 @@ void ParChecker::LoadMorePars(void* repairer) bool loadedOK = ((Repairer*)repairer)->LoadPacketsFromFile(szParFilename); if (loadedOK) { - info("File %s successfully loaded for par-check", BaseFileName(szParFilename), m_szInfoName); + info("File %s successfully loaded for par-check", Util::BaseFileName(szParFilename), m_szInfoName); } else { - info("Could not load file %s for par-check", BaseFileName(szParFilename), m_szInfoName); + info("Could not load file %s for par-check", Util::BaseFileName(szParFilename), m_szInfoName); } free(szParFilename); } diff --git a/PrePostProcessor.cpp b/PrePostProcessor.cpp index 6e5169de..b08ee4fa 100644 --- a/PrePostProcessor.cpp +++ b/PrePostProcessor.cpp @@ -203,7 +203,8 @@ void PrePostProcessor::QueueCoordinatorUpdate(Subject * Caller, void * Aspect) info("Collection %s deleted from queue", szNZBNiceName); } #ifndef DISABLE_PARCHECK - if (g_pOptions->GetParCheck() && + if (g_pOptions->GetParCheck() && + g_pOptions->GetDecoder() != Options::dcNone && pAspect->eAction == QueueCoordinator::eaFileCompleted) { CheckPars(pAspect->pDownloadQueue, pAspect->pFileInfo); @@ -282,7 +283,10 @@ void PrePostProcessor::CheckIncomingNZBs() bakname2[1024-1] = '\0'; } - rename(fullfilename, bakname2); + if (rename(fullfilename, bakname2)) + { + error("Could not rename file %s to %s! Errcode: %i", fullfilename, bakname2, errno); + } } } } @@ -397,7 +401,7 @@ bool PrePostProcessor::AddPar(FileInfo * pFileInfo, bool bDeleted) m_mutexParChecker.Lock(); bool bSameCollection = m_ParChecker.IsRunning() && !strcmp(pFileInfo->GetNZBInfo()->GetFilename(), m_ParChecker.GetNZBFilename()) && - SameParCollection(pFileInfo->GetFilename(), BaseFileName(m_ParChecker.GetParFilename())); + SameParCollection(pFileInfo->GetFilename(), Util::BaseFileName(m_ParChecker.GetParFilename())); if (bSameCollection) { if (!bDeleted) @@ -459,13 +463,7 @@ void PrePostProcessor::ParCheckerUpdate(Subject * Caller, void * Aspect) snprintf(szBrokenLogName, 1024, "%s%c_brokenlog.txt", szPath, (int)PATH_SEPARATOR); szBrokenLogName[1024-1] = '\0'; - bool bExists = false; - if (m_ParChecker.GetRepairNotNeeded()) - { - struct stat buffer; - bExists = !stat(szBrokenLogName, &buffer); - } - if (!m_ParChecker.GetRepairNotNeeded() || bExists) + if (!m_ParChecker.GetRepairNotNeeded() || Util::FileExists(szBrokenLogName)) { FILE* file = fopen(szBrokenLogName, "a"); if (m_ParChecker.GetStatus() == ParChecker::psFailed) @@ -661,10 +659,8 @@ void PrePostProcessor::ExecPostScript(const char * szPath, const char * szNZBFil return; } - info("Executing post-process for %s (%s)", szPath, BaseFileName(szNZBFilename)); - struct stat buffer; - bool bExists = !stat(szScript, &buffer); - if (!bExists) + info("Executing post-process for %s (%s)", szPath, Util::BaseFileName(szNZBFilename)); + if (!Util::FileExists(szScript)) { error("Could not start post-process: could not find file %s", szScript); return; diff --git a/QueueCoordinator.cpp b/QueueCoordinator.cpp index 4d58882c..58784efa 100644 --- a/QueueCoordinator.cpp +++ b/QueueCoordinator.cpp @@ -720,7 +720,7 @@ void QueueCoordinator::ResetHangingDownloads() } else { - error("Could not terminate hanging download %s", BaseFileName(pArticleInfo->GetResultFilename())); + error("Could not terminate hanging download %s", Util::BaseFileName(pArticleInfo->GetResultFilename())); } m_ActiveDownloads.erase(it); // it's not safe to destroy pArticleDownloader, because the state of object is unknown diff --git a/RemoteClient.cpp b/RemoteClient.cpp index 36a0b6b4..490effca 100644 --- a/RemoteClient.cpp +++ b/RemoteClient.cpp @@ -168,7 +168,7 @@ bool RemoteClient::RequestServerDownload(const char* szName, bool bAddFirst) // Read the file into the buffer char* szBuffer = NULL; int iLength = 0; - if (!LoadFileIntoBuffer(szName, &szBuffer, &iLength)) + if (!Util::LoadFileIntoBuffer(szName, &szBuffer, &iLength)) { printf("Could not load file %s\n", szName); return false; @@ -262,8 +262,8 @@ bool RemoteClient::RequestServerList() { SNZBListResponseEntry* pListAnswer = (SNZBListResponseEntry*) pBufPtr; - long long lFileSize = JoinInt64(ntohl(pListAnswer->m_iFileSizeHi), ntohl(pListAnswer->m_iFileSizeLo)); - long long lRemainingSize = JoinInt64(ntohl(pListAnswer->m_iRemainingSizeHi), ntohl(pListAnswer->m_iRemainingSizeLo)); + long long lFileSize = Util::JoinInt64(ntohl(pListAnswer->m_iFileSizeHi), ntohl(pListAnswer->m_iFileSizeLo)); + long long lRemainingSize = Util::JoinInt64(ntohl(pListAnswer->m_iRemainingSizeHi), ntohl(pListAnswer->m_iRemainingSizeLo)); char szCompleted[100]; szCompleted[0] = '\0'; @@ -309,7 +309,7 @@ bool RemoteClient::RequestServerList() free(pBuf); } - long long iAllBytes = JoinInt64(ntohl(ListResponse.m_iDownloadedBytesHi), ntohl(ListResponse.m_iDownloadedBytesLo)); + long long iAllBytes = Util::JoinInt64(ntohl(ListResponse.m_iDownloadedBytesHi), ntohl(ListResponse.m_iDownloadedBytesLo)); float fAverageSpeed = ntohl(ListResponse.m_iDownloadTimeSec) > 0 ? iAllBytes / ntohl(ListResponse.m_iDownloadTimeSec) : 0; printf("Session download rate: %.1f KB/s\n", (float)(fAverageSpeed / 1024.0)); diff --git a/Util.cpp b/Util.cpp index ffd96882..b5668784 100644 --- a/Util.cpp +++ b/Util.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef WIN32 #include #else @@ -44,27 +45,6 @@ #include "nzbget.h" #include "Util.h" -char* BaseFileName(const char* filename) -{ - char* p = (char*)strrchr(filename, PATH_SEPARATOR); - char* p1 = (char*)strrchr(filename, ALT_PATH_SEPARATOR); - if (p1) - { - if ((p && p < p1) || !p) - { - p = p1; - } - } - if (p) - { - return p + 1; - } - else - { - return (char*)filename; - } -} - #ifdef WIN32 // getopt for WIN32: @@ -217,7 +197,28 @@ const char* DirBrowser::Next() #endif -void NormalizePathSeparators(char* szPath) +char* Util::BaseFileName(const char* filename) +{ + char* p = (char*)strrchr(filename, PATH_SEPARATOR); + char* p1 = (char*)strrchr(filename, ALT_PATH_SEPARATOR); + if (p1) + { + if ((p && p < p1) || !p) + { + p = p1; + } + } + if (p) + { + return p + 1; + } + else + { + return (char*)filename; + } +} + +void Util::NormalizePathSeparators(char* szPath) { for (char* p = szPath; *p; p++) { @@ -228,7 +229,7 @@ void NormalizePathSeparators(char* szPath) } } -bool ForceDirectories(const char* szPath) +bool Util::ForceDirectories(const char* szPath) { char* szNormPath = strdup(szPath); NormalizePathSeparators(szNormPath); @@ -281,7 +282,7 @@ bool ForceDirectories(const char* szPath) return bOK; } -bool LoadFileIntoBuffer(const char* szFileName, char** pBuffer, int* pBufferLength) +bool Util::LoadFileIntoBuffer(const char* szFileName, char** pBuffer, int* pBufferLength) { FILE* pFile = fopen(szFileName, "r"); if (!pFile) @@ -313,7 +314,7 @@ bool LoadFileIntoBuffer(const char* szFileName, char** pBuffer, int* pBufferLeng return true; } -bool SetFileSize(const char* szFilename, int iSize) +bool Util::SetFileSize(const char* szFilename, int iSize) { bool bOK = false; #ifdef WIN32 @@ -330,7 +331,7 @@ bool SetFileSize(const char* szFilename, int iSize) { fclose(pFile); } - // there no reliable function to expand file on POSIX, so we must try different approaches, + // there are no reliable function to expand file on POSIX, so we must try different approaches, // starting with the fastest one and hoping it will work // 1) set file size using function "truncate" (it is fast, if works) truncate(szFilename, iSize); @@ -357,7 +358,7 @@ bool SetFileSize(const char* szFilename, int iSize) } //replace bad chars in filename -void MakeValidFilename(char* szFilename, char cReplaceChar) +void Util::MakeValidFilename(char* szFilename, char cReplaceChar) { char* p = szFilename; while (*p) @@ -377,18 +378,18 @@ void MakeValidFilename(char* szFilename, char cReplaceChar) } } -long long JoinInt64(unsigned int Hi, unsigned int Lo) +long long Util::JoinInt64(unsigned int Hi, unsigned int Lo) { return (((long long)Hi) << 32) + Lo; } -void SplitInt64(long long Int64, unsigned int* Hi, unsigned int* Lo) +void Util::SplitInt64(long long Int64, unsigned int* Hi, unsigned int* Lo) { *Hi = (unsigned int)(Int64 >> 32); *Lo = (unsigned int)Int64; } -float EqualTime(_timeval* t1, _timeval* t2) +float Util::EqualTime(_timeval* t1, _timeval* t2) { #ifdef WIN32 return t1->time == t2->time && t1->millitm == t2->millitm; @@ -397,7 +398,7 @@ float EqualTime(_timeval* t1, _timeval* t2) #endif } -bool EmptyTime(_timeval* t) +bool Util::EmptyTime(_timeval* t) { #ifdef WIN32 return t->time == 0 && t->millitm == 0; @@ -406,7 +407,7 @@ bool EmptyTime(_timeval* t) #endif } -float DiffTime(_timeval* t1, _timeval* t2) +float Util::DiffTime(_timeval* t1, _timeval* t2) { #ifdef WIN32 return ((t1->time - t2->time) + (t1->millitm - t2->millitm) / 1000.0); @@ -487,7 +488,7 @@ unsigned int DecodeByteQuartet(char* szInputBuffer, char* szOutputBuffer) return -1; } -unsigned int DecodeBase64(char* szInputBuffer, int iInputBufferLength, char* szOutputBuffer) +unsigned int Util::DecodeBase64(char* szInputBuffer, int iInputBufferLength, char* szOutputBuffer) { unsigned int InputBufferIndex = 0; unsigned int OutputBufferIndex = 0; @@ -526,7 +527,7 @@ unsigned int DecodeBase64(char* szInputBuffer, int iInputBufferLength, char* szO /* END - Base64 */ -char* XmlEncode(const char* raw) +char* Util::XmlEncode(const char* raw) { // calculate the required outputstring-size based on number of xml-entities and their sizes int iReqSize = strlen(raw); @@ -590,7 +591,7 @@ BreakLoop: return result; } -void XmlDecode(char* raw) +void Util::XmlDecode(char* raw) { char* output = raw; for (char* p = raw;;) @@ -645,7 +646,7 @@ BreakLoop: *output = '\0'; } -const char* FindTag(const char* szXml, const char* szTag, int* iValueLength) +const char* Util::FindTag(const char* szXml, const char* szTag, int* iValueLength) { char szOpenTag[100]; snprintf(szOpenTag, 100, "<%s>", szTag); @@ -667,7 +668,7 @@ const char* FindTag(const char* szXml, const char* szTag, int* iValueLength) return pstart + iTagLen; } -bool ParseTagValue(const char* szXml, const char* szTag, char* szValueBuf, int iValueBufSize, const char** pTagEnd) +bool Util::ParseTagValue(const char* szXml, const char* szTag, char* szValueBuf, int iValueBufSize, const char** pTagEnd) { int iValueLen = 0; const char* szValue = FindTag(szXml, szTag, &iValueLen); @@ -684,3 +685,64 @@ bool ParseTagValue(const char* szXml, const char* szTag, char* szValueBuf, int i } return true; } + +bool Util::MoveFile(const char* szSrcFilename, const char* szDstFilename) +{ + bool bOK = rename(szSrcFilename, szDstFilename) == 0; + +#ifndef WIN32 + if (!bOK && (errno == EXDEV)) + { + FILE* infile = fopen(szSrcFilename, "r"); + if (!infile) + { + return false; + } + + FILE* outfile = fopen(szDstFilename, "w+"); + if (!outfile) + { + fclose(infile); + return false; + } + + static const int BUFFER_SIZE = 1024 * 50; + char* buffer = (char*)malloc(BUFFER_SIZE); + + int cnt = BUFFER_SIZE; + while (cnt == BUFFER_SIZE) + { + cnt = (int)fread(buffer, 1, BUFFER_SIZE, infile); + fwrite(buffer, 1, cnt, outfile); + } + + fclose(infile); + fclose(outfile); + free(buffer); + + bOK = remove(szSrcFilename) == 0; + } +#endif + + return bOK; +} + +bool Util::FileExists(const char* szFilename) +{ + struct stat buffer; + bool bExists = !stat(szFilename, &buffer) && S_ISREG(buffer.st_mode);; + return bExists; +} + +bool Util::DirectoryExists(const char* szDirFilename) +{ + struct stat buffer; + bool bExists = !stat(szDirFilename, &buffer) && S_ISDIR(buffer.st_mode); + return bExists; +} + +bool Util::CreateDirectory(const char* szDirFilename) +{ + mkdir(szDirFilename, S_DIRMODE); + return DirectoryExists(szDirFilename); +} diff --git a/Util.h b/Util.h index 23e847f4..bd6246c7 100644 --- a/Util.h +++ b/Util.h @@ -58,43 +58,52 @@ public: const char* Next(); }; -char* BaseFileName(const char* filename); -void NormalizePathSeparators(char* szPath); -bool ForceDirectories(const char* szPath); -bool LoadFileIntoBuffer(const char* szFileName, char** pBuffer, int* pBufferLength); -bool SetFileSize(const char* szFilename, int iSize); -void MakeValidFilename(char* szFilename, char cReplaceChar); +class Util +{ +public: -long long JoinInt64(unsigned int Hi, unsigned int Lo); -void SplitInt64(long long Int64, unsigned int* Hi, unsigned int* Lo); + static char* BaseFileName(const char* filename); + static void NormalizePathSeparators(char* szPath); + static bool LoadFileIntoBuffer(const char* szFileName, char** pBuffer, int* pBufferLength); + static bool SetFileSize(const char* szFilename, int iSize); + static void MakeValidFilename(char* szFilename, char cReplaceChar); + static bool MoveFile(const char* szSrcFilename, const char* szDstFilename); + static bool FileExists(const char* szFilename); + static bool DirectoryExists(const char* szDirFilename); + static bool CreateDirectory(const char* szDirFilename); + static bool ForceDirectories(const char* szPath); -float EqualTime(_timeval* t1, _timeval* t2); -bool EmptyTime(_timeval* t); -float DiffTime(_timeval* t1, _timeval* t2); + static long long JoinInt64(unsigned int Hi, unsigned int Lo); + static void SplitInt64(long long Int64, unsigned int* Hi, unsigned int* Lo); -unsigned int DecodeBase64(char* szInputBuffer, int iInputBufferLength, char* szOutputBuffer); + static float EqualTime(_timeval* t1, _timeval* t2); + static bool EmptyTime(_timeval* t); + static float DiffTime(_timeval* t1, _timeval* t2); -/* - * Encodes string to be used as content of xml-tag. - * Returns new string allocated with malloc, it need to be freed by caller. - */ -char* XmlEncode(const char* raw); + static unsigned int DecodeBase64(char* szInputBuffer, int iInputBufferLength, char* szOutputBuffer); -/* - * Decodes string from xml. - * The string is decoded on the place overwriting the content of raw-data. - */ -void XmlDecode(char* raw); + /* + * Encodes string to be used as content of xml-tag. + * Returns new string allocated with malloc, it need to be freed by caller. + */ + static char* XmlEncode(const char* raw); -/* - * Returns pointer to tag-content and length of content in iValueLength - * The returned pointer points to the part of source-string, no additional strings are allocated. - */ -const char* FindTag(const char* szXml, const char* szTag, int* iValueLength); + /* + * Decodes string from xml. + * The string is decoded on the place overwriting the content of raw-data. + */ + static void XmlDecode(char* raw); -/* - * Parses tag-content into szValueBuf. - */ -bool ParseTagValue(const char* szXml, const char* szTag, char* szValueBuf, int iValueBufSize, const char** pTagEnd); + /* + * Returns pointer to tag-content and length of content in iValueLength + * The returned pointer points to the part of source-string, no additional strings are allocated. + */ + static const char* FindTag(const char* szXml, const char* szTag, int* iValueLength); + + /* + * Parses tag-content into szValueBuf. + */ + static bool ParseTagValue(const char* szXml, const char* szTag, char* szValueBuf, int iValueBufSize, const char** pTagEnd); +}; #endif diff --git a/XmlRpc.cpp b/XmlRpc.cpp index 49a7bd22..2b56f661 100644 --- a/XmlRpc.cpp +++ b/XmlRpc.cpp @@ -85,7 +85,7 @@ void XmlRpcProcessor::Execute() return; } if (char* pe = strrchr(szAuthInfo64, '\r')) *pe = '\0'; - szAuthInfo[DecodeBase64(szAuthInfo64, 0, szAuthInfo)] = '\0'; + szAuthInfo[Util::DecodeBase64(szAuthInfo64, 0, szAuthInfo)] = '\0'; } if (!strncmp(p, "\r", 1)) { @@ -142,7 +142,7 @@ void XmlRpcProcessor::Dispatch() XmlCommand* command = NULL; char szMethodName[100]; - if (!ParseTagValue(m_szRequest, "methodName", szMethodName, sizeof(szMethodName), NULL)) + if (!Util::ParseTagValue(m_szRequest, "methodName", szMethodName, sizeof(szMethodName), NULL)) { command = new ErrorXmlCommand(1, "Invalid request"); } @@ -303,10 +303,10 @@ void XmlCommand::SendBoolResponse(bool bOK) bool XmlCommand::NextIntParam(int* iValue) { int iLen = 0; - const char* szParam = FindTag(m_szRequestPtr, "i4", &iLen); + const char* szParam = Util::FindTag(m_szRequestPtr, "i4", &iLen); if (!szParam) { - szParam = FindTag(m_szRequestPtr, "int", &iLen); + szParam = Util::FindTag(m_szRequestPtr, "int", &iLen); } if (szParam) { @@ -407,7 +407,7 @@ void StatusXmlCommand::Execute() unsigned int iRemainingSizeHi, iRemainingSizeLo; int iDownloadRate = (int)(g_pQueueCoordinator->CalcCurrentDownloadSpeed() * 1024); long long iRemainingSize = g_pQueueCoordinator->CalcRemainingSize(); - SplitInt64(iRemainingSize, &iRemainingSizeHi, &iRemainingSizeLo); + Util::SplitInt64(iRemainingSize, &iRemainingSizeHi, &iRemainingSizeLo); int iRemainingMBytes = iRemainingSize / 1024 / 1024; int iDownloadLimit = (int)(g_pOptions->GetDownloadRate() * 1024); bool bServerPaused = g_pOptions->GetPause(); @@ -421,7 +421,7 @@ void StatusXmlCommand::Execute() bool bServerStandBy; g_pQueueCoordinator->CalcStat(&iUpTimeSec, &iDownloadTimeSec, &iAllBytes, &bServerStandBy); int iDownloadedMBytes = iAllBytes / 1024 / 1024; - SplitInt64(iAllBytes, &iDownloadedSizeHi, &iDownloadedSizeLo); + Util::SplitInt64(iAllBytes, &iDownloadedSizeHi, &iDownloadedSizeLo); int iAverageDownloadRate = iDownloadTimeSec > 0 ? iAllBytes / iDownloadTimeSec : 0; char szContent[2048]; @@ -487,7 +487,7 @@ void LogXmlCommand::Execute() for (unsigned int i = (unsigned int)iStart; i < pMessages->size(); i++) { Message* pMessage = (*pMessages)[i]; - char* xmltext = XmlEncode(pMessage->GetText()); + char* xmltext = Util::XmlEncode(pMessage->GetText()); snprintf(szItemBuf, szItemBufSize, LOG_ITEM, pMessage->GetID(), szMessageType[pMessage->GetKind()], pMessage->GetTime(), xmltext); szItemBuf[szItemBufSize-1] = '\0'; free(xmltext); @@ -532,12 +532,12 @@ void ListFilesXmlCommand::Execute() FileInfo* pFileInfo = *it; unsigned int iFileSizeHi, iFileSizeLo; unsigned int iRemainingSizeLo, iRemainingSizeHi; - SplitInt64(pFileInfo->GetSize(), &iFileSizeHi, &iFileSizeLo); - SplitInt64(pFileInfo->GetRemainingSize(), &iRemainingSizeHi, &iRemainingSizeLo); - char* xmlNZBFilename = XmlEncode(pFileInfo->GetNZBInfo()->GetFilename()); - char* xmlSubject = XmlEncode(pFileInfo->GetSubject()); - char* xmlFilename = XmlEncode(pFileInfo->GetFilename()); - char* xmlDestDir = XmlEncode(pFileInfo->GetNZBInfo()->GetDestDir()); + Util::SplitInt64(pFileInfo->GetSize(), &iFileSizeHi, &iFileSizeLo); + Util::SplitInt64(pFileInfo->GetRemainingSize(), &iRemainingSizeHi, &iRemainingSizeLo); + char* xmlNZBFilename = Util::XmlEncode(pFileInfo->GetNZBInfo()->GetFilename()); + char* xmlSubject = Util::XmlEncode(pFileInfo->GetSubject()); + char* xmlFilename = Util::XmlEncode(pFileInfo->GetFilename()); + char* xmlDestDir = Util::XmlEncode(pFileInfo->GetNZBInfo()->GetDestDir()); snprintf(szItemBuf, szItemBufSize, LIST_ITEM, pFileInfo->GetID(), iFileSizeLo, iFileSizeHi, iRemainingSizeLo, iRemainingSizeHi, (int)pFileInfo->GetFilenameConfirmed(), (int)pFileInfo->GetPaused(), @@ -601,17 +601,17 @@ void ListGroupsXmlCommand::Execute() unsigned int iRemainingSizeLo, iRemainingSizeHi, iRemainingSizeMB; unsigned int iPausedSizeLo, iPausedSizeHi, iPausedSizeMB; char szNZBNicename[1024]; - SplitInt64(pGroupInfo->GetNZBInfo()->GetSize(), &iFileSizeHi, &iFileSizeLo); + Util::SplitInt64(pGroupInfo->GetNZBInfo()->GetSize(), &iFileSizeHi, &iFileSizeLo); iFileSizeMB = pGroupInfo->GetNZBInfo()->GetSize() / 1024 / 1024; - SplitInt64(pGroupInfo->GetRemainingSize(), &iRemainingSizeHi, &iRemainingSizeLo); + Util::SplitInt64(pGroupInfo->GetRemainingSize(), &iRemainingSizeHi, &iRemainingSizeLo); iRemainingSizeMB = pGroupInfo->GetRemainingSize() / 1024 / 1024; - SplitInt64(pGroupInfo->GetPausedSize(), &iPausedSizeHi, &iPausedSizeLo); + Util::SplitInt64(pGroupInfo->GetPausedSize(), &iPausedSizeHi, &iPausedSizeLo); iPausedSizeMB = pGroupInfo->GetPausedSize() / 1024 / 1024; pGroupInfo->GetNZBInfo()->GetNiceNZBName(szNZBNicename, sizeof(szNZBNicename)); - char* xmlNZBNicename = XmlEncode(szNZBNicename); - char* xmlNZBFilename = XmlEncode(pGroupInfo->GetNZBInfo()->GetFilename()); - char* xmlDestDir = XmlEncode(pGroupInfo->GetNZBInfo()->GetDestDir()); + char* xmlNZBNicename = Util::XmlEncode(szNZBNicename); + char* xmlNZBFilename = Util::XmlEncode(pGroupInfo->GetNZBInfo()->GetFilename()); + char* xmlDestDir = Util::XmlEncode(pGroupInfo->GetNZBInfo()->GetDestDir()); snprintf(szItemBuf, szItemBufSize, LIST_ITEM, pGroupInfo->GetFirstID(), pGroupInfo->GetLastID(), iFileSizeLo, iFileSizeHi, iFileSizeMB, iRemainingSizeLo, iRemainingSizeHi, iRemainingSizeMB, @@ -668,7 +668,7 @@ EditCommandEntry EditCommandNameMap[] = { void EditQueueXmlCommand::Execute() { char szEditCommand[100]; - if (!ParseTagValue(m_szRequest, "string", szEditCommand, sizeof(szEditCommand), NULL)) + if (!Util::ParseTagValue(m_szRequest, "string", szEditCommand, sizeof(szEditCommand), NULL)) { SendErrorResponse(2, "Invalid parameter"); return; @@ -719,18 +719,18 @@ void EditQueueXmlCommand::Execute() void DownloadXmlCommand::Execute() { char szFileName[1024]; - if (!ParseTagValue(m_szRequest, "string", szFileName, sizeof(szFileName), NULL)) + if (!Util::ParseTagValue(m_szRequest, "string", szFileName, sizeof(szFileName), NULL)) { SendErrorResponse(2, "Invalid parameter"); return; } - XmlDecode(szFileName); + Util::XmlDecode(szFileName); debug("FileName=%s", szFileName); const char* pTagEnd; char szAddTop[10]; - if (!ParseTagValue(m_szRequest, "boolean", szAddTop, sizeof(szAddTop), &pTagEnd)) + if (!Util::ParseTagValue(m_szRequest, "boolean", szAddTop, sizeof(szAddTop), &pTagEnd)) { SendErrorResponse(2, "Invalid parameter"); return; @@ -739,14 +739,14 @@ void DownloadXmlCommand::Execute() bool bAddTop = !strcmp(szAddTop, "1"); int iLen = 0; - char* szFileContent = (char*)FindTag(pTagEnd, "string", &iLen); + char* szFileContent = (char*)Util::FindTag(pTagEnd, "string", &iLen); if (!szFileContent) { SendErrorResponse(2, "Invalid parameter"); return; } - szFileContent[DecodeBase64(szFileContent, iLen, szFileContent)] = '\0'; + szFileContent[Util::DecodeBase64(szFileContent, iLen, szFileContent)] = '\0'; //debug("FileContent=%s", szFileContent); NZBFile* pNZBFile = NZBFile::CreateFromBuffer(szFileName, szFileContent, iLen); @@ -787,10 +787,10 @@ void PostQueueXmlCommand::Execute() char szNZBNicename[1024]; NZBInfo::MakeNiceNZBName(pParJob->GetNZBFilename(), szNZBNicename, sizeof(szNZBNicename)); - char* xmlNZBNicename = XmlEncode(szNZBNicename); - char* xmlNZBFilename = XmlEncode(pParJob->GetNZBFilename()); - char* xmlParFilename = XmlEncode(pParJob->GetParFilename()); - char* xmlInfoName = XmlEncode(pParJob->GetInfoName()); + char* xmlNZBNicename = Util::XmlEncode(szNZBNicename); + char* xmlNZBFilename = Util::XmlEncode(pParJob->GetNZBFilename()); + char* xmlParFilename = Util::XmlEncode(pParJob->GetParFilename()); + char* xmlInfoName = Util::XmlEncode(pParJob->GetInfoName()); snprintf(szItemBuf, szItemBufSize, POSTQUEUE_ITEM, szNZBNicename, xmlNZBFilename, xmlParFilename, xmlInfoName); szItemBuf[szItemBufSize-1] = '\0';