1: // Copyright (C) 1994-1998 by Symantec
  2: // Copyright (C) 2000-2009 by Digital Mars
  3: // All Rights Reserved
  4: // http://www.digitalmars.com
  5: // Written by Walter Bright
  6: /*
  7:  * This source file is made available for personal use
  8:  * only. The license is in /dmd/src/dmd/backendlicense.txt
  9:  * or /dm/src/dmd/backendlicense.txt
 10:  * For any other uses, please contact Digital Mars.
 11:  */
 12: 
 13: /*
 14:  * Operating system specific routines.
 15:  * Placed here to avoid cluttering
 16:  * up code with OS .h files.
 17:  */
 18: 
 19: #include <stdio.h>
 20: #include <time.h>
 21: #include <stdlib.h>
 22: #include <string.h>
 23: 
 24: #if DOS386
 25: #include <dos.h>
 26: #include <sys\stat.h>
 27: #endif
 28: 
 29: #if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
 30: #include <sys/types.h>
 31: #include <sys/stat.h>
 32: #include <fcntl.h>
 33: #include <errno.h>
 34: #include <unistd.h>
 35: #include <pthread.h>
 36: #define GetLastError() errno
 37: #elif _WIN32
 38: #include <dos.h>
 39: #include <sys\stat.h>
 40: #include        <windows.h>
 41: #endif
 42: 
 43: #if __DMC__ || __GNUC__ || _MSC_VER
 44: static char __file__[] = __FILE__;      /* for tassert.h                */
 45: #include        "tassert.h"
 46: #else
 47: #include        <assert.h>
 48: #endif
 49: 
 50: #if _WINDLL
 51: extern void dll_printf(const char *format,...);
 52: #define dbg_printf dll_printf
 53: #else
 54: #define dbg_printf printf
 55: #endif
 56: 
 57: #if _MSC_VER
 58: #include <malloc.h>
 59: #endif
 60: 
 61: int file_createdirs(char *name);
 62: 
 63: /***********************************
 64:  * Called when there is an error returned by the operating system.
 65:  * This function does not return.
 66:  */
 67: 
 68: void os_error(int line)
 69: {
 70: #if _WIN32
 71:     dbg_printf("System error: %ldL\n",GetLastError());
 72: #endif
 73:     local_assert(line);
 74: }
 75: 
 76: #if 1
 77: #undef dbg_printf
 78: #define dbg_printf      (void)
 79: #endif
 80: 
 81: #define os_error() os_error(__LINE__)
 82: #pragma noreturn(os_error)
warning C4068: unknown pragma
83: 84: #if _WIN32 85: /********************************* 86: * Allocate a chunk of memory from the operating system. 87: * Bypass malloc and friends. 88: */ 89: 90: static HANDLE hHeap; 91: 92: void *globalrealloc(void *oldp,size_t newsize) 93: { 94: #if 0 95: void *p; 96: 97: // Initialize heap 98: if (!hHeap) 99: { hHeap = HeapCreate(0,0x10000,0); 100: if (!hHeap) 101: os_error(); 102: } 103: 104: newsize = (newsize + 3) & ~3L; // round up to dwords 105: if (newsize == 0) 106: { 107: if (oldp && HeapFree(hHeap,0,oldp) == FALSE) 108: os_error(); 109: p = NULL; 110: } 111: else if (!oldp) 112: { 113: p = newsize ? HeapAlloc(hHeap,0,newsize) : NULL; 114: } 115: else 116: p = HeapReAlloc(hHeap,0,oldp,newsize); 117: #elif 1 118: MEMORY_BASIC_INFORMATION query; 119: void *p; 120: BOOL bSuccess; 121: 122: if (!oldp) 123: p = VirtualAlloc (NULL, newsize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 124: else 125: { 126: VirtualQuery (oldp, &query, sizeof(query)); 127: if (!newsize) 128: { 129: p = NULL; 130: goto L1; 131: } 132: else 133: { newsize = (newsize + 0xFFFF) & ~0xFFFFL; 134: 135: if (query.RegionSize >= newsize) 136: p = oldp; 137: else 138: { p = VirtualAlloc(NULL,newsize,MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE); 139: if (p) 140: memcpy(p,oldp,query.RegionSize); 141: L1: 142: bSuccess = VirtualFree(oldp,query.RegionSize,MEM_DECOMMIT);
warning C6250: Calling 'VirtualFree' without the MEM_RELEASE flag might free memory but not address descriptors (VADs). This causes address space leaks
143: if (bSuccess) 144: bSuccess = VirtualFree(oldp,0,MEM_RELEASE); 145: if (!bSuccess) 146: os_error(); 147: } 148: } 149: } 150: #else 151: void *p; 152: 153: if (!oldp) 154: p = (void *)GlobalAlloc (0, newsize); 155: else if (!newsize) 156: { GlobalFree(oldp); 157: p = NULL; 158: } 159: else 160: p = (void *)GlobalReAlloc(oldp,newsize,0); 161: #endif 162: dbg_printf("globalrealloc(oldp = %p, size = x%x) = %p\n",oldp,newsize,p); 163: return p; 164: } 165: 166: /***************************************** 167: * Functions to manage allocating a single virtual address space. 168: */ 169: 170: void *vmem_reserve(void *ptr,unsigned long size) 171: { void *p; 172: 173: #if 1 174: p = VirtualAlloc(ptr,size,MEM_RESERVE,PAGE_READWRITE); 175: dbg_printf("vmem_reserve(ptr = %p, size = x%lx) = %p\n",ptr,size,p); 176: #else 177: dbg_printf("vmem_reserve(ptr = %p, size = x%lx) = %p\n",ptr,size,p); 178: p = VirtualAlloc(ptr,size,MEM_RESERVE,PAGE_READWRITE); 179: if (!p) 180: os_error(); 181: #endif 182: return p; 183: } 184: 185: /***************************************** 186: * Commit memory. 187: * Returns: 188: * 0 failure 189: * !=0 success 190: */ 191: 192: int vmem_commit(void *ptr, unsigned long size) 193: { int i; 194: 195: dbg_printf("vmem_commit(ptr = %p,size = x%lx)\n",ptr,size); 196: i = (int) VirtualAlloc(ptr,size,MEM_COMMIT,PAGE_READWRITE); 197: if (i == 0) 198: dbg_printf("failed to commit\n"); 199: return i; 200: } 201: 202: void vmem_decommit(void *ptr,unsigned long size) 203: { 204: dbg_printf("vmem_decommit(ptr = %p, size = x%lx)\n",ptr,size); 205: if (ptr) 206: { if (!VirtualFree(ptr, size, MEM_DECOMMIT))
warning C6250: Calling 'VirtualFree' without the MEM_RELEASE flag might free memory but not address descriptors (VADs). This causes address space leaks
207: os_error(); 208: } 209: } 210: 211: void vmem_release(void *ptr,unsigned long size) 212: { 213: dbg_printf("vmem_release(ptr = %p, size = x%lx)\n",ptr,size); 214: if (ptr) 215: { 216: if (!VirtualFree(ptr, 0, MEM_RELEASE)) 217: os_error(); 218: } 219: } 220: 221: /******************************************** 222: * Map file for read, copy on write, into virtual address space. 223: * Input: 224: * ptr address to map file to, if NULL then pick an address 225: * size length of the file 226: * flag 0 read / write 227: * 1 read / copy on write 228: * 2 read only 229: * Returns: 230: * NULL failure 231: * ptr pointer to start of mapped file 232: */ 233: 234: static HANDLE hFile = INVALID_HANDLE_VALUE; 235: static HANDLE hFileMap = NULL; 236: static void *pview; 237: static void *preserve; 238: static size_t preserve_size; 239: 240: void *vmem_mapfile(const char *filename,void *ptr,unsigned long size,int flag) 241: { 242: OSVERSIONINFO OsVerInfo; 243: 244: OsVerInfo.dwOSVersionInfoSize = sizeof(OsVerInfo); 245: GetVersionEx(&OsVerInfo); 246: 247: dbg_printf("vmem_mapfile(filename = '%s', ptr = %p, size = x%lx, flag = %d)\n",filename,ptr,size,flag); 248: 249: hFile = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 250: FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 251: OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 252: if (hFile == INVALID_HANDLE_VALUE) 253: goto L1; // failure 254: dbg_printf(" file created\n"); 255: 256: // Windows 95 does not implement PAGE_WRITECOPY (unfortunately treating 257: // it just like PAGE_READWRITE). 258: if (flag == 1 && OsVerInfo.dwPlatformId == 1) // Windows 95, 98, ME 259: hFileMap = NULL; 260: else 261: hFileMap = CreateFileMapping(hFile,NULL, 262: (flag == 1) ? PAGE_WRITECOPY : PAGE_READWRITE,0,size,NULL); 263: 264: if (hFileMap == NULL) // mapping failed 265: { 266: #if 1 267: // Win32s seems to always fail here. 268: DWORD nbytes; 269: 270: dbg_printf(" mapping failed\n"); 271: // If it was NT failing, assert. 272: assert(OsVerInfo.dwPlatformId != VER_PLATFORM_WIN32_NT); 273: 274: // To work around, just read the file into memory. 275: assert(flag == 1); 276: preserve = vmem_reserve(ptr,size); 277: if (!preserve) 278: goto L2; 279: if (!vmem_commit(preserve,size)) 280: { 281: vmem_release(preserve,size); 282: preserve = NULL; 283: goto L2; 284: } 285: preserve_size = size; 286: if (!ReadFile(hFile,preserve,size,&nbytes,NULL)) 287: os_error(); 288: assert(nbytes == size); 289: if (CloseHandle(hFile) != TRUE) 290: os_error(); 291: hFile = INVALID_HANDLE_VALUE; 292: return preserve; 293: #else 294: // Instead of working around, we should find out why it failed. 295: os_error(); 296: #endif 297: } 298: else 299: { 300: dbg_printf(" mapping created\n"); 301: pview = MapViewOfFileEx(hFileMap,flag ? FILE_MAP_COPY : FILE_MAP_WRITE, 302: 0,0,size,ptr); 303: if (pview == NULL) // mapping view failed 304: { //os_error(); 305: goto L3; 306: } 307: } 308: dbg_printf(" pview = %p\n",pview); 309: 310: return pview; 311: 312: Terminate:
warning C4102: 'Terminate' : unreferenced label
313: if (UnmapViewOfFile(pview) == FALSE) 314: os_error(); 315: pview = NULL; 316: L3: 317: if (CloseHandle(hFileMap) != TRUE) 318: os_error(); 319: hFileMap = NULL; 320: L2: 321: if (CloseHandle(hFile) != TRUE) 322: os_error(); 323: hFile = INVALID_HANDLE_VALUE; 324: L1: 325: return NULL; // failure 326: } 327: 328: /***************************** 329: * Set size of mapped file. 330: */ 331: 332: void vmem_setfilesize(unsigned long size) 333: { 334: if (hFile != INVALID_HANDLE_VALUE) 335: { if (SetFilePointer(hFile,size,NULL,FILE_BEGIN) == 0xFFFFFFFF) 336: os_error(); 337: if (SetEndOfFile(hFile) == FALSE) 338: os_error(); 339: } 340: } 341: 342: /***************************** 343: * Unmap previous file mapping. 344: */ 345: 346: void vmem_unmapfile() 347: { 348: dbg_printf("vmem_unmapfile()\n"); 349: 350: vmem_decommit(preserve,preserve_size); 351: vmem_release(preserve,preserve_size); 352: preserve = NULL; 353: preserve_size = 0; 354: 355: #if 0 356: if (pview) 357: { int i; 358: 359: i = UnmapViewOfFile(pview); 360: dbg_printf("i = x%x\n",i); 361: if (i == FALSE) 362: os_error(); 363: } 364: #else 365: // Note that under Windows 95, UnmapViewOfFile() seems to return random 366: // values, not TRUE or FALSE. 367: if (pview && UnmapViewOfFile(pview) == FALSE) 368: os_error(); 369: #endif 370: pview = NULL; 371: 372: if (hFileMap != NULL && CloseHandle(hFileMap) != TRUE) 373: os_error(); 374: hFileMap = NULL; 375: 376: if (hFile != INVALID_HANDLE_VALUE && CloseHandle(hFile) != TRUE) 377: os_error(); 378: hFile = INVALID_HANDLE_VALUE; 379: } 380: 381: /**************************************** 382: * Determine a base address that we can use for mapping files to. 383: */ 384: 385: void *vmem_baseaddr() 386: { 387: OSVERSIONINFO OsVerInfo; 388: void *p; 389: 390: OsVerInfo.dwOSVersionInfoSize = sizeof(OsVerInfo); 391: GetVersionEx(&OsVerInfo); 392: 393: // These values for the address were determined by trial and error. 394: switch (OsVerInfo.dwPlatformId) 395: { 396: case VER_PLATFORM_WIN32s: // Win32s 397: // The fact that this is a different address than other 398: // WIN32 implementations causes us a lot of grief. 399: p = (void *) 0xC0000000; 400: break; 401: 402: case 1: //VER_PLATFORM_WIN32_WINDOWS: // Windows 95 403: // I've found 0x90000000..0xB work. All others fail. 404: default: // unknown 405: p = (void *) 0x90000000; 406: break; 407: 408: case VER_PLATFORM_WIN32_NT: // Windows NT 409: // Pick a value that is not coincident with the base address 410: // of any commonly used system DLLs. 411: p = (void *) 0x38000000; 412: break; 413: } 414: 415: return p; 416: } 417: 418: /******************************************** 419: * Calculate the amount of memory to reserve, adjusting 420: * *psize downwards. 421: */ 422: 423: void vmem_reservesize(unsigned long *psize) 424: { 425: MEMORYSTATUS ms; 426: OSVERSIONINFO OsVerInfo; 427: 428: unsigned long size; 429: 430: ms.dwLength = sizeof(ms); 431: GlobalMemoryStatus(&ms); 432: dbg_printf("dwMemoryLoad x%lx\n",ms.dwMemoryLoad); 433: dbg_printf("dwTotalPhys x%lx\n",ms.dwTotalPhys); 434: dbg_printf("dwAvailPhys x%lx\n",ms.dwAvailPhys); 435: dbg_printf("dwTotalPageFile x%lx\n",ms.dwTotalPageFile); 436: dbg_printf("dwAvailPageFile x%lx\n",ms.dwAvailPageFile); 437: dbg_printf("dwTotalVirtual x%lx\n",ms.dwTotalVirtual); 438: dbg_printf("dwAvailVirtual x%lx\n",ms.dwAvailVirtual); 439: 440: 441: OsVerInfo.dwOSVersionInfoSize = sizeof(OsVerInfo); 442: GetVersionEx(&OsVerInfo); 443: 444: switch (OsVerInfo.dwPlatformId) 445: { 446: case VER_PLATFORM_WIN32s: // Win32s 447: case 1: //VER_PLATFORM_WIN32_WINDOWS: // Windows 95 448: default: // unknown 449: size = (ms.dwAvailPageFile < ms.dwAvailVirtual) 450: ? ms.dwAvailPageFile 451: : ms.dwAvailVirtual; 452: size = (unsigned long long)size * 8 / 10; 453: size &= ~0xFFFFL; 454: if (size < *psize) 455: *psize = size; 456: break; 457: 458: case VER_PLATFORM_WIN32_NT: // Windows NT 459: // NT can expand the paging file 460: break; 461: } 462: 463: } 464: 465: /******************************************** 466: * Return amount of physical memory. 467: */ 468: 469: unsigned long vmem_physmem() 470: { 471: MEMORYSTATUS ms; 472: 473: ms.dwLength = sizeof(ms); 474: GlobalMemoryStatus(&ms); 475: return ms.dwTotalPhys; 476: } 477: 478: ////////////////////////////////////////////////////////////// 479: 480: /*************************************************** 481: * Load library. 482: */ 483: 484: static HINSTANCE hdll; 485: 486: void os_loadlibrary(const char *dllname) 487: { 488: hdll = LoadLibrary((LPCTSTR) dllname); 489: if (!hdll) 490: os_error(); 491: } 492: 493: /************************************************* 494: */ 495: 496: void os_freelibrary() 497: { 498: if (hdll) 499: { 500: if (FreeLibrary(hdll) != TRUE) 501: os_error(); 502: hdll = NULL; 503: } 504: } 505: 506: /************************************************* 507: */ 508: 509: void *os_getprocaddress(const char *funcname) 510: { void *fp; 511: 512: //printf("getprocaddress('%s')\n",funcname); 513: assert(hdll); 514: fp = (void *)GetProcAddress(hdll,(LPCSTR)funcname); 515: if (!fp) 516: os_error(); 517: return fp; 518: } 519: 520: ////////////////////////////////////////////////////////////// 521: 522: 523: /********************************* 524: */ 525: 526: void os_term() 527: { 528: if (hHeap) 529: { if (HeapDestroy(hHeap) == FALSE) 530: { hHeap = NULL; 531: os_error(); 532: } 533: hHeap = NULL; 534: } 535: os_freelibrary(); 536: } 537: 538: /*************************************************** 539: * Do our own storage allocator (being suspicious of the library one). 540: */ 541: 542: #if 1 543: 544: void os_heapinit() { } 545: void os_heapterm() { } 546: 547: #else 548: 549: static HANDLE hHeap; 550: 551: void os_heapinit() 552: { 553: hHeap = HeapCreate(0,0x10000,0); 554: if (!hHeap) 555: os_error(); 556: } 557: 558: void os_heapterm() 559: { 560: if (hHeap) 561: { if (HeapDestroy(hHeap) == FALSE) 562: os_error(); 563: } 564: } 565: 566: void * __cdecl calloc(size_t x,size_t y) 567: { size_t size; 568: 569: size = x * y; 570: return size ? HeapAlloc(hHeap,HEAP_ZERO_MEMORY,size) : NULL; 571: } 572: 573: void __cdecl free(void *p) 574: { 575: if (p && HeapFree(hHeap,0,p) == FALSE) 576: os_error(); 577: } 578: 579: void * __cdecl malloc(size_t size) 580: { 581: return size ? HeapAlloc(hHeap,0,size) : NULL; 582: } 583: 584: void * __cdecl realloc(void *p,size_t newsize) 585: { 586: if (newsize == 0) 587: free(p); 588: else if (!p) 589: p = malloc(newsize); 590: else 591: p = HeapReAlloc(hHeap,0,p,newsize); 592: return p; 593: } 594: 595: #endif 596: 597: ////////////////////////////////////////// 598: // Return a value that will hopefully be unique every time 599: // we call it. 600: 601: unsigned long os_unique() 602: { 603: unsigned long long x; 604: 605: QueryPerformanceCounter((LARGE_INTEGER *)&x); 606: return x;
warning C4244: 'return' : conversion from 'unsigned __int64' to 'unsigned long', possible loss of data
607: } 608: 609: #elif DOS386 610: 611: ////////////////////////////////////////// 612: // Return a value that will hopefully be unique every time 613: // we call it. 614: 615: unsigned long os_unique() 616: { 617: if (cputype() >= 5) // if cpuid instruction supported 618: { 619: __asm 620: { 621: mov EAX,1 622: cpuid 623: test EDX,0x20 // is rdtsc supported? 624: jz L1 // no 625: rdtsc 626: } 627: } 628: else 629: { 630: L1: time(NULL); 631: } 632: return _EAX; 633: } 634: 635: #endif 636: 637: /******************************************* 638: * Return !=0 if file exists. 639: * 0: file doesn't exist 640: * 1: normal file 641: * 2: directory 642: */ 643: 644: int os_file_exists(const char *name) 645: { 646: #if _WIN32 647: DWORD dw; 648: int result; 649: 650: dw = GetFileAttributes(name); 651: if (dw == -1L) 652: result = 0; 653: else if (dw & FILE_ATTRIBUTE_DIRECTORY) 654: result = 2; 655: else 656: result = 1; 657: return result; 658: #elif DOS386 659: struct FIND *find; 660: 661: find = findfirst(name,FA_DIREC | FA_SYSTEM | FA_HIDDEN); 662: if (!find) 663: return 0; 664: return (find->attribute & FA_DIREC) ? 2 : 1; 665: #elif linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 666: struct stat buf; 667: 668: return stat(name,&buf) == 0; /* file exists if stat succeeded */ 669: 670: #else 671: return filesize(name) != -1L; 672: #endif 673: } 674: 675: /************************************** 676: * Get file size of open file. Return -1L on error. 677: */ 678: 679: #if __DMC__ 680: extern "C" void * __cdecl _osfhnd[]; 681: #endif 682: 683: long os_file_size(int fd) 684: { 685: #if __DMC__ 686: return GetFileSize(_osfhnd[fd],NULL); 687: #else 688: struct stat buf; 689: 690: return (fstat(fd,&buf)) ? -1L : buf.st_size; 691: #endif 692: } 693: 694: /************************************************** 695: * For 16 bit programs, we need the 16 bit filename. 696: * Returns: 697: * malloc'd string, NULL if none 698: */ 699: 700: #if _WIN32 701: 702: char *file_8dot3name(const char *filename) 703: { 704: HANDLE h; 705: WIN32_FIND_DATA fileinfo; 706: char *buf; 707: int i; 708: 709: h = FindFirstFile(filename,&fileinfo); 710: if (h == INVALID_HANDLE_VALUE) 711: return NULL; 712: if (fileinfo.cAlternateFileName[0]) 713: { 714: for (i = strlen(filename); i > 0; i--) 715: if (filename[i] == '\\' || filename[i] == ':') 716: { i++; 717: break; 718: } 719: buf = (char *) malloc(i + 14); 720: if (buf) 721: { 722: memcpy(buf,filename,i); 723: strcpy(buf + i,fileinfo.cAlternateFileName);
warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(105) : see declaration of 'strcpy'
724: } 725: } 726: else 727: buf = strdup(filename);
warning C4996: 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strdup. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(238) : see declaration of 'strdup'
728: FindClose(h); 729: return buf; 730: } 731: 732: #endif 733: 734: /********************************************** 735: * Write a file. 736: * Returns: 737: * 0 success 738: */ 739: 740: int file_write(char *name, void *buffer, unsigned len) 741: { 742: #if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 743: int fd; 744: ssize_t numwritten; 745: 746: fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 747: S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 748: if (fd == -1) 749: goto err; 750: 751: numwritten = ::write(fd, buffer, len); 752: if (len != numwritten) 753: goto err2; 754: 755: if (close(fd) == -1) 756: goto err; 757: 758: return 0; 759: 760: err2: 761: close(fd); 762: err: 763: return 1; 764: #endif 765: #if _WIN32 766: HANDLE h; 767: DWORD numwritten; 768: 769: h = CreateFile((LPTSTR)name,GENERIC_WRITE,0,NULL,CREATE_ALWAYS, 770: FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL); 771: if (h == INVALID_HANDLE_VALUE) 772: { 773: if (GetLastError() == ERROR_PATH_NOT_FOUND) 774: { 775: if (!file_createdirs(name)) 776: { 777: h = CreateFile((LPTSTR)name,GENERIC_WRITE,0,NULL,CREATE_ALWAYS, 778: FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL); 779: if (h != INVALID_HANDLE_VALUE) 780: goto Lok; 781: } 782: } 783: goto err; 784: } 785: 786: Lok: 787: if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE) 788: goto err2; 789: 790: if (len != numwritten) 791: goto err2; 792: 793: if (!CloseHandle(h)) 794: goto err; 795: return 0; 796: 797: err2: 798: CloseHandle(h); 799: err: 800: return 1; 801: #endif 802: #if _MSDOS 803: return 1; 804: #endif 805: } 806: 807: /******************************** 808: * Create directories up to filename. 809: * Input: 810: * name path/filename 811: * Returns: 812: * 0 success 813: * !=0 failure 814: */ 815: 816: int file_createdirs(char *name) 817: { 818: #if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 819: return 1; 820: #endif 821: #if _WIN32 822: int len = strlen(name); 823: char *path = (char *)alloca(len + 1);
warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
824: char *p; 825: 826: memcpy(path, name, len + 1); 827: 828: for (p = path + len; ; p--) 829: { 830: if (p == path) 831: goto Lfail; 832: switch (*p) 833: { 834: case ':': 835: case '/': 836: case '\\': 837: *p = 0; 838: if (!CreateDirectory((LPTSTR)path, NULL)) 839: { // Failed 840: if (file_createdirs(path)) 841: goto Lfail; 842: if (!CreateDirectory((LPTSTR)path, NULL)) 843: goto Lfail; 844: } 845: return 0; 846: } 847: } 848: 849: Lfail: 850: return 1; 851: #endif 852: #if _MSDOS 853: return 1; 854: #endif 855: } 856: 857: /*********************************** 858: * Return size of OS critical section. 859: * NOTE: can't use the sizeof() calls directly since cross compiling is 860: * supported and would end up using the host sizes rather than the target 861: * sizes. 862: */ 863: 864: #if _WIN32 865: int os_critsecsize32() 866: { 867: return sizeof(CRITICAL_SECTION); 868: } 869: 870: int os_critsecsize64() 871: { 872: assert(0); 873: return 0; 874: } 875: #endif 876: 877: #if linux 878: int os_critsecsize32() 879: { 880: return 24; // sizeof(pthread_mutex_t) on 32 bit 881: } 882: 883: int os_critsecsize64() 884: { 885: return 40; // sizeof(pthread_mutex_t) on 64 bit 886: } 887: #endif 888: 889: #if __FreeBSD__ 890: int os_critsecsize32() 891: { 892: return 4; // sizeof(pthread_mutex_t) on 32 bit 893: } 894: 895: int os_critsecsize64() 896: { 897: return 8; // sizeof(pthread_mutex_t) on 64 bit 898: } 899: #endif 900: 901: #if __OpenBSD__ 902: int os_critsecsize32() 903: { 904: return 4; // sizeof(pthread_mutex_t) on 32 bit 905: } 906: 907: int os_critsecsize64() 908: { 909: assert(0); 910: return 8; // sizeof(pthread_mutex_t) on 64 bit 911: } 912: #endif 913: 914: #if __APPLE__ || __sun&&__SVR4 915: int os_critsecsize32() 916: { 917: return sizeof(pthread_mutex_t); 918: } 919: 920: int os_critsecsize64() 921: { 922: assert(0); 923: return 0; 924: } 925: #endif 926: 927: 928: