2020-04-21 12:28:06 +02:00
|
|
|
#include "common.h"
|
|
|
|
#include "crossplatform.h"
|
|
|
|
|
2020-05-11 19:10:01 +02:00
|
|
|
// Codes compatible with Windows and Linux
|
|
|
|
#ifndef _WIN32
|
|
|
|
|
2020-04-21 12:28:06 +02:00
|
|
|
// For internal use
|
|
|
|
// wMilliseconds is not needed
|
|
|
|
void tmToSystemTime(const tm *tm, SYSTEMTIME *out) {
|
|
|
|
out->wYear = tm->tm_year + 1900;
|
|
|
|
out->wMonth = tm->tm_mon + 1;
|
|
|
|
out->wDayOfWeek = tm->tm_wday;
|
|
|
|
out->wDay = tm->tm_mday;
|
|
|
|
out->wHour = tm->tm_hour;
|
|
|
|
out->wMinute = tm->tm_min;
|
|
|
|
out->wSecond = tm->tm_sec;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetLocalTime_CP(SYSTEMTIME *out) {
|
|
|
|
time_t timestamp = time(nil);
|
|
|
|
tm *localTm = localtime(×tamp);
|
|
|
|
tmToSystemTime(localTm, out);
|
|
|
|
}
|
2020-05-11 19:10:01 +02:00
|
|
|
#endif
|
2020-04-21 12:28:06 +02:00
|
|
|
|
2020-05-11 04:55:57 +02:00
|
|
|
// Compatible with Linux/POSIX and MinGW on Windows
|
|
|
|
#ifndef _WIN32
|
2020-04-21 12:28:06 +02:00
|
|
|
HANDLE FindFirstFile(const char* pathname, WIN32_FIND_DATA* firstfile) {
|
|
|
|
char newpathname[32];
|
|
|
|
strncpy(newpathname, pathname, 32);
|
|
|
|
char* path = strtok(newpathname, "\\*");
|
|
|
|
strncpy(firstfile->folder, path, sizeof(firstfile->folder));
|
|
|
|
|
|
|
|
// Both w/ extension and w/o extension is ok
|
|
|
|
if (strlen(path) + 2 != strlen(pathname))
|
|
|
|
strncpy(firstfile->extension, strtok(NULL, "\\*"), sizeof(firstfile->extension));
|
|
|
|
else
|
|
|
|
strncpy(firstfile->extension, "", sizeof(firstfile->extension));
|
|
|
|
|
|
|
|
HANDLE d;
|
2020-05-11 04:55:57 +02:00
|
|
|
if ((d = (HANDLE)opendir(path)) == NULL || !FindNextFile(d, firstfile))
|
2020-04-21 12:28:06 +02:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FindNextFile(HANDLE d, WIN32_FIND_DATA* finddata) {
|
|
|
|
dirent *file;
|
|
|
|
static struct stat fileStats;
|
|
|
|
static char path[PATH_MAX], relativepath[NAME_MAX + sizeof(finddata->folder) + 1];
|
|
|
|
int extensionLen = strlen(finddata->extension);
|
2020-05-11 04:55:57 +02:00
|
|
|
while ((file = readdir((DIR*)d)) != NULL) {
|
2020-04-21 12:28:06 +02:00
|
|
|
|
|
|
|
// We only want "DT_REG"ular Files, but reportedly some FS and OSes gives DT_UNKNOWN as type.
|
|
|
|
if ((file->d_type == DT_UNKNOWN || file->d_type == DT_REG) &&
|
|
|
|
(extensionLen == 0 || strncmp(&file->d_name[strlen(file->d_name) - extensionLen], finddata->extension, extensionLen) == 0)) {
|
|
|
|
|
|
|
|
sprintf(relativepath, "%s/%s", finddata->folder, file->d_name);
|
|
|
|
realpath(relativepath, path);
|
|
|
|
stat(path, &fileStats);
|
|
|
|
strncpy(finddata->cFileName, file->d_name, sizeof(finddata->cFileName));
|
|
|
|
finddata->ftLastWriteTime = fileStats.st_mtime;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetDateFormat(int unused1, int unused2, SYSTEMTIME* in, int unused3, char* out, int size) {
|
|
|
|
tm linuxTime;
|
|
|
|
linuxTime.tm_year = in->wYear - 1900;
|
|
|
|
linuxTime.tm_mon = in->wMonth - 1;
|
|
|
|
linuxTime.tm_wday = in->wDayOfWeek;
|
|
|
|
linuxTime.tm_mday = in->wDay;
|
|
|
|
linuxTime.tm_hour = in->wHour;
|
|
|
|
linuxTime.tm_min = in->wMinute;
|
|
|
|
linuxTime.tm_sec = in->wSecond;
|
|
|
|
strftime(out, size, nl_langinfo(D_FMT), &linuxTime);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FileTimeToSystemTime(time_t* writeTime, SYSTEMTIME* out) {
|
|
|
|
tm *ptm = gmtime(writeTime);
|
|
|
|
tmToSystemTime(ptm, out);
|
|
|
|
}
|
2020-05-11 04:55:57 +02:00
|
|
|
#endif
|
|
|
|
|
2020-05-11 19:10:01 +02:00
|
|
|
// Funcs/features from Windows that we need on other platforms
|
2020-05-11 04:55:57 +02:00
|
|
|
#ifndef _WIN32
|
|
|
|
char *strupr(char *s) {
|
|
|
|
char* tmp = s;
|
|
|
|
|
|
|
|
for (;*tmp;++tmp) {
|
|
|
|
*tmp = toupper((unsigned char) *tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
char *strlwr(char *s) {
|
|
|
|
char* tmp = s;
|
|
|
|
|
|
|
|
for (;*tmp;++tmp) {
|
|
|
|
*tmp = tolower((unsigned char) *tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *trim(char *s) {
|
|
|
|
char *ptr;
|
|
|
|
if (!s)
|
|
|
|
return NULL; // handle NULL string
|
|
|
|
if (!*s)
|
|
|
|
return s; // handle empty string
|
|
|
|
for (ptr = s + strlen(s) - 1; (ptr >= s) && isspace(*ptr); --ptr);
|
|
|
|
ptr[1] = '\0';
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen)
|
|
|
|
// r must have strlen(path) + 2 bytes
|
|
|
|
int casepath(char const *path, char *r)
|
|
|
|
{
|
|
|
|
size_t l = strlen(path);
|
|
|
|
char *p = (char*)alloca(l + 1);
|
|
|
|
strcpy(p, path);
|
|
|
|
|
|
|
|
// my addon: change \'s with /
|
|
|
|
char *nextBs;
|
|
|
|
while(nextBs = strstr(p, "\\")){
|
|
|
|
*nextBs = '/';
|
|
|
|
}
|
|
|
|
|
|
|
|
// my addon: linux doesn't handle filenames with spaces at the end nicely
|
|
|
|
p = trim(p);
|
|
|
|
|
|
|
|
size_t rl = 0;
|
|
|
|
|
|
|
|
DIR *d;
|
|
|
|
if (p[0] == '/')
|
|
|
|
{
|
|
|
|
d = opendir("/");
|
|
|
|
p = p + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d = opendir(".");
|
|
|
|
r[0] = '.';
|
|
|
|
r[1] = 0;
|
|
|
|
rl = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int last = 0;
|
|
|
|
char *c = strsep(&p, "/");
|
|
|
|
while (c)
|
|
|
|
{
|
|
|
|
if (!d)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (last)
|
|
|
|
{
|
|
|
|
closedir(d);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
r[rl] = '/';
|
|
|
|
rl += 1;
|
|
|
|
r[rl] = 0;
|
|
|
|
|
|
|
|
struct dirent *e = readdir(d);
|
|
|
|
while (e)
|
|
|
|
{
|
|
|
|
if (strcasecmp(c, e->d_name) == 0)
|
|
|
|
{
|
|
|
|
strcpy(r + rl, e->d_name);
|
|
|
|
rl += strlen(e->d_name);
|
|
|
|
|
|
|
|
closedir(d);
|
|
|
|
d = opendir(r);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
e = readdir(d);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!e)
|
|
|
|
{
|
|
|
|
strcpy(r + rl, c);
|
|
|
|
rl += strlen(c);
|
|
|
|
last = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = strsep(&p, "/");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d) closedir(d);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|