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 | |
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
-rw-r--r-- | include/mingw.h | 4 | ||||
-rw-r--r-- | libbb/execable.c | 26 | ||||
-rw-r--r-- | win32/mingw.c | 70 |
3 files changed, 74 insertions, 26 deletions
diff --git a/include/mingw.h b/include/mingw.h index 08d776c84..1ef13c638 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -337,6 +337,7 @@ static inline void sync(void) {} | |||
337 | NOIMPL(ttyname_r,int fd UNUSED_PARAM, char *buf UNUSED_PARAM, int sz UNUSED_PARAM); | 337 | NOIMPL(ttyname_r,int fd UNUSED_PARAM, char *buf UNUSED_PARAM, int sz UNUSED_PARAM); |
338 | int mingw_unlink(const char *pathname); | 338 | int mingw_unlink(const char *pathname); |
339 | NOIMPL(vfork,void); | 339 | NOIMPL(vfork,void); |
340 | int mingw_access(const char *name, int mode); | ||
340 | 341 | ||
341 | #define dup2 mingw_dup2 | 342 | #define dup2 mingw_dup2 |
342 | #define getcwd mingw_getcwd | 343 | #define getcwd mingw_getcwd |
@@ -344,6 +345,9 @@ NOIMPL(vfork,void); | |||
344 | #define open mingw_open | 345 | #define open mingw_open |
345 | #define unlink mingw_unlink | 346 | #define unlink mingw_unlink |
346 | 347 | ||
348 | #undef access | ||
349 | #define access mingw_access | ||
350 | |||
347 | /* | 351 | /* |
348 | * utime.h | 352 | * utime.h |
349 | */ | 353 | */ |
diff --git a/libbb/execable.c b/libbb/execable.c index afb957e43..c2a7bf0ca 100644 --- a/libbb/execable.c +++ b/libbb/execable.c | |||
@@ -16,31 +16,7 @@ | |||
16 | int FAST_FUNC execable_file(const char *name) | 16 | int FAST_FUNC execable_file(const char *name) |
17 | { | 17 | { |
18 | struct stat s; | 18 | struct stat s; |
19 | #if ENABLE_PLATFORM_MINGW32 | ||
20 | if (!stat(name, &s) && S_ISREG(s.st_mode)) { | ||
21 | int len, fd, n; | ||
22 | char buf[100]; | ||
23 | |||
24 | if ((len=strlen(name)) > 4 && | ||
25 | (!strcasecmp(name+len-4, ".exe") || | ||
26 | !strcasecmp(name+len-4, ".com"))) { | ||
27 | return 1; | ||
28 | } | ||
29 | |||
30 | fd = open(name, O_RDONLY); | ||
31 | if (fd < 0) | ||
32 | return 0; | ||
33 | n = read(fd, buf, sizeof(buf)-1); | ||
34 | close(fd); | ||
35 | if (n < 4) /* at least '#!/x' and not error */ | ||
36 | return 0; | ||
37 | |||
38 | return (buf[0] == '#' && buf[1] == '!'); | ||
39 | } | ||
40 | return 0; | ||
41 | #else | ||
42 | return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode)); | 19 | return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode)); |
43 | #endif | ||
44 | } | 20 | } |
45 | 21 | ||
46 | /* search (*PATHp) for an executable file; | 22 | /* search (*PATHp) for an executable file; |
@@ -76,7 +52,7 @@ char* FAST_FUNC find_execable(const char *filename, char **PATHp) | |||
76 | if (len > 4 && | 52 | if (len > 4 && |
77 | (!strcasecmp(p+len-4, ".exe") || | 53 | (!strcasecmp(p+len-4, ".exe") || |
78 | !strcasecmp(p+len-4, ".com"))) | 54 | !strcasecmp(p+len-4, ".com"))) |
79 | ; /* nothing, already tested by find_execable() */ | 55 | ; /* nothing, already tested by execable_file() */ |
80 | else { | 56 | else { |
81 | char *np = xmalloc(len+4+1); | 57 | char *np = xmalloc(len+4+1); |
82 | memcpy(np, p, len); | 58 | memcpy(np, p, len); |
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 | } | ||