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: