736 lines
18 KiB
C
736 lines
18 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these librararies and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* $TOG: MMDb.c /main/19 1998/10/23 13:48:52 mgreess $ */
|
|
/*
|
|
* +SNOTICE
|
|
*
|
|
* Copyright 1995 Sun Microsystems, Inc. All rights reserved.
|
|
*
|
|
* +ENOTICE
|
|
*/
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
#include <sys/utsname.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
|
|
#ifdef NLS16
|
|
#include <limits.h>
|
|
#endif
|
|
|
|
#include <sys/stat.h>
|
|
#include <sys/param.h> /* MAXPATHLEN, MAXHOSTNAMELEN */
|
|
#define X_INCLUDE_DIRENT_H
|
|
#define XOS_USE_XT_LOCKING
|
|
#include <X11/Xos_r.h>
|
|
#include <Dt/DbReader.h>
|
|
#include <Dt/DtsDb.h>
|
|
#include <Dt/DtsMM.h>
|
|
#include <Dt/DtShmDb.h>
|
|
#include <Dt/Dts.h>
|
|
#include <Dt/ActionP.h>
|
|
#include <Dt/ActionDbP.h>
|
|
#include <Dt/ActionUtilP.h>
|
|
#include <Dt/DtNlUtils.h>
|
|
#include <Dt/UserMsg.h>
|
|
#include "myassertP.h"
|
|
#include "DtSvcLock.h"
|
|
|
|
static void build_file_list(DtShmProtoIntList, DtDirPaths *,
|
|
DtDtsMMHeader *, const char *);
|
|
extern int cde_dc_field_compare(DtDtsDbField **, DtDtsDbField **);
|
|
extern int cde_dc_compare(DtDtsDbRecord **, DtDtsDbRecord **);
|
|
static void _DtMMSortDataTypes(DtShmProtoStrtab str_handle);
|
|
static void _DtMMAddActionsToDataAttribute(DtDtsDbDatabase *db_ptr);
|
|
static int write_db(DtDtsMMHeader *header, void *index, int size,
|
|
const char *CacheFile);
|
|
static int build_new_db(DtShmProtoStrtab, DtShmProtoIntList, int, DtDtsDbDatabase **);
|
|
static int build_name_list(DtDtsDbDatabase *, DtShmProtoIntList, DtDtsMMHeader *);
|
|
|
|
static DtShmProtoStrtab shm_handle = 0;
|
|
static DtShmProtoIntList int_handle = 0;
|
|
|
|
#define QtB(a) _DtShmProtoAddStrtab(shm_handle, XrmQuarkToString(a), &isnew)
|
|
|
|
int
|
|
_MMWriteDb(DtDirPaths *dirs, int num_db, DtDtsDbDatabase **db_list,
|
|
const char *CacheFile)
|
|
{
|
|
DtDtsMMHeader header;
|
|
char *suffix = ".dt";
|
|
int tbl_size;
|
|
void *tbl_data;
|
|
DtDtsDbDatabase *db;
|
|
int returnCode;
|
|
|
|
_DtSvcProcessLock();
|
|
memset(&header, '\0', sizeof(header));
|
|
int_handle = _DtShmProtoInitIntLst(50000);
|
|
shm_handle = _DtShmProtoInitStrtab(10000);
|
|
|
|
build_file_list(int_handle, dirs, &header, suffix);
|
|
|
|
_DtMMSortDataTypes(shm_handle);
|
|
db = (DtDtsDbDatabase *) _DtDtsDbGet(DtDTS_DA_NAME);
|
|
_DtMMAddActionsToDataAttribute(db);
|
|
|
|
header.pathhash = _DtDtsMMPathHash(dirs);
|
|
header.num_db = num_db;
|
|
header.db_offset = build_new_db(shm_handle, int_handle, num_db,
|
|
db_list);
|
|
db = (DtDtsDbDatabase *) _DtDtsDbGet("DATA_CRITERIA");
|
|
build_name_list(db, int_handle, &header);
|
|
|
|
tbl_size = _DtShmProtoSizeStrtab(shm_handle);
|
|
tbl_data = (void *) _DtShmProtoAddIntLst(int_handle,
|
|
tbl_size/sizeof(int), &header.str_tbl_offset);
|
|
_DtShmProtoCopyStrtab(shm_handle, tbl_data);
|
|
|
|
|
|
tbl_size = _DtShmProtoSizeIntLst(int_handle);
|
|
tbl_data = (void *)malloc(tbl_size);
|
|
memset(tbl_data, '\0', tbl_size);
|
|
tbl_data = (void *)_DtShmProtoCopyIntLst(int_handle, tbl_data);
|
|
|
|
returnCode = write_db(&header, tbl_data, tbl_size, CacheFile);
|
|
_DtShmProtoDestroyStrtab(shm_handle);
|
|
_DtShmProtoDestroyIntLst(int_handle);
|
|
_DtSvcProcessUnlock();
|
|
free(tbl_data);
|
|
|
|
return returnCode;
|
|
}
|
|
|
|
static void
|
|
build_file_list(DtShmProtoIntList int_handle, DtDirPaths *dirs,
|
|
DtDtsMMHeader *header, const char *suffix)
|
|
{
|
|
DIR *dirp;
|
|
struct dirent *dp = NULL;
|
|
struct stat buf;
|
|
char cur_path[MAXPATHLEN+1];
|
|
void *data;
|
|
int size = sizeof(buf.st_mtime);
|
|
int i;
|
|
int isnew;
|
|
DtShmBoson *boson_list = 0;
|
|
time_t *mtime_list = 0;
|
|
int count = 0;
|
|
_Xreaddirparams dirEntryBuf;
|
|
struct dirent *result;
|
|
|
|
/* Theses here to make sure it gets into the string tables
|
|
because actions uses it in its "types" field. */
|
|
_DtShmProtoAddStrtab(shm_handle, DtDTS_DT_UNKNOWN, &isnew);
|
|
_DtShmProtoAddStrtab(shm_handle, DtDTS_DT_RECURSIVE_LINK, &isnew);
|
|
_DtShmProtoAddStrtab(shm_handle, DtDTS_DT_BROKEN_LINK, &isnew);
|
|
|
|
getcwd(cur_path, sizeof(cur_path));
|
|
for(i = 0; dirs->paths[i]; i++)
|
|
{
|
|
chdir(dirs->paths[i]);
|
|
stat(".", &buf);
|
|
count++;
|
|
boson_list = (int *)realloc(boson_list, count*sizeof(int));
|
|
mtime_list = (time_t *)realloc(mtime_list, count*sizeof(time_t));
|
|
|
|
mtime_list[count-1] = buf.st_mtime;
|
|
boson_list[count-1] = _DtShmProtoAddStrtab(shm_handle, dirs->paths[i], &isnew);
|
|
dirp = opendir(".");
|
|
while ((result = _XReaddir(dirp, dirEntryBuf)) != NULL)
|
|
{
|
|
char *c = strrchr(result->d_name, suffix[0]);
|
|
if(c && strcmp(c, suffix) == 0)
|
|
{
|
|
char *pathname = malloc(MAXPATHLEN+1);
|
|
sprintf(pathname, "%s/%s", dirs->paths[i], result->d_name);
|
|
stat(result->d_name, &buf);
|
|
count++;
|
|
boson_list = (int *)realloc(boson_list, count*sizeof(int));
|
|
mtime_list = (time_t *)realloc(mtime_list, count*sizeof(time_t));
|
|
mtime_list[count-1] = buf.st_mtime;
|
|
boson_list[count-1] = _DtShmProtoAddStrtab(shm_handle,
|
|
pathname, &isnew);
|
|
if (pathname) free(pathname);
|
|
continue;
|
|
}
|
|
}
|
|
(void)closedir( dirp );
|
|
}
|
|
chdir(cur_path);
|
|
data = _DtShmProtoAddIntLst(int_handle, count, &header->files_offset);
|
|
memcpy(data, boson_list, count*sizeof(int));
|
|
data = _DtShmProtoAddIntLst(int_handle, count*sizeof(time_t)/sizeof(int), &header->mtimes_offset);
|
|
memcpy(data, mtime_list, count*sizeof(time_t));
|
|
header->files_count = count;
|
|
if(boson_list)free(boson_list);
|
|
if(mtime_list)free(mtime_list);
|
|
return;
|
|
}
|
|
|
|
static int
|
|
db_table_size(int num_db, DtDtsDbDatabase **db_list)
|
|
{
|
|
int db;
|
|
DtDtsDbDatabase *db_ptr;
|
|
int rec;
|
|
DtDtsDbRecord *rec_ptr;
|
|
int fld;
|
|
DtDtsDbField *fld_ptr;
|
|
int size = 0;
|
|
|
|
size += num_db*sizeof(DtDtsMMDatabase);
|
|
for(db = 0; db < num_db; db++)
|
|
{
|
|
db_ptr = db_list[db];
|
|
size += db_ptr->recordCount * sizeof(DtDtsMMRecord);
|
|
for(rec = 0; rec < db_ptr->recordCount; rec++)
|
|
{
|
|
rec_ptr = db_ptr->recordList[rec];
|
|
size += rec_ptr->fieldCount * sizeof(DtDtsMMField);
|
|
}
|
|
}
|
|
return(size/sizeof(int));
|
|
}
|
|
static void
|
|
_DtMMSortDataTypes(DtShmProtoStrtab str_handle)
|
|
{
|
|
DtDtsDbDatabase *dc;
|
|
DtDtsDbDatabase *da;
|
|
int i;
|
|
|
|
_DtSvcProcessLock();
|
|
dc = (DtDtsDbDatabase *) _DtDtsDbGet(DtDTS_DC_NAME);
|
|
da = (DtDtsDbDatabase *) _DtDtsDbGet(DtDTS_DA_NAME);
|
|
|
|
/*_DtDtsDbPrintRecords(dc, stdout);*/
|
|
for(i = 0; i < dc->recordCount; i++)
|
|
{
|
|
if(dc->recordList[i]->compare != cde_dc_field_compare)
|
|
{
|
|
_DtDtsDbFieldSort(dc->recordList[i],
|
|
cde_dc_field_compare);
|
|
}
|
|
}
|
|
_DtDtsDbRecordSort(dc, cde_dc_compare);
|
|
|
|
for(i = 0; i < da->recordCount; i++)
|
|
{
|
|
if(da->recordList[i]->compare !=
|
|
_DtDtsDbCompareFieldNames)
|
|
{
|
|
_DtDtsDbFieldSort(da->recordList[i],
|
|
_DtDtsDbCompareFieldNames);
|
|
}
|
|
}
|
|
|
|
_DtDtsDbRecordSort(da, _DtDtsDbCompareRecordNames);
|
|
/*_DtDtsDbPrintRecords(dc, stdout);*/
|
|
_DtSvcProcessUnlock();
|
|
}
|
|
|
|
static void
|
|
add_if_missing(DtDtsDbRecord *rec_ptr, XrmQuark name, char *value)
|
|
{
|
|
DtDtsDbField *fld_ptr;
|
|
int fld;
|
|
int found = 0;
|
|
|
|
for(fld = 0; fld < rec_ptr->fieldCount; fld++)
|
|
{
|
|
fld_ptr = rec_ptr->fieldList[fld];
|
|
if(name == fld_ptr->fieldName)
|
|
{
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
if(found)
|
|
{
|
|
return;
|
|
}
|
|
|
|
fld_ptr = _DtDtsDbAddField(rec_ptr);
|
|
fld_ptr->fieldName = name;
|
|
fld_ptr->fieldValue = value;
|
|
_DtDtsDbFieldSort(rec_ptr, 0);
|
|
|
|
return;
|
|
}
|
|
|
|
static void
|
|
_DtMMAddActionsToDataAttribute(DtDtsDbDatabase *db_ptr)
|
|
{
|
|
int rec;
|
|
DtDtsDbRecord *rec_ptr;
|
|
int action_flag = 0;
|
|
int sort_flag = 0;
|
|
int found_flag = 0;
|
|
int n;
|
|
const char *tmp;
|
|
XrmQuark desc_qrk = XrmStringToQuark(DtDTS_DA_DESCRIPTION);
|
|
XrmQuark icon_qrk = XrmStringToQuark(DtDTS_DA_ICON);
|
|
XrmQuark label_qrk = XrmStringToQuark(DtDTS_DA_LABEL);
|
|
|
|
for(rec = 0; rec < db_ptr->recordCount; rec++)
|
|
{
|
|
int found_des = 0;
|
|
int found_icon = 0;
|
|
int found_label = 0;
|
|
char *obj_type;
|
|
|
|
rec_ptr = db_ptr->recordList[rec];
|
|
obj_type = XrmQuarkToString(rec_ptr->recordName);
|
|
|
|
if ( _DtDtsDbGetFieldByName(rec_ptr,
|
|
DtDTS_DA_IS_ACTION) == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
add_if_missing(rec_ptr, desc_qrk,
|
|
DtActionDescription(obj_type));
|
|
add_if_missing(rec_ptr, icon_qrk, DtActionIcon(obj_type));
|
|
add_if_missing(rec_ptr, label_qrk, DtActionLabel(obj_type));
|
|
}
|
|
}
|
|
|
|
static int
|
|
build_new_db(DtShmProtoStrtab shm_handle, DtShmProtoIntList int_handle, int num_db, DtDtsDbDatabase **db_list)
|
|
{
|
|
DtDtsMMDatabase *new_db_list;
|
|
int db;
|
|
DtDtsDbDatabase *db_ptr;
|
|
DtDtsMMDatabase *new_db_ptr;
|
|
int rec;
|
|
DtDtsDbRecord *rec_ptr;
|
|
DtDtsMMRecord *new_rec_ptr;
|
|
DtDtsMMRecord *new_rec_ptr_list;
|
|
int fld;
|
|
DtDtsDbField *fld_ptr;
|
|
DtDtsMMField *new_fld_ptr;
|
|
DtDtsMMField *new_fld_ptr_list;
|
|
int index;
|
|
int db_index;
|
|
int isnew;
|
|
char *tmp;
|
|
|
|
/* create a space to hold the list of database structures */
|
|
new_db_list = (DtDtsMMDatabase *)_DtShmProtoAddIntLst(int_handle,
|
|
num_db*sizeof(DtDtsMMDatabase)/sizeof(int),
|
|
&db_index);
|
|
for(db = 0; db < num_db; db++)
|
|
{
|
|
int last_boson = -1;
|
|
int list_count = 0;
|
|
DtShmProtoInttab nameIndex;
|
|
int size;
|
|
int *idx;
|
|
|
|
new_db_ptr = &new_db_list[db];
|
|
db_ptr = db_list[db];
|
|
|
|
new_db_ptr->databaseName = _DtShmProtoAddStrtab(shm_handle, db_ptr->databaseName, &isnew);
|
|
new_db_ptr->recordCount = db_ptr->recordCount;
|
|
/* create space to hold record list */
|
|
new_rec_ptr_list = (DtDtsMMRecord *)_DtShmProtoAddIntLst(int_handle,
|
|
db_ptr->recordCount*sizeof(DtDtsMMRecord)/sizeof(int),
|
|
&index);
|
|
|
|
new_db_ptr->recordList = index;
|
|
/* create index to names list */
|
|
nameIndex = _DtShmProtoInitInttab(db_ptr->recordCount);
|
|
for(rec = 0; rec < db_ptr->recordCount; rec++)
|
|
{
|
|
new_rec_ptr = &new_rec_ptr_list[rec];
|
|
rec_ptr = db_ptr->recordList[rec];
|
|
new_rec_ptr->recordName = QtB(rec_ptr->recordName);
|
|
|
|
if(new_rec_ptr->recordName != last_boson)
|
|
{
|
|
/* save name position */
|
|
_DtShmProtoAddInttab(nameIndex, new_rec_ptr->recordName, rec);
|
|
|
|
last_boson = new_rec_ptr->recordName;
|
|
}
|
|
new_rec_ptr->pathId = _DtShmProtoAddStrtab(shm_handle,
|
|
tmp = _DtDbPathIdToString(rec_ptr->pathId),
|
|
&isnew);
|
|
XtFree(tmp);
|
|
new_rec_ptr->seq = rec_ptr->seq;
|
|
new_rec_ptr->fieldCount = rec_ptr->fieldCount;
|
|
|
|
/* create space for field list */
|
|
new_fld_ptr_list = (DtDtsMMField *)_DtShmProtoAddIntLst(int_handle,
|
|
rec_ptr->fieldCount*sizeof(DtDtsMMField)/sizeof(int),
|
|
&index);
|
|
|
|
new_rec_ptr->fieldList = index;
|
|
for(fld = 0; fld < rec_ptr->fieldCount; fld++)
|
|
{
|
|
new_fld_ptr = &new_fld_ptr_list[fld];
|
|
fld_ptr = rec_ptr->fieldList[fld];
|
|
|
|
new_fld_ptr->fieldName = QtB(fld_ptr->fieldName);
|
|
new_fld_ptr->fieldValue = fld_ptr->fieldValue?_DtShmProtoAddStrtab(shm_handle,
|
|
fld_ptr->fieldValue, &isnew):0;
|
|
}
|
|
}
|
|
/* create table for index and save it */
|
|
size = _DtShmProtoSizeInttab(nameIndex);
|
|
idx = _DtShmProtoAddIntLst(int_handle, size/sizeof(int), &new_db_ptr->nameIndex);
|
|
_DtShmProtoCopyInttab(nameIndex, (void *)idx);
|
|
_DtShmProtoDestroyInttab(nameIndex);
|
|
}
|
|
return(db_index);
|
|
}
|
|
|
|
struct list
|
|
{
|
|
DtShmBoson boson;
|
|
int rec;
|
|
};
|
|
|
|
static int
|
|
srch(const void *a, const void *b)
|
|
{
|
|
int results = ((struct list *)a)->boson - ((struct list *)b)->boson;
|
|
|
|
if(results == 0)
|
|
{
|
|
results = ((struct list *)a)->rec - ((struct list *)b)->rec;
|
|
}
|
|
return(results);
|
|
}
|
|
|
|
static void
|
|
showtable(
|
|
DtDtsDbDatabase *db,
|
|
struct list *name_index,
|
|
struct list *other,
|
|
DtDtsMMHeader *head,
|
|
int other_break)
|
|
{
|
|
int i;
|
|
|
|
printf("============== names =====================\n");
|
|
for(i = 0; name_index[i].boson; i++)
|
|
{
|
|
printf("%20s -> %s\n",
|
|
XrmQuarkToString(db->recordList[name_index[i].rec]->recordName),
|
|
_DtShmProtoLookUpStrtab(shm_handle,
|
|
name_index[i].boson));
|
|
}
|
|
printf("%d entries\n", i);
|
|
|
|
printf("============= other ======================\n");
|
|
for(i = 0; i < other_break; i++)
|
|
{
|
|
printf("%s\n",
|
|
XrmQuarkToString(db->recordList[other[i].rec]->recordName));
|
|
}
|
|
printf("%d entries\n", i);
|
|
}
|
|
|
|
static int
|
|
build_name_list(DtDtsDbDatabase *db,
|
|
DtShmProtoIntList int_handle,
|
|
DtDtsMMHeader *head)
|
|
{
|
|
struct list *other;
|
|
int i;
|
|
char *c;
|
|
int isnew;
|
|
struct list *name_index;
|
|
int next = 0;
|
|
int other_break = 0;
|
|
DtShmProtoInttab indexList = 0;
|
|
DtShmBoson last_boson = -1;
|
|
int *list_of_recs = 0;
|
|
int list_count = 0;
|
|
int index = 0;
|
|
int size;
|
|
void *space;
|
|
|
|
/* create tmp space for two lists */
|
|
name_index = (struct list *)calloc(db->recordCount*2,
|
|
sizeof(struct list));
|
|
other = (struct list *)calloc(db->recordCount, sizeof(struct list));
|
|
|
|
/* step through all records */
|
|
for(i = 0; i < db->recordCount; i++)
|
|
{
|
|
DtShmBoson boson;
|
|
char *attr;
|
|
char *t;
|
|
|
|
/* see if a name pattern exist */
|
|
attr = _DtDtsDbGetFieldByName(db->recordList[i],
|
|
DtDTS_NAME_PATTERN);
|
|
if(!attr)
|
|
{
|
|
/* it didn't so check path pattern */
|
|
attr = _DtDtsDbGetFieldByName(db->recordList[i],
|
|
DtDTS_PATH_PATTERN);
|
|
if(!attr)
|
|
{
|
|
/* neither exist so save it as plain buffer */
|
|
if(!head->buffer_start_index)
|
|
{
|
|
head->buffer_start_index = other_break;
|
|
}
|
|
other[other_break++].rec = i;
|
|
continue; /* go to next record */
|
|
}
|
|
}
|
|
|
|
/* we have a name now find its final component */
|
|
c = strrchr(attr, '/');
|
|
if(c)
|
|
{
|
|
c++;
|
|
}
|
|
if(!c)
|
|
{
|
|
c = attr;
|
|
}
|
|
else
|
|
{
|
|
attr = c;
|
|
}
|
|
|
|
/* now see if that final component has any *,?,[ */
|
|
while(c && *c &&
|
|
!(*c == '*' ||
|
|
*c == '[' ||
|
|
*c == '?' ||
|
|
*c == '$' ))
|
|
{
|
|
c++;
|
|
}
|
|
|
|
|
|
if(c && *c == '\0')
|
|
{
|
|
/* it doesn't so save it in the name index */
|
|
name_index[next].boson =
|
|
_DtShmProtoAddStrtab(shm_handle,
|
|
(const char *)attr, &isnew);
|
|
name_index[next++].rec = i;
|
|
continue; /* next record */
|
|
}
|
|
|
|
/* the name had something in it now lets get the suffix */
|
|
c = strrchr(attr, '.');
|
|
attr = c;
|
|
|
|
/* lets see if the suffix has any *,?,[ */
|
|
while(c && *c &&
|
|
!(*c == '*' ||
|
|
*c == '[' ||
|
|
*c == '?' ||
|
|
*c == '$' ))
|
|
{
|
|
c++;
|
|
}
|
|
if(c && *c == '\0')
|
|
{
|
|
/* it doesn't so save it in the name index */
|
|
name_index[next].boson =
|
|
_DtShmProtoAddStrtab(shm_handle,
|
|
(const char *)attr, &isnew);
|
|
name_index[next++].rec = i;
|
|
}
|
|
else
|
|
{
|
|
/* couldn't find any thing so save it as other */
|
|
other[other_break++].rec = i;
|
|
}
|
|
|
|
}
|
|
|
|
if (next > 0)
|
|
{
|
|
qsort(name_index, next, sizeof(struct list), srch);
|
|
}
|
|
|
|
/*
|
|
showtable(db, name_index, other, head, other_break);
|
|
printf(" next = %d\n", next);
|
|
printf(" other_break = %d\n", other_break);
|
|
printf("head->buffer_start_index = %d\n", head->buffer_start_index);
|
|
*/
|
|
/* create a table and add the records to it. However
|
|
duplicates need to be in separate lists.
|
|
*/
|
|
indexList = _DtShmProtoInitInttab(next+3);
|
|
for(i = 0; i <= next; i++)
|
|
{
|
|
if(i != next && (last_boson == -1 || name_index[i].boson == last_boson))
|
|
{
|
|
/* this a new list of records or an addition to one */
|
|
list_of_recs = (int *)realloc(list_of_recs,
|
|
++list_count*sizeof(int));
|
|
last_boson = name_index[i].boson;
|
|
list_of_recs[list_count-1] = name_index[i].rec;
|
|
}
|
|
else
|
|
{
|
|
/* we reached the end of a list now we check how many
|
|
are in the list.
|
|
*/
|
|
if(list_count == 1)
|
|
{
|
|
/* if just one just add it in the index */
|
|
_DtShmProtoAddInttab(indexList,
|
|
last_boson, list_of_recs[0]);
|
|
}
|
|
else
|
|
{
|
|
/* if there are multiple items in the list
|
|
create a table for them */
|
|
int *list = _DtShmProtoAddIntLst(int_handle,
|
|
list_count, &index);
|
|
|
|
/* write the list to the to the table */
|
|
memcpy(list, list_of_recs,
|
|
list_count*sizeof(int));
|
|
|
|
/* then index on the negative of the boson
|
|
so that we know it is a list */
|
|
_DtShmProtoAddInttab(indexList,
|
|
last_boson, -index);
|
|
list_count = 0;
|
|
list_of_recs = (int *)realloc(list_of_recs,
|
|
++list_count*sizeof(int));
|
|
}
|
|
if ( i != next )
|
|
{
|
|
/* reset for the next set */
|
|
last_boson = name_index[i].boson;
|
|
list_of_recs[list_count-1] = name_index[i].rec;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/* same thing but they all go into a separate list */
|
|
if(other_break > 0)
|
|
{
|
|
/* create the space */
|
|
int *list = _DtShmProtoAddIntLst(int_handle,
|
|
other_break, &head->no_name_offset);
|
|
|
|
/* copy it into the list */
|
|
for(i = 0; i < other_break; i++)
|
|
{
|
|
list[i] = other[i].rec;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
head->no_name_offset = -1;
|
|
}
|
|
|
|
/* make the real space */
|
|
size = _DtShmProtoSizeInttab(indexList);
|
|
space = _DtShmProtoAddIntLst(int_handle, size/sizeof(int),
|
|
&head->name_list_offset);
|
|
_DtShmProtoCopyInttab(indexList, space);
|
|
_DtShmProtoDestroyInttab(indexList);
|
|
if(name_index)free(name_index);
|
|
if(list_of_recs)free(list_of_recs);
|
|
if(other)free(other);
|
|
return(index);
|
|
}
|
|
|
|
static int
|
|
write_db(DtDtsMMHeader *header, void *index, int size, const char *CacheFile)
|
|
{
|
|
int fd;
|
|
mode_t cmask = umask((mode_t)077);
|
|
char *tmpfile;
|
|
|
|
if ((tmpfile = malloc(sizeof(_DTDTSMMTEMPDIR) +
|
|
sizeof(_DTDTSMMTEMPFILE) + 7)) == NULL) {
|
|
_DtSimpleError(DtProgName, DtError, NULL, tmpfile, NULL);
|
|
return 0;
|
|
}
|
|
|
|
sprintf(tmpfile, "%s/%sXXXXXX", _DTDTSMMTEMPDIR, _DTDTSMMTEMPFILE);
|
|
fd = mkstemp(tmpfile);
|
|
|
|
umask(cmask);
|
|
|
|
if(fd == -1)
|
|
{
|
|
_DtSimpleError(
|
|
DtProgName, DtError, NULL,
|
|
(char*) tmpfile, NULL);
|
|
return(0);
|
|
}
|
|
|
|
/* Remove file on write failure - we don't */
|
|
/* want a partial dtdbcache file. */
|
|
if ((write(fd, header, sizeof(DtDtsMMHeader))
|
|
!= sizeof(DtDtsMMHeader)) ||
|
|
(write(fd, index, size) != size))
|
|
{
|
|
close(fd);
|
|
unlink(tmpfile);
|
|
free(tmpfile);
|
|
return(0);
|
|
}
|
|
|
|
close(fd);
|
|
|
|
if(rename((const char *)tmpfile, CacheFile) == -1)
|
|
{
|
|
_DtSimpleError(
|
|
DtProgName, DtError, NULL,
|
|
(char*) CacheFile, NULL);
|
|
unlink(CacheFile); /* Just in case? */
|
|
unlink(tmpfile);
|
|
free(tmpfile);
|
|
return(0);
|
|
}
|
|
free(tmpfile);
|
|
return(1);
|
|
}
|
|
|
|
|
|
_DtActionCompareRecordBoson(
|
|
DtDtsMMRecord *record1,
|
|
DtDtsMMRecord *record2 )
|
|
{
|
|
int results = (int)record1->recordName - (int)record2->recordName;
|
|
|
|
if (results)
|
|
return(results);
|
|
|
|
return((int)record1 - (int)record2);
|
|
}
|