/*
	ZazouMiniWebServer

	Copyright (C) 2003-2007 Xavier Garreau <xavier@xgarreau.org>

	This file is part of ZazouMiniWebServer.

    ZazouMiniWebServer is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    ZazouMiniWebServer is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ZazouMiniWebServer; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/
	
#include "ZOSAL.h"
#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>


// CRITICAL_SECTION :: implementation
int InitializeCriticalSection (CRITICAL_SECTION* cs) {
	return pthread_mutex_init(&(cs->mutex), NULL);
}

int DeleteCriticalSection(CRITICAL_SECTION* cs) {
	return pthread_mutex_destroy (&(cs->mutex));
}

int EnterCriticalSection(CRITICAL_SECTION* cs) {
	return pthread_mutex_lock (&(cs->mutex));
}

int LeaveCriticalSection(CRITICAL_SECTION* cs) {
	return pthread_mutex_unlock (&(cs->mutex));
}

// Gestion du temps :: Implementation
void GetLocalTime (SYSTEMTIME* st, time_t when) {
	struct tm * tms;
	const time_t when_t =  (when) ? when : time (NULL);
	tms = localtime ( &when_t );
        st->wSecond = (tms->tm_sec == 60) ? 0 : tms->tm_sec;     /* seconds (0 - 60) */
        st->wMinute = tms->tm_min;     /* minutes (0 - 59) */
        st->wHour = tms->tm_hour;    /* hours (0 - 23) */
        st->wDay = tms->tm_mday;    /* day of month (1 - 31) */
        st->wMonth = tms->tm_mon + 1;     /* month of year (0 - 11) */
        st->wYear = tms->tm_year + 1900;    /* year - 1900 */
        st->wDayOfWeek = tms->tm_wday;    /* day of week (Sunday = 0) */
        st->wMilliseconds = 0;
}

// Gestion du temps :: Implementation
void GetSystemTime (SYSTEMTIME* st, time_t when) {
	struct tm * tms;
	const time_t when_t = (when) ? when : time (NULL);
	tms = gmtime ( &when_t );
        st->wSecond = (tms->tm_sec == 60) ? 0 : tms->tm_sec;     /* seconds (0 - 60) */
        st->wMinute = tms->tm_min;     /* minutes (0 - 59) */
        st->wHour = tms->tm_hour;    /* hours (0 - 23) */
        st->wDay = tms->tm_mday;    /* day of month (1 - 31) */
        st->wMonth = tms->tm_mon + 1;     /* month of year (0 - 11) */
        st->wYear = tms->tm_year + 1900;    /* year - 1900 */
        st->wDayOfWeek = tms->tm_wday;    /* day of week (Sunday = 0) */
        st->wMilliseconds = 0;
}

// Dynamic loader :: Implémentation
HMODULE	LoadLibrary (const char* filename) {
	return dlopen (filename, RTLD_LAZY);
}

int 	FreeLibrary (HMODULE module) {
	return dlclose (module);
}

// errno
DWORD GetLastError (void) {
	return errno;
}

// Répertoire courant
int GetCurrentDirectory (int taille, char* buf) {
	char *tmp = NULL;
	char* ret = NULL;
	int retlen = 0;
	int tmpsize = taille;

	if (!tmpsize) {
		tmpsize = 256;
	}
	do {
		tmp = (char*)realloc(tmp, tmpsize);
		if (tmp) {
			memset (tmp, 0, tmpsize);
			ret = getcwd (tmp, tmpsize);
			tmpsize += 256;
		} else {
			break;
		}
	} while (!ret && errno == ERANGE);

	if (ret) {
		retlen = strlen(ret)+1;
		free (ret);
		if (taille && buf) {
			memcpy (buf, ret, taille);
		}
	}
	return retlen;
}

DWORD GetCurrentProcessId (void) {
	return getpid();
}

BOOL CreateDirectory (LPCTSTR dirpath, void* dummy_security_attributes) {
	int error = mkdir (dirpath, 00777);

	return (error == 0); // Return TRUE if an error occured
}
