1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate */
26*7c478bd9Sstevel@tonic-gate
27*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
28*7c478bd9Sstevel@tonic-gate #include <sys/exacct.h>
29*7c478bd9Sstevel@tonic-gate #include <sys/exacct_catalog.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/exacct_impl.h>
31*7c478bd9Sstevel@tonic-gate
32*7c478bd9Sstevel@tonic-gate #ifndef _KERNEL
33*7c478bd9Sstevel@tonic-gate #include <limits.h>
34*7c478bd9Sstevel@tonic-gate #include <errno.h>
35*7c478bd9Sstevel@tonic-gate #include <poll.h>
36*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
37*7c478bd9Sstevel@tonic-gate #include <strings.h>
38*7c478bd9Sstevel@tonic-gate #else
39*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
40*7c478bd9Sstevel@tonic-gate #endif
41*7c478bd9Sstevel@tonic-gate
42*7c478bd9Sstevel@tonic-gate /*
43*7c478bd9Sstevel@tonic-gate * extended accounting file core routines
44*7c478bd9Sstevel@tonic-gate *
45*7c478bd9Sstevel@tonic-gate * Routines shared by libexacct and the kernel for the definition,
46*7c478bd9Sstevel@tonic-gate * construction and packing of extended accounting (exacct) records.
47*7c478bd9Sstevel@tonic-gate *
48*7c478bd9Sstevel@tonic-gate * Locking
49*7c478bd9Sstevel@tonic-gate * All routines in this file use ea_alloc(), which is a malloc() wrapper
50*7c478bd9Sstevel@tonic-gate * in userland and a kmem_alloc(..., KM_SLEEP) wrapper in the kernel.
51*7c478bd9Sstevel@tonic-gate * Accordingly, all routines require a context suitable for KM_SLEEP
52*7c478bd9Sstevel@tonic-gate * allocations.
53*7c478bd9Sstevel@tonic-gate */
54*7c478bd9Sstevel@tonic-gate
55*7c478bd9Sstevel@tonic-gate #define DEFAULT_ENTRIES 4
56*7c478bd9Sstevel@tonic-gate
57*7c478bd9Sstevel@tonic-gate /*
58*7c478bd9Sstevel@tonic-gate * ea_alloc() and ea_free() provide a wrapper for the common
59*7c478bd9Sstevel@tonic-gate * exacct code offering access to either the kmem allocator, or to libc's
60*7c478bd9Sstevel@tonic-gate * malloc.
61*7c478bd9Sstevel@tonic-gate */
62*7c478bd9Sstevel@tonic-gate void *
ea_alloc(size_t size)63*7c478bd9Sstevel@tonic-gate ea_alloc(size_t size)
64*7c478bd9Sstevel@tonic-gate {
65*7c478bd9Sstevel@tonic-gate #ifndef _KERNEL
66*7c478bd9Sstevel@tonic-gate void *p;
67*7c478bd9Sstevel@tonic-gate
68*7c478bd9Sstevel@tonic-gate while ((p = malloc(size)) == NULL && errno == EAGAIN)
69*7c478bd9Sstevel@tonic-gate (void) poll(NULL, 0, 10 * MILLISEC);
70*7c478bd9Sstevel@tonic-gate if (p == NULL) {
71*7c478bd9Sstevel@tonic-gate EXACCT_SET_ERR(EXR_SYSCALL_FAIL);
72*7c478bd9Sstevel@tonic-gate } else {
73*7c478bd9Sstevel@tonic-gate EXACCT_SET_ERR(EXR_OK);
74*7c478bd9Sstevel@tonic-gate }
75*7c478bd9Sstevel@tonic-gate return (p);
76*7c478bd9Sstevel@tonic-gate #else
77*7c478bd9Sstevel@tonic-gate return (kmem_alloc(size, KM_SLEEP));
78*7c478bd9Sstevel@tonic-gate #endif
79*7c478bd9Sstevel@tonic-gate }
80*7c478bd9Sstevel@tonic-gate
81*7c478bd9Sstevel@tonic-gate #ifndef _KERNEL
82*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
83*7c478bd9Sstevel@tonic-gate #endif
84*7c478bd9Sstevel@tonic-gate void
ea_free(void * ptr,size_t size)85*7c478bd9Sstevel@tonic-gate ea_free(void *ptr, size_t size)
86*7c478bd9Sstevel@tonic-gate {
87*7c478bd9Sstevel@tonic-gate #ifndef _KERNEL
88*7c478bd9Sstevel@tonic-gate free(ptr);
89*7c478bd9Sstevel@tonic-gate #else
90*7c478bd9Sstevel@tonic-gate kmem_free(ptr, size);
91*7c478bd9Sstevel@tonic-gate #endif
92*7c478bd9Sstevel@tonic-gate }
93*7c478bd9Sstevel@tonic-gate
94*7c478bd9Sstevel@tonic-gate /*
95*7c478bd9Sstevel@tonic-gate * ea_strdup() returns a pointer that, if non-NULL, must be freed using
96*7c478bd9Sstevel@tonic-gate * ea_strfree() once its useful life ends.
97*7c478bd9Sstevel@tonic-gate */
98*7c478bd9Sstevel@tonic-gate char *
ea_strdup(const char * ptr)99*7c478bd9Sstevel@tonic-gate ea_strdup(const char *ptr)
100*7c478bd9Sstevel@tonic-gate {
101*7c478bd9Sstevel@tonic-gate /* Sets exacct_errno. */
102*7c478bd9Sstevel@tonic-gate char *p = ea_alloc(strlen(ptr) + 1);
103*7c478bd9Sstevel@tonic-gate if (p != NULL) {
104*7c478bd9Sstevel@tonic-gate bcopy(ptr, p, strlen(ptr) + 1);
105*7c478bd9Sstevel@tonic-gate }
106*7c478bd9Sstevel@tonic-gate return (p);
107*7c478bd9Sstevel@tonic-gate }
108*7c478bd9Sstevel@tonic-gate
109*7c478bd9Sstevel@tonic-gate /*
110*7c478bd9Sstevel@tonic-gate * ea_strfree() frees a string allocated with ea_strdup().
111*7c478bd9Sstevel@tonic-gate */
112*7c478bd9Sstevel@tonic-gate void
ea_strfree(char * ptr)113*7c478bd9Sstevel@tonic-gate ea_strfree(char *ptr)
114*7c478bd9Sstevel@tonic-gate {
115*7c478bd9Sstevel@tonic-gate #ifndef _KERNEL
116*7c478bd9Sstevel@tonic-gate free(ptr);
117*7c478bd9Sstevel@tonic-gate #else
118*7c478bd9Sstevel@tonic-gate kmem_free(ptr, strlen(ptr) + 1);
119*7c478bd9Sstevel@tonic-gate #endif
120*7c478bd9Sstevel@tonic-gate }
121*7c478bd9Sstevel@tonic-gate
122*7c478bd9Sstevel@tonic-gate /*
123*7c478bd9Sstevel@tonic-gate * ea_cond_memcpy_at_offset() provides a simple conditional memcpy() that allows
124*7c478bd9Sstevel@tonic-gate * us to write a pack routine that returns a valid buffer size, copying only in
125*7c478bd9Sstevel@tonic-gate * the case that a non-NULL buffer is provided.
126*7c478bd9Sstevel@tonic-gate */
127*7c478bd9Sstevel@tonic-gate static void
ea_cond_memcpy_at_offset(void * dst,size_t offset,size_t dstsize,void * src,size_t size)128*7c478bd9Sstevel@tonic-gate ea_cond_memcpy_at_offset(void *dst, size_t offset, size_t dstsize, void *src,
129*7c478bd9Sstevel@tonic-gate size_t size)
130*7c478bd9Sstevel@tonic-gate {
131*7c478bd9Sstevel@tonic-gate char *cdst = dst;
132*7c478bd9Sstevel@tonic-gate char *csrc = src;
133*7c478bd9Sstevel@tonic-gate
134*7c478bd9Sstevel@tonic-gate if (dst == NULL || src == NULL || size == 0 || offset + size > dstsize)
135*7c478bd9Sstevel@tonic-gate return;
136*7c478bd9Sstevel@tonic-gate
137*7c478bd9Sstevel@tonic-gate bcopy(csrc, cdst + offset, size);
138*7c478bd9Sstevel@tonic-gate }
139*7c478bd9Sstevel@tonic-gate
140*7c478bd9Sstevel@tonic-gate /*
141*7c478bd9Sstevel@tonic-gate * exacct_order{16,32,64}() are byte-swapping routines that place the native
142*7c478bd9Sstevel@tonic-gate * data indicated by the input pointer in big-endian order. Each exacct_order
143*7c478bd9Sstevel@tonic-gate * function is its own inverse.
144*7c478bd9Sstevel@tonic-gate */
145*7c478bd9Sstevel@tonic-gate #ifndef _LITTLE_ENDIAN
146*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
147*7c478bd9Sstevel@tonic-gate #endif /* _LITTLE_ENDIAN */
148*7c478bd9Sstevel@tonic-gate void
exacct_order16(uint16_t * in)149*7c478bd9Sstevel@tonic-gate exacct_order16(uint16_t *in)
150*7c478bd9Sstevel@tonic-gate {
151*7c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN
152*7c478bd9Sstevel@tonic-gate uint8_t s;
153*7c478bd9Sstevel@tonic-gate union {
154*7c478bd9Sstevel@tonic-gate uint16_t agg;
155*7c478bd9Sstevel@tonic-gate uint8_t arr[2];
156*7c478bd9Sstevel@tonic-gate } t;
157*7c478bd9Sstevel@tonic-gate
158*7c478bd9Sstevel@tonic-gate t.agg = *in;
159*7c478bd9Sstevel@tonic-gate
160*7c478bd9Sstevel@tonic-gate s = t.arr[0];
161*7c478bd9Sstevel@tonic-gate t.arr[0] = t.arr[1];
162*7c478bd9Sstevel@tonic-gate t.arr[1] = s;
163*7c478bd9Sstevel@tonic-gate
164*7c478bd9Sstevel@tonic-gate *in = t.agg;
165*7c478bd9Sstevel@tonic-gate #endif /* _LITTLE_ENDIAN */
166*7c478bd9Sstevel@tonic-gate }
167*7c478bd9Sstevel@tonic-gate
168*7c478bd9Sstevel@tonic-gate #ifndef _LITTLE_ENDIAN
169*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
170*7c478bd9Sstevel@tonic-gate #endif /* _LITTLE_ENDIAN */
171*7c478bd9Sstevel@tonic-gate void
exacct_order32(uint32_t * in)172*7c478bd9Sstevel@tonic-gate exacct_order32(uint32_t *in)
173*7c478bd9Sstevel@tonic-gate {
174*7c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN
175*7c478bd9Sstevel@tonic-gate uint16_t s;
176*7c478bd9Sstevel@tonic-gate union {
177*7c478bd9Sstevel@tonic-gate uint32_t agg;
178*7c478bd9Sstevel@tonic-gate uint16_t arr[2];
179*7c478bd9Sstevel@tonic-gate } t;
180*7c478bd9Sstevel@tonic-gate
181*7c478bd9Sstevel@tonic-gate t.agg = *in;
182*7c478bd9Sstevel@tonic-gate exacct_order16(&t.arr[0]);
183*7c478bd9Sstevel@tonic-gate exacct_order16(&t.arr[1]);
184*7c478bd9Sstevel@tonic-gate
185*7c478bd9Sstevel@tonic-gate s = t.arr[0];
186*7c478bd9Sstevel@tonic-gate t.arr[0] = t.arr[1];
187*7c478bd9Sstevel@tonic-gate t.arr[1] = s;
188*7c478bd9Sstevel@tonic-gate
189*7c478bd9Sstevel@tonic-gate *in = t.agg;
190*7c478bd9Sstevel@tonic-gate #endif /* _LITTLE_ENDIAN */
191*7c478bd9Sstevel@tonic-gate }
192*7c478bd9Sstevel@tonic-gate
193*7c478bd9Sstevel@tonic-gate #ifndef _LITTLE_ENDIAN
194*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
195*7c478bd9Sstevel@tonic-gate #endif /* _LITTLE_ENDIAN */
196*7c478bd9Sstevel@tonic-gate void
exacct_order64(uint64_t * in)197*7c478bd9Sstevel@tonic-gate exacct_order64(uint64_t *in)
198*7c478bd9Sstevel@tonic-gate {
199*7c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN
200*7c478bd9Sstevel@tonic-gate uint32_t s;
201*7c478bd9Sstevel@tonic-gate union {
202*7c478bd9Sstevel@tonic-gate uint64_t agg;
203*7c478bd9Sstevel@tonic-gate uint32_t arr[2];
204*7c478bd9Sstevel@tonic-gate } t;
205*7c478bd9Sstevel@tonic-gate
206*7c478bd9Sstevel@tonic-gate t.agg = *in;
207*7c478bd9Sstevel@tonic-gate exacct_order32(&t.arr[0]);
208*7c478bd9Sstevel@tonic-gate exacct_order32(&t.arr[1]);
209*7c478bd9Sstevel@tonic-gate
210*7c478bd9Sstevel@tonic-gate s = t.arr[0];
211*7c478bd9Sstevel@tonic-gate t.arr[0] = t.arr[1];
212*7c478bd9Sstevel@tonic-gate t.arr[1] = s;
213*7c478bd9Sstevel@tonic-gate
214*7c478bd9Sstevel@tonic-gate *in = t.agg;
215*7c478bd9Sstevel@tonic-gate #endif /* _LITTLE_ENDIAN */
216*7c478bd9Sstevel@tonic-gate }
217*7c478bd9Sstevel@tonic-gate
218*7c478bd9Sstevel@tonic-gate int
ea_match_object_catalog(ea_object_t * obj,ea_catalog_t catmask)219*7c478bd9Sstevel@tonic-gate ea_match_object_catalog(ea_object_t *obj, ea_catalog_t catmask)
220*7c478bd9Sstevel@tonic-gate {
221*7c478bd9Sstevel@tonic-gate ea_catalog_t catval = obj->eo_catalog;
222*7c478bd9Sstevel@tonic-gate
223*7c478bd9Sstevel@tonic-gate #define EM_MATCH(v, m, M) ((m & M) == 0 || (v & M) == (m & M))
224*7c478bd9Sstevel@tonic-gate return (EM_MATCH(catval, catmask, EXT_TYPE_MASK) &&
225*7c478bd9Sstevel@tonic-gate EM_MATCH(catval, catmask, EXC_CATALOG_MASK) &&
226*7c478bd9Sstevel@tonic-gate EM_MATCH(catval, catmask, EXD_DATA_MASK));
227*7c478bd9Sstevel@tonic-gate #undef EM_MATCH
228*7c478bd9Sstevel@tonic-gate }
229*7c478bd9Sstevel@tonic-gate
230*7c478bd9Sstevel@tonic-gate int
ea_set_item(ea_object_t * obj,ea_catalog_t tag,const void * value,size_t valsize)231*7c478bd9Sstevel@tonic-gate ea_set_item(ea_object_t *obj, ea_catalog_t tag,
232*7c478bd9Sstevel@tonic-gate const void *value, size_t valsize)
233*7c478bd9Sstevel@tonic-gate {
234*7c478bd9Sstevel@tonic-gate ea_item_t *item = &obj->eo_item;
235*7c478bd9Sstevel@tonic-gate
236*7c478bd9Sstevel@tonic-gate if ((tag & EXT_TYPE_MASK) == EXT_GROUP) {
237*7c478bd9Sstevel@tonic-gate EXACCT_SET_ERR(EXR_INVALID_OBJ);
238*7c478bd9Sstevel@tonic-gate return (-1);
239*7c478bd9Sstevel@tonic-gate }
240*7c478bd9Sstevel@tonic-gate
241*7c478bd9Sstevel@tonic-gate bzero(obj, sizeof (ea_object_t));
242*7c478bd9Sstevel@tonic-gate obj->eo_type = EO_ITEM;
243*7c478bd9Sstevel@tonic-gate obj->eo_catalog = tag;
244*7c478bd9Sstevel@tonic-gate
245*7c478bd9Sstevel@tonic-gate switch (obj->eo_catalog & EXT_TYPE_MASK) {
246*7c478bd9Sstevel@tonic-gate case EXT_UINT8:
247*7c478bd9Sstevel@tonic-gate item->ei_u.ei_u_uint8 = *(uint8_t *)value;
248*7c478bd9Sstevel@tonic-gate item->ei_size = sizeof (uint8_t);
249*7c478bd9Sstevel@tonic-gate break;
250*7c478bd9Sstevel@tonic-gate case EXT_UINT16:
251*7c478bd9Sstevel@tonic-gate item->ei_u.ei_u_uint16 = *(uint16_t *)value;
252*7c478bd9Sstevel@tonic-gate item->ei_size = sizeof (uint16_t);
253*7c478bd9Sstevel@tonic-gate break;
254*7c478bd9Sstevel@tonic-gate case EXT_UINT32:
255*7c478bd9Sstevel@tonic-gate item->ei_u.ei_u_uint32 = *(uint32_t *)value;
256*7c478bd9Sstevel@tonic-gate item->ei_size = sizeof (uint32_t);
257*7c478bd9Sstevel@tonic-gate break;
258*7c478bd9Sstevel@tonic-gate case EXT_UINT64:
259*7c478bd9Sstevel@tonic-gate item->ei_u.ei_u_uint64 = *(uint64_t *)value;
260*7c478bd9Sstevel@tonic-gate item->ei_size = sizeof (uint64_t);
261*7c478bd9Sstevel@tonic-gate break;
262*7c478bd9Sstevel@tonic-gate case EXT_DOUBLE:
263*7c478bd9Sstevel@tonic-gate item->ei_u.ei_u_double = *(double *)value;
264*7c478bd9Sstevel@tonic-gate item->ei_size = sizeof (double);
265*7c478bd9Sstevel@tonic-gate break;
266*7c478bd9Sstevel@tonic-gate case EXT_STRING:
267*7c478bd9Sstevel@tonic-gate if ((item->ei_string = ea_strdup((char *)value)) == NULL) {
268*7c478bd9Sstevel@tonic-gate /* exacct_errno set above. */
269*7c478bd9Sstevel@tonic-gate return (-1);
270*7c478bd9Sstevel@tonic-gate }
271*7c478bd9Sstevel@tonic-gate item->ei_size = strlen(item->ei_string) + 1;
272*7c478bd9Sstevel@tonic-gate break;
273*7c478bd9Sstevel@tonic-gate case EXT_EXACCT_OBJECT:
274*7c478bd9Sstevel@tonic-gate if ((item->ei_object = ea_alloc(valsize)) == NULL) {
275*7c478bd9Sstevel@tonic-gate /* exacct_errno set above. */
276*7c478bd9Sstevel@tonic-gate return (-1);
277*7c478bd9Sstevel@tonic-gate }
278*7c478bd9Sstevel@tonic-gate bcopy(value, item->ei_object, valsize);
279*7c478bd9Sstevel@tonic-gate item->ei_size = valsize;
280*7c478bd9Sstevel@tonic-gate break;
281*7c478bd9Sstevel@tonic-gate case EXT_RAW:
282*7c478bd9Sstevel@tonic-gate if ((item->ei_raw = ea_alloc(valsize)) == NULL) {
283*7c478bd9Sstevel@tonic-gate /* exacct_errno set above. */
284*7c478bd9Sstevel@tonic-gate return (-1);
285*7c478bd9Sstevel@tonic-gate }
286*7c478bd9Sstevel@tonic-gate bcopy(value, item->ei_raw, valsize);
287*7c478bd9Sstevel@tonic-gate item->ei_size = valsize;
288*7c478bd9Sstevel@tonic-gate break;
289*7c478bd9Sstevel@tonic-gate default:
290*7c478bd9Sstevel@tonic-gate EXACCT_SET_ERR(EXR_INVALID_OBJ);
291*7c478bd9Sstevel@tonic-gate return (-1);
292*7c478bd9Sstevel@tonic-gate }
293*7c478bd9Sstevel@tonic-gate
294*7c478bd9Sstevel@tonic-gate EXACCT_SET_ERR(EXR_OK);
295*7c478bd9Sstevel@tonic-gate return (0);
296*7c478bd9Sstevel@tonic-gate }
297*7c478bd9Sstevel@tonic-gate
298*7c478bd9Sstevel@tonic-gate int
ea_set_group(ea_object_t * obj,ea_catalog_t tag)299*7c478bd9Sstevel@tonic-gate ea_set_group(ea_object_t *obj, ea_catalog_t tag)
300*7c478bd9Sstevel@tonic-gate {
301*7c478bd9Sstevel@tonic-gate if ((tag & EXT_TYPE_MASK) != EXT_GROUP) {
302*7c478bd9Sstevel@tonic-gate EXACCT_SET_ERR(EXR_INVALID_OBJ);
303*7c478bd9Sstevel@tonic-gate return (-1);
304*7c478bd9Sstevel@tonic-gate }
305*7c478bd9Sstevel@tonic-gate
306*7c478bd9Sstevel@tonic-gate bzero(obj, sizeof (ea_object_t));
307*7c478bd9Sstevel@tonic-gate
308*7c478bd9Sstevel@tonic-gate obj->eo_type = EO_GROUP;
309*7c478bd9Sstevel@tonic-gate obj->eo_catalog = tag;
310*7c478bd9Sstevel@tonic-gate obj->eo_u.eo_u_group.eg_nobjs = 0;
311*7c478bd9Sstevel@tonic-gate obj->eo_u.eo_u_group.eg_objs = NULL;
312*7c478bd9Sstevel@tonic-gate
313*7c478bd9Sstevel@tonic-gate EXACCT_SET_ERR(EXR_OK);
314*7c478bd9Sstevel@tonic-gate return (0);
315*7c478bd9Sstevel@tonic-gate }
316*7c478bd9Sstevel@tonic-gate
317*7c478bd9Sstevel@tonic-gate void
ea_free_object(ea_object_t * obj,int flag)318*7c478bd9Sstevel@tonic-gate ea_free_object(ea_object_t *obj, int flag)
319*7c478bd9Sstevel@tonic-gate {
320*7c478bd9Sstevel@tonic-gate ea_object_t *next = obj;
321*7c478bd9Sstevel@tonic-gate ea_object_t *save;
322*7c478bd9Sstevel@tonic-gate
323*7c478bd9Sstevel@tonic-gate while (next != NULL) {
324*7c478bd9Sstevel@tonic-gate if (next->eo_type == EO_GROUP) {
325*7c478bd9Sstevel@tonic-gate ea_free_object(next->eo_group.eg_objs, flag);
326*7c478bd9Sstevel@tonic-gate } else if (next->eo_type == EO_ITEM) {
327*7c478bd9Sstevel@tonic-gate switch (next->eo_catalog & EXT_TYPE_MASK) {
328*7c478bd9Sstevel@tonic-gate case EXT_STRING:
329*7c478bd9Sstevel@tonic-gate if (flag == EUP_ALLOC)
330*7c478bd9Sstevel@tonic-gate ea_strfree(next->eo_item.ei_string);
331*7c478bd9Sstevel@tonic-gate break;
332*7c478bd9Sstevel@tonic-gate case EXT_RAW:
333*7c478bd9Sstevel@tonic-gate case EXT_EXACCT_OBJECT:
334*7c478bd9Sstevel@tonic-gate if (flag == EUP_ALLOC)
335*7c478bd9Sstevel@tonic-gate ea_free(next->eo_item.ei_raw,
336*7c478bd9Sstevel@tonic-gate next->eo_item.ei_size);
337*7c478bd9Sstevel@tonic-gate break;
338*7c478bd9Sstevel@tonic-gate default:
339*7c478bd9Sstevel@tonic-gate /* No action required for other types. */
340*7c478bd9Sstevel@tonic-gate break;
341*7c478bd9Sstevel@tonic-gate }
342*7c478bd9Sstevel@tonic-gate }
343*7c478bd9Sstevel@tonic-gate /* No action required for EO_NONE. */
344*7c478bd9Sstevel@tonic-gate
345*7c478bd9Sstevel@tonic-gate save = next;
346*7c478bd9Sstevel@tonic-gate next = next->eo_next;
347*7c478bd9Sstevel@tonic-gate #ifdef _KERNEL
348*7c478bd9Sstevel@tonic-gate kmem_cache_free(exacct_object_cache, save);
349*7c478bd9Sstevel@tonic-gate #else
350*7c478bd9Sstevel@tonic-gate ea_free(save, sizeof (ea_object_t));
351*7c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
352*7c478bd9Sstevel@tonic-gate }
353*7c478bd9Sstevel@tonic-gate }
354*7c478bd9Sstevel@tonic-gate
355*7c478bd9Sstevel@tonic-gate int
ea_free_item(ea_object_t * obj,int flag)356*7c478bd9Sstevel@tonic-gate ea_free_item(ea_object_t *obj, int flag)
357*7c478bd9Sstevel@tonic-gate {
358*7c478bd9Sstevel@tonic-gate if (obj->eo_type != EO_ITEM) {
359*7c478bd9Sstevel@tonic-gate EXACCT_SET_ERR(EXR_INVALID_OBJ);
360*7c478bd9Sstevel@tonic-gate return (-1);
361*7c478bd9Sstevel@tonic-gate }
362*7c478bd9Sstevel@tonic-gate
363*7c478bd9Sstevel@tonic-gate switch (obj->eo_catalog & EXT_TYPE_MASK) {
364*7c478bd9Sstevel@tonic-gate case EXT_STRING:
365*7c478bd9Sstevel@tonic-gate if (flag == EUP_ALLOC)
366*7c478bd9Sstevel@tonic-gate ea_strfree(obj->eo_item.ei_string);
367*7c478bd9Sstevel@tonic-gate break;
368*7c478bd9Sstevel@tonic-gate case EXT_RAW:
369*7c478bd9Sstevel@tonic-gate case EXT_EXACCT_OBJECT:
370*7c478bd9Sstevel@tonic-gate if (flag == EUP_ALLOC)
371*7c478bd9Sstevel@tonic-gate ea_free(obj->eo_item.ei_raw, obj->eo_item.ei_size);
372*7c478bd9Sstevel@tonic-gate break;
373*7c478bd9Sstevel@tonic-gate default:
374*7c478bd9Sstevel@tonic-gate /* No action required for other types. */
375*7c478bd9Sstevel@tonic-gate break;
376*7c478bd9Sstevel@tonic-gate }
377*7c478bd9Sstevel@tonic-gate
378*7c478bd9Sstevel@tonic-gate obj->eo_catalog = 0;
379*7c478bd9Sstevel@tonic-gate obj->eo_type = EO_NONE;
380*7c478bd9Sstevel@tonic-gate EXACCT_SET_ERR(EXR_OK);
381*7c478bd9Sstevel@tonic-gate return (0);
382*7c478bd9Sstevel@tonic-gate }
383*7c478bd9Sstevel@tonic-gate
384*7c478bd9Sstevel@tonic-gate static void
ea_attach_object(ea_object_t ** objp,ea_object_t * obj)385*7c478bd9Sstevel@tonic-gate ea_attach_object(ea_object_t **objp, ea_object_t *obj)
386*7c478bd9Sstevel@tonic-gate {
387*7c478bd9Sstevel@tonic-gate ea_object_t *tp;
388*7c478bd9Sstevel@tonic-gate
389*7c478bd9Sstevel@tonic-gate tp = *objp;
390*7c478bd9Sstevel@tonic-gate *objp = obj;
391*7c478bd9Sstevel@tonic-gate obj->eo_next = tp;
392*7c478bd9Sstevel@tonic-gate }
393*7c478bd9Sstevel@tonic-gate
394*7c478bd9Sstevel@tonic-gate int
ea_attach_to_object(ea_object_t * root,ea_object_t * obj)395*7c478bd9Sstevel@tonic-gate ea_attach_to_object(ea_object_t *root, ea_object_t *obj)
396*7c478bd9Sstevel@tonic-gate {
397*7c478bd9Sstevel@tonic-gate if (obj->eo_type == EO_GROUP || obj->eo_type == EO_ITEM) {
398*7c478bd9Sstevel@tonic-gate ea_attach_object(&root->eo_next, obj);
399*7c478bd9Sstevel@tonic-gate EXACCT_SET_ERR(EXR_OK);
400*7c478bd9Sstevel@tonic-gate return (0);
401*7c478bd9Sstevel@tonic-gate } else {
402*7c478bd9Sstevel@tonic-gate EXACCT_SET_ERR(EXR_INVALID_OBJ);
403*7c478bd9Sstevel@tonic-gate return (-1);
404*7c478bd9Sstevel@tonic-gate }
405*7c478bd9Sstevel@tonic-gate }
406*7c478bd9Sstevel@tonic-gate
407*7c478bd9Sstevel@tonic-gate /*
408*7c478bd9Sstevel@tonic-gate * ea_attach_to_group() takes a group object and an additional exacct object and
409*7c478bd9Sstevel@tonic-gate * attaches the latter to the object list of the former. The attached exacct
410*7c478bd9Sstevel@tonic-gate * object can be the head of a chain of objects. If group isn't actually an
411*7c478bd9Sstevel@tonic-gate * object of type EO_GROUP, do nothing, such that we don't destroy its contents.
412*7c478bd9Sstevel@tonic-gate */
413*7c478bd9Sstevel@tonic-gate int
ea_attach_to_group(ea_object_t * group,ea_object_t * obj)414*7c478bd9Sstevel@tonic-gate ea_attach_to_group(ea_object_t *group, ea_object_t *obj)
415*7c478bd9Sstevel@tonic-gate {
416*7c478bd9Sstevel@tonic-gate uint_t n = 0;
417*7c478bd9Sstevel@tonic-gate ea_object_t *next;
418*7c478bd9Sstevel@tonic-gate ea_object_t **nextp;
419*7c478bd9Sstevel@tonic-gate
420*7c478bd9Sstevel@tonic-gate if (group->eo_type != EO_GROUP) {
421*7c478bd9Sstevel@tonic-gate EXACCT_SET_ERR(EXR_INVALID_OBJ);
422*7c478bd9Sstevel@tonic-gate return (-1);
423*7c478bd9Sstevel@tonic-gate }
424*7c478bd9Sstevel@tonic-gate
425*7c478bd9Sstevel@tonic-gate for (next = obj; next != NULL; next = next->eo_next)
426*7c478bd9Sstevel@tonic-gate n++;
427*7c478bd9Sstevel@tonic-gate
428*7c478bd9Sstevel@tonic-gate group->eo_group.eg_nobjs += n;
429*7c478bd9Sstevel@tonic-gate
430*7c478bd9Sstevel@tonic-gate for (nextp = &group->eo_group.eg_objs; *nextp != NULL;
431*7c478bd9Sstevel@tonic-gate nextp = &(*nextp)->eo_next)
432*7c478bd9Sstevel@tonic-gate continue;
433*7c478bd9Sstevel@tonic-gate
434*7c478bd9Sstevel@tonic-gate ea_attach_object(nextp, obj);
435*7c478bd9Sstevel@tonic-gate EXACCT_SET_ERR(EXR_OK);
436*7c478bd9Sstevel@tonic-gate return (0);
437*7c478bd9Sstevel@tonic-gate }
438*7c478bd9Sstevel@tonic-gate
439*7c478bd9Sstevel@tonic-gate /*
440*7c478bd9Sstevel@tonic-gate * ea_pack_object takes the given exacct object series beginning with obj and
441*7c478bd9Sstevel@tonic-gate * places it in buf. Since ea_pack_object needs to be runnable in kernel
442*7c478bd9Sstevel@tonic-gate * context, we construct it to use its own stack of state. Specifically, we
443*7c478bd9Sstevel@tonic-gate * store the locations of the sizes of open records (records whose construction
444*7c478bd9Sstevel@tonic-gate * is in progress). curr_frame is used to indicate the current frame. Just
445*7c478bd9Sstevel@tonic-gate * prior to decrementing curr_frame, we must ensure that the correct size for
446*7c478bd9Sstevel@tonic-gate * that frame is placed in the given offset.
447*7c478bd9Sstevel@tonic-gate */
448*7c478bd9Sstevel@tonic-gate struct es_frame {
449*7c478bd9Sstevel@tonic-gate ea_object_t *esf_obj;
450*7c478bd9Sstevel@tonic-gate ea_size_t esf_size;
451*7c478bd9Sstevel@tonic-gate ea_size_t esf_bksize;
452*7c478bd9Sstevel@tonic-gate ea_size_t esf_offset;
453*7c478bd9Sstevel@tonic-gate };
454*7c478bd9Sstevel@tonic-gate
455*7c478bd9Sstevel@tonic-gate static void
incr_parent_frames(struct es_frame * base,int n,size_t amt)456*7c478bd9Sstevel@tonic-gate incr_parent_frames(struct es_frame *base, int n, size_t amt)
457*7c478bd9Sstevel@tonic-gate {
458*7c478bd9Sstevel@tonic-gate int i;
459*7c478bd9Sstevel@tonic-gate
460*7c478bd9Sstevel@tonic-gate for (i = 0; i <= n; i++) {
461*7c478bd9Sstevel@tonic-gate base[i].esf_size += amt;
462*7c478bd9Sstevel@tonic-gate base[i].esf_bksize += amt;
463*7c478bd9Sstevel@tonic-gate }
464*7c478bd9Sstevel@tonic-gate }
465*7c478bd9Sstevel@tonic-gate
466*7c478bd9Sstevel@tonic-gate size_t
ea_pack_object(ea_object_t * obj,void * buf,size_t bufsize)467*7c478bd9Sstevel@tonic-gate ea_pack_object(ea_object_t *obj, void *buf, size_t bufsize)
468*7c478bd9Sstevel@tonic-gate {
469*7c478bd9Sstevel@tonic-gate struct es_frame *estack;
470*7c478bd9Sstevel@tonic-gate uint_t neframes;
471*7c478bd9Sstevel@tonic-gate ea_object_t *curr_obj = obj;
472*7c478bd9Sstevel@tonic-gate int curr_frame = 0;
473*7c478bd9Sstevel@tonic-gate size_t curr_pos = 0;
474*7c478bd9Sstevel@tonic-gate ea_size_t placeholder = 0;
475*7c478bd9Sstevel@tonic-gate int end_of_group = 0;
476*7c478bd9Sstevel@tonic-gate uint32_t gp_backskip = sizeof (ea_catalog_t) + sizeof (ea_size_t) +
477*7c478bd9Sstevel@tonic-gate sizeof (uint32_t) + sizeof (uint32_t);
478*7c478bd9Sstevel@tonic-gate uint32_t lge_backskip;
479*7c478bd9Sstevel@tonic-gate
480*7c478bd9Sstevel@tonic-gate exacct_order32(&gp_backskip);
481*7c478bd9Sstevel@tonic-gate estack = ea_alloc(sizeof (struct es_frame) * DEFAULT_ENTRIES);
482*7c478bd9Sstevel@tonic-gate if (estack == NULL) {
483*7c478bd9Sstevel@tonic-gate /* exacct_errno set above. */
484*7c478bd9Sstevel@tonic-gate return ((size_t)-1);
485*7c478bd9Sstevel@tonic-gate }
486*7c478bd9Sstevel@tonic-gate bzero(estack, sizeof (struct es_frame) * DEFAULT_ENTRIES);
487*7c478bd9Sstevel@tonic-gate neframes = DEFAULT_ENTRIES;
488*7c478bd9Sstevel@tonic-gate
489*7c478bd9Sstevel@tonic-gate /*
490*7c478bd9Sstevel@tonic-gate * 1. Start with the current object.
491*7c478bd9Sstevel@tonic-gate */
492*7c478bd9Sstevel@tonic-gate for (;;) {
493*7c478bd9Sstevel@tonic-gate void *src;
494*7c478bd9Sstevel@tonic-gate size_t size;
495*7c478bd9Sstevel@tonic-gate
496*7c478bd9Sstevel@tonic-gate /*
497*7c478bd9Sstevel@tonic-gate * 1a. If at the bottom of the stack, we are done.
498*7c478bd9Sstevel@tonic-gate * If at the end of a group, place the correct size at the head
499*7c478bd9Sstevel@tonic-gate * of the chain, the correct backskip amount in the next
500*7c478bd9Sstevel@tonic-gate * position in the buffer, and retreat to the previous frame.
501*7c478bd9Sstevel@tonic-gate */
502*7c478bd9Sstevel@tonic-gate if (end_of_group) {
503*7c478bd9Sstevel@tonic-gate if (--curr_frame < 0) {
504*7c478bd9Sstevel@tonic-gate break;
505*7c478bd9Sstevel@tonic-gate }
506*7c478bd9Sstevel@tonic-gate
507*7c478bd9Sstevel@tonic-gate exacct_order64(&estack[curr_frame].esf_size);
508*7c478bd9Sstevel@tonic-gate ea_cond_memcpy_at_offset(buf,
509*7c478bd9Sstevel@tonic-gate estack[curr_frame].esf_offset, bufsize,
510*7c478bd9Sstevel@tonic-gate &estack[curr_frame].esf_size, sizeof (ea_size_t));
511*7c478bd9Sstevel@tonic-gate exacct_order64(&estack[curr_frame].esf_size);
512*7c478bd9Sstevel@tonic-gate
513*7c478bd9Sstevel@tonic-gate /*
514*7c478bd9Sstevel@tonic-gate * Note that the large backskip is only 32 bits, whereas
515*7c478bd9Sstevel@tonic-gate * an object can be up to 2^64 bytes long. If an object
516*7c478bd9Sstevel@tonic-gate * is greater than 2^32 bytes long set the large
517*7c478bd9Sstevel@tonic-gate * backskip to 0. This will prevent the file being
518*7c478bd9Sstevel@tonic-gate * read backwards by causing EOF to be returned when the
519*7c478bd9Sstevel@tonic-gate * big object is encountered, but reading forwards will
520*7c478bd9Sstevel@tonic-gate * still be OK as it ignores the large backskip field.
521*7c478bd9Sstevel@tonic-gate */
522*7c478bd9Sstevel@tonic-gate estack[curr_frame].esf_bksize += sizeof (uint32_t);
523*7c478bd9Sstevel@tonic-gate
524*7c478bd9Sstevel@tonic-gate lge_backskip =
525*7c478bd9Sstevel@tonic-gate estack[curr_frame].esf_bksize > UINT_MAX
526*7c478bd9Sstevel@tonic-gate ? 0 : (uint32_t)estack[curr_frame].esf_bksize;
527*7c478bd9Sstevel@tonic-gate exacct_order32(&lge_backskip);
528*7c478bd9Sstevel@tonic-gate ea_cond_memcpy_at_offset(buf, curr_pos, bufsize,
529*7c478bd9Sstevel@tonic-gate &lge_backskip, sizeof (lge_backskip));
530*7c478bd9Sstevel@tonic-gate
531*7c478bd9Sstevel@tonic-gate curr_pos += sizeof (uint32_t);
532*7c478bd9Sstevel@tonic-gate incr_parent_frames(estack, curr_frame,
533*7c478bd9Sstevel@tonic-gate sizeof (uint32_t));
534*7c478bd9Sstevel@tonic-gate
535*7c478bd9Sstevel@tonic-gate if ((curr_obj = estack[curr_frame].esf_obj) != NULL) {
536*7c478bd9Sstevel@tonic-gate end_of_group = 0;
537*7c478bd9Sstevel@tonic-gate estack[curr_frame].esf_obj = NULL;
538*7c478bd9Sstevel@tonic-gate estack[curr_frame].esf_size = 0;
539*7c478bd9Sstevel@tonic-gate estack[curr_frame].esf_bksize = 0;
540*7c478bd9Sstevel@tonic-gate } else {
541*7c478bd9Sstevel@tonic-gate continue;
542*7c478bd9Sstevel@tonic-gate }
543*7c478bd9Sstevel@tonic-gate }
544*7c478bd9Sstevel@tonic-gate
545*7c478bd9Sstevel@tonic-gate /*
546*7c478bd9Sstevel@tonic-gate * 2. Write the catalog tag.
547*7c478bd9Sstevel@tonic-gate */
548*7c478bd9Sstevel@tonic-gate exacct_order32(&curr_obj->eo_catalog);
549*7c478bd9Sstevel@tonic-gate ea_cond_memcpy_at_offset(buf, curr_pos, bufsize,
550*7c478bd9Sstevel@tonic-gate &curr_obj->eo_catalog, sizeof (ea_catalog_t));
551*7c478bd9Sstevel@tonic-gate exacct_order32(&curr_obj->eo_catalog);
552*7c478bd9Sstevel@tonic-gate
553*7c478bd9Sstevel@tonic-gate incr_parent_frames(estack, curr_frame, sizeof (ea_catalog_t));
554*7c478bd9Sstevel@tonic-gate estack[curr_frame].esf_size -= sizeof (ea_catalog_t);
555*7c478bd9Sstevel@tonic-gate curr_pos += sizeof (ea_catalog_t);
556*7c478bd9Sstevel@tonic-gate estack[curr_frame].esf_offset = curr_pos;
557*7c478bd9Sstevel@tonic-gate
558*7c478bd9Sstevel@tonic-gate /*
559*7c478bd9Sstevel@tonic-gate * 2a. If this type is of variable size, reserve space for the
560*7c478bd9Sstevel@tonic-gate * size field.
561*7c478bd9Sstevel@tonic-gate */
562*7c478bd9Sstevel@tonic-gate switch (curr_obj->eo_catalog & EXT_TYPE_MASK) {
563*7c478bd9Sstevel@tonic-gate case EXT_GROUP:
564*7c478bd9Sstevel@tonic-gate case EXT_STRING:
565*7c478bd9Sstevel@tonic-gate case EXT_EXACCT_OBJECT:
566*7c478bd9Sstevel@tonic-gate case EXT_RAW:
567*7c478bd9Sstevel@tonic-gate exacct_order64(&placeholder);
568*7c478bd9Sstevel@tonic-gate ea_cond_memcpy_at_offset(buf, curr_pos, bufsize,
569*7c478bd9Sstevel@tonic-gate &placeholder, sizeof (ea_size_t));
570*7c478bd9Sstevel@tonic-gate exacct_order64(&placeholder);
571*7c478bd9Sstevel@tonic-gate
572*7c478bd9Sstevel@tonic-gate incr_parent_frames(estack, curr_frame,
573*7c478bd9Sstevel@tonic-gate sizeof (ea_size_t));
574*7c478bd9Sstevel@tonic-gate estack[curr_frame].esf_size -= sizeof (ea_size_t);
575*7c478bd9Sstevel@tonic-gate curr_pos += sizeof (ea_size_t);
576*7c478bd9Sstevel@tonic-gate break;
577*7c478bd9Sstevel@tonic-gate default:
578*7c478bd9Sstevel@tonic-gate break;
579*7c478bd9Sstevel@tonic-gate }
580*7c478bd9Sstevel@tonic-gate
581*7c478bd9Sstevel@tonic-gate if (curr_obj->eo_type == EO_GROUP) {
582*7c478bd9Sstevel@tonic-gate /*
583*7c478bd9Sstevel@tonic-gate * 3A. If it's a group put its next pointer, size, and
584*7c478bd9Sstevel@tonic-gate * size position on the stack, add 1 to the stack,
585*7c478bd9Sstevel@tonic-gate * set the current object to eg_objs, and goto 1.
586*7c478bd9Sstevel@tonic-gate */
587*7c478bd9Sstevel@tonic-gate estack[curr_frame].esf_obj = curr_obj->eo_next;
588*7c478bd9Sstevel@tonic-gate
589*7c478bd9Sstevel@tonic-gate /*
590*7c478bd9Sstevel@tonic-gate * 3Aa. Insert the number of objects in the group.
591*7c478bd9Sstevel@tonic-gate */
592*7c478bd9Sstevel@tonic-gate exacct_order32(&curr_obj->eo_group.eg_nobjs);
593*7c478bd9Sstevel@tonic-gate ea_cond_memcpy_at_offset(buf, curr_pos, bufsize,
594*7c478bd9Sstevel@tonic-gate &curr_obj->eo_group.eg_nobjs,
595*7c478bd9Sstevel@tonic-gate sizeof (uint32_t));
596*7c478bd9Sstevel@tonic-gate exacct_order32(&curr_obj->eo_group.eg_nobjs);
597*7c478bd9Sstevel@tonic-gate
598*7c478bd9Sstevel@tonic-gate incr_parent_frames(estack, curr_frame,
599*7c478bd9Sstevel@tonic-gate sizeof (uint32_t));
600*7c478bd9Sstevel@tonic-gate curr_pos += sizeof (uint32_t);
601*7c478bd9Sstevel@tonic-gate
602*7c478bd9Sstevel@tonic-gate /*
603*7c478bd9Sstevel@tonic-gate * 3Ab. Insert a backskip of the appropriate size.
604*7c478bd9Sstevel@tonic-gate */
605*7c478bd9Sstevel@tonic-gate ea_cond_memcpy_at_offset(buf, curr_pos, bufsize,
606*7c478bd9Sstevel@tonic-gate &gp_backskip, sizeof (uint32_t));
607*7c478bd9Sstevel@tonic-gate
608*7c478bd9Sstevel@tonic-gate incr_parent_frames(estack, curr_frame,
609*7c478bd9Sstevel@tonic-gate sizeof (uint32_t));
610*7c478bd9Sstevel@tonic-gate curr_pos += sizeof (uint32_t);
611*7c478bd9Sstevel@tonic-gate
612*7c478bd9Sstevel@tonic-gate curr_frame++;
613*7c478bd9Sstevel@tonic-gate
614*7c478bd9Sstevel@tonic-gate if (curr_frame >= neframes) {
615*7c478bd9Sstevel@tonic-gate /*
616*7c478bd9Sstevel@tonic-gate * Expand the eframe stack to handle the
617*7c478bd9Sstevel@tonic-gate * requested depth.
618*7c478bd9Sstevel@tonic-gate */
619*7c478bd9Sstevel@tonic-gate uint_t new_neframes = 2 * neframes;
620*7c478bd9Sstevel@tonic-gate struct es_frame *new_estack =
621*7c478bd9Sstevel@tonic-gate ea_alloc(new_neframes *
622*7c478bd9Sstevel@tonic-gate sizeof (struct es_frame));
623*7c478bd9Sstevel@tonic-gate if (new_estack == NULL) {
624*7c478bd9Sstevel@tonic-gate ea_free(estack, neframes *
625*7c478bd9Sstevel@tonic-gate sizeof (struct es_frame));
626*7c478bd9Sstevel@tonic-gate /* exacct_errno set above. */
627*7c478bd9Sstevel@tonic-gate return ((size_t)-1);
628*7c478bd9Sstevel@tonic-gate }
629*7c478bd9Sstevel@tonic-gate
630*7c478bd9Sstevel@tonic-gate bzero(new_estack, new_neframes *
631*7c478bd9Sstevel@tonic-gate sizeof (struct es_frame));
632*7c478bd9Sstevel@tonic-gate bcopy(estack, new_estack, neframes *
633*7c478bd9Sstevel@tonic-gate sizeof (struct es_frame));
634*7c478bd9Sstevel@tonic-gate
635*7c478bd9Sstevel@tonic-gate ea_free(estack, neframes *
636*7c478bd9Sstevel@tonic-gate sizeof (struct es_frame));
637*7c478bd9Sstevel@tonic-gate estack = new_estack;
638*7c478bd9Sstevel@tonic-gate neframes = new_neframes;
639*7c478bd9Sstevel@tonic-gate } else {
640*7c478bd9Sstevel@tonic-gate bzero(&estack[curr_frame],
641*7c478bd9Sstevel@tonic-gate sizeof (struct es_frame));
642*7c478bd9Sstevel@tonic-gate }
643*7c478bd9Sstevel@tonic-gate
644*7c478bd9Sstevel@tonic-gate estack[curr_frame].esf_offset = curr_pos;
645*7c478bd9Sstevel@tonic-gate if ((curr_obj = curr_obj->eo_group.eg_objs) == NULL) {
646*7c478bd9Sstevel@tonic-gate end_of_group = 1;
647*7c478bd9Sstevel@tonic-gate }
648*7c478bd9Sstevel@tonic-gate
649*7c478bd9Sstevel@tonic-gate continue;
650*7c478bd9Sstevel@tonic-gate }
651*7c478bd9Sstevel@tonic-gate
652*7c478bd9Sstevel@tonic-gate /*
653*7c478bd9Sstevel@tonic-gate * 3B. Otherwise we're considering an item: add its ei_size to
654*7c478bd9Sstevel@tonic-gate * all sizes on the stack, and copy its size into position.
655*7c478bd9Sstevel@tonic-gate */
656*7c478bd9Sstevel@tonic-gate switch (curr_obj->eo_catalog & EXT_TYPE_MASK) {
657*7c478bd9Sstevel@tonic-gate case EXT_UINT8:
658*7c478bd9Sstevel@tonic-gate src = &curr_obj->eo_item.ei_uint8;
659*7c478bd9Sstevel@tonic-gate size = sizeof (uint8_t);
660*7c478bd9Sstevel@tonic-gate break;
661*7c478bd9Sstevel@tonic-gate case EXT_UINT16:
662*7c478bd9Sstevel@tonic-gate src = &curr_obj->eo_item.ei_uint16;
663*7c478bd9Sstevel@tonic-gate size = sizeof (uint16_t);
664*7c478bd9Sstevel@tonic-gate exacct_order16(src);
665*7c478bd9Sstevel@tonic-gate break;
666*7c478bd9Sstevel@tonic-gate case EXT_UINT32:
667*7c478bd9Sstevel@tonic-gate src = &curr_obj->eo_item.ei_uint32;
668*7c478bd9Sstevel@tonic-gate size = sizeof (uint32_t);
669*7c478bd9Sstevel@tonic-gate exacct_order32(src);
670*7c478bd9Sstevel@tonic-gate break;
671*7c478bd9Sstevel@tonic-gate case EXT_UINT64:
672*7c478bd9Sstevel@tonic-gate src = &curr_obj->eo_item.ei_uint64;
673*7c478bd9Sstevel@tonic-gate size = sizeof (uint64_t);
674*7c478bd9Sstevel@tonic-gate exacct_order64(src);
675*7c478bd9Sstevel@tonic-gate break;
676*7c478bd9Sstevel@tonic-gate case EXT_DOUBLE:
677*7c478bd9Sstevel@tonic-gate src = &curr_obj->eo_item.ei_double;
678*7c478bd9Sstevel@tonic-gate size = sizeof (double);
679*7c478bd9Sstevel@tonic-gate exacct_order64((uint64_t *)src);
680*7c478bd9Sstevel@tonic-gate break;
681*7c478bd9Sstevel@tonic-gate case EXT_STRING:
682*7c478bd9Sstevel@tonic-gate src = curr_obj->eo_item.ei_string;
683*7c478bd9Sstevel@tonic-gate size = curr_obj->eo_item.ei_size;
684*7c478bd9Sstevel@tonic-gate break;
685*7c478bd9Sstevel@tonic-gate case EXT_EXACCT_OBJECT:
686*7c478bd9Sstevel@tonic-gate src = curr_obj->eo_item.ei_object;
687*7c478bd9Sstevel@tonic-gate size = curr_obj->eo_item.ei_size;
688*7c478bd9Sstevel@tonic-gate break;
689*7c478bd9Sstevel@tonic-gate case EXT_RAW:
690*7c478bd9Sstevel@tonic-gate src = curr_obj->eo_item.ei_raw;
691*7c478bd9Sstevel@tonic-gate size = curr_obj->eo_item.ei_size;
692*7c478bd9Sstevel@tonic-gate break;
693*7c478bd9Sstevel@tonic-gate case EXT_NONE:
694*7c478bd9Sstevel@tonic-gate default:
695*7c478bd9Sstevel@tonic-gate src = NULL;
696*7c478bd9Sstevel@tonic-gate size = 0;
697*7c478bd9Sstevel@tonic-gate break;
698*7c478bd9Sstevel@tonic-gate }
699*7c478bd9Sstevel@tonic-gate
700*7c478bd9Sstevel@tonic-gate ea_cond_memcpy_at_offset(buf, curr_pos, bufsize, src, size);
701*7c478bd9Sstevel@tonic-gate incr_parent_frames(estack, curr_frame, size);
702*7c478bd9Sstevel@tonic-gate curr_pos += size;
703*7c478bd9Sstevel@tonic-gate
704*7c478bd9Sstevel@tonic-gate /*
705*7c478bd9Sstevel@tonic-gate * 4. Write the large backskip amount into the buffer.
706*7c478bd9Sstevel@tonic-gate * See above for note about why this may be set to 0.
707*7c478bd9Sstevel@tonic-gate */
708*7c478bd9Sstevel@tonic-gate incr_parent_frames(estack, curr_frame, sizeof (uint32_t));
709*7c478bd9Sstevel@tonic-gate
710*7c478bd9Sstevel@tonic-gate lge_backskip = estack[curr_frame].esf_bksize > UINT_MAX
711*7c478bd9Sstevel@tonic-gate ? 0 : (uint32_t)estack[curr_frame].esf_bksize;
712*7c478bd9Sstevel@tonic-gate exacct_order32(&lge_backskip);
713*7c478bd9Sstevel@tonic-gate ea_cond_memcpy_at_offset(buf, curr_pos, bufsize,
714*7c478bd9Sstevel@tonic-gate &lge_backskip, sizeof (lge_backskip));
715*7c478bd9Sstevel@tonic-gate
716*7c478bd9Sstevel@tonic-gate curr_pos += sizeof (uint32_t);
717*7c478bd9Sstevel@tonic-gate
718*7c478bd9Sstevel@tonic-gate switch (curr_obj->eo_catalog & EXT_TYPE_MASK) {
719*7c478bd9Sstevel@tonic-gate case EXT_RAW:
720*7c478bd9Sstevel@tonic-gate case EXT_STRING:
721*7c478bd9Sstevel@tonic-gate case EXT_EXACCT_OBJECT:
722*7c478bd9Sstevel@tonic-gate exacct_order64(&estack[curr_frame].esf_size);
723*7c478bd9Sstevel@tonic-gate ea_cond_memcpy_at_offset(buf,
724*7c478bd9Sstevel@tonic-gate estack[curr_frame].esf_offset, bufsize,
725*7c478bd9Sstevel@tonic-gate &estack[curr_frame].esf_size, sizeof (ea_size_t));
726*7c478bd9Sstevel@tonic-gate exacct_order64(&estack[curr_frame].esf_size);
727*7c478bd9Sstevel@tonic-gate break;
728*7c478bd9Sstevel@tonic-gate case EXT_UINT16:
729*7c478bd9Sstevel@tonic-gate exacct_order16(src);
730*7c478bd9Sstevel@tonic-gate break;
731*7c478bd9Sstevel@tonic-gate case EXT_UINT32:
732*7c478bd9Sstevel@tonic-gate exacct_order32(src);
733*7c478bd9Sstevel@tonic-gate break;
734*7c478bd9Sstevel@tonic-gate case EXT_UINT64:
735*7c478bd9Sstevel@tonic-gate exacct_order64(src);
736*7c478bd9Sstevel@tonic-gate break;
737*7c478bd9Sstevel@tonic-gate case EXT_DOUBLE:
738*7c478bd9Sstevel@tonic-gate exacct_order64((uint64_t *)src);
739*7c478bd9Sstevel@tonic-gate break;
740*7c478bd9Sstevel@tonic-gate default:
741*7c478bd9Sstevel@tonic-gate break;
742*7c478bd9Sstevel@tonic-gate }
743*7c478bd9Sstevel@tonic-gate
744*7c478bd9Sstevel@tonic-gate /*
745*7c478bd9Sstevel@tonic-gate * 5. If ei_next is NULL, we are at the end of a group.a If
746*7c478bd9Sstevel@tonic-gate * not, move on to the next item on the list.
747*7c478bd9Sstevel@tonic-gate */
748*7c478bd9Sstevel@tonic-gate if (curr_obj->eo_next == NULL) {
749*7c478bd9Sstevel@tonic-gate end_of_group = 1;
750*7c478bd9Sstevel@tonic-gate } else {
751*7c478bd9Sstevel@tonic-gate curr_obj = curr_obj->eo_next;
752*7c478bd9Sstevel@tonic-gate estack[curr_frame].esf_obj = NULL;
753*7c478bd9Sstevel@tonic-gate estack[curr_frame].esf_size = 0;
754*7c478bd9Sstevel@tonic-gate estack[curr_frame].esf_bksize = 0;
755*7c478bd9Sstevel@tonic-gate }
756*7c478bd9Sstevel@tonic-gate }
757*7c478bd9Sstevel@tonic-gate
758*7c478bd9Sstevel@tonic-gate ea_free(estack, neframes * sizeof (struct es_frame));
759*7c478bd9Sstevel@tonic-gate EXACCT_SET_ERR(EXR_OK);
760*7c478bd9Sstevel@tonic-gate return (curr_pos);
761*7c478bd9Sstevel@tonic-gate }
762