8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / cmd / svr4pkg / libinst / open_package_datastream.c
blob2896a99e807dac6667e8e917ac722b3651893fb2
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 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 #include <stdio.h>
29 #include <time.h>
30 #include <wait.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <ulimit.h>
34 #include <sys/stat.h>
35 #include <sys/statvfs.h>
36 #include <assert.h>
37 #include <fcntl.h>
38 #include <errno.h>
39 #include <ctype.h>
40 #include <dirent.h>
41 #include <string.h>
42 #include <signal.h>
43 #include <locale.h>
44 #include <libintl.h>
45 #include <pkgstrct.h>
46 #include <pkginfo.h>
47 #include <pkgdev.h>
48 #include <pkglocs.h>
49 #include <pwd.h>
50 #include <pkglib.h>
51 #include <libinst.h>
52 #include <libadm.h>
53 #include <messages.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
90 boolean_t
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)
95 int n;
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) {
117 *r_repeat = 0;
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:
139 * - char *device
140 * - char *label
141 * - int options
142 * - char *prompt
143 * - char *norewind - no rewind device (NULL to use device)
144 * Returns:
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);
157 switch (n) {
158 case 0: /* volume open, label matches */
159 if (ds_readbuf(a_pkgdev->cdevice)) {
160 (*r_idsName) = a_pkgdev->cdevice;
162 break;
163 case 3: /* user selected quit */
164 quit(3);
165 /* NOTREACHED */
166 case 2: /* unknown device (devattr failed) */
167 progerr(ERR_UNKNOWN_DEV, a_pkgdev->name);
168 quit(99);
169 /* NOTREACHED */
170 default: /* device not accessable */
171 progerr(ERR_PKGVOL);
172 logerr(LOG_GETVOL_RET, n);
173 quit(99);
174 /* NOTREACHED */
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;
188 } else {
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.
198 if (a_spoolDir) {
199 return (B_TRUE);
202 /* create temp dir for op if input data stream specified */
204 if (*r_idsName) {
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));
212 quit(99);
213 /* NOTREACHED */
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,
234 a_pkgdev->mount);
235 a_pkgdev->rdonly++;
236 n = pkgmount(a_pkgdev, NULL, 0, 0, 0);
237 if (n != 0) {
238 /* pkgmount failed */
239 return (B_FALSE);
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,
254 a_pkgdev->norewind);
256 switch (n) {
257 case 0: /* volume open, label matches */
258 break;
259 case 3: /* user selected quit */
260 quit(3);
261 /* NOTREACHED */
262 case 2: /* unknown device (devattr failed) */
263 progerr(ERR_UNKNOWN_DEV, a_pkgdev->name);
264 quit(99);
265 /* NOTREACHED */
266 default:
267 progerr(ERR_PKGVOL);
268 logerr(LOG_GETVOL_RET, n);
269 quit(99);
270 /* NOTREACHED */
274 if (chdir(a_pkgdev->dirname)) {
275 progerr(ERR_CHDIR, a_pkgdev->dirname);
276 quit(99);
277 /* NOTREACHED */
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);
292 quit(99);
293 /* NOTREACHED */
297 return (B_TRUE);