(file) Return to util.c CVS log (file) (dir) Up to [OMI] / omi / tests / util

  1 krisbash 1.1 /*
  2              **==============================================================================
  3              **
  4              ** Open Management Infrastructure (OMI)
  5              **
  6              ** Copyright (c) Microsoft Corporation
  7              ** 
  8              ** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
  9              ** use this file except in compliance with the License. You may obtain a copy 
 10              ** of the License at 
 11              **
 12              **     http://www.apache.org/licenses/LICENSE-2.0 
 13              **
 14              ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15              ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
 16              ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
 17              ** MERCHANTABLITY OR NON-INFRINGEMENT. 
 18              **
 19              ** See the Apache 2 License for the specific language governing permissions 
 20              ** and limitations under the License.
 21              **
 22 krisbash 1.1 **==============================================================================
 23              */
 24              
 25              #include <ctype.h>
 26              #include <time.h>
 27              #include <pal/file.h>
 28              #include <pal/strings.h>
 29              #include <pal/format.h>
 30              #include <base/process.h>
 31              #include <pal/sleep.h>
 32              #include <base/paths.h>
 33              #include <base/log.h>
 34              #include <pal/dir.h>
 35              #include <pal/lock.h>
 36              #include "util.h"
 37              
 38              #ifdef _MSC_VER
 39              # include <windows.h>
 40              # include <shlobj.h>
 41              #else
 42              # include <unistd.h>
 43 krisbash 1.1 # include <sys/types.h>
 44              # include <sys/time.h>
 45              # include <pwd.h>
 46              # include <unistd.h>
 47              #endif
 48              
 49              #ifdef _PREFAST_
 50                  #pragma prefast(push)
 51                  /* ANSI API ('SHGetFolderPathA') should not be called from Unicode modules. */
 52                  /* Calling ANSI APIs leads to unexpected results when handling multi-lingual */
 53                  /* text or Unicode-only languages. Use the Unicode version of this API instead.*/
 54                  #pragma prefast(disable:38020)
 55              #endif
 56              
 57              /* get user home directory */
 58              const char* gethomedir()
 59              {
 60              #ifdef _MSC_VER
 61                  static char path[MAX_PATH];
 62                  if (SHGetFolderPathA( NULL, CSIDL_PROFILE, NULL, 0, path ) != S_OK)
 63                  {
 64 krisbash 1.1         path[0] = '\0';
 65                  }
 66                  return (const char *)path;
 67              #else
 68                  struct passwd *pw = getpwuid(getuid());
 69                  return pw->pw_dir;
 70              #endif
 71              }
 72              
 73              MI_Char* ansiToMI(const char* src)
 74              {
 75                  MI_Char* mistr = NULL;
 76                  if (g_batch && src)
 77                  {
 78                      MI_Uint32 size = strlen(src) + 1;
 79                      mistr = (MI_Char*) Batch_Get(g_batch, size*sizeof(MI_Char));
 80                      if (mistr)
 81                      {
 82                          MI_Uint32 i;
 83                          for (i = 0; i < size; i++)
 84                          {
 85 krisbash 1.1                 mistr[i] = (MI_Char)src[i];
 86                          }
 87                      }
 88                  }
 89                  return mistr;
 90              }
 91              
 92              char* MIToansi(const MI_Char* src)
 93              {
 94              #if (MI_CHAR_TYPE == 2)
 95                  char* str = NULL;
 96                  if (g_batch && src)
 97                  {
 98                      MI_Uint32 size = wcslen(src) + 1;
 99                      str = (char*) Batch_Get(g_batch, size*sizeof(char));
100                      if (str)
101                      {
102                          MI_Uint32 i;
103                          for (i = 0; i < size; i++)
104                          {
105                              str[i] = (char)src[i];
106 krisbash 1.1             }
107                      }
108                  }
109                  return str;
110              #else
111                  return (char*)src;
112              #endif
113              }
114              
115              int StringCompare(const MI_Char* s1, const MI_Char* s2)
116              {
117                  return Tcscasecmp(s1, s2);
118              }
119              
120              int __GetCurrentTimeInUsec(MI_Uint64* usec)
121              {
122              #if defined(CONFIG_OS_WINDOWS)
123                  FILETIME ft;
124                  ULARGE_INTEGER tmp;
125              
126                  GetSystemTimeAsFileTime(&ft);
127 krisbash 1.1     tmp.u.LowPart = ft.dwLowDateTime;
128                  tmp.u.HighPart = ft.dwHighDateTime;
129                  tmp.QuadPart -= 0X19DB1DED53E8000;
130                  *usec = tmp.QuadPart / (UINT64)10;
131              
132                  return 0;
133              #else
134                  struct timeval tv;
135                  struct timezone tz;
136                  memset(&tv, 0, sizeof(tv));
137                  memset(&tz, 0, sizeof(tz));
138              
139                  if (gettimeofday(&tv, &tz) != 0)
140                      return -1;
141              
142                  *usec = (MI_Uint64)tv.tv_sec * (MI_Uint64)1000000 + (MI_Uint64)tv.tv_usec;
143                  return 0;
144              #endif
145              }
146              
147              #define TIMESTAMP_SIZE 256
148 krisbash 1.1 static int __GetTimeStamp(_Pre_writable_size_(TIMESTAMP_SIZE) char buf[TIMESTAMP_SIZE])
149              {
150              #if defined(CONFIG_OS_WINDOWS)
151                  {
152                      SYSTEMTIME systime;
153                      GetLocalTime(&systime);
154              
155                      sprintf_s(
156                          buf,
157                          TIMESTAMP_SIZE,
158                          "%02u/%02u/%02u %02u:%02u:%02u",
159                          systime.wYear,
160                          systime.wMonth,
161                          systime.wDay,
162                          systime.wHour,
163                          systime.wMinute,
164                          systime.wSecond);
165                  }
166              #else
167                  MI_Uint64 usec;
168              
169 krisbash 1.1     if (__GetCurrentTimeInUsec(&usec) != 0)
170                  {
171                      buf[0] = '\0';
172                      return -1;
173                  }
174              
175                  {
176                      time_t t = usec / 1000000;
177                      struct tm tm;
178                      localtime_r(&t, &tm);
179                      sprintf(
180                          buf,
181                          "%02u/%02u/%02u %02u:%02u:%02u",
182                          tm.tm_year + 1900,
183                          tm.tm_mon + 1,
184                          tm.tm_mday,
185                          tm.tm_hour,
186                          tm.tm_min,
187                          tm.tm_sec);
188                  }
189              #endif
190 krisbash 1.1 
191                  return 0;
192              }
193              
194              static void _PrintThreadID(FILE* f)
195              {
196                  ThreadID currentthread = Thread_ID();
197              #ifdef _MSC_VER
198                  fprintf(f, "Thread: 0x%x", (unsigned int)(currentthread.__impl));
199              #else
200                  size_t i;
201                  size_t threadsize = sizeof(currentthread.__impl);
202                  unsigned char *ptc = (unsigned char*)(void*)(&currentthread.__impl);
203                  fprintf(f, "Thread: 0x");
204                  for(i=0; i < threadsize; i++) {
205                      fprintf(f, "%02x", (unsigned)(ptc[i]));
206                  }
207              #endif
208              }
209              
210              void _WriteHeader(
211 krisbash 1.1     const char* file,
212                  unsigned int line)
213              {
214                  char buf[256];
215                  __GetTimeStamp(buf);
216                  _PrintThreadID(g_logfile);
217                  fprintf(g_logfile, " : %s : ", buf);
218                  if (file)
219                      fprintf(g_logfile, "%s(%u): ", file, line);
220              }
221              
222              void WriteLog(const char* fmt, ...)
223              {
224                  if (g_logfile)
225                  {
226                      va_list ap;
227                      memset(&ap, 0, sizeof(ap));
228                      va_start(ap, fmt);
229                      Vfprintf(g_logfile, fmt, ap);
230                      va_end(ap);
231              
232 krisbash 1.1         fprintf(g_logfile, "\r\n");
233                      FlushLog(g_logfile);
234                  }
235              }
236              
237              void FlushLog(FILE* file)
238              {
239                  if (file)
240                  {
241                      fflush(file);
242                      //File_Close(g_logfile);
243                      //g_logfile = File_Open(g_logfilepath, "a+");
244                  }
245              }
246              
247              
248              /*
249              **==============================================================================
250              **
251              ** Consume instance
252              **
253 krisbash 1.1 **==============================================================================
254              */
255              static MI_Result _ConsumeInstanceResults(
256                  _In_ InstanceOperationStruct* ios,
257                  _In_ MI_Operation *miOperation)
258              {
259                  MI_Result miResult = MI_RESULT_FAILED;
260                  MI_Boolean moreResults = MI_FALSE;
261              
262                  if (MI_TRUE == ios->sync)
263                  {
264                      do
265                      {
266                          const MI_Instance *miInstanceResult = NULL;
267                          MI_Result _miResult;
268                          const MI_Char *errorString = NULL;
269                          const MI_Instance *errorDetails = NULL;
270              
271                          _miResult = MI_Operation_GetInstance(
272                              miOperation,
273                              &miInstanceResult,
274 krisbash 1.1                 &moreResults,
275                              &miResult,
276                              &errorString,
277                              &errorDetails);
278                          if (_miResult != MI_RESULT_OK)
279                          {
280                              miResult = _miResult;
281                          }
282                          if (miInstanceResult)
283                              ios->count++;
284                      } while ((miResult == MI_RESULT_OK) && (moreResults == MI_TRUE));
285                  }
286                  else
287                  {
288                      ptrdiff_t finished;
289                      finished = ios->finished;
290                      while (!finished)
291                      {
292                          CondLock_Wait((ptrdiff_t)&ios->finished, &ios->finished, finished, CONDLOCK_DEFAULT_SPINCOUNT);
293                          finished = ios->finished;
294                          miResult = ios->finalResult;
295 krisbash 1.1         }
296                  }
297              
298                  return miResult;
299              }
300              
301              /*
302              **==============================================================================
303              **
304              ** Async operation, the callback to receive instance results
305              **
306              **==============================================================================
307              */
308              static MI_Result g_finalResult;
309              static MI_Boolean g_called;
310              static MI_Boolean g_moreResults;
311              void MI_CALL _InstanceResultCallback(
312                  _In_opt_     MI_Operation *operation,
313                  _In_     void *callbackContext,
314                  _In_opt_ const MI_Instance *instance,
315                           MI_Boolean moreResults,
316 krisbash 1.1     _In_     MI_Result resultCode,
317                  _In_opt_z_ const MI_Char *errorString,
318                  _In_opt_ const MI_Instance *errorDetails,
319                  _In_opt_ MI_Result (MI_CALL * resultAcknowledgement)(_In_ MI_Operation *operation))
320              {
321                  InstanceOperationStruct* ios = (InstanceOperationStruct*)callbackContext;
322                  if (instance)
323                      ios->count ++;
324                  if (moreResults == MI_FALSE)
325                  {
326                      ios->finalResult = resultCode;
327                      ios->finished = 1;
328                      CondLock_Broadcast((ptrdiff_t)&ios->finished);
329                  }
330                  g_finalResult = resultCode;
331                  g_called = MI_TRUE;
332                  g_moreResults = moreResults;
333              }
334              
335              /*
336              **==============================================================================
337 krisbash 1.1 **
338              ** Read instance for given class
339              **
340              **==============================================================================
341              */
342              _Use_decl_annotations_
343              MI_Result EnumerateInstance(
344                  InstanceOperationStruct* ios,
345                  const MI_Char* nameSpace,
346                  const MI_Char* className)
347              {
348                  MI_Result miResult;
349                  MI_Operation miOperation = MI_OPERATION_NULL;
350                  MI_OperationCallbacks _callbacks = MI_OPERATIONCALLBACKS_NULL;
351                  MI_OperationCallbacks *callbacks = NULL;
352              
353                  if (ios->sync == MI_FALSE)
354                  {
355                      _callbacks.callbackContext = ios;
356                      _callbacks.instanceResult = _InstanceResultCallback;
357                      callbacks = &_callbacks;
358 krisbash 1.1         ios->finished = 0;
359                      ios->finalResult = MI_RESULT_FAILED;
360                  }
361              
362                  MI_Session_EnumerateInstances(&ios->session, 0, NULL, nameSpace, className, MI_FALSE, callbacks, &miOperation);
363                  miResult = _ConsumeInstanceResults(ios, &miOperation);
364                  MI_Operation_Close(&miOperation);
365                  return miResult;
366              }
367              
368              
369              static Process serverProcess;
370              MI_Char s_socketFile[PAL_MAX_PATH_SIZE];
371              char s_socketFile_a[PAL_MAX_PATH_SIZE];
372              
373              /*
374              **==============================================================================
375              **
376              ** Remember if the server is started or not
377              **
378              **==============================================================================
379 krisbash 1.1 */
380              int g_serverstarted = 0;
381              
382              #if defined(_MSC_VER)
383              unsigned short _GetUnittestPortNumber()
384              {
385                  return 21718;
386              }
387              #else
388              unsigned short _GetUnittestPortNumber()
389              {
390                  return 10000 + ((geteuid() % 200) * 200);
391              }
392              #endif
393              unsigned short UnittestPortNumberWSMANHTTP()
394              {
395                  return _GetUnittestPortNumber() + 198;
396              }
397              unsigned short UnittestPortNumberWSMANHTTPS()
398              {
399                  return _GetUnittestPortNumber() + 197;
400 krisbash 1.1 }
401              
402              MI_Result StartOmiserver()
403              {
404                  const char* path = OMI_GetPath(ID_SERVERPROGRAM);
405                  const char* argv[17];
406                  char http[32];
407                  char https[32];
408                  int i;
409                  InstanceOperationStruct ios;
410                  MI_Result r;
411              
412                  memset(&ios, 0, sizeof(InstanceOperationStruct));
413              
414                  //
415                  // kill running omiserver if have any
416                  //
417                  {
418                      char buf[64];
419                      sprintf(buf, "pkill -9 %s", "omiserver");
420                      system(buf);
421 krisbash 1.1         Sleep_Milliseconds(10);
422                  }
423              
424                  Snprintf(http, sizeof(http),"%d", UnittestPortNumberWSMANHTTP());
425                  Snprintf(https, sizeof(https),"%d", UnittestPortNumberWSMANHTTPS());
426              
427                  Strlcpy(s_socketFile_a, OMI_GetPath(ID_SOCKETFILE), sizeof(s_socketFile_a)/sizeof(s_socketFile_a[0]));
428                  TcsStrlcpy(s_socketFile, s_socketFile_a, sizeof(s_socketFile)/sizeof(s_socketFile[0]));
429              
430                  argv[0] = path;
431                  argv[1] = "--rundir";
432              #if defined(CONFIG_OS_WINDOWS)
433                  argv[2] = "..";
434              #else
435                  argv[2] = OMI_GetPath(ID_PREFIX);
436              #endif
437                  argv[3] = "--ignoreAuthentication";
438                  argv[4] = "--socketfile";
439                  argv[5] = s_socketFile_a;
440                  argv[6] = "--httpport";
441                  argv[7] = http;
442 krisbash 1.1     argv[8] = "--httpsport";
443                  argv[9] = https;
444                  argv[10] = "--livetime";
445                  argv[11] = "1800";
446              
447                  argv[12] = "--loglevel";
448                  argv[13] = Log_GetLevelString(Log_GetLevel());
449                  argv[14] = NULL;
450              
451                  if (Process_StartChild(&serverProcess, path, (char**)argv) != 0)
452                  {
453                      NitsAssert(0, PAL_T("Failed to create omiserver process"));
454                      return MI_RESULT_FAILED;
455                  }
456              
457                  g_serverstarted = 1;
458              
459                  /*  wait for server to start */
460                  r = MI_Application_Initialize(0, NULL, NULL, &ios.app);
461                  if (r != MI_RESULT_OK)
462                  {
463 krisbash 1.1         NitsAssert(0, PAL_T("Failed to Initialize MI_Application"));
464                      return r;
465                  }
466              
467                  for (i = 0; i < 100; i++)
468                  {
469                      Sleep_Milliseconds(50);
470                      r = MI_Application_NewSession(&ios.app, NULL, NULL, NULL, NULL, NULL, &ios.session);
471                      if (r == MI_RESULT_OK)
472                      {
473                          break;
474                      }
475                  }
476              
477                  if (r != MI_RESULT_OK)
478                  {
479                      NitsAssert(0, PAL_T("Failed to create session"));
480                      MI_Application_Close(&ios.app);
481                      return r;
482                  }
483              
484 krisbash 1.1     /* TODO: Use MI_Session_TestConnection if it is implemented */
485                  for (i = 0; i < 1000; i++)
486                  {
487                      g_finalResult = MI_RESULT_OK;
488                      g_called = MI_FALSE;
489                      g_moreResults = MI_FALSE;
490                      r = EnumerateInstance(&ios, MI_T("root/omi"), MI_T("omi_identify"));
491                      if (r == MI_RESULT_OK)
492                      {
493                          break;
494                      }
495                      Sleep_Milliseconds(50);
496                  }
497                  if (r != MI_RESULT_OK)
498                  {
499                      NitsAssert(0, PAL_T("Failed to enumerate omi_identify instance"));
500                  }
501                  MI_Session_Close(&ios.session, NULL, NULL);
502                  MI_Application_Close(&ios.app);
503                  return r;
504              }
505 krisbash 1.1 
506              MI_Result StopOmiserver()
507              {
508                  MI_Result r = MI_RESULT_OK;
509                  if (g_serverstarted == 1)
510                  {
511                      /*
512                       * For e2e test, server might be busy, and e2e cancellation is not complete yet,
513                       * sleep two seconds to mitigate server hang issues during shutting down.
514                       */
515                      Sleep_Milliseconds(2000);
516                      if (Process_StopChild(&serverProcess) != 0)
517                      {
518                          memset((void*)&serverProcess, 0, sizeof(Process));
519                          r = MI_RESULT_FAILED;
520                      }
521                      g_serverstarted = 0;
522                  }
523                  return r;
524              }
525              
526 krisbash 1.1 
527              /*
528              **==============================================================================
529              **
530              ** string hash function
531              **
532              **==============================================================================
533              */
534              
535              /* A number used to caculate hash value */
536              #define HASH_SEED_PRIME_NUMBER 1313038763
537              
538              /* String hash algorithm */
539              PAL_EXTERN_C size_t StringHash(_In_ const HashBucket* bucket)
540              {
541                  StringBucket* strbucket = (StringBucket*)bucket;
542                  size_t hash = HASH_SEED_PRIME_NUMBER;
543                  const MI_Char* p = strbucket->key;
544                  while(*p)
545                  {
546                      hash ^= ((hash << 5) + tolower(*p) + (hash >> 2));
547 krisbash 1.1         p++;
548                  }
549                  return hash;
550              }
551              
552              PAL_EXTERN_C int StringBucketEqual(
553                  const HashBucket* bucket1_,
554                  const HashBucket* bucket2_)
555              {
556                  StringBucket* bucket1 = (StringBucket*)bucket1_;
557                  StringBucket* bucket2 = (StringBucket*)bucket2_;
558                  return Tcscasecmp(bucket1->key, bucket2->key) == 0;
559              }
560              
561              PAL_EXTERN_C void StringBucketRelease(
562                  HashBucket* bucket_)
563              {
564                  StringBucket* bucket = (StringBucket*)bucket_;
565                  PAL_Free(bucket->key);
566                  PAL_Free(bucket);
567              }
568 krisbash 1.1 
569              _Use_decl_annotations_
570              int StringHashMap_Init(
571                  StringHashMap* self)
572              {
573                  return HashMap_Init(&self->map, 32, StringHash, StringBucketEqual, StringBucketRelease);
574              }
575              
576              _Use_decl_annotations_
577              void StringHashMap_Destroy(
578                  StringHashMap* self)
579              {
580                  HashMap_Destroy(&self->map);
581              }
582              
583              /* returns:
584                 -  non-null : found
585                 -  null     : key not present
586              */ 
587              _Use_decl_annotations_
588              StringBucket* StringHashMap_Find(
589 krisbash 1.1     StringHashMap* self,
590                  const MI_Char* key)
591              {
592                  StringBucket b;
593                  b.key = (MI_Char*)key;
594                  return (StringBucket*)HashMap_Find(&self->map, (const HashBucket*)&b);
595              }
596              
597              /* returns:
598                 -  0 : inserted the new item
599                 -  1 : the item is already present (and HashMap was not modified)
600                 - -1 : out of memory
601              
602                 (there are no failure paths / no other return value is possible)
603              */
604              _Use_decl_annotations_
605              int StringHashMap_Insert(
606                  StringHashMap* self,
607                  const MI_Char* key)
608              {
609                  StringBucket *b;
610 krisbash 1.1     b = (StringBucket*)PAL_Calloc( 1, sizeof(StringBucket) );
611                  if ( b )
612                  {
613                      b->key = PAL_Tcsdup( key );
614                      b->count = 0;
615                      return HashMap_Insert( &self->map, (HashBucket*)b );
616                  }
617                  return -1;
618              }
619              
620              /* returns:
621                 -  0 : success
622                 - -1 : key not found - hashmap remains unchanged.
623              */
624              _Use_decl_annotations_
625              int StringHashMap_Remove(
626                  StringHashMap* self,
627                  const MI_Char* key)
628              {
629                  StringBucket b;
630                  b.key = (MI_Char*)key;
631 krisbash 1.1     return HashMap_Remove(&self->map, (const HashBucket*)&b);
632              }
633              
634              
635              /* 
636                 Returns one element from the hash table. May be invoked
637                 multiple times (e.g. if you remove the element), returning
638                 null when empty.
639               
640                 *iter should be zero initialized before first call
641              */
642              _Use_decl_annotations_
643              const StringBucket* StringHashMap_Top(
644                  StringHashMap* self,
645                  size_t *iter)
646              {
647                  return (StringBucket*) HashMap_Top( &self->map, iter );
648              }
649              
650              MI_Result StartServer_Assert()
651              {
652 krisbash 1.1 # if !defined(_MSC_VER)
653                  MI_Result r = StartOmiserver();
654                  NitsAssert(r == MI_RESULT_OK, PAL_T("Failed to start Omiserver"));
655                  return r;
656              #else
657                  return MI_RESULT_OK;
658              #endif
659              }
660              
661              MI_Result StopServer_Assert()
662              {
663              # if !defined(_MSC_VER)
664                  MI_Result r = StopOmiserver();
665                  NitsAssert(r == MI_RESULT_OK, PAL_T("Failed to stop Omiserver"));
666                  return r;
667              #else
668                  return MI_RESULT_OK;
669              #endif
670              }
671              
672              #ifdef _PREFAST_
673 krisbash 1.1     #pragma prefast(pop)
674              #endif

ViewCVS 0.9.2