Home | History | Annotate | Line # | Download | only in libzfs
      1 /*     $NetBSD: mnttab.c,v 1.4 2019/01/27 02:08:34 pgoyette Exp $  */
      2 
      3 /*-
      4  * Copyright (c) 2006 Pawel Jakub Dawidek <pjd (at) FreeBSD.org>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 /*
     30  * This file implements Solaris compatible getmntany() and hasmntopt()
     31  * functions.
     32  */
     33 
     34 #include <sys/cdefs.h>
     35 __FBSDID("$FreeBSD: head/cddl/compat/opensolaris/misc/mnttab.c 209962 2010-07-12 23:49:04Z mm $");
     36 __RCSID("$NetBSD: mnttab.c,v 1.4 2019/01/27 02:08:34 pgoyette Exp $");
     37 
     38 #include <sys/param.h>
     39 #include <sys/statvfs.h>
     40 #include <sys/mntent.h>
     41 #include <sys/mnttab.h>
     42 
     43 #include <stdio.h>
     44 #include <errno.h>
     45 #include <stdio.h>
     46 #include <stdlib.h>
     47 #include <string.h>
     48 #include <ctype.h>
     49 
     50 char *
     51 mntopt(char **p)
     52 {
     53 	char *cp = *p;
     54 	char *retstr;
     55 
     56 	while (*cp && isspace(*cp))
     57 		cp++;
     58 
     59 	retstr = cp;
     60 	while (*cp && *cp != ',')
     61 		cp++;
     62 
     63 	if (*cp) {
     64 		*cp = '\0';
     65 		cp++;
     66 	}
     67 
     68 	*p = cp;
     69 	return (retstr);
     70 }
     71 
     72 char *
     73 hasmntopt(struct mnttab *mnt, char *opt)
     74 {
     75 	char tmpopts[MNT_LINE_MAX];
     76 	char *f, *opts = tmpopts;
     77 
     78 	if (mnt->mnt_mntopts == NULL)
     79 		return (NULL);
     80 	(void) strcpy(opts, mnt->mnt_mntopts);
     81 	f = mntopt(&opts);
     82 	for (; *f; f = mntopt(&opts)) {
     83 		if (strncmp(opt, f, strlen(opt)) == 0)
     84 			return (f - tmpopts + mnt->mnt_mntopts);
     85 	}
     86 	return (NULL);
     87 }
     88 
     89 static void
     90 optadd(char *mntopts, size_t size, const char *opt)
     91 {
     92 
     93 	if (mntopts[0] != '\0')
     94 		strlcat(mntopts, ",", size);
     95 	strlcat(mntopts, opt, size);
     96 }
     97 
     98 void
     99 statvfs2mnttab(struct statvfs *sfs, struct mnttab *mp)
    100 {
    101 	static char mntopts[MNTMAXSTR];
    102 	long flags;
    103 
    104 	mntopts[0] = '\0';
    105 
    106 	flags = sfs->f_flag;
    107 #define	OPTADD(opt)	optadd(mntopts, sizeof(mntopts), (opt))
    108 	if (flags & MNT_RDONLY)
    109 		OPTADD(MNTOPT_RO);
    110 	else
    111 		OPTADD(MNTOPT_RW);
    112 	if (flags & MNT_NOSUID)
    113 		OPTADD(MNTOPT_NOSUID);
    114 	else
    115 		OPTADD(MNTOPT_SETUID);
    116 	if (flags & MNT_UPDATE)
    117 		OPTADD(MNTOPT_REMOUNT);
    118 	if (flags & MNT_NOATIME)
    119 		OPTADD(MNTOPT_NOATIME);
    120 	else
    121 		OPTADD(MNTOPT_ATIME);
    122 	OPTADD(MNTOPT_NOXATTR);
    123 	if (flags & MNT_NOEXEC)
    124 		OPTADD(MNTOPT_NOEXEC);
    125 	else
    126 		OPTADD(MNTOPT_EXEC);
    127 #undef	OPTADD
    128 	mp->mnt_special = sfs->f_mntfromname;
    129 	mp->mnt_mountp = sfs->f_mntonname;
    130 	mp->mnt_fstype = sfs->f_fstypename;
    131 	mp->mnt_mntopts = mntopts;
    132 }
    133 
    134 static struct statvfs *gsfs;
    135 static int allfs;
    136 
    137 static int
    138 statvfs_init(void)
    139 {
    140 	struct statvfs *sfs;
    141 	int error;
    142 
    143 	if (gsfs != NULL) {
    144 		free(gsfs);
    145 		gsfs = NULL;
    146 	}
    147 	allfs = getvfsstat(NULL, 0, ST_WAIT);
    148 	if (allfs == -1)
    149 		goto fail;
    150 	gsfs = malloc(sizeof(gsfs[0]) * allfs * 2);
    151 	if (gsfs == NULL)
    152 		goto fail;
    153 	allfs = getvfsstat(gsfs, sizeof(gsfs[0]) * allfs * 2, ST_WAIT);
    154 	if (allfs == -1)
    155 		goto fail;
    156 	sfs = realloc(gsfs, allfs * sizeof(gsfs[0]));
    157 	if (sfs != NULL)
    158 		gsfs = sfs;
    159 	return (0);
    160 fail:
    161 	error = errno;
    162 	if (gsfs != NULL)
    163 		free(gsfs);
    164 	gsfs = NULL;
    165 	allfs = 0;
    166 	return (error);
    167 }
    168 
    169 int
    170 getmntany(FILE *fd, struct mnttab *mgetp, struct mnttab *mrefp)
    171 {
    172 	int i, error;
    173 
    174 	error = statvfs_init();
    175 	if (error != 0)
    176 		return (error);
    177 
    178 	for (i = 0; i < allfs; i++) {
    179 		if (mrefp->mnt_special != NULL &&
    180 		    strcmp(mrefp->mnt_special, gsfs[i].f_mntfromname) != 0) {
    181 			continue;
    182 		}
    183 		if (mrefp->mnt_mountp != NULL &&
    184 		    strcmp(mrefp->mnt_mountp, gsfs[i].f_mntonname) != 0) {
    185 			continue;
    186 		}
    187 		if (mrefp->mnt_fstype != NULL &&
    188 		    strcmp(mrefp->mnt_fstype, gsfs[i].f_fstypename) != 0) {
    189 			continue;
    190 		}
    191 		statvfs2mnttab(&gsfs[i], mgetp);
    192 		return (0);
    193 	}
    194 	return (-1);
    195 }
    196 
    197 int
    198 getmntent(FILE *fp, struct mnttab *mp)
    199 {
    200 	struct statvfs *sfs;
    201 	int error, nfs;
    202 
    203 	nfs = (int)lseek(fileno(fp), 0, SEEK_CUR);
    204 	if (nfs == -1)
    205 		return (errno);
    206 	/* If nfs is 0, we want to refresh our cache. */
    207 	if (nfs == 0 || gsfs == NULL) {
    208 		error = statvfs_init();
    209 		if (error != 0)
    210 			return (error);
    211 	}
    212 	if (nfs >= allfs)
    213 		return (-1);
    214 	statvfs2mnttab(&gsfs[nfs], mp);
    215 	if (lseek(fileno(fp), 1, SEEK_CUR) == -1)
    216 		return (errno);
    217 	return (0);
    218 }
    219