xref: /onnv-gate/usr/src/lib/libc/port/gen/getmntent.c (revision 10910:951a65b3846b)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
54830Skeerthi  * Common Development and Distribution License (the "License").
64830Skeerthi  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
214830Skeerthi 
220Sstevel@tonic-gate /*
23*10910SRobert.Harris@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
306812Sraf #include "lint.h"
310Sstevel@tonic-gate #include <mtlib.h>
320Sstevel@tonic-gate #include <stdio.h>
330Sstevel@tonic-gate #include <sys/types.h>
340Sstevel@tonic-gate #include <sys/stat.h>
350Sstevel@tonic-gate #include <sys/mnttab.h>
360Sstevel@tonic-gate #include <sys/mntio.h>
370Sstevel@tonic-gate #include <string.h>
380Sstevel@tonic-gate #include <ctype.h>
390Sstevel@tonic-gate #include <errno.h>
400Sstevel@tonic-gate #include <stdlib.h>
410Sstevel@tonic-gate #include <thread.h>
420Sstevel@tonic-gate #include <synch.h>
430Sstevel@tonic-gate #include <libc.h>
440Sstevel@tonic-gate #include <unistd.h>
450Sstevel@tonic-gate #include "tsd.h"
46*10910SRobert.Harris@Sun.COM #include <atomic.h>
47*10910SRobert.Harris@Sun.COM #include <strings.h>
480Sstevel@tonic-gate 
490Sstevel@tonic-gate static int getmntent_compat(FILE *fp, struct mnttab *mp);
500Sstevel@tonic-gate 
510Sstevel@tonic-gate #define	GETTOK_R(xx, ll, tmp)\
520Sstevel@tonic-gate 	if ((mp->xx = (char *)strtok_r(ll, sepstr, tmp)) == NULL)\
530Sstevel@tonic-gate 		return (MNT_TOOFEW);\
540Sstevel@tonic-gate 	if (strcmp(mp->xx, dash) == 0)\
550Sstevel@tonic-gate 		mp->xx = NULL
560Sstevel@tonic-gate 
570Sstevel@tonic-gate #define	DIFF(xx)\
580Sstevel@tonic-gate 	(mrefp->xx != NULL && (mgetp->xx == NULL ||\
590Sstevel@tonic-gate 	    strcmp(mrefp->xx, mgetp->xx) != 0))
600Sstevel@tonic-gate 
610Sstevel@tonic-gate #define	SDIFF(xx, typem, typer)\
620Sstevel@tonic-gate 	((mgetp->xx == NULL) || (stat64(mgetp->xx, &statb) == -1) ||\
630Sstevel@tonic-gate 	((statb.st_mode & S_IFMT) != typem) ||\
640Sstevel@tonic-gate 	    (statb.st_rdev != typer))
650Sstevel@tonic-gate 
660Sstevel@tonic-gate static const char	sepstr[] = " \t\n";
670Sstevel@tonic-gate static const char	dash[] = "-";
680Sstevel@tonic-gate 
690Sstevel@tonic-gate typedef struct {
700Sstevel@tonic-gate 	size_t	buflen;
710Sstevel@tonic-gate 	char	*buf;
720Sstevel@tonic-gate } thread_data_t;
730Sstevel@tonic-gate 
740Sstevel@tonic-gate static void
750Sstevel@tonic-gate destroy_thread_data(void *arg)
760Sstevel@tonic-gate {
770Sstevel@tonic-gate 	thread_data_t *thread_data = arg;
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 	if (thread_data->buf != NULL) {
800Sstevel@tonic-gate 		free(thread_data->buf);
810Sstevel@tonic-gate 		thread_data->buf = NULL;
820Sstevel@tonic-gate 	}
830Sstevel@tonic-gate 	thread_data->buflen = 0;
840Sstevel@tonic-gate }
850Sstevel@tonic-gate 
860Sstevel@tonic-gate static char *
870Sstevel@tonic-gate getmntbuf(size_t size)
880Sstevel@tonic-gate {
890Sstevel@tonic-gate 	thread_data_t *thread_data;
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	thread_data = tsdalloc(_T_GETMNTENT,
920Sstevel@tonic-gate 	    sizeof (thread_data_t), destroy_thread_data);
930Sstevel@tonic-gate 	if (thread_data == NULL)
940Sstevel@tonic-gate 		return (NULL);
950Sstevel@tonic-gate 	if (thread_data->buf == NULL ||
960Sstevel@tonic-gate 	    thread_data->buflen < size) {
970Sstevel@tonic-gate 		if (thread_data->buf != NULL)
980Sstevel@tonic-gate 			free(thread_data->buf);
990Sstevel@tonic-gate 		thread_data->buflen = 0;
1000Sstevel@tonic-gate 		if ((thread_data->buf = malloc(size)) == NULL)
1010Sstevel@tonic-gate 			return (NULL);
1020Sstevel@tonic-gate 		thread_data->buflen = size;
1030Sstevel@tonic-gate 	}
1040Sstevel@tonic-gate 	return (thread_data->buf);
1050Sstevel@tonic-gate }
1060Sstevel@tonic-gate 
107*10910SRobert.Harris@Sun.COM static int
108*10910SRobert.Harris@Sun.COM getmntany_compat(FILE *fp, struct mnttab *mgetp, struct mnttab *mrefp)
1090Sstevel@tonic-gate {
1100Sstevel@tonic-gate 	int	ret, bstat;
1110Sstevel@tonic-gate 	mode_t	bmode;
1120Sstevel@tonic-gate 	dev_t	brdev;
1130Sstevel@tonic-gate 	struct stat64	statb;
1140Sstevel@tonic-gate 
115380Seschrock 	/*
116380Seschrock 	 * Ignore specials that don't correspond to real devices to avoid doing
117380Seschrock 	 * unnecessary lookups in stat64().
118380Seschrock 	 */
119380Seschrock 	if (mrefp->mnt_special && mrefp->mnt_special[0] == '/' &&
120380Seschrock 	    stat64(mrefp->mnt_special, &statb) == 0 &&
1210Sstevel@tonic-gate 	    ((bmode = (statb.st_mode & S_IFMT)) == S_IFBLK ||
1220Sstevel@tonic-gate 	    bmode == S_IFCHR)) {
1230Sstevel@tonic-gate 		bstat = 1;
1240Sstevel@tonic-gate 		brdev = statb.st_rdev;
1250Sstevel@tonic-gate 	} else {
1260Sstevel@tonic-gate 		bstat = 0;
1270Sstevel@tonic-gate 	}
1280Sstevel@tonic-gate 
129*10910SRobert.Harris@Sun.COM 	while ((ret = getmntent_compat(fp, mgetp)) == 0 &&
1300Sstevel@tonic-gate 	    ((bstat == 0 && DIFF(mnt_special)) ||
1310Sstevel@tonic-gate 	    (bstat == 1 && SDIFF(mnt_special, bmode, brdev)) ||
1320Sstevel@tonic-gate 	    DIFF(mnt_mountp) ||
1330Sstevel@tonic-gate 	    DIFF(mnt_fstype) ||
1340Sstevel@tonic-gate 	    DIFF(mnt_mntopts) ||
1350Sstevel@tonic-gate 	    DIFF(mnt_time)))
1360Sstevel@tonic-gate 		;
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 	return (ret);
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate int
142*10910SRobert.Harris@Sun.COM getmntany(FILE *fp, struct mnttab *mgetp, struct mnttab *mrefp)
1430Sstevel@tonic-gate {
144*10910SRobert.Harris@Sun.COM 	struct mntentbuf embuf;
145*10910SRobert.Harris@Sun.COM 	char *copyp, *bufp;
146*10910SRobert.Harris@Sun.COM 	int ret;
147*10910SRobert.Harris@Sun.COM 
148*10910SRobert.Harris@Sun.COM 
149*10910SRobert.Harris@Sun.COM 	/*
150*10910SRobert.Harris@Sun.COM 	 * We collect all of the text strings pointed to by members of the
151*10910SRobert.Harris@Sun.COM 	 * user's preferences struct into a single buffer. At the same time
152*10910SRobert.Harris@Sun.COM 	 * populate the members of the results struct to point to the
153*10910SRobert.Harris@Sun.COM 	 * corresponding words. We then ask the kernel to figure out the
154*10910SRobert.Harris@Sun.COM 	 * rest; if this is a non-mntfs file then we handover to
155*10910SRobert.Harris@Sun.COM 	 * getmntany_compat().
156*10910SRobert.Harris@Sun.COM 	 */
157*10910SRobert.Harris@Sun.COM 	if ((copyp = bufp = getmntbuf(MNT_LINE_MAX)) == NULL) {
158*10910SRobert.Harris@Sun.COM 		errno = ENOMEM;
159*10910SRobert.Harris@Sun.COM 		return (-1);
160*10910SRobert.Harris@Sun.COM 	}
161*10910SRobert.Harris@Sun.COM 	bzero(mgetp, sizeof (struct mnttab));
162*10910SRobert.Harris@Sun.COM 	if (mrefp->mnt_special) {
163*10910SRobert.Harris@Sun.COM 		mgetp->mnt_special = copyp;
164*10910SRobert.Harris@Sun.COM 		copyp += snprintf(mgetp->mnt_special, MNT_LINE_MAX, "%s",
165*10910SRobert.Harris@Sun.COM 		    mrefp->mnt_special) + 1;
166*10910SRobert.Harris@Sun.COM 	}
167*10910SRobert.Harris@Sun.COM 	if (mrefp->mnt_mountp) {
168*10910SRobert.Harris@Sun.COM 		mgetp->mnt_mountp = copyp;
169*10910SRobert.Harris@Sun.COM 		copyp += snprintf(mgetp->mnt_mountp,
170*10910SRobert.Harris@Sun.COM 		    bufp + MNT_LINE_MAX - copyp, "%s", mrefp->mnt_mountp) + 1;
171*10910SRobert.Harris@Sun.COM 	}
172*10910SRobert.Harris@Sun.COM 	if (mrefp->mnt_fstype) {
173*10910SRobert.Harris@Sun.COM 		mgetp->mnt_fstype = copyp;
174*10910SRobert.Harris@Sun.COM 		copyp += snprintf(mgetp->mnt_fstype,
175*10910SRobert.Harris@Sun.COM 		    bufp + MNT_LINE_MAX - copyp, "%s", mrefp->mnt_fstype) + 1;
176*10910SRobert.Harris@Sun.COM 	}
177*10910SRobert.Harris@Sun.COM 	if (mrefp->mnt_mntopts) {
178*10910SRobert.Harris@Sun.COM 		mgetp->mnt_mntopts = copyp;
179*10910SRobert.Harris@Sun.COM 		copyp += snprintf(mgetp->mnt_mntopts,
180*10910SRobert.Harris@Sun.COM 		    bufp + MNT_LINE_MAX - copyp, "%s", mrefp->mnt_mntopts) + 1;
181*10910SRobert.Harris@Sun.COM 	}
182*10910SRobert.Harris@Sun.COM 	if (mrefp->mnt_time) {
183*10910SRobert.Harris@Sun.COM 		mgetp->mnt_time = copyp;
184*10910SRobert.Harris@Sun.COM 		(void) snprintf(mgetp->mnt_time, bufp + MNT_LINE_MAX - copyp,
185*10910SRobert.Harris@Sun.COM 		    "%s", mrefp->mnt_time);
186*10910SRobert.Harris@Sun.COM 	}
187*10910SRobert.Harris@Sun.COM 
188*10910SRobert.Harris@Sun.COM 	embuf.mbuf_emp = (struct extmnttab *)mgetp;
189*10910SRobert.Harris@Sun.COM 	embuf.mbuf_bufsize = MNT_LINE_MAX;
190*10910SRobert.Harris@Sun.COM 	embuf.mbuf_buf = bufp;
1910Sstevel@tonic-gate 
192*10910SRobert.Harris@Sun.COM 	switch (ret = ioctl(fileno(fp), MNTIOC_GETMNTANY, &embuf)) {
193*10910SRobert.Harris@Sun.COM 	case 0:
194*10910SRobert.Harris@Sun.COM 		/* Success. */
195*10910SRobert.Harris@Sun.COM 		return (0);
196*10910SRobert.Harris@Sun.COM 	case MNTFS_EOF:
197*10910SRobert.Harris@Sun.COM 		return (-1);
198*10910SRobert.Harris@Sun.COM 	case MNTFS_TOOLONG:
199*10910SRobert.Harris@Sun.COM 		return (MNT_TOOLONG);
200*10910SRobert.Harris@Sun.COM 	default:
201*10910SRobert.Harris@Sun.COM 		/* A failure of some kind. */
202*10910SRobert.Harris@Sun.COM 		if (errno == ENOTTY)
203*10910SRobert.Harris@Sun.COM 			return (getmntany_compat(fp, mgetp, mrefp));
204*10910SRobert.Harris@Sun.COM 		else
205*10910SRobert.Harris@Sun.COM 			return (ret);
206*10910SRobert.Harris@Sun.COM 	}
207*10910SRobert.Harris@Sun.COM }
208*10910SRobert.Harris@Sun.COM 
209*10910SRobert.Harris@Sun.COM /*
210*10910SRobert.Harris@Sun.COM  * Common code for getmntent() and getextmntent().
211*10910SRobert.Harris@Sun.COM  *
212*10910SRobert.Harris@Sun.COM  * These functions serve to populate a structure supplied by the user. Common
213*10910SRobert.Harris@Sun.COM  * to both struct mnttab and struct extmnttab is a set of pointers to the
214*10910SRobert.Harris@Sun.COM  * individual text fields that form an entry in /etc/mnttab. We arrange for the
215*10910SRobert.Harris@Sun.COM  * text itself to be stored in some thread-local storage, and for the kernel to
216*10910SRobert.Harris@Sun.COM  * populate both this buffer and the structure directly.
217*10910SRobert.Harris@Sun.COM  *
218*10910SRobert.Harris@Sun.COM  * If getmntent() passes a file that isn't provided by mntfs then we assume that
219*10910SRobert.Harris@Sun.COM  * it is a simple text file and give it to getmntent_compat() to parse. For
220*10910SRobert.Harris@Sun.COM  * getextmntent() we give up; it requires major and minor numbers that only the
221*10910SRobert.Harris@Sun.COM  * kernel can provide.
222*10910SRobert.Harris@Sun.COM  */
223*10910SRobert.Harris@Sun.COM static int
224*10910SRobert.Harris@Sun.COM getmntent_common(FILE *fp, struct extmnttab *emp, int command)
225*10910SRobert.Harris@Sun.COM {
226*10910SRobert.Harris@Sun.COM 	struct mntentbuf embuf;
227*10910SRobert.Harris@Sun.COM 	static size_t bufsize = MNT_LINE_MAX;
228*10910SRobert.Harris@Sun.COM 	int ret;
229*10910SRobert.Harris@Sun.COM 
230*10910SRobert.Harris@Sun.COM 	embuf.mbuf_emp = emp;
231*10910SRobert.Harris@Sun.COM 	embuf.mbuf_bufsize = bufsize;
232*10910SRobert.Harris@Sun.COM 	if ((embuf.mbuf_buf = getmntbuf(embuf.mbuf_bufsize)) == NULL) {
233*10910SRobert.Harris@Sun.COM 		errno = ENOMEM;
234*10910SRobert.Harris@Sun.COM 		return (-1);
235*10910SRobert.Harris@Sun.COM 	}
236*10910SRobert.Harris@Sun.COM 
237*10910SRobert.Harris@Sun.COM 	while ((ret = ioctl(fileno(fp), command, &embuf)) == MNTFS_TOOLONG) {
238*10910SRobert.Harris@Sun.COM 		/* The buffer wasn't large enough. */
239*10910SRobert.Harris@Sun.COM 		(void) atomic_swap_ulong((unsigned long *)&bufsize,
240*10910SRobert.Harris@Sun.COM 		    2 * embuf.mbuf_bufsize);
241*10910SRobert.Harris@Sun.COM 		embuf.mbuf_bufsize = bufsize;
242*10910SRobert.Harris@Sun.COM 		if ((embuf.mbuf_buf = getmntbuf(embuf.mbuf_bufsize)) == NULL) {
243*10910SRobert.Harris@Sun.COM 			errno = ENOMEM;
244*10910SRobert.Harris@Sun.COM 			return (-1);
245*10910SRobert.Harris@Sun.COM 		}
246*10910SRobert.Harris@Sun.COM 	}
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate 	switch (ret) {
249*10910SRobert.Harris@Sun.COM 	case 0:
250*10910SRobert.Harris@Sun.COM 		/*
251*10910SRobert.Harris@Sun.COM 		 * We were successful, but we may have to enforce getmntent()'s
252*10910SRobert.Harris@Sun.COM 		 * documented limit on the line length.
253*10910SRobert.Harris@Sun.COM 		 */
254*10910SRobert.Harris@Sun.COM 		if (command == MNTIOC_GETMNTENT &&
255*10910SRobert.Harris@Sun.COM 		    (emp->mnt_time + strlen(emp->mnt_time) + 1 -
256*10910SRobert.Harris@Sun.COM 		    emp->mnt_special > MNT_LINE_MAX))
257*10910SRobert.Harris@Sun.COM 			return (MNT_TOOLONG);
258*10910SRobert.Harris@Sun.COM 		else
259*10910SRobert.Harris@Sun.COM 			return (0);
260*10910SRobert.Harris@Sun.COM 	case MNTFS_EOF:
261*10910SRobert.Harris@Sun.COM 		/* EOF. */
262*10910SRobert.Harris@Sun.COM 		return (-1);
263*10910SRobert.Harris@Sun.COM 	default:
264*10910SRobert.Harris@Sun.COM 		/* A non-mntfs file. */
265*10910SRobert.Harris@Sun.COM 		if (command == MNTIOC_GETMNTENT)
266*10910SRobert.Harris@Sun.COM 			return (getmntent_compat(fp, (struct mnttab *)emp));
267*10910SRobert.Harris@Sun.COM 		else
268*10910SRobert.Harris@Sun.COM 			return (ret);
2690Sstevel@tonic-gate 	}
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate 
272*10910SRobert.Harris@Sun.COM int
273*10910SRobert.Harris@Sun.COM getmntent(FILE *fp, struct mnttab *mp)
274*10910SRobert.Harris@Sun.COM {
275*10910SRobert.Harris@Sun.COM 	return (getmntent_common(fp, (struct extmnttab *)mp, MNTIOC_GETMNTENT));
276*10910SRobert.Harris@Sun.COM }
277*10910SRobert.Harris@Sun.COM 
278*10910SRobert.Harris@Sun.COM /*ARGSUSED*/
279*10910SRobert.Harris@Sun.COM int
280*10910SRobert.Harris@Sun.COM getextmntent(FILE *fp, struct extmnttab *emp, size_t len)
281*10910SRobert.Harris@Sun.COM {
282*10910SRobert.Harris@Sun.COM 	return (getmntent_common(fp, emp, MNTIOC_GETEXTMNTENT));
283*10910SRobert.Harris@Sun.COM }
284*10910SRobert.Harris@Sun.COM 
2850Sstevel@tonic-gate char *
2860Sstevel@tonic-gate mntopt(char **p)
2870Sstevel@tonic-gate {
2880Sstevel@tonic-gate 	char *cp = *p;
2890Sstevel@tonic-gate 	char *retstr;
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	while (*cp && isspace(*cp))
2920Sstevel@tonic-gate 		cp++;
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	retstr = cp;
2950Sstevel@tonic-gate 	while (*cp && *cp != ',')
2960Sstevel@tonic-gate 		cp++;
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	if (*cp) {
2990Sstevel@tonic-gate 		*cp = '\0';
3000Sstevel@tonic-gate 		cp++;
3010Sstevel@tonic-gate 	}
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 	*p = cp;
3040Sstevel@tonic-gate 	return (retstr);
3050Sstevel@tonic-gate }
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate char *
3080Sstevel@tonic-gate hasmntopt(struct mnttab *mnt, char *opt)
3090Sstevel@tonic-gate {
3100Sstevel@tonic-gate 	char tmpopts[MNT_LINE_MAX];
3110Sstevel@tonic-gate 	char *f, *opts = tmpopts;
3124830Skeerthi 	size_t	len;
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	if (mnt->mnt_mntopts == NULL)
3150Sstevel@tonic-gate 		return (NULL);
3160Sstevel@tonic-gate 	(void) strcpy(opts, mnt->mnt_mntopts);
3174830Skeerthi 	len = strlen(opt);
3180Sstevel@tonic-gate 	f = mntopt(&opts);
3190Sstevel@tonic-gate 	for (; *f; f = mntopt(&opts)) {
3204830Skeerthi 		/*
3214830Skeerthi 		 * Match only complete substrings. For options
3224830Skeerthi 		 * which use a delimiter (such as 'retry=3'),
3234830Skeerthi 		 * treat the delimiter as the end of the substring.
3244830Skeerthi 		 */
3254830Skeerthi 		if (strncmp(opt, f, len) == 0 &&
3264830Skeerthi 		    (f[len] == '\0' || !isalnum(f[len])))
3270Sstevel@tonic-gate 			return (f - tmpopts + mnt->mnt_mntopts);
3280Sstevel@tonic-gate 	}
3290Sstevel@tonic-gate 	return (NULL);
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate void
3330Sstevel@tonic-gate resetmnttab(FILE *fp)
3340Sstevel@tonic-gate {
3350Sstevel@tonic-gate 	rewind(fp);
3360Sstevel@tonic-gate }
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate /*
3390Sstevel@tonic-gate  * Compatibility for non-mntfs files.  For backwards compatibility, we continue
3400Sstevel@tonic-gate  * to have to support this broken interface.  Note that getextmntent() has
3410Sstevel@tonic-gate  * always failed when using a file other than /etc/mnttab, because it relies on
3420Sstevel@tonic-gate  * an ioctl() call.
3430Sstevel@tonic-gate  */
3440Sstevel@tonic-gate static int
3450Sstevel@tonic-gate getline(char *lp, FILE *fp)
3460Sstevel@tonic-gate {
3470Sstevel@tonic-gate 	char	*cp;
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	while ((lp = fgets(lp, MNT_LINE_MAX, fp)) != NULL) {
3500Sstevel@tonic-gate 		if (strlen(lp) == MNT_LINE_MAX-1 && lp[MNT_LINE_MAX-2] != '\n')
3510Sstevel@tonic-gate 			return (MNT_TOOLONG);
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 		for (cp = lp; *cp == ' ' || *cp == '\t'; cp++)
3540Sstevel@tonic-gate 			;
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 		if (*cp != '#' && *cp != '\n')
3570Sstevel@tonic-gate 			return (0);
3580Sstevel@tonic-gate 	}
3590Sstevel@tonic-gate 	return (-1);
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate static int
3630Sstevel@tonic-gate getmntent_compat(FILE *fp, struct mnttab *mp)
3640Sstevel@tonic-gate {
3650Sstevel@tonic-gate 	int	ret;
3660Sstevel@tonic-gate 	char	*tmp;
3670Sstevel@tonic-gate 	char	*line = getmntbuf(MNT_LINE_MAX);
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	if (line == NULL) {
3700Sstevel@tonic-gate 		errno = ENOMEM;
3710Sstevel@tonic-gate 		return (-1);
3720Sstevel@tonic-gate 	}
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 	/* skip leading spaces and comments */
3750Sstevel@tonic-gate 	if ((ret = getline(line, fp)) != 0)
3760Sstevel@tonic-gate 		return (ret);
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	/* split up each field */
3790Sstevel@tonic-gate 	GETTOK_R(mnt_special, line, &tmp);
3800Sstevel@tonic-gate 	GETTOK_R(mnt_mountp, NULL, &tmp);
3810Sstevel@tonic-gate 	GETTOK_R(mnt_fstype, NULL, &tmp);
3820Sstevel@tonic-gate 	GETTOK_R(mnt_mntopts, NULL, &tmp);
3830Sstevel@tonic-gate 	GETTOK_R(mnt_time, NULL, &tmp);
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 	/* check for too many fields */
3860Sstevel@tonic-gate 	if (strtok_r(NULL, sepstr, &tmp) != NULL)
3870Sstevel@tonic-gate 		return (MNT_TOOMANY);
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 	return (0);
3900Sstevel@tonic-gate }
391