ba7c30865a5b621be1b94b3e41d7d5e4f5e39e8a
[oweals/cde.git] / cde / lib / DtSvc / DtUtil1 / DtsDb.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
25  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
26  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
27  * (c) Copyright 1993, 1994 Novell, Inc.                                *
28  */
29 /*
30  *+SNOTICE
31  *
32  *      $TOG: DtsDb.c /main/10 1998/10/23 13:48:04 mgreess $
33  *
34  *      RESTRICTED CONFIDENTIAL INFORMATION:
35  *      
36  *      The information in this document is subject to special
37  *      restrictions in a confidential disclosure agreement bertween
38  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
39  *      document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
40  *      Sun's specific written approval.  This documment and all copies
41  *      and derivative works thereof must be returned or destroyed at
42  *      Sun's request.
43  *
44  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
45  *
46  *+ENOTICE
47  */
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <unistd.h>
51 #include <sys/types.h>
52 #include <sys/stat.h>
53 #include <fcntl.h>
54 #ifdef  SUN_DB
55 #include <sys/mman.h>
56 #endif
57 #include <string.h>
58 #include <Dt/DbReader.h>
59 #include "Dt/DtsDb.h"
60 #include <Dt/UserMsg.h>
61 #include "DtSvcLock.h"
62
63 extern char *strdup(const char *);
64
65 #define PADMEM 10
66
67 typedef int     (*genfunc)(const void *, const void *);
68
69 static  DtDtsDbDatabase **db_list;
70 static  int     num_db = 0;
71
72 void
73 _DtDtsDbPrintFields(DtDtsDbRecord  *rec_ptr, FILE *fd)
74 {
75         int             fld;
76         DtDtsDbField    *fld_ptr;
77
78         for(fld = 0; fld < rec_ptr->fieldCount; fld++)
79         {
80                 fld_ptr = rec_ptr->fieldList[fld];
81                 fprintf(fd, "\t\t[%d]\t%s\t%s\n", fld,
82                         XrmQuarkToString(fld_ptr->fieldName),
83                         fld_ptr->fieldValue?
84                                 fld_ptr->fieldValue:"(NULL)");
85         }
86 }
87
88 void
89 _DtDtsDbPrintRecords(DtDtsDbDatabase  *db_ptr, FILE *fd)
90 {
91         int             rec;
92         DtDtsDbRecord   *rec_ptr;
93
94         _DtSvcProcessLock();
95         fprintf(fd, "%d Records\n", db_ptr->recordCount);
96         for(rec = 0; rec < db_ptr->recordCount; rec++)
97         {
98                 rec_ptr = db_ptr->recordList[rec];
99                 fprintf(fd, "\tRec[%d] name = %s\n\t%d Fields\n", rec,
100                         XrmQuarkToString(rec_ptr->recordName),
101                         rec_ptr->fieldCount);
102                 _DtDtsDbPrintFields(rec_ptr, fd);
103         }
104         _DtSvcProcessUnlock();
105 }
106
107 void
108 _DtDtsDbPrint(FILE *org_fd)
109 {
110         int             db;
111         int             rec;
112         DtDtsDbDatabase *db_ptr;
113         DtDtsDbRecord   *rec_ptr;
114         FILE            *fd = org_fd;
115
116         _DtSvcProcessLock();
117         for(db = 0; db < num_db; db++)
118         {
119                 if(!db_list[db])
120                 {
121                         continue;
122                 }
123                 db_ptr = db_list[db];
124                 if(fd == 0)
125                 {
126                         chdir("/tmp");
127                         if((fd = fopen(db_ptr->databaseName, "w")) == NULL)
128                         {
129                             _DtSimpleError(
130                                         DtProgName, DtError, NULL,
131                                         db_ptr->databaseName, NULL);
132                             continue;
133                         }
134                 }
135                 fprintf(fd, "DB[%d] ", db);
136                 fprintf(fd, "name = %s\n", db_ptr->databaseName);
137                 _DtDtsDbPrintRecords(db_ptr, fd);
138                 if(org_fd == 0)
139                 {
140                         fclose(fd);
141                         fd = 0;
142                 }
143         }
144         _DtSvcProcessUnlock();
145 }
146
147 int
148 _DtDtsDbCompareRecordNames(DtDtsDbRecord **a, DtDtsDbRecord **b)
149 {
150         return ((*a)->recordName - (*b)->recordName);
151 }
152
153 int
154 _DtDtsDbCompareFieldNames(DtDtsDbField **a, DtDtsDbField **b)
155 {
156         return ((*a)->fieldName - (*b)->fieldName);
157 }
158
159 #include <Dt/Dts.h>
160
161 DtDtsDbDatabase **
162 _DtDtsDbInit(void)
163 {
164         DtDtsDbDatabase **db;
165
166         _DtSvcProcessLock();
167         num_db = 0;
168         db = db_list = (DtDtsDbDatabase **)calloc(num_db+3, sizeof(DtDtsDbDatabase *));
169         db_list[0] = (DtDtsDbDatabase *)calloc(1, sizeof(DtDtsDbDatabase));
170         db_list[0]->databaseName = (char *)strdup(DtDTS_DC_NAME);
171         db_list[0]->ActionSequenceNumber = 0;
172         num_db++;
173
174         db_list[1] = (DtDtsDbDatabase *)calloc(1, sizeof(DtDtsDbDatabase));
175         db_list[1]->databaseName = (char *)strdup(DtDTS_DA_NAME);
176         db_list[1]->ActionSequenceNumber = 0;
177         num_db++;
178
179         _DtSvcProcessUnlock();
180         return(db);
181 }
182
183 char **
184 _DtsDbListDb(void)
185 {
186         int     i;
187         char    **list = 0;
188
189         _DtSvcProcessLock();
190         for ( i = 0; db_list[i]; i++ );
191
192         if(i > 0)
193         {
194                 list = (char **)calloc(i+1, sizeof(char *));
195                 for ( i = 0; db_list[i]; i++ )
196                 {
197                         list[i] = (char *)strdup(db_list[i]->databaseName);
198                 }
199         }
200         _DtSvcProcessUnlock();
201         return(list);
202 }
203
204 DtDtsDbDatabase *
205 _DtDtsDbAddDatabase( char *db_name )
206 {
207         int i = 0;
208         DtDtsDbDatabase **new_db_list;
209         DtDtsDbDatabase *ret_db;
210
211         _DtSvcProcessLock();
212         if ( !db_list )
213         {
214                 _DtDtsDbInit();
215         }
216         for ( i = 0; db_list[i]; i++ )
217         {
218                 if ( !strcmp(db_list[i]->databaseName,db_name) )
219                 {
220                         /*
221                          * A database with the given name already exists.
222                          * return a pointer to the existing database.
223                          */
224                         ret_db = db_list[i];
225                         _DtSvcProcessUnlock();
226
227                         return ret_db;
228                 }
229         }       
230         /*
231          * We now have a count of the existing databases.
232          * allocate enough space for the existing databases + the new one 
233          * + a NULL pointer to terminate the vector.
234          */
235
236         new_db_list = (DtDtsDbDatabase **)calloc(i+2,sizeof(DtDtsDbDatabase *));
237
238         memmove(new_db_list,db_list,sizeof(DtDtsDbDatabase *) * i );
239         new_db_list[i] = (DtDtsDbDatabase *)calloc(1, sizeof(DtDtsDbDatabase));
240         new_db_list[i]->databaseName = strdup(db_name);
241         new_db_list[i]->ActionSequenceNumber = 0;
242         free(db_list);
243         db_list = new_db_list;
244         num_db++;
245
246         ret_db = db_list[i];
247         _DtSvcProcessUnlock();
248
249         return ret_db;
250 }
251
252 int
253 _DtDtsDbDeleteDb(DtDtsDbDatabase *db)
254 {
255         int     i;
256         int     flag = 0;
257
258         _DtSvcProcessLock();
259         _DtDtsDbDeleteRecords(db);
260         free(db->databaseName);
261         free(db);
262
263         for(i = 0; db_list[i]; i++)
264         {
265                 if(db_list[i] == db)
266                 {
267                         flag = 1;
268                         db_list[i] = 0;
269                 }
270                 if(flag)
271                 {
272                         db_list[i] = db_list[i+1];
273                 }
274         }
275         if(db_list[0] == 0)
276         {
277                 free(db_list);
278                 db_list = 0;
279         }
280         _DtSvcProcessUnlock();
281         return(0);
282 }
283
284
285 DtDtsDbDatabase *
286 _DtDtsDbGet(char *name)
287 {
288         DtDtsDbDatabase *ret_db;
289         int             i;
290
291         _DtSvcProcessLock();
292         if(!db_list)
293         {
294                 _DtDtsDbInit();
295         }
296         for(i = 0; db_list && db_list[i] && db_list[i]->databaseName; i++)
297         {
298                 if(strcmp(db_list[i]->databaseName, name) == 0)
299                 {
300                         ret_db = db_list[i];
301                         _DtSvcProcessUnlock();
302
303                         return(ret_db);
304                 }
305         }
306         _DtSvcProcessUnlock();
307         return(NULL);
308 }
309
310 void
311 _DtDtsDbFieldSort(DtDtsDbRecord *rec, _DtDtsDbFieldCompare compare)
312 {
313         if(compare == NULL)
314         {
315                 compare = _DtDtsDbCompareFieldNames;
316         }
317         qsort(rec->fieldList,
318                 rec->fieldCount,
319                 sizeof(DtDtsDbField *),
320                 (genfunc)compare);
321         rec->compare = compare;
322 }
323
324 void
325 _DtDtsDbRecordSort(DtDtsDbDatabase *db, _DtDtsDbRecordCompare compare)
326 {
327         if(compare == NULL)
328         {
329                 compare = _DtDtsDbCompareRecordNames;
330         }
331         qsort(db->recordList,
332                 db->recordCount,
333                 sizeof(DtDtsDbRecord *),
334                 (genfunc)compare);
335         db->compare = compare;
336 }
337
338 DtDtsDbField *
339 _DtDtsDbGetField(DtDtsDbRecord *rec, char *name)
340 {
341         int i;
342
343         /*
344          * Field names have been quarked so quark 'name' and
345          * do a linear search for the quark'ed field name.
346          */
347         XrmQuark        tmp = XrmStringToQuark (name);
348
349         for (i = 0; i < rec->fieldCount; i++)
350         {
351                 if (rec->fieldList[i]->fieldName == tmp)
352                 {
353                         return (rec->fieldList[i]);
354                 }
355         }
356         return(NULL);
357 }
358
359 char *
360 _DtDtsDbGetFieldByName(DtDtsDbRecord *rec, char *name)
361 {
362         DtDtsDbField    *result;
363
364         result = _DtDtsDbGetField(rec, name);
365         if(result)
366         {
367                 return(result->fieldValue);
368         }
369         else
370         {
371                 return(NULL);
372         }
373
374 }
375
376 DtDtsDbRecord *
377 _DtDtsDbGetRecordByName(DtDtsDbDatabase *db, char *name)
378 {
379         DtDtsDbRecord   srch;
380         DtDtsDbRecord   **result;
381         DtDtsDbRecord   *s = &srch;
382         int i;
383         XrmQuark        name_quark = XrmStringToQuark(name);
384
385         /*
386          * If the fields are not sorted in alphanumeric order
387          * by name a binary search will fail.  So do the slow but
388          * sure linear search.
389          */
390         if(db->compare != _DtDtsDbCompareRecordNames)
391         {
392
393                 for (i = 0; i < db->recordCount; i++)
394                 {
395                         if (db->recordList[i]->recordName == name_quark)
396                         {
397                                 return (db->recordList[i]);
398                         }
399                 }
400                 return NULL;
401         }
402
403         srch.recordName = name_quark;   
404
405         if(db->recordCount == 0 || db->recordList == NULL)
406         {
407                 result = NULL;
408         }
409         else
410         {
411                 result = (DtDtsDbRecord **)bsearch(&s,
412                         db->recordList,
413                         db->recordCount,
414                         sizeof(DtDtsDbRecord *),
415                         (genfunc)_DtDtsDbCompareRecordNames);
416         }
417
418         if(result)
419         {
420                 return(*result);
421         }
422         else
423         {
424                 return(NULL);
425         }
426
427 }
428
429 DtDtsDbRecord *
430 _DtDtsDbAddRecord(DtDtsDbDatabase *db)
431 {
432         DtDtsDbRecord   **newlist;
433         int             rec = db->recordCount;
434
435         db->compare = (_DtDtsDbRecordCompare)NULL;
436         if(rec%PADMEM == 0)
437         {
438                 newlist = (DtDtsDbRecord **)calloc(rec+PADMEM,
439                                 sizeof(DtDtsDbRecord *));
440                 if(db->recordList)
441                 {
442                         memmove(newlist, db->recordList,
443                                 rec*sizeof(DtDtsDbRecord *));
444                         free(db->recordList);
445                 }
446                 db->recordList = newlist;
447         }
448         db->recordList[rec] = (DtDtsDbRecord *)calloc(1, sizeof(DtDtsDbRecord));
449         db->recordCount++;
450
451         return(db->recordList[rec]);
452 }
453
454 int
455 _DtDtsDbDeleteRecord(DtDtsDbRecord *rec, DtDtsDbDatabase *db)
456 {
457         int     i;
458
459         _DtDtsDbDeleteFields(rec);
460         free(rec);
461
462         for(i = 0; i < db->recordCount; i++)
463         {
464                 if(db->recordList[i] == rec)
465                 {
466                         memmove(        &(db->recordList[i]),
467                                 &(db->recordList[i+1]),
468                                 (db->recordCount - i - 1)*
469                                         sizeof(DtDtsDbRecord *));
470                         db->recordCount--;
471                         return(1);
472                 }
473         }
474
475         return(0);
476 }
477
478 int
479 _DtDtsDbDeleteRecords(DtDtsDbDatabase *db)
480 {
481         int     i;
482
483         for(i = 0; i < db->recordCount; i++)
484         {
485                 _DtDtsDbDeleteFields(db->recordList[i]);
486                 free(db->recordList[i]);
487         }
488         free(db->recordList);
489         db->recordList = 0;
490         return(0);
491 }
492
493 DtDtsDbField *
494 _DtDtsDbAddField(DtDtsDbRecord *rec)
495 {
496         DtDtsDbField    **newlist;
497         int             flds = rec->fieldCount;
498
499         if(flds%PADMEM == 0)
500         {
501                 newlist = (DtDtsDbField **)calloc(flds+PADMEM,
502                                 sizeof(DtDtsDbField *));
503                 if(rec->fieldList)
504                 {
505                         memmove(newlist, rec->fieldList,
506                                 flds*sizeof(DtDtsDbField *));
507                         free(rec->fieldList);
508                 }
509                 rec->fieldList = newlist;
510         }
511         rec->fieldList[flds] = (DtDtsDbField *)calloc(1, sizeof(DtDtsDbField));
512         rec->fieldCount++;
513
514         return(rec->fieldList[flds]);
515 }
516
517 int
518 _DtDtsDbDeleteField(DtDtsDbField *fld, DtDtsDbRecord *rec)
519 {
520         int     i;
521
522         free(fld);
523         for(i = 0; i < rec->fieldCount; i++)
524         {
525                 if(rec->fieldList[i] == fld)
526                 {
527                         memmove(        &(rec->fieldList[i]),
528                                 &(rec->fieldList[i+1]),
529                                 (rec->fieldCount - i - 1)*
530                                         sizeof(DtDtsDbField *));
531                         rec->fieldCount--;
532                         return(1);
533                 }
534         }
535
536         return(0);
537 }
538
539 int
540 _DtDtsDbDeleteFields(DtDtsDbRecord *rec)
541 {
542         int     i;
543
544         for(i = 0; i < rec->fieldCount; i++)
545         {
546                 free(rec->fieldList[i]->fieldValue);
547                 free(rec->fieldList[i]);
548         }
549         free(rec->fieldList);
550         rec->fieldList = 0;
551         return(0);
552 }
553
554 int
555 _DtDtsMMCreateFile(DtDirPaths *dirs, const char *CacheFile)
556 {
557         return _MMWriteDb(dirs, num_db, db_list, CacheFile);
558 }