add cmdline to proc_begin
Stefan Schuermans

Stefan Schuermans commited on 2020-05-17 13:10:13
Showing 5 changed files, with 148 additions and 1 deletions.

... ...
@@ -18,6 +18,8 @@ add_library(
18 18
   src/cleaner.h
19 19
   src/event.c
20 20
   src/macros.h
21
+  src/stringlist.c
22
+  src/stringlist.h
21 23
   src/symlink.c
22 24
   src/symlink.h
23 25
   src/timestamp.c
... ...
@@ -1,5 +1,6 @@
1 1
 #include <liblwpttr/event.h>
2 2
 #include "cleaner.h"
3
+#include "stringlist.h"
3 4
 #include "symlink.h"
4 5
 #include "timestamp.h"
5 6
 
... ...
@@ -46,6 +47,10 @@ int lwpttr_event_proc_begin(void **data, size_t *size) {
46 47
   if (symlink_read("/proc/self/cwd", &proc_begin.cwd, cleaner) != 0) {
47 48
     return -1;
48 49
   }
50
+  if (stringlist_read("/proc/self/cmdline", &proc_begin.n_cmdline,
51
+                      &proc_begin.cmdline, cleaner) != 0) {
52
+    return -1;
53
+  }
49 54
 
50 55
   struct _Lwproctrace__Event event = LWPROCTRACE__EVENT__INIT;
51 56
   event.timestamp = &timestamp;
... ...
@@ -0,0 +1,120 @@
1
+#include "stringlist.h"
2
+#include "cleaner.h"
3
+
4
+#include <fcntl.h>
5
+#include <stdlib.h>
6
+#include <string.h>
7
+#include <sys/types.h>
8
+#include <sys/stat.h>
9
+#include <unistd.h>
10
+
11
+/**
12
+ * @brief read file contents
13
+ * @param[in] pathname path to file containing zero-terminated string list
14
+ * @param[out] *size size of file contents
15
+ * @return pointer to malloc-ed file contents or NULL
16
+ */
17
+static char * stringlist_read_file(char const *pathname, size_t *size) {
18
+  /* it is not possible to get file size before, because this yields zero for
19
+     files like /proc/self/cmdline */
20
+  *size = 0;
21
+  /* open file */
22
+  int fd = open(pathname, O_RDONLY);
23
+  if (fd == -1) {
24
+    return NULL;
25
+  }
26
+  /* get initial buffer */
27
+  size_t sz = 4096;
28
+  char *data = malloc(sz);
29
+  if (! data) {
30
+    close(fd);
31
+    return NULL;
32
+  }
33
+  /* read file contents - potentially iteratively */
34
+  size_t pos = 0;
35
+  while (1) {
36
+    /* read file contents */
37
+    ssize_t len = read(fd, data + pos, sz - pos);
38
+    /* error -> cleanup and return failure */
39
+    if (len < 0) {
40
+      free(data);
41
+      close(fd);
42
+      return NULL;
43
+    }
44
+    if (len == 0 ) {
45
+      /* end of file -> return data */
46
+      *size = pos;
47
+      return data;
48
+    }
49
+    /* data read -> add to buffer */
50
+    pos += len;
51
+    /* buffer full ? -> enlarge */
52
+    if (pos >= sz) {
53
+      sz *= 2;
54
+      char *data2 = realloc(data, sz);
55
+      /* out of memory ? -> cleanup and return failure */
56
+      if (! data2) {
57
+        free(data);
58
+        close(fd);
59
+        return NULL;
60
+      }
61
+      /* use new buffer */
62
+      data = data2;
63
+    }
64
+  }
65
+}
66
+
67
+/**
68
+ * @brief make array with pointers to strings
69
+ * @param[in] data pointer to string list
70
+ * @param[in] sz size of string list
71
+ * @param[out] *cnt number of entries in array
72
+ * @return pointer to malloc-ed array of NULL
73
+ */
74
+static char ** stringlist_make_ptrs(char *data, size_t sz, size_t *cnt) {
75
+  /* count strings */
76
+  size_t pos = 0;
77
+  *cnt = 0;
78
+  while (pos < sz) {
79
+    pos += strlen(data + pos) + 1;
80
+    ++*cnt;
81
+  }
82
+  /* allocate array for pointers */
83
+  char **ptrs = malloc(*cnt * sizeof(char *));
84
+  if (! ptrs) {
85
+    *cnt = 0;
86
+    return NULL;
87
+  }
88
+  /* fill pointers into array */
89
+  pos = 0;
90
+  for (size_t i = 0; i < *cnt; ++i) {
91
+    ptrs[i] = data + pos;
92
+    pos += strlen(data + pos) + 1;
93
+  }
94
+  return ptrs;
95
+}
96
+
97
+int stringlist_read(char const *pathname, size_t *n, char ***strs,
98
+                    lwpttr_cleaner_t *cleaner) {
99
+  *n = 0;
100
+  *strs = NULL;
101
+  /* read file contents */
102
+  size_t sz;
103
+  char *data = stringlist_read_file(pathname, &sz);
104
+  if (! data) {
105
+    lwpttr_cleaner_cleanup(cleaner);
106
+    return -1;
107
+  }
108
+  lwpttr_cleaner_add_ptr(cleaner, data);
109
+  /* create pointer array */
110
+  size_t cnt;
111
+  char **ptrs = stringlist_make_ptrs(data, sz, &cnt);
112
+  if (! ptrs) {
113
+    lwpttr_cleaner_cleanup(cleaner);
114
+    return -1;
115
+  }
116
+  lwpttr_cleaner_add_ptr(cleaner, ptrs);
117
+  *n = cnt;
118
+  *strs = ptrs;
119
+  return 0;
120
+}
... ...
@@ -0,0 +1,20 @@
1
+#ifndef LWPTTR_STRINGLIST_H
2
+#define LWPTTR_STRINGLIST_H
3
+
4
+#include "cleaner.h"
5
+
6
+#include <stdlib.h>
7
+
8
+/**
9
+ * @brief read string list file
10
+ * @param[in] pathname path to file containing zero-terminated string list
11
+ * @param[out] *n number of strings read
12
+ * @param[out] *strs strings read
13
+ * @param[in,out] cleaner object, malloc-ed string is added to it
14
+ * @return 0 on success, -1 on error
15
+ *         (on error, cleanup is done and cleaner is deallocated)
16
+ */
17
+int stringlist_read(char const *pathname, size_t *n, char ***strs,
18
+                    lwpttr_cleaner_t *cleaner);
19
+
20
+#endif /* #ifndef LWPTTR_STRINGLIST_H */
... ...
@@ -7,7 +7,7 @@ add_test(
7 7
     > out.proto
8 8
     LWPTPL_OUTPUT=out.proto \
9 9
     LD_PRELOAD=${CMAKE_BINARY_DIR}/liblwptpl/liblwptpl.so \
10
-    /bin/true
10
+    /bin/true a b 'c d'
11 11
     ls -l out.proto
12 12
     protoc --proto_path ${CMAKE_SOURCE_DIR}/liblwpttr lwproctrace.proto \
13 13
            --decode lwproctrace.event < out.proto
14 14