geniconvtbl: put full cpp path in its argv
[unleashed.git] / usr / src / lib / libfsmgt / common / nfs_mntinfo.c
blobd39eb812c633a6d559859cc3d6ce7569c05c24f6
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <kvm.h>
33 #include <kstat.h>
34 #include <sys/types.h>
35 #include <sys/mnttab.h>
36 #include <sys/mntent.h>
37 #include <nfs/nfs.h>
38 #include <nfs/nfs_clnt.h>
39 #include <sys/mkdev.h>
40 #include <inttypes.h>
41 #include <sys/stat.h>
44 #include "libfsmgt.h"
45 #include "replica.h"
47 #define IGNORE 0
48 #define DEV 1
51 * Private variables
54 static char *mntopts[] = { MNTOPT_IGNORE, MNTOPT_DEV, NULL };
57 * Private method declarations
60 static int ignore(char *);
61 static int get_kstat_info(nfs_mntlist_t *, int *);
62 static nfs_mntlist_t *get_mount_data(fs_mntlist_t *, int *);
63 static nfs_mntlist_t *get_nfs_info(fs_mntlist_t *, int *);
64 static nfs_mntlist_t *kstat_mount(nfs_mntlist_t *, kstat_t *);
65 static int load_kstat_data(kstat_ctl_t *, nfs_mntlist_t *, kstat_t *, int *);
66 static kid_t safe_kstat_read(kstat_ctl_t *, kstat_t *, void *, int *);
69 * Public methods
72 void
73 nfs_free_mntinfo_list(nfs_mntlist_t *list)
75 nfs_mntlist_t *tmp;
76 int i;
78 while (list != NULL) {
79 free(list->nml_resource);
80 free(list->nml_mountp);
81 free(list->nml_fstype);
82 free(list->nml_mntopts);
83 free(list->nml_time);
84 for (i = 0; i < list->nml_failovercount; i++) {
85 free(list->nml_failoverlist[i]);
87 free(list->nml_failoverlist);
88 free(list->nml_securitymode);
89 tmp = list->next;
90 free(list);
91 list = tmp;
93 } /* nfs_free_mntinfo_list */
95 nfs_mntlist_t *
96 nfs_get_filtered_mount_list(char *resource, char *mountp, char *mntopts,
97 char *time, boolean_t find_overlays, int *errp) {
99 fs_mntlist_t *fs_mount_list;
100 nfs_mntlist_t *nfs_mount_list;
102 fs_mount_list = fs_get_filtered_mount_list(resource, mountp,
103 MNTTYPE_NFS, mntopts, time, find_overlays, errp);
104 if (fs_mount_list == NULL) {
105 return (NULL);
108 if ((nfs_mount_list = get_nfs_info(fs_mount_list, errp)) == NULL) {
109 fs_free_mount_list(fs_mount_list);
110 return (NULL);
113 fs_free_mount_list(fs_mount_list);
114 return (nfs_mount_list);
115 } /* nfs_get_filtered_mount_list */
117 nfs_mntlist_t *
118 nfs_get_mounts_by_mntopt(char *mntopt, boolean_t find_overlays, int *errp)
120 fs_mntlist_t *fs_mount_list;
121 nfs_mntlist_t *nfs_mount_list;
123 fs_mount_list = fs_get_mounts_by_mntopt(mntopt, find_overlays, errp);
124 if (fs_mount_list == NULL) {
125 return (NULL);
128 if ((nfs_mount_list = get_nfs_info(fs_mount_list, errp)) == NULL) {
129 fs_free_mount_list(fs_mount_list);
130 return (NULL);
133 fs_free_mount_list(fs_mount_list);
134 return (nfs_mount_list);
135 } /* nfs_get_mount_by_mntopt */
137 nfs_mntlist_t *
138 nfs_get_mount_list(int *errp)
140 fs_mntlist_t *fs_mount_list;
141 nfs_mntlist_t *nfs_mount_list;
142 boolean_t find_overlays = B_TRUE;
144 if ((fs_mount_list = fs_get_mount_list(find_overlays, errp)) == NULL) {
145 fprintf(stderr, "nfs_mntinfo: Can't access mnttab. %s\n",
146 strerror(*errp));
147 return (NULL);
150 if ((nfs_mount_list = get_nfs_info(fs_mount_list, errp)) == NULL) {
151 fs_free_mount_list(fs_mount_list);
152 return (NULL);
155 fs_free_mount_list(fs_mount_list);
156 return (nfs_mount_list);
157 } /* nfs_get_mount_list */
160 * Private methods
163 static int
164 get_kstat_info(nfs_mntlist_t *nfs_mntinfo, int *errp)
166 kstat_ctl_t *libkstat_cookie = NULL;
167 nfs_mntlist_t *mrp;
168 kstat_t *ksp;
170 if ((libkstat_cookie = kstat_open()) == NULL) {
171 *errp = errno;
172 fprintf(stderr,
173 "nfs_mntinfo: kstat_open(): can't open /dev/kstat.\n");
174 return (-1);
177 * Each kstat consists of header and data sections that are
178 * connected as a "chain" or linked list of kstat stuctures.
179 * The kc_chain used here is the pointer to the global kstat
180 * chain (or the head of the chain of kstat's).
182 for (ksp = libkstat_cookie->kc_chain; ksp; ksp = ksp->ks_next) {
183 if ((ksp->ks_type == KSTAT_TYPE_RAW) &&
184 (strcmp(ksp->ks_module, "nfs") == 0) &&
185 (strcmp(ksp->ks_name, "mntinfo") == 0) &&
186 ((mrp = kstat_mount(nfs_mntinfo, ksp)) != NULL)) {
187 if (load_kstat_data(libkstat_cookie, mrp, ksp, errp)
188 == -1) {
189 nfs_free_mntinfo_list(mrp);
190 return (-1);
194 return (0);
195 } /* get_kstat_info */
197 static int
198 load_kstat_data(kstat_ctl_t *libkstat_cookie, nfs_mntlist_t *mrp,
199 kstat_t *ksp, int *errp)
201 struct mntinfo_kstat mik;
202 seconfig_t nfs_sec;
204 if (mrp == 0) {
205 return (0);
208 if (safe_kstat_read(libkstat_cookie, ksp, &mik, errp) == -1) {
209 return (-1);
212 if (strlcpy(mrp->nml_proto, mik.mik_proto, KNC_STRSIZE)
213 >= KNC_STRSIZE) {
214 *errp = errno;
215 return (-1);
217 if (strlcpy(mrp->nml_curserver, mik.mik_curserver, SYS_NMLN)
218 >= SYS_NMLN) {
219 *errp = errno;
220 return (-1);
222 mrp->nml_vers = mik.mik_vers;
224 * get the secmode name from /etc/nfssec.conf.
226 if (!nfs_getseconfig_bynumber(mik.mik_secmod, &nfs_sec)) {
227 mrp->nml_securitymode = strdup(nfs_sec.sc_name);
228 } else {
229 mrp->nml_securitymode = NULL;
231 mrp->nml_curread = mik.mik_curread;
232 mrp->nml_curwrite = mik.mik_curwrite;
233 mrp->nml_timeo = mik.mik_timeo;
234 mrp->nml_retrans = mik.mik_retrans;
235 mrp->nml_acregmin = mik.mik_acregmin;
236 mrp->nml_acregmax = mik.mik_acregmax;
237 mrp->nml_acdirmin = mik.mik_acdirmin;
238 mrp->nml_acdirmax = mik.mik_acdirmax;
239 mrp->nml_hard =
240 ((mik.mik_flags & MI_HARD) ? B_TRUE : B_FALSE);
241 mrp->nml_intr =
242 ((mik.mik_flags & MI_INT) ? B_TRUE : B_FALSE);
243 mrp->nml_noac =
244 ((mik.mik_flags & MI_NOAC) ? B_TRUE : B_FALSE);
245 mrp->nml_nocto =
246 ((mik.mik_flags & MI_NOCTO) ? B_TRUE : B_FALSE);
247 mrp->nml_grpid =
248 ((mik.mik_flags & MI_GRPID) ? B_TRUE : B_FALSE);
249 mrp->nml_directio =
250 ((mik.mik_flags & MI_DIRECTIO) ? B_TRUE : B_FALSE);
251 mrp->nml_xattr =
252 ((mik.mik_flags & MI_EXTATTR) ? B_TRUE : B_FALSE);
253 return (0);
256 nfs_mntlist_t *
257 kstat_mount(nfs_mntlist_t *nfs_mntinfo, kstat_t *ksp) {
258 nfs_mntlist_t *mrp;
260 * MAXMIN is used to retrieve the minor number
261 * which is compared to the kstat instance.
262 * If they are the same then this is an instance
263 * for which mount information is needed.
264 * MAXMIN is the maximum minor number and is
265 * defined in mkdev.h.
267 mrp = nfs_mntinfo;
268 while ((mrp != NULL) &&
269 ((mrp->nml_fsid & MAXMIN) != ksp->ks_instance)) {
270 mrp = mrp->next;
272 return (mrp);
275 static nfs_mntlist_t *
276 get_nfs_info(fs_mntlist_t *fslist, int *errp) {
277 nfs_mntlist_t *mrp = NULL;
278 nfs_mntlist_t *headptr = NULL;
279 nfs_mntlist_t *tailptr = NULL;
280 fs_mntlist_t *fsmnt_list;
282 for (fsmnt_list = fslist; fsmnt_list; fsmnt_list = fsmnt_list->next) {
283 /* ignore non "nfs" and the "ignore" entries */
285 if ((strcmp(fsmnt_list->fstype, MNTTYPE_NFS) != 0) ||
286 (ignore(fsmnt_list->mntopts))) {
287 continue;
290 if ((mrp = get_mount_data(fsmnt_list, errp)) == NULL) {
291 nfs_free_mntinfo_list(headptr);
292 return (NULL);
294 if (tailptr == NULL) {
295 headptr = mrp;
296 tailptr = mrp;
297 tailptr->next = NULL;
298 } else {
299 tailptr->next = mrp;
300 tailptr = mrp;
301 tailptr->next = NULL;
305 if (get_kstat_info(headptr, errp) == -1) {
306 nfs_free_mntinfo_list(mrp);
307 return (NULL);
309 return (headptr);
311 } /* get_nfs_info */
314 static nfs_mntlist_t *
315 get_mount_data(fs_mntlist_t *fsmnt_list, int *errp) {
316 struct replica *rep_list; /* defined in replica.h */
317 nfs_mntlist_t *mrp;
318 int i, server_count = 0;
319 struct stat stat_buf;
321 if ((mrp = malloc(sizeof (nfs_mntlist_t))) == 0) {
322 *errp = errno;
323 return (NULL);
326 if ((stat(fsmnt_list->mountp, &stat_buf) == 0)) {
327 mrp->nml_fsid = stat_buf.st_dev;
328 } else {
329 *errp = errno;
330 nfs_free_mntinfo_list(mrp);
331 return (NULL);
334 if ((mrp->nml_resource = strdup(fsmnt_list->resource))
335 == NULL) {
336 *errp = errno;
337 nfs_free_mntinfo_list(mrp);
338 return (NULL);
340 if ((rep_list =
341 parse_replica(mrp->nml_resource, &server_count)) == NULL) {
342 nfs_free_mntinfo_list(mrp);
343 return (NULL);
345 if ((mrp->nml_failoverlist =
346 calloc(server_count, sizeof (char *))) == NULL) {
347 nfs_free_mntinfo_list(mrp);
348 return (NULL);
350 for (i = 0; i < server_count; i++) {
351 mrp->nml_failoverlist[i] =
352 malloc(strlen(rep_list[i].host) + strlen(":") +
353 strlen(rep_list[i].path) + 2);
354 if (!mrp->nml_failoverlist[i]) {
355 nfs_free_mntinfo_list(mrp);
356 return (NULL);
358 sprintf(mrp->nml_failoverlist[i], "%s%s%s",
359 rep_list[i].host, ":", rep_list[i].path);
362 * If the number of servers is not 1 then resource is
363 * either a failover list or there is an error. In either
364 * case the path can't be determined and curpath is set to
365 * unknown".
367 if (server_count == 1) {
368 if (strcmp(rep_list[0].host, "nfs") == 0) {
369 char *path;
370 char *last;
371 path = strdup(rep_list[0].path);
372 if ((path = (char *)strtok_r(path, "//",
373 &last)) != NULL) {
374 strcpy(mrp->nml_curpath,
375 strcat("/", last));
376 } else {
378 * If NULL is returned this is an
379 * invalid path entry. no path can
380 * be determined.
382 strcpy(mrp->nml_curpath, "unknown");
384 } else {
385 strcpy(mrp->nml_curpath,
386 (strchr(mrp->nml_failoverlist[0],
387 ':') + 1));
389 } else {
391 * more than one server in the failover list
392 * path can't be determined.
394 strcpy(mrp->nml_curpath, "unknown");
397 mrp->nml_failovercount = server_count;
399 for (i = 0; i < server_count; i++) {
400 if (rep_list[i].host) {
401 free(rep_list[i].host);
403 if (rep_list[i].path) {
404 free(rep_list[i].path);
407 free(rep_list);
409 if ((mrp->nml_mountp = strdup(fsmnt_list->mountp)) == NULL) {
410 *errp = errno;
411 nfs_free_mntinfo_list(mrp);
412 return (NULL);
414 if ((mrp->nml_fstype = strdup(fsmnt_list->fstype)) == NULL) {
415 *errp = errno;
416 nfs_free_mntinfo_list(mrp);
417 return (NULL);
419 if ((mrp->nml_mntopts = strdup(fsmnt_list->mntopts)) == NULL) {
420 *errp = errno;
421 nfs_free_mntinfo_list(mrp);
422 return (NULL);
424 if ((mrp->nml_time = strdup(fsmnt_list->time)) == NULL) {
425 *errp = errno;
426 nfs_free_mntinfo_list(mrp);
427 return (NULL);
429 if (fsmnt_list->overlayed) {
430 mrp->nml_overlayed = B_TRUE;
431 } else {
432 mrp->nml_overlayed = B_FALSE;
434 return (mrp);
435 } /* get_mount_data */
437 kid_t
438 safe_kstat_read(
439 kstat_ctl_t *libkstat_cookie,
440 kstat_t *ksp,
441 void *data,
442 int *errp)
445 kid_t kstat_chain_id = kstat_read(libkstat_cookie, ksp, data);
447 if (kstat_chain_id == -1) {
448 *errp = errno;
449 return (-1);
451 return (kstat_chain_id);
452 } /* safe_kstat_read */
456 * ignore - Checks for the ignore mount option in the mount opts string.
457 * Returns 1 if the ignore option is found and 0 if not.
459 static int
460 ignore(char *opts)
462 char *value;
463 char *s;
464 char *tmp;
466 if (opts == NULL)
467 return (0);
468 s = strdup(opts);
469 if (s == NULL)
470 return (0);
472 tmp = s;
474 while (*s != '\0') {
475 if (getsubopt(&s, mntopts, &value) == IGNORE) {
476 free(tmp);
477 return (1);
480 free(tmp);
481 return (0);
482 } /* ignore */