aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-07-25 10:52:55 +0100
committerRon Yorston <rmy@pobox.com>2021-07-25 10:52:55 +0100
commit15fcbd19c84df418017880af7514ea5cc64ba39d (patch)
tree64b39edb02854f582d529835a4aa50e5048015c2
parentbc8ebe551a2407b5e29c7f98bee4b470c1093947 (diff)
downloadbusybox-w32-15fcbd19c84df418017880af7514ea5cc64ba39d.tar.gz
busybox-w32-15fcbd19c84df418017880af7514ea5cc64ba39d.tar.bz2
busybox-w32-15fcbd19c84df418017880af7514ea5cc64ba39d.zip
win32: special case for devices files in stat(2)
The diff applet calls stat(2) on the files it's asked to process. This includes /dev/null when the -N flag is used and /dev/fd/* files when process substitution is used. Treat device files as a special case in get_file_attr(), returning a fake set of attributes with FILE_ATTRIBUTE_DEVICE set. This value is unused elsewhere in busybox-w32. Ensure it's unset in other cases. When FILE_ATTRIBUTE_DEVICE is set: - adjust some permissions; - avoid calling has_exec_format() as this opens/closes the file which breaks process substitution. These changes improve the behaviour of diff but they also have other effects. For example, the stat and ls applets now report details of device files. There may be unintended consequences.
-rw-r--r--win32/mingw.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/win32/mingw.c b/win32/mingw.c
index a65a0a6d1..82316e69d 100644
--- a/win32/mingw.c
+++ b/win32/mingw.c
@@ -328,11 +328,11 @@ static inline mode_t file_attr_to_st_mode(DWORD attr)
328{ 328{
329 mode_t fMode = S_IRUSR|S_IRGRP|S_IROTH; 329 mode_t fMode = S_IRUSR|S_IRGRP|S_IROTH;
330 if (attr & FILE_ATTRIBUTE_DIRECTORY) 330 if (attr & FILE_ATTRIBUTE_DIRECTORY)
331 fMode |= S_IFDIR|S_IWUSR|S_IWGRP|S_IXUSR|S_IXGRP|S_IXOTH; 331 fMode |= S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH;
332 else 332 else
333 fMode |= S_IFREG; 333 fMode |= S_IFREG;
334 if (!(attr & FILE_ATTRIBUTE_READONLY)) 334 if (!(attr & FILE_ATTRIBUTE_READONLY))
335 fMode |= S_IWUSR|S_IWGRP; 335 fMode |= S_IWUSR|S_IWGRP|(attr & FILE_ATTRIBUTE_DEVICE ? S_IWOTH : 0);
336 return fMode; 336 return fMode;
337} 337}
338 338
@@ -340,15 +340,28 @@ static inline int get_file_attr(const char *fname, WIN32_FILE_ATTRIBUTE_DATA *fd
340{ 340{
341 size_t len; 341 size_t len;
342 342
343 if (GetFileAttributesExA(fname, GetFileExInfoStandard, fdata)) 343 if (get_dev_type(fname) != NOT_DEVICE || get_dev_fd(fname) >= 0) {
344 /* Fake attributes for special devices */
345 FILETIME epoch = {0xd53e8000, 0x019db1de}; // Unix epoch as FILETIME
346 fdata->dwFileAttributes = FILE_ATTRIBUTE_DEVICE;
347 fdata->ftCreationTime = fdata->ftLastAccessTime =
348 fdata->ftLastWriteTime = epoch;
349 fdata->nFileSizeHigh = fdata->nFileSizeLow = 0;
344 return 0; 350 return 0;
351 }
352
353 if (GetFileAttributesExA(fname, GetFileExInfoStandard, fdata)) {
354 fdata->dwFileAttributes &= ~FILE_ATTRIBUTE_DEVICE;
355 return 0;
356 }
345 357
346 if (GetLastError() == ERROR_SHARING_VIOLATION) { 358 if (GetLastError() == ERROR_SHARING_VIOLATION) {
347 HANDLE hnd; 359 HANDLE hnd;
348 WIN32_FIND_DATA fd; 360 WIN32_FIND_DATA fd;
349 361
350 if ((hnd=FindFirstFile(fname, &fd)) != INVALID_HANDLE_VALUE) { 362 if ((hnd=FindFirstFile(fname, &fd)) != INVALID_HANDLE_VALUE) {
351 fdata->dwFileAttributes = fd.dwFileAttributes; 363 fdata->dwFileAttributes =
364 fd.dwFileAttributes & ~FILE_ATTRIBUTE_DEVICE;
352 fdata->ftCreationTime = fd.ftCreationTime; 365 fdata->ftCreationTime = fd.ftCreationTime;
353 fdata->ftLastAccessTime = fd.ftLastAccessTime; 366 fdata->ftLastAccessTime = fd.ftLastAccessTime;
354 fdata->ftLastWriteTime = fd.ftLastWriteTime; 367 fdata->ftLastWriteTime = fd.ftLastWriteTime;
@@ -586,6 +599,7 @@ static int do_lstat(int follow, const char *file_name, struct mingw_stat *buf)
586 buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes); 599 buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
587 buf->st_attr = fdata.dwFileAttributes; 600 buf->st_attr = fdata.dwFileAttributes;
588 if (S_ISREG(buf->st_mode) && 601 if (S_ISREG(buf->st_mode) &&
602 !(buf->st_attr & FILE_ATTRIBUTE_DEVICE) &&
589 (has_exe_suffix(file_name) || has_exec_format(file_name))) 603 (has_exe_suffix(file_name) || has_exec_format(file_name)))
590 buf->st_mode |= S_IXUSR|S_IXGRP|S_IXOTH; 604 buf->st_mode |= S_IXUSR|S_IXGRP|S_IXOTH;
591 buf->st_size = fdata.nFileSizeLow | 605 buf->st_size = fdata.nFileSizeLow |
@@ -616,7 +630,8 @@ static int do_lstat(int follow, const char *file_name, struct mingw_stat *buf)
616 else { 630 else {
617 buf->st_uid = 0; 631 buf->st_uid = 0;
618 buf->st_gid = 0; 632 buf->st_gid = 0;
619 buf->st_mode &= ~(S_IROTH|S_IWOTH|S_IXOTH); 633 if (!(buf->st_attr & FILE_ATTRIBUTE_DEVICE))
634 buf->st_mode &= ~(S_IROTH|S_IWOTH|S_IXOTH);
620 } 635 }
621#endif 636#endif
622 637