5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28 /*
29 * System includes
30 */
31
32 #include <stdio.h>
33 #include <limits.h>
34 #include <errno.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <libgen.h>
38 #include <string.h>
39 #include <wait.h>
40 #include <signal.h>
41 #include <malloc.h>
42 #include <sys/types.h>
43 #include <sys/mount.h>
44 #include <sys/stat.h>
88
89 /* returned by already_mounted() */
90 #define MNT_NOT 0
91 #define MNT_EXACT 1
92 #define MNT_AVAIL 2
93
94 /* used with is_remote_src() */
95 #define NOT_REMOTE 0
96 #define REAL_REMOTE 1
97 #define SELF_SERVE 2
98
99 /*
100 * Due to /etc/mnttab files containing entries for multiple nfs hosts
101 * HOST_NM_LN needs to be accommodating. The recommended value in the sysinfo
102 * man page of 257 needs to be expanded. See bugid 4076513.
103 * 1024 chars is defined in the mnttab.h header as the max size of an entry.
104 */
105
106 #define HOST_NM_LN MNT_LINE_MAX
107
108 /* These cachefs definitions should be in mntent.h. Maybe some day. */
109 #define MNTTYPE_CFS "cachefs"
110 #define MNTOPT_BACKFSTYPE "backfstype"
111 #define MNTTYPE_AUTO "autofs"
112
113 /*
114 * Utilities for getting filesystem information from the mount table.
115 *
116 * Note: vanilla SVr4 code (pkginstall/dockspace.c) used the output from
117 * popen() on the "/etc/mount" command. However, we need to get more
118 * information about mounted filesystems, so we use the C interfaces to
119 * the mount table, which also happens to be much faster than running
120 * another process. Since several of the pkg commands need access to the
121 * the code has been placed here, to be included in the libinst library.
122 */
123
124 #define ALLOC_CHUNK 30
125
126 /*
127 * fs_tab_ent_comp - compare fstable entries first by length in reverse
128 * order, then alphabetically.
129 */
130 static int
131 fs_tab_ent_comp(const void *e1, const void *e2)
132 {
210
211 (void) close(fd);
212 (void) unlink(testfile);
213
214 return (retval);
215 }
216
217 /* This returns the hostname portion of a remote path. */
218 char *
219 get_server_host(uint32_t n)
220 {
221 static char hostname[HOST_NM_LN], *host_end;
222
223 if (fs_tab_used == 0) {
224 return ("unknown source");
225 }
226
227 if (n < fs_tab_used) {
228 (void) strcpy(hostname, fs_tab[n]->remote_name);
229 if ((host_end = strchr(hostname, ':')) == NULL) {
230 if ((strcmp(fs_tab[n]->fstype, MNTTYPE_AUTO)) == NULL)
231 return ("automounter");
232 else
233 return (fs_tab[n]->fstype);
234 } else {
235 *host_end = '\0';
236 return (hostname);
237 }
238 }
239
240 return ("unknown source");
241 }
242
243 /*
244 * This pulls the path out of a hostpath which may be of the form host:path
245 * where path is an absolute path. NOTE: If path turns out to be relative,
246 * this returns NULL.
247 */
248 static char *
249 path_part(char *hostpath)
250 {
697 * into fs_tab[].
698 */
699 static int
700 construct_mt(struct mnttab *mt)
701 {
702 struct fstable *nfte;
703
704 /*
705 * Initialize fstable structure and make the standard entries.
706 */
707 if ((nfte = fs_tab_init(mt->mnt_mountp, mt->mnt_fstype)) == NULL)
708 return (1);
709
710 /*
711 * See if this is served from another host.
712 * Testing the type is cheap; finding the hostname is not.
713 * At this point, we're using the REAL mnttab; since we're not
714 * allowed to mount ourself with "NFS", "NFS" must be remote.
715 * The automount will translate "nfs:self" to a lofs mount.
716 */
717 if (strcmp(mt->mnt_fstype, MNTTYPE_AUTO) == 0 ||
718 strcmp(mt->mnt_fstype, MNTTYPE_NFS) == 0 ||
719 is_remote_src(mt->mnt_special) == REAL_REMOTE)
720 nfte->remote = 1;
721 else
722 nfte->remote = 0;
723
724 /* It's mounted now (by definition), so we don't have to remap it. */
725 nfte->srvr_map = 0;
726 nfte->mounted = 1;
727
728 nfte->remote_name = strdup(mt->mnt_special);
729
730 /*
731 * This checks the mount commands which establish the most
732 * basic level of access. Later further tests may be
733 * necessary to fully qualify this. We set this bit
734 * preliminarily because we have access to the mount data
735 * now.
736 */
737 nfte->writeable = 0; /* Assume read-only. */
946 strcmp(vfs->vfs_fstype, MNTTYPE_LOFS) !=
947 0)
948 continue; /* not interesting */
949
950 /*
951 * Construct client_mountp by prepending the
952 * install_root to the 'mount point' name.
953 */
954 if (strcmp(vfs->vfs_mountp, "/") == 0) {
955 (void) strcpy(client_mountp,
956 install_root);
957 } else {
958 (void) snprintf(client_mountp,
959 sizeof (client_mountp), "%s%s",
960 install_root, vfs->vfs_mountp);
961 }
962
963 /*
964 * We also skip the entry if the vfs_special
965 * path and the client_path are the same.
966 * There's no need to mount it, it's just a
967 * cachefs optimization that mounts a
968 * directory over itself from this server.
969 */
970 if ((is_remote == SELF_SERVE) &&
971 strcmp(path_part(vfs->vfs_special),
972 client_mountp) == 0)
973 continue;
974
975 /* Determine if this is already mounted. */
976 link_name = strdup(path_part(vfs->vfs_special));
977 mnt_stat = already_mounted(vfs,
978 (is_remote != REAL_REMOTE), client_mountp,
979 link_name);
980
981 if (mnt_stat == MNT_EXACT) {
982 mod_existing(vfs, match_mount,
983 is_remote);
984 } else { /* MNT_NOT */
985 if (construct_vfs(vfs, client_mountp,
986 link_name, is_remote, mnt_stat)) {
987 return (1);
988 }
|
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
26 */
27
28
29 /*
30 * System includes
31 */
32
33 #include <stdio.h>
34 #include <limits.h>
35 #include <errno.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <libgen.h>
39 #include <string.h>
40 #include <wait.h>
41 #include <signal.h>
42 #include <malloc.h>
43 #include <sys/types.h>
44 #include <sys/mount.h>
45 #include <sys/stat.h>
89
90 /* returned by already_mounted() */
91 #define MNT_NOT 0
92 #define MNT_EXACT 1
93 #define MNT_AVAIL 2
94
95 /* used with is_remote_src() */
96 #define NOT_REMOTE 0
97 #define REAL_REMOTE 1
98 #define SELF_SERVE 2
99
100 /*
101 * Due to /etc/mnttab files containing entries for multiple nfs hosts
102 * HOST_NM_LN needs to be accommodating. The recommended value in the sysinfo
103 * man page of 257 needs to be expanded. See bugid 4076513.
104 * 1024 chars is defined in the mnttab.h header as the max size of an entry.
105 */
106
107 #define HOST_NM_LN MNT_LINE_MAX
108
109 /*
110 * Utilities for getting filesystem information from the mount table.
111 *
112 * Note: vanilla SVr4 code (pkginstall/dockspace.c) used the output from
113 * popen() on the "/etc/mount" command. However, we need to get more
114 * information about mounted filesystems, so we use the C interfaces to
115 * the mount table, which also happens to be much faster than running
116 * another process. Since several of the pkg commands need access to the
117 * the code has been placed here, to be included in the libinst library.
118 */
119
120 #define ALLOC_CHUNK 30
121
122 /*
123 * fs_tab_ent_comp - compare fstable entries first by length in reverse
124 * order, then alphabetically.
125 */
126 static int
127 fs_tab_ent_comp(const void *e1, const void *e2)
128 {
206
207 (void) close(fd);
208 (void) unlink(testfile);
209
210 return (retval);
211 }
212
213 /* This returns the hostname portion of a remote path. */
214 char *
215 get_server_host(uint32_t n)
216 {
217 static char hostname[HOST_NM_LN], *host_end;
218
219 if (fs_tab_used == 0) {
220 return ("unknown source");
221 }
222
223 if (n < fs_tab_used) {
224 (void) strcpy(hostname, fs_tab[n]->remote_name);
225 if ((host_end = strchr(hostname, ':')) == NULL) {
226 if ((strcmp(fs_tab[n]->fstype, MNTTYPE_AUTOFS)) == NULL)
227 return ("automounter");
228 else
229 return (fs_tab[n]->fstype);
230 } else {
231 *host_end = '\0';
232 return (hostname);
233 }
234 }
235
236 return ("unknown source");
237 }
238
239 /*
240 * This pulls the path out of a hostpath which may be of the form host:path
241 * where path is an absolute path. NOTE: If path turns out to be relative,
242 * this returns NULL.
243 */
244 static char *
245 path_part(char *hostpath)
246 {
693 * into fs_tab[].
694 */
695 static int
696 construct_mt(struct mnttab *mt)
697 {
698 struct fstable *nfte;
699
700 /*
701 * Initialize fstable structure and make the standard entries.
702 */
703 if ((nfte = fs_tab_init(mt->mnt_mountp, mt->mnt_fstype)) == NULL)
704 return (1);
705
706 /*
707 * See if this is served from another host.
708 * Testing the type is cheap; finding the hostname is not.
709 * At this point, we're using the REAL mnttab; since we're not
710 * allowed to mount ourself with "NFS", "NFS" must be remote.
711 * The automount will translate "nfs:self" to a lofs mount.
712 */
713 if (strcmp(mt->mnt_fstype, MNTTYPE_AUTOFS) == 0 ||
714 strcmp(mt->mnt_fstype, MNTTYPE_NFS) == 0 ||
715 is_remote_src(mt->mnt_special) == REAL_REMOTE)
716 nfte->remote = 1;
717 else
718 nfte->remote = 0;
719
720 /* It's mounted now (by definition), so we don't have to remap it. */
721 nfte->srvr_map = 0;
722 nfte->mounted = 1;
723
724 nfte->remote_name = strdup(mt->mnt_special);
725
726 /*
727 * This checks the mount commands which establish the most
728 * basic level of access. Later further tests may be
729 * necessary to fully qualify this. We set this bit
730 * preliminarily because we have access to the mount data
731 * now.
732 */
733 nfte->writeable = 0; /* Assume read-only. */
942 strcmp(vfs->vfs_fstype, MNTTYPE_LOFS) !=
943 0)
944 continue; /* not interesting */
945
946 /*
947 * Construct client_mountp by prepending the
948 * install_root to the 'mount point' name.
949 */
950 if (strcmp(vfs->vfs_mountp, "/") == 0) {
951 (void) strcpy(client_mountp,
952 install_root);
953 } else {
954 (void) snprintf(client_mountp,
955 sizeof (client_mountp), "%s%s",
956 install_root, vfs->vfs_mountp);
957 }
958
959 /*
960 * We also skip the entry if the vfs_special
961 * path and the client_path are the same.
962 */
963 if ((is_remote == SELF_SERVE) &&
964 strcmp(path_part(vfs->vfs_special),
965 client_mountp) == 0)
966 continue;
967
968 /* Determine if this is already mounted. */
969 link_name = strdup(path_part(vfs->vfs_special));
970 mnt_stat = already_mounted(vfs,
971 (is_remote != REAL_REMOTE), client_mountp,
972 link_name);
973
974 if (mnt_stat == MNT_EXACT) {
975 mod_existing(vfs, match_mount,
976 is_remote);
977 } else { /* MNT_NOT */
978 if (construct_vfs(vfs, client_mountp,
979 link_name, is_remote, mnt_stat)) {
980 return (1);
981 }
|