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