1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29 
30 
31 
32 #include <limits.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <errno.h>
37 #include <locale.h>
38 #include <libintl.h>
39 #include <pkglib.h>
40 #include <libadm.h>
41 
42 #define	ERR_MEMORY	"memory allocation failure, errno=%d"
43 
44 /*
45  * using factor of eight limits maximum
46  * memory fragmentation to 12.5%
47  */
48 #define	MEMSIZ	PATH_MAX*8
49 #define	NULL	0
50 
51 struct dup {
52 	char	mem[MEMSIZ];
53 	struct dup *next;
54 };
55 
56 static struct dup *head, *tail, *new;
57 
58 static int	size, initialized;
59 static void	pathinit();
60 static void	growstore();
61 
62 /*
63  * These functions allocate space for all the path names required
64  * in the packaging code. They are all allocated here so as to reduce
65  * memory fragmentation.
66  */
67 
68 /* Initialize storage area. */
69 static void
70 pathinit()
71 {
72 	if (head == NULL)
73 		size = (-1);
74 	else {
75 		/* free all memory used except initial structure */
76 		tail = head->next;
77 		while (tail) {
78 			new = tail->next;
79 			free(tail);
80 			tail = new;
81 		}
82 		tail = head;
83 		size = MEMSIZ;
84 	}
85 
86 	initialized = 1;
87 }
88 
89 /* Allocate additional space for storage area. */
90 static void
91 growstore()
92 {
93 	/* need more memory */
94 	new = calloc(1, sizeof (struct dup));
95 	if (new == NULL) {
96 		progerr(gettext(ERR_MEMORY), errno);
97 		quit(99);
98 	}
99 	if (head == NULL)
100 		head = new;
101 	else
102 		tail->next = new;
103 	tail = new;
104 	size = MEMSIZ;
105 }
106 
107 /* Allocate and return a pointer. If n == 0, initialize. */
108 char *
109 pathalloc(int n)
110 {
111 	char	*pt;
112 
113 	if (n <= 0) {
114 		pathinit();
115 		pt = NULL;
116 	} else {
117 		if (!initialized)
118 			pathinit();
119 
120 		n++;	/* Account for terminating null. */
121 
122 		if (size < n)
123 			growstore();
124 
125 		pt = &tail->mem[MEMSIZ-size];
126 		size -= n;
127 	}
128 
129 	return (pt);
130 }
131 
132 /* Allocate and insert a pathname returning a pointer to the new string. */
133 char *
134 pathdup(char *s)
135 {
136 	char	*pt;
137 	int	n;
138 
139 	if (s == NULL) {
140 		pathinit();
141 		pt = NULL;
142 	} else {
143 		if (!initialized)
144 			pathinit();
145 
146 		n = strlen(s) + 1;	/* string + null terminator */
147 
148 		if (size < n)
149 			growstore();
150 
151 		pt = &tail->mem[MEMSIZ-size];
152 		size -= n;
153 
154 		(void) strcpy(pt, s);
155 	}
156 
157 	return (pt);
158 }
159