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]
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.
41 #include <libdevinfo.h>
43 #include <sys/sunddi.h>
44 #include <sys/types.h>
46 #include <sys/mount.h>
49 #define HSFS_OPTS "ro"
50 #define UFS_OPTS "nologging,noatime"
52 static boolean_t mounted
= B_FALSE
;
55 check_volsetid(const char *volid
)
58 char buf
[BUFSIZ
], *cp
;
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
)
67 ret
= strcmp(volid
, buf
);
75 mount_image(const char *path
, const char *volid
)
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)
90 /* Mounted, see if it's the image we're looking for, unmount if not */
91 ret
= check_volsetid(volid
);
93 (void) umount("/.cdrom");
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
105 mount_minor(di_node_t node
, di_minor_t minor
, void *arg
)
108 struct dk_cinfo dkinfo
;
109 char *nt
, *mnp
, *cp
, *volid
= (char *)arg
;
110 char mpath
[PATH_MAX
];
112 nt
= di_minor_nodetype(minor
);
114 return (DI_WALK_CONTINUE
);
116 mnp
= di_devfs_minor_path(minor
);
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))
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
)
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)
141 ret
= ioctl(fd
, DKIOCINFO
, &dkinfo
);
143 if (ret
!= 0 || dkinfo
.dki_ctype
!= DKC_CDROM
)
147 /* Remove raw suffix from path to get to block device for mount */
148 if ((cp
= strstr(mpath
, ",raw")) != NULL
)
150 if (mount_image(mpath
, volid
) == 0)
152 printf("Found %s media at %s\n", volid
, mpath
);
157 di_devfs_path_free(mnp
);
158 return (mounted
? DI_WALK_TERMINATE
: DI_WALK_CONTINUE
);
161 int main(int argc
, char **argv
)
166 fprintf(stderr
, "Usage: %s <volsetid>\n", argv
[0]);
170 /* Initialize libdevinfo and walk the tree */
171 if ((root_node
= di_init("/", DINFOCPYALL
)) == DI_NODE_NIL
) {
174 (void) di_walk_minor(root_node
, DDI_NT_BLOCK
, 0, argv
[1], mount_minor
);
177 return (mounted
? 0 : 1);