0
|
1 module dmd.File;
|
|
2
|
|
3 import dmd.FileName;
|
|
4 import dmd.Array;
|
|
5 import dmd.Util;
|
|
6
|
|
7 import core.stdc.stdlib;
|
|
8 import core.sys.windows.windows;
|
|
9
|
|
10 import std.string : toStringz;
|
|
11
|
4
|
12 import core.memory;
|
2
|
13
|
0
|
14 class File
|
|
15 {
|
|
16 int ref_; // != 0 if this is a reference to someone else's buffer
|
|
17 ubyte* buffer; // data for our file
|
|
18 uint len; // amount of data in buffer[]
|
|
19 void* touchtime; // system time to use for file
|
|
20
|
|
21 FileName name; // name of our file
|
|
22
|
|
23 this(string n)
|
|
24 {
|
|
25 name = new FileName(n);
|
|
26 }
|
|
27
|
|
28 this(FileName n)
|
|
29 {
|
|
30 name = n;
|
|
31 }
|
|
32
|
|
33 ~this()
|
|
34 {
|
|
35 if (buffer !is null) {
|
|
36 if (ref_ == 0) {
|
2
|
37 ///free(buffer);
|
0
|
38 } else {
|
|
39 version (_WIN32) {
|
|
40 if (ref_ == 2) {
|
|
41 UnmapViewOfFile(buffer);
|
|
42 }
|
|
43 }
|
|
44 }
|
|
45 }
|
|
46
|
|
47 if (touchtime !is null) {
|
2
|
48 ///free(touchtime);
|
0
|
49 }
|
|
50 }
|
|
51
|
|
52 void mark()
|
|
53 {
|
|
54 ///mem.mark(buffer);
|
|
55 ///mem.mark(touchtime);
|
|
56 ///mem.mark(name);
|
|
57 }
|
|
58
|
|
59 string toChars()
|
|
60 {
|
|
61 return name.toChars();
|
|
62 }
|
|
63
|
|
64 /* Read file, return !=0 if error
|
|
65 */
|
|
66
|
|
67 int read()
|
|
68 {
|
|
69 version (POSIX) {
|
|
70 int result = 0;
|
|
71
|
|
72 string name = this.name.toChars();
|
|
73
|
|
74 //printf("File::read('%s')\n",name);
|
|
75 int fd = open(name, O_RDONLY);
|
|
76 if (fd == -1) {
|
|
77 result = errno;
|
|
78 //printf("\topen error, errno = %d\n", errno);
|
|
79 goto err1;
|
|
80 }
|
|
81
|
|
82 if (ref_ == 0) {
|
2
|
83 ///free(buffer);
|
0
|
84 }
|
|
85
|
|
86 ref_ = 0; // we own the buffer now
|
|
87
|
|
88 //printf("\tfile opened\n");
|
|
89 stat buf;
|
|
90 if (fstat(fd, &buf)) {
|
|
91 printf("\tfstat error, errno = %d\n", errno);
|
|
92 goto err2;
|
|
93 }
|
|
94
|
|
95 off_t size = buf.st_size;
|
2
|
96 buffer = cast(ubyte*)GC.malloc(size + 2);
|
0
|
97 if (buffer is null) {
|
|
98 printf("\tmalloc error, errno = %d\n", errno);
|
|
99 goto err2;
|
|
100 }
|
|
101
|
|
102 ssize_t numread = .read(fd, buffer, size);
|
|
103 if (numread != size) {
|
|
104 printf("\tread error, errno = %d\n",errno);
|
|
105 goto err2;
|
|
106 }
|
|
107
|
|
108 if (touchtime !is null) {
|
|
109 memcpy(touchtime, &buf, buf.sizeof);
|
|
110 }
|
|
111
|
|
112 if (close(fd) == -1) {
|
|
113 printf("\tclose error, errno = %d\n",errno);
|
|
114 goto err;
|
|
115 }
|
|
116
|
|
117 len = size;
|
|
118
|
|
119 // Always store a wchar ^Z past end of buffer so scanner has a sentinel
|
|
120 buffer[size] = 0; // ^Z is obsolete, use 0
|
|
121 buffer[size + 1] = 0;
|
|
122
|
|
123 return 0;
|
|
124
|
|
125 err2:
|
|
126 close(fd);
|
|
127
|
|
128 err:
|
2
|
129 ///free(buffer);
|
0
|
130 buffer = null;
|
|
131 len = 0;
|
|
132
|
|
133 err1:
|
|
134 result = 1;
|
|
135 return result;
|
|
136 } else version (_WIN32) {
|
|
137 DWORD size;
|
|
138 DWORD numread;
|
|
139 HANDLE h;
|
|
140 int result = 0;
|
|
141
|
|
142 string name = this.name.toChars();
|
|
143 //std.stdio.writeln("Open file ", name);
|
|
144
|
|
145 h = CreateFileA(toStringz(name), GENERIC_READ, FILE_SHARE_READ, null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, HANDLE.init);
|
|
146 if (h == INVALID_HANDLE_VALUE) {
|
|
147 goto err1;
|
|
148 }
|
|
149
|
|
150 if (!ref_) {
|
2
|
151 ///free(buffer);
|
0
|
152 }
|
|
153 ref_ = 0;
|
|
154
|
|
155 size = GetFileSize(h, null);
|
2
|
156 buffer = cast(ubyte*) GC.malloc(size + 2);
|
0
|
157 if (!buffer)
|
|
158 goto err2;
|
|
159
|
|
160 if (ReadFile(h, buffer, size, &numread, null) != TRUE)
|
|
161 goto err2;
|
|
162
|
|
163 if (numread != size)
|
|
164 goto err2;
|
|
165
|
|
166 if (touchtime) {
|
|
167 if (!GetFileTime(h, null, null, &(cast(WIN32_FIND_DATA*)touchtime).ftLastWriteTime))
|
|
168 goto err2;
|
|
169 }
|
|
170
|
|
171 if (!CloseHandle(h))
|
|
172 goto err;
|
|
173
|
|
174 len = size;
|
|
175
|
|
176 // Always store a wchar ^Z past end of buffer so scanner has a sentinel
|
|
177 buffer[size] = 0; // ^Z is obsolete, use 0
|
|
178 buffer[size + 1] = 0;
|
|
179 return 0;
|
|
180
|
|
181 err2:
|
|
182 CloseHandle(h);
|
|
183 err:
|
2
|
184 ///free(buffer);
|
0
|
185 buffer = null;
|
|
186 len = 0;
|
|
187
|
|
188 err1:
|
|
189 result = 1;
|
|
190 return result;
|
|
191 } else {
|
|
192 static assert(0);
|
|
193 }
|
|
194 }
|
|
195
|
|
196 /* Write file, either succeed or fail
|
|
197 * with error message & exit.
|
|
198 */
|
|
199
|
|
200 void readv()
|
|
201 {
|
|
202 if (read())
|
|
203 error("Error reading file '%s'\n",name.toChars());
|
|
204 }
|
|
205
|
|
206 /* Read file, return !=0 if error
|
|
207 */
|
|
208
|
|
209 int mmread()
|
|
210 {
|
|
211 assert(false);
|
|
212 }
|
|
213
|
|
214 /* Write file, either succeed or fail
|
|
215 * with error message & exit.
|
|
216 */
|
|
217
|
|
218 void mmreadv()
|
|
219 {
|
|
220 assert(false);
|
|
221 }
|
|
222
|
|
223 /* Write file, return !=0 if error
|
|
224 */
|
|
225
|
|
226 /*********************************************
|
|
227 * Write a file.
|
|
228 * Returns:
|
|
229 * 0 success
|
|
230 */
|
|
231 int write()
|
|
232 {
|
|
233 version (POSIX) {
|
|
234 assert(false);
|
|
235 /+
|
|
236 int fd;
|
|
237 ssize_t numwritten;
|
|
238 char *name;
|
|
239
|
|
240 name = this->name->toChars();
|
|
241 fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 0644);
|
|
242 if (fd == -1)
|
|
243 goto err;
|
|
244
|
|
245 numwritten = ::write(fd, buffer, len);
|
|
246 if (len != numwritten)
|
|
247 goto err2;
|
|
248
|
|
249 if (close(fd) == -1)
|
|
250 goto err;
|
|
251
|
|
252 if (touchtime)
|
|
253 { struct utimbuf ubuf;
|
|
254
|
|
255 ubuf.actime = ((struct stat *)touchtime)->st_atime;
|
|
256 ubuf.modtime = ((struct stat *)touchtime)->st_mtime;
|
|
257 if (utime(name, &ubuf))
|
|
258 goto err;
|
|
259 }
|
|
260 return 0;
|
|
261
|
|
262 err2:
|
|
263 close(fd);
|
|
264 ::remove(name);
|
|
265 err:
|
|
266 return 1;
|
|
267 +/
|
|
268 } else version (_WIN32) {
|
|
269 HANDLE h;
|
|
270 DWORD numwritten;
|
|
271
|
|
272 const(char)* name = toStringz(this.name.toChars());
|
|
273 h = CreateFileA(name, GENERIC_WRITE, 0, null, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, null);
|
|
274 if (h == INVALID_HANDLE_VALUE)
|
|
275 goto err;
|
|
276
|
|
277 if (WriteFile(h, buffer, len, &numwritten, null) != TRUE)
|
|
278 goto err2;
|
|
279
|
|
280 if (len != numwritten)
|
|
281 goto err2;
|
|
282
|
|
283 if (touchtime) {
|
|
284 SetFileTime(h, null, null, &(cast(WIN32_FIND_DATA*)touchtime).ftLastWriteTime);
|
|
285 }
|
|
286 if (!CloseHandle(h))
|
|
287 goto err;
|
|
288 return 0;
|
|
289
|
|
290 err2:
|
|
291 CloseHandle(h);
|
|
292 DeleteFileA(name);
|
|
293 err:
|
|
294 return 1;
|
|
295 } else {
|
|
296 static assert(false);
|
|
297 }
|
|
298 }
|
|
299
|
|
300 /* Write file, either succeed or fail
|
|
301 * with error message & exit.
|
|
302 */
|
|
303
|
|
304 void writev()
|
|
305 {
|
|
306 if (write()) {
|
|
307 error("Error writing file '%s'\n", name.toChars());
|
|
308 }
|
|
309 }
|
|
310
|
|
311 /* Return !=0 if file exists.
|
|
312 * 0: file doesn't exist
|
|
313 * 1: normal file
|
|
314 * 2: directory
|
|
315 */
|
|
316
|
|
317 /* Append to file, return !=0 if error
|
|
318 */
|
|
319
|
|
320 int append()
|
|
321 {
|
|
322 assert(false);
|
|
323 }
|
|
324
|
|
325 /* Append to file, either succeed or fail
|
|
326 * with error message & exit.
|
|
327 */
|
|
328
|
|
329 void appendv()
|
|
330 {
|
|
331 assert(false);
|
|
332 }
|
|
333
|
|
334 /* Return !=0 if file exists.
|
|
335 * 0: file doesn't exist
|
|
336 * 1: normal file
|
|
337 * 2: directory
|
|
338 */
|
|
339
|
|
340 int exists()
|
|
341 {
|
|
342 assert(false);
|
|
343 }
|
|
344
|
|
345 /* Given wildcard filespec, return an array of
|
|
346 * matching File's.
|
|
347 */
|
|
348
|
|
349 static Array match(char*)
|
|
350 {
|
|
351 assert(false);
|
|
352 }
|
|
353
|
|
354 static Array match(FileName *)
|
|
355 {
|
|
356 assert(false);
|
|
357 }
|
|
358
|
|
359 // Compare file times.
|
|
360 // Return <0 this < f
|
|
361 // =0 this == f
|
|
362 // >0 this > f
|
|
363 int compareTime(File f)
|
|
364 {
|
|
365 assert(false);
|
|
366 }
|
|
367
|
|
368 // Read system file statistics
|
|
369 void stat()
|
|
370 {
|
|
371 assert(false);
|
|
372 }
|
|
373
|
|
374 /* Set buffer
|
|
375 */
|
|
376
|
|
377 void setbuffer(void* buffer, uint len)
|
|
378 {
|
|
379 this.buffer = cast(ubyte*)buffer;
|
|
380 this.len = len;
|
|
381 }
|
|
382
|
|
383 void checkoffset(size_t offset, size_t nbytes)
|
|
384 {
|
|
385 assert(false);
|
|
386 }
|
|
387
|
|
388 void remove() // delete file
|
|
389 {
|
|
390 version (POSIX) {
|
|
391 .remove(this.name.toChars());
|
|
392 } else version (_WIN32) {
|
|
393 DeleteFileA(toStringz(this.name.toChars()));
|
|
394 } else {
|
|
395 assert(0);
|
|
396 }
|
|
397 }
|
|
398 } |