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 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
35 #include <sys/statvfs.h>
56 * *****************************************************************************
57 * global external (public) functions
58 * *****************************************************************************
62 * open package datastream
63 * Arguments: a_argc - (int) - [RO, *RO]
64 * - number of arguments available in a_argv
65 * a_argv - (char **) - [RO, *RO]
66 * - arguments representing package names to add
67 * a_spoolDir - (char *) - [RO, *RO]
68 * - directory to write the package (spool) into
69 * - if == (char *)NULL then install the packages
70 * - if != (char *)NULL then write packages into directory
71 * a_device - (char *) - [RO, *RO]
72 * - device to read packages from when spooling
73 * - ignored if a_spoolDir == (char *)NULL
74 * r_repeat - (int *) - [RO, *RW]
75 * - set == 0 if no further package names in argc/argv
76 * - set != 0 IF there are package names in argc/argv
77 * - if == (int *)NULL - not set
78 * r_idsName - (char **) - [RW, *RW]
79 * - set to the name of package input data stream device
80 * - if == (char *)NULL - no input data stream; that is,
81 * -- the packages are in a directory and not in a stream
82 * - if != (char *)NULL - this is the device/file that
83 * -- is the datastream that contains the packages to add
84 * a_pkgdev - (struct pkgdev *) - [RO, *RW]
85 * - pkgdev structure containing package device to open
86 * Returns: B_TRUE - datastream opened successfully
87 * B_FALSE - datastream failed to open
91 open_package_datastream(int a_argc
, char **a_argv
, char *a_spoolDir
,
92 char *a_device
, int *r_repeat
, char **r_idsName
, char *a_tmpdir
,
93 struct pkgdev
*a_pkgdev
, int a_optind
)
97 /* entry assertions */
99 assert(a_argv
!= (char **)NULL
);
100 assert(r_idsName
!= (char **)NULL
);
101 assert(a_tmpdir
!= (char *)NULL
);
102 assert(a_pkgdev
!= (struct pkgdev
*)NULL
);
104 /* entry debug information */
106 echoDebug(DBG_ODS_ENTRY
);
107 echoDebug(DBG_ODS_ARGS
,
108 a_pkgdev
->bdevice
? a_pkgdev
->bdevice
: "?",
109 a_pkgdev
->cdevice
? a_pkgdev
->cdevice
: "?",
110 a_pkgdev
->pathname
? a_pkgdev
->pathname
: "?",
111 a_argc
, a_device
? a_device
: "?");
113 /* reset possible return values to defaults */
115 *r_idsName
= (char *)NULL
;
116 if (r_repeat
!= (int *)NULL
) {
121 * Determine how to access the package source "device":
122 * - if a block device is associated with the source:
123 * -- make sure the next "volume" is mounted and ready.
124 * -- input data stream is associated character device
125 * - if char device but no block device associated with device:
126 * -- input data stream is associated character device
127 * - else if a path is associated with device:
128 * -- input data stream is associated path
131 if (a_pkgdev
->bdevice
!= (char *)NULL
) {
132 /* package source is block device */
135 * _getvol verifies that the specified device is accessible and
136 * that a volume of the appropriate medium has been inserted.
137 * _getvol is in libadm.h - delivered by ON as part of SUNWcsl
138 * is somewhat analagous to getvol(1M) - args are:
143 * - char *norewind - no rewind device (NULL to use device)
145 * 0 - okay, label matches
146 * 1 - device not accessable
147 * 2 - unknown device (devattr failed)
148 * 3 - user selected quit
149 * 4 - label does not match
152 echoDebug(DBG_ODS_DATASTREAM_BDEV
, a_pkgdev
->bdevice
);
154 n
= _getvol(a_pkgdev
->bdevice
, NULL
, 0L,
155 MSG_INSERT_VOL
, a_pkgdev
->norewind
);
158 case 0: /* volume open, label matches */
159 if (ds_readbuf(a_pkgdev
->cdevice
)) {
160 (*r_idsName
) = a_pkgdev
->cdevice
;
163 case 3: /* user selected quit */
166 case 2: /* unknown device (devattr failed) */
167 progerr(ERR_UNKNOWN_DEV
, a_pkgdev
->name
);
170 default: /* device not accessable */
172 logerr(LOG_GETVOL_RET
, n
);
176 } else if (a_pkgdev
->cdevice
!= (char *)NULL
) {
177 /* package source is character device */
179 echoDebug(DBG_ODS_DATASTREAM_CDEV
, a_pkgdev
->cdevice
);
181 (*r_idsName
) = a_pkgdev
->cdevice
;
182 } else if (a_pkgdev
->pathname
!= (char *)NULL
) {
183 /* package source is path name to file */
185 echoDebug(DBG_ODS_DATASTREAM_ISFILE
, a_pkgdev
->pathname
);
187 (*r_idsName
) = a_pkgdev
->pathname
;
189 echoDebug(DBG_ODS_DATASTREAM_UNK
);
193 * If writing the packages into a spool directory instead of
194 * installing the packages, invoke pkgtrans to perform the
195 * conversion and exit.
202 /* create temp dir for op if input data stream specified */
206 * initialize datastream,
207 * dirname is set to directory where package is unstreamed
209 if (setup_temporary_directory(&a_pkgdev
->dirname
, a_tmpdir
,
210 "dstream") == B_FALSE
) {
211 progerr(ERR_STREAMDIR
, strerror(errno
));
217 if (r_repeat
!= (int *)NULL
) {
218 *r_repeat
= (a_optind
>= a_argc
);
222 * mount source device (e.g. floppy) if no input data stream
223 * specified, and the package source device is mountable. If
224 * the pkgmount fails, go back and try to mount the package
225 * source again. When a package is split up into multiple
226 * volumes (such as floppies), it might be possible to go back
227 * and insert a different copy of the required volume/floppy
228 * if the current one cannot be mounted. Otherwise this could
229 * have just called quit() if the mount failed...
232 if (((*r_idsName
) == (char *)NULL
) && a_pkgdev
->mount
) {
233 echoDebug(DBG_ODS_DATASTREAM_MOUNTING
, *r_idsName
,
236 n
= pkgmount(a_pkgdev
, NULL
, 0, 0, 0);
238 /* pkgmount failed */
244 * open and initialize input data stream if specified
247 if ((*r_idsName
) != (char *)NULL
) {
248 echoDebug(DBG_ODS_DATASTREAM_INIT
, *r_idsName
);
250 /* use character device to force rewind of datastream */
251 if ((a_pkgdev
->cdevice
!= (char *)NULL
) &&
252 (a_pkgdev
->bdevice
== (char *)NULL
)) {
253 n
= _getvol(a_pkgdev
->name
, NULL
, 0L, NULL
,
257 case 0: /* volume open, label matches */
259 case 3: /* user selected quit */
262 case 2: /* unknown device (devattr failed) */
263 progerr(ERR_UNKNOWN_DEV
, a_pkgdev
->name
);
268 logerr(LOG_GETVOL_RET
, n
);
274 if (chdir(a_pkgdev
->dirname
)) {
275 progerr(ERR_CHDIR
, a_pkgdev
->dirname
);
281 * initialize datastream for subsequent installation;
282 * read the source device;
283 * aquire the header data and check it for validity;
284 * creates subdirectories in package stream directory
285 * (a_pkgdev->dirname) for each package and retrieves each
286 * packages pkginfo and pkgmap files
289 if (ds_init(*r_idsName
, &a_argv
[a_optind
],
290 a_pkgdev
->norewind
)) {
291 progerr(ERR_DSINIT
, *r_idsName
);