/*
 * hostapd / Interface steering
 * Copyright (c) 2015 Google, Inc.
 *
 * This software may be distributed under the terms of the BSD license.
 * See README for more details.
 */

#include "includes.h"

#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include "common.h"
#include "common/defs.h"
#include "common/ieee802_11_defs.h"
#include "hostapd.h"
#include "steering.h"

static int get_timestamp_filename(const struct ieee80211_mgmt *mgmt,
                                  logged_request_type type,
                                  steering_path_type path_type, char *buf,
                                  size_t len) {
  char *path = (path_type == STEERING_PATH ?
                steering_timestamp_path : request_logging_path);

	if (path == NULL) {
		return 0;
	}

	if (os_snprintf(buf, len, "%s/" COMPACT_MACSTR ".%d", path,
	                MAC2STR(mgmt->sa), type) < 0) {
		wpa_printf(MSG_ERROR, "os_snprintf couldn't format filename: %s",
		           strerror(errno));
		return 0;
	}

	return 1;
}

int write_timestamp_file(const struct ieee80211_mgmt *mgmt,
                         const struct hostapd_data *hapd,
                         logged_request_type type,
                         const struct os_reltime timestamp) {
	FILE *f;
	char filename[1024], tmp_filename[1024];
	int success = 0;

	if (!get_timestamp_filename(mgmt, type, LOGGING_PATH, filename,
	                            sizeof(filename))) {
		return 0;
	}

	/* Create a temporary filename to prevent multiple interfaces on the same band
	 * from touching each others' writes.
         * Code review:  Still necessary?
	 */
	if (os_snprintf(tmp_filename, sizeof(tmp_filename), "%s%s", filename,
	                os_strrchr(hapd->iface->config_fname, '.')) < 0) {
		wpa_printf(MSG_ERROR, "os_snprintf couldn't format temp filename: %s",
		           strerror(errno));
	}

	if ((f = fopen(tmp_filename, "w")) == NULL) {
		wpa_printf(MSG_ERROR, "fopen(%s) for write: %s", tmp_filename,
		           strerror(errno));
		return 0;
	}

	if (fprintf(f, "%d %d", timestamp.sec, timestamp.usec) < 0) {
		wpa_printf(MSG_ERROR, "fprintf to %s: %s", tmp_filename, strerror(errno));
	} else {
		success = 1;
	}

	if (fclose(f) == EOF) {
		wpa_printf(MSG_ERROR, "fclose(%s): %s", tmp_filename, strerror(errno));
		return 0;
	}

	if (rename(tmp_filename, filename) != 0) {
		wpa_printf(MSG_ERROR, "rename(%s, %s): %s", tmp_filename, filename,
		           strerror(errno));
		return 0;
	}

	return success;
}

int maybe_write_timestamp_file(const struct ieee80211_mgmt *mgmt,
                               const struct hostapd_data *hapd,
                               logged_request_type type) {
	struct os_reltime now, prev_logged_timestamp, new_timestamp;
	if (!request_logging_path) {
		return 0;
	}

	os_get_reltime(&now);
	if (garbage_collect_timestamp_files() == -1) {
		wpa_printf(MSG_ERROR,
		           "Garbage collecting steering timestamp files failed: %s",
		           strerror(errno));
		return 0;
	}
	if (!read_timestamp_file(mgmt, type, LOGGING_PATH, &prev_logged_timestamp) ||
	    os_reltime_expired(&now, &prev_logged_timestamp,
	                       BANDSTEERING_EXPIRATION_SECONDS)) {
		new_timestamp.sec = now.sec + BANDSTEERING_DELAY_SECONDS;
		new_timestamp.usec = now.usec;
		if (!write_timestamp_file(mgmt, hapd, type, new_timestamp)) {
			wpa_printf(MSG_ERROR, "Failed to write timestamp file.");
			return 0;
		} else {
			wpa_printf(MSG_INFO, "Set timestamp for " MACSTR " (type=%d)",
			           MAC2STR(mgmt->sa), type);
			return 1;
		}
	}
}

int read_timestamp_file(const struct ieee80211_mgmt *mgmt,
                        logged_request_type type,
                        steering_path_type path_type,
                        struct os_reltime *timestamp) {
	FILE *f;
	char filename[1024];
	int success = 0;
	struct stat st;
	os_time_t sec = 0, usec = 0;

	if (!get_timestamp_filename(mgmt, type, path_type, filename,
	                            sizeof(filename))) {
		return 0;
	}

	if (stat(filename, &st) == -1) {
		return 0;
	}

	f = fopen(filename, "r");
	if (f == NULL) {
		wpa_printf(MSG_ERROR, "open(%s) for read: %s", filename, strerror(errno));
		return 0;
	}

	if (fscanf(f, "%d %d", &timestamp->sec, &timestamp->usec) != 2) {
		wpa_printf(MSG_ERROR, "fscanf from %s: %s", filename, strerror(errno));
	} else {
		success = 1;
	}

	if (fclose(f) == EOF) {
		wpa_printf(MSG_ERROR, "fclose(%s): %s", filename, strerror(errno));
		return 0;
	}

	return success;
}

int file_ctime_lt(const struct dirent **a, const struct dirent **b) {
	struct stat astat, bstat;

	/* If we can't stat both of the files, give up and say they're equivalent. */
	if (stat((*a)->d_name, &astat) == -1 || stat((*b)->d_name, &bstat) == -1) {
		return 0;
	}

	return astat.st_ctime - bstat.st_ctime;
}

int garbage_collect_timestamp_files(const char *path) {
	int num_timestamp_files = 0, num_timestamp_files_deleted = 0, i = 0;
	struct dirent **namelist;
	char original_cwd[1024];
	char *filename;
	int error = 0;

	if (getcwd(original_cwd, sizeof(original_cwd)) == NULL) {
		wpa_printf(MSG_ERROR, "getcwd(): %s", strerror(errno));
		return -1;
	}

	if (chdir(request_logging_path) == -1) {
		wpa_printf(MSG_ERROR, "chdir(%s): %s",
		           request_logging_path, strerror(errno));
		return -1;
	}

	num_timestamp_files = scandir(request_logging_path, &namelist, NULL,
	                              file_ctime_lt);
	for (i = 0; i < num_timestamp_files; ++i) {
		if (MAX_STEERING_TIMESTAMP_FILES <
		    /* The -2 is because scandir includes "." and "..". */
		    (num_timestamp_files - 2) - num_timestamp_files_deleted) {
			filename = namelist[i]->d_name;
			if (filename[0] != '.' && !error) {
				if (unlink(filename) == -1) {
					wpa_printf(MSG_ERROR, "unlink(%s): %s",
					           unlink(filename), strerror(errno));
					error = 1;
				} else {
					++num_timestamp_files_deleted;
				}
			}
		}
		os_free(namelist[i]);
	}
	os_free(namelist);

	if (chdir(original_cwd) == -1) {
		wpa_printf(MSG_ERROR, "chdir(%s): %s", original_cwd, strerror(errno));
		return -1;
	}

	return error ? -1 : num_timestamp_files_deleted;
}
