aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2010-04-14 06:52:06 +0200
committerNguyễn Thái Ngọc Duy <pclouds@gmail.com>2010-04-20 19:14:13 +0200
commit1712a701605d6599507bec1a2e88b7e28590c07a (patch)
tree3def65840b4c5d266c455d500d33cadbce00dee4
parentd32669a273676eaec45d55de35a2470f23035aca (diff)
downloadbusybox-w32-1712a701605d6599507bec1a2e88b7e28590c07a.tar.gz
busybox-w32-1712a701605d6599507bec1a2e88b7e28590c07a.tar.bz2
busybox-w32-1712a701605d6599507bec1a2e88b7e28590c07a.zip
win32: Replace stat/lstat
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
-rw-r--r--win32/mingw.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/win32/mingw.c b/win32/mingw.c
index eede8ef6d..4721f89cb 100644
--- a/win32/mingw.c
+++ b/win32/mingw.c
@@ -149,6 +149,140 @@ FILE *mingw_fopen (const char *filename, const char *mode)
149 return fopen(filename, mode); 149 return fopen(filename, mode);
150} 150}
151 151
152static inline time_t filetime_to_time_t(const FILETIME *ft)
153{
154 long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
155 winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
156 winTime /= 10000000; /* Nano to seconds resolution */
157 return (time_t)winTime;
158}
159
160static inline int file_attr_to_st_mode (DWORD attr)
161{
162 int fMode = S_IREAD;
163 if (attr & FILE_ATTRIBUTE_DIRECTORY)
164 fMode |= S_IFDIR;
165 else
166 fMode |= S_IFREG;
167 if (!(attr & FILE_ATTRIBUTE_READONLY))
168 fMode |= S_IWRITE;
169 return fMode;
170}
171
172static inline int get_file_attr(const char *fname, WIN32_FILE_ATTRIBUTE_DATA *fdata)
173{
174 if (GetFileAttributesExA(fname, GetFileExInfoStandard, fdata))
175 return 0;
176
177 switch (GetLastError()) {
178 case ERROR_ACCESS_DENIED:
179 case ERROR_SHARING_VIOLATION:
180 case ERROR_LOCK_VIOLATION:
181 case ERROR_SHARING_BUFFER_EXCEEDED:
182 return EACCES;
183 case ERROR_BUFFER_OVERFLOW:
184 return ENAMETOOLONG;
185 case ERROR_NOT_ENOUGH_MEMORY:
186 return ENOMEM;
187 default:
188 return ENOENT;
189 }
190}
191
192/* We keep the do_lstat code in a separate function to avoid recursion.
193 * When a path ends with a slash, the stat will fail with ENOENT. In
194 * this case, we strip the trailing slashes and stat again.
195 */
196static int do_lstat(const char *file_name, struct stat *buf)
197{
198 WIN32_FILE_ATTRIBUTE_DATA fdata;
199
200 if (!(errno = get_file_attr(file_name, &fdata))) {
201 int len = strlen(file_name);
202
203 buf->st_ino = 0;
204 buf->st_gid = 0;
205 buf->st_uid = 0;
206 buf->st_nlink = 1;
207 buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
208 if (len > 4 && !strcmp(file_name+len-4, ".exe"))
209 buf->st_mode |= S_IEXEC;
210 buf->st_size = fdata.nFileSizeLow |
211 (((off64_t)fdata.nFileSizeHigh)<<32);
212 buf->st_dev = buf->st_rdev = 0; /* not used by Git */
213 buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
214 buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
215 buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
216 return 0;
217 }
218 return -1;
219}
220
221/* We provide our own lstat/fstat functions, since the provided
222 * lstat/fstat functions are so slow. These stat functions are
223 * tailored for Git's usage (read: fast), and are not meant to be
224 * complete. Note that Git stat()s are redirected to mingw_lstat()
225 * too, since Windows doesn't really handle symlinks that well.
226 */
227int mingw_lstat(const char *file_name, struct stat *buf)
228{
229 int namelen;
230 static char alt_name[PATH_MAX];
231
232 if (!do_lstat(file_name, buf))
233 return 0;
234
235 /* if file_name ended in a '/', Windows returned ENOENT;
236 * try again without trailing slashes
237 */
238 if (errno != ENOENT)
239 return -1;
240
241 namelen = strlen(file_name);
242 if (namelen && file_name[namelen-1] != '/')
243 return -1;
244 while (namelen && file_name[namelen-1] == '/')
245 --namelen;
246 if (!namelen || namelen >= PATH_MAX)
247 return -1;
248
249 memcpy(alt_name, file_name, namelen);
250 alt_name[namelen] = 0;
251 return do_lstat(alt_name, buf);
252}
253
254#undef fstat
255int mingw_fstat(int fd, struct stat *buf)
256{
257 HANDLE fh = (HANDLE)_get_osfhandle(fd);
258 BY_HANDLE_FILE_INFORMATION fdata;
259
260 if (fh == INVALID_HANDLE_VALUE) {
261 errno = EBADF;
262 return -1;
263 }
264 /* direct non-file handles to MS's fstat() */
265 if (GetFileType(fh) != FILE_TYPE_DISK)
266 return _fstati64(fd, buf);
267
268 if (GetFileInformationByHandle(fh, &fdata)) {
269 buf->st_ino = 0;
270 buf->st_gid = 0;
271 buf->st_uid = 0;
272 buf->st_nlink = 1;
273 buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
274 buf->st_size = fdata.nFileSizeLow |
275 (((off64_t)fdata.nFileSizeHigh)<<32);
276 buf->st_dev = buf->st_rdev = 0; /* not used by Git */
277 buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
278 buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
279 buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
280 return 0;
281 }
282 errno = EBADF;
283 return -1;
284}
285
152unsigned int sleep (unsigned int seconds) 286unsigned int sleep (unsigned int seconds)
153{ 287{
154 Sleep(seconds*1000); 288 Sleep(seconds*1000);