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

  1 mike  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 mike  1.1 **==============================================================================
 23           */
 24           
 25           #include <stdio.h>
 26           #include <ctype.h>
 27 krisbash 1.3 #include <pal/strings.h>
 28 mike     1.1 #include <base/list.h>
 29 krisbash 1.3 #include <pal/format.h>
 30              #include <pal/file.h>
 31              #include <base/log.h>
 32 mike     1.1 #include "regfile.h"
 33              
 34 krisbash 1.3 #define REG_INDICATION_CLASS "INDICATIONCLASS"
 35              
 36 mike     1.1 // Parse an identifies of the form "[A-Za-z_][A-Za-z_0-9]*"
 37 krisbash 1.3 _Return_type_success_(return == 0)
 38              static int _ParseIdentifier(_Inout_ CharPtr* pOut, _Out_ CharPtr* start, _Out_ CharPtr* end)
 39 mike     1.1 {
 40                  char* p = *pOut;
 41              
 42                  /* Skip leading whitespace */
 43 krisbash 1.3     while (*p && isspace((unsigned char)(*p)))
 44 mike     1.1         p++;
 45              
 46                  /* Set start of identifier */
 47                  *start = p;
 48              
 49                  /* Expect [A-Za-z_] characters */
 50                  if (!isalpha((unsigned char)(*p)) && *p != '_')
 51                      return -1;
 52              
 53                  /* Skip [A-Za-z_0-9] characters */
 54 krisbash 1.3     while (*p && (isalnum((unsigned char)(*p)) || *p == '_'))
 55 mike     1.1         p++;
 56              
 57                  /* Set end of identifier */
 58                  *end = p;
 59              
 60                  *pOut = p;
 61                  return 0;
 62              }
 63              
 64              // Parase class path of the form "CLASS1:CLASS2:CLASS3"
 65 krisbash 1.3 _Return_type_success_(return == 0)
 66              static int _ParseClassPath(_Inout_ CharPtr* pOut, _Out_ CharPtr* start, _Out_ CharPtr* end)
 67 mike     1.1 {
 68                  char* p = *pOut;
 69              
 70                  /* Skip leading whitespace */
 71 krisbash 1.3     while (*p && isspace((unsigned char)(*p)))
 72 mike     1.1         p++;
 73              
 74                  /* Set start of identifier */
 75                  *start = p;
 76              
 77                  /* Expect [A-Za-z_] characters */
 78                  if (!isalpha((unsigned char)(*p)) && *p != '_')
 79                      return -1;
 80              
 81                  /* Skip [A-Za-z_0-9] characters */
 82 krisbash 1.3     while (*p && (isalnum((unsigned char)(*p)) || *p == '_' || *p == ':'))
 83 mike     1.1         p++;
 84              
 85                  /* Set end of identifier */
 86                  *end = p;
 87              
 88                  *pOut = p;
 89                  return 0;
 90              }
 91              
 92 krisbash 1.3 _Return_type_success_(return == 0)
 93              static int _ExpectChar(_Inout_ CharPtr* pOut, char ch)
 94 mike     1.1 {
 95                  char* p = *pOut;
 96              
 97                  /* Skip whitespace */
 98 krisbash 1.3     while (*p && isspace((unsigned char)(*p)))
 99 mike     1.1         p++;
100              
101                  /* Expect character */
102                  if (*p != ch)
103                      return -1;
104                  p++;
105              
106                  *pOut = p;
107                  return 0;
108              }
109              
110              // Parse a line of the form 'KEY=VALUE'
111 krisbash 1.3 _Return_type_success_(return == 0)
112              static int _ParseKeyValueLine(_Inout_ CharPtr* pOut, _Out_ CharPtr* keyOut, _Out_ CharPtr* valueOut)
113 mike     1.1 {
114                  char* p = *pOut;
115                  char* keyEnd;
116              
117                  /* Parse key */
118                  if (_ParseIdentifier(&p, keyOut, &keyEnd) != 0)
119                      return-1;
120              
121                  /* If out of input, error out */
122                  if (!*p)
123                      return -1;
124              
125                  /* Skip whitespace */
126                  if (_ExpectChar(&p, '=') != 0)
127                      return -1;
128              
129                  /* Null-terminate the key */
130                  *keyEnd = '\0';
131              
132                  /* Skip whitespace */
133 krisbash 1.3     while (*p && isspace((unsigned char)(*p)))
134 mike     1.1         p++;
135              
136                  /* Set value */
137                  *valueOut = p;
138              
139                  *pOut = p;
140                  return 0;
141              }
142              
143 krisbash 1.3 /*
144               * Parses <value> from `*CLASS=<value>` of the forms from .reg file:
145               * 1. `<ClassPath>`                             (Non-Association class)
146               * 2. `<ClassPath>{<ClassPath>,<ClassPath>}`    (Association class)
147               */
148              _Return_type_success_(return == 0)
149 mike     1.1 static int _ParseClassValue(
150 krisbash 1.3     _Inout_ CharPtr* pOut, 
151                  _Out_ CharPtr* nameOut, 
152                  _Out_ CharPtr* refName1Out,
153                  _Out_ CharPtr* refName2Out)
154 mike     1.1 {
155                  char* p = *pOut;
156                  char* start;
157                  char* end;
158              
159                  /* Expect class name */
160                  if (_ParseClassPath(&p, &start, &end) != 0)
161                      return -1;
162              
163                  /* Skip whitespace */
164 krisbash 1.3     while (*p && isspace((unsigned char)(*p)))
165 mike     1.1         p++;
166              
167                  /* If end of line */
168                  if (!*p)
169                  {
170                      *nameOut = start;
171                      *end = '\0';
172                      *refName1Out = NULL;
173                      *refName2Out = NULL;
174                      *pOut = p;
175                      return 0;
176                  }
177              
178                  /* Expect '{' character */
179                  if (_ExpectChar(&p, '{') != 0)
180                      return -1;
181              
182                  /* Get 'name' */
183                  *nameOut = start;
184                  *end = '\0';
185              
186 mike     1.1     /* Expect reference name */
187                  if (_ParseClassPath(&p, &start, &end) != 0)
188                      return -1;
189              
190                  /* Expect ',' character */
191                  if (_ExpectChar(&p, ',') != 0)
192                      return -1;
193              
194                  /* Get 'refName1' */
195                  *refName1Out = start;
196                  *end = '\0';
197              
198                  /* Expect reference name */
199                  if (_ParseClassPath(&p, &start, &end) != 0)
200                      return -1;
201              
202                  /* Expect '}' character */
203                  if (_ExpectChar(&p, '}') != 0)
204                      return -1;
205              
206                  /* Get 'refName1' */
207 mike     1.1     *refName2Out = start;
208                  *end = '\0';
209              
210                  *pOut = p;
211                  return 0;
212              }
213              
214 krisbash 1.3 
215              
216              /* Parse indication class from reg file */
217              _Return_type_success_(return == 0)
218              int ParseIndicationClass(
219                  _Inout_ CharPtr* pOut,
220                  _Inout_ RegFile* self,
221                  _In_opt_z_ char* hosting,
222                  _In_ ProvRegType type)
223              {
224              #ifdef DISABLE_INDICATION
225                  /* Ignore indication classes */
226                  MI_UNUSED(pOut);
227                  MI_UNUSED(self);
228                  MI_UNUSED(hosting);
229                  MI_UNUSED(type);
230                  return 0;
231              #else /* ifndef DISABLE_INDICATION */
232                  char* name = NULL;
233                  char* refName1 = NULL;
234                  char* refName2 = NULL;
235 krisbash 1.3     RegClass* rc;
236              
237                  if (_ParseClassValue(pOut, &name, &refName1, &refName2) != 0)
238                  {
239                      trace_RegFile_ParseIndication_ClassValueFailed();
240                      return -1;
241                  }
242              
243                  rc = (RegClass*)PAL_Calloc(1, sizeof(RegClass));
244                  if (!rc)
245                  {
246                      trace_RegFile_AllocFailure();
247                      return -1;
248                  }
249              
250                  List_Append(
251                      (ListElem**)&self->classesHead,
252                      (ListElem**)&self->classesTail,
253                      (ListElem*)rc);
254              
255                  if (refName1 || refName2)
256 krisbash 1.3     {
257                      trace_RegFile_IndicationClassCannotHaveRefClass();
258                      return -1;
259                  }
260              
261                  rc->name = PAL_Strdup(name);
262                  if (!rc->name)
263                  {
264                      trace_RegFile_OutOfMemory_Name();
265                      return -1;
266                  }
267              
268                  if (hosting)
269                  {
270                      rc->hosting = PAL_Strdup(hosting);
271                      if(!rc->hosting)
272                      {
273                          trace_RegFile_OutOfMemory_Hosting();
274                          return -1;
275                      }
276                  }
277 krisbash 1.3     rc->regtype = type;
278                  return 0;
279              #endif /* ifndef DISABLE_INDICATION */
280              }
281              
282              
283 mike     1.1 RegFile* RegFile_New(const char* path)
284              {
285                  FILE* is;
286 krisbash 1.3     char buf[MAX_LINE];
287 mike     1.1     int foundLibrary = 0;
288                  char* hosting = NULL;
289                  RegFile* self = 0;
290              
291                  /* Open the file */
292 krisbash 1.3     is = File_Open(path, "rb");
293 mike     1.1     if (!is)
294                      return NULL;
295              
296                  /* Allocate self structure */
297 krisbash 1.3     self = (RegFile*)PAL_Calloc(1, sizeof(RegFile));
298 mike     1.1     if (!self)
299                  {
300                      fclose(is);
301                      return NULL;
302                  }
303              
304                  /* Read line by line */
305                  while (fgets(buf, sizeof(buf), is) != NULL)
306                  {
307                      char* start = buf;
308                      char* p = start;
309                      char* key;
310                      char* value;
311              
312 krisbash 1.3         /* Skip leading whitespace */
313                      while (*p && isspace((unsigned char)(*p)))
314                          p++;
315              
316 mike     1.1         /* Skip comment lines */
317                      if (*p == '#')
318                          continue;
319              
320                      /* Remove trailing whitespace */
321                      {
322                          char* end = buf + strlen(buf);
323              
324                          while (end != start && isspace((unsigned char)end[-1]))
325                              *--end = '\0';
326                      }
327 krisbash 1.3                
328 mike     1.1         /* Skip blank lines */
329                      if (*p == '\0')
330                          continue;
331              
332                      /* Look for LIBRARY= */
333                      if (_ParseKeyValueLine(&p, &key, &value) != 0)
334                          goto failed;
335              
336                      if (strcmp(key, "LIBRARY") == 0)
337                      {
338                          if (foundLibrary)
339                              goto failed;
340              
341 krisbash 1.3             self->library = PAL_Strdup(value);
342 mike     1.1 
343                          if (!self->library)
344                              goto failed;
345              
346                          foundLibrary = 1;
347                      }
348                      else if (strcmp(key, "HOSTING") == 0)
349                      {
350                          if (hosting)
351 krisbash 1.3                 PAL_Free(hosting);
352 mike     1.1 
353 krisbash 1.3             hosting = PAL_Strdup(value);
354 mike     1.1         }
355 krisbash 1.3         else if (strcmp(key, "INSTANCELIFETIME") == 0)
356                      {
357                          if (strcmp(value, "CONTEXT") == 0)
358                          {
359                              self->instanceLifetimeContext = 1;
360                          }
361                          else
362                          {
363                              goto failed;
364                          }
365                      }
366              #if defined(CONFIG_ENABLE_PREEXEC)
367                      else if (strcmp(key, "PREEXEC") == 0)
368                      {
369                          self->preexec = PAL_Strdup(value);
370                      }
371              #endif /* defined(CONFIG_ENABLE_PREEXEC) */
372 mike     1.1         else if (strcmp(key, "CLASS") == 0)
373                      {
374                          char* name;
375                          char* refName1;
376                          char* refName2;
377                          RegClass* rc;
378              
379                          if (_ParseClassValue(&p, &name, &refName1, &refName2) != 0)
380                              goto failed;
381              
382 krisbash 1.3             rc = (RegClass*)PAL_Calloc(1, sizeof(RegClass));
383 mike     1.1             if (!rc)
384                              goto failed;
385              
386                          List_Append(
387                              (ListElem**)&self->classesHead,
388                              (ListElem**)&self->classesTail,
389                              (ListElem*)rc);
390              
391 krisbash 1.3             rc->name = PAL_Strdup(name);
392 mike     1.1             if (!rc->name)
393                              goto failed;
394              
395                          if (refName1)
396                          {
397 krisbash 1.3                 rc->refName1 = PAL_Strdup(refName1);
398 mike     1.1                 if (!rc->refName1)
399                                  goto failed;
400                          }
401              
402                          if (refName2)
403                          {
404 krisbash 1.3                 rc->refName2 = PAL_Strdup(refName2);
405 mike     1.1                 if (!rc->refName2)
406                                  goto failed;
407                          }
408              
409                          if (hosting)
410 krisbash 1.3             {
411                              rc->hosting = PAL_Strdup(hosting);
412                              if(!rc->hosting)
413                                  goto failed;
414                          }
415                      }
416                      else if (strcmp(key, "EXTRACLASS") == 0)
417                      {
418                          char* name;
419                          char* refName1;
420                          char* refName2;
421                          RegClass* rc;
422              
423                          if (_ParseClassValue(&p, &name, &refName1, &refName2) != 0)
424                              goto failed;
425              
426                          rc = (RegClass*)PAL_Calloc(1, sizeof(RegClass));
427                          if (!rc)
428                              goto failed;
429              
430                          List_Append(
431 krisbash 1.3                 (ListElem**)&self->extraClassesHead,
432                              (ListElem**)&self->extraClassesTail,
433                              (ListElem*)rc);
434              
435                          rc->name = PAL_Strdup(name);
436                          if (!rc->name)
437                              goto failed;
438              
439                          /* no need to use refName1, refName2 as the definition of these classes will be present as part of CLASSES list or EXTRACLASSES list */
440              
441                          if (hosting)
442                          {
443                              rc->hosting = PAL_Strdup(hosting);
444                              if(!rc->hosting)
445                                  goto failed;
446                          }
447                      }
448                      else if (strcmp(key, REG_INDICATION_CLASS) == 0)
449                      {
450                          int r = ParseIndicationClass(&p, self, hosting, PROVREG_INDICATION);
451                          if (r == -1)
452 krisbash 1.3                 goto failed;
453 mike     1.1         }
454                  }
455              
456                  if (hosting)
457 krisbash 1.3         PAL_Free(hosting);
458              
459                  /*If LIBRARY was not found (That should NOT happen),
460                  which means that this regfile is corrupted (The user might have modified it by hand). So go to failed*/
461                  if(!foundLibrary)
462                  {
463                      trace_RegFile_MissingLibraryTag(path);
464                      goto failed;
465                  }
466 mike     1.1 
467                  fclose(is);
468              
469                  return self;
470              
471              failed:
472                  if (self)
473                      RegFile_Delete(self);
474              
475                  if (is)
476                      fclose(is);
477              
478                  return NULL;
479              }
480              
481 krisbash 1.3 static void _RegClassList_Delete(RegClass *regClassHead)
482 mike     1.1 {
483                  RegClass* rc;
484                  RegClass* next;
485 krisbash 1.3     
486                  for(rc = regClassHead; rc; rc = next)
487                  {
488                      if (rc->name)
489                          PAL_Free(rc->name);
490                      
491                      if (rc->refName1)
492                          PAL_Free(rc->refName1);
493                      
494                      if (rc->refName2)
495                          PAL_Free(rc->refName2);
496                      
497                      if (rc->hosting)
498                          PAL_Free(rc->hosting);
499                      
500                      next = rc->next;
501                      PAL_Free(rc);
502                  }
503              }
504 mike     1.1 
505 krisbash 1.3 void RegFile_Delete(RegFile* self)
506              {
507 mike     1.1     if (!self)
508                      return;
509              
510                  if (self->library)
511 krisbash 1.3         PAL_Free(self->library);
512 mike     1.1 
513 krisbash 1.3 #if defined(CONFIG_ENABLE_PREEXEC)
514 mike     1.1 
515 krisbash 1.3     if (self->preexec)
516                      PAL_Free(self->preexec);
517 mike     1.1 
518 krisbash 1.3 #endif /* defined(CONFIG_ENABLE_PREEXEC) */
519 mike     1.1 
520 krisbash 1.3     _RegClassList_Delete(self->classesHead);
521                  _RegClassList_Delete(self->extraClassesHead);
522 mike     1.1 
523 krisbash 1.3     PAL_Free(self);
524 mike     1.1 }
525              
526              void RegFile_Print(RegFile* self, FILE* os)
527              {
528                  RegClass* rc;
529              
530 krisbash 1.3     Ftprintf(os, ZT("LIBRARY=%s\n"), scs(self->library));
531              
532              #if defined(CONFIG_ENABLE_PREEXEC)
533              
534                  Ftprintf(os, ZT("PREEXEC=%s\n"), scs(self->preexec));
535              
536              #endif /* defined(CONFIG_ENABLE_PREEXEC) */
537 mike     1.1 
538                  for (rc = self->classesHead; rc; rc = rc->next)
539                  {
540 krisbash 1.3         Ftprintf(os, ZT("CLASS=%s"), scs(rc->name));
541 mike     1.1 
542                      if (rc->refName1 && rc->refName2)
543                      {
544 krisbash 1.3             Ftprintf(os, ZT("{"));
545                          Ftprintf(os, ZT("%s"), scs(rc->refName1));
546                          Ftprintf(os, ZT(","));
547                          Ftprintf(os, ZT("%s"), scs(rc->refName2));
548                          Ftprintf(os, ZT("}"));
549 mike     1.1         }
550              
551 krisbash 1.3         Ftprintf(os, ZT("\n"));
552 mike     1.1     }
553              }

ViewCVS 0.9.2