+/* Returns the name of the log file used by VLF_FILE, or a null pointer if no
+ * log file has been set. (A non-null return value does not assert that the
+ * named log file is in use: if vlog_set_log_file() or vlog_reopen_log_file()
+ * fails, it still sets the log file name.) */
+const char *
+vlog_get_log_file(void)
+{
+ return log_file_name;
+}
+
+/* Sets the name of the log file used by VLF_FILE to 'file_name', or to the
+ * default file name if 'file_name' is null. Returns 0 if successful,
+ * otherwise a positive errno value. */
+int
+vlog_set_log_file(const char *file_name)
+{
+ char *old_log_file_name;
+ enum vlog_module module;
+ int error;
+
+ /* Close old log file. */
+ if (log_file) {
+ VLOG_WARN("closing log file");
+ fclose(log_file);
+ log_file = NULL;
+ }
+
+ /* Update log file name and free old name. The ordering is important
+ * because 'file_name' might be 'log_file_name' or some suffix of it. */
+ old_log_file_name = log_file_name;
+ log_file_name = (file_name
+ ? xstrdup(file_name)
+ : xasprintf("%s/%s.log", ofp_logdir, program_name));
+ free(old_log_file_name);
+ file_name = NULL; /* Might have been freed. */
+
+ /* Open new log file and update min_levels[] to reflect whether we actually
+ * have a log_file. */
+ log_file = fopen(log_file_name, "a");
+ for (module = 0; module < VLM_N_MODULES; module++) {
+ update_min_level(module);
+ }
+
+ /* Log success or failure. */
+ if (!log_file) {
+ VLOG_WARN("failed to open %s for logging: %s",
+ log_file_name, strerror(errno));
+ error = errno;
+ } else {
+ VLOG_WARN("opened log file %s", log_file_name);
+ error = 0;
+ }
+
+ return error;
+}
+
+/* Closes and then attempts to re-open the current log file. (This is useful
+ * just after log rotation, to ensure that the new log file starts being used.)
+ * Returns 0 if successful, otherwise a positive errno value. */
+int
+vlog_reopen_log_file(void)
+{
+ return vlog_set_log_file(log_file_name);
+}
+