1 #include "csf.h"
2 #include "csfimpl.h"
3 
4 #include <stdlib.h>
5 
6 /***************/
7 /* EXTERNALS   */
8 /***************/
9 
10 static MAP **mapList    = NULL;
11 static size_t mapListLen = 4;
12 
13 /*********************/
14 /* LOCAL DEFINITIONS */
15 /*********************/
16 
17 /**********************/
18 /* LOCAL DECLARATIONS */
19 /**********************/
20 
21 /******************/
22 /* IMPLEMENTATION */
23 /******************/
24 
25 
26 /* close all open maps at exit  (LIBRARY_INTERNAL)
27  * passed through atexit to c-library
28  * exit code
29  */
CsfCloseCsfKernel(void)30 static void CsfCloseCsfKernel(void)
31 {
32   size_t i;
33 
34   for(i = 0; i < mapListLen; i++)
35    if(mapList[i] != NULL)
36     if(Mclose(mapList[i]))
37       (void)fprintf(stderr,"CSF_INTERNAL_ERROR: unable to close %s at exit\n",
38         mapList[i]->fileName);
39   CSF_FREE(mapList);
40   mapList = NULL;
41 }
42 
43 /* boot the CSF runtime library (LIBRARY_INTERNAL)
44  * CsfBootCsfKernel creates the mapList and adds the function to
45  *  close all files at a system exit
46  *
47  * NOTE
48  * Note that CsfBootCsfKernel never returns if there isn't enough
49  * memory to allocate an array of mapListLen pointers, or if
50  * the atexit() call fails
51  */
CsfBootCsfKernel(void)52 void CsfBootCsfKernel(void)
53 {
54   POSTCOND(mapList == NULL);
55 
56   mapList = (MAP **)calloc(mapListLen,sizeof(MAP *));
57   if (mapList == NULL) {
58     (void)fprintf(stderr,"CSF_INTERNAL_ERROR: Not enough memory to use CSF-files\n");
59     exit(1);
60   }
61 
62   if (atexit(CsfCloseCsfKernel)) {
63     (void)fprintf(stderr,"CSF_INTERNAL_ERROR: Impossible to close CSF-files automatically at exit\n");
64     exit(1);
65   }
66 }
67 
68 /* check if the kernel is booted (LIBRARY_INTERNAL)
69  * returns 0 if not, nonzero if already booted
70  */
CsfIsBootedCsfKernel(void)71 int CsfIsBootedCsfKernel(void)
72 {
73   return(mapList != NULL);
74 }
75 
76 /* put map in run time structure (LIBRARY_INTERNAL)
77  * Every map opened or created is
78  * registered in a list for verification
79  * if functions get a valid map handle
80  * passed and for automatic closing
81  * at exit if the application forgets it.
82  */
CsfRegisterMap(MAP * m)83 void CsfRegisterMap(
84   MAP *m) /* map handle to be registered, the field m->mapListId is
85            * initialized
86            */
87 {
88   size_t i=0;
89 
90   while (i < mapListLen && mapList[i] != NULL)
91     i++;
92 
93   if(i == mapListLen)
94   {
95     size_t j;
96     MAP** mapListNew;
97     /* double size */
98     /* +1 to make clang static analyzer not warn about realloc(0) */
99     mapListLen = 2 * mapListLen + 1;
100     mapListNew=realloc(mapList,sizeof(MAP *)*mapListLen);
101     if (mapListNew == NULL) {
102      (void)fprintf(stderr,"CSF_INTERNAL_ERROR: Not enough memory to use CSF-files\n");
103       exit(1);
104     }
105     mapList = mapListNew;
106     /* initialize new part, i at begin */
107     for(j=i; j < mapListLen; ++j)
108       mapList[j]=0;
109   }
110 
111   mapList[i] =   m;
112   m->mapListId = (int)i;
113 }
114 
115 /* remove map from run time structure (LIBRARY_INTERNAL)
116  * The map handle will become invalid.
117  */
CsfUnloadMap(MAP * m)118 void CsfUnloadMap(
119   MAP *m) /* map handle */
120 {
121   POSTCOND(CsfIsValidMap(m));
122 
123   mapList[m->mapListId] = NULL;
124   m->mapListId = -1;
125 }
126 
127 /* check if the map handle is created via the csf kernel (LIBRARY_INTERNAL)
128  */
CsfIsValidMap(const MAP * m)129 int CsfIsValidMap(
130   const MAP *m) /* map handle */
131 {
132   return(CsfIsBootedCsfKernel() && m != NULL
133           && m->mapListId >= 0 && ((size_t)m->mapListId) < mapListLen
134     && mapList[m->mapListId] == m);
135 }
136