]>
Commit | Line | Data |
---|---|---|
db08389d OO |
1 | /* |
2 | * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com> | |
ef316a27 | 3 | * Copyright (C) 2014 Karel Zak <kzak@redhat.com> |
db08389d OO |
4 | * |
5 | * This file may be distributed under the terms of the | |
6 | * GNU Lesser General Public License. | |
7 | */ | |
8 | #ifndef UTIL_LINUX_DEBUG_H | |
9 | #define UTIL_LINUX_DEBUG_H | |
10 | ||
ef316a27 KZ |
11 | |
12 | /* | |
13 | * util-linux debug macros | |
14 | * | |
15 | * The debug stuff is based on <name>_debug_mask that controls what outputs is | |
16 | * expected. The mask is usually initialized by <NAME>_DEBUG= env.variable | |
17 | * | |
18 | * After successful initialization the flag <PREFIX>_DEBUG_INIT is always set | |
19 | * to the mask (this flag is required). The <PREFIX> is usually library API | |
20 | * prefix (e.g. MNT_) or program name (e.g. CFDISK_) | |
21 | * | |
22 | * In the code is possible to use | |
23 | * | |
24 | * DBG(FOO, ul_debug("this is output for foo")); | |
25 | * | |
26 | * where for the FOO has to be defined <PREFIX>_DEBUG_FOO. | |
27 | * | |
28 | * It's possible to initialize the mask by comma delimited strings with | |
29 | * subsystem names (e.g. "LIBMOUNT_DEBUG=options,tab"). In this case is | |
30 | * necessary to define mask names array. This functionality is optional. | |
31 | * | |
9e930041 | 32 | * It's strongly recommended to use UL_* macros to define/declare/use |
ef316a27 KZ |
33 | * the debug stuff. |
34 | * | |
35 | * See disk-utils/cfdisk.c: cfdisk_init_debug() for programs debug | |
36 | * or libmount/src/init.c: mnt_init_debug() for library debug | |
37 | * | |
38 | */ | |
39 | ||
db08389d | 40 | #include <stdarg.h> |
14ad2353 | 41 | #include <string.h> |
db08389d | 42 | |
ef316a27 KZ |
43 | struct ul_debug_maskname { |
44 | const char *name; | |
45 | int mask; | |
46 | const char *help; | |
47 | }; | |
48 | #define UL_DEBUG_EMPTY_MASKNAMES {{ NULL, 0, NULL }} | |
49 | #define UL_DEBUG_DEFINE_MASKNAMES(m) static const struct ul_debug_maskname m ## _masknames[] | |
50 | #define UL_DEBUG_MASKNAMES(m) m ## _masknames | |
1e063303 | 51 | |
cb3fa847 OO |
52 | #define UL_DEBUG_DEFINE_MASK(m) int m ## _debug_mask |
53 | #define UL_DEBUG_DECLARE_MASK(m) extern UL_DEBUG_DEFINE_MASK(m) | |
54 | ||
55 | /* p - flag prefix, m - flag postfix */ | |
56 | #define UL_DEBUG_DEFINE_FLAG(p, m) p ## m | |
57 | ||
58 | /* l - library name, p - flag prefix, m - flag postfix, x - function */ | |
e7b49879 | 59 | #define __UL_DBG(l, p, m, x) \ |
d282c88d KZ |
60 | do { \ |
61 | if ((p ## m) & l ## _debug_mask) { \ | |
62 | fprintf(stderr, "%d: %s: %8s: ", getpid(), # l, # m); \ | |
63 | x; \ | |
64 | } \ | |
65 | } while (0) | |
db08389d | 66 | |
e7b49879 KZ |
67 | #define __UL_DBG_CALL(l, p, m, x) \ |
68 | do { \ | |
69 | if ((p ## m) & l ## _debug_mask) { \ | |
70 | x; \ | |
71 | } \ | |
72 | } while (0) | |
73 | ||
74 | #define __UL_DBG_FLUSH(l, p) \ | |
75 | do { \ | |
76 | if (l ## _debug_mask && \ | |
77 | l ## _debug_mask != p ## INIT) { \ | |
78 | fflush(stderr); \ | |
79 | } \ | |
80 | } while (0) | |
81 | ||
82 | ||
d282c88d KZ |
83 | #define __UL_INIT_DEBUG(lib, pref, mask, env) \ |
84 | do { \ | |
85 | if (lib ## _debug_mask & pref ## INIT) \ | |
86 | ; \ | |
87 | else if (!mask) { \ | |
88 | char *str = getenv(# env); \ | |
89 | if (str) \ | |
ef316a27 | 90 | lib ## _debug_mask = ul_debug_parse_envmask(lib ## _masknames, str); \ |
d282c88d KZ |
91 | } else \ |
92 | lib ## _debug_mask = mask; \ | |
93 | lib ## _debug_mask |= pref ## INIT; \ | |
d282c88d | 94 | } while (0) |
db08389d | 95 | |
14ad2353 | 96 | |
db08389d OO |
97 | static inline void __attribute__ ((__format__ (__printf__, 1, 2))) |
98 | ul_debug(const char *mesg, ...) | |
99 | { | |
100 | va_list ap; | |
101 | va_start(ap, mesg); | |
102 | vfprintf(stderr, mesg, ap); | |
103 | va_end(ap); | |
104 | fputc('\n', stderr); | |
105 | } | |
106 | ||
107 | static inline void __attribute__ ((__format__ (__printf__, 2, 3))) | |
0e0943c1 | 108 | ul_debugobj(const void *handler, const char *mesg, ...) |
db08389d OO |
109 | { |
110 | va_list ap; | |
111 | ||
112 | if (handler) | |
113 | fprintf(stderr, "[%p]: ", handler); | |
114 | va_start(ap, mesg); | |
115 | vfprintf(stderr, mesg, ap); | |
116 | va_end(ap); | |
117 | fputc('\n', stderr); | |
118 | } | |
119 | ||
ef316a27 KZ |
120 | static inline int ul_debug_parse_envmask( |
121 | const struct ul_debug_maskname flagnames[], | |
122 | const char *mask) | |
14ad2353 OO |
123 | { |
124 | int res; | |
125 | char *ptr; | |
126 | ||
127 | /* let's check for a numeric mask first */ | |
128 | res = strtoul(mask, &ptr, 0); | |
129 | ||
130 | /* perhaps it's a comma-separated string? */ | |
ef316a27 | 131 | if (ptr && *ptr && flagnames && flagnames[0].name) { |
14ad2353 OO |
132 | char *msbuf, *ms, *name; |
133 | res = 0; | |
134 | ||
135 | ms = msbuf = strdup(mask); | |
136 | if (!ms) | |
137 | return res; | |
138 | ||
139 | while ((name = strtok_r(ms, ",", &ptr))) { | |
ef316a27 | 140 | const struct ul_debug_maskname *d; |
14ad2353 OO |
141 | ms = ptr; |
142 | ||
ef316a27 KZ |
143 | for (d = flagnames; d && d->name; d++) { |
144 | if (strcmp(name, d->name) == 0) { | |
145 | res |= d->mask; | |
14ad2353 OO |
146 | break; |
147 | } | |
14ad2353 OO |
148 | } |
149 | /* nothing else we can do by OR-ing the mask */ | |
150 | if (res == 0xffff) | |
151 | break; | |
152 | } | |
153 | free(msbuf); | |
ef316a27 KZ |
154 | } else if (ptr && strcmp(ptr, "all") == 0) |
155 | res = 0xffff; | |
156 | ||
14ad2353 OO |
157 | return res; |
158 | } | |
ef316a27 KZ |
159 | |
160 | static inline void ul_debug_print_masks( | |
161 | const char *env, | |
162 | const struct ul_debug_maskname flagnames[]) | |
163 | { | |
164 | const struct ul_debug_maskname *d; | |
165 | ||
166 | if (!flagnames) | |
167 | return; | |
168 | ||
169 | fprintf(stderr, "Available \"%s=<name>[,...]|<mask>\" debug masks:\n", | |
170 | env); | |
171 | for (d = flagnames; d && d->name; d++) { | |
172 | if (!d->help) | |
173 | continue; | |
174 | fprintf(stderr, " %-8s [0x%04x] : %s\n", | |
175 | d->name, d->mask, d->help); | |
176 | } | |
177 | } | |
178 | ||
db08389d | 179 | #endif /* UTIL_LINUX_DEBUG_H */ |