diff options
author | Ron Yorston <rmy@pobox.com> | 2012-05-09 11:20:06 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2012-05-09 15:00:05 +0100 |
commit | f2459f232790aab0434d1cc6471ea62bc193e636 (patch) | |
tree | 876d184a89f20b9e23d24020dbb3f6f01b519768 /win32 | |
parent | 0c9c04defd7b21aab1f18eaabd2f461b6a425964 (diff) | |
download | busybox-w32-f2459f232790aab0434d1cc6471ea62bc193e636.tar.gz busybox-w32-f2459f232790aab0434d1cc6471ea62bc193e636.tar.bz2 busybox-w32-f2459f232790aab0434d1cc6471ea62bc193e636.zip |
mingw32: make access(2) check file format for executables
Diffstat (limited to 'win32')
-rw-r--r-- | win32/mingw.c | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/win32/mingw.c b/win32/mingw.c index be08c5bd5..a6c969596 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -225,7 +225,8 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf) | |||
225 | buf->st_uid = 0; | 225 | buf->st_uid = 0; |
226 | buf->st_nlink = 1; | 226 | buf->st_nlink = 1; |
227 | buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes); | 227 | buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes); |
228 | if (len > 4 && !strcmp(file_name+len-4, ".exe")) | 228 | if (len > 4 && (!strcasecmp(file_name+len-4, ".exe") || |
229 | !strcasecmp(file_name+len-4, ".com"))) | ||
229 | buf->st_mode |= S_IEXEC; | 230 | buf->st_mode |= S_IEXEC; |
230 | buf->st_size = fdata.nFileSizeLow | | 231 | buf->st_size = fdata.nFileSizeLow | |
231 | (((off64_t)fdata.nFileSizeHigh)<<32); | 232 | (((off64_t)fdata.nFileSizeHigh)<<32); |
@@ -762,3 +763,70 @@ char *strptime(const char *s UNUSED_PARAM, const char *format UNUSED_PARAM, stru | |||
762 | { | 763 | { |
763 | return NULL; | 764 | return NULL; |
764 | } | 765 | } |
766 | |||
767 | #undef access | ||
768 | int mingw_access(const char *name, int mode) | ||
769 | { | ||
770 | int ret; | ||
771 | struct stat s; | ||
772 | int fd, n, offset, sig; | ||
773 | unsigned char buf[1024]; | ||
774 | |||
775 | /* Windows can only handle test for existence, read or write */ | ||
776 | if (mode == F_OK || (mode & ~X_OK)) { | ||
777 | ret = _access(name, mode & ~X_OK); | ||
778 | if (ret < 0 || !(mode & X_OK)) { | ||
779 | return ret; | ||
780 | } | ||
781 | } | ||
782 | |||
783 | if (!mingw_stat(name, &s) && S_ISREG(s.st_mode)) { | ||
784 | |||
785 | /* stat marks .exe and .com files as executable */ | ||
786 | if ((s.st_mode&S_IEXEC)) { | ||
787 | return 0; | ||
788 | } | ||
789 | |||
790 | fd = open(name, O_RDONLY); | ||
791 | if (fd < 0) | ||
792 | return -1; | ||
793 | n = read(fd, buf, sizeof(buf)-1); | ||
794 | close(fd); | ||
795 | if (n < 4) /* at least '#!/x' and not error */ | ||
796 | return -1; | ||
797 | |||
798 | /* shell script */ | ||
799 | if (buf[0] == '#' && buf[1] == '!') { | ||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | /* | ||
804 | * Poke about in file to see if it's a PE binary. I've just copied | ||
805 | * the magic from the file command. | ||
806 | */ | ||
807 | if (buf[0] == 'M' && buf[1] == 'Z') { | ||
808 | offset = (buf[0x19] << 8) + buf[0x18]; | ||
809 | if (offset > 0x3f) { | ||
810 | offset = (buf[0x3f] << 24) + (buf[0x3e] << 16) + | ||
811 | (buf[0x3d] << 8) + buf[0x3c]; | ||
812 | if (offset < sizeof(buf)-100) { | ||
813 | if (memcmp(buf+offset, "PE\0\0", 4) == 0) { | ||
814 | sig = (buf[offset+25] << 8) + buf[offset+24]; | ||
815 | if (sig == 0x10b || sig == 0x20b) { | ||
816 | sig = (buf[offset+23] << 8) + buf[offset+22]; | ||
817 | if ((sig & 0x2000) != 0) { | ||
818 | /* DLL */ | ||
819 | return -1; | ||
820 | } | ||
821 | sig = buf[offset+92]; | ||
822 | return !(sig == 1 || sig == 2 || | ||
823 | sig == 3 || sig == 7); | ||
824 | } | ||
825 | } | ||
826 | } | ||
827 | } | ||
828 | } | ||
829 | } | ||
830 | |||
831 | return -1; | ||
832 | } | ||