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) 2017 Peter Tribble.
27 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
31 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
32 /* All Rights Reserved */
45 #include <sys/types.h>
56 #define MSG_CHK_STRM "Checking uninstalled stream format package " \
58 #define MSG_CHK_DIR "Checking uninstalled directory format package " \
60 #define MSG_NOTROOT "NOTE: \"root\" permission may be required to " \
61 "validate all objects in the client filesystem."
62 #define MSG_CONT "Continuing."
64 #define WRN_F_SPOOL "WARNING: %s is spooled. Ignoring \"f\" argument"
66 #define ERR_ROOT_SET "Could not set install root from the environment."
67 #define ERR_ROOT_CMD "Command line install root contends with environment."
68 #define ERR_IOPEN "unable to open input file <%s>"
69 #define ERR_IEMPTY "no pathnames in file specified by -i option"
70 #define ERR_POPTION "no pathname included with -p option"
71 #define ERR_PARTIAL_POPTION "no pathname included with -P option"
72 #define ERR_MAXPATHS "too many pathnames in option list (limit is %d)"
73 #define ERR_NOTROOT "You must be \"root\" for \"%s -f\" to" \
75 #define ERR_SEL_PKG "No packages selected for verification."
76 #define ERR_CAT_LNGTH "The category argument exceeds the SVr4 ABI\n" \
77 " defined maximum supported length of 16 characters."
78 #define ERR_CAT_FND "Category argument <%s> cannot be found."
79 #define ERR_CAT_INV "Category argument <%s> is invalid."
80 #define ERR_TOO_MANY "too many pathnames in list, limit is %d"
81 #define ERR_PATHS_INVALID "Pathnames in %s are not valid."
82 #define ERR_MKDIR "unable to make directory <%s>"
83 #define ERR_USAGE "usage:\n" \
84 "\t%s [-l|vqacnxf] [-R rootdir] [-p path[, ...] | " \
86 "\t\t[-i file] [options]\n" \
87 "\t%s -d device [-f][-l|v] [-p path[, ...] | " \
89 "\t\t[-V ...] [-M] [-i file] [-Y category[, ...] | " \
91 "\twhere options may include ONE of the " \
93 "\t\t-m pkgmap [-e envfile]\n" \
94 "\t\tpkginst [...]\n" \
95 "\t\t-Y category[, ...]\n"
102 char *pathlist
[MAXPATHS
], *ppathlist
[MAXPATHS
], pkgspool
[PATH_MAX
];
103 short used
[MAXPATHS
];
105 struct cfent
**eptlist
;
122 static char *mapfile
,
126 static int errflg
= 0;
127 static int map_client
= 1;
130 static void setpathlist(char *);
131 static void usage(void);
133 extern char **environ
;
137 extern int checkmap(int, int, char *, char *, char *, char *, int);
139 extern int checkscripts(char *inst_dir
, int silent
);
142 main(int argc
, char *argv
[])
144 int pkgfmt
= 0; /* Makes more sense as a pointer, but */
145 /* 18N is compromised. */
146 char file
[PATH_MAX
+1],
149 char *all_pkgs
[4] = {"all", NULL
};
150 char **category
= NULL
;
151 char *catg_arg
= NULL
;
159 /* initialize locale mechanism */
161 (void) setlocale(LC_ALL
, "");
163 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
164 #define TEXT_DOMAIN "SYS_TEST"
166 (void) textdomain(TEXT_DOMAIN
);
168 /* determine program name */
170 prog
= set_prog_name(argv
[0]);
172 /* establish installation root directory */
174 if (!set_inst_root(getenv("PKG_INSTALL_ROOT"))) {
175 progerr(gettext(ERR_ROOT_SET
));
179 /* check if not ABI compliant mode */
180 abi_sym_ptr
= getenv("PKG_NONABI_SYMLINKS");
181 if (abi_sym_ptr
&& strncasecmp(abi_sym_ptr
, "TRUE", 4) == 0) {
182 set_nonABI_symlinks();
186 if ((uniTmp
= getenv("PKG_NO_UNIFIED")) != NULL
)
189 while ((c
= getopt(argc
, argv
, "Y:R:e:p:d:nLli:vaV:Mm:cqxfP:?"))
193 pathlist
[npaths
] = strtok(optarg
, " , ");
194 if (pathlist
[npaths
++] == NULL
) {
195 progerr(gettext(ERR_POPTION
));
198 while (pathlist
[npaths
] = strtok(NULL
, " , ")) {
199 if (npaths
++ >= MAXPATHS
) {
200 progerr(gettext(ERR_MAXPATHS
),
221 * Allow admin to establish the client filesystem using a
222 * vfstab-like file of stable format.
225 vfstab_file
= flex_device(optarg
, 2);
231 progerr(gettext(ERR_NOTROOT
), prog
);
291 catg_arg
= strdup(optarg
);
293 if ((category
= get_categories(catg_arg
)) == NULL
) {
294 progerr(gettext(ERR_CAT_INV
), catg_arg
);
296 } else if (is_not_valid_length(category
)) {
297 progerr(gettext(ERR_CAT_LNGTH
));
303 ppathlist
[npaths
] = strtok(optarg
, " , ");
304 if ((ppathlist
[npaths
] == NULL
) ||
305 (ppathlist
[npaths
][0] == '-')) {
306 progerr(gettext(ERR_PARTIAL_POPTION
));
310 while (ppathlist
[npaths
] = strtok(NULL
, " , ")) {
311 if (npaths
++ >= MAXPATHS
) {
312 progerr(gettext(ERR_MAXPATHS
),
323 * Although usage() calls a noreturn function,
324 * needed to add return (1); so that main() would
325 * pass compilation checks. The statement below
326 * should never be executed.
332 /* Check for incompatible options */
336 /* Check for root dir and device dir if set */
338 if (!set_inst_root(Rvalue
)) {
339 progerr(gettext(ERR_ROOT_CMD
));
345 device
= flex_device(dvalue
, 1);
347 if (lflag
|| Lflag
) {
348 /* we're only supposed to list information */
349 if ((cflag
>= 0) || (aflag
>= 0) ||
350 qflag
|| xflag
|| fflag
|| nflag
|| vflag
)
354 set_PKGpaths(get_inst_root());
356 if (catg_arg
!= NULL
&& device
== NULL
) {
360 pkg
= gpkglist(pkgdir
, all_pkgs
, category
);
362 progerr(gettext(ERR_CAT_FND
), catg_arg
);
365 for (pkgcnt
= 0; pkg
[pkgcnt
] != NULL
; pkgcnt
++)
368 } else if (catg_arg
!= NULL
&& optind
< argc
) {
372 pkgcnt
= (argc
- optind
);
375 /* read the environment for the pkgserver */
376 pkgserversetmode(DEFAULTMODE
);
378 environ
= NULL
; /* Sever the parent environment. */
386 /* check for incompatible options */
387 if (device
|| pkgcnt
)
389 put_path_params(); /* Restore what's needed. */
391 /* send pathtype if partial path */
392 pathtype
= (ppathlist
[0] != NULL
) ? 1 : 0;
393 if (checkmap(0, (device
!= NULL
), mapfile
, envfile
, NULL
,
397 /* check for incompatible options */
398 if ((cflag
>= 0) || (aflag
>= 0))
400 if (qflag
|| xflag
|| nflag
|| envfile
)
403 if ((spooldir
= devattr(device
, "pathname")) == NULL
)
405 if (isdir(spooldir
)) {
406 tmpdir
= spooldir
= qstrdup(tmpnam(NULL
));
408 logerr(gettext(WRN_F_SPOOL
), *pkg
);
411 if (mkdir(spooldir
, 0755)) {
412 progerr(gettext(ERR_MKDIR
), spooldir
);
415 if (n
= pkgtrans(device
, spooldir
, pkg
, PT_SILENT
))
417 if (catg_arg
!= NULL
)
418 pkg
= gpkglist(spooldir
, all_pkgs
, category
);
420 pkg
= gpkglist(spooldir
, all_pkgs
, NULL
);
423 if (catg_arg
!= NULL
)
424 pkg
= gpkglist(spooldir
,
425 pkgcnt
? pkg
: all_pkgs
, category
);
427 pkg
= gpkglist(spooldir
,
428 pkgcnt
? pkg
: all_pkgs
, NULL
);
433 * At this point pkg[] is the list of packages to check. They
434 * are in directory format in spooldir.
437 if (catg_arg
!= NULL
) {
438 progerr(gettext(ERR_CAT_FND
), catg_arg
);
441 progerr(gettext(ERR_SEL_PKG
));
448 for (n
= 0; pkg
[n
]; n
++) {
449 char locenv
[PATH_MAX
];
453 gettext(MSG_CHK_DIR
), pkg
[n
], device
);
456 gettext(MSG_CHK_STRM
), pkg
[n
], device
);
458 (void) snprintf(pkgspool
, sizeof (pkgspool
),
459 "%s/%s", spooldir
, pkg
[n
]);
460 (void) snprintf(file
, sizeof (file
),
461 "%s/install", pkgspool
);
462 /* Here we check the install scripts. */
464 gettext("## Checking control scripts.\n"));
465 (void) checkscripts(file
, 0);
466 /* Verify consistency with the pkgmap. */
468 gettext("## Checking package objects.\n"));
469 (void) snprintf(file
, sizeof (file
),
470 "%s/pkgmap", pkgspool
);
471 (void) snprintf(locenv
, sizeof (locenv
),
472 "%s/pkginfo", pkgspool
);
476 * NOTE : checkmap() frees the environ data and
477 * pointer when it's through with them.
479 if (checkmap(0, (device
!= NULL
), file
, envfile
,
483 gettext("## Checking is complete.\n"));
489 put_path_params(); /* Restore what's needed. */
492 * If this is a check of a client of some sort, we'll need to
493 * mount up the client's filesystems. If the caller isn't
494 * root, this may not be possible.
496 if (is_an_inst_root()) {
498 logerr(gettext(MSG_NOTROOT
));
499 logerr(gettext(MSG_CONT
));
501 if (get_mntinfo(map_client
, vfstab_file
))
508 (void) snprintf(file
, sizeof (file
),
509 "%s/contents", get_PKGADM());
510 if (ppathlist
[0] != NULL
) {
511 for (n
= 0; ppathlist
[n
]; n
++) {
512 if (checkmap(1, (device
!= NULL
), file
, NULL
,
513 NULL
, ppathlist
[n
], 1))
516 } else if (pkg
[0] != NULL
) {
517 if (checkmap(1, (device
!= NULL
), file
, NULL
,
522 if (checkmap(1, (device
!= NULL
), file
, NULL
,
532 quit(errflg
? 1 : 0);
533 /* LINTED: no return */
537 setpathlist(char *file
)
542 char pathname
[PATH_MAX
];
544 * This trap laid to catch a mismatch between the declaration above and
545 * the hard-coded constant in the fscanf below
548 #error "PATH_MAX changed, so we have a bug to fix"
551 if (strcmp(file
, "-") == 0) {
554 if ((fd
= open(file
, O_RDONLY
)) == -1) {
555 progerr(gettext(ERR_IOPEN
), file
);
558 if (fstat(fd
, &st
) == -1) {
559 progerr(gettext(ERR_IOPEN
), file
);
562 if (S_ISDIR(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
563 progerr(gettext(ERR_PATHS_INVALID
), file
);
566 if ((fplist
= fdopen(fd
, "r")) == NULL
) {
567 progerr(gettext(ERR_IOPEN
), file
);
571 while (fscanf(fplist
, "%1024s", pathname
) == 1) {
572 if (*pathname
== '\0') {
573 progerr(gettext(ERR_PATHS_INVALID
), file
);
576 pathlist
[npaths
] = qstrdup(pathname
);
577 if (npaths
++ > MAXPATHS
) {
578 progerr(gettext(ERR_TOO_MANY
), MAXPATHS
);
583 progerr(gettext(ERR_IEMPTY
));
586 (void) fclose(fplist
);
592 /* cleanup any temporary directories */
594 if (tmpdir
!= NULL
) {
595 (void) rrmdir(tmpdir
);
599 (void) pkghead(NULL
);
607 char *prog
= get_prog_name();
609 (void) fprintf(stderr
, gettext(ERR_USAGE
), prog
, prog
);