]> git.proxmox.com Git - mirror_spl-debian.git/blame - cmd/spl.c
Prep for for 0.3.0 tag, this is the tag which was used for all
[mirror_spl-debian.git] / cmd / spl.c
CommitLineData
57d1b188 1#include <stdlib.h>
2#include <stddef.h>
3#include <stdio.h>
4#include <string.h>
5#include <errno.h>
6#include <unistd.h>
7#include <sys/types.h>
8#include <fcntl.h>
9#include "../include/spl-ctl.h"
10
11static int spl_debug_mask = ~0;
12static int spl_debug_subsystem = ~0;
13
14/* all strings nul-terminated; only the struct and hdr need to be freed */
15struct dbg_line {
16 struct spl_debug_header *hdr;
17 char *file;
18 char *fn;
19 char *text;
20};
21
22static int
23cmp_rec(const void *p1, const void *p2)
24{
25 struct dbg_line *d1 = *(struct dbg_line **)p1;
26 struct dbg_line *d2 = *(struct dbg_line **)p2;
27
28 if (d1->hdr->ph_sec < d2->hdr->ph_sec)
29 return -1;
30
31 if (d1->hdr->ph_sec == d2->hdr->ph_sec &&
32 d1->hdr->ph_usec < d2->hdr->ph_usec)
33 return -1;
34
35 if (d1->hdr->ph_sec == d2->hdr->ph_sec &&
36 d1->hdr->ph_usec == d2->hdr->ph_usec)
37 return 0;
38
39 return 1;
40}
41
42static void
43print_rec(struct dbg_line **linev, int used, FILE *out)
44{
45 int i;
46
47 for (i = 0; i < used; i++) {
48 struct dbg_line *line = linev[i];
49 struct spl_debug_header *hdr = line->hdr;
50
892d5106 51 fprintf(out, "%08x:%08x:%u:%u.%06llu:%u:%u:%u:(%s:%u:%s()) %s",
57d1b188 52 hdr->ph_subsys, hdr->ph_mask, hdr->ph_cpu_id,
53 hdr->ph_sec, (unsigned long long)hdr->ph_usec,
892d5106 54 hdr->ph_stack, hdr->ph_pid, hdr->ph_stack, line->file,
57d1b188 55 hdr->ph_line_num, line->fn, line->text);
56 free(line->hdr);
57 free(line);
58 }
59
60 free(linev);
61}
62
63static int
64add_rec(struct dbg_line *line, struct dbg_line ***linevp, int *lenp, int used)
65{
66 struct dbg_line **linev = *linevp;
67
68 if (used == *lenp) {
69 int nlen = *lenp + 512;
70 int nsize = nlen * sizeof(struct dbg_line *);
71
72 linev = *linevp ? realloc(*linevp, nsize) : malloc(nsize);
73 if (!linev)
74 return 0;
75 *linevp = linev;
76 *lenp = nlen;
77 }
78 linev[used] = line;
79 return 1;
80}
81
82static int
83parse_buffer(FILE *in, FILE *out)
84{
85 struct dbg_line *line;
86 struct spl_debug_header *hdr;
87 char buf[4097], *p;
88 unsigned long dropped = 0, kept = 0;
89 struct dbg_line **linev = NULL;
90 const int phl = sizeof(hdr->ph_len);
91 const int phf = sizeof(hdr->ph_flags);
92 int rc, linev_len = 0;
93
94 while (1) {
95 rc = fread(buf, phl + phf, 1, in);
96 if (rc <= 0)
97 break;
98
99 hdr = (void *)buf;
100 if (hdr->ph_len == 0)
101 break;
102 if (hdr->ph_len > 4094) {
103 fprintf(stderr, "unexpected large record: %d bytes. "
104 "aborting.\n", hdr->ph_len);
105 break;
106 }
107
108 rc = fread(buf + phl + phf, 1, hdr->ph_len - phl - phf, in);
109 if (rc <= 0)
110 break;
111
112 if (hdr->ph_mask &&
113 (!(spl_debug_subsystem & hdr->ph_subsys) ||
114 (!(spl_debug_mask & hdr->ph_mask)))) {
115 dropped++;
116 continue;
117 }
118
119 line = malloc(sizeof(*line));
120 if (line == NULL) {
121 fprintf(stderr, "malloc failed; printing accumulated "
122 "records and exiting.\n");
123 break;
124 }
125
126 line->hdr = malloc(hdr->ph_len + 1);
127 if (line->hdr == NULL) {
128 free(line);
129 fprintf(stderr, "malloc failed; printing accumulated "
130 "records and exiting.\n");
131 break;
132 }
133
134 p = (void *)line->hdr;
135 memcpy(line->hdr, buf, hdr->ph_len);
136 p[hdr->ph_len] = '\0';
137
138 p += sizeof(*hdr);
139 line->file = p;
140 p += strlen(line->file) + 1;
141 line->fn = p;
142 p += strlen(line->fn) + 1;
143 line->text = p;
144
145 if (!add_rec(line, &linev, &linev_len, kept)) {
146 fprintf(stderr, "malloc failed; printing accumulated "
147 "records and exiting.\n");
148 break;
149 }
150 kept++;
151 }
152
153 if (linev) {
154 qsort(linev, kept, sizeof(struct dbg_line *), cmp_rec);
155 print_rec(linev, kept, out);
156 }
157
158 printf("Debug log: %lu lines, %lu kept, %lu dropped.\n",
159 dropped + kept, kept, dropped);
160 return 0;
161}
162
163int
164main(int argc, char *argv[])
165{
166 int fdin, fdout;
167 FILE *in, *out = stdout;
168 int rc, o_lf = 0;
169
170 if (argc > 3 || argc < 2) {
171 fprintf(stderr, "usage: %s <input> [output]\n", argv[0]);
172 return 0;
173 }
174
175#ifdef __USE_LARGEFILE64
176 o_lf = O_LARGEFILE;
177#endif
178
179 fdin = open(argv[1], O_RDONLY | o_lf);
180 if (fdin == -1) {
181 fprintf(stderr, "open(%s) failed: %s\n", argv[1],
182 strerror(errno));
183 return 1;
184 }
185 in = fdopen(fdin, "r");
186 if (in == NULL) {
187 fprintf(stderr, "fopen(%s) failed: %s\n", argv[1],
188 strerror(errno));
189 close(fdin);
190 return 1;
191 }
192 if (argc > 2) {
193 fdout = open(argv[2], O_CREAT | O_TRUNC | O_WRONLY | o_lf, 0600);
194 if (fdout == -1) {
195 fprintf(stderr, "open(%s) failed: %s\n", argv[2],
196 strerror(errno));
197 fclose(in);
198 return 1;
199 }
200 out = fdopen(fdout, "w");
201 if (out == NULL) {
202 fprintf(stderr, "fopen(%s) failed: %s\n", argv[2],
203 strerror(errno));
204 fclose(in);
205 close(fdout);
206 return 1;
207 }
208 }
209
210 rc = parse_buffer(in, out);
211
212 fclose(in);
213 if (out != stdout)
214 fclose(out);
215
216 return rc;
217}