diff options
-rw-r--r-- | winsup/cygwin/dlfcn.cc | 3 | ||||
-rw-r--r-- | winsup/cygwin/fhandler/base.cc | 48 | ||||
-rw-r--r-- | winsup/cygwin/fhandler/console.cc | 32 | ||||
-rw-r--r-- | winsup/cygwin/fhandler/pty.cc | 30 | ||||
-rw-r--r-- | winsup/cygwin/fhandler/termios.cc | 31 | ||||
-rw-r--r-- | winsup/cygwin/fork.cc | 2 | ||||
-rw-r--r-- | winsup/cygwin/include/sys/termios.h | 1 | ||||
-rw-r--r-- | winsup/cygwin/local_includes/fhandler.h | 7 | ||||
-rw-r--r-- | winsup/cygwin/local_includes/thread.h | 31 | ||||
-rw-r--r-- | winsup/cygwin/local_includes/tty.h | 6 | ||||
-rw-r--r-- | winsup/cygwin/release/3.6.1 | 18 | ||||
-rw-r--r-- | winsup/cygwin/thread.cc | 36 | ||||
-rw-r--r-- | winsup/doc/faq-using.xml | 5 | ||||
-rw-r--r-- | winsup/testsuite/winsup.api/ltp/sbrk01.c | 2 | ||||
-rw-r--r-- | winsup/testsuite/winsup.api/ltp/symlink01.c | 172 |
15 files changed, 282 insertions, 142 deletions
diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc index f029ebb..10bd0ac 100644 --- a/winsup/cygwin/dlfcn.cc +++ b/winsup/cygwin/dlfcn.cc @@ -408,7 +408,8 @@ extern "C" int dladdr (const void *addr, Dl_info *info) { HMODULE hModule; - BOOL ret = GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + BOOL ret = GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT| + GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR) addr, &hModule); if (!ret) diff --git a/winsup/cygwin/fhandler/base.cc b/winsup/cygwin/fhandler/base.cc index a5d15c7..32aca2c 100644 --- a/winsup/cygwin/fhandler/base.cc +++ b/winsup/cygwin/fhandler/base.cc @@ -526,8 +526,9 @@ fhandler_base::open (int flags, mode_t mode) ULONG file_attributes = 0; ULONG shared = (get_major () == DEV_TAPE_MAJOR ? 0 : FILE_SHARE_VALID_FLAGS); ULONG create_disposition; + FILE_BASIC_INFORMATION fbi; OBJECT_ATTRIBUTES attr; - IO_STATUS_BLOCK io; + IO_STATUS_BLOCK io, io_bi; NTSTATUS status; PFILE_FULL_EA_INFORMATION p = NULL; ULONG plen = 0; @@ -719,16 +720,32 @@ fhandler_base::open (int flags, mode_t mode) goto done; } - if (io.Information == FILE_CREATED) - { - /* Correct file attributes are needed for later use in, e.g. fchmod. */ - FILE_BASIC_INFORMATION fbi; + /* Fix up file attributes, they are desperately needed later. + + Originally we only did that in the FILE_CREATED case below, but that's + insufficient: - if (!NT_SUCCESS (NtQueryInformationFile (fh, &io, &fbi, sizeof fbi, - FileBasicInformation))) - fbi.FileAttributes = file_attributes | FILE_ATTRIBUTE_ARCHIVE; - pc.file_attributes (fbi.FileAttributes); + If two threads try to create the same file at the same time, it's + possible that path_conv::check returns the file as non-existant, i. e., + pc.file_attributes () returns INVALID_FILE_ATTRIBUTES, 0xffffffff. + However, one of the NtCreateFile will beat the other, so only one of + them returns with FILE_CREATED. + The other fhandler_base::open() will instead run into the O_TRUNC + conditional (further below), blindly check for the SPARSE attribute + and remove that bit. The result is that the attributes will be + 0xfffffdff, i.e., everything but SPARSE. Most annoying is that + pc.isdir() will return TRUE. Hilarity ensues. + + Note that we use a different IO_STATUS_BLOCK, so as not to overwrite + io.Information... */ + if (!NT_SUCCESS (NtQueryInformationFile (fh, &io_bi, &fbi, sizeof fbi, + FileBasicInformation))) + fbi.FileAttributes = file_attributes | FILE_ATTRIBUTE_ARCHIVE; + pc.file_attributes (fbi.FileAttributes); + + if (io.Information == FILE_CREATED) + { /* Always create files using a NULL SD. Create correct permission bits afterwards, maintaining the owner and group information just like chmod. This is done for two reasons. @@ -752,18 +769,17 @@ fhandler_base::open (int flags, mode_t mode) set_created_file_access (fh, pc, mode); } - /* If you O_TRUNC a file on Linux, the data is truncated, but the EAs are - preserved. If you open a file on Windows with FILE_OVERWRITE{_IF} or - FILE_SUPERSEDE, all streams are truncated, including the EAs. So we don't - use the FILE_OVERWRITE{_IF} flags, but instead just open the file and set - the size of the data stream explicitely to 0. Apart from being more Linux - compatible, this implementation has the pleasant side-effect to be more - than 5% faster than using FILE_OVERWRITE{_IF} (tested on W7 32 bit). */ if ((flags & O_TRUNC) && (flags & O_ACCMODE) != O_RDONLY && io.Information != FILE_CREATED && get_device () == FH_FS) { + /* If you O_TRUNC a file on Linux, the data is truncated, but the EAs are + preserved. If you open a file on Windows with FILE_OVERWRITE{_IF} or + FILE_SUPERSEDE, all streams are truncated, including the EAs. So we + don't use FILE_OVERWRITE{_IF} but just open the file and truncate the + data stream to size 0. Apart from being more Linux compatible, this + has the pleasant side-effect to be more than 5% faster. */ FILE_END_OF_FILE_INFORMATION feofi = { EndOfFile:{ QuadPart:0 } }; status = NtSetInformationFile (fh, &io, &feofi, sizeof feofi, FileEndOfFileInformation); diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc index f162698..c613643 100644 --- a/winsup/cygwin/fhandler/console.cc +++ b/winsup/cygwin/fhandler/console.cc @@ -509,7 +509,7 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp) case not_signalled_but_done: case done_with_debugger: processed = true; - ttyp->output_stopped = false; + ttyp->output_stopped &= ~BY_VSTOP; if (ti.c_lflag & NOFLSH) goto remove_record; con.num_processed = 0; @@ -1144,6 +1144,15 @@ fhandler_console::read (void *pv, size_t& buflen) push_process_state process_state (PID_TTYIN); + if (get_ttyp ()->input_stopped && is_nonblocking ()) + { + set_errno (EAGAIN); + buflen = (size_t) -1; + return; + } + while (get_ttyp ()->input_stopped) + cygwait (10); + size_t copied_chars = 0; DWORD timeout = is_nonblocking () ? 0 : @@ -2131,6 +2140,7 @@ fhandler_console::ioctl (unsigned int cmd, void *arg) release_output_mutex (); return -1; case FIONREAD: + case TIOCINQ: { DWORD n; int ret = 0; @@ -2183,6 +2193,14 @@ fhandler_console::ioctl (unsigned int cmd, void *arg) return 0; } break; + case TCXONC: + res = this->tcflow ((int)(intptr_t) arg); + release_output_mutex (); + return res; + case TCFLSH: + res = this->tcflush ((int)(intptr_t) arg); + release_output_mutex (); + return res; } release_output_mutex (); @@ -2215,6 +2233,8 @@ int fhandler_console::tcsetattr (int a, struct termios const *t) { get_ttyp ()->ti = *t; + set_input_mode (tty::cygwin, t, &handle_set); + set_output_mode (tty::cygwin, t, &handle_set); return 0; } @@ -4170,8 +4190,8 @@ fhandler_console::write (const void *vsrc, size_t len) void fhandler_console::doecho (const void *str, DWORD len) { - bool stopped = get_ttyp ()->output_stopped; - get_ttyp ()->output_stopped = false; + int stopped = get_ttyp ()->output_stopped; + get_ttyp ()->output_stopped = 0; write (str, len); get_ttyp ()->output_stopped = stopped; } @@ -4709,3 +4729,9 @@ fhandler_console::cons_mode_on_close () return tty::restore; /* otherwise, restore */ } + +int +fhandler_console::tcdrain () +{ + return 0; +} diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc index 3128b92..b882b90 100644 --- a/winsup/cygwin/fhandler/pty.cc +++ b/winsup/cygwin/fhandler/pty.cc @@ -1304,6 +1304,15 @@ fhandler_pty_slave::read (void *ptr, size_t& len) push_process_state process_state (PID_TTYIN); + if (get_ttyp ()->input_stopped && is_nonblocking ()) + { + set_errno (EAGAIN); + len = (size_t) -1; + return; + } + while (get_ttyp ()->input_stopped) + cygwait (10); + if (ptr) /* Indicating not tcflush(). */ mask_switch_to_nat_pipe (true, true); @@ -1650,6 +1659,7 @@ fhandler_pty_slave::ioctl (unsigned int cmd, void *arg) retval = this->tcsetpgrp ((pid_t) (intptr_t) arg); goto out; case FIONREAD: + case TIOCINQ: { DWORD n; if (!bytes_available (n)) @@ -1664,6 +1674,12 @@ fhandler_pty_slave::ioctl (unsigned int cmd, void *arg) } } goto out; + case TCXONC: + retval = this->tcflow ((int)(intptr_t) arg); + goto out; + case TCFLSH: + retval = this->tcflush ((int)(intptr_t) arg); + goto out; default: return fhandler_base::ioctl (cmd, arg); } @@ -2342,6 +2358,7 @@ fhandler_pty_master::ioctl (unsigned int cmd, void *arg) case TIOCSPGRP: return this->tcsetpgrp ((pid_t) (intptr_t) arg); case FIONREAD: + case TIOCINQ: { DWORD n; if (!bytes_available (n)) @@ -2352,6 +2369,10 @@ fhandler_pty_master::ioctl (unsigned int cmd, void *arg) *(int *) arg = (int) n; } break; + case TCXONC: + return this->tcflow ((int)(intptr_t) arg); + case TCFLSH: + return this->tcflush ((int)(intptr_t) arg); default: return fhandler_base::ioctl (cmd, arg); } @@ -4194,3 +4215,12 @@ fhandler_pty_common::resume_from_temporarily_attach (DWORD resume_pid) } release_attach_mutex (); } + +int +fhandler_pty_common::tcdrain () +{ + DWORD n; + while (bytes_available (n) && n > 0) + cygwait (10); + return 0; +} diff --git a/winsup/cygwin/fhandler/termios.cc b/winsup/cygwin/fhandler/termios.cc index a3cecdb..19d6220 100644 --- a/winsup/cygwin/fhandler/termios.cc +++ b/winsup/cygwin/fhandler/termios.cc @@ -491,16 +491,16 @@ fhandler_termios::process_stop_start (char c, tty *ttyp) { if (CCEQ (ti.c_cc[VSTOP], c)) { - ttyp->output_stopped = true; + ttyp->output_stopped |= BY_VSTOP; return true; } else if (CCEQ (ti.c_cc[VSTART], c)) { restart_output: - ttyp->output_stopped = false; + ttyp->output_stopped &= ~BY_VSTOP; return true; } - else if ((ti.c_iflag & IXANY) && ttyp->output_stopped) + else if ((ti.c_iflag & IXANY) && (ttyp->output_stopped & BY_VSTOP)) goto restart_output; } if ((ti.c_lflag & ICANON) && (ti.c_lflag & IEXTEN) @@ -540,7 +540,7 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti, fallthrough; case not_signalled_but_done: case done_with_debugger: - get_ttyp ()->output_stopped = false; + get_ttyp ()->output_stopped &= ~BY_VSTOP; continue; case not_signalled_with_nat_reader: disable_eof_key = true; @@ -915,3 +915,26 @@ fhandler_termios::get_console_process_id (DWORD pid, bool match, } return res_pri ?: res; } + +int +fhandler_termios::tcflow (int action) +{ + switch (action) + { + case TCOOFF: + get_ttyp ()->output_stopped |= BY_TCFLOW; + return 0; + case TCOON: + get_ttyp ()->output_stopped = 0; + return 0; + case TCIOFF: + get_ttyp ()->input_stopped |= BY_TCFLOW; + return 0; + case TCION: + get_ttyp ()->input_stopped = 0; + return 0; + default: + set_errno (EINVAL); + return -1; + } +} diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index 783971b..f88acdb 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -187,7 +187,6 @@ frok::child (volatile char * volatile here) ForceCloseHandle1 (fork_info->forker_finished, forker_finished); - pthread::atforkchild (); cygbench ("fork-child"); ld_preload (); fixup_hooks_after_fork (); @@ -199,6 +198,7 @@ frok::child (volatile char * volatile here) CloseHandle (hParent); hParent = NULL; cygwin_finished_initializing = true; + pthread::atforkchild (); return 0; } diff --git a/winsup/cygwin/include/sys/termios.h b/winsup/cygwin/include/sys/termios.h index d1b4a0a..4c03042 100644 --- a/winsup/cygwin/include/sys/termios.h +++ b/winsup/cygwin/include/sys/termios.h @@ -18,6 +18,7 @@ details. */ #define TIOCMBIC 0x5417 #define TIOCMSET 0x5418 #define TIOCINQ 0x541B +#define TCXONC 0x540A #define TIOCSCTTY 0x540E /* TIOCINQ is utilized instead of FIONREAD which has been diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h index 8c71d84..2177cec 100644 --- a/winsup/cygwin/local_includes/fhandler.h +++ b/winsup/cygwin/local_includes/fhandler.h @@ -1979,6 +1979,7 @@ class fhandler_termios: public fhandler_base virtual off_t lseek (off_t, int); pid_t tcgetsid (); virtual int fstat (struct stat *buf); + int tcflow (int); fhandler_termios (void *) {} @@ -2143,12 +2144,12 @@ class dev_console char cons_rabuf[40]; // cannot get longer than char buf[40] in char_command char *cons_rapoi; bool cursor_key_app_mode; - bool disable_master_thread; + volatile bool disable_master_thread; tty::cons_mode curr_input_mode; tty::cons_mode curr_output_mode; DWORD prev_input_mode; DWORD prev_output_mode; - bool master_thread_suspended; + volatile bool master_thread_suspended; int num_processed; /* Number of input events in the current input buffer already processed by cons_master_thread(). */ @@ -2273,6 +2274,7 @@ private: int tcflush (int); int tcsetattr (int a, const struct termios *t); int tcgetattr (struct termios *t); + int tcdrain (); int ioctl (unsigned int cmd, void *); int init (HANDLE, DWORD, mode_t, int64_t = 0); @@ -2391,6 +2393,7 @@ class fhandler_pty_common: public fhandler_termios DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms); void __release_output_mutex (const char *fn, int ln); + int tcdrain (); int close (int flag = -1); off_t lseek (off_t, int); bool bytes_available (DWORD& n); diff --git a/winsup/cygwin/local_includes/thread.h b/winsup/cygwin/local_includes/thread.h index b349628..3955609 100644 --- a/winsup/cygwin/local_includes/thread.h +++ b/winsup/cygwin/local_includes/thread.h @@ -221,13 +221,12 @@ public: ~pthread_key (); static void fixup_before_fork () { - keys.for_each (&pthread_key::_fixup_before_fork); + for_each (_fixup_before_fork); } static void fixup_after_fork () { - keys.fixup_after_fork (); - keys.for_each (&pthread_key::_fixup_after_fork); + for_each (_fixup_after_fork); } static void run_all_destructors () @@ -246,21 +245,39 @@ public: for (int i = 0; i < PTHREAD_DESTRUCTOR_ITERATIONS; ++i) { iterate_dtors_once_more = false; - keys.for_each (&pthread_key::run_destructor); + for_each (run_destructor); if (!iterate_dtors_once_more) break; } } - /* List support calls */ - class pthread_key *next; private: - static List<pthread_key> keys; + int key_idx; + static class keys_list { + LONG64 seq; + LONG64 busy_cnt; + pthread_key *key; + static bool used (LONG64 seq1) { return (seq1 & 3) != 0; } + static bool ready (LONG64 seq1) { return (seq1 & 3) == 2; } + public: + keys_list () : seq (0), busy_cnt (INT64_MIN), key (NULL) {} + friend class pthread_key; + } keys[PTHREAD_KEYS_MAX]; void _fixup_before_fork (); void _fixup_after_fork (); void (*destructor) (void *); void run_destructor (); void *fork_buf; + static void for_each (void (pthread_key::*callback) ()) { + for (size_t cnt = 0; cnt < PTHREAD_KEYS_MAX; cnt++) + { + if (!keys_list::ready (keys[cnt].seq)) + continue; + if (InterlockedIncrement64 (&keys[cnt].busy_cnt) > 0) + (keys[cnt].key->*callback) (); + InterlockedDecrement64 (&keys[cnt].busy_cnt); + } + } }; class pthread_attr: public verifyable_object diff --git a/winsup/cygwin/local_includes/tty.h b/winsup/cygwin/local_includes/tty.h index 2a047d7..a418ab1 100644 --- a/winsup/cygwin/local_includes/tty.h +++ b/winsup/cygwin/local_includes/tty.h @@ -30,6 +30,9 @@ details. */ #define MIN_CTRL_C_SLOP 50 #endif +#define BY_TCFLOW 2 +#define BY_VSTOP 1 + typedef void *HPCON; #include "devices.h" @@ -43,7 +46,8 @@ class tty_min public: pid_t pgid; - bool output_stopped; /* FIXME: Maybe do this with a mutex someday? */ + volatile int output_stopped; /* FIXME: Maybe do this with a mutex someday? */ + volatile int input_stopped; fh_devices ntty; ULONGLONG last_ctrl_c; /* tick count of last ctrl-c */ bool is_console; diff --git a/winsup/cygwin/release/3.6.1 b/winsup/cygwin/release/3.6.1 index 07a29ec..e24766d 100644 --- a/winsup/cygwin/release/3.6.1 +++ b/winsup/cygwin/release/3.6.1 @@ -31,3 +31,21 @@ Fixes: - Return EMFILE when opening /dev/ptmx too many times. Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257786.html + +- Move pthread::atforkchild() at the end of fork::child(). This fixes + subprocess failure in cmake (>= 3.29.x). + Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257800.html + Addresses: https://github.com/msys2/msys2-runtime/issues/272 + +- Don't increment DLL reference count in dladdr. + Addresses: https://cygwin.com/pipermail/cygwin/2025-April/257862.html + +- Fix tcsetattr() for console which has been broken sinse cygwin 3.5.5. + +- Fix up cached DOS attributes when trying to create the same file in + two (or more) threads/processes concurrently. + Addresses: https://cygwin.com/pipermail/cygwin/2025-April/257871.html + +- Fix deadlock when calling pthread_key_create in the destructor of + a pthread_key. + Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257705.html diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 9ee9650..fea6079 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -1666,27 +1666,49 @@ pthread_rwlock::_fixup_after_fork () /* pthread_key */ /* static members */ /* This stores pthread_key information across fork() boundaries */ -List<pthread_key> pthread_key::keys; +pthread_key::keys_list pthread_key::keys[PTHREAD_KEYS_MAX]; /* non-static members */ -pthread_key::pthread_key (void (*aDestructor) (void *)):verifyable_object (PTHREAD_KEY_MAGIC), destructor (aDestructor) +pthread_key::pthread_key (void (*aDestructor) (void *)) : + verifyable_object (PTHREAD_KEY_MAGIC), destructor (aDestructor) { tls_index = TlsAlloc (); if (tls_index == TLS_OUT_OF_INDEXES) magic = 0; else - keys.insert (this); + for (size_t cnt = 0; cnt < PTHREAD_KEYS_MAX; cnt++) + { + LONG64 seq = keys[cnt].seq; + if (!keys_list::used (seq) + && InterlockedCompareExchange64 (&keys[cnt].seq, + seq + 1, seq) == seq) + { + keys[cnt].key = this; + keys[cnt].busy_cnt = 0; + key_idx = cnt; + InterlockedIncrement64 (&keys[key_idx].seq); + break; + } + } } pthread_key::~pthread_key () { - /* We may need to make the list code lock the list during operations - */ if (magic != 0) { - keys.remove (this); - TlsFree (tls_index); + LONG64 seq = keys[key_idx].seq; + if (keys_list::ready (seq) + && InterlockedCompareExchange64 (&keys[key_idx].seq, + seq + 1, seq) == seq) + { + while (InterlockedCompareExchange64 (&keys[key_idx].busy_cnt, + INT64_MIN, 0) > 0) + yield (); + keys[key_idx].key = NULL; + InterlockedIncrement64 (&keys[key_idx].seq); + TlsFree (tls_index); + } } } diff --git a/winsup/doc/faq-using.xml b/winsup/doc/faq-using.xml index e5e4479..111702c 100644 --- a/winsup/doc/faq-using.xml +++ b/winsup/doc/faq-using.xml @@ -855,6 +855,11 @@ possible to preset the sparse attribute with <literal>chattr</literal>. ---a-S-------- 2/is_sparse ---a-S-------- 2/maybe_sparse ---a-S-------- 2/not_sparse + $ lssparse -H 0/is_sparse # from cygutils-extra package + Hole range[1]: offset=0x0, length=0x100000 + Data range[2]: offset=0x100000, length=0x4 + $ lssparse -H 0/not_sparse + Data range[1]: offset=0x0, length=0x100004 </screen> <para>With <literal>sparse</literal> mount option or a SSD, all <literal>?/maybe_sparse</literal> files would be sparse. diff --git a/winsup/testsuite/winsup.api/ltp/sbrk01.c b/winsup/testsuite/winsup.api/ltp/sbrk01.c index 700fb6b..ed30338 100644 --- a/winsup/testsuite/winsup.api/ltp/sbrk01.c +++ b/winsup/testsuite/winsup.api/ltp/sbrk01.c @@ -140,7 +140,7 @@ main(int ac, char **av) ***************************************************************/ if ( (msg=parse_opts(ac, av, (option_t *) NULL, NULL)) != (char *) NULL ) { tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); - tst_exit(0); + tst_exit(); } /*************************************************************** diff --git a/winsup/testsuite/winsup.api/ltp/symlink01.c b/winsup/testsuite/winsup.api/ltp/symlink01.c index 186a85b..a1441c6 100644 --- a/winsup/testsuite/winsup.api/ltp/symlink01.c +++ b/winsup/testsuite/winsup.api/ltp/symlink01.c @@ -288,26 +288,27 @@ #include "test.h" #include "usctest.h" +struct all_test_cases; void setup(); void cleanup(void) __attribute__((noreturn)); void help(); -void delete_files(); -void do_EEXIST(); -void do_ENOENT(); -void do_ELOOP(); -void do_ENOTDIR(); -void do_EXDEV(); -void do_ENAMETOOLONG(); -void do_EINVAL(); -void do_readlink(); -void do_stat(); -void do_chdir(); -void do_link(); -void do_unlink(); -void do_chmod(); -void do_utime(); -void do_rename(); -void do_open(); +void delete_files(char *path1, char *path2); +void do_EEXIST(struct all_test_cases *tc_ptr); +void do_ENOENT(struct all_test_cases *tc_ptr); +void do_ELOOP(struct all_test_cases *tc_ptr); +void do_ENOTDIR(struct all_test_cases *tc_ptr); +void do_EXDEV(struct all_test_cases *tc_ptr); +void do_ENAMETOOLONG(struct all_test_cases *tc_ptr); +void do_EINVAL(struct all_test_cases *tc_ptr); +void do_readlink(struct all_test_cases *tc_ptr); +void do_stat(struct all_test_cases *tc_ptr); +void do_chdir(struct all_test_cases *tc_ptr); +void do_link(struct all_test_cases *tc_ptr); +void do_unlink(struct all_test_cases *tc_ptr); +void do_chmod(struct all_test_cases *tc_ptr); +void do_utime(struct all_test_cases *tc_ptr); +void do_rename(struct all_test_cases *tc_ptr); +void do_open(struct all_test_cases *tc_ptr); #define S_FILE "symbolic" /* Name of symbolic link file */ #define O_FILE "object" /* Name of object file */ @@ -378,8 +379,14 @@ const char *msgs[] = { /* * Define test object setup and validation functions */ -int creat_both(), creat_symlink(), creat_path_max(), ck_symlink(), - creat_object(), ck_object(), ck_both(), ck_path_max(); +int creat_both(const char *path1, const char *path2, const char *path3); +int creat_symlink(const char *path1, const char *path2, const char *unused); +int creat_path_max(const char *path1, const char *path2, const char *path3); +int creat_object(const char *path1, const char *unused1, const char *unused2); +int ck_symlink(const char *path1, const char *path2, const char *path3); +int ck_object(const char *path1, const char *path2, const char *path3); +int ck_both(const char *path1, const char *path2, const char *path3); +int ck_path_max(const char *path1, const char *path2, const char *path3); /* @@ -391,10 +398,10 @@ struct all_test_cases int test_fail; int errno_val; int pass_msg; - int (*test_setup)(); - int (*ck_test)(); + int (*test_setup)(const char *, const char *, const char *); + int (*ck_test)(const char *, const char *, const char *); const char *fn_arg[3]; - + } test_objects[] = { {SYMLINK, 0, 0, 0, creat_symlink, ck_symlink, {"%bc+eFhi!k", S_FILE, NULL}}, {SYMLINK, 0, 0, 0, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}}, @@ -491,7 +498,6 @@ char test_msg[BUFMAX]; char full_path[PATH_MAX+1+1]; /* Add one for '\0' and another to exceed the PATH_MAX limit, see creat_path_max() */ extern int Tst_count; extern char *TESTDIR; -extern char *strrchr(); extern int errno; struct stat asymlink, statter; @@ -511,8 +517,8 @@ option_t Options[] = { int main(int argc, char *argv[]) { - struct tcses *tcs_ptr, *get_tcs_info(); - int do_syscalltests(); + struct tcses *tcs_ptr, *get_tcs_info(char *ptr); + int do_syscalltests(struct tcses *tcs); void cleanup(); int lc; /* loop counter */ const char *msg; /* message returned from parse_opts */ @@ -589,8 +595,7 @@ main(int argc, char *argv[]) * * Argument is path to program name. ***********************************************************************/ -struct tcses *get_tcs_info(ptr) -char *ptr; +struct tcses *get_tcs_info(char *ptr) { unsigned ctr; struct tcses *tcs_ptr; @@ -605,16 +610,14 @@ char *ptr; } #endif - for(ctr=0; ctr < (sizeof(all_tcses)/sizeof(struct tcses)); ctr++) { - if ( strcmp(ptr, all_tcses[ctr].tcid) == 0 || + if ( strcmp(ptr, all_tcses[ctr].tcid) == 0 || strcmp(ptr, all_tcses[ctr].syscall) == 0 ) { tcs_ptr = &all_tcses[ctr]; TCID = all_tcses[ctr].tcid; TST_TOTAL=tcs_ptr->test_cases; return(tcs_ptr); } - } return(NULL); } @@ -628,8 +631,7 @@ char *ptr; * link file and a minus one if the path doesn't point at a file. ***********************************************************************/ int -see_if_a_symlink(path) -char *path; +see_if_a_symlink(const char *path) { if (lstat(path, &asymlink) < 0) return(-1); @@ -644,8 +646,7 @@ char *path; * This function performs without any hesitation, file(s) deletions ***********************************************************************/ void -delete_files(path1, path2) -char *path1, *path2; +delete_files(char *path1, char *path2) { unlink(path1); unlink(path2); @@ -660,8 +661,7 @@ char *path1, *path2; * ***********************************************************************/ int -creat_symlink(path1, path2) -char *path1, *path2; +creat_symlink(const char *path1, const char *path2, const char *unused) { TEST( symlink(path1, path2) ); errno=TEST_ERRNO; @@ -671,7 +671,7 @@ char *path1, *path2; "symlink(2) Failure when creating setup %s object file: errno:%d %s", path1, errno, strerror(errno)); return(0); - } + } else { sprintf(Buf, "symlink(%s, %s) was succesful.\n", path1, path2); strcat(Buffer, Buf); @@ -690,8 +690,7 @@ char *path1, *path2; * ***********************************************************************/ int -creat_object(path1) -char *path1; +creat_object(const char *path1, const char *unused1, const char *unused2) { int fd; if ((fd=creat(path1, MODE)) == -1) { @@ -700,7 +699,7 @@ char *path1; "creat(2) Failure when creating setup %s object file: errno:%d %s", path1, errno, strerror(errno)); return(0); - } + } else { sprintf(Buf, "creat(%s, %#o) was succesful.\n", path1, MODE); strcat(Buffer, Buf); @@ -728,12 +727,11 @@ char *path1; * ***********************************************************************/ int -creat_both(path1, path2, path3) -char *path1, *path2, *path3; +creat_both(const char *path1, const char *path2, const char *path3) { - if (creat_symlink(path1, path2) == -1) + if (creat_symlink(path1, path2, NULL) == -1) return(0); - else if (creat_object(path3) == -1) + else if (creat_object(path3, NULL, NULL) == -1) return(0); return(1); } @@ -748,8 +746,7 @@ char *path1, *path2, *path3; * ***********************************************************************/ int -ck_symlink(path1, path2, path3) -char *path1, *path2, *path3; +ck_symlink(const char *path1, const char *path2, const char *path3) { int ret; @@ -780,8 +777,7 @@ char *path1, *path2, *path3; * ***********************************************************************/ int -ck_both(path1, path2, path3) -char *path1, *path2, *path3; +ck_both(const char *path1, const char *path2, const char *path3) { if (ck_symlink(path1, path2, path3) == 0) return(0); @@ -804,7 +800,6 @@ char *path1, *path2, *path3; return(0); } return(1); - } /*********************************************************************** @@ -816,8 +811,7 @@ char *path1, *path2, *path3; * Argument three is regular file name ***********************************************************************/ int -creat_path_max(path1, path2, path3) -char *path1, *path2, *path3; +creat_path_max(const char *path1, const char *path2, const char *path3) { int ctr, to_go, size, whole_chunks; char buf [PATH_MAX]; @@ -858,8 +852,7 @@ char *path1, *path2, *path3; * Argument three is regular file name ***********************************************************************/ int -ck_path_max(path1, path2, path3) -char *path1, *path2, *path3; +ck_path_max(const char *path1, const char *path2, const char *path3) { if (strlen(full_path) == (PATH_MAX+1)) return(1); @@ -884,8 +877,7 @@ char *path1, *path2, *path3; * ***********************************************************************/ int -ck_object(path1, path2, path3) -char *path1, *path2, *path3; +ck_object(const char *path1, const char *path2, const char *path3) { int ret; @@ -897,7 +889,7 @@ char *path1, *path2, *path3; } else if (ret == 1) { TEST_RESULT=TFAIL; - sprintf(test_msg, + sprintf(test_msg, "lstat(2) detected a regular object file as a symbolic link file"); return(0); } @@ -912,7 +904,6 @@ char *path1, *path2, *path3; sprintf(test_msg, "lstat(2) and stat(2) do not return same inode information for an object file"); return(0); - } return(1); } @@ -923,8 +914,7 @@ char *path1, *path2, *path3; * Argument is a ptr into the all_tcses array of structures of type tcses ***********************************************************************/ int -do_syscalltests(tcs) -struct tcses *tcs; +do_syscalltests(struct tcses *tcs) { int ctr, ret; struct all_test_cases *tc_ptr; @@ -957,20 +947,20 @@ struct tcses *tcs; } TEST_RESULT=TPASS; delete_files(S_FILE, O_FILE); - /* + /* * Perform test case setup */ ret = (tc_ptr->test_setup)(tc_ptr->fn_arg[0], tc_ptr->fn_arg[1], - tc_ptr->fn_arg[2], tc_ptr->errno_val); + tc_ptr->fn_arg[2]); /* If an expected error, try it out */ if (tc_ptr->test_fail) { - /* + /* * Try to perform test verification function */ if (! (tc_ptr->ck_test)(tc_ptr->fn_arg[0], tc_ptr->fn_arg[1], - tc_ptr->fn_arg[2], tc_ptr->errno_val)) + tc_ptr->fn_arg[2])) tst_resm(TEST_RESULT, test_msg); else if (tc_ptr->errno_val == EEXIST) do_EEXIST(tc_ptr); @@ -990,22 +980,22 @@ struct tcses *tcs; tst_resm(TBROK, "Test Case Declaration Error"); } else if (ret == 1) { /* No setup function error */ - + if (tc_ptr->errno_val != 0) tst_resm(TBROK, "Test Case Declaration Error"); else { - /* + /* * Perform test verification function */ ret=(tc_ptr->ck_test)(tc_ptr->fn_arg[0], tc_ptr->fn_arg[1], - tc_ptr->fn_arg[2], tc_ptr->errno_val); + tc_ptr->fn_arg[2]); /* Perform requested symbolic link system call test */ if ((cktcsid(tc_ptr->tcid, SYMLINK)) || (cktcsid(tc_ptr->tcid, LSTAT))) { if (ret == 1) - tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]); + tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]); else tst_resm(TEST_RESULT, test_msg); } @@ -1047,8 +1037,7 @@ struct tcses *tcs; * all_test_cases ***********************************************************************/ void -do_EEXIST(tc_ptr) -struct all_test_cases *tc_ptr; +do_EEXIST(struct all_test_cases *tc_ptr) { if (cktcsid(tc_ptr->tcid, SYMLINK)) { @@ -1109,8 +1098,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_ENOENT(tc_ptr) -struct all_test_cases *tc_ptr; +do_ENOENT(struct all_test_cases *tc_ptr) { if (cktcsid(tc_ptr->tcid, STAT)) { @@ -1204,8 +1192,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_ELOOP(tc_ptr) -struct all_test_cases *tc_ptr; +do_ELOOP(struct all_test_cases *tc_ptr) { if (cktcsid(tc_ptr->tcid, STAT)) { @@ -1314,8 +1301,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_ENOTDIR(tc_ptr) -struct all_test_cases *tc_ptr; +do_ENOTDIR(struct all_test_cases *tc_ptr) { if (cktcsid(tc_ptr->tcid, RMDIR)) { @@ -1350,8 +1336,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_EXDEV(tc_ptr) -struct all_test_cases *tc_ptr; +do_EXDEV(struct all_test_cases *tc_ptr) { if (cktcsid(tc_ptr->tcid, RENAME)) { @@ -1388,8 +1373,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_ENAMETOOLONG(tc_ptr) -struct all_test_cases *tc_ptr; +do_ENAMETOOLONG(struct all_test_cases *tc_ptr) { int ret; @@ -1440,8 +1424,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_EINVAL(tc_ptr) -struct all_test_cases *tc_ptr; +do_EINVAL(struct all_test_cases *tc_ptr) { if (cktcsid(tc_ptr->tcid, READLINK)) { TEST( readlink(tc_ptr->fn_arg[0], test_msg, BUFMAX) ); @@ -1473,8 +1456,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_readlink(tc_ptr) -struct all_test_cases *tc_ptr; +do_readlink(struct all_test_cases *tc_ptr) { char scratch[PATH_MAX]; int ret; @@ -1514,8 +1496,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_stat(tc_ptr) -struct all_test_cases *tc_ptr; +do_stat(struct all_test_cases *tc_ptr) { if (statter.st_dev != asymlink.st_dev) tst_resm(TFAIL, @@ -1575,8 +1556,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_chdir(tc_ptr) -struct all_test_cases *tc_ptr; +do_chdir(struct all_test_cases *tc_ptr) { if (mkdir(tc_ptr->fn_arg[2],MODE) == -1) tst_resm(TFAIL, "Could not create a setup directory file"); @@ -1626,8 +1606,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_link(tc_ptr) -struct all_test_cases *tc_ptr; +do_link(struct all_test_cases *tc_ptr) { struct stat stbuf; @@ -1688,8 +1667,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_unlink(tc_ptr) -struct all_test_cases *tc_ptr; +do_unlink(struct all_test_cases *tc_ptr) { if (stat(tc_ptr->fn_arg[2], &asymlink) == -1) tst_resm(TBROK, @@ -1730,8 +1708,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_chmod(tc_ptr) -struct all_test_cases *tc_ptr; +do_chmod(struct all_test_cases *tc_ptr) { if (stat(tc_ptr->fn_arg[2], &asymlink) == -1) tst_resm(TBROK, @@ -1772,8 +1749,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_utime(tc_ptr) -struct all_test_cases *tc_ptr; +do_utime(struct all_test_cases *tc_ptr) { struct utimbuf utimes; @@ -1828,8 +1804,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_rename(tc_ptr) -struct all_test_cases *tc_ptr; +do_rename(struct all_test_cases *tc_ptr) { int pts_at_object = 0; @@ -1870,8 +1845,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_open(tc_ptr) -struct all_test_cases *tc_ptr; +do_open(struct all_test_cases *tc_ptr) { int fd = -1; int ret, pts_at_object = 0; |