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