/**
 * @file oparchive.cpp
 * Implement oparchive utility
 *
 * @remark Copyright 2003, 2004 OProfile authors
 * @remark Read the file COPYING
 *
 * @author Will Cohen
 * @author John Levon
 * @author Philippe Elie
 */

#include <cstdlib>

#include <iostream>
#include <fstream>
#include <cstdlib>

#include <errno.h>
#include <string.h>
#include <dirent.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "op_file.h"
#include "op_bfd.h"
#include "op_config.h"
#include "oparchive_options.h"
#include "file_manip.h"
#include "cverb.h"
#include "image_errors.h"
#include "string_manip.h"
#include "locate_images.h"

using namespace std;

namespace {


void copy_one_file(image_error err, string const & source, string const & dest)
{
	if (!op_file_readable(source))
		return;

	if (options::list_files) {
		cout << source << endl;
		return;
	}

	if (!copy_file(source, dest) && err == image_ok) {
		cerr << "can't copy from " << source << " to " << dest
		     << " cause: " << strerror(errno) << endl;
	}
}

void copy_stats(string const & session_samples_dir,
		string const & archive_path)
{
	DIR * dir;
	struct dirent * dirent;
	string stats_path;
	
	stats_path = session_samples_dir + "stats/";

	if (!(dir = opendir(stats_path.c_str()))) {
		cerr << "Session overflow stats not available" << endl;
		return;
	}

	string sample_base_dir = session_samples_dir.substr(archive_path.size());
	string archive_stats = options::outdirectory + sample_base_dir + "stats/";
	string archive_stats_path = archive_stats + "event_lost_overflow";
	if (!options::list_files &&
	    create_path(archive_stats_path.c_str())) {
		cerr << "Unable to create directory for "
		     <<	archive_stats << "." << endl;
		exit (EXIT_FAILURE);
	}

	copy_one_file(image_ok, stats_path + "/event_lost_overflow", archive_stats_path);

	while ((dirent = readdir(dir))) {
		int cpu_nr;
		string path;
		if (sscanf(dirent->d_name, "cpu%d", &cpu_nr) != 1)
			continue;
		path = string(dirent->d_name) + "/" + "sample_lost_overflow";
		archive_stats_path = archive_stats + path;
		if (!options::list_files &&
		    create_path(archive_stats_path.c_str())) {
			cerr << "Unable to create directory for "
			     <<	archive_stats_path << "." << endl;
			exit (EXIT_FAILURE);
		}
		copy_one_file(image_ok, stats_path + path, archive_stats_path);

	}
	closedir(dir);

}

int oparchive(options::spec const & spec)
{
	handle_options(spec);

	string archive_path = classes.extra_found_images.get_archive_path();

	/* Check to see if directory can be created */
	if (!options::list_files && create_path(options::outdirectory.c_str())) {
		cerr << "Unable to create directory for " 
		     <<	options::outdirectory << "." << endl;
		exit (EXIT_FAILURE);
	}

	/* copy over each of the executables and the debuginfo files */
	list<inverted_profile> iprofiles = invert_profiles(classes);

	report_image_errors(iprofiles, classes.extra_found_images);

	list<inverted_profile>::iterator it = iprofiles.begin();
	list<inverted_profile>::iterator const end = iprofiles.end();

	cverb << vdebug << "(exe_names)" << endl << endl;
	for (; it != end; ++it) {

		string exe_name = it->image;
		image_error error;
		string real_exe_name =
			classes.extra_found_images.find_image_path(it->image,
						  error, true);

		if (error == image_ok)
			exe_name = classes.extra_found_images.strip_path_prefix(real_exe_name);

		// output name must be identical to the original name, when
		// using this archive the used fixup will be identical e.g.:
		// oparchive -p /lib/modules/2.6.42/kernel -o tmp;
		// opreport  -p /lib/modules/2.6.42/kernel { archive:tmp }
		string exe_archive_file = options::outdirectory + exe_name;

		// FIXME: hacky
		if (it->error == image_not_found && is_prefix(exe_name, "anon "))
			continue;

		cverb << vdebug << real_exe_name << endl;
		/* Create directory for executable file. */
		if (!options::list_files &&
			create_path(exe_archive_file.c_str())) {
			cerr << "Unable to create directory for "
			     << exe_archive_file << "." << endl;
			exit (EXIT_FAILURE);
		}

		/* Copy actual executable files */
		copy_one_file(it->error, real_exe_name, exe_archive_file);

		/* If there are any debuginfo files, copy them over.
		 * Need to copy the debug info file to somewhere we'll
		 * find it - executable location + "/.debug"
		 * to avoid overwriting files with the same name. The
		 * /usr/lib/debug search path is not going to work.
		 */
		bfd * ibfd = open_bfd(real_exe_name);
		if (ibfd) {
			string dirname = op_dirname(real_exe_name);
			string debug_filename;
			if (find_separate_debug_file(ibfd, real_exe_name,
				debug_filename, classes.extra_found_images)) {
				/* found something copy it over */
				string dest_debug_dir = options::outdirectory +
					dirname + "/.debug/";
				if (!options::list_files &&
				    create_dir(dest_debug_dir.c_str())) {
					cerr << "Unable to create directory: "
					<< dest_debug_dir << "." << endl;
					exit (EXIT_FAILURE);
				}

				string dest_debug = dest_debug_dir +
					op_basename(debug_filename);
				copy_one_file(image_ok, debug_filename, dest_debug);
			}
			bfd_close(ibfd);
		}
	}

	/* copy over each of the sample files */
	list<string>::iterator sit = sample_files.begin();
	list<string>::iterator const send = sample_files.end();

	string a_sample_file = *sit;
	int offset = a_sample_file.find('{');
	string base_samples_dir = a_sample_file.substr(0, offset);
	copy_stats(base_samples_dir, archive_path);

	cverb << vdebug << "(sample_names)" << endl << endl;

	for (; sit != send; ++sit) {
		string sample_name = *sit;
		/* Get rid of the the archive_path from the name */
		string sample_base = sample_name.substr(archive_path.size());
		string sample_archive_file = options::outdirectory + sample_base;
		
		cverb << vdebug << sample_name << endl;
		cverb << vdebug << " destp " << sample_archive_file << endl;
		if (!options::list_files &&
			create_path(sample_archive_file.c_str())) {
			cerr << "Unable to create directory for "
			     <<	sample_archive_file << "." << endl;
			exit (EXIT_FAILURE);
		}

		/* Copy over actual sample file. */
		copy_one_file(image_ok, sample_name, sample_archive_file);
	}

	/* copy over the <session-dir>/abi file if it exists */
	string abi_name = string(op_session_dir) + "/abi";
	copy_one_file(image_ok, archive_path + abi_name,
	              options::outdirectory + abi_name);

	/* copy over the <session-dir>/samples/oprofiled.log file */
	string log_name = string(op_samples_dir) + "/oprofiled.log";
	copy_one_file(image_ok, archive_path + log_name,
	              options::outdirectory + log_name);

	return 0;
}

}  // anonymous namespace


int main(int argc, char const * argv[])
{
	return run_pp_tool(argc, argv, oparchive);
}
