diff options
author | Ron Yorston <rmy@pobox.com> | 2021-07-25 10:52:55 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-07-25 10:52:55 +0100 |
commit | 15fcbd19c84df418017880af7514ea5cc64ba39d (patch) | |
tree | 64b39edb02854f582d529835a4aa50e5048015c2 | |
parent | bc8ebe551a2407b5e29c7f98bee4b470c1093947 (diff) | |
download | busybox-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.c | 25 |
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 | ||