| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2020-04-16 03:42:30 +00:00
										 |  |  |     Copyright (c) 2006-2020 Chung, Hyung-Hwan. All rights reserved. | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |     modification, are permitted provided that the following conditions | 
					
						
							|  |  |  |     are met: | 
					
						
							|  |  |  |     1. Redistributions of source code must retain the above copyright | 
					
						
							|  |  |  |        notice, this list of conditions and the following disclaimer. | 
					
						
							|  |  |  |     2. Redistributions in binary form must reproduce the above copyright | 
					
						
							|  |  |  |        notice, this list of conditions and the following disclaimer in the | 
					
						
							|  |  |  |        documentation and/or other materials provided with the distribution. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | 
					
						
							|  |  |  |     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 
					
						
							|  |  |  |     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 
					
						
							|  |  |  |     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 
					
						
							|  |  |  |     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 
					
						
							|  |  |  |     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
					
						
							|  |  |  |     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
					
						
							|  |  |  |     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
					
						
							|  |  |  |     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 
					
						
							|  |  |  |     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <hawk-fio.h>
 | 
					
						
							|  |  |  | #include "hawk-prv.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | #	include <windows.h>
 | 
					
						
							|  |  |  | /*#	include <psapi.h>*/ /* for GetMappedFileName(). but dynamically loaded */ | 
					
						
							|  |  |  | #	include <tchar.h>
 | 
					
						
							|  |  |  | #	if !defined(INVALID_SET_FILE_POINTER)
 | 
					
						
							|  |  |  | #		define INVALID_SET_FILE_POINTER ((DWORD)-1)
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | #elif defined(__OS2__)
 | 
					
						
							|  |  |  | #	define INCL_DOSFILEMGR
 | 
					
						
							|  |  |  | #	define INCL_DOSMODULEMGR
 | 
					
						
							|  |  |  | #	define INCL_DOSPROCESS
 | 
					
						
							|  |  |  | #	define INCL_DOSERRORS
 | 
					
						
							|  |  |  | #	include <os2.h>
 | 
					
						
							|  |  |  | #elif defined(__DOS__)
 | 
					
						
							|  |  |  | #	include <io.h>
 | 
					
						
							|  |  |  | #	include <fcntl.h>
 | 
					
						
							|  |  |  | #	include <errno.h>
 | 
					
						
							|  |  |  | #elif defined(vms) || defined(__vms)
 | 
					
						
							|  |  |  | #	define __NEW_STARLET 1
 | 
					
						
							|  |  |  | #	include <starlet.h>
 | 
					
						
							|  |  |  | #	include <rms.h>
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #	include "syscall.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* internal status codes */ | 
					
						
							|  |  |  | enum | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	STATUS_APPEND      = (1 << 0), | 
					
						
							|  |  |  | 	STATUS_NOCLOSE     = (1 << 1), | 
					
						
							|  |  |  | 	STATUS_WIN32_STDIN = (1 << 2) | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef DWORD WINAPI (*getmappedfilename_t) ( | 
					
						
							|  |  |  | 	HANDLE hProcess, | 
					
						
							|  |  |  | 	LPVOID lpv, | 
					
						
							|  |  |  | 	LPTSTR lpFilename, | 
					
						
							|  |  |  | 	DWORD nSize | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__OS2__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(__WATCOMC__) && (__WATCOMC__ < 1200) && !defined(LONGLONG_INCLUDED)
 | 
					
						
							|  |  |  | typedef struct _LONGLONG { | 
					
						
							|  |  |  | 	ULONG ulLo; | 
					
						
							|  |  |  | 	LONG  ulHi; | 
					
						
							|  |  |  | } LONGLONG, *PLONGLONG; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct _ULONGLONG { | 
					
						
							|  |  |  | 	ULONG ulLo; | 
					
						
							|  |  |  | 	ULONG ulHi; | 
					
						
							|  |  |  | } ULONGLONG, *PULONGLONG; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef APIRET APIENTRY (*dosopenl_t) ( | 
					
						
							|  |  |  | 	PSZ pszFileName, | 
					
						
							|  |  |  | 	PHFILE pHf, | 
					
						
							|  |  |  | 	PULONG pulAction, | 
					
						
							|  |  |  | 	LONGLONG cbFile, | 
					
						
							|  |  |  | 	ULONG ulAttribute, | 
					
						
							|  |  |  | 	ULONG fsOpenFlags, | 
					
						
							|  |  |  | 	ULONG fsOpenMode, | 
					
						
							|  |  |  | 	PEAOP2 peaop2 | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef APIRET APIENTRY (*dossetfileptrl_t) ( | 
					
						
							|  |  |  | 	HFILE hFile, | 
					
						
							|  |  |  | 	LONGLONG ib, | 
					
						
							|  |  |  | 	ULONG method, | 
					
						
							|  |  |  | 	PLONGLONG ibActual | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef APIRET APIENTRY (*dossetfilesizel_t) ( | 
					
						
							|  |  |  | 	HFILE hFile, | 
					
						
							|  |  |  | 	LONGLONG cbSize | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int dos_set = 0; | 
					
						
							|  |  |  | static dosopenl_t dos_open_l = HAWK_NULL; | 
					
						
							|  |  |  | static dossetfileptrl_t dos_set_file_ptr_l = HAWK_NULL; | 
					
						
							|  |  |  | static dossetfilesizel_t dos_set_file_size_l = HAWK_NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | hawk_fio_t* hawk_fio_open (hawk_gem_t* gem, hawk_oow_t xtnsize, const hawk_ooch_t* path, int flags, int mode) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	hawk_fio_t* fio; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	fio = (hawk_fio_t*)hawk_gem_allocmem(gem, HAWK_SIZEOF(hawk_fio_t) + xtnsize); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	if (fio) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 		if (hawk_fio_init (fio, gem, path, flags, mode) <= -1) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 			hawk_gem_freemem (gem, fio); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			return HAWK_NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else HAWK_MEMSET (fio + 1, 0, xtnsize); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fio; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hawk_fio_close (hawk_fio_t* fio) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hawk_fio_fini (fio); | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	hawk_gem_freemem (fio->gem, fio); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | int hawk_fio_init (hawk_fio_t* fio, hawk_gem_t* gem, const hawk_ooch_t* path, int flags, int mode) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	hawk_fio_hnd_t handle; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 	hawk_uint32_t temp_no; | 
					
						
							|  |  |  | 	hawk_ooch_t* temp_ptr; | 
					
						
							|  |  |  | 	hawk_bch_t* temp_ptr_b; | 
					
						
							|  |  |  | 	hawk_oow_t temp_tries; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 	int fellback = 0; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(__OS2__)
 | 
					
						
							|  |  |  | 	if (!dos_set) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		DosEnterCritSec (); | 
					
						
							|  |  |  | 		if (!dos_set) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			HMODULE mod; | 
					
						
							|  |  |  | 			if (DosLoadModule(NULL, 0, "DOSCALL1", &mod) == NO_ERROR) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* look up routines by ordinal */ | 
					
						
							|  |  |  | 				DosQueryProcAddr (mod, 981, NULL, (PFN*)&dos_open_l); | 
					
						
							|  |  |  | 				DosQueryProcAddr (mod, 988, NULL, (PFN*)&dos_set_file_ptr_l); | 
					
						
							|  |  |  | 				DosQueryProcAddr (mod, 989, NULL, (PFN*)&dos_set_file_size_l); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			dos_set = 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		DosExitCritSec (); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HAWK_MEMSET (fio, 0, HAWK_SIZEOF(*fio)); | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	fio->gem = gem; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!(flags & (HAWK_FIO_READ | HAWK_FIO_WRITE | HAWK_FIO_APPEND | HAWK_FIO_HANDLE))) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		/* one of HAWK_FIO_READ, HAWK_FIO_WRITE, HAWK_FIO_APPEND,
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		 * and HAWK_FIO_HANDLE must be specified */ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, HAWK_EINVAL); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Store some flags for later use */ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	if (flags & HAWK_FIO_NOCLOSE) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		fio->status |= STATUS_NOCLOSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 	if (flags & HAWK_FIO_TEMPORARY) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hawk_ntime_t now; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*if (flags & (HAWK_FIO_HANDLE | HAWK_FIO_BCSTRPATH))*/ | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_HANDLE) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 			/* HAWK_FIO_TEMPORARY and HAWK_FIO_HANDLE/HAWK_FIO_BCSTRPATH
 | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 			 * are mutually exclusive */ | 
					
						
							|  |  |  | 			hawk_gem_seterrnum (fio->gem, HAWK_NULL, HAWK_EINVAL); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		temp_no = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_BCSTRPATH) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 			for (temp_ptr_b = (hawk_bch_t*)path; *temp_ptr_b; temp_ptr_b++) | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 				temp_no += *temp_ptr_b; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (temp_ptr_b - (hawk_bch_t*)path < 4) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hawk_gem_seterrnum (fio->gem, HAWK_NULL, HAWK_EINVAL); | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 				return -1; | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			temp_ptr_b -= 4; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* if HAWK_FIO_TEMPORARY is used, the path name must be writable. */ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 			for (temp_ptr = (hawk_ooch_t*)path; *temp_ptr; temp_ptr++) | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 				temp_no += *temp_ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* The path name template must be at least 4 characters long
 | 
					
						
							|  |  |  | 			 * excluding the terminating null. this function fails if not */ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 			if (temp_ptr - path < 4) | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				hawk_gem_seterrnum (fio->gem, HAWK_NULL, HAWK_EINVAL); | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 				return -1; | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			temp_ptr -= 4; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		hawk_get_ntime (&now); | 
					
						
							|  |  |  | 		temp_no += (now.sec & 0xFFFFFFFFlu); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		temp_tries = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	retry_temporary: | 
					
						
							|  |  |  | 		temp_tries++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Fails after 5000 tries. 5000 randomly chosen */ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (temp_tries > 5000) | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			hawk_gem_seterrnum (fio->gem, HAWK_NULL, HAWK_EINVAL); | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 			return -1; | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		/* Generate the next random number to use to make a
 | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 		 * new path name */ | 
					
						
							|  |  |  | 		temp_no = hawk_rand31(temp_no); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		/*
 | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 		 * You must not pass a constant string for a path name | 
					
						
							|  |  |  | 		 * when HAWK_FIO_TEMPORARY is set, because it changes | 
					
						
							|  |  |  | 		 * the path name with a random number generated | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_BCSTRPATH) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hawk_fmt_uintmax_to_bcstr ( | 
					
						
							|  |  |  | 				temp_ptr_b, | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 				4, | 
					
						
							|  |  |  | 				temp_no % 0x10000, | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 				16 | HAWK_FMT_UINTMAX_NOTRUNC | HAWK_FMT_UINTMAX_NONULL, | 
					
						
							|  |  |  | 				4, | 
					
						
							|  |  |  | 				'\0', | 
					
						
							|  |  |  | 				HAWK_NULL | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hawk_fmt_uintmax_to_oocstr ( | 
					
						
							|  |  |  | 				temp_ptr, | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 				4, | 
					
						
							|  |  |  | 				temp_no % 0x10000, | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 				16 | HAWK_FMT_UINTMAX_NOTRUNC | HAWK_FMT_UINTMAX_NONULL, | 
					
						
							|  |  |  | 				4, | 
					
						
							|  |  |  | 				HAWK_T('\0'), | 
					
						
							|  |  |  | 				HAWK_NULL | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 	if (flags & HAWK_FIO_HANDLE) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		handle = *(hawk_fio_hnd_t*)path; | 
					
						
							|  |  |  | 		/* do not specify an invalid handle value */ | 
					
						
							| 
									
										
										
										
											2025-06-18 23:45:34 +09:00
										 |  |  | 		/*HAWK_ASSERT(hawk, handle != INVALID_HANDLE_VALUE);*/ | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (handle == GetStdHandle (STD_INPUT_HANDLE)) | 
					
						
							|  |  |  | 			fio->status |= STATUS_WIN32_STDIN; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		DWORD desired_access = 0; | 
					
						
							|  |  |  | 		DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; | 
					
						
							|  |  |  | 		DWORD creation_disposition = 0; | 
					
						
							|  |  |  | 		DWORD flag_and_attr = FILE_ATTRIBUTE_NORMAL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (fellback) share_mode &= ~FILE_SHARE_DELETE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_APPEND) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (fellback) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				desired_access |= GENERIC_WRITE; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* this is not officially documented for CreateFile.
 | 
					
						
							|  |  |  | 				 * ZwCreateFile (kernel) seems to document it */ | 
					
						
							|  |  |  | 				fio->status &= ~STATUS_APPEND; | 
					
						
							|  |  |  | 				desired_access |= FILE_APPEND_DATA; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (flags & HAWK_FIO_WRITE) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* In WIN32, FILE_APPEND_DATA and GENERIC_WRITE can't
 | 
					
						
							|  |  |  | 			 * be used together */ | 
					
						
							|  |  |  | 			desired_access |= GENERIC_WRITE; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_READ) desired_access |= GENERIC_READ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_CREATE) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			creation_disposition = | 
					
						
							|  |  |  | 				(flags & HAWK_FIO_EXCLUSIVE)? CREATE_NEW: | 
					
						
							|  |  |  | 				(flags & HAWK_FIO_TRUNCATE)? CREATE_ALWAYS: OPEN_ALWAYS; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (flags & HAWK_FIO_TRUNCATE) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			creation_disposition = TRUNCATE_EXISTING; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else creation_disposition = OPEN_EXISTING; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_NOSHREAD) | 
					
						
							|  |  |  | 			share_mode &= ~FILE_SHARE_READ; | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_NOSHWRITE) | 
					
						
							|  |  |  | 			share_mode &= ~FILE_SHARE_WRITE; | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_NOSHDELETE) | 
					
						
							|  |  |  | 			share_mode &= ~FILE_SHARE_DELETE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (!(mode & HAWK_FIO_WUSR)) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			flag_and_attr = FILE_ATTRIBUTE_READONLY; | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (flags & HAWK_FIO_SYNC) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			flag_and_attr |= FILE_FLAG_WRITE_THROUGH; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(FILE_FLAG_OPEN_REPARSE_POINT)
 | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_NOFOLLOW) | 
					
						
							|  |  |  | 			flag_and_attr |= FILE_FLAG_OPEN_REPARSE_POINT; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* these two are just hints to OS */ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (flags & HAWK_FIO_RANDOM) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			flag_and_attr |= FILE_FLAG_RANDOM_ACCESS; | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (flags & HAWK_FIO_SEQUENTIAL) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			flag_and_attr |= FILE_FLAG_SEQUENTIAL_SCAN; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 		if (flags & HAWK_FIO_BCSTRPATH) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-01-10 15:30:57 +00:00
										 |  |  | 			handle = CreateFileA( | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 				(const hawk_bch_t*)path, desired_access, share_mode, | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 				HAWK_NULL, /* set noinherit by setting no secattr */ | 
					
						
							|  |  |  | 				creation_disposition, flag_and_attr, 0 | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-01-10 15:30:57 +00:00
										 |  |  | 			handle = CreateFile( | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 				path, desired_access, share_mode, | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 				HAWK_NULL, /* set noinherit by setting no secattr */ | 
					
						
							|  |  |  | 				creation_disposition, flag_and_attr, 0 | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (handle == INVALID_HANDLE_VALUE) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			DWORD e = GetLastError(); | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 			if (!fellback && e == ERROR_INVALID_PARAMETER && | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			    ((share_mode & FILE_SHARE_DELETE) || (flags & HAWK_FIO_APPEND))) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* old windows fails with ERROR_INVALID_PARAMETER
 | 
					
						
							|  |  |  | 				 * when some advanced flags are used. so try again | 
					
						
							|  |  |  | 				 * with fallback flags */ | 
					
						
							|  |  |  | 				fellback = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				share_mode &= ~FILE_SHARE_DELETE; | 
					
						
							|  |  |  | 				if (flags & HAWK_FIO_APPEND) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					fio->status |= STATUS_APPEND; | 
					
						
							|  |  |  | 					desired_access &= ~FILE_APPEND_DATA; | 
					
						
							|  |  |  | 					desired_access |= GENERIC_WRITE; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 				if (flags & HAWK_FIO_BCSTRPATH) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2020-01-10 15:30:57 +00:00
										 |  |  | 					handle = CreateFileA( | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 						(const hawk_bch_t*)path, desired_access, share_mode, | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 						HAWK_NULL, /* set noinherit by setting no secattr */ | 
					
						
							|  |  |  | 						creation_disposition, flag_and_attr, 0 | 
					
						
							|  |  |  | 					); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2020-01-10 15:30:57 +00:00
										 |  |  | 					handle = CreateFile( | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 						path, desired_access, share_mode, | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 						HAWK_NULL, /* set noinherit by setting no secattr */ | 
					
						
							|  |  |  | 						creation_disposition, flag_and_attr, 0 | 
					
						
							|  |  |  | 					); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 				if (handle == INVALID_HANDLE_VALUE) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 				i	if (flags & HAWK_FIO_TEMPORARY) goto retry_temporary; | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 					hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(GetLastError())); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 					return -1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 				if (flags & HAWK_FIO_TEMPORARY) goto retry_temporary; | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 				hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(e)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* some special check */ | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | 	if (GetFileType(handle) == FILE_TYPE_UNKNOWN) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(GetLastError())); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		CloseHandle (handle); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO: support more features on WIN32 - TEMPORARY, DELETE_ON_CLOSE */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__OS2__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (flags & HAWK_FIO_HANDLE) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		handle = *(hawk_fio_hnd_t*)path; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		APIRET ret; | 
					
						
							|  |  |  | 		ULONG action_taken = 0; | 
					
						
							|  |  |  | 		ULONG open_action, open_mode, open_attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(HAWK_OOCH_IS_BCH)
 | 
					
						
							|  |  |  | 		const hawk_bch_t* path_mb = path; | 
					
						
							|  |  |  | 	#else
 | 
					
						
							|  |  |  | 		hawk_bch_t path_mb_buf[CCHMAXPATH]; | 
					
						
							|  |  |  | 		hawk_bch_t* path_mb; | 
					
						
							|  |  |  | 		hawk_oow_t wl, ml; | 
					
						
							|  |  |  | 		int px; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 		if (flags & HAWK_FIO_BCSTRPATH) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			path_mb = (hawk_bch_t*)path; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			path_mb = path_mb_buf; | 
					
						
							|  |  |  | 			ml = HAWK_COUNTOF(path_mb_buf); | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 			px = hawk_gem_convutobcstr(fio->gem, path, &wl, path_mb, &ml); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			if (px == -2) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* the static buffer is too small.
 | 
					
						
							|  |  |  | 				 * dynamically allocate a buffer */ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 				path_mb = hawk_gem_duputobcstr(fio->gem, path, HAWK_NUL); | 
					
						
							|  |  |  | 				if (path_mb == HAWK_NULL) return -1; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 			else if (px <= -1) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 		if (flags & HAWK_FIO_APPEND) fio->status |= STATUS_APPEND; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_CREATE) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (flags & HAWK_FIO_EXCLUSIVE) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 				open_action = OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else if (flags & HAWK_FIO_TRUNCATE) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 				open_action = OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 				open_action = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (flags & HAWK_FIO_TRUNCATE) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 			open_action = OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 			open_action = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		open_mode = OPEN_FLAGS_NOINHERIT; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 		if (flags & HAWK_FIO_SYNC) open_mode |= OPEN_FLAGS_WRITE_THROUGH; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 		if ((flags & HAWK_FIO_NOSHREAD) && (flags & HAWK_FIO_NOSHWRITE)) open_mode |= OPEN_SHARE_DENYREADWRITE; | 
					
						
							|  |  |  | 		else if (flags & HAWK_FIO_NOSHREAD) open_mode |= OPEN_SHARE_DENYREAD; | 
					
						
							|  |  |  | 		else if (flags & HAWK_FIO_NOSHWRITE) open_mode |= OPEN_SHARE_DENYWRITE; | 
					
						
							|  |  |  | 		else open_mode |= OPEN_SHARE_DENYNONE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if ((flags & HAWK_FIO_READ) && (flags & HAWK_FIO_WRITE)) open_mode |= OPEN_ACCESS_READWRITE; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		else if (flags & HAWK_FIO_READ) open_mode |= OPEN_ACCESS_READONLY; | 
					
						
							|  |  |  | 		else if (flags & HAWK_FIO_WRITE) open_mode |= OPEN_ACCESS_WRITEONLY; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		open_attr = (mode & HAWK_FIO_WUSR)? FILE_NORMAL: FILE_READONLY; | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	#if defined(FIL_STANDARDL)
 | 
					
						
							|  |  |  | 		if (dos_open_l) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			LONGLONG zero; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			zero.ulLo = 0; | 
					
						
							|  |  |  | 			zero.ulHi = 0; | 
					
						
							|  |  |  | 			ret = dos_open_l ( | 
					
						
							|  |  |  | 				path_mb,       /* file name */ | 
					
						
							|  |  |  | 				&handle,       /* file handle */ | 
					
						
							|  |  |  | 				&action_taken, /* store action taken */ | 
					
						
							|  |  |  | 				zero,          /* size */ | 
					
						
							|  |  |  | 				open_attr,     /* attribute */ | 
					
						
							|  |  |  | 				open_action,   /* action if it exists */ | 
					
						
							|  |  |  | 				open_mode,     /* open mode */ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 				0L | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 			ret = DosOpen ( | 
					
						
							|  |  |  | 				path_mb,       /* file name */ | 
					
						
							|  |  |  | 				&handle,       /* file handle */ | 
					
						
							|  |  |  | 				&action_taken, /* store action taken */ | 
					
						
							|  |  |  | 				0,             /* size */ | 
					
						
							|  |  |  | 				open_attr,     /* attribute */ | 
					
						
							|  |  |  | 				open_action,   /* action if it exists */ | 
					
						
							|  |  |  | 				open_mode,     /* open mode */ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 				0L | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			); | 
					
						
							|  |  |  | 	#if defined(FIL_STANDARDL)
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(HAWK_OOCH_IS_BCH)
 | 
					
						
							|  |  |  | 		/* nothing to do */ | 
					
						
							|  |  |  | 	#else
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 		if (path_mb != path_mb_buf) hawk_gem_freemem (fio->gem, path_mb); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (ret != NO_ERROR) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 			if (flags & HAWK_FIO_TEMPORARY) goto retry_temporary; | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 			hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(ret)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__DOS__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (flags & HAWK_FIO_HANDLE) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		handle = *(hawk_fio_hnd_t*)path; | 
					
						
							|  |  |  | 		/* do not specify an invalid handle value */ | 
					
						
							| 
									
										
										
										
											2025-06-18 23:45:34 +09:00
										 |  |  | 		/*HAWK_ASSERT(hawk, handle >= 0);*/ | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int oflags = 0; | 
					
						
							|  |  |  | 		int permission = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(HAWK_OOCH_IS_BCH)
 | 
					
						
							|  |  |  | 		const hawk_bch_t* path_mb = path; | 
					
						
							|  |  |  | 	#else
 | 
					
						
							|  |  |  | 		hawk_bch_t path_mb_buf[_MAX_PATH]; | 
					
						
							|  |  |  | 		hawk_bch_t* path_mb; | 
					
						
							|  |  |  | 		hawk_oow_t wl, ml; | 
					
						
							|  |  |  | 		int px; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 		if (flags & HAWK_FIO_BCSTRPATH) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			path_mb = (hawk_bch_t*)path; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			path_mb = path_mb_buf; | 
					
						
							|  |  |  | 			ml = HAWK_COUNTOF(path_mb_buf); | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 			px = hawk_gem_convutobcstr(fio->gem, path, &wl, path_mb, &ml); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			if (px == -2) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 				/* static buffer size not enough.
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 				 * switch to dynamic allocation */ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 				path_mb = hawk_gem_duputobcstr(fio->gem, path, HAWK_NULL); | 
					
						
							|  |  |  | 				if (path_mb == HAWK_NULL)  return -1; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 			else if (px <= -1) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_APPEND) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if ((flags & HAWK_FIO_READ)) oflags |= O_RDWR; | 
					
						
							|  |  |  | 			else oflags |= O_WRONLY; | 
					
						
							|  |  |  | 			oflags |= O_APPEND; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if ((flags & HAWK_FIO_READ) && | 
					
						
							|  |  |  | 			    (flags & HAWK_FIO_WRITE)) oflags |= O_RDWR; | 
					
						
							|  |  |  | 			else if (flags & HAWK_FIO_READ) oflags |= O_RDONLY; | 
					
						
							|  |  |  | 			else if (flags & HAWK_FIO_WRITE) oflags |= O_WRONLY; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_CREATE) oflags |= O_CREAT; | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_TRUNCATE) oflags |= O_TRUNC; | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_EXCLUSIVE) oflags |= O_EXCL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		oflags |= O_BINARY | O_NOINHERIT; | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		if (mode & HAWK_FIO_RUSR) permission |= S_IREAD; | 
					
						
							|  |  |  | 		if (mode & HAWK_FIO_WUSR) permission |= S_IWRITE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		handle = open ( | 
					
						
							|  |  |  | 			path_mb, | 
					
						
							|  |  |  | 			oflags, | 
					
						
							|  |  |  | 			permission | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(HAWK_OOCH_IS_BCH)
 | 
					
						
							|  |  |  | 		/* nothing to do */ | 
					
						
							|  |  |  | 	#else
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 		if (path_mb != path_mb_buf) hawk_gem_freemem (fio->gem, path_mb); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (handle <= -1) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 			if (flags & HAWK_FIO_TEMPORARY) goto retry_temporary; | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 			hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(vms) || defined(__vms)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (flags & HAWK_FIO_HANDLE) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* TODO: implement this */ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, HAWK_ENOIMPL); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		struct FAB* fab; | 
					
						
							|  |  |  | 		struct RAB* rab; | 
					
						
							|  |  |  | 		unsigned long r0; | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	#if defined(HAWK_OOCH_IS_BCH)
 | 
					
						
							|  |  |  | 		const hawk_bch_t* path_mb = path; | 
					
						
							|  |  |  | 	#else
 | 
					
						
							|  |  |  | 		hawk_bch_t path_mb_buf[1024]; | 
					
						
							|  |  |  | 		hawk_bch_t* path_mb; | 
					
						
							|  |  |  | 		hawk_oow_t wl, ml; | 
					
						
							|  |  |  | 		int px; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 		if (flags & HAWK_FIO_BCSTRPATH) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			path_mb = (hawk_bch_t*)path; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			path_mb = path_mb_buf; | 
					
						
							|  |  |  | 			ml = HAWK_COUNTOF(path_mb_buf); | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 			px = hawk_convutobcstr(fio->gem, path, &wl, path_mb, &ml); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			if (px == -2) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* the static buffer is too small.
 | 
					
						
							|  |  |  | 				 * allocate a buffer */ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 				path_mb = hawk_duputobcstr(fio->gem, path, mmgr); | 
					
						
							|  |  |  | 				if (path_mb == HAWK_NULL) return -1; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 			else if (px <= -1) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 		rab = (struct RAB*)hawk_gem_allocmem(fio->gem, HAWK_SIZEOF(*rab) + HAWK_SIZEOF(*fab)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		if (rab == HAWK_NULL) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 	#if defined(HAWK_OOCH_IS_BCH)
 | 
					
						
							|  |  |  | 			/* nothing to do */ | 
					
						
							|  |  |  | 	#else
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 			if (path_mb != path_mb_buf) hawk_gem_freemem (fio->gem, path_mb); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	#endif
 | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		fab = (struct FAB*)(rab + 1); | 
					
						
							|  |  |  | 		*rab = cc$rms_rab; | 
					
						
							|  |  |  | 		rab->rab$l_fab = fab; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		*fab = cc$rms_fab; | 
					
						
							|  |  |  | 		fab->fab$l_fna = path_mb; | 
					
						
							|  |  |  | 		fab->fab$b_fns = strlen(path_mb); | 
					
						
							|  |  |  | 		fab->fab$b_org = FAB$C_SEQ; | 
					
						
							|  |  |  | 		fab->fab$b_rfm = FAB$C_VAR; /* FAB$C_STM, FAB$C_STMLF, FAB$C_VAR, etc... */ | 
					
						
							|  |  |  | 		fab->fab$b_fac = FAB$M_GET | FAB$M_PUT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		fab->fab$b_fac = FAB$M_NIL; | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_READ) fab->fab$b_fac |= FAB$M_GET; | 
					
						
							|  |  |  | 		if (flags & (HAWK_FIO_WRITE | HAWK_FIO_APPEND)) fab->fab$b_fac |= FAB$M_PUT | FAB$M_TRN; /* put, truncate */ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		fab->fab$b_shr |= FAB$M_SHRPUT | FAB$M_SHRGET; /* FAB$M_NIL */ | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_NOSHREAD) fab->fab$b_shr &= ~FAB$M_SHRGET; | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_NOSHWRITE) fab->fab$b_shr &= ~FAB$M_SHRPUT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_APPEND) rab->rab$l_rop |= RAB$M_EOF; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (flags & HAWK_FIO_CREATE) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 			if (flags & HAWK_FIO_EXCLUSIVE) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 				fab->fab$l_fop &= ~FAB$M_CIF; | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				fab->fab$l_fop |= FAB$M_CIF; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			r0 = sys$create (&fab, 0, 0); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			r0 = sys$open (&fab, 0, 0); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (r0 != RMS$_NORMAL && r0 != RMS$_CREATED) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 	#if defined(HAWK_OOCH_IS_BCH)
 | 
					
						
							|  |  |  | 			/* nothing to do */ | 
					
						
							|  |  |  | 	#else
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 			if (path_mb != path_mb_buf) hawk_gem_freemem (fio->gem, path_mb); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	#endif
 | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 			hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(r0)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		r0 = sys$connect (&rab, 0, 0); | 
					
						
							|  |  |  | 		if (r0 != RMS$_NORMAL) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 	#if defined(HAWK_OOCH_IS_BCH)
 | 
					
						
							|  |  |  | 			/* nothing to do */ | 
					
						
							|  |  |  | 	#else
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 			if (path_mb != path_mb_buf) hawk_gem_freemem (fio->gem, path_mb); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	#endif
 | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 			hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(r0)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(HAWK_OOCH_IS_BCH)
 | 
					
						
							|  |  |  | 		/* nothing to do */ | 
					
						
							|  |  |  | 	#else
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 		if (path_mb != path_mb_buf) hawk_gem_freemem (fio->gem, path_mb); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		handle = rab; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (flags & HAWK_FIO_HANDLE) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		handle = *(hawk_fio_hnd_t*)path; | 
					
						
							|  |  |  | 		/* do not specify an invalid handle value */ | 
					
						
							| 
									
										
										
										
											2025-06-18 23:45:34 +09:00
										 |  |  | 		/*HAWK_ASSERT(hawk, handle >= 0);*/ | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int desired_access = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(HAWK_OOCH_IS_BCH)
 | 
					
						
							|  |  |  | 		const hawk_bch_t* path_mb = path; | 
					
						
							|  |  |  | 	#else
 | 
					
						
							|  |  |  | 		hawk_bch_t path_mb_buf[1024];  /* PATH_MAX instead? */ | 
					
						
							|  |  |  | 		hawk_bch_t* path_mb; | 
					
						
							|  |  |  | 		hawk_oow_t wl, ml; | 
					
						
							|  |  |  | 		int px; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 		if (flags & HAWK_FIO_BCSTRPATH) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			path_mb = (hawk_bch_t*)path; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			path_mb = path_mb_buf; | 
					
						
							|  |  |  | 			ml = HAWK_COUNTOF(path_mb_buf); | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 			px = hawk_conv_ucstr_to_bcstr_with_cmgr(path, &wl, path_mb, &ml, fio->gem->cmgr); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			if (px == -2) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* the static buffer is too small.
 | 
					
						
							|  |  |  | 				 * allocate a buffer */ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 				path_mb = hawk_gem_duputobcstr(fio->gem, path, HAWK_NULL); | 
					
						
							|  |  |  | 				if (path_mb == HAWK_NULL) return -1; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 			else if (px <= -1) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 				hawk_gem_seterrnum (fio->gem, HAWK_NULL, HAWK_EINVAL); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * rwa -> RDWR   | APPEND | 
					
						
							|  |  |  | 		 * ra  -> RDWR   | APPEND | 
					
						
							|  |  |  | 		 * wa  -> WRONLY | APPEND | 
					
						
							|  |  |  | 		 * a   -> WRONLY | APPEND | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_APPEND) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if ((flags & HAWK_FIO_READ)) desired_access |= O_RDWR; | 
					
						
							|  |  |  | 			else desired_access |= O_WRONLY; | 
					
						
							|  |  |  | 			desired_access |= O_APPEND; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if ((flags & HAWK_FIO_READ) && | 
					
						
							|  |  |  | 			    (flags & HAWK_FIO_WRITE)) desired_access |= O_RDWR; | 
					
						
							|  |  |  | 			else if (flags & HAWK_FIO_READ) desired_access |= O_RDONLY; | 
					
						
							|  |  |  | 			else if (flags & HAWK_FIO_WRITE) desired_access |= O_WRONLY; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_CREATE) desired_access |= O_CREAT; | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_TRUNCATE) desired_access |= O_TRUNC; | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_EXCLUSIVE) desired_access |= O_EXCL; | 
					
						
							|  |  |  | 	#if defined(O_SYNC)
 | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_SYNC) desired_access |= O_SYNC; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(O_NOFOLLOW)
 | 
					
						
							|  |  |  | 		if (flags & HAWK_FIO_NOFOLLOW) desired_access |= O_NOFOLLOW; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(O_LARGEFILE)
 | 
					
						
							|  |  |  | 		desired_access |= O_LARGEFILE; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 	#if defined(O_CLOEXEC)
 | 
					
						
							|  |  |  | 		desired_access |= O_CLOEXEC; /* no inherit */ | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		handle = HAWK_OPEN(path_mb, desired_access, mode); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(HAWK_OOCH_IS_BCH)
 | 
					
						
							|  |  |  | 		/* nothing to do */ | 
					
						
							|  |  |  | 	#else
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (path_mb != path_mb_buf && path_mb != (hawk_bch_t*)path) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 			hawk_gem_freemem (fio->gem, path_mb); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (handle == -1) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-03-31 17:14:52 +00:00
										 |  |  | 			if (flags & HAWK_FIO_TEMPORARY) goto retry_temporary; | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 			hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		#if !defined(O_CLOEXEC) && defined(FD_CLOEXEC)
 | 
					
						
							|  |  |  | 			int flag = fcntl(handle, F_GETFD); | 
					
						
							|  |  |  | 			if (flag >= 0) fcntl (handle, F_SETFD, flag | FD_CLOEXEC); | 
					
						
							|  |  |  | 		#endif
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* set some file access hints */ | 
					
						
							|  |  |  | 	#if defined(POSIX_FADV_RANDOM)
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (flags & HAWK_FIO_RANDOM) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			posix_fadvise (handle, 0, 0, POSIX_FADV_RANDOM); | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 	#if defined(POSIX_FADV_SEQUENTIAL)
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (flags & HAWK_FIO_SEQUENTIAL) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			posix_fadvise (handle, 0, 0, POSIX_FADV_SEQUENTIAL); | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fio->handle = handle; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hawk_fio_fini (hawk_fio_t* fio) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!(fio->status & STATUS_NOCLOSE)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 		CloseHandle (fio->handle); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__OS2__)
 | 
					
						
							|  |  |  | 		DosClose (fio->handle); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__DOS__)
 | 
					
						
							|  |  |  | 		close (fio->handle); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(vms) || defined(__vms)
 | 
					
						
							|  |  |  | 		struct RAB* rab = (struct RAB*)fio->handle; | 
					
						
							|  |  |  | 		sys$disconnect (rab, 0, 0); | 
					
						
							|  |  |  | 		sys$close ((struct FAB*)(rab + 1), 0, 0); | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 		hawk_gem_freemem (fio->gem, fio->handle); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 		HAWK_CLOSE (fio->handle); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_fio_hnd_t hawk_fio_gethnd (const hawk_fio_t* fio) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return fio->handle; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_fio_off_t hawk_fio_seek (hawk_fio_t* fio, hawk_fio_off_t offset, hawk_fio_ori_t origin) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 	static int seek_map[] = | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		FILE_BEGIN, | 
					
						
							|  |  |  | 		FILE_CURRENT, | 
					
						
							|  |  |  | 		FILE_END | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 	LARGE_INTEGER x; | 
					
						
							|  |  |  | 	#if defined(_WIN64)
 | 
					
						
							|  |  |  | 	LARGE_INTEGER y; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	/* HAWK_ASSERT (fio->hawk, HAWK_SIZEOF(offset) <= HAWK_SIZEOF(x.QuadPart));*/ | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(_WIN64)
 | 
					
						
							|  |  |  | 	x.QuadPart = offset; | 
					
						
							|  |  |  | 	if (SetFilePointerEx (fio->handle, x, &y, seek_map[origin]) == FALSE) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return (hawk_fio_off_t)-1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return (hawk_fio_off_t)y.QuadPart; | 
					
						
							|  |  |  | 	#else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* SetFilePointerEx is not available on Windows NT 4.
 | 
					
						
							|  |  |  | 	 * So let's use SetFilePointer */ | 
					
						
							|  |  |  | 	x.QuadPart = offset; | 
					
						
							|  |  |  | 	x.LowPart = SetFilePointer ( | 
					
						
							|  |  |  | 		fio->handle, x.LowPart, &x.HighPart, seek_map[origin]); | 
					
						
							|  |  |  | 	if (x.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(GetLastError())); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return (hawk_fio_off_t)-1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return (hawk_fio_off_t)x.QuadPart; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__OS2__)
 | 
					
						
							|  |  |  | 	static int seek_map[] = | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		FILE_BEGIN, | 
					
						
							|  |  |  | 		FILE_CURRENT, | 
					
						
							|  |  |  | 		FILE_END | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(FIL_STANDARDL)
 | 
					
						
							|  |  |  | 	if (dos_set_file_ptr_l) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		LONGLONG pos, newpos; | 
					
						
							|  |  |  | 		APIRET ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 		/*HAWK_ASSERT (fio->hawk, HAWK_SIZEOF(offset) >= HAWK_SIZEOF(pos));*/ | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		pos.ulLo = (ULONG)(offset&0xFFFFFFFFlu); | 
					
						
							|  |  |  | 		pos.ulHi = (ULONG)(offset>>32); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ret = dos_set_file_ptr_l (fio->handle, pos, seek_map[origin], &newpos); | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (ret != NO_ERROR) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 			hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(ret)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			return (hawk_fio_off_t)-1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return ((hawk_fio_off_t)newpos.ulHi << 32) | newpos.ulLo; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 		ULONG newpos; | 
					
						
							|  |  |  | 		APIRET ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ret = DosSetFilePtr (fio->handle, offset, seek_map[origin], &newpos); | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (ret != NO_ERROR) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 			hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(ret)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			return (hawk_fio_off_t)-1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return newpos; | 
					
						
							|  |  |  | 	#if defined(FIL_STANDARDL)
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__DOS__)
 | 
					
						
							|  |  |  | 	static int seek_map[] = | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		SEEK_SET, | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		SEEK_CUR, | 
					
						
							|  |  |  | 		SEEK_END | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return lseek (fio->handle, offset, seek_map[origin]); | 
					
						
							|  |  |  | #elif defined(vms) || defined(__vms)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO: */ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	hawk_gem_seterrnum (fio->gem, HAWK_NULL, HAWK_ENOIMPL); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return (hawk_fio_off_t)-1; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	static int seek_map[] = | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		SEEK_SET, | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		SEEK_CUR, | 
					
						
							|  |  |  | 		SEEK_END | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(HAWK_LLSEEK)
 | 
					
						
							|  |  |  | 	loff_t tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	if (HAWK_LLSEEK(fio->handle, | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		(unsigned long)(offset>>32), | 
					
						
							|  |  |  | 		(unsigned long)(offset&0xFFFFFFFFlu), | 
					
						
							|  |  |  | 		&tmp, | 
					
						
							|  |  |  | 		seek_map[origin]) == -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return (hawk_fio_off_t)-1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return (hawk_fio_off_t)tmp; | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	return HAWK_LSEEK(fio->handle, offset, seek_map[origin]); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int hawk_fio_truncate (hawk_fio_t* fio, hawk_fio_off_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 	if (hawk_fio_seek (fio, size, HAWK_FIO_BEGIN) == (hawk_fio_off_t)-1) return -1; | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	if (SetEndOfFile(fio->handle) == FALSE) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(GetLastError())); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | #elif defined(__OS2__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	APIRET ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(FIL_STANDARDL)
 | 
					
						
							|  |  |  | 	if (dos_set_file_size_l) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		LONGLONG sz; | 
					
						
							|  |  |  | 		/* the file must have the write access for it to succeed */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		sz.ulLo = (ULONG)(size&0xFFFFFFFFlu); | 
					
						
							|  |  |  | 		sz.ulHi = (ULONG)(size>>32); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ret = dos_set_file_size_l (fio->handle, sz); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 		ret = DosSetFileSize (fio->handle, size); | 
					
						
							|  |  |  | 	#if defined(FIL_STANDARDL)
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ret != NO_ERROR) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(ret)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__DOS__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 	n = chsize (fio->handle, size); | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 	if (n <= -1) hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(vms) || defined(__vms)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	unsigned long r0; | 
					
						
							|  |  |  | 	struct RAB* rab = (struct RAB*)fio->handle; | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	if ((r0 = sys$rewind (rab, 0, 0)) != RMS$_NORMAL || | 
					
						
							|  |  |  | 	    (r0 = sys$truncate (rab, 0, 0)) != RMS$_NORMAL) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(r0)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(HAVE_FTRUNCATE)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 	n = HAWK_FTRUNCATE (fio->handle, size); | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 	if (n <= -1) hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	hawk_gem_seterrnum (fio->gem, HAWK_NULL, HAWK_ENOIMPL); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return -1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_ooi_t hawk_fio_read (hawk_fio_t* fio, void* buf, hawk_oow_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DWORD count; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	if (size > (HAWK_TYPE_MAX(hawk_ooi_t) & HAWK_TYPE_MAX(DWORD))) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		size = HAWK_TYPE_MAX(hawk_ooi_t) & HAWK_TYPE_MAX(DWORD); | 
					
						
							|  |  |  | 	if (ReadFile (fio->handle, buf, (DWORD)size, &count, HAWK_NULL) == FALSE) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		DWORD e = GetLastError(); | 
					
						
							|  |  |  | 		/* special case when ReadFile returns failure with ERROR_BROKEN_PIPE.
 | 
					
						
							|  |  |  | 		 * this happens when an anonymous pipe is a standard input for redirection. | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		 * assuming that ERROR_BROKEN_PIPE doesn't occur with normal | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		 * input streams, i treat the condition as a normal EOF indicator. */ | 
					
						
							|  |  |  | 		if ((fio->status & STATUS_WIN32_STDIN) && e == ERROR_BROKEN_PIPE) return 0; | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(e)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return (hawk_ooi_t)count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__OS2__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	APIRET ret; | 
					
						
							|  |  |  | 	ULONG count; | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	if (size > (HAWK_TYPE_MAX(hawk_ooi_t) & HAWK_TYPE_MAX(ULONG))) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		size = HAWK_TYPE_MAX(hawk_ooi_t) & HAWK_TYPE_MAX(ULONG); | 
					
						
							|  |  |  | 	ret = DosRead (fio->handle, buf, (ULONG)size, &count); | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	if (ret != NO_ERROR) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(ret)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return (hawk_ooi_t)count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__DOS__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int n; | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	if (size > (HAWK_TYPE_MAX(hawk_ooi_t) & HAWK_TYPE_MAX(unsigned int))) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		size = HAWK_TYPE_MAX(hawk_ooi_t) & HAWK_TYPE_MAX(unsigned int); | 
					
						
							|  |  |  | 	n = read (fio->handle, buf, size); | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 	if (n <= -1) hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(vms) || defined(__vms)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	unsigned long r0; | 
					
						
							|  |  |  | 	struct RAB* rab = (struct RAB*)fio->handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (size > 32767) size = 32767; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rab->rab$l_ubf = buf; | 
					
						
							|  |  |  | 	rab->rab$w_usz = size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r0 = sys$get (rab, 0, 0); | 
					
						
							|  |  |  | 	if (r0 != RMS$_NORMAL) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(r0)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return rab->rab$w_rsz; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hawk_ooi_t n; | 
					
						
							|  |  |  | 	if (size > HAWK_TYPE_MAX(hawk_ooi_t)) size = HAWK_TYPE_MAX(hawk_ooi_t); | 
					
						
							|  |  |  | 	n = HAWK_READ (fio->handle, buf, size); | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 	if (n <= -1) hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return n; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_ooi_t hawk_fio_write (hawk_fio_t* fio, const void* data, hawk_oow_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DWORD count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    	if (fio->status & STATUS_APPEND) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | /* TODO: only when FILE_APPEND_DATA failed???  how do i know this??? */ | 
					
						
							|  |  |  | 		/* i do this on a best-effort basis */ | 
					
						
							|  |  |  | 	#if defined(_WIN64)
 | 
					
						
							|  |  |  | 		LARGE_INTEGER x; | 
					
						
							|  |  |  | 		x.QuadPart = 0; | 
					
						
							|  |  |  |     		SetFilePointerEx (fio->handle, x, HAWK_NULL, FILE_END); | 
					
						
							|  |  |  | 	#else
 | 
					
						
							|  |  |  |     		SetFilePointer (fio->handle, 0, HAWK_NULL, FILE_END); | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  |     	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	if (size > (HAWK_TYPE_MAX(hawk_ooi_t) & HAWK_TYPE_MAX(DWORD))) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		size = HAWK_TYPE_MAX(hawk_ooi_t) & HAWK_TYPE_MAX(DWORD); | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	if (WriteFile (fio->handle, data, (DWORD)size, &count, HAWK_NULL) == FALSE) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(GetLastError())); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return (hawk_ooi_t)count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__OS2__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	APIRET ret; | 
					
						
							|  |  |  | 	ULONG count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    	if (fio->status & STATUS_APPEND) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* i do this on a best-effort basis */ | 
					
						
							|  |  |  | 	#if defined(FIL_STANDARDL)
 | 
					
						
							|  |  |  | 		if (dos_set_file_ptr_l) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			LONGLONG pos, newpos; | 
					
						
							|  |  |  | 			pos.ulLo = (ULONG)0; | 
					
						
							|  |  |  | 			pos.ulHi = (ULONG)0; | 
					
						
							|  |  |  |     			dos_set_file_ptr_l (fio->handle, pos, FILE_END, &newpos); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 			ULONG newpos; | 
					
						
							|  |  |  |     			DosSetFilePtr (fio->handle, 0, FILE_END, &newpos); | 
					
						
							|  |  |  | 	#if defined(FIL_STANDARDL)
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  |     	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	if (size > (HAWK_TYPE_MAX(hawk_ooi_t) & HAWK_TYPE_MAX(ULONG))) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		size = HAWK_TYPE_MAX(hawk_ooi_t) & HAWK_TYPE_MAX(ULONG); | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	ret = DosWrite(fio->handle, | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		(PVOID)data, (ULONG)size, &count); | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	if (ret != NO_ERROR) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(ret)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return (hawk_ooi_t)count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__DOS__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int n; | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	if (size > (HAWK_TYPE_MAX(hawk_ooi_t) & HAWK_TYPE_MAX(unsigned int))) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		size = HAWK_TYPE_MAX(hawk_ooi_t) & HAWK_TYPE_MAX(unsigned int); | 
					
						
							|  |  |  | 	n = write (fio->handle, data, size); | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 	if (n <= -1) hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(vms) || defined(__vms)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	unsigned long r0; | 
					
						
							|  |  |  | 	struct RAB* rab = (struct RAB*)fio->handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (size > 32767) size = 32767; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rab->rab$l_rbf = (char*)data; | 
					
						
							|  |  |  | 	rab->rab$w_rsz = size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r0 = sys$put (rab, 0, 0); | 
					
						
							|  |  |  | 	if (r0 != RMS$_NORMAL) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(r0)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return rab->rab$w_rsz; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hawk_ooi_t n; | 
					
						
							|  |  |  | 	if (size > HAWK_TYPE_MAX(hawk_ooi_t)) size = HAWK_TYPE_MAX(hawk_ooi_t); | 
					
						
							|  |  |  | 	n = HAWK_WRITE (fio->handle, data, size); | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 	if (n <= -1) hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return n; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int get_devname_from_handle ( | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	hawk_fio_t* fio, hawk_ooch_t* buf, hawk_oow_t len) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	HANDLE map = NULL; | 
					
						
							|  |  |  | 	void* mem = NULL; | 
					
						
							|  |  |  | 	DWORD olen; | 
					
						
							|  |  |  | 	HINSTANCE psapi; | 
					
						
							|  |  |  | 	getmappedfilename_t getmappedfilename; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	/* try to load psapi.dll dynamially for
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	 * systems without it. direct linking to the library | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	 * may end up with dependency failure on such systems. | 
					
						
							|  |  |  | 	 * this way, the worst case is that this function simply | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	 * fails. */ | 
					
						
							|  |  |  | 	psapi = LoadLibrary (HAWK_T("PSAPI.DLL")); | 
					
						
							|  |  |  | 	if (!psapi) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(GetLastError())); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	getmappedfilename = (getmappedfilename_t) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		GetProcAddress (psapi, HAWK_BT("GetMappedFileName")); | 
					
						
							|  |  |  | 	if (!getmappedfilename) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(GetLastError())); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		FreeLibrary (psapi); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* create a file mapping object */ | 
					
						
							|  |  |  | 	map = CreateFileMapping ( | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		fio->handle, | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		NULL, | 
					
						
							|  |  |  | 		PAGE_READONLY, | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		0, | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		1, | 
					
						
							|  |  |  | 		NULL | 
					
						
							|  |  |  | 	); | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	if (map == NULL) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(GetLastError())); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		FreeLibrary (psapi); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* create a file mapping to get the file name. */ | 
					
						
							|  |  |  | 	mem = MapViewOfFile (map, FILE_MAP_READ, 0, 0, 1); | 
					
						
							|  |  |  | 	if (mem == NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(GetLastError())); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		CloseHandle (map); | 
					
						
							|  |  |  | 		FreeLibrary (psapi); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	olen = getmappedfilename (GetCurrentProcess(), mem, buf, len); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	if (olen == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(GetLastError())); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		UnmapViewOfFile (mem); | 
					
						
							|  |  |  | 		CloseHandle (map); | 
					
						
							|  |  |  | 		FreeLibrary (psapi); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	UnmapViewOfFile (mem); | 
					
						
							|  |  |  | 	CloseHandle (map); | 
					
						
							|  |  |  | 	FreeLibrary (psapi); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | static int get_volname_from_handle (hawk_fio_t* fio, hawk_ooch_t* buf, hawk_oow_t len) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (get_devname_from_handle (fio, buf, len) == -1) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-18 08:16:34 +00:00
										 |  |  | 	if (hawk_comp_oocstr_limited(buf, HAWK_T("\\Device\\LanmanRedirector\\"), 25, 1) == 0) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		/*buf[0] = HAWK_T('\\');*/ | 
					
						
							| 
									
										
										
										
											2019-12-18 08:16:34 +00:00
										 |  |  | 		hawk_copy_oocstr_unlimited (&buf[1], &buf[24]); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		DWORD n; | 
					
						
							|  |  |  | 		hawk_ooch_t drives[128]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-18 08:16:34 +00:00
										 |  |  | 		n = GetLogicalDriveStrings(HAWK_COUNTOF(drives), drives); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (n == 0 /* error */ || | 
					
						
							|  |  |  | 		    n > HAWK_COUNTOF(drives) /* buffer small */) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 			hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(GetLastError())); | 
					
						
							| 
									
										
										
										
											2019-12-18 08:16:34 +00:00
										 |  |  | 			return -1; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		while (n > 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hawk_ooch_t drv[3]; | 
					
						
							|  |  |  | 			hawk_ooch_t path[MAX_PATH]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			drv[0] = drives[--n]; | 
					
						
							|  |  |  | 			drv[1] = HAWK_T(':'); | 
					
						
							|  |  |  | 			drv[2] = HAWK_T('\0'); | 
					
						
							|  |  |  | 			if (QueryDosDevice (drv, path, HAWK_COUNTOF(path))) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-12-18 08:16:34 +00:00
										 |  |  | 				hawk_oow_t pl = hawk_count_oocstr(path); | 
					
						
							|  |  |  | 				hawk_oow_t bl = hawk_count_oocstr(buf); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 				if (bl > pl && buf[pl] == HAWK_T('\\') && | 
					
						
							| 
									
										
										
										
											2019-12-18 08:16:34 +00:00
										 |  |  | 				    hawk_comp_oochars(buf, pl, path, pl, 1) == 0) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 				{ | 
					
						
							|  |  |  | 					buf[0] = drv[0]; | 
					
						
							|  |  |  | 					buf[1] = HAWK_T(':'); | 
					
						
							| 
									
										
										
										
											2019-12-18 08:16:34 +00:00
										 |  |  | 					hawk_copy_oocstr_unlimited (&buf[2], &buf[pl]); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	/* if the match is not found, the device name is returned
 | 
					
						
							|  |  |  | 	 * without translation */ | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int hawk_fio_chmod (hawk_fio_t* fio, int mode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int flags = FILE_ATTRIBUTE_NORMAL; | 
					
						
							|  |  |  | 	hawk_ooch_t name[MAX_PATH]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* it is a best effort implementation. if the file size is 0,
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	 * it can't even get the file name from the handle and thus fails. | 
					
						
							|  |  |  | 	 * if GENERIC_READ is not set in CreateFile, CreateFileMapping fails. | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	 * so if this fio is opened without HAWK_FIO_READ, this function fails. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (get_volname_from_handle (fio, name, HAWK_COUNTOF(name)) == -1) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!(mode & HAWK_FIO_WUSR)) flags = FILE_ATTRIBUTE_READONLY; | 
					
						
							|  |  |  | 	if (SetFileAttributes (name, flags) == FALSE) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(GetLastError())); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__OS2__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	APIRET n; | 
					
						
							|  |  |  | 	int flags = FILE_NORMAL; | 
					
						
							|  |  |  | 	#if defined(FIL_STANDARDL)
 | 
					
						
							|  |  |  | 	FILESTATUS3L stat; | 
					
						
							|  |  |  | 	#else
 | 
					
						
							|  |  |  | 	FILESTATUS3 stat; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 	ULONG size = HAWK_SIZEOF(stat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(FIL_STANDARDL)
 | 
					
						
							|  |  |  | 	n = DosQueryFileInfo (fio->handle, FIL_STANDARDL, &stat, size); | 
					
						
							|  |  |  | 	#else
 | 
					
						
							|  |  |  | 	n = DosQueryFileInfo (fio->handle, FIL_STANDARD, &stat, size); | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 	if (n != NO_ERROR) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(n)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!(mode & HAWK_FIO_WUSR)) flags = FILE_READONLY; | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	stat.attrFile = flags; | 
					
						
							|  |  |  | 	#if defined(FIL_STANDARDL)
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	n = DosSetFileInfo(fio->handle, FIL_STANDARDL, &stat, size); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	#else
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	n = DosSetFileInfo(fio->handle, FIL_STANDARD, &stat, size); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	#endif
 | 
					
						
							|  |  |  | 	if (n != NO_ERROR) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(n)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__DOS__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int permission = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (mode & HAWK_FIO_RUSR) permission |= S_IREAD; | 
					
						
							|  |  |  | 	if (mode & HAWK_FIO_WUSR) permission |= S_IWRITE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO: fchmod not available. find a way to do this
 | 
					
						
							|  |  |  | 	return fchmod (fio->handle, permission); */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	hawk_gem_seterrnum (fio->gem, HAWK_NULL, HAWK_ENOIMPL); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(vms) || defined(__vms)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO: */ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	hawk_gem_seterrnum (fio->gem, HAWK_NULL, HAWK_ENOIMPL); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return (hawk_fio_off_t)-1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(HAVE_FCHMOD)
 | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 	n = HAWK_FCHMOD (fio->handle, mode); | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 	if (n <= -1) hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	hawk_gem_seterrnum (fio->gem, HAWK_NULL, HAWK_ENOIMPL); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int hawk_fio_sync (hawk_fio_t* fio) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (FlushFileBuffers (fio->handle) == FALSE) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(GetLastError())); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__OS2__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	APIRET n; | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	n = DosResetBuffer (fio->handle); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	if (n != NO_ERROR) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 		hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(n)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__DOS__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 	n = fsync (fio->handle); | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 	if (n <= -1) hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(vms) || defined(__vms)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO: */ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	hawk_gem_seterrnum (fio->gem, HAWK_NULL, HAWK_ENOIMPL); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return (hawk_fio_off_t)-1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(HAVE_FSYNC)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int n; | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	n = HAWK_FSYNC(fio->handle); | 
					
						
							| 
									
										
										
										
											2020-01-01 05:20:28 +00:00
										 |  |  | 	if (n <= -1) hawk_gem_seterrnum (fio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return n; | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	hawk_gem_seterrnum (fio->gem, HAWK_NULL, HAWK_ENOIMPL); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return -1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int hawk_fio_lock (hawk_fio_t* fio, hawk_fio_lck_t* lck, int flags) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	/* TODO: hawk_fio_lock
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	 * struct flock fl; | 
					
						
							|  |  |  | 	 * fl.l_type = F_RDLCK, F_WRLCK; | 
					
						
							|  |  |  | 	 * HAWK_FCNTL (fio->handle, F_SETLK, &fl); | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	hawk_gem_seterrnum (fio->gem, HAWK_NULL, HAWK_ENOIMPL); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int hawk_fio_unlock (hawk_fio_t* fio, hawk_fio_lck_t* lck, int flags) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	/* TODO: hawk_fio_unlock
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	 * struct flock fl; | 
					
						
							|  |  |  | 	 * fl.l_type = F_UNLCK; | 
					
						
							|  |  |  | 	 * HAWK_FCNTL (fio->handle, F_SETLK, &fl); | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2019-12-17 08:53:33 +00:00
										 |  |  | 	hawk_gem_seterrnum (fio->gem, HAWK_NULL, HAWK_ENOIMPL); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int hawk_get_std_fio_handle (hawk_fio_std_t std, hawk_fio_hnd_t* hnd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 	static DWORD tab[] = | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		STD_INPUT_HANDLE, | 
					
						
							|  |  |  | 		STD_OUTPUT_HANDLE, | 
					
						
							|  |  |  | 		STD_ERROR_HANDLE | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | #elif defined(vms) || defined(__vms)
 | 
					
						
							|  |  |  | 	/* TODO */ | 
					
						
							|  |  |  | 	static int tab[] = { 0, 1, 2 }; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	static hawk_fio_hnd_t tab[] = | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | #if defined(__OS2__)
 | 
					
						
							|  |  |  | 		(HFILE)0, (HFILE)1, (HFILE)2 | 
					
						
							|  |  |  | #elif defined(__DOS__)
 | 
					
						
							|  |  |  | 		0, 1, 2 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 		0, 1, 2 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (std < 0 || std >= HAWK_COUNTOF(tab)) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HANDLE tmp = GetStdHandle(tab[std]); | 
					
						
							|  |  |  | 		if (tmp == INVALID_HANDLE_VALUE) return -1; | 
					
						
							|  |  |  | 		*hnd = tmp; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #elif defined(vms) || defined(__vms)
 | 
					
						
							|  |  |  | 	/* TODO: */ | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	*hnd = tab[std]; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } |