qemu logging extensions

(1) Clear the logs upon receiving a SIGUSR1 signal
(2) Add logging timestamps for network connections
(3) Extended TCP redirect logs to include local src
    ip/port and fixed byte-ordering in log files

Change-Id: I51e7293c8eeb5979a92e67f52f1c6416400d83c6
diff --git a/vl-android.c b/vl-android.c
index d94bec0..cb32eb2 100644
--- a/vl-android.c
+++ b/vl-android.c
@@ -406,6 +406,10 @@
 
 extern void  dprint( const char* format, ... );
 
+const char* dns_log_filename = NULL;
+const char* drop_log_filename = NULL;
+static int rotate_logs_requested = 0;
+
 const char* savevm_on_exit = NULL;
 
 #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
@@ -512,6 +516,52 @@
 #endif
 }
 
+/*
+ * Sets a flag (rotate_logs_requested) to clear both the DNS and the
+ * drop logs upon receiving a SIGUSR1 signal. We need to clear the logs
+ * between the tasks that do not require restarting Qemu.
+ */
+void rotate_qemu_logs_handler(int signum) {
+  rotate_logs_requested = 1;
+}
+
+/*
+ * Resets the rotate_log_requested_flag. Normally called after qemu
+ * logs has been rotated.
+ */
+void reset_rotate_qemu_logs_request(void) {
+  rotate_logs_requested = 0;
+}
+
+/*
+ * Clears the passed qemu log when the rotate_logs_requested
+ * is set. We need to clear the logs between the tasks that do not
+ * require restarting Qemu.
+ */
+FILE* rotate_qemu_log(FILE* old_log_fd, const char* filename) {
+  FILE* new_log_fd = NULL;
+  if (old_log_fd) {
+    if (fclose(old_log_fd) == -1) {
+      fprintf(stderr, "Cannot close old_log fd\n");
+      exit(errno);
+    }
+  }
+
+  if (!filename) {
+    fprintf(stderr, "The log filename to be rotated is not provided");
+    exit(-1);
+  }
+
+  new_log_fd = fopen(filename , "wb+");
+  if (new_log_fd == NULL) {
+    fprintf(stderr, "Cannot open the log file: %s for write.\n",
+            filename);
+    exit(1);
+  }
+
+  return new_log_fd;
+}
+
 /***********************************************************/
 void hw_error(const char *fmt, ...)
 {
@@ -3122,6 +3172,17 @@
 #ifdef CONFIG_PROFILER
             dev_time += profile_getclock() - ti;
 #endif
+
+            if (rotate_logs_requested) {
+                FILE* new_dns_log_fd = rotate_qemu_log(get_slirp_dns_log_fd(),
+                                                        dns_log_filename);
+                FILE* new_drop_log_fd = rotate_qemu_log(get_slirp_drop_log_fd(),
+                                                         drop_log_filename);
+                slirp_dns_log_fd(new_dns_log_fd);
+                slirp_drop_log_fd(new_drop_log_fd);
+                reset_rotate_qemu_logs_request();
+            }
+
         } while (vm_can_run());
 
         if (qemu_debug_requested())
@@ -3623,6 +3684,23 @@
     return 0;
 }
 
+#ifndef _WIN32
+/*
+ * Initializes the SIGUSR1 signal handler to clear Qemu logs.
+ */
+void init_qemu_clear_logs_sig() {
+  struct sigaction act;
+  sigfillset(&act.sa_mask);
+  act.sa_flags = 0;
+  act.sa_handler = rotate_qemu_logs_handler;
+  if (sigaction(SIGUSR1, &act, NULL) == -1) {
+    fprintf(stderr, "Failed to setup SIGUSR1 handler to clear Qemu logs\n");
+    exit(-1);
+  }
+}
+#endif
+
+
 
 /* parses a null-terminated string specifying a network port (e.g., "80") or
  * port range (e.g., "[6666-7000]"). In case of a single port, lport and hport
@@ -4580,7 +4658,8 @@
              case QEMU_OPTION_drop_log:
                 {
                     FILE* drop_log_fd;
-                    drop_log_fd = fopen(optarg, "w");
+                    drop_log_filename = optarg;
+                    drop_log_fd = fopen(optarg, "w+");
 
                     if (!drop_log_fd) {
                         fprintf(stderr, "Cannot open drop log: %s\n", optarg);
@@ -4594,7 +4673,8 @@
             case QEMU_OPTION_dns_log:
                 {
                     FILE* dns_log_fd;
-                    dns_log_fd = fopen(optarg, "wb");
+                    dns_log_filename = optarg;
+                    dns_log_fd = fopen(optarg, "wb+");
 
                     if (dns_log_fd == NULL) {
                         fprintf(stderr, "Cannot open dns log: %s\n", optarg);
@@ -5359,6 +5439,10 @@
     }
 #endif
 
+#ifndef _WIN32
+    init_qemu_clear_logs_sig();
+#endif
+
     /* init the dynamic translator */
     cpu_exec_init_all(tb_size * 1024 * 1024);