xref: /illumos-gate/usr/src/cmd/filesync/debug.c (revision 75987085654d02c643b3f641d1a52d001b8d60cc)
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, Version 1.0 only
6   * (the "License").  You may not use this file except in compliance
7   * with the License.
8   *
9   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10   * or http://www.opensolaris.org/os/licensing.
11   * See the License for the specific language governing permissions
12   * and limitations under the License.
13   *
14   * When distributing Covered Code, include this CDDL HEADER in each
15   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16   * If applicable, add the following below this CDDL HEADER, with the
17   * fields enclosed by brackets "[]" replaced with your own identifying
18   * information: Portions Copyright [yyyy] [name of copyright owner]
19   *
20   * CDDL HEADER END
21   */
22  /*
23   * Copyright 1995-2003 Sun Microsystems, Inc.  All rights reserved.
24   * Use is subject to license terms.
25   */
26  
27  /*
28   * module:
29   *	debug.c
30   *
31   * purpose:
32   *	utility routines for debugging filesync (tracing, diagnostics,
33   *	and error simulation)
34   *
35   * contents:
36   *	showflags	display a word of flags symbolicly
37   *	dbg_usage	printout usage info for -D switch
38   *	err_usage	printout usage info for -E switch
39   *	dbg_set_error	enable an error simulation
40   *	dbg_check_error	check for error simulation
41   *
42   *
43   * note:
44   *	there are numerous flag words and bit fields in this
45   *	program, and it would be horrendous to just print them
46   *	out in hex (in debugging output).  These routines use
47   *	a "flaglist" data structure to map between bits and
48   *	character string names or descriptions.
49   *
50   *	a flaglist is merely a list of paired bits and name strings.
51   */
52  
53  #include <stdio.h>
54  #include <stdlib.h>
55  #include <string.h>
56  #include <ctype.h>
57  #include <errno.h>
58  
59  #include "filesync.h"
60  #include "database.h"
61  #include "debug.h"
62  
63  
64  /* bits in opt_debug for usage message					*/
65  static struct flaglist dbgflags[] =
66  {	DBG_BASE,	"BASE: base include building",
67  	DBG_RULE,	"RULE: rule tree building",
68  	DBG_STAT,	"STAT: file stats",
69  	DBG_ANAL,	"ANAL: difference analysis",
70  	DBG_RECON,	"RECO: reconciliation list processing",
71  	DBG_VARS,	"VARS: qualification and expansion",
72  	DBG_FILES,	"FILE: rule and baseline files",
73  	DBG_LIST,	"LIST: tree building",
74  	DBG_EVAL,	"EVAL: tree walking",
75  	DBG_IGNORE,	"IGNO: ignore list",
76  	DBG_MISC,	"MISC: everything else",
77  	0,		0
78  };
79  
80  /* bits in opt_debug for dsiplay					*/
81  struct flaglist dbgmap[] =
82  {	DBG_BASE,	"BASE",
83  	DBG_RULE,	"RULE",
84  	DBG_STAT,	"STAT",
85  	DBG_ANAL,	"ANAL",
86  	DBG_RECON,	"RECO",
87  	DBG_VARS,	"VARS",
88  	DBG_FILES,	"FILE",
89  	DBG_LIST,	"LIST",
90  	DBG_EVAL,	"EVAL",
91  	DBG_IGNORE,	"IGNO",
92  	DBG_MISC,	"MISC",
93  	0,		0
94  };
95  
96  /* bits in the rules flag field					*/
97  struct flaglist rflags[] =
98  {	R_IGNORE, 	"IGNORE",
99  	R_PROGRAM,	"PROGRAM",
100  	R_WILD,		"WILD",
101  	R_NEW,		"NEW",
102  	R_BOGUS,	"BOGUS",
103  	R_RESTRICT,	"RESTRICT",
104  	0,		0
105  };
106  
107  /* bits in the files flag field					*/
108  struct flaglist fileflags[] =
109  {	F_NEW, 		"new",
110  	F_IN_BASELINE,	"base",
111  	F_IN_SOURCE,	"srce",
112  	F_IN_DEST,	"dest",
113  	F_EVALUATE,	"eval",
114  	F_SPARSE,	"sparse",
115  	F_REMOVE,	"remove",
116  	F_CONFLICT,	"conflict",
117  	F_LISTED,	"listed",
118  	F_STAT_ERROR,	"statfail",
119  	0,		0
120  };
121  
122  /* bits in the file src/dst difference mask			*/
123  struct flaglist diffmap[] = {
124  	D_CREATE,	"create",
125  	D_DELETE,	"delete",
126  	D_MTIME,	"modtime",
127  	D_SIZE,		"size",
128  	D_UID,		"uid",
129  	D_GID,		"gid",
130  	D_PROT,		"modes",
131  	D_LINKS,	"links",
132  	D_TYPE,		"type",
133  	D_FACLS,	"facls",
134  	D_RENAME_TO,	"rename2",
135  	D_RENAME_FROM,	"renamed",
136  	0,		0
137  };
138  
139  /* bits in the exit error code mask				*/
140  struct flaglist errmap[] = {
141  	ERR_RESOLVABLE,	"resolvable",
142  	ERR_UNRESOLVED,	"unresolvable",
143  	ERR_MISSING,	"missing files",
144  	ERR_PERM,	"permissions",
145  	ERR_FILES,	"rule/base errors",
146  	ERR_INVAL,	"invalid arguments",
147  	ERR_NOBASE,	"bad base dir",
148  	ERR_OTHER,	"other",
149  	0,		0
150  };
151  
152  /*
153   * routine:
154   *	showflags
155   *
156   * purpose:
157   *	format flags for printing
158   *
159   * parameters:
160   *	pointer to map
161   *	mask to be interpreted \
162   *
163   * returns:
164   *	pointer to a static buffer
165   */
166  char *
167  showflags(struct flaglist *map, long mask)
168  {	int i;
169  	static char outbuf[MAX_NAME];
170  
171  	outbuf[0] = 0;
172  	for (i = 0; map[i].fl_mask; i++)
173  		if (mask & map[i].fl_mask) {
174  			if (outbuf[0])
175  				strcat(outbuf, "|");
176  			strcat(outbuf, map[i].fl_name);
177  		}
178  
179  	return (outbuf);
180  }
181  
182  /*
183   * routines:
184   *	dbg_usage, err_usage
185   *
186   * purpose:
187   *	to print out usage messages for the secret debugging flags
188   *
189   * returns:
190   *	void
191   */
192  void
193  dbg_usage(void)
194  {	int i;
195  
196  	fprintf(stderr, "Usage:\tfilesync -Dmask ...\n");
197  	for (i = 0; dbgflags[i].fl_mask; i++)
198  		fprintf(stderr, "\t0x%04lx .... %s\n",
199  			dbgflags[i].fl_mask, dbgflags[i].fl_name);
200  	fprintf(stderr, "\n");
201  }
202  
203  #ifdef	DBG_ERRORS
204  /*
205   * The -E flag is a debugging feature that enables the user to request
206   * the simulation of difficult to trigger error conditions in order
207   * to test out the error handling code in filesync.  We maintain a
208   * registry that specifies a file name and an operation, and an errno
209   * to be returned if the specified operation is attempted on the
210   * specified file.
211   */
212  void
213  err_usage(void)
214  {
215  	fprintf(stderr, "Usage:\tfilesync -E<errno>,<code>,<filename>\n");
216  	fprintf(stderr, "\ts ... eval stat source\n");
217  	fprintf(stderr, "\tS ... eval stat destination\n");
218  	fprintf(stderr, "\tn ... eval nftw source\n");
219  	fprintf(stderr, "\tN ... eval nftw destination\n");
220  	fprintf(stderr, "\tc ... reconcile copy create\n");
221  	fprintf(stderr, "\to ... reconcile copy open\n");
222  	fprintf(stderr, "\tr ... reconcile copy read/readlink\n");
223  	fprintf(stderr, "\tw ... reconcile copy write\n");
224  	fprintf(stderr, "\tl ... reconcile link/symlink\n");
225  	fprintf(stderr, "\tu ... reconcile unlink\n");
226  	fprintf(stderr, "\td ... reconcile mkdir/mknod\n");
227  	fprintf(stderr, "\tD ... reconcile rmdir\n");
228  	fprintf(stderr, "\tm ... reconcile rename\n");
229  	fprintf(stderr, "\tR ... reconcile restat\n");
230  	fprintf(stderr, "\tp ... reconcile protection (chmod)");
231  	fprintf(stderr, "\ta ... reconcile access control (setfacl)");
232  	fprintf(stderr, "\tO ... reconcile ownership (chown)");
233  	fprintf(stderr, "\tZ ... out of space on target\n");
234  	fprintf(stderr, "\n");
235  }
236  
237  /*
238   * this data structure us used to keep track of the error simulations
239   * that have been requested.
240   */
241  static struct errsim {
242  	int Errno;		/* error number to return	*/
243  	char code;		/* event triggering the error	*/
244  	char *file;		/* file name triggering error	*/
245  } errsim[ DBG_MAX_ERR ];
246  
247  static int num_errs;		/* number of simulated errors	*/
248  
249  
250  /*
251   * routine:
252   *	dbg_set_error
253   *
254   * purpose:
255   * 	note that we have been requested to simulate file access errors
256   *
257   * parameters:
258   *	argument string <errno>,<errcode>,<filename>
259   *
260   * returns:
261   *	error mask
262   */
263  int
264  dbg_set_error(char *arg)
265  {	char *s;
266  	char error_type;
267  	int error_no;
268  
269  	if (num_errs >= DBG_MAX_ERR) {
270  		fprintf(stderr, "ERROR: only %d -E specifications allowed\n",
271  				DBG_MAX_ERR);
272  		return (ERR_INVAL);
273  	}
274  
275  	/* get the error number		*/
276  	if (!isdigit(arg[0]))
277  		return (ERR_INVAL);
278  	error_no = strtol(arg, &s, 0);
279  
280  	/* get the error condition	*/
281  	if (*s++ != ',' || !isalpha(*s))
282  		return (ERR_INVAL);
283  	error_type = *s;
284  
285  	/* get the file name		*/
286  	while (*s && *s != ',') s++;
287  	if (*s++ != ',' || *s == 0)
288  		return (ERR_INVAL);
289  
290  	/* register the error simulation	*/
291  	errsim[num_errs].Errno = error_no;
292  	errsim[num_errs].code  = error_type;
293  	errsim[num_errs].file  = s;
294  
295  	if (opt_debug & DBG_MISC)
296  		fprintf(stderr, "MISC: errsim[%d] %c(%s) -> %d\n",
297  			num_errs, error_type, s, error_no);
298  
299  	num_errs++;
300  
301  	return (0);
302  }
303  
304  /*
305   * routine:
306   *	dbg_chk_error
307   *
308   * purpose:
309   *	determine whether or not we have been asked to simulate an
310   *	error for a specified file.
311   *
312   * parameters:
313   *	file name
314   *
315   * returns:
316   *	errno (or zero if no error)
317   */
318  int
319  dbg_chk_error(const char *name, char code)
320  {	int i;
321  
322  	for (i = 0; i < num_errs; i++) {
323  		/* see if this code matches any registered condition	*/
324  		if (code != errsim[i].code)
325  			continue;
326  
327  		/* see if this also matches the file name	*/
328  		if (!suffix(name, errsim[i].file))
329  			continue;
330  
331  		/* we have a winner				*/
332  		if (opt_debug & DBG_MISC)
333  			fprintf(stderr, "MISC: trigger %d for file %c(%s)\n",
334  				errsim[i].Errno, code, name);
335  		return (errsim[i].Errno);
336  	}
337  	return (0);
338  }
339  
340  #else	/* ! DBG_ERRORS	*/
341  void
342  err_usage(void)
343  {
344  	fprintf(stderr, "ERROR: this filesync does not support -E\n");
345  }
346  
347  int
348  dbg_set_error(char *arg)
349  {
350  	return (ERR_INVAL);
351  }
352  
353  int
354  dbg_chk_error(const char *name, char code)
355  {
356  	return (0);
357  }
358  #endif
359