]> granicus.if.org Git - strace/blob - stage_output.c
evdev: decode struct input_absinfo regardless of in-kernel definitions
[strace] / stage_output.c
1 /*
2  * Copyright (c) 2017 Intel Corporation
3  * Copyright (c) 2019 Paul Chaignon <paul.chaignon@gmail.com>
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: LGPL-2.1-or-later
7  */
8
9 /*
10  * open_memstream returns a FILE stream that allows writing to a
11  * dynamically growing buffer, that can be either copied to
12  * tcp->outf (syscall successful) or dropped (syscall failed)
13  */
14
15 #include "defs.h"
16
17 struct staged_output_data {
18         char *memfptr;
19         size_t memfloc;
20         FILE *real_outf;        /* Backup for real outf while staging */
21 };
22
23 FILE *
24 strace_open_memstream(struct tcb *tcp)
25 {
26         FILE *fp = NULL;
27
28 #if HAVE_OPEN_MEMSTREAM
29         tcp->staged_output_data = xmalloc(sizeof(*tcp->staged_output_data));
30         fp = open_memstream(&tcp->staged_output_data->memfptr,
31                             &tcp->staged_output_data->memfloc);
32         if (!fp)
33                 perror_msg_and_die("open_memstream");
34         /*
35          * Call to fflush required to update tcp->memfptr,
36          * see open_memstream man page.
37          */
38         fflush(fp);
39
40         /* Store the FILE pointer for later restauration. */
41         tcp->staged_output_data->real_outf = tcp->outf;
42         tcp->outf = fp;
43 #endif
44
45         return fp;
46 }
47
48 void
49 strace_close_memstream(struct tcb *tcp, bool publish)
50 {
51 #if HAVE_OPEN_MEMSTREAM
52         if (!tcp->staged_output_data) {
53                 debug_msg("memstream already closed");
54                 return;
55         }
56
57         if (fclose(tcp->outf))
58                 perror_msg("fclose(tcp->outf)");
59
60         tcp->outf = tcp->staged_output_data->real_outf;
61         if (tcp->staged_output_data->memfptr) {
62                 if (publish)
63                         fputs_unlocked(tcp->staged_output_data->memfptr,
64                                        tcp->outf);
65                 else
66                         debug_msg("syscall output dropped: %s",
67                                   tcp->staged_output_data->memfptr);
68
69                 free(tcp->staged_output_data->memfptr);
70                 tcp->staged_output_data->memfptr = NULL;
71         }
72         free(tcp->staged_output_data);
73         tcp->staged_output_data = NULL;
74 #endif
75 }