2 * Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
28 * This file implements Solaris compatible getmntany() and hasmntopt()
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
35 #include <sys/param.h>
36 #include <sys/mount.h>
37 #include <sys/mntent.h>
38 #include <sys/mnttab.h>
53 while (*cp
&& isspace(*cp
))
57 while (*cp
&& *cp
!= ',')
70 hasmntopt(struct mnttab
*mnt
, const char *opt
)
72 char tmpopts
[MNT_LINE_MAX
];
73 char *f
, *opts
= tmpopts
;
75 if (mnt
->mnt_mntopts
== NULL
)
77 (void) strlcpy(opts
, mnt
->mnt_mntopts
, MNT_LINE_MAX
);
79 for (; *f
; f
= mntopt(&opts
)) {
80 if (strncmp(opt
, f
, strlen(opt
)) == 0)
81 return (f
- tmpopts
+ mnt
->mnt_mntopts
);
87 optadd(char *mntopts
, size_t size
, const char *opt
)
90 if (mntopts
[0] != '\0')
91 strlcat(mntopts
, ",", size
);
92 strlcat(mntopts
, opt
, size
);
95 static __thread
char gfstypename
[MFSNAMELEN
];
96 static __thread
char gmntfromname
[MNAMELEN
];
97 static __thread
char gmntonname
[MNAMELEN
];
98 static __thread
char gmntopts
[MNTMAXSTR
];
101 statfs2mnttab(struct statfs
*sfs
, struct mnttab
*mp
)
105 strlcpy(gfstypename
, sfs
->f_fstypename
, sizeof (gfstypename
));
106 mp
->mnt_fstype
= gfstypename
;
108 strlcpy(gmntfromname
, sfs
->f_mntfromname
, sizeof (gmntfromname
));
109 mp
->mnt_special
= gmntfromname
;
111 strlcpy(gmntonname
, sfs
->f_mntonname
, sizeof (gmntonname
));
112 mp
->mnt_mountp
= gmntonname
;
114 flags
= sfs
->f_flags
;
116 #define OPTADD(opt) optadd(gmntopts, sizeof (gmntopts), (opt))
117 if (flags
& MNT_RDONLY
)
121 if (flags
& MNT_NOSUID
)
122 OPTADD(MNTOPT_NOSETUID
);
124 OPTADD(MNTOPT_SETUID
);
125 if (flags
& MNT_UPDATE
)
126 OPTADD(MNTOPT_REMOUNT
);
127 if (flags
& MNT_NOATIME
)
128 OPTADD(MNTOPT_NOATIME
);
130 OPTADD(MNTOPT_ATIME
);
131 OPTADD(MNTOPT_NOXATTR
);
132 if (flags
& MNT_NOEXEC
)
133 OPTADD(MNTOPT_NOEXEC
);
137 mp
->mnt_mntopts
= gmntopts
;
140 static pthread_rwlock_t gsfs_lock
= PTHREAD_RWLOCK_INITIALIZER
;
141 static struct statfs
*gsfs
= NULL
;
142 static int allfs
= 0;
150 (void) pthread_rwlock_wrlock(&gsfs_lock
);
156 allfs
= getfsstat(NULL
, 0, MNT_NOWAIT
);
159 gsfs
= malloc(sizeof (gsfs
[0]) * allfs
* 2);
162 allfs
= getfsstat(gsfs
, (long)(sizeof (gsfs
[0]) * allfs
* 2),
166 sfs
= realloc(gsfs
, allfs
* sizeof (gsfs
[0]));
169 (void) pthread_rwlock_unlock(&gsfs_lock
);
177 (void) pthread_rwlock_unlock(&gsfs_lock
);
182 getmntany(FILE *fd __unused
, struct mnttab
*mgetp
, struct mnttab
*mrefp
)
186 error
= statfs_init();
190 (void) pthread_rwlock_rdlock(&gsfs_lock
);
192 for (i
= 0; i
< allfs
; i
++) {
193 if (mrefp
->mnt_special
!= NULL
&&
194 strcmp(mrefp
->mnt_special
, gsfs
[i
].f_mntfromname
) != 0) {
197 if (mrefp
->mnt_mountp
!= NULL
&&
198 strcmp(mrefp
->mnt_mountp
, gsfs
[i
].f_mntonname
) != 0) {
201 if (mrefp
->mnt_fstype
!= NULL
&&
202 strcmp(mrefp
->mnt_fstype
, gsfs
[i
].f_fstypename
) != 0) {
205 statfs2mnttab(&gsfs
[i
], mgetp
);
206 (void) pthread_rwlock_unlock(&gsfs_lock
);
209 (void) pthread_rwlock_unlock(&gsfs_lock
);
214 getmntent(FILE *fp
, struct mnttab
*mp
)
218 nfs
= (int)lseek(fileno(fp
), 0, SEEK_CUR
);
221 /* If nfs is 0, we want to refresh out cache. */
222 if (nfs
== 0 || gsfs
== NULL
) {
223 error
= statfs_init();
227 (void) pthread_rwlock_rdlock(&gsfs_lock
);
229 (void) pthread_rwlock_unlock(&gsfs_lock
);
232 statfs2mnttab(&gsfs
[nfs
], mp
);
233 (void) pthread_rwlock_unlock(&gsfs_lock
);
234 if (lseek(fileno(fp
), 1, SEEK_CUR
) == -1)