RDK Documentation (Open Sourced RDK Components)
inotify-minidump-watcher.c
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2016 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 #include <assert.h>
21 #include <errno.h>
22 #include <fnmatch.h>
23 #include <limits.h>
24 #include <signal.h>
25 #include <stddef.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <sys/inotify.h>
29 #include <unistd.h>
30 #ifdef YOCTO_BUILD
31 #include "secure_wrapper.h"
32 #endif
33 
34 /**
35  * @defgroup Crashupload Crashupload
36  *
37  * - Crashupload component helps to upload coredump and minidump files (crashes) that happened in the STBs to the crash portal server.
38  * - The crash portal processes these crash dumps and logs and provides a meaningful backtrace.
39  * - Whenever the crash happens STB will create a minidump file with ".dmp" extention at configured path(for ex: /minidumps/).
40  * - Then this dump file will be converted into tar file before getting uploaded to the RDK crash portal.
41  * - This tar file has a naming convention as build-id_mac_date_box<type_device-model_dumpfilenumber.dmp.tgz.
42  * - It is possible to download this "*.dmp.tgz" file directly from the RDK crash portal using MAC address of the device
43  * and filters to see minidump report and to download this file.
44  * - It contains dump file and some log files like version.txt and core_log.txt.
45  * - The RDK crash portal url at which dump file gets upload can be configured in uploadDumps.sh script file in the box.
46  *
47  * @defgroup Crashupload_API Crashupload Public APIs
48  * @ingroup Crashupload
49  *
50  */
51 
52 #ifdef __GNUC__
53 # define ALIGNAS(TYPE) __attribute__ ((aligned(__alignof__(TYPE))))
54 #else
55 # define ALIGNAS(TYPE) /* empty */
56 #endif
57 
58 static volatile int interrupted = 0;
59 
60 
61 /**
62  * @addtogroup Crashupload_API
63  * @{
64  */
65 
66 /**
67  * @brief Signal Handler function.
68  *
69  * @param[in] s Signal Type
70  *
71  */
72 
73 static void
75 {
76  if (s == SIGINT)
77  interrupted = 1;
78 }
79 
80 /**
81  * @brief This API notifies whether dump is generated in the minidump directory and triggers the
82  * upload dump script to upload the files to server.
83  *
84  * @param[in] directory Directory name
85  * @param[in] command_to_run Shell script to execute
86  * @param[in] command_args Arguments for shell script
87  * @param[in] patterns Pattern to verify, Patterns can be *.dmp, *.cmd etc.
88  * @param[in] pattern_count Number of patterns to be verified.
89  */
90 
91 static int
92 directory_watcher(const char *const directory,
93  const char* command_to_run,
94  const char* command_args,
95  const char *const *const patterns,
96  const size_t pattern_count)
97 {
98  int notifyfd = -1;
99  int watchfd = -1;
100  int ret = 0;
101  const char * errmsg = "unknown error";
102 
103  notifyfd = inotify_init();
104  if (notifyfd < 0)
105  {
106  errmsg = "inotify_init";
107  goto catch;
108  }
109  watchfd = inotify_add_watch(notifyfd, directory, IN_CREATE);
110  if (watchfd < 0)
111  {
112  errmsg = "inotify_add_watch";
113  goto catch;
114  }
115  while (1)
116  {
117  char buffer[sizeof(struct inotify_event) + NAME_MAX + 1] ALIGNAS(struct inotify_event) = {0};
118  const struct inotify_event * event_ptr;
119  /* coverity fix CID: 136730 */
120  ssize_t count = read(notifyfd, buffer, (sizeof(buffer) - 1));
121  if (count < 0)
122  {
123  if (interrupted)
124  goto finally;
125  errmsg = "read";
126  goto catch;
127  }
128  event_ptr = (const struct inotify_event *) buffer;
129  assert(event_ptr->wd == watchfd);
130  assert(event_ptr->mask & IN_CREATE);
131  if (event_ptr->len)
132  {
133  size_t i;
134  for (i = 0; i < pattern_count; ++i)
135  {
136  switch (fnmatch(patterns[i], event_ptr->name, FNM_PATHNAME))
137  {
138  case 0:
139  /* Your application logic here... */
140  if (printf("%s\n", event_ptr->name) < 0)
141  {
142  errmsg = "printf";
143  goto catch;
144  }
145  else
146  {
147  /* Exit from wait if the command to run is NULL */
148  if(strncmp(command_to_run,"NULL",4) == 0){
149  printf("Flag file is created. Exiting from wait \n");
150  goto finally;
151  }
152  printf("Calling the binary %s\n",command_to_run);
153 #ifdef YOCTO_BUILD
154  v_secure_system("sh -c '%s %s'",command_to_run,command_args);
155 #else
156  char command[50];
157 
158  if(command_to_run == NULL || command_args == NULL)
159  {
160  errmsg = "NULL";
161  goto catch;
162  }
163 
164  if (sizeof(command) <= (strlen(command_to_run)+strlen(command_args)+strlen("ssh -c ' '")))
165  {
166  errmsg = "command buffer overflow";
167  goto catch;
168  }
169  sprintf(command,"sh -c '%s %s'",command_to_run,command_args);
170 
171  system(command);
172 #endif
173  printf("The script /lib/rdk/uploadDumps.sh execution completed..!");
174  }
175  break;
176  case FNM_NOMATCH:
177  break;
178  default:
179  errmsg = "fnmatch";
180  goto catch;
181  }
182  }
183  }
184  }
185  finally:
186  if (watchfd >= 0)
187  {
188  int status = close(watchfd);
189  watchfd = -1;
190  if (status < 0)
191  {
192  errmsg = "close(watchfd)";
193  goto catch;
194  }
195  }
196  if (notifyfd >= 0)
197  {
198  int status = close(notifyfd);
199  notifyfd = -1;
200  if (status < 0)
201  {
202  errmsg = "close(notifyfd)";
203  goto catch;
204  }
205  }
206  return ret;
207  catch:
208  if (errmsg && errno)
209  perror(errmsg);
210  ret = -1;
211  goto finally;
212 }
213 
214 /**
215  * @brief Main Function.
216  *
217  * This binary is used to monitor the specified directory in the box and when there is a change, corresponding upload script will kick in
218  * and uploads the files to the server.
219  *
220  * Usage: /usr/bin/inotify-minidump-watcher DIRECTORY COMMAND_TO_RUN COMMAND_ARGS PATTERN
221  * Eg: /usr/bin/inotify-minidump-watcher /minidumps /lib/rdk/uploadDumps.sh "" 0 *.dmp
222 */
223 
224 int
225 main(const int argc, const char *const *const argv)
226 {
227  if (argc < 5)
228  {
229  fprintf(stderr, "usage: %s DIRECTORY COMMAND_TO_RUN COMMAND_ARGS PATTERN...\n", argv[0]);
230  return EXIT_FAILURE;
231  }
232 
233  struct sigaction sa;
234  sa.sa_handler = process_interrupt_handler;
235  sigemptyset(&sa.sa_mask);
236  sa.sa_flags = 0;
237  sigaction(SIGINT, &sa, NULL);
238 
239  if (directory_watcher(argv[1], argv[2] , argv[3], argv + 4, argc - 4) < 0)
240  return EXIT_FAILURE;
241 
242  return EXIT_SUCCESS;
243 }
244 
245 /**
246  * @} // End of Doxygen
247  */
248 
directory_watcher
static int directory_watcher(const char *const directory, const char *command_to_run, const char *command_args, const char *const *const patterns, const size_t pattern_count)
This API notifies whether dump is generated in the minidump directory and triggers the upload dump sc...
Definition: inotify-minidump-watcher.c:92
main
int main(const int argc, const char *const *const argv)
Main Function.
Definition: inotify-minidump-watcher.c:225
process_interrupt_handler
static void process_interrupt_handler(const int s)
Signal Handler function.
Definition: inotify-minidump-watcher.c:74