aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2012-05-09 11:20:06 +0100
committerRon Yorston <rmy@pobox.com>2012-05-09 15:00:05 +0100
commitf2459f232790aab0434d1cc6471ea62bc193e636 (patch)
tree876d184a89f20b9e23d24020dbb3f6f01b519768
parent0c9c04defd7b21aab1f18eaabd2f461b6a425964 (diff)
downloadbusybox-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.h4
-rw-r--r--libbb/execable.c26
-rw-r--r--win32/mingw.c70
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) {}
337NOIMPL(ttyname_r,int fd UNUSED_PARAM, char *buf UNUSED_PARAM, int sz UNUSED_PARAM); 337NOIMPL(ttyname_r,int fd UNUSED_PARAM, char *buf UNUSED_PARAM, int sz UNUSED_PARAM);
338int mingw_unlink(const char *pathname); 338int mingw_unlink(const char *pathname);
339NOIMPL(vfork,void); 339NOIMPL(vfork,void);
340int 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 @@
16int FAST_FUNC execable_file(const char *name) 16int 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
768int 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}