mfstscan.c revision 7475:9a5f7406e094
1/*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27#include <sys/types.h>
28
29#include <ftw.h>
30#include <libintl.h>
31#include <libscf.h>
32#include <libuutil.h>
33#include <locale.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <unistd.h>
38
39#include "manifest_hash.h"
40
41#define	MAX_DEPTH	24
42
43static scf_handle_t *hndl;
44static int tflag;
45
46/*
47 * mfstscan - service manifest change detection utility
48 *
49 * mfstscan walks the given filesystem hierarchies, and reports those manifests
50 * with changed or absent hash entries.  Manifests are expected to end with a
51 * .xml suffix--other files will be ignored.
52 */
53
54static void
55usage()
56{
57	(void) fprintf(stderr, gettext("Usage: %s [-t] path ...\n"),
58	    uu_getpname());
59	exit(UU_EXIT_USAGE);
60}
61
62/*ARGSUSED*/
63static int
64process(const char *fn, const struct stat *sp, int ftw_type,
65    struct FTW *ftws)
66{
67	char *suffix_match;
68
69	if (ftw_type != FTW_F)
70		return (0);
71
72	suffix_match = strstr(fn, ".xml");
73	if (suffix_match == NULL || strcmp(suffix_match, ".xml") != 0)
74		return (0);
75
76	if (mhash_test_file(hndl, fn, 0, NULL, NULL) == MHASH_NEWFILE)
77		(void) printf("%s\n", fn);
78
79	return (0);
80}
81
82int
83main(int argc, char *argv[])
84{
85	int i;
86	int paths_walked = 0;
87	struct stat sb;
88
89	(void) uu_setpname(argv[0]);
90
91	while ((i = getopt(argc, argv, "t")) != -1) {
92		switch (i) {
93		case 't':
94			tflag = 1;
95			paths_walked = 1;
96			break;
97		case '?':
98		default:
99			usage();
100			/*NOTREACHED*/
101		}
102	}
103
104	if (optind >= argc)
105		usage();
106
107	hndl = scf_handle_create(SCF_VERSION);
108
109	if (scf_handle_bind(hndl) != SCF_SUCCESS)
110		uu_die(gettext("cannot bind to repository: %s\n"),
111		    scf_strerror(scf_error()));
112
113	for (i = optind; i < argc; i++) {
114		if (tflag) {
115			char *pname = mhash_filename_to_propname(argv[i],
116			    B_FALSE);
117
118			if (pname != NULL)
119				(void) puts(pname);
120			else
121				uu_warn(gettext("cannot resolve pathname "
122				    "for %s"), argv[i]);
123
124			continue;
125		}
126
127		if (stat(argv[i], &sb) == -1) {
128			uu_warn(gettext("cannot stat %s"), argv[i]);
129			continue;
130		}
131
132		if (nftw(argv[i], process, MAX_DEPTH, FTW_MOUNT) == -1)
133			uu_warn(gettext("file tree walk of %s encountered "
134			    "error"), argv[i]);
135		else
136			paths_walked++;
137	}
138
139	(void) scf_handle_unbind(hndl);
140	(void) scf_handle_destroy(hndl);
141
142	if (!paths_walked)
143		uu_die(gettext("no paths walked\n"));
144
145	return (0);
146}
147