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/param.h>
33 #include <sys/mount.h>
34 #include <sys/mntent.h>
35 #include <sys/mnttab.h>
50 while (*cp
&& isspace(*cp
))
54 while (*cp
&& *cp
!= ',')
67 hasmntopt(struct mnttab
*mnt
, const char *opt
)
69 char tmpopts
[MNT_LINE_MAX
];
70 char *f
, *opts
= tmpopts
;
72 if (mnt
->mnt_mntopts
== NULL
)
74 (void) strlcpy(opts
, mnt
->mnt_mntopts
, MNT_LINE_MAX
);
76 for (; *f
; f
= mntopt(&opts
)) {
77 if (strncmp(opt
, f
, strlen(opt
)) == 0)
78 return (f
- tmpopts
+ mnt
->mnt_mntopts
);
84 optadd(char *mntopts
, size_t size
, const char *opt
)
87 if (mntopts
[0] != '\0')
88 strlcat(mntopts
, ",", size
);
89 strlcat(mntopts
, opt
, size
);
92 static __thread
char gfstypename
[MFSNAMELEN
];
93 static __thread
char gmntfromname
[MNAMELEN
];
94 static __thread
char gmntonname
[MNAMELEN
];
95 static __thread
char gmntopts
[MNTMAXSTR
];
98 statfs2mnttab(struct statfs
*sfs
, struct mnttab
*mp
)
102 strlcpy(gfstypename
, sfs
->f_fstypename
, sizeof (gfstypename
));
103 mp
->mnt_fstype
= gfstypename
;
105 strlcpy(gmntfromname
, sfs
->f_mntfromname
, sizeof (gmntfromname
));
106 mp
->mnt_special
= gmntfromname
;
108 strlcpy(gmntonname
, sfs
->f_mntonname
, sizeof (gmntonname
));
109 mp
->mnt_mountp
= gmntonname
;
111 flags
= sfs
->f_flags
;
113 #define OPTADD(opt) optadd(gmntopts, sizeof (gmntopts), (opt))
114 if (flags
& MNT_RDONLY
)
118 if (flags
& MNT_NOSUID
)
119 OPTADD(MNTOPT_NOSETUID
);
121 OPTADD(MNTOPT_SETUID
);
122 if (flags
& MNT_UPDATE
)
123 OPTADD(MNTOPT_REMOUNT
);
124 if (flags
& MNT_NOATIME
)
125 OPTADD(MNTOPT_NOATIME
);
127 OPTADD(MNTOPT_ATIME
);
128 OPTADD(MNTOPT_NOXATTR
);
129 if (flags
& MNT_NOEXEC
)
130 OPTADD(MNTOPT_NOEXEC
);
134 mp
->mnt_mntopts
= gmntopts
;
137 static pthread_rwlock_t gsfs_lock
= PTHREAD_RWLOCK_INITIALIZER
;
138 static struct statfs
*gsfs
= NULL
;
139 static int allfs
= 0;
147 (void) pthread_rwlock_wrlock(&gsfs_lock
);
153 allfs
= getfsstat(NULL
, 0, MNT_NOWAIT
);
156 gsfs
= malloc(sizeof (gsfs
[0]) * allfs
* 2);
159 allfs
= getfsstat(gsfs
, (long)(sizeof (gsfs
[0]) * allfs
* 2),
163 sfs
= realloc(gsfs
, allfs
* sizeof (gsfs
[0]));
166 (void) pthread_rwlock_unlock(&gsfs_lock
);
174 (void) pthread_rwlock_unlock(&gsfs_lock
);
179 getmntany(FILE *fd __unused
, struct mnttab
*mgetp
, struct mnttab
*mrefp
)
183 error
= statfs_init();
187 (void) pthread_rwlock_rdlock(&gsfs_lock
);
189 for (i
= 0; i
< allfs
; i
++) {
190 if (mrefp
->mnt_special
!= NULL
&&
191 strcmp(mrefp
->mnt_special
, gsfs
[i
].f_mntfromname
) != 0) {
194 if (mrefp
->mnt_mountp
!= NULL
&&
195 strcmp(mrefp
->mnt_mountp
, gsfs
[i
].f_mntonname
) != 0) {
198 if (mrefp
->mnt_fstype
!= NULL
&&
199 strcmp(mrefp
->mnt_fstype
, gsfs
[i
].f_fstypename
) != 0) {
202 statfs2mnttab(&gsfs
[i
], mgetp
);
203 (void) pthread_rwlock_unlock(&gsfs_lock
);
206 (void) pthread_rwlock_unlock(&gsfs_lock
);
211 getmntent(FILE *fp
, struct mnttab
*mp
)
215 nfs
= (int)lseek(fileno(fp
), 0, SEEK_CUR
);
218 /* If nfs is 0, we want to refresh out cache. */
219 if (nfs
== 0 || gsfs
== NULL
) {
220 error
= statfs_init();
224 (void) pthread_rwlock_rdlock(&gsfs_lock
);
226 (void) pthread_rwlock_unlock(&gsfs_lock
);
229 statfs2mnttab(&gsfs
[nfs
], mp
);
230 (void) pthread_rwlock_unlock(&gsfs_lock
);
231 if (lseek(fileno(fp
), 1, SEEK_CUR
) == -1)