summaryrefslogtreecommitdiffstats
path: root/private/crt32/lowio/osfinfo.c
blob: 8ccff39c498fbfe878cc4b18cb8840bd0ee40324 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
/***
*osfinfo.c - Win32 _osfhnd[] support routines
*
*	Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
*	Defines the internally used routine _alloc_osfhnd()
*	and the user visible routine _get_osfhandle().
*
*Revision History:
*	11-16-90  GJF	What can I say? The custom heap business was getting
*			a little slow...
*	12-03-90  GJF	Fixed my stupid syntax errors.
*       12-06-90  SRW   Changed to use _osfile and _osfhnd instead of _osfinfo
*       12-28-90  SRW   Added cast of void * to char * for Mips C Compiler
*       02-18-91  SRW   Fixed bug in _alloc_osfhnd with setting FOPEN bit
*                       (only caller should do that) [_WIN32_]
*       02-18-91  SRW   Fixed bug in _alloc_osfhnd with checking against
*                       _NFILE_ instead of _nfile [_WIN32_]
*       02-18-91  SRW   Added debug output to _alloc_osfhnd if out of
*                       file handles. [_WIN32_]
*       02-25-91  SRW   Renamed _get_free_osfhnd to be _alloc_osfhnd [_WIN32_]
*	02-25-91  SRW	Exposed _get_osfhandle and _open_osfhandle [_WIN32_]
*	08-08-91  GJF	Use ANSI-fied form of constant names.
*	11-25-91  GJF	Lock fh before checking whether it's free.
*	12-31-91  GJF	Improved multi-thread lock usage [_WIN32_].
*	02-13-92  GJF	Replaced _nfile with _nhandle
*	07-15-92  GJF	Fixed setting of flags in _open_osfhnd.
*	02-19-93  GJF	If GetFileType fails in _open_osfhandle, don't unlock
*			fh (it wasn't locked)!
*
*******************************************************************************/

#ifdef	_WIN32_

#include <cruntime.h>
#include <errno.h>
#include <internal.h>
#include <fcntl.h>
#include <msdos.h>
#include <os2dll.h>
#include <stdlib.h>
#include <oscalls.h>

/***
*int _alloc_osfhnd() - get free _osfhnd[] entry
*
*Purpose:
*	Finds the first free entry in _osfhnd[], mark it in use and return
*	the index of the entry to the caller.
*
*Entry:
*	none
*
*Exit:
*	returns index of entry in fh, if successful
*	return -1, if no free entry is found in _osfhnd[].
*
*	MULTITHREAD NOTE: IF SUCCESSFUL, THE HANDLE IS LOCKED WHEN IT IS
*	RETURNED TO THE CALLER!
*
*Exceptions:
*
*******************************************************************************/

int _CRTAPI1 _alloc_osfhnd(
	void
	)
{
	int fh; 		/* _osfhnd[] index */

	_mlock(_OSFHND_LOCK);	/* lock the _osfhnd[] table */

	/*
	 * search _osfhnd[] for an entry that is not currently being used.
	 * if one is found, mark it in use and set the _osfhandle field to
	 * INVALID_HANDLE_VALUE.
	 */
	for ( fh = 0 ; fh < _nhandle ; fh++ ) {
		if ( (_osfile[fh] & FOPEN) == 0 ) {
#ifdef MTHREAD
			_lock_fh(fh);

			/*
			 * make sure the entry is still free
			 */
			if ( (_osfile[fh] & FOPEN) != 0 ) {
				/*
				 * entry now in use! release the lock and
				 *  continue looping.
				 */
				_unlock_fh(fh);
				continue;
			}
#endif

			/*
			 * free entry found! initialize it and
			 * break out of the loop
			 */
			_osfhnd[fh] = (long)INVALID_HANDLE_VALUE;
			break;
		}
	}

	_munlock(_OSFHND_LOCK);	/* unlock the _osfhnd[] table */

#if defined(DEBUG) && defined(_WIN32_)
	if (fh >= _nhandle) {
	    DbgPrint( "WINCRT: more than %d open files\n", _nhandle );
            }
#endif

	/*
	 * return the index of the previously free table entry, if one was
	 * found. return -1 otherwise.
	 */
	return( (fh >= _nhandle) ? -1 : fh );
}


/***
*int _set_osfhnd(int fh) - set OS file handle table value
*
*Purpose:
*	If fh is in range and if _osfhnd[fh] is marked with
*	INVALID_HANDLE_VALUE then set _osfhnd[fh] to the passed value.
*
*Entry:
*	int fh -	index of _osfhnd[] entry
*       long fh     -   new value of this handle entry
*
*Exit:
*	Returns zero if successful.
*	Returns -1 and sets errno to EBADF otherwise.
*
*Exceptions:
*
*******************************************************************************/

