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.4 #include <pal/strings.h>
28 #include <pal/format.h>
29 #include <base/log.h>
|
30 mike 1.1 #include <base/paths.h>
|
31 krisbash 1.4 #include <base/naming.h>
|
32 mike 1.1 #include "provreg.h"
33 #include "regfile.h"
34
|
35 krisbash 1.4
|
36 mike 1.1 typedef struct _ProvRegNamespaceNode
37 {
38 struct _ProvRegNamespaceNode* next;
39 MI_ConstString ns;
40 struct _ProvRegClassInheritanceNode* tree;
41 }
42 ProvRegNamespaceNode;
43
44 typedef struct _ProvRegAssocBackLinkNode
45 {
46 struct _ProvRegAssocBackLinkNode* next;
47 struct _ProvRegClassInheritanceNode* assocClass;
48 }
49 ProvRegAssocBackLinkNode;
50
51 typedef struct _ProvRegClassInheritanceNode
52 {
53 MI_ConstString cn;
|
54 krisbash 1.4 const char* library;
55 ProvHosting hosting;
56 const char* user;
|
57 mike 1.1 struct _ProvRegClassInheritanceNode* parent;
58 struct _ProvRegClassInheritanceNode* nextSibling;
59 struct _ProvRegClassInheritanceNode* firstChild;
60 /* assoc support */
61 /* left/right are not-null only for assoc class */
62 struct _ProvRegClassInheritanceNode* left;
63 struct _ProvRegClassInheritanceNode* right;
64
65 /* linked list of all assoc classes that refer this class */
66 ProvRegAssocBackLinkNode* associatorClasses;
67 }
68 ProvRegClassInheritanceNode;
69
70 #if (MI_CHAR_TYPE == 1)
|
71 krisbash 1.4 #define MI_ScasecmpChar_MIChar Tcscasecmp
|
72 mike 1.1 #else
73 static int MI_ScasecmpChar_MIChar(
74 const char* str1,
|
75 krisbash 1.4 const ZChar* str2 )
|
76 mike 1.1 {
77 /* assuming str2 is ascii char-set only */
78 for(;;)
79 {
80 int c1 = tolower((unsigned char)*str1);
81 int c2 = tolower((unsigned char)*str2);
82
83 if (c1 != c2 )
84 {
85 return c1 < c2 ? -1 : 1;
86 }
87 if (!c1)
88 break;
89
90 str1++;
91 str2++;
92 }
93
94 return 0;
95 }
96 #endif
97 mike 1.1
98 /* returns last segment from the string or string itself;
99 for example, for string abc,edf,ghk function returns 'ghk', 'edf' and 'abc' */
|
100 krisbash 1.4 static char* _GetNextReverse(_Inout_ CharPtr* text, char delim)
|
101 mike 1.1 {
102 char* start = *text;
103 char* end;
104 size_t len;
105
106 /* If at end of string */
107 if (!*start)
108 return NULL;
109
110 len = strlen(start);
111
112 /* end of string */
113 end = start + len;
114
115 /* Remove trailing whitespace */
116 for (; end != start && isspace((unsigned char)end[-1]);)
117 *--end = '\0';
118
119 /* Skip non-colon character characters */
120 for (; end != start && *end != delim; end--)
121 ;
122 mike 1.1
123 if ( end == start )
124 { /* last block - move position to the end to point to \0 */
125 *text = start + len;
126 }
127 else
128 { /* skip delimiter*/
129 *end = 0;
130 end++;
131 }
|
132 krisbash 1.4 #ifdef _MSC_VER
133 #pragma prefast(push)
134 #pragma prefast (disable: 26016)
135 #endif
|
136 mike 1.1
137 /* Skip leading whitespace */
138 while (*end && isspace((unsigned char)*end))
139 end++;
140
|
141 krisbash 1.4 #ifdef _MSC_VER
142 #pragma prefast(pop)
143 #endif
144
|
145 mike 1.1 return end;
146 }
147
148 /* ********************************************************* */
149 /* *** namespace operations *** */
150 /* ********************************************************* */
151
152 ProvRegNamespaceNode* _FindNamespace(
153 ProvReg* self,
|
154 krisbash 1.4 MI_ConstString ns,
155 MI_Boolean extraClass)
|
156 mike 1.1 {
157 /* find namespace node in the list */
|
158 krisbash 1.4 ProvRegNamespaceNode* current;
159 if(extraClass)
160 current = self->namespacesForExtraClasses;
161 else
162 current = self->namespaces;
|
163 mike 1.1
|
164 krisbash 1.4 while (current && Tcscasecmp(ns,current->ns) != 0)
|
165 mike 1.1 current = current->next;
166
167 return current;
168 }
169
170 ProvRegNamespaceNode* _FindOrCreateNamespace(
171 ProvReg* self,
|
172 krisbash 1.4 MI_ConstString ns,
173 MI_Boolean extraClass)
|
174 mike 1.1 {
|
175 krisbash 1.4 ProvRegNamespaceNode* item = _FindNamespace(self,ns, extraClass);
|
176 mike 1.1
177 if (item)
178 return item;
179
180 item = (ProvRegNamespaceNode*)Batch_GetClear(
181 &self->batch, sizeof(ProvRegNamespaceNode));
182
183 if (item)
184 {
|
185 krisbash 1.4 if(extraClass)
186 {
187 size_t size;
188 size = Tcslen(ns) + 1;
189
190 {
191 ZChar* nameSpace = Batch_Get(&self->batch, size * sizeof(ZChar));
192 if(nameSpace == NULL)
193 {
194 trace_OutOfMemory();
195 return NULL;
196 }
197 Tcslcpy(nameSpace, ns, size);
198
199 item->ns = nameSpace;
200 item->next = self->namespacesForExtraClasses;
201 self->namespacesForExtraClasses = item;
202 }
203 }
204 else
205 {
206 krisbash 1.4 item->ns = ns; /* no need to strdup, since it's already in batch*/
207 item->next = self->namespaces;
208 self->namespaces = item;
209 }
|
210 mike 1.1 }
211
212 return item;
213 }
214
215 /* ********************************************************* */
216 /* *** tree operations *** */
217 /* ********************************************************* */
218 ProvRegClassInheritanceNode* _GetNextTreeNodeLimittedBy(
219 ProvRegClassInheritanceNode* item,
220 ProvRegClassInheritanceNode* subtreeRoot)
221 {
222 /* first-child */
223 if (item->firstChild)
224 return item->firstChild;
225
226 /* sibling */
227 if (item->nextSibling)
228 return item->nextSibling;
229
230 /* sibling of direct or indirect parent*/
231 mike 1.1 while (item && item->parent != subtreeRoot)
232 {
233 item = item->parent;
234
|
235 krisbash 1.4 if (item && item->nextSibling)
|
236 mike 1.1 return item->nextSibling;
237 }
238
239 /* end of tree */
240 return 0;
241 }
242
243 ProvRegClassInheritanceNode* _GetNextTreeNode(
244 ProvRegClassInheritanceNode* item)
245 {
246 return _GetNextTreeNodeLimittedBy(item,0);
247 }
248
249 ProvRegClassInheritanceNode* _FindClassNodeInTreeByChar(
250 ProvRegClassInheritanceNode* root,
251 const char* cn)
252 {
253 while (root)
254 {
255 if (MI_ScasecmpChar_MIChar(cn,root->cn)==0)
256 {
257 mike 1.1 return root;
258 }
259 root = _GetNextTreeNode(root);
260 }
261 return root;
262 }
263
264 ProvRegClassInheritanceNode* _FindClassNodeInTree(
265 ProvRegClassInheritanceNode* root,
|
266 krisbash 1.4 const ZChar* cn)
|
267 mike 1.1 {
268 while (root)
269 {
|
270 krisbash 1.4 if (Tcscasecmp(cn,root->cn)==0)
|
271 mike 1.1 {
272 return root;
273 }
274 root = _GetNextTreeNode(root);
275 }
276 return root;
277 }
278
279 MI_Boolean _ValidateTreeNodes(
280 ProvRegClassInheritanceNode* derivedNode,
281 ProvRegClassInheritanceNode* baseNode)
282 {
283 /* if we have no nodes - it's fine - no info yet*/
284 if ( !derivedNode && !baseNode )
285 return MI_TRUE;
286
287 /* if we have both nodes - check they are child/parent */
288 if ( derivedNode && baseNode )
289 return derivedNode->parent == baseNode;
290
291 /* base must be specified */
292 mike 1.1 if ( derivedNode && !baseNode )
293 return MI_FALSE;
294
295 /* only one node is known - ok */
296 return MI_TRUE;
297 }
298
299 static MI_Result _AddClassInheritanceInfo(
300 ProvReg* self,
301 MI_ConstString ns,
302 const char* derivedClass, /* can be null */
|
303 krisbash 1.4 const char* baseClass,
304 const char* library,
305 ProvHosting hosting,
306 const char* user,
307 MI_Boolean extraClass)
|
308 mike 1.1 {
309 /* get (or create if needed) namespace item */
|
310 krisbash 1.4 ProvRegNamespaceNode* namespaceNode = _FindOrCreateNamespace(self,ns, extraClass);
|
311 mike 1.1 ProvRegClassInheritanceNode* derivedNode, *baseNode;
312
313 if (!namespaceNode)
314 return MI_RESULT_FAILED;
315
316 /* find classes' nodes */
317 derivedNode = derivedClass ? _FindClassNodeInTreeByChar(namespaceNode->tree, derivedClass) : 0;
318 baseNode = _FindClassNodeInTreeByChar(namespaceNode->tree, baseClass);
319
320 /* validate nodes */
321 if (!_ValidateTreeNodes(derivedNode,baseNode))
322 return MI_RESULT_INVALID_CLASS_HIERARCHY;
323
324 /* create missing nodes and insert them into tree */
325 if ( !baseNode )
326 {
327 baseNode = (ProvRegClassInheritanceNode*)Batch_GetClear(
328 &self->batch, sizeof(ProvRegClassInheritanceNode));
329
330 if ( !baseNode )
331 return MI_RESULT_FAILED;
332 mike 1.1
|
333 krisbash 1.4 baseNode->cn = Batch_StrTcsdup(&self->batch, baseClass);
334 baseNode->library = Batch_Strdup(&self->batch, library);
335 baseNode->hosting = hosting;
336 if(user)
337 {
338 baseNode->user = Batch_Strdup(&self->batch, user);
339 if(!baseNode->user)
340 return MI_RESULT_FAILED;
341 }
|
342 mike 1.1
|
343 krisbash 1.4 if ( !baseNode->cn || !baseNode->library)
|
344 mike 1.1 return MI_RESULT_FAILED;
345
346 /* insert into tree */
347 baseNode->nextSibling = namespaceNode->tree;
348 namespaceNode->tree = baseNode;
349 }
350
351 if ( !derivedNode && derivedClass)
352 {
353 derivedNode = (ProvRegClassInheritanceNode*)Batch_GetClear(
354 &self->batch, sizeof(ProvRegClassInheritanceNode));
355
356 if ( !derivedNode )
357 return MI_RESULT_FAILED;
358
|
359 krisbash 1.4 derivedNode->cn = Batch_StrTcsdup(&self->batch, derivedClass);
360 derivedNode->library = Batch_Strdup(&self->batch, library);
361 derivedNode->hosting = hosting;
362 if(user)
363 {
364 derivedNode->user = Batch_Strdup(&self->batch, user);
365 if(!derivedNode->user)
366 return MI_RESULT_FAILED;
367 }
|
368 mike 1.1
|
369 krisbash 1.4 if ( !derivedNode->cn || !derivedNode->library)
|
370 mike 1.1 return MI_RESULT_FAILED;
371
372 /* add as a child */
373 derivedNode->parent = baseNode;
374 derivedNode->nextSibling = baseNode->firstChild;
375 baseNode->firstChild = derivedNode;
376 }
377
378 return MI_RESULT_OK;
379 }
380
381 static MI_Result _AddAssociation(
382 ProvReg* self,
383 MI_ConstString ns,
384 const char* assoc,
385 const char* left,
386 const char* right)
387 {
388 /* find all related nodes */
389 ProvRegNamespaceNode* namespaceNode;
390 ProvRegClassInheritanceNode *leftNode, *rightNode, *assocNode;
391 mike 1.1
392 /* check namespace */
|
393 krisbash 1.4 namespaceNode = _FindNamespace(self,ns, MI_FALSE);
|
394 mike 1.1
395 if (!namespaceNode)
396 return MI_RESULT_INVALID_NAMESPACE;
397
398 /* find class */
399 leftNode = _FindClassNodeInTreeByChar(namespaceNode->tree, left);
400 rightNode = _FindClassNodeInTreeByChar(namespaceNode->tree, right);
401 assocNode = _FindClassNodeInTreeByChar(namespaceNode->tree, assoc);
402
403 if (!leftNode || !rightNode || !assocNode)
404 return MI_RESULT_INVALID_CLASS;
405
406 /* add cross-links */
407 assocNode->left = leftNode;
408 assocNode->right = rightNode;
409
410 {
411 ProvRegAssocBackLinkNode* newLinkItemLeft;
412 newLinkItemLeft = (ProvRegAssocBackLinkNode*)Batch_GetClear(
413 &self->batch, sizeof(ProvRegAssocBackLinkNode));
414
415 mike 1.1 if (!newLinkItemLeft)
416 return MI_RESULT_FAILED;
417
418 newLinkItemLeft->assocClass = assocNode;
419 newLinkItemLeft->next = leftNode->associatorClasses;
420 leftNode->associatorClasses = newLinkItemLeft;
421 }
422
423 /* check if assoc links different classes */
424 if (leftNode != rightNode)
425 {
426 ProvRegAssocBackLinkNode* newLinkItemRight;
427 newLinkItemRight = (ProvRegAssocBackLinkNode*)Batch_GetClear(
428 &self->batch, sizeof(ProvRegAssocBackLinkNode));
429 if (!newLinkItemRight)
430 return MI_RESULT_FAILED;
431
432 newLinkItemRight->assocClass = assocNode;
433 newLinkItemRight->next = rightNode->associatorClasses;
434 rightNode->associatorClasses = newLinkItemRight;
435 }
436 mike 1.1
437 return MI_RESULT_OK;
438 }
439
440 static MI_Result _GetSubclasses2(
441 ProvReg* self,
442 ProvRegEntry* e,
|
443 krisbash 1.4 _Inout_ CharPtr p)
|
444 mike 1.1 {
445 /* get all sub-classes */
446 char* baseClass = _GetNextReverse(&p, ':');
447 char* derivedClass = _GetNextReverse(&p, ':');
448 MI_Result r;
449
450 /* expecting to find at least one class */
451 if (!baseClass)
452 return MI_RESULT_INVALID_CLASS;
453
454 while ( derivedClass )
455 {
456 r = _AddClassInheritanceInfo(self, e->nameSpace, derivedClass,
|
457 krisbash 1.4 baseClass, e->libraryName, e->hosting, e->user, MI_FALSE);
|
458 mike 1.1
459 if ( MI_RESULT_OK != r )
460 return r;
461
462 baseClass = derivedClass;
463 derivedClass = _GetNextReverse(&p, ':');
464 }
465
466 /* add base class with no parent */
|
467 krisbash 1.4 r = _AddClassInheritanceInfo(self, e->nameSpace, derivedClass, baseClass, e->libraryName, e->hosting, e->user, MI_FALSE);
|
468 mike 1.1 if (MI_RESULT_OK != r)
469 return r;
470
|
471 krisbash 1.4 e->className = Batch_StrTcsdup(&self->batch, baseClass);
|
472 mike 1.1 if (!e->className)
473 {
474 return MI_RESULT_FAILED;
475 }
|
476 krisbash 1.4 e->classNameHash = Hash(e->className);
|
477 mike 1.1
478 return MI_RESULT_OK;
479 }
480
481 static int _AddEntry(
482 ProvReg* self,
483 const char* nameSpace,
484 RegFile* regFile,
485 RegClass* regClass)
486 {
487 ProvRegEntry* e;
488
489 #if 0
490 RegFile_Print(regFile, stdout);
491 #endif
492
493 /* Allocate new provider register entry */
494 e = (ProvRegEntry*)Batch_GetClear(&self->batch, sizeof(ProvRegEntry));
495 if (!e)
496 return -1;
497
498 mike 1.1 /* ProvRegEntry.provInterface */
499 e->provInterface = PROV_INTERFACE_STATIK;
500
501 /* ProvRegEntry.nameSpace */
|
502 krisbash 1.4 e->nameSpace = Batch_StrTcsdup(&self->batch, nameSpace);
503 if (!e->nameSpace)
504 return -1;
505
506 e->nameSpaceHash = Hash(e->nameSpace);
|
507 mike 1.1
508 /* ProvRegEntry.libraryName */
|
509 krisbash 1.4 e->libraryName = Batch_Strdup(&self->batch, regFile->library);
510 if (!e->libraryName)
511 {
512 trace_ProvReg_ProvRegEntry_NULLLibraryName(nameSpace, regClass->name);
513 return -1;
514 }
515
516 #if defined(CONFIG_ENABLE_PREEXEC)
517
518 /* ProvRegEntry.preexec */
519 if (regFile->preexec)
520 {
521 e->preexec = Batch_Strdup(&self->batch, regFile->preexec);
522 if (!e->preexec)
523 return -1;
524 }
525
526 #endif /* defined(CONFIG_ENABLE_PREEXEC) */
|
527 mike 1.1
528 /* ProvRegEntry.hosting*/
529 e->hosting = PROV_HOSTING_INPROC;
530
|
531 krisbash 1.4 e->regType = regClass->regtype;
532
533 e->instanceLifetimeContext = regFile->instanceLifetimeContext;
534
|
535 mike 1.1 if (regClass->hosting)
536 {
537 char hosting[64];
538 Strlcpy(hosting, regClass->hosting, sizeof(hosting));
539
540 /* it either user name or one of two special values:
541 * @inproc@
|
542 krisbash 1.4 * @requestor@
|
543 mike 1.1 */
544 if (strcmp(hosting, PROV_REG_HOSTING_INPROC) == 0)
545 {
546 e->hosting = PROV_HOSTING_INPROC;
547 }
548 else if (strcmp(hosting, PROV_REG_HOSTING_REQUESTOR) == 0)
549 {
550 e->hosting = PROV_HOSTING_REQUESTOR;
551 }
552 else
553 {
554 e->hosting = PROV_HOSTING_USER;
|
555 krisbash 1.4 e->user = Batch_Strdup(&self->batch, hosting);
|
556 mike 1.1 if (!e->user)
557 return -1;
558 }
559 }
560
561 /* If an association */
562 if (regClass->refName1 && regClass->refName2)
563 {
564 if (_GetSubclasses2(self, e, regClass->refName1) != MI_RESULT_OK)
565 return -1;
566
567 if (_GetSubclasses2(self, e, regClass->refName2) != MI_RESULT_OK)
568 return -1;
569
570 if (_GetSubclasses2(self, e, regClass->name) != MI_RESULT_OK)
571 return -1;
572
573 if (_AddAssociation(self, e->nameSpace, regClass->name,
574 regClass->refName1, regClass->refName2) != MI_RESULT_OK)
575 {
576 return -1;
577 mike 1.1 }
578 }
579 else
580 {
581 if (_GetSubclasses2(self, e, regClass->name) != MI_RESULT_OK)
582 return -1;
583 }
584
585 /* Add entry to end of list */
586 {
587 e->next = NULL;
588
589 if (self->tail)
590 {
591 self->tail->next = e;
592 self->tail = e;
593 }
594 else
595 {
596 self->tail = e;
597 self->head = e;
598 mike 1.1 }
599 }
600
601 return 0;
602 }
603
|
604 krisbash 1.4 static int _AddEntryForExtraClass(
605 ProvReg* self,
606 const char* nameSpace,
607 RegFile* regFile,
608 RegClass* regClass)
609 {
610 /* get all sub-classes */
611 ProvHosting hosting;
612 const char* user = NULL;
613 CharPtr p = regClass->name;
614 char* baseClass = _GetNextReverse(&p, ':');
615 char* derivedClass = _GetNextReverse(&p, ':');
616 MI_Result r;
617 size_t size = strlen(nameSpace) + 1;
618
619 hosting = PROV_HOSTING_INPROC;
620
621 if (regClass->hosting)
622 {
623 /* it either user name or one of two special values:
624 * @inproc@
625 krisbash 1.4 * @requestor@
626 */
627 if (strcmp(regClass->hosting, PROV_REG_HOSTING_INPROC) == 0)
628 {
629 hosting = PROV_HOSTING_INPROC;
630 }
631 else if (strcmp(regClass->hosting, PROV_REG_HOSTING_REQUESTOR) == 0)
632 {
633 hosting = PROV_HOSTING_REQUESTOR;
634 }
635 else
636 {
637 hosting = PROV_HOSTING_USER;
638 user = regClass->hosting;
639 }
640 }
641
642 #if 0
643 RegFile_Print(regFile, stdout);
644 #endif
645
646 krisbash 1.4 /* expecting to find at least one class */
647 if (!baseClass)
648 return MI_RESULT_INVALID_CLASS;
649
650 {
651 ZChar s[PAL_MAX_PATH_SIZE];
652 size_t i;
653
654 if(size > PAL_MAX_PATH_SIZE)
655 return -1;
656
657 for(i=0; i < size; i++)
658 s[i] = (ZChar) nameSpace[i];
659
660 while ( derivedClass )
661 {
662 r = _AddClassInheritanceInfo(self, s, derivedClass,
663 baseClass, regFile->library, hosting, user, MI_TRUE);
664
665 if ( MI_RESULT_OK != r )
666 return r;
667 krisbash 1.4
668 baseClass = derivedClass;
669 derivedClass = _GetNextReverse(&p, ':');
670 }
671
672 /* add base class with no parent */
673 r = _AddClassInheritanceInfo(self, s, derivedClass,
674 baseClass, regFile->library, hosting, user, MI_TRUE);
675
676 if (MI_RESULT_OK != r)
677 return -1;
678 }
679
680 return 0;
681 }
682
683 /* Initialize ProvReg strucutre from given directory */
684 _Use_decl_annotations_
685 MI_Result ProvReg_Init(ProvReg* self, const char* directory)
|
686 mike 1.1 {
|
687 krisbash 1.4 RegFile* reg = NULL;
|
688 mike 1.1 Dir* dir = NULL;
689 Dir* dir2 = NULL;
|
690 krisbash 1.4 MI_Result r = MI_RESULT_FAILED;
691
|
692 mike 1.1 /* Zero-fill self */
693 memset(self, 0, sizeof(*self));
694
|
695 krisbash 1.4 dir = Dir_Open(directory);
696 if (!dir)
697 {
698 return r;
699 }
700
|
701 mike 1.1 /* Initialize batch allocator */
702 Batch_Init(&self->batch, BATCH_MAX_PAGES);
703
704 /* For each namespace directory in 'omirgister' */
705 for (;;)
706 {
707 DirEnt* ent = Dir_Read(dir);
|
708 krisbash 1.4
|
709 mike 1.1 if (!ent)
|
710 krisbash 1.4 {
|
711 mike 1.1 break;
|
712 krisbash 1.4 }
|
713 mike 1.1
714 /* Ignore system directories */
715 if (strcmp(ent->name, ".") == 0 || strcmp(ent->name, "..") == 0)
716 continue;
717
718 /* Skip 'CVS' directories */
719 if (strcmp(ent->name, "CVS") == 0)
720 continue;
721
722 /* Scan .reg files in the current namespace directory */
723 {
|
724 krisbash 1.4 char path[PAL_MAX_PATH_SIZE];
|
725 mike 1.1
|
726 krisbash 1.4 Strlcpy(path, directory, sizeof(path));
|
727 mike 1.1 Strlcat(path, "/", sizeof(path));
728 Strlcat(path, ent->name, sizeof(path));
729
|
730 krisbash 1.4 /* Skip if not a dir */
731 if(!Isdir(path))
732 continue;
733
|
734 mike 1.1 dir2 = Dir_Open(path);
735 if (!dir2)
736 {
737 goto failed;
738 }
739
740 for (;;)
741 {
742 DirEnt* ent2 = Dir_Read(dir2);
743 if (!ent2)
|
744 krisbash 1.4 {
|
745 mike 1.1 break;
|
746 krisbash 1.4 }
|
747 mike 1.1
748 /* Ignore system directories */
749 if (strcmp(ent2->name,".") == 0 || strcmp(ent2->name,"..") == 0)
|
750 krisbash 1.4 {
|
751 mike 1.1 continue;
|
752 krisbash 1.4 }
753
754 /* Skip non-reg file */
755 {
756 char* affix = Strrchr(ent2->name, '.');
757 if (!affix || (Strcasecmp(&affix[1], "reg") != 0))
758 continue;
759 }
|
760 mike 1.1
761 /* Load the reg file */
762 {
|
763 krisbash 1.4 char regPath[PAL_MAX_PATH_SIZE];
|
764 mike 1.1
765 /* Form path to .reg file */
766 Strlcpy(regPath, path, sizeof(regPath));
767 Strlcat(regPath, "/", sizeof(regPath));
768 Strlcat(regPath, ent2->name, sizeof(regPath));
769
770 /* Create new reg file object */
771 reg = RegFile_New(regPath);
772 if (!reg)
773 {
|
774 krisbash 1.4 trace_ProvReg_SkipRegFile(scs(regPath));
775 continue;
|
776 mike 1.1 }
777
778 /* For each class in the reg file */
779 {
780 RegClass* rc;
|
781 krisbash 1.4 char* p = ent->name;
782
783 /* Transpose NAMESPACE_SEPARATOR characters to '/'
784 * characters
785 */
786 while (*p)
787 {
788 if (*p == NAMESPACE_SEPARATOR)
789 *p = '/';
790 p++;
791 }
|
792 mike 1.1
793 for (rc = reg->classesHead; rc; rc = rc->next)
794 {
|
795 krisbash 1.4 if (_AddEntry(self, ent->name, reg, rc) != 0)
|
796 mike 1.1 {
|
797 krisbash 1.4 goto failed;
|
798 mike 1.1 }
|
799 krisbash 1.4 }
800 }
|
801 mike 1.1
|
802 krisbash 1.4 /* For each extraClass in the reg file */
803 {
804 RegClass* rc;
805 char* p = ent->name;
806
807 /* Transpose NAMESPACE_SEPARATOR characters to '/'
808 * characters
809 */
810 while (*p)
811 {
812 if (*p == NAMESPACE_SEPARATOR)
813 *p = '/';
814 p++;
815 }
816
817 for (rc = reg->extraClassesHead; rc; rc = rc->next)
818 {
819 if (_AddEntryForExtraClass(self, ent->name, reg, rc) != 0)
|
820 mike 1.1 {
821 goto failed;
822 }
823 }
824 }
825
826 /* Delete the current entry */
827 RegFile_Delete(reg);
828 reg = NULL;
829 }
830 }
831
832 /* Close the directory */
833 Dir_Close(dir2);
834 dir2 = NULL;
835 }
836 }
|
837 krisbash 1.4 r = MI_RESULT_OK;
|
838 mike 1.1
839 failed:
|
840 krisbash 1.4 if (dir2)
841 {
842 Dir_Close(dir2);
843 }
|
844 mike 1.1 if (dir)
|
845 krisbash 1.4 {
|
846 mike 1.1 Dir_Close(dir);
|
847 krisbash 1.4 }
848 if (r != MI_RESULT_OK)
849 {
850 ProvReg_Destroy(self);
851 memset(self, 0, sizeof(*self));
852 }
853 if(reg)
854 {
855 RegFile_Delete(reg);
856 reg = NULL;
857 }
858 return r;
859 }
|
860 mike 1.1
|
861 krisbash 1.4 /* Initialize ProvReg strucutre from omiregister directory */
862 _Use_decl_annotations_
863 MI_Result ProvReg_Init2(ProvReg* self)
864 {
865 return ProvReg_Init(self, OMI_GetPath(ID_REGISTERDIR));
|
866 mike 1.1 }
867
868 void ProvReg_Destroy(
869 ProvReg* self)
870 {
871 Batch_Destroy(&self->batch);
872 }
873
874 void ProvReg_Dump(
875 ProvReg* self,
876 FILE* os)
877 {
878 ProvRegEntry* p;
879
880 for (p = self->head; p; p = p->next)
881 {
|
882 krisbash 1.4 Ftprintf(os, PAL_T("==== ProvRegEntry\n"));
883 Ftprintf(os, PAL_T("provInterface[%u]\n"), p->provInterface);
884 Ftprintf(os, PAL_T("nameSpace[%T]\n"), tcs(p->nameSpace));
885 Ftprintf(os, PAL_T("className[%T]\n"), tcs(p->className));
886 Ftprintf(os, PAL_T("libraryName[%s]\n"), scs(p->libraryName));
|
887 mike 1.1 }
888 }
889
890 const ProvRegEntry* ProvReg_FindProviderForClass(
891 ProvReg* self,
|
892 krisbash 1.4 const ZChar* nameSpace,
893 const ZChar* className,
894 MI_Result *findError)
|
895 mike 1.1 {
|
896 krisbash 1.4 return ProvReg_FindProviderForClassByType(self, nameSpace, className, PROVREG_DEFAULT, findError);
897 }
|
898 mike 1.1
899
900 /* returns ok or not-found; baseClass will be null if no base class exist */
901 MI_Result ProvReg_GetDirectBaseClass(
902 ProvReg* self,
|
903 krisbash 1.4 const ZChar* nameSpace,
904 const ZChar* className,
905 const ZChar** baseClass,
906 MI_Boolean extraClass)
|
907 mike 1.1 {
908 ProvRegClassInheritanceNode* classNode;
909 ProvRegNamespaceNode* namespaceNode;
910
911 /* clear out param */
912 *baseClass = 0;
913
914 /* check namespace */
|
915 krisbash 1.4 namespaceNode = _FindNamespace(self,nameSpace, extraClass);
|
916 mike 1.1
917 if (!namespaceNode)
918 return MI_RESULT_INVALID_NAMESPACE;
919
920 /* find class */
921 classNode = _FindClassNodeInTree(namespaceNode->tree, className);
922
923 if (!classNode)
924 return MI_RESULT_INVALID_CLASS;
925
926 if (classNode->parent)
927 {
928 *baseClass = classNode->parent->cn;
929 }
930
931 return MI_RESULT_OK;
932 }
933
934 /* enumerates classes derived classes:
935 - if deep == false and className == null, returns all root classes
936 - if deep == true and className == null, returns all classes
937 mike 1.1 - if deep == false and className provided, returns all classes directly derived from given
938 - if deep == true and className provided, returns all classes derived from given
939 */
940 MI_Result ProvReg_BeginClasses(
941 ProvReg* self,
|
942 krisbash 1.4 const ZChar* nameSpace,
943 const ZChar* className,
|
944 mike 1.1 MI_Boolean deep,
|
945 krisbash 1.4 ProvRegPosition* pos,
946 MI_Boolean extraClass)
|
947 mike 1.1 {
948 ProvRegNamespaceNode* namespaceNode;
949
950 /* clear pos */
951 memset( pos, 0, sizeof(*pos));
952 pos->deep = deep;
953
954 /* check namespace */
|
955 krisbash 1.4 namespaceNode = _FindNamespace(self,nameSpace, extraClass);
|
956 mike 1.1
957 if (!namespaceNode)
958 return MI_RESULT_INVALID_NAMESPACE;
959
960 /* find class */
961 if (className)
962 {
963 pos->start = _FindClassNodeInTree(namespaceNode->tree, className);
964
965 if (!pos->start)
966 return MI_RESULT_INVALID_CLASS;
967
968 pos->current = pos->start->firstChild;
969 }
970 else
971 {
972 pos->start = 0;
973 pos->current = namespaceNode->tree;
974 }
975
976 return MI_RESULT_OK;
977 mike 1.1 }
978
979 MI_Result ProvReg_NextClass(
980 ProvRegPosition* pos,
|
981 krisbash 1.4 const ZChar** className,
|
982 mike 1.1 MI_Boolean* done)
983 {
984 if (!pos->current)
985 {
986 *className = 0;
987
988 if (done)
989 *done = MI_TRUE;
990
991 return MI_RESULT_OK;
992 }
993
994 *className = pos->current->cn;
995
996 if (pos->deep)
997 {
998 pos->current = _GetNextTreeNodeLimittedBy(pos->current,pos->start);
999 }
1000 else
1001 {
1002 pos->current = pos->current->nextSibling;
1003 mike 1.1 }
1004
1005 if (done)
1006 *done = MI_FALSE;
1007
1008 return MI_RESULT_OK;
1009 }
1010
1011 MI_Result ProvReg_EndClasses(
1012 ProvRegPosition* pos)
1013 {
1014 memset( pos, -1, sizeof(*pos));
1015 return MI_RESULT_OK;
1016 }
1017
1018 /* returns enumerator to all registered association classes by given instance class
1019 and (optionally) assoc/result classes */
1020 MI_EXPORT MI_Result ProvReg_BeginAssocClasses(
1021 ProvReg* self,
|
1022 krisbash 1.4 const ZChar* nameSpace,
1023 const ZChar* className,
1024 const ZChar* assocClassName, /* can be NULL */
1025 const ZChar* resultClassName, /* can be NULL */
|
1026 mike 1.1 ProvRegAssocPosition* pos)
1027 {
1028 ProvRegNamespaceNode* namespaceNode;
1029
1030 if (!nameSpace || !className || !pos)
1031 return MI_RESULT_INVALID_PARAMETER;
1032
1033 /* clear pos */
1034 memset( pos, 0, sizeof(*pos));
1035
1036 /* check namespace */
|
1037 krisbash 1.4 namespaceNode = _FindNamespace(self,nameSpace, MI_FALSE);
|
1038 mike 1.1
1039 if (!namespaceNode)
1040 return MI_RESULT_INVALID_NAMESPACE;
1041
1042 /* find class */
1043 pos->currentLeft = _FindClassNodeInTree(namespaceNode->tree, className);
1044
1045 if (!pos->currentLeft)
1046 return MI_RESULT_INVALID_CLASS;
1047
1048 //pos->currentAssoc = pos->currentLeft->associatorClasses;
1049
1050 /* validate optional parameters */
1051 if (assocClassName)
1052 {
1053 ProvRegClassInheritanceNode* assocClassNode = _FindClassNodeInTree(namespaceNode->tree, assocClassName);
1054
1055 if (!assocClassNode)
1056 return MI_RESULT_INVALID_CLASS;
1057
1058 /* store node pointer */
1059 mike 1.1 pos->assocClass = assocClassNode;
1060 }
1061
1062 if (resultClassName)
1063 {
1064 ProvRegClassInheritanceNode* resultClassNode = _FindClassNodeInTree(namespaceNode->tree, resultClassName);
1065
1066 if (!resultClassNode)
1067 return MI_RESULT_INVALID_CLASS;
1068
1069 /* store node pointer */
1070 pos->resultClass = resultClassNode;
1071 }
1072
1073 return MI_RESULT_OK;
1074 }
1075
1076 static MI_Boolean _GetNextAssoc(
1077 ProvRegAssocPosition* pos)
1078 {
1079 /* check if we are at new node */
1080 mike 1.1 if (!pos->currentAssoc || !pos->currentLeft)
1081 {
1082 /* find class with assoc link */
1083 while (pos->currentLeft && !pos->currentLeft->associatorClasses)
1084 pos->currentLeft = pos->currentLeft->parent;
1085
1086 if (!pos->currentLeft)
1087 return MI_FALSE;
1088
1089 pos->currentAssoc = pos->currentLeft->associatorClasses;
1090 return MI_TRUE;
1091 }
1092
1093 pos->currentAssoc = pos->currentAssoc->next;
1094
1095 if (pos->currentAssoc)
1096 return MI_TRUE;
1097
1098 /* skip to parent */
1099 pos->currentLeft = pos->currentLeft->parent;
1100 return _GetNextAssoc(pos);
1101 mike 1.1 }
1102
1103 static MI_Boolean _IsNodeOrParentOf(
1104 ProvRegClassInheritanceNode* parent,
1105 ProvRegClassInheritanceNode* node)
1106 {
1107 while (node)
1108 {
1109 if (node == parent)
1110 return MI_TRUE;
1111
1112 node = node->parent;
1113 }
1114 return MI_FALSE;
1115 }
1116
1117 MI_EXPORT MI_Result ProvReg_NextAssocClass(
1118 ProvRegAssocPosition* pos,
|
1119 krisbash 1.4 const ZChar** className,
|
1120 mike 1.1 MI_Boolean* done)
1121 {
1122 /* navigate to next */
1123 if (!pos->currentLeft)
1124 {
1125 if (done)
1126 *done = MI_TRUE;
|
1127 mike 1.2
|
1128 mike 1.1 return MI_RESULT_OK;
1129 }
1130
1131 while (_GetNextAssoc(pos))
1132 {
1133 /* check filters */
1134 if ( (!pos->assocClass || _IsNodeOrParentOf(pos->assocClass, pos->currentAssoc->assocClass))
1135 && (!pos->resultClass || _IsNodeOrParentOf(pos->resultClass,
1136 pos->currentAssoc->assocClass->left != pos->currentLeft ? pos->currentAssoc->assocClass->left : pos->currentAssoc->assocClass->right)
1137 || _IsNodeOrParentOf(
1138 pos->currentAssoc->assocClass->left != pos->currentLeft ? pos->currentAssoc->assocClass->left : pos->currentAssoc->assocClass->right,
1139 pos->resultClass)) )
1140 {
1141 *className = pos->currentAssoc->assocClass->cn;
|
1142 mike 1.2
|
1143 mike 1.1 if (done)
1144 *done = MI_FALSE;
|
1145 mike 1.2
|
1146 mike 1.1 return MI_RESULT_OK;
1147 }
1148 }
1149
1150 if (done)
1151 *done = MI_TRUE;
|
1152 mike 1.2
|
1153 mike 1.1 return MI_RESULT_OK;
1154 }
1155
1156 MI_EXPORT MI_Result ProvReg_EndAssocClasses(
1157 ProvRegAssocPosition* pos)
1158 {
1159 memset( pos, -1, sizeof(*pos));
1160 return MI_RESULT_OK;
1161 }
1162
|
1163 krisbash 1.4 void MapRegPositionValuesToRegEntry(
1164 ProvRegEntry* reg,
1165 ProvRegPosition* pos)
1166 {
1167 if(reg && pos)
1168 {
1169 reg->className = pos->start->cn;
1170 reg->classNameHash = Hash(pos->start->cn);
1171 reg->hosting = pos->start->hosting;
1172 reg->libraryName = pos->start->library;
1173 //reg->provInterface
1174 reg->next = NULL;
1175 reg->user = pos->start->user;
1176 }
1177 }
1178
1179 /* Find event steam provider under given namespace */
1180 _Use_decl_annotations_
1181 const ProvRegEntry* ProvReg_FindProviderForClassByType(
1182 ProvReg* self,
1183 const ZChar* nameSpace,
1184 krisbash 1.4 const ZChar* className,
1185 ProvRegType type,
1186 MI_Result *findError)
1187 {
1188 ProvRegEntry* p;
1189 MI_Boolean namespaceFound = 0;
1190 unsigned int nameSpaceHash = Hash(nameSpace);
1191 unsigned int classNameHash = 0;
1192 if (!className)
1193 {
1194 if(findError)
1195 *findError = MI_RESULT_INVALID_PARAMETER;
1196 return NULL;
1197 }
1198 if (className)
1199 classNameHash = Hash(className);
1200
1201 for (p = self->head; p; p = p->next)
1202 {
1203 // comparing namespace everytime may slightly affect perf
1204 // but it enables us to give right error back to the client
1205 krisbash 1.4 if (nameSpaceHash == p->nameSpaceHash &&
1206 Tcscasecmp(p->nameSpace, nameSpace) == 0)
1207 {
1208 if (p->regType == type)
1209 {
1210 if (className)
1211 {
1212 /* for normal and indication class */
1213 if( classNameHash == p->classNameHash &&
1214 Tcscasecmp(p->className, className) == 0)
1215 {
1216 if(findError)
1217 {
1218 *findError = MI_RESULT_OK;
1219 }
1220 return p;
1221 }
1222 }
1223 else
1224 {
1225 /* for event stream class */
1226 krisbash 1.4 if(findError)
1227 {
1228 *findError = MI_RESULT_OK;
1229 }
1230 return p;
1231 }
1232 namespaceFound = MI_TRUE;
1233 }
1234 }
1235 }
1236
1237 if(findError)
1238 {
1239 *findError = (MI_TRUE == namespaceFound) ? MI_RESULT_INVALID_CLASS : MI_RESULT_INVALID_NAMESPACE;
1240 }
1241 /* Not found */
1242 return NULL;
1243 }
|