2 * Copyright (C) 2013-2019 Red Hat Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44 struct debug_flag
*next
;
45 char *name
; /* plugin or filter name */
46 char *flag
; /* flag name */
47 char *symbol
; /* symbol, eg. "myplugin_debug_foo" */
48 int value
; /* value of flag */
49 bool used
; /* if flag was successfully set */
52 /* Synthesize the name of the *_debug_* variable from the plugin name
56 symbol_of_debug_flag (const char *name
, const char *flag
)
62 len
= asprintf (&var
, "%s_debug_%s", name
, flag
);
68 /* If there are any '.'s remaining in the name, convert them to '_'. */
69 for (i
= 0; i
< (size_t) len
; ++i
) {
74 return var
; /* caller frees */
77 /* Parse and add a single -D flag from the command line.
79 * Debug Flag must be "NAME.FLAG=N".
81 * arg p q (after +1 adjustment below)
84 add_debug_flag (const char *arg
)
86 struct debug_flag
*flag
;
89 p
= strchr (arg
, '.');
90 q
= strchr (arg
, '=');
91 if (p
== NULL
|| q
== NULL
) {
94 "%s: -D (Debug Flag) must have the format NAME.FLAG=N\n",
98 p
++; /* +1 adjustment */
101 if (p
- arg
<= 1) goto bad_debug_flag
; /* NAME too short */
102 if (p
> q
) goto bad_debug_flag
;
103 if (q
- p
<= 1) goto bad_debug_flag
; /* FLAG too short */
104 if (*q
== '\0') goto bad_debug_flag
; /* N too short */
106 flag
= malloc (sizeof *flag
);
113 flag
->name
= strndup (arg
, p
-arg
-1);
114 if (!flag
->name
) goto debug_flag_perror
;
115 flag
->flag
= strndup (p
, q
-p
-1);
116 if (!flag
->flag
) goto debug_flag_perror
;
117 if (nbdkit_parse_int ("flag", q
, &flag
->value
) == -1)
120 flag
->symbol
= symbol_of_debug_flag (flag
->name
, flag
->flag
);
122 /* Add flag to the linked list. */
123 flag
->next
= debug_flags
;
127 /* Apply all debug flags applicable to this backend. */
129 apply_debug_flags (void *dl
, const char *name
)
131 struct debug_flag
*flag
;
133 for (flag
= debug_flags
; flag
!= NULL
; flag
= flag
->next
) {
134 if (!flag
->used
&& strcmp (name
, flag
->name
) == 0) {
137 /* Find the symbol. */
138 sym
= dlsym (dl
, flag
->symbol
);
145 "%s: warning: -D %s.%s: %s does not contain a "
146 "global variable called %s\n",
147 program_name
, name
, flag
->flag
, name
, flag
->symbol
);
150 /* Mark this flag as used. */
157 free_debug_flags (void)
159 while (debug_flags
!= NULL
) {
160 struct debug_flag
*next
= debug_flags
->next
;
162 if (!debug_flags
->used
)
163 fprintf (stderr
, "%s: warning: debug flag -D %s.%s was not used\n",
164 program_name
, debug_flags
->name
, debug_flags
->flag
);
165 free (debug_flags
->name
);
166 free (debug_flags
->flag
);
167 free (debug_flags
->symbol
);