MiscUtils.cpp
上传用户:woshihumen
上传日期:2013-07-18
资源大小:484k
文件大小:33k
源码类别:

Email服务器

开发平台:

Visual C++

  1. /*
  2.  *  XMail by Davide Libenzi ( Intranet and Internet mail server )
  3.  *  Copyright (C) 1999,..,2004  Davide Libenzi
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  *  Davide Libenzi <davidel@xmailserver.org>
  20.  *
  21.  */
  22. #include "SysInclude.h"
  23. #include "SysDep.h"
  24. #include "SvrDefines.h"
  25. #include "ShBlocks.h"
  26. #include "StrUtils.h"
  27. #include "SList.h"
  28. #include "MD5.h"
  29. #include "Base64Enc.h"
  30. #include "BuffSock.h"
  31. #include "MailConfig.h"
  32. #include "UsrUtils.h"
  33. #include "SvrUtils.h"
  34. #include "MessQueue.h"
  35. #include "MailSvr.h"
  36. #include "MiscUtils.h"
  37. #define IPPROP_LINE_MAX             1024
  38. enum IPMapFileds {
  39. ipmFromIP = 0,
  40. ipmFromMask,
  41. ipmAllow,
  42. ipmPrecedence,
  43. ipmMax
  44. };
  45. struct FileScan {
  46. char szListFile[SYS_MAX_PATH];
  47. FILE *pListFile;
  48. };
  49. static int MscCopyFileLL(const char *pszCopyTo, const char *pszCopyFrom,
  50.  char const *pszMode);
  51. int MscUniqueFile(char const *pszDir, char *pszFilePath)
  52. {
  53. ///////////////////////////////////////////////////////////////////////////////
  54. //  Get thread ID and host name. We do not use atomic inc on ulUniqSeq, since
  55. //  collision is prevented by the thread ID
  56. ///////////////////////////////////////////////////////////////////////////////
  57. static unsigned long ulUniqSeq = 0;
  58. unsigned long ulThreadID = SysGetCurrentThreadId();
  59. SYS_INT64 iMsTime = SysMsTime();
  60. char szHostName[MAX_HOST_NAME] = "";
  61. gethostname(szHostName, sizeof(szHostName) - 1);
  62. sprintf(pszFilePath, "%s" SYS_SLASH_STR SYS_LLU_FMT ".%lu.%lx.%s",
  63. pszDir, iMsTime, ulThreadID, ulUniqSeq++, szHostName);
  64. return (0);
  65. }
  66. int MscRecvTextFile(const char *pszFileName, BSOCK_HANDLE hBSock, int iTimeout,
  67.     int (*pStopProc) (void *), void *pParam)
  68. {
  69. FILE *pFile = fopen(pszFileName, "wt");
  70. if (pFile == NULL) {
  71. ErrSetErrorCode(ERR_FILE_CREATE, pszFileName);
  72. return (ERR_FILE_CREATE);
  73. }
  74. char szBuffer[2048] = "";
  75. while (BSckGetString(hBSock, szBuffer, sizeof(szBuffer) - 1, iTimeout) != NULL) {
  76. if (strcmp(szBuffer, ".") == 0)
  77. break;
  78. if (szBuffer[0] == '.')
  79. fprintf(pFile, "%sn", szBuffer + 1);
  80. else
  81. fprintf(pFile, "%sn", szBuffer);
  82. if ((pStopProc != NULL) && pStopProc(pParam)) {
  83. fclose(pFile);
  84. return (ErrGetErrorCode());
  85. }
  86. }
  87. fclose(pFile);
  88. return (0);
  89. }
  90. int MscSendTextFile(const char *pszFileName, BSOCK_HANDLE hBSock, int iTimeout,
  91.     int (*pStopProc) (void *), void *pParam)
  92. {
  93. FILE *pFile = fopen(pszFileName, "rt");
  94. if (pFile == NULL) {
  95. ErrSetErrorCode(ERR_FILE_OPEN, pszFileName);
  96. return (ERR_FILE_OPEN);
  97. }
  98. char szBuffer[2048] = "";
  99. while (MscFGets(szBuffer, sizeof(szBuffer) - 1, pFile) != NULL) {
  100. if (szBuffer[0] == '.')
  101. for (int ii = strlen(szBuffer); ii >= 0; ii--)
  102. szBuffer[ii + 1] = szBuffer[ii];
  103. if (BSckSendString(hBSock, szBuffer, iTimeout) <= 0) {
  104. fclose(pFile);
  105. return (ErrGetErrorCode());
  106. }
  107. if ((pStopProc != NULL) && pStopProc(pParam)) {
  108. fclose(pFile);
  109. return (ErrGetErrorCode());
  110. }
  111. }
  112. fclose(pFile);
  113. return (BSckSendString(hBSock, ".", iTimeout));
  114. }
  115. char *MscTranslatePath(char *pszPath)
  116. {
  117. for (int ii = 0; pszPath[ii] != ''; ii++) {
  118. switch (pszPath[ii]) {
  119. case ('/'):
  120. case ('\'):
  121. pszPath[ii] = SYS_SLASH_CHAR;
  122. break;
  123. }
  124. }
  125. return (pszPath);
  126. }
  127. void *MscLoadFile(char const *pszFilePath, unsigned int &uFileSize)
  128. {
  129. FILE *pFile = fopen(pszFilePath, "rb");
  130. if (pFile == NULL) {
  131. ErrSetErrorCode(ERR_FILE_OPEN, pszFilePath);
  132. return (NULL);
  133. }
  134. fseek(pFile, 0, SEEK_END);
  135. uFileSize = (unsigned int) ftell(pFile);
  136. ///////////////////////////////////////////////////////////////////////////////
  137. //  Alloc one extra byte to enable placing a '' to terminate an eventual
  138. //  string representation and to avoid SysAlloc() to fail if uFileSize == 0
  139. ///////////////////////////////////////////////////////////////////////////////
  140. void *pFileData = SysAlloc(uFileSize + 1);
  141. if (pFileData == NULL) {
  142. fclose(pFile);
  143. return (NULL);
  144. }
  145. rewind(pFile);
  146. if (uFileSize != 0)
  147. fread(pFileData, uFileSize, 1, pFile);
  148. fclose(pFile);
  149. return (pFileData);
  150. }
  151. int MscLockFile(const char *pszFileName, int iMaxWait, int iWaitStep)
  152. {
  153. while ((iMaxWait > 0) && (SysLockFile(pszFileName) < 0)) {
  154. SysSleep(iWaitStep);
  155. iMaxWait -= iWaitStep;
  156. }
  157. return ((iMaxWait > 0) ? 0 : SysLockFile(pszFileName));
  158. }
  159. int MscGetTimeNbrString(char *pszTimeStr, int iStringSize, time_t tTime)
  160. {
  161. if (tTime == 0)
  162. time(&tTime);
  163. struct tm tmSession;
  164. SysLocalTime(&tTime, &tmSession);
  165. SysSNPrintf(pszTimeStr, iStringSize, "%04d-%02d-%02d %02d:%02d:%02d",
  166.     tmSession.tm_year + 1900,
  167.     tmSession.tm_mon + 1,
  168.     tmSession.tm_mday, tmSession.tm_hour, tmSession.tm_min, tmSession.tm_sec);
  169. return (0);
  170. }
  171. int MscGetTime(struct tm &tmLocal, int &iDiffHours, int &iDiffMins, time_t tCurr)
  172. {
  173. if (tCurr == 0)
  174. time(&tCurr);
  175. SysLocalTime(&tCurr, &tmLocal);
  176. struct tm tmTimeLOC = tmLocal;
  177. struct tm tmTimeGM;
  178. SysGMTime(&tCurr, &tmTimeGM);
  179. tmTimeLOC.tm_isdst = 0;
  180. tmTimeGM.tm_isdst = 0;
  181. time_t tLocal = mktime(&tmTimeLOC);
  182. time_t tGM = mktime(&tmTimeGM);
  183. int iSecsDiff = (int) difftime(tLocal, tGM);
  184. int iSignDiff = Sign(iSecsDiff);
  185. int iMinutes = Abs(iSecsDiff) / 60;
  186. iDiffMins = iMinutes % 60;
  187. iDiffHours = iSignDiff * (iMinutes / 60);
  188. return (0);
  189. }
  190. char *MscStrftime(struct tm const *ptmTime, char *pszDateStr, int iSize)
  191. {
  192. const char *pszWDays[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
  193. const char *pszMonths[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  194. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  195. };
  196. SysSNPrintf(pszDateStr, iSize, "%s, %d %s %d %02d:%02d:%02d",
  197.     pszWDays[ptmTime->tm_wday], ptmTime->tm_mday,
  198.     pszMonths[ptmTime->tm_mon], ptmTime->tm_year + 1900,
  199.     ptmTime->tm_hour, ptmTime->tm_min, ptmTime->tm_sec);
  200. return (pszDateStr);
  201. }
  202. int MscGetTimeStr(char *pszTimeStr, int iStringSize, time_t tCurr)
  203. {
  204. int iDiffHours = 0;
  205. int iDiffMins = 0;
  206. struct tm tmTime;
  207. MscGetTime(tmTime, iDiffHours, iDiffMins, tCurr);
  208. char szDiffTime[128] = "";
  209. if (iDiffHours > 0)
  210. sprintf(szDiffTime, " +%02d%02d", iDiffHours, iDiffMins);
  211. else
  212. sprintf(szDiffTime, " -%02d%02d", -iDiffHours, iDiffMins);
  213. MscStrftime(&tmTime, pszTimeStr, iStringSize - strlen(szDiffTime) - 1);
  214. strcat(pszTimeStr, szDiffTime);
  215. return (0);
  216. }
  217. int MscGetDirectorySize(char const *pszPath, bool bRecurse, unsigned long &ulDirSize,
  218. unsigned long &ulNumFiles, int (*pFNValidate) (char const *))
  219. {
  220. char szFileName[SYS_MAX_PATH] = "";
  221. SYS_HANDLE hFind = SysFirstFile(pszPath, szFileName);
  222. if (hFind == SYS_INVALID_HANDLE)
  223. return (ErrGetErrorCode());
  224. ulDirSize = 0;
  225. do {
  226. if (SysIsDirectory(hFind)) {
  227. if (bRecurse && SYS_IS_VALID_FILENAME(szFileName)) {
  228. unsigned long ulSubDirSize = 0;
  229. unsigned long ulSubNumFiles = 0;
  230. char szSubPath[SYS_MAX_PATH] = "";
  231. StrSNCpy(szSubPath, pszPath);
  232. AppendSlash(szSubPath);
  233. StrSNCat(szSubPath, szFileName);
  234. if (MscGetDirectorySize(szSubPath, bRecurse, ulSubDirSize,
  235. ulSubNumFiles, pFNValidate) < 0) {
  236. ErrorPush();
  237. SysFindClose(hFind);
  238. return (ErrorPop());
  239. }
  240. ulNumFiles += ulSubNumFiles;
  241. ulDirSize += ulSubDirSize;
  242. }
  243. } else if ((pFNValidate == NULL) || pFNValidate(szFileName)) {
  244. ++ulNumFiles;
  245. ulDirSize += SysGetSize(hFind);
  246. }
  247. } while (SysNextFile(hFind, szFileName));
  248. SysFindClose(hFind);
  249. return (0);
  250. }
  251. FSCAN_HANDLE MscFirstFile(char const *pszPath, int iListDirs, char *pszFileName)
  252. {
  253. FileScan *pFS = (FileScan *) SysAlloc(sizeof(FileScan));
  254. if (pFS == NULL)
  255. return (INVALID_FSCAN_HANDLE);
  256. SysGetTmpFile(pFS->szListFile);
  257. if (MscGetFileList(pszPath, pFS->szListFile, iListDirs) < 0) {
  258. if (SysExistFile(pFS->szListFile))
  259. SysRemove(pFS->szListFile);
  260. SysFree(pFS);
  261. return (INVALID_FSCAN_HANDLE);
  262. }
  263. if ((pFS->pListFile = fopen(pFS->szListFile, "rb")) == NULL) {
  264. SysRemove(pFS->szListFile);
  265. SysFree(pFS);
  266. return (INVALID_FSCAN_HANDLE);
  267. }
  268. if (MscGetString(pFS->pListFile, pszFileName, SYS_MAX_PATH - 1) == NULL) {
  269. fclose(pFS->pListFile);
  270. SysRemove(pFS->szListFile);
  271. SysFree(pFS);
  272. return (INVALID_FSCAN_HANDLE);
  273. }
  274. return ((FSCAN_HANDLE) pFS);
  275. }
  276. int MscNextFile(FSCAN_HANDLE hFileScan, char *pszFileName)
  277. {
  278. FileScan *pFS = (FileScan *) hFileScan;
  279. if (MscGetString(pFS->pListFile, pszFileName, SYS_MAX_PATH - 1) == NULL)
  280. return (0);
  281. return (1);
  282. }
  283. void MscCloseFindFile(FSCAN_HANDLE hFileScan)
  284. {
  285. FileScan *pFS = (FileScan *) hFileScan;
  286. fclose(pFS->pListFile);
  287. SysRemove(pFS->szListFile);
  288. SysFree(pFS);
  289. }
  290. int MscGetFileList(char const *pszPath, const char *pszListFile, int iListDirs)
  291. {
  292. FILE *pListFile = fopen(pszListFile, "wb");
  293. if (pListFile == NULL) {
  294. ErrSetErrorCode(ERR_FILE_CREATE);
  295. return (ERR_FILE_CREATE);
  296. }
  297. char szFileName[SYS_MAX_PATH] = "";
  298. SYS_HANDLE hFind = SysFirstFile(pszPath, szFileName);
  299. if (hFind != SYS_INVALID_HANDLE) {
  300. do {
  301. if (iListDirs || !SysIsDirectory(hFind))
  302. fprintf(pListFile, "%srn", szFileName);
  303. } while (SysNextFile(hFind, szFileName));
  304. SysFindClose(hFind);
  305. }
  306. fclose(pListFile);
  307. return (0);
  308. }
  309. int MscCreateEmptyFile(const char *pszFileName)
  310. {
  311. FILE *pFile = fopen(pszFileName, "wb");
  312. if (pFile == NULL) {
  313. ErrSetErrorCode(ERR_FILE_CREATE);
  314. return (ERR_FILE_CREATE);
  315. }
  316. fclose(pFile);
  317. return (0);
  318. }
  319. int MscClearDirectory(const char *pszPath, int iRecurseSubs)
  320. {
  321. char szFileName[SYS_MAX_PATH] = "";
  322. SYS_HANDLE hFind = SysFirstFile(pszPath, szFileName);
  323. if (hFind == SYS_INVALID_HANDLE)
  324. return (0);
  325. char szTmpFileName[SYS_MAX_PATH] = "";
  326. SysGetTmpFile(szTmpFileName);
  327. FILE *pFile = fopen(szTmpFileName, "w+t");
  328. if (pFile == NULL) {
  329. SysFindClose(hFind);
  330. ErrSetErrorCode(ERR_FILE_CREATE);
  331. return (ERR_FILE_CREATE);
  332. }
  333. int iFileCount = 0;
  334. do {
  335. if (SysIsDirectory(hFind)) {
  336. if (iRecurseSubs && SYS_IS_VALID_FILENAME(szFileName)) {
  337. char szSubPath[SYS_MAX_PATH] = "";
  338. StrSNCpy(szSubPath, pszPath);
  339. AppendSlash(szSubPath);
  340. StrSNCat(szSubPath, szFileName);
  341. if (MscClearDirectory(szSubPath, iRecurseSubs) < 0) {
  342. fclose(pFile);
  343. SysRemove(szTmpFileName);
  344. return (ErrGetErrorCode());
  345. }
  346. if (SysRemoveDir(szSubPath) < 0) {
  347. fclose(pFile);
  348. SysRemove(szTmpFileName);
  349. return (ErrGetErrorCode());
  350. }
  351. }
  352. } else {
  353. fprintf(pFile, "%sn", szFileName);
  354. ++iFileCount;
  355. }
  356. } while (SysNextFile(hFind, szFileName));
  357. SysFindClose(hFind);
  358. if (iFileCount > 0) {
  359. fseek(pFile, 0, SEEK_SET);
  360. while (MscFGets(szFileName, sizeof(szFileName) - 1, pFile) != NULL) {
  361. char szFilePath[SYS_MAX_PATH] = "";
  362. StrSNCpy(szFilePath, pszPath);
  363. AppendSlash(szFilePath);
  364. StrSNCat(szFilePath, szFileName);
  365. if (SysRemove(szFilePath) < 0) {
  366. fclose(pFile);
  367. SysRemove(szTmpFileName);
  368. return (ErrGetErrorCode());
  369. }
  370. }
  371. }
  372. fclose(pFile);
  373. SysRemove(szTmpFileName);
  374. return (0);
  375. }
  376. static int MscCopyFileLL(const char *pszCopyTo, const char *pszCopyFrom,
  377.  char const *pszMode)
  378. {
  379. FILE *pFileIn = fopen(pszCopyFrom, "rb");
  380. if (pFileIn == NULL) {
  381. ErrSetErrorCode(ERR_FILE_OPEN);
  382. return (ERR_FILE_OPEN);
  383. }
  384. FILE *pFileOut = fopen(pszCopyTo, pszMode);
  385. if (pFileOut == NULL) {
  386. fclose(pFileIn);
  387. ErrSetErrorCode(ERR_FILE_CREATE);
  388. return (ERR_FILE_CREATE);
  389. }
  390. unsigned int uReaded;
  391. char szBuffer[2048];
  392. do {
  393. uReaded = fread(szBuffer, 1, sizeof(szBuffer), pFileIn);
  394. if (uReaded > 0) {
  395. if (fwrite(szBuffer, 1, uReaded, pFileOut) != uReaded) {
  396. fclose(pFileOut);
  397. fclose(pFileIn);
  398. SysRemove(pszCopyTo);
  399. ErrSetErrorCode(ERR_FILE_WRITE);
  400. return (ERR_FILE_WRITE);
  401. }
  402. }
  403. } while (uReaded == sizeof(szBuffer));
  404. fclose(pFileOut);
  405. fclose(pFileIn);
  406. return (0);
  407. }
  408. int MscCopyFile(const char *pszCopyTo, const char *pszCopyFrom)
  409. {
  410. return (MscCopyFileLL(pszCopyTo, pszCopyFrom, "wb"));
  411. }
  412. int MscAppendFile(const char *pszCopyTo, const char *pszCopyFrom)
  413. {
  414. return (MscCopyFileLL(pszCopyTo, pszCopyFrom, "a+b"));
  415. }
  416. int MscCopyFile(FILE * pFileOut, FILE * pFileIn, unsigned long ulBaseOffset,
  417. unsigned long ulCopySize)
  418. {
  419. ///////////////////////////////////////////////////////////////////////////////
  420. //  Setup copy size and seek start byte
  421. ///////////////////////////////////////////////////////////////////////////////
  422. if (ulBaseOffset == (unsigned long) -1)
  423. ulBaseOffset = (unsigned long) ftell(pFileIn);
  424. fseek(pFileIn, 0, SEEK_END);
  425. unsigned long ulFileSize = (unsigned long) ftell(pFileIn);
  426. if (ulCopySize == (unsigned long) -1)
  427. ulCopySize = ulFileSize - ulBaseOffset;
  428. else
  429. ulCopySize = Min(ulCopySize, ulFileSize - ulBaseOffset);
  430. fseek(pFileIn, ulBaseOffset, SEEK_SET);
  431. ///////////////////////////////////////////////////////////////////////////////
  432. //  Copy bytes
  433. ///////////////////////////////////////////////////////////////////////////////
  434. char szBuffer[2048];
  435. while (ulCopySize > 0) {
  436. unsigned int uToRead = (unsigned int) Min(ulCopySize, sizeof(szBuffer));
  437. unsigned int uReaded = fread(szBuffer, 1, uToRead, pFileIn);
  438. if (uReaded > 0) {
  439. if (fwrite(szBuffer, 1, uReaded, pFileOut) != uReaded) {
  440. ErrSetErrorCode(ERR_FILE_WRITE);
  441. return (ERR_FILE_WRITE);
  442. }
  443. ulCopySize -= uReaded;
  444. }
  445. if (uReaded != uToRead) {
  446. ErrSetErrorCode(ERR_FILE_READ);
  447. return (ERR_FILE_READ);
  448. }
  449. }
  450. return (0);
  451. }
  452. int MscMoveFile(char const *pszOldName, char const *pszNewName)
  453. {
  454. if (MscCopyFile(pszNewName, pszOldName) < 0)
  455. return (ErrGetErrorCode());
  456. return (SysRemove(pszOldName));
  457. }
  458. char *MscGetString(FILE * pFile, char *pszBuffer, int iMaxChars)
  459. {
  460. return ((fgets(pszBuffer, iMaxChars, pFile) != NULL) ? StrEOLTrim(pszBuffer) : NULL);
  461. }
  462. char *MscFGets(char *pszLine, int iLineSize, FILE * pFile)
  463. {
  464. if (fgets(pszLine, iLineSize, pFile) == NULL)
  465. return (NULL);
  466. int ii;
  467. for (ii = strlen(pszLine); (ii > 0) && ((pszLine[ii - 1] == 'r') ||
  468. (pszLine[ii - 1] == 'n')); ii--);
  469. pszLine[ii] = '';
  470. return (pszLine);
  471. }
  472. char *MscGetConfigLine(char *pszLine, int iLineSize, FILE * pFile, bool bSkipComments)
  473. {
  474. while (MscFGets(pszLine, iLineSize, pFile) != NULL) {
  475. if ((strlen(pszLine) > 0) && (!bSkipComments || (pszLine[0] != TAB_COMMENT_CHAR)))
  476. return (pszLine);
  477. }
  478. ErrSetErrorCode(ERR_FILE_EOF);
  479. return (NULL);
  480. }
  481. int MscGetPeerHost(SYS_SOCKET SockFD, char *pszFQDN)
  482. {
  483. SYS_INET_ADDR PeerInfo;
  484. if (SysGetPeerInfo(SockFD, PeerInfo) < 0)
  485. return (ErrGetErrorCode());
  486. return (SysGetHostByAddr(PeerInfo, pszFQDN));
  487. }
  488. int MscGetSockHost(SYS_SOCKET SockFD, char *pszFQDN)
  489. {
  490. SYS_INET_ADDR SockInfo;
  491. if (SysGetSockInfo(SockFD, SockInfo) < 0)
  492. return (ErrGetErrorCode());
  493. return (SysGetHostByAddr(SockInfo, pszFQDN));
  494. }
  495. int MscGetServerAddress(char const *pszServer, SYS_INET_ADDR & SvrAddr, int iPortNo)
  496. {
  497. char szServer[MAX_HOST_NAME] = "";
  498. ZeroData(SvrAddr);
  499. if (MscSplitAddressPort(pszServer, szServer, iPortNo, iPortNo) < 0)
  500. return (ErrGetErrorCode());
  501. NET_ADDRESS NetAddr;
  502. if ((SysInetAddr(szServer, NetAddr) < 0) && (SysGetHostByName(szServer, NetAddr) < 0))
  503. return (ErrGetErrorCode());
  504. SysSetupAddress(SvrAddr, AF_INET, NetAddr, iPortNo);
  505. return (0);
  506. }
  507. int MscSplitFQDN(const char *pszFQDN, char *pszHost, char *pszDomain)
  508. {
  509. const char *pszDot = strchr(pszFQDN, '.');
  510. if (pszDot == NULL) {
  511. if (pszHost != NULL)
  512. strcpy(pszHost, pszFQDN);
  513. if (pszDomain != NULL)
  514. SetEmptyString(pszDomain);
  515. } else {
  516. if (pszHost != NULL) {
  517. int iHostLength = (int) (pszDot - pszFQDN);
  518. strncpy(pszHost, pszFQDN, iHostLength);
  519. pszHost[iHostLength] = '';
  520. }
  521. if (pszDomain != NULL) {
  522. strcpy(pszDomain, pszDot + 1);
  523. int iDomainLength = strlen(pszDomain);
  524. if ((iDomainLength > 0) && (pszDomain[iDomainLength - 1] == '.'))
  525. pszDomain[iDomainLength - 1] = '';
  526. }
  527. }
  528. return (0);
  529. }
  530. char *MscLogFilePath(char const *pszLogFile, char *pszLogFilePath)
  531. {
  532. time_t tCurrent;
  533. time(&tCurrent);
  534. long lRotStep = (unsigned long) (3600L * iLogRotateHours);
  535. long lTimeZone = SysGetTimeZone();
  536. long lDayLight = SysGetDayLight();
  537. time_t tLogFileTime = (time_t) (NbrFloor((SYS_INT64) tCurrent - lTimeZone + lDayLight,
  538.  lRotStep) + lTimeZone - lDayLight);
  539. struct tm tmLocTime;
  540. char szLogsDir[SYS_MAX_PATH] = "";
  541. SysLocalTime(&tLogFileTime, &tmLocTime);
  542. SvrGetLogsDir(szLogsDir, sizeof(szLogsDir));
  543. AppendSlash(szLogsDir);
  544. sprintf(pszLogFilePath, "%s%s-%04d%02d%02d%02d%02d",
  545. szLogsDir, pszLogFile,
  546. tmLocTime.tm_year + 1900,
  547. tmLocTime.tm_mon + 1, tmLocTime.tm_mday, tmLocTime.tm_hour, tmLocTime.tm_min);
  548. return (pszLogFilePath);
  549. }
  550. int MscFileLog(char const *pszLogFile, char const *pszFormat, ...)
  551. {
  552. char szLogFilePath[SYS_MAX_PATH] = "";
  553. MscLogFilePath(pszLogFile, szLogFilePath);
  554. FILE *pLogFile = fopen(szLogFilePath, "a+t");
  555. if (pLogFile == NULL) {
  556. ErrSetErrorCode(ERR_FILE_OPEN);
  557. return (ERR_FILE_OPEN);
  558. }
  559. va_list Args;
  560. va_start(Args, pszFormat);
  561. vfprintf(pLogFile, pszFormat, Args);
  562. va_end(Args);
  563. fclose(pLogFile);
  564. return (0);
  565. }
  566. int MscSplitPath(char const *pszFilePath, char *pszDir, char *pszFName, char *pszExt)
  567. {
  568. char const *pszSlash = strrchr(pszFilePath, SYS_SLASH_CHAR);
  569. char const *pszFile = NULL;
  570. if (pszSlash != NULL) {
  571. pszFile = pszSlash + 1;
  572. if (pszDir != NULL) {
  573. int iDirLength = (int) (pszFile - pszFilePath);
  574. strncpy(pszDir, pszFilePath, iDirLength);
  575. pszDir[iDirLength] = '';
  576. }
  577. } else {
  578. pszFile = pszFilePath;
  579. if (pszDir != NULL)
  580. SetEmptyString(pszDir);
  581. }
  582. char const *pszDot = strrchr(pszFile, '.');
  583. if (pszDot != NULL) {
  584. if (pszFName != NULL) {
  585. int iNameLength = (int) (pszDot - pszFile);
  586. strncpy(pszFName, pszFile, iNameLength);
  587. pszFName[iNameLength] = '';
  588. }
  589. if (pszExt != NULL)
  590. strcpy(pszExt, pszDot);
  591. } else {
  592. if (pszFName != NULL)
  593. strcpy(pszFName, pszFile);
  594. if (pszExt != NULL)
  595. SetEmptyString(pszExt);
  596. }
  597. return (0);
  598. }
  599. int MscGetFileName(char const *pszFilePath, char *pszFileName)
  600. {
  601. char const *pszSlash = strrchr(pszFilePath, SYS_SLASH_CHAR);
  602. strcpy(pszFileName, (pszSlash != NULL) ? (pszSlash + 1) : pszFilePath);
  603. return (0);
  604. }
  605. int MscCreateClientSocket(char const *pszServer, int iPortNo, int iSockType,
  606.   SYS_SOCKET * pSockFD, SYS_INET_ADDR * pSvrAddr,
  607.   SYS_INET_ADDR * pSockAddr, int iTimeout)
  608. {
  609. ///////////////////////////////////////////////////////////////////////////////
  610. //  Get server address
  611. ///////////////////////////////////////////////////////////////////////////////
  612. SYS_INET_ADDR SvrAddr;
  613. if (MscGetServerAddress(pszServer, SvrAddr, iPortNo) < 0)
  614. return (ErrGetErrorCode());
  615. SYS_SOCKET SockFD = SysCreateSocket(AF_INET, iSockType, 0);
  616. if (SockFD == SYS_INVALID_SOCKET)
  617. return (ErrGetErrorCode());
  618. if (SysConnect(SockFD, &SvrAddr, sizeof(SvrAddr), iTimeout) < 0) {
  619. ErrorPush();
  620. SysCloseSocket(SockFD);
  621. return (ErrorPop());
  622. }
  623. SYS_INET_ADDR SockAddr;
  624. ZeroData(SockAddr);
  625. if (SysGetSockInfo(SockFD, SockAddr) < 0) {
  626. ErrorPush();
  627. SysCloseSocket(SockFD);
  628. return (ErrorPop());
  629. }
  630. *pSockFD = SockFD;
  631. if (pSvrAddr != NULL)
  632. *pSvrAddr = SvrAddr;
  633. if (pSockAddr != NULL)
  634. *pSockAddr = SockAddr;
  635. return (0);
  636. }
  637. int MscCreateServerSockets(int iNumAddr, SYS_INET_ADDR const *pSvrAddr, int iPortNo,
  638.    int iListenSize, SYS_SOCKET * pSockFDs, int &iNumSockFDs)
  639. {
  640. if (iNumAddr == 0) {
  641. SYS_SOCKET SvrSockFD = SysCreateSocket(AF_INET, SOCK_STREAM, 0);
  642. if (SvrSockFD == SYS_INVALID_SOCKET)
  643. return (ErrGetErrorCode());
  644. SYS_INET_ADDR InSvrAddr;
  645. SysSetupAddress(InSvrAddr, AF_INET, htonl(INADDR_ANY), iPortNo);
  646. if (SysBindSocket(SvrSockFD, (struct sockaddr *) &InSvrAddr, sizeof(InSvrAddr)) <
  647.     0) {
  648. ErrorPush();
  649. SysCloseSocket(SvrSockFD);
  650. return (ErrorPop());
  651. }
  652. SysListenSocket(SvrSockFD, iListenSize);
  653. *pSockFDs = SvrSockFD;
  654. iNumSockFDs = 1;
  655. } else {
  656. iNumSockFDs = 0;
  657. for (int ii = 0; ii < iNumAddr; ii++) {
  658. SYS_SOCKET SvrSockFD = SysCreateSocket(AF_INET, SOCK_STREAM, 0);
  659. if (SvrSockFD == SYS_INVALID_SOCKET) {
  660. ErrorPush();
  661. for (--iNumSockFDs; iNumSockFDs >= 0; iNumSockFDs--)
  662. SysCloseSocket(pSockFDs[iNumSockFDs]);
  663. return (ErrorPop());
  664. }
  665. SYS_INET_ADDR InSvrAddr = pSvrAddr[ii];
  666. if (SysGetAddrPort(InSvrAddr) == 0)
  667. SysSetAddrPort(InSvrAddr, iPortNo);
  668. if (SysBindSocket
  669.     (SvrSockFD, (struct sockaddr *) &InSvrAddr, sizeof(InSvrAddr)) < 0) {
  670. ErrorPush();
  671. SysCloseSocket(SvrSockFD);
  672. for (--iNumSockFDs; iNumSockFDs >= 0; iNumSockFDs--)
  673. SysCloseSocket(pSockFDs[iNumSockFDs]);
  674. return (ErrorPop());
  675. }
  676. SysListenSocket(SvrSockFD, iListenSize);
  677. pSockFDs[iNumSockFDs++] = SvrSockFD;
  678. }
  679. }
  680. return (0);
  681. }
  682. int MscGetMaxSockFD(SYS_SOCKET const *pSockFDs, int iNumSockFDs)
  683. {
  684. int iMaxFD = 0;
  685. for (int ii = 0; ii < iNumSockFDs; ii++)
  686. if (iMaxFD < (int) pSockFDs[ii])
  687. iMaxFD = (int) pSockFDs[ii];
  688. return (iMaxFD);
  689. }
  690. int MscAcceptServerConnection(SYS_SOCKET const *pSockFDs, int iNumSockFDs,
  691.       SYS_SOCKET * pConnSockFD, int &iNumConnSockFD, int iTimeout)
  692. {
  693. int ii;
  694. SYS_fd_set fdReadSet;
  695. ZeroData(fdReadSet);
  696. SYS_FD_ZERO(&fdReadSet);
  697. for (ii = 0; ii < iNumSockFDs; ii++)
  698. SYS_FD_SET(pSockFDs[ii], &fdReadSet);
  699. int iSelectResult = SysSelect(MscGetMaxSockFD(pSockFDs, iNumSockFDs),
  700.       &fdReadSet, NULL, NULL, iTimeout);
  701. if (iSelectResult < 0)
  702. return (ErrGetErrorCode());
  703. iNumConnSockFD = 0;
  704. for (ii = 0; ii < iNumSockFDs; ii++) {
  705. if (SYS_FD_ISSET(pSockFDs[ii], &fdReadSet)) {
  706. SYS_INET_ADDR ConnAddr;
  707. int iConnAddrLength = sizeof(ConnAddr);
  708. ZeroData(ConnAddr);
  709. SYS_SOCKET ConnSockFD = SysAccept(pSockFDs[ii], &ConnAddr,
  710.   &iConnAddrLength, iTimeout);
  711. if (ConnSockFD != SYS_INVALID_SOCKET)
  712. pConnSockFD[iNumConnSockFD++] = ConnSockFD;
  713. }
  714. }
  715. return (0);
  716. }
  717. int MscLoadAddressFilter(char const *const *ppszFilter, int iNumTokens, AddressFilter & AF)
  718. {
  719. ZeroData(AF);
  720. if (iNumTokens > 1) {
  721. SysInetAddr(ppszFilter[0], *((NET_ADDRESS *) AF.Addr));
  722. SysInetAddr(ppszFilter[1], *((NET_ADDRESS *) AF.Mask));
  723. } else {
  724. char const *pszMask;
  725. if ((pszMask = strchr(ppszFilter[0], '/')) != NULL) {
  726. int ii;
  727. int iAddrLength = (int) (pszMask - ppszFilter[0]);
  728. int iMaskBits = atoi(pszMask + 1);
  729. char szFilter[128];
  730. iAddrLength = Min(iAddrLength, sizeof(szFilter) - 1);
  731. strncpy(szFilter, ppszFilter[0], iAddrLength);
  732. szFilter[iAddrLength] = '';
  733. SysInetAddr(szFilter, *((NET_ADDRESS *) AF.Addr));
  734. iMaskBits = Min(iMaskBits, 8 * sizeof(NET_ADDRESS));
  735. for (ii = 0; (ii + 8) <= iMaskBits; ii += 8)
  736. AF.Mask[ii / 8] = 0xff;
  737. if (ii < iMaskBits)
  738. AF.Mask[ii / 8] =
  739.     (SYS_UINT8) (((1 << (iMaskBits - ii)) - 1) << (8 - iMaskBits +
  740.    ii));
  741. } else {
  742. SysInetAddr(ppszFilter[0], *((NET_ADDRESS *) AF.Addr));
  743. for (int ii = 0; ii < sizeof(NET_ADDRESS); ii++)
  744. AF.Mask[ii] = (AF.Addr[ii] != 0) ? 0xff : 0x00;
  745. }
  746. }
  747. return (0);
  748. }
  749. bool MscAddressMatch(AddressFilter const &AF, NET_ADDRESS const &TestAddr)
  750. {
  751. SYS_UINT8 ByteAddr[sizeof(NET_ADDRESS)];
  752. *((NET_ADDRESS *) ByteAddr) = TestAddr;
  753. for (int ii = 0; ii < sizeof(NET_ADDRESS); ii++)
  754. if ((ByteAddr[ii] & AF.Mask[ii]) != (AF.Addr[ii] & AF.Mask[ii]))
  755. return (false);
  756. return (true);
  757. }
  758. int MscCheckAllowedIP(char const *pszMapFile, const SYS_INET_ADDR & PeerInfo, bool bDefault)
  759. {
  760. FILE *pMapFile = fopen(pszMapFile, "rt");
  761. if (pMapFile == NULL) {
  762. ErrSetErrorCode(ERR_FILE_OPEN, pszMapFile);
  763. return (ERR_FILE_OPEN);
  764. }
  765. NET_ADDRESS TestAddr;
  766. SysGetAddrAddress(PeerInfo, TestAddr);
  767. bool bAllow = bDefault;
  768. int iPrecedence = -1;
  769. char szMapLine[512] = "";
  770. while (MscGetConfigLine(szMapLine, sizeof(szMapLine) - 1, pMapFile) != NULL) {
  771. char **ppszStrings = StrGetTabLineStrings(szMapLine);
  772. if (ppszStrings == NULL)
  773. continue;
  774. int iFieldsCount = StrStringsCount(ppszStrings);
  775. AddressFilter AF;
  776. if ((iFieldsCount >= ipmMax) &&
  777.     (MscLoadAddressFilter(ppszStrings, iFieldsCount, AF) == 0) &&
  778.     MscAddressMatch(AF, TestAddr)) {
  779. int iCurrPrecedence = atoi(ppszStrings[ipmPrecedence]);
  780. if (iCurrPrecedence >= iPrecedence) {
  781. iPrecedence = iCurrPrecedence;
  782. bAllow =
  783.     (stricmp(ppszStrings[ipmAllow], "ALLOW") == 0) ? true : false;
  784. }
  785. }
  786. StrFreeStrings(ppszStrings);
  787. }
  788. fclose(pMapFile);
  789. if (!bAllow) {
  790. ErrSetErrorCode(ERR_IP_NOT_ALLOWED);
  791. return (ERR_IP_NOT_ALLOWED);
  792. }
  793. return (0);
  794. }
  795. char **MscGetIPProperties(char const *pszFileName, const SYS_INET_ADDR & PeerInfo)
  796. {
  797. ///////////////////////////////////////////////////////////////////////////////
  798. //  Get peer IP addresses
  799. ///////////////////////////////////////////////////////////////////////////////
  800. NET_ADDRESS PeerAddr;
  801. SysGetAddrAddress(PeerInfo, PeerAddr);
  802. ///////////////////////////////////////////////////////////////////////////////
  803. //  Open the IP properties database. Fail smoothly if the file does not exist
  804. ///////////////////////////////////////////////////////////////////////////////
  805. FILE *pFile = fopen(pszFileName, "rt");
  806. if (pFile == NULL)
  807. return (NULL);
  808. char szLine[IPPROP_LINE_MAX] = "";
  809. while (MscGetConfigLine(szLine, sizeof(szLine) - 1, pFile) != NULL) {
  810. char **ppszTokens = StrGetTabLineStrings(szLine);
  811. if (ppszTokens == NULL)
  812. continue;
  813. int iFieldsCount = StrStringsCount(ppszTokens);
  814. AddressFilter AFPeer;
  815. if ((iFieldsCount >= 1) && (MscLoadAddressFilter(&ppszTokens[0], 1, AFPeer) == 0)
  816.     && MscAddressMatch(AFPeer, PeerAddr)) {
  817. fclose(pFile);
  818. return (ppszTokens);
  819. }
  820. StrFreeStrings(ppszTokens);
  821. }
  822. fclose(pFile);
  823. return (NULL);
  824. }
  825. int MscMD5Authenticate(const char *pszPassword, const char *pszTimeStamp, const char *pszDigest)
  826. {
  827. char *pszHash = StrSprint("%s%s", pszTimeStamp, pszPassword);
  828. if (pszHash == NULL)
  829. return (ErrGetErrorCode());
  830. char szMD5[128] = "";
  831. do_md5_string(pszHash, strlen(pszHash), szMD5);
  832. SysFree(pszHash);
  833. if (stricmp(pszDigest, szMD5) != 0) {
  834. ErrSetErrorCode(ERR_MD5_AUTH_FAILED);
  835. return (ERR_MD5_AUTH_FAILED);
  836. }
  837. return (0);
  838. }
  839. char *MscExtractServerTimeStamp(char const *pszResponse, char *pszTimeStamp, int iMaxTimeStamp)
  840. {
  841. char const *pszStartTS = strchr(pszResponse, '<');
  842. char const *pszEndTS = strchr(pszResponse, '>');
  843. if ((pszStartTS == NULL) || (pszEndTS == NULL))
  844. return (NULL);
  845. int iLengthTS = (int) (pszEndTS - pszStartTS) + 1;
  846. if (iLengthTS <= 0)
  847. return (NULL);
  848. iLengthTS = Min(iLengthTS, iMaxTimeStamp - 1);
  849. strncpy(pszTimeStamp, pszStartTS, iLengthTS);
  850. pszTimeStamp[iLengthTS] = '';
  851. return (pszTimeStamp);
  852. }
  853. int MscBase64FileEncode(char const *pszBoundary, char const *pszFilePath, FILE * pFileOut)
  854. {
  855. FILE *pFileIn = fopen(pszFilePath, "rb");
  856. if (pFileIn == NULL) {
  857. ErrSetErrorCode(ERR_FILE_OPEN, pszFilePath);
  858. return (ERR_FILE_OPEN);
  859. }
  860. char szFName[SYS_MAX_PATH] = "";
  861. char szExt[SYS_MAX_PATH] = "";
  862. MscSplitPath(pszFilePath, NULL, szFName, szExt);
  863. fprintf(pFileOut, "rn--%srn"
  864. "Content-Type: application/octet-stream;rn"
  865. "tname="%s%s"rn"
  866. "Content-Transfer-Encoding: base64rn"
  867. "Content-Disposition: attachment;rn"
  868. "tfilename="%s%s"rnrn", pszBoundary, szFName, szExt, szFName, szExt);
  869. ///////////////////////////////////////////////////////////////////////////////
  870. //  Note that sizeof(szFileBuffer) must be multiple of 3
  871. ///////////////////////////////////////////////////////////////////////////////
  872. unsigned int uReadSize;
  873. char szFileBuffer[80 * 3] = "";
  874. char szEncBuffer[512] = "";
  875. do {
  876. uReadSize = fread(szFileBuffer, 1, sizeof(szFileBuffer), pFileIn);
  877. if (uReadSize > 0) {
  878. unsigned int uOutLength = sizeof(szEncBuffer);
  879. encode64(szFileBuffer, uReadSize, szEncBuffer, sizeof(szEncBuffer) - 1,
  880.  &uOutLength);
  881. unsigned int uWriteSize = 80;
  882. char *pszWrite = szEncBuffer;
  883. for (; uOutLength > 0; uOutLength -= uWriteSize, pszWrite += uWriteSize) {
  884. uWriteSize = Min(uOutLength, uWriteSize);
  885. if (!fwrite(pszWrite, uWriteSize, 1, pFileOut)) {
  886. fclose(pFileIn);
  887. ErrSetErrorCode(ERR_FILE_WRITE);
  888. return (ERR_FILE_WRITE);
  889. }
  890. fputs("rn", pFileOut);
  891. }
  892. }
  893. } while (uReadSize == sizeof(szFileBuffer));
  894. fclose(pFileIn);
  895. return (0);
  896. }
  897. int MscRootedName(char const *pszHostName)
  898. {
  899. char const *pszDot = strrchr(pszHostName, '.');
  900. return ((pszDot == NULL) ? 0 : ((strlen(pszDot) == 0) ? 1 : 0));
  901. }
  902. int MscCramMD5(char const *pszSecret, char const *pszChallenge, char *pszDigest)
  903. {
  904. int iLenght = (int) strlen(pszSecret);
  905. struct md5_ctx ctx;
  906. unsigned char isecret[64];
  907. unsigned char osecret[64];
  908. unsigned char md5secret[16];
  909. if (iLenght > 64) {
  910. md5_init_ctx(&ctx);
  911. md5_process_bytes(pszSecret, iLenght, &ctx);
  912. md5_finish_ctx(&ctx, md5secret);
  913. pszSecret = (char const *) md5secret;
  914. iLenght = 16;
  915. }
  916. ZeroData(isecret);
  917. memcpy(isecret, pszSecret, iLenght);
  918. ZeroData(osecret);
  919. memcpy(osecret, pszSecret, iLenght);
  920. for (int ii = 0; ii < 64; ii++) {
  921. isecret[ii] ^= 0x36;
  922. osecret[ii] ^= 0x5c;
  923. }
  924. md5_init_ctx(&ctx);
  925. md5_process_bytes(isecret, 64, &ctx);
  926. md5_process_bytes((unsigned char *) pszChallenge, (int) strlen(pszChallenge), &ctx);
  927. md5_finish_ctx(&ctx, md5secret);
  928. md5_init_ctx(&ctx);
  929. md5_process_bytes(osecret, 64, &ctx);
  930. md5_process_bytes(md5secret, 16, &ctx);
  931. md5_finish_ctx(&ctx, md5secret);
  932. md5_hex(md5secret, pszDigest);
  933. return (0);
  934. }
  935. SYS_UINT32 MscHashString(char const *pszBuffer, int iLength, SYS_UINT32 uHashInit)
  936. {
  937. SYS_UINT32 uHashVal = uHashInit;
  938. while (iLength > 0) {
  939. --iLength;
  940. uHashVal += (uHashVal << 5);
  941. uHashVal ^= (SYS_UINT32) * pszBuffer++;
  942. }
  943. return (uHashVal);
  944. }
  945. int MscSplitAddressPort(char const *pszConnSpec, char *pszAddress, int &iPortNo, int iDefPortNo)
  946. {
  947. char const *pszEnd = NULL, *pszPort;
  948. iPortNo = iDefPortNo;
  949. if (*pszConnSpec == '[') {
  950. pszConnSpec++;
  951. if ((pszEnd = strchr(pszConnSpec, ']')) == NULL) {
  952. ErrSetErrorCode(ERR_BAD_SERVER_ADDR);
  953. return (ERR_BAD_SERVER_ADDR);
  954. }
  955. if ((pszPort = strrchr(pszEnd + 1, '|')) == NULL)
  956. pszPort = strrchr(pszEnd + 1, ':');
  957. if (pszPort != NULL)
  958. iPortNo = atoi(pszPort + 1);
  959. } else {
  960. if ((pszPort = strrchr(pszConnSpec, '|')) == NULL)
  961. pszPort = strrchr(pszConnSpec, ':');
  962. if ((pszEnd = pszPort) != NULL)
  963. iPortNo = atoi(pszPort + 1);
  964. }
  965. if (pszEnd != NULL) {
  966. int iAddrLen = Min((int) (pszEnd - pszConnSpec), MAX_HOST_NAME - 1);
  967. strncpy(pszAddress, pszConnSpec, iAddrLen);
  968. pszAddress[iAddrLen] = '';
  969. } else
  970. strncpy(pszAddress, pszConnSpec, MAX_HOST_NAME - 1);
  971. return (0);
  972. }
  973. SYS_UINT16 MscReadUint16(void const *pData)
  974. {
  975. SYS_UINT16 uValue;
  976. memcpy(&uValue, pData, sizeof(uValue));
  977. return (uValue);
  978. }
  979. SYS_UINT32 MscReadUint32(void const *pData)
  980. {
  981. SYS_UINT32 uValue;
  982. memcpy(&uValue, pData, sizeof(uValue));
  983. return (uValue);
  984. }
  985. SYS_UINT64 MscReadUint64(void const *pData)
  986. {
  987. SYS_UINT64 uValue;
  988. memcpy(&uValue, pData, sizeof(uValue));
  989. return (uValue);
  990. }
  991. void *MscWriteUint16(void *pData, SYS_UINT16 uValue)
  992. {
  993. return (memcpy(pData, &uValue, sizeof(uValue)));
  994. }
  995. void *MscWriteUint32(void *pData, SYS_UINT32 uValue)
  996. {
  997. return (memcpy(pData, &uValue, sizeof(uValue)));
  998. }
  999. void *MscWriteUint64(void *pData, SYS_UINT64 uValue)
  1000. {
  1001. return (memcpy(pData, &uValue, sizeof(uValue)));
  1002. }
  1003. int MscCmdStringCheck(char const *pszString)
  1004. {
  1005. for (; *pszString != ''; pszString++)
  1006. if (((*pszString < ' ') || (*pszString > '~')) && (*pszString != 't')) {
  1007. ErrSetErrorCode(ERR_BAD_CMDSTR_CHARS);
  1008. return (ERR_BAD_CMDSTR_CHARS);
  1009. }
  1010. return (0);
  1011. }
  1012. int MscGetSectionSize(FileSection const *pFS, unsigned long *pulSize)
  1013. {
  1014. if (pFS->ulEndOffset == (unsigned long) -1) {
  1015. SYS_FILE_INFO FI;
  1016. if (SysGetFileInfo(pFS->szFilePath, FI) < 0)
  1017. return (ErrGetErrorCode());
  1018. *pulSize = FI.ulSize - pFS->ulStartOffset;
  1019. } else
  1020. *pulSize = pFS->ulEndOffset - pFS->ulStartOffset;
  1021. return (0);
  1022. }