|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Win32 interface
5: *
6: * Copyright 1997 Mathias Ortmann
7: */
8:
1.1.1.2 root 9: #include "config.h"
10: #include "sysconfig.h"
11: #include "sysdeps.h"
12:
1.1 root 13: #include <windows.h>
14: #include <stdlib.h>
15: #include <stdarg.h>
1.1.1.3 ! root 16: #include <ddraw.h>
1.1 root 17: #include <commctrl.h>
18: #include <commdlg.h>
19: #include <stdio.h>
20: #include <fcntl.h>
21: #include <sys/stat.h>
22: #include <io.h>
1.1.1.3 ! root 23: #include <sys/types.h>
! 24: #include <sys/timeb.h>
! 25: #include <process.h>
1.1 root 26: #include "options.h"
1.1.1.3 ! root 27: #include "posixemu.h"
! 28: #include "filesys.h"
! 29:
! 30: /* Our Win32 implementation of this function */
! 31: void gettimeofday( struct timeval *tv, void *blah )
! 32: {
! 33: struct timeb time;
! 34: ftime( &time );
! 35:
! 36: tv->tv_sec = time.time;
! 37: tv->tv_usec = time.millitm * 1000;
! 38: }
! 39:
! 40: /* convert time_t to/from AmigaDOS time */
! 41: #define secs_per_day ( 24 * 60 * 60 )
! 42: #define diff ( (8 * 365 + 2) * secs_per_day )
! 43:
! 44: void get_time(time_t t, long* days, long* mins, long* ticks)
! 45: {
! 46: /* time_t is secs since 1-1-1970 */
! 47: /* days since 1-1-1978 */
! 48: /* mins since midnight */
! 49: /* ticks past minute @ 50Hz */
! 50:
! 51: t -= diff;
! 52: *days = t / secs_per_day;
! 53: t -= *days * secs_per_day;
! 54: *mins = t / 60;
! 55: t -= *mins * 60;
! 56: *ticks = t * 50;
! 57: }
1.1 root 58:
59: /* stdioemu, posixemu, mallocemu, and various file system helper routines */
60: static DWORD lasterror;
61:
62: static int isillegal (unsigned char *str)
63: {
1.1.1.3 ! root 64: int result = 0;
1.1 root 65: unsigned char a = *str, b = str[1], c = str[2];
66:
67: if (a >= 'a' && a <= 'z')
68: a &= ~' ';
69: if (b >= 'a' && b <= 'z')
70: b &= ~' ';
71: if (c >= 'a' && c <= 'z')
72: c &= ~' ';
73:
1.1.1.3 ! root 74: result = ( (a == 'A' && b == 'U' && c == 'X') ||
! 75: (a == 'C' && b == 'O' && c == 'N') ||
! 76: (a == 'P' && b == 'R' && c == 'N') ||
! 77: (a == 'N' && b == 'U' && c == 'L') );
! 78:
! 79: return result;
1.1 root 80: }
81:
82: static int checkspace (char *str, char s, char d)
83: {
84: char *ptr = str;
85:
86: while (*ptr && *ptr == s)
87: ptr++;
88:
89: if (!*ptr || *ptr == '/' || *ptr == '\\') {
90: while (str < ptr)
91: *(str++) = d;
92: return 0;
93: }
94: return 1;
95: }
96:
97: /* This is sick and incomplete... in the meantime, I have discovered six new illegal file name formats
98: * M$ sucks! */
1.1.1.2 root 99: void fname_atow (const char *src, char *dst, int size)
1.1 root 100: {
1.1.1.2 root 101: char *lastslash = dst, *strt = dst, *posn = NULL, *temp = NULL;
1.1 root 102: int i, j;
103:
1.1.1.2 root 104: temp = xmalloc( size );
105:
1.1 root 106: while (size-- > 0) {
107: if (!(*dst = *src++))
108: break;
109:
110: if (*dst == '~' || *dst == '|' || *dst == '*' || *dst == '?') {
111: if (size > 2) {
112: sprintf (dst, "~%02x", *dst);
113: size -= 2;
114: dst += 2;
115: }
116: } else if (*dst == '/') {
1.1.1.3 ! root 117: if (checkspace (lastslash, ' ', (char)0xa0) && (dst - lastslash == 3 || (dst - lastslash > 3 && lastslash[3] == '.')) && isillegal (lastslash)) {
1.1 root 118: i = dst - lastslash - 3;
119: dst++;
120: for (j = i + 1; j--; dst--)
121: *dst = dst[-1];
1.1.1.3 ! root 122: *(dst++) = (char)0xa0;
1.1 root 123: dst += i;
124: size--;
1.1.1.3 ! root 125: } else if (*lastslash == '.' && (dst - lastslash == 1 || (lastslash[1] == '.' && dst - lastslash == 2)) && size) {
! 126: *(dst++) = (char)0xa0;
1.1 root 127: size--;
128: }
129: *dst = '\\';
130: lastslash = dst + 1;
131: }
132: dst++;
133: }
134:
1.1.1.3 ! root 135: if (checkspace (lastslash, ' ', (char)0xa0) && (dst - lastslash == 3 || (dst - lastslash > 3 && lastslash[3] == '.')) && isillegal (lastslash) && size > 1) {
1.1 root 136: i = dst - lastslash - 3;
137: dst++;
138: for (j = i + 1; j--; dst--)
139: *dst = dst[-1];
1.1.1.3 ! root 140: *(dst++) = (char)0xa0;
1.1 root 141: } else if (!strcmp (lastslash, ".") || !strcmp (lastslash, ".."))
142: strcat (lastslash, "\xa0");
143:
1.1.1.2 root 144: /* Major kludge, because I can't find the problem... */
145: if( ( posn = strstr( strt, "..\xA0\\" ) ) == strt && temp)
1.1 root 146: {
1.1.1.2 root 147: strcpy( temp, "..\\" );
148: strcat( temp, strt + 4 );
149: strcpy( strt, temp );
1.1 root 150: }
1.1.1.3 ! root 151:
! 152: /* Another major kludge, for the MUI installation... */
! 153: if( *strt == ' ' ) /* first char as a space is illegal in Windoze */
! 154: {
! 155: sprintf( temp, "~%02x%s", ' ', strt+1 );
! 156: strcpy( strt, temp );
! 157: }
1.1 root 158: }
159:
160: static int hextol (char a)
161: {
162: if (a >= '0' && a <= '9')
163: return a - '0';
164: if (a >= 'a' && a <= 'f')
165: return a - 'a' + 10;
166: if (a >= 'A' && a <= 'F')
167: return a - 'A' + 10;
168: return 2;
169: }
170:
171: /* Win32 file name restrictions suck... */
172: void fname_wtoa (unsigned char *ptr)
173: {
174: unsigned char *lastslash = ptr;
175:
176: while (*ptr) {
177: if (*ptr == '~') {
178: *ptr = hextol (ptr[1]) * 16 + hextol (ptr[2]);
179: strcpy (ptr + 1, ptr + 3);
180: } else if (*ptr == '\\') {
1.1.1.3 ! root 181: if (checkspace (lastslash, ' ', (char)0xa0) && ptr - lastslash > 3 && lastslash[3] == 0xa0 && isillegal (lastslash)) {
1.1 root 182: ptr--;
183: strcpy (lastslash + 3, lastslash + 4);
184: }
185: *ptr = '/';
186: lastslash = ptr + 1;
187: }
188: ptr++;
189: }
190:
1.1.1.3 ! root 191: if (checkspace (lastslash, ' ', (char)0xa0) && ptr - lastslash > 3 && lastslash[3] == 0xa0 && isillegal (lastslash))
1.1 root 192: strcpy (lastslash + 3, lastslash + 4);
193: }
194:
1.1.1.3 ! root 195: #ifndef HAVE_TRUNCATE
! 196: int truncate (const char *name, long int len)
1.1 root 197: {
1.1.1.3 ! root 198: HANDLE hFile;
! 199: BOOL bResult = FALSE;
! 200: int result = -1;
! 201:
! 202: #if 0
! 203: char buf[1024];
! 204:
! 205: fname_atow(name,buf,sizeof buf);
! 206:
! 207: if( ( hFile = CreateFile( buf, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
! 208: OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ) ) != INVALID_HANDLE_VALUE )
! 209: {
! 210: if( SetFilePointer( hFile, len, NULL, FILE_BEGIN ) == (DWORD)len )
! 211: {
! 212: if( SetEndOfFile( hFile ) == TRUE )
! 213: result = 0;
! 214: }
! 215: else
! 216: {
! 217: write_log( "SetFilePointer() failure for %s to posn %d\n", buf, len );
! 218: }
! 219: CloseHandle( hFile );
! 220: }
! 221: else
! 222: {
! 223: write_log( "CreateFile() failed to open %s\n", buf );
! 224: }
! 225: #else
! 226: if( ( hFile = CreateFile( name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
! 227: OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ) ) != INVALID_HANDLE_VALUE )
! 228: {
! 229: if( SetFilePointer( hFile, len, NULL, FILE_BEGIN ) == (DWORD)len )
! 230: {
! 231: if( SetEndOfFile( hFile ) == TRUE )
! 232: result = 0;
! 233: }
! 234: else
! 235: {
! 236: write_log( "SetFilePointer() failure for %s to posn %d\n", name, len );
! 237: }
! 238: CloseHandle( hFile );
! 239: }
! 240: else
! 241: {
! 242: write_log( "CreateFile() failed to open %s\n", name );
! 243: }
! 244: #endif
! 245: if( result == -1 )
! 246: lasterror = GetLastError();
! 247: return result;
1.1 root 248: }
1.1.1.3 ! root 249: #endif
1.1 root 250:
1.1.1.3 ! root 251: #if 0
! 252:
! 253: DIR {
! 254: WIN32_FIND_DATA finddata;
! 255: HANDLE hDir;
! 256: int getnext;
! 257: };
! 258:
! 259: DIR *posixemu_opendir(const char *path)
1.1 root 260: {
1.1.1.3 ! root 261: char buf[1024];
! 262: DIR *dir;
! 263:
! 264: if (!(dir = (DIR *)GlobalAlloc(GPTR,sizeof(DIR))))
! 265: {
! 266: lasterror = GetLastError();
! 267: return 0;
! 268: }
! 269: #if 0
! 270: fname_atow(path,buf,sizeof buf-4);
! 271: #else
! 272: strcpy( buf, path );
! 273: #endif
! 274: strcat(buf,"\\*");
! 275:
! 276: if ((dir->hDir = FindFirstFile(buf,&dir->finddata)) == INVALID_HANDLE_VALUE)
! 277: {
! 278: lasterror = GetLastError();
! 279: GlobalFree(dir);
! 280: return 0;
! 281: }
! 282:
! 283: return dir;
1.1 root 284: }
285:
1.1.1.3 ! root 286: struct dirent *posixemu_readdir(DIR *dir)
1.1 root 287: {
1.1.1.3 ! root 288: if (dir->getnext)
! 289: {
! 290: if (!FindNextFile(dir->hDir,&dir->finddata))
! 291: {
! 292: lasterror = GetLastError();
! 293: return 0;
! 294: }
! 295: }
! 296: dir->getnext = TRUE;
! 297:
! 298: fname_wtoa(dir->finddata.cFileName);
! 299: return (struct dirent *)dir->finddata.cFileName;
1.1 root 300: }
301:
1.1.1.3 ! root 302: void posixemu_closedir(DIR *dir)
1.1 root 303: {
1.1.1.3 ! root 304: FindClose(dir->hDir);
! 305: GlobalFree(dir);
1.1 root 306: }
307: #endif
1.1.1.3 ! root 308:
! 309: int w32fopendel(char *name, char *mode, int delflag)
1.1 root 310: {
1.1.1.3 ! root 311: HANDLE hFile;
! 312:
! 313: if ((hFile = CreateFile(name,
! 314: mode[1] == '+' ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ, // ouch :)
! 315: FILE_SHARE_READ | FILE_SHARE_WRITE,
! 316: NULL,
! 317: OPEN_EXISTING,
! 318: delflag ? FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE : FILE_ATTRIBUTE_NORMAL,
! 319: NULL)) == INVALID_HANDLE_VALUE)
! 320: {
! 321: lasterror = GetLastError();
! 322: hFile = 0;
! 323: }
! 324:
! 325: return (int)hFile; /* return handle */
1.1 root 326: }
1.1.1.3 ! root 327:
! 328: DWORD getattr(const char *name, LPFILETIME lpft, size_t *size)
! 329: {
! 330: HANDLE hFind;
! 331: WIN32_FIND_DATA fd;
1.1 root 332:
1.1.1.3 ! root 333: if ((hFind = FindFirstFile(name,&fd)) == INVALID_HANDLE_VALUE)
! 334: {
! 335: lasterror = GetLastError();
! 336:
! 337: fd.dwFileAttributes = GetFileAttributes(name);
! 338:
! 339: return fd.dwFileAttributes;
! 340: }
! 341:
! 342: FindClose(hFind);
! 343:
! 344: if (lpft) *lpft = fd.ftLastWriteTime;
! 345: if (size) *size = fd.nFileSizeLow;
! 346:
! 347: return fd.dwFileAttributes;
! 348: }
! 349:
! 350: #if 0
! 351: int posixemu_stat(const char *name, struct stat *statbuf)
1.1.1.2 root 352: {
1.1.1.3 ! root 353: DWORD attr;
! 354: FILETIME ft, lft;
! 355:
! 356: if ((attr = getattr(name,&ft,(size_t*)&statbuf->st_size)) == (DWORD)~0)
! 357: {
! 358: lasterror = GetLastError();
! 359: return -1;
! 360: }
! 361: else
! 362: {
! 363: statbuf->st_mode = (attr & FILE_ATTRIBUTE_READONLY) ? FILEFLAG_READ: FILEFLAG_READ | FILEFLAG_WRITE;
! 364: if (attr & FILE_ATTRIBUTE_ARCHIVE) statbuf->st_mode |= FILEFLAG_ARCHIVE;
! 365: if (attr & FILE_ATTRIBUTE_DIRECTORY) statbuf->st_mode |= FILEFLAG_DIR;
! 366: FileTimeToLocalFileTime(&ft,&lft);
! 367: statbuf->st_mtime = (*(__int64 *)&lft-((__int64)(369*365+89)*(__int64)(24*60*60)*(__int64)10000000))/(__int64)10000000;
! 368: }
1.1.1.2 root 369: return 0;
370: }
1.1.1.3 ! root 371:
! 372: int posixemu_chmod(const char *name, int mode)
! 373: {
! 374: DWORD attr = FILE_ATTRIBUTE_NORMAL;
! 375: if (mode & 0x05) attr |= FILE_ATTRIBUTE_READONLY; /* Delete (0x01) or Write (0x04) bits */
! 376: if (mode & 0x10) attr |= FILE_ATTRIBUTE_ARCHIVE;
! 377:
! 378: if (SetFileAttributes(name,attr)) return 1;
! 379: lasterror = GetLastError();
! 380:
! 381: return -1;
! 382: }
1.1.1.2 root 383: #endif
1.1.1.3 ! root 384:
! 385: void tmToSystemTime( struct tm *tmtime, LPSYSTEMTIME systime )
! 386: {
! 387: if( tmtime == NULL )
! 388: {
! 389: GetSystemTime( systime );
! 390: }
! 391: else
! 392: {
! 393: systime->wDay = tmtime->tm_mday;
! 394: systime->wDayOfWeek = tmtime->tm_wday;
! 395: systime->wMonth = tmtime->tm_mon + 1;
! 396: systime->wYear = tmtime->tm_year + 1900;
! 397: systime->wHour = tmtime->tm_hour;
! 398: systime->wMinute = tmtime->tm_min;
! 399: systime->wSecond = tmtime->tm_sec;
! 400: systime->wMilliseconds = 0;
! 401: }
! 402: }
! 403:
! 404: static int setfiletime(const char *name, unsigned int days, int minute, int tick)
! 405: {
! 406: FILETIME LocalFileTime, FileTime;
! 407: HANDLE hFile;
! 408: int success;
! 409: 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)
! 410: {
! 411: lasterror = GetLastError();
! 412: return 0;
! 413: }
! 414:
! 415: *(__int64 *)&LocalFileTime = (((__int64)(377*365+91+days)*(__int64)1440+(__int64)minute)*(__int64)(60*50)+(__int64)tick)*(__int64)200000;
! 416:
! 417: if (!LocalFileTimeToFileTime(&LocalFileTime,&FileTime)) FileTime = LocalFileTime;
! 418:
! 419: if (!(success = SetFileTime(hFile,&FileTime,&FileTime,&FileTime))) lasterror = GetLastError();
! 420: CloseHandle(hFile);
! 421:
! 422: return success;
! 423: }
! 424:
! 425: int posixemu_utime( const char *name, struct utimbuf *time )
! 426: {
! 427: int result = -1;
! 428: long days, mins, ticks;
! 429:
! 430: get_time( time->actime, &days, &mins, &ticks );
! 431:
! 432: if( setfiletime( name, days, mins, ticks ) )
! 433: result = 0;
! 434:
! 435: return result;
! 436: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.