xref: /onnv-gate/usr/src/cmd/fs.d/nfs/nfslog/buffer_list.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright (c) 1999 by Sun Microsystems, Inc.
24*0Sstevel@tonic-gate  * All rights reserved.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/types.h>
30*0Sstevel@tonic-gate #include <sys/stat.h>
31*0Sstevel@tonic-gate #include <errno.h>
32*0Sstevel@tonic-gate #include <syslog.h>
33*0Sstevel@tonic-gate #include <libintl.h>
34*0Sstevel@tonic-gate #include <unistd.h>
35*0Sstevel@tonic-gate #include <strings.h>
36*0Sstevel@tonic-gate #include <string.h>
37*0Sstevel@tonic-gate #include <assert.h>
38*0Sstevel@tonic-gate #include <stdlib.h>
39*0Sstevel@tonic-gate #include "nfslogd.h"
40*0Sstevel@tonic-gate #include "../lib/nfslogtab.h"
41*0Sstevel@tonic-gate #include "buffer_list.h"
42*0Sstevel@tonic-gate 
43*0Sstevel@tonic-gate static int buildbuffer_list(struct buffer_ent **, timestruc_t *);
44*0Sstevel@tonic-gate static void free_buffer_ent(struct buffer_ent *);
45*0Sstevel@tonic-gate static struct buffer_ent *findbuffer(struct buffer_ent *, char *);
46*0Sstevel@tonic-gate static void free_sharepnt_list(struct sharepnt_ent *);
47*0Sstevel@tonic-gate static void free_sharepnt_ent(struct sharepnt_ent *);
48*0Sstevel@tonic-gate #ifdef	DEBUG
49*0Sstevel@tonic-gate static void print_sharepnt_list(struct sharepnt_ent *);
50*0Sstevel@tonic-gate #endif
51*0Sstevel@tonic-gate static struct sharepnt_ent *findsharepnt(struct sharepnt_ent *, char *,
52*0Sstevel@tonic-gate 	struct sharepnt_ent **);
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate /*
55*0Sstevel@tonic-gate  * Builds the buffer list from NFSLOGTAB and returns it in *listpp.
56*0Sstevel@tonic-gate  * Returns 0 on success, non-zero error code otherwise.
57*0Sstevel@tonic-gate  */
58*0Sstevel@tonic-gate int
getbuffer_list(struct buffer_ent ** listpp,timestruc_t * lu)59*0Sstevel@tonic-gate getbuffer_list(struct buffer_ent **listpp, timestruc_t *lu)
60*0Sstevel@tonic-gate {
61*0Sstevel@tonic-gate 	*listpp = NULL;
62*0Sstevel@tonic-gate 	return (buildbuffer_list(listpp, lu));
63*0Sstevel@tonic-gate }
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate /*
66*0Sstevel@tonic-gate  * If NFSLOGTAB has not been modified since the last time we read it,
67*0Sstevel@tonic-gate  * it simply returns the same buffer list, otherwise it re-reads NFSLOGTAB
68*0Sstevel@tonic-gate  * and rebuilds the list.
69*0Sstevel@tonic-gate  * No NFSLOGTAB is not treated as an error.
70*0Sstevel@tonic-gate  * Returns 0 on success, non-zero error code otherwise
71*0Sstevel@tonic-gate  */
72*0Sstevel@tonic-gate int
checkbuffer_list(struct buffer_ent ** listpp,timestruc_t * lu)73*0Sstevel@tonic-gate checkbuffer_list(struct buffer_ent **listpp, timestruc_t *lu)
74*0Sstevel@tonic-gate {
75*0Sstevel@tonic-gate 	struct stat st;
76*0Sstevel@tonic-gate 	int error = 0;
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate 	if (stat(NFSLOGTAB, &st) == -1) {
79*0Sstevel@tonic-gate 		error = errno;
80*0Sstevel@tonic-gate 		if (error != ENOENT) {
81*0Sstevel@tonic-gate 			syslog(LOG_ERR, gettext("Can't stat %s - %s"),
82*0Sstevel@tonic-gate 				NFSLOGTAB, strerror(error));
83*0Sstevel@tonic-gate 			error = 0;
84*0Sstevel@tonic-gate 		}
85*0Sstevel@tonic-gate 		return (error);
86*0Sstevel@tonic-gate 	}
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate 	if (lu->tv_sec == st.st_mtim.tv_sec &&
89*0Sstevel@tonic-gate 	    lu->tv_nsec == st.st_mtim.tv_nsec)
90*0Sstevel@tonic-gate 		return (0);
91*0Sstevel@tonic-gate 
92*0Sstevel@tonic-gate 	free_buffer_list(listpp);	/* free existing list first */
93*0Sstevel@tonic-gate 	return (buildbuffer_list(listpp, lu));
94*0Sstevel@tonic-gate }
95*0Sstevel@tonic-gate 
96*0Sstevel@tonic-gate /*
97*0Sstevel@tonic-gate  * Does the actual work of reading NFSLOGTAB, and building the
98*0Sstevel@tonic-gate  * buffer list. If *be_head already contains entries, it will
99*0Sstevel@tonic-gate  * update the list with new information.
100*0Sstevel@tonic-gate  * Returns 0 on success, non-zero error code otherwise.
101*0Sstevel@tonic-gate  */
102*0Sstevel@tonic-gate static int
buildbuffer_list(struct buffer_ent ** be_head,timestruc_t * lu)103*0Sstevel@tonic-gate buildbuffer_list(struct buffer_ent **be_head, timestruc_t *lu)
104*0Sstevel@tonic-gate {
105*0Sstevel@tonic-gate 	FILE *fd;
106*0Sstevel@tonic-gate 	struct buffer_ent *be_tail = NULL, *bep;
107*0Sstevel@tonic-gate 	struct sharepnt_ent *se_tail = NULL, *sep;
108*0Sstevel@tonic-gate 	struct logtab_ent *lep;
109*0Sstevel@tonic-gate 	struct stat st;
110*0Sstevel@tonic-gate 	int error = 0, res;
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate 	if ((fd = fopen(NFSLOGTAB, "r+")) == NULL) {
113*0Sstevel@tonic-gate 		error = errno;
114*0Sstevel@tonic-gate 		if (error != ENOENT) {
115*0Sstevel@tonic-gate 			syslog(LOG_ERR, gettext("%s - %s\n"), NFSLOGTAB,
116*0Sstevel@tonic-gate 				strerror(error));
117*0Sstevel@tonic-gate 			error = 0;
118*0Sstevel@tonic-gate 		}
119*0Sstevel@tonic-gate 		return (error);
120*0Sstevel@tonic-gate 	}
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate 	if (lockf(fileno(fd), F_LOCK, 0L) < 0) {
123*0Sstevel@tonic-gate 		error = errno;
124*0Sstevel@tonic-gate 		syslog(LOG_ERR, gettext("cannot lock %s - %s\n"), NFSLOGTAB,
125*0Sstevel@tonic-gate 			strerror(error));
126*0Sstevel@tonic-gate 		(void) fclose(fd);
127*0Sstevel@tonic-gate 		return (error);
128*0Sstevel@tonic-gate 	}
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 	assert(*be_head == NULL);
131*0Sstevel@tonic-gate 	while ((res = logtab_getent(fd, &lep)) > 0) {
132*0Sstevel@tonic-gate 		if (bep = findbuffer(*be_head, lep->le_buffer)) {
133*0Sstevel@tonic-gate 			/*
134*0Sstevel@tonic-gate 			 * Add sharepnt to buffer list
135*0Sstevel@tonic-gate 			 */
136*0Sstevel@tonic-gate 			if (sep = findsharepnt(bep->be_sharepnt,
137*0Sstevel@tonic-gate 			    lep->le_path, &se_tail)) {
138*0Sstevel@tonic-gate 				/*
139*0Sstevel@tonic-gate 				 * Sharepoint already in list,
140*0Sstevel@tonic-gate 				 * update its state.
141*0Sstevel@tonic-gate 				 */
142*0Sstevel@tonic-gate 				sep->se_state = lep->le_state;
143*0Sstevel@tonic-gate 			} else {
144*0Sstevel@tonic-gate 				/*
145*0Sstevel@tonic-gate 				 * Need to add to sharepoint list
146*0Sstevel@tonic-gate 				 */
147*0Sstevel@tonic-gate 				sep = (struct sharepnt_ent *)
148*0Sstevel@tonic-gate 					malloc(sizeof (*sep));
149*0Sstevel@tonic-gate 				if (sep == NULL) {
150*0Sstevel@tonic-gate 					error = ENOMEM;
151*0Sstevel@tonic-gate 					goto errout;
152*0Sstevel@tonic-gate 				}
153*0Sstevel@tonic-gate 				(void) memset(sep, 0, sizeof (*sep));
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate 				sep->se_name = strdup(lep->le_path);
156*0Sstevel@tonic-gate 				if (sep->se_name == NULL) {
157*0Sstevel@tonic-gate 					error = ENOMEM;
158*0Sstevel@tonic-gate 					goto errout;
159*0Sstevel@tonic-gate 				}
160*0Sstevel@tonic-gate 				sep->se_state = lep->le_state;
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 				assert(se_tail != NULL);
163*0Sstevel@tonic-gate 				assert(se_tail->se_next == NULL);
164*0Sstevel@tonic-gate 				se_tail->se_next = sep;
165*0Sstevel@tonic-gate 			}
166*0Sstevel@tonic-gate 		} else {
167*0Sstevel@tonic-gate 			/*
168*0Sstevel@tonic-gate 			 * Add new buffer to list
169*0Sstevel@tonic-gate 			 */
170*0Sstevel@tonic-gate 			bep = (struct buffer_ent *)malloc(sizeof (*bep));
171*0Sstevel@tonic-gate 			if (bep == NULL) {
172*0Sstevel@tonic-gate 				error = ENOMEM;
173*0Sstevel@tonic-gate 				goto errout;
174*0Sstevel@tonic-gate 			}
175*0Sstevel@tonic-gate 			(void) memset(bep, 0, sizeof (*bep));
176*0Sstevel@tonic-gate 
177*0Sstevel@tonic-gate 			bep->be_name = strdup(lep->le_buffer);
178*0Sstevel@tonic-gate 			if (bep->be_name == NULL) {
179*0Sstevel@tonic-gate 				error = ENOMEM;
180*0Sstevel@tonic-gate 				goto errout;
181*0Sstevel@tonic-gate 			}
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 			if (*be_head == NULL)
184*0Sstevel@tonic-gate 				*be_head = bep;
185*0Sstevel@tonic-gate 			else
186*0Sstevel@tonic-gate 				be_tail->be_next = bep;
187*0Sstevel@tonic-gate 			be_tail = bep;
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate 			bep->be_sharepnt = (struct sharepnt_ent *)
190*0Sstevel@tonic-gate 				malloc(sizeof (*(bep->be_sharepnt)));
191*0Sstevel@tonic-gate 			(void) memset(bep->be_sharepnt, 0,
192*0Sstevel@tonic-gate 				sizeof (*(bep->be_sharepnt)));
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate 			if (bep->be_sharepnt == NULL) {
195*0Sstevel@tonic-gate 				error = ENOMEM;
196*0Sstevel@tonic-gate 				goto errout;
197*0Sstevel@tonic-gate 			}
198*0Sstevel@tonic-gate 			bep->be_sharepnt->se_name = strdup(lep->le_path);
199*0Sstevel@tonic-gate 			if (bep->be_sharepnt->se_name == NULL) {
200*0Sstevel@tonic-gate 				error = ENOMEM;
201*0Sstevel@tonic-gate 				goto errout;
202*0Sstevel@tonic-gate 			}
203*0Sstevel@tonic-gate 			bep->be_sharepnt->se_state = lep->le_state;
204*0Sstevel@tonic-gate 		}
205*0Sstevel@tonic-gate 	}
206*0Sstevel@tonic-gate 
207*0Sstevel@tonic-gate 	if (res < 0) {
208*0Sstevel@tonic-gate 		error = EIO;
209*0Sstevel@tonic-gate 		goto errout;
210*0Sstevel@tonic-gate 	}
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate 	/*
213*0Sstevel@tonic-gate 	 * Get modification time while we have the file locked.
214*0Sstevel@tonic-gate 	 */
215*0Sstevel@tonic-gate 	if (lu) {
216*0Sstevel@tonic-gate 		if ((error = fstat(fileno(fd), &st)) == -1) {
217*0Sstevel@tonic-gate 			syslog(LOG_ERR, gettext("Can't stat %s"), NFSLOGTAB);
218*0Sstevel@tonic-gate 			goto errout;
219*0Sstevel@tonic-gate 		}
220*0Sstevel@tonic-gate 		*lu = st.st_mtim;
221*0Sstevel@tonic-gate 	}
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate 	(void) fclose(fd);
224*0Sstevel@tonic-gate 	return (error);
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate errout:
227*0Sstevel@tonic-gate 	(void) fclose(fd);
228*0Sstevel@tonic-gate 	if (lep)
229*0Sstevel@tonic-gate 		logtab_ent_free(lep);
230*0Sstevel@tonic-gate 	free_buffer_list(be_head);
231*0Sstevel@tonic-gate 	assert(*be_head == NULL);
232*0Sstevel@tonic-gate 	syslog(LOG_ERR, gettext("cannot read %s: %s\n"), NFSLOGTAB,
233*0Sstevel@tonic-gate 		strerror(error));
234*0Sstevel@tonic-gate 
235*0Sstevel@tonic-gate 	return (error);
236*0Sstevel@tonic-gate }
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate /*
239*0Sstevel@tonic-gate  * Removes the entry from the buffer list and frees it.
240*0Sstevel@tonic-gate  */
241*0Sstevel@tonic-gate void
remove_buffer_ent(struct buffer_ent ** be_listpp,struct buffer_ent * bep)242*0Sstevel@tonic-gate remove_buffer_ent(struct buffer_ent **be_listpp, struct buffer_ent *bep)
243*0Sstevel@tonic-gate {
244*0Sstevel@tonic-gate 	struct buffer_ent *p, *prev;
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate 	for (p = prev = *be_listpp; p != NULL; p = p->be_next) {
247*0Sstevel@tonic-gate 		if (p == bep) {
248*0Sstevel@tonic-gate 			if (p == *be_listpp)
249*0Sstevel@tonic-gate 				*be_listpp = (*be_listpp)->be_next;
250*0Sstevel@tonic-gate 			else
251*0Sstevel@tonic-gate 				prev->be_next = bep->be_next;
252*0Sstevel@tonic-gate 			free_buffer_ent(bep);
253*0Sstevel@tonic-gate 			break;
254*0Sstevel@tonic-gate 		}
255*0Sstevel@tonic-gate 		prev = p;
256*0Sstevel@tonic-gate 	}
257*0Sstevel@tonic-gate }
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate /*
260*0Sstevel@tonic-gate  * Frees the buffer list.
261*0Sstevel@tonic-gate  */
262*0Sstevel@tonic-gate void
free_buffer_list(struct buffer_ent ** be_listpp)263*0Sstevel@tonic-gate free_buffer_list(struct buffer_ent **be_listpp)
264*0Sstevel@tonic-gate {
265*0Sstevel@tonic-gate 	struct buffer_ent *bep, *nextp;
266*0Sstevel@tonic-gate 
267*0Sstevel@tonic-gate 	for (bep = *be_listpp; bep != NULL; bep = nextp) {
268*0Sstevel@tonic-gate 		nextp = bep->be_next;
269*0Sstevel@tonic-gate 		free_buffer_ent(bep);
270*0Sstevel@tonic-gate 	}
271*0Sstevel@tonic-gate 	*be_listpp = NULL;
272*0Sstevel@tonic-gate }
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate static void
free_buffer_ent(struct buffer_ent * bep)275*0Sstevel@tonic-gate free_buffer_ent(struct buffer_ent *bep)
276*0Sstevel@tonic-gate {
277*0Sstevel@tonic-gate 	assert(bep != NULL);
278*0Sstevel@tonic-gate 	if (debug)
279*0Sstevel@tonic-gate 		(void) printf("freeing %s\n", bep->be_name);
280*0Sstevel@tonic-gate 	if (bep->be_name != NULL)
281*0Sstevel@tonic-gate 		free(bep->be_name);
282*0Sstevel@tonic-gate 	if (bep->be_sharepnt != NULL)
283*0Sstevel@tonic-gate 		free_sharepnt_list(bep->be_sharepnt);
284*0Sstevel@tonic-gate 	free(bep);
285*0Sstevel@tonic-gate }
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate static void
free_sharepnt_list(struct sharepnt_ent * sep_listp)288*0Sstevel@tonic-gate free_sharepnt_list(struct sharepnt_ent *sep_listp)
289*0Sstevel@tonic-gate {
290*0Sstevel@tonic-gate 	struct sharepnt_ent *nextp;
291*0Sstevel@tonic-gate 
292*0Sstevel@tonic-gate 	for (; sep_listp != NULL; sep_listp = nextp) {
293*0Sstevel@tonic-gate 		nextp = sep_listp->se_next;
294*0Sstevel@tonic-gate 		free_sharepnt_ent(sep_listp);
295*0Sstevel@tonic-gate 	}
296*0Sstevel@tonic-gate 	free(sep_listp);
297*0Sstevel@tonic-gate }
298*0Sstevel@tonic-gate 
299*0Sstevel@tonic-gate /*
300*0Sstevel@tonic-gate  * Removes the entry from the sharepnt list and frees it.
301*0Sstevel@tonic-gate  */
302*0Sstevel@tonic-gate void
remove_sharepnt_ent(struct sharepnt_ent ** se_listpp,struct sharepnt_ent * sep)303*0Sstevel@tonic-gate remove_sharepnt_ent(struct sharepnt_ent **se_listpp, struct sharepnt_ent *sep)
304*0Sstevel@tonic-gate {
305*0Sstevel@tonic-gate 	struct sharepnt_ent *p, *prev;
306*0Sstevel@tonic-gate 
307*0Sstevel@tonic-gate 	for (p = prev = *se_listpp; p != NULL; p = p->se_next) {
308*0Sstevel@tonic-gate 		if (p == sep) {
309*0Sstevel@tonic-gate 			if (p == *se_listpp)
310*0Sstevel@tonic-gate 				*se_listpp = (*se_listpp)->se_next;
311*0Sstevel@tonic-gate 			else
312*0Sstevel@tonic-gate 				prev->se_next = sep->se_next;
313*0Sstevel@tonic-gate 			free_sharepnt_ent(sep);
314*0Sstevel@tonic-gate 			break;
315*0Sstevel@tonic-gate 		}
316*0Sstevel@tonic-gate 		prev = p;
317*0Sstevel@tonic-gate 	}
318*0Sstevel@tonic-gate }
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate static void
free_sharepnt_ent(struct sharepnt_ent * sep)321*0Sstevel@tonic-gate free_sharepnt_ent(struct sharepnt_ent *sep)
322*0Sstevel@tonic-gate {
323*0Sstevel@tonic-gate 	assert(sep != NULL);
324*0Sstevel@tonic-gate 	if (debug)
325*0Sstevel@tonic-gate 		(void) printf("freeing %s\n", sep->se_name);
326*0Sstevel@tonic-gate 	if (sep->se_name != NULL)
327*0Sstevel@tonic-gate 		free(sep->se_name);
328*0Sstevel@tonic-gate 	free(sep);
329*0Sstevel@tonic-gate }
330*0Sstevel@tonic-gate 
331*0Sstevel@tonic-gate #ifdef DEBUG
332*0Sstevel@tonic-gate void
printbuffer_list(struct buffer_ent * bep)333*0Sstevel@tonic-gate printbuffer_list(struct buffer_ent *bep)
334*0Sstevel@tonic-gate {
335*0Sstevel@tonic-gate 	for (; bep != NULL; bep = bep->be_next) {
336*0Sstevel@tonic-gate 		(void) printf("%s\n", bep->be_name);
337*0Sstevel@tonic-gate 		if (bep->be_sharepnt != NULL)
338*0Sstevel@tonic-gate 			print_sharepnt_list(bep->be_sharepnt);
339*0Sstevel@tonic-gate 	}
340*0Sstevel@tonic-gate }
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate static void
print_sharepnt_list(struct sharepnt_ent * sep)343*0Sstevel@tonic-gate print_sharepnt_list(struct sharepnt_ent *sep)
344*0Sstevel@tonic-gate {
345*0Sstevel@tonic-gate 	for (; sep != NULL; sep = sep->se_next)
346*0Sstevel@tonic-gate 		(void) printf("\t(%d) %s\n", sep->se_state, sep->se_name);
347*0Sstevel@tonic-gate }
348*0Sstevel@tonic-gate #endif
349*0Sstevel@tonic-gate 
350*0Sstevel@tonic-gate /*
351*0Sstevel@tonic-gate  * Returns a pointer to the buffer matching 'name', NULL otherwise.
352*0Sstevel@tonic-gate  */
353*0Sstevel@tonic-gate static struct buffer_ent *
findbuffer(struct buffer_ent * bep,char * name)354*0Sstevel@tonic-gate findbuffer(struct buffer_ent *bep, char *name)
355*0Sstevel@tonic-gate {
356*0Sstevel@tonic-gate 	for (; bep != NULL; bep = bep->be_next) {
357*0Sstevel@tonic-gate 		if (strcmp(bep->be_name, name) == 0)
358*0Sstevel@tonic-gate 			return (bep);
359*0Sstevel@tonic-gate 	}
360*0Sstevel@tonic-gate 	return (NULL);
361*0Sstevel@tonic-gate }
362*0Sstevel@tonic-gate 
363*0Sstevel@tonic-gate /*
364*0Sstevel@tonic-gate  * Returns a pointer the sharepoint entry matching 'name'.
365*0Sstevel@tonic-gate  * Otherwise, it sets '*se_tail' to the last element of the list
366*0Sstevel@tonic-gate  * to make insertion of new element easier, and returns NULL.
367*0Sstevel@tonic-gate  */
368*0Sstevel@tonic-gate static struct sharepnt_ent *
findsharepnt(struct sharepnt_ent * sep,char * name,struct sharepnt_ent ** se_tail)369*0Sstevel@tonic-gate findsharepnt(
370*0Sstevel@tonic-gate 	struct sharepnt_ent *sep,
371*0Sstevel@tonic-gate 	char *name,
372*0Sstevel@tonic-gate 	struct sharepnt_ent **se_tail)
373*0Sstevel@tonic-gate {
374*0Sstevel@tonic-gate 	struct sharepnt_ent *tail;
375*0Sstevel@tonic-gate 
376*0Sstevel@tonic-gate 	for (; sep != NULL; sep = sep->se_next) {
377*0Sstevel@tonic-gate 		if (strcmp(sep->se_name, name) == 0)
378*0Sstevel@tonic-gate 			return (sep);
379*0Sstevel@tonic-gate 		tail = sep;
380*0Sstevel@tonic-gate 	}
381*0Sstevel@tonic-gate 	*se_tail = tail;
382*0Sstevel@tonic-gate 	return (NULL);
383*0Sstevel@tonic-gate }
384