--- uae/src/od-win32/posixemu.c 2018/04/24 16:42:57 1.1.1.2 +++ uae/src/od-win32/posixemu.c 2018/04/24 17:19:24 1.1.1.5 @@ -6,28 +6,61 @@ * Copyright 1997 Mathias Ortmann */ -#include "config.h" #include "sysconfig.h" #include "sysdeps.h" #include -#include #include #include +#include #include #include #include #include #include #include - +#include +#include +#include #include "options.h" +#include "posixemu.h" +#include "filesys.h" + +/* Our Win32 implementation of this function */ +void gettimeofday( struct timeval *tv, void *blah ) +{ + struct timeb time; + ftime( &time ); + + tv->tv_sec = time.time; + tv->tv_usec = time.millitm * 1000; +} + +/* convert time_t to/from AmigaDOS time */ +#define secs_per_day ( 24 * 60 * 60 ) +#define diff ( (8 * 365 + 2) * secs_per_day ) + +void get_time(time_t t, long* days, long* mins, long* ticks) +{ + /* time_t is secs since 1-1-1970 */ + /* days since 1-1-1978 */ + /* mins since midnight */ + /* ticks past minute @ 50Hz */ + + t -= diff; + *days = t / secs_per_day; + t -= *days * secs_per_day; + *mins = t / 60; + t -= *mins * 60; + *ticks = t * 50; +} /* stdioemu, posixemu, mallocemu, and various file system helper routines */ static DWORD lasterror; static int isillegal (unsigned char *str) { + int result = 0; unsigned char a = *str, b = str[1], c = str[2]; if (a >= 'a' && a <= 'z') @@ -37,10 +70,12 @@ static int isillegal (unsigned char *str if (c >= 'a' && c <= 'z') c &= ~' '; - return (a == 'A' && b == 'U' && c == 'X' || - a == 'C' && b == 'O' && c == 'N' || - a == 'P' && b == 'R' && c == 'N' || - a == 'N' && b == 'U' && c == 'L'); + result = ( (a == 'A' && b == 'U' && c == 'X') || + (a == 'C' && b == 'O' && c == 'N') || + (a == 'P' && b == 'R' && c == 'N') || + (a == 'N' && b == 'U' && c == 'L') ); + + return result; } static int checkspace (char *str, char s, char d) @@ -78,16 +113,16 @@ void fname_atow (const char *src, char * dst += 2; } } else if (*dst == '/') { - if (checkspace (lastslash, ' ', 0xa0) && (dst - lastslash == 3 || (dst - lastslash > 3 && lastslash[3] == '.')) && isillegal (lastslash)) { + if (checkspace (lastslash, ' ', (char)0xa0) && (dst - lastslash == 3 || (dst - lastslash > 3 && lastslash[3] == '.')) && isillegal (lastslash)) { i = dst - lastslash - 3; dst++; for (j = i + 1; j--; dst--) *dst = dst[-1]; - *(dst++) = 0xa0; + *(dst++) = (char)0xa0; dst += i; size--; - } else if (*lastslash == '.' && (dst - lastslash == 1 || lastslash[1] == '.' && dst - lastslash == 2) && size) { - *(dst++) = 0xa0; + } else if (*lastslash == '.' && (dst - lastslash == 1 || (lastslash[1] == '.' && dst - lastslash == 2)) && size) { + *(dst++) = (char)0xa0; size--; } *dst = '\\'; @@ -96,21 +131,28 @@ void fname_atow (const char *src, char * dst++; } - if (checkspace (lastslash, ' ', 0xa0) && (dst - lastslash == 3 || (dst - lastslash > 3 && lastslash[3] == '.')) && isillegal (lastslash) && size > 1) { + if (checkspace (lastslash, ' ', (char)0xa0) && (dst - lastslash == 3 || (dst - lastslash > 3 && lastslash[3] == '.')) && isillegal (lastslash) && size > 1) { i = dst - lastslash - 3; dst++; for (j = i + 1; j--; dst--) *dst = dst[-1]; - *(dst++) = 0xa0; + *(dst++) = (char)0xa0; } else if (!strcmp (lastslash, ".") || !strcmp (lastslash, "..")) strcat (lastslash, "\xa0"); /* Major kludge, because I can't find the problem... */ if( ( posn = strstr( strt, "..\xA0\\" ) ) == strt && temp) { - strcpy( temp, "..\\" ); - strcat( temp, strt + 4 ); - strcpy( strt, temp ); + strcpy( temp, "..\\" ); + strcat( temp, strt + 4 ); + strcpy( strt, temp ); + } + + /* Another major kludge, for the MUI installation... */ + if( *strt == ' ' ) /* first char as a space is illegal in Windoze */ + { + sprintf( temp, "~%02x%s", ' ', strt+1 ); + strcpy( strt, temp ); } } @@ -135,7 +177,7 @@ void fname_wtoa (unsigned char *ptr) *ptr = hextol (ptr[1]) * 16 + hextol (ptr[2]); strcpy (ptr + 1, ptr + 3); } else if (*ptr == '\\') { - if (checkspace (lastslash, ' ', 0xa0) && ptr - lastslash > 3 && lastslash[3] == 0xa0 && isillegal (lastslash)) { + if (checkspace (lastslash, ' ', (char)0xa0) && ptr - lastslash > 3 && lastslash[3] == 0xa0 && isillegal (lastslash)) { ptr--; strcpy (lastslash + 3, lastslash + 4); } @@ -145,67 +187,249 @@ void fname_wtoa (unsigned char *ptr) ptr++; } - if (checkspace (lastslash, ' ', 0xa0) && ptr - lastslash > 3 && lastslash[3] == 0xa0 && isillegal (lastslash)) + if (checkspace (lastslash, ' ', (char)0xa0) && ptr - lastslash > 3 && lastslash[3] == 0xa0 && isillegal (lastslash)) strcpy (lastslash + 3, lastslash + 4); } -/* pthread Win32 emulation */ -void sem_init (HANDLE * event, int manual_reset, int initial_state) +#ifndef HAVE_TRUNCATE +int truncate (const char *name, long int len) { - *event = CreateEvent (NULL, manual_reset, initial_state, NULL); + HANDLE hFile; + BOOL bResult = FALSE; + int result = -1; + +#if 0 + char buf[1024]; + + fname_atow(name,buf,sizeof buf); + + if( ( hFile = CreateFile( buf, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ) ) != INVALID_HANDLE_VALUE ) + { + if( SetFilePointer( hFile, len, NULL, FILE_BEGIN ) == (DWORD)len ) + { + if( SetEndOfFile( hFile ) == TRUE ) + result = 0; + } + else + { + write_log ( "SetFilePointer() failure for %s to posn %d\n", buf, len ); + } + CloseHandle( hFile ); + } + else + { + write_log ( "CreateFile() failed to open %s\n", buf ); + } +#else + if( ( hFile = CreateFile( name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ) ) != INVALID_HANDLE_VALUE ) + { + if( SetFilePointer( hFile, len, NULL, FILE_BEGIN ) == (DWORD)len ) + { + if( SetEndOfFile( hFile ) == TRUE ) + result = 0; + } + else + { + write_log ( "SetFilePointer() failure for %s to posn %d\n", name, len ); + } + CloseHandle( hFile ); + } + else + { + write_log ( "CreateFile() failed to open %s\n", name ); + } +#endif + if( result == -1 ) + lasterror = GetLastError(); + return result; } +#endif + +#if 0 -void sem_wait (HANDLE * event) +DIR { + WIN32_FIND_DATA finddata; + HANDLE hDir; + int getnext; +}; + +DIR *posixemu_opendir(const char *path) { - WaitForSingleObject (*event, INFINITE); + char buf[1024]; + DIR *dir; + + if (!(dir = (DIR *)GlobalAlloc(GPTR,sizeof(DIR)))) + { + lasterror = GetLastError(); + return 0; + } +#if 0 + fname_atow(path,buf,sizeof buf-4); +#else + strcpy( buf, path ); +#endif + strcat(buf,"\\*"); + + if ((dir->hDir = FindFirstFile(buf,&dir->finddata)) == INVALID_HANDLE_VALUE) + { + lasterror = GetLastError(); + GlobalFree(dir); + return 0; + } + + return dir; } -void sem_post (HANDLE * event) +struct dirent *posixemu_readdir(DIR *dir) { - SetEvent (*event); + if (dir->getnext) + { + if (!FindNextFile(dir->hDir,&dir->finddata)) + { + lasterror = GetLastError(); + return 0; + } + } + dir->getnext = TRUE; + + fname_wtoa(dir->finddata.cFileName); + return (struct dirent *)dir->finddata.cFileName; } -int sem_trywait (HANDLE * event) +void posixemu_closedir(DIR *dir) { - return WaitForSingleObject (*event, 0) == WAIT_OBJECT_0; + FindClose(dir->hDir); + GlobalFree(dir); } - -/* Mega-klduge to prevent problems with Watcom's habit of passing - * arguments in registers... */ -static HANDLE thread_sem; -static void *(*thread_startfunc) (void *); -#ifndef __GNUC__ -static void * __stdcall thread_starter (void *arg) -#else -static void * thread_starter( void *arg ) #endif + +int w32fopendel(char *name, char *mode, int delflag) { - void *(*func) (void *) = thread_startfunc; - SetEvent (thread_sem); - return (*func) (arg); -} - -/* this creates high priority threads by default to speed up the file system (kludge, will be - * replaced by a set_penguin_priority() routine soon) */ -int start_penguin (void *(*f) (void *), void *arg, DWORD * foo) -{ - static int have_event = 0; - HANDLE hThread; - - if (! have_event) { - thread_sem = CreateEvent (NULL, 0, 0, NULL); - have_event = 1; - } - thread_startfunc = f; - hThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) thread_starter, arg, 0, foo); - SetThreadPriority (hThread, THREAD_PRIORITY_HIGHEST); - WaitForSingleObject (thread_sem, INFINITE); + HANDLE hFile; + + if ((hFile = CreateFile(name, + mode[1] == '+' ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ, // ouch :) + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + delflag ? FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE : FILE_ATTRIBUTE_NORMAL, + NULL)) == INVALID_HANDLE_VALUE) + { + lasterror = GetLastError(); + hFile = 0; + } + + return (int)hFile; /* return handle */ } + +DWORD getattr(const char *name, LPFILETIME lpft, size_t *size) +{ + HANDLE hFind; + WIN32_FIND_DATA fd; -#ifndef HAVE_TRUNCATE -int truncate (const char *name, long int len) + if ((hFind = FindFirstFile(name,&fd)) == INVALID_HANDLE_VALUE) + { + lasterror = GetLastError(); + + fd.dwFileAttributes = GetFileAttributes(name); + + return fd.dwFileAttributes; + } + + FindClose(hFind); + + if (lpft) *lpft = fd.ftLastWriteTime; + if (size) *size = fd.nFileSizeLow; + + return fd.dwFileAttributes; +} + +#if 0 +int posixemu_stat(const char *name, struct stat *statbuf) { - /* @@@ - there doesn't seem to be a way to truncate a file under Windows??? */ + DWORD attr; + FILETIME ft, lft; + + if ((attr = getattr(name,&ft,(size_t*)&statbuf->st_size)) == (DWORD)~0) + { + lasterror = GetLastError(); + return -1; + } + else + { + statbuf->st_mode = (attr & FILE_ATTRIBUTE_READONLY) ? FILEFLAG_READ: FILEFLAG_READ | FILEFLAG_WRITE; + if (attr & FILE_ATTRIBUTE_ARCHIVE) statbuf->st_mode |= FILEFLAG_ARCHIVE; + if (attr & FILE_ATTRIBUTE_DIRECTORY) statbuf->st_mode |= FILEFLAG_DIR; + FileTimeToLocalFileTime(&ft,&lft); + statbuf->st_mtime = (*(__int64 *)&lft-((__int64)(369*365+89)*(__int64)(24*60*60)*(__int64)10000000))/(__int64)10000000; + } return 0; } + +int posixemu_chmod(const char *name, int mode) +{ + DWORD attr = FILE_ATTRIBUTE_NORMAL; + if (mode & 0x05) attr |= FILE_ATTRIBUTE_READONLY; /* Delete (0x01) or Write (0x04) bits */ + if (mode & 0x10) attr |= FILE_ATTRIBUTE_ARCHIVE; + + if (SetFileAttributes(name,attr)) return 1; + lasterror = GetLastError(); + + return -1; +} #endif + +void tmToSystemTime( struct tm *tmtime, LPSYSTEMTIME systime ) +{ + if( tmtime == NULL ) + { + GetSystemTime( systime ); + } + else + { + systime->wDay = tmtime->tm_mday; + systime->wDayOfWeek = tmtime->tm_wday; + systime->wMonth = tmtime->tm_mon + 1; + systime->wYear = tmtime->tm_year + 1900; + systime->wHour = tmtime->tm_hour; + systime->wMinute = tmtime->tm_min; + systime->wSecond = tmtime->tm_sec; + systime->wMilliseconds = 0; + } +} + +static int setfiletime(const char *name, unsigned int days, int minute, int tick) +{ + FILETIME LocalFileTime, FileTime; + HANDLE hFile; + int success; + if ((hFile = CreateFile(name, GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL)) == INVALID_HANDLE_VALUE) + { + lasterror = GetLastError(); + return 0; + } + + *(__int64 *)&LocalFileTime = (((__int64)(377*365+91+days)*(__int64)1440+(__int64)minute)*(__int64)(60*50)+(__int64)tick)*(__int64)200000; + + if (!LocalFileTimeToFileTime(&LocalFileTime,&FileTime)) FileTime = LocalFileTime; + + if (!(success = SetFileTime(hFile,&FileTime,&FileTime,&FileTime))) lasterror = GetLastError(); + CloseHandle(hFile); + + return success; +} + +int posixemu_utime( const char *name, struct utimbuf *time ) +{ + int result = -1; + long days, mins, ticks; + + get_time( time->actime, &days, &mins, &ticks ); + + if( setfiletime( name, days, mins, ticks ) ) + result = 0; + + return result; +}