int _CRTAPI1 _set_osfhnd (
	int fh,    	/* index into _osfhnd[] (user's file handle) */
        long value
	)
{
	if ( ((unsigned)fh < (unsigned)_nhandle) &&
	     (_osfhnd[fh] == (long)INVALID_HANDLE_VALUE)
           ) {
                switch (fh) {
                case 0: SetStdHandle( STD_INPUT_HANDLE, (HANDLE)value );  break;
                case 1: SetStdHandle( STD_OUTPUT_HANDLE, (HANDLE)value ); break;
                case 2: SetStdHandle( STD_ERROR_HANDLE, (HANDLE)value );  break;
                }

                _osfhnd[fh] = value;
		return(0);
	} else {
		errno = EBADF;		/* bad handle */
		_doserrno = 0L; 	/* not an OS error */
		return -1;
	}
}


/***
*int _free_osfhnd(int fh) - free OS file handle table entry
*
*Purpose:
*	If fh is in range and if _osfhnd[fh] is in use and NOT marked
*       with 0xfffffff
*
*Entry:
*	int fh -	index of _osfhnd[] entry
*
*Exit:
*	Returns zero if successful.
*	Returns -1 and sets errno to EBADF otherwise.
*
*Exceptions:
*
*******************************************************************************/

int _CRTAPI1 _free_osfhnd (
	int fh		/* index into _osfhnd[] (user's file handle) */
	)
{
	if ( ((unsigned)fh < (unsigned)_nhandle) &&
             (_osfile[fh] & FOPEN) &&
	     (_osfhnd[fh] != (long)INVALID_HANDLE_VALUE)
           ) {
                switch (fh) {
                case 0: SetStdHandle( STD_INPUT_HANDLE, NULL );  break;
                case 1: SetStdHandle( STD_OUTPUT_HANDLE, NULL ); break;
                case 2: SetStdHandle( STD_ERROR_HANDLE, NULL );  break;
                }

		_osfhnd[fh] = (long)INVALID_HANDLE_VALUE;
		return(0);
	} else {
		errno = EBADF;		/* bad handle */
		_doserrno = 0L; 	/* not an OS error */
		return -1;
	}
}


/***
*long _get_osfhandle(int fh) - get OS file handle
*
*Purpose:
*	If fh is in range and if _osfhnd[fh] is marked free, return
*	_osfhnd[fh]
*
*Entry:
*	int fh -	index of _osfhnd[] entry
*
*Exit:
*	Returns the OS file handle if successful.
*	Returns -1 and sets errno to EBADF otherwise.
*
*Exceptions:
*
*******************************************************************************/

long _CRTAPI1 _get_osfhandle (
	int fh		/* index into _osfhnd[] (user's file handle) */
	)
{
	if ( ((unsigned)fh < (unsigned)_nhandle) && (_osfile[fh] & FOPEN) )
		return(_osfhnd[fh]);
	else {
		errno = EBADF;		/* bad handle */
		_doserrno = 0L; 	/* not an OS error */
		return -1;
	}
}

/***
*int _open_osfhandle(long osfhandle, int flags) - open C Runtime file handle
*
*Purpose:
*	This function allocates a free C Runtime file handle and sets it
*	to point to the Win32 file handle specified by the first parameter.
*
*Entry:
*       long osfhandle -Win32 file handle to associate with C Runtime file handle.
*	int flags -     flags to associate with C Runtime file handle.
*
*Exit:
*	returns index of entry in fh, if successful
*	return -1, if no free entry is found in _osfhnd[].
*
*Exceptions:
*
*******************************************************************************/

int _CRTAPI1 _open_osfhandle(
        long osfhandle,
        int flags
        )
{
        int fh;
	char fileflags; 		/* _osfile flags */
	DWORD isdev;			/* device indicator in low byte */

	/* copy relevant flags from second parameter */

	fileflags = 0;

	if ( flags & _O_APPEND )
		fileflags |= FAPPEND;

	if ( flags & _O_TEXT )
                fileflags |= FTEXT;

	/* find out what type of file (file/device/pipe) */

        isdev = GetFileType((HANDLE)osfhandle);
        if (isdev == FILE_TYPE_UNKNOWN) {
		/* OS error */
		_dosmaperr( GetLastError() );	/* map error */
		return -1;
	}

	/* is isdev value to set flags */
	if (isdev == FILE_TYPE_CHAR)
		fileflags |= FDEV;
	else if (isdev == FILE_TYPE_PIPE)
		fileflags |= FPIPE;


        /* attempt to allocate a C Runtime file handle */

        if ( (fh = _alloc_osfhnd()) == -1 ) {
		errno = EMFILE; 	/* too many open files */
		_doserrno = 0L;         /* not an OS error */
                return -1;	        /* return error to caller */
        }

	/*
	 * the file is open. now, set the info in _osfhnd array
	 */

        _set_osfhnd(fh, osfhandle);

	fileflags |= FOPEN;		/* mark as open */

	_osfile[fh] = fileflags;	/* set osfile entry */

	_unlock_fh(fh); 		/* unlock handle */

	return fh;			/* return handle */
}

#else

#error ERROR - WIN32 TARGET ONLY!

#endif