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
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.
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]
23 * Copyright 1995-2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
32 * utility routines for debugging filesync (tracing, diagnostics,
33 * and error simulation)
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
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.
50 * a flaglist is merely a list of paired bits and name strings.
52 #pragma ident "%Z%%M% %I% %E% SMI"
65 /* bits in opt_debug for usage message */
66 static struct flaglist dbgflags
[] =
67 { DBG_BASE
, "BASE: base include building",
68 DBG_RULE
, "RULE: rule tree building",
69 DBG_STAT
, "STAT: file stats",
70 DBG_ANAL
, "ANAL: difference analysis",
71 DBG_RECON
, "RECO: reconciliation list processing",
72 DBG_VARS
, "VARS: qualification and expansion",
73 DBG_FILES
, "FILE: rule and baseline files",
74 DBG_LIST
, "LIST: tree building",
75 DBG_EVAL
, "EVAL: tree walking",
76 DBG_IGNORE
, "IGNO: ignore list",
77 DBG_MISC
, "MISC: everything else",
81 /* bits in opt_debug for dsiplay */
82 struct flaglist dbgmap
[] =
97 /* bits in the rules flag field */
98 struct flaglist rflags
[] =
100 R_PROGRAM
, "PROGRAM",
104 R_RESTRICT
, "RESTRICT",
108 /* bits in the files flag field */
109 struct flaglist fileflags
[] =
111 F_IN_BASELINE
, "base",
117 F_CONFLICT
, "conflict",
119 F_STAT_ERROR
, "statfail",
123 /* bits in the file src/dst difference mask */
124 struct flaglist diffmap
[] = {
135 D_RENAME_TO
, "rename2",
136 D_RENAME_FROM
, "renamed",
140 /* bits in the exit error code mask */
141 struct flaglist errmap
[] = {
142 ERR_RESOLVABLE
, "resolvable",
143 ERR_UNRESOLVED
, "unresolvable",
144 ERR_MISSING
, "missing files",
145 ERR_PERM
, "permissions",
146 ERR_FILES
, "rule/base errors",
147 ERR_INVAL
, "invalid arguments",
148 ERR_NOBASE
, "bad base dir",
158 * format flags for printing
162 * mask to be interpreted \
165 * pointer to a static buffer
168 showflags(struct flaglist
*map
, long mask
)
170 static char outbuf
[MAX_NAME
];
173 for (i
= 0; map
[i
].fl_mask
; i
++)
174 if (mask
& map
[i
].fl_mask
) {
177 strcat(outbuf
, map
[i
].fl_name
);
185 * dbg_usage, err_usage
188 * to print out usage messages for the secret debugging flags
197 fprintf(stderr
, "Usage:\tfilesync -Dmask ...\n");
198 for (i
= 0; dbgflags
[i
].fl_mask
; i
++)
199 fprintf(stderr
, "\t0x%04lx .... %s\n",
200 dbgflags
[i
].fl_mask
, dbgflags
[i
].fl_name
);
201 fprintf(stderr
, "\n");
206 * The -E flag is a debugging feature that enables the user to request
207 * the simulation of difficult to trigger error conditions in order
208 * to test out the error handling code in filesync. We maintain a
209 * registry that specifies a file name and an operation, and an errno
210 * to be returned if the specified operation is attempted on the
216 fprintf(stderr
, "Usage:\tfilesync -E<errno>,<code>,<filename>\n");
217 fprintf(stderr
, "\ts ... eval stat source\n");
218 fprintf(stderr
, "\tS ... eval stat destination\n");
219 fprintf(stderr
, "\tn ... eval nftw source\n");
220 fprintf(stderr
, "\tN ... eval nftw destination\n");
221 fprintf(stderr
, "\tc ... reconcile copy create\n");
222 fprintf(stderr
, "\to ... reconcile copy open\n");
223 fprintf(stderr
, "\tr ... reconcile copy read/readlink\n");
224 fprintf(stderr
, "\tw ... reconcile copy write\n");
225 fprintf(stderr
, "\tl ... reconcile link/symlink\n");
226 fprintf(stderr
, "\tu ... reconcile unlink\n");
227 fprintf(stderr
, "\td ... reconcile mkdir/mknod\n");
228 fprintf(stderr
, "\tD ... reconcile rmdir\n");
229 fprintf(stderr
, "\tm ... reconcile rename\n");
230 fprintf(stderr
, "\tR ... reconcile restat\n");
231 fprintf(stderr
, "\tp ... reconcile protection (chmod)");
232 fprintf(stderr
, "\ta ... reconcile access control (setfacl)");
233 fprintf(stderr
, "\tO ... reconcile ownership (chown)");
234 fprintf(stderr
, "\tZ ... out of space on target\n");
235 fprintf(stderr
, "\n");
239 * this data structure us used to keep track of the error simulations
240 * that have been requested.
242 static struct errsim
{
243 int Errno
; /* error number to return */
244 char code
; /* event triggering the error */
245 char *file
; /* file name triggering error */
246 } errsim
[ DBG_MAX_ERR
];
248 static int num_errs
; /* number of simulated errors */
256 * note that we have been requested to simulate file access errors
259 * argument string <errno>,<errcode>,<filename>
265 dbg_set_error(char *arg
)
270 if (num_errs
>= DBG_MAX_ERR
) {
271 fprintf(stderr
, "ERROR: only %d -E specifications allowed\n",
276 /* get the error number */
277 if (!isdigit(arg
[0]))
279 error_no
= strtol(arg
, &s
, 0);
281 /* get the error condition */
282 if (*s
++ != ',' || !isalpha(*s
))
286 /* get the file name */
287 while (*s
&& *s
!= ',') s
++;
288 if (*s
++ != ',' || *s
== 0)
291 /* register the error simulation */
292 errsim
[num_errs
].Errno
= error_no
;
293 errsim
[num_errs
].code
= error_type
;
294 errsim
[num_errs
].file
= s
;
296 if (opt_debug
& DBG_MISC
)
297 fprintf(stderr
, "MISC: errsim[%d] %c(%s) -> %d\n",
298 num_errs
, error_type
, s
, error_no
);
310 * determine whether or not we have been asked to simulate an
311 * error for a specified file.
317 * errno (or zero if no error)
320 dbg_chk_error(const char *name
, char code
)
323 for (i
= 0; i
< num_errs
; i
++) {
324 /* see if this code matches any registered condition */
325 if (code
!= errsim
[i
].code
)
328 /* see if this also matches the file name */
329 if (!suffix(name
, errsim
[i
].file
))
332 /* we have a winner */
333 if (opt_debug
& DBG_MISC
)
334 fprintf(stderr
, "MISC: trigger %d for file %c(%s)\n",
335 errsim
[i
].Errno
, code
, name
);
336 return (errsim
[i
].Errno
);
341 #else /* ! DBG_ERRORS */
345 fprintf(stderr
, "ERROR: this filesync does not support -E\n");
349 dbg_set_error(char *arg
)
355 dbg_chk_error(const char *name
, char code
)