1*5c51f124SMoriah Waterland /* 2*5c51f124SMoriah Waterland * CDDL HEADER START 3*5c51f124SMoriah Waterland * 4*5c51f124SMoriah Waterland * The contents of this file are subject to the terms of the 5*5c51f124SMoriah Waterland * Common Development and Distribution License (the "License"). 6*5c51f124SMoriah Waterland * You may not use this file except in compliance with the License. 7*5c51f124SMoriah Waterland * 8*5c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing. 10*5c51f124SMoriah Waterland * See the License for the specific language governing permissions 11*5c51f124SMoriah Waterland * and limitations under the License. 12*5c51f124SMoriah Waterland * 13*5c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each 14*5c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the 16*5c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying 17*5c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner] 18*5c51f124SMoriah Waterland * 19*5c51f124SMoriah Waterland * CDDL HEADER END 20*5c51f124SMoriah Waterland */ 21*5c51f124SMoriah Waterland 22*5c51f124SMoriah Waterland /* 23*5c51f124SMoriah Waterland * Copyright 1996 Sun Microsystems, Inc. All rights reserved. 24*5c51f124SMoriah Waterland * Use is subject to license terms. 25*5c51f124SMoriah Waterland */ 26*5c51f124SMoriah Waterland 27*5c51f124SMoriah Waterland 28*5c51f124SMoriah Waterland #include <stdio.h> 29*5c51f124SMoriah Waterland #include <string.h> 30*5c51f124SMoriah Waterland #include <stdlib.h> 31*5c51f124SMoriah Waterland #include <libintl.h> 32*5c51f124SMoriah Waterland #include "pkglib.h" 33*5c51f124SMoriah Waterland 34*5c51f124SMoriah Waterland /* 35*5c51f124SMoriah Waterland * This is the module responsible for allocating and maintaining lists that 36*5c51f124SMoriah Waterland * require allocation of memory. For certain lists, large chunks are 37*5c51f124SMoriah Waterland * allocated once to contain a large number of entries in each chunk (bl_* 38*5c51f124SMoriah Waterland * for block list). The other approach involves the augmentation of linked 39*5c51f124SMoriah Waterland * lists, each entry of which is alloc'd individually. 40*5c51f124SMoriah Waterland */ 41*5c51f124SMoriah Waterland #define ERR_CS_ALLOC "ERROR: Cannot allocate control structure for %s array." 42*5c51f124SMoriah Waterland #define ERR_MEM_ALLOC "ERROR: Cannot allocate memory for %s array." 43*5c51f124SMoriah Waterland 44*5c51f124SMoriah Waterland #define MAX_ARRAYS 50 45*5c51f124SMoriah Waterland 46*5c51f124SMoriah Waterland #define ARRAY_END(x) (bl_cs_array[x]->cur_segment->avail_ptr) 47*5c51f124SMoriah Waterland #define REC_SIZE(x) (bl_cs_array[x]->struct_size) 48*5c51f124SMoriah Waterland #define EOSEG(x) (bl_cs_array[x]->cur_segment->eoseg_ptr) 49*5c51f124SMoriah Waterland #define GET_AVAIL(x) (ARRAY_END(x) + REC_SIZE(x)) 50*5c51f124SMoriah Waterland 51*5c51f124SMoriah Waterland struct alloc_seg { 52*5c51f124SMoriah Waterland char *seg_ptr; /* ptr to the allocated block */ 53*5c51f124SMoriah Waterland char *avail_ptr; /* ptr to the next available list element */ 54*5c51f124SMoriah Waterland char *eoseg_ptr; /* last byte in the segment */ 55*5c51f124SMoriah Waterland int full; /* segment has no available space */ 56*5c51f124SMoriah Waterland struct alloc_seg *next; /* next record */ 57*5c51f124SMoriah Waterland }; 58*5c51f124SMoriah Waterland 59*5c51f124SMoriah Waterland struct blk_list_cs { 60*5c51f124SMoriah Waterland int struct_size; /* size of a single list element */ 61*5c51f124SMoriah Waterland int count_per_block; /* number of list elements per block */ 62*5c51f124SMoriah Waterland int block_size; /* just to save time - alloc size */ 63*5c51f124SMoriah Waterland int data_handle; /* list_handle for pointer array */ 64*5c51f124SMoriah Waterland struct alloc_seg *alloc_segs; /* memory pool */ 65*5c51f124SMoriah Waterland 66*5c51f124SMoriah Waterland struct alloc_seg *cur_segment; /* the current allocated segment */ 67*5c51f124SMoriah Waterland int total_elem; /* total elements stored */ 68*5c51f124SMoriah Waterland int contiguous; /* use realloc to grow */ 69*5c51f124SMoriah Waterland char *desc; /* description of the list */ 70*5c51f124SMoriah Waterland }; 71*5c51f124SMoriah Waterland 72*5c51f124SMoriah Waterland static struct blk_list_cs *bl_cs_array[MAX_ARRAYS]; 73*5c51f124SMoriah Waterland static int next_array_elem; 74*5c51f124SMoriah Waterland 75*5c51f124SMoriah Waterland /* Support functions */ 76*5c51f124SMoriah Waterland static int 77*5c51f124SMoriah Waterland invalid_handle(int list_handle) 78*5c51f124SMoriah Waterland { 79*5c51f124SMoriah Waterland if (list_handle < 0 || list_handle >= next_array_elem) 80*5c51f124SMoriah Waterland return (1); 81*5c51f124SMoriah Waterland 82*5c51f124SMoriah Waterland return (0); 83*5c51f124SMoriah Waterland } 84*5c51f124SMoriah Waterland 85*5c51f124SMoriah Waterland static int 86*5c51f124SMoriah Waterland invalid_record(int list_handle, int recno) 87*5c51f124SMoriah Waterland { 88*5c51f124SMoriah Waterland if (invalid_handle(list_handle)) 89*5c51f124SMoriah Waterland return (1); 90*5c51f124SMoriah Waterland 91*5c51f124SMoriah Waterland if (recno < 0 || recno > bl_cs_array[list_handle]->total_elem) 92*5c51f124SMoriah Waterland return (1); 93*5c51f124SMoriah Waterland 94*5c51f124SMoriah Waterland return (0); 95*5c51f124SMoriah Waterland } 96*5c51f124SMoriah Waterland 97*5c51f124SMoriah Waterland static void 98*5c51f124SMoriah Waterland free_list(int list_handle) 99*5c51f124SMoriah Waterland { 100*5c51f124SMoriah Waterland struct blk_list_cs *bl_ptr; 101*5c51f124SMoriah Waterland struct alloc_seg *segstr_ptr, *nextstr_ptr; 102*5c51f124SMoriah Waterland 103*5c51f124SMoriah Waterland /* Make sure this wasn't free'd earlier */ 104*5c51f124SMoriah Waterland if (bl_cs_array[list_handle] == NULL) 105*5c51f124SMoriah Waterland return; 106*5c51f124SMoriah Waterland 107*5c51f124SMoriah Waterland bl_ptr = bl_cs_array[list_handle]; 108*5c51f124SMoriah Waterland 109*5c51f124SMoriah Waterland /* First free the alloc_seg list. */ 110*5c51f124SMoriah Waterland segstr_ptr = bl_ptr->alloc_segs; 111*5c51f124SMoriah Waterland 112*5c51f124SMoriah Waterland if (segstr_ptr) { 113*5c51f124SMoriah Waterland do { 114*5c51f124SMoriah Waterland nextstr_ptr = segstr_ptr->next; 115*5c51f124SMoriah Waterland 116*5c51f124SMoriah Waterland /* Free the memory block. */ 117*5c51f124SMoriah Waterland free((void *)segstr_ptr->seg_ptr); 118*5c51f124SMoriah Waterland 119*5c51f124SMoriah Waterland /* Free the control structure. */ 120*5c51f124SMoriah Waterland free((void *)segstr_ptr); 121*5c51f124SMoriah Waterland segstr_ptr = nextstr_ptr; 122*5c51f124SMoriah Waterland } while (segstr_ptr); 123*5c51f124SMoriah Waterland } 124*5c51f124SMoriah Waterland 125*5c51f124SMoriah Waterland /* Free the block control structure. */ 126*5c51f124SMoriah Waterland free((void *)bl_ptr->desc); 127*5c51f124SMoriah Waterland free((void *)bl_ptr); 128*5c51f124SMoriah Waterland 129*5c51f124SMoriah Waterland bl_cs_array[list_handle] = NULL; 130*5c51f124SMoriah Waterland } 131*5c51f124SMoriah Waterland 132*5c51f124SMoriah Waterland /* Allocate another alloc_seg structure. */ 133*5c51f124SMoriah Waterland static int 134*5c51f124SMoriah Waterland alloc_next_seg(struct blk_list_cs *bl_ptr) 135*5c51f124SMoriah Waterland { 136*5c51f124SMoriah Waterland struct alloc_seg *new_alloc_cs; 137*5c51f124SMoriah Waterland 138*5c51f124SMoriah Waterland if (bl_ptr->contiguous) { 139*5c51f124SMoriah Waterland int offset_to_avail, seg_size, new_size; 140*5c51f124SMoriah Waterland struct alloc_seg *alloc_segment; 141*5c51f124SMoriah Waterland 142*5c51f124SMoriah Waterland if (bl_ptr->alloc_segs) { 143*5c51f124SMoriah Waterland alloc_segment = bl_ptr->alloc_segs; 144*5c51f124SMoriah Waterland 145*5c51f124SMoriah Waterland offset_to_avail = (alloc_segment->avail_ptr - 146*5c51f124SMoriah Waterland alloc_segment->seg_ptr); 147*5c51f124SMoriah Waterland seg_size = (alloc_segment->eoseg_ptr - 148*5c51f124SMoriah Waterland alloc_segment->seg_ptr); 149*5c51f124SMoriah Waterland new_size = (seg_size + bl_ptr->block_size); 150*5c51f124SMoriah Waterland } else { 151*5c51f124SMoriah Waterland if ((bl_ptr->alloc_segs = 152*5c51f124SMoriah Waterland (struct alloc_seg *)calloc(1, 153*5c51f124SMoriah Waterland sizeof (struct alloc_seg))) == NULL) { 154*5c51f124SMoriah Waterland logerr(gettext(ERR_CS_ALLOC), (bl_ptr->desc ? 155*5c51f124SMoriah Waterland bl_ptr->desc : "an unknown")); 156*5c51f124SMoriah Waterland return (0); 157*5c51f124SMoriah Waterland } 158*5c51f124SMoriah Waterland 159*5c51f124SMoriah Waterland alloc_segment = bl_ptr->alloc_segs; 160*5c51f124SMoriah Waterland 161*5c51f124SMoriah Waterland offset_to_avail = 0; 162*5c51f124SMoriah Waterland seg_size = 0; 163*5c51f124SMoriah Waterland new_size = bl_ptr->block_size; 164*5c51f124SMoriah Waterland } 165*5c51f124SMoriah Waterland 166*5c51f124SMoriah Waterland bl_ptr->cur_segment = alloc_segment; 167*5c51f124SMoriah Waterland 168*5c51f124SMoriah Waterland if ((alloc_segment->seg_ptr = 169*5c51f124SMoriah Waterland (char *)realloc((void *)alloc_segment->seg_ptr, 170*5c51f124SMoriah Waterland (unsigned)new_size)) == NULL) { 171*5c51f124SMoriah Waterland logerr(gettext(ERR_MEM_ALLOC), (bl_ptr->desc ? 172*5c51f124SMoriah Waterland bl_ptr->desc : "an unknown")); 173*5c51f124SMoriah Waterland return (0); 174*5c51f124SMoriah Waterland } 175*5c51f124SMoriah Waterland 176*5c51f124SMoriah Waterland alloc_segment->next = NULL; 177*5c51f124SMoriah Waterland 178*5c51f124SMoriah Waterland /* reset the status */ 179*5c51f124SMoriah Waterland alloc_segment->full = 0; 180*5c51f124SMoriah Waterland 181*5c51f124SMoriah Waterland /* readjust the original pointers */ 182*5c51f124SMoriah Waterland alloc_segment->avail_ptr = alloc_segment->seg_ptr + 183*5c51f124SMoriah Waterland offset_to_avail; 184*5c51f124SMoriah Waterland alloc_segment->eoseg_ptr = alloc_segment->seg_ptr + new_size; 185*5c51f124SMoriah Waterland 186*5c51f124SMoriah Waterland (void) memset(alloc_segment->avail_ptr, '\000', 187*5c51f124SMoriah Waterland bl_ptr->block_size); 188*5c51f124SMoriah Waterland } else { 189*5c51f124SMoriah Waterland /* Allocate the control structure and link it into the list. */ 190*5c51f124SMoriah Waterland if ((new_alloc_cs = (struct alloc_seg *)malloc( 191*5c51f124SMoriah Waterland sizeof (struct alloc_seg))) == NULL) { 192*5c51f124SMoriah Waterland logerr(gettext(ERR_CS_ALLOC), (bl_ptr->desc ? 193*5c51f124SMoriah Waterland bl_ptr->desc : "an unknown")); 194*5c51f124SMoriah Waterland return (0); 195*5c51f124SMoriah Waterland } 196*5c51f124SMoriah Waterland 197*5c51f124SMoriah Waterland if (bl_ptr->alloc_segs == NULL) { 198*5c51f124SMoriah Waterland /* 199*5c51f124SMoriah Waterland * If this is the first allocation, then initialize 200*5c51f124SMoriah Waterland * the head pointer and set cur_segment to this first 201*5c51f124SMoriah Waterland * block of memory. 202*5c51f124SMoriah Waterland */ 203*5c51f124SMoriah Waterland bl_ptr->alloc_segs = new_alloc_cs; 204*5c51f124SMoriah Waterland } else { 205*5c51f124SMoriah Waterland /* 206*5c51f124SMoriah Waterland * Otherwise, point the current cur_segment to the 207*5c51f124SMoriah Waterland * next one and then point to the new one. 208*5c51f124SMoriah Waterland */ 209*5c51f124SMoriah Waterland bl_ptr->cur_segment->next = new_alloc_cs; 210*5c51f124SMoriah Waterland } 211*5c51f124SMoriah Waterland 212*5c51f124SMoriah Waterland new_alloc_cs->next = NULL; 213*5c51f124SMoriah Waterland bl_ptr->cur_segment = new_alloc_cs; 214*5c51f124SMoriah Waterland 215*5c51f124SMoriah Waterland new_alloc_cs->full = 0; 216*5c51f124SMoriah Waterland 217*5c51f124SMoriah Waterland /* Now allocate the block of memory that this controls. */ 218*5c51f124SMoriah Waterland if ((new_alloc_cs->seg_ptr = calloc(bl_ptr->count_per_block, 219*5c51f124SMoriah Waterland bl_ptr->struct_size)) == NULL) { 220*5c51f124SMoriah Waterland logerr(gettext(ERR_MEM_ALLOC), (bl_ptr->desc ? 221*5c51f124SMoriah Waterland bl_ptr->desc : "an unknown")); 222*5c51f124SMoriah Waterland return (0); 223*5c51f124SMoriah Waterland } 224*5c51f124SMoriah Waterland 225*5c51f124SMoriah Waterland new_alloc_cs->avail_ptr = new_alloc_cs->seg_ptr; 226*5c51f124SMoriah Waterland new_alloc_cs->eoseg_ptr = (new_alloc_cs->seg_ptr + 227*5c51f124SMoriah Waterland bl_ptr->block_size); 228*5c51f124SMoriah Waterland } 229*5c51f124SMoriah Waterland 230*5c51f124SMoriah Waterland return (1); 231*5c51f124SMoriah Waterland } 232*5c51f124SMoriah Waterland 233*5c51f124SMoriah Waterland /* 234*5c51f124SMoriah Waterland * These first functions (beginning with bl_*) manage simple block lists. The 235*5c51f124SMoriah Waterland * pointers returned, may get lost if they aren't assigned to an array or 236*5c51f124SMoriah Waterland * something. While individual records can be obtained by record number, the 237*5c51f124SMoriah Waterland * process isn't very efficient. Look to the array management section 238*5c51f124SMoriah Waterland * (ar_*)for an easily administrable list. 239*5c51f124SMoriah Waterland */ 240*5c51f124SMoriah Waterland 241*5c51f124SMoriah Waterland /* 242*5c51f124SMoriah Waterland * Create a block list. Allocate memory for a block list structure and 243*5c51f124SMoriah Waterland * initialize that structure. This doesn't actually allocate memory for the 244*5c51f124SMoriah Waterland * list yet, just the controlling data structure. Returns -1 on failure and a 245*5c51f124SMoriah Waterland * valid block list handle otherwise. 246*5c51f124SMoriah Waterland * 247*5c51f124SMoriah Waterland * NOTE: At the time of writing, it was not seen as important to recover block 248*5c51f124SMoriah Waterland * pointers made available with a bl_free() (two of these at most in 249*5c51f124SMoriah Waterland * pkginstall). If this became important later, we could trade efficiency for 250*5c51f124SMoriah Waterland * speed by ignoring next_array_elem and actually scanning through the array 251*5c51f124SMoriah Waterland * for a NULL pointer and then return that. 252*5c51f124SMoriah Waterland */ 253*5c51f124SMoriah Waterland int 254*5c51f124SMoriah Waterland bl_create(int count_per_block, int struct_size, char *desc) 255*5c51f124SMoriah Waterland { 256*5c51f124SMoriah Waterland struct blk_list_cs *bl_ptr; 257*5c51f124SMoriah Waterland int retval; 258*5c51f124SMoriah Waterland 259*5c51f124SMoriah Waterland if ((bl_cs_array[next_array_elem] = 260*5c51f124SMoriah Waterland (struct blk_list_cs *)calloc(1, sizeof (struct blk_list_cs))) == 261*5c51f124SMoriah Waterland NULL) { 262*5c51f124SMoriah Waterland logerr(gettext(ERR_CS_ALLOC), (desc ? desc : "an unknown")); 263*5c51f124SMoriah Waterland return (-1); 264*5c51f124SMoriah Waterland } 265*5c51f124SMoriah Waterland 266*5c51f124SMoriah Waterland bl_ptr = bl_cs_array[next_array_elem]; 267*5c51f124SMoriah Waterland retval = next_array_elem++; 268*5c51f124SMoriah Waterland 269*5c51f124SMoriah Waterland bl_ptr->data_handle = -1; 270*5c51f124SMoriah Waterland bl_ptr->struct_size = struct_size; 271*5c51f124SMoriah Waterland bl_ptr->count_per_block = count_per_block; 272*5c51f124SMoriah Waterland bl_ptr->block_size = (count_per_block * struct_size); 273*5c51f124SMoriah Waterland bl_ptr->desc = strdup((desc ? desc : "unknown")); 274*5c51f124SMoriah Waterland 275*5c51f124SMoriah Waterland return (retval); 276*5c51f124SMoriah Waterland } 277*5c51f124SMoriah Waterland 278*5c51f124SMoriah Waterland /* 279*5c51f124SMoriah Waterland * Get the next available entry in the list. This will allocate memory as 280*5c51f124SMoriah Waterland * required based on the initialization values in bl_create(). Returns a 281*5c51f124SMoriah Waterland * pointer to the allocated memory segment or NULL if operation was not 282*5c51f124SMoriah Waterland * possible. 283*5c51f124SMoriah Waterland */ 284*5c51f124SMoriah Waterland char * 285*5c51f124SMoriah Waterland bl_next_avail(int list_handle) 286*5c51f124SMoriah Waterland { 287*5c51f124SMoriah Waterland struct blk_list_cs *bl_ptr; 288*5c51f124SMoriah Waterland char *retval; 289*5c51f124SMoriah Waterland 290*5c51f124SMoriah Waterland if (invalid_handle(list_handle)) 291*5c51f124SMoriah Waterland return (NULL); 292*5c51f124SMoriah Waterland 293*5c51f124SMoriah Waterland bl_ptr = bl_cs_array[list_handle]; 294*5c51f124SMoriah Waterland 295*5c51f124SMoriah Waterland /* 296*5c51f124SMoriah Waterland * Allocate more memory if none is allocated yet or our last access 297*5c51f124SMoriah Waterland * filled the allotted segment. 298*5c51f124SMoriah Waterland */ 299*5c51f124SMoriah Waterland if (bl_ptr->cur_segment == NULL || bl_ptr->cur_segment->full) 300*5c51f124SMoriah Waterland if (!alloc_next_seg(bl_ptr)) 301*5c51f124SMoriah Waterland return (NULL); 302*5c51f124SMoriah Waterland 303*5c51f124SMoriah Waterland /* Get the correct pointer. */ 304*5c51f124SMoriah Waterland retval = bl_ptr->cur_segment->avail_ptr; 305*5c51f124SMoriah Waterland 306*5c51f124SMoriah Waterland /* Advance it and mark if full. */ 307*5c51f124SMoriah Waterland bl_ptr->cur_segment->avail_ptr += bl_ptr->struct_size; 308*5c51f124SMoriah Waterland bl_ptr->total_elem++; 309*5c51f124SMoriah Waterland 310*5c51f124SMoriah Waterland if (bl_ptr->cur_segment->avail_ptr >= bl_ptr->cur_segment->eoseg_ptr) 311*5c51f124SMoriah Waterland bl_ptr->cur_segment->full = 1; 312*5c51f124SMoriah Waterland 313*5c51f124SMoriah Waterland return (retval); 314*5c51f124SMoriah Waterland } 315*5c51f124SMoriah Waterland 316*5c51f124SMoriah Waterland char * 317*5c51f124SMoriah Waterland bl_get_record(int list_handle, int recno) 318*5c51f124SMoriah Waterland { 319*5c51f124SMoriah Waterland struct blk_list_cs *bl_ptr; 320*5c51f124SMoriah Waterland struct alloc_seg *cur_as_ptr; 321*5c51f124SMoriah Waterland int cur_rec = 0; 322*5c51f124SMoriah Waterland 323*5c51f124SMoriah Waterland if (invalid_record(list_handle, recno)) 324*5c51f124SMoriah Waterland return (NULL); 325*5c51f124SMoriah Waterland 326*5c51f124SMoriah Waterland bl_ptr = bl_cs_array[list_handle]; 327*5c51f124SMoriah Waterland 328*5c51f124SMoriah Waterland cur_as_ptr = bl_ptr->alloc_segs; 329*5c51f124SMoriah Waterland 330*5c51f124SMoriah Waterland while (recno > (cur_rec + bl_ptr->count_per_block)) { 331*5c51f124SMoriah Waterland cur_as_ptr = cur_as_ptr->next; 332*5c51f124SMoriah Waterland 333*5c51f124SMoriah Waterland if (cur_as_ptr == NULL) 334*5c51f124SMoriah Waterland return (NULL); 335*5c51f124SMoriah Waterland 336*5c51f124SMoriah Waterland cur_rec += bl_ptr->count_per_block; 337*5c51f124SMoriah Waterland } 338*5c51f124SMoriah Waterland 339*5c51f124SMoriah Waterland /* 340*5c51f124SMoriah Waterland * Now cur_as_ptr points to the allocated segment bearing the 341*5c51f124SMoriah Waterland * intended record and all we do now is move down that by the 342*5c51f124SMoriah Waterland * remaining record lengths. 343*5c51f124SMoriah Waterland */ 344*5c51f124SMoriah Waterland 345*5c51f124SMoriah Waterland return ((char *)cur_as_ptr + ((recno - cur_rec) * bl_ptr->struct_size)); 346*5c51f124SMoriah Waterland } 347*5c51f124SMoriah Waterland 348*5c51f124SMoriah Waterland void 349*5c51f124SMoriah Waterland bl_free(int list_handle) 350*5c51f124SMoriah Waterland { 351*5c51f124SMoriah Waterland int cur_handle; 352*5c51f124SMoriah Waterland 353*5c51f124SMoriah Waterland if (list_handle == -1) { 354*5c51f124SMoriah Waterland for (cur_handle = 0; cur_handle < next_array_elem; 355*5c51f124SMoriah Waterland cur_handle++) { 356*5c51f124SMoriah Waterland free_list(cur_handle); 357*5c51f124SMoriah Waterland } 358*5c51f124SMoriah Waterland } else { 359*5c51f124SMoriah Waterland if (invalid_handle(list_handle)) 360*5c51f124SMoriah Waterland return; 361*5c51f124SMoriah Waterland 362*5c51f124SMoriah Waterland free_list(list_handle); 363*5c51f124SMoriah Waterland } 364*5c51f124SMoriah Waterland } 365*5c51f124SMoriah Waterland 366*5c51f124SMoriah Waterland /* 367*5c51f124SMoriah Waterland * These are the array management functions. They insert into (and can return 368*5c51f124SMoriah Waterland * a pointer to) a contiguous list of pointers to stuff. This keeps 369*5c51f124SMoriah Waterland * everything together in a very handy package and is very similar in 370*5c51f124SMoriah Waterland * appearance to the arrays created by the old AT&T code. The method for 371*5c51f124SMoriah Waterland * presenting the interface is entirely different, however. 372*5c51f124SMoriah Waterland */ 373*5c51f124SMoriah Waterland 374*5c51f124SMoriah Waterland /* 375*5c51f124SMoriah Waterland * This constructs, maintains and returns pointers into a growable array of 376*5c51f124SMoriah Waterland * pointers to structures of the form 377*5c51f124SMoriah Waterland * struct something *array[n] 378*5c51f124SMoriah Waterland * The last element in the array is always NULL. 379*5c51f124SMoriah Waterland */ 380*5c51f124SMoriah Waterland int 381*5c51f124SMoriah Waterland ar_create(int count_per_block, int struct_size, char *desc) 382*5c51f124SMoriah Waterland { 383*5c51f124SMoriah Waterland int data_handle, retval; 384*5c51f124SMoriah Waterland char ar_desc[60]; 385*5c51f124SMoriah Waterland struct blk_list_cs *array_ptr; 386*5c51f124SMoriah Waterland 387*5c51f124SMoriah Waterland if ((data_handle = bl_create(count_per_block, struct_size, desc)) == -1) 388*5c51f124SMoriah Waterland return (-1); 389*5c51f124SMoriah Waterland 390*5c51f124SMoriah Waterland sprintf(ar_desc, "%s pointer", desc); 391*5c51f124SMoriah Waterland if ((retval = bl_create(count_per_block, sizeof (char *), 392*5c51f124SMoriah Waterland ar_desc)) == -1) 393*5c51f124SMoriah Waterland return (-1); 394*5c51f124SMoriah Waterland 395*5c51f124SMoriah Waterland array_ptr = bl_cs_array[retval]; 396*5c51f124SMoriah Waterland 397*5c51f124SMoriah Waterland array_ptr->contiguous = 1; 398*5c51f124SMoriah Waterland array_ptr->data_handle = data_handle; 399*5c51f124SMoriah Waterland 400*5c51f124SMoriah Waterland return (retval); 401*5c51f124SMoriah Waterland } 402*5c51f124SMoriah Waterland 403*5c51f124SMoriah Waterland /* Return a pointer to the first element in the array. */ 404*5c51f124SMoriah Waterland char ** 405*5c51f124SMoriah Waterland ar_get_head(int list_handle) 406*5c51f124SMoriah Waterland { 407*5c51f124SMoriah Waterland if (invalid_handle(list_handle) || 408*5c51f124SMoriah Waterland bl_cs_array[list_handle]->alloc_segs == NULL) 409*5c51f124SMoriah Waterland return (NULL); 410*5c51f124SMoriah Waterland 411*5c51f124SMoriah Waterland return ((char **)bl_cs_array[list_handle]->alloc_segs->seg_ptr); 412*5c51f124SMoriah Waterland } 413*5c51f124SMoriah Waterland 414*5c51f124SMoriah Waterland /* 415*5c51f124SMoriah Waterland * Free up the entry in the array indicated by index, but hold onto it for 416*5c51f124SMoriah Waterland * future use. 417*5c51f124SMoriah Waterland */ 418*5c51f124SMoriah Waterland int 419*5c51f124SMoriah Waterland ar_delete(int list_handle, int index) 420*5c51f124SMoriah Waterland { 421*5c51f124SMoriah Waterland char **array; 422*5c51f124SMoriah Waterland char *deleted_rec; 423*5c51f124SMoriah Waterland int i; 424*5c51f124SMoriah Waterland struct blk_list_cs *list_ptr, *data_ptr; 425*5c51f124SMoriah Waterland 426*5c51f124SMoriah Waterland if ((array = ar_get_head(list_handle)) == NULL) 427*5c51f124SMoriah Waterland return (0); 428*5c51f124SMoriah Waterland 429*5c51f124SMoriah Waterland if (invalid_record(list_handle, index)) 430*5c51f124SMoriah Waterland return (0); 431*5c51f124SMoriah Waterland 432*5c51f124SMoriah Waterland /* Get the pointer to the array control structure. */ 433*5c51f124SMoriah Waterland list_ptr = bl_cs_array[list_handle]; 434*5c51f124SMoriah Waterland 435*5c51f124SMoriah Waterland if (!(list_ptr->contiguous)) 436*5c51f124SMoriah Waterland return (0); /* This isn't an array. */ 437*5c51f124SMoriah Waterland 438*5c51f124SMoriah Waterland data_ptr = bl_cs_array[list_ptr->data_handle]; 439*5c51f124SMoriah Waterland 440*5c51f124SMoriah Waterland /* 441*5c51f124SMoriah Waterland * Since this looks just like an array. Record the pointer being 442*5c51f124SMoriah Waterland * deleted for insertion into the avail list at the end and move all 443*5c51f124SMoriah Waterland * elements below it up one. 444*5c51f124SMoriah Waterland */ 445*5c51f124SMoriah Waterland deleted_rec = array[index]; 446*5c51f124SMoriah Waterland 447*5c51f124SMoriah Waterland for (i = index; array[i] != NULL; i++) 448*5c51f124SMoriah Waterland array[i] = array[i+1]; 449*5c51f124SMoriah Waterland 450*5c51f124SMoriah Waterland /* 451*5c51f124SMoriah Waterland * Now insert the deleted entry into the avails list after the NULL 452*5c51f124SMoriah Waterland * and adjust the avail_ptr to point to the NULL again. 453*5c51f124SMoriah Waterland */ 454*5c51f124SMoriah Waterland array[i] = deleted_rec; 455*5c51f124SMoriah Waterland list_ptr->alloc_segs->avail_ptr -= list_ptr->struct_size; 456*5c51f124SMoriah Waterland 457*5c51f124SMoriah Waterland /* Adjust other entries in the control structure. */ 458*5c51f124SMoriah Waterland list_ptr->alloc_segs->full = 0; 459*5c51f124SMoriah Waterland list_ptr->total_elem -= 1; 460*5c51f124SMoriah Waterland 461*5c51f124SMoriah Waterland /* Clear the deleted data area. */ 462*5c51f124SMoriah Waterland (void) memset(deleted_rec, '\000', data_ptr->struct_size); 463*5c51f124SMoriah Waterland 464*5c51f124SMoriah Waterland return (1); 465*5c51f124SMoriah Waterland } 466*5c51f124SMoriah Waterland 467*5c51f124SMoriah Waterland /* 468*5c51f124SMoriah Waterland * Return a new pointer to a structure pointer. Find an available element in 469*5c51f124SMoriah Waterland * the array and point it at an available element in the data pool 470*5c51f124SMoriah Waterland * constructed of block lists. Allocate new memory as necessary. 471*5c51f124SMoriah Waterland */ 472*5c51f124SMoriah Waterland char ** 473*5c51f124SMoriah Waterland ar_next_avail(int list_handle) 474*5c51f124SMoriah Waterland { 475*5c51f124SMoriah Waterland struct blk_list_cs *array_ptr; 476*5c51f124SMoriah Waterland char *data_area, **pointer_area; 477*5c51f124SMoriah Waterland 478*5c51f124SMoriah Waterland if (invalid_handle(list_handle) || 479*5c51f124SMoriah Waterland !(bl_cs_array[list_handle]->contiguous) || 480*5c51f124SMoriah Waterland invalid_handle(bl_cs_array[list_handle]->data_handle)) 481*5c51f124SMoriah Waterland return (NULL); 482*5c51f124SMoriah Waterland 483*5c51f124SMoriah Waterland array_ptr = bl_cs_array[list_handle]; 484*5c51f124SMoriah Waterland 485*5c51f124SMoriah Waterland /* 486*5c51f124SMoriah Waterland * First see if an avail has already been allocated (it will be right 487*5c51f124SMoriah Waterland * after the NULL termination of the array if it exists). Return 488*5c51f124SMoriah Waterland * that, if found. 489*5c51f124SMoriah Waterland */ 490*5c51f124SMoriah Waterland if ((bl_cs_array[list_handle]->cur_segment != NULL) && 491*5c51f124SMoriah Waterland (ARRAY_END(list_handle) + REC_SIZE(list_handle) < 492*5c51f124SMoriah Waterland EOSEG(list_handle)) && 493*5c51f124SMoriah Waterland (*(pointer_area = (char **) GET_AVAIL(list_handle)) != NULL)) { 494*5c51f124SMoriah Waterland /* We can reclaim a previous deletion. */ 495*5c51f124SMoriah Waterland data_area = *pointer_area; 496*5c51f124SMoriah Waterland 497*5c51f124SMoriah Waterland *(char **)(ARRAY_END(list_handle)) = data_area; /* reactivate */ 498*5c51f124SMoriah Waterland *pointer_area-- = NULL; /* new end */ 499*5c51f124SMoriah Waterland 500*5c51f124SMoriah Waterland array_ptr->cur_segment->avail_ptr += array_ptr->struct_size; 501*5c51f124SMoriah Waterland array_ptr->total_elem++; 502*5c51f124SMoriah Waterland } else { 503*5c51f124SMoriah Waterland /* 504*5c51f124SMoriah Waterland * Get the data area first. This is the record we're pointing 505*5c51f124SMoriah Waterland * to from the array. 506*5c51f124SMoriah Waterland */ 507*5c51f124SMoriah Waterland data_area = bl_next_avail(array_ptr->data_handle); 508*5c51f124SMoriah Waterland 509*5c51f124SMoriah Waterland /* Now get the next pointer from the pointer array. */ 510*5c51f124SMoriah Waterland pointer_area = (char **) bl_next_avail(list_handle); 511*5c51f124SMoriah Waterland 512*5c51f124SMoriah Waterland *pointer_area = data_area; 513*5c51f124SMoriah Waterland 514*5c51f124SMoriah Waterland /* 515*5c51f124SMoriah Waterland * The array must be NULL terminated. So, if the block list 516*5c51f124SMoriah Waterland * structure is full, we have to grow it without resetting 517*5c51f124SMoriah Waterland * the avail pointer. NOTE: This will only work for a 518*5c51f124SMoriah Waterland * contiguous list! 519*5c51f124SMoriah Waterland */ 520*5c51f124SMoriah Waterland if (bl_cs_array[list_handle]->alloc_segs->full) { 521*5c51f124SMoriah Waterland char **old_list_pointer, **new_list_pointer; 522*5c51f124SMoriah Waterland 523*5c51f124SMoriah Waterland /* 524*5c51f124SMoriah Waterland * First grab the old numbers in case realloc() moves 525*5c51f124SMoriah Waterland * everything. 526*5c51f124SMoriah Waterland */ 527*5c51f124SMoriah Waterland old_list_pointer = ar_get_head(list_handle); 528*5c51f124SMoriah Waterland 529*5c51f124SMoriah Waterland /* 530*5c51f124SMoriah Waterland * Now allocate additional contiguous memory, moving 531*5c51f124SMoriah Waterland * the original block if necessary. 532*5c51f124SMoriah Waterland */ 533*5c51f124SMoriah Waterland if (!alloc_next_seg(array_ptr)) 534*5c51f124SMoriah Waterland return (NULL); 535*5c51f124SMoriah Waterland 536*5c51f124SMoriah Waterland /* 537*5c51f124SMoriah Waterland * Now determine if everything moved and readjust the 538*5c51f124SMoriah Waterland * pointer_area if required. 539*5c51f124SMoriah Waterland */ 540*5c51f124SMoriah Waterland new_list_pointer = ar_get_head(list_handle); 541*5c51f124SMoriah Waterland 542*5c51f124SMoriah Waterland if (old_list_pointer != new_list_pointer) { 543*5c51f124SMoriah Waterland pointer_area += (new_list_pointer - 544*5c51f124SMoriah Waterland old_list_pointer); 545*5c51f124SMoriah Waterland } 546*5c51f124SMoriah Waterland } 547*5c51f124SMoriah Waterland } 548*5c51f124SMoriah Waterland 549*5c51f124SMoriah Waterland return (pointer_area); 550*5c51f124SMoriah Waterland } 551*5c51f124SMoriah Waterland 552*5c51f124SMoriah Waterland /* 553*5c51f124SMoriah Waterland * Relinquish the array back to the memory pool. Note that there is no method 554*5c51f124SMoriah Waterland * provided to free *all* arrays. 555*5c51f124SMoriah Waterland */ 556*5c51f124SMoriah Waterland void 557*5c51f124SMoriah Waterland ar_free(int list_handle) 558*5c51f124SMoriah Waterland { 559*5c51f124SMoriah Waterland if (invalid_handle(list_handle)) 560*5c51f124SMoriah Waterland return; 561*5c51f124SMoriah Waterland 562*5c51f124SMoriah Waterland bl_free(bl_cs_array[list_handle]->data_handle); 563*5c51f124SMoriah Waterland bl_free(list_handle); 564*5c51f124SMoriah Waterland } 565