summaryrefslogtreecommitdiffstats
path: root/private/crt32/lowio/chsize.c
blob: d25278023c070cb9aa297de5e47fa23de01b71af (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
/***
*chsize.c - OS/2 change size of a file
*
*	Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
*
*Purpose:
*	contains the _chsize() function - changes the size of a file.
*
*Revision History:
*	03-13-84  RN	initial version
*	05-17-86  SKS	ported to OS/2
*	07-07-87  JCR	Added (_doserrno == 5) check that is in DOS 3.2 version
*	10-29-87  JCR	Multi-thread support; also, re-wrote for efficiency
*	12-11-87  JCR	Added "_LOAD_DS" to declaration
*	05-25-88  PHG	Merged DLL and normal versions
*	10-03-88  GJF	Changed DOSNEWSIZE to SYSNEWSIZE
*	10-10-88  GJF	Made API names match DOSCALLS.H
*	04-13-89  JCR	New syscall interface
*	05-25-89  JCR	386 OS/2 calls use '_syscall' calling convention
*	03-12-90  GJF	Replaced _LOAD_DS with _CALLTYPE1, added #include
*			<cruntime.h>, removed #include <register.h> and fixed
*			the copyright. Also, cleaned up the formatting a bit.
*	04-04-90  GJF	Added #include <string.h>, removed #include <dos.h>.
*	05-21-90  GJF	Fixed stack checking pragma syntax.
*	07-24-90  SBM	Replaced <assertm.h> by <assert.h>, removed '32'
*			from API names
*	09-28-90  GJF	New-style function declarator.
*	12-03-90  GJF	Appended Win32 version of the function. It is based
*			on the Cruiser version and probably could be merged
*			in later (much later).
*	12-04-90  SRW	Changed to include <oscalls.h> instead of <doscalls.h>
*	12-06-90  SRW	Changed to use _osfile and _osfhnd instead of _osfinfo
*	12-28-90  SRW	Added _CRUISER_ conditional around check_stack pragma
*	01-16-91  GJF	ANSI naming. Also, fixed _chsize_lk parameter decls.
*       02-07-91  SRW   Changed to call _get_osfhandle [_WIN32_]
*	04-09-91  PNT	Added _MAC_ conditional
*	02-13-92  GJF	Replaced _nfile by _nhandle for Win32.
*	05-01-92  GJF	Fixed embarrassing bug (didn't work for Win32)!
*
*******************************************************************************/

#include <cruntime.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <fcntl.h>
#include <msdos.h>
#include <io.h>
#include <string.h>
#include <oscalls.h>
#include <internal.h>
#include <os2dll.h>

#ifdef	_CRUISER_
#pragma check_stack(on) 	/* turn stack probes on */
#endif  /* ndef _CRUISER_ */

/***
*int _chsize(filedes, size) - change size of a file
*
*Purpose:
*	Change file size. Assume file is open for writing, or we can't do it.
*	The DOS way to do this is to go to the right spot and write 0 bytes. The
*	Xenix way to do this is to make a system call. We write '\0' bytes because
*	DOS won't do this for you if you lseek beyond eof, though Xenix will.
*
*Entry:
*	int filedes - file handle to change size of
*	long size - new size of file
*
*Exit:
*	return 0 if successful
*	returns -1 and sets errno if fails
*
*Exceptions:
*
*******************************************************************************/

#ifdef MTHREAD

/* define normal version that locks/unlocks, validates fh */

int _CALLTYPE1 _chsize (
	REG1 int filedes,
	long size
	)
{
	int r;				/* return value */

#ifdef	_WIN32_
	if ( (unsigned)filedes >= (unsigned)_nhandle ) {
#else
	if (filedes < 0 || filedes >= _nfile) {
#endif
		errno = EBADF;
		return(-1);
	}
	_lock_fh(filedes);
        r = _chsize_lk(filedes,size);
	_unlock_fh(filedes);

        return r;
}

/* now define version that doesn't lock/unlock, validate fh */
int _CALLTYPE1 _chsize_lk (
	REG1 int filedes,
	long size
	)
{
	long filend;
	long extend;
	long place;
	int cnt;
	char blanks[BUFSIZ];
	REG2 char *bl = blanks;
	int oldmode;
	int retval = 0;	/* assume good return */

#else

/* now define normal version */

int _CALLTYPE1 _chsize (
	REG1 int filedes,
	long size
	)
{
	long filend;
	long extend;
	long place;
	int cnt;
	char blanks[BUFSIZ];
	REG2 char *bl = blanks;
	int oldmode;
	int retval = 0;	/* assume good return */

#ifdef	_WIN32_
	if ( (unsigned)filedes >= (unsigned)_nhandle ) {
#else
	if (filedes < 0 || filedes >= _nfile) {
#endif
		errno = EBADF;
		return(-1);
	}

#endif
	assert(size >= 0);

	/* Get current file position and seek to end */
	if ( ((place = _lseek_lk(filedes, 0L, SEEK_CUR)) == -1L) ||
	    ((filend = _lseek_lk(filedes, 0L, SEEK_END)) == -1L) )
		return -1;

	extend = size - filend;

	/* Grow or shrink the file as necessary */

	if (extend > 0L) {

		/* extending the file */

		memset(bl, '\0', BUFSIZ);
		oldmode = _setmode_lk(filedes, _O_BINARY);

		/* pad out with nulls */
		do  {
			cnt = (extend >= (long)BUFSIZ ) ? BUFSIZ : (int)extend;
			if ( ( cnt = _write_lk( filedes, bl, (extend >=
			(long)BUFSIZ ) ? BUFSIZ : (int)extend)) == -1 ) {
				/* Error on write */
				if (_doserrno == ERROR_ACCESS_DENIED)
					errno = EACCES;
				retval = cnt;
				break;	/* leave write loop */
			}
		}
		while ((extend -= (long)cnt) > 0L);

		_setmode_lk(filedes, oldmode);
		/* retval set correctly */
	}

	else  if (extend < 0L) {
		/* shortening the file */
#ifdef	_CRUISER_

		retval = ( DOSSETFILESIZE(filedes, size) ? -1 : 0 );

#else	/* ndef _CRUISER_ */

#ifdef	_WIN32_
		/*
		 * Set file pointer to new eof...and truncate it there.
		 */
		_lseek_lk(filedes, size, SEEK_SET);

		if ( (retval = SetEndOfFile((HANDLE)_get_osfhandle(filedes)) ?
		    0 : -1) == -1 ) {
			errno = EACCES;
			_doserrno = GetLastError();
		}

#else	/* ndef _WIN32_ */

#ifdef	_MAC_

	TBD();

#else	/* ndef _MAC_ */

#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!

#endif	/* _MAC_ */

#endif	/* _WIN32_ */

#endif	/* _CRUISER_ */
	}

	/* else */
	/* no file change needed */
	/* retval = 0; */


/* Common return code */

	_lseek_lk(filedes, place, SEEK_SET);
	return retval;
}