Fix shadow variable warnings.
[metze/wireshark/wip.git] / wiretap / logcat_text.c
1 /* logcat_text.c
2  *
3  * Copyright 2014, Michal Orynicz for Tieto Corporation
4  * Copyright 2014, Michal Labedzki for Tieto Corporation
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include "config.h"
22
23 #include <string.h>
24
25 #include "wtap-int.h"
26 #include "file_wrappers.h"
27
28 #include "logcat_text.h"
29 #include "logcat.h"
30
31 struct dumper_t {
32     int type;
33 };
34
35 /* Returns '?' for invalid priorities */
36 static gchar get_priority(const guint8 priority) {
37     static gchar priorities[] = "??VDIWEFS";
38
39     if (priority >= (guint8) sizeof(priorities))
40         return '?';
41
42     return priorities[priority];
43 }
44
45 static gint buffered_detect_version(const guint8 *pd)
46 {
47     const struct logger_entry     *log_entry;
48     const struct logger_entry_v2  *log_entry_v2;
49     gint                     version;
50     const guint8            *msg_payload = NULL;
51     guint8                  *msg_part;
52     guint8                  *msg_end;
53     guint16                  msg_len;
54
55     log_entry    = (const struct logger_entry *)(const void *) pd;
56     log_entry_v2 = (const struct logger_entry_v2 *)(const void *) pd;
57
58     /* must contain at least priority and two nulls as separator */
59     if (log_entry->len < 3)
60         return -1;
61
62     /* payload length may not exceed the maximum payload size */
63     if (log_entry->len > LOGGER_ENTRY_MAX_PAYLOAD)
64         return -1;
65
66     /* cannot rely on __pad being 0 for v1, use heuristics to find out what
67      * version is in use. First assume the smallest msg. */
68     for (version = 1; version <= 2; ++version) {
69         if (version == 1) {
70             msg_payload = (const guint8 *) (log_entry + 1);
71         } else if (version == 2) {
72             /* v2 is 4 bytes longer */
73             msg_payload = (const guint8 *) (log_entry_v2 + 1);
74             if (log_entry_v2->hdr_size != sizeof(*log_entry_v2))
75                 continue;
76         }
77
78         /* A v2 msg has a 32-bit userid instead of v1 priority */
79         if (get_priority(msg_payload[0]) == '?')
80             continue;
81
82         /* Is there a terminating '\0' for the tag? */
83         msg_part = (guint8 *) memchr(msg_payload, '\0', log_entry->len - 1);
84         if (msg_part == NULL)
85             continue;
86
87         /* if msg is '\0'-terminated, is it equal to the payload len? */
88         ++msg_part;
89         msg_len = (guint16)(log_entry->len - (msg_part - msg_payload));
90         msg_end = (guint8 *) memchr(msg_part, '\0', msg_len);
91         /* is the end of the buffer (-1) equal to the end of msg? */
92         if (msg_end && (msg_payload + log_entry->len - 1 != msg_end))
93             continue;
94
95         return version;
96     }
97
98     return -1;
99 }
100
101 static gchar *logcat_log(const struct dumper_t *dumper, guint32 seconds,
102         gint milliseconds, gint pid, gint tid, gchar priority, const gchar *tag,
103         const gchar *log)
104 {
105     gchar  time_buffer[15];
106     time_t datetime;
107
108     datetime = (time_t) seconds;
109
110     switch (dumper->type) {
111         case WTAP_ENCAP_LOGCAT_BRIEF:
112             return g_strdup_printf("%c/%-8s(%5i): %s\n",
113                     priority, tag, pid, log);
114         case WTAP_ENCAP_LOGCAT_PROCESS:
115             /* NOTE: Last parameter should be "process name", not tag;
116                      Unfortunately, we do not have process name */
117             return g_strdup_printf("%c(%5i) %s  (%s)\n",
118                     priority, pid, log, "");
119         case WTAP_ENCAP_LOGCAT_TAG:
120             return g_strdup_printf("%c/%-8s: %s\n",
121                    priority, tag, log);
122         case WTAP_ENCAP_LOGCAT_THREAD:
123             return g_strdup_printf("%c(%5i:%5i) %s\n",
124                     priority, pid, tid, log);
125         case WTAP_ENCAP_LOGCAT_TIME:
126             strftime(time_buffer, sizeof(time_buffer), "%m-%d %H:%M:%S",
127                     gmtime(&datetime));
128             return g_strdup_printf("%s.%03i %c/%-8s(%5i): %s\n",
129                     time_buffer, milliseconds, priority, tag, pid, log);
130         case WTAP_ENCAP_LOGCAT_THREADTIME:
131             strftime(time_buffer, sizeof(time_buffer), "%m-%d %H:%M:%S",
132                     gmtime(&datetime));
133             return g_strdup_printf("%s.%03i %5i %5i %c %-8s: %s\n",
134                     time_buffer, milliseconds, pid, tid, priority, tag, log);
135         case WTAP_ENCAP_LOGCAT_LONG:
136             strftime(time_buffer, sizeof(time_buffer), "%m-%d %H:%M:%S",
137                     gmtime(&datetime));
138             return g_strdup_printf("[ %s.%03i %5i:%5i %c/%-8s ]\n%s\n\n",
139                     time_buffer, milliseconds, pid, tid, priority, tag, log);
140         default:
141             return NULL;
142     }
143
144 }
145
146 static void get_time(gchar *string, struct wtap_pkthdr *phdr) {
147     gint ms;
148     struct tm date;
149     time_t seconds;
150
151     if (6 == sscanf(string, "%d-%d %d:%d:%d.%d", &date.tm_mon, &date.tm_mday, &date.tm_hour,
152                     &date.tm_min, &date.tm_sec, &ms)) {
153         date.tm_year = 70;
154         date.tm_mon -= 1;
155         seconds = mktime(&date);
156         phdr->ts.secs = (time_t) seconds;
157         phdr->ts.nsecs = (int) (ms * 1e6);
158         phdr->presence_flags = WTAP_HAS_TS;
159     } else {
160         phdr->presence_flags = 0;
161         phdr->ts.secs = (time_t) 0;
162         phdr->ts.nsecs = (int) 0;
163     }
164 }
165
166 static gboolean logcat_text_read_packet(FILE_T fh, struct wtap_pkthdr *phdr,
167         Buffer *buf, gint file_type) {
168     gint8 *pd;
169     gchar cbuff[WTAP_MAX_PACKET_SIZE];
170     gchar *ret = NULL;
171
172     do {
173         ret = file_gets(cbuff, WTAP_MAX_PACKET_SIZE, fh);
174     } while (NULL != ret && 3 > strlen(cbuff) && !file_eof(fh));
175
176     if (NULL == ret || 3 > strlen(cbuff)) {
177         return FALSE;
178     }
179
180     if (WTAP_FILE_TYPE_SUBTYPE_LOGCAT_LONG == file_type &&
181             !g_regex_match_simple(SPECIAL_STRING, cbuff, (GRegexCompileFlags)((gint) G_REGEX_ANCHORED | (gint) G_REGEX_RAW), G_REGEX_MATCH_NOTEMPTY)) {
182         gint64 file_off = 0;
183         gchar lbuff[WTAP_MAX_PACKET_SIZE];
184         int err;
185         gchar *ret2 = NULL;
186
187         file_off = file_tell(fh);
188         ret2 = file_gets(lbuff,WTAP_MAX_PACKET_SIZE, fh);
189         while (NULL != ret2 && 2 < strlen(lbuff) && !file_eof(fh)) {
190             g_strlcat(cbuff,lbuff,WTAP_MAX_PACKET_SIZE);
191             file_off = file_tell(fh);
192             ret2 = file_gets(lbuff,WTAP_MAX_PACKET_SIZE, fh);
193         }
194
195         if(NULL == ret2 || 2 < strlen(lbuff)) {
196             return FALSE;
197         }
198
199         file_seek(fh,file_off,SEEK_SET,&err);
200     }
201
202     phdr->rec_type = REC_TYPE_PACKET;
203     phdr->caplen = (guint32)strlen(cbuff);
204     phdr->len = phdr->caplen;
205
206     ws_buffer_assure_space(buf, phdr->caplen + 1);
207     pd = ws_buffer_start_ptr(buf);
208     if ((WTAP_FILE_TYPE_SUBTYPE_LOGCAT_TIME == file_type
209             || WTAP_FILE_TYPE_SUBTYPE_LOGCAT_THREADTIME == file_type
210             || WTAP_FILE_TYPE_SUBTYPE_LOGCAT_LONG == file_type)
211             && '-' != cbuff[0]) { /* the last part filters out the -- beginning of... lines */
212         if (WTAP_FILE_TYPE_SUBTYPE_LOGCAT_LONG == file_type) {
213             get_time(cbuff+2, phdr);
214         } else {
215             get_time(cbuff, phdr);
216         }
217     } else {
218         phdr->presence_flags = 0;
219         phdr->ts.secs = (time_t) 0;
220         phdr->ts.nsecs = (int) 0;
221     }
222     memcpy(pd, cbuff, phdr->caplen + 1);
223     return TRUE;
224 }
225
226 static gboolean logcat_text_read(wtap *wth, int *err _U_ , gchar **err_info _U_,
227         gint64 *data_offset) {
228     *data_offset = file_tell(wth->fh);
229
230     return logcat_text_read_packet(wth->fh, &wth->phdr, wth->frame_buffer,
231             wth->file_type_subtype);
232 }
233
234 static gboolean logcat_text_seek_read(wtap *wth, gint64 seek_off,
235         struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info _U_) {
236     if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
237         return FALSE;
238
239     if (!logcat_text_read_packet(wth->random_fh, phdr, buf,
240             wth->file_type_subtype)) {
241         if (*err == 0)
242             *err = WTAP_ERR_SHORT_READ;
243         return FALSE;
244     }
245     return TRUE;
246 }
247
248 wtap_open_return_val logcat_text_open(wtap *wth, int *err, gchar **err_info _U_) {
249     gchar cbuff[WTAP_MAX_PACKET_SIZE];
250     gchar *ret = NULL;
251
252     if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
253         return WTAP_OPEN_ERROR;
254
255     do {
256         ret = file_gets(cbuff, WTAP_MAX_PACKET_SIZE, wth->fh);
257     } while (NULL != ret && !file_eof(wth->fh)
258             && ((3 > strlen(cbuff))
259                     || g_regex_match_simple(SPECIAL_STRING, cbuff, (GRegexCompileFlags)((gint) G_REGEX_ANCHORED | (gint) G_REGEX_RAW),
260                             G_REGEX_MATCH_NOTEMPTY)));
261
262     if (g_regex_match_simple(BRIEF_STRING, cbuff, (GRegexCompileFlags)((gint) G_REGEX_ANCHORED | (gint) G_REGEX_RAW),
263             G_REGEX_MATCH_NOTEMPTY)) {
264         wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_LOGCAT_BRIEF;
265         wth->file_encap = WTAP_ENCAP_LOGCAT_BRIEF;
266     } else if (g_regex_match_simple(TAG_STRING, cbuff, (GRegexCompileFlags)((gint) G_REGEX_ANCHORED | (gint) G_REGEX_RAW),
267             G_REGEX_MATCH_NOTEMPTY)) {
268         wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_LOGCAT_TAG;
269         wth->file_encap = WTAP_ENCAP_LOGCAT_TAG;
270     } else if (g_regex_match_simple(PROCESS_STRING, cbuff, (GRegexCompileFlags)((gint) G_REGEX_ANCHORED | (gint) G_REGEX_RAW),
271             G_REGEX_MATCH_NOTEMPTY)) {
272         wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_LOGCAT_PROCESS;
273         wth->file_encap = WTAP_ENCAP_LOGCAT_PROCESS;
274     } else if (g_regex_match_simple(TIME_STRING, cbuff, (GRegexCompileFlags)((gint) G_REGEX_ANCHORED | (gint) G_REGEX_RAW),
275             G_REGEX_MATCH_NOTEMPTY)) {
276         wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_LOGCAT_TIME;
277         wth->file_encap = WTAP_ENCAP_LOGCAT_TIME;
278     } else if (g_regex_match_simple(THREAD_STRING, cbuff, (GRegexCompileFlags)((gint) G_REGEX_ANCHORED | (gint) G_REGEX_RAW),
279             G_REGEX_MATCH_NOTEMPTY)) {
280         wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_LOGCAT_THREAD;
281         wth->file_encap = WTAP_ENCAP_LOGCAT_THREAD;
282     } else if (g_regex_match_simple(THREADTIME_STRING, cbuff, (GRegexCompileFlags)((gint) G_REGEX_ANCHORED | (gint) G_REGEX_RAW),
283             G_REGEX_MATCH_NOTEMPTY)) {
284         wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_LOGCAT_THREADTIME;
285         wth->file_encap = WTAP_ENCAP_LOGCAT_THREADTIME;
286     } else if (g_regex_match_simple(LONG_STRING, cbuff, (GRegexCompileFlags)((gint) G_REGEX_ANCHORED | (gint) G_REGEX_RAW),
287             G_REGEX_MATCH_NOTEMPTY)) {
288         wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_LOGCAT_LONG;
289         wth->file_encap = WTAP_ENCAP_LOGCAT_LONG;
290     } else {
291         return WTAP_OPEN_NOT_MINE;
292     }
293
294     if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
295         return WTAP_OPEN_ERROR;
296
297     wth->snapshot_length = 0;
298
299     wth->subtype_read = logcat_text_read;
300     wth->subtype_seek_read = logcat_text_seek_read;
301     wth->file_tsprec = WTAP_TSPREC_USEC;
302     return WTAP_OPEN_MINE;
303 }
304
305 int logcat_text_brief_dump_can_write_encap(int encap) {
306     if (encap == WTAP_ENCAP_PER_PACKET)
307         return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
308
309     switch (encap) {
310     case WTAP_ENCAP_LOGCAT:
311     case WTAP_ENCAP_LOGCAT_BRIEF:
312     case WTAP_ENCAP_WIRESHARK_UPPER_PDU:
313         return 0;
314     default:
315         return WTAP_ERR_UNWRITABLE_ENCAP;
316     }
317 }
318
319 int logcat_text_process_dump_can_write_encap(int encap) {
320     if (encap == WTAP_ENCAP_PER_PACKET)
321         return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
322
323     switch (encap) {
324     case WTAP_ENCAP_LOGCAT:
325     case WTAP_ENCAP_LOGCAT_PROCESS:
326     case WTAP_ENCAP_WIRESHARK_UPPER_PDU:
327         return 0;
328     default:
329         return WTAP_ERR_UNWRITABLE_ENCAP;
330     }
331 }
332
333 int logcat_text_tag_dump_can_write_encap(int encap) {
334     if (encap == WTAP_ENCAP_PER_PACKET)
335         return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
336
337     switch (encap) {
338     case WTAP_ENCAP_LOGCAT:
339     case WTAP_ENCAP_LOGCAT_TAG:
340     case WTAP_ENCAP_WIRESHARK_UPPER_PDU:
341         return 0;
342     default:
343         return WTAP_ERR_UNWRITABLE_ENCAP;
344     }
345 }
346
347 int logcat_text_time_dump_can_write_encap(int encap) {
348     if (encap == WTAP_ENCAP_PER_PACKET)
349         return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
350
351     switch (encap) {
352     case WTAP_ENCAP_LOGCAT:
353     case WTAP_ENCAP_LOGCAT_TIME:
354     case WTAP_ENCAP_WIRESHARK_UPPER_PDU:
355         return 0;
356     default:
357         return WTAP_ERR_UNWRITABLE_ENCAP;
358     }
359 }
360
361 int logcat_text_thread_dump_can_write_encap(int encap) {
362     if (encap == WTAP_ENCAP_PER_PACKET)
363         return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
364
365     switch (encap) {
366     case WTAP_ENCAP_LOGCAT:
367     case WTAP_ENCAP_LOGCAT_THREAD:
368     case WTAP_ENCAP_WIRESHARK_UPPER_PDU:
369         return 0;
370     default:
371         return WTAP_ERR_UNWRITABLE_ENCAP;
372     }
373 }
374
375 int logcat_text_threadtime_dump_can_write_encap(int encap) {
376     if (encap == WTAP_ENCAP_PER_PACKET)
377         return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
378
379     switch (encap) {
380     case WTAP_ENCAP_LOGCAT:
381     case WTAP_ENCAP_LOGCAT_THREADTIME:
382     case WTAP_ENCAP_WIRESHARK_UPPER_PDU:
383         return 0;
384     default:
385         return WTAP_ERR_UNWRITABLE_ENCAP;
386     }
387 }
388
389 int logcat_text_long_dump_can_write_encap(int encap) {
390     if (encap == WTAP_ENCAP_PER_PACKET)
391         return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
392
393     switch (encap) {
394     case WTAP_ENCAP_LOGCAT:
395     case WTAP_ENCAP_LOGCAT_LONG:
396     case WTAP_ENCAP_WIRESHARK_UPPER_PDU:
397         return 0;
398     default:
399         return WTAP_ERR_UNWRITABLE_ENCAP;
400     }
401 }
402
403 static gboolean logcat_text_dump_text(wtap_dumper *wdh,
404     const struct wtap_pkthdr *phdr,
405     const guint8 *pd, int *err, gchar **err_info)
406 {
407     gchar                          *buf;
408     gint                            length;
409     gchar                           priority;
410     const struct logger_entry      *log_entry;
411     const struct logger_entry_v2   *log_entry_v2;
412     gint                            payload_length;
413     const gchar                    *tag;
414     gint32                          pid;
415     gint32                          tid;
416     gint32                          seconds;
417     gint32                          milliseconds;
418     const guint8                   *msg_payload = NULL;
419     const gchar                    *msg_begin;
420     gint                            msg_pre_skip;
421     gchar                          *log;
422     gchar                          *log_part;
423     gchar                          *log_next;
424     gint                           logcat_version;
425     const struct dumper_t          *dumper        = (const struct dumper_t *) wdh->priv;
426
427     /* We can only write packet records. */
428     if (phdr->rec_type != REC_TYPE_PACKET) {
429         *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
430         return FALSE;
431     }
432
433     switch (wdh->encap) {
434     case WTAP_ENCAP_WIRESHARK_UPPER_PDU:
435         {
436             gint skipped_length;
437
438             skipped_length = logcat_exported_pdu_length(pd);
439             pd += skipped_length;
440
441             if (!wtap_dump_file_write(wdh, (const gchar*) pd, phdr->caplen - skipped_length, err)) {
442                 return FALSE;
443             }
444         }
445         break;
446     case WTAP_ENCAP_LOGCAT:
447         /* Skip EXPORTED_PDU*/
448         if (wdh->encap == WTAP_ENCAP_WIRESHARK_UPPER_PDU) {
449             gint skipped_length;
450
451             skipped_length = logcat_exported_pdu_length(pd);
452             pd += skipped_length;
453
454             logcat_version = buffered_detect_version(pd);
455         } else {
456             const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
457
458             logcat_version = pseudo_header->logcat.version;
459         }
460
461         log_entry    = (const struct logger_entry *)(const void *) pd;
462         log_entry_v2 = (const struct logger_entry_v2 *)(const void *) pd;
463
464         payload_length = GINT32_FROM_LE(log_entry->len);
465         pid = GINT32_FROM_LE(log_entry->pid);
466         tid = GINT32_FROM_LE(log_entry->tid);
467         seconds = GINT32_FROM_LE(log_entry->sec);
468         milliseconds = GINT32_FROM_LE(log_entry->nsec) / 1000000;
469
470         /* msg: <prio:1><tag:N>\0<msg:N>\0 with N >= 0, last \0 can be missing */
471         if (logcat_version == 1) {
472             msg_payload = (const guint8 *) (log_entry + 1);
473
474             priority = get_priority(msg_payload[0]);
475             tag = msg_payload + 1;
476             msg_pre_skip = 1 + (gint) strlen(tag) + 1;
477             msg_begin = msg_payload + msg_pre_skip;
478         } else if (logcat_version == 2) {
479             msg_payload = (const guint8 *) (log_entry_v2 + 1);
480
481             priority = get_priority(msg_payload[0]);
482             tag = msg_payload + 1;
483             msg_pre_skip = 1 + (gint) strlen(tag) + 1;
484             msg_begin = msg_payload + msg_pre_skip;
485         } else {
486             *err = WTAP_ERR_UNWRITABLE_REC_DATA;
487             *err_info = g_strdup_printf("logcat: version %d isn't supported",
488                                         logcat_version);
489             return FALSE;
490         }
491
492         /* copy the message part. If a nul byte was missing, it will be added. */
493         log = g_strndup(msg_begin, payload_length - msg_pre_skip);
494
495         /* long format: display one header followed by the whole message (which may
496          * contain new lines). Other formats: include tag, etc. with each line */
497         log_next = log;
498         do {
499             log_part = log_next;
500             if (dumper->type == WTAP_ENCAP_LOGCAT_LONG) {
501                 /* read until end, there is no next string */
502                 log_next = NULL;
503             } else {
504                 /* read until next newline */
505                 log_next = strchr(log_part, '\n');
506                 if (log_next != NULL) {
507                     *log_next = '\0';
508                     ++log_next;
509                     /* ignore trailing newline */
510                     if (*log_next == '\0') {
511                         log_next = NULL;
512                     }
513                 }
514             }
515
516             buf = logcat_log(dumper, seconds, milliseconds, pid, tid, priority, tag, log_part);
517             if (!buf) {
518                 g_free(log);
519                 return FALSE;
520             }
521             length = (guint32) strlen(buf);
522
523             if (!wtap_dump_file_write(wdh, buf, length, err)) {
524                 g_free(log);
525                 return FALSE;
526             }
527
528             wdh->bytes_dumped += length;
529         } while (log_next != NULL );
530
531         g_free(log);
532
533         break;
534     case WTAP_ENCAP_LOGCAT_BRIEF:
535     case WTAP_ENCAP_LOGCAT_TAG:
536     case WTAP_ENCAP_LOGCAT_PROCESS:
537     case WTAP_ENCAP_LOGCAT_TIME:
538     case WTAP_ENCAP_LOGCAT_THREAD:
539     case WTAP_ENCAP_LOGCAT_THREADTIME:
540     case WTAP_ENCAP_LOGCAT_LONG:
541         if (dumper->type == wdh->encap) {
542             if (!wtap_dump_file_write(wdh, (const gchar*) pd, phdr->caplen, err)) {
543                 return FALSE;
544             }
545         } else {
546             *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
547             return FALSE;
548         }
549     }
550
551     return TRUE;
552 }
553
554 static gboolean logcat_text_dump_open(wtap_dumper *wdh, guint dump_type, int *err _U_) {
555     struct dumper_t *dumper;
556
557     dumper = (struct dumper_t *) g_malloc(sizeof(struct dumper_t));
558     dumper->type = dump_type;
559
560     wdh->priv = dumper;
561     wdh->subtype_write = logcat_text_dump_text;
562
563     return TRUE;
564 }
565
566 gboolean logcat_text_brief_dump_open(wtap_dumper *wdh, int *err) {
567     return logcat_text_dump_open(wdh, WTAP_ENCAP_LOGCAT_BRIEF, err);
568 }
569
570 gboolean logcat_text_process_dump_open(wtap_dumper *wdh, int *err) {
571     return logcat_text_dump_open(wdh, WTAP_ENCAP_LOGCAT_PROCESS, err);
572 }
573
574 gboolean logcat_text_tag_dump_open(wtap_dumper *wdh, int *err) {
575     return logcat_text_dump_open(wdh, WTAP_ENCAP_LOGCAT_TAG, err);
576 }
577
578 gboolean logcat_text_time_dump_open(wtap_dumper *wdh, int *err) {
579     return logcat_text_dump_open(wdh, WTAP_ENCAP_LOGCAT_TIME, err);
580 }
581
582 gboolean logcat_text_thread_dump_open(wtap_dumper *wdh, int *err) {
583     return logcat_text_dump_open(wdh, WTAP_ENCAP_LOGCAT_THREAD, err);
584 }
585
586 gboolean logcat_text_threadtime_dump_open(wtap_dumper *wdh, int *err) {
587     return logcat_text_dump_open(wdh, WTAP_ENCAP_LOGCAT_THREADTIME, err);
588 }
589
590 gboolean logcat_text_long_dump_open(wtap_dumper *wdh, int *err) {
591     return logcat_text_dump_open(wdh, WTAP_ENCAP_LOGCAT_LONG, err);
592 }
593
594 /*
595  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
596  *
597  * Local variables:
598  * c-basic-offset: 4
599  * tab-width: 8
600  * indent-tabs-mode: nil
601  * End:
602  *
603  * vi: set shiftwidth=4 tabstop=8 expandtab:
604  * :indentSize=4:tabSize=8:noTabs=true:
605  */