123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530 |
- /* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * 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; either
- * version 2 of the License, or (at your option) any later version.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *
- * File: ODPlat.c
- *
- * Description: Contains platform-specific utility functions. Non-platform
- * specific utility functions are implemented in odutil.c
- *
- * Revisions: Date Ver Who Change
- * ---------------------------------------------------------------
- * Oct 14, 1994 6.00 BP Created, with od_yield().
- * Nov 01, 1994 6.00 BP Added new directory access functions.
- * Dec 09, 1994 6.00 BP Eliminate access to old dir functions.
- * Dec 31, 1994 6.00 BP Added timing, file delete functions.
- * Dec 31, 1994 6.00 BP Remove #ifndef USEINLINE DOS code.
- * Dec 31, 1994 6.00 BP Added ODMultitasker and ODPlatInit()
- * Nov 14, 1995 6.00 BP 32-bit portability.
- * Nov 16, 1995 6.00 BP Removed oddoor.h, added odcore.h.
- * Nov 17, 1995 6.00 BP Added multithreading functions.
- * Nov 21, 1995 6.00 BP Ported to Win32.
- * Dec 12, 1995 6.00 BP Added entry, exit and kernel macros.
- * Dec 13, 1995 6.00 BP Added ODThreadWaitForExit().
- * Dec 13, 1995 6.00 BP Added ODThreadGetCurrent().
- * Dec 19, 1995 6.00 BP Fixed ODThreadGetCurrent() (Win32).
- * Dec 30, 1995 6.00 BP Added ODCALL for calling convention.
- * Jan 23, 1996 6.00 BP Added ODProcessExit().
- * Jan 30, 1996 6.00 BP Replaced od_yield() with od_sleep().
- * Jan 30, 1996 6.00 BP Add semaphore timeout.
- * Jan 31, 1996 6.00 BP Add ODTimerLeft(), rm ODTimerSleep().
- * Feb 19, 1996 6.00 BP Changed version number to 6.00.
- * Mar 03, 1996 6.10 BP Begin version 6.10.
- * Mar 06, 1996 6.10 BP Prevent TC calls N_LXMUL@ & N_LXDIV@.
- * Mar 19, 1996 6.10 BP MSVC15 source-level compatibility.
- * Aug 10, 2003 6.23 SH *nix support
- */
- #define BUILDING_OPENDOORS
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <ctype.h>
- #include <string.h>
- #include "OpenDoor.h"
- #ifdef ODPLAT_NIX
- #include <sys/time.h>
- #include <glob.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #endif
- #include "ODGen.h"
- #include "ODCore.h"
- #include "ODPlat.h"
- #include "ODUtil.h"
- #include "ODSwap.h"
- #include "ODKrnl.h"
- #ifdef ODPLAT_WIN32
- #include "windows.h"
- #endif /* ODPLAT_WIN32 */
- /* Multitasker type, only availvable under DOS. */
- #ifdef ODPLAT_DOS
- tODMultitasker ODMultitasker = kMultitaskerNone;
- static void ODPlatYield(void);
- #endif /* ODPLAT_DOS */
- /* ----------------------------------------------------------------------------
- * ODPlatInit()
- *
- * Performs any initialization required to use the utility functions supplied
- * by this module.
- *
- * Parameters: none
- *
- * Return: void
- */
- void ODPlatInit(void)
- {
- #ifdef ODPLAT_DOS
- /* If this is the DOS version of OpenDoors, then ODPlatInit() must */
- /* determine what multitasker we are running under. */
- /* Check whether running under OS/2. */
- ASM mov ah, 0x30
- ASM int 0x21
- ASM cmp al, 0x0a
- ASM jl NoOS2
- /* If we get to this point, then OS/2 has been detected. */
- ODMultitasker = kMultitaskerOS2;
- return;
- NoOS2:
- /* Check whether we are running under DesqView. */
- ASM mov cx, 0x4445
- ASM mov dx, 0x5351
- ASM mov ax, 0x2b01
- ASM int 0x21
- ASM cmp al, 0xff
- ASM je NoDesqView
- /* If we get to this point, then DesqView has been detected. */
- ODMultitasker = kMultitaskerDV;
- NoDesqView:
- /* Check whether we are running under Windows. */
- ASM push di
- ASM push si
- ASM mov ax, 0x1600
- ASM int 0x2f
- ASM pop si
- ASM pop di
- ASM cmp al, 0x00
- ASM je NoWindows
- ASM cmp al, 0x80
- ASM je NoWindows
- /* If we get to this point, then Windows has been detected. */
- ODMultitasker = kMultitaskerWin;
- NoWindows:
- ODMultitasker = kMultitaskerNone;
- #endif /* ODPLAT_DOS */
- }
- /* ----------------------------------------------------------------------------
- * ODPlatYield() *** PRIVATE FUNCTION ***
- *
- * Yields control to other tasks when running as a DOS application under a
- * multitasking system.
- *
- * Parameters: none
- *
- * Return: void
- */
- #ifdef ODPLAT_DOS
- static void ODPlatYield(void)
- {
- switch(ODMultitasker)
- {
- case kMultitaskerDV:
- ASM mov ax, 0x1000
- ASM int 0x15
- break;
- case kMultitaskerWin:
- ASM mov ax, 0x1680
- ASM int 0x2f
- break;
- case kMultitaskerOS2:
- default:
- ASM int 0x28
- }
- }
- #endif /* ODPLAT_DOS */
- /* ========================================================================= */
- /* Multithreading and synchronization support. */
- /* ========================================================================= */
- #ifdef OD_MULTITHREADED
- /* ----------------------------------------------------------------------------
- * ODThreadCreate()
- *
- * Starts a new thread of concurrent execution.
- *
- * Parameters: phThread - Pointer to the location where the handle to the
- * new thread should be stored.
- *
- * pfThreadProc - Function to call to begin execution of the
- * thread.
- *
- * pThreadParam - Parameter to pass to the thread function when
- * it is called.
- *
- * Return: kOCRCSuccess on success, or an error code on failure.
- */
- tODResult ODThreadCreate(tODThreadHandle *phThread,
- ptODThreadProc *pfThreadProc, void *pThreadParam)
- {
- #ifdef ODPLAT_WIN32
- DWORD dwThreadID;
- HANDLE hNewThread;
- ASSERT(phThread != NULL);
- ASSERT(pfThreadProc != NULL);
-
- /* Attempt to create the new thread. */
- hNewThread = CreateThread(NULL, 0, pfThreadProc, pThreadParam,
- 0, &dwThreadID);
- /* Check for thread creation failure. */
- if(hNewThread == NULL)
- {
- return(kODRCGeneralFailure);
- }
- /* Pass newly created thread's handle back to the caller. */
- *phThread = hNewThread;
- /* Return with success. */
- return(kODRCSuccess);
- #endif /* ODPLAT_WIN32 */
- }
- /* ----------------------------------------------------------------------------
- * ODThreadExit()
- *
- * Causes the calling thread to be terminated.
- *
- * Parameters: none
- *
- * Return: Never returns!
- */
- void ODThreadExit()
- {
- #ifdef ODPLAT_WIN32
- ExitThread(0);
- #endif /* ODPLAT_WIN32 */
- /* We should never get here. */
- ASSERT(FALSE);
- }
- /* ----------------------------------------------------------------------------
- * ODThreadTerminate()
- *
- * Terminates the specified thread.
- *
- * Parameters: hThread - Handle to the thread to be terminated.
- *
- * Return: kOCRCSuccess on success, or an error code on failure.
- */
- tODResult ODThreadTerminate(tODThreadHandle hThread)
- {
- ASSERT(hThread != NULL);
- #ifdef ODPLAT_WIN32
- return(TerminateThread(hThread, 0) ? kODRCSuccess : kODRCGeneralFailure);
- #endif /* ODPLAT_WIN32 */
- }
- /* ----------------------------------------------------------------------------
- * ODThreadSuspend()
- *
- * Pauses execution of the specified thread, until the ODThreadResume()
- * function is called.
- *
- * Parameters: hThread - Handle to the thread to be suspended.
- *
- * Return: kOCRCSuccess on success, or an error code on failure.
- */
- tODResult ODThreadSuspend(tODThreadHandle hThread)
- {
- ASSERT(hThread != NULL);
- #ifdef ODPLAT_WIN32
- return(SuspendThread(hThread) == 0xFFFFFFFF ? kODRCGeneralFailure
- : kODRCSuccess);
- #endif /* ODPLAT_WIN32 */
- }
- /* ----------------------------------------------------------------------------
- * ODThreadResume()
- *
- * Continues execution of a thread previously paused by a call to
- * ODThreadSuspend().
- *
- * Parameters: hThread - Handle to the thread to be resumed.
- *
- * Return: kOCRCSuccess on success, or an error code on failure.
- */
- tODResult ODThreadResume(tODThreadHandle hThread)
- {
- ASSERT(hThread != NULL);
- #ifdef ODPLAT_WIN32
- return(ResumeThread(hThread) == 0xFFFFFFFF ? kODRCGeneralFailure
- : kODRCSuccess);
- #endif /* ODPLAT_WIN32 */
- }
- /* ----------------------------------------------------------------------------
- * ODThreadSetPriority()
- *
- * Changes the execution priority of a thread. Since the exact semantics of
- * thread priorities are different for each platform, this function should
- * be used carefully. The caller should assume that no thread will run if there
- * exists a non-blocked thread with a higher priority.
- *
- * Parameters: hThread - Handle to the thread to change the priority of.
- *
- * ThreadPriority - New priority to assign to the thread.
- *
- * Return: kOCRCSuccess on success, or an error code on failure.
- */
- tODResult ODThreadSetPriority(tODThreadHandle hThread,
- tODThreadPriority ThreadPriority)
- {
- #ifdef ODPLAT_WIN32
- int nWindowsThreadPriority;
- ASSERT(hThread != NULL);
- /* Determine the Windows thread priority to assign to the thread. */
- switch(ThreadPriority)
- {
- case OD_PRIORITY_LOWEST:
- nWindowsThreadPriority = THREAD_PRIORITY_LOWEST;
- break;
- case OD_PRIORITY_BELOW_NORMAL:
- nWindowsThreadPriority = THREAD_PRIORITY_BELOW_NORMAL;
- break;
- case OD_PRIORITY_NORMAL:
- nWindowsThreadPriority = THREAD_PRIORITY_NORMAL;
- break;
- case OD_PRIORITY_ABOVE_NORMAL:
- nWindowsThreadPriority = THREAD_PRIORITY_ABOVE_NORMAL;
- break;
- case OD_PRIORITY_HIGHEST:
- nWindowsThreadPriority = THREAD_PRIORITY_HIGHEST;
- break;
- default:
- ASSERT(FALSE);
- }
- /* Update the thread's priority. */
- return(SetThreadPriority(hThread, nWindowsThreadPriority)
- ? kODRCSuccess : kODRCGeneralFailure);
- #endif /* ODPLAT_WIN32 */
- }
- /* ----------------------------------------------------------------------------
- * ODThreadWaitForExit()
- *
- * Blocks until the specified thread is terminated.
- *
- * Parameters: hThread - Handle to the thread to wait for.
- *
- * Return: void
- */
- void ODThreadWaitForExit(tODThreadHandle hThread)
- {
- #ifdef ODPLAT_WIN32
- WaitForSingleObject(hThread, INFINITE);
- #endif /* ODPLAT_WIN32 */
- }
- /* ----------------------------------------------------------------------------
- * ODThreadGetCurrent()
- *
- * Obtains a handle to the thread that called this function.
- *
- * Parameters: None.
- *
- * Return: Handle to the current thread.
- */
- tODThreadHandle ODThreadGetCurrent(void)
- {
- #ifdef ODPLAT_WIN32
- HANDLE hDuplicate;
- if(!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
- GetCurrentProcess(), &hDuplicate, 0, FALSE, DUPLICATE_SAME_ACCESS))
- {
- return(NULL);
- }
- return(hDuplicate);
- #endif /* ODPLAT_WIN32 */
- }
- /* ----------------------------------------------------------------------------
- * ODSemaphoreAlloc()
- *
- * Allocates a semaphore synchronization object.
- *
- * Parameters: phSemaphore - Pointer to location where the handle to the
- * newly created semaphore should be stored.
- *
- * nInitialCount - Initial value to assign to the semaphore.
- *
- * nMaximumCount - Maximum value that the semaphore may have
- * (if supported by the current platform).
- *
- * Return: kOCRCSuccess on success, or an error code on failure.
- */
- tODResult ODSemaphoreAlloc(tODSemaphoreHandle *phSemaphore, INT nInitialCount,
- INT nMaximumCount)
- {
- ASSERT(phSemaphore != NULL);
- ASSERT(nInitialCount >= 0);
- ASSERT(nMaximumCount >= nInitialCount);
- #ifdef ODPLAT_WIN32
- *phSemaphore = CreateSemaphore(NULL, (LONG)nInitialCount,
- (LONG)nMaximumCount, NULL);
- return(*phSemaphore == NULL ? kODRCGeneralFailure : kODRCSuccess);
- #endif /* ODPLAT_WIN32 */
- }
- /* ----------------------------------------------------------------------------
- * ODSemaphoreFree()
- *
- * Deallocates a semaphore that we previously created by ODSemaphoreAlloc().
- *
- * Parameters: hSemaphore - Handle to semaphore to deallocate.
- *
- * Return: void
- */
- void ODSemaphoreFree(tODSemaphoreHandle hSemaphore)
- {
- ASSERT(hSemaphore != NULL);
- #ifdef ODPLAT_WIN32
- DeleteObject(hSemaphore);
- #endif /* ODPLAT_WIN32 */
- }
- /* ----------------------------------------------------------------------------
- * ODSemaphoreUp()
- *
- * Increments the count of the specified semaphore.
- *
- * Parameters: hSemaphore - Semaphore to increment.
- *
- * nIncrementBy - Amount to add to the semaphore's current value.
- *
- * Return: void
- */
- void ODSemaphoreUp(tODSemaphoreHandle hSemaphore, INT nIncrementBy)
- {
- ASSERT(hSemaphore != NULL);
- ASSERT(nIncrementBy > 0);
- #ifdef ODPLAT_WIN32
- ReleaseSemaphore(hSemaphore, nIncrementBy, NULL);
- #endif /* ODPLAT_WIN32 */
- }
- /* ----------------------------------------------------------------------------
- * ODSemaphoreDown()
- *
- * Decrements the count of the specified semaphore. A semaphore may never have
- * a value less than 0. Hence, an attempt to decrement the value of a
- * semaphore below zero will cause the calling thread to be blocked until some
- * other thread increments the semaphore.
- *
- * Parameters: hSemaphore - Handle to the semaphore to decrement.
- *
- * Timeout - Maximum time to wait for the semaphore to be
- * incremented, or OD_NO_TIMEOUT to prevent this
- * function from returning before the semaphore is
- * incremented.
- *
- * Return: kODRCSuccess, or kODRCTimeout if the semaphore was not
- * decremented before Timeout milliseconds elapsed.
- */
- tODResult ODSemaphoreDown(tODSemaphoreHandle hSemaphore, tODMilliSec Timeout)
- {
- ASSERT(hSemaphore != NULL);
- #ifdef ODPLAT_WIN32
- if(WaitForSingleObject(hSemaphore, Timeout) != WAIT_OBJECT_0)
- {
- return(kODRCTimeout);
- }
- #endif /* ODPLAT_WIN32 */
- /* Return with success. */
- return(kODRCSuccess);
- }
- #endif /* OD_MULTITHREADED */
- /* ----------------------------------------------------------------------------
- * ODProcessExit()
- *
- * Ends the current process.
- *
- * Parameters: nExitCode - Exit code to return to the calling process.
- *
- * Return: Never returns.
- */
- void ODProcessExit(INT nExitCode)
- {
- #ifdef ODPLAT_WIN32
- ExitProcess(nExitCode);
- #else /* !ODPLAT_WIN32 */
- exit(nExitCode);
- #endif /* !ODPLAT_WIN32 */
- }
- /* ========================================================================= */
- /* Millisecond timer functions. */
- /* ========================================================================= */
- #ifdef ODPLAT_DOS
- /* For the DOS platform, we need to know the number of milliseconds per */
- /* clock tick. */
- #define MILLISEC_PER_TICK 55 /* (approx. == 1000 / CLOCKS_PER_SEC) */
- #endif /* ODPLAT_DOS */
- /* ----------------------------------------------------------------------------
- * ODTimerStart()
- *
- * Starts a timer for a specified number of milliseconds. Future calls to
- * ODTimerElapsed() can be used to determine whether or not specified time
- * has elapsed. Note that while this function accepts its parameter in
- * milliseconds, it does not gurantee millisecond resolution. In fact, under
- * DOS, this timer mechanism has just under a 55 millisecond resolution, with
- * an average error of about 27 milliseconds.
- *
- * Parameters: pTimer - Pointer to a tODTimer structure that will be later
- * passed to ODTimerElapsed().
- *
- * Duration - Number of milliseconds after which timer should
- * elapse.
- *
- * Return: void
- */
- void ODTimerStart(tODTimer *pTimer, tODMilliSec Duration)
- {
- #ifdef ODPLAT_NIX
- struct timeval tv;
- #endif
- ASSERT(pTimer != NULL);
- ASSERT(Duration >= 0);
- #ifdef ODPLAT_DOS
- /* Store timer start time right away. */
- pTimer->Start = clock();
- /* Calculate duration of timer. */
- ODDWordDivide((DWORD *)&pTimer->Duration, NULL, Duration,
- MILLISEC_PER_TICK);
- #endif /* ODPLAT_DOS */
- #ifdef ODPLAT_WIN32
- /* Store timer start time now. */
- pTimer->Start = GetTickCount();
- pTimer->Duration = Duration;
- #endif /* ODPLAT_WIN32 */
- #ifdef ODPLAT_NIX
- gettimeofday(&tv,NULL);
- pTimer->Start=tv.tv_sec*1000+tv.tv_usec/1000;
- pTimer->Duration = Duration;
- #endif
- }
- /* ----------------------------------------------------------------------------
- * ODTimerElapsed()
- *
- * Determines whether or not a timer set by ODTimerStart() has elapsed.
- *
- * Parameters: pTimer - Pointer to a tODTimer structure that was populated
- * by ODTimerStart().
- *
- * Return: TRUE if timer has elapsed, FALSE if it has not.
- */
- BOOL ODTimerElapsed(tODTimer *pTimer)
- {
- ASSERT(pTimer != NULL);
- #ifdef ODPLAT_DOS
- return(clock() > pTimer->Start + pTimer->Duration
- || clock() < pTimer->Start);
- #endif /* ODPLAT_DOS */
- #ifdef ODPLAT_WIN32
- return(ODTimerLeft(pTimer)==0);
- #endif /* ODPLAT_WIN32 */
- #ifdef ODPLAT_NIX
- return(ODTimerLeft(pTimer)==0);
- #endif
- }
- /* ----------------------------------------------------------------------------
- * ODTimerWaitForElapse()
- *
- * Sleeps until the specified timer elapses.
- *
- * Parameters: pTimer - Pointer to a tODTimer structure that was populated
- * by ODTimerStart().
- *
- * Return: void
- */
- void ODTimerWaitForElapse(tODTimer *pTimer)
- {
- ASSERT(pTimer != NULL);
- #ifdef ODPLAT_DOS
- /* Under DOS, our timer resolution is low enough (only 18.2 ticks per */
- /* second), that we cannot accurately calculate the time to sleep for. */
- /* For this reason, we simply loop until the timer has elapsed, yielding */
- /* control to other tasks if when the timer has not elapsed. */
- /* While timer has not elapsed. */
- while(!ODTimerElapsed(pTimer))
- {
- /* Let other tasks run. */
- od_sleep(0);
- }
- #else /* !ODPLAT_DOS */
- /* Under other platforms, timer resolution is high enough that we can */
- /* ask the OS to block this thread for the amount of time required */
- /* for the timer to elapse. */
- od_sleep(ODTimerLeft(pTimer));
- #endif /* !ODPLAT_DOS */
- }
- /* ----------------------------------------------------------------------------
- * ODTimerLeft()
- *
- * Determines the number of milliseconds left before the timer elapses.
- *
- * Parameters: pTimer - Pointer to a tODTimer structure that was populated
- * by ODTimerStart().
- *
- * Return: Number of milliseconds before timer elapses, or 0 if the timer
- * has already elapsed.
- */
- tODMilliSec ODTimerLeft(tODTimer *pTimer)
- {
- #ifdef ODPLAT_NIX
- struct timeval tv;
- time_t nowtick;
- #endif
- ASSERT(pTimer != NULL);
- #ifdef ODPLAT_DOS
- {
- clock_t Now = clock();
- clock_t Left;
- /* If timer has elapsed, return 0. */
- if(Now > pTimer->Start + pTimer->Duration
- || Now < pTimer->Start)
- {
- return(0);
- }
- Left = pTimer->Start + pTimer->Duration - Now;
- return(ODDWordMultiply(Left, MILLISEC_PER_TICK));
- }
- #elif defined(ODPLAT_NIX)
- gettimeofday(&tv,NULL);
- nowtick=tv.tv_sec*1000+(tv.tv_usec/1000);
- if(pTimer->Start+pTimer->Duration <= nowtick)
- return(0);
- return((tODMilliSec)(pTimer->Start + pTimer->Duration - nowtick));
- #else /* !ODPLAT_DOS */
- {
- tODMilliSec Now;
- #ifdef ODPLAT_WIN32
- Now = GetTickCount();
- #endif /* ODPLAT_WIN32 */
- /* If timer has elapsed, return 0. */
- if(Now > pTimer->Start + pTimer->Duration
- || Now < pTimer->Start)
- {
- return(0);
- }
- return(pTimer->Start + pTimer->Duration - Now);
- }
- #endif /* !ODPLAT_DOS */
- }
- /* ----------------------------------------------------------------------------
- * od_sleep()
- *
- * Sleeps for the specified number of milliseconds, being as friendly to other
- * running tasks as possible. Under DOS, this function uses the ODTimerStart()/
- * ODTimerElapsed() mechanism, and so its accuracy is limited by the accuracy
- * of that mechanism.
- *
- * Parameters: Milliseconds - Number of milliseconds to sleep. A value of 0
- * allows any other waiting processes to run for
- * the rest of the current timeslice.
- *
- * Return: void
- */
- ODAPIDEF void ODCALL od_sleep(tODMilliSec Milliseconds)
- {
- #ifdef ODPLAT_NIX
- struct timeval tv;
- struct timeval start;
- time_t started;
- time_t left
- #endif
- /* Log function entry if running in trace mode. */
- TRACE(TRACE_API, "od_sleep()");
- /* Ensure that OpenDoors is initialized before proceeding. */
- if(!bODInitialized) od_init();
- OD_API_ENTRY();
- #ifdef ODPLAT_DOS
- if(Milliseconds == 0)
- {
- ODPlatYield();
- }
- else
- {
- tODTimer SleepTimer;
- ODTimerStart(&SleepTimer, Milliseconds);
- while(!ODTimerElapsed(&SleepTimer))
- {
- /* Let other tasks run. */
- ODPlatYield();
- }
- }
- #endif /* ODPLAT_DOS */
- #ifdef ODPLAT_WIN32
- Sleep(Milliseconds);
- #endif /* ODPLAT_WIN32 */
- #ifdef ODPLAT_NIX
- if(Milliseconds==0) {
- /* Prevent 100% CPU *only* no delay is actually required here */
- tv.tv_sec=0;
- tv.tv_usec=1000;
- select(0,NULL,NULL,NULL,&tv);
- }
- else {
- gettimeofday(&start,NULL);
- started=start.tv_sec*1000+(start.tv_usec/1000);
- while(1) {
- /* This is timing sensitive and *MUST* wait for at least Milliseconds regardless of 100% CPU or signals */
- gettimeofday(&tv,NULL);
- left=tv.tv_sec*1000+(tv.tv_usec/1000);
- left-=started;
- left=Milliseconds-left;
- tv.tv_sec = left/1000;
- tv.tv_usec = (left*1000)%1000000;
- if(tv.tv_sec<0 || tv.tv_usec<0)
- break;
- if(!select(0,NULL,NULL,NULL,&tv))
- break;
- }
- }
- #endif
- OD_API_EXIT();
- }
- /* ========================================================================= */
- /* Directory access. */
- /* ========================================================================= */
- /* Structure for directories entries returned by DOS. */
- #ifdef ODPLAT_DOS
- typedef struct
- {
- BYTE abtReserved[21];
- BYTE btAttrib;
- WORD wFileTime;
- WORD wFileDate;
- DWORD dwFileSize;
- char szFileName[13];
- } tDOSDirEntry;
- #endif /* ODPLAT_DOS */
- /* Dir handle structure. */
- typedef struct
- {
- BOOL bEOF;
- #ifdef ODPLAT_DOS
- tDOSDirEntry FindBlock;
- #endif /* ODPLAT_DOS */
- #ifdef ODPLAT_WIN32
- HANDLE hWindowsDir;
- WIN32_FIND_DATA WindowsDirEntry;
- int wAttributes;
- #endif /* ODPLAT_WIN32 */
- #ifdef ODPLAT_NIX
- glob_t g;
- int pos;
- int wAttributes;
- #endif
- } tODDirInfo;
- /* Directory access private function prototypes. */
- #if defined(ODPLAT_DOS) || defined(ODPLAT_WIN32)
- static time_t DOSToCTime(WORD wDate, WORD wTime);
- #endif
- #ifdef ODPLAT_DOS
- static INT ODDirDOSFindFirst(CONST char *pszPath, tDOSDirEntry *pBlock,
- WORD wAttributes);
- static INT ODDirDOSFindNext(tDOSDirEntry *pBlock);
- #endif /* ODPLAT_DOS */
- #ifdef ODPLAT_WIN32
- static BOOL ODDirWinMatchesAttributes(tODDirInfo *pDirInfo);
- #endif /* ODPLAT_WIN32 */
- /* ----------------------------------------------------------------------------
- * ODDirOpen()
- *
- * Opens a directory for future access using ODDirRead(). On Success,
- * ODDirOpen() provides a directory handle that represents a list of directory
- * entries that match the specified path and attributes. When finished with
- * the directory handle, the caller should release it using ODDirClose().
- *
- * Parameters: pszPath - Directory with filename (wildcards are supported),
- * for which matching files should be found. If there
- * are no matching files, ODDirOpen() returns with
- * kODRCNoMatch.
- *
- * nAttributes - One or more of the DIR_ATTRIB_... constants,
- * connected by the bitmap-OR (|) operator.
- *
- * phDir - Pointer to a tODDirHandle, into which ODDirOpen()
- * will place a valid directory handle if and only
- * if it returns kODRCSuccess.
- *
- * Return: A tODResult indicating success or reason for failure.
- */
- tODResult ODDirOpen(CONST char *pszPath, WORD wAttributes, tODDirHandle *phDir)
- {
- tODDirInfo *pDirInfo;
- ASSERT(pszPath != NULL);
- ASSERT(phDir != NULL);
- /* Attempt to allocate a directory information structure. */
- if((pDirInfo = malloc(sizeof(tODDirInfo))) == NULL)
- {
- /* If unable to allocate enough memory, return this state to the */
- /* caller. */
- return(kODRCNoMemory);
- }
- /* Initialize directory information structure. */
- pDirInfo->bEOF = FALSE;
- #ifdef ODPLAT_DOS
- /* Read the first matching directory entry structure. */
- if(ODDirDOSFindFirst(pszPath, &pDirInfo->FindBlock, wAttributes))
- {
- /* If unable to read directory entry, release directory information */
- /* structure, and return indicating that there are no matching files. */
- free(pDirInfo);
- return(kODRCNoMatch);
- }
- #endif /* ODPLAT_DOS */
- #ifdef ODPLAT_WIN32
- /* Store a copy of the attributes passed to open function. */
- pDirInfo->wAttributes = wAttributes;
- /* Attempt to read first directory entry. */
- pDirInfo->hWindowsDir = FindFirstFile(pszPath, &pDirInfo->WindowsDirEntry);
- if(pDirInfo->hWindowsDir == INVALID_HANDLE_VALUE)
- {
- /* If unable to read directory entry, release directory information */
- /* structure, and return indicating that there are no matching files. */
- free(pDirInfo);
- return(kODRCNoMatch);
- }
- /* If first file doesn't match specified attributes, then find one that */
- /* does. */
- /* Find next matching entry, if any. */
- while(!ODDirWinMatchesAttributes(pDirInfo))
- {
- if(!FindNextFile(pDirInfo->hWindowsDir, &pDirInfo->WindowsDirEntry))
- {
- /* If unable to find matching directory entry, then release */
- /* structure, return indicating that there are no matching files. */
- free(pDirInfo);
- return(kODRCNoMatch);
- }
- }
- #endif /* ODPLAT_WIN32 */
- #ifdef ODPLAT_NIX
- if(glob(pszPath,GLOB_NOSORT,NULL,&(pDirInfo->g)))
- return(kODRCNoMatch);
- if(pDirInfo->g.gl_pathc==0) {
- globfree(&(pDirInfo->g));
- return(kODRCNoMatch);
- }
- pDirInfo->pos=0;
- pDirInfo->wAttributes = wAttributes;
- #endif
- /* Now that open operation is complete, give the caller a directory */
- /* handle. */
- *phDir = ODPTR2HANDLE(pDirInfo, tODDirInfo);
- /* Return with success. */
- return(kODRCSuccess);
- }
- /* ----------------------------------------------------------------------------
- * ODDirRead()
- *
- * Reads the next directory entry from an open directory, placing the directory
- * information into the tODDirEntry structure pointed to by pDirEntry.
- *
- * Parameters: hDir - Handle to an open directory, as provided by
- * ODDirOpen().
- *
- * pDirEntry - Pointer to structure into which directory entry
- * information should be placed.
- *
- * Return: A tODResult indicating success or reason for failure. After the
- * last directory entry has been read, all subsequent calls to
- * ODDirRead() will return kODRCEndOfFile.
- */
- tODResult ODDirRead(tODDirHandle hDir, tODDirEntry *pDirEntry)
- {
- tODDirInfo *pDirInfo = ODHANDLE2PTR(hDir, tODDirInfo);
- #ifdef ODPLAT_WIN32
- WORD wDOSDate;
- WORD wDOSTime;
- #endif /* ODPLAT_WIN32 */
- #ifdef ODPLAT_NIX
- struct stat st;
- #endif
-
- ASSERT(pDirEntry != NULL);
- ASSERT(pDirInfo != NULL);
- /* Check whether the last directory entry has been returned yet. */
- if(pDirInfo->bEOF)
- {
- /* Return this state information to the caller. */
- return(kODRCEndOfFile);
- }
- #ifdef ODPLAT_DOS
- /* Provide the caller with the information from the previously read */
- /* directory entry. */
- /* Copy the filename to the caller's structure. */
- ODStringCopy(pDirEntry->szFileName, pDirInfo->FindBlock.szFileName,
- DIR_FILENAME_SIZE);
- /* Copy the attributes to the caller's structure. */
- pDirEntry->wAttributes = pDirInfo->FindBlock.btAttrib;
- /* Copy the file size to the caller's structure. */
- pDirEntry->dwFileSize = pDirInfo->FindBlock.dwFileSize;
- /* Determine the last file write time, in C library time format. */
- pDirEntry->LastWriteTime = DOSToCTime(pDirInfo->FindBlock.wFileDate,
- pDirInfo->FindBlock.wFileTime);
- /* Read next directory entry, if any. */
- pDirInfo->bEOF = ODDirDOSFindNext(&pDirInfo->FindBlock);
- #endif /* ODPLAT_DOS */
- #ifdef ODPLAT_WIN32
- /* Provide the caller with the information from the previously read */
- /* directory entry. */
- /* Copy filename from Win32 8.3 filename. */
- if(strlen(pDirInfo->WindowsDirEntry.cAlternateFileName) == 0)
- {
- ODStringCopy(pDirEntry->szFileName,
- pDirInfo->WindowsDirEntry.cFileName, DIR_FILENAME_SIZE);
- }
- else
- {
- ODStringCopy(pDirEntry->szFileName,
- pDirInfo->WindowsDirEntry.cAlternateFileName, DIR_FILENAME_SIZE);
- }
- /* Copy attribute bits. */
- pDirEntry->wAttributes = DIR_ATTRIB_NORMAL;
- if(pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
- {
- pDirEntry->wAttributes |= DIR_ATTRIB_ARCH;
- }
- if(pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- pDirEntry->wAttributes |= DIR_ATTRIB_DIREC;
- }
- if(pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
- {
- pDirEntry->wAttributes |= DIR_ATTRIB_HIDDEN;
- }
- if(pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
- {
- pDirEntry->wAttributes |= DIR_ATTRIB_RDONLY;
- }
- if(pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
- {
- pDirEntry->wAttributes |= DIR_ATTRIB_SYSTEM;
- }
- /* Copy the file size to the caller's structure. */
- pDirEntry->dwFileSize = (long)pDirInfo->WindowsDirEntry.nFileSizeLow;
- /* Determine the last file write time, in C library time format. */
- FileTimeToDosDateTime(&pDirInfo->WindowsDirEntry.ftLastWriteTime, &wDOSDate,
- &wDOSTime);
- pDirEntry->LastWriteTime = DOSToCTime(wDOSDate, wDOSTime);
- /* Find next matching entry, if any. */
- do
- {
- if(!FindNextFile(pDirInfo->hWindowsDir, &pDirInfo->WindowsDirEntry))
- {
- pDirInfo->bEOF = TRUE;
- }
- } while(!ODDirWinMatchesAttributes(pDirInfo));
- #endif /* ODPLAT_WIN32 */
- #ifdef ODPLAT_NIX
- while(!pDirInfo->bEOF) {
- if(strrchr(pDirInfo->g.gl_pathv[pDirInfo->pos],DIRSEP)==NULL)
- strcpy(pDirEntry->szFileName,pDirInfo->g.gl_pathv[pDirInfo->pos]);
- else
- strcpy(pDirEntry->szFileName,strrchr(pDirInfo->g.gl_pathv[pDirInfo->pos],DIRSEP));
- stat(pDirInfo->g.gl_pathv[pDirInfo->pos],&st);
- pDirEntry->wAttributes=DIR_ATTRIB_NORMAL;
- if(st.st_mode & S_IFDIR)
- pDirEntry->wAttributes |= DIR_ATTRIB_DIREC;
- if(!st.st_mode & S_IWUSR)
- pDirEntry->wAttributes |= DIR_ATTRIB_RDONLY;
- if(!st.st_mode & S_IRUSR)
- pDirEntry->wAttributes |= DIR_ATTRIB_SYSTEM;
- pDirEntry->LastWriteTime=st.st_mtime;
- pDirEntry->dwFileSize=st.st_size;
- pDirInfo->pos++;
- if(pDirInfo->pos==pDirInfo->g.gl_pathc)
- pDirInfo->bEOF=TRUE;
- if(pDirEntry->wAttributes==pDirInfo->wAttributes)
- return(kODRCSuccess);
- if(pDirInfo->bEOF==TRUE)
- return(kODRCEndOfFile);
- }
- #endif
- /* Return with success. */
- return(kODRCSuccess);
- }
- /* ----------------------------------------------------------------------------
- * ODDirClose()
- *
- * Closes and open directory handle.
- *
- * Parameters: hDir - Handle to an open directory handle, as provided by the
- * ODDirOpen() function.
- *
- * Return: void
- */
- void ODDirClose(tODDirHandle hDir)
- {
- tODDirInfo *pDirInfo = ODHANDLE2PTR(hDir, tODDirInfo);
- ASSERT(pDirInfo != NULL);
- #ifdef ODPLAT_WIN32
- /* Under Win32, close directory handle. */
- FindClose(pDirInfo->hWindowsDir);
- #endif /* ODPLAT_WIN32 */
- #ifdef ODPLAT_NIX
- globfree(&(pDirInfo->g));
- #endif
- /* Free the directory information structure. */
- free(pDirInfo);
- }
- #if defined(ODPLAT_DOS) || defined(ODPLAT_WIN32)
- /* ----------------------------------------------------------------------------
- * DOSToCTime() *** PRIVATE FUNCTION ***
- *
- * Converts DOS directory entry time format to the C library time format.
- *
- * Parameters: uDate - Date portion of the time to be converted.
- *
- * uTime - Time of day portion of the time to be converted.
- *
- * Return: The specified time, represented as a time_t.
- */
- static time_t DOSToCTime(WORD wDate, WORD wTime)
- {
- struct tm TimeStruct;
- TimeStruct.tm_sec = (wTime & 0x001f) * 2;
- TimeStruct.tm_min = (wTime & 0x07e0) >> 5;
- TimeStruct.tm_hour = (wTime & 0xf800) >> 11;
- TimeStruct.tm_mday = wDate & 0x001f;
- TimeStruct.tm_mon = ((wDate & 0x01e0) >> 5) - 1;
- TimeStruct.tm_year = 80 + ((wDate & 0xfe00) >> 9);
- return(mktime(&TimeStruct));
- }
- #endif
- /* MS-DOS specific functions for directory access. */
- #ifdef ODPLAT_DOS
- /* ----------------------------------------------------------------------------
- * ODDirDOSFindFirst() *** PRIVATE FUNCTION ***
- *
- * MS-DOS specific "Find First" function for reading directory entries. This
- * is essentially just a C-language interface to the interrupt function call
- * that is provided by DOS.
- *
- * Parameters: pszPath - Pointer to string containing directory and
- * filespec to search for.
- *
- * pBlock - Pointer to directory block.
- *
- * nAttributes - Attributes to match, if any.
- *
- * Return: 0 on success, -1 on failure.
- */
- static int ODDirDOSFindFirst(CONST char *pszPath, tDOSDirEntry *pBlock,
- WORD wAttributes)
- {
- int nToReturn;
- ASSERT(pszPath != NULL);
- ASSERT(pBlock != NULL);
- ASM push ds
- ASM mov ah, 0x2f /* Int 0x21, ah=0x2f: Get current DOS DTA */
- ASM int 0x21 /* Get current DTA */
- ASM push bx /* Store offset of current DTA on stack */
- ASM push es /* Store segment of current DTA on stack */
- ASM mov ah, 0x1a /* Int 0x21, ah=0x1a: Set new DOS DTA */
- #ifdef LARGEDATA /* If using far pointers */
- ASM lds dx, pBlock /* Load DS:DX with far address of pBlock */
- #else /* If using near pointers */
- ASM mov dx, pBlock /* Load DX with near address of pBlock */
- #endif
- ASM int 0x21 /* Set DOS DTA */
- ASM mov ah, 0x4e /* Int 0x21, ah=0x4e: DOS findfirst function */
- ASM mov cx, wAttributes /* Load attributes into CX */
- #ifdef LARGEDATA /* If using far pointers */
- ASM lds dx, pszPath /* Load DS:DX with far address in pszPath */
- #else /* If using near pointers */
- ASM mov dx, pszPath /* Load DX with near address in pszPath */
- #endif
- ASM int 0x21 /* Call findfirst function */
- ASM jc error /* If carry flag is set, then an error has ocurred */
- ASM mov word ptr nToReturn, 0 /* If no error, return 0 */
- ASM jmp after_result
- error:
- ASM mov word ptr nToReturn, -1 /* If error, return -1 */
- after_result:
- ASM mov ah, 0x1a /* Int 0x21, ah=0x1a: Set new DOS DTA */
- ASM pop ds /* Pop original DTA segment off of stack */
- ASM pop dx /* Pop original DTA offest from stack */
- ASM int 0x21 /* Reset DOS DTA to original */
- ASM pop ds /* Restore DS stored at function startup */
- return(nToReturn);
- }
- /* ----------------------------------------------------------------------------
- * ODDirDOSFindNext() *** PRIVATE FUNCTION ***
- *
- * MS-DOS specific "Find Next" function for reading directory entries. This
- * is essentially just a C-language interface to the interrupt function call
- * that is provided by DOS.
- *
- * Parameters: pBlock - Pointer to block in which to store next directory
- * entry.
- *
- * Return: 0 on success, -1 on failure.
- */
- static int ODDirDOSFindNext(tDOSDirEntry *pBlock)
- {
- int nToReturn;
- ASSERT(pBlock != NULL);
- ASM push ds /* Save DS */
- ASM mov ah, 0x2f /* Int 0x21, ah=0x2f: Get current DOS DTA */
- ASM int 0x21 /* Get current DTA */
- ASM push bx /* Store offset of current DTA on stack */
- ASM push es /* Store segment of current DTA on stack */
- ASM mov ah, 0x1a /* Int 0x21, ah=0x1a: Set new DOS DTA */
- #ifdef LARGEDATA /* If using far pointers */
- ASM lds dx, pBlock /* Load DS:DX with far address of pBlock */
- #else /* If using near pointers */
- ASM mov dx, pBlock /* Load DX with near address of pBlock */
- #endif
- ASM int 0x21 /* Set DOS DTA */
- ASM mov ah, 0x4f /* Int 0x21, ah=0x4f: DOS findnext function */
- ASM int 0x21 /* Call findfirst function */
- ASM jc error /* If carry flag is set, then an error has ocurred */
- ASM mov word ptr nToReturn, 0 /* If no error, return 0 */
- ASM jmp after_result
- error:
- ASM mov word ptr nToReturn, -1 /* If error, return -1 */
- after_result:
- ASM mov ah, 0x1a /* Int 0x21, ah=0x1a: Set new DOS DTA */
- ASM pop ds /* Pop original DTA segment off of stack */
- ASM pop dx /* Pop original DTA offest from stack */
- ASM int 0x21 /* Reset DOS DTA to original */
- ASM pop ds /* Restore DS stored at function startup */
- return(nToReturn);
- }
- #endif /* ODPLAT_DOS */
- /* Win32 specific private functions for directory access. */
- #ifdef ODPLAT_WIN32
- /* ----------------------------------------------------------------------------
- * ODDirWinMatchesAttributes() *** PRIVATE FUNCTION ***
- *
- * Determines whether or not the directory entry pDirInfo->WindowsDirEntry
- * meets the attribute requirements specified in pDirInfo->nAttributes
- *
- * Parameters: pDirInfo - Pointer to a directory information structure with
- * attribute and directory entry values.
- *
- * Return: TRUE if the file matches the attributes, FALSE if it does not.
- */
- static BOOL ODDirWinMatchesAttributes(tODDirInfo *pDirInfo)
- {
- if((pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- && !(pDirInfo->wAttributes & DIR_ATTRIB_DIREC))
- {
- return(FALSE);
- }
- if((pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
- && !(pDirInfo->wAttributes & DIR_ATTRIB_ARCH))
- {
- return(FALSE);
- }
- if((pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
- && !(pDirInfo->wAttributes & DIR_ATTRIB_HIDDEN))
- {
- return(FALSE);
- }
- if((pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
- && !(pDirInfo->wAttributes & DIR_ATTRIB_RDONLY))
- {
- return(FALSE);
- }
- if((pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
- && !(pDirInfo->wAttributes & DIR_ATTRIB_SYSTEM))
- {
- return(FALSE);
- }
- return(TRUE);
- }
- #endif /* ODPLAT_WIN32 */
- /* ----------------------------------------------------------------------------
- * ODDirChangeCurrent()
- *
- * Changes current directory to the one specified.
- *
- * Parameters: pszPath - String containing path to change to.
- *
- * Return: void
- */
- void ODDirChangeCurrent(char *pszPath)
- {
- #ifdef ODPLAT_DOS
- int nDrive = 0;
- if(pszPath[1] == ':')
- {
- nDrive = (toupper(pszPath[0]) - 'A');
- }
- _setdrvcd(nDrive, (char *)pszPath);
- #endif /* ODPLAT_DOS */
- #ifdef ODPLAT_WIN32
- SetCurrentDirectory(pszPath);
- #endif /* ODPLAT_WIN32 */
- #ifdef ODPLAT_NIX
- chdir(pszPath);
- #endif
- }
- /* ----------------------------------------------------------------------------
- * ODDirGetCurrent()
- *
- * Obtains the name of the current directory, including the current drive
- * designator.
- *
- * Parameters: pszPath - String containing path to change to.
- *
- * nMaxPathChars - Maximum characters in the buffer pointer to by
- * pszPath.
- *
- * Return: void
- */
- void ODDirGetCurrent(char *pszPath, INT nMaxPathChars)
- {
- ASSERT(pszPath != NULL);
- ASSERT(nMaxPathChars > 0);
- #ifdef ODPLAT_DOS
- UNUSED(nMaxPathChars);
- strcpy(pszPath, "X:\\");
- pszPath[0] = 'A' + _getdrv();
- _getcd(0, (char *)pszPath + 3);
- #endif /* ODPLAT_DOS */
- #ifdef ODPLAT_WIN32
- GetCurrentDirectory(nMaxPathChars, pszPath);
- #endif /* ODPLAT_WIN32 */
- #ifdef ODPLAT_NIX
- getcwd(pszPath,nMaxPathChars);
- #endif
- ASSERT((INT)strlen(pszPath) + 1 <= nMaxPathChars);
- }
- /* ========================================================================= */
- /* Misc. Functions */
- /* ========================================================================= */
- /* ----------------------------------------------------------------------------
- * ODFileDelete()
- *
- * Deletes the file with the specified filename.
- *
- * Parameters: pszPath - Filename, possibly with path, to delete.
- *
- * Return: kODRCSuccess on success, or an error code on failure.
- */
- tODResult ODFileDelete(CONST char *pszPath)
- {
- #ifdef ODPLAT_DOS
- {
- tODResult Result;
- ASM push ds
- #ifdef LARGEDATA
- ASM lds dx, pszPath
- #else /* !LARGEDATA */
- ASM mov ax, ss
- ASM mov ds, ax
- ASM mov dx, pszPath
- #endif /* !LARGEDATA */
- ASM mov ah, 0x41
- ASM int 0x21
- ASM jc Failure
- ASM mov word ptr Result, kODRCSuccess
- ASM jmp Done
- Failure:
- ASM mov word ptr Result, kODRCGeneralFailure
- Done:
- ASM pop ds
- return(Result);
- }
- #endif /* ODPLAT_DOS */
- #ifdef ODPLAT_WIN32
- return(DeleteFile(pszPath) ? kODRCSuccess : kODRCGeneralFailure);
- #endif /* ODPLAT_WIN32 */
- #ifdef ODPLAT_NIX
- return(unlink(pszPath));
- #endif
- }
- /* ----------------------------------------------------------------------------
- * ODFileAccessMode()
- *
- * Determines the access permissions of a file.
- *
- * Parameters: pszFilename - Name of file to test.
- *
- * nAccessMode - Indicates which file access mode to test for.
- * A value of 0 indicates existance, 2 indicates
- * write permission, 4 indicates read permission,
- * and 6 indicates read/write permission.
- *
- * Return: FALSE if file can be accessed or TRUE if file cannot be
- * accessed.
- */
- BOOL ODFileAccessMode(char *pszFilename, int nAccessMode)
- {
- FILE *pfFileToTest;
- char *pszModeString;
- tODDirHandle hDir;
- #ifdef ODPLAT_DOS
- BYTE nLength;
- /* If we are looking for the root directory. */
- nLength = strlen(pszFilename);
- if((nLength == 3 && pszFilename[1] == ':' && pszFilename[2] == DIRSEP) ||
- (nLength == 1 && pszFilename[0] == DIRSEP))
- {
- if(nAccessMode == 0)
- {
- int to_return = FALSE;
- #ifdef LARGEDATA
- ASM push ds
- ASM lds dx, pszFilename
- #else
- ASM mov dx, pszFilename
- #endif
- ASM mov ax, 0x4300
- ASM int 0x21
- ASM jnc done
- ASM mov word ptr to_return, TRUE
- done:
- #ifdef LARGEDATA
- ASM pop ds
- #endif
- return(to_return);
- }
- else
- {
- return(TRUE);
- }
- }
- #endif /* ODPLAT_DOS */
- /* If the file doesn't exit, we fail in any mode. */
- if(ODDirOpen(pszFilename,
- DIR_ATTRIB_ARCH | DIR_ATTRIB_RDONLY | DIR_ATTRIB_DIREC,
- &hDir) != kODRCSuccess)
- {
- return(TRUE);
- }
- /* If directory open succeeded, then close it again. */
- ODDirClose(hDir);
- /* If the file does exist, then amode 0 is satisfied. */
- if(nAccessMode == 0) return(FALSE);
- /* If testing for an access permission, determine corresponding fopen() */
- /* mode. */
- switch(nAccessMode)
- {
- case 2:
- pszModeString = "a";
- break;
- case 4:
- pszModeString = "r";
- break;
- default:
- pszModeString = "r+";
- }
- /* Attempt to open the file, if unable to do so return failure. */
- if((pfFileToTest=fopen(pszFilename,pszModeString)) == NULL) return(TRUE);
- /* If file open was successful, close it again, and return success. */
- fclose(pfFileToTest);
- return(FALSE);
- }
|