"Fossies" - the Fresh Open Source Software Archive

Member "dmd-2.089.1/src/dmd/backend/os.d" (14 Dec 2019, 21307 Bytes) of package /linux/misc/dmd-2.089.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) D source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "os.d": 2.086.1_vs_2.087.0.

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