xref: /onnv-gate/usr/src/lib/libc/port/gen/getmntent.c (revision 380:4ae8f505c115)
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
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*380Seschrock  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
300Sstevel@tonic-gate /*	  All Rights Reserved  	*/
310Sstevel@tonic-gate 
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #pragma weak getmntany = _getmntany
340Sstevel@tonic-gate #pragma weak getmntent = _getmntent
350Sstevel@tonic-gate #pragma weak getextmntent = _getextmntent
360Sstevel@tonic-gate #pragma weak resetmnttab = _resetmnttab
370Sstevel@tonic-gate #pragma weak hasmntopt = _hasmntopt
380Sstevel@tonic-gate 
390Sstevel@tonic-gate #include "synonyms.h"
400Sstevel@tonic-gate #include <mtlib.h>
410Sstevel@tonic-gate #include <stdio.h>
420Sstevel@tonic-gate #include <sys/types.h>
430Sstevel@tonic-gate #include <sys/stat.h>
440Sstevel@tonic-gate #include <sys/mnttab.h>
450Sstevel@tonic-gate #include <sys/mntio.h>
460Sstevel@tonic-gate #include <string.h>
470Sstevel@tonic-gate #include <ctype.h>
480Sstevel@tonic-gate #include <errno.h>
490Sstevel@tonic-gate #include <stdlib.h>
500Sstevel@tonic-gate #include <thread.h>
510Sstevel@tonic-gate #include <synch.h>
520Sstevel@tonic-gate #include <libc.h>
530Sstevel@tonic-gate #include <unistd.h>
540Sstevel@tonic-gate #include "tsd.h"
550Sstevel@tonic-gate 
560Sstevel@tonic-gate static int getmntent_compat(FILE *fp, struct mnttab *mp);
570Sstevel@tonic-gate static int convert_mntent(struct extmnttab *, struct extmnttab *, int);
580Sstevel@tonic-gate 
590Sstevel@tonic-gate #define	GETTOK_R(xx, ll, tmp)\
600Sstevel@tonic-gate 	if ((mp->xx = (char *)strtok_r(ll, sepstr, tmp)) == NULL)\
610Sstevel@tonic-gate 		return (MNT_TOOFEW);\
620Sstevel@tonic-gate 	if (strcmp(mp->xx, dash) == 0)\
630Sstevel@tonic-gate 		mp->xx = NULL
640Sstevel@tonic-gate 
650Sstevel@tonic-gate #define	DIFF(xx)\
660Sstevel@tonic-gate 	(mrefp->xx != NULL && (mgetp->xx == NULL ||\
670Sstevel@tonic-gate 	    strcmp(mrefp->xx, mgetp->xx) != 0))
680Sstevel@tonic-gate 
690Sstevel@tonic-gate #define	SDIFF(xx, typem, typer)\
700Sstevel@tonic-gate 	((mgetp->xx == NULL) || (stat64(mgetp->xx, &statb) == -1) ||\
710Sstevel@tonic-gate 	((statb.st_mode & S_IFMT) != typem) ||\
720Sstevel@tonic-gate 	    (statb.st_rdev != typer))
730Sstevel@tonic-gate 
740Sstevel@tonic-gate static const char	sepstr[] = " \t\n";
750Sstevel@tonic-gate static const char	dash[] = "-";
760Sstevel@tonic-gate 
770Sstevel@tonic-gate typedef struct {
780Sstevel@tonic-gate 	size_t	buflen;
790Sstevel@tonic-gate 	char	*buf;
800Sstevel@tonic-gate } thread_data_t;
810Sstevel@tonic-gate 
820Sstevel@tonic-gate static void
830Sstevel@tonic-gate destroy_thread_data(void *arg)
840Sstevel@tonic-gate {
850Sstevel@tonic-gate 	thread_data_t *thread_data = arg;
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 	if (thread_data->buf != NULL) {
880Sstevel@tonic-gate 		free(thread_data->buf);
890Sstevel@tonic-gate 		thread_data->buf = NULL;
900Sstevel@tonic-gate 	}
910Sstevel@tonic-gate 	thread_data->buflen = 0;
920Sstevel@tonic-gate }
930Sstevel@tonic-gate 
940Sstevel@tonic-gate static char *
950Sstevel@tonic-gate getmntbuf(size_t size)
960Sstevel@tonic-gate {
970Sstevel@tonic-gate 	thread_data_t *thread_data;
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	if (size < MNT_LINE_MAX)
1000Sstevel@tonic-gate 		size = MNT_LINE_MAX;
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 	thread_data = tsdalloc(_T_GETMNTENT,
1030Sstevel@tonic-gate 	    sizeof (thread_data_t), destroy_thread_data);
1040Sstevel@tonic-gate 	if (thread_data == NULL)
1050Sstevel@tonic-gate 		return (NULL);
1060Sstevel@tonic-gate 	if (thread_data->buf == NULL ||
1070Sstevel@tonic-gate 	    thread_data->buflen < size) {
1080Sstevel@tonic-gate 		if (thread_data->buf != NULL)
1090Sstevel@tonic-gate 			free(thread_data->buf);
1100Sstevel@tonic-gate 		thread_data->buflen = 0;
1110Sstevel@tonic-gate 		if ((thread_data->buf = malloc(size)) == NULL)
1120Sstevel@tonic-gate 			return (NULL);
1130Sstevel@tonic-gate 		thread_data->buflen = size;
1140Sstevel@tonic-gate 	}
1150Sstevel@tonic-gate 	return (thread_data->buf);
1160Sstevel@tonic-gate }
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate int
1190Sstevel@tonic-gate getmntany(FILE *fp, struct mnttab *mgetp, struct mnttab *mrefp)
1200Sstevel@tonic-gate {
1210Sstevel@tonic-gate 	int	ret, bstat;
1220Sstevel@tonic-gate 	mode_t	bmode;
1230Sstevel@tonic-gate 	dev_t	brdev;
1240Sstevel@tonic-gate 	struct stat64	statb;
1250Sstevel@tonic-gate 
126*380Seschrock 	/*
127*380Seschrock 	 * Ignore specials that don't correspond to real devices to avoid doing
128*380Seschrock 	 * unnecessary lookups in stat64().
129*380Seschrock 	 */
130*380Seschrock 	if (mrefp->mnt_special && mrefp->mnt_special[0] == '/' &&
131*380Seschrock 	    stat64(mrefp->mnt_special, &statb) == 0 &&
1320Sstevel@tonic-gate 	    ((bmode = (statb.st_mode & S_IFMT)) == S_IFBLK ||
1330Sstevel@tonic-gate 	    bmode == S_IFCHR)) {
1340Sstevel@tonic-gate 		bstat = 1;
1350Sstevel@tonic-gate 		brdev = statb.st_rdev;
1360Sstevel@tonic-gate 	} else {
1370Sstevel@tonic-gate 		bstat = 0;
1380Sstevel@tonic-gate 	}
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 	while ((ret = getmntent(fp, mgetp)) == 0 &&
1410Sstevel@tonic-gate 	    ((bstat == 0 && DIFF(mnt_special)) ||
1420Sstevel@tonic-gate 	    (bstat == 1 && SDIFF(mnt_special, bmode, brdev)) ||
1430Sstevel@tonic-gate 	    DIFF(mnt_mountp) ||
1440Sstevel@tonic-gate 	    DIFF(mnt_fstype) ||
1450Sstevel@tonic-gate 	    DIFF(mnt_mntopts) ||
1460Sstevel@tonic-gate 	    DIFF(mnt_time)))
1470Sstevel@tonic-gate 		;
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	return (ret);
1500Sstevel@tonic-gate }
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate int
1530Sstevel@tonic-gate getmntent(FILE *fp, struct mnttab *mp)
1540Sstevel@tonic-gate {
1550Sstevel@tonic-gate 	int	ret;
1560Sstevel@tonic-gate 	struct	extmnttab *emp;
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 	ret = ioctl(fileno(fp), MNTIOC_GETMNTENT, &emp);
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 	switch (ret) {
1610Sstevel@tonic-gate 		case 0:
1620Sstevel@tonic-gate 			return (convert_mntent(emp, (struct extmnttab *)mp, 0));
1630Sstevel@tonic-gate 		case 1:
1640Sstevel@tonic-gate 			return (-1);
1650Sstevel@tonic-gate 		default:
1660Sstevel@tonic-gate 			return (getmntent_compat(fp, mp));
1670Sstevel@tonic-gate 	}
1680Sstevel@tonic-gate }
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate char *
1710Sstevel@tonic-gate mntopt(char **p)
1720Sstevel@tonic-gate {
1730Sstevel@tonic-gate 	char *cp = *p;
1740Sstevel@tonic-gate 	char *retstr;
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	while (*cp && isspace(*cp))
1770Sstevel@tonic-gate 		cp++;
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 	retstr = cp;
1800Sstevel@tonic-gate 	while (*cp && *cp != ',')
1810Sstevel@tonic-gate 		cp++;
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate 	if (*cp) {
1840Sstevel@tonic-gate 		*cp = '\0';
1850Sstevel@tonic-gate 		cp++;
1860Sstevel@tonic-gate 	}
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 	*p = cp;
1890Sstevel@tonic-gate 	return (retstr);
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate char *
1930Sstevel@tonic-gate hasmntopt(struct mnttab *mnt, char *opt)
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate 	char tmpopts[MNT_LINE_MAX];
1960Sstevel@tonic-gate 	char *f, *opts = tmpopts;
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	if (mnt->mnt_mntopts == NULL)
1990Sstevel@tonic-gate 		return (NULL);
2000Sstevel@tonic-gate 	(void) strcpy(opts, mnt->mnt_mntopts);
2010Sstevel@tonic-gate 	f = mntopt(&opts);
2020Sstevel@tonic-gate 	for (; *f; f = mntopt(&opts)) {
2030Sstevel@tonic-gate 		if (strncmp(opt, f, strlen(opt)) == 0)
2040Sstevel@tonic-gate 			return (f - tmpopts + mnt->mnt_mntopts);
2050Sstevel@tonic-gate 	}
2060Sstevel@tonic-gate 	return (NULL);
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate /*ARGSUSED*/
2100Sstevel@tonic-gate int
2110Sstevel@tonic-gate getextmntent(FILE *fp, struct extmnttab *mp, size_t len)
2120Sstevel@tonic-gate {
2130Sstevel@tonic-gate 	int	ret;
2140Sstevel@tonic-gate 	struct	extmnttab *emp;
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate 	ret = ioctl(fileno(fp), MNTIOC_GETMNTENT, &emp);
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	switch (ret) {
2190Sstevel@tonic-gate 		case 0:
2200Sstevel@tonic-gate 			return (convert_mntent(emp, mp, 1));
2210Sstevel@tonic-gate 		case 1:
2220Sstevel@tonic-gate 			return (-1);
2230Sstevel@tonic-gate 		default:
2240Sstevel@tonic-gate 			return (ret);
2250Sstevel@tonic-gate 	}
2260Sstevel@tonic-gate }
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate void
2290Sstevel@tonic-gate resetmnttab(FILE *fp)
2300Sstevel@tonic-gate {
2310Sstevel@tonic-gate 	rewind(fp);
2320Sstevel@tonic-gate }
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate /*
2350Sstevel@tonic-gate  * This is a horrible function, necessary to support this broken interface.
2360Sstevel@tonic-gate  * Some callers of get(ext)mntent assume that the memory is valid even after the
2370Sstevel@tonic-gate  * file is closed.  Since we switched to a direct ioctl() interface, this is no
2380Sstevel@tonic-gate  * longer true.  In order to support these apps, we have to put the data into a
2390Sstevel@tonic-gate  * thread specific buffer.
2400Sstevel@tonic-gate  */
2410Sstevel@tonic-gate static int
2420Sstevel@tonic-gate convert_mntent(struct extmnttab *src, struct extmnttab *dst, int isext)
2430Sstevel@tonic-gate {
2440Sstevel@tonic-gate 	size_t len;
2450Sstevel@tonic-gate 	char *buf;
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	len = src->mnt_time - src->mnt_special + strlen(src->mnt_time) + 1;
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	buf = getmntbuf(len);
2500Sstevel@tonic-gate 	if (buf == NULL) {
2510Sstevel@tonic-gate 		errno = ENOMEM;
2520Sstevel@tonic-gate 		return (-1);
2530Sstevel@tonic-gate 	}
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	memcpy(buf, src->mnt_special, len);
2560Sstevel@tonic-gate 	dst->mnt_special = buf;
2570Sstevel@tonic-gate 	dst->mnt_mountp = buf + (src->mnt_mountp - src->mnt_special);
2580Sstevel@tonic-gate 	dst->mnt_fstype = buf + (src->mnt_fstype - src->mnt_special);
2590Sstevel@tonic-gate 	dst->mnt_mntopts = buf + (src->mnt_mntopts - src->mnt_special);
2600Sstevel@tonic-gate 	dst->mnt_time = buf + (src->mnt_time - src->mnt_special);
2610Sstevel@tonic-gate 	if (isext) {
2620Sstevel@tonic-gate 		dst->mnt_major = src->mnt_major;
2630Sstevel@tonic-gate 		dst->mnt_minor = src->mnt_minor;
2640Sstevel@tonic-gate 	}
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	return (0);
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate /*
2700Sstevel@tonic-gate  * Compatibility for non-mntfs files.  For backwards compatibility, we continue
2710Sstevel@tonic-gate  * to have to support this broken interface.  Note that getextmntent() has
2720Sstevel@tonic-gate  * always failed when using a file other than /etc/mnttab, because it relies on
2730Sstevel@tonic-gate  * an ioctl() call.
2740Sstevel@tonic-gate  */
2750Sstevel@tonic-gate static int
2760Sstevel@tonic-gate getline(char *lp, FILE *fp)
2770Sstevel@tonic-gate {
2780Sstevel@tonic-gate 	char	*cp;
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 	while ((lp = fgets(lp, MNT_LINE_MAX, fp)) != NULL) {
2810Sstevel@tonic-gate 		if (strlen(lp) == MNT_LINE_MAX-1 && lp[MNT_LINE_MAX-2] != '\n')
2820Sstevel@tonic-gate 			return (MNT_TOOLONG);
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 		for (cp = lp; *cp == ' ' || *cp == '\t'; cp++)
2850Sstevel@tonic-gate 			;
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 		if (*cp != '#' && *cp != '\n')
2880Sstevel@tonic-gate 			return (0);
2890Sstevel@tonic-gate 	}
2900Sstevel@tonic-gate 	return (-1);
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate static int
2940Sstevel@tonic-gate getmntent_compat(FILE *fp, struct mnttab *mp)
2950Sstevel@tonic-gate {
2960Sstevel@tonic-gate 	int	ret;
2970Sstevel@tonic-gate 	char	*tmp;
2980Sstevel@tonic-gate 	char	*line = getmntbuf(MNT_LINE_MAX);
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 	if (line == NULL) {
3010Sstevel@tonic-gate 		errno = ENOMEM;
3020Sstevel@tonic-gate 		return (-1);
3030Sstevel@tonic-gate 	}
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 	/* skip leading spaces and comments */
3060Sstevel@tonic-gate 	if ((ret = getline(line, fp)) != 0)
3070Sstevel@tonic-gate 		return (ret);
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	/* split up each field */
3100Sstevel@tonic-gate 	GETTOK_R(mnt_special, line, &tmp);
3110Sstevel@tonic-gate 	GETTOK_R(mnt_mountp, NULL, &tmp);
3120Sstevel@tonic-gate 	GETTOK_R(mnt_fstype, NULL, &tmp);
3130Sstevel@tonic-gate 	GETTOK_R(mnt_mntopts, NULL, &tmp);
3140Sstevel@tonic-gate 	GETTOK_R(mnt_time, NULL, &tmp);
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate 	/* check for too many fields */
3170Sstevel@tonic-gate 	if (strtok_r(NULL, sepstr, &tmp) != NULL)
3180Sstevel@tonic-gate 		return (MNT_TOOMANY);
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 	return (0);
3210Sstevel@tonic-gate }
322