1 /*
2 Low Level Interface Library
3
4 Copyright 1983-2008 Green Hills Software,Inc.
5
6 * This program is the property of Green Hills Software, Inc,
7 * its contents are proprietary information and no part of it
8 * is to be disclosed to anyone except employees of Green Hills
9 * Software, Inc., or as agreed in writing signed by the President
10 * of Green Hills Software, Inc.
11 */
12 /* ind_trnc.c: NON-ANSI truncate() facility. Provided for FORTRAN support. */
13
14 #include "indos.h"
15 #include "ind_io.h"
16
17 #if !defined(ANYBSD) && !defined(ANYSYSV4)
18
19 #if defined(__VXWORKS)
20
21 #include <stdio.h>
22 #include <string.h>
23
24 #else
25
26 #ifndef L_tmpnam
27 #define L_tmpnam 32
28 #endif
29
30
31 #ifdef TMPNAMPREFIX
32 # define L_TMPNAMEPREFIX 0
33 #elif defined(ANYUNIX)||defined(UNIXSYSCALLS)||defined(vms)||defined(__vms)
34 # define TMPNAMPREFIX "gh_"
35 # define L_TMPNAMEPREFIX 3
36 #else
37 # define TMPNAMPREFIX "T"
38 # define L_TMPNAMEPREFIX 1
39 #endif
40
41 /* access is better everywhere */
42 #define USE_ACCESS
43
44 #ifndef USE_ACESS
45 int stat(char *, struct stat *);
46 #endif
47
tmpnam(char * s)48 static char *tmpnam(char *s) {
49 /******************************************************************************/
50 /* This static tmpnam function is only needed for truncate, which is */
51 /* only needed if the Green Hills Fortran Library is being used. */
52 /* There is an exact copy of this function in the Green Hills C library. */
53 /******************************************************************************/
54 #pragma ghs nowarning 1908
55 static const char hexmap[32]="0123456789abcdefghijklmnopqrstuv";
56 #pragma ghs endnowarning
57 int cnt = 0;
58 int chan, u=17;
59 char *p, *q;
60 #ifdef TMPNAMPREFIX
61 /* if (sizeof(space) < (sizeof(TMPNAMPREFIX) + 8)) */
62 /* return NULL; */
63 #elif defined(ANYUNIX)||defined(UNIXSYSCALLS)||defined(vms)||defined(__vms)
64 #else
65 #endif
66 #if L_tmpnam < L_TMPNAMEPREFIX + 8
67 # error L_tmpnam too small
68 #endif
69 #if defined(ANYUNIX) || defined(UNIXSYSCALLS) || defined(MSW)
70 u = getpid();
71 #endif
72 /* if ( s==NULL ) */
73 /* s=space; */
74 for (p = s, q = TMPNAMPREFIX; *q; )
75 *p++ = *q++;
76 #if defined(ANYUNIX) || defined(UNIXSYSCALLS) || defined(MSW)
77 *p++ = hexmap[(u>>10) & 31];
78 *p++ = hexmap[(u>>5) & 31];
79 *p++ = hexmap[u & 31];
80 #endif
81 #ifndef USE_ACCESS
82 olderrno = __gh_get_errno(); /* access does not mess with errno */
83 #endif
84 do {
85 char *qq = p;
86 u = (++cnt & 0x0fffff);
87 do {
88 *qq++ = hexmap[u & 31];
89 u >>= 5;
90 } while (u);
91 *qq = '\0';
92 #ifdef USE_ACESS
93 chan = access(s, F_OK);
94 #else
95 {
96 struct stat st;
97 chan = stat(s, &st);
98 }
99 #endif
100 } while ( chan!=-1 );
101 #ifndef USE_ACCESS
102 __gh_set_errno(olderrno);
103 #endif
104 return(s);
105 }
106
107 #endif /* defined(__VXWORKS) */
108
109 /******************************************************************************/
110 /* The Green Hills C Library does not use the truncate function, it is only */
111 /* needed if the Green Hills Fortran Library is being used. */
112 /* */
113 /* int truncate(const char *path, int length); */
114 /* */
115 /* If the file named "path" is longer than "length" bytes it is truncated */
116 /* to "length" bytes. */
117 /* */
118 /* Return 0 if the named file is truncated or was previously less than */
119 /* length bytes. Return -1 if the file cannot be truncated, and set */
120 /* errno appropriately. */
121 /* */
122 /* REENTRANT */
123 /******************************************************************************/
124
125 #define _0777 0x1ff
126 #if defined(__VXWORKS)
127 #define __CREAT_ARG O_WRONLY
128 #else
129 #define __CREAT_ARG _0777
130 #endif
131
132 #define LBUFSIZ 1024
133
truncate(const char * path,long length)134 int truncate(const char *path, long length)
135 {
136 /*
137 The following implementation copies the first "length" bytes of the file
138 named "path" to a temporary file, then it creates a new file with
139 the name "path" and copies the temporary file back into it. At the end
140 the temporary file is deleted. The prefered implementation is to shorten
141 the file without copying, but many operating systems lack such an operation.
142 */
143 char buf[LBUFSIZ];
144 char namebuff[L_tmpnam];
145 int inf, of;
146 int count = 0;
147 char *tmpname = tmpnam(namebuff);
148
149 /* handle the two trivial cases efficiently:
150 length is 0 and length is greater than or equal to actual size of file
151 */
152 if (length == 0) {
153 if ((of = creat(path, __CREAT_ARG)) == -1)
154 return -1;
155 close(of);
156 return 0;
157 }
158
159 #if !defined(CROSSUNIX) && \
160 (defined(ANYUNIX)||defined(UNIXSYSCALLS)||defined(MSW)||defined(__VXWORKS))
161 {
162 struct stat stat1;
163 if (stat((char *)path, &stat1) < 0)
164 return -1;
165
166 if (stat1.st_size != (unsigned long)-1 && length >= stat1.st_size)
167 return 0;
168 }
169 #endif
170
171 if ((inf = open(path, 0, 0)) == -1 || (of = creat(tmpname, __CREAT_ARG)) == -1)
172 {
173 if (inf != -1)
174 close(inf);
175 return(-1);
176 }
177 while (length > 0 && (count = read(inf, buf, LBUFSIZ)) > 0) {
178 if (count > length)
179 count = length;
180 if (count > write(of, buf, count)) {
181 count = -1;
182 break;
183 }
184 length -= count;
185 }
186 close(inf);
187 close(of);
188
189 if (length == 0 && count >= 0) {
190
191 if (rename(tmpname, path) == 0) {
192 return(0);
193 }
194 #if defined(vms) || defined(__vms)
195 delete(path);
196 #elif defined (__VXWORKS)
197 {
198 char *tmp_path = malloc (strlen(path) + 1);
199 if (tmp_path == NULL)
200 return -1;
201 strcpy (tmp_path, path);
202 unlink(tmp_path);
203 free (tmp_path);
204 }
205 #else
206 unlink(path);
207 #endif
208 if (rename(tmpname, path) == 0) {
209 return(0);
210 }
211
212 if ((inf = open(tmpname, 0, 0)) == -1 || (of = creat(path, _0777)) == -1)
213 {
214 if (inf != -1)
215 close(inf);
216 return(-1);
217 }
218 while ((count = read(inf, buf, LBUFSIZ)) > 0)
219 if (count > write(of, buf, count)) {
220 count = -1;
221 break;
222 }
223 close(inf);
224 close(of);
225 }
226 #if defined(vms) || defined(__vms)
227 delete(tmpname);
228 #else
229 unlink(tmpname);
230 #endif
231 return(count);
232 }
233
234 #else
235
236 int _M_empty_file_illegal;
237
238 #endif /* ! ANYBSD */
239