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*13093SRoger.Faulkner@Oracle.COM * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */
270Sstevel@tonic-gate /* All Rights Reserved */
280Sstevel@tonic-gate
296812Sraf #include "lint.h"
300Sstevel@tonic-gate #include <mtlib.h>
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate #include <sys/stat.h>
340Sstevel@tonic-gate #include <sys/mnttab.h>
350Sstevel@tonic-gate #include <sys/mntio.h>
360Sstevel@tonic-gate #include <string.h>
370Sstevel@tonic-gate #include <ctype.h>
380Sstevel@tonic-gate #include <errno.h>
390Sstevel@tonic-gate #include <stdlib.h>
400Sstevel@tonic-gate #include <thread.h>
410Sstevel@tonic-gate #include <synch.h>
420Sstevel@tonic-gate #include <libc.h>
430Sstevel@tonic-gate #include <unistd.h>
440Sstevel@tonic-gate #include "tsd.h"
4510910SRobert.Harris@Sun.COM #include <atomic.h>
4610910SRobert.Harris@Sun.COM #include <strings.h>
470Sstevel@tonic-gate
480Sstevel@tonic-gate static int getmntent_compat(FILE *fp, struct mnttab *mp);
490Sstevel@tonic-gate
500Sstevel@tonic-gate #define GETTOK_R(xx, ll, tmp)\
510Sstevel@tonic-gate if ((mp->xx = (char *)strtok_r(ll, sepstr, tmp)) == NULL)\
520Sstevel@tonic-gate return (MNT_TOOFEW);\
530Sstevel@tonic-gate if (strcmp(mp->xx, dash) == 0)\
540Sstevel@tonic-gate mp->xx = NULL
550Sstevel@tonic-gate
560Sstevel@tonic-gate #define DIFF(xx)\
570Sstevel@tonic-gate (mrefp->xx != NULL && (mgetp->xx == NULL ||\
580Sstevel@tonic-gate strcmp(mrefp->xx, mgetp->xx) != 0))
590Sstevel@tonic-gate
600Sstevel@tonic-gate #define SDIFF(xx, typem, typer)\
610Sstevel@tonic-gate ((mgetp->xx == NULL) || (stat64(mgetp->xx, &statb) == -1) ||\
620Sstevel@tonic-gate ((statb.st_mode & S_IFMT) != typem) ||\
630Sstevel@tonic-gate (statb.st_rdev != typer))
640Sstevel@tonic-gate
650Sstevel@tonic-gate static const char sepstr[] = " \t\n";
660Sstevel@tonic-gate static const char dash[] = "-";
670Sstevel@tonic-gate
680Sstevel@tonic-gate typedef struct {
690Sstevel@tonic-gate size_t buflen;
700Sstevel@tonic-gate char *buf;
710Sstevel@tonic-gate } thread_data_t;
720Sstevel@tonic-gate
730Sstevel@tonic-gate static void
destroy_thread_data(void * arg)740Sstevel@tonic-gate destroy_thread_data(void *arg)
750Sstevel@tonic-gate {
760Sstevel@tonic-gate thread_data_t *thread_data = arg;
770Sstevel@tonic-gate
780Sstevel@tonic-gate if (thread_data->buf != NULL) {
790Sstevel@tonic-gate free(thread_data->buf);
800Sstevel@tonic-gate thread_data->buf = NULL;
810Sstevel@tonic-gate }
820Sstevel@tonic-gate thread_data->buflen = 0;
830Sstevel@tonic-gate }
840Sstevel@tonic-gate
850Sstevel@tonic-gate static char *
getmntbuf(size_t size)860Sstevel@tonic-gate getmntbuf(size_t size)
870Sstevel@tonic-gate {
880Sstevel@tonic-gate thread_data_t *thread_data;
890Sstevel@tonic-gate
900Sstevel@tonic-gate thread_data = tsdalloc(_T_GETMNTENT,
910Sstevel@tonic-gate sizeof (thread_data_t), destroy_thread_data);
920Sstevel@tonic-gate if (thread_data == NULL)
930Sstevel@tonic-gate return (NULL);
940Sstevel@tonic-gate if (thread_data->buf == NULL ||
950Sstevel@tonic-gate thread_data->buflen < size) {
960Sstevel@tonic-gate if (thread_data->buf != NULL)
970Sstevel@tonic-gate free(thread_data->buf);
980Sstevel@tonic-gate thread_data->buflen = 0;
990Sstevel@tonic-gate if ((thread_data->buf = malloc(size)) == NULL)
1000Sstevel@tonic-gate return (NULL);
1010Sstevel@tonic-gate thread_data->buflen = size;
1020Sstevel@tonic-gate }
1030Sstevel@tonic-gate return (thread_data->buf);
1040Sstevel@tonic-gate }
1050Sstevel@tonic-gate
10610910SRobert.Harris@Sun.COM static int
getmntany_compat(FILE * fp,struct mnttab * mgetp,struct mnttab * mrefp)10710910SRobert.Harris@Sun.COM getmntany_compat(FILE *fp, struct mnttab *mgetp, struct mnttab *mrefp)
1080Sstevel@tonic-gate {
1090Sstevel@tonic-gate int ret, bstat;
1100Sstevel@tonic-gate mode_t bmode;
1110Sstevel@tonic-gate dev_t brdev;
1120Sstevel@tonic-gate struct stat64 statb;
1130Sstevel@tonic-gate
114380Seschrock /*
115380Seschrock * Ignore specials that don't correspond to real devices to avoid doing
116380Seschrock * unnecessary lookups in stat64().
117380Seschrock */
118380Seschrock if (mrefp->mnt_special && mrefp->mnt_special[0] == '/' &&
119380Seschrock stat64(mrefp->mnt_special, &statb) == 0 &&
1200Sstevel@tonic-gate ((bmode = (statb.st_mode & S_IFMT)) == S_IFBLK ||
1210Sstevel@tonic-gate bmode == S_IFCHR)) {
1220Sstevel@tonic-gate bstat = 1;
1230Sstevel@tonic-gate brdev = statb.st_rdev;
1240Sstevel@tonic-gate } else {
1250Sstevel@tonic-gate bstat = 0;
1260Sstevel@tonic-gate }
1270Sstevel@tonic-gate
12810910SRobert.Harris@Sun.COM while ((ret = getmntent_compat(fp, mgetp)) == 0 &&
1290Sstevel@tonic-gate ((bstat == 0 && DIFF(mnt_special)) ||
1300Sstevel@tonic-gate (bstat == 1 && SDIFF(mnt_special, bmode, brdev)) ||
1310Sstevel@tonic-gate DIFF(mnt_mountp) ||
1320Sstevel@tonic-gate DIFF(mnt_fstype) ||
1330Sstevel@tonic-gate DIFF(mnt_mntopts) ||
1340Sstevel@tonic-gate DIFF(mnt_time)))
1350Sstevel@tonic-gate ;
1360Sstevel@tonic-gate
1370Sstevel@tonic-gate return (ret);
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate
1400Sstevel@tonic-gate int
getmntany(FILE * fp,struct mnttab * mgetp,struct mnttab * mrefp)14110910SRobert.Harris@Sun.COM getmntany(FILE *fp, struct mnttab *mgetp, struct mnttab *mrefp)
1420Sstevel@tonic-gate {
14310910SRobert.Harris@Sun.COM struct mntentbuf embuf;
14410910SRobert.Harris@Sun.COM char *copyp, *bufp;
14510910SRobert.Harris@Sun.COM int ret;
14610910SRobert.Harris@Sun.COM
14710910SRobert.Harris@Sun.COM
14810910SRobert.Harris@Sun.COM /*
14910910SRobert.Harris@Sun.COM * We collect all of the text strings pointed to by members of the
15010910SRobert.Harris@Sun.COM * user's preferences struct into a single buffer. At the same time
15110910SRobert.Harris@Sun.COM * populate the members of the results struct to point to the
15210910SRobert.Harris@Sun.COM * corresponding words. We then ask the kernel to figure out the
15310910SRobert.Harris@Sun.COM * rest; if this is a non-mntfs file then we handover to
15410910SRobert.Harris@Sun.COM * getmntany_compat().
15510910SRobert.Harris@Sun.COM */
15610910SRobert.Harris@Sun.COM if ((copyp = bufp = getmntbuf(MNT_LINE_MAX)) == NULL) {
15710910SRobert.Harris@Sun.COM errno = ENOMEM;
15810910SRobert.Harris@Sun.COM return (-1);
15910910SRobert.Harris@Sun.COM }
16010910SRobert.Harris@Sun.COM bzero(mgetp, sizeof (struct mnttab));
16110910SRobert.Harris@Sun.COM if (mrefp->mnt_special) {
16210910SRobert.Harris@Sun.COM mgetp->mnt_special = copyp;
16310910SRobert.Harris@Sun.COM copyp += snprintf(mgetp->mnt_special, MNT_LINE_MAX, "%s",
16410910SRobert.Harris@Sun.COM mrefp->mnt_special) + 1;
16510910SRobert.Harris@Sun.COM }
16610910SRobert.Harris@Sun.COM if (mrefp->mnt_mountp) {
16710910SRobert.Harris@Sun.COM mgetp->mnt_mountp = copyp;
16810910SRobert.Harris@Sun.COM copyp += snprintf(mgetp->mnt_mountp,
16910910SRobert.Harris@Sun.COM bufp + MNT_LINE_MAX - copyp, "%s", mrefp->mnt_mountp) + 1;
17010910SRobert.Harris@Sun.COM }
17110910SRobert.Harris@Sun.COM if (mrefp->mnt_fstype) {
17210910SRobert.Harris@Sun.COM mgetp->mnt_fstype = copyp;
17310910SRobert.Harris@Sun.COM copyp += snprintf(mgetp->mnt_fstype,
17410910SRobert.Harris@Sun.COM bufp + MNT_LINE_MAX - copyp, "%s", mrefp->mnt_fstype) + 1;
17510910SRobert.Harris@Sun.COM }
17610910SRobert.Harris@Sun.COM if (mrefp->mnt_mntopts) {
17710910SRobert.Harris@Sun.COM mgetp->mnt_mntopts = copyp;
17810910SRobert.Harris@Sun.COM copyp += snprintf(mgetp->mnt_mntopts,
17910910SRobert.Harris@Sun.COM bufp + MNT_LINE_MAX - copyp, "%s", mrefp->mnt_mntopts) + 1;
18010910SRobert.Harris@Sun.COM }
18110910SRobert.Harris@Sun.COM if (mrefp->mnt_time) {
18210910SRobert.Harris@Sun.COM mgetp->mnt_time = copyp;
18310910SRobert.Harris@Sun.COM (void) snprintf(mgetp->mnt_time, bufp + MNT_LINE_MAX - copyp,
18410910SRobert.Harris@Sun.COM "%s", mrefp->mnt_time);
18510910SRobert.Harris@Sun.COM }
18610910SRobert.Harris@Sun.COM
18710910SRobert.Harris@Sun.COM embuf.mbuf_emp = (struct extmnttab *)mgetp;
18810910SRobert.Harris@Sun.COM embuf.mbuf_bufsize = MNT_LINE_MAX;
18910910SRobert.Harris@Sun.COM embuf.mbuf_buf = bufp;
1900Sstevel@tonic-gate
19110910SRobert.Harris@Sun.COM switch (ret = ioctl(fileno(fp), MNTIOC_GETMNTANY, &embuf)) {
19210910SRobert.Harris@Sun.COM case 0:
19310910SRobert.Harris@Sun.COM /* Success. */
19410910SRobert.Harris@Sun.COM return (0);
19510910SRobert.Harris@Sun.COM case MNTFS_EOF:
19610910SRobert.Harris@Sun.COM return (-1);
19710910SRobert.Harris@Sun.COM case MNTFS_TOOLONG:
19810910SRobert.Harris@Sun.COM return (MNT_TOOLONG);
19910910SRobert.Harris@Sun.COM default:
20010910SRobert.Harris@Sun.COM /* A failure of some kind. */
20110910SRobert.Harris@Sun.COM if (errno == ENOTTY)
20210910SRobert.Harris@Sun.COM return (getmntany_compat(fp, mgetp, mrefp));
20310910SRobert.Harris@Sun.COM else
20410910SRobert.Harris@Sun.COM return (ret);
20510910SRobert.Harris@Sun.COM }
20610910SRobert.Harris@Sun.COM }
20710910SRobert.Harris@Sun.COM
20810910SRobert.Harris@Sun.COM /*
20910910SRobert.Harris@Sun.COM * Common code for getmntent() and getextmntent().
21010910SRobert.Harris@Sun.COM *
21110910SRobert.Harris@Sun.COM * These functions serve to populate a structure supplied by the user. Common
21210910SRobert.Harris@Sun.COM * to both struct mnttab and struct extmnttab is a set of pointers to the
21310910SRobert.Harris@Sun.COM * individual text fields that form an entry in /etc/mnttab. We arrange for the
21410910SRobert.Harris@Sun.COM * text itself to be stored in some thread-local storage, and for the kernel to
21510910SRobert.Harris@Sun.COM * populate both this buffer and the structure directly.
21610910SRobert.Harris@Sun.COM *
21710910SRobert.Harris@Sun.COM * If getmntent() passes a file that isn't provided by mntfs then we assume that
21810910SRobert.Harris@Sun.COM * it is a simple text file and give it to getmntent_compat() to parse. For
21910910SRobert.Harris@Sun.COM * getextmntent() we give up; it requires major and minor numbers that only the
22010910SRobert.Harris@Sun.COM * kernel can provide.
22110910SRobert.Harris@Sun.COM */
22210910SRobert.Harris@Sun.COM static int
getmntent_common(FILE * fp,struct extmnttab * emp,int command)22310910SRobert.Harris@Sun.COM getmntent_common(FILE *fp, struct extmnttab *emp, int command)
22410910SRobert.Harris@Sun.COM {
22510910SRobert.Harris@Sun.COM struct mntentbuf embuf;
22610910SRobert.Harris@Sun.COM static size_t bufsize = MNT_LINE_MAX;
22710910SRobert.Harris@Sun.COM int ret;
22810910SRobert.Harris@Sun.COM
22910910SRobert.Harris@Sun.COM embuf.mbuf_emp = emp;
23010910SRobert.Harris@Sun.COM embuf.mbuf_bufsize = bufsize;
23110910SRobert.Harris@Sun.COM if ((embuf.mbuf_buf = getmntbuf(embuf.mbuf_bufsize)) == NULL) {
23210910SRobert.Harris@Sun.COM errno = ENOMEM;
23310910SRobert.Harris@Sun.COM return (-1);
23410910SRobert.Harris@Sun.COM }
23510910SRobert.Harris@Sun.COM
23610910SRobert.Harris@Sun.COM while ((ret = ioctl(fileno(fp), command, &embuf)) == MNTFS_TOOLONG) {
23710910SRobert.Harris@Sun.COM /* The buffer wasn't large enough. */
23810910SRobert.Harris@Sun.COM (void) atomic_swap_ulong((unsigned long *)&bufsize,
23910910SRobert.Harris@Sun.COM 2 * embuf.mbuf_bufsize);
24010910SRobert.Harris@Sun.COM embuf.mbuf_bufsize = bufsize;
24110910SRobert.Harris@Sun.COM if ((embuf.mbuf_buf = getmntbuf(embuf.mbuf_bufsize)) == NULL) {
24210910SRobert.Harris@Sun.COM errno = ENOMEM;
24310910SRobert.Harris@Sun.COM return (-1);
24410910SRobert.Harris@Sun.COM }
24510910SRobert.Harris@Sun.COM }
2460Sstevel@tonic-gate
2470Sstevel@tonic-gate switch (ret) {
24810910SRobert.Harris@Sun.COM case 0:
24910910SRobert.Harris@Sun.COM /*
25010910SRobert.Harris@Sun.COM * We were successful, but we may have to enforce getmntent()'s
25110910SRobert.Harris@Sun.COM * documented limit on the line length.
25210910SRobert.Harris@Sun.COM */
25310910SRobert.Harris@Sun.COM if (command == MNTIOC_GETMNTENT &&
25410910SRobert.Harris@Sun.COM (emp->mnt_time + strlen(emp->mnt_time) + 1 -
25510910SRobert.Harris@Sun.COM emp->mnt_special > MNT_LINE_MAX))
25610910SRobert.Harris@Sun.COM return (MNT_TOOLONG);
25710910SRobert.Harris@Sun.COM else
25810910SRobert.Harris@Sun.COM return (0);
25910910SRobert.Harris@Sun.COM case MNTFS_EOF:
26010910SRobert.Harris@Sun.COM /* EOF. */
26110910SRobert.Harris@Sun.COM return (-1);
26210910SRobert.Harris@Sun.COM default:
26310910SRobert.Harris@Sun.COM /* A non-mntfs file. */
26410910SRobert.Harris@Sun.COM if (command == MNTIOC_GETMNTENT)
26510910SRobert.Harris@Sun.COM return (getmntent_compat(fp, (struct mnttab *)emp));
26610910SRobert.Harris@Sun.COM else
26710910SRobert.Harris@Sun.COM return (ret);
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate
27110910SRobert.Harris@Sun.COM int
getmntent(FILE * fp,struct mnttab * mp)27210910SRobert.Harris@Sun.COM getmntent(FILE *fp, struct mnttab *mp)
27310910SRobert.Harris@Sun.COM {
27410910SRobert.Harris@Sun.COM return (getmntent_common(fp, (struct extmnttab *)mp, MNTIOC_GETMNTENT));
27510910SRobert.Harris@Sun.COM }
27610910SRobert.Harris@Sun.COM
27710910SRobert.Harris@Sun.COM /*ARGSUSED*/
27810910SRobert.Harris@Sun.COM int
getextmntent(FILE * fp,struct extmnttab * emp,size_t len)27910910SRobert.Harris@Sun.COM getextmntent(FILE *fp, struct extmnttab *emp, size_t len)
28010910SRobert.Harris@Sun.COM {
28110910SRobert.Harris@Sun.COM return (getmntent_common(fp, emp, MNTIOC_GETEXTMNTENT));
28210910SRobert.Harris@Sun.COM }
28310910SRobert.Harris@Sun.COM
2840Sstevel@tonic-gate char *
mntopt(char ** p)2850Sstevel@tonic-gate mntopt(char **p)
2860Sstevel@tonic-gate {
2870Sstevel@tonic-gate char *cp = *p;
2880Sstevel@tonic-gate char *retstr;
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate while (*cp && isspace(*cp))
2910Sstevel@tonic-gate cp++;
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate retstr = cp;
2940Sstevel@tonic-gate while (*cp && *cp != ',')
2950Sstevel@tonic-gate cp++;
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate if (*cp) {
2980Sstevel@tonic-gate *cp = '\0';
2990Sstevel@tonic-gate cp++;
3000Sstevel@tonic-gate }
3010Sstevel@tonic-gate
3020Sstevel@tonic-gate *p = cp;
3030Sstevel@tonic-gate return (retstr);
3040Sstevel@tonic-gate }
3050Sstevel@tonic-gate
3060Sstevel@tonic-gate char *
hasmntopt(struct mnttab * mnt,char * opt)3070Sstevel@tonic-gate hasmntopt(struct mnttab *mnt, char *opt)
3080Sstevel@tonic-gate {
3090Sstevel@tonic-gate char tmpopts[MNT_LINE_MAX];
3100Sstevel@tonic-gate char *f, *opts = tmpopts;
3114830Skeerthi size_t len;
3120Sstevel@tonic-gate
3130Sstevel@tonic-gate if (mnt->mnt_mntopts == NULL)
3140Sstevel@tonic-gate return (NULL);
3150Sstevel@tonic-gate (void) strcpy(opts, mnt->mnt_mntopts);
3164830Skeerthi len = strlen(opt);
3170Sstevel@tonic-gate f = mntopt(&opts);
3180Sstevel@tonic-gate for (; *f; f = mntopt(&opts)) {
3194830Skeerthi /*
3204830Skeerthi * Match only complete substrings. For options
3214830Skeerthi * which use a delimiter (such as 'retry=3'),
3224830Skeerthi * treat the delimiter as the end of the substring.
3234830Skeerthi */
3244830Skeerthi if (strncmp(opt, f, len) == 0 &&
3254830Skeerthi (f[len] == '\0' || !isalnum(f[len])))
3260Sstevel@tonic-gate return (f - tmpopts + mnt->mnt_mntopts);
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate return (NULL);
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate
3310Sstevel@tonic-gate void
resetmnttab(FILE * fp)3320Sstevel@tonic-gate resetmnttab(FILE *fp)
3330Sstevel@tonic-gate {
3340Sstevel@tonic-gate rewind(fp);
3350Sstevel@tonic-gate }
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate /*
3380Sstevel@tonic-gate * Compatibility for non-mntfs files. For backwards compatibility, we continue
3390Sstevel@tonic-gate * to have to support this broken interface. Note that getextmntent() has
3400Sstevel@tonic-gate * always failed when using a file other than /etc/mnttab, because it relies on
3410Sstevel@tonic-gate * an ioctl() call.
3420Sstevel@tonic-gate */
3430Sstevel@tonic-gate static int
getaline(char * lp,FILE * fp)344*13093SRoger.Faulkner@Oracle.COM getaline(char *lp, FILE *fp)
3450Sstevel@tonic-gate {
3460Sstevel@tonic-gate char *cp;
3470Sstevel@tonic-gate
3480Sstevel@tonic-gate while ((lp = fgets(lp, MNT_LINE_MAX, fp)) != NULL) {
3490Sstevel@tonic-gate if (strlen(lp) == MNT_LINE_MAX-1 && lp[MNT_LINE_MAX-2] != '\n')
3500Sstevel@tonic-gate return (MNT_TOOLONG);
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate for (cp = lp; *cp == ' ' || *cp == '\t'; cp++)
3530Sstevel@tonic-gate ;
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate if (*cp != '#' && *cp != '\n')
3560Sstevel@tonic-gate return (0);
3570Sstevel@tonic-gate }
3580Sstevel@tonic-gate return (-1);
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate static int
getmntent_compat(FILE * fp,struct mnttab * mp)3620Sstevel@tonic-gate getmntent_compat(FILE *fp, struct mnttab *mp)
3630Sstevel@tonic-gate {
3640Sstevel@tonic-gate int ret;
3650Sstevel@tonic-gate char *tmp;
3660Sstevel@tonic-gate char *line = getmntbuf(MNT_LINE_MAX);
3670Sstevel@tonic-gate
3680Sstevel@tonic-gate if (line == NULL) {
3690Sstevel@tonic-gate errno = ENOMEM;
3700Sstevel@tonic-gate return (-1);
3710Sstevel@tonic-gate }
3720Sstevel@tonic-gate
3730Sstevel@tonic-gate /* skip leading spaces and comments */
374*13093SRoger.Faulkner@Oracle.COM if ((ret = getaline(line, fp)) != 0)
3750Sstevel@tonic-gate return (ret);
3760Sstevel@tonic-gate
3770Sstevel@tonic-gate /* split up each field */
3780Sstevel@tonic-gate GETTOK_R(mnt_special, line, &tmp);
3790Sstevel@tonic-gate GETTOK_R(mnt_mountp, NULL, &tmp);
3800Sstevel@tonic-gate GETTOK_R(mnt_fstype, NULL, &tmp);
3810Sstevel@tonic-gate GETTOK_R(mnt_mntopts, NULL, &tmp);
3820Sstevel@tonic-gate GETTOK_R(mnt_time, NULL, &tmp);
3830Sstevel@tonic-gate
3840Sstevel@tonic-gate /* check for too many fields */
3850Sstevel@tonic-gate if (strtok_r(NULL, sepstr, &tmp) != NULL)
3860Sstevel@tonic-gate return (MNT_TOOMANY);
3870Sstevel@tonic-gate
3880Sstevel@tonic-gate return (0);
3890Sstevel@tonic-gate }
390