DtSvc/DtUtil1: fix implicit function declarations
[oweals/cde.git] / cde / lib / DtSvc / DtUtil1 / MMDb.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 /* $TOG: MMDb.c /main/19 1998/10/23 13:48:52 mgreess $ */
24 /*
25  * +SNOTICE
26  * 
27  * Copyright 1995 Sun Microsystems, Inc.  All rights reserved.
28  * 
29  * +ENOTICE
30  */
31 #include <stdio.h>
32 #include <sys/types.h>
33
34 #include <unistd.h>
35 #include <sys/utsname.h>
36 #include <stdlib.h>
37
38 #include <ctype.h>
39 #include <string.h>
40 #include <stdint.h>
41
42 #ifdef NLS16
43 #include <limits.h>
44 #endif
45
46 #include <sys/stat.h>
47 #include <sys/param.h>          /* MAXPATHLEN, MAXHOSTNAMELEN */
48 #define X_INCLUDE_DIRENT_H
49 #define XOS_USE_XT_LOCKING
50 #include <X11/Xos_r.h>
51 #include <Dt/DbReader.h>
52 #include <Dt/DtsDb.h>
53 #include <Dt/DtsMM.h>
54 #include <Dt/DtShmDb.h>
55 #include <Dt/Dts.h>
56 #include <Dt/ActionP.h>
57 #include <Dt/ActionDbP.h>
58 #include <Dt/ActionUtilP.h>
59 #include <Dt/DtNlUtils.h>
60 #include <Dt/UserMsg.h>
61 #include "myassertP.h"
62 #include "DtSvcLock.h"
63
64 static void build_file_list(DtShmProtoIntList, DtDirPaths *,
65                             DtDtsMMHeader *, const char *);
66 extern  int     cde_dc_field_compare(DtDtsDbField **, DtDtsDbField **);
67 extern  int     cde_dc_compare(DtDtsDbRecord **, DtDtsDbRecord **);
68 static void     _DtMMSortDataTypes(DtShmProtoStrtab str_handle);
69 static void     _DtMMAddActionsToDataAttribute(DtDtsDbDatabase *db_ptr);
70 static int      write_db(DtDtsMMHeader *header, void *index, int size,
71                          const char *CacheFile);
72 static int      build_new_db(DtShmProtoStrtab, DtShmProtoIntList, int, DtDtsDbDatabase **);
73 static int      build_name_list(DtDtsDbDatabase *, DtShmProtoIntList, DtDtsMMHeader *);
74
75 static  DtShmProtoStrtab        shm_handle = 0;
76 static  DtShmProtoIntList       int_handle = 0;
77
78 #define QtB(a)  _DtShmProtoAddStrtab(shm_handle, XrmQuarkToString(a), &isnew)
79
80 /* DtsMM.c */
81 extern int _DtDtsMMPathHash(DtDirPaths *dirs);
82
83
84 int
85 _MMWriteDb(DtDirPaths *dirs, int num_db, DtDtsDbDatabase **db_list,
86            const char *CacheFile)
87 {
88         DtDtsMMHeader           header;
89         char                    *suffix = ".dt";
90         int                     tbl_size;
91         void                    *tbl_data;
92         DtDtsDbDatabase         *db;
93         int                     returnCode;
94
95         _DtSvcProcessLock();
96         memset(&header, '\0', sizeof(header));
97         int_handle = _DtShmProtoInitIntLst(50000);
98         shm_handle = _DtShmProtoInitStrtab(10000);
99
100         build_file_list(int_handle, dirs, &header, suffix);
101
102         _DtMMSortDataTypes(shm_handle);
103         db = (DtDtsDbDatabase   *) _DtDtsDbGet(DtDTS_DA_NAME);
104         _DtMMAddActionsToDataAttribute(db);
105
106         header.pathhash = _DtDtsMMPathHash(dirs);
107         header.num_db = num_db;
108         header.db_offset = build_new_db(shm_handle, int_handle, num_db,
109 db_list);
110         db = (DtDtsDbDatabase   *) _DtDtsDbGet("DATA_CRITERIA");
111         build_name_list(db, int_handle, &header);
112
113         tbl_size = _DtShmProtoSizeStrtab(shm_handle);
114         tbl_data = (void *) _DtShmProtoAddIntLst(int_handle,
115                                 tbl_size/sizeof(int), &header.str_tbl_offset);
116         _DtShmProtoCopyStrtab(shm_handle, tbl_data);
117
118
119         tbl_size = _DtShmProtoSizeIntLst(int_handle);
120         tbl_data = (void *)malloc(tbl_size);
121         memset(tbl_data, '\0', tbl_size);
122         tbl_data = (void *)_DtShmProtoCopyIntLst(int_handle, tbl_data);
123
124         returnCode = write_db(&header, tbl_data, tbl_size, CacheFile);
125         _DtShmProtoDestroyStrtab(shm_handle);
126         _DtShmProtoDestroyIntLst(int_handle);
127         _DtSvcProcessUnlock();
128         free(tbl_data);
129
130         return returnCode;
131 }
132
133 static void
134 build_file_list(DtShmProtoIntList int_handle, DtDirPaths *dirs,
135                 DtDtsMMHeader *header, const char *suffix)
136 {
137         DIR                     *dirp;
138         struct dirent           *dp = NULL;
139         struct stat             buf;
140         char                    cur_path[MAXPATHLEN+1];
141         void                    *data;
142         int                     size = sizeof(buf.st_mtime);
143         int                     i;
144         int                     isnew;
145         DtShmBoson              *boson_list = 0;
146         time_t                  *mtime_list = 0;
147         int                     count = 0;
148         _Xreaddirparams         dirEntryBuf;
149         struct dirent           *result;
150
151         /* Theses here to make sure it gets into the string tables
152            because actions uses it in its "types" field. */
153         _DtShmProtoAddStrtab(shm_handle, DtDTS_DT_UNKNOWN, &isnew);
154         _DtShmProtoAddStrtab(shm_handle, DtDTS_DT_RECURSIVE_LINK, &isnew);
155         _DtShmProtoAddStrtab(shm_handle, DtDTS_DT_BROKEN_LINK, &isnew);
156
157         getcwd(cur_path, sizeof(cur_path));
158         for(i = 0; dirs->paths[i]; i++)
159         {
160                 chdir(dirs->paths[i]);
161                 stat(".", &buf);
162                 count++;
163                 boson_list = (int *)realloc(boson_list, count*sizeof(int));
164                 mtime_list = (time_t *)realloc(mtime_list, count*sizeof(time_t));
165
166                 mtime_list[count-1] = buf.st_mtime;
167                 boson_list[count-1] = _DtShmProtoAddStrtab(shm_handle, dirs->paths[i], &isnew);
168                 dirp = opendir(".");
169                 while ((result = _XReaddir(dirp, dirEntryBuf)) != NULL)
170                 {
171                         char    *c = strrchr(result->d_name, suffix[0]);
172                         if(c && strcmp(c, suffix) == 0)
173                         {
174                                 char    *pathname = malloc(MAXPATHLEN+1);
175                                 sprintf(pathname, "%s/%s", dirs->paths[i], result->d_name);
176                                 stat(result->d_name, &buf);
177                                 count++;
178                                 boson_list = (int *)realloc(boson_list, count*sizeof(int));
179                                 mtime_list = (time_t *)realloc(mtime_list, count*sizeof(time_t));
180                                 mtime_list[count-1] = buf.st_mtime;
181                                 boson_list[count-1] = _DtShmProtoAddStrtab(shm_handle,
182                                         pathname, &isnew);
183                                 free(pathname);
184                                 continue;
185                         }
186                 }
187                 (void)closedir( dirp );
188         }
189         chdir(cur_path);
190         data = _DtShmProtoAddIntLst(int_handle, count, &header->files_offset);
191         memcpy(data, boson_list, count*sizeof(int));
192         data = _DtShmProtoAddIntLst(int_handle, count*sizeof(time_t)/sizeof(int), &header->mtimes_offset);
193         memcpy(data, mtime_list, count*sizeof(time_t));
194         header->files_count = count;
195         free(boson_list);
196         free(mtime_list);
197         return;
198 }
199
200 static int
201 db_table_size(int num_db, DtDtsDbDatabase **db_list)
202 {
203         int                     db;
204         DtDtsDbDatabase         *db_ptr;
205         int                     rec;
206         DtDtsDbRecord           *rec_ptr;
207         int                     fld;
208         DtDtsDbField            *fld_ptr;
209         int                     size = 0;
210
211         size += num_db*sizeof(DtDtsMMDatabase);
212         for(db = 0; db < num_db; db++)
213         {
214                 db_ptr = db_list[db];
215                 size += db_ptr->recordCount * sizeof(DtDtsMMRecord);
216                 for(rec = 0; rec < db_ptr->recordCount; rec++)
217                 {
218                         rec_ptr = db_ptr->recordList[rec];
219                         size += rec_ptr->fieldCount * sizeof(DtDtsMMField);
220                 }
221         }
222         return(size/sizeof(int));
223 }
224 static void
225 _DtMMSortDataTypes(DtShmProtoStrtab str_handle)
226 {
227         DtDtsDbDatabase *dc;
228         DtDtsDbDatabase *da;
229         int             i;
230
231         _DtSvcProcessLock();       
232         dc = (DtDtsDbDatabase *) _DtDtsDbGet(DtDTS_DC_NAME);
233         da = (DtDtsDbDatabase *) _DtDtsDbGet(DtDTS_DA_NAME);
234
235 /*_DtDtsDbPrintRecords(dc, stdout);*/
236         for(i = 0; i < dc->recordCount; i++)
237         {
238                 if(dc->recordList[i]->compare != cde_dc_field_compare)
239                 {
240                         _DtDtsDbFieldSort(dc->recordList[i], 
241                                 cde_dc_field_compare);
242                 }
243         }
244         _DtDtsDbRecordSort(dc, cde_dc_compare);
245
246         for(i = 0; i < da->recordCount; i++)
247         {
248                 if(da->recordList[i]->compare !=
249                                 _DtDtsDbCompareFieldNames)
250                 {
251                         _DtDtsDbFieldSort(da->recordList[i], 
252                                 _DtDtsDbCompareFieldNames);
253                 }
254         }
255
256         _DtDtsDbRecordSort(da, _DtDtsDbCompareRecordNames);
257 /*_DtDtsDbPrintRecords(dc, stdout);*/
258         _DtSvcProcessUnlock();
259 }
260
261 static void
262 add_if_missing(DtDtsDbRecord *rec_ptr, XrmQuark name, char *value)
263 {
264         DtDtsDbField    *fld_ptr;
265         int             fld;
266         int             found = 0;
267
268         for(fld = 0; fld < rec_ptr->fieldCount; fld++)
269         {
270                 fld_ptr = rec_ptr->fieldList[fld];
271                 if(name == fld_ptr->fieldName)
272                 {
273                         found = 1;
274                         break;
275                 }
276         }
277         if(found)
278         {
279                 return;
280         }
281
282         fld_ptr = _DtDtsDbAddField(rec_ptr);
283         fld_ptr->fieldName = name;
284         fld_ptr->fieldValue = value;
285         _DtDtsDbFieldSort(rec_ptr, 0);
286
287         return;
288 }
289
290 static void
291 _DtMMAddActionsToDataAttribute(DtDtsDbDatabase *db_ptr)
292 {
293         int             rec;
294         DtDtsDbRecord   *rec_ptr;
295         int             action_flag = 0;
296         int             sort_flag = 0;
297         int             found_flag = 0;
298         int             n;
299         const   char    *tmp;
300         XrmQuark        desc_qrk = XrmStringToQuark(DtDTS_DA_DESCRIPTION);
301         XrmQuark        icon_qrk = XrmStringToQuark(DtDTS_DA_ICON);
302         XrmQuark        label_qrk = XrmStringToQuark(DtDTS_DA_LABEL);
303
304         for(rec = 0; rec < db_ptr->recordCount; rec++)
305         {
306                 int     found_des = 0;
307                 int     found_icon = 0;
308                 int     found_label = 0;
309                 char    *obj_type;
310
311                 rec_ptr = db_ptr->recordList[rec];
312                 obj_type = XrmQuarkToString(rec_ptr->recordName);
313
314                 if ( _DtDtsDbGetFieldByName(rec_ptr,
315                                 DtDTS_DA_IS_ACTION) == 0 )
316                 {
317                         continue;
318                 }
319                 add_if_missing(rec_ptr, desc_qrk, 
320                                 DtActionDescription(obj_type));
321                 add_if_missing(rec_ptr, icon_qrk, DtActionIcon(obj_type));
322                 add_if_missing(rec_ptr, label_qrk, DtActionLabel(obj_type));
323         }
324 }
325
326 static int
327 build_new_db(DtShmProtoStrtab shm_handle, DtShmProtoIntList int_handle, int num_db, DtDtsDbDatabase **db_list)
328 {
329         DtDtsMMDatabase         *new_db_list;
330         int                     db;
331         DtDtsDbDatabase         *db_ptr;
332         DtDtsMMDatabase         *new_db_ptr;
333         int                     rec;
334         DtDtsDbRecord           *rec_ptr;
335         DtDtsMMRecord           *new_rec_ptr;
336         DtDtsMMRecord           *new_rec_ptr_list;
337         int                     fld;
338         DtDtsDbField            *fld_ptr;
339         DtDtsMMField            *new_fld_ptr;
340         DtDtsMMField            *new_fld_ptr_list;
341         int                     index;
342         int                     db_index;
343         int                     isnew;
344         char                    *tmp;
345
346         /* create a space to hold the list of database structures */
347         new_db_list = (DtDtsMMDatabase *)_DtShmProtoAddIntLst(int_handle,
348                         num_db*sizeof(DtDtsMMDatabase)/sizeof(int),
349                         &db_index);
350         for(db = 0; db < num_db; db++)
351         {
352                 int     last_boson = -1;
353                 int     list_count = 0;
354                 DtShmProtoInttab        nameIndex;
355                 int             size;
356                 int             *idx;
357
358                 new_db_ptr = &new_db_list[db];
359                 db_ptr = db_list[db];
360
361                 new_db_ptr->databaseName = _DtShmProtoAddStrtab(shm_handle, db_ptr->databaseName, &isnew);
362                 new_db_ptr->recordCount = db_ptr->recordCount;
363                 /* create space to hold record list */
364                 new_rec_ptr_list = (DtDtsMMRecord *)_DtShmProtoAddIntLst(int_handle,
365                                 db_ptr->recordCount*sizeof(DtDtsMMRecord)/sizeof(int),
366                                 &index);
367
368                 new_db_ptr->recordList = index;
369                 /* create index to names list */
370                 nameIndex = _DtShmProtoInitInttab(db_ptr->recordCount);
371                 for(rec = 0; rec < db_ptr->recordCount; rec++)
372                 {
373                         new_rec_ptr = &new_rec_ptr_list[rec];
374                         rec_ptr = db_ptr->recordList[rec];
375                         new_rec_ptr->recordName = QtB(rec_ptr->recordName);
376
377                         if(new_rec_ptr->recordName != last_boson)
378                         {
379                                 /* save name position */
380                                 _DtShmProtoAddInttab(nameIndex, new_rec_ptr->recordName, rec);
381
382                                 last_boson = new_rec_ptr->recordName;
383                         }
384                         new_rec_ptr->pathId = _DtShmProtoAddStrtab(shm_handle,
385                                 tmp = _DtDbPathIdToString(rec_ptr->pathId),
386                                                  &isnew);
387                         XtFree(tmp);
388                         new_rec_ptr->seq = rec_ptr->seq;
389                         new_rec_ptr->fieldCount = rec_ptr->fieldCount;
390
391                         /* create space for field list */
392                         new_fld_ptr_list = (DtDtsMMField *)_DtShmProtoAddIntLst(int_handle,
393                                 rec_ptr->fieldCount*sizeof(DtDtsMMField)/sizeof(int),
394                                 &index);
395
396                         new_rec_ptr->fieldList = index;
397                         for(fld = 0; fld < rec_ptr->fieldCount; fld++)
398                         {
399                                 new_fld_ptr = &new_fld_ptr_list[fld];
400                                 fld_ptr = rec_ptr->fieldList[fld];
401
402                                 new_fld_ptr->fieldName  = QtB(fld_ptr->fieldName);
403                                 new_fld_ptr->fieldValue = fld_ptr->fieldValue?_DtShmProtoAddStrtab(shm_handle,
404                                         fld_ptr->fieldValue, &isnew):0;
405                         }
406                 }
407                 /* create table for index and save it */
408                 size = _DtShmProtoSizeInttab(nameIndex);
409                 idx = _DtShmProtoAddIntLst(int_handle, size/sizeof(int), &new_db_ptr->nameIndex);
410                 _DtShmProtoCopyInttab(nameIndex, (void *)idx);
411                 _DtShmProtoDestroyInttab(nameIndex);
412         }
413         return(db_index);
414 }
415
416 struct  list
417 {
418         DtShmBoson      boson;
419         int             rec;
420 };
421
422 static int
423 srch(const void *a, const void *b)
424 {
425         int results = ((struct list *)a)->boson - ((struct list *)b)->boson;
426
427         if(results == 0)
428         {
429                 results = ((struct list *)a)->rec - ((struct list *)b)->rec;
430         }
431         return(results);
432 }
433
434 static void
435 showtable(
436         DtDtsDbDatabase *db,
437         struct list *name_index, 
438         struct list *other, 
439         DtDtsMMHeader *head,
440         int other_break)
441 {
442         int     i;
443
444         printf("============== names =====================\n");
445         for(i = 0; name_index[i].boson; i++)
446         {
447                 printf("%20s -> %s\n",
448                         XrmQuarkToString(db->recordList[name_index[i].rec]->recordName),
449                         _DtShmProtoLookUpStrtab(shm_handle, 
450                                         name_index[i].boson));
451         }
452         printf("%d entries\n", i);
453         
454         printf("============= other ======================\n");
455         for(i = 0; i < other_break; i++)
456         {
457                 printf("%s\n",
458                         XrmQuarkToString(db->recordList[other[i].rec]->recordName));
459         }
460         printf("%d entries\n", i);                      
461 }
462
463 static int
464 build_name_list(DtDtsDbDatabase *db,
465                 DtShmProtoIntList int_handle,
466                 DtDtsMMHeader   *head)
467 {
468         struct list     *other;
469         int             i;
470         char            *c;
471         int             isnew;
472         struct list     *name_index;
473         int             next = 0;
474         int             other_break = 0;
475         DtShmProtoInttab        indexList = 0;
476         DtShmBoson      last_boson = -1;
477         int             *list_of_recs = 0;
478         int             list_count = 0;
479         int             index = 0;
480         int             size;
481         void            *space;
482
483         /* create tmp space for two lists */
484         name_index = (struct list *)calloc(db->recordCount*2,
485                                         sizeof(struct list));
486         other = (struct list *)calloc(db->recordCount, sizeof(struct list));
487
488         /* step through all records */
489         for(i = 0; i < db->recordCount; i++)
490         {
491                 DtShmBoson      boson;
492                 char    *attr;
493                 char    *t;
494
495                 /* see if a name pattern exist */
496                 attr = _DtDtsDbGetFieldByName(db->recordList[i],
497                                 DtDTS_NAME_PATTERN);
498                 if(!attr)
499                 {
500                         /* it didn't so check path pattern */
501                         attr = _DtDtsDbGetFieldByName(db->recordList[i],
502                                 DtDTS_PATH_PATTERN);
503                         if(!attr)
504                         {
505                                 /* neither exist so save it as plain buffer */
506                                 if(!head->buffer_start_index)
507                                 {
508                                         head->buffer_start_index = other_break;
509                                 }
510                                 other[other_break++].rec = i;
511                                 continue; /* go to next record */
512                         }
513                 }
514
515                 /* we have a name now find its final component */
516                 c = strrchr(attr, '/');
517                 if(c)
518                 {
519                         c++;
520                 }
521                 if(!c)
522                 {
523                         c = attr;
524                 }
525                 else
526                 {
527                         attr = c;
528                 }
529
530                 /* now see if that final component has any *,?,[ */
531                 while(c && *c &&
532                           !(*c == '*' ||
533                             *c == '[' ||
534                             *c == '?' ||
535                             *c == '$' ))
536                 {
537                         c++;
538                 }
539
540
541                 if(c && *c == '\0')
542                 {
543                         /* it doesn't so save it in the name index */
544                         name_index[next].boson = 
545                                 _DtShmProtoAddStrtab(shm_handle,
546                                         (const char *)attr, &isnew);
547                         name_index[next++].rec = i;
548                         continue; /* next record */
549                 }
550
551                 /* the name had something in it now lets get the suffix */
552                 c = strrchr(attr, '.');
553                 attr = c;
554
555                 /* lets see if the suffix has any  *,?,[ */
556                 while(c && *c &&
557                           !(*c == '*' ||
558                             *c == '[' ||
559                             *c == '?' ||
560                             *c == '$' ))
561                 {
562                         c++;
563                 }
564                 if(c && *c == '\0')
565                 {
566                         /* it doesn't so save it in the name index */
567                         name_index[next].boson = 
568                         _DtShmProtoAddStrtab(shm_handle,
569                                         (const char *)attr, &isnew);
570                         name_index[next++].rec = i;
571                 }
572                 else
573                 {
574                         /* couldn't find any thing so save it as other */
575                         other[other_break++].rec = i;
576                 }
577
578         }
579
580         if (next > 0)
581         {
582                 qsort(name_index, next, sizeof(struct list), srch);
583         }
584
585 /*
586 showtable(db, name_index, other, head, other_break);
587 printf("                    next = %d\n", next);
588 printf("             other_break = %d\n", other_break);
589 printf("head->buffer_start_index = %d\n", head->buffer_start_index);
590 */
591         /* create a table and add the records to it. However
592            duplicates need to be in separate lists.
593         */
594         indexList = _DtShmProtoInitInttab(next+3);
595         for(i = 0; i <= next; i++)
596         {
597                 if(i != next && (last_boson == -1 || name_index[i].boson == last_boson))
598                 {
599                         /* this a new list of records or an addition to one */
600                         list_of_recs = (int *)realloc(list_of_recs, 
601                                         ++list_count*sizeof(int));
602                         last_boson = name_index[i].boson;
603                         list_of_recs[list_count-1] = name_index[i].rec;
604                 }
605                 else
606                 {
607                         /* we reached the end of a list now we check how many
608                                 are in the list. 
609                         */
610                         if(list_count == 1)
611                         {
612                                 /* if just one just add it in the index */
613                                 _DtShmProtoAddInttab(indexList,
614                                                 last_boson, list_of_recs[0]);
615                         }
616                         else
617                         {
618                                 /* if there are multiple items in the list
619                                    create a table for them */
620                                 int     *list = _DtShmProtoAddIntLst(int_handle,
621                                                 list_count, &index);
622
623                                 /* write the list to the to the table */
624                                 memcpy(list, list_of_recs,
625                                                 list_count*sizeof(int));
626
627                                 /* then index on the negative of the boson
628                                    so that we know it is a list */
629                                 _DtShmProtoAddInttab(indexList,
630                                                 last_boson, -index);
631                                 list_count = 0;
632                                 list_of_recs = (int *)realloc(list_of_recs, 
633                                                 ++list_count*sizeof(int));
634                         }
635                         if ( i != next )
636                         {
637                                 /* reset for the next set */
638                                 last_boson = name_index[i].boson;
639                                 list_of_recs[list_count-1] = name_index[i].rec;
640                         }
641                 }
642
643         }
644
645         /* same thing but they all go into a separate list */
646         if(other_break > 0)
647         {
648                 /* create the space */
649                 int     *list = _DtShmProtoAddIntLst(int_handle,
650                                 other_break, &head->no_name_offset);
651
652                 /* copy it into the list */
653                 for(i = 0; i < other_break; i++)
654                 {
655                         list[i] = other[i].rec;
656                 }
657         }
658         else
659         {
660                 head->no_name_offset = -1;
661         }
662
663         /* make the real space */
664         size = _DtShmProtoSizeInttab(indexList);
665         space = _DtShmProtoAddIntLst(int_handle, size/sizeof(int), 
666                                 &head->name_list_offset);
667         _DtShmProtoCopyInttab(indexList, space);
668         _DtShmProtoDestroyInttab(indexList);
669         free(name_index);
670         free(list_of_recs);
671         free(other);
672         return(index);
673 }
674
675 static int
676 write_db(DtDtsMMHeader *header, void *index, int size, const char *CacheFile)
677 {
678         int     fd;
679         mode_t  cmask = umask((mode_t)077);
680         char    *tmpfile;
681
682         if ((tmpfile = malloc(sizeof(_DTDTSMMTEMPDIR) +
683             sizeof(_DTDTSMMTEMPFILE) + 7)) == NULL) {
684                 _DtSimpleError(DtProgName, DtError, NULL, tmpfile, NULL);
685                 return 0;
686         }
687
688         sprintf(tmpfile, "%s/%sXXXXXX", _DTDTSMMTEMPDIR, _DTDTSMMTEMPFILE);
689         fd = mkstemp(tmpfile);
690
691         umask(cmask);
692
693         if(fd ==  -1)
694         {
695                 _DtSimpleError(
696                         DtProgName, DtError, NULL,
697                         (char*) tmpfile, NULL);
698                 free(tmpfile);
699                 return(0);
700         }
701
702         /* Remove file on write failure - we don't */
703         /* want a partial dtdbcache file. */
704         if ((write(fd, header, sizeof(DtDtsMMHeader))
705              != sizeof(DtDtsMMHeader)) ||
706             (write(fd, index, size) != size))
707         {
708                 close(fd);
709                 unlink(tmpfile);
710                 free(tmpfile);
711                 return(0);
712         }
713
714         close(fd);
715
716         if(rename((const char *)tmpfile, CacheFile) == -1)
717         {
718                 _DtSimpleError(
719                         DtProgName, DtError, NULL,
720                         (char*) CacheFile, NULL);
721                 unlink(CacheFile); /* Just in case? */
722                 unlink(tmpfile);
723                 free(tmpfile);
724                 return(0);
725         }
726         free(tmpfile);
727         return(1);
728 }
729
730
731 intptr_t _DtActionCompareRecordBoson(
732         DtDtsMMRecord *record1,
733         DtDtsMMRecord *record2 )
734 {
735         int results = (int)record1->recordName - (int)record2->recordName;
736
737         if (results)
738                 return(results);
739
740         return((intptr_t)record1 - (intptr_t)record2);
741 }