145
|
1
|
|
2 /* Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
|
|
3 * http://www.digitalmars.com
|
|
4 * Distributed under the Boost Software License, Version 1.0.
|
|
5 * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
6 * https://github.com/D-Programming-Language/dmd/blob/master/src/root/file.c
|
|
7 */
|
|
8
|
|
9 #include "dsystem.h"
|
|
10 #include "file.h"
|
|
11
|
|
12 #if _WIN32
|
|
13 #include <windows.h>
|
|
14 #endif
|
|
15
|
|
16 #if POSIX
|
|
17 #include <utime.h>
|
|
18 #endif
|
|
19
|
|
20 #include "filename.h"
|
|
21 #include "array.h"
|
|
22 #include "rmem.h"
|
|
23
|
|
24 /****************************** File ********************************/
|
|
25
|
|
26 File::File(const FileName *n)
|
|
27 {
|
|
28 ref = 0;
|
|
29 buffer = NULL;
|
|
30 len = 0;
|
|
31 name = const_cast<FileName *>(n);
|
|
32 }
|
|
33
|
|
34 File *File::create(const char *n)
|
|
35 {
|
|
36 return new File(n);
|
|
37 }
|
|
38
|
|
39 File::File(const char *n)
|
|
40 {
|
|
41 ref = 0;
|
|
42 buffer = NULL;
|
|
43 len = 0;
|
|
44 name = new FileName(n);
|
|
45 }
|
|
46
|
|
47 File::~File()
|
|
48 {
|
|
49 if (buffer)
|
|
50 {
|
|
51 if (ref == 0)
|
|
52 mem.xfree(buffer);
|
|
53 #if _WIN32
|
|
54 if (ref == 2)
|
|
55 UnmapViewOfFile(buffer);
|
|
56 #endif
|
|
57 }
|
|
58 }
|
|
59
|
|
60 /*************************************
|
|
61 */
|
|
62
|
|
63 bool File::read()
|
|
64 {
|
|
65 if (len)
|
|
66 return false; // already read the file
|
|
67 #if POSIX
|
|
68 size_t size;
|
|
69 struct stat buf;
|
|
70 ssize_t numread;
|
|
71
|
|
72 const char *name = this->name->toChars();
|
|
73 //printf("File::read('%s')\n",name);
|
|
74 int fd = open(name, O_RDONLY);
|
|
75 if (fd == -1)
|
|
76 {
|
|
77 //printf("\topen error, errno = %d\n",errno);
|
|
78 goto err1;
|
|
79 }
|
|
80
|
|
81 if (!ref)
|
|
82 ::free(buffer);
|
|
83 ref = 0; // we own the buffer now
|
|
84
|
|
85 //printf("\tfile opened\n");
|
|
86 if (fstat(fd, &buf))
|
|
87 {
|
|
88 printf("\tfstat error, errno = %d\n",errno);
|
|
89 goto err2;
|
|
90 }
|
|
91 size = (size_t)buf.st_size;
|
|
92 #ifdef IN_GCC
|
|
93 buffer = (unsigned char *) ::xmalloc(size + 2);
|
|
94 #else
|
|
95 buffer = (unsigned char *) ::malloc(size + 2);
|
|
96 #endif
|
|
97 if (!buffer)
|
|
98 {
|
|
99 printf("\tmalloc error, errno = %d\n",errno);
|
|
100 goto err2;
|
|
101 }
|
|
102
|
|
103 numread = ::read(fd, buffer, size);
|
|
104 if (numread != (ssize_t)size)
|
|
105 {
|
|
106 printf("\tread error, errno = %d\n",errno);
|
|
107 goto err2;
|
|
108 }
|
|
109
|
|
110 if (close(fd) == -1)
|
|
111 {
|
|
112 printf("\tclose error, errno = %d\n",errno);
|
|
113 goto err;
|
|
114 }
|
|
115
|
|
116 len = size;
|
|
117
|
|
118 // Always store a wchar ^Z past end of buffer so scanner has a sentinel
|
|
119 buffer[size] = 0; // ^Z is obsolete, use 0
|
|
120 buffer[size + 1] = 0;
|
|
121 return false;
|
|
122
|
|
123 err2:
|
|
124 close(fd);
|
|
125 err:
|
|
126 ::free(buffer);
|
|
127 buffer = NULL;
|
|
128 len = 0;
|
|
129
|
|
130 err1:
|
|
131 return true;
|
|
132 #elif _WIN32
|
|
133 DWORD size;
|
|
134 DWORD numread;
|
|
135
|
|
136 const char *name = this->name->toChars();
|
|
137 HANDLE h = CreateFileA(name,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
|
|
138 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
|
139 if (h == INVALID_HANDLE_VALUE)
|
|
140 goto err1;
|
|
141
|
|
142 if (!ref)
|
|
143 ::free(buffer);
|
|
144 ref = 0;
|
|
145
|
|
146 size = GetFileSize(h,NULL);
|
|
147 #ifdef IN_GCC
|
|
148 buffer = (unsigned char *) ::xmalloc(size + 2);
|
|
149 #else
|
|
150 buffer = (unsigned char *) ::malloc(size + 2);
|
|
151 #endif
|
|
152 if (!buffer)
|
|
153 goto err2;
|
|
154
|
|
155 if (ReadFile(h,buffer,size,&numread,NULL) != TRUE)
|
|
156 goto err2;
|
|
157
|
|
158 if (numread != size)
|
|
159 goto err2;
|
|
160
|
|
161 if (!CloseHandle(h))
|
|
162 goto err;
|
|
163
|
|
164 len = size;
|
|
165
|
|
166 // Always store a wchar ^Z past end of buffer so scanner has a sentinel
|
|
167 buffer[size] = 0; // ^Z is obsolete, use 0
|
|
168 buffer[size + 1] = 0;
|
|
169 return 0;
|
|
170
|
|
171 err2:
|
|
172 CloseHandle(h);
|
|
173 err:
|
|
174 ::free(buffer);
|
|
175 buffer = NULL;
|
|
176 len = 0;
|
|
177
|
|
178 err1:
|
|
179 return true;
|
|
180 #else
|
|
181 assert(0);
|
|
182 #endif
|
|
183 }
|
|
184
|
|
185 /*********************************************
|
|
186 * Write a file.
|
|
187 * Returns:
|
|
188 * false success
|
|
189 */
|
|
190
|
|
191 bool File::write()
|
|
192 {
|
|
193 #if POSIX
|
|
194 ssize_t numwritten;
|
|
195
|
|
196 const char *name = this->name->toChars();
|
|
197 int fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, (6 << 6) | (4 << 3) | 4);
|
|
198 if (fd == -1)
|
|
199 goto err;
|
|
200
|
|
201 numwritten = ::write(fd, buffer, len);
|
|
202 if ((ssize_t)len != numwritten)
|
|
203 goto err2;
|
|
204
|
|
205 if (close(fd) == -1)
|
|
206 goto err;
|
|
207
|
|
208 return false;
|
|
209
|
|
210 err2:
|
|
211 close(fd);
|
|
212 ::remove(name);
|
|
213 err:
|
|
214 return true;
|
|
215 #elif _WIN32
|
|
216 DWORD numwritten;
|
|
217
|
|
218 const char *name = this->name->toChars();
|
|
219 HANDLE h = CreateFileA(name,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
|
|
220 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
|
221 if (h == INVALID_HANDLE_VALUE)
|
|
222 goto err;
|
|
223
|
|
224 if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE)
|
|
225 goto err2;
|
|
226
|
|
227 if (len != numwritten)
|
|
228 goto err2;
|
|
229
|
|
230 if (!CloseHandle(h))
|
|
231 goto err;
|
|
232 return false;
|
|
233
|
|
234 err2:
|
|
235 CloseHandle(h);
|
|
236 DeleteFileA(name);
|
|
237 err:
|
|
238 return true;
|
|
239 #else
|
|
240 assert(0);
|
|
241 #endif
|
|
242 }
|
|
243
|
|
244 void File::remove()
|
|
245 {
|
|
246 #if POSIX
|
|
247 ::remove(this->name->toChars());
|
|
248 #elif _WIN32
|
|
249 DeleteFileA(this->name->toChars());
|
|
250 #else
|
|
251 assert(0);
|
|
252 #endif
|
|
253 }
|
|
254
|
|
255 const char *File::toChars()
|
|
256 {
|
|
257 return name->toChars();
|
|
258 }
|