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