/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 1996 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <libintl.h>
#include "pkglib.h"
/*
* This is the module responsible for allocating and maintaining lists that
* require allocation of memory. For certain lists, large chunks are
* allocated once to contain a large number of entries in each chunk (bl_*
* for block list). The other approach involves the augmentation of linked
* lists, each entry of which is alloc'd individually.
*/
struct alloc_seg {
};
struct blk_list_cs {
};
static int next_array_elem;
/* Support functions */
static int
{
return (1);
return (0);
}
static int
{
if (invalid_handle(list_handle))
return (1);
return (1);
return (0);
}
static void
{
/* Make sure this wasn't free'd earlier */
return;
/* First free the alloc_seg list. */
if (segstr_ptr) {
do {
/* Free the memory block. */
/* Free the control structure. */
free((void *)segstr_ptr);
} while (segstr_ptr);
}
/* Free the block control structure. */
}
/* Allocate another alloc_seg structure. */
static int
{
if (bl_ptr->contiguous) {
if (bl_ptr->alloc_segs) {
} else {
if ((bl_ptr->alloc_segs =
return (0);
}
offset_to_avail = 0;
seg_size = 0;
}
if ((alloc_segment->seg_ptr =
return (0);
}
/* reset the status */
alloc_segment->full = 0;
/* readjust the original pointers */
bl_ptr->block_size);
} else {
/* Allocate the control structure and link it into the list. */
return (0);
}
/*
* If this is the first allocation, then initialize
* the head pointer and set cur_segment to this first
* block of memory.
*/
} else {
/*
* Otherwise, point the current cur_segment to the
* next one and then point to the new one.
*/
}
new_alloc_cs->full = 0;
/* Now allocate the block of memory that this controls. */
return (0);
}
bl_ptr->block_size);
}
return (1);
}
/*
* These first functions (beginning with bl_*) manage simple block lists. The
* pointers returned, may get lost if they aren't assigned to an array or
* something. While individual records can be obtained by record number, the
* process isn't very efficient. Look to the array management section
* (ar_*)for an easily administrable list.
*/
/*
* Create a block list. Allocate memory for a block list structure and
* initialize that structure. This doesn't actually allocate memory for the
* list yet, just the controlling data structure. Returns -1 on failure and a
* valid block list handle otherwise.
*
* NOTE: At the time of writing, it was not seen as important to recover block
* pointers made available with a bl_free() (two of these at most in
* pkginstall). If this became important later, we could trade efficiency for
* speed by ignoring next_array_elem and actually scanning through the array
* for a NULL pointer and then return that.
*/
int
{
int retval;
if ((bl_cs_array[next_array_elem] =
NULL) {
return (-1);
}
retval = next_array_elem++;
return (retval);
}
/*
* Get the next available entry in the list. This will allocate memory as
* required based on the initialization values in bl_create(). Returns a
* pointer to the allocated memory segment or NULL if operation was not
* possible.
*/
char *
{
char *retval;
if (invalid_handle(list_handle))
return (NULL);
/*
* Allocate more memory if none is allocated yet or our last access
* filled the allotted segment.
*/
if (!alloc_next_seg(bl_ptr))
return (NULL);
/* Get the correct pointer. */
/* Advance it and mark if full. */
bl_ptr->total_elem++;
return (retval);
}
char *
{
int cur_rec = 0;
return (NULL);
if (cur_as_ptr == NULL)
return (NULL);
}
/*
* Now cur_as_ptr points to the allocated segment bearing the
* intended record and all we do now is move down that by the
* remaining record lengths.
*/
}
void
{
int cur_handle;
if (list_handle == -1) {
cur_handle++) {
}
} else {
if (invalid_handle(list_handle))
return;
}
}
/*
* These are the array management functions. They insert into (and can return
* a pointer to) a contiguous list of pointers to stuff. This keeps
* everything together in a very handy package and is very similar in
* appearance to the arrays created by the old AT&T code. The method for
* presenting the interface is entirely different, however.
*/
/*
* This constructs, maintains and returns pointers into a growable array of
* pointers to structures of the form
* struct something *array[n]
* The last element in the array is always NULL.
*/
int
{
return (-1);
ar_desc)) == -1)
return (-1);
return (retval);
}
/* Return a pointer to the first element in the array. */
char **
{
if (invalid_handle(list_handle) ||
return (NULL);
}
/*
* Free up the entry in the array indicated by index, but hold onto it for
* future use.
*/
int
{
char **array;
char *deleted_rec;
int i;
return (0);
return (0);
/* Get the pointer to the array control structure. */
if (!(list_ptr->contiguous))
return (0); /* This isn't an array. */
/*
* Since this looks just like an array. Record the pointer being
* deleted for insertion into the avail list at the end and move all
* elements below it up one.
*/
/*
* Now insert the deleted entry into the avails list after the NULL
* and adjust the avail_ptr to point to the NULL again.
*/
array[i] = deleted_rec;
/* Adjust other entries in the control structure. */
/* Clear the deleted data area. */
return (1);
}
/*
* Return a new pointer to a structure pointer. Find an available element in
* the array and point it at an available element in the data pool
* constructed of block lists. Allocate new memory as necessary.
*/
char **
{
if (invalid_handle(list_handle) ||
return (NULL);
/*
* First see if an avail has already been allocated (it will be right
* after the NULL termination of the array if it exists). Return
* that, if found.
*/
EOSEG(list_handle)) &&
/* We can reclaim a previous deletion. */
array_ptr->total_elem++;
} else {
/*
* Get the data area first. This is the record we're pointing
* to from the array.
*/
/* Now get the next pointer from the pointer array. */
/*
* The array must be NULL terminated. So, if the block list
* structure is full, we have to grow it without resetting
* the avail pointer. NOTE: This will only work for a
* contiguous list!
*/
/*
* First grab the old numbers in case realloc() moves
* everything.
*/
/*
* Now allocate additional contiguous memory, moving
* the original block if necessary.
*/
if (!alloc_next_seg(array_ptr))
return (NULL);
/*
* Now determine if everything moved and readjust the
* pointer_area if required.
*/
if (old_list_pointer != new_list_pointer) {
pointer_area += (new_list_pointer -
}
}
}
return (pointer_area);
}
/*
* Relinquish the array back to the memory pool. Note that there is no method
* provided to free *all* arrays.
*/
void
{
if (invalid_handle(list_handle))
return;
}