git @ Cat's Eye Technologies linapple / master src / config.cpp
master

Tree @master (Download .tar.gz)

config.cpp @masterraw · history · blame

// Central class for managing user configuration files and locations
//
// Copyright (C) 2017 Greg Hedger

#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <sys/stat.h>
#include <iostream>
#include <fcntl.h>
#include <cstdio>

#include "config.h"

using namespace std;

Config::Config()
{
}

std::string Config::GetUserFilePath()
{
	m_optsFilePath = GetHomePath() + USER_DIRECTORY_NAME;
	return m_optsFilePath.c_str();
}

void Config::ChangeToHomeDirectory()
{
	if(chdir(GetHomePath().c_str()))
	{
		// TODO: LOG ERROR
    cout << "Cannot switch to home directory ('" << GetHomePath().c_str() << "')" << std::endl;
	}
}

void Config::ChangeToUserDirectory()
{
	if(chdir((GetHomePath() + USER_DIRECTORY_NAME).c_str()))
	{

    cout << "Cannot switch to home directory ('" << GetHomePath().c_str() << "')" << std::endl;
	}
}

// Simple POSIX file copy
bool Config::CopyFile(std::string srcFile, std::string destFile)
{
  const int bufSize = 1024;
	bool bRet = true;
	char buf[bufSize];
	size_t size;

	// Attempt to open files
	int source = open(srcFile.c_str(), O_RDONLY, 0);
	int dest = open(destFile.c_str(), O_WRONLY | O_CREAT /*| O_TRUNC*/, 0644);

	if (source && dest)
	{
		// Copy
		while ((size = read(source, buf, bufSize)) > 0) {
			if(0 >= write(dest, buf, size)) {
				// Handle error;
        std::cout << "Error writing '" << destFile.c_str() << "' (" << size << ")" << std::endl;
        std::cout << "Source file: " << srcFile.c_str() << std::endl;

				bRet = false;
				break;
			}
		}

		// Close files
		if(source) {
			close(source);
		}
		if(dest) {
			close(dest);
		}
	} else {
    std::cout << "Error copying '" << srcFile.c_str() << "' to '" << destFile.c_str() << "'" << std::endl;
		bRet = false;
	}
	return bRet;
}

// ValidateUserDirectory
// Checks for presence of user directory structure for configuration files
bool Config::ValidateUserDirectory()
{

// GPH TOOD: Revisit with more elegant solution.
// Looks like there's an official way to copy all files in a directory
// for c++17 using filesystem::, but I just want something that's
// going to work.
static const char *files[] =
{
  "charset40.bmp",
  "font.bmp",
  "splash.bmp",
  "Printer.txt",
  "Master.dsk",
  "LICENSE",
  "linapple.conf",
  "icon.bmp",
  ""
};

	bool bResult = false;
	struct stat buffer;
	std::string userDir = GetHomePath();
	userDir += USER_DIRECTORY_NAME;
	std::string installDir = GetInstallPath();

	// Check that the entire subtree exists
	bResult = (stat (userDir.c_str(), &buffer) == 0);
	bResult &= (stat ((userDir + CONF_DIRECTORY_NAME).c_str(), &buffer) == 0);
	bResult &= (stat ((userDir + SAVED_DIRECTORY_NAME).c_str(), &buffer) == 0);
	bResult &= (stat ((userDir + FTP_DIRECTORY_NAME).c_str(), &buffer) == 0);
	bResult &= (stat (GetUserFilePath().c_str(), &buffer) == 0);
	if (!bResult) {
		// Directory is absent.  This means we need to create it and copy over
		// defaults from the install location.
		mkdir(userDir.c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
		mkdir((userDir + CONF_DIRECTORY_NAME).c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
		mkdir((userDir + SAVED_DIRECTORY_NAME).c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
		mkdir((userDir + FTP_DIRECTORY_NAME).c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);

    cout << "Copying Files\n" << std::endl;

		// Copy config options file
    for( unsigned int i = 0; *files[ i ]; i++ ) {
      string dest = GetUserFilePath();
		  CopyFile(
			  (GetInstallPath() + files[ i ]),
        dest + files[ i ]
      );
    }
	}
	return bResult;
}

std::string Config::GetInstallPath()
{
	return INSTALL_DIRECTORY_NAME;
}

std::string Config::GetHomePath()
{
	struct passwd *pw = getpwuid(getuid());
	const char *homedir = pw->pw_dir;
	std::string path = homedir;
	return path;
}