/* $Header$ */ /************************************************************************** * ****** ISTK Release 1.2 ***** * * * * * * This code has been produced by numerous authors at the CERN centre for * * high energy physics, Geneve, Switzerland, at the SSC laboratory in * * Dallas, Texas, USA and at the Lawrence Berekeley Laboratory in * * California, USA. * * The latter two institutions perform work under US Government contract. * * The intent of the work is to provide useful code for people who need * * it, with an emphasis on free and collaborative exchange of ideas, * * techniques and implementations. * * Please read the disclaimer and copyright notices contained in the ISTK * * distribution and in distributed applications. * * * **************************************************************************/ /* Reference release Aug 10 1991 - C G Saltmarsh */ /* Has the basics used at CDG & SSC 1988-1991, plus vxworks support */ #include #include #include #ifndef VXWORKS #include #else #define BITSPERBYTE 8 #define BITS(type) (BITSPERBYTE * (int)sizeof(type)) #endif #ifndef vms #include #ifndef VXWORKS #include #endif #endif #if defined(vms) #include "sdsgen.h" #include "sds_externs.h" #else #include "Sds/sdsgen.h" #include "Sds/sds_externs.h" #endif #ifdef MEMMAP #include #endif #define SDS_INC_DIREC 32 #define SDS_INC_SUBS 32 #define SDS_INC_HEAP 256 #define SDS_FIXED -1 extern char *strncpy(); #if !defined(hpux) && !defined(VXWORKS) && !defined(mips) #if !defined(vms) #if ! defined (__GCC_2__) #if defined(__GNUC__) #if __GNUC__ != 2 extern char *memcpy(); #endif #endif #endif #endif #endif /* Forward declarations */ #ifndef VXWORKS off_t lseek(); #endif extern void sds_delete_scp(struct sds_control_p *); extern sds_handle next_sds(); void sds_fixbits(struct type_list *); sds_handle sds_prepads(struct direc *, sds_handle); char **sds_saverestore(sds_handle, struct direc *, int); sds_handle sds_type_duplicate_def(sds_handle, sds_handle, sds_code); sds_handle sds_start_heap(sds_handle); sds_handle sds_inc_heap(sds_handle, int); long tlist_len(struct type_list *); struct direc * sds_inc_direc_size(sds_handle); sds_handle sds_pname(sds_handle,sds_code,char *); /*********************************************************************/ sds_handle sds_dup(old_sds,name) sds_handle old_sds; char *name; /*********************************************************************/ { sds_handle new_sds; sds_code object,typecode; struct direc *dptr,*old_dptr; struct sds_control_p *scp; if (!sds_initialised()) { fprintf(stderr,"Sds must be initialised with sds_init()"); exit(1); } if ((old_dptr = sds_direc(old_sds)) == DNULL) { sds_push_error(SDS_NO_SUCH_SDS,SDS_ERROR,"Dataset to be duplicated"); return 0L; } if ((new_sds = good_sds(name))) { sds_push_error(SDS_DEJA_LA,SDS_WARNING,"Trying to make duplicate"); return 0L; } if ((new_sds = sds_new(name)) == 0) { sds_push_error(SDS_NO_SPC,SDS_WARNING,"Trying to make duplicate"); return 0L; } scp = sds_control(new_sds); scp->dup_size = (sds_handle *)sds_malloc(old_dptr[0].nelems * sizeof(long)); for (object = 1;object < old_dptr[0].nelems; object++) { scp->dup_size[object] = old_dptr[object].nelems; sds_cleanup(old_sds); if ((typecode = old_dptr[object].elemcod) & SDS_INDLIST) typecode = sds_duplicate_def(old_sds,new_sds,object); sds_declare_structure(new_sds, sds_obind2ptr(old_sds,object), sds_obind2name(old_sds,object), old_dptr[object].nelems, typecode); dptr = sds_direc(new_sds); dptr[object].structype = old_dptr[object].structype; if (old_dptr[object].illoca == SDS_DISJOINT_OBJECT) dptr[object].illoca = SDS_DISJOINT_OBJECT; } return new_sds; } /*********************************************************************/ sds_handle sds_duplicate_def(source_sds,new_sds,object) sds_handle source_sds,new_sds; sds_code object; /*********************************************************************/ { struct direc *dptr = sds_direc(source_sds); sds_code typecode = dptr[object].elemcod; return sds_type_duplicate_def(source_sds,new_sds,typecode); } /*********************************************************************/ void sds_put_name(sds,object,name) sds_handle sds; sds_code object; char *name; /*********************************************************************/ { char *oname = sds_obind2name(sds,object); int len = strlen(oname); strncpy(oname,name,len); } /*********************************************************************/ sds_handle sds_pname(sds,object,name) sds_handle sds; sds_code object; char *name; /*********************************************************************/ { struct direc* dptr = sds_direc(sds); dptr[object].obj_name = sds_add_to_heap(sds,name,','); return dptr[object].obj_name; } /*********************************************************************/ char * sds_obind2name(sds,object) sds_handle sds; sds_code object; /*********************************************************************/ { return(sds_oname(sds,object,SDS_GEN_NAME)); } /*********************************************************************/ sds_handle sds_named_elements(sds,object) sds_handle sds; sds_code object; /************************************************************************/ { struct direc *dptr = sds_direc(sds); if (dptr == DNULL) { sds_push_error(SDS_NO_SUCH_SDS,SDS_ERROR,""); return 0L; } return((sds_handle)(dptr[object].obj_name >> 16)); } /*********************************************************************/ char * sds_oname(sds,object,elem) sds_handle sds; sds_code elem,object; /*********************************************************************/ { struct direc *dptr = sds_direc(sds); char *cptr; elem++; if (dptr == DNULL) { sds_push_error(SDS_NO_SUCH_SDS, SDS_ERROR," Finding object name"); return (char *)0; } if (elem > (dptr[object].obj_name >> 16)) { sds_push_error(SDS_NO_SUCH_OBJ,SDS_ERROR,"Finding object name"); return (char *)0; } cptr = (sds_heap(sds) + (dptr[object].obj_name & 0xffff)); cptr = sds_jstr(cptr,elem); return(cptr); } /*********************************************************************/ sds_handle sds_new(name) char *name; /*********************************************************************/ { struct direc *ddptr; sds_handle sds; struct sds_control_p *scp; sds_handle heap_place; if (!sds_initialised()) { fprintf(stderr,"Sds must be initialised with sds_init()"); exit(1); } if ((sds = good_sds(name))) { sds_push_error(SDS_DEJA_LA,SDS_WARNING,"Trying to make new dataset"); return sds; } if (!(sds = next_sds())) return 0L; scp = sds_control(sds); /* Start-up space for the directory */ ddptr = scp->dptr = (struct direc *)sds_calloc((unsigned int)SDS_INC_DIREC, (unsigned int)sizeof(struct direc)); if (ddptr == 0 ) { sds_push_error(SDS_NO_SUCH_SDS,SDS_ERROR,"Trying to make new dataset"); return 0L; } scp->allofl = SDS_DPTR_ALLOC; scp->direc_size = SDS_INC_DIREC; /* Initialise direc[0]: the directory entry */ ddptr[0].nelems = (unsigned long)1; ddptr[0].elemsz = sizeof(struct direc); ddptr[0].align_type = sds_palign(SDS_DIRECTORY_STRUCTURE); ddptr[0].offst = SDS_NOT_ASSEMBLED; ddptr[0].structype = (short)0; ddptr[0].illoca = (unsigned char)0; scp->tlist = TNULL; scp->shead = HNULL; heap_place = sds_add_to_heap(sds,name,0); if (heap_place < 0) { ddptr[0].obj_name = (sds_code)heap_place; return 0L; } /* And timestamp it for the hell of it */ sds_tstamp(sds,SDS_TIMESTAMP_ALL); return(sds); } /*********************************************************************/ sds_handle sds_access(source_name,source_type,mode) char *source_name; sds_code source_type,mode; /* get access to an (alleged?) SDS outside process memory. Unless this involves attaching to shared memory, this means I load into process memory. */ /*********************************************************************/ { struct direc *dptr = 0; sds_handle sds = SDS_NO_SUCH_SDS; int obj; struct sds_control_p *scp; int success = 0; char *temprpt = malloc(strlen(source_name) + 32); sprintf(temprpt,"Dataset %s", source_name); if (!sds_initialised()) { fprintf(stderr,"Sds must be initialised with sds_init()"); exit(1); } if (source_type & SDS_PROC_MEM) { free(temprpt); return good_sds(source_name); } if ((source_type & SDS_FILE) || (source_type == SDS_SEQUENTIAL)) { if ((source_type & SDS_DIREC_ONLY) || (source_type == SDS_SEQUENTIAL)) { int fd; sds_handle orig_state,sdsn; struct sds_header head; sdsn = sds = next_sds(); if ((fd = sds_open_file(source_name, O_RDONLY | O_BINARY)) >= 0) { if ((sds = sds_cload_direc(sds,fd,&orig_state, &head)) != 0) { dptr = sds_direc(sds); success = 1; if (source_type == SDS_SEQUENTIAL) dptr[0].offst = SDS_NOT_ASSEMBLED; } else { if (sds_last_return() == SDS_GOOD_FORMAT) { if ((sds = sds_load_direc(sdsn,fd, &head))) { dptr = sds_direc(sds); success = 1; if (source_type == SDS_SEQUENTIAL) dptr[0].offst = SDS_NOT_ASSEMBLED; } } } sds_close_fd(fd); } } else { if ((sds = sds_load_conv(source_name))) { dptr = sds_direc(sds); success = 1; } } } #ifdef SHMEM else if (source_type & SDS_SHARED_MEM) { if (shm_q(source_name)) { /* it exists! */ if ((sds = next_sds()) < 0) return(sds); if (mode & SDS_READ) dptr = (struct direc *)shm_attr(source_name); else dptr = (struct direc *)shm_attw(source_name); if (dptr != 0) { success = 1; set_sys_vars(sds,dptr); } } else sds_push_error(SDS_NO_SUCH_SDS, SDS_ERROR, "Attach to shared mem"); } #endif else sds_push_error(SDS_NO_SUCH_SDS, SDS_ERROR, "undefined sds source type"); if (!success) { sds_push_error(sds_last_error(), SDS_ERROR, temprpt); free(temprpt); return 0L; } free(temprpt); scp = sds_control(sds); scp->source = source_type; scp->load_name = malloc(strlen(source_name) + 1); strcpy(scp->load_name, source_name); scp->is_proto = 0; /* clean up in case allocation flags have been left in file (not nice) */ if (!(source_type & SDS_SHARED_MEM)) for (obj = 0;obj < dptr[0].nelems; obj++) dptr[obj].illoca &= ~(SDS_WAS_ALLOCATED | SDS_EXTERNAL_OBJECT | SDS_REALLOC); return(sds); } /*********************************************************************/ void set_sys_vars(sds,dptr) sds_handle sds; struct direc *dptr; /*********************************************************************/ { struct sds_control_p *scp = sds_control(sds); scp->dptr = dptr; scp->direc_size = SDS_FIXED; scp->shead = (struct sds_header *)((char *)dptr - dptr[0].offst); scp->tlist = scp->shead->list_size? (struct type_list *)((char *)scp->shead + BASE_OFFSET):TNULL; scp->heap = (char *)scp->shead + (int)scp->shead->list_size + BASE_OFFSET; scp->current_heap = scp->heap + scp->shead->heap_size; } /*********************************************************************/ sds_handle sds_start_heap(sds) sds_handle sds; /*********************************************************************/ { struct sds_control_p *scp = sds_control(sds); if (scp->heap != NULL) return 0L; scp->current_heap = scp->heap = (char*) sds_malloc(SDS_INC_HEAP); scp->heap_size = SDS_INC_HEAP; scp->allofl |= SDS_HEAP_ALLOC; return 1L; } /*********************************************************************/ sds_handle sds_inc_heap(sds,count) sds_handle sds; int count; /*********************************************************************/ { struct sds_control_p *scp = sds_control(sds); int delta = scp->current_heap - scp->heap; scp->heap_size += count * SDS_INC_HEAP; scp->current_heap = scp->heap = sds_realloc(scp->heap,(unsigned)scp->heap_size); scp->current_heap += delta; return 1L; } /*********************************************************************/ sds_off_t sds_add_to_heap(sds_handle sds,char *buffer,char delim) /*********************************************************************/ { struct sds_control_p *scp = sds_control(sds); long temp,count; int incr,space_left,size = (int)strlen(buffer) + 1; if (!scp->heap) if (!sds_start_heap(sds)) return -1L; space_left = scp->heap_size - (scp->current_heap - scp->heap); if ((incr = (size - space_left)) > 0) { incr = 1 + incr/SDS_INC_HEAP; if (!(sds_inc_heap(sds,incr))) return -1L; } count = sds_namelist(scp->current_heap,buffer,delim); temp = (scp->current_heap - scp->heap) + (count << 16); scp->current_heap += size; return temp; } /*********************************************************************/ struct direc * sds_inc_direc_size(sds) sds_handle sds; /*********************************************************************/ { struct sds_control_p *scp = sds_control(sds); scp->direc_size += SDS_INC_DIREC; scp->dptr = (struct direc *)sds_realloc((char *)scp->dptr, (unsigned int)(scp->direc_size*sizeof(struct direc))); return scp->dptr; } /*********************************************************************/ long tlist_len(tyl) struct type_list *tyl; /*********************************************************************/ { long len = (long)0; if (tyl == TNULL) return(len); while ((tyl++)->elemcod != SDS_ENDLIST) len++; return(++len); } /*********************************************************************/ sds_handle sds_define_structure(sds,ty_list,names) sds_handle sds; struct type_list *ty_list; char *names; /*********************************************************************/ { long new_size = 0,old_size = 0; struct type_list *size_align,tlist_head; struct type_list *new_list,*ttemp = ty_list,*oldlist; struct sds_control_p *scp = sds_control(sds); int i; char align; /* clear up any bitfield definitions passed in.... */ sds_fixbits(ty_list); /* How big is the new one? (NB: delimited by SDS_ENDLIST, not SDS_RETLIST */ new_size = tlist_len(ty_list) + (long)2L; /* (A size/namelist pair will be added:, and the size/alignment type pair:hence the '+2' */ /* And the old one? */ if ((oldlist = scp->tlist) != NULL) old_size = tlist_len(oldlist) - (long)1L; /* Here I subtract 1 to throw away the SDS_ENDLIST which marks the end of the type_list buffer */ /* This is the first tlist entry: giving number of elements in the object and, if provided, a pointer to and length of its namelist */ tlist_head.elemcod = SDS_LENLIST; if (names != (char *)0) tlist_head.nelems = sds_add_to_heap(sds,names,','); else tlist_head.nelems = (unsigned long)0; if (old_size)/* There is an existing list, so get more space.... */ { scp->tlist = new_list = (struct type_list *)sds_realloc(scp->tlist, (unsigned)(new_size+old_size) * sizeof(struct type_list)); } else { /* No old list, simple malloc needed... */ scp->tlist = new_list = (struct type_list *)sds_malloc((unsigned long)new_size * (unsigned long)sizeof(struct type_list)); scp->allofl |= SDS_TLIST_ALLOC; } /* ...and put the new list on the end */ new_list += old_size; new_list->nelems = tlist_head.nelems; new_list->elemcod = tlist_head.elemcod; new_list++; /* the next slot is for the size/align pair, calculated soon */ size_align = new_list++; for (i=0;inelems = ttemp->nelems; new_list->elemcod = ttemp->elemcod; if ((new_list->elemcod & SDS_LOCALLIST)) { new_list->elemcod &= ~SDS_LOCALLIST; new_list->elemcod |= SDS_INDLIST; new_list->elemcod += old_size; } new_list++; ttemp++; } old_size |= SDS_INDLIST; size_align->elemcod = SDS_SIZE_ALIGN; size_align->nelems = sds_tlsize(sds,old_size,&align); size_align->elemcod |= (long)(align & 0xff); /* Return the pointer with its indirection flag */ return(old_size); } /*********************************************************************/ sds_handle sds_resize_object(sds,object,new_size) sds_handle sds; sds_code object; sds_code new_size; /*********************************************************************/ { struct direc *dptr = sds_direc(sds); sds_handle ret = 1L; if ( dptr[0].offst != SDS_NOT_ASSEMBLED) { sds_push_error(SDS_NOT_ASSEMBL,SDS_WARNING,"Resize attempted, unassembled dataset"); ret = 0L; } else if (dptr[object].nelems != new_size) { dptr[object].nelems = new_size; dptr[object].illoca |= SDS_REALLOC; } else { sds_push_error(SDS_CANNOT_RESIZE,SDS_WARNING,"Null resize attempted"); ret = 0L; } return ret; } /*********************************************************************/ void sds_destroy(sds) sds_handle sds; /*********************************************************************/ { sds_handle object; struct direc *dptr = sds_direc(sds); if (dptr == DNULL) return; if (sds_source(sds) == SDS_SHARED_MEM) { #ifdef SHMEM sds_discard(sds); #endif } else if (sds_source(sds) == SDS_FILE) { sds_discard(sds); } else { for (object = 1;object < dptr[0].nelems;object++) { if (dptr[object].illoca & SDS_WAS_ALLOCATED) free(sds_obind2ptr(sds,object)); else if (dptr[(int)object].structype == SDS_RECORDS) sds_destroy_record_def( (struct record_header *)sds_obind2ptr(sds,object),0); } sds_discard(sds); } } /*********************************************************************/ void sds_discard(sds) sds_handle sds; /*********************************************************************/ { int object_count; char ***elstart; int **varcount; char *temp; struct sds_control_p *scp = sds_control(sds); struct direc *dptr = sds_direc(sds); #ifdef MEMMAP int disob,object; #endif if (dptr == DNULL) return; temp = (char *)sds_head(sds); object_count = dptr[0].nelems; /* Clean up the three malloc regions and the serial stream and flag everything NULL */ if (scp->source == SDS_SHARED_MEM) { #ifdef SHMEM shm_quit(dptr); #endif } #ifdef MEMMAP else if (scp->source == SDS_MAPPED_MEM) { disob = 0; /* find out if an object has been searately mapped: if not, the whole file must have been */ for (object=1; objectsource == SDS_FILE) { if ((scp->heap != NULL) && (scp->allofl & SDS_HEAP_ALLOC)) { scp->allofl &= ~SDS_HEAP_ALLOC; free(scp->heap); } free(temp); } else { if ((dptr != DNULL) && (scp->allofl & SDS_DPTR_ALLOC)) { scp->allofl &= ~SDS_DPTR_ALLOC; free((char *)dptr); } if ((scp->tlist != TNULL) && (scp->allofl & SDS_TLIST_ALLOC)) { scp->allofl &= ~SDS_TLIST_ALLOC; free((char *)scp->tlist); } if ((scp->heap != NULL) && (scp->allofl & SDS_HEAP_ALLOC)) { scp->allofl &= ~SDS_HEAP_ALLOC; free(scp->heap); } if ((scp->shead != NULL) && (scp->allofl & SDS_HEAD_ALLOC)) { scp->allofl &= ~SDS_HEAD_ALLOC; free(scp->shead); } if ((scp->dup_size != NULL) && (scp->allofl & SDS_DUP_ALLOC)) { scp->allofl &= ~SDS_DUP_ALLOC; free(scp->dup_size); } } elstart = scp->element_start; varcount = scp->varel_count; if (elstart != NULL) { int i; for (i=1;ishead = NULL; scp->dup_size = NULL; scp->dptr = NULL; scp->stream = SDS_FILE_OP; scp->tlist = NULL; scp->source = 0; scp->heap = NULL; if (scp->src) sds_delete_rescon(scp->src); if (scp->load_name) free(scp->load_name); if (scp->target_name) free(scp->target_name); if (scp->file_offsets) free(scp->file_offsets); sds_delete_scp(scp); } /*********************************************************************/ sds_handle sds_declare_structure(sds,obj_ptr,name,number,code) sds_handle sds; void *obj_ptr; char *name; sds_code number; sds_code code; /*********************************************************************/ { struct direc *ddptr; sds_code object; sds_handle tsz; unsigned char atype; struct sds_control_p *scp; short structype = 0; if (code & SDS_RECLIST) { code &= ~SDS_RECLIST; structype = SDS_RECORDS; } if (!(scp = sds_control(sds))) { sds_push_error(SDS_NO_SUCH_SDS, SDS_ERROR, "Adding object to non-existant dataset"); return 0L; } if (obj_ptr == SDS_ALLOCATE && scp->target_name) { sds_push_error(SDS_FILE_OP,SDS_ERROR,"Cannot allocate for targeted file"); return 0L; } /* If I can't find this thing's size, it is a. not a known primitive and b. not a described complex object. So bug off. */ if (code & SDS_INDLIST) tsz = sds_tlsize(sds,code,(char *)&atype); else tsz = sds_element_size(sds,code,&atype); if (tsz == 0) { sds_push_error(SDS_ZERO_LENGTH, SDS_ERROR, "Adding incomplete object"); return 0L; } /* Found it. Add one to directory list.... */ ddptr = scp->dptr; object = (int)ddptr[0].nelems++; /* May have to get more memory for the directory structure */ if (object == scp->direc_size) ddptr = sds_inc_direc_size(sds); /* Fill in the definition of this object */ ddptr[object].offst = (sds_off_t)obj_ptr; ddptr[object].elemcod = code; ddptr[object].elemsz = tsz; ddptr[object].nelems = number; ddptr[object].wtime = 0; ddptr[object].illoca = 0; ddptr[object].align_type = atype; ddptr[object].structype = structype; if ((!sds_pname(sds,(long)object,name))) sds_push_error(SDS_NO_MEM, SDS_WARNING, "While adding object"); /* Write to disk if requested */ if (scp->target_name != NULL) { long padbytes[2]; char b[4096]; int c = 0,s = 4096; off_t cur = lseek(scp->tstream, 0L, SEEK_CUR); int pads = align_delta((sds_off_t)cur ,ddptr[(int)object].align_type); padbytes[0] = padbytes[1] = 0L; if (pads && sds_buffered(scp->tstream, (char *)padbytes, pads, b,s,&c) != pads) { sds_push_error(SDS_FILE_WR, SDS_ERROR, "Adding data object to file"); return 0L; } if (!sds_write_object(scp->tstream,sds,object,obj_ptr,b,s,&c)) { sds_push_error(SDS_FILE_WR,SDS_ERROR, "Adding data object to file"); return 0L; } sds_flush(scp->tstream, b,&c); } /* And return its object number */ return(object); } /*********************************************************************/ char ** sds_saverestore(sds,dptr, flag) sds_handle sds; struct direc *dptr; int flag; /*********************************************************************/ { int i; long junk = 0; struct sds_saverestore *sr = sds_saver(); /* I'm going to put the real object addresses in this pointer list */ if (flag == SDS_SAVE_STATE) { sr->opointer = (char **)sds_malloc((unsigned int)dptr[0].nelems * (unsigned int)sizeof(char *)); if (sr->opointer == 0 ) { sds_push_error(SDS_NO_MEM, SDS_ERROR,"calloc failure, sds_make"); return (char **)0; } /* Get the addresses from the approved routine ... */ /* Save the directory state in case it's NOT_ASSEMBLED */ sr->sds_state = (char *)dptr[0].offst; for (i=0;i < dptr[0].nelems;i++) sr->opointer[i] = (char*) sds_getp(dptr,i); if (sr->sds_state == (char *)SDS_NOT_ASSEMBLED) sr->status = offil(sds, 0, 0, &junk); return sr->opointer; } else { /* leave things as before in case dataset expansion is required */ if (sr->sds_state == (char *)SDS_NOT_ASSEMBLED) { dptr[0].offst = (sds_off_t)sr->sds_state; for (i=1;i < dptr[0].nelems;i++) dptr[i].offst = (sds_off_t)sr->opointer[i]; } free((char *)sr->opointer); return NULL; } } /*********************************************************************/ sds_handle sds_ass(sds,name,flg) sds_handle sds; sds_code flg; char *name; /* 'assemble' means assemble the bits of an SDS into a coherent thing. That means the target place for assembly must be specified. In the simplest case - assemble in process memory - the only action will be to allocate memory for any objects which don't yet have any - no new SDS is created. For assembly to *shared memory* a contiguous memory chunk has to be filled, so a new SDS is made. Assembling to file or streaming to a network do generate a new SDS but it is NOT accessible to the generating process without more work (eg sds_load) so no new SDS index is returned */ /*********************************************************************/ { struct direc *dptr; char *cptr; sds_handle sds_return = sds; unsigned long i; int tw,ow,fd; char **object_pointer; struct sds_control_p *scp; long padbytes[2]; char b[4096]; int c = 0,s = 4096; #ifdef SHMEM sds_handle cp_size; sds_off_t new_base,new_offset; struct direc *new_dptr; #endif padbytes[0] = padbytes[1] = 0L; if (!(scp = sds_control(sds))) { sds_push_error(SDS_NO_SUCH_SDS,SDS_ERROR,"Assembling non-existant dataset"); return 0L; } dptr = sds_direc(sds); if ((scp->target_name)) { char buf[1024]; char *ch; int nb,pads; char *tname = sds_malloc(strlen(scp->target_name) + 5); if ((ch = strrchr(scp->target_name,'.')) != (char *)0) *ch = (char)0; strcpy(tname,scp->target_name); strcat(tname,".tmp"); if (scp->tstream != SDS_FILE_OP) sds_close_fd(scp->tstream); if ((scp->tstream = sds_open_file(scp->target_name, O_RDONLY)) == -1) { sds_push_error(SDS_FILE_OP,SDS_ERROR, "Could not open data file"); sds_return = 0L; } else if ((fd = sds_open_file(tname,O_RDWR)) >= 0) { object_pointer = sds_saverestore(sds,dptr,SDS_SAVE_STATE); if ((tw = sds_write_header(fd,sds,b,s,&c)) < 0) { sds_push_error(SDS_FILE_WR,SDS_ERROR,"Failure writing header to file"); sds_return = 0L; } else if ((pads = sds_prepads(&dptr[0], tw)) > 0) { if (sds_buffered(fd, (char *)padbytes, pads,b,s,&c) != pads) { sds_push_error(SDS_FILE_WR,SDS_ERROR,"Failure writing pads to file"); sds_return = 0L; } else tw += pads; } if ((ow = sds_write_object(fd,sds,0,(char *)scp->dptr,b,s,&c)) < 0) { sds_push_error(SDS_FILE_WR,SDS_ERROR, "Failure writing directory to file"); sds_return = 0L; } tw += ow; if (lseek(scp->tstream,0,SEEK_SET) == -1) { sds_push_error(SDS_FILE_OP,SDS_ERROR,"lseek on data target"); sds_return = 0L; } else { while((nb = read(scp->tstream, buf, 1024)) > 0) sds_buffered(fd,buf, nb,b,s,&c); if (nb == -1) { sds_push_error(SDS_FILE_RD,SDS_ERROR,"read on data target"); sds_return = 0L; } sds_flush(scp->tstream,b,&c); sds_close_fd(scp->tstream); scp->tstream = (int)NULL; } sds_close_fd(fd); } else { sds_push_error(SDS_FILE_OP,SDS_ERROR, "Could not open file"); sds_return = 0L; } if (sds_return) { #if defined(__MSDOS__) unlink(scp->target_name); #endif rename(tname,scp->target_name); } free(tname); sds_saverestore(sds,dptr,SDS_RESTORE_STATE); } else if ((flg & SDS_FILE)) /* no new sds created */ { object_pointer = sds_saverestore(sds,dptr,SDS_SAVE_STATE); if ((fd = sds_open_file(name,(int)flg)) >= 0) { if (!to_file(sds,fd,object_pointer)) { sds_push_error(SDS_FILE_WR,SDS_ERROR, "Failure writing dataset to file"); sds_return = 0L; } sds_close_fd(fd); } else { sds_push_error(SDS_FILE_OP,SDS_ERROR, "Could not open file"); sds_return = 0L; } sds_saverestore(sds,dptr,SDS_RESTORE_STATE); } else if (flg & SDS_SYBASE) /* no new sds created */ { #ifndef SDSDB sds_push_error(SDS_FILE_OP,SDS_ERROR,"Database operations not supported:"); return 0L; #else object_pointer = sds_saverestore(sds,dptr,SDS_SAVE_STATE); sds_return = sds_db_make(sds,name,name,flg,object_pointer); sds_saverestore(sds,dptr,SDS_RESTORE_STATE); #endif } #ifdef SHMEM else if (flg & SDS_SHARED_MEM) /* a new sds is created */ { if ((sds_return = next_sds()) >= 0) { object_pointer = sds_saverestore(sds,dptr,SDS_SAVE_STATE); /* Allocate the memory */ if ((cptr = (char *)shm_make(name, sds_fullsize(sds),0666)) == (char *)0) { sds_push_error(SDS_NO_MEM,SDS_ERROR, "Shared memory failure"); return 0L; } /* Make and load the sds header,tlist and heap */ cptr += sds_mem_header(sds,cptr); cptr += align_delta((sds_off_t)cptr,dptr[0].align_type); /* How big is the directory? */ cp_size = (sds_handle)dptr[0].nelems*dptr[0].elemsz; /* Copy the directory over */ memcpy(cptr,(char *)dptr,cp_size); new_dptr = (struct direc *)cptr; new_base = (sds_off_t)cptr; set_sys_vars(sds_return,(struct direc *)cptr); cptr += cp_size; /* And all the objects */ for (i=1;i < dptr[0].nelems;i++) { new_dptr[i].illoca = SDS_EXTERNAL_OBJECT; cptr += align_delta((sds_off_t)cptr,dptr[i].align_type); new_offset = new_dptr[0].offst + (sds_off_t)cptr - new_base; if (new_offset != new_dptr[i].offst ) new_dptr[i].offst = (sds_off_t)new_offset; cp_size = (sds_handle)dptr[i].nelems; if (dptr[i].illoca & SDS_REALLOC) if (scp->dup_size[i] < dptr[i].nelems) cp_size = scp->dup_size[i]; cp_size *= dptr[i].elemsz; if (new_dptr[i].structype & SDS_RECORDS) { cptr += sds_copy_records(sds_return,cptr, (sds_record_handle *)object_pointer[i]); new_dptr[i].structype &= ~SDS_RECORDS; } else { if (object_pointer[i] != SDS_ALLOCATE) memcpy(cptr, object_pointer[i], cp_size); cptr += (int)dptr[i].nelems*dptr[i].elemsz; } } sds_saverestore(sds,dptr,SDS_RESTORE_STATE); } } #endif else if (flg & SDS_PROC_MEM) /* Just do necessary memory allocation */ { for (i=1;i < dptr[0].nelems;i++) { if ((dptr[i].offst == (sds_code)SDS_ALLOCATE)) { dptr[i].offst = (sds_off_t)sds_calloc(dptr[i].nelems,dptr[i].elemsz); dptr[i].illoca |= SDS_WAS_ALLOCATED; } else if (dptr[i].illoca & SDS_REALLOC) { /* Can't: have to copy over? if (dptr[i].illoca & SDS_WAS_ALLOCATED) free((char *)dptr[i].offst; */ dptr[i].offst = (sds_off_t)sds_calloc(dptr[i].nelems,dptr[i].elemsz); dptr[i].illoca |= SDS_WAS_ALLOCATED; dptr[i].illoca &= ~SDS_REALLOC; } else { dptr[i].illoca |= SDS_EXTERNAL_OBJECT; } } scp->is_proto = 0; } else /* this is an unknown target */ { sds_return = 0L; sds_push_error(SDS_TRANSFER_UNDEF,SDS_WARNING, "Do not understand this assembly target"); } return sds_return; } /*********************************************************************/ sds_handle to_file(sds,fd,object_pointer) sds_handle sds; int fd; char **object_pointer; /*********************************************************************/ { struct direc *dptr; unsigned long i; sds_handle total_write = 0; sds_handle pads, ob_write; long padbytes[2]; char b[4096]; int c= 0,s= 4096; padbytes[0] = padbytes[1] = 0L; if ((dptr = sds_direc(sds)) == DNULL) { sds_push_error(SDS_NO_SUCH_SDS,SDS_ERROR,"Writing non-existant dataset to file"); return 0L; } if ((total_write = sds_write_header(fd,sds,b,s,&c)) < 0) { sds_push_error(SDS_FILE_WR,SDS_ERROR,"Writing header failed"); return 0L; } for (i=0;i < dptr[0].nelems;i++) { if (dptr[i].illoca != SDS_DISJOINT_OBJECT) { if ((pads = sds_prepads(&dptr[i], total_write)) > 0) { if (sds_buffered(fd, (char *)padbytes, pads,b,s,&c) != pads) { sds_push_error(SDS_FILE_WR,SDS_ERROR,"Writing pads failed"); return 0L; } else total_write += pads; } if ((ob_write = sds_write_object(fd,sds,i,object_pointer[i],b,s,&c)) < 0) { sds_push_error(SDS_FILE_WR,SDS_ERROR,"Writing object"); return 0L; } else total_write += ob_write; } } sds_flush(fd,b,&c); return 1L;; } /*********************************************************************/ sds_handle sds_prepads(dptr, total_write) struct direc *dptr; sds_handle total_write; /*********************************************************************/ { return (sds_handle)align_delta((sds_off_t)total_write,dptr->align_type); } /*********************************************************************/ sds_handle sds_mem_header(sds,cptr) sds_handle sds; char *cptr; /*********************************************************************/ { struct sds_header *sdsh = (struct sds_header *)cptr; sdsh->magic_number = (long)SDS_MAGIC; sdsh->version = SDS_VERSION; sdsh->controlbits |= SDS_BIGADDR?SDS_FROM_BIGADDR:0; sdsh->list_size = (short)tlist_size(sds_tlist(sds)); sdsh->heap_size = (short)sds_heap_size(sds); sdsh->heap_size += (short)align_delta((sds_off_t)sdsh->heap_size,4); cptr += sizeof(struct sds_header); if (sdsh->list_size) /* there is a tlist */ { memcpy(cptr,(char *)sds_tlist(sds),(int)sdsh->list_size); cptr += sdsh->list_size; } memcpy(cptr,sds_heap(sds),(int)sdsh->heap_size); return((int)sdsh->list_size +(int)sdsh->heap_size + sizeof(struct sds_header)); } /*********************************************************************/ sds_handle sds_write_header(int fd,sds_handle sds,char *b, int s, int *c) /*********************************************************************/ { struct sds_header sdsh; int ret_size = 0L; sdsh.magic_number = (long)SDS_MAGIC; sdsh.version = SDS_VERSION; sdsh.controlbits = SDS_BIGADDR?SDS_FROM_BIGADDR:0; sdsh.list_size = (short)tlist_size(sds_tlist(sds)); sdsh.heap_size = (short)sds_heap_size(sds); ret_size += sds_buffered(fd,(char *)&sdsh,sizeof(struct sds_header),b,s,c); if (sdsh.list_size) ret_size += sds_buffered(fd,(char *)sds_tlist(sds),(int)sdsh.list_size,b,s,c); ret_size += sds_buffered(fd,sds_heap(sds),(int)sdsh.heap_size,b,s,c); return ret_size; } /*********************************************************************/ sds_handle sds_write_object(int fd,sds_handle sds,sds_code i,void *pointer, char *b,int s, int *c) /*********************************************************************/ { unsigned long pad_size = 0; unsigned long realloc_size = 0; unsigned long total_size = 0; unsigned long temp_size = 0; struct direc *dptr = sds_direc(sds); unsigned char pattern = 0xff; total_size = dptr[i].nelems*dptr[i].elemsz; realloc_size = total_size; if (i == 0) { /* Directory: do not copy over RECORD flags, and mark disjoint objects as unknown address */ int obcount; pointer = sds_malloc(total_size); memcpy(pointer, (char *)dptr, total_size); dptr = (struct direc *)pointer; for (obcount=0;obcountstream = SDS_FILE_OP; sds_push_error(ierr,SDS_ERROR,"Directory load"); return 0; } lhsize = (int)header.heap_size + (int)header.list_size; lhsize += align_delta(lhsize + BASE_OFFSET,sds_palign(SDS_DIRECTORY_STRUCTURE)); list_ptr = (char*) sds_malloc((unsigned)lhsize); if (sds_read(fd,lhsize,list_ptr) != lhsize) { sds_push_error(SDS_FILE_NOP,SDS_ERROR,"Unexpected end-of-dataset"); return 0; } /* Find size of directory */ if (sds_read(fd,sizeof(struct direc),(char *)dtp) != sizeof(struct direc)) { sds_push_error(SDS_FILE_NOP,SDS_ERROR,"Unexpected end-of-dataset"); return 0; } ndirecs = (int)dtemp.nelems; /* throw away previous directory */ if (scp->dptr != DNULL) { free((char *)scp->dptr); scp->dptr = DNULL; } /* New directory,tlist heap and header go here */ ar = ((ndirecs*sizeof(struct direc)) + (unsigned int)BASE_OFFSET + (unsigned int)header.heap_size + (unsigned int)header.list_size); ar += align_delta(ar,sds_palign(SDS_DIRECTORY_STRUCTURE)); cptr = (char*) sds_malloc(ar); scp->allofl = SDS_HEAD_ALLOC; /* Copy in header..... */ memcpy(cptr,(char *)&header,BASE_OFFSET); cptr += BASE_OFFSET; /* Copy in tlist and heap */ memcpy(cptr,list_ptr,lhsize); cptr += lhsize; dptr = (struct direc *)cptr; /* Copy in top directory..... */ memcpy(cptr,(char *)&dtemp,sizeof(struct direc)); set_sys_vars(sds,(struct direc *)cptr); cptr += sizeof(struct direc); /* Read in rest of directory..... */ if (sds_read(fd,sizeof(struct direc)*(ndirecs-1),cptr) != sizeof(struct direc)*(ndirecs-1)) { sds_push_error(SDS_FILE_NOP,SDS_ERROR,"Unexpected end-of-dataset"); return 0; } /* reclaim some space. */ free(list_ptr); /* Save offsets and mark object addresses impossible */ scp->file_offsets = (sds_handle *)malloc(dptr[0].nelems * sizeof(long)); for (o = 1; o< dptr[0].nelems; o++) { scp->file_offsets[o] = (long)dptr[(int)o].offst; dptr[(int)o].offst = SDS_IMPOSSIBLE_ADDRESS; } return sds; } /*********************************************************************/ sds_handle sds_read_header(sds_handle sds,int fd,struct sds_header *header) /*********************************************************************/ { if (sds_read(fd,sizeof(struct sds_header),(char *)header) != sizeof(struct sds_header)) { sds_push_error(SDS_FILE_RD,SDS_ERROR,"Header load"); return 0L; } if (header->version != SDS_VERSION ) { sds_push_error(SDS_BAD_VERSION,SDS_WARNING,"Header load"); return 0L; } return 1L; } /*********************************************************************/ int sds_open_file(name,flg) int flg; char *name; /* Here be System Dragons eg VMS's plethora of file type flags */ /*********************************************************************/ { int fflag = O_RDWR,fd; char errstring[128]; errstring[0] = (char )0; if (flg != O_RDONLY) fflag |= (flg & (int)SDS_APPEND)?O_APPEND:O_CREAT | O_TRUNC; else fflag = flg; #ifdef vms if (!(fflag & O_APPEND)) { if ((fd = creat(name,0666,"ctx=nocvt","ctx = bin","mrs = 2048","rfm=udf")) < 0) { strcpy(errstring,"Cannot create file "); } } else #endif if ((fd = open(name,fflag,0666)) == -1) { strcpy(errstring,"Cannot open file "); } if (*errstring != (char)0) { strcat(errstring, name); sds_push_error(SDS_FILE_OP,SDS_ERROR,errstring); return -1; } #ifdef VXWORKS lseek(fd,0,SEEK_END); /* Go to end of file. */ #endif return(fd); } /*********************************************************************/ sds_handle sds_write_pattern(int fd,unsigned long size,char pattern,char *b,int s, int *c) /* Write crud to unallocated object going to eg file, although I'm not really sure why anyone would do it. Still, it's possible so one must do something rational-ish */ /*********************************************************************/ { #define SDS_JUNK_BUFFER 256 char buffer[SDS_JUNK_BUFFER]; int i,mod = (int)size/SDS_JUNK_BUFFER; int frac = (int)size%SDS_JUNK_BUFFER; memset(buffer,pattern,SDS_JUNK_BUFFER); if (mod > 0) for (i=0;iversion; version = (float)ver; return version; } /* Additions to support SDS to file descriptors. */ /***********************************************************************/ sds_handle sds_write2fd(fd,sds) int fd; sds_handle sds; /***********************************************************************/ { struct direc *dptr; sds_handle sds_return = sds; char **object_pointer; if ((dptr = sds_direc(sds)) == DNULL) { sds_push_error(SDS_NO_SUCH_SDS, SDS_ERROR, "Write to file desc"); return 0L; } object_pointer = sds_saverestore(sds,dptr,SDS_SAVE_STATE); if (!to_file(sds,fd,object_pointer)) { sds_push_error(SDS_FILE_WR, SDS_ERROR, "Could not send data to fd"); sds_return = 0L; } sds_saverestore(sds,dptr,SDS_RESTORE_STATE); return(sds_return); } void sds_settype(s,t,type, size) struct type_list *s,*t; sds_code type; int size; { unsigned short a = 0xff00; int nb,sz = 0; t++; while (s != t) { nb = s->nelems & SDS_BITFIELD_NMASK; if (*(char *)&a) /* Big endian or..... */ { sz += nb; s->nelems = ((size - sz) << 16) + nb; } else /* ....little endian! */ { s->nelems = (sz << 16) + nb; sz += nb; } s->elemcod = type; s++; } t--; t->nelems |= SDS_LAST_BITFIELD; } void sds_fixbits(struct type_list *tl) { struct type_list *startbits; int bitson = 0, bitsize = 0; while (tl->elemcod != SDS_RETLIST) { if (tl->elemcod == SDS_BITFIELD) { if (!bitson) { bitson = 1; startbits = tl; } if ((bitson && tl[1].elemcod != SDS_BITFIELD) || (bitsize > BITS(int))) { bitson = 0; if ((bitsize + tl->nelems) <= BITS(char)) { tl->nelems += bitsize << 16; bitsize = 0; sds_settype(startbits,tl,SDS_CHAR_BITFIELD, 8); } else if ((bitsize + tl->nelems) <= BITS(short)) { tl->nelems += bitsize << 16; bitsize = 0; sds_settype(startbits,tl,SDS_SHORT_BITFIELD, 16); } else if ((bitsize + tl->nelems) <= BITS(int)) { tl->nelems += bitsize << 16; bitsize = 0; sds_settype(startbits,tl,SDS_LONG_BITFIELD, 32); } else { sds_settype(startbits,tl,SDS_LONG_BITFIELD,32); startbits = &tl[-1]; bitsize = tl[-1].nelems & SDS_BITFIELD_NMASK; tl->nelems += bitsize << 16; bitsize += tl[0].nelems & SDS_BITFIELD_NMASK; bitson = 1; } } else { tl->nelems += bitsize << 16; bitsize += tl->nelems & SDS_BITFIELD_NMASK; } } tl++; } } sds_handle sds_pmem_attach(char *mem) { sds_handle sds; struct direc *dptr; struct sds_header *h = (struct sds_header *)mem; if ((sds = next_sds()) < 0) return sds; dptr = (struct direc *)(mem + BASE_OFFSET + h->heap_size + h->list_size); set_sys_vars(sds, dptr); return sds; }