add some more missing things to known_extras
[unleashed-kayak.git] / src / mount_media.c
blob2a05fde827e30905b1b52f46f65af9aa711cc040
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
27 * The install boot_archive contains a minimal set of utilities under /usr and
28 * devfs is not populated. The SMF service live-fs-root bootstraps the process
29 * by locating the media device and mounting the compressed /usr and /opt
30 * to provide a fully functioning system. This utility traverses the device
31 * tree looking for devices that potentially contain the media image, mounts
32 * each in turn and checks whether it contains the volume set id passed on
33 * the comamnd line. An exit of 0 means we succeeded, non-zero means we failed.
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <fcntl.h>
41 #include <libdevinfo.h>
42 #include <limits.h>
43 #include <sys/sunddi.h>
44 #include <sys/types.h>
45 #include <sys/dkio.h>
46 #include <sys/mount.h>
47 #include <sys/stat.h>
49 #define HSFS_OPTS "ro"
50 #define UFS_OPTS "nologging,noatime"
52 static boolean_t mounted = B_FALSE;
54 static int
55 check_volsetid(const char *volid)
57 FILE *fp;
58 char buf[BUFSIZ], *cp;
59 int ret = -1;
61 /* Check volume set id against requested */
62 if ((fp = fopen("/.cdrom/.volsetid", "r")) != NULL) {
63 if (fgets(buf, BUFSIZ, fp) != NULL) {
64 /* Strip newline if present */
65 if ((cp = strchr(buf, '\n')) != NULL)
66 *cp = '\0';
67 ret = strcmp(volid, buf);
69 (void) fclose(fp);
71 return (ret);
74 static int
75 mount_image(const char *path, const char *volid)
77 int ret = -1;
78 char opts[MAX_MNTOPT_STR];
80 /* First try mounting it as hsfs; if that fails, try ufs */
81 strcpy(opts, HSFS_OPTS);
82 if (mount(path, "/.cdrom", MS_RDONLY | MS_OPTIONSTR, "hsfs",
83 NULL, 0, opts, sizeof (opts)) != 0) {
84 strcpy(opts, UFS_OPTS);
85 if (mount(path, "/.cdrom", MS_OPTIONSTR, "ufs", NULL, 0,
86 opts, sizeof (opts)) != 0)
87 return (ret);
90 /* Mounted, see if it's the image we're looking for, unmount if not */
91 ret = check_volsetid(volid);
92 if (ret != 0)
93 (void) umount("/.cdrom");
94 return (ret);
98 * Callback function for di_walk_minor. For each node that appears to match
99 * our criteria (a USB block device, or a CD), mount it and see if it
100 * matches the volume set id passed on the command line. If so, we're done
101 * and can terminate the walk. In all error cases, just continue walking the
102 * tree.
104 static int
105 mount_minor(di_node_t node, di_minor_t minor, void *arg)
107 int fd, ret, **prop;
108 struct dk_cinfo dkinfo;
109 char *nt, *mnp, *cp, *volid = (char *)arg;
110 char mpath[PATH_MAX];
112 nt = di_minor_nodetype(minor);
113 if (nt == NULL)
114 return (DI_WALK_CONTINUE);
116 mnp = di_devfs_minor_path(minor);
117 if (mnp == NULL)
118 return (DI_WALK_CONTINUE);
120 strcpy(mpath, "/devices");
121 strlcat(mpath, mnp, PATH_MAX);
123 /*printf("Checking %s\n", mnp);*/
125 /* If it's a block device and claims to be USB, try mounting it */
126 if ((di_minor_spectype(minor) == S_IFBLK) &&
127 (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "usb", prop) != -1))
128 goto mount;
130 /* Node type is a CD. Try mounting it */
131 if (strstr(nt, DDI_NT_CD) != NULL ||
132 strstr(nt, DDI_NT_CD_CHAN) != NULL)
133 goto mount;
136 * If node type is not marked, Xvm devices for instance
137 * need to check device type via ioctls
139 if ((fd = open(mpath, O_NDELAY | O_RDONLY)) == -1)
140 goto end;
141 ret = ioctl(fd, DKIOCINFO, &dkinfo);
142 (void) close(fd);
143 if (ret != 0 || dkinfo.dki_ctype != DKC_CDROM)
144 goto end;
146 mount:
147 /* Remove raw suffix from path to get to block device for mount */
148 if ((cp = strstr(mpath, ",raw")) != NULL)
149 *cp = '\0';
150 if (mount_image(mpath, volid) == 0)
152 printf("Found %s media at %s\n", volid, mpath);
153 mounted = B_TRUE;
156 end:
157 di_devfs_path_free(mnp);
158 return (mounted ? DI_WALK_TERMINATE : DI_WALK_CONTINUE);
161 int main(int argc, char **argv)
163 di_node_t root_node;
165 if (argc == 1) {
166 fprintf(stderr, "Usage: %s <volsetid>\n", argv[0]);
167 return (1);
170 /* Initialize libdevinfo and walk the tree */
171 if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
172 return (1);
174 (void) di_walk_minor(root_node, DDI_NT_BLOCK, 0, argv[1], mount_minor);
175 di_fini(root_node);
177 return (mounted ? 0 : 1);