1168754Sbushman/*-
2168754Sbushman * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
3251867Seadler * All rights reserved.
4168754Sbushman *
5168754Sbushman * Redistribution and use in source and binary forms, with or without
6168754Sbushman * modification, are permitted provided that the following conditions
7168754Sbushman * are met:
8168754Sbushman * 1. Redistributions of source code must retain the above copyright
9168754Sbushman *    notice, this list of conditions and the following disclaimer.
10168754Sbushman * 2. Redistributions in binary form must reproduce the above copyright
11168754Sbushman *    notice, this list of conditions and the following disclaimer in the
12168754Sbushman *    documentation and/or other materials provided with the distribution.
13168754Sbushman *
14168754Sbushman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15168754Sbushman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16168754Sbushman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17168754Sbushman * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18168754Sbushman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19168754Sbushman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20168754Sbushman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21168754Sbushman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22168754Sbushman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23168754Sbushman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24168754Sbushman * SUCH DAMAGE.
25168754Sbushman *
26168754Sbushman */
27168754Sbushman
28168754Sbushman#include <sys/cdefs.h>
29168754Sbushman__FBSDID("$FreeBSD$");
30168754Sbushman
31168754Sbushman#include <arpa/inet.h>
32168754Sbushman#include <assert.h>
33168754Sbushman#include <errno.h>
34168754Sbushman#include <grp.h>
35168754Sbushman#include <stdio.h>
36168754Sbushman#include <stdlib.h>
37168754Sbushman#include <string.h>
38168754Sbushman#include <stringlist.h>
39168754Sbushman#include <unistd.h>
40168754Sbushman#include "testutil.h"
41168754Sbushman
42168754Sbushmanenum test_methods {
43168754Sbushman	TEST_GETGRENT,
44168754Sbushman	TEST_GETGRNAM,
45168754Sbushman	TEST_GETGRGID,
46168754Sbushman	TEST_GETGRENT_2PASS,
47168754Sbushman	TEST_BUILD_SNAPSHOT
48168754Sbushman};
49168754Sbushman
50168754Sbushmanstatic int debug = 0;
51168754Sbushmanstatic enum test_methods method = TEST_BUILD_SNAPSHOT;
52168754Sbushman
53168754SbushmanDECLARE_TEST_DATA(group)
54168754SbushmanDECLARE_TEST_FILE_SNAPSHOT(group)
55168754SbushmanDECLARE_1PASS_TEST(group)
56168754SbushmanDECLARE_2PASS_TEST(group)
57168754Sbushman
58168754Sbushmanstatic void clone_group(struct group *, struct group const *);
59168754Sbushmanstatic int compare_group(struct group *, struct group *, void *);
60168754Sbushmanstatic void dump_group(struct group *);
61168754Sbushmanstatic void free_group(struct group *);
62168754Sbushman
63168754Sbushmanstatic void sdump_group(struct group *, char *, size_t);
64168754Sbushmanstatic int group_read_snapshot_func(struct group *, char *);
65168754Sbushman
66168754Sbushmanstatic int group_check_ambiguity(struct group_test_data *,
67168754Sbushman	struct group *);
68168754Sbushmanstatic int group_fill_test_data(struct group_test_data *);
69168754Sbushmanstatic int group_test_correctness(struct group *, void *);
70168754Sbushmanstatic int group_test_getgrnam(struct group *, void *);
71168754Sbushmanstatic int group_test_getgrgid(struct group *, void *);
72168754Sbushmanstatic int group_test_getgrent(struct group *, void *);
73168754Sbushman
74168754Sbushmanstatic void usage(void)  __attribute__((__noreturn__));
75168754Sbushman
76168754SbushmanIMPLEMENT_TEST_DATA(group)
77168754SbushmanIMPLEMENT_TEST_FILE_SNAPSHOT(group)
78168754SbushmanIMPLEMENT_1PASS_TEST(group)
79168754SbushmanIMPLEMENT_2PASS_TEST(group)
80168754Sbushman
81168754Sbushmanstatic void
82168754Sbushmanclone_group(struct group *dest, struct group const *src)
83168754Sbushman{
84168754Sbushman	assert(dest != NULL);
85168754Sbushman	assert(src != NULL);
86168754Sbushman
87168754Sbushman	char **cp;
88168754Sbushman	int members_num;
89168754Sbushman
90168754Sbushman	memset(dest, 0, sizeof(struct group));
91168754Sbushman
92168754Sbushman	if (src->gr_name != NULL) {
93168754Sbushman		dest->gr_name = strdup(src->gr_name);
94168754Sbushman		assert(dest->gr_name != NULL);
95168754Sbushman	}
96168754Sbushman
97168754Sbushman	if (src->gr_passwd != NULL) {
98168754Sbushman		dest->gr_passwd = strdup(src->gr_passwd);
99168754Sbushman		assert(dest->gr_passwd != NULL);
100168754Sbushman	}
101168754Sbushman	dest->gr_gid = src->gr_gid;
102168754Sbushman
103168754Sbushman	if (src->gr_mem != NULL) {
104168754Sbushman		members_num = 0;
105168754Sbushman		for (cp = src->gr_mem; *cp; ++cp)
106168754Sbushman			++members_num;
107168754Sbushman
108168754Sbushman		dest->gr_mem = (char **)malloc(
109168754Sbushman			(members_num + 1) * (sizeof(char *)));
110168754Sbushman		assert(dest->gr_mem != NULL);
111168754Sbushman		memset(dest->gr_mem, 0, (members_num+1) * (sizeof(char *)));
112168754Sbushman
113168754Sbushman		for (cp = src->gr_mem; *cp; ++cp) {
114168754Sbushman			dest->gr_mem[cp - src->gr_mem] = strdup(*cp);
115168754Sbushman			assert(dest->gr_mem[cp - src->gr_mem] != NULL);
116168754Sbushman		}
117168754Sbushman	}
118168754Sbushman}
119168754Sbushman
120168754Sbushmanstatic void
121168754Sbushmanfree_group(struct group *grp)
122168754Sbushman{
123168754Sbushman	char **cp;
124168754Sbushman
125168754Sbushman	assert(grp != NULL);
126168754Sbushman
127168754Sbushman	free(grp->gr_name);
128168754Sbushman	free(grp->gr_passwd);
129168754Sbushman
130168754Sbushman	for (cp = grp->gr_mem; *cp; ++cp)
131168754Sbushman		free(*cp);
132168754Sbushman	free(grp->gr_mem);
133168754Sbushman}
134168754Sbushman
135168754Sbushmanstatic  int
136168754Sbushmancompare_group(struct group *grp1, struct group *grp2, void *mdata)
137168754Sbushman{
138168754Sbushman	char **c1, **c2;
139168754Sbushman
140168754Sbushman	if (grp1 == grp2)
141168754Sbushman		return (0);
142168754Sbushman
143168754Sbushman	if ((grp1 == NULL) || (grp2 == NULL))
144168754Sbushman		goto errfin;
145168754Sbushman
146168754Sbushman	if ((strcmp(grp1->gr_name, grp2->gr_name) != 0) ||
147168754Sbushman		(strcmp(grp1->gr_passwd, grp2->gr_passwd) != 0) ||
148168754Sbushman		(grp1->gr_gid != grp2->gr_gid))
149168754Sbushman			goto errfin;
150168754Sbushman
151168754Sbushman	c1 = grp1->gr_mem;
152168754Sbushman	c2 = grp2->gr_mem;
153168754Sbushman
154168754Sbushman	if ((grp1->gr_mem == NULL) || (grp2->gr_mem == NULL))
155168754Sbushman		goto errfin;
156168754Sbushman
157168754Sbushman	for (;*c1 && *c2; ++c1, ++c2)
158168754Sbushman		if (strcmp(*c1, *c2) != 0)
159168754Sbushman			goto errfin;
160168754Sbushman
161168754Sbushman	if ((*c1 != '\0') || (*c2 != '\0'))
162168754Sbushman		goto errfin;
163168754Sbushman
164168754Sbushman	return 0;
165168754Sbushman
166168754Sbushmanerrfin:
167168754Sbushman	if ((debug) && (mdata == NULL)) {
168168754Sbushman		printf("following structures are not equal:\n");
169168754Sbushman		dump_group(grp1);
170168754Sbushman		dump_group(grp2);
171168754Sbushman	}
172168754Sbushman
173168754Sbushman	return (-1);
174168754Sbushman}
175168754Sbushman
176168754Sbushmanstatic void
177168754Sbushmansdump_group(struct group *grp, char *buffer, size_t buflen)
178168754Sbushman{
179168754Sbushman	char **cp;
180168754Sbushman	int written;
181168754Sbushman
182168754Sbushman	written = snprintf(buffer, buflen, "%s %s %d",
183168754Sbushman		grp->gr_name, grp->gr_passwd, grp->gr_gid);
184168754Sbushman	buffer += written;
185168754Sbushman	if (written > buflen)
186168754Sbushman		return;
187168754Sbushman	buflen -= written;
188168754Sbushman
189168754Sbushman	if (grp->gr_mem != NULL) {
190168754Sbushman		if (*(grp->gr_mem) != '\0') {
191168754Sbushman			for (cp = grp->gr_mem; *cp; ++cp) {
192168754Sbushman				written = snprintf(buffer, buflen, " %s",*cp);
193168754Sbushman				buffer += written;
194168754Sbushman				if (written > buflen)
195168754Sbushman					return;
196168754Sbushman				buflen -= written;
197168754Sbushman
198168754Sbushman				if (buflen == 0)
199168754Sbushman					return;
200168754Sbushman			}
201168754Sbushman		} else
202168754Sbushman			snprintf(buffer, buflen, " nomem");
203168754Sbushman	} else
204168754Sbushman		snprintf(buffer, buflen, " (null)");
205168754Sbushman}
206168754Sbushman
207168754Sbushmanstatic int
208168754Sbushmangroup_read_snapshot_func(struct group *grp, char *line)
209168754Sbushman{
210168754Sbushman	StringList *sl;
211168754Sbushman	char *s, *ps, *ts;
212168754Sbushman	int i;
213168754Sbushman
214168754Sbushman	if (debug)
215168754Sbushman		printf("1 line read from snapshot:\n%s\n", line);
216168754Sbushman
217168754Sbushman	i = 0;
218168754Sbushman	sl = NULL;
219168754Sbushman	ps = line;
220168754Sbushman	memset(grp, 0, sizeof(struct group));
221168754Sbushman	while ( (s = strsep(&ps, " ")) != NULL) {
222168754Sbushman		switch (i) {
223168754Sbushman			case 0:
224168754Sbushman				grp->gr_name = strdup(s);
225168754Sbushman				assert(grp->gr_name != NULL);
226168754Sbushman			break;
227168754Sbushman
228168754Sbushman			case 1:
229168754Sbushman				grp->gr_passwd = strdup(s);
230168754Sbushman				assert(grp->gr_passwd != NULL);
231168754Sbushman			break;
232168754Sbushman
233168754Sbushman			case 2:
234168754Sbushman				grp->gr_gid = (gid_t)strtol(s, &ts, 10);
235168754Sbushman				if (*ts != '\0') {
236168754Sbushman					free(grp->gr_name);
237168754Sbushman					free(grp->gr_passwd);
238168754Sbushman					return (-1);
239168754Sbushman				}
240168754Sbushman			break;
241168754Sbushman
242168754Sbushman			default:
243168754Sbushman				if (sl == NULL) {
244168754Sbushman					if (strcmp(s, "(null)") == 0)
245168754Sbushman						return (0);
246168754Sbushman
247168754Sbushman					sl = sl_init();
248168754Sbushman					assert(sl != NULL);
249168754Sbushman
250168754Sbushman					if (strcmp(s, "nomem") != 0) {
251168754Sbushman						ts = strdup(s);
252168754Sbushman						assert(ts != NULL);
253168754Sbushman						sl_add(sl, ts);
254168754Sbushman					}
255168754Sbushman				} else {
256168754Sbushman					ts = strdup(s);
257168754Sbushman					assert(ts != NULL);
258168754Sbushman					sl_add(sl, ts);
259168754Sbushman				}
260168754Sbushman			break;
261168754Sbushman		};
262168754Sbushman		++i;
263168754Sbushman	}
264168754Sbushman
265168754Sbushman	if (i < 3) {
266168754Sbushman		free(grp->gr_name);
267168754Sbushman		free(grp->gr_passwd);
268168754Sbushman		memset(grp, 0, sizeof(struct group));
269168754Sbushman		return (-1);
270168754Sbushman	}
271168754Sbushman
272168754Sbushman	sl_add(sl, NULL);
273168754Sbushman	grp->gr_mem = sl->sl_str;
274168754Sbushman
275168754Sbushman	/* NOTE: is it a dirty hack or not? */
276168754Sbushman	free(sl);
277168754Sbushman	return (0);
278168754Sbushman}
279168754Sbushman
280168754Sbushmanstatic void
281168754Sbushmandump_group(struct group *result)
282168754Sbushman{
283168754Sbushman	if (result != NULL) {
284168754Sbushman		char buffer[1024];
285168754Sbushman		sdump_group(result, buffer, sizeof(buffer));
286168754Sbushman		printf("%s\n", buffer);
287168754Sbushman	} else
288168754Sbushman		printf("(null)\n");
289168754Sbushman}
290168754Sbushman
291168754Sbushmanstatic int
292168754Sbushmangroup_fill_test_data(struct group_test_data *td)
293168754Sbushman{
294168754Sbushman	struct group *grp;
295168754Sbushman
296168754Sbushman	setgroupent(1);
297168754Sbushman	while ((grp = getgrent()) != NULL) {
298168754Sbushman		if (group_test_correctness(grp, NULL) == 0)
299168754Sbushman			TEST_DATA_APPEND(group, td, grp);
300168754Sbushman		else
301168754Sbushman			return (-1);
302168754Sbushman	}
303168754Sbushman	endgrent();
304168754Sbushman
305168754Sbushman	return (0);
306168754Sbushman}
307168754Sbushman
308168754Sbushmanstatic int
309168754Sbushmangroup_test_correctness(struct group *grp, void *mdata)
310168754Sbushman{
311168754Sbushman	if (debug) {
312168754Sbushman		printf("testing correctness with the following data:\n");
313168754Sbushman		dump_group(grp);
314168754Sbushman	}
315168754Sbushman
316168754Sbushman	if (grp == NULL)
317168754Sbushman		goto errfin;
318168754Sbushman
319168754Sbushman	if (grp->gr_name == NULL)
320168754Sbushman		goto errfin;
321168754Sbushman
322168754Sbushman	if (grp->gr_passwd == NULL)
323168754Sbushman		goto errfin;
324168754Sbushman
325168754Sbushman	if (grp->gr_mem == NULL)
326168754Sbushman		goto errfin;
327168754Sbushman
328168754Sbushman	if (debug)
329168754Sbushman		printf("correct\n");
330168754Sbushman
331168754Sbushman	return (0);
332168754Sbushmanerrfin:
333168754Sbushman	if (debug)
334168754Sbushman		printf("incorrect\n");
335168754Sbushman
336168754Sbushman	return (-1);
337168754Sbushman}
338168754Sbushman
339168754Sbushman/* group_check_ambiguity() is needed here because when doing the getgrent()
340168754Sbushman * calls sequence, records from different nsswitch sources can be different,
341168754Sbushman * though having the same pw_name/pw_uid */
342168754Sbushmanstatic int
343168754Sbushmangroup_check_ambiguity(struct group_test_data *td, struct group *pwd)
344168754Sbushman{
345168754Sbushman
346168754Sbushman	return (TEST_DATA_FIND(group, td, pwd, compare_group,
347168754Sbushman		NULL) != NULL ? 0 : -1);
348168754Sbushman}
349168754Sbushman
350168754Sbushmanstatic int
351168754Sbushmangroup_test_getgrnam(struct group *grp_model, void *mdata)
352168754Sbushman{
353168754Sbushman	struct group *grp;
354168754Sbushman
355168754Sbushman	if (debug) {
356168754Sbushman		printf("testing getgrnam() with the following data:\n");
357168754Sbushman		dump_group(grp_model);
358168754Sbushman	}
359168754Sbushman
360168754Sbushman	grp = getgrnam(grp_model->gr_name);
361168754Sbushman	if (group_test_correctness(grp, NULL) != 0)
362168754Sbushman		goto errfin;
363168754Sbushman
364168754Sbushman	if ((compare_group(grp, grp_model, NULL) != 0) &&
365168754Sbushman	    (group_check_ambiguity((struct group_test_data *)mdata, grp)
366168754Sbushman	    !=0))
367168754Sbushman	    goto errfin;
368168754Sbushman
369168754Sbushman	if (debug)
370168754Sbushman		printf("ok\n");
371168754Sbushman	return (0);
372168754Sbushman
373168754Sbushmanerrfin:
374168754Sbushman	if (debug)
375168754Sbushman		printf("not ok\n");
376168754Sbushman
377168754Sbushman	return (-1);
378168754Sbushman}
379168754Sbushman
380168754Sbushmanstatic int
381168754Sbushmangroup_test_getgrgid(struct group *grp_model, void *mdata)
382168754Sbushman{
383168754Sbushman	struct group *grp;
384168754Sbushman
385168754Sbushman	if (debug) {
386168754Sbushman		printf("testing getgrgid() with the following data...\n");
387168754Sbushman		dump_group(grp_model);
388168754Sbushman	}
389168754Sbushman
390168754Sbushman	grp = getgrgid(grp_model->gr_gid);
391168754Sbushman	if ((group_test_correctness(grp, NULL) != 0) ||
392168754Sbushman	    ((compare_group(grp, grp_model, NULL) != 0) &&
393168754Sbushman	    (group_check_ambiguity((struct group_test_data *)mdata, grp)
394168754Sbushman	    != 0))) {
395168754Sbushman	    if (debug)
396168754Sbushman		printf("not ok\n");
397168754Sbushman	    return (-1);
398168754Sbushman	} else {
399168754Sbushman	    if (debug)
400168754Sbushman		printf("ok\n");
401168754Sbushman	    return (0);
402168754Sbushman	}
403168754Sbushman}
404168754Sbushman
405168754Sbushmanstatic int
406168754Sbushmangroup_test_getgrent(struct group *grp, void *mdata)
407168754Sbushman{
408168754Sbushman	/* Only correctness can be checked when doing 1-pass test for
409168754Sbushman	 * getgrent(). */
410168754Sbushman	return (group_test_correctness(grp, NULL));
411168754Sbushman}
412168754Sbushman
413168754Sbushmanstatic void
414168754Sbushmanusage(void)
415168754Sbushman{
416168754Sbushman	(void)fprintf(stderr,
417168754Sbushman	    "Usage: %s -nge2 [-d] [-s <file>]\n",
418168754Sbushman	    getprogname());
419168754Sbushman	exit(1);
420168754Sbushman}
421168754Sbushman
422168754Sbushmanint
423168754Sbushmanmain(int argc, char **argv)
424168754Sbushman{
425168754Sbushman	struct group_test_data td, td_snap, td_2pass;
426168754Sbushman	char *snapshot_file;
427168754Sbushman	int rv;
428168754Sbushman	int c;
429168754Sbushman
430168754Sbushman	if (argc < 2)
431168754Sbushman		usage();
432168754Sbushman
433168754Sbushman	snapshot_file = NULL;
434168754Sbushman	while ((c = getopt(argc, argv, "nge2ds:")) != -1)
435168754Sbushman		switch (c) {
436168754Sbushman		case 'd':
437168754Sbushman			debug++;
438168754Sbushman			break;
439168754Sbushman		case 'n':
440168754Sbushman			method = TEST_GETGRNAM;
441168754Sbushman			break;
442168754Sbushman		case 'g':
443168754Sbushman			method = TEST_GETGRGID;
444168754Sbushman			break;
445168754Sbushman		case 'e':
446168754Sbushman			method = TEST_GETGRENT;
447168754Sbushman			break;
448168754Sbushman		case '2':
449168754Sbushman			method = TEST_GETGRENT_2PASS;
450168754Sbushman			break;
451168754Sbushman		case 's':
452168754Sbushman			snapshot_file = strdup(optarg);
453168754Sbushman			break;
454168754Sbushman		default:
455168754Sbushman			usage();
456168754Sbushman		}
457168754Sbushman
458168754Sbushman	TEST_DATA_INIT(group, &td, clone_group, free_group);
459168754Sbushman	TEST_DATA_INIT(group, &td_snap, clone_group, free_group);
460168754Sbushman	if (snapshot_file != NULL) {
461168754Sbushman		if (access(snapshot_file, W_OK | R_OK) != 0) {
462168754Sbushman			if (errno == ENOENT)
463168754Sbushman				method = TEST_BUILD_SNAPSHOT;
464168754Sbushman			else {
465168754Sbushman				if (debug)
466168754Sbushman					printf("can't access the file %s\n",
467168754Sbushman				snapshot_file);
468168754Sbushman
469168754Sbushman				rv = -1;
470168754Sbushman				goto fin;
471168754Sbushman			}
472168754Sbushman		} else {
473168754Sbushman			if (method == TEST_BUILD_SNAPSHOT) {
474168754Sbushman				rv = 0;
475168754Sbushman				goto fin;
476168754Sbushman			}
477168754Sbushman
478168754Sbushman			TEST_SNAPSHOT_FILE_READ(group, snapshot_file,
479168754Sbushman				&td_snap, group_read_snapshot_func);
480168754Sbushman		}
481168754Sbushman	}
482168754Sbushman
483168754Sbushman	rv = group_fill_test_data(&td);
484168754Sbushman	if (rv == -1)
485168754Sbushman		return (-1);
486168754Sbushman	switch (method) {
487168754Sbushman	case TEST_GETGRNAM:
488168754Sbushman		if (snapshot_file == NULL)
489168754Sbushman			rv = DO_1PASS_TEST(group, &td,
490168754Sbushman				group_test_getgrnam, (void *)&td);
491168754Sbushman		else
492168754Sbushman			rv = DO_1PASS_TEST(group, &td_snap,
493168754Sbushman				group_test_getgrnam, (void *)&td_snap);
494168754Sbushman		break;
495168754Sbushman	case TEST_GETGRGID:
496168754Sbushman		if (snapshot_file == NULL)
497168754Sbushman			rv = DO_1PASS_TEST(group, &td,
498168754Sbushman				group_test_getgrgid, (void *)&td);
499168754Sbushman		else
500168754Sbushman			rv = DO_1PASS_TEST(group, &td_snap,
501168754Sbushman				group_test_getgrgid, (void *)&td_snap);
502168754Sbushman		break;
503168754Sbushman	case TEST_GETGRENT:
504168754Sbushman		if (snapshot_file == NULL)
505168754Sbushman			rv = DO_1PASS_TEST(group, &td, group_test_getgrent,
506168754Sbushman				(void *)&td);
507168754Sbushman		else
508168754Sbushman			rv = DO_2PASS_TEST(group, &td, &td_snap,
509168754Sbushman				compare_group, NULL);
510168754Sbushman		break;
511168754Sbushman	case TEST_GETGRENT_2PASS:
512168754Sbushman			TEST_DATA_INIT(group, &td_2pass, clone_group, free_group);
513168754Sbushman			rv = group_fill_test_data(&td_2pass);
514168754Sbushman			if (rv != -1)
515168754Sbushman				rv = DO_2PASS_TEST(group, &td, &td_2pass,
516168754Sbushman					compare_group, NULL);
517168754Sbushman			TEST_DATA_DESTROY(group, &td_2pass);
518168754Sbushman		break;
519168754Sbushman	case TEST_BUILD_SNAPSHOT:
520168754Sbushman		if (snapshot_file != NULL)
521168754Sbushman		    rv = TEST_SNAPSHOT_FILE_WRITE(group, snapshot_file, &td,
522168754Sbushman			sdump_group);
523168754Sbushman		break;
524168754Sbushman	default:
525168754Sbushman		rv = 0;
526168754Sbushman		break;
527168754Sbushman	};
528168754Sbushman
529168754Sbushmanfin:
530168754Sbushman	TEST_DATA_DESTROY(group, &td_snap);
531168754Sbushman	TEST_DATA_DESTROY(group, &td);
532168754Sbushman	free(snapshot_file);
533168754Sbushman	return (rv);
534168754Sbushman}
535