Mercurial > illumos > onarm
annotate usr/src/cmd/filesync/debug.c @ 4:1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Mon, 31 Aug 2009 14:38:03 +0900 |
parents | c9caec207d52 |
children |
rev | line source |
---|---|
0 | 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 */ | |
4
1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
Koji Uno <koji.uno@sun.com>
parents:
0
diff
changeset
|
52 #pragma ident "%Z%%M% %I% %E% SMI" |
0 | 53 |
54 #include <stdio.h> | |
55 #include <stdlib.h> | |
56 #include <string.h> | |
57 #include <ctype.h> | |
58 #include <errno.h> | |
59 | |
60 #include "filesync.h" | |
61 #include "database.h" | |
62 #include "debug.h" | |
63 | |
64 | |
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", | |
78 0, 0 | |
79 }; | |
80 | |
81 /* bits in opt_debug for dsiplay */ | |
82 struct flaglist dbgmap[] = | |
83 { DBG_BASE, "BASE", | |
84 DBG_RULE, "RULE", | |
85 DBG_STAT, "STAT", | |
86 DBG_ANAL, "ANAL", | |
87 DBG_RECON, "RECO", | |
88 DBG_VARS, "VARS", | |
89 DBG_FILES, "FILE", | |
90 DBG_LIST, "LIST", | |
91 DBG_EVAL, "EVAL", | |
92 DBG_IGNORE, "IGNO", | |
93 DBG_MISC, "MISC", | |
94 0, 0 | |
95 }; | |
96 | |
97 /* bits in the rules flag field */ | |
98 struct flaglist rflags[] = | |
99 { R_IGNORE, "IGNORE", | |
100 R_PROGRAM, "PROGRAM", | |
101 R_WILD, "WILD", | |
102 R_NEW, "NEW", | |
103 R_BOGUS, "BOGUS", | |
104 R_RESTRICT, "RESTRICT", | |
105 0, 0 | |
106 }; | |
107 | |
108 /* bits in the files flag field */ | |
109 struct flaglist fileflags[] = | |
110 { F_NEW, "new", | |
111 F_IN_BASELINE, "base", | |
112 F_IN_SOURCE, "srce", | |
113 F_IN_DEST, "dest", | |
114 F_EVALUATE, "eval", | |
115 F_SPARSE, "sparse", | |
116 F_REMOVE, "remove", | |
117 F_CONFLICT, "conflict", | |
118 F_LISTED, "listed", | |
119 F_STAT_ERROR, "statfail", | |
120 0, 0 | |
121 }; | |
122 | |
123 /* bits in the file src/dst difference mask */ | |
124 struct flaglist diffmap[] = { | |
125 D_CREATE, "create", | |
126 D_DELETE, "delete", | |
127 D_MTIME, "modtime", | |
128 D_SIZE, "size", | |
129 D_UID, "uid", | |
130 D_GID, "gid", | |
131 D_PROT, "modes", | |
132 D_LINKS, "links", | |
133 D_TYPE, "type", | |
134 D_FACLS, "facls", | |
135 D_RENAME_TO, "rename2", | |
136 D_RENAME_FROM, "renamed", | |
137 0, 0 | |
138 }; | |
139 | |
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", | |
149 ERR_OTHER, "other", | |
150 0, 0 | |
151 }; | |
152 | |
153 /* | |
154 * routine: | |
155 * showflags | |
156 * | |
157 * purpose: | |
158 * format flags for printing | |
159 * | |
160 * parameters: | |
161 * pointer to map | |
162 * mask to be interpreted \ | |
163 * | |
164 * returns: | |
165 * pointer to a static buffer | |
166 */ | |
167 char * | |
168 showflags(struct flaglist *map, long mask) | |
169 { int i; | |
170 static char outbuf[MAX_NAME]; | |
171 | |
172 outbuf[0] = 0; | |
173 for (i = 0; map[i].fl_mask; i++) | |
174 if (mask & map[i].fl_mask) { | |
175 if (outbuf[0]) | |
176 strcat(outbuf, "|"); | |
177 strcat(outbuf, map[i].fl_name); | |
178 } | |
179 | |
180 return (outbuf); | |
181 } | |
182 | |
183 /* | |
184 * routines: | |
185 * dbg_usage, err_usage | |
186 * | |
187 * purpose: | |
188 * to print out usage messages for the secret debugging flags | |
189 * | |
190 * returns: | |
191 * void | |
192 */ | |
193 void | |
194 dbg_usage(void) | |
195 { int i; | |
196 | |
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"); | |
202 } | |
203 | |
204 #ifdef DBG_ERRORS | |
205 /* | |
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 | |
211 * specified file. | |
212 */ | |
213 void | |
214 err_usage(void) | |
215 { | |
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"); | |
236 } | |
237 | |
238 /* | |
239 * this data structure us used to keep track of the error simulations | |
240 * that have been requested. | |
241 */ | |
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 ]; | |
247 | |
248 static int num_errs; /* number of simulated errors */ | |
249 | |
250 | |
251 /* | |
252 * routine: | |
253 * dbg_set_error | |
254 * | |
255 * purpose: | |
256 * note that we have been requested to simulate file access errors | |
257 * | |
258 * parameters: | |
259 * argument string <errno>,<errcode>,<filename> | |
260 * | |
261 * returns: | |
262 * error mask | |
263 */ | |
264 int | |
265 dbg_set_error(char *arg) | |
266 { char *s; | |
267 char error_type; | |
268 int error_no; | |
269 | |
270 if (num_errs >= DBG_MAX_ERR) { | |
271 fprintf(stderr, "ERROR: only %d -E specifications allowed\n", | |
272 DBG_MAX_ERR); | |
273 return (ERR_INVAL); | |
274 } | |
275 | |
276 /* get the error number */ | |
277 if (!isdigit(arg[0])) | |
278 return (ERR_INVAL); | |
279 error_no = strtol(arg, &s, 0); | |
280 | |
281 /* get the error condition */ | |
282 if (*s++ != ',' || !isalpha(*s)) | |
283 return (ERR_INVAL); | |
284 error_type = *s; | |
285 | |
286 /* get the file name */ | |
287 while (*s && *s != ',') s++; | |
288 if (*s++ != ',' || *s == 0) | |
289 return (ERR_INVAL); | |
290 | |
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; | |
295 | |
296 if (opt_debug & DBG_MISC) | |
297 fprintf(stderr, "MISC: errsim[%d] %c(%s) -> %d\n", | |
298 num_errs, error_type, s, error_no); | |
299 | |
300 num_errs++; | |
301 | |
302 return (0); | |
303 } | |
304 | |
305 /* | |
306 * routine: | |
307 * dbg_chk_error | |
308 * | |
309 * purpose: | |
310 * determine whether or not we have been asked to simulate an | |
311 * error for a specified file. | |
312 * | |
313 * parameters: | |
314 * file name | |
315 * | |
316 * returns: | |
317 * errno (or zero if no error) | |
318 */ | |
319 int | |
320 dbg_chk_error(const char *name, char code) | |
321 { int i; | |
322 | |
323 for (i = 0; i < num_errs; i++) { | |
324 /* see if this code matches any registered condition */ | |
325 if (code != errsim[i].code) | |
326 continue; | |
327 | |
328 /* see if this also matches the file name */ | |
329 if (!suffix(name, errsim[i].file)) | |
330 continue; | |
331 | |
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); | |
337 } | |
338 return (0); | |
339 } | |
340 | |
341 #else /* ! DBG_ERRORS */ | |
342 void | |
343 err_usage(void) | |
344 { | |
345 fprintf(stderr, "ERROR: this filesync does not support -E\n"); | |
346 } | |
347 | |
348 int | |
349 dbg_set_error(char *arg) | |
350 { | |
351 return (ERR_INVAL); | |
352 } | |
353 | |
354 int | |
355 dbg_chk_error(const char *name, char code) | |
356 { | |
357 return (0); | |
358 } | |
359 #endif |