/* ******************************************************************************* * Copyright (c) 1996 Martin Poole * ******************************************************************************* ** ** WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! ** ** Any changes to be made to this file should first be checked with ** mplib1 source control for library integrity. ** ** mplib1 source control can be reached at mplib1@quatermass.co.uk ** * * $Source: /home/cvs/cvsroot/onelan/onelan/src/mplib1/libsrc/bpo_init.c,v $ * $Author: mpoole $ * $Date: 2002/10/07 09:37:36 $ * $Revision: 1.2 $ * ******************************************************************************* * * Change History * * $Log: bpo_init.c,v $ * Revision 1.2 2002/10/07 09:37:36 mpoole * Initial checkin of mplib1-3.1.0 * * Revision 1.1 2002/10/07 09:36:53 mpoole * Initial checkin of mplib1-3.1.0 * * ******************************************************************************* */ #ident "$Header: /home/cvs/cvsroot/onelan/onelan/src/mplib1/libsrc/bpo_init.c,v 1.2 2002/10/07 09:37:36 mpoole Exp $" /* ------------------------------------------------------------------ Include files ------------------------------------------------------------------ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "include/bpo_init_internal.h" #include "include/bpo_alloc_private.h" #include #include #include #include #include /* ------------------------------------------------------------------ defines ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ structures ------------------------------------------------------------------ */ struct sodb_search { const char *hint; struct sodb_track *sotp; struct sodb *sodbp; }; struct procwalk { int which_procs; int (*isp_disp)( char *res_name, off_t res_off, void *param1, void *param2 ); struct sodb *sodbp; void *f_param1; void *f_param2; }; /* ------------------------------------------------------------------ static variables ------------------------------------------------------------------ */ static int bpo_init_debug=0; static char init_debug_str[]="BPO_INIT_DEBUG"; static int done_init=0; static dl_List_t SODB_List; /* ------------------------------------------------------------------ Code starts here ------------------------------------------------------------------ */ static void SODB_exit_this( void *vp1, void *vp2 ) { struct sodb *sodbp; sodbp = vp1; if (sodbp->sodb_type == SODB_T_MMAP) Detach_SODB_mmap( sodbp ); else Detach_SODB_shm( sodbp ); return; } static void SODB_at_exit( void ) { if (done_init) { /* cleanup whatever has been used */ dl_Walk_List( &SODB_List, SODB_exit_this, NULL ); } return; } void Do_SODB_Init( void ) { if (done_init==0) { dl_Init_List( &SODB_List, LN_IGNORECASE ); atexit( SODB_at_exit ); done_init = 1; } return; } static int Add_Track( struct sodb *sodbp, char *upper, char *name, int alloc_name, int mmap_fd, mode_t priv ) { struct sodb_track *sotp; int as; int rv=0; if (done_init) { as = sizeof(struct sodb_track); if (alloc_name) as += Sstrlen(name); sotp = malloc( (size_t)as ); if (sotp) { if (alloc_name) Sstrcpy( sotp->fname, name ); sotp->sodbp = sodbp; sotp->mmap_fd = mmap_fd; sotp->upper = upper; sotp->access_mode = priv; dl_Init_Node( &sotp->st_Node, (alloc_name)?sotp->fname:name, sotp ); dl_Add_Head( &SODB_List, &sotp->st_Node ); rv=1; } } return(rv); } static int find_SODB( struct sodb_track *sotp, struct sodb_search *sodbsp ) { struct sodb *sodbp; sodbp = sotp->sodbp; if ( sodbsp->sodbp == NULL ) { /* not already found so check */ if (sodbp->sodb_magic == SODB_MAGIC) { /* This is an SODB */ if ( (char *)sodbp <= sodbsp->hint && ((char *)sodbp + sodbp->sodb_size) > sodbsp->hint ) { /* This is it ! */ sodbsp->sodbp = sodbp; sodbsp->sotp = sotp; return(1); } } } return(0); } void * Get_SODB_Base( const void *hint1 ) { struct sodb_search sodbs; if (done_init==0) Do_SODB_Init(); sodbs.sodbp = NULL; sodbs.sotp = NULL; sodbs.hint = hint1; dl_Walk_List2( &SODB_List, (dl_Walk_List2_t)find_SODB, &sodbs ); return( (void *)sodbs.sodbp ); } static void * Get_SODB_Track( const void *hint1 ) { struct sodb_search sodbs; if (done_init==0) Do_SODB_Init(); sodbs.sodbp = NULL; sodbs.sotp = NULL; sodbs.hint = hint1; dl_Walk_List2( &SODB_List, (dl_Walk_List2_t)find_SODB, &sodbs ); return( (void *)sodbs.sotp ); } int SODB_in_Segment( const void *hint, const void *chk ) { struct sodb_track *sotp; int rv=0; sotp = Get_SODB_Track( hint ); if (sotp && sotp->sodbp) { rv = ( (const char *)chk >= (const char *)sotp->sodbp && (const char *)chk <= (const char *)sotp->upper); } return(rv); } off_t Get_SODB_Offset( const void *vp ) { struct sodb *sodbp; if (done_init==0) Do_SODB_Init(); sodbp = Get_SODB_Base( vp ); if (sodbp == NULL) return(0); return( (off_t)((const char *)vp - (const char *)sodbp) ); } void * Get_SODB_Pointer( const void *hint, off_t item_offset ) { struct sodb *sodbp; if (done_init==0) Do_SODB_Init(); sodbp = Get_SODB_Base( hint ); if (sodbp == NULL) return(NULL); return( (void *) (((char *)sodbp) + item_offset ) ); } mode_t Get_SODB_Privs( const void *hint ) { struct sodb_track *sotp; if (done_init==0) Do_SODB_Init(); sotp = Get_SODB_Track( hint ); if (sotp == NULL) return(0); return( sotp->access_mode ); } int Detach_SODB_lump( const void *hint ) { struct sodb_track *sotp; sotp = Get_SODB_Track( hint ); if (sotp==NULL) return(0); if (sotp->mmap_fd==-1) { shmdt((char *)sotp->sodbp); } else { munmap( (caddr_t)sotp->sodbp, sotp->sodbp->sodb_size ); /* close the file involved */ close( sotp->mmap_fd ); } dl_Remove_Node( &sotp->st_Node ); free(sotp); return(1); } int Detach_SODB_shm( const void *hint ) { return(Detach_SODB_lump( hint )); } int Detach_SODB_mmap( const void *hint ) { return(Detach_SODB_lump( hint )); } void * Attach_SODB_image_raw( const char *fname, off_t foff, size_t fsize ) { int fd; struct sodb *sodbp = NULL; struct stat tstat; caddr_t mblock; void *sodb_rv; if (done_init==0) Do_SODB_Init(); bpo_init_debug = get_config_flag(init_debug_str); fd = open( fname, O_RDWR ); if (fd == -1) { if (bpo_init_debug) fprintfile(stderr,"Attach_SODB_image_raw: Can't open file %s\n", fname ); return( NULL ); } stat( fname, &tstat ); if (tstat.st_size == 0 ) { if (bpo_init_debug) fprintfile(stderr,"Attach_SODB_image_raw: file (%s) is 0 bytes\n", fname ); close(fd); return(NULL); } /* File is now at least long enough to use */ mblock = mmap( 0, (fsize)?fsize:tstat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, foff ); if ( mblock == (caddr_t)-1 ) { if (bpo_init_debug) fprintfile(stderr,"Attach_SODB_image_raw: cannot mmap\n"); close(fd); return(NULL); } sodbp = (struct sodb *)mblock; sodb_rv = sodbp; Add_Track( sodbp, ((char *)sodbp) + ((fsize)?fsize:tstat.st_size), fname, 1, fd, 0600 ); return(sodb_rv); } void * Attach_SODB_image( const char *fname ) { return( Attach_SODB_image_raw( fname, 0, 0 ) ); } static void * Create_SODB_mmap_raw( const char *use_name, const char *mmap_name, size_t msize, off_t moff, int flags, mode_t priv ) { int fd,changed=0; struct sodb *sodbp = NULL; struct sodb_resource *sodbrp; struct stat tstat; caddr_t mblock; void *sodb_rv; mode_t old_mask; if (done_init==0) Do_SODB_Init(); bpo_init_debug = get_config_flag(init_debug_str); /* Do we need to adjust the size of the block to allow for the header ? */ if (flags & SODB_ADD_HEADER) msize += sizeof(struct sodb); old_mask=umask((mode_t)0); fd = open( mmap_name, O_RDWR | O_CREAT, priv ); (void)umask(old_mask); if (fd == -1) return( NULL ); stat( mmap_name, &tstat ); if (tstat.st_size == 0 ) { int t; char tbuf[1024]; if (bpo_init_debug) fprintfile(stderr,"Growing 0 length mmap file(%s)\n", mmap_name ); /* Time to pad the file out to the required length */ lseek( fd, tstat.st_size, SEEK_SET ); t = (moff + msize) - tstat.st_size; memset( tbuf, '\0', 1024 ); while (t) { write( fd, tbuf, (size_t)((t<1024)?t:1024) ); t -= (t<1024)?t:1024; }; } stat( mmap_name, &tstat ); if (tstat.st_size < (moff + msize)) { if (bpo_init_debug) fprintfile(stderr,"File too small to mmap(size=%d needed=%d)\n", tstat.st_size, moff + msize ); return( NULL ); } /* File is now at least long enough to use */ mblock = mmap( 0, msize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, moff ); if ( mblock == (caddr_t)-1 ) { close(fd); return(NULL); } sodbp = (struct sodb *)mblock; sodb_rv = (flags & SODB_ADD_HEADER) ? (void *)((char *)sodbp + sizeof(struct sodb)) : sodbp; if (sodbp->sodb_magic != SODB_MAGIC) { /* This is not yet an SODB */ sodbp->sodb_magic = SODB_MAGIC; sodbp->sodb_version = SODB_CURRENT_VERSION; changed = 1; Sstrcpy( sodbp->sodb_use_name, (use_name)?use_name:mmap_name ); sodbp->sodb_flags = flags; Init_SODB_Resources( sodbp ); } else if ( sodbp->sodb_size != msize ) { if (bpo_init_debug) fprintfile(stderr,"SODB does not match indicated size %d vs. %d\n", sodbp->sodb_size, msize ); sodb_rv=NULL; }else if ( stricmp( sodbp->sodb_use_name, (use_name)?use_name:mmap_name ) != 0) { if (bpo_init_debug) fprintfile(stderr,"SODB does not match provided string <%s> vs. <%s>\n", sodbp->sodb_use_name, (use_name)?use_name:mmap_name ); sodb_rv=NULL; }else if ( sodbp->sodb_version!=SODB_CURRENT_VERSION ) { if (bpo_init_debug) fprintfile(stderr,"SODB does not match current version <%d> vs. <%d>\n", SODB_CURRENT_VERSION, sodbp->sodb_version ); sodb_rv=NULL; } if (sodb_rv==NULL) { munmap( mblock, msize ); close(fd); return(NULL); } sodbp->sodb_size = msize; sodbp->sodb_type = SODB_T_MMAP; stat( mmap_name, &sodbp->mmap_stat ); /* sodbp->mmap_fd = fd; Not a good idea */ sodbp->mmap_fd = -1; sodbp->mmap_prot = PROT_READ | PROT_WRITE; sodbp->mmap_flags = MAP_SHARED; sodbp->mmap_off = moff; Sstrcpy( sodbp->mmap_name, mmap_name ); sodbp->ipc_key = (key_t)-1; sodbp->ipc_path[0] = '\0'; sodbp->ipc_tok_id = '\0'; sodbp->ipc_id = 0; if (flags & SODB_USE_SHALLOC) { /* time to call the shalloc init routine */ sodbp->shalloc_offset = sizeof(struct sodb); sodbp->shalloc_size = msize - sizeof(struct sodb); if (changed) { sodbrp = shalloc_init( sodbp, sizeof(struct sodb), msize - sizeof(struct sodb) ); if (sodbrp) bpo_Add_Tail_Raw( &sodbp->sodb_resource_list, sodbp, &sodbrp->res_node ); } else if (bpo_init_debug) fprintfile(stderr, "No change in structure, shalloc_init not called\n" ); } Add_Track( sodbp, ((char *)sodbp) + msize, sodbp->sodb_use_name, 0, fd, priv ); return(sodb_rv); } void * Create_SODB_mmap_priv( const char *use_name, const char *mmap_name, size_t msize, off_t moff, int flags, mode_t priv ) { return(Create_SODB_mmap_raw( use_name, mmap_name, msize, moff, flags, priv )); } void * Create_SODB_mmap( const char *use_name, const char *mmap_name, size_t msize, off_t moff, int flags ) { return(Create_SODB_mmap_raw( use_name, mmap_name, msize, moff, flags, SODB_MMAP_PRIV )); } static void * Create_SODB_shm_raw( const char *use_name, const char *fname, char id, size_t msize, int flags, mode_t priv ) { int fd,changed=0; struct sodb *sodbp = NULL; struct sodb_resource *sodbrp; struct stat tstat; caddr_t mblock; key_t mipckey; int mshmid; void *sodb_rv; if (done_init==0) Do_SODB_Init(); bpo_init_debug = get_config_flag(init_debug_str); /* Do we need to adjust the size of the block to allow for the header ? */ if (flags & SODB_ADD_HEADER) msize += sizeof(struct sodb); fd = stat( fname, &tstat ); if (fd == -1) return( NULL ); mipckey = ftok( fname, id ); if (bpo_init_debug) fprintfile(stderr,"ftok returns: %x\n", mipckey); if ( mipckey == -1) return(NULL); mshmid = shmget( mipckey, msize, (int)priv ); if (bpo_init_debug) fprintfile(stderr,"shmget FIND: %x\n", mshmid); if (mshmid== -1) { /* Does not exist, create it */ mshmid = shmget( mipckey, msize, IPC_CREAT | (int)priv ); if (bpo_init_debug) fprintfile(stderr,"shmget CREAT: %x\n", mshmid); if (mshmid==-1) return(NULL); mblock = shmat( mshmid, NULL, 0); ((struct sodb *)mblock)->sodb_magic = 0; /* Force new segment code */ if (bpo_init_debug) fprintfile(stderr,"shmat: %p\n", mblock); }else { /* segment exists, just look at it */ mblock = shmat( mshmid, NULL, 0); if (bpo_init_debug) fprintfile(stderr,"shmat(exists): %p\n", mblock); } if (mblock == (void *)-1) return(NULL); sodbp = (struct sodb *)mblock; sodb_rv = (flags & SODB_ADD_HEADER) ? (void *)((char *)sodbp + sizeof(struct sodb)) : sodbp; if (sodbp->sodb_magic != SODB_MAGIC) { if (bpo_init_debug) fprintfile(stderr,"Clearing block\n" ); /* This is not yet an SODB */ memset( mblock, '\0', msize ); if (bpo_init_debug) fprintfile(stderr,"Initing block\n" ); sodbp->sodb_magic = SODB_MAGIC; sodbp->sodb_version = SODB_CURRENT_VERSION; Sstrcpy( sodbp->sodb_use_name, (use_name)?use_name:fname ); changed = 1; sodbp->sodb_flags = flags; if (bpo_init_debug) fprintfile(stderr,"Initing resources\n" ); Init_SODB_Resources( sodbp ); if (bpo_init_debug) fprintfile(stderr,"Initing resource done\n" ); } else if ( sodbp->sodb_size != msize || ( stricmp( sodbp->sodb_use_name, (use_name && *use_name)?use_name:fname ) != 0) ) { if (bpo_init_debug) { if (sodbp->sodb_size != msize) { fprintfile(stderr,"SODB does not match indicated size %d vs. %d\n", sodbp->sodb_size, msize ); }else { fprintfile(stderr,"SODB does not match provided string <%s> vs. <%s>\n", sodbp->sodb_use_name, (use_name)?use_name:fname ); } } shmdt( mblock ); /* shmctl( sodbp->ipc_id, IPC_RMID, NULL );*/ return(NULL); } sodbp->ipc_key = mipckey; Sstrcpy( sodbp->ipc_path, fname ); sodbp->ipc_tok_id = id; sodbp->ipc_id = mshmid; sodbp->sodb_size = msize; sodbp->sodb_type = SODB_T_IPC; if (flags & SODB_USE_SHALLOC) { /* time to call the shalloc init routine */ if (changed) { if (bpo_init_debug) fprintfile(stderr, "shalloc_init being called\n" ); sodbrp = shalloc_init( sodbp, sizeof(struct sodb), msize - sizeof(struct sodb) ); if (bpo_init_debug) fprintfile(stderr, "shalloc_init returned %p\n", sodbrp ); if (sodbrp) bpo_Add_Tail_Raw( &sodbp->sodb_resource_list, sodbp, &sodbrp->res_node ); if (bpo_init_debug) fprintfile(stderr, "shalloc_init resource added to list\n" ); } else if (bpo_init_debug) fprintfile(stderr, "No change in structure, shalloc_init not called\n" ); } /* Now store details of this SODB in the process private space */ Add_Track( sodbp, ((char *)sodbp) + msize, sodbp->sodb_use_name, 0, -1, priv ); return(sodb_rv); } void * Create_SODB_shm_priv( const char *use_name, const char *fname, char id, size_t msize, int flags, mode_t priv ) { return(Create_SODB_shm_raw( use_name, fname, id, msize, flags, priv )); } void * Create_SODB_shm( const char *use_name, const char *fname, char id, size_t msize, int flags ) { return(Create_SODB_shm_raw( use_name, fname, id, msize, flags, SODB_IPC_PRIV )); } /* -- End of File -- */