xref: /onnv-gate/usr/src/lib/libkmsagent/common/SYSCommon.c (revision 12720:3db6e0082404)
1*12720SWyllys.Ingersoll@Sun.COM /*
2*12720SWyllys.Ingersoll@Sun.COM  * CDDL HEADER START
3*12720SWyllys.Ingersoll@Sun.COM  *
4*12720SWyllys.Ingersoll@Sun.COM  * The contents of this file are subject to the terms of the
5*12720SWyllys.Ingersoll@Sun.COM  * Common Development and Distribution License (the "License").
6*12720SWyllys.Ingersoll@Sun.COM  * You may not use this file except in compliance with the License.
7*12720SWyllys.Ingersoll@Sun.COM  *
8*12720SWyllys.Ingersoll@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12720SWyllys.Ingersoll@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*12720SWyllys.Ingersoll@Sun.COM  * See the License for the specific language governing permissions
11*12720SWyllys.Ingersoll@Sun.COM  * and limitations under the License.
12*12720SWyllys.Ingersoll@Sun.COM  *
13*12720SWyllys.Ingersoll@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*12720SWyllys.Ingersoll@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*12720SWyllys.Ingersoll@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*12720SWyllys.Ingersoll@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*12720SWyllys.Ingersoll@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*12720SWyllys.Ingersoll@Sun.COM  *
19*12720SWyllys.Ingersoll@Sun.COM  * CDDL HEADER END
20*12720SWyllys.Ingersoll@Sun.COM  */
21*12720SWyllys.Ingersoll@Sun.COM 
22*12720SWyllys.Ingersoll@Sun.COM /*
23*12720SWyllys.Ingersoll@Sun.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*12720SWyllys.Ingersoll@Sun.COM  */
25*12720SWyllys.Ingersoll@Sun.COM 
26*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
27*12720SWyllys.Ingersoll@Sun.COM  * Module:            SYSCommon.c
28*12720SWyllys.Ingersoll@Sun.COM  *-------------------------------------------------------------------------*/
29*12720SWyllys.Ingersoll@Sun.COM 
30*12720SWyllys.Ingersoll@Sun.COM #include <stdio.h>
31*12720SWyllys.Ingersoll@Sun.COM #include "SYSCommon.h"
32*12720SWyllys.Ingersoll@Sun.COM #include <time.h>
33*12720SWyllys.Ingersoll@Sun.COM #include <errno.h>
34*12720SWyllys.Ingersoll@Sun.COM #include <sys/stat.h>
35*12720SWyllys.Ingersoll@Sun.COM #include <sys/types.h>
36*12720SWyllys.Ingersoll@Sun.COM #include <signal.h>
37*12720SWyllys.Ingersoll@Sun.COM 
38*12720SWyllys.Ingersoll@Sun.COM #ifndef WIN32
39*12720SWyllys.Ingersoll@Sun.COM #include <unistd.h>
40*12720SWyllys.Ingersoll@Sun.COM #endif
41*12720SWyllys.Ingersoll@Sun.COM 
42*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
43*12720SWyllys.Ingersoll@Sun.COM #include <io.h>
44*12720SWyllys.Ingersoll@Sun.COM #include <stdlib.h>   /* for malloc, calloc, and free */
45*12720SWyllys.Ingersoll@Sun.COM #elif defined K_LINUX_PLATFORM
46*12720SWyllys.Ingersoll@Sun.COM #include <unistd.h>   /* it includes usleep(us) */
47*12720SWyllys.Ingersoll@Sun.COM #include <sys/time.h>
48*12720SWyllys.Ingersoll@Sun.COM #include <fts.h>
49*12720SWyllys.Ingersoll@Sun.COM #else
50*12720SWyllys.Ingersoll@Sun.COM /*
51*12720SWyllys.Ingersoll@Sun.COM  * Directory traversal code is not yet available for Solaris.
52*12720SWyllys.Ingersoll@Sun.COM  * If such code will need to be written, then it will probably use ftw.h.
53*12720SWyllys.Ingersoll@Sun.COM  */
54*12720SWyllys.Ingersoll@Sun.COM #endif
55*12720SWyllys.Ingersoll@Sun.COM 
56*12720SWyllys.Ingersoll@Sun.COM #ifdef K_SOLARIS_PLATFORM
57*12720SWyllys.Ingersoll@Sun.COM /* For K_AdjustLocalClock */
58*12720SWyllys.Ingersoll@Sun.COM #include <unistd.h>
59*12720SWyllys.Ingersoll@Sun.COM /* For K_SetRootPassword */
60*12720SWyllys.Ingersoll@Sun.COM #define    __EXTENSIONS__    /* to expose flockfile and friends in stdio.h */
61*12720SWyllys.Ingersoll@Sun.COM #include <errno.h>
62*12720SWyllys.Ingersoll@Sun.COM #include <libgen.h>
63*12720SWyllys.Ingersoll@Sun.COM #include <malloc.h>
64*12720SWyllys.Ingersoll@Sun.COM #include <signal.h>
65*12720SWyllys.Ingersoll@Sun.COM #include <stdio.h>
66*12720SWyllys.Ingersoll@Sun.COM #include <stdlib.h>
67*12720SWyllys.Ingersoll@Sun.COM #include <strings.h>
68*12720SWyllys.Ingersoll@Sun.COM #include <stropts.h>
69*12720SWyllys.Ingersoll@Sun.COM #include <unistd.h>
70*12720SWyllys.Ingersoll@Sun.COM #include <termio.h>
71*12720SWyllys.Ingersoll@Sun.COM #include <security/pam_appl.h>
72*12720SWyllys.Ingersoll@Sun.COM #include <widec.h>
73*12720SWyllys.Ingersoll@Sun.COM #endif
74*12720SWyllys.Ingersoll@Sun.COM 
75*12720SWyllys.Ingersoll@Sun.COM #ifdef K_LINUX_PLATFORM
76*12720SWyllys.Ingersoll@Sun.COM extern int pthread_mutexattr_settype __P ((pthread_mutexattr_t *__attr,
77*12720SWyllys.Ingersoll@Sun.COM                        int __kind));
78*12720SWyllys.Ingersoll@Sun.COM #endif
79*12720SWyllys.Ingersoll@Sun.COM 
80*12720SWyllys.Ingersoll@Sun.COM #ifdef K_HPUX_PLATFORM
atoll(const char * str)81*12720SWyllys.Ingersoll@Sun.COM int64 atoll(const char *str)
82*12720SWyllys.Ingersoll@Sun.COM {
83*12720SWyllys.Ingersoll@Sun.COM     int64 tmp = 0;
84*12720SWyllys.Ingersoll@Sun.COM     sscanf(str, "%lld", &tmp);
85*12720SWyllys.Ingersoll@Sun.COM     return tmp;
86*12720SWyllys.Ingersoll@Sun.COM }
87*12720SWyllys.Ingersoll@Sun.COM 
88*12720SWyllys.Ingersoll@Sun.COM #endif
89*12720SWyllys.Ingersoll@Sun.COM 
90*12720SWyllys.Ingersoll@Sun.COM 
91*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
92*12720SWyllys.Ingersoll@Sun.COM  * Function: K_CreateThread
93*12720SWyllys.Ingersoll@Sun.COM  *
94*12720SWyllys.Ingersoll@Sun.COM  * Description:
95*12720SWyllys.Ingersoll@Sun.COM  *  Thread creation function "CreateThread" takes a thread function
96*12720SWyllys.Ingersoll@Sun.COM  *  and its parameter to create a thread. It also has a Boolean
97*12720SWyllys.Ingersoll@Sun.COM  *  parameter to indicate if the thread is detached or joinable.
98*12720SWyllys.Ingersoll@Sun.COM  *  A new thread's handle is returned through the output parameter.
99*12720SWyllys.Ingersoll@Sun.COM  *
100*12720SWyllys.Ingersoll@Sun.COM  * Input
101*12720SWyllys.Ingersoll@Sun.COM  * -----
102*12720SWyllys.Ingersoll@Sun.COM  *    i_pFunc         Function pointer of the thread function
103*12720SWyllys.Ingersoll@Sun.COM  *    i_pvData        The point of the parameter passed to the thread function
104*12720SWyllys.Ingersoll@Sun.COM  *    i_bIsDetached   The thread is detached or not
105*12720SWyllys.Ingersoll@Sun.COM  *                    (Note: It is not supported on Win32)
106*12720SWyllys.Ingersoll@Sun.COM  *
107*12720SWyllys.Ingersoll@Sun.COM  * Output
108*12720SWyllys.Ingersoll@Sun.COM  * ------
109*12720SWyllys.Ingersoll@Sun.COM  *    o_pNewThread    The Thread handle
110*12720SWyllys.Ingersoll@Sun.COM  *
111*12720SWyllys.Ingersoll@Sun.COM  * Return value       Error code
112*12720SWyllys.Ingersoll@Sun.COM  *
113*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
114*12720SWyllys.Ingersoll@Sun.COM 
K_CreateThread(K_ThreadFunc i_pFunc,void * i_pvData,int i_bIsDetached,K_THREAD_HANDLE * o_pNewThread)115*12720SWyllys.Ingersoll@Sun.COM int K_CreateThread(K_ThreadFunc i_pFunc,
116*12720SWyllys.Ingersoll@Sun.COM                   void *i_pvData,
117*12720SWyllys.Ingersoll@Sun.COM                   int i_bIsDetached,
118*12720SWyllys.Ingersoll@Sun.COM                   K_THREAD_HANDLE *o_pNewThread)
119*12720SWyllys.Ingersoll@Sun.COM {
120*12720SWyllys.Ingersoll@Sun.COM     int iOK = K_SYS_OK;
121*12720SWyllys.Ingersoll@Sun.COM     int iReturn = 0;
122*12720SWyllys.Ingersoll@Sun.COM 
123*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
124*12720SWyllys.Ingersoll@Sun.COM 
125*12720SWyllys.Ingersoll@Sun.COM     {
126*12720SWyllys.Ingersoll@Sun.COM        unsigned id;
127*12720SWyllys.Ingersoll@Sun.COM 
128*12720SWyllys.Ingersoll@Sun.COM         *o_pNewThread = (HANDLE)_beginthreadex(NULL,
129*12720SWyllys.Ingersoll@Sun.COM                                         0,
130*12720SWyllys.Ingersoll@Sun.COM                                         (int (_stdcall *) (void *vpData))i_pFunc,
131*12720SWyllys.Ingersoll@Sun.COM                                         i_pvData,
132*12720SWyllys.Ingersoll@Sun.COM                                         0,
133*12720SWyllys.Ingersoll@Sun.COM                                         &id);
134*12720SWyllys.Ingersoll@Sun.COM 
135*12720SWyllys.Ingersoll@Sun.COM 
136*12720SWyllys.Ingersoll@Sun.COM         if(*o_pNewThread == 0)
137*12720SWyllys.Ingersoll@Sun.COM         {
138*12720SWyllys.Ingersoll@Sun.COM #ifdef SYS_DEBUG
139*12720SWyllys.Ingersoll@Sun.COM             printf(" (%s, %d): error creating pthread, error = %d\n",
140*12720SWyllys.Ingersoll@Sun.COM                 __FILE__, __LINE__, iReturn);
141*12720SWyllys.Ingersoll@Sun.COM #endif
142*12720SWyllys.Ingersoll@Sun.COM             return K_SYS_ERR_CREATE_THREAD;
143*12720SWyllys.Ingersoll@Sun.COM         }
144*12720SWyllys.Ingersoll@Sun.COM 
145*12720SWyllys.Ingersoll@Sun.COM         return K_SYS_OK;
146*12720SWyllys.Ingersoll@Sun.COM     }
147*12720SWyllys.Ingersoll@Sun.COM 
148*12720SWyllys.Ingersoll@Sun.COM #else
149*12720SWyllys.Ingersoll@Sun.COM     pthread_attr_t attr;
150*12720SWyllys.Ingersoll@Sun.COM 
151*12720SWyllys.Ingersoll@Sun.COM     iReturn = pthread_attr_init(&attr);
152*12720SWyllys.Ingersoll@Sun.COM 
153*12720SWyllys.Ingersoll@Sun.COM     if ( iReturn == 0 )
154*12720SWyllys.Ingersoll@Sun.COM     {
155*12720SWyllys.Ingersoll@Sun.COM         iReturn = pthread_attr_setdetachstate(&attr, (i_bIsDetached) ?
156*12720SWyllys.Ingersoll@Sun.COM                     PTHREAD_CREATE_DETACHED :
157*12720SWyllys.Ingersoll@Sun.COM                     PTHREAD_CREATE_JOINABLE);
158*12720SWyllys.Ingersoll@Sun.COM     }
159*12720SWyllys.Ingersoll@Sun.COM 
160*12720SWyllys.Ingersoll@Sun.COM #ifdef UNIX
161*12720SWyllys.Ingersoll@Sun.COM     if ( iReturn == 0 )
162*12720SWyllys.Ingersoll@Sun.COM     {
163*12720SWyllys.Ingersoll@Sun.COM         iReturn = pthread_attr_setstacksize(&attr, 1024*1024);
164*12720SWyllys.Ingersoll@Sun.COM     }
165*12720SWyllys.Ingersoll@Sun.COM #endif
166*12720SWyllys.Ingersoll@Sun.COM 
167*12720SWyllys.Ingersoll@Sun.COM     if ( iReturn == 0 )
168*12720SWyllys.Ingersoll@Sun.COM     {
169*12720SWyllys.Ingersoll@Sun.COM         iReturn = pthread_create(o_pNewThread, &attr, (void *(*)(void *)) i_pFunc, i_pvData);
170*12720SWyllys.Ingersoll@Sun.COM     }
171*12720SWyllys.Ingersoll@Sun.COM 
172*12720SWyllys.Ingersoll@Sun.COM     if ( iReturn == 0 )
173*12720SWyllys.Ingersoll@Sun.COM     {
174*12720SWyllys.Ingersoll@Sun.COM         iReturn = pthread_attr_destroy(&attr);
175*12720SWyllys.Ingersoll@Sun.COM     }
176*12720SWyllys.Ingersoll@Sun.COM 
177*12720SWyllys.Ingersoll@Sun.COM     // TODO: Log error?
178*12720SWyllys.Ingersoll@Sun.COM     if ( iReturn )
179*12720SWyllys.Ingersoll@Sun.COM     {
180*12720SWyllys.Ingersoll@Sun.COM #ifdef SYS_DEBUG
181*12720SWyllys.Ingersoll@Sun.COM         printf(" (%s, %d): error creating pthread, error = %d\n",
182*12720SWyllys.Ingersoll@Sun.COM                 __FILE__, __LINE__, iReturn);
183*12720SWyllys.Ingersoll@Sun.COM #endif
184*12720SWyllys.Ingersoll@Sun.COM 
185*12720SWyllys.Ingersoll@Sun.COM         iOK = K_SYS_ERR_CREATE_THREAD;
186*12720SWyllys.Ingersoll@Sun.COM     }
187*12720SWyllys.Ingersoll@Sun.COM 
188*12720SWyllys.Ingersoll@Sun.COM     return iOK;
189*12720SWyllys.Ingersoll@Sun.COM #endif
190*12720SWyllys.Ingersoll@Sun.COM }
191*12720SWyllys.Ingersoll@Sun.COM 
192*12720SWyllys.Ingersoll@Sun.COM 
193*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
194*12720SWyllys.Ingersoll@Sun.COM  * Function: K_JoinThread
195*12720SWyllys.Ingersoll@Sun.COM  *
196*12720SWyllys.Ingersoll@Sun.COM  * Description:
197*12720SWyllys.Ingersoll@Sun.COM  *  Thread joining function is called when the current thread
198*12720SWyllys.Ingersoll@Sun.COM  *  waits another thread to terminate.
199*12720SWyllys.Ingersoll@Sun.COM  *
200*12720SWyllys.Ingersoll@Sun.COM  * Input
201*12720SWyllys.Ingersoll@Sun.COM  * -----
202*12720SWyllys.Ingersoll@Sun.COM  *    i_hThread        The thread handle of the to-be-joined thread
203*12720SWyllys.Ingersoll@Sun.COM  *
204*12720SWyllys.Ingersoll@Sun.COM  * Output
205*12720SWyllys.Ingersoll@Sun.COM  * ------
206*12720SWyllys.Ingersoll@Sun.COM  *    (none)
207*12720SWyllys.Ingersoll@Sun.COM  *
208*12720SWyllys.Ingersoll@Sun.COM  * Return value        Error code
209*12720SWyllys.Ingersoll@Sun.COM  *
210*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
211*12720SWyllys.Ingersoll@Sun.COM 
K_JoinThread(K_THREAD_HANDLE i_hThread)212*12720SWyllys.Ingersoll@Sun.COM int  K_JoinThread(K_THREAD_HANDLE i_hThread)
213*12720SWyllys.Ingersoll@Sun.COM {
214*12720SWyllys.Ingersoll@Sun.COM     int iOK = K_SYS_OK;
215*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
216*12720SWyllys.Ingersoll@Sun.COM 
217*12720SWyllys.Ingersoll@Sun.COM     WaitForSingleObject(i_hThread, INFINITE);
218*12720SWyllys.Ingersoll@Sun.COM 
219*12720SWyllys.Ingersoll@Sun.COM #else
220*12720SWyllys.Ingersoll@Sun.COM     {
221*12720SWyllys.Ingersoll@Sun.COM         int iReturn;
222*12720SWyllys.Ingersoll@Sun.COM         iReturn = pthread_join(i_hThread, NULL);
223*12720SWyllys.Ingersoll@Sun.COM 
224*12720SWyllys.Ingersoll@Sun.COM         if ( iReturn )
225*12720SWyllys.Ingersoll@Sun.COM         {
226*12720SWyllys.Ingersoll@Sun.COM 
227*12720SWyllys.Ingersoll@Sun.COM #ifdef SYS_DEBUG
228*12720SWyllys.Ingersoll@Sun.COM             printf(" (%s, %d): error creating pthread, error = %d\n",
229*12720SWyllys.Ingersoll@Sun.COM                     __FILE__, __LINE__, iReturn);
230*12720SWyllys.Ingersoll@Sun.COM #endif
231*12720SWyllys.Ingersoll@Sun.COM             iOK = K_SYS_ERR_JOIN_THREAD;
232*12720SWyllys.Ingersoll@Sun.COM         }
233*12720SWyllys.Ingersoll@Sun.COM     }
234*12720SWyllys.Ingersoll@Sun.COM 
235*12720SWyllys.Ingersoll@Sun.COM #endif
236*12720SWyllys.Ingersoll@Sun.COM     return iOK;
237*12720SWyllys.Ingersoll@Sun.COM }
238*12720SWyllys.Ingersoll@Sun.COM 
239*12720SWyllys.Ingersoll@Sun.COM 
240*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
241*12720SWyllys.Ingersoll@Sun.COM  * Function: K_GetCurrentThreadId
242*12720SWyllys.Ingersoll@Sun.COM  *
243*12720SWyllys.Ingersoll@Sun.COM  * Description:
244*12720SWyllys.Ingersoll@Sun.COM  *  Returns the thread ID of the current thread.
245*12720SWyllys.Ingersoll@Sun.COM  *
246*12720SWyllys.Ingersoll@Sun.COM  * Input
247*12720SWyllys.Ingersoll@Sun.COM  * -----
248*12720SWyllys.Ingersoll@Sun.COM  *    (none)
249*12720SWyllys.Ingersoll@Sun.COM  *
250*12720SWyllys.Ingersoll@Sun.COM  * Output
251*12720SWyllys.Ingersoll@Sun.COM  * ------
252*12720SWyllys.Ingersoll@Sun.COM  *    (none)
253*12720SWyllys.Ingersoll@Sun.COM  *
254*12720SWyllys.Ingersoll@Sun.COM  * Return value        The thread ID
255*12720SWyllys.Ingersoll@Sun.COM  *
256*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
257*12720SWyllys.Ingersoll@Sun.COM 
K_GetCurrentThreadId()258*12720SWyllys.Ingersoll@Sun.COM int K_GetCurrentThreadId()
259*12720SWyllys.Ingersoll@Sun.COM {
260*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
261*12720SWyllys.Ingersoll@Sun.COM     return GetCurrentThreadId();
262*12720SWyllys.Ingersoll@Sun.COM #else
263*12720SWyllys.Ingersoll@Sun.COM     return pthread_self();
264*12720SWyllys.Ingersoll@Sun.COM #endif
265*12720SWyllys.Ingersoll@Sun.COM 
266*12720SWyllys.Ingersoll@Sun.COM }
267*12720SWyllys.Ingersoll@Sun.COM 
268*12720SWyllys.Ingersoll@Sun.COM 
269*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
270*12720SWyllys.Ingersoll@Sun.COM  * Function: K_CreateMutex
271*12720SWyllys.Ingersoll@Sun.COM  *
272*12720SWyllys.Ingersoll@Sun.COM  * Description:
273*12720SWyllys.Ingersoll@Sun.COM  *  The mutex creation function creates a mutex according to the given
274*12720SWyllys.Ingersoll@Sun.COM  *  mutex type, and returns the mutex handle to the output parameter.
275*12720SWyllys.Ingersoll@Sun.COM  *
276*12720SWyllys.Ingersoll@Sun.COM  * Input
277*12720SWyllys.Ingersoll@Sun.COM  * -----
278*12720SWyllys.Ingersoll@Sun.COM  *    i_bIsRecursive   Indication whether the mutex can be entered recursively
279*12720SWyllys.Ingersoll@Sun.COM  *
280*12720SWyllys.Ingersoll@Sun.COM  * Output
281*12720SWyllys.Ingersoll@Sun.COM  * ------
282*12720SWyllys.Ingersoll@Sun.COM  *    o_phandle        the handle pointer to the mutex
283*12720SWyllys.Ingersoll@Sun.COM  *
284*12720SWyllys.Ingersoll@Sun.COM  * Return value        Error Code
285*12720SWyllys.Ingersoll@Sun.COM  *
286*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
287*12720SWyllys.Ingersoll@Sun.COM 
K_CreateMutex(K_MUTEX_HANDLE * o_phandle)288*12720SWyllys.Ingersoll@Sun.COM int K_CreateMutex( K_MUTEX_HANDLE *o_phandle )
289*12720SWyllys.Ingersoll@Sun.COM {
290*12720SWyllys.Ingersoll@Sun.COM     int iOK = K_SYS_OK;
291*12720SWyllys.Ingersoll@Sun.COM     BOOL bIsRecursive = 1;  // this used to be an input -- but why do we want this to be optional?
292*12720SWyllys.Ingersoll@Sun.COM 
293*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
294*12720SWyllys.Ingersoll@Sun.COM     {
295*12720SWyllys.Ingersoll@Sun.COM         *o_phandle = (WIN32Mutex *)malloc(sizeof(WIN32Mutex));
296*12720SWyllys.Ingersoll@Sun.COM         if(*o_phandle == NULL)
297*12720SWyllys.Ingersoll@Sun.COM         {
298*12720SWyllys.Ingersoll@Sun.COM             return K_SYS_ERR_NO_MEMORY;
299*12720SWyllys.Ingersoll@Sun.COM         }
300*12720SWyllys.Ingersoll@Sun.COM         (*o_phandle)->m_bIsRecursive = bIsRecursive;
301*12720SWyllys.Ingersoll@Sun.COM         if(bIsRecursive)
302*12720SWyllys.Ingersoll@Sun.COM         {
303*12720SWyllys.Ingersoll@Sun.COM                 InitializeCriticalSection(&((*o_phandle)->m_stCriticalSection));
304*12720SWyllys.Ingersoll@Sun.COM         }
305*12720SWyllys.Ingersoll@Sun.COM         else
306*12720SWyllys.Ingersoll@Sun.COM         {
307*12720SWyllys.Ingersoll@Sun.COM             (*o_phandle)->m_handle = CreateMutex(NULL, FALSE, NULL);
308*12720SWyllys.Ingersoll@Sun.COM         }
309*12720SWyllys.Ingersoll@Sun.COM 
310*12720SWyllys.Ingersoll@Sun.COM     }
311*12720SWyllys.Ingersoll@Sun.COM #else
312*12720SWyllys.Ingersoll@Sun.COM     {
313*12720SWyllys.Ingersoll@Sun.COM         int iType;
314*12720SWyllys.Ingersoll@Sun.COM         pthread_mutexattr_t attr;
315*12720SWyllys.Ingersoll@Sun.COM 
316*12720SWyllys.Ingersoll@Sun.COM         if ( pthread_mutexattr_init(&attr) )
317*12720SWyllys.Ingersoll@Sun.COM         {
318*12720SWyllys.Ingersoll@Sun.COM             return K_SYS_ERR_COND;
319*12720SWyllys.Ingersoll@Sun.COM         }
320*12720SWyllys.Ingersoll@Sun.COM 
321*12720SWyllys.Ingersoll@Sun.COM         if(bIsRecursive)
322*12720SWyllys.Ingersoll@Sun.COM         {
323*12720SWyllys.Ingersoll@Sun.COM             iType =
324*12720SWyllys.Ingersoll@Sun.COM #ifdef K_LINUX_PLATFORM
325*12720SWyllys.Ingersoll@Sun.COM             PTHREAD_MUTEX_RECURSIVE_NP;
326*12720SWyllys.Ingersoll@Sun.COM #else
327*12720SWyllys.Ingersoll@Sun.COM             PTHREAD_MUTEX_RECURSIVE;
328*12720SWyllys.Ingersoll@Sun.COM #endif
329*12720SWyllys.Ingersoll@Sun.COM 
330*12720SWyllys.Ingersoll@Sun.COM             if ( pthread_mutexattr_settype(&attr, iType) )
331*12720SWyllys.Ingersoll@Sun.COM             {
332*12720SWyllys.Ingersoll@Sun.COM                 return K_SYS_ERR_COND;
333*12720SWyllys.Ingersoll@Sun.COM             }
334*12720SWyllys.Ingersoll@Sun.COM         }
335*12720SWyllys.Ingersoll@Sun.COM 
336*12720SWyllys.Ingersoll@Sun.COM         *o_phandle = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
337*12720SWyllys.Ingersoll@Sun.COM         if(*o_phandle == NULL)
338*12720SWyllys.Ingersoll@Sun.COM         {
339*12720SWyllys.Ingersoll@Sun.COM             return K_SYS_ERR_NO_MEMORY;
340*12720SWyllys.Ingersoll@Sun.COM         }
341*12720SWyllys.Ingersoll@Sun.COM 
342*12720SWyllys.Ingersoll@Sun.COM         if ( pthread_mutex_init(*o_phandle, &attr) )
343*12720SWyllys.Ingersoll@Sun.COM         {
344*12720SWyllys.Ingersoll@Sun.COM             return K_SYS_ERR_COND;
345*12720SWyllys.Ingersoll@Sun.COM         }
346*12720SWyllys.Ingersoll@Sun.COM 
347*12720SWyllys.Ingersoll@Sun.COM         if ( pthread_mutexattr_destroy(&attr) )
348*12720SWyllys.Ingersoll@Sun.COM         {
349*12720SWyllys.Ingersoll@Sun.COM             return K_SYS_ERR_COND;
350*12720SWyllys.Ingersoll@Sun.COM         }
351*12720SWyllys.Ingersoll@Sun.COM     }
352*12720SWyllys.Ingersoll@Sun.COM #endif
353*12720SWyllys.Ingersoll@Sun.COM 
354*12720SWyllys.Ingersoll@Sun.COM     return iOK;
355*12720SWyllys.Ingersoll@Sun.COM }
356*12720SWyllys.Ingersoll@Sun.COM 
357*12720SWyllys.Ingersoll@Sun.COM 
358*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
359*12720SWyllys.Ingersoll@Sun.COM  * Function: K_LockMutex
360*12720SWyllys.Ingersoll@Sun.COM  *
361*12720SWyllys.Ingersoll@Sun.COM  * Description:
362*12720SWyllys.Ingersoll@Sun.COM  *  K_LockMutex is used to lock the mutex, and K_UnlockMutex is
363*12720SWyllys.Ingersoll@Sun.COM  *  used to unlock it.
364*12720SWyllys.Ingersoll@Sun.COM  *
365*12720SWyllys.Ingersoll@Sun.COM  * Input
366*12720SWyllys.Ingersoll@Sun.COM  * -----
367*12720SWyllys.Ingersoll@Sun.COM  *    i_handle        the mutex handle
368*12720SWyllys.Ingersoll@Sun.COM  *
369*12720SWyllys.Ingersoll@Sun.COM  * Output
370*12720SWyllys.Ingersoll@Sun.COM  * ------
371*12720SWyllys.Ingersoll@Sun.COM  *    (none)
372*12720SWyllys.Ingersoll@Sun.COM  *
373*12720SWyllys.Ingersoll@Sun.COM  * Return value       Error Code
374*12720SWyllys.Ingersoll@Sun.COM  *
375*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
376*12720SWyllys.Ingersoll@Sun.COM 
K_LockMutex(K_MUTEX_HANDLE i_handle)377*12720SWyllys.Ingersoll@Sun.COM int K_LockMutex(K_MUTEX_HANDLE i_handle)
378*12720SWyllys.Ingersoll@Sun.COM {
379*12720SWyllys.Ingersoll@Sun.COM     int iOK = K_SYS_OK;
380*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
381*12720SWyllys.Ingersoll@Sun.COM 
382*12720SWyllys.Ingersoll@Sun.COM     if(i_handle->m_bIsRecursive)
383*12720SWyllys.Ingersoll@Sun.COM     {
384*12720SWyllys.Ingersoll@Sun.COM         EnterCriticalSection(&(i_handle->m_stCriticalSection));
385*12720SWyllys.Ingersoll@Sun.COM     }
386*12720SWyllys.Ingersoll@Sun.COM     else
387*12720SWyllys.Ingersoll@Sun.COM     {
388*12720SWyllys.Ingersoll@Sun.COM         WaitForSingleObject(i_handle->m_handle, INFINITE);
389*12720SWyllys.Ingersoll@Sun.COM     }
390*12720SWyllys.Ingersoll@Sun.COM 
391*12720SWyllys.Ingersoll@Sun.COM #else
392*12720SWyllys.Ingersoll@Sun.COM 
393*12720SWyllys.Ingersoll@Sun.COM     if ( pthread_mutex_lock(i_handle) )
394*12720SWyllys.Ingersoll@Sun.COM     {
395*12720SWyllys.Ingersoll@Sun.COM         return K_SYS_ERR_COND;
396*12720SWyllys.Ingersoll@Sun.COM     }
397*12720SWyllys.Ingersoll@Sun.COM 
398*12720SWyllys.Ingersoll@Sun.COM #endif
399*12720SWyllys.Ingersoll@Sun.COM     return iOK; // TODO: better error handling
400*12720SWyllys.Ingersoll@Sun.COM }
401*12720SWyllys.Ingersoll@Sun.COM 
402*12720SWyllys.Ingersoll@Sun.COM 
403*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
404*12720SWyllys.Ingersoll@Sun.COM  * Function: K_UnlockMutex
405*12720SWyllys.Ingersoll@Sun.COM  *
406*12720SWyllys.Ingersoll@Sun.COM  * Description:
407*12720SWyllys.Ingersoll@Sun.COM  *  K_UnlockMutex is used to unlock the lock.
408*12720SWyllys.Ingersoll@Sun.COM  *
409*12720SWyllys.Ingersoll@Sun.COM  * Input
410*12720SWyllys.Ingersoll@Sun.COM  * -----
411*12720SWyllys.Ingersoll@Sun.COM  *    i_handle        the mutex handle
412*12720SWyllys.Ingersoll@Sun.COM  *
413*12720SWyllys.Ingersoll@Sun.COM  * Output
414*12720SWyllys.Ingersoll@Sun.COM  * ------
415*12720SWyllys.Ingersoll@Sun.COM  *    (none)
416*12720SWyllys.Ingersoll@Sun.COM  *
417*12720SWyllys.Ingersoll@Sun.COM  * Return value       Error Code
418*12720SWyllys.Ingersoll@Sun.COM  *
419*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
420*12720SWyllys.Ingersoll@Sun.COM 
K_UnlockMutex(K_MUTEX_HANDLE i_handle)421*12720SWyllys.Ingersoll@Sun.COM int K_UnlockMutex(K_MUTEX_HANDLE i_handle)
422*12720SWyllys.Ingersoll@Sun.COM {
423*12720SWyllys.Ingersoll@Sun.COM     int iOK = K_SYS_OK;
424*12720SWyllys.Ingersoll@Sun.COM 
425*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
426*12720SWyllys.Ingersoll@Sun.COM     if(i_handle->m_bIsRecursive)
427*12720SWyllys.Ingersoll@Sun.COM     {
428*12720SWyllys.Ingersoll@Sun.COM         LeaveCriticalSection(&(i_handle->m_stCriticalSection));
429*12720SWyllys.Ingersoll@Sun.COM     }
430*12720SWyllys.Ingersoll@Sun.COM     else
431*12720SWyllys.Ingersoll@Sun.COM     {
432*12720SWyllys.Ingersoll@Sun.COM         ReleaseMutex(i_handle->m_handle);
433*12720SWyllys.Ingersoll@Sun.COM     }
434*12720SWyllys.Ingersoll@Sun.COM 
435*12720SWyllys.Ingersoll@Sun.COM #else
436*12720SWyllys.Ingersoll@Sun.COM 
437*12720SWyllys.Ingersoll@Sun.COM     if ( pthread_mutex_unlock(i_handle) )
438*12720SWyllys.Ingersoll@Sun.COM     {
439*12720SWyllys.Ingersoll@Sun.COM         return K_SYS_ERR_COND;
440*12720SWyllys.Ingersoll@Sun.COM     }
441*12720SWyllys.Ingersoll@Sun.COM #endif
442*12720SWyllys.Ingersoll@Sun.COM 
443*12720SWyllys.Ingersoll@Sun.COM     return iOK; // TODO: better error handling
444*12720SWyllys.Ingersoll@Sun.COM }
445*12720SWyllys.Ingersoll@Sun.COM 
446*12720SWyllys.Ingersoll@Sun.COM 
447*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
448*12720SWyllys.Ingersoll@Sun.COM  * Function: K_DestroyMutex
449*12720SWyllys.Ingersoll@Sun.COM  *
450*12720SWyllys.Ingersoll@Sun.COM  * Description:
451*12720SWyllys.Ingersoll@Sun.COM  *  When a mutex is no longer needed, K_DestroyMutex must be called
452*12720SWyllys.Ingersoll@Sun.COM  *  to destroy it.
453*12720SWyllys.Ingersoll@Sun.COM  *
454*12720SWyllys.Ingersoll@Sun.COM  * Input
455*12720SWyllys.Ingersoll@Sun.COM  * -----
456*12720SWyllys.Ingersoll@Sun.COM  *    i_handle        the mutex handle
457*12720SWyllys.Ingersoll@Sun.COM  * Output
458*12720SWyllys.Ingersoll@Sun.COM  * ------
459*12720SWyllys.Ingersoll@Sun.COM  *    (none)
460*12720SWyllys.Ingersoll@Sun.COM  *
461*12720SWyllys.Ingersoll@Sun.COM  * Return value       Error Code
462*12720SWyllys.Ingersoll@Sun.COM  *
463*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
464*12720SWyllys.Ingersoll@Sun.COM 
K_DestroyMutex(K_MUTEX_HANDLE i_handle)465*12720SWyllys.Ingersoll@Sun.COM int K_DestroyMutex(K_MUTEX_HANDLE i_handle)
466*12720SWyllys.Ingersoll@Sun.COM {
467*12720SWyllys.Ingersoll@Sun.COM 
468*12720SWyllys.Ingersoll@Sun.COM     int iOK = K_SYS_OK;
469*12720SWyllys.Ingersoll@Sun.COM 
470*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
471*12720SWyllys.Ingersoll@Sun.COM 
472*12720SWyllys.Ingersoll@Sun.COM     if(i_handle->m_bIsRecursive)
473*12720SWyllys.Ingersoll@Sun.COM     {
474*12720SWyllys.Ingersoll@Sun.COM         DeleteCriticalSection(&(i_handle->m_stCriticalSection));
475*12720SWyllys.Ingersoll@Sun.COM     }
476*12720SWyllys.Ingersoll@Sun.COM     else
477*12720SWyllys.Ingersoll@Sun.COM     {
478*12720SWyllys.Ingersoll@Sun.COM         CloseHandle(i_handle->m_handle);
479*12720SWyllys.Ingersoll@Sun.COM     }
480*12720SWyllys.Ingersoll@Sun.COM     free(i_handle);
481*12720SWyllys.Ingersoll@Sun.COM 
482*12720SWyllys.Ingersoll@Sun.COM #else
483*12720SWyllys.Ingersoll@Sun.COM     pthread_mutex_destroy(i_handle);
484*12720SWyllys.Ingersoll@Sun.COM     free(i_handle);
485*12720SWyllys.Ingersoll@Sun.COM #endif
486*12720SWyllys.Ingersoll@Sun.COM     return iOK; // TODO: better error handling
487*12720SWyllys.Ingersoll@Sun.COM }
488*12720SWyllys.Ingersoll@Sun.COM 
489*12720SWyllys.Ingersoll@Sun.COM 
490*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
491*12720SWyllys.Ingersoll@Sun.COM  * Function: K_InitConditionalVariable
492*12720SWyllys.Ingersoll@Sun.COM  *
493*12720SWyllys.Ingersoll@Sun.COM  * Description:
494*12720SWyllys.Ingersoll@Sun.COM  *  This function initializes a conditional variable.  Upon successful
495*12720SWyllys.Ingersoll@Sun.COM  *  completion, the new condition variable is returned via the condition
496*12720SWyllys.Ingersoll@Sun.COM  *  parameter, and 0 is returned.  Otherwise, an error code is returned.
497*12720SWyllys.Ingersoll@Sun.COM  *
498*12720SWyllys.Ingersoll@Sun.COM  * Input
499*12720SWyllys.Ingersoll@Sun.COM  * -----
500*12720SWyllys.Ingersoll@Sun.COM  *    i_pCond         the pointer to the conditional variable which is to be
501*12720SWyllys.Ingersoll@Sun.COM  *                    initialized
502*12720SWyllys.Ingersoll@Sun.COM  *
503*12720SWyllys.Ingersoll@Sun.COM  * Output
504*12720SWyllys.Ingersoll@Sun.COM  * ------
505*12720SWyllys.Ingersoll@Sun.COM  *    (none)
506*12720SWyllys.Ingersoll@Sun.COM  *
507*12720SWyllys.Ingersoll@Sun.COM  * Return value       Error Code
508*12720SWyllys.Ingersoll@Sun.COM  *
509*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
510*12720SWyllys.Ingersoll@Sun.COM 
K_InitConditionalVariable(K_ConditionalVariable * i_pCond)511*12720SWyllys.Ingersoll@Sun.COM int K_InitConditionalVariable (K_ConditionalVariable * i_pCond)
512*12720SWyllys.Ingersoll@Sun.COM {
513*12720SWyllys.Ingersoll@Sun.COM     int iOK = K_SYS_OK;
514*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
515*12720SWyllys.Ingersoll@Sun.COM 
516*12720SWyllys.Ingersoll@Sun.COM     i_pCond->m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
517*12720SWyllys.Ingersoll@Sun.COM     i_pCond->m_hMutex = CreateMutex(NULL, FALSE, NULL);
518*12720SWyllys.Ingersoll@Sun.COM     i_pCond->m_iSignalAll = 0;
519*12720SWyllys.Ingersoll@Sun.COM     i_pCond->m_iNumWaiting = 0;
520*12720SWyllys.Ingersoll@Sun.COM 
521*12720SWyllys.Ingersoll@Sun.COM #else
522*12720SWyllys.Ingersoll@Sun.COM 
523*12720SWyllys.Ingersoll@Sun.COM     if ( pthread_cond_init(i_pCond, NULL) )
524*12720SWyllys.Ingersoll@Sun.COM     {
525*12720SWyllys.Ingersoll@Sun.COM         return K_SYS_ERR_COND;
526*12720SWyllys.Ingersoll@Sun.COM     }
527*12720SWyllys.Ingersoll@Sun.COM 
528*12720SWyllys.Ingersoll@Sun.COM #endif
529*12720SWyllys.Ingersoll@Sun.COM 
530*12720SWyllys.Ingersoll@Sun.COM     return iOK;
531*12720SWyllys.Ingersoll@Sun.COM }
532*12720SWyllys.Ingersoll@Sun.COM 
533*12720SWyllys.Ingersoll@Sun.COM 
534*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
535*12720SWyllys.Ingersoll@Sun.COM  * Function: K_DestroyConditionalVariable
536*12720SWyllys.Ingersoll@Sun.COM  *
537*12720SWyllys.Ingersoll@Sun.COM  * Description:
538*12720SWyllys.Ingersoll@Sun.COM  *  This function destroys a conditional variable.  Upon successful
539*12720SWyllys.Ingersoll@Sun.COM  *  completion, the condition variable is destroyed, and 0 is returned.
540*12720SWyllys.Ingersoll@Sun.COM  *  Otherwise, an error code is returned.
541*12720SWyllys.Ingersoll@Sun.COM  *  After deletion of the condition variable, the condition parameter
542*12720SWyllys.Ingersoll@Sun.COM  *  is not valid until it is initialized again by a call to the
543*12720SWyllys.Ingersoll@Sun.COM  *  K_InitConditionalVariable subroutine.
544*12720SWyllys.Ingersoll@Sun.COM  *
545*12720SWyllys.Ingersoll@Sun.COM  * Input
546*12720SWyllys.Ingersoll@Sun.COM  * -----
547*12720SWyllys.Ingersoll@Sun.COM  *    i_pCond        the pointer to the conditional variable which is to be
548*12720SWyllys.Ingersoll@Sun.COM  *                   destroyed
549*12720SWyllys.Ingersoll@Sun.COM  * Output
550*12720SWyllys.Ingersoll@Sun.COM  * ------
551*12720SWyllys.Ingersoll@Sun.COM  *    (none)
552*12720SWyllys.Ingersoll@Sun.COM  *
553*12720SWyllys.Ingersoll@Sun.COM  * Return value      Error Code
554*12720SWyllys.Ingersoll@Sun.COM  *
555*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
556*12720SWyllys.Ingersoll@Sun.COM 
K_DestroyConditionalVariable(K_ConditionalVariable * i_pCond)557*12720SWyllys.Ingersoll@Sun.COM int K_DestroyConditionalVariable(K_ConditionalVariable * i_pCond)
558*12720SWyllys.Ingersoll@Sun.COM {
559*12720SWyllys.Ingersoll@Sun.COM     int iOK = K_SYS_OK;
560*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
561*12720SWyllys.Ingersoll@Sun.COM     CloseHandle(i_pCond->m_hMutex);
562*12720SWyllys.Ingersoll@Sun.COM     CloseHandle(i_pCond->m_hEvent);
563*12720SWyllys.Ingersoll@Sun.COM #else
564*12720SWyllys.Ingersoll@Sun.COM 
565*12720SWyllys.Ingersoll@Sun.COM     if ( pthread_cond_destroy(i_pCond) )
566*12720SWyllys.Ingersoll@Sun.COM     {
567*12720SWyllys.Ingersoll@Sun.COM         return K_SYS_ERR_COND;
568*12720SWyllys.Ingersoll@Sun.COM     }
569*12720SWyllys.Ingersoll@Sun.COM 
570*12720SWyllys.Ingersoll@Sun.COM #endif
571*12720SWyllys.Ingersoll@Sun.COM     return iOK;
572*12720SWyllys.Ingersoll@Sun.COM 
573*12720SWyllys.Ingersoll@Sun.COM }
574*12720SWyllys.Ingersoll@Sun.COM 
575*12720SWyllys.Ingersoll@Sun.COM 
576*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
577*12720SWyllys.Ingersoll@Sun.COM  * Function: K_WaitConditionalVariable
578*12720SWyllys.Ingersoll@Sun.COM  *
579*12720SWyllys.Ingersoll@Sun.COM  * Description:
580*12720SWyllys.Ingersoll@Sun.COM  *  This function is used to block on a condition variable.
581*12720SWyllys.Ingersoll@Sun.COM  *  They are called with mutex locked by the calling thread or undefined
582*12720SWyllys.Ingersoll@Sun.COM  *  behaviour will result.
583*12720SWyllys.Ingersoll@Sun.COM  *
584*12720SWyllys.Ingersoll@Sun.COM  * Input
585*12720SWyllys.Ingersoll@Sun.COM  * -----
586*12720SWyllys.Ingersoll@Sun.COM  *    i_pCond        the pointer to the conditional variable
587*12720SWyllys.Ingersoll@Sun.COM  *    i_handle       the companion mutex handle
588*12720SWyllys.Ingersoll@Sun.COM  *
589*12720SWyllys.Ingersoll@Sun.COM  * Output
590*12720SWyllys.Ingersoll@Sun.COM  * ------
591*12720SWyllys.Ingersoll@Sun.COM  *    (none)
592*12720SWyllys.Ingersoll@Sun.COM  *
593*12720SWyllys.Ingersoll@Sun.COM  * Return value      Error Code
594*12720SWyllys.Ingersoll@Sun.COM  *
595*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
596*12720SWyllys.Ingersoll@Sun.COM 
K_WaitConditionalVariable(K_ConditionalVariable * i_pCond,K_MUTEX_HANDLE i_handle)597*12720SWyllys.Ingersoll@Sun.COM int  K_WaitConditionalVariable(K_ConditionalVariable * i_pCond,
598*12720SWyllys.Ingersoll@Sun.COM                                K_MUTEX_HANDLE i_handle)
599*12720SWyllys.Ingersoll@Sun.COM {
600*12720SWyllys.Ingersoll@Sun.COM 
601*12720SWyllys.Ingersoll@Sun.COM     int iOK = K_SYS_OK;
602*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
603*12720SWyllys.Ingersoll@Sun.COM     DWORD res;
604*12720SWyllys.Ingersoll@Sun.COM 
605*12720SWyllys.Ingersoll@Sun.COM     while (1)
606*12720SWyllys.Ingersoll@Sun.COM     {
607*12720SWyllys.Ingersoll@Sun.COM         iOK = WaitForSingleObject(i_pCond->m_hMutex, INFINITE);
608*12720SWyllys.Ingersoll@Sun.COM         if (iOK != WAIT_OBJECT_0)
609*12720SWyllys.Ingersoll@Sun.COM         {
610*12720SWyllys.Ingersoll@Sun.COM             return K_SYS_ERR_COND;
611*12720SWyllys.Ingersoll@Sun.COM         }
612*12720SWyllys.Ingersoll@Sun.COM         i_pCond->m_iNumWaiting++;
613*12720SWyllys.Ingersoll@Sun.COM         ReleaseMutex(i_pCond->m_hMutex);
614*12720SWyllys.Ingersoll@Sun.COM 
615*12720SWyllys.Ingersoll@Sun.COM         K_UnlockMutex(i_handle);
616*12720SWyllys.Ingersoll@Sun.COM         res = WaitForSingleObject(i_pCond->m_hEvent, INFINITE);
617*12720SWyllys.Ingersoll@Sun.COM         i_pCond->m_iNumWaiting--;
618*12720SWyllys.Ingersoll@Sun.COM 
619*12720SWyllys.Ingersoll@Sun.COM         if (res != WAIT_OBJECT_0)
620*12720SWyllys.Ingersoll@Sun.COM         {
621*12720SWyllys.Ingersoll@Sun.COM             ReleaseMutex(i_pCond->m_hMutex);
622*12720SWyllys.Ingersoll@Sun.COM             return K_SYS_ERR_COND;
623*12720SWyllys.Ingersoll@Sun.COM         }
624*12720SWyllys.Ingersoll@Sun.COM 
625*12720SWyllys.Ingersoll@Sun.COM         if (i_pCond->m_iSignalAll)
626*12720SWyllys.Ingersoll@Sun.COM         {
627*12720SWyllys.Ingersoll@Sun.COM             if (i_pCond->m_iNumWaiting == 0)
628*12720SWyllys.Ingersoll@Sun.COM             {
629*12720SWyllys.Ingersoll@Sun.COM                 ResetEvent(i_pCond->m_hEvent);
630*12720SWyllys.Ingersoll@Sun.COM             }
631*12720SWyllys.Ingersoll@Sun.COM             break;
632*12720SWyllys.Ingersoll@Sun.COM         }
633*12720SWyllys.Ingersoll@Sun.COM 
634*12720SWyllys.Ingersoll@Sun.COM         if (i_pCond->m_iSignalled)
635*12720SWyllys.Ingersoll@Sun.COM         {
636*12720SWyllys.Ingersoll@Sun.COM             i_pCond->m_iSignalled = 0;
637*12720SWyllys.Ingersoll@Sun.COM             ResetEvent(i_pCond->m_hEvent);
638*12720SWyllys.Ingersoll@Sun.COM             break;
639*12720SWyllys.Ingersoll@Sun.COM         }
640*12720SWyllys.Ingersoll@Sun.COM         ReleaseMutex(i_pCond->m_hMutex);
641*12720SWyllys.Ingersoll@Sun.COM     }
642*12720SWyllys.Ingersoll@Sun.COM 
643*12720SWyllys.Ingersoll@Sun.COM     K_LockMutex(i_handle);
644*12720SWyllys.Ingersoll@Sun.COM 
645*12720SWyllys.Ingersoll@Sun.COM     return K_SYS_OK;
646*12720SWyllys.Ingersoll@Sun.COM #else
647*12720SWyllys.Ingersoll@Sun.COM 
648*12720SWyllys.Ingersoll@Sun.COM     if ( pthread_cond_wait(i_pCond, i_handle) )
649*12720SWyllys.Ingersoll@Sun.COM     {
650*12720SWyllys.Ingersoll@Sun.COM         return K_SYS_ERR_COND;
651*12720SWyllys.Ingersoll@Sun.COM     }
652*12720SWyllys.Ingersoll@Sun.COM 
653*12720SWyllys.Ingersoll@Sun.COM #endif
654*12720SWyllys.Ingersoll@Sun.COM     return iOK; // TODO: better error handling
655*12720SWyllys.Ingersoll@Sun.COM }
656*12720SWyllys.Ingersoll@Sun.COM 
657*12720SWyllys.Ingersoll@Sun.COM 
658*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
659*12720SWyllys.Ingersoll@Sun.COM  * Function: K_SignalConditionalVariable
660*12720SWyllys.Ingersoll@Sun.COM  *
661*12720SWyllys.Ingersoll@Sun.COM  * Description:
662*12720SWyllys.Ingersoll@Sun.COM  *  This function is used to restart one of the threads that are waiting on
663*12720SWyllys.Ingersoll@Sun.COM  *  the condition variable.  If no threads are waiting on it, nothing happens.
664*12720SWyllys.Ingersoll@Sun.COM  *  If several threads are waiting on it, exactly one is restarted.
665*12720SWyllys.Ingersoll@Sun.COM  *
666*12720SWyllys.Ingersoll@Sun.COM  * Input
667*12720SWyllys.Ingersoll@Sun.COM  * -----
668*12720SWyllys.Ingersoll@Sun.COM  *    i_pCond        the pointer to the conditional variable
669*12720SWyllys.Ingersoll@Sun.COM  *
670*12720SWyllys.Ingersoll@Sun.COM  * Output
671*12720SWyllys.Ingersoll@Sun.COM  * ------
672*12720SWyllys.Ingersoll@Sun.COM  *    (none)
673*12720SWyllys.Ingersoll@Sun.COM  *
674*12720SWyllys.Ingersoll@Sun.COM  * Return value      Error Code
675*12720SWyllys.Ingersoll@Sun.COM  *
676*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
677*12720SWyllys.Ingersoll@Sun.COM 
K_SignalConditionalVariable(K_ConditionalVariable * i_pCond)678*12720SWyllys.Ingersoll@Sun.COM int K_SignalConditionalVariable(K_ConditionalVariable * i_pCond)
679*12720SWyllys.Ingersoll@Sun.COM {
680*12720SWyllys.Ingersoll@Sun.COM     int iOK = K_SYS_OK;
681*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
682*12720SWyllys.Ingersoll@Sun.COM 
683*12720SWyllys.Ingersoll@Sun.COM     int iReturn;
684*12720SWyllys.Ingersoll@Sun.COM 
685*12720SWyllys.Ingersoll@Sun.COM     iReturn = WaitForSingleObject(i_pCond->m_hMutex, INFINITE);
686*12720SWyllys.Ingersoll@Sun.COM     if (iReturn != WAIT_OBJECT_0)
687*12720SWyllys.Ingersoll@Sun.COM     {
688*12720SWyllys.Ingersoll@Sun.COM         return K_SYS_ERR_COND;
689*12720SWyllys.Ingersoll@Sun.COM     }
690*12720SWyllys.Ingersoll@Sun.COM 
691*12720SWyllys.Ingersoll@Sun.COM     i_pCond->m_iSignalled = 1;
692*12720SWyllys.Ingersoll@Sun.COM 
693*12720SWyllys.Ingersoll@Sun.COM     iReturn = SetEvent(i_pCond->m_hEvent);
694*12720SWyllys.Ingersoll@Sun.COM     if (iReturn == 0)
695*12720SWyllys.Ingersoll@Sun.COM     {
696*12720SWyllys.Ingersoll@Sun.COM         iOK = K_SYS_ERR_COND;
697*12720SWyllys.Ingersoll@Sun.COM     }
698*12720SWyllys.Ingersoll@Sun.COM     ReleaseMutex(i_pCond->m_hMutex);
699*12720SWyllys.Ingersoll@Sun.COM 
700*12720SWyllys.Ingersoll@Sun.COM     return iOK;
701*12720SWyllys.Ingersoll@Sun.COM #else
702*12720SWyllys.Ingersoll@Sun.COM 
703*12720SWyllys.Ingersoll@Sun.COM     if ( pthread_cond_signal(i_pCond) )
704*12720SWyllys.Ingersoll@Sun.COM     {
705*12720SWyllys.Ingersoll@Sun.COM         return K_SYS_ERR_COND;
706*12720SWyllys.Ingersoll@Sun.COM     }
707*12720SWyllys.Ingersoll@Sun.COM 
708*12720SWyllys.Ingersoll@Sun.COM #endif
709*12720SWyllys.Ingersoll@Sun.COM     return iOK;
710*12720SWyllys.Ingersoll@Sun.COM }
711*12720SWyllys.Ingersoll@Sun.COM 
712*12720SWyllys.Ingersoll@Sun.COM 
713*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
714*12720SWyllys.Ingersoll@Sun.COM  * Function: K_BroadcastConditionalVariable
715*12720SWyllys.Ingersoll@Sun.COM  *
716*12720SWyllys.Ingersoll@Sun.COM  * Description:
717*12720SWyllys.Ingersoll@Sun.COM  *  This function is used to restart all threads that are waiting on
718*12720SWyllys.Ingersoll@Sun.COM  *  the condition variable.
719*12720SWyllys.Ingersoll@Sun.COM  *
720*12720SWyllys.Ingersoll@Sun.COM  * Input
721*12720SWyllys.Ingersoll@Sun.COM  * -----
722*12720SWyllys.Ingersoll@Sun.COM  *    i_pCond        the pointer to the conditional variable
723*12720SWyllys.Ingersoll@Sun.COM  *
724*12720SWyllys.Ingersoll@Sun.COM  * Output
725*12720SWyllys.Ingersoll@Sun.COM  * ------
726*12720SWyllys.Ingersoll@Sun.COM  *    (none)
727*12720SWyllys.Ingersoll@Sun.COM  *
728*12720SWyllys.Ingersoll@Sun.COM  * Return value      Error Code
729*12720SWyllys.Ingersoll@Sun.COM  *
730*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
731*12720SWyllys.Ingersoll@Sun.COM 
K_BroadcastConditionalVariable(K_ConditionalVariable * i_pCond)732*12720SWyllys.Ingersoll@Sun.COM int K_BroadcastConditionalVariable(K_ConditionalVariable * i_pCond)
733*12720SWyllys.Ingersoll@Sun.COM {
734*12720SWyllys.Ingersoll@Sun.COM 
735*12720SWyllys.Ingersoll@Sun.COM     int iOK = K_SYS_OK;
736*12720SWyllys.Ingersoll@Sun.COM 
737*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
738*12720SWyllys.Ingersoll@Sun.COM 
739*12720SWyllys.Ingersoll@Sun.COM     int iReturn;
740*12720SWyllys.Ingersoll@Sun.COM 
741*12720SWyllys.Ingersoll@Sun.COM     iReturn = WaitForSingleObject(i_pCond->m_hMutex, INFINITE);
742*12720SWyllys.Ingersoll@Sun.COM     if (iReturn != WAIT_OBJECT_0)
743*12720SWyllys.Ingersoll@Sun.COM     {
744*12720SWyllys.Ingersoll@Sun.COM         return K_SYS_ERR_COND;
745*12720SWyllys.Ingersoll@Sun.COM     }
746*12720SWyllys.Ingersoll@Sun.COM     i_pCond->m_iSignalled = 1;
747*12720SWyllys.Ingersoll@Sun.COM     i_pCond->m_iSignalAll = 1;
748*12720SWyllys.Ingersoll@Sun.COM 
749*12720SWyllys.Ingersoll@Sun.COM     iReturn = SetEvent(i_pCond->m_hEvent);
750*12720SWyllys.Ingersoll@Sun.COM 
751*12720SWyllys.Ingersoll@Sun.COM     if (iReturn == 0)
752*12720SWyllys.Ingersoll@Sun.COM     {
753*12720SWyllys.Ingersoll@Sun.COM         iOK = K_SYS_ERR_COND;
754*12720SWyllys.Ingersoll@Sun.COM     }
755*12720SWyllys.Ingersoll@Sun.COM 
756*12720SWyllys.Ingersoll@Sun.COM     ReleaseMutex(i_pCond->m_hMutex);
757*12720SWyllys.Ingersoll@Sun.COM 
758*12720SWyllys.Ingersoll@Sun.COM     return iOK;
759*12720SWyllys.Ingersoll@Sun.COM 
760*12720SWyllys.Ingersoll@Sun.COM #else
761*12720SWyllys.Ingersoll@Sun.COM 
762*12720SWyllys.Ingersoll@Sun.COM     if ( pthread_cond_broadcast(i_pCond) )
763*12720SWyllys.Ingersoll@Sun.COM     {
764*12720SWyllys.Ingersoll@Sun.COM         return K_SYS_ERR_COND;
765*12720SWyllys.Ingersoll@Sun.COM     }
766*12720SWyllys.Ingersoll@Sun.COM 
767*12720SWyllys.Ingersoll@Sun.COM #endif
768*12720SWyllys.Ingersoll@Sun.COM     return iOK;
769*12720SWyllys.Ingersoll@Sun.COM }
770*12720SWyllys.Ingersoll@Sun.COM 
771*12720SWyllys.Ingersoll@Sun.COM 
772*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
773*12720SWyllys.Ingersoll@Sun.COM  * Function: K_Sleep
774*12720SWyllys.Ingersoll@Sun.COM  *
775*12720SWyllys.Ingersoll@Sun.COM  * Description:
776*12720SWyllys.Ingersoll@Sun.COM  *  Sleep for a given period in given milliseconds.
777*12720SWyllys.Ingersoll@Sun.COM  *
778*12720SWyllys.Ingersoll@Sun.COM  * Input
779*12720SWyllys.Ingersoll@Sun.COM  * -----
780*12720SWyllys.Ingersoll@Sun.COM  *    i_ms        milliseconds
781*12720SWyllys.Ingersoll@Sun.COM  *
782*12720SWyllys.Ingersoll@Sun.COM  * Output
783*12720SWyllys.Ingersoll@Sun.COM  * ------
784*12720SWyllys.Ingersoll@Sun.COM  *    (none)
785*12720SWyllys.Ingersoll@Sun.COM  *
786*12720SWyllys.Ingersoll@Sun.COM  * Return value   (none)
787*12720SWyllys.Ingersoll@Sun.COM  *
788*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
789*12720SWyllys.Ingersoll@Sun.COM 
K_Sleep(int i_ms)790*12720SWyllys.Ingersoll@Sun.COM void K_Sleep(int i_ms)
791*12720SWyllys.Ingersoll@Sun.COM {
792*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
793*12720SWyllys.Ingersoll@Sun.COM     Sleep(i_ms);
794*12720SWyllys.Ingersoll@Sun.COM #else
795*12720SWyllys.Ingersoll@Sun.COM     usleep(i_ms * 1000);
796*12720SWyllys.Ingersoll@Sun.COM #endif
797*12720SWyllys.Ingersoll@Sun.COM }
798*12720SWyllys.Ingersoll@Sun.COM 
799*12720SWyllys.Ingersoll@Sun.COM 
800*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
801*12720SWyllys.Ingersoll@Sun.COM  * Function: K_GetTickCount
802*12720SWyllys.Ingersoll@Sun.COM  *
803*12720SWyllys.Ingersoll@Sun.COM  * Description:
804*12720SWyllys.Ingersoll@Sun.COM  *  The K_GetTickCount function retrieves the number of
805*12720SWyllys.Ingersoll@Sun.COM  *  milliseconds that have elapsed since the system was started.
806*12720SWyllys.Ingersoll@Sun.COM  *
807*12720SWyllys.Ingersoll@Sun.COM  * Input
808*12720SWyllys.Ingersoll@Sun.COM  * -----
809*12720SWyllys.Ingersoll@Sun.COM  *    (none)
810*12720SWyllys.Ingersoll@Sun.COM  *
811*12720SWyllys.Ingersoll@Sun.COM  * Output
812*12720SWyllys.Ingersoll@Sun.COM  * ------
813*12720SWyllys.Ingersoll@Sun.COM  *    (none)
814*12720SWyllys.Ingersoll@Sun.COM  *
815*12720SWyllys.Ingersoll@Sun.COM  * Return value        the elasped milliseconds since the system was started
816*12720SWyllys.Ingersoll@Sun.COM  *
817*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
818*12720SWyllys.Ingersoll@Sun.COM 
K_GetTickCount()819*12720SWyllys.Ingersoll@Sun.COM unsigned int K_GetTickCount()
820*12720SWyllys.Ingersoll@Sun.COM {
821*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
822*12720SWyllys.Ingersoll@Sun.COM     return (unsigned int)GetTickCount();
823*12720SWyllys.Ingersoll@Sun.COM #else
824*12720SWyllys.Ingersoll@Sun.COM     {
825*12720SWyllys.Ingersoll@Sun.COM         struct timeval tv;
826*12720SWyllys.Ingersoll@Sun.COM         gettimeofday( &tv, NULL );
827*12720SWyllys.Ingersoll@Sun.COM         /* this will rollover ~ every 49.7 days
828*12720SWyllys.Ingersoll@Sun.COM            dont surprise when it returns negative values, since we are only interested
829*12720SWyllys.Ingersoll@Sun.COM           in using  sth like "tickCount2 - tickCount1" to get the time interval
830*12720SWyllys.Ingersoll@Sun.COM         */
831*12720SWyllys.Ingersoll@Sun.COM         return ( tv.tv_sec * 1000 ) + ( tv.tv_usec / 1000 );
832*12720SWyllys.Ingersoll@Sun.COM     }
833*12720SWyllys.Ingersoll@Sun.COM #endif
834*12720SWyllys.Ingersoll@Sun.COM }
835*12720SWyllys.Ingersoll@Sun.COM 
836*12720SWyllys.Ingersoll@Sun.COM 
837*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
838*12720SWyllys.Ingersoll@Sun.COM  * Function: K_AdjustClock
839*12720SWyllys.Ingersoll@Sun.COM  *
840*12720SWyllys.Ingersoll@Sun.COM  * Description:
841*12720SWyllys.Ingersoll@Sun.COM  *  The K_AdjustClock function immediately adjusts the system clock by
842*12720SWyllys.Ingersoll@Sun.COM  *  the given number of seconds.  A positive number adjusts the system
843*12720SWyllys.Ingersoll@Sun.COM  *  clock forward; a negative number adjusts the system clock backward.
844*12720SWyllys.Ingersoll@Sun.COM  *
845*12720SWyllys.Ingersoll@Sun.COM  * Input
846*12720SWyllys.Ingersoll@Sun.COM  * -----
847*12720SWyllys.Ingersoll@Sun.COM  *    i_iAdjustmentInSeconds   Number of seconds by which to adjust the
848*12720SWyllys.Ingersoll@Sun.COM  *                             system clock
849*12720SWyllys.Ingersoll@Sun.COM  * Output
850*12720SWyllys.Ingersoll@Sun.COM  * ------
851*12720SWyllys.Ingersoll@Sun.COM  *    (none)
852*12720SWyllys.Ingersoll@Sun.COM  *
853*12720SWyllys.Ingersoll@Sun.COM  * Return value        1 if successful, 0 on error
854*12720SWyllys.Ingersoll@Sun.COM  *
855*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
856*12720SWyllys.Ingersoll@Sun.COM 
K_AdjustClock(long i_iAdjustmentInSeconds)857*12720SWyllys.Ingersoll@Sun.COM int K_AdjustClock( long i_iAdjustmentInSeconds )
858*12720SWyllys.Ingersoll@Sun.COM {
859*12720SWyllys.Ingersoll@Sun.COM #ifndef WIN32
860*12720SWyllys.Ingersoll@Sun.COM     struct timeval stDateTime;
861*12720SWyllys.Ingersoll@Sun.COM     if ( 0 != gettimeofday(&stDateTime, NULL) )
862*12720SWyllys.Ingersoll@Sun.COM     {
863*12720SWyllys.Ingersoll@Sun.COM         return FALSE;
864*12720SWyllys.Ingersoll@Sun.COM     }
865*12720SWyllys.Ingersoll@Sun.COM 
866*12720SWyllys.Ingersoll@Sun.COM     stDateTime.tv_sec += i_iAdjustmentInSeconds;
867*12720SWyllys.Ingersoll@Sun.COM 
868*12720SWyllys.Ingersoll@Sun.COM     if ( 0 != settimeofday(&stDateTime, NULL) )
869*12720SWyllys.Ingersoll@Sun.COM     {
870*12720SWyllys.Ingersoll@Sun.COM         return FALSE;
871*12720SWyllys.Ingersoll@Sun.COM     }
872*12720SWyllys.Ingersoll@Sun.COM #else
873*12720SWyllys.Ingersoll@Sun.COM     // TODO: implement for Windows
874*12720SWyllys.Ingersoll@Sun.COM     return FALSE;
875*12720SWyllys.Ingersoll@Sun.COM #endif
876*12720SWyllys.Ingersoll@Sun.COM 
877*12720SWyllys.Ingersoll@Sun.COM     return TRUE;
878*12720SWyllys.Ingersoll@Sun.COM }
879*12720SWyllys.Ingersoll@Sun.COM 
880*12720SWyllys.Ingersoll@Sun.COM 
881*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
882*12720SWyllys.Ingersoll@Sun.COM  * Function: K_IsLittleEndian
883*12720SWyllys.Ingersoll@Sun.COM  *
884*12720SWyllys.Ingersoll@Sun.COM  * Description:
885*12720SWyllys.Ingersoll@Sun.COM  *  Checks to see whether this platform uses little endian integer
886*12720SWyllys.Ingersoll@Sun.COM  *  representation.
887*12720SWyllys.Ingersoll@Sun.COM  *
888*12720SWyllys.Ingersoll@Sun.COM  * Input
889*12720SWyllys.Ingersoll@Sun.COM  * -----
890*12720SWyllys.Ingersoll@Sun.COM  *    (none)
891*12720SWyllys.Ingersoll@Sun.COM  *
892*12720SWyllys.Ingersoll@Sun.COM  * Output
893*12720SWyllys.Ingersoll@Sun.COM  * ------
894*12720SWyllys.Ingersoll@Sun.COM  *    (none)
895*12720SWyllys.Ingersoll@Sun.COM  *
896*12720SWyllys.Ingersoll@Sun.COM  * Return value        1 for little endian
897*12720SWyllys.Ingersoll@Sun.COM  *
898*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
899*12720SWyllys.Ingersoll@Sun.COM 
K_IsLittleEndian()900*12720SWyllys.Ingersoll@Sun.COM int K_IsLittleEndian()
901*12720SWyllys.Ingersoll@Sun.COM {
902*12720SWyllys.Ingersoll@Sun.COM     short iWord = 0x4321;
903*12720SWyllys.Ingersoll@Sun.COM     return ((*(unsigned char*)&iWord) == 0x21);
904*12720SWyllys.Ingersoll@Sun.COM }
905*12720SWyllys.Ingersoll@Sun.COM 
906*12720SWyllys.Ingersoll@Sun.COM 
907*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
908*12720SWyllys.Ingersoll@Sun.COM  * Function: K_FileLength32
909*12720SWyllys.Ingersoll@Sun.COM  *
910*12720SWyllys.Ingersoll@Sun.COM  * Description:
911*12720SWyllys.Ingersoll@Sun.COM  *  Gets the size in bytes of the file associated with the given FILE pointer.
912*12720SWyllys.Ingersoll@Sun.COM  *
913*12720SWyllys.Ingersoll@Sun.COM  * Input
914*12720SWyllys.Ingersoll@Sun.COM  * -----
915*12720SWyllys.Ingersoll@Sun.COM  *    i_fpFile         File handle
916*12720SWyllys.Ingersoll@Sun.COM  *
917*12720SWyllys.Ingersoll@Sun.COM  * Output
918*12720SWyllys.Ingersoll@Sun.COM  * ------
919*12720SWyllys.Ingersoll@Sun.COM  *    (none)
920*12720SWyllys.Ingersoll@Sun.COM  *
921*12720SWyllys.Ingersoll@Sun.COM  * Return value        File size in bytes, or -1L on error
922*12720SWyllys.Ingersoll@Sun.COM  *
923*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
924*12720SWyllys.Ingersoll@Sun.COM 
K_FileLength32(FILE * i_fpFile)925*12720SWyllys.Ingersoll@Sun.COM long K_FileLength32( FILE* i_fpFile )
926*12720SWyllys.Ingersoll@Sun.COM {
927*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
928*12720SWyllys.Ingersoll@Sun.COM     int iFileDescriptor = _fileno( i_fpFile );
929*12720SWyllys.Ingersoll@Sun.COM     struct _stat stStat;
930*12720SWyllys.Ingersoll@Sun.COM 
931*12720SWyllys.Ingersoll@Sun.COM     if ( _fstat(iFileDescriptor, &stStat) != 0)
932*12720SWyllys.Ingersoll@Sun.COM     {
933*12720SWyllys.Ingersoll@Sun.COM         // error
934*12720SWyllys.Ingersoll@Sun.COM         return -1L;
935*12720SWyllys.Ingersoll@Sun.COM     }
936*12720SWyllys.Ingersoll@Sun.COM 
937*12720SWyllys.Ingersoll@Sun.COM #else
938*12720SWyllys.Ingersoll@Sun.COM     int iFileDescriptor = fileno( i_fpFile );
939*12720SWyllys.Ingersoll@Sun.COM     struct stat stStat;
940*12720SWyllys.Ingersoll@Sun.COM 
941*12720SWyllys.Ingersoll@Sun.COM     if ( fstat(iFileDescriptor, &stStat) != 0)
942*12720SWyllys.Ingersoll@Sun.COM     {
943*12720SWyllys.Ingersoll@Sun.COM         // error
944*12720SWyllys.Ingersoll@Sun.COM         return -1L;
945*12720SWyllys.Ingersoll@Sun.COM     }
946*12720SWyllys.Ingersoll@Sun.COM 
947*12720SWyllys.Ingersoll@Sun.COM #endif
948*12720SWyllys.Ingersoll@Sun.COM 
949*12720SWyllys.Ingersoll@Sun.COM     return stStat.st_size;
950*12720SWyllys.Ingersoll@Sun.COM }
951*12720SWyllys.Ingersoll@Sun.COM 
952*12720SWyllys.Ingersoll@Sun.COM 
953*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
954*12720SWyllys.Ingersoll@Sun.COM  * Function: K_StringCompareNoCase
955*12720SWyllys.Ingersoll@Sun.COM  *
956*12720SWyllys.Ingersoll@Sun.COM  * Description:
957*12720SWyllys.Ingersoll@Sun.COM  *  Compares the two given strings insensitive to case.
958*12720SWyllys.Ingersoll@Sun.COM  *
959*12720SWyllys.Ingersoll@Sun.COM  * Input
960*12720SWyllys.Ingersoll@Sun.COM  * -----
961*12720SWyllys.Ingersoll@Sun.COM  *    i_sString1       First string
962*12720SWyllys.Ingersoll@Sun.COM  *    i_sString2       Second string
963*12720SWyllys.Ingersoll@Sun.COM  *
964*12720SWyllys.Ingersoll@Sun.COM  * Output
965*12720SWyllys.Ingersoll@Sun.COM  * ------
966*12720SWyllys.Ingersoll@Sun.COM  *    (none)
967*12720SWyllys.Ingersoll@Sun.COM  *
968*12720SWyllys.Ingersoll@Sun.COM  * Return value        0 if identical, -1 if first string is less than second
969*12720SWyllys.Ingersoll@Sun.COM  *                     string, or 1 if first string is greater than second
970*12720SWyllys.Ingersoll@Sun.COM  *
971*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
972*12720SWyllys.Ingersoll@Sun.COM 
K_StringCompareNoCase(const char * i_sString1,const char * i_sString2)973*12720SWyllys.Ingersoll@Sun.COM int K_StringCompareNoCase( const char* i_sString1, const char* i_sString2 )
974*12720SWyllys.Ingersoll@Sun.COM {
975*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
976*12720SWyllys.Ingersoll@Sun.COM     return _stricmp( i_sString1, i_sString2 );
977*12720SWyllys.Ingersoll@Sun.COM #else
978*12720SWyllys.Ingersoll@Sun.COM     return strcasecmp( i_sString1, i_sString2 );
979*12720SWyllys.Ingersoll@Sun.COM #endif
980*12720SWyllys.Ingersoll@Sun.COM }
981*12720SWyllys.Ingersoll@Sun.COM 
982*12720SWyllys.Ingersoll@Sun.COM 
983*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
984*12720SWyllys.Ingersoll@Sun.COM  * Function: K_StringCompareNoCaseWide
985*12720SWyllys.Ingersoll@Sun.COM  *
986*12720SWyllys.Ingersoll@Sun.COM  * Description:
987*12720SWyllys.Ingersoll@Sun.COM  *  Compares the two given wide strings insensitive to case.
988*12720SWyllys.Ingersoll@Sun.COM  *
989*12720SWyllys.Ingersoll@Sun.COM  * Input
990*12720SWyllys.Ingersoll@Sun.COM  * -----
991*12720SWyllys.Ingersoll@Sun.COM  *    i_wsString1      First wide string
992*12720SWyllys.Ingersoll@Sun.COM  *    i_wsString2      Second wide string
993*12720SWyllys.Ingersoll@Sun.COM  *
994*12720SWyllys.Ingersoll@Sun.COM  * Output
995*12720SWyllys.Ingersoll@Sun.COM  * ------
996*12720SWyllys.Ingersoll@Sun.COM  *    (none)
997*12720SWyllys.Ingersoll@Sun.COM  *
998*12720SWyllys.Ingersoll@Sun.COM  * Return value        0 if identical, -1 if first string is less than second
999*12720SWyllys.Ingersoll@Sun.COM  *                     string, or 1 if first string is greater than second
1000*12720SWyllys.Ingersoll@Sun.COM  *
1001*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
1002*12720SWyllys.Ingersoll@Sun.COM 
K_StringCompareNoCaseWide(const wchar_t * i_wsString1,const wchar_t * i_wsString2)1003*12720SWyllys.Ingersoll@Sun.COM int K_StringCompareNoCaseWide( const wchar_t* i_wsString1, const wchar_t* i_wsString2 )
1004*12720SWyllys.Ingersoll@Sun.COM {
1005*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
1006*12720SWyllys.Ingersoll@Sun.COM     return _wcsicmp( i_wsString1, i_wsString2 );
1007*12720SWyllys.Ingersoll@Sun.COM #elif defined K_SOLARIS_PLATFORM
1008*12720SWyllys.Ingersoll@Sun.COM     return wscasecmp( i_wsString1, i_wsString2 );
1009*12720SWyllys.Ingersoll@Sun.COM #else
1010*12720SWyllys.Ingersoll@Sun.COM     return wcscasecmp( i_wsString1, i_wsString2 );
1011*12720SWyllys.Ingersoll@Sun.COM #endif
1012*12720SWyllys.Ingersoll@Sun.COM }
1013*12720SWyllys.Ingersoll@Sun.COM 
1014*12720SWyllys.Ingersoll@Sun.COM 
1015*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
1016*12720SWyllys.Ingersoll@Sun.COM  * Function: K_CreateDirectory
1017*12720SWyllys.Ingersoll@Sun.COM  *
1018*12720SWyllys.Ingersoll@Sun.COM  * Description:
1019*12720SWyllys.Ingersoll@Sun.COM  *  Creates a directory with the given path name.
1020*12720SWyllys.Ingersoll@Sun.COM  *
1021*12720SWyllys.Ingersoll@Sun.COM  * Input
1022*12720SWyllys.Ingersoll@Sun.COM  * -----
1023*12720SWyllys.Ingersoll@Sun.COM  *    i_sDirectoryName  Directory name
1024*12720SWyllys.Ingersoll@Sun.COM  *
1025*12720SWyllys.Ingersoll@Sun.COM  * Output
1026*12720SWyllys.Ingersoll@Sun.COM  * ------
1027*12720SWyllys.Ingersoll@Sun.COM  *    (none)
1028*12720SWyllys.Ingersoll@Sun.COM  *
1029*12720SWyllys.Ingersoll@Sun.COM  * Return value        0 on success, -1 on failure
1030*12720SWyllys.Ingersoll@Sun.COM  *
1031*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
1032*12720SWyllys.Ingersoll@Sun.COM 
K_CreateDirectory(const char * i_sDirectoryName)1033*12720SWyllys.Ingersoll@Sun.COM int K_CreateDirectory( const char* i_sDirectoryName )
1034*12720SWyllys.Ingersoll@Sun.COM {
1035*12720SWyllys.Ingersoll@Sun.COM     // TODO: make this build all parent directories as well.
1036*12720SWyllys.Ingersoll@Sun.COM 
1037*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
1038*12720SWyllys.Ingersoll@Sun.COM     if ( CreateDirectoryA( i_sDirectoryName, NULL ) )
1039*12720SWyllys.Ingersoll@Sun.COM     {
1040*12720SWyllys.Ingersoll@Sun.COM         return 0;
1041*12720SWyllys.Ingersoll@Sun.COM     }
1042*12720SWyllys.Ingersoll@Sun.COM     else
1043*12720SWyllys.Ingersoll@Sun.COM     {
1044*12720SWyllys.Ingersoll@Sun.COM         DWORD dwError = GetLastError();
1045*12720SWyllys.Ingersoll@Sun.COM         return ( dwError == ERROR_ALREADY_EXISTS ) ? 0 : (dwError ? dwError : -1);
1046*12720SWyllys.Ingersoll@Sun.COM     }
1047*12720SWyllys.Ingersoll@Sun.COM #else
1048*12720SWyllys.Ingersoll@Sun.COM     if ( mkdir( i_sDirectoryName, S_IRWXU ) == 0 )
1049*12720SWyllys.Ingersoll@Sun.COM     {
1050*12720SWyllys.Ingersoll@Sun.COM         return 0;
1051*12720SWyllys.Ingersoll@Sun.COM     }
1052*12720SWyllys.Ingersoll@Sun.COM     else
1053*12720SWyllys.Ingersoll@Sun.COM     {
1054*12720SWyllys.Ingersoll@Sun.COM         return ( errno == EEXIST ) ? 0 : (errno ? errno : -1);
1055*12720SWyllys.Ingersoll@Sun.COM     }
1056*12720SWyllys.Ingersoll@Sun.COM #endif
1057*12720SWyllys.Ingersoll@Sun.COM }
1058*12720SWyllys.Ingersoll@Sun.COM 
1059*12720SWyllys.Ingersoll@Sun.COM 
1060*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
1061*12720SWyllys.Ingersoll@Sun.COM  * Function: K_DeleteFile
1062*12720SWyllys.Ingersoll@Sun.COM  *
1063*12720SWyllys.Ingersoll@Sun.COM  * Description:
1064*12720SWyllys.Ingersoll@Sun.COM  *  Deletes the given file.
1065*12720SWyllys.Ingersoll@Sun.COM  *
1066*12720SWyllys.Ingersoll@Sun.COM  * Input
1067*12720SWyllys.Ingersoll@Sun.COM  * -----
1068*12720SWyllys.Ingersoll@Sun.COM  *    i_sFilename      Name of file to delete
1069*12720SWyllys.Ingersoll@Sun.COM  *
1070*12720SWyllys.Ingersoll@Sun.COM  * Output
1071*12720SWyllys.Ingersoll@Sun.COM  * ------
1072*12720SWyllys.Ingersoll@Sun.COM  *    (none)
1073*12720SWyllys.Ingersoll@Sun.COM  *
1074*12720SWyllys.Ingersoll@Sun.COM  * Return value        0 on success, errno on failure
1075*12720SWyllys.Ingersoll@Sun.COM  *
1076*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
1077*12720SWyllys.Ingersoll@Sun.COM 
K_DeleteFile(const char * i_sFilename)1078*12720SWyllys.Ingersoll@Sun.COM int K_DeleteFile( const char* i_sFilename )
1079*12720SWyllys.Ingersoll@Sun.COM {
1080*12720SWyllys.Ingersoll@Sun.COM     int bSuccess = 0;
1081*12720SWyllys.Ingersoll@Sun.COM 
1082*12720SWyllys.Ingersoll@Sun.COM     bSuccess =
1083*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
1084*12720SWyllys.Ingersoll@Sun.COM         _unlink(
1085*12720SWyllys.Ingersoll@Sun.COM #else
1086*12720SWyllys.Ingersoll@Sun.COM         unlink(
1087*12720SWyllys.Ingersoll@Sun.COM #endif
1088*12720SWyllys.Ingersoll@Sun.COM             i_sFilename ) == 0;
1089*12720SWyllys.Ingersoll@Sun.COM 
1090*12720SWyllys.Ingersoll@Sun.COM     return bSuccess ? 0 : errno;
1091*12720SWyllys.Ingersoll@Sun.COM }
1092*12720SWyllys.Ingersoll@Sun.COM 
1093*12720SWyllys.Ingersoll@Sun.COM 
1094*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
1095*12720SWyllys.Ingersoll@Sun.COM  * Function: K_ReadFile
1096*12720SWyllys.Ingersoll@Sun.COM  *
1097*12720SWyllys.Ingersoll@Sun.COM  * Description:
1098*12720SWyllys.Ingersoll@Sun.COM  *  Reads from the given file and passes the bytes read back to the output
1099*12720SWyllys.Ingersoll@Sun.COM  *  parameter.  The caller must deallocate o_ppFileData using free().
1100*12720SWyllys.Ingersoll@Sun.COM  *
1101*12720SWyllys.Ingersoll@Sun.COM  * Input
1102*12720SWyllys.Ingersoll@Sun.COM  * -----
1103*12720SWyllys.Ingersoll@Sun.COM  *    i_sFilename      Name of file from which to read
1104*12720SWyllys.Ingersoll@Sun.COM  *
1105*12720SWyllys.Ingersoll@Sun.COM  * Output
1106*12720SWyllys.Ingersoll@Sun.COM  * ------
1107*12720SWyllys.Ingersoll@Sun.COM  *    o_ppFileData     Pointer to bytes read
1108*12720SWyllys.Ingersoll@Sun.COM  *
1109*12720SWyllys.Ingersoll@Sun.COM  * Return value        Number of bytes read on success, -1 on failure
1110*12720SWyllys.Ingersoll@Sun.COM  *
1111*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
1112*12720SWyllys.Ingersoll@Sun.COM 
K_ReadFile(const char * i_sFilename,unsigned char ** o_ppFileData)1113*12720SWyllys.Ingersoll@Sun.COM int K_ReadFile( const char* i_sFilename, unsigned char** o_ppFileData )
1114*12720SWyllys.Ingersoll@Sun.COM {
1115*12720SWyllys.Ingersoll@Sun.COM     FILE* pFile = 0;
1116*12720SWyllys.Ingersoll@Sun.COM     long iFileSize = 0;
1117*12720SWyllys.Ingersoll@Sun.COM 
1118*12720SWyllys.Ingersoll@Sun.COM     if ( !i_sFilename || (strlen(i_sFilename) <= 0) || !o_ppFileData )
1119*12720SWyllys.Ingersoll@Sun.COM     {
1120*12720SWyllys.Ingersoll@Sun.COM         return -1;
1121*12720SWyllys.Ingersoll@Sun.COM     }
1122*12720SWyllys.Ingersoll@Sun.COM 
1123*12720SWyllys.Ingersoll@Sun.COM     *o_ppFileData = 0;
1124*12720SWyllys.Ingersoll@Sun.COM 
1125*12720SWyllys.Ingersoll@Sun.COM     // Open the file
1126*12720SWyllys.Ingersoll@Sun.COM 
1127*12720SWyllys.Ingersoll@Sun.COM     pFile = fopen( i_sFilename, "rb" );
1128*12720SWyllys.Ingersoll@Sun.COM     if ( !pFile )
1129*12720SWyllys.Ingersoll@Sun.COM     {
1130*12720SWyllys.Ingersoll@Sun.COM         return -1;
1131*12720SWyllys.Ingersoll@Sun.COM     }
1132*12720SWyllys.Ingersoll@Sun.COM 
1133*12720SWyllys.Ingersoll@Sun.COM     // Determine the file size
1134*12720SWyllys.Ingersoll@Sun.COM 
1135*12720SWyllys.Ingersoll@Sun.COM     if ( fseek( pFile, 0, SEEK_END ) )
1136*12720SWyllys.Ingersoll@Sun.COM     {
1137*12720SWyllys.Ingersoll@Sun.COM         (void) fclose( pFile );
1138*12720SWyllys.Ingersoll@Sun.COM         return -1;
1139*12720SWyllys.Ingersoll@Sun.COM     }
1140*12720SWyllys.Ingersoll@Sun.COM 
1141*12720SWyllys.Ingersoll@Sun.COM     iFileSize = ftell( pFile );
1142*12720SWyllys.Ingersoll@Sun.COM     if ( iFileSize < 0 )
1143*12720SWyllys.Ingersoll@Sun.COM     {
1144*12720SWyllys.Ingersoll@Sun.COM         (void) fclose( pFile );
1145*12720SWyllys.Ingersoll@Sun.COM         return -1;
1146*12720SWyllys.Ingersoll@Sun.COM     }
1147*12720SWyllys.Ingersoll@Sun.COM     else if ( iFileSize == 0 )
1148*12720SWyllys.Ingersoll@Sun.COM     {
1149*12720SWyllys.Ingersoll@Sun.COM         (void) fclose( pFile );
1150*12720SWyllys.Ingersoll@Sun.COM         return 0;
1151*12720SWyllys.Ingersoll@Sun.COM     }
1152*12720SWyllys.Ingersoll@Sun.COM 
1153*12720SWyllys.Ingersoll@Sun.COM     if ( fseek( pFile, 0, SEEK_SET ) )
1154*12720SWyllys.Ingersoll@Sun.COM     {
1155*12720SWyllys.Ingersoll@Sun.COM         (void) fclose( pFile );
1156*12720SWyllys.Ingersoll@Sun.COM         return -1;
1157*12720SWyllys.Ingersoll@Sun.COM     }
1158*12720SWyllys.Ingersoll@Sun.COM 
1159*12720SWyllys.Ingersoll@Sun.COM     *o_ppFileData = (unsigned char*)malloc( iFileSize );
1160*12720SWyllys.Ingersoll@Sun.COM     if ( !*o_ppFileData )
1161*12720SWyllys.Ingersoll@Sun.COM     {
1162*12720SWyllys.Ingersoll@Sun.COM         // Out of memory.
1163*12720SWyllys.Ingersoll@Sun.COM         (void) fclose( pFile );
1164*12720SWyllys.Ingersoll@Sun.COM         return -1;
1165*12720SWyllys.Ingersoll@Sun.COM     }
1166*12720SWyllys.Ingersoll@Sun.COM 
1167*12720SWyllys.Ingersoll@Sun.COM     if ( iFileSize != (long)fread( *o_ppFileData, 1, iFileSize, pFile ) )
1168*12720SWyllys.Ingersoll@Sun.COM     {
1169*12720SWyllys.Ingersoll@Sun.COM         free( *o_ppFileData );
1170*12720SWyllys.Ingersoll@Sun.COM         *o_ppFileData = 0;
1171*12720SWyllys.Ingersoll@Sun.COM         (void) fclose( pFile );
1172*12720SWyllys.Ingersoll@Sun.COM         return -1;
1173*12720SWyllys.Ingersoll@Sun.COM     }
1174*12720SWyllys.Ingersoll@Sun.COM 
1175*12720SWyllys.Ingersoll@Sun.COM     (void) fclose( pFile );
1176*12720SWyllys.Ingersoll@Sun.COM 
1177*12720SWyllys.Ingersoll@Sun.COM     return iFileSize;
1178*12720SWyllys.Ingersoll@Sun.COM }
1179*12720SWyllys.Ingersoll@Sun.COM 
1180*12720SWyllys.Ingersoll@Sun.COM 
1181*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
1182*12720SWyllys.Ingersoll@Sun.COM  * Function: K_ReadFileString
1183*12720SWyllys.Ingersoll@Sun.COM  *
1184*12720SWyllys.Ingersoll@Sun.COM  * Description:
1185*12720SWyllys.Ingersoll@Sun.COM  *  Reads from the given file and passes the bytes read back to the output
1186*12720SWyllys.Ingersoll@Sun.COM  *  parameter, appending these bytes with a null terminator.  There is no
1187*12720SWyllys.Ingersoll@Sun.COM  *  guarantee that there are no non-text characters in the returned "string".
1188*12720SWyllys.Ingersoll@Sun.COM  *  The caller must deallocate o_ppFileData using free().
1189*12720SWyllys.Ingersoll@Sun.COM  *
1190*12720SWyllys.Ingersoll@Sun.COM  * Input
1191*12720SWyllys.Ingersoll@Sun.COM  * -----
1192*12720SWyllys.Ingersoll@Sun.COM  *    i_sFilename      Name of file from which to read
1193*12720SWyllys.Ingersoll@Sun.COM  *
1194*12720SWyllys.Ingersoll@Sun.COM  * Output
1195*12720SWyllys.Ingersoll@Sun.COM  * ------
1196*12720SWyllys.Ingersoll@Sun.COM  *    o_psFileDataString     Pointer to bytes read
1197*12720SWyllys.Ingersoll@Sun.COM  *
1198*12720SWyllys.Ingersoll@Sun.COM  * Return value        Number of bytes read (including null terminator) on
1199*12720SWyllys.Ingersoll@Sun.COM  *                     success (0 if file is empty), -1 on failure
1200*12720SWyllys.Ingersoll@Sun.COM  *
1201*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
1202*12720SWyllys.Ingersoll@Sun.COM 
K_ReadFileString(const char * i_sFilename,char ** o_psFileDataString)1203*12720SWyllys.Ingersoll@Sun.COM int K_ReadFileString( const char* i_sFilename, char** o_psFileDataString )
1204*12720SWyllys.Ingersoll@Sun.COM {
1205*12720SWyllys.Ingersoll@Sun.COM     unsigned char* pFileData = 0;
1206*12720SWyllys.Ingersoll@Sun.COM     int iFileSize = 0;
1207*12720SWyllys.Ingersoll@Sun.COM 
1208*12720SWyllys.Ingersoll@Sun.COM     *o_psFileDataString = 0;
1209*12720SWyllys.Ingersoll@Sun.COM 
1210*12720SWyllys.Ingersoll@Sun.COM     iFileSize = K_ReadFile( i_sFilename, &pFileData );
1211*12720SWyllys.Ingersoll@Sun.COM 
1212*12720SWyllys.Ingersoll@Sun.COM     if ( iFileSize <= 0 )
1213*12720SWyllys.Ingersoll@Sun.COM     {
1214*12720SWyllys.Ingersoll@Sun.COM         return iFileSize;
1215*12720SWyllys.Ingersoll@Sun.COM     }
1216*12720SWyllys.Ingersoll@Sun.COM 
1217*12720SWyllys.Ingersoll@Sun.COM     *o_psFileDataString = (char*)malloc( iFileSize+1 );
1218*12720SWyllys.Ingersoll@Sun.COM 
1219*12720SWyllys.Ingersoll@Sun.COM     if ( !*o_psFileDataString )
1220*12720SWyllys.Ingersoll@Sun.COM     {
1221*12720SWyllys.Ingersoll@Sun.COM         // Out of memory.
1222*12720SWyllys.Ingersoll@Sun.COM         if ( pFileData )
1223*12720SWyllys.Ingersoll@Sun.COM         {
1224*12720SWyllys.Ingersoll@Sun.COM             free( pFileData );
1225*12720SWyllys.Ingersoll@Sun.COM         }
1226*12720SWyllys.Ingersoll@Sun.COM         return -1;
1227*12720SWyllys.Ingersoll@Sun.COM     }
1228*12720SWyllys.Ingersoll@Sun.COM 
1229*12720SWyllys.Ingersoll@Sun.COM     memcpy( *o_psFileDataString, pFileData, iFileSize );
1230*12720SWyllys.Ingersoll@Sun.COM 
1231*12720SWyllys.Ingersoll@Sun.COM     (*o_psFileDataString)[iFileSize] = '\0';
1232*12720SWyllys.Ingersoll@Sun.COM 
1233*12720SWyllys.Ingersoll@Sun.COM     if ( pFileData )
1234*12720SWyllys.Ingersoll@Sun.COM     {
1235*12720SWyllys.Ingersoll@Sun.COM         free( pFileData );
1236*12720SWyllys.Ingersoll@Sun.COM     }
1237*12720SWyllys.Ingersoll@Sun.COM 
1238*12720SWyllys.Ingersoll@Sun.COM     return iFileSize+1;
1239*12720SWyllys.Ingersoll@Sun.COM }
1240*12720SWyllys.Ingersoll@Sun.COM 
1241*12720SWyllys.Ingersoll@Sun.COM 
1242*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
1243*12720SWyllys.Ingersoll@Sun.COM  * Function: K_WriteFile
1244*12720SWyllys.Ingersoll@Sun.COM  *
1245*12720SWyllys.Ingersoll@Sun.COM  * Description:
1246*12720SWyllys.Ingersoll@Sun.COM  *  Writes the given bytes to the given file.
1247*12720SWyllys.Ingersoll@Sun.COM  *
1248*12720SWyllys.Ingersoll@Sun.COM  * Input
1249*12720SWyllys.Ingersoll@Sun.COM  * -----
1250*12720SWyllys.Ingersoll@Sun.COM  *    i_sFilename      Name of file to which to write
1251*12720SWyllys.Ingersoll@Sun.COM  *    i_pFileData      Bytes to write
1252*12720SWyllys.Ingersoll@Sun.COM  *    i_iFileDataSize  Number of bytes to write
1253*12720SWyllys.Ingersoll@Sun.COM  *
1254*12720SWyllys.Ingersoll@Sun.COM  * Output
1255*12720SWyllys.Ingersoll@Sun.COM  * ------
1256*12720SWyllys.Ingersoll@Sun.COM  *    (none)
1257*12720SWyllys.Ingersoll@Sun.COM  *
1258*12720SWyllys.Ingersoll@Sun.COM  * Return value        0 on success, errno or -1 (generic error) on failure
1259*12720SWyllys.Ingersoll@Sun.COM  *
1260*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
1261*12720SWyllys.Ingersoll@Sun.COM 
K_WriteFile(const char * i_sFilename,const unsigned char * i_pFileData,int i_iFileDataSize)1262*12720SWyllys.Ingersoll@Sun.COM int K_WriteFile( const char* i_sFilename, const unsigned char* i_pFileData, int i_iFileDataSize )
1263*12720SWyllys.Ingersoll@Sun.COM {
1264*12720SWyllys.Ingersoll@Sun.COM     FILE* pFile = 0;
1265*12720SWyllys.Ingersoll@Sun.COM 
1266*12720SWyllys.Ingersoll@Sun.COM     if ( !i_sFilename || (strlen(i_sFilename) <= 0) || (!i_pFileData && (i_iFileDataSize > 0)) || (i_iFileDataSize < 0) )
1267*12720SWyllys.Ingersoll@Sun.COM     {
1268*12720SWyllys.Ingersoll@Sun.COM         return -1;
1269*12720SWyllys.Ingersoll@Sun.COM     }
1270*12720SWyllys.Ingersoll@Sun.COM 
1271*12720SWyllys.Ingersoll@Sun.COM     pFile = fopen( i_sFilename, "wb" );
1272*12720SWyllys.Ingersoll@Sun.COM     if ( !pFile )
1273*12720SWyllys.Ingersoll@Sun.COM     {
1274*12720SWyllys.Ingersoll@Sun.COM         int iError = errno;
1275*12720SWyllys.Ingersoll@Sun.COM         return (iError != 0) ? iError : -1;
1276*12720SWyllys.Ingersoll@Sun.COM     }
1277*12720SWyllys.Ingersoll@Sun.COM 
1278*12720SWyllys.Ingersoll@Sun.COM     if ( i_iFileDataSize > 0 )
1279*12720SWyllys.Ingersoll@Sun.COM     {
1280*12720SWyllys.Ingersoll@Sun.COM         if ( i_iFileDataSize != (int)fwrite( i_pFileData, 1, i_iFileDataSize, pFile ) )
1281*12720SWyllys.Ingersoll@Sun.COM         {
1282*12720SWyllys.Ingersoll@Sun.COM             int iError = ferror( pFile );
1283*12720SWyllys.Ingersoll@Sun.COM             (void) fclose( pFile );
1284*12720SWyllys.Ingersoll@Sun.COM             return (iError != 0) ? iError : -1;
1285*12720SWyllys.Ingersoll@Sun.COM         }
1286*12720SWyllys.Ingersoll@Sun.COM     }
1287*12720SWyllys.Ingersoll@Sun.COM 
1288*12720SWyllys.Ingersoll@Sun.COM     (void) fclose( pFile );
1289*12720SWyllys.Ingersoll@Sun.COM 
1290*12720SWyllys.Ingersoll@Sun.COM     return 0;
1291*12720SWyllys.Ingersoll@Sun.COM }
1292*12720SWyllys.Ingersoll@Sun.COM 
1293*12720SWyllys.Ingersoll@Sun.COM 
1294*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
1295*12720SWyllys.Ingersoll@Sun.COM  * Function: K_WriteFileString
1296*12720SWyllys.Ingersoll@Sun.COM  *
1297*12720SWyllys.Ingersoll@Sun.COM  * Description:
1298*12720SWyllys.Ingersoll@Sun.COM  *  Writes the given null-terminated bytes to the given file.  The null
1299*12720SWyllys.Ingersoll@Sun.COM  *  terminator itself is not written to the file.
1300*12720SWyllys.Ingersoll@Sun.COM  *
1301*12720SWyllys.Ingersoll@Sun.COM  * Input
1302*12720SWyllys.Ingersoll@Sun.COM  * -----
1303*12720SWyllys.Ingersoll@Sun.COM  *    i_sFilename      Name of file to which to write
1304*12720SWyllys.Ingersoll@Sun.COM  *    i_sFileData      Bytes to write
1305*12720SWyllys.Ingersoll@Sun.COM  *
1306*12720SWyllys.Ingersoll@Sun.COM  * Output
1307*12720SWyllys.Ingersoll@Sun.COM  * ------
1308*12720SWyllys.Ingersoll@Sun.COM  *    (none)
1309*12720SWyllys.Ingersoll@Sun.COM  *
1310*12720SWyllys.Ingersoll@Sun.COM  * Return value        0 on success, errno or -1 (generic error) on failure
1311*12720SWyllys.Ingersoll@Sun.COM  *
1312*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
1313*12720SWyllys.Ingersoll@Sun.COM 
K_WriteFileString(const char * i_sFilename,const char * i_sFileData)1314*12720SWyllys.Ingersoll@Sun.COM int K_WriteFileString( const char* i_sFilename, const char* i_sFileData )
1315*12720SWyllys.Ingersoll@Sun.COM {
1316*12720SWyllys.Ingersoll@Sun.COM     if ( !i_sFilename || (strlen(i_sFilename) <= 0) || !i_sFileData || (strlen(i_sFileData) <= 0) )
1317*12720SWyllys.Ingersoll@Sun.COM     {
1318*12720SWyllys.Ingersoll@Sun.COM         return -1;
1319*12720SWyllys.Ingersoll@Sun.COM     }
1320*12720SWyllys.Ingersoll@Sun.COM 
1321*12720SWyllys.Ingersoll@Sun.COM     return K_WriteFile( i_sFilename, (const unsigned char*)i_sFileData, strlen(i_sFileData) );
1322*12720SWyllys.Ingersoll@Sun.COM }
1323*12720SWyllys.Ingersoll@Sun.COM 
1324*12720SWyllys.Ingersoll@Sun.COM 
1325*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
1326*12720SWyllys.Ingersoll@Sun.COM  * Function: K_FileExists
1327*12720SWyllys.Ingersoll@Sun.COM  *
1328*12720SWyllys.Ingersoll@Sun.COM  * Description:
1329*12720SWyllys.Ingersoll@Sun.COM  *  Checks to see whehter the given file exists.
1330*12720SWyllys.Ingersoll@Sun.COM  *
1331*12720SWyllys.Ingersoll@Sun.COM  * Input
1332*12720SWyllys.Ingersoll@Sun.COM  * -----
1333*12720SWyllys.Ingersoll@Sun.COM  *    i_sFilename      Name of file to check
1334*12720SWyllys.Ingersoll@Sun.COM  *
1335*12720SWyllys.Ingersoll@Sun.COM  * Output
1336*12720SWyllys.Ingersoll@Sun.COM  * ------
1337*12720SWyllys.Ingersoll@Sun.COM  *    (none)
1338*12720SWyllys.Ingersoll@Sun.COM  *
1339*12720SWyllys.Ingersoll@Sun.COM  * Return value        1 if file exists, 0 if not, -1 on failure
1340*12720SWyllys.Ingersoll@Sun.COM  *
1341*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
1342*12720SWyllys.Ingersoll@Sun.COM 
K_FileExists(const char * i_sFilename)1343*12720SWyllys.Ingersoll@Sun.COM int K_FileExists( const char* i_sFilename )
1344*12720SWyllys.Ingersoll@Sun.COM {
1345*12720SWyllys.Ingersoll@Sun.COM     FILE* pFile = 0;
1346*12720SWyllys.Ingersoll@Sun.COM 
1347*12720SWyllys.Ingersoll@Sun.COM     if ( !i_sFilename || (strlen(i_sFilename) <= 0) )
1348*12720SWyllys.Ingersoll@Sun.COM     {
1349*12720SWyllys.Ingersoll@Sun.COM         return -1;
1350*12720SWyllys.Ingersoll@Sun.COM     }
1351*12720SWyllys.Ingersoll@Sun.COM 
1352*12720SWyllys.Ingersoll@Sun.COM     pFile = fopen( i_sFilename, "r+" );
1353*12720SWyllys.Ingersoll@Sun.COM 
1354*12720SWyllys.Ingersoll@Sun.COM     if ( !pFile )
1355*12720SWyllys.Ingersoll@Sun.COM     {
1356*12720SWyllys.Ingersoll@Sun.COM         if ( errno == ENOENT )
1357*12720SWyllys.Ingersoll@Sun.COM         {
1358*12720SWyllys.Ingersoll@Sun.COM             return 0;
1359*12720SWyllys.Ingersoll@Sun.COM         }
1360*12720SWyllys.Ingersoll@Sun.COM 
1361*12720SWyllys.Ingersoll@Sun.COM         return -1;
1362*12720SWyllys.Ingersoll@Sun.COM     }
1363*12720SWyllys.Ingersoll@Sun.COM 
1364*12720SWyllys.Ingersoll@Sun.COM     (void) fclose( pFile );
1365*12720SWyllys.Ingersoll@Sun.COM 
1366*12720SWyllys.Ingersoll@Sun.COM     return 1;
1367*12720SWyllys.Ingersoll@Sun.COM }
1368*12720SWyllys.Ingersoll@Sun.COM 
1369*12720SWyllys.Ingersoll@Sun.COM 
1370*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
1371*12720SWyllys.Ingersoll@Sun.COM  * Function: K_CopyFile
1372*12720SWyllys.Ingersoll@Sun.COM  *
1373*12720SWyllys.Ingersoll@Sun.COM  * Description:
1374*12720SWyllys.Ingersoll@Sun.COM  *  Reads from the given source file and writes these bytes to the given
1375*12720SWyllys.Ingersoll@Sun.COM  *  destination file.
1376*12720SWyllys.Ingersoll@Sun.COM  *
1377*12720SWyllys.Ingersoll@Sun.COM  * Input
1378*12720SWyllys.Ingersoll@Sun.COM  * -----
1379*12720SWyllys.Ingersoll@Sun.COM  *    i_sSrcFilename   Name of file from which to read
1380*12720SWyllys.Ingersoll@Sun.COM  *    i_sDestFilename  Name of file to which to write
1381*12720SWyllys.Ingersoll@Sun.COM  *
1382*12720SWyllys.Ingersoll@Sun.COM  * Output
1383*12720SWyllys.Ingersoll@Sun.COM  * ------
1384*12720SWyllys.Ingersoll@Sun.COM  *    o_pbFileExists   Non-zero if the destination file already exists
1385*12720SWyllys.Ingersoll@Sun.COM  *
1386*12720SWyllys.Ingersoll@Sun.COM  * Return value        0 on success, errno or -1 (generic error) on failure
1387*12720SWyllys.Ingersoll@Sun.COM  *
1388*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
1389*12720SWyllys.Ingersoll@Sun.COM 
K_CopyFile(const char * i_sSrcFilename,const char * i_sDestFilename,int * o_pbFileExists)1390*12720SWyllys.Ingersoll@Sun.COM int K_CopyFile( const char* i_sSrcFilename, const char* i_sDestFilename, int* o_pbFileExists )
1391*12720SWyllys.Ingersoll@Sun.COM {
1392*12720SWyllys.Ingersoll@Sun.COM     unsigned char* pFileData = 0;
1393*12720SWyllys.Ingersoll@Sun.COM     int iFileSize = 0;
1394*12720SWyllys.Ingersoll@Sun.COM     int iError, iFileExists;
1395*12720SWyllys.Ingersoll@Sun.COM 
1396*12720SWyllys.Ingersoll@Sun.COM     if ( !i_sSrcFilename || (strlen(i_sSrcFilename) <= 0)
1397*12720SWyllys.Ingersoll@Sun.COM          || !i_sDestFilename || (strlen(i_sDestFilename) <= 0)
1398*12720SWyllys.Ingersoll@Sun.COM          || !o_pbFileExists )
1399*12720SWyllys.Ingersoll@Sun.COM     {
1400*12720SWyllys.Ingersoll@Sun.COM         return -1;
1401*12720SWyllys.Ingersoll@Sun.COM     }
1402*12720SWyllys.Ingersoll@Sun.COM 
1403*12720SWyllys.Ingersoll@Sun.COM     *o_pbFileExists = 0;
1404*12720SWyllys.Ingersoll@Sun.COM 
1405*12720SWyllys.Ingersoll@Sun.COM     iFileExists = K_FileExists( i_sDestFilename );
1406*12720SWyllys.Ingersoll@Sun.COM 
1407*12720SWyllys.Ingersoll@Sun.COM     if ( iFileExists < 0 )
1408*12720SWyllys.Ingersoll@Sun.COM     {
1409*12720SWyllys.Ingersoll@Sun.COM         iError = errno;
1410*12720SWyllys.Ingersoll@Sun.COM         return (iError == 0) ? -1 : iError;
1411*12720SWyllys.Ingersoll@Sun.COM     }
1412*12720SWyllys.Ingersoll@Sun.COM     else if ( iFileExists > 0 )
1413*12720SWyllys.Ingersoll@Sun.COM     {
1414*12720SWyllys.Ingersoll@Sun.COM         *o_pbFileExists = 1;
1415*12720SWyllys.Ingersoll@Sun.COM         return -1;
1416*12720SWyllys.Ingersoll@Sun.COM     }
1417*12720SWyllys.Ingersoll@Sun.COM 
1418*12720SWyllys.Ingersoll@Sun.COM     iFileSize = K_ReadFile( i_sSrcFilename, &pFileData );
1419*12720SWyllys.Ingersoll@Sun.COM     if ( iFileSize < 0 )
1420*12720SWyllys.Ingersoll@Sun.COM     {
1421*12720SWyllys.Ingersoll@Sun.COM         iError = errno;
1422*12720SWyllys.Ingersoll@Sun.COM         return (iError == 0) ? -1 : iError;
1423*12720SWyllys.Ingersoll@Sun.COM     }
1424*12720SWyllys.Ingersoll@Sun.COM 
1425*12720SWyllys.Ingersoll@Sun.COM     iError = K_WriteFile( i_sDestFilename, pFileData, iFileSize );
1426*12720SWyllys.Ingersoll@Sun.COM 
1427*12720SWyllys.Ingersoll@Sun.COM     if ( pFileData )
1428*12720SWyllys.Ingersoll@Sun.COM     {
1429*12720SWyllys.Ingersoll@Sun.COM         free( pFileData );
1430*12720SWyllys.Ingersoll@Sun.COM     }
1431*12720SWyllys.Ingersoll@Sun.COM 
1432*12720SWyllys.Ingersoll@Sun.COM     return iError;
1433*12720SWyllys.Ingersoll@Sun.COM }
1434*12720SWyllys.Ingersoll@Sun.COM 
1435*12720SWyllys.Ingersoll@Sun.COM 
1436*12720SWyllys.Ingersoll@Sun.COM #ifdef K_LINUX_PLATFORM
fts_compare(const FTSENT ** i_ppF1,const FTSENT ** i_ppF2)1437*12720SWyllys.Ingersoll@Sun.COM static int fts_compare( const FTSENT** i_ppF1, const FTSENT** i_ppF2 )
1438*12720SWyllys.Ingersoll@Sun.COM {
1439*12720SWyllys.Ingersoll@Sun.COM     return strcmp( (*i_ppF1)->fts_name, (*i_ppF2)->fts_name );
1440*12720SWyllys.Ingersoll@Sun.COM }
1441*12720SWyllys.Ingersoll@Sun.COM #else
1442*12720SWyllys.Ingersoll@Sun.COM /*
1443*12720SWyllys.Ingersoll@Sun.COM  * Directory traversal code is not yet available for Solaris.
1444*12720SWyllys.Ingersoll@Sun.COM  * If such code will need to be written, then it will probably use ftw.h.
1445*12720SWyllys.Ingersoll@Sun.COM  */
1446*12720SWyllys.Ingersoll@Sun.COM #endif
1447*12720SWyllys.Ingersoll@Sun.COM 
1448*12720SWyllys.Ingersoll@Sun.COM 
1449*12720SWyllys.Ingersoll@Sun.COM /*
1450*12720SWyllys.Ingersoll@Sun.COM  *  TODO:  Set up functions for platform-specific find-file operations to
1451*12720SWyllys.Ingersoll@Sun.COM  *  help clean up the code below.
1452*12720SWyllys.Ingersoll@Sun.COM  */
1453*12720SWyllys.Ingersoll@Sun.COM 
1454*12720SWyllys.Ingersoll@Sun.COM typedef struct K_FindInfo
1455*12720SWyllys.Ingersoll@Sun.COM {
1456*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
1457*12720SWyllys.Ingersoll@Sun.COM     struct _finddata_t m_stFindData;
1458*12720SWyllys.Ingersoll@Sun.COM     long m_hFile;
1459*12720SWyllys.Ingersoll@Sun.COM #elif defined K_LINUX_PLATFORM
1460*12720SWyllys.Ingersoll@Sun.COM     FTS* m_pFTS;
1461*12720SWyllys.Ingersoll@Sun.COM     FTSENT* m_pFTSENT;
1462*12720SWyllys.Ingersoll@Sun.COM #else
1463*12720SWyllys.Ingersoll@Sun.COM /*
1464*12720SWyllys.Ingersoll@Sun.COM  * Directory traversal code is not yet available for Solaris.
1465*12720SWyllys.Ingersoll@Sun.COM  * If such code will need to be written, then it will probably use ftw.h.
1466*12720SWyllys.Ingersoll@Sun.COM  */
1467*12720SWyllys.Ingersoll@Sun.COM     int unused;
1468*12720SWyllys.Ingersoll@Sun.COM #endif
1469*12720SWyllys.Ingersoll@Sun.COM } K_FindInfo;
1470*12720SWyllys.Ingersoll@Sun.COM 
1471*12720SWyllys.Ingersoll@Sun.COM // Memory for filename is held in i_pFindInfo.
K_GetFilenameFromInfo(const K_FindInfo * i_pFindInfo)1472*12720SWyllys.Ingersoll@Sun.COM const char* K_GetFilenameFromInfo( const K_FindInfo* i_pFindInfo )
1473*12720SWyllys.Ingersoll@Sun.COM {
1474*12720SWyllys.Ingersoll@Sun.COM     if( !i_pFindInfo )
1475*12720SWyllys.Ingersoll@Sun.COM     {
1476*12720SWyllys.Ingersoll@Sun.COM         return 0;
1477*12720SWyllys.Ingersoll@Sun.COM     }
1478*12720SWyllys.Ingersoll@Sun.COM 
1479*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
1480*12720SWyllys.Ingersoll@Sun.COM     return i_pFindInfo->m_stFindData.name;
1481*12720SWyllys.Ingersoll@Sun.COM #elif defined K_LINUX_PLATFORM
1482*12720SWyllys.Ingersoll@Sun.COM     return i_pFindInfo->m_pFTSENT->fts_name;
1483*12720SWyllys.Ingersoll@Sun.COM #else
1484*12720SWyllys.Ingersoll@Sun.COM /*
1485*12720SWyllys.Ingersoll@Sun.COM  * Directory traversal code is not yet available for Solaris.
1486*12720SWyllys.Ingersoll@Sun.COM  * If such code will need to be written, then it will probably use ftw.h.
1487*12720SWyllys.Ingersoll@Sun.COM  */
1488*12720SWyllys.Ingersoll@Sun.COM     FATAL_ASSERT( 0 );
1489*12720SWyllys.Ingersoll@Sun.COM     return 0;
1490*12720SWyllys.Ingersoll@Sun.COM #endif
1491*12720SWyllys.Ingersoll@Sun.COM }
1492*12720SWyllys.Ingersoll@Sun.COM 
1493*12720SWyllys.Ingersoll@Sun.COM // Forward declarations
1494*12720SWyllys.Ingersoll@Sun.COM int K_FindFileNext( K_FindInfo* io_pFindInfo );
1495*12720SWyllys.Ingersoll@Sun.COM void K_FindFileClose( K_FindInfo* io_pFindInfo );
1496*12720SWyllys.Ingersoll@Sun.COM 
1497*12720SWyllys.Ingersoll@Sun.COM // Returns 0 if successful, 1 if not found, -1 if error.
1498*12720SWyllys.Ingersoll@Sun.COM // If not error, K_FindFileClose must be called.
1499*12720SWyllys.Ingersoll@Sun.COM // o_pFindInfo must not be null.
K_FindFileFirst(const char * i_sDirectoryName,K_FindInfo * o_pFindInfo)1500*12720SWyllys.Ingersoll@Sun.COM int K_FindFileFirst( const char* i_sDirectoryName, K_FindInfo* o_pFindInfo )
1501*12720SWyllys.Ingersoll@Sun.COM {
1502*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
1503*12720SWyllys.Ingersoll@Sun.COM     char* sSearchString = 0;
1504*12720SWyllys.Ingersoll@Sun.COM     int iSearchStringIndex = 0;
1505*12720SWyllys.Ingersoll@Sun.COM #endif
1506*12720SWyllys.Ingersoll@Sun.COM 
1507*12720SWyllys.Ingersoll@Sun.COM     if ( !i_sDirectoryName || (strlen(i_sDirectoryName) <= 0) || !o_pFindInfo )
1508*12720SWyllys.Ingersoll@Sun.COM     {
1509*12720SWyllys.Ingersoll@Sun.COM         return -1;
1510*12720SWyllys.Ingersoll@Sun.COM     }
1511*12720SWyllys.Ingersoll@Sun.COM 
1512*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
1513*12720SWyllys.Ingersoll@Sun.COM     memset( o_pFindInfo, 0, sizeof(K_FindInfo) );
1514*12720SWyllys.Ingersoll@Sun.COM 
1515*12720SWyllys.Ingersoll@Sun.COM     iSearchStringIndex = strlen(i_sDirectoryName);
1516*12720SWyllys.Ingersoll@Sun.COM     if ( i_sDirectoryName[iSearchStringIndex-1] == PATH_SEPARATOR )
1517*12720SWyllys.Ingersoll@Sun.COM     {
1518*12720SWyllys.Ingersoll@Sun.COM         iSearchStringIndex += 2;
1519*12720SWyllys.Ingersoll@Sun.COM     }
1520*12720SWyllys.Ingersoll@Sun.COM     else
1521*12720SWyllys.Ingersoll@Sun.COM     {
1522*12720SWyllys.Ingersoll@Sun.COM         iSearchStringIndex += 3;
1523*12720SWyllys.Ingersoll@Sun.COM     }
1524*12720SWyllys.Ingersoll@Sun.COM 
1525*12720SWyllys.Ingersoll@Sun.COM     sSearchString = (char*)calloc( iSearchStringIndex, 1 );
1526*12720SWyllys.Ingersoll@Sun.COM     if ( !sSearchString )
1527*12720SWyllys.Ingersoll@Sun.COM     {
1528*12720SWyllys.Ingersoll@Sun.COM         return -1;
1529*12720SWyllys.Ingersoll@Sun.COM     }
1530*12720SWyllys.Ingersoll@Sun.COM 
1531*12720SWyllys.Ingersoll@Sun.COM     strcpy( sSearchString, i_sDirectoryName );
1532*12720SWyllys.Ingersoll@Sun.COM     iSearchStringIndex--;
1533*12720SWyllys.Ingersoll@Sun.COM     sSearchString[iSearchStringIndex] = '\0';
1534*12720SWyllys.Ingersoll@Sun.COM     iSearchStringIndex--;
1535*12720SWyllys.Ingersoll@Sun.COM     sSearchString[iSearchStringIndex] = '*';
1536*12720SWyllys.Ingersoll@Sun.COM     iSearchStringIndex--;
1537*12720SWyllys.Ingersoll@Sun.COM     sSearchString[iSearchStringIndex] = PATH_SEPARATOR;
1538*12720SWyllys.Ingersoll@Sun.COM 
1539*12720SWyllys.Ingersoll@Sun.COM     o_pFindInfo->m_hFile = _findfirst( sSearchString, &o_pFindInfo->m_stFindData );
1540*12720SWyllys.Ingersoll@Sun.COM     free( sSearchString );
1541*12720SWyllys.Ingersoll@Sun.COM     if ( o_pFindInfo->m_hFile == -1 )
1542*12720SWyllys.Ingersoll@Sun.COM     {
1543*12720SWyllys.Ingersoll@Sun.COM         if ( errno == ENOENT )
1544*12720SWyllys.Ingersoll@Sun.COM         {
1545*12720SWyllys.Ingersoll@Sun.COM             return 1;
1546*12720SWyllys.Ingersoll@Sun.COM         }
1547*12720SWyllys.Ingersoll@Sun.COM         else
1548*12720SWyllys.Ingersoll@Sun.COM         {
1549*12720SWyllys.Ingersoll@Sun.COM             return -1;
1550*12720SWyllys.Ingersoll@Sun.COM         }
1551*12720SWyllys.Ingersoll@Sun.COM     }
1552*12720SWyllys.Ingersoll@Sun.COM #elif defined K_LINUX_PLATFORM
1553*12720SWyllys.Ingersoll@Sun.COM     memset( o_pFindInfo, 0, sizeof(K_FindInfo) );
1554*12720SWyllys.Ingersoll@Sun.COM 
1555*12720SWyllys.Ingersoll@Sun.COM     o_pFindInfo->m_pFTS = fts_open( aPath, FTS_PHYSICAL | FTS_NOSTAT, fts_compare );
1556*12720SWyllys.Ingersoll@Sun.COM     if ( !o_pFindInfo->m_pFTS )
1557*12720SWyllys.Ingersoll@Sun.COM     {
1558*12720SWyllys.Ingersoll@Sun.COM         return -1;
1559*12720SWyllys.Ingersoll@Sun.COM     }
1560*12720SWyllys.Ingersoll@Sun.COM 
1561*12720SWyllys.Ingersoll@Sun.COM     o_pFindInfo->m_pFTSENT = fts_read( o_pFindInfo->m_pFTS );
1562*12720SWyllys.Ingersoll@Sun.COM     if ( !o_pFindInfo->m_pFTSENT )
1563*12720SWyllys.Ingersoll@Sun.COM     {
1564*12720SWyllys.Ingersoll@Sun.COM         if ( errno == 0 )
1565*12720SWyllys.Ingersoll@Sun.COM         {
1566*12720SWyllys.Ingersoll@Sun.COM             return 1;
1567*12720SWyllys.Ingersoll@Sun.COM         }
1568*12720SWyllys.Ingersoll@Sun.COM         else
1569*12720SWyllys.Ingersoll@Sun.COM         {
1570*12720SWyllys.Ingersoll@Sun.COM             fts_close( o_pFindInfo->m_pFTS );
1571*12720SWyllys.Ingersoll@Sun.COM             return -1;
1572*12720SWyllys.Ingersoll@Sun.COM         }
1573*12720SWyllys.Ingersoll@Sun.COM     }
1574*12720SWyllys.Ingersoll@Sun.COM #else
1575*12720SWyllys.Ingersoll@Sun.COM /*
1576*12720SWyllys.Ingersoll@Sun.COM  * Directory traversal code is not yet available for Solaris.
1577*12720SWyllys.Ingersoll@Sun.COM  * If such code will need to be written, then it will probably use ftw.h.
1578*12720SWyllys.Ingersoll@Sun.COM  */
1579*12720SWyllys.Ingersoll@Sun.COM #endif
1580*12720SWyllys.Ingersoll@Sun.COM 
1581*12720SWyllys.Ingersoll@Sun.COM     // If what we found is not actually a file, get the next hit.
1582*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
1583*12720SWyllys.Ingersoll@Sun.COM     if ( (o_pFindInfo->m_stFindData.attrib & _A_SUBDIR) )
1584*12720SWyllys.Ingersoll@Sun.COM #elif defined K_LINUX_PLATFORM
1585*12720SWyllys.Ingersoll@Sun.COM     if ( !(o_pFindInfo->m_pFTSENT->fts_info & FTS_F) )
1586*12720SWyllys.Ingersoll@Sun.COM #else
1587*12720SWyllys.Ingersoll@Sun.COM /*
1588*12720SWyllys.Ingersoll@Sun.COM  * Directory traversal code is not yet available for Solaris.
1589*12720SWyllys.Ingersoll@Sun.COM  * If such code will need to be written, then it will probably use ftw.h.
1590*12720SWyllys.Ingersoll@Sun.COM  */
1591*12720SWyllys.Ingersoll@Sun.COM #endif
1592*12720SWyllys.Ingersoll@Sun.COM     {
1593*12720SWyllys.Ingersoll@Sun.COM         int iNextReturn = K_FindFileNext( o_pFindInfo );
1594*12720SWyllys.Ingersoll@Sun.COM         if ( iNextReturn < 0 )
1595*12720SWyllys.Ingersoll@Sun.COM         {
1596*12720SWyllys.Ingersoll@Sun.COM             K_FindFileClose( o_pFindInfo );
1597*12720SWyllys.Ingersoll@Sun.COM             return -1;
1598*12720SWyllys.Ingersoll@Sun.COM         }
1599*12720SWyllys.Ingersoll@Sun.COM         else
1600*12720SWyllys.Ingersoll@Sun.COM         {
1601*12720SWyllys.Ingersoll@Sun.COM             return iNextReturn;
1602*12720SWyllys.Ingersoll@Sun.COM         }
1603*12720SWyllys.Ingersoll@Sun.COM     }
1604*12720SWyllys.Ingersoll@Sun.COM 
1605*12720SWyllys.Ingersoll@Sun.COM #if defined(WIN32) || defined(K_LINUX_PLATFORM)
1606*12720SWyllys.Ingersoll@Sun.COM     return 0;
1607*12720SWyllys.Ingersoll@Sun.COM #endif
1608*12720SWyllys.Ingersoll@Sun.COM }
1609*12720SWyllys.Ingersoll@Sun.COM 
1610*12720SWyllys.Ingersoll@Sun.COM // Returns 0 if successful, 1 if not found, -1 if error.
K_FindFileNext(K_FindInfo * io_pFindInfo)1611*12720SWyllys.Ingersoll@Sun.COM int K_FindFileNext( K_FindInfo* io_pFindInfo )
1612*12720SWyllys.Ingersoll@Sun.COM {
1613*12720SWyllys.Ingersoll@Sun.COM     if ( !io_pFindInfo )
1614*12720SWyllys.Ingersoll@Sun.COM     {
1615*12720SWyllys.Ingersoll@Sun.COM         return -1;
1616*12720SWyllys.Ingersoll@Sun.COM     }
1617*12720SWyllys.Ingersoll@Sun.COM 
1618*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
1619*12720SWyllys.Ingersoll@Sun.COM     if ( _findnext( io_pFindInfo->m_hFile, &io_pFindInfo->m_stFindData ) != 0 )
1620*12720SWyllys.Ingersoll@Sun.COM     {
1621*12720SWyllys.Ingersoll@Sun.COM         return (errno == ENOENT) ? 1 : -1;
1622*12720SWyllys.Ingersoll@Sun.COM     }
1623*12720SWyllys.Ingersoll@Sun.COM #elif defined K_LINUX_PLATFORM
1624*12720SWyllys.Ingersoll@Sun.COM     io_pFindInfo->m_pFTSENT = fts_read( io_pFindInfo->m_pFTS );
1625*12720SWyllys.Ingersoll@Sun.COM     if ( !io_pFindInfo->m_pFTSENT )
1626*12720SWyllys.Ingersoll@Sun.COM     {
1627*12720SWyllys.Ingersoll@Sun.COM         return (errno == 0) ? 1 : -1;
1628*12720SWyllys.Ingersoll@Sun.COM     }
1629*12720SWyllys.Ingersoll@Sun.COM #else
1630*12720SWyllys.Ingersoll@Sun.COM /*
1631*12720SWyllys.Ingersoll@Sun.COM  * Directory traversal code is not yet available for Solaris.
1632*12720SWyllys.Ingersoll@Sun.COM  * If such code will need to be written, then it will probably use ftw.h.
1633*12720SWyllys.Ingersoll@Sun.COM  */
1634*12720SWyllys.Ingersoll@Sun.COM #endif
1635*12720SWyllys.Ingersoll@Sun.COM 
1636*12720SWyllys.Ingersoll@Sun.COM     // If what we found is not actually a file, get the next hit.
1637*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
1638*12720SWyllys.Ingersoll@Sun.COM     if ( (io_pFindInfo->m_stFindData.attrib & _A_SUBDIR) )
1639*12720SWyllys.Ingersoll@Sun.COM #elif defined K_LINUX_PLATFORM
1640*12720SWyllys.Ingersoll@Sun.COM     if ( !(io_pFindInfo->m_pFTSENT->fts_info & FTS_F) )
1641*12720SWyllys.Ingersoll@Sun.COM #else
1642*12720SWyllys.Ingersoll@Sun.COM /*
1643*12720SWyllys.Ingersoll@Sun.COM  * Directory traversal code is not yet available for Solaris.
1644*12720SWyllys.Ingersoll@Sun.COM  * If such code will need to be written, then it will probably use ftw.h.
1645*12720SWyllys.Ingersoll@Sun.COM  */
1646*12720SWyllys.Ingersoll@Sun.COM #endif
1647*12720SWyllys.Ingersoll@Sun.COM     {
1648*12720SWyllys.Ingersoll@Sun.COM         return K_FindFileNext( io_pFindInfo );
1649*12720SWyllys.Ingersoll@Sun.COM     }
1650*12720SWyllys.Ingersoll@Sun.COM 
1651*12720SWyllys.Ingersoll@Sun.COM #if defined(WIN32) || defined(K_LINUX_PLATFORM)
1652*12720SWyllys.Ingersoll@Sun.COM     return 0;
1653*12720SWyllys.Ingersoll@Sun.COM #endif
1654*12720SWyllys.Ingersoll@Sun.COM }
1655*12720SWyllys.Ingersoll@Sun.COM 
K_FindFileClose(K_FindInfo * io_pFindInfo)1656*12720SWyllys.Ingersoll@Sun.COM void K_FindFileClose( K_FindInfo* io_pFindInfo )
1657*12720SWyllys.Ingersoll@Sun.COM {
1658*12720SWyllys.Ingersoll@Sun.COM     if ( !io_pFindInfo )
1659*12720SWyllys.Ingersoll@Sun.COM     {
1660*12720SWyllys.Ingersoll@Sun.COM         return;
1661*12720SWyllys.Ingersoll@Sun.COM     }
1662*12720SWyllys.Ingersoll@Sun.COM 
1663*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
1664*12720SWyllys.Ingersoll@Sun.COM     _findclose( io_pFindInfo->m_hFile );
1665*12720SWyllys.Ingersoll@Sun.COM #elif defined K_LINUX_PLATFORM
1666*12720SWyllys.Ingersoll@Sun.COM     fts_close( io_pFindInfo->m_pFTS );
1667*12720SWyllys.Ingersoll@Sun.COM #else
1668*12720SWyllys.Ingersoll@Sun.COM /*
1669*12720SWyllys.Ingersoll@Sun.COM  * Directory traversal code is not yet available for Solaris.
1670*12720SWyllys.Ingersoll@Sun.COM  * If such code will need to be written, then it will probably use ftw.h.
1671*12720SWyllys.Ingersoll@Sun.COM  */
1672*12720SWyllys.Ingersoll@Sun.COM #endif
1673*12720SWyllys.Ingersoll@Sun.COM }
1674*12720SWyllys.Ingersoll@Sun.COM 
1675*12720SWyllys.Ingersoll@Sun.COM 
1676*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
1677*12720SWyllys.Ingersoll@Sun.COM  * Function: K_GetFilenamesInDirectoryCount
1678*12720SWyllys.Ingersoll@Sun.COM  *
1679*12720SWyllys.Ingersoll@Sun.COM  * Description:
1680*12720SWyllys.Ingersoll@Sun.COM  *  Reads the given directory and returns the number of files that it contains.
1681*12720SWyllys.Ingersoll@Sun.COM  *
1682*12720SWyllys.Ingersoll@Sun.COM  * Input
1683*12720SWyllys.Ingersoll@Sun.COM  * -----
1684*12720SWyllys.Ingersoll@Sun.COM  *    i_sDirectoryName  Name of directory
1685*12720SWyllys.Ingersoll@Sun.COM  *
1686*12720SWyllys.Ingersoll@Sun.COM  * Output
1687*12720SWyllys.Ingersoll@Sun.COM  * ------
1688*12720SWyllys.Ingersoll@Sun.COM  *    (none)
1689*12720SWyllys.Ingersoll@Sun.COM  *
1690*12720SWyllys.Ingersoll@Sun.COM  * Return value        Number of files on success, -1 on failure
1691*12720SWyllys.Ingersoll@Sun.COM  *
1692*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
1693*12720SWyllys.Ingersoll@Sun.COM 
K_GetFilenamesInDirectoryCount(const char * i_sDirectoryName)1694*12720SWyllys.Ingersoll@Sun.COM int K_GetFilenamesInDirectoryCount( const char* i_sDirectoryName )
1695*12720SWyllys.Ingersoll@Sun.COM {
1696*12720SWyllys.Ingersoll@Sun.COM     K_FindInfo stFindInfo;
1697*12720SWyllys.Ingersoll@Sun.COM     int iCurrentFile = 0;
1698*12720SWyllys.Ingersoll@Sun.COM     int iError = 0;
1699*12720SWyllys.Ingersoll@Sun.COM 
1700*12720SWyllys.Ingersoll@Sun.COM     if ( !i_sDirectoryName || (strlen(i_sDirectoryName) <= 0) )
1701*12720SWyllys.Ingersoll@Sun.COM     {
1702*12720SWyllys.Ingersoll@Sun.COM         return -1;
1703*12720SWyllys.Ingersoll@Sun.COM     }
1704*12720SWyllys.Ingersoll@Sun.COM 
1705*12720SWyllys.Ingersoll@Sun.COM     iError = K_FindFileFirst( i_sDirectoryName, &stFindInfo );
1706*12720SWyllys.Ingersoll@Sun.COM     if ( iError < 0 )
1707*12720SWyllys.Ingersoll@Sun.COM     {
1708*12720SWyllys.Ingersoll@Sun.COM         // error
1709*12720SWyllys.Ingersoll@Sun.COM         return -1;
1710*12720SWyllys.Ingersoll@Sun.COM     }
1711*12720SWyllys.Ingersoll@Sun.COM     else if ( iError > 0 )
1712*12720SWyllys.Ingersoll@Sun.COM     {
1713*12720SWyllys.Ingersoll@Sun.COM         // no files found
1714*12720SWyllys.Ingersoll@Sun.COM         K_FindFileClose( &stFindInfo );
1715*12720SWyllys.Ingersoll@Sun.COM         return 0;
1716*12720SWyllys.Ingersoll@Sun.COM     }
1717*12720SWyllys.Ingersoll@Sun.COM 
1718*12720SWyllys.Ingersoll@Sun.COM     while ( 1 )
1719*12720SWyllys.Ingersoll@Sun.COM     {
1720*12720SWyllys.Ingersoll@Sun.COM         iCurrentFile++;
1721*12720SWyllys.Ingersoll@Sun.COM 
1722*12720SWyllys.Ingersoll@Sun.COM         iError = K_FindFileNext( &stFindInfo );
1723*12720SWyllys.Ingersoll@Sun.COM         if ( iError < 0 )
1724*12720SWyllys.Ingersoll@Sun.COM         {
1725*12720SWyllys.Ingersoll@Sun.COM             // error
1726*12720SWyllys.Ingersoll@Sun.COM             K_FindFileClose( &stFindInfo );
1727*12720SWyllys.Ingersoll@Sun.COM             return -1;
1728*12720SWyllys.Ingersoll@Sun.COM         }
1729*12720SWyllys.Ingersoll@Sun.COM         else if ( iError > 0 )
1730*12720SWyllys.Ingersoll@Sun.COM         {
1731*12720SWyllys.Ingersoll@Sun.COM             // no more files found
1732*12720SWyllys.Ingersoll@Sun.COM             break;
1733*12720SWyllys.Ingersoll@Sun.COM         }
1734*12720SWyllys.Ingersoll@Sun.COM     }
1735*12720SWyllys.Ingersoll@Sun.COM 
1736*12720SWyllys.Ingersoll@Sun.COM     K_FindFileClose( &stFindInfo );
1737*12720SWyllys.Ingersoll@Sun.COM 
1738*12720SWyllys.Ingersoll@Sun.COM     return iCurrentFile;
1739*12720SWyllys.Ingersoll@Sun.COM }
1740*12720SWyllys.Ingersoll@Sun.COM 
1741*12720SWyllys.Ingersoll@Sun.COM 
1742*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
1743*12720SWyllys.Ingersoll@Sun.COM  * Function: K_GetFilenamesInDirectory
1744*12720SWyllys.Ingersoll@Sun.COM  *
1745*12720SWyllys.Ingersoll@Sun.COM  * Description:
1746*12720SWyllys.Ingersoll@Sun.COM  *  Reads the given directory and returns an array of names of files that it
1747*12720SWyllys.Ingersoll@Sun.COM  *  contains.  A null pointer appears at the last item in the array.  The
1748*12720SWyllys.Ingersoll@Sun.COM  *  caller must deallocate o_pasFilenames by using K_FreeFilenames or by
1749*12720SWyllys.Ingersoll@Sun.COM  *  calling free() for each file name and then calling free() on the array
1750*12720SWyllys.Ingersoll@Sun.COM  *  itself.
1751*12720SWyllys.Ingersoll@Sun.COM  *
1752*12720SWyllys.Ingersoll@Sun.COM  * Input
1753*12720SWyllys.Ingersoll@Sun.COM  * -----
1754*12720SWyllys.Ingersoll@Sun.COM  *    i_sDirectoryName  Name of directory
1755*12720SWyllys.Ingersoll@Sun.COM  *
1756*12720SWyllys.Ingersoll@Sun.COM  * Output
1757*12720SWyllys.Ingersoll@Sun.COM  * ------
1758*12720SWyllys.Ingersoll@Sun.COM  *    o_pasFilenames   Array of names of files found in this directory
1759*12720SWyllys.Ingersoll@Sun.COM  *
1760*12720SWyllys.Ingersoll@Sun.COM  * Return value        Number of files on success, -1 on failure
1761*12720SWyllys.Ingersoll@Sun.COM  *
1762*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
1763*12720SWyllys.Ingersoll@Sun.COM 
K_GetFilenamesInDirectory(const char * i_sDirectoryName,char *** o_pasFilenames)1764*12720SWyllys.Ingersoll@Sun.COM int K_GetFilenamesInDirectory(
1765*12720SWyllys.Ingersoll@Sun.COM         const char* i_sDirectoryName,
1766*12720SWyllys.Ingersoll@Sun.COM         char*** o_pasFilenames )
1767*12720SWyllys.Ingersoll@Sun.COM {
1768*12720SWyllys.Ingersoll@Sun.COM     // Note that we iterate through the filenames twice -- once to get the count
1769*12720SWyllys.Ingersoll@Sun.COM     // (K_GetFilenamesInDirectoryCount) and then once to get all the names. But
1770*12720SWyllys.Ingersoll@Sun.COM     // it may happen that the count changes between these calls.  So we'll retrieve
1771*12720SWyllys.Ingersoll@Sun.COM     // at most the number of files that's returned in the first pass.
1772*12720SWyllys.Ingersoll@Sun.COM 
1773*12720SWyllys.Ingersoll@Sun.COM     K_FindInfo stFindInfo;
1774*12720SWyllys.Ingersoll@Sun.COM     int iFilenameCount = 0, iCurrentFile = 0;
1775*12720SWyllys.Ingersoll@Sun.COM     int iError = 0;
1776*12720SWyllys.Ingersoll@Sun.COM 
1777*12720SWyllys.Ingersoll@Sun.COM     if ( !i_sDirectoryName || (strlen(i_sDirectoryName) <= 0) || !o_pasFilenames )
1778*12720SWyllys.Ingersoll@Sun.COM     {
1779*12720SWyllys.Ingersoll@Sun.COM         return -1;
1780*12720SWyllys.Ingersoll@Sun.COM     }
1781*12720SWyllys.Ingersoll@Sun.COM 
1782*12720SWyllys.Ingersoll@Sun.COM     *o_pasFilenames = 0;
1783*12720SWyllys.Ingersoll@Sun.COM 
1784*12720SWyllys.Ingersoll@Sun.COM     iFilenameCount = K_GetFilenamesInDirectoryCount( i_sDirectoryName );
1785*12720SWyllys.Ingersoll@Sun.COM 
1786*12720SWyllys.Ingersoll@Sun.COM     if ( iFilenameCount < 0 )
1787*12720SWyllys.Ingersoll@Sun.COM     {
1788*12720SWyllys.Ingersoll@Sun.COM         return -1;
1789*12720SWyllys.Ingersoll@Sun.COM     }
1790*12720SWyllys.Ingersoll@Sun.COM 
1791*12720SWyllys.Ingersoll@Sun.COM     iError = K_FindFileFirst( i_sDirectoryName, &stFindInfo );
1792*12720SWyllys.Ingersoll@Sun.COM     if ( iError < 0 )
1793*12720SWyllys.Ingersoll@Sun.COM     {
1794*12720SWyllys.Ingersoll@Sun.COM         // error
1795*12720SWyllys.Ingersoll@Sun.COM         return -1;
1796*12720SWyllys.Ingersoll@Sun.COM     }
1797*12720SWyllys.Ingersoll@Sun.COM     else if ( iError > 0 )
1798*12720SWyllys.Ingersoll@Sun.COM     {
1799*12720SWyllys.Ingersoll@Sun.COM         // No files found
1800*12720SWyllys.Ingersoll@Sun.COM         K_FindFileClose( &stFindInfo );
1801*12720SWyllys.Ingersoll@Sun.COM         return 0;
1802*12720SWyllys.Ingersoll@Sun.COM     }
1803*12720SWyllys.Ingersoll@Sun.COM 
1804*12720SWyllys.Ingersoll@Sun.COM     *o_pasFilenames = (char**)calloc( (iFilenameCount+1), sizeof(char*) );    // +1 for the null last one
1805*12720SWyllys.Ingersoll@Sun.COM     if ( !*o_pasFilenames )
1806*12720SWyllys.Ingersoll@Sun.COM     {
1807*12720SWyllys.Ingersoll@Sun.COM         // Out of memory
1808*12720SWyllys.Ingersoll@Sun.COM         K_FindFileClose( &stFindInfo );
1809*12720SWyllys.Ingersoll@Sun.COM         return -1;
1810*12720SWyllys.Ingersoll@Sun.COM     }
1811*12720SWyllys.Ingersoll@Sun.COM 
1812*12720SWyllys.Ingersoll@Sun.COM     while ( 1 )
1813*12720SWyllys.Ingersoll@Sun.COM     {
1814*12720SWyllys.Ingersoll@Sun.COM         const char* sFilename = K_GetFilenameFromInfo( &stFindInfo );
1815*12720SWyllys.Ingersoll@Sun.COM 
1816*12720SWyllys.Ingersoll@Sun.COM         size_t iFilenameLength = sFilename ? strlen( sFilename ) : 0;
1817*12720SWyllys.Ingersoll@Sun.COM 
1818*12720SWyllys.Ingersoll@Sun.COM         if ( iFilenameLength <= 0 )
1819*12720SWyllys.Ingersoll@Sun.COM         {
1820*12720SWyllys.Ingersoll@Sun.COM             K_FreeFilenames( *o_pasFilenames );
1821*12720SWyllys.Ingersoll@Sun.COM             K_FindFileClose( &stFindInfo );
1822*12720SWyllys.Ingersoll@Sun.COM             return -1;
1823*12720SWyllys.Ingersoll@Sun.COM         }
1824*12720SWyllys.Ingersoll@Sun.COM 
1825*12720SWyllys.Ingersoll@Sun.COM         (*o_pasFilenames)[iCurrentFile] = (char*)calloc( (iFilenameLength+1), sizeof(char) );
1826*12720SWyllys.Ingersoll@Sun.COM         if ( !(*o_pasFilenames)[iCurrentFile] )
1827*12720SWyllys.Ingersoll@Sun.COM         {
1828*12720SWyllys.Ingersoll@Sun.COM             K_FreeFilenames( *o_pasFilenames );
1829*12720SWyllys.Ingersoll@Sun.COM             K_FindFileClose( &stFindInfo );
1830*12720SWyllys.Ingersoll@Sun.COM             return -1;
1831*12720SWyllys.Ingersoll@Sun.COM         }
1832*12720SWyllys.Ingersoll@Sun.COM 
1833*12720SWyllys.Ingersoll@Sun.COM         strncpy( (*o_pasFilenames)[iCurrentFile], sFilename, iFilenameLength );
1834*12720SWyllys.Ingersoll@Sun.COM         (*o_pasFilenames)[iCurrentFile][iFilenameLength] = '\0';
1835*12720SWyllys.Ingersoll@Sun.COM 
1836*12720SWyllys.Ingersoll@Sun.COM         iCurrentFile++;
1837*12720SWyllys.Ingersoll@Sun.COM 
1838*12720SWyllys.Ingersoll@Sun.COM         if ( iCurrentFile >= iFilenameCount )
1839*12720SWyllys.Ingersoll@Sun.COM         {
1840*12720SWyllys.Ingersoll@Sun.COM             break;
1841*12720SWyllys.Ingersoll@Sun.COM         }
1842*12720SWyllys.Ingersoll@Sun.COM 
1843*12720SWyllys.Ingersoll@Sun.COM         iError = K_FindFileNext( &stFindInfo );
1844*12720SWyllys.Ingersoll@Sun.COM         if ( iError < 0 )
1845*12720SWyllys.Ingersoll@Sun.COM         {
1846*12720SWyllys.Ingersoll@Sun.COM             // error
1847*12720SWyllys.Ingersoll@Sun.COM             K_FindFileClose( &stFindInfo );
1848*12720SWyllys.Ingersoll@Sun.COM             return -1;
1849*12720SWyllys.Ingersoll@Sun.COM         }
1850*12720SWyllys.Ingersoll@Sun.COM         else if ( iError > 0 )
1851*12720SWyllys.Ingersoll@Sun.COM         {
1852*12720SWyllys.Ingersoll@Sun.COM             // no more files found
1853*12720SWyllys.Ingersoll@Sun.COM             break;
1854*12720SWyllys.Ingersoll@Sun.COM         }
1855*12720SWyllys.Ingersoll@Sun.COM     }
1856*12720SWyllys.Ingersoll@Sun.COM 
1857*12720SWyllys.Ingersoll@Sun.COM     K_FindFileClose( &stFindInfo );
1858*12720SWyllys.Ingersoll@Sun.COM 
1859*12720SWyllys.Ingersoll@Sun.COM     return iCurrentFile;
1860*12720SWyllys.Ingersoll@Sun.COM }
1861*12720SWyllys.Ingersoll@Sun.COM 
1862*12720SWyllys.Ingersoll@Sun.COM 
1863*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
1864*12720SWyllys.Ingersoll@Sun.COM  * Function: K_FreeFilenames
1865*12720SWyllys.Ingersoll@Sun.COM  *
1866*12720SWyllys.Ingersoll@Sun.COM  * Description:
1867*12720SWyllys.Ingersoll@Sun.COM  *  Deallocates the memory allocated in a successful call to
1868*12720SWyllys.Ingersoll@Sun.COM  *  K_GetFilenamesInDirectory.
1869*12720SWyllys.Ingersoll@Sun.COM  *
1870*12720SWyllys.Ingersoll@Sun.COM  * Input
1871*12720SWyllys.Ingersoll@Sun.COM  * -----
1872*12720SWyllys.Ingersoll@Sun.COM  *    i_asFilenames    Array of names of files
1873*12720SWyllys.Ingersoll@Sun.COM  *
1874*12720SWyllys.Ingersoll@Sun.COM  * Output
1875*12720SWyllys.Ingersoll@Sun.COM  * ------
1876*12720SWyllys.Ingersoll@Sun.COM  *    (none)
1877*12720SWyllys.Ingersoll@Sun.COM  *
1878*12720SWyllys.Ingersoll@Sun.COM  * Return value        (none)
1879*12720SWyllys.Ingersoll@Sun.COM  *
1880*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
1881*12720SWyllys.Ingersoll@Sun.COM 
K_FreeFilenames(char ** i_asFilenames)1882*12720SWyllys.Ingersoll@Sun.COM void K_FreeFilenames( char** i_asFilenames )
1883*12720SWyllys.Ingersoll@Sun.COM {
1884*12720SWyllys.Ingersoll@Sun.COM     int i;
1885*12720SWyllys.Ingersoll@Sun.COM 
1886*12720SWyllys.Ingersoll@Sun.COM     if ( !i_asFilenames )
1887*12720SWyllys.Ingersoll@Sun.COM     {
1888*12720SWyllys.Ingersoll@Sun.COM         return;
1889*12720SWyllys.Ingersoll@Sun.COM     }
1890*12720SWyllys.Ingersoll@Sun.COM 
1891*12720SWyllys.Ingersoll@Sun.COM     for ( i = 0; (i_asFilenames[i] != 0); i++ )
1892*12720SWyllys.Ingersoll@Sun.COM     {
1893*12720SWyllys.Ingersoll@Sun.COM         free( i_asFilenames[i] );
1894*12720SWyllys.Ingersoll@Sun.COM         i_asFilenames[i] = 0;
1895*12720SWyllys.Ingersoll@Sun.COM     }
1896*12720SWyllys.Ingersoll@Sun.COM 
1897*12720SWyllys.Ingersoll@Sun.COM     free( i_asFilenames );
1898*12720SWyllys.Ingersoll@Sun.COM }
1899*12720SWyllys.Ingersoll@Sun.COM 
1900*12720SWyllys.Ingersoll@Sun.COM 
1901*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
1902*12720SWyllys.Ingersoll@Sun.COM  * Function: K_AdjustLocalClock
1903*12720SWyllys.Ingersoll@Sun.COM  *
1904*12720SWyllys.Ingersoll@Sun.COM  * Description:
1905*12720SWyllys.Ingersoll@Sun.COM  *  The K_AdjustLocalClock function gradually adjusts the system clock by
1906*12720SWyllys.Ingersoll@Sun.COM  *  the given number of seconds.  A positive number adjusts the system
1907*12720SWyllys.Ingersoll@Sun.COM  *  clock forward; a negative number adjusts the system clock backward.
1908*12720SWyllys.Ingersoll@Sun.COM  *
1909*12720SWyllys.Ingersoll@Sun.COM  * Input
1910*12720SWyllys.Ingersoll@Sun.COM  * -----
1911*12720SWyllys.Ingersoll@Sun.COM  *    i_iAdjustmentInSeconds   Number of seconds by which to adjust the
1912*12720SWyllys.Ingersoll@Sun.COM  *                             system clock
1913*12720SWyllys.Ingersoll@Sun.COM  * Output
1914*12720SWyllys.Ingersoll@Sun.COM  * ------
1915*12720SWyllys.Ingersoll@Sun.COM  *    (none)
1916*12720SWyllys.Ingersoll@Sun.COM  *
1917*12720SWyllys.Ingersoll@Sun.COM  * Return value        1 if successful, 0 on error
1918*12720SWyllys.Ingersoll@Sun.COM  *
1919*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
1920*12720SWyllys.Ingersoll@Sun.COM 
K_AdjustLocalClock(int i_iNumberOfSeconds)1921*12720SWyllys.Ingersoll@Sun.COM int K_AdjustLocalClock( int i_iNumberOfSeconds )
1922*12720SWyllys.Ingersoll@Sun.COM {
1923*12720SWyllys.Ingersoll@Sun.COM     struct timeval delta, lastchange;
1924*12720SWyllys.Ingersoll@Sun.COM 
1925*12720SWyllys.Ingersoll@Sun.COM #ifndef K_SOLARIS_PLATFORM
1926*12720SWyllys.Ingersoll@Sun.COM     /* Only supported/tested on Solaris at the moment */
1927*12720SWyllys.Ingersoll@Sun.COM 
1928*12720SWyllys.Ingersoll@Sun.COM     return -1;
1929*12720SWyllys.Ingersoll@Sun.COM #else
1930*12720SWyllys.Ingersoll@Sun.COM     /* WARNING: uses standard C time functions with Year 2038 limitations */
1931*12720SWyllys.Ingersoll@Sun.COM     time_t now;
1932*12720SWyllys.Ingersoll@Sun.COM 
1933*12720SWyllys.Ingersoll@Sun.COM     if ( (now = time(NULL)) == ((time_t)-1) )
1934*12720SWyllys.Ingersoll@Sun.COM     {
1935*12720SWyllys.Ingersoll@Sun.COM         return -1;
1936*12720SWyllys.Ingersoll@Sun.COM     }
1937*12720SWyllys.Ingersoll@Sun.COM 
1938*12720SWyllys.Ingersoll@Sun.COM     delta.tv_sec = i_iNumberOfSeconds;
1939*12720SWyllys.Ingersoll@Sun.COM     delta.tv_usec = 0;
1940*12720SWyllys.Ingersoll@Sun.COM 
1941*12720SWyllys.Ingersoll@Sun.COM     return adjtime(&delta, &lastchange);
1942*12720SWyllys.Ingersoll@Sun.COM #endif
1943*12720SWyllys.Ingersoll@Sun.COM }
1944*12720SWyllys.Ingersoll@Sun.COM 
1945*12720SWyllys.Ingersoll@Sun.COM 
1946*12720SWyllys.Ingersoll@Sun.COM #ifdef K_SOLARIS_PLATFORM
pam_tty_conv(int num_msg,struct pam_message ** mess,struct pam_response ** resp,void * my_data)1947*12720SWyllys.Ingersoll@Sun.COM static int pam_tty_conv(
1948*12720SWyllys.Ingersoll@Sun.COM     int num_msg,
1949*12720SWyllys.Ingersoll@Sun.COM     struct pam_message** mess,
1950*12720SWyllys.Ingersoll@Sun.COM     struct pam_response** resp,
1951*12720SWyllys.Ingersoll@Sun.COM     void* my_data)
1952*12720SWyllys.Ingersoll@Sun.COM {
1953*12720SWyllys.Ingersoll@Sun.COM     // Following code implements a console-based PAM "conversation" function
1954*12720SWyllys.Ingersoll@Sun.COM     // (based sample code from Solaris 10 Software Developer Collection >>
1955*12720SWyllys.Ingersoll@Sun.COM     // Solaris Security for Developers Guide >>
1956*12720SWyllys.Ingersoll@Sun.COM     // 3.  Writing PAM Applications and Services)
1957*12720SWyllys.Ingersoll@Sun.COM 
1958*12720SWyllys.Ingersoll@Sun.COM     struct pam_message* m = *mess;
1959*12720SWyllys.Ingersoll@Sun.COM     struct pam_response* r;
1960*12720SWyllys.Ingersoll@Sun.COM     int i, j;
1961*12720SWyllys.Ingersoll@Sun.COM     const char* sPassword = (const char*)my_data;
1962*12720SWyllys.Ingersoll@Sun.COM     int error = PAM_CONV_ERR;
1963*12720SWyllys.Ingersoll@Sun.COM 
1964*12720SWyllys.Ingersoll@Sun.COM     if (num_msg <= 0 || num_msg >= PAM_MAX_NUM_MSG)
1965*12720SWyllys.Ingersoll@Sun.COM     {
1966*12720SWyllys.Ingersoll@Sun.COM         (void) fprintf(stderr, "PAM error: bad number of messages");
1967*12720SWyllys.Ingersoll@Sun.COM         *resp = NULL;
1968*12720SWyllys.Ingersoll@Sun.COM         return (PAM_CONV_ERR);
1969*12720SWyllys.Ingersoll@Sun.COM     }
1970*12720SWyllys.Ingersoll@Sun.COM 
1971*12720SWyllys.Ingersoll@Sun.COM     if ((*resp = r = calloc(num_msg, sizeof (struct pam_response))) == NULL)
1972*12720SWyllys.Ingersoll@Sun.COM     {
1973*12720SWyllys.Ingersoll@Sun.COM         return (PAM_BUF_ERR);
1974*12720SWyllys.Ingersoll@Sun.COM     }
1975*12720SWyllys.Ingersoll@Sun.COM 
1976*12720SWyllys.Ingersoll@Sun.COM     // Loop through messages
1977*12720SWyllys.Ingersoll@Sun.COM     for (i = 0; i < num_msg; i++) {
1978*12720SWyllys.Ingersoll@Sun.COM 
1979*12720SWyllys.Ingersoll@Sun.COM         // bad message from service module
1980*12720SWyllys.Ingersoll@Sun.COM         if (m->msg == NULL)
1981*12720SWyllys.Ingersoll@Sun.COM         {
1982*12720SWyllys.Ingersoll@Sun.COM             (void) fprintf(stderr, "PAM error: bad message");
1983*12720SWyllys.Ingersoll@Sun.COM             goto err;
1984*12720SWyllys.Ingersoll@Sun.COM         }
1985*12720SWyllys.Ingersoll@Sun.COM 
1986*12720SWyllys.Ingersoll@Sun.COM         // fix up final newline: removed for prompts, added back for messages
1987*12720SWyllys.Ingersoll@Sun.COM         if (m->msg[strlen(m->msg)] == '\n')
1988*12720SWyllys.Ingersoll@Sun.COM         {
1989*12720SWyllys.Ingersoll@Sun.COM             m->msg[strlen(m->msg)] = '\0';
1990*12720SWyllys.Ingersoll@Sun.COM         }
1991*12720SWyllys.Ingersoll@Sun.COM 
1992*12720SWyllys.Ingersoll@Sun.COM         // Since the KMA has its own password prompts and enforces its own rule checks, we already have the
1993*12720SWyllys.Ingersoll@Sun.COM         // new password in memory.  So instead of displaying PAM prompts and collecting user responses, we
1994*12720SWyllys.Ingersoll@Sun.COM         // "automate" by assuming that the prompts correspond to the standard sequence of "New password:"
1995*12720SWyllys.Ingersoll@Sun.COM         // followed by "Confirm password:" and so in each case we immediately return the password we already
1996*12720SWyllys.Ingersoll@Sun.COM         // have in memory.  This violates the PAM "conversation" function instructions (which say, basically,
1997*12720SWyllys.Ingersoll@Sun.COM         // not to assume any particular sequence of prompts since there could be any number of underlying
1998*12720SWyllys.Ingersoll@Sun.COM         // password managers), but since the KMA is running on an appliance with a fixed password manager,
1999*12720SWyllys.Ingersoll@Sun.COM         // our assumptions should hold.
2000*12720SWyllys.Ingersoll@Sun.COM 
2001*12720SWyllys.Ingersoll@Sun.COM         r->resp = NULL;
2002*12720SWyllys.Ingersoll@Sun.COM         r->resp_retcode = 0;
2003*12720SWyllys.Ingersoll@Sun.COM         switch (m->msg_style)
2004*12720SWyllys.Ingersoll@Sun.COM         {
2005*12720SWyllys.Ingersoll@Sun.COM         case PAM_PROMPT_ECHO_OFF:
2006*12720SWyllys.Ingersoll@Sun.COM         case PAM_PROMPT_ECHO_ON:
2007*12720SWyllys.Ingersoll@Sun.COM             // Assume the prompt asked for New/Confirm password, so return password.
2008*12720SWyllys.Ingersoll@Sun.COM             if ( (r->resp = strdup(sPassword)) == NULL )
2009*12720SWyllys.Ingersoll@Sun.COM             {
2010*12720SWyllys.Ingersoll@Sun.COM                 error = PAM_BUF_ERR;
2011*12720SWyllys.Ingersoll@Sun.COM                 goto err;
2012*12720SWyllys.Ingersoll@Sun.COM             }
2013*12720SWyllys.Ingersoll@Sun.COM             break;
2014*12720SWyllys.Ingersoll@Sun.COM 
2015*12720SWyllys.Ingersoll@Sun.COM         case PAM_ERROR_MSG:
2016*12720SWyllys.Ingersoll@Sun.COM             // Assuming the system is configured properly and the KMA password prompts enforce password strength rules,
2017*12720SWyllys.Ingersoll@Sun.COM             // there should not be errors because of weak passwords, etc.  Still, print errors so users/support can
2018*12720SWyllys.Ingersoll@Sun.COM             // diagnose problems.
2019*12720SWyllys.Ingersoll@Sun.COM             (void) fputs(m->msg, stderr);
2020*12720SWyllys.Ingersoll@Sun.COM             (void) fputc('\n', stderr);
2021*12720SWyllys.Ingersoll@Sun.COM             break;
2022*12720SWyllys.Ingersoll@Sun.COM 
2023*12720SWyllys.Ingersoll@Sun.COM         case PAM_TEXT_INFO:
2024*12720SWyllys.Ingersoll@Sun.COM             // Supress prompts (again, making assumptions).
2025*12720SWyllys.Ingersoll@Sun.COM             break;
2026*12720SWyllys.Ingersoll@Sun.COM 
2027*12720SWyllys.Ingersoll@Sun.COM         default:
2028*12720SWyllys.Ingersoll@Sun.COM             (void) fprintf(stderr, "PAM error: unknown message");
2029*12720SWyllys.Ingersoll@Sun.COM             goto err;
2030*12720SWyllys.Ingersoll@Sun.COM         }
2031*12720SWyllys.Ingersoll@Sun.COM         if (errno == EINTR)
2032*12720SWyllys.Ingersoll@Sun.COM         {
2033*12720SWyllys.Ingersoll@Sun.COM             goto err;
2034*12720SWyllys.Ingersoll@Sun.COM         }
2035*12720SWyllys.Ingersoll@Sun.COM 
2036*12720SWyllys.Ingersoll@Sun.COM         // next message/response
2037*12720SWyllys.Ingersoll@Sun.COM         m++;
2038*12720SWyllys.Ingersoll@Sun.COM         r++;
2039*12720SWyllys.Ingersoll@Sun.COM     }
2040*12720SWyllys.Ingersoll@Sun.COM     return (PAM_SUCCESS);
2041*12720SWyllys.Ingersoll@Sun.COM 
2042*12720SWyllys.Ingersoll@Sun.COM err:
2043*12720SWyllys.Ingersoll@Sun.COM     // Service modules do not clean up responses if an error is returned.
2044*12720SWyllys.Ingersoll@Sun.COM     // Free responses here.
2045*12720SWyllys.Ingersoll@Sun.COM     for (j = 0; j < i; j++, r++)
2046*12720SWyllys.Ingersoll@Sun.COM     {
2047*12720SWyllys.Ingersoll@Sun.COM         if (r->resp)
2048*12720SWyllys.Ingersoll@Sun.COM         {
2049*12720SWyllys.Ingersoll@Sun.COM             // clear before freeing -- may be a password
2050*12720SWyllys.Ingersoll@Sun.COM             bzero(r->resp, strlen(r->resp));
2051*12720SWyllys.Ingersoll@Sun.COM             free(r->resp);
2052*12720SWyllys.Ingersoll@Sun.COM             r->resp = NULL;
2053*12720SWyllys.Ingersoll@Sun.COM         }
2054*12720SWyllys.Ingersoll@Sun.COM     }
2055*12720SWyllys.Ingersoll@Sun.COM     free(r);
2056*12720SWyllys.Ingersoll@Sun.COM     *resp = NULL;
2057*12720SWyllys.Ingersoll@Sun.COM     return error;
2058*12720SWyllys.Ingersoll@Sun.COM }
2059*12720SWyllys.Ingersoll@Sun.COM #endif
2060*12720SWyllys.Ingersoll@Sun.COM 
2061*12720SWyllys.Ingersoll@Sun.COM 
2062*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
2063*12720SWyllys.Ingersoll@Sun.COM  * Function: K_SetRootPassword
2064*12720SWyllys.Ingersoll@Sun.COM  *
2065*12720SWyllys.Ingersoll@Sun.COM  * Description:
2066*12720SWyllys.Ingersoll@Sun.COM  *  The K_SetRootPassword function sets the password for the root user via
2067*12720SWyllys.Ingersoll@Sun.COM  *  Pluggable Authentication Module (PAM).  This function is interactive.
2068*12720SWyllys.Ingersoll@Sun.COM  *
2069*12720SWyllys.Ingersoll@Sun.COM  * Input
2070*12720SWyllys.Ingersoll@Sun.COM  * -----
2071*12720SWyllys.Ingersoll@Sun.COM  *    i_sPassword      Password to set
2072*12720SWyllys.Ingersoll@Sun.COM  *
2073*12720SWyllys.Ingersoll@Sun.COM  * Output
2074*12720SWyllys.Ingersoll@Sun.COM  * ------
2075*12720SWyllys.Ingersoll@Sun.COM  *    (none)
2076*12720SWyllys.Ingersoll@Sun.COM  *
2077*12720SWyllys.Ingersoll@Sun.COM  * Return value        0 if successful, -1 on error
2078*12720SWyllys.Ingersoll@Sun.COM  *
2079*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
2080*12720SWyllys.Ingersoll@Sun.COM 
K_SetRootPassword(const char * i_sPassword)2081*12720SWyllys.Ingersoll@Sun.COM int K_SetRootPassword( const char* i_sPassword )
2082*12720SWyllys.Ingersoll@Sun.COM {
2083*12720SWyllys.Ingersoll@Sun.COM     // Only supported/tested on Solaris at the moment
2084*12720SWyllys.Ingersoll@Sun.COM #ifndef K_SOLARIS_PLATFORM
2085*12720SWyllys.Ingersoll@Sun.COM     return -1;
2086*12720SWyllys.Ingersoll@Sun.COM #else
2087*12720SWyllys.Ingersoll@Sun.COM     // Based on sample code from Solaris 10 Software Developer Collection >>
2088*12720SWyllys.Ingersoll@Sun.COM     // Solaris Security for Developers Guide >>
2089*12720SWyllys.Ingersoll@Sun.COM     // 3. Writing PAM Applications and Services
2090*12720SWyllys.Ingersoll@Sun.COM 
2091*12720SWyllys.Ingersoll@Sun.COM     // TODO: Return PAM error codes (to be logged) instead of emitting
2092*12720SWyllys.Ingersoll@Sun.COM     // messages to screen?
2093*12720SWyllys.Ingersoll@Sun.COM 
2094*12720SWyllys.Ingersoll@Sun.COM     struct pam_conv conv;
2095*12720SWyllys.Ingersoll@Sun.COM     pam_handle_t *pamh;
2096*12720SWyllys.Ingersoll@Sun.COM     int err;
2097*12720SWyllys.Ingersoll@Sun.COM 
2098*12720SWyllys.Ingersoll@Sun.COM     conv.conv = pam_tty_conv;
2099*12720SWyllys.Ingersoll@Sun.COM     conv.appdata_ptr = (void*)i_sPassword;
2100*12720SWyllys.Ingersoll@Sun.COM 
2101*12720SWyllys.Ingersoll@Sun.COM     // Initialize PAM framework
2102*12720SWyllys.Ingersoll@Sun.COM     err = pam_start("KeyMgr", "root", &conv, &pamh);
2103*12720SWyllys.Ingersoll@Sun.COM     if (err != PAM_SUCCESS)
2104*12720SWyllys.Ingersoll@Sun.COM     {
2105*12720SWyllys.Ingersoll@Sun.COM         fprintf(stderr, "PAM error: %s\n", pam_strerror(pamh, err));
2106*12720SWyllys.Ingersoll@Sun.COM         return -1;
2107*12720SWyllys.Ingersoll@Sun.COM     }
2108*12720SWyllys.Ingersoll@Sun.COM 
2109*12720SWyllys.Ingersoll@Sun.COM     // Change password
2110*12720SWyllys.Ingersoll@Sun.COM     err = pam_chauthtok(pamh, 0);
2111*12720SWyllys.Ingersoll@Sun.COM     if (err != PAM_SUCCESS)
2112*12720SWyllys.Ingersoll@Sun.COM     {
2113*12720SWyllys.Ingersoll@Sun.COM         fprintf(stderr, "PAM error: %s\n", pam_strerror(pamh, err));
2114*12720SWyllys.Ingersoll@Sun.COM         // fall through to cleanup
2115*12720SWyllys.Ingersoll@Sun.COM     }
2116*12720SWyllys.Ingersoll@Sun.COM 
2117*12720SWyllys.Ingersoll@Sun.COM     // Cleanup session
2118*12720SWyllys.Ingersoll@Sun.COM     pam_end(pamh, 0);
2119*12720SWyllys.Ingersoll@Sun.COM 
2120*12720SWyllys.Ingersoll@Sun.COM     return (err == PAM_SUCCESS) ? 0 : -1;
2121*12720SWyllys.Ingersoll@Sun.COM #endif
2122*12720SWyllys.Ingersoll@Sun.COM }
2123*12720SWyllys.Ingersoll@Sun.COM 
2124*12720SWyllys.Ingersoll@Sun.COM 
2125*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
2126*12720SWyllys.Ingersoll@Sun.COM  * Function: K_Alarm
2127*12720SWyllys.Ingersoll@Sun.COM  *
2128*12720SWyllys.Ingersoll@Sun.COM  * Description:
2129*12720SWyllys.Ingersoll@Sun.COM  *  Calls alarm(2) on Unix in order to cause the operating system to generate
2130*12720SWyllys.Ingersoll@Sun.COM  *  a SIGALRM signal for this process after the given number of real-time
2131*12720SWyllys.Ingersoll@Sun.COM  *  seconds.  Does nothing on Windows.
2132*12720SWyllys.Ingersoll@Sun.COM  *
2133*12720SWyllys.Ingersoll@Sun.COM  * Input
2134*12720SWyllys.Ingersoll@Sun.COM  * -----
2135*12720SWyllys.Ingersoll@Sun.COM  *    i_iSeconds       Number of seconds after which to generate a SIGALRM
2136*12720SWyllys.Ingersoll@Sun.COM  *                     signal
2137*12720SWyllys.Ingersoll@Sun.COM  *
2138*12720SWyllys.Ingersoll@Sun.COM  * Output
2139*12720SWyllys.Ingersoll@Sun.COM  * ------
2140*12720SWyllys.Ingersoll@Sun.COM  *    (none)
2141*12720SWyllys.Ingersoll@Sun.COM  *
2142*12720SWyllys.Ingersoll@Sun.COM  * Return value        If a previous alarm request is pending, then it returns
2143*12720SWyllys.Ingersoll@Sun.COM  *                     the number of seconds until this previous request would
2144*12720SWyllys.Ingersoll@Sun.COM  *                     have generated a SIGALRM signal.  Otherwise, returns 0.
2145*12720SWyllys.Ingersoll@Sun.COM  *
2146*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
2147*12720SWyllys.Ingersoll@Sun.COM 
K_Alarm(unsigned int i_iSeconds)2148*12720SWyllys.Ingersoll@Sun.COM unsigned int K_Alarm( unsigned int i_iSeconds )
2149*12720SWyllys.Ingersoll@Sun.COM {
2150*12720SWyllys.Ingersoll@Sun.COM #ifndef WIN32
2151*12720SWyllys.Ingersoll@Sun.COM     return alarm( i_iSeconds );
2152*12720SWyllys.Ingersoll@Sun.COM #else
2153*12720SWyllys.Ingersoll@Sun.COM     return 0;
2154*12720SWyllys.Ingersoll@Sun.COM #endif
2155*12720SWyllys.Ingersoll@Sun.COM }
2156*12720SWyllys.Ingersoll@Sun.COM 
2157*12720SWyllys.Ingersoll@Sun.COM 
2158*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
2159*12720SWyllys.Ingersoll@Sun.COM  * Function: K_GetExtendedVersionFromBase
2160*12720SWyllys.Ingersoll@Sun.COM  *
2161*12720SWyllys.Ingersoll@Sun.COM  * Description:
2162*12720SWyllys.Ingersoll@Sun.COM  *  This KMS-specific function prepends the timestamp value to the specified
2163*12720SWyllys.Ingersoll@Sun.COM  *  base replication schema version and returns this value as an extended
2164*12720SWyllys.Ingersoll@Sun.COM  *  replication schema version.
2165*12720SWyllys.Ingersoll@Sun.COM  *
2166*12720SWyllys.Ingersoll@Sun.COM  * Input
2167*12720SWyllys.Ingersoll@Sun.COM  * -----
2168*12720SWyllys.Ingersoll@Sun.COM  *    i_iBaseSchemaVersion  Base replication schema version
2169*12720SWyllys.Ingersoll@Sun.COM  *
2170*12720SWyllys.Ingersoll@Sun.COM  * Output
2171*12720SWyllys.Ingersoll@Sun.COM  * ------
2172*12720SWyllys.Ingersoll@Sun.COM  *    (none)
2173*12720SWyllys.Ingersoll@Sun.COM  *
2174*12720SWyllys.Ingersoll@Sun.COM  * Return value        Extended replication schema version
2175*12720SWyllys.Ingersoll@Sun.COM  *
2176*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
2177*12720SWyllys.Ingersoll@Sun.COM 
K_GetExtendedVersionFromBase(unsigned int i_iBaseSchemaVersion)2178*12720SWyllys.Ingersoll@Sun.COM unsigned int K_GetExtendedVersionFromBase( unsigned int i_iBaseSchemaVersion )
2179*12720SWyllys.Ingersoll@Sun.COM {
2180*12720SWyllys.Ingersoll@Sun.COM     // seconds since 1970, force to 32-bit
2181*12720SWyllys.Ingersoll@Sun.COM #ifdef WIN32
2182*12720SWyllys.Ingersoll@Sun.COM     INT32 iTimeStamp = (INT32) time(NULL);
2183*12720SWyllys.Ingersoll@Sun.COM #else
2184*12720SWyllys.Ingersoll@Sun.COM     int32_t iTimeStamp = (int32_t) time(NULL);
2185*12720SWyllys.Ingersoll@Sun.COM #endif
2186*12720SWyllys.Ingersoll@Sun.COM     // minutes since 1970
2187*12720SWyllys.Ingersoll@Sun.COM     iTimeStamp = iTimeStamp / 60;
2188*12720SWyllys.Ingersoll@Sun.COM     // minutes since 2000 (approximately)
2189*12720SWyllys.Ingersoll@Sun.COM     iTimeStamp -= (30*365*24*60);
2190*12720SWyllys.Ingersoll@Sun.COM     // shift 8 bits to clear out room for schema version #
2191*12720SWyllys.Ingersoll@Sun.COM     iTimeStamp = iTimeStamp << 8;
2192*12720SWyllys.Ingersoll@Sun.COM     // add schema version # to lower end
2193*12720SWyllys.Ingersoll@Sun.COM     iTimeStamp |= i_iBaseSchemaVersion;
2194*12720SWyllys.Ingersoll@Sun.COM 
2195*12720SWyllys.Ingersoll@Sun.COM     return (unsigned int) iTimeStamp;
2196*12720SWyllys.Ingersoll@Sun.COM 
2197*12720SWyllys.Ingersoll@Sun.COM }
2198*12720SWyllys.Ingersoll@Sun.COM 
2199*12720SWyllys.Ingersoll@Sun.COM 
2200*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
2201*12720SWyllys.Ingersoll@Sun.COM  * Function: K_ParseTimestampFromExtendedVersion
2202*12720SWyllys.Ingersoll@Sun.COM  *
2203*12720SWyllys.Ingersoll@Sun.COM  * Description:
2204*12720SWyllys.Ingersoll@Sun.COM  *  This KMS-specific function parses the timestamp value from the given
2205*12720SWyllys.Ingersoll@Sun.COM  *  extended replication schema version and returns this timestamp value.
2206*12720SWyllys.Ingersoll@Sun.COM  *
2207*12720SWyllys.Ingersoll@Sun.COM  * Input
2208*12720SWyllys.Ingersoll@Sun.COM  * -----
2209*12720SWyllys.Ingersoll@Sun.COM  *    i_iExtendedSchemaVersion  Extended replication schema version
2210*12720SWyllys.Ingersoll@Sun.COM  *
2211*12720SWyllys.Ingersoll@Sun.COM  * Output
2212*12720SWyllys.Ingersoll@Sun.COM  * ------
2213*12720SWyllys.Ingersoll@Sun.COM  *    (none)
2214*12720SWyllys.Ingersoll@Sun.COM  *
2215*12720SWyllys.Ingersoll@Sun.COM  * Return value        Timestamp value
2216*12720SWyllys.Ingersoll@Sun.COM  *
2217*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
2218*12720SWyllys.Ingersoll@Sun.COM 
K_ParseTimestampFromExtendedVersion(unsigned int i_iExtendedSchemaVersion)2219*12720SWyllys.Ingersoll@Sun.COM unsigned int K_ParseTimestampFromExtendedVersion(
2220*12720SWyllys.Ingersoll@Sun.COM     unsigned int i_iExtendedSchemaVersion )
2221*12720SWyllys.Ingersoll@Sun.COM {
2222*12720SWyllys.Ingersoll@Sun.COM     unsigned int iTimeStamp = i_iExtendedSchemaVersion >> 8;
2223*12720SWyllys.Ingersoll@Sun.COM 
2224*12720SWyllys.Ingersoll@Sun.COM     return iTimeStamp;
2225*12720SWyllys.Ingersoll@Sun.COM }
2226*12720SWyllys.Ingersoll@Sun.COM 
2227*12720SWyllys.Ingersoll@Sun.COM 
2228*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
2229*12720SWyllys.Ingersoll@Sun.COM  * Function: K_ParseBaseFromExtendedVersion
2230*12720SWyllys.Ingersoll@Sun.COM  *
2231*12720SWyllys.Ingersoll@Sun.COM  * Description:
2232*12720SWyllys.Ingersoll@Sun.COM  *  This KMS-specific function parses the base replication schema value from
2233*12720SWyllys.Ingersoll@Sun.COM  *  the given extended replication schema version and returns this base value.
2234*12720SWyllys.Ingersoll@Sun.COM  *
2235*12720SWyllys.Ingersoll@Sun.COM  * Input
2236*12720SWyllys.Ingersoll@Sun.COM  * -----
2237*12720SWyllys.Ingersoll@Sun.COM  *    i_iExtendedSchemaVersion  Extended replication schema version
2238*12720SWyllys.Ingersoll@Sun.COM  *
2239*12720SWyllys.Ingersoll@Sun.COM  * Output
2240*12720SWyllys.Ingersoll@Sun.COM  * ------
2241*12720SWyllys.Ingersoll@Sun.COM  *    (none)
2242*12720SWyllys.Ingersoll@Sun.COM  *
2243*12720SWyllys.Ingersoll@Sun.COM  * Return value        Base replication schema value
2244*12720SWyllys.Ingersoll@Sun.COM  *
2245*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
2246*12720SWyllys.Ingersoll@Sun.COM 
K_ParseBaseFromExtendedVersion(unsigned int i_iExtendedSchemaVersion)2247*12720SWyllys.Ingersoll@Sun.COM unsigned int K_ParseBaseFromExtendedVersion(
2248*12720SWyllys.Ingersoll@Sun.COM     unsigned int i_iExtendedSchemaVersion )
2249*12720SWyllys.Ingersoll@Sun.COM {
2250*12720SWyllys.Ingersoll@Sun.COM     unsigned int iBaseSchemaVersion = i_iExtendedSchemaVersion & 0x000000FF;
2251*12720SWyllys.Ingersoll@Sun.COM 
2252*12720SWyllys.Ingersoll@Sun.COM     return iBaseSchemaVersion;
2253*12720SWyllys.Ingersoll@Sun.COM }
2254*12720SWyllys.Ingersoll@Sun.COM 
2255*12720SWyllys.Ingersoll@Sun.COM 
2256*12720SWyllys.Ingersoll@Sun.COM /*---------------------------------------------------------------------------
2257*12720SWyllys.Ingersoll@Sun.COM  * Function: K_System
2258*12720SWyllys.Ingersoll@Sun.COM  *
2259*12720SWyllys.Ingersoll@Sun.COM  * Description:
2260*12720SWyllys.Ingersoll@Sun.COM  *  This function is a thread-safe replacement for the unsafe system(3C) call.
2261*12720SWyllys.Ingersoll@Sun.COM  *  See the popen(3C) man page for more information.
2262*12720SWyllys.Ingersoll@Sun.COM  *
2263*12720SWyllys.Ingersoll@Sun.COM  * Input
2264*12720SWyllys.Ingersoll@Sun.COM  * -----
2265*12720SWyllys.Ingersoll@Sun.COM  *    i_sCmd           Command to execute
2266*12720SWyllys.Ingersoll@Sun.COM  *
2267*12720SWyllys.Ingersoll@Sun.COM  * Output
2268*12720SWyllys.Ingersoll@Sun.COM  * ------
2269*12720SWyllys.Ingersoll@Sun.COM  *    (none)
2270*12720SWyllys.Ingersoll@Sun.COM  *
2271*12720SWyllys.Ingersoll@Sun.COM  * Return value        Termination status of the command language interpreter
2272*12720SWyllys.Ingersoll@Sun.COM  *                     if successful, -1 on failure
2273*12720SWyllys.Ingersoll@Sun.COM  *
2274*12720SWyllys.Ingersoll@Sun.COM  *--------------------------------------------------------------------------*/
2275*12720SWyllys.Ingersoll@Sun.COM 
K_System(const char * i_sCmd)2276*12720SWyllys.Ingersoll@Sun.COM int K_System( const char *i_sCmd )
2277*12720SWyllys.Ingersoll@Sun.COM {
2278*12720SWyllys.Ingersoll@Sun.COM #ifndef WIN32
2279*12720SWyllys.Ingersoll@Sun.COM         FILE *p;
2280*12720SWyllys.Ingersoll@Sun.COM         int rc;
2281*12720SWyllys.Ingersoll@Sun.COM         struct sigaction sOldAction;
2282*12720SWyllys.Ingersoll@Sun.COM 
2283*12720SWyllys.Ingersoll@Sun.COM         // Save signal handler
2284*12720SWyllys.Ingersoll@Sun.COM         sigaction( SIGCHLD, NULL, &sOldAction );
2285*12720SWyllys.Ingersoll@Sun.COM 
2286*12720SWyllys.Ingersoll@Sun.COM         // Use default child signal handler
2287*12720SWyllys.Ingersoll@Sun.COM         sigset( SIGCHLD, SIG_DFL );
2288*12720SWyllys.Ingersoll@Sun.COM 
2289*12720SWyllys.Ingersoll@Sun.COM         p = popen( i_sCmd, "w" );
2290*12720SWyllys.Ingersoll@Sun.COM         if ( p == NULL )
2291*12720SWyllys.Ingersoll@Sun.COM         {
2292*12720SWyllys.Ingersoll@Sun.COM             rc = -1;
2293*12720SWyllys.Ingersoll@Sun.COM         }
2294*12720SWyllys.Ingersoll@Sun.COM         else
2295*12720SWyllys.Ingersoll@Sun.COM         {
2296*12720SWyllys.Ingersoll@Sun.COM             rc = pclose( p );
2297*12720SWyllys.Ingersoll@Sun.COM         }
2298*12720SWyllys.Ingersoll@Sun.COM 
2299*12720SWyllys.Ingersoll@Sun.COM         // Reset signal handler
2300*12720SWyllys.Ingersoll@Sun.COM         sigset( SIGCHLD, sOldAction.sa_handler );
2301*12720SWyllys.Ingersoll@Sun.COM 
2302*12720SWyllys.Ingersoll@Sun.COM         return rc;
2303*12720SWyllys.Ingersoll@Sun.COM #else
2304*12720SWyllys.Ingersoll@Sun.COM         return system( i_sCmd );
2305*12720SWyllys.Ingersoll@Sun.COM #endif
2306*12720SWyllys.Ingersoll@Sun.COM }
2307*12720SWyllys.Ingersoll@Sun.COM 
2308