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 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
44 #include <instzones_api.h>
51 #define BASEDIR "/BASEDIR/"
53 #define INSTALF (*prog == 'i')
54 #define REMOVEF (*prog == 'r')
56 #define MSG_MANMOUNT "Assuming mounts were provided."
58 #define ERR_PKGNAME_TOO_LONG \
59 "The package name specified on the command line\n" \
60 "exceeds the maximum package name length: a package name may contain a\n" \
61 "maximum of <%d> characters; however, the package name specified on\n" \
62 "the command line contains <%d> characters, which exceeds the maximum\n" \
63 "package name length by <%d> characters. Please specify a package name\n" \
64 "that contains no more than <%d> characters."
66 #define ERR_DB_GET "unable to retrieve entries from the database."
67 #define ERR_DB_PUT "unable to update the package database."
68 #define ERR_ROOT_SET "Could not set install root from the environment."
69 #define ERR_ROOT_CMD "Command line install root contends with environment."
70 #define ERR_CLASSLONG "classname argument too long"
71 #define ERR_CLASSCHAR "bad character in classname"
72 #define ERR_INVAL "package instance <%s> is invalid"
73 #define ERR_NOTINST "package instance <%s> is not installed"
74 #define ERR_MERG "unable to merge contents file"
75 #define ERR_SORT "unable to sort contents file"
76 #define ERR_I_FAIL "installf did not complete successfully"
77 #define ERR_R_FAIL "removef did not complete successfully"
78 #define ERR_NOTROOT "You must be \"root\" for %s to execute properly."
79 #define ERR_USAGE0 "usage:\n" \
80 "\t%s [[-M|-A] -R host_path] [-V ...] pkginst path " \
82 "\t%s [[-M|-A] -R host_path] [-V ...] pkginst path\n"
84 #define ERR_USAGE1 "usage:\n" \
85 "\t%s [[-M] -R host_path] [-V ...] [-c class] <pkginst> " \
87 "\t%s [[-M] -R host_path] [-V ...] [-c class] <pkginst> " \
89 "\t where <specs> may be defined as:\n" \
90 "\t\tf <mode> <owner> <group>\n" \
91 "\t\tv <mode> <owner> <group>\n" \
92 "\t\te <mode> <owner> <group>\n" \
93 "\t\td <mode> <owner> <group>\n" \
94 "\t\tx <mode> <owner> <group>\n" \
95 "\t\tp <mode> <owner> <group>\n" \
96 "\t\tc <major> <minor> <mode> <owner> <group>\n" \
97 "\t\tb <major> <minor> <mode> <owner> <group>\n" \
98 "\t\ts <path>=<srcpath>\n" \
99 "\t\tl <path>=<srcpath>\n" \
100 "\t%s [[-M] -R host_path] [-V ...] [-c class] -f pkginst\n"
102 #define CMD_SORT "sort +0 -1"
106 extern char dbst
; /* libinst/pkgdbmerg.c */
108 struct cfextra
**extlist
;
109 struct pinfo
**eptlist
;
111 char *classname
= NULL
;
123 /* libadm/pkgparam.c */
124 extern void set_PKGADM(char *newpath
);
125 extern void set_PKGLOC(char *newpath
);
127 extern void set_limit(void);
130 main(int argc
, char **argv
)
133 PKGserver pkgserver
= NULL
;
137 char *vfstab_file
= NULL
;
138 char *temp_cl_basedir
;
139 char outbuf
[PATH_MAX
];
146 int pkgrmremote
= 0; /* don't remove remote files */
151 (void) signal(SIGHUP
, exit
);
152 (void) signal(SIGINT
, exit
);
153 (void) signal(SIGQUIT
, exit
);
155 /* initialize locale mechanism */
157 (void) setlocale(LC_ALL
, "");
159 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
160 #define TEXT_DOMAIN "SYS_TEST"
161 #endif /* !defined(TEXT_DOMAIN) */
163 (void) textdomain(TEXT_DOMAIN
);
165 /* determine program name */
167 prog
= set_prog_name(argv
[0]);
169 /* tell instzones interface how to access package output functions */
171 z_set_output_functions(echo
, echoDebug
, progerr
);
173 /* only allow root to run this program */
176 progerr(gettext(ERR_NOTROOT
), prog
);
180 ulim
= getenv("PKG_ULIMIT");
181 script
= getenv("PKG_PROC_SCRIPT");
183 if (ulim
&& script
) {
188 /* bug id 4244631, not ABI compliant */
189 abi_sym_ptr
= getenv("PKG_NONABI_SYMLINKS");
190 if (abi_sym_ptr
&& strncasecmp(abi_sym_ptr
, "TRUE", 4) == 0)
191 set_nonABI_symlinks();
194 if ((uniTmp
= getenv("PKG_NO_UNIFIED")) != NULL
)
196 if (!set_inst_root(getenv("PKG_INSTALL_ROOT"))) {
197 progerr(gettext(ERR_ROOT_SET
));
201 while ((c
= getopt(argc
, argv
, "c:V:fAMR:?")) != EOF
) {
209 /* validate that classname is acceptable */
210 if (strlen(classname
) > (size_t)CLSSIZ
) {
211 progerr(gettext(ERR_CLASSLONG
));
214 for (pt
= classname
; *pt
; pt
++) {
215 if (!isalpha(*pt
) && !isdigit(*pt
)) {
216 progerr(gettext(ERR_CLASSCHAR
));
223 * Don't map the client filesystem onto the server's. Assume
224 * the mounts have been made for us.
231 * Allow admin to establish the client filesystem using a
232 * vfstab-like file of stable format.
235 vfstab_file
= flex_device(optarg
, 2);
243 case 'R': /* added for newroot option */
244 if (!set_inst_root(optarg
)) {
245 progerr(gettext(ERR_ROOT_CMD
));
254 * Although usage() calls a noreturn function,
255 * needed to add return (1); so that main() would
256 * pass compilation checks. The statement below
257 * should never be executed.
263 if (pkgrmremote
&& (!is_an_inst_root() || fflag
|| INSTALF
)) {
269 * Get the mount table info and store internally.
271 if (get_mntinfo(map_client
, vfstab_file
))
275 * This function defines the standard /var/... directories used later
276 * to construct the paths to the various databases.
278 (void) set_PKGpaths(get_inst_root());
281 * If this is being installed on a client whose /var filesystem is
282 * mounted in some odd way, remap the administrative paths to the
283 * real filesystem. This could be avoided by simply mounting up the
284 * client now; but we aren't yet to the point in the process where
285 * modification of the filesystem is permitted.
287 if (is_an_inst_root()) {
290 fsys_value
= fsys(get_PKGLOC());
291 if (use_srvr_map_n(fsys_value
))
292 set_PKGLOC(server_map(get_PKGLOC(), fsys_value
));
294 fsys_value
= fsys(get_PKGADM());
295 if (use_srvr_map_n(fsys_value
))
296 set_PKGADM(server_map(get_PKGADM(), fsys_value
));
300 * get the package name and verify length is not too long
303 pkginst
= argv
[optind
++];
304 if (pkginst
== NULL
) {
312 progerr(gettext(ERR_PKGNAME_TOO_LONG
), PKGSIZ
, n
, n
-PKGSIZ
,
319 * The following is used to setup the environment. Note that the
320 * variable 'BASEDIR' is only meaningful for this utility if there
321 * is an install root, recorded in PKG_INSTALL_ROOT. Otherwise, this
322 * utility can create a file or directory anywhere unfettered by
323 * the basedir associated with the package instance.
325 if ((err
= set_basedirs(0, NULL
, pkginst
, 1)) != 0)
329 mkbasedir(0, get_basedir());
332 /* installf and removef must only have pkginst */
333 if (optind
!= argc
) {
339 * installf and removef must have at minimum
340 * pkginst & pathname specified on command line
342 if (optind
>= argc
) {
352 if (pkgnmchk(pkginst
, "all", 0)) {
353 progerr(gettext(ERR_INVAL
), pkginst
);
356 if (fpkginst(pkginst
, NULL
, NULL
) == NULL
) {
357 progerr(gettext(ERR_NOTINST
), pkginst
);
362 * This maps the client filesystems into the server's space.
364 if (map_client
&& !mount_client())
365 logerr(gettext(MSG_MANMOUNT
));
367 /* open the package database (contents) file */
369 if (!ocfile(&pkgserver
, &cfTmpVfp
, 0L)) {
374 dbchg
= dofinal(pkgserver
, cfTmpVfp
, REMOVEF
, classname
, prog
);
378 if (installf(argc
-optind
, &argv
[optind
]))
382 removef(argc
-optind
, &argv
[optind
]);
385 dbchg
= pkgdbmerg(pkgserver
, cfTmpVfp
, extlist
);
387 progerr(gettext(ERR_MERG
));
393 if ((n
= swapcfile(pkgserver
, &cfTmpVfp
, pkginst
, 1))
396 } else if (n
== RESULT_ERR
) {
403 if (REMOVEF
&& !fflag
) {
404 for (n
= 0; extlist
[n
]; n
++) {
405 ept
= &(extlist
[n
]->cf_ent
);
407 /* Skip duplicated paths */
408 if ((n
> 0) && (strncmp(ept
->path
,
409 extlist
[n
-1]->cf_ent
.path
, PATH_MAX
) == 0)) {
413 if (!extlist
[n
]->mstat
.shared
) {
415 * Only output paths that can be deleted.
416 * so need to skip if the object is owned
417 * by a remote server and removal is not
421 (ept
->pinfo
->status
== SERVED_FILE
) &&
426 if (is_a_cl_basedir() && !is_an_inst_root()) {
428 * A path in contents db might have
429 * other prefix than BASEDIR of the
432 temp_cl_basedir
= get_client_basedir();
433 if (strncmp(ept
->path
, temp_cl_basedir
,
434 strlen(temp_cl_basedir
)) == 0) {
435 c
= strlen(temp_cl_basedir
);
436 (void) snprintf(outbuf
,
437 sizeof (outbuf
), "%s/%s\n",
441 (void) snprintf(outbuf
,
443 "%s\n", &(ept
->path
[c
]));
445 } else if (is_an_inst_root()) {
446 (void) snprintf(outbuf
, sizeof (outbuf
),
447 "%s/%s\n", get_inst_root(),
450 (void) snprintf(outbuf
, sizeof (outbuf
),
451 "%s\n", &(ept
->path
[c
]));
454 (void) printf("%s", outbuf
);
457 } else if (INSTALF
&& !fflag
) {
458 for (n
= 0; extlist
[n
]; n
++) {
459 ept
= &(extlist
[n
]->cf_ent
);
461 if (strchr("dxcbp", ept
->ftype
)) {
462 tp
= fixpath(ept
->path
);
463 (void) averify(1, &ept
->ftype
, tp
, &ept
->ainfo
);
468 pkgcloseserver(pkgserver
);
470 z_destroyMountTable();
472 quit(warnflag
? 1 : 0);
473 /* LINTED: no return */
479 char *prog
= get_prog_name();
483 if (ulim
&& script
) {
485 set_ulimit(script
, gettext(ERR_R_FAIL
));
487 set_ulimit(script
, gettext(ERR_I_FAIL
));
497 char *prog
= get_prog_name();
500 (void) fprintf(stderr
, gettext(ERR_USAGE0
), prog
, prog
);
502 (void) fprintf(stderr
, gettext(ERR_USAGE1
), prog
, prog
, prog
);