3 * Linux Trace Toolkit Daemon
5 * This is a simple daemon that reads a few relayfs channels and save them in a
10 * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
15 #include <sys/types.h>
36 struct channel_trace_fd
{
41 static char *trace_name
= NULL
;
42 static char *channel_name
= NULL
;
43 static int daemon_mode
= 0;
44 static int append_mode
= 0;
48 * -t directory Directory name of the trace to write to. Will be created.
49 * -c directory Root directory of the relayfs trace channels.
50 * -d Run in background (daemon).
51 * -a Trace append mode.
53 void show_arguments(void)
55 printf("Please use the following arguments :\n");
57 printf("-t directory Directory name of the trace to write to.\n"
58 " It will be created.\n");
59 printf("-c directory Root directory of the relayfs trace channels.\n");
60 printf("-d Run in background (daemon).\n");
61 printf("-a Append to an possibly existing trace.\n");
68 * Parses the command line arguments.
70 * Returns 1 if the arguments were correct, but doesn't ask for program
71 * continuation. Returns -1 if the arguments are incorrect, or 0 if OK.
73 int parse_arguments(int argc
, char **argv
)
79 if(strcmp(argv
[1], "-h") == 0) {
86 switch(argv
[argn
][0]) {
88 switch(argv
[argn
][1]) {
91 trace_name
= argv
[argn
+1];
97 channel_name
= argv
[argn
+1];
108 printf("Invalid argument '%s'.\n", argv
[argn
]);
114 printf("Invalid argument '%s'.\n", argv
[argn
]);
121 if(trace_name
== NULL
) {
122 printf("Please specify a trace name.\n");
127 if(channel_name
== NULL
) {
128 printf("Please specify a channel name.\n");
138 printf("Linux Trace Toolkit Trace Daemon\n");
140 printf("Reading from relayfs directory : %s\n", channel_name
);
141 printf("Writing to trace directory : %s\n", trace_name
);
146 int open_channel_trace_pairs(char *subchannel_name
, char *subtrace_name
,
147 struct channel_trace_fd
*fd_pairs
)
149 DIR *channel_dir
= opendir(subchannel_name
);
150 struct dirent
*entry
;
151 struct stat stat_buf
;
153 char path_channel
[PATH_MAX
];
154 int path_channel_len
;
155 char *path_channel_ptr
;
156 char path_trace
[PATH_MAX
];
158 char *path_trace_ptr
;
160 if(channel_dir
== NULL
) {
161 perror(subchannel_name
);
165 //FIXME : check if the directory already exist, and ask the user if he wants
166 //to append to the traces.
167 printf("Creating trace subdirectory %s\n", subtrace_name
);
168 ret
= mkdir(subtrace_name
, S_IRWXU
|S_IRWXG
|S_IRWXO
);
170 if(errno
== EEXIST
&& append_mode
) {
171 printf("Appending to directory %s as resquested\n", subtrace_name
);
173 perror(subtrace_name
);
178 strncpy(path_channel
, subchannel_name
, PATH_MAX
-1);
179 path_channel_len
= strlen(path_channel
);
180 path_channel
[path_channel_len
] = '/';
182 path_channel_ptr
= path_channel
+ path_channel_len
;
184 strncpy(path_trace
, subtrace_name
, PATH_MAX
-1);
185 path_trace_len
= strlen(path_trace
);
186 path_trace
[path_trace_len
] = '/';
188 path_trace_ptr
= path_trace
+ path_trace_len
;
190 while((entry
= readdir(channel_dir
)) != NULL
) {
192 if(entry
->d_name
[0] == '.') continue;
194 strncpy(path_channel_ptr
, entry
->d_name
, PATH_MAX
- path_channel_len
);
195 strncpy(path_trace_ptr
, entry
->d_name
, PATH_MAX
- path_trace_len
);
197 ret
= stat(path_channel
, &stat_buf
);
199 perror(path_channel
);
203 printf("Channel file : %s\n", path_channel
);
205 if(S_ISDIR(stat_buf
.st_mode
)) {
207 printf("Entering channel subdirectory...\n");
208 ret
= open_channel_trace_pairs(path_channel
, path_trace
, fd_pairs
);
209 if(ret
< 0) continue;
210 } else if(S_ISREG(stat_buf
.st_mode
)) {
211 printf("Opening file.\n");
213 fd_pairs
->pair
= realloc(fd_pairs
->pair
,
214 ++fd_pairs
->num_pairs
* sizeof(struct fd_pair
));
216 /* Open the channel in read mode */
217 fd_pairs
->pair
[fd_pairs
->num_pairs
-1].channel
=
218 open(path_channel
, O_RDONLY
| O_NONBLOCK
);
219 if(fd_pairs
->pair
[fd_pairs
->num_pairs
-1].channel
== -1) {
220 perror(path_channel
);
222 /* Open the trace in write mode, only append if append_mode */
223 ret
= stat(path_trace
, &stat_buf
);
226 printf("Appending to file %s as resquested\n", path_trace
);
228 fd_pairs
->pair
[fd_pairs
->num_pairs
-1].trace
=
229 open(path_trace
, O_WRONLY
|O_APPEND
,
230 S_IRWXU
|S_IRWXG
|S_IRWXO
);
232 if(fd_pairs
->pair
[fd_pairs
->num_pairs
-1].trace
== -1) {
236 printf("File %s exists, cannot open. Try append mode.\n", path_trace
);
240 if(errno
== ENOENT
) {
241 fd_pairs
->pair
[fd_pairs
->num_pairs
-1].trace
=
242 open(path_trace
, O_WRONLY
|O_CREAT
|O_EXCL
,
243 S_IRWXU
|S_IRWXG
|S_IRWXO
);
244 if(fd_pairs
->pair
[fd_pairs
->num_pairs
-1].trace
== -1) {
252 closedir(channel_dir
);
259 * Read the realyfs channels and write them in the paired tracefiles.
261 * @fd_pairs : paired channels and trace files.
263 * returns 0 on success, -1 on error.
265 * Note that the high priority polled channels are consumed first. We then poll
266 * again to see if these channels are still in priority. Only when no
267 * high priority channel is left, we start reading low priority channels.
269 * Note that a channel is considered high priority when the buffer is almost
273 int read_channels(struct channel_trace_fd
*fd_pairs
)
275 struct pollfd
*pollfd
;
279 pollfd
= malloc(fd_pairs
->num_pairs
* sizeof(struct pollfd
));
281 for(i
=0;i
<fd_pairs
->num_pairs
;i
++) {
282 pollfd
[i
].fd
= fd_pairs
->pair
[i
].channel
;
283 pollfd
[i
].events
= POLLIN
|POLLPRI
;
288 num_rdy
= poll(pollfd
, fd_pairs
->num_pairs
, -1);
290 perror("Poll error");
294 printf("Data received\n");
296 for(i
=0;i
<fd_pairs
->num_pairs
;i
++) {
297 switch(pollfd
[i
].revents
) {
299 printf("Error returned in polling fd %d.\n", pollfd
[i
].fd
);
302 printf("Polling fd %d tells it has hung up.\n", pollfd
[i
].fd
);
305 printf("Polling fd %d tells fd is not open.\n", pollfd
[i
].fd
);
308 /* Take care of high priority channels first. */
313 for(i
=0;i
<fd_pairs
->num_pairs
;i
++) {
314 switch(pollfd
[i
].revents
) {
316 /* Take care of low priority channels. */
329 void close_channel_trace_pairs(struct channel_trace_fd
*fd_pairs
)
334 for(i
=0;i
<fd_pairs
->num_pairs
;i
++) {
335 ret
= close(fd_pairs
->pair
[i
].channel
);
336 if(ret
== -1) perror("Close error on channel");
337 ret
= close(fd_pairs
->pair
[i
].trace
);
338 if(ret
== -1) perror("Close error on trace");
340 free(fd_pairs
->pair
);
343 int main(int argc
, char ** argv
)
347 struct channel_trace_fd fd_pairs
= { NULL
, 0 };
349 ret
= parse_arguments(argc
, argv
);
351 if(ret
!= 0) show_arguments();
352 if(ret
< 0) return EINVAL
;
353 if(ret
> 0) return 0;
365 printf("An error occured while forking.\n");
368 /* else, we are the child, continue... */
371 if(ret
= open_channel_trace_pairs(channel_name
, trace_name
, &fd_pairs
))
374 ret
= read_channels(&fd_pairs
);
377 close_channel_trace_pairs(&fd_pairs
);