libc, libutil: remove compat hacks
[minix.git] / commands / gcov-pull / gcov-pull.c
blobe67241c26d697a76ff531bf8bfdf1a04070f8c38
1 /*
2 * gcov-pull - Request gcov data from server and write it to gcda files
3 * Author: Anton Kuijsten
4 */
6 #include <fcntl.h>
7 #include <stdio.h>
8 #include <lib.h>
9 #include <unistd.h>
10 #include <sys/types.h>
11 #include <stdlib.h>
12 #ifndef __NBSD_LIBC
13 #include <alloca.h>
14 #endif
15 #include <string.h>
16 #include <assert.h>
17 #include <minix/gcov.h>
19 #define BUFF_SZ (4 * 1024 * 1024) /* 4MB */
21 int read_int(void);
23 char *buff_p;
25 /* helper function to read int from the buffer */
26 int read_int(void)
28 int res;
29 memcpy(&res, buff_p, sizeof(int));
30 buff_p += sizeof(int);
31 return res;
34 int main(int argc, char *argv[])
36 FILE *fd = NULL;
37 int server_nr, command, size, result;
38 char buff[BUFF_SZ]; /* Buffer for all the metadata and file data sent */
40 if(argc!=2 || sscanf(argv[1], "%d", &server_nr)!=1) {
41 fprintf(stderr, "Usage: %s <pid>\n", argv[0]);
42 return 1;
46 When making a GCOV call to a server, the gcov library linked into
47 the server will try to write gcov data to disk. This writing is
48 normally done with calls to the vfs, using stdio library calls.
49 This is not correct behaviour for servers, especially vfs itself.
50 Therefore, the server catches those attempts. The messages used for
51 this communication are stored in a buffer. When the gcov operation
52 is done, the buffer is copied from the server to this user space,
53 from where the calls are finally made to the vfs. GCOV calls to the
54 various servers are all routed trough vfs. For more information, see
55 the <minix/gcov.h> header file.
58 /* visit complete buffer, so vm won't has to
59 manage the pages while flushing
60 */
61 memset(buff, 'a', sizeof(buff));
63 buff_p = buff;
65 result = gcov_flush_svr(buff_p, BUFF_SZ, server_nr);
67 if(result >= BUFF_SZ) {
68 fprintf(stderr, "Too much data to hold in buffer: %d\n", result);
69 fprintf(stderr, "Maximum: %d\n", BUFF_SZ);
70 return 1;
73 if(result < 0) {
74 fprintf(stderr, "Call failed\n");
75 return 1;
78 /* At least GCOVOP_END opcode expected. */
79 if(result < sizeof(int)) {
80 fprintf(stderr, "Invalid gcov data from pid %d\n", server_nr);
81 return 1;
84 /* Only GCOVOP_END is valid but empty. */
85 if(result == sizeof(int)) {
86 fprintf(stderr, "no gcov data.\n");
87 return 0;
90 /* Iterate through the system calls contained in the buffer,
91 * and execute them
93 while((command=read_int()) != GCOVOP_END) {
94 char *fn;
95 switch(command) {
96 case GCOVOP_OPEN:
97 size = read_int();
98 fn = buff_p;
99 if(strchr(fn, '/')) {
100 fn = strrchr(fn, '/');
101 assert(fn);
102 fn++;
104 assert(fn);
105 if(!(fd = fopen(fn, "w+"))) {
106 perror(buff_p);
107 exit(1);
109 buff_p += size;
110 break;
111 case GCOVOP_CLOSE:
112 if(!fd) {
113 fprintf(stderr, "bogus close\n");
114 exit(1);
116 fclose(fd);
117 fd = NULL;
118 break;
119 case GCOVOP_WRITE:
120 size = read_int();
121 fwrite(buff_p, size, 1, fd);
122 buff_p += size;
123 break;
124 default:
125 fprintf(stderr, "bogus command %d in buffer.\n",
126 command);
127 exit(1);
131 return 0;