automotive-dlt
dlt_cdh_context.c
Go to the documentation of this file.
1 /*
2  * @licence app begin@
3  * SPDX license identifier: MPL-2.0
4  *
5  * Copyright (C) 2011-2015, BMW AG
6  *
7  * This file is part of GENIVI Project DLT - Diagnostic Log and Trace.
8  *
9  * This Source Code Form is subject to the terms of the
10  * Mozilla Public License (MPL), v. 2.0.
11  * If a copy of the MPL was not distributed with this file,
12  * You can obtain one at http://mozilla.org/MPL/2.0/.
13  *
14  * For further information see http://www.genivi.org/.
15  * @licence end@
16  */
17 
28 #include <stdio.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <errno.h>
33 #include <dirent.h>
34 #include <syslog.h>
35 
36 #include "dlt_cdh.h"
37 
38 // Global buffer for file reading
39 char g_buffer[4096];
40 
41 /* ===================================================================
42  ** Method : get_exec_name(...)
43  **
44  ** Description : read executable filename
45  **
46  ** Parameters : INPUT p_pid_str pid of the process
47  ** OUTPUT p_exec_name executable name
48  ** INPUT p_exec_name_maxsize size of p_exec_name buffer
49  **
50  ** Returns : 0 if success, else -1
51  ** ===================================================================*/
52 cdh_status_t get_exec_name(unsigned int p_pid, char* p_exec_name, int p_exec_name_maxsize)
53 {
54  char l_exe_link[CORE_MAX_FILENAME_LENGTH] = { 0 };
55  char *l_name_ptr = NULL;
56 
57  memset(l_exe_link, 0, sizeof(l_exe_link));
58  snprintf(l_exe_link, sizeof(l_exe_link) - 1, "/proc/%d/exe", p_pid);
59 
60  if (readlink(l_exe_link, g_buffer, p_exec_name_maxsize) < 0)
61  return CDH_NOK;
62 
63  if ((l_name_ptr = strrchr(g_buffer, '/')) == NULL)
64  return CDH_NOK;
65 
66  memset(p_exec_name, 0, p_exec_name_maxsize);
67  strncpy(p_exec_name, l_name_ptr + 1, p_exec_name_maxsize - 1);
68 
69  return CDH_OK;
70 }
71 
72 /* ===================================================================
73  ** Method : dump_file_to(...)
74  **
75  ** Description : dump the content of file p_src_filename to the file descriptor p_fout
76  **
77  ** Parameters : INPUT p_src_filename
78  ** INPUT p_fout
79  **
80  ** Returns : 0 if success, else -1
81  ** ===================================================================*/
82 cdh_status_t dump_file_to(const char* p_src_filename, FILE* p_fout)
83 {
84  FILE* l_fin = NULL;
85  int bytes_read = 0;
86 
87  if (p_fout == NULL)
88  return CDH_NOK;
89 
90  fprintf(p_fout, "\n==== Dumping file <%s> ====\n", p_src_filename);
91 
92  if ((l_fin = fopen(p_src_filename, "rt")) == NULL)
93  {
94  syslog(LOG_ERR, "ERR opening info file '%s' for dumping [%s]",
95  p_src_filename,
96  strerror(errno));
97 
98  fprintf(p_fout, "**error**\n");
99 
100  return CDH_NOK;
101  }
102 
103  while ((bytes_read = fread(g_buffer, 1, sizeof(g_buffer), l_fin)) != 0)
104  {
105  int i = 0;
106 
107  // changes all "\0" in the file to a "\n"
108  // (needed for example for /proc/<pid>/cmdline, to keep all arguments)
109  for (i = 0; i < bytes_read; i++)
110  {
111  if (g_buffer[i] == '\000')
112  g_buffer[i] = '\n';
113  }
114 
115  fwrite(g_buffer, 1, bytes_read, p_fout);
116  if (ferror(p_fout))
117  {
118  syslog(LOG_ERR, "Writing in context file failed [%s]", strerror(errno));
119  fclose(p_fout);
120  fclose(l_fin);
121 
122  return CDH_NOK;
123 
124  }
125  }
126 
127  if (ferror(l_fin))
128  {
129  syslog(LOG_ERR, "reading '%s' failed [%s]", p_src_filename, strerror(errno));
130  fclose(l_fin);
131 
132  return CDH_NOK;
133  }
134 
135  fclose(l_fin);
136 
137  fprintf(p_fout, "\n");
138  return CDH_OK;
139 }
140 
141 //*************************************************************************************************/
142 // "ls -l" implementation for /proc/<pid>/fd (at least)
143 // Taken from coreutils sources, lib/filemode.c
144 //
145 /* Return a character indicating the type of file described by
146  file mode BITS:
147  '-' regular file
148  'b' block special file
149  'c' character special file
150  'C' high performance ("contiguous data") file
151  'd' directory
152  'D' door
153  'l' symbolic link
154  'm' multiplexed file (7th edition Unix; obsolete)
155  'n' network special file (HP-UX)
156  'p' fifo (named pipe)
157  'P' port
158  's' socket
159  'w' whiteout (4.4BSD)
160  '?' some other file type */
161 
162 static char ftypelet(mode_t bits)
163 {
164  /* These are the most common, so test for them first. */
165  if (S_ISREG(bits))
166  return '-';
167  if (S_ISDIR(bits))
168  return 'd';
169 
170  /* Other letters standardized by POSIX 1003.1-2004. */
171  if (S_ISBLK(bits))
172  return 'b';
173  if (S_ISCHR(bits))
174  return 'c';
175  if (S_ISLNK(bits))
176  return 'l';
177  if (S_ISFIFO(bits))
178  return 'p';
179 
180  /* Other file types (though not letters) standardized by POSIX. */
181  if (S_ISSOCK(bits))
182  return 's';
183 
184  /* Nonstandard file types.
185  if (S_ISCTG (bits))
186  return 'C';
187  if (S_ISDOOR (bits))
188  return 'D';
189  if (S_ISMPB (bits) || S_ISMPC (bits))
190  return 'm';
191  if (S_ISNWK (bits))
192  return 'n';
193  if (S_ISPORT (bits))
194  return 'P';
195  if (S_ISWHT (bits))
196  return 'w';
197  */
198 
199  return '?';
200 }
201 
202 void strmode(mode_t mode, char *str)
203 {
204  if (str == NULL)
205  return;
206 
207  str[0] = ftypelet(mode);
208  str[1] = mode & S_IRUSR ? 'r' : '-';
209  str[2] = mode & S_IWUSR ? 'w' : '-';
210  str[3] = (mode & S_ISUID
211  ? (mode & S_IXUSR ? 's' : 'S')
212  :
213  (mode & S_IXUSR ? 'x' : '-'));
214  str[4] = mode & S_IRGRP ? 'r' : '-';
215  str[5] = mode & S_IWGRP ? 'w' : '-';
216  str[6] = (mode & S_ISGID
217  ? (mode & S_IXGRP ? 's' : 'S')
218  :
219  (mode & S_IXGRP ? 'x' : '-'));
220  str[7] = mode & S_IROTH ? 'r' : '-';
221  str[8] = mode & S_IWOTH ? 'w' : '-';
222  str[9] = (mode & S_ISVTX
223  ? (mode & S_IXOTH ? 't' : 'T')
224  :
225  (mode & S_IXOTH ? 'x' : '-'));
226  str[10] = ' ';
227  str[11] = '\0';
228 }
229 
230 /* ===================================================================
231  ** Method : list_dircontent_to(...)
232  **
233  ** Description : list the filenames in p_dirname directory to the file descriptor p_fout
234  **
235  ** Parameters : INPUT p_dirname
236  ** INPUT p_fout
237  **
238  ** Returns : 0 if success, else -1
239  ** ===================================================================*/
240 cdh_status_t list_dircontent_to(const char* p_dirname, FILE* p_fout)
241 {
242  DIR* l_dd = NULL; // directory descriptor
243  struct dirent* l_entity = NULL;
244 
245  if ((l_dd = opendir(p_dirname)) == NULL)
246  {
247  syslog(LOG_ERR, "ERR reading info dir '%s' failed [%s]", p_dirname, strerror(errno));
248  return CDH_NOK;
249  }
250 
251  fprintf(p_fout, "==== Listing directory <%s> ====\n", p_dirname);
252 
253  while ((l_entity = readdir(l_dd)) != NULL)
254  {
255  char l_fullpath[CORE_MAX_FILENAME_LENGTH] = { 0 };
256  char l_linkpath[CORE_MAX_FILENAME_LENGTH] = { 0 };
257  char l_modebuf[12] = { 0 };
258 
259  struct stat l_stat;
260  ssize_t l_size = 0;
261 
262  if (!strcmp(l_entity->d_name, ".") || !strcmp(l_entity->d_name, ".."))
263  continue;
264 
265  snprintf(l_fullpath, sizeof(l_fullpath), "%s/%s", p_dirname, l_entity->d_name);
266 
267  if (lstat(l_fullpath, &l_stat) < 0)
268  {
269  syslog(LOG_ERR, "ERR lstat on '%s' failed. [%s]", l_fullpath, strerror(errno));
270  continue;
271  }
272 
273  strmode(l_stat.st_mode, l_modebuf);
274 
275  fprintf(p_fout, "%s %ld %d %d %ld %4s",
276  l_modebuf,
277  l_stat.st_nlink,
278  l_stat.st_uid,
279  l_stat.st_gid,
280  l_stat.st_size,
281  l_entity->d_name);
282 
283  switch (l_stat.st_mode & S_IFMT)
284  {
285  case S_IFBLK:
286  fprintf(p_fout, " [block device]\n");
287  break;
288 
289  case S_IFCHR:
290  fprintf(p_fout, " [character device]\n");
291  break;
292 
293  case S_IFDIR:
294  fprintf(p_fout, " [directory]\n");
295  break;
296 
297  case S_IFIFO:
298  fprintf(p_fout, " [FIFO/pipe]\n");
299  break;
300 
301  case S_IFLNK:
302  l_size = readlink(l_fullpath, l_linkpath, sizeof(l_linkpath));
303  l_linkpath[l_size] = 0;
304  fprintf(p_fout, " -> %s\n", l_linkpath);
305  break;
306 
307  case S_IFREG:
308  fprintf(p_fout, " [regular file]\n");
309  break;
310 
311  case S_IFSOCK:
312  fprintf(p_fout, " [socket]\n");
313  break;
314 
315  default:
316  fprintf(p_fout, " [unknown?]\n");
317  break;
318  }
319 
320  } // while ( (l_entity = readdir(l_dd)) != NULL )
321 
322  fprintf(p_fout, "===========================\n");
323  closedir(l_dd);
324 
325  return CDH_OK;
326 }
327 
328 //*************************************************************************************************/
329 // END of "ls -l" implementation for /proc/<pid>/fd (at least)
330 //*************************************************************************************************/
331 
332 /* ===================================================================
333  ** Method : write_proc_context(...)
334  **
335  ** Description : write the context data of the crashed process
336  ** (context data coming mainly from /proc)
337  **
338  ** Parameters : INPUT p_proc crashed process info
339  **
340  ** Returns : 0 if success, else -1
341  ** ===================================================================*/
343 {
344  FILE* l_fout = NULL;
345  char l_procfile[256] = { 0 };
346  char l_outfilename[CORE_MAX_FILENAME_LENGTH] = { 0 };
347 
348  if (p_proc == NULL)
349  return CDH_NOK;
350 
351  snprintf(l_outfilename, sizeof(l_outfilename), CONTEXT_FILE_PATTERN,
353  p_proc->timestamp,
354  p_proc->name,
355  p_proc->pid);
356 
357  if ((l_fout = fopen(l_outfilename, "w+t")) == NULL)
358  {
359  syslog(LOG_ERR, "ERR Cannot open context file '%s' [%s]", l_outfilename, strerror(errno));
360  return CDH_NOK;
361  }
362 
363 #define PROC_FILENAME(x) do{\
364  snprintf(l_procfile, sizeof(l_procfile), "/proc/%d/"x,\
365  p_proc->pid);\
366 } while(0)
367 
368  fprintf(l_fout, "ProcName:%s\n", p_proc->name);
369  fprintf(l_fout, "ThreadName:%s\n", p_proc->threadname);
370  fprintf(l_fout, "PID:%d\n", p_proc->pid);
371  fprintf(l_fout, "signal:%d\n", p_proc->signal);
372 
373  PROC_FILENAME("cmdline");
374  dump_file_to(l_procfile, l_fout);
375 
376  PROC_FILENAME("cgroup");
377  dump_file_to(l_procfile, l_fout);
378 
379  PROC_FILENAME("stack");
380  dump_file_to(l_procfile, l_fout);
381 
382  dump_file_to("/proc/loadavg", l_fout);
383  dump_file_to("/etc/sysrel", l_fout);
384  dump_file_to("/proc/version", l_fout);
385 
386  PROC_FILENAME("environ");
387  dump_file_to(l_procfile, l_fout);
388 
389  PROC_FILENAME("status");
390  dump_file_to(l_procfile, l_fout);
391 
392  PROC_FILENAME("sched");
393  dump_file_to(l_procfile, l_fout);
394 
395  PROC_FILENAME("maps");
396  dump_file_to(l_procfile, l_fout);
397 
398  PROC_FILENAME("fd");
399  list_dircontent_to(l_procfile, l_fout);
400 
401 #undef PROC_FILENAME
402 
403  fflush(l_fout);
404 
405  return CDH_OK;
406 }
407 
cdh_status_t get_exec_name(unsigned int p_pid, char *p_exec_name, int p_exec_name_maxsize)
char name[MAX_PROC_NAME_LENGTH]
Definition: dlt_cdh.h:65
int signal
Definition: dlt_cdh.h:69
static char ftypelet(mode_t bits)
#define CONTEXT_FILE_PATTERN
Definition: dlt_cdh.h:48
cdh_status_t
#define CORE_TMP_DIRECTORY
Definition: dlt_cdh.h:40
#define PROC_FILENAME(x)
char g_buffer[4096]
cdh_status_t list_dircontent_to(const char *p_dirname, FILE *p_fout)
cdh_status_t write_proc_context(const proc_info_t *p_proc)
pid_t pid
Definition: dlt_cdh.h:67
cdh_status_t dump_file_to(const char *p_src_filename, FILE *p_fout)
char threadname[MAX_PROC_NAME_LENGTH]
Definition: dlt_cdh.h:66
static char str[DLT_DAEMON_TEXTBUFSIZE]
Definition: dlt-daemon.c:80
uint32_t timestamp
Definition: dlt_cdh.h:68
#define CORE_MAX_FILENAME_LENGTH
Definition: dlt_cdh.h:42
void strmode(mode_t mode, char *str)
#define NULL
Definition: dlt_common.h:232