From 95a8465ba0fb3ea0fb9033e4823b1f65c4554f27 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Mon, 5 Mar 2001 06:28:25 +0000 Subject: [PATCH] * dlopen.c (dlopen): Return NULL when name is NULL (suggested by chrisiasci@aol.com). * cygwin.din: Add a new, internally used export - _check_for_executable. * dcrt0.cc (dll_crt0_1): Set _check_for_executable for older binaries. Pass user_data to premain functions. * fhandler.cc (fhandler_disk_file::open): Only check for executable if the linked program is intereested in the executable bit. (fhandler_disk_file::check_execable_p): Delete. * fhandler.h (executable_states): New enumeration of various states of executable bit caring. (fhandler_base::set_execable_p): New method. * fhandler_termios.cc (fhandler_termios::line_edit): Flag when a signal has been sent to the tty. Return -1 when this is so. * fhandler_console.cc (fhandler_console::read): Return -1 when signal sending character encountered. * path.cc (path_conv::check): Record when path refers to a disk device. Move executable extension check here. (check_sysfile): Accomodate new EXEC path states. (has_suffix): Remove. (next_suffix): Remove. (class suffix_scan): New clas. (suffix_scan::has): New method. (suffix_scan:next): New method. (symlink_info::check): Use suffix_scan method to control for scanning for suffixes. * path.h (path_conv::exec_state): New method. * perprocess.h: Make "C" friendly. * include/cygwin/version.h: Define CYGWIN_VERSION_CHECK_FOR_S_IEXEC. Bump CYGWIN_VERSION_API_MINOR. * include/sys/cygwin.h: Change premain declarations. * winsup.h: Move __cplusplus test to after builtin defines. --- winsup/cygwin/ChangeLog | 39 +++++ winsup/cygwin/cygwin.din | 1 + winsup/cygwin/dcrt0.cc | 15 +- winsup/cygwin/debug.h | 1 + winsup/cygwin/dir.cc | 1 + winsup/cygwin/dlfcn.cc | 12 +- winsup/cygwin/dtable.cc | 1 + winsup/cygwin/environ.cc | 4 +- winsup/cygwin/exec.cc | 1 + winsup/cygwin/fhandler.cc | 28 +--- winsup/cygwin/fhandler.h | 16 +- winsup/cygwin/fhandler_console.cc | 17 +- winsup/cygwin/fhandler_raw.cc | 1 + winsup/cygwin/fhandler_tape.cc | 1 + winsup/cygwin/fhandler_termios.cc | 7 + winsup/cygwin/fhandler_tty.cc | 4 +- winsup/cygwin/include/cygwin/version.h | 7 +- winsup/cygwin/include/sys/cygwin.h | 14 +- winsup/cygwin/include/sys/file.h | 8 +- winsup/cygwin/lib/_cygwin_S_IEXEC.cc | 29 ++++ winsup/cygwin/net.cc | 1 + winsup/cygwin/path.cc | 214 +++++++++++++++---------- winsup/cygwin/path.h | 18 ++- winsup/cygwin/perprocess.h | 12 +- winsup/cygwin/security.cc | 1 + winsup/cygwin/spawn.cc | 1 + winsup/cygwin/syscalls.cc | 4 +- winsup/cygwin/winsup.h | 4 +- 28 files changed, 315 insertions(+), 147 deletions(-) create mode 100644 winsup/cygwin/lib/_cygwin_S_IEXEC.cc diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 35b7fa5df..38ea288c0 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,42 @@ +Mon Mar 5 01:25:03 2001 Christopher Faylor + + * dlopen.c (dlopen): Return NULL when name is NULL (suggested by + chrisiasci@aol.com). + + * cygwin.din: Add a new, internally used export - + _check_for_executable. + * dcrt0.cc (dll_crt0_1): Set _check_for_executable for older binaries. + Pass user_data to premain functions. + * fhandler.cc (fhandler_disk_file::open): Only check for executable if + the linked program is intereested in the executable bit. + (fhandler_disk_file::check_execable_p): Delete. + * fhandler.h (executable_states): New enumeration of various states of + executable bit caring. + (fhandler_base::set_execable_p): New method. + + * fhandler_termios.cc (fhandler_termios::line_edit): Flag when a signal + has been sent to the tty. Return -1 when this is so. + * fhandler_console.cc (fhandler_console::read): Return -1 when signal + sending character encountered. + + * path.cc (path_conv::check): Record when path refers to a disk device. + Move executable extension check here. + (check_sysfile): Accomodate new EXEC path states. + (has_suffix): Remove. + (next_suffix): Remove. + (class suffix_scan): New clas. + (suffix_scan::has): New method. + (suffix_scan:next): New method. + (symlink_info::check): Use suffix_scan method to control for scanning + for suffixes. + * path.h (path_conv::exec_state): New method. + * perprocess.h: Make "C" friendly. + * include/cygwin/version.h: Define CYGWIN_VERSION_CHECK_FOR_S_IEXEC. + Bump CYGWIN_VERSION_API_MINOR. + * include/sys/cygwin.h: Change premain declarations. + + * winsup.h: Move __cplusplus test to after builtin defines. + 2001-03-04 Egor Duda * fhandler.h (class fhandler_tty_common): New mutex and event to diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index 184c10b06..fb6364c3d 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -8,6 +8,7 @@ __infinity __main __srget __swbuf +_check_for_executable DATA ; __vc__10pinfo_listi @ALLOCA@ cygwin_stackdump diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 7206fa116..a76e9e5ca 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -27,11 +27,11 @@ details. */ #include "child_info.h" #define NEED_VFORK #include "perthread.h" +#include "perprocess.h" #include "path.h" #include "dtable.h" #include "shared_info.h" #include "cygwin_version.h" -#include "perprocess.h" #include "dll_init.h" #include "host_dependent.h" #include "security.h" @@ -108,7 +108,11 @@ extern "C" /* resourcelocks */ &_reslock, /* threadinterface */ &_mtinterf, /* impure_ptr */ &reent_data, }; - BOOL ignore_case_with_glob = FALSE; + bool ignore_case_with_glob = FALSE; + int __declspec (dllexport) _check_for_executable = FALSE; +#ifdef DEBUGGING + int pinger = 0; +#endif }; char *old_title = NULL; @@ -752,6 +756,9 @@ dll_crt0_1 () longjmp (fork_info->jmp, fork_info->cygpid); } + if (!CYGWIN_VERSION_CHECK_FOR_S_IEXEC) + _check_for_executable = TRUE; + #ifdef DEBUGGING { extern void fork_init (); @@ -808,7 +815,7 @@ dll_crt0_1 () if (user_data->premain[0]) for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++) - user_data->premain[i] (__argc, __argv); + user_data->premain[i] (__argc, __argv, user_data); /* Set up __progname for getopt error call. */ __progname = __argv[0]; @@ -832,7 +839,7 @@ dll_crt0_1 () /* Execute any specified "premain" functions */ if (user_data->premain[PREMAIN_LEN / 2]) for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++) - user_data->premain[i] (__argc, __argv); + user_data->premain[i] (__argc, __argv, user_data); debug_printf ("user_data->main %p", user_data->main); diff --git a/winsup/cygwin/debug.h b/winsup/cygwin/debug.h index 2f06286c7..02289eeb5 100644 --- a/winsup/cygwin/debug.h +++ b/winsup/cygwin/debug.h @@ -67,6 +67,7 @@ void __stdcall add_handle (const char *, int, HANDLE, const char *); BOOL __stdcall close_handle (const char *, int, HANDLE, const char *, BOOL); int __stdcall lpfu (const char *, int, DWORD timeout); void __stdcall cygbench (const char *s); +extern int pinger; #endif /*DEBUGGING*/ #endif /*_DEBUG_H_*/ diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc index aa4092b95..3c10dfa73 100644 --- a/winsup/cygwin/dir.cc +++ b/winsup/cygwin/dir.cc @@ -22,6 +22,7 @@ details. */ #include "pinfo.h" #include "cygerrno.h" #include "fhandler.h" +#include "perprocess.h" #include "path.h" #include "security.h" #include "cygheap.h" diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc index 73c44f12d..f553ef877 100644 --- a/winsup/cygwin/dlfcn.cc +++ b/winsup/cygwin/dlfcn.cc @@ -14,9 +14,9 @@ details. */ #include #include #include "fhandler.h" +#include "perprocess.h" #include "path.h" #include "thread.h" -#include "perprocess.h" #include "dlfcn.h" #include "dll_init.h" @@ -166,19 +166,15 @@ dlopen (const char *name, int) { SetResourceLock(LOCK_DLL_LIST,READ_LOCK|WRITE_LOCK," dlopen"); - void *ret = 0; + void *ret; if (!name) - { - /* handle for the current module */ - ret = (void *) GetModuleHandle (NULL); - } + ret = (void *) GetModuleHandle (NULL); /* handle for the current module */ else { /* handle for the named library */ const char *fullpath = get_full_path_of_dll (name); - if (fullpath) - ret = (void *) LoadLibrary (fullpath); + ret = fullpath ? (void *) LoadLibrary (fullpath) : NULL; } if (!ret) diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index 1d0b9cb9a..f20effcc4 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -26,6 +26,7 @@ details. */ #include "pinfo.h" #include "cygheap.h" #include "cygerrno.h" +#include "perprocess.h" #include "fhandler.h" #include "path.h" #include "dtable.h" diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc index df4c60fc8..77cf8da8d 100644 --- a/winsup/cygwin/environ.cc +++ b/winsup/cygwin/environ.cc @@ -18,16 +18,16 @@ details. */ #include "sync.h" #include "sigproc.h" #include "pinfo.h" +#include "perprocess.h" #include "fhandler.h" #include "path.h" #include "cygerrno.h" #include "cygheap.h" #include "registry.h" #include "environ.h" -#include "perprocess.h" extern BOOL allow_glob; -extern BOOL ignore_case_with_glob; +extern bool ignore_case_with_glob; extern BOOL allow_ntea; extern BOOL allow_smbntsec; extern BOOL allow_winsymlinks; diff --git a/winsup/cygwin/exec.cc b/winsup/cygwin/exec.cc index 6438d16e2..e7131ccde 100644 --- a/winsup/cygwin/exec.cc +++ b/winsup/cygwin/exec.cc @@ -13,6 +13,7 @@ details. */ #include #include #include +#include "perprocess.h" #include "fhandler.h" #include "path.h" #include "sync.h" diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 40aa50849..82fa034cd 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -17,11 +17,11 @@ details. */ #include #include #include "cygerrno.h" +#include "perprocess.h" #include "fhandler.h" #include "path.h" #include "shared_info.h" #include "host_dependent.h" -#include "perprocess.h" #include "security.h" static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */ @@ -1226,9 +1226,6 @@ fhandler_disk_file::open (path_conv& real_path, int flags, mode_t mode) win32_path_name_ = real_path.get_win32 (); set_no_free_names (); } - /* If necessary, do various other things to see if path is a program. */ - if (!real_path.isexec ()) - real_path.set_exec (check_execable_p (get_win32_name ())); if (real_path.isbinary ()) { @@ -1264,9 +1261,9 @@ fhandler_disk_file::open (path_conv& real_path, int flags, mode_t mode) extern BOOL allow_ntea; - if (!real_path.isexec () && !allow_ntea - && (!allow_ntsec || !real_path.has_acls ()) - && GetFileType (get_handle ()) == FILE_TYPE_DISK) + if (real_path.isdisk () + && (real_path.exec_state () == dont_know_if_executable) + && !allow_ntea && (!allow_ntsec || !real_path.has_acls ())) { DWORD done; char magic[3]; @@ -1283,7 +1280,7 @@ fhandler_disk_file::open (path_conv& real_path, int flags, mode_t mode) SetFilePointer (get_handle(), 0, 0, FILE_END); set_symlink_p (real_path.issymlink ()); - set_execable_p (real_path.isexec ()); + set_execable_p (real_path.exec_state ()); set_socket_p (real_path.issocket ()); out: @@ -1457,21 +1454,6 @@ fhandler_disk_file::lock (int cmd, struct flock *fl) return 0; } -/* Perform various heuristics on PATH to see if it's a program. */ - -int -fhandler_disk_file::check_execable_p (const char *path) -{ - int len = strlen (path); - const char *ch = path + (len > 4 ? len - 4 : len); - - if (strcasematch (".exe", ch) - || strcasematch (".bat", ch) - || strcasematch (".com", ch)) - return 1; - return 0; -} - /**********************************************************************/ /* /dev/null */ diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 73aa294a6..3196f2114 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -130,6 +130,14 @@ enum bg_check_types bg_signalled = 2 }; +enum executable_states +{ + is_executable, + not_executable, + dont_care_if_executable, + dont_know_if_executable +}; + class fhandler_base { private: @@ -219,7 +227,10 @@ public: void set_socket_p () { FHSETF (LOCAL); } int get_execable_p () { return FHISSETF (EXECABL); } - void set_execable_p (int val) { FHCONDSETF (val, EXECABL); } + void set_execable_p (executable_states val) + { + FHCONDSETF (val == is_executable, EXECABL); + } void set_execable_p () { FHSETF (EXECABL); } int get_append_p () { return FHISSETF (APPEND); } @@ -477,9 +488,6 @@ private: class fhandler_disk_file: public fhandler_base { -private: - int check_execable_p (const char *path); - public: fhandler_disk_file (const char *name); diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index 7ef123784..6e8c76c1c 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -178,8 +178,7 @@ fhandler_console::read (void *pv, size_t buflen) case WAIT_OBJECT_0: break; case WAIT_OBJECT_0 + 1: - set_sig_errno (EINTR); - return -1; + goto sig_exit; default: __seterrno (); return -1; @@ -358,8 +357,14 @@ fhandler_console::read (void *pv, size_t buflen) continue; } - if (toadd && line_edit (toadd, nread)) - break; + if (toadd) + { + int res = line_edit (toadd, nread); + if (res < 0) + goto sig_exit; + else if (res) + break; + } #undef ich } @@ -374,6 +379,10 @@ fhandler_console::read (void *pv, size_t buflen) #undef buf return copied_chars; + + sig_exit: + set_sig_errno (EINTR); + return -1; } void diff --git a/winsup/cygwin/fhandler_raw.cc b/winsup/cygwin/fhandler_raw.cc index d8ecf61ea..f307fb514 100644 --- a/winsup/cygwin/fhandler_raw.cc +++ b/winsup/cygwin/fhandler_raw.cc @@ -18,6 +18,7 @@ #include #include "cygheap.h" #include "cygerrno.h" +#include "perprocess.h" #include "fhandler.h" #include "path.h" diff --git a/winsup/cygwin/fhandler_tape.cc b/winsup/cygwin/fhandler_tape.cc index d1c2c8572..57d782a4c 100644 --- a/winsup/cygwin/fhandler_tape.cc +++ b/winsup/cygwin/fhandler_tape.cc @@ -18,6 +18,7 @@ details. */ #include #include "cygheap.h" #include "cygerrno.h" +#include "perprocess.h" #include "fhandler.h" #include "path.h" diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_termios.cc index 1d0491379..046199903 100644 --- a/winsup/cygwin/fhandler_termios.cc +++ b/winsup/cygwin/fhandler_termios.cc @@ -165,6 +165,7 @@ fhandler_termios::line_edit (const char *rptr, int nread, int always_accept) { char c; int input_done = 0; + bool sawsig = FALSE; int iscanon = tc->ti.c_lflag & ICANON; while (nread-- > 0) @@ -210,6 +211,7 @@ fhandler_termios::line_edit (const char *rptr, int nread, int always_accept) termios_printf ("got interrupt %d, sending signal %d", c, sig); kill_pgrp (tc->getpgid (), sig); tc->ti.c_lflag &= ~FLUSHO; + sawsig = 1; goto restart_output; } not_a_sig: @@ -296,6 +298,11 @@ fhandler_termios::line_edit (const char *rptr, int nread, int always_accept) if (!iscanon || always_accept) set_input_done (ralen > 0); + if (sawsig) + { + // tc->write_error = EINTR; + input_done = -1; + } if (input_done) (void) accept_input (); diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index c3165285e..909264dc9 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -194,7 +194,7 @@ process_input (void *) { int nraw = tty_master->console->read ((void *) rawbuf, (size_t) INP_BUFFER_SIZE); - tty_master->line_edit (rawbuf, nraw); + (void) tty_master->line_edit (rawbuf, nraw); } } @@ -1000,7 +1000,7 @@ fhandler_pty_master::close () int fhandler_pty_master::write (const void *ptr, size_t len) { - line_edit ((char *) ptr, len); + (void) line_edit ((char *) ptr, len); return len; } diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 1095aac3b..60ffe1cb4 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -79,7 +79,9 @@ details. */ (CYGWIN_VERSION_DLL_MAKE_COMBINED (user_data->api_major, user_data->api_minor) <= \ 20) - +#define CYGWIN_VERSION_CHECK_FOR_S_IEXEC \ + (CYGWIN_VERSION_DLL_MAKE_COMBINED (user_data->api_major, user_data->api_minor) >= \ + 36) /* We used to use the DLL major/minor to track non-backward-compatible interface changes to the API. Now we use an API major/minor number for this purpose. */ @@ -127,10 +129,11 @@ details. */ 34: Separated out mount table 35: Export drand48, erand48, jrand48, lcong48, lrand48, mrand48, nrand48, seed48, and srand48. + 36: Added _cygwin_S_IEXEC, et al */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 35 +#define CYGWIN_VERSION_API_MINOR 36 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h index 2b3370cfa..daab7795d 100644 --- a/winsup/cygwin/include/sys/cygwin.h +++ b/winsup/cygwin/include/sys/cygwin.h @@ -31,11 +31,6 @@ extern int cygwin_conv_to_full_posix_path (const char *, char *); extern int cygwin_posix_path_list_p (const char *); extern void cygwin_split_path (const char *, char *, char *); -extern void cygwin_premain0 (int argc, char **argv); -extern void cygwin_premain1 (int argc, char **argv); -extern void cygwin_premain2 (int argc, char **argv); -extern void cygwin_premain3 (int argc, char **argv); - struct __cygwin_perfile { const char *name; @@ -149,7 +144,7 @@ struct per_process void *(*calloc)(size_t, size_t); /* For future expansion of values set by the app. */ - void (*premain[4]) (int, char **); + void (*premain[4]) (int, char **, struct per_process *); /* The rest are *internal* to cygwin.dll. Those that are here because we want the child to inherit the value from @@ -165,7 +160,7 @@ struct per_process void *heapptr; /* current index into heap */ void *heaptop; /* current top of heap */ - DWORD unused1; /* unused */ + DWORD unused1; /* Non-zero means the task was forked. The value is the pid. Inherited from parent. */ @@ -190,6 +185,11 @@ struct per_process }; #define per_process_overwrite ((unsigned) &(((struct per_process *) NULL)->resourcelocks)) +extern void cygwin_premain0 (int argc, char **argv, struct per_process *); +extern void cygwin_premain1 (int argc, char **argv, struct per_process *); +extern void cygwin_premain2 (int argc, char **argv, struct per_process *); +extern void cygwin_premain3 (int argc, char **argv, struct per_process *); + extern void cygwin_set_impersonation_token (const HANDLE); /* included if is included */ diff --git a/winsup/cygwin/include/sys/file.h b/winsup/cygwin/include/sys/file.h index 79f5f65f5..dacf33429 100644 --- a/winsup/cygwin/include/sys/file.h +++ b/winsup/cygwin/include/sys/file.h @@ -24,7 +24,13 @@ #define F_OK 0 /* does file exist */ -#define X_OK 1 /* is it executable by caller */ +#define _X_OK 1 /* is it executable by caller */ +#if defined (__CYGWIN__) || defined (__INSIDE_CYGWIN__) +# define X_OK _X_OK /* Check for execute permission. */ +#else +extern const unsigned _cygwin_X_OK; +# define X_OK _cygwin_X_OK +#endif #define W_OK 2 /* is it writable by caller */ #define R_OK 4 /* is it readable by caller */ diff --git a/winsup/cygwin/lib/_cygwin_S_IEXEC.cc b/winsup/cygwin/lib/_cygwin_S_IEXEC.cc new file mode 100644 index 000000000..eeb12f4a2 --- /dev/null +++ b/winsup/cygwin/lib/_cygwin_S_IEXEC.cc @@ -0,0 +1,29 @@ +/* _cygwin_S_IEXEC.cc: stat helper stuff + + Copyright 2001 Red Hat, Inc. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#if 0 +#include "windows.h" +#include +#include "perprocess.h" +#endif +#include +#include + +const unsigned _cygwin_S_IEXEC = S_IEXEC; +const unsigned _cygwin_S_IXUSR = S_IXUSR; +const unsigned _cygwin_S_IXGRP = S_IXGRP; +const unsigned _cygwin_S_IXOTH = S_IXOTH; +const unsigned _cygwin_X_OK = X_OK; + +extern int __declspec (dllimport) _check_for_executable; +struct _cygwin_bob__ +{ + _cygwin_bob__ () {_check_for_executable = 1;} +} _cygwin_dummy_bob__; diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index fcada7b7f..837f3b9ff 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -25,6 +25,7 @@ details. */ #include #include "cygheap.h" #include "cygerrno.h" +#include "perprocess.h" #include "fhandler.h" #include "path.h" #include "dtable.h" diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 5355f1982..cf026fe82 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -64,6 +64,7 @@ details. */ #include #include #include "cygerrno.h" +#include "perprocess.h" #include "fhandler.h" #include "path.h" #include "sync.h" @@ -412,6 +413,7 @@ out: } else { + set_isdisk (); debug_printf ("GetVolumeInformation(%s) = OK, full_path(%s), set_has_acls(%d)", tmp_buf, full_path, volflags & FS_PERSISTENT_ACLS); if (!allow_smbntsec @@ -428,6 +430,16 @@ out: if (saw_symlinks) set_has_symlinks (); + if (!error && !(path_flags & (PATH_ALL_EXEC | PATH_NOTEXEC))) + { + const char *p = strchr (path, '\0') - 4; + if (p >= path && + (strcasematch (".exe", p) || + strcasematch (".bat", p) || + strcasematch (".com", p))) + path_flags |= PATH_EXEC; + } + #if 0 if (!error) { @@ -565,7 +577,7 @@ get_device_number (const char *name, int &unit, BOOL from_conv) else if (deveq ("tcp") || deveq ("udp") || deveq ("streamsocket") || deveq ("dgsocket")) devn = FH_SOCKET; - else if (! from_conv) + else if (!from_conv) devn = get_raw_device_number (name - 5, path_conv (name - 5, PC_SYM_IGNORE).get_win32 (), @@ -821,7 +833,6 @@ normalize_win32_path (const char *src, char *dst) debug_printf ("%s = normalize_win32_path (%s)", dst_start, src_start); return 0; } - /* Various utilities. */ @@ -1303,7 +1314,7 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path, for (int i = 0; i < nmounts; ++i) { mount_item &mi = mount[native_sorted[i]]; - if (! path_prefix_p (mi.native_path, pathbuf, mi.native_pathlen)) + if (!path_prefix_p (mi.native_path, pathbuf, mi.native_pathlen)) continue; /* SRC_PATH is in the mount table. */ @@ -1387,7 +1398,7 @@ mount_info::read_mounts (reg_key& r) posix_path_size = MAX_PATH; /* FIXME: if maximum posix_path_size is 256, we're going to run into problems if we ever try to store a mount point that's - over 256 but is under MAX_PATH! */ + over 256 but is under MAX_PATH. */ res = RegEnumKeyEx (key, i, posix_path, &posix_path_size, NULL, NULL, NULL, NULL); @@ -1503,7 +1514,7 @@ mount_info::add_reg_mount (const char * native_path, const char * posix_path, un cygwin_shared->sys_mount_table_counter++; } - return 0; /* Success! */ + return 0; /* Success */ err: __seterrno_from_win_error (res); return -1; @@ -1542,7 +1553,7 @@ mount_info::del_reg_mount (const char * posix_path, unsigned flags) return -1; } - return 0; /* Success! */ + return 0; /* Success */ } /* read_cygdrive_info_from_registry: Read the default prefix and flags @@ -2060,7 +2071,7 @@ mount_item::getmntent () binary or textmode, or exec. We don't print `silent' here; it's a magic internal thing. */ - if (! (flags & MOUNT_BINARY)) + if (!(flags & MOUNT_BINARY)) strcpy (mount_table->mnt_opts, (char *) "textmode"); else strcpy (mount_table->mnt_opts, (char *) "binmode"); @@ -2333,36 +2344,6 @@ done: return res; } -static __inline char * -has_suffix (const char *path, const suffix_info *suffixes) -{ - assert (path); - char *ext = strrchr (path, '.'); - if (ext) - for (const suffix_info *ex = suffixes; ex->name != NULL; ex++) - if (strcasematch (ext, ex->name)) - return ext; - return NULL; -} - -static __inline__ int -next_suffix (char *ext_here, const suffix_info *&suffixes) -{ - if (!suffixes) - return 1; - - while (suffixes && suffixes->name) - if (!suffixes->addon) - suffixes++; - else - { - strcpy (ext_here, suffixes->name); - suffixes++; - return 1; - } - return 0; -} - static int check_sysfile (const char *path, DWORD fileattr, HANDLE h, char *contents, int *error, unsigned *pflags) @@ -2371,7 +2352,7 @@ check_sysfile (const char *path, DWORD fileattr, HANDLE h, DWORD got; int res = 0; - if (! ReadFile (h, cookie_buf, sizeof (cookie_buf), &got, 0)) + if (!ReadFile (h, cookie_buf, sizeof (cookie_buf), &got, 0)) { debug_printf ("ReadFile1 failed"); *error = EIO; @@ -2408,12 +2389,107 @@ check_sysfile (const char *path, DWORD fileattr, HANDLE h, else { /* Not a symlink, see if executable. */ - if (!(*pflags & PATH_ALL_EXEC) && has_exec_chars (cookie_buf, got)) + if (*pflags & PATH_ALL_EXEC) + /* Nothing to do */; + else if (has_exec_chars (cookie_buf, got)) *pflags |= PATH_EXEC; - } + else + *pflags |= PATH_NOTEXEC; + } + syscall_printf ("%d = symlink.check_sysfile (%s, %s) (%p)", + res, path, contents, *pflags); return res; } +#define SCAN_BEG 0 +#define SCAN_LNK 1 +#define SCAN_TERM1 2 +#define SCAN_JUSTCHECK 3 + +class suffix_scan +{ + char *ext_here; + const suffix_info *suffixes; + int state; + int nullterm; +public: + const char *path; + char *has (const char *, const suffix_info *, char **); + int next (); + int lnk_match () {return state == SCAN_LNK + 1;} +}; + +char * +suffix_scan::has (const char *in_path, const suffix_info *in_suffixes, char **ext_where) +{ + path = in_path; + suffixes = in_suffixes; + nullterm = 0; + state = SCAN_BEG; + if (suffixes) + { + ext_here = *ext_where = strrchr (in_path, '.'); + if (ext_here) + { + /* Check if the extension matches a known extension */ + for (const suffix_info *ex = in_suffixes; ex->name != NULL; ex++) + if (strcasematch (ext_here, ex->name)) + { + state = SCAN_JUSTCHECK; + goto known_suffix; + } + /* Didn't match. Use last resort -- .lnk. */ + if (strcasematch (ext_here, ".lnk")) + { + state = SCAN_LNK; + goto known_suffix; + } + } + } + + /* Didn't find a matching suffix. */ + ext_here = *ext_where = strchr (path, '\0'); + nullterm = 1; + return NULL; + + known_suffix: + suffixes = NULL; /* Has an extension so don't scan for one. */ + return ext_here; +} + +int +suffix_scan::next () +{ + if (suffixes) + { + while (suffixes && suffixes->name) + if (!suffixes->addon) + suffixes++; + else + { + strcpy (ext_here, suffixes->name); + suffixes++; + return 1; + } + suffixes = NULL; + state++; + } + + switch (state++) + { + case SCAN_LNK: + strcpy (ext_here, ".lnk"); + /* fall through */ + case SCAN_BEG: + case SCAN_JUSTCHECK: + return 1; + default: + if (nullterm && ext_here) + *ext_here = '\0'; + return 0; + } +} + /* Check if PATH is a symlink. PATH must be a valid Win32 path name. If PATH is a symlink, put the value of the symlink--the file to @@ -2432,43 +2508,25 @@ check_sysfile (const char *path, DWORD fileattr, HANDLE h, stored into BUF if PATH is a symlink. */ int -symlink_info::check (const char *in_path, const suffix_info *suffixes) +symlink_info::check (const char *path, const suffix_info *suffixes) { HANDLE h; int res = 0; - char extbuf[MAX_PATH + 5]; - const char *path = in_path; - BOOL check_lnk = FALSE; - - if (!suffixes) - ext_here = NULL; - else if ((known_suffix = has_suffix (in_path, suffixes)) != NULL) - { - suffixes = NULL; - ext_here = NULL; - } - else - { -restart: - path = strcpy (extbuf, in_path); - ext_here = strchr (path, '\0'); - } + suffix_scan suffix; is_symlink = TRUE; + known_suffix = suffix.has (path, suffixes, &ext_here); - error = 0; - do + while (suffix.next ()) { - if (!next_suffix (ext_here, suffixes)) - break; error = 0; - fileattr = GetFileAttributesA (path); + fileattr = GetFileAttributesA (suffix.path); if (fileattr == (DWORD) -1) { /* The GetFileAttributesA call can fail for reasons that don't matter, so we just return 0. For example, getting the attributes of \\HOST will typically fail. */ - debug_printf ("GetFileAttributesA (%s) failed", path); + debug_printf ("GetFileAttributesA (%s) failed", suffix.path); error = geterrno_from_win_error (GetLastError (), EACCES); continue; } @@ -2479,7 +2537,7 @@ restart: goto file_not_symlink; /* Windows shortcuts are treated as symlinks. */ - if (!strcasecmp (path + strlen (path) - 4, ".lnk")) + if (suffix.lnk_match ()) sym_check = 1; /* The old Cygwin method creating symlinks: */ @@ -2493,27 +2551,27 @@ restart: /* Open the file. */ - h = CreateFileA (path, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih, OPEN_EXISTING, + h = CreateFileA (suffix.path, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); res = -1; if (h == INVALID_HANDLE_VALUE) goto file_not_symlink; else if (sym_check == 1 - && !(res = check_shortcut (path, fileattr, h, + && !(res = check_shortcut (suffix.path, fileattr, h, contents, &error, &pflags))) { CloseHandle (h); /* If searching for `foo' and then finding a `foo.lnk' which is no shortcut, return the same as if file not found. */ - if (check_lnk) + if (suffix.lnk_match ()) { fileattr = (DWORD)-1; - goto out; + break; } goto file_not_symlink; } else if (sym_check == 2 && - !(res = check_sysfile (path, fileattr, h, + !(res = check_sysfile (suffix.path, fileattr, h, contents, &error, &pflags))) { CloseHandle (h); @@ -2521,14 +2579,7 @@ restart: } CloseHandle (h); - goto out; - } - while (suffixes); - if (!check_lnk) - { - suffixes = lnk_suffixes; - check_lnk = TRUE; - goto restart; + break; } goto out; @@ -2539,8 +2590,7 @@ file_not_symlink: out: syscall_printf ("%d = symlink.check (%s, %p) (%p)", - res, path, contents, pflags); - + res, suffix.path, contents, pflags); return res; } @@ -2846,7 +2896,7 @@ extern "C" int cygwin_posix_path_list_p (const char *path) { - int posix_p = ! (strchr (path, ';') || isdrive (path)); + int posix_p = !(strchr (path, ';') || isdrive (path)); return posix_p; } @@ -2946,7 +2996,7 @@ cygwin_split_path (const char *path, char *dir, char *file) *dir++ = *path++; *dir++ = *path++; *dir++ = '/'; - if (! *path) + if (!*path) { *dir = 0; *file = 0; diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index 6d0a195e3..40b8eec5b 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -37,6 +37,8 @@ enum path_types PATH_EXEC = MOUNT_EXEC, PATH_CYGWIN_EXEC = MOUNT_CYGWIN_EXEC, PATH_ALL_EXEC = PATH_CYGWIN_EXEC | PATH_EXEC, + PATH_ISDISK = 0x04000000, + PATH_NOTEXEC = 0x08000000, PATH_HAS_SYMLINKS = 0x10000000, PATH_HASBUGGYOPEN = 0x20000000, PATH_SOCKET = 0x40000000, @@ -50,6 +52,7 @@ class path_conv unsigned path_flags; + int isdisk () {return path_flags & PATH_ISDISK;} int has_acls () {return path_flags & PATH_HASACLS;} int has_symlinks () {return path_flags & PATH_HAS_SYMLINKS;} int hasgood_inode () {return path_flags & PATH_HASACLS;} // Not strictly correct @@ -57,13 +60,24 @@ class path_conv int isbinary () {return path_flags & PATH_BINARY;} int issymlink () {return path_flags & PATH_SYMLINK;} int issocket () {return path_flags & PATH_SOCKET;} - int isexec () {return path_flags & PATH_ALL_EXEC;} int iscygexec () {return path_flags & PATH_CYGWIN_EXEC;} + executable_states exec_state () + { + extern int _check_for_executable; + if (path_flags & PATH_ALL_EXEC) + return is_executable; + if (path_flags & PATH_NOTEXEC) + return not_executable; + if (!_check_for_executable) + return dont_care_if_executable; + return dont_know_if_executable; + } void set_binary () {path_flags |= PATH_BINARY;} void set_symlink () {path_flags |= PATH_SYMLINK;} void set_has_symlinks () {path_flags |= PATH_HAS_SYMLINKS;} - void set_exec (int x = 1) {path_flags |= x ? PATH_EXEC : PATH_NOTHING;} + void set_isdisk () {path_flags |= PATH_ISDISK;} + void set_exec (int x = 1) {path_flags |= x ? PATH_EXEC : PATH_NOTEXEC;} void set_has_acls (int x = 1) {path_flags |= x ? PATH_HASACLS : PATH_NOTHING;} void set_has_buggy_open (int x = 1) {path_flags |= x ? PATH_HASBUGGYOPEN : PATH_NOTHING;} diff --git a/winsup/cygwin/perprocess.h b/winsup/cygwin/perprocess.h index a649ece74..c0a555983 100644 --- a/winsup/cygwin/perprocess.h +++ b/winsup/cygwin/perprocess.h @@ -1,6 +1,6 @@ /* per_process.h: main Cygwin header file. - Copyright 2000 Red Hat, Inc. + Copyright 2000, 2001 Red Hat, Inc. This file is part of Cygwin. @@ -10,11 +10,19 @@ details. */ #include +#ifdef __cplusplus +extern "C" { +#endif + /* Pointer into application's static data */ -extern "C" per_process __cygwin_user_data; +extern struct per_process __cygwin_user_data; #define user_data (&__cygwin_user_data) /* We use the following to test that sizeof hasn't changed. When adding or deleting members, insert fillers or use the reserved entries. Do not change this value. */ #define SIZEOF_PER_PROCESS (42 * 4) + +#ifdef __cplusplus +} +#endif diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index bef29d2cf..a92236549 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -25,6 +25,7 @@ details. */ #include #include #include "cygerrno.h" +#include "perprocess.h" #include "fhandler.h" #include "path.h" #include "dtable.h" diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 75c3a8d14..e9d3659b2 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -21,6 +21,7 @@ details. */ #include #include "cygerrno.h" #include +#include "perprocess.h" #include "fhandler.h" #include "path.h" #include "dtable.h" diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index eedf59ace..2497d8bf8 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -26,6 +26,7 @@ details. */ #include #include #include "cygerrno.h" +#include "perprocess.h" #include "fhandler.h" #include "path.h" #include "dtable.h" @@ -34,7 +35,6 @@ details. */ #include "pinfo.h" #include #include "shared_info.h" -#include "perprocess.h" #include "security.h" #include "cygheap.h" @@ -1071,7 +1071,7 @@ stat_worker (const char *caller, const char *name, struct stat *buf, atts = real_path.file_attributes (); - debug_printf ("%d = GetFileAttributesA (%s)", atts, real_path.get_win32 ()); + debug_printf ("%d = file_attributes for '%s'", atts, real_path.get_win32 ()); strcpy (root, real_path.get_win32 ()); dtype = GetDriveType (rootdir (root)); diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index a7bc08687..1578cdfca 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -14,8 +14,6 @@ details. */ #define __INSIDE_CYGWIN__ -#ifdef __cplusplus - #define alloca __builtin_alloca #define strlen __builtin_strlen #define strcmp __builtin_strcmp @@ -26,6 +24,8 @@ details. */ # define memset __builtin_memset #endif +#ifdef __cplusplus + #if !defined(__STDC_VERSION__) || __STDC_VERSION__ >= 199900L #define NEW_MACRO_VARARGS #endif