* [LTP] [PATCH v4 0/2] Improve ioctl02.c @ 2023-09-18 8:55 Marius Kittler 2023-09-18 8:55 ` [LTP] [PATCH v4 1/2] Refactor ioctl02.c to use the new test API Marius Kittler 2023-09-18 8:55 ` [LTP] [PATCH v4 2/2] Make checks for termio flags more strict Marius Kittler 0 siblings, 2 replies; 6+ messages in thread From: Marius Kittler @ 2023-09-18 8:55 UTC (permalink / raw) To: ltp Improve ioctl02.c Marius Kittler (2): Refactor ioctl02.c to use the new test API Make checks for termio flags more strict testcases/kernel/syscalls/ioctl/ioctl02.c | 394 ++++++---------------- 1 file changed, 94 insertions(+), 300 deletions(-) -- 2.42.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 6+ messages in thread
* [LTP] [PATCH v4 1/2] Refactor ioctl02.c to use the new test API 2023-09-18 8:55 [LTP] [PATCH v4 0/2] Improve ioctl02.c Marius Kittler @ 2023-09-18 8:55 ` Marius Kittler 2023-09-18 10:07 ` Petr Vorel 2023-09-18 15:37 ` Martin Doucha 2023-09-18 8:55 ` [LTP] [PATCH v4 2/2] Make checks for termio flags more strict Marius Kittler 1 sibling, 2 replies; 6+ messages in thread From: Marius Kittler @ 2023-09-18 8:55 UTC (permalink / raw) To: ltp * Use checkpoint API instead of signals * Use SAFE_…-macros instead of manual error handling * See https://github.com/linux-test-project/ltp/issues/637 for related discussion. Signed-off-by: Marius Kittler <mkittler@suse.de> --- testcases/kernel/syscalls/ioctl/ioctl02.c | 381 +++++----------------- 1 file changed, 89 insertions(+), 292 deletions(-) diff --git a/testcases/kernel/syscalls/ioctl/ioctl02.c b/testcases/kernel/syscalls/ioctl/ioctl02.c index b4d4a3594..e5510124c 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl02.c +++ b/testcases/kernel/syscalls/ioctl/ioctl02.c @@ -1,195 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) International Business Machines Corp., 2001 - * Copyright (c) 2020 Petr Vorel <pvorel@suse.cz> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Copyright (c) International Business Machines Corp., 2001 + * Copyright (c) 2020 Petr Vorel <pvorel@suse.cz> + * Copyright (c) 2023 Marius Kittler <mkittler@suse.de> */ -/* - * NAME - * ioctl02.c +/*\ + * [Description] * - * DESCRIPTION * Testcase to test the TCGETA, and TCSETA ioctl implementations for * the tty driver * - * ALGORITHM * In this test, the parent and child open the parentty and the childtty * respectively. After opening the childtty the child flushes the stream - * and sends a SIGUSR1 to the parent (thereby asking it to continue its - * testing). The parent, which was waiting for this signal to arrive, now - * starts the testing. It issues a TCGETA ioctl to get all the tty - * parameters. It then changes them to known values by issuing a TCSETA - * ioctl. Then the parent issues a TCGETA ioctl again and compares the - * received values with what it had set earlier. The test fails if TCGETA - * or TCSETA fails, or if the received values don't match those that were - * set. The parent does all the testing, the requirement of the child - * process is to moniter the testing done by the parent, and hence the - * child just waits for the parent. - * - * USAGE: <for command-line> - * ioctl02 -D /dev/tty[0-9] [-c n] [-f] [-i n] [-I x] [-P x] [-t] - * where, -c n : Run n copies concurrently. - * -f : Turn off functionality Testing. - * -i n : Execute test n times. - * -I x : Execute test for x seconds. - * -P x : Pause for x seconds between iterations. - * -t : Turn on syscall timing. - * - * HISTORY - * 07/2001 Ported by Wayne Boyer - * - * RESTRICTIONS - * test must be run with the -D option - * test may have to be run as root depending on the tty permissions + * and sends a wakes the parent (thereby asking it to continue its + * testing). The parent, then starts the testing. It issues a TCGETA + * ioctl to get all the tty parameters. It then changes them to known + * values by issuing a TCSETA ioctl. Then the parent issues a TCGETA + * ioctl again and compares the received values with what it had set + * earlier. The test fails if TCGETA or TCSETA fails, or if the received + * values don't match those that were set. The parent does all the + * testing, the requirement of the child process is to moniter the + * testing done by the parent, and hence the child just waits for the + * parent. */ #include <stdio.h> #include <fcntl.h> -#include <signal.h> #include <errno.h> #include <sys/wait.h> #include <sys/types.h> #include <sys/stat.h> #include <termios.h> -#include "test.h" -#include "safe_macros.h" -#include "lapi/ioctl.h" - -#define CNUL 0 -char *TCID = "ioctl02"; -int TST_TOTAL = 1; +#include "tst_checkpoint.h" +#include "tst_test.h" +#include "tst_safe_macros.h" static struct termio termio, save_io; static char *parenttty, *childtty; -static int parentfd, childfd; +static int parentfd = -1, childfd = -1; static int parentpid, childpid; -static volatile int sigterm, sigusr1, sigusr2; -static int closed = 1; static int do_child_setup(void); -static int do_parent_setup(void); static int run_ptest(void); static int run_ctest(void); -static int chk_tty_parms(); +static int chk_tty_parms(void); static void setup(void); static void cleanup(void); -static void help(void); static void do_child(void); -void do_child_uclinux(void); -static void sigterm_handler(void); -static int Devflag; -static char *devname; +static char *device; -static option_t options[] = { - {"D:", &Devflag, &devname}, - {NULL, NULL, NULL} -}; +static const int checkpoint_child_ready = 1; +static const int checkpoint_parent_done_testing = 2; -int main(int ac, char **av) +static void verify_ioctl(void) { - int lc; - int rval; - - tst_parse_opts(ac, av, options, &help); - -#ifdef UCLINUX - maybe_run_child(&do_child_uclinux, "dS", &parentpid, &childtty); -#endif - - if (!Devflag) - tst_brkm(TBROK, NULL, "You must specify a tty device with " - "the -D option."); - - tst_require_root(); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { + parenttty = device; + childtty = device; - tst_count = 0; + parentpid = getpid(); + childpid = SAFE_FORK(); + if (childpid == 0) + do_child(); - parenttty = devname; - childtty = devname; - - parentpid = getpid(); - - childpid = FORK_OR_VFORK(); - if (childpid < 0) - tst_brkm(TBROK, cleanup, "fork failed"); - - if (childpid == 0) { /* child */ -#ifdef UCLINUX - if (self_exec(av[0], "dS", parentpid, childtty) < 0) - tst_brkm(TBROK, cleanup, "self_exec failed"); -#else - do_child(); -#endif - } + TST_CHECKPOINT_WAIT2(checkpoint_child_ready, 5000); - while (!sigusr1) - sleep(1); - - sigusr1 = 0; - - parentfd = do_parent_setup(); - if (parentfd < 0) { - kill(childpid, SIGTERM); - waitpid(childpid, NULL, 0); - cleanup(); - } + parentfd = SAFE_OPEN(parenttty, O_RDWR, 0777); + /* flush tty queues to remove old output */ + SAFE_IOCTL(parentfd, TCFLSH, 2); - /* run the parent test */ - rval = run_ptest(); - if (rval == -1) { - /* - * Parent cannot set/get ioctl parameters. - * SIGTERM the child and cleanup. - */ - kill(childpid, SIGTERM); - waitpid(childpid, NULL, 0); - cleanup(); - } + /* run the parent test */ + int rval = run_ptest(); + if (rval != 0) + tst_res(TFAIL, "TCGETA/TCSETA tests FAILED with " + "%d %s", rval, rval > 1 ? "errors" : "error"); + else + tst_res(TPASS, "TCGETA/TCSETA tests SUCCEEDED"); - if (rval != 0) - tst_resm(TFAIL, "TCGETA/TCSETA tests FAILED with " - "%d %s", rval, rval > 1 ? "errors" : "error"); - else - tst_resm(TPASS, "TCGETA/TCSETA tests SUCCEEDED"); - - /* FIXME: check return codes. */ - (void)kill(childpid, SIGTERM); - (void)waitpid(childpid, NULL, 0); - - /* - * Clean up things from the parent by restoring the - * tty device information that was saved in setup() - * and closing the tty file descriptor. - */ - if (ioctl(parentfd, TCSETA, &save_io) == -1) - tst_resm(TINFO, "ioctl restore failed in main"); - SAFE_CLOSE(cleanup, parentfd); - - closed = 1; - } - cleanup(); + TST_CHECKPOINT_WAKE(checkpoint_parent_done_testing); - tst_exit(); + /* + * Clean up things from the parent by restoring the + * tty device information that was saved in setup() + * and closing the tty file descriptor. + */ + SAFE_IOCTL(parentfd, TCSETA, &save_io); + SAFE_CLOSE(parentfd); } static void do_child(void) @@ -201,28 +100,12 @@ static void do_child(void) _exit(0); } -void do_child_uclinux(void) -{ - struct sigaction act; - - /* Set up the signal handlers again */ - act.sa_handler = (void *)sigterm_handler; - act.sa_flags = 0; - sigemptyset(&act.sa_mask); - (void)sigaction(SIGTERM, &act, 0); - - /* Run the normal child */ - do_child(); -} - /* * run_ptest() - setup the various termio structure values and issue * the TCSETA ioctl call with the TEST macro. */ static int run_ptest(void) { - int i, rval; - /* Use "old" line discipline */ termio.c_line = 0; @@ -230,7 +113,7 @@ static int run_ptest(void) termio.c_cflag = B50 | CS7 | CREAD | PARENB | PARODD | CLOCAL; /* Set control chars. */ - for (i = 0; i < NCC; i++) { + for (int i = 0; i < NCC; i++) { if (i == VEOL2) continue; termio.c_cc[i] = CSTART; @@ -248,38 +131,18 @@ static int run_ptest(void) /* Set output modes. */ termio.c_oflag = OPOST | OLCUC | ONLCR | ONOCR; - TEST(ioctl(parentfd, TCSETA, &termio)); - - if (TEST_RETURN < 0) { - tst_resm(TFAIL, "ioctl TCSETA failed : " - "errno = %d", TEST_ERRNO); - return -1; - } + SAFE_IOCTL(parentfd, TCSETA, &termio); /* Get termio and see if all parameters actually got set */ - rval = ioctl(parentfd, TCGETA, &termio); - if (rval < 0) { - tst_resm(TFAIL, "ioctl TCGETA failed. Ending test."); - return -1; - } - + SAFE_IOCTL(parentfd, TCGETA, &termio); return chk_tty_parms(); } static int run_ctest(void) { - /* - * Wait till the parent has finished testing. - */ - while (!sigterm) - sleep(1); - - sigterm = 0; - - tst_resm(TINFO, "child: Got SIGTERM from parent."); - - if (close(childfd) == -1) - tst_resm(TINFO, "close() in run_ctest() failed"); + TST_CHECKPOINT_WAIT(checkpoint_parent_done_testing); + tst_res(TINFO, "child: parent has finished testing"); + SAFE_CLOSE(childfd); return 0; } @@ -288,7 +151,7 @@ static int chk_tty_parms(void) int i, flag = 0; if (termio.c_line != 0) { - tst_resm(TINFO, "line discipline has incorrect value %o", + tst_res(TINFO, "line discipline has incorrect value %o", termio.c_line); flag++; } @@ -301,7 +164,7 @@ static int chk_tty_parms(void) */ #if 0 if (termio.c_cflag != (B50 | CS7 | CREAD | PARENB | PARODD | CLOCAL)) { - tst_resm(TINFO, "cflag has incorrect value. %o", + tst_res(TINFO, "cflag has incorrect value. %o", termio.c_cflag); flag++; } @@ -309,19 +172,18 @@ static int chk_tty_parms(void) for (i = 0; i < NCC; i++) { if (i == VEOL2) { - if (termio.c_cc[VEOL2] == CNUL) { + if (!termio.c_cc[i]) { continue; } else { - tst_resm(TINFO, "control char %d has " - "incorrect value %d %d", i, - termio.c_cc[i], CNUL); + tst_res(TINFO, "control char %d has " + "incorrect value %d", i, termio.c_cc[i]); flag++; continue; } } if (termio.c_cc[i] != CSTART) { - tst_resm(TINFO, "control char %d has incorrect " + tst_res(TINFO, "control char %d has incorrect " "value %d.", i, termio.c_cc[i]); flag++; } @@ -330,7 +192,7 @@ static int chk_tty_parms(void) if (! (termio.c_lflag && (ISIG | ICANON | XCASE | ECHO | ECHOE | NOFLSH))) { - tst_resm(TINFO, "lflag has incorrect value. %o", + tst_res(TINFO, "lflag has incorrect value. %o", termio.c_lflag); flag++; } @@ -339,130 +201,65 @@ static int chk_tty_parms(void) (termio.c_iflag && (BRKINT | IGNPAR | INPCK | ISTRIP | ICRNL | IUCLC | IXON | IXANY | IXOFF))) { - tst_resm(TINFO, "iflag has incorrect value. %o", + tst_res(TINFO, "iflag has incorrect value. %o", termio.c_iflag); flag++; } if (!(termio.c_oflag && (OPOST | OLCUC | ONLCR | ONOCR))) { - tst_resm(TINFO, "oflag has incorrect value. %o", + tst_res(TINFO, "oflag has incorrect value. %o", termio.c_oflag); flag++; } if (!flag) - tst_resm(TINFO, "termio values are set as expected"); + tst_res(TINFO, "termio values are set as expected"); return flag; } -static int do_parent_setup(void) -{ - int pfd; - - pfd = SAFE_OPEN(cleanup, parenttty, O_RDWR, 0777); - - /* unset the closed flag */ - closed = 0; - - /* flush tty queues to remove old output */ - SAFE_IOCTL(cleanup, pfd, TCFLSH, 2); - return pfd; -} - static int do_child_setup(void) { - int cfd; - - cfd = open(childtty, O_RDWR, 0777); - if (cfd < 0) { - tst_resm(TINFO, "Could not open %s in do_child_setup(), errno " - "= %d", childtty, errno); - /* signal the parent so we don't hang the test */ - kill(parentpid, SIGUSR1); - return -1; - } + int cfd = SAFE_OPEN(childtty, O_RDWR, 0777); /* flush tty queues to remove old output */ - if (ioctl(cfd, TCFLSH, 2) < 0) { - tst_resm(TINFO, "ioctl TCFLSH failed. : errno = %d", errno); - /* signal the parent so we don't hang the test */ - kill(parentpid, SIGUSR1); - return -1; - } + SAFE_IOCTL(cfd, TCFLSH, 2); /* tell the parent that we're done */ - kill(parentpid, SIGUSR1); - + TST_CHECKPOINT_WAKE(checkpoint_child_ready); return cfd; } -/* - * Define the signals handlers here. - */ -static void sigterm_handler(void) -{ - sigterm = 1; -} - -static void sigusr1_handler(void) -{ - sigusr1 = 1; -} - -static void sigusr2_handler(void) -{ - sigusr2 = 1; -} - -static void help(void) -{ - printf(" -D <tty device> : for example, /dev/tty[0-9]\n"); -} - static void setup(void) { - int fd; - struct sigaction act; + if (!device) + tst_brk(TBROK, "You must specify a tty device with -D option"); /* XXX: TERRNO required all over the place */ - fd = SAFE_OPEN(NULL, devname, O_RDWR, 0777); + int fd = SAFE_OPEN(device, O_RDWR, 0777); /* Save the current device information - to be restored in cleanup() */ - SAFE_IOCTL(cleanup, fd, TCGETA, &save_io); + SAFE_IOCTL(fd, TCGETA, &save_io); /* Close the device */ - SAFE_CLOSE(cleanup, fd); - - /* Set up the signal handlers */ - act.sa_handler = (void *)sigterm_handler; - act.sa_flags = 0; - sigemptyset(&act.sa_mask); - (void)sigaction(SIGTERM, &act, 0); - - act.sa_handler = (void *)sigusr1_handler; - act.sa_flags = 0; - (void)sigaction(SIGUSR1, &act, 0); - - act.sa_handler = (void *)sigusr2_handler; - act.sa_flags = 0; - (void)sigaction(SIGUSR2, &act, 0); - - act.sa_handler = SIG_IGN; - act.sa_flags = 0; - (void)sigaction(SIGTTOU, &act, 0); - - sigterm = sigusr1 = sigusr2 = 0; - - TEST_PAUSE; + SAFE_CLOSE(fd); } static void cleanup(void) { - if (!closed) { - if (ioctl(parentfd, TCSETA, &save_io) == -1) - tst_resm(TINFO, "ioctl restore failed in cleanup()"); - if (close(parentfd) == -1) - tst_resm(TINFO, "close() failed in cleanup()"); - } + if (parentfd >= 0) + SAFE_IOCTL(parentfd, TCSETA, &save_io); } + +static struct tst_test test = { + .needs_root = 1, + .needs_checkpoints = 1, + .forks_child = 1, + .setup = setup, + .cleanup = cleanup, + .test_all = verify_ioctl, + .options = (struct tst_option[]) { + {"D:", &device, "Tty device. For example, /dev/tty[0-9]"}, + {} + } +}; \ No newline at end of file -- 2.42.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [LTP] [PATCH v4 1/2] Refactor ioctl02.c to use the new test API 2023-09-18 8:55 ` [LTP] [PATCH v4 1/2] Refactor ioctl02.c to use the new test API Marius Kittler @ 2023-09-18 10:07 ` Petr Vorel 2023-09-18 13:14 ` Petr Vorel 2023-09-18 15:37 ` Martin Doucha 1 sibling, 1 reply; 6+ messages in thread From: Petr Vorel @ 2023-09-18 10:07 UTC (permalink / raw) To: Marius Kittler; +Cc: ltp Hi Marius, Could you please fix formatting and other common errors? $ make check-getxattr01 CHECK testcases/kernel/syscalls/getxattr/getxattr01.c getxattr01.c:81: WARNING: Missing a blank line after declarations getxattr01.c:83: WARNING: Missing a blank line after declarations getxattr01.c:106: WARNING: braces {} are not necessary for single statement blocks getxattr01.c:127: WARNING: Missing a blank line after declarations make: [../../../../include/mk/rules.mk:56: check-getxattr01] Error 1 (ignored) getxattr01.c:50:3: warning: Symbol 'tcases' has no prototype or library ('tst_') prefix. Should it be static? Also (very nit), backticks (`) are good for github formatting, but they look strange in git commits. Could you avoid using it in git subject? (e.g. "Port `getxattr01.c` to new test API" should be "Port getxattr01.c to new test API"). > Related issue: https://github.com/linux-test-project/ltp/issues/583 We use: Fixes: #583 Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [LTP] [PATCH v4 1/2] Refactor ioctl02.c to use the new test API 2023-09-18 10:07 ` Petr Vorel @ 2023-09-18 13:14 ` Petr Vorel 0 siblings, 0 replies; 6+ messages in thread From: Petr Vorel @ 2023-09-18 13:14 UTC (permalink / raw) To: Marius Kittler, ltp > Hi Marius, > Could you please fix formatting and other common errors? > $ make check-getxattr01 > CHECK testcases/kernel/syscalls/getxattr/getxattr01.c > getxattr01.c:81: WARNING: Missing a blank line after declarations > getxattr01.c:83: WARNING: Missing a blank line after declarations > getxattr01.c:106: WARNING: braces {} are not necessary for single statement > blocks > getxattr01.c:127: WARNING: Missing a blank line after declarations > make: [../../../../include/mk/rules.mk:56: check-getxattr01] Error 1 (ignored) > getxattr01.c:50:3: warning: Symbol 'tcases' has no prototype or library ('tst_') > prefix. Should it be static? > Also (very nit), backticks (`) are good for github formatting, but they look > strange in git commits. Could you avoid using it in git subject? > (e.g. "Port `getxattr01.c` to new test API" should be "Port getxattr01.c to > new test API"). Hm, this was meant to be posted to getxattr01 v2 patch, posting it there. https://patchwork.ozlabs.org/project/ltp/patch/20230915135752.7275-1-mkittler@suse.de/ Kind regards, Petr > > Related issue: https://github.com/linux-test-project/ltp/issues/583 > We use: > Fixes: #583 > Kind regards, > Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [LTP] [PATCH v4 1/2] Refactor ioctl02.c to use the new test API 2023-09-18 8:55 ` [LTP] [PATCH v4 1/2] Refactor ioctl02.c to use the new test API Marius Kittler 2023-09-18 10:07 ` Petr Vorel @ 2023-09-18 15:37 ` Martin Doucha 1 sibling, 0 replies; 6+ messages in thread From: Martin Doucha @ 2023-09-18 15:37 UTC (permalink / raw) To: Marius Kittler, ltp Hi, three small things below. On 18. 09. 23 10:55, Marius Kittler wrote: > * Use checkpoint API instead of signals > * Use SAFE_…-macros instead of manual error handling > * See https://github.com/linux-test-project/ltp/issues/637 > for related discussion. > > Signed-off-by: Marius Kittler <mkittler@suse.de> > --- > testcases/kernel/syscalls/ioctl/ioctl02.c | 381 +++++----------------- > 1 file changed, 89 insertions(+), 292 deletions(-) > > diff --git a/testcases/kernel/syscalls/ioctl/ioctl02.c b/testcases/kernel/syscalls/ioctl/ioctl02.c > index b4d4a3594..e5510124c 100644 > --- a/testcases/kernel/syscalls/ioctl/ioctl02.c > +++ b/testcases/kernel/syscalls/ioctl/ioctl02.c > @@ -1,195 +1,94 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > /* > - * Copyright (c) International Business Machines Corp., 2001 > - * Copyright (c) 2020 Petr Vorel <pvorel@suse.cz> > - * > - * This program is free software; you can redistribute it and/or modify > - * it under the terms of the GNU General Public License as published by > - * the Free Software Foundation; either version 2 of the License, or > - * (at your option) any later version. > - * > - * This program is distributed in the hope that it will be useful, > - * but WITHOUT ANY WARRANTY; without even the implied warranty of > - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > - * the GNU General Public License for more details. > - * > - * You should have received a copy of the GNU General Public License > - * along with this program; if not, write to the Free Software > - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA > + * Copyright (c) International Business Machines Corp., 2001 > + * Copyright (c) 2020 Petr Vorel <pvorel@suse.cz> > + * Copyright (c) 2023 Marius Kittler <mkittler@suse.de> > */ > > -/* > - * NAME > - * ioctl02.c > +/*\ > + * [Description] > * > - * DESCRIPTION > * Testcase to test the TCGETA, and TCSETA ioctl implementations for > * the tty driver > * > - * ALGORITHM > * In this test, the parent and child open the parentty and the childtty > * respectively. After opening the childtty the child flushes the stream > - * and sends a SIGUSR1 to the parent (thereby asking it to continue its > - * testing). The parent, which was waiting for this signal to arrive, now > - * starts the testing. It issues a TCGETA ioctl to get all the tty > - * parameters. It then changes them to known values by issuing a TCSETA > - * ioctl. Then the parent issues a TCGETA ioctl again and compares the > - * received values with what it had set earlier. The test fails if TCGETA > - * or TCSETA fails, or if the received values don't match those that were > - * set. The parent does all the testing, the requirement of the child > - * process is to moniter the testing done by the parent, and hence the > - * child just waits for the parent. > - * > - * USAGE: <for command-line> > - * ioctl02 -D /dev/tty[0-9] [-c n] [-f] [-i n] [-I x] [-P x] [-t] > - * where, -c n : Run n copies concurrently. > - * -f : Turn off functionality Testing. > - * -i n : Execute test n times. > - * -I x : Execute test for x seconds. > - * -P x : Pause for x seconds between iterations. > - * -t : Turn on syscall timing. > - * > - * HISTORY > - * 07/2001 Ported by Wayne Boyer > - * > - * RESTRICTIONS > - * test must be run with the -D option > - * test may have to be run as root depending on the tty permissions > + * and sends a wakes the parent (thereby asking it to continue its There are some typos here. > + * testing). The parent, then starts the testing. It issues a TCGETA > + * ioctl to get all the tty parameters. It then changes them to known > + * values by issuing a TCSETA ioctl. Then the parent issues a TCGETA > + * ioctl again and compares the received values with what it had set > + * earlier. The test fails if TCGETA or TCSETA fails, or if the received > + * values don't match those that were set. The parent does all the > + * testing, the requirement of the child process is to moniter the > + * testing done by the parent, and hence the child just waits for the > + * parent. > */ > > #include <stdio.h> > #include <fcntl.h> > -#include <signal.h> > #include <errno.h> > #include <sys/wait.h> > #include <sys/types.h> > #include <sys/stat.h> > #include <termios.h> > -#include "test.h" > -#include "safe_macros.h" > -#include "lapi/ioctl.h" > - > -#define CNUL 0 > > -char *TCID = "ioctl02"; > -int TST_TOTAL = 1; > +#include "tst_checkpoint.h" > +#include "tst_test.h" > +#include "tst_safe_macros.h" > > static struct termio termio, save_io; > > static char *parenttty, *childtty; > -static int parentfd, childfd; > +static int parentfd = -1, childfd = -1; > static int parentpid, childpid; > -static volatile int sigterm, sigusr1, sigusr2; > -static int closed = 1; > > static int do_child_setup(void); > -static int do_parent_setup(void); > static int run_ptest(void); > static int run_ctest(void); > -static int chk_tty_parms(); > +static int chk_tty_parms(void); > static void setup(void); > static void cleanup(void); > -static void help(void); > static void do_child(void); > -void do_child_uclinux(void); > -static void sigterm_handler(void); > > -static int Devflag; > -static char *devname; > +static char *device; > > -static option_t options[] = { > - {"D:", &Devflag, &devname}, > - {NULL, NULL, NULL} > -}; > +static const int checkpoint_child_ready = 1; > +static const int checkpoint_parent_done_testing = 2; > > -int main(int ac, char **av) > +static void verify_ioctl(void) > { > - int lc; > - int rval; > - > - tst_parse_opts(ac, av, options, &help); > - > -#ifdef UCLINUX > - maybe_run_child(&do_child_uclinux, "dS", &parentpid, &childtty); > -#endif > - > - if (!Devflag) > - tst_brkm(TBROK, NULL, "You must specify a tty device with " > - "the -D option."); > - > - tst_require_root(); > - > - setup(); > - > - for (lc = 0; TEST_LOOPING(lc); lc++) { > + parenttty = device; > + childtty = device; > > - tst_count = 0; > + parentpid = getpid(); > + childpid = SAFE_FORK(); > + if (childpid == 0) > + do_child(); > > - parenttty = devname; > - childtty = devname; > - > - parentpid = getpid(); > - > - childpid = FORK_OR_VFORK(); > - if (childpid < 0) > - tst_brkm(TBROK, cleanup, "fork failed"); > - > - if (childpid == 0) { /* child */ > -#ifdef UCLINUX > - if (self_exec(av[0], "dS", parentpid, childtty) < 0) > - tst_brkm(TBROK, cleanup, "self_exec failed"); > -#else > - do_child(); > -#endif > - } > + TST_CHECKPOINT_WAIT2(checkpoint_child_ready, 5000); > > - while (!sigusr1) > - sleep(1); > - > - sigusr1 = 0; > - > - parentfd = do_parent_setup(); > - if (parentfd < 0) { > - kill(childpid, SIGTERM); > - waitpid(childpid, NULL, 0); > - cleanup(); > - } > + parentfd = SAFE_OPEN(parenttty, O_RDWR, 0777); > + /* flush tty queues to remove old output */ > + SAFE_IOCTL(parentfd, TCFLSH, 2); > > - /* run the parent test */ > - rval = run_ptest(); > - if (rval == -1) { > - /* > - * Parent cannot set/get ioctl parameters. > - * SIGTERM the child and cleanup. > - */ > - kill(childpid, SIGTERM); > - waitpid(childpid, NULL, 0); > - cleanup(); > - } > + /* run the parent test */ > + int rval = run_ptest(); > + if (rval != 0) > + tst_res(TFAIL, "TCGETA/TCSETA tests FAILED with " > + "%d %s", rval, rval > 1 ? "errors" : "error"); > + else > + tst_res(TPASS, "TCGETA/TCSETA tests SUCCEEDED"); > > - if (rval != 0) > - tst_resm(TFAIL, "TCGETA/TCSETA tests FAILED with " > - "%d %s", rval, rval > 1 ? "errors" : "error"); > - else > - tst_resm(TPASS, "TCGETA/TCSETA tests SUCCEEDED"); > - > - /* FIXME: check return codes. */ > - (void)kill(childpid, SIGTERM); > - (void)waitpid(childpid, NULL, 0); > - > - /* > - * Clean up things from the parent by restoring the > - * tty device information that was saved in setup() > - * and closing the tty file descriptor. > - */ > - if (ioctl(parentfd, TCSETA, &save_io) == -1) > - tst_resm(TINFO, "ioctl restore failed in main"); > - SAFE_CLOSE(cleanup, parentfd); > - > - closed = 1; > - } > - cleanup(); > + TST_CHECKPOINT_WAKE(checkpoint_parent_done_testing); > > - tst_exit(); > + /* > + * Clean up things from the parent by restoring the > + * tty device information that was saved in setup() > + * and closing the tty file descriptor. > + */ > + SAFE_IOCTL(parentfd, TCSETA, &save_io); > + SAFE_CLOSE(parentfd); This will be done automatically in cleanup(). > } > > static void do_child(void) > @@ -201,28 +100,12 @@ static void do_child(void) > _exit(0); > } > > -void do_child_uclinux(void) > -{ > - struct sigaction act; > - > - /* Set up the signal handlers again */ > - act.sa_handler = (void *)sigterm_handler; > - act.sa_flags = 0; > - sigemptyset(&act.sa_mask); > - (void)sigaction(SIGTERM, &act, 0); > - > - /* Run the normal child */ > - do_child(); > -} > - > /* > * run_ptest() - setup the various termio structure values and issue > * the TCSETA ioctl call with the TEST macro. > */ > static int run_ptest(void) > { > - int i, rval; > - > /* Use "old" line discipline */ > termio.c_line = 0; > > @@ -230,7 +113,7 @@ static int run_ptest(void) > termio.c_cflag = B50 | CS7 | CREAD | PARENB | PARODD | CLOCAL; > > /* Set control chars. */ > - for (i = 0; i < NCC; i++) { > + for (int i = 0; i < NCC; i++) { > if (i == VEOL2) > continue; > termio.c_cc[i] = CSTART; > @@ -248,38 +131,18 @@ static int run_ptest(void) > /* Set output modes. */ > termio.c_oflag = OPOST | OLCUC | ONLCR | ONOCR; > > - TEST(ioctl(parentfd, TCSETA, &termio)); > - > - if (TEST_RETURN < 0) { > - tst_resm(TFAIL, "ioctl TCSETA failed : " > - "errno = %d", TEST_ERRNO); > - return -1; > - } > + SAFE_IOCTL(parentfd, TCSETA, &termio); > > /* Get termio and see if all parameters actually got set */ > - rval = ioctl(parentfd, TCGETA, &termio); > - if (rval < 0) { > - tst_resm(TFAIL, "ioctl TCGETA failed. Ending test."); > - return -1; > - } > - > + SAFE_IOCTL(parentfd, TCGETA, &termio); > return chk_tty_parms(); > } > > static int run_ctest(void) > { > - /* > - * Wait till the parent has finished testing. > - */ > - while (!sigterm) > - sleep(1); > - > - sigterm = 0; > - > - tst_resm(TINFO, "child: Got SIGTERM from parent."); > - > - if (close(childfd) == -1) > - tst_resm(TINFO, "close() in run_ctest() failed"); > + TST_CHECKPOINT_WAIT(checkpoint_parent_done_testing); > + tst_res(TINFO, "child: parent has finished testing"); > + SAFE_CLOSE(childfd); > return 0; > } > > @@ -288,7 +151,7 @@ static int chk_tty_parms(void) > int i, flag = 0; > > if (termio.c_line != 0) { > - tst_resm(TINFO, "line discipline has incorrect value %o", > + tst_res(TINFO, "line discipline has incorrect value %o", > termio.c_line); > flag++; > } > @@ -301,7 +164,7 @@ static int chk_tty_parms(void) > */ > #if 0 > if (termio.c_cflag != (B50 | CS7 | CREAD | PARENB | PARODD | CLOCAL)) { > - tst_resm(TINFO, "cflag has incorrect value. %o", > + tst_res(TINFO, "cflag has incorrect value. %o", > termio.c_cflag); > flag++; > } > @@ -309,19 +172,18 @@ static int chk_tty_parms(void) > > for (i = 0; i < NCC; i++) { > if (i == VEOL2) { > - if (termio.c_cc[VEOL2] == CNUL) { > + if (!termio.c_cc[i]) { > continue; > } else { > - tst_resm(TINFO, "control char %d has " > - "incorrect value %d %d", i, > - termio.c_cc[i], CNUL); > + tst_res(TINFO, "control char %d has " > + "incorrect value %d", i, termio.c_cc[i]); > flag++; > continue; > } > } > > if (termio.c_cc[i] != CSTART) { > - tst_resm(TINFO, "control char %d has incorrect " > + tst_res(TINFO, "control char %d has incorrect " > "value %d.", i, termio.c_cc[i]); > flag++; > } > @@ -330,7 +192,7 @@ static int chk_tty_parms(void) > if (! > (termio.c_lflag > && (ISIG | ICANON | XCASE | ECHO | ECHOE | NOFLSH))) { > - tst_resm(TINFO, "lflag has incorrect value. %o", > + tst_res(TINFO, "lflag has incorrect value. %o", > termio.c_lflag); > flag++; > } > @@ -339,130 +201,65 @@ static int chk_tty_parms(void) > (termio.c_iflag > && (BRKINT | IGNPAR | INPCK | ISTRIP | ICRNL | IUCLC | IXON | IXANY > | IXOFF))) { > - tst_resm(TINFO, "iflag has incorrect value. %o", > + tst_res(TINFO, "iflag has incorrect value. %o", > termio.c_iflag); > flag++; > } > > if (!(termio.c_oflag && (OPOST | OLCUC | ONLCR | ONOCR))) { > - tst_resm(TINFO, "oflag has incorrect value. %o", > + tst_res(TINFO, "oflag has incorrect value. %o", > termio.c_oflag); > flag++; > } > > if (!flag) > - tst_resm(TINFO, "termio values are set as expected"); > + tst_res(TINFO, "termio values are set as expected"); > > return flag; > } > > -static int do_parent_setup(void) > -{ > - int pfd; > - > - pfd = SAFE_OPEN(cleanup, parenttty, O_RDWR, 0777); > - > - /* unset the closed flag */ > - closed = 0; > - > - /* flush tty queues to remove old output */ > - SAFE_IOCTL(cleanup, pfd, TCFLSH, 2); > - return pfd; > -} > - > static int do_child_setup(void) > { > - int cfd; > - > - cfd = open(childtty, O_RDWR, 0777); > - if (cfd < 0) { > - tst_resm(TINFO, "Could not open %s in do_child_setup(), errno " > - "= %d", childtty, errno); > - /* signal the parent so we don't hang the test */ > - kill(parentpid, SIGUSR1); > - return -1; > - } > + int cfd = SAFE_OPEN(childtty, O_RDWR, 0777); > > /* flush tty queues to remove old output */ > - if (ioctl(cfd, TCFLSH, 2) < 0) { > - tst_resm(TINFO, "ioctl TCFLSH failed. : errno = %d", errno); > - /* signal the parent so we don't hang the test */ > - kill(parentpid, SIGUSR1); > - return -1; > - } > + SAFE_IOCTL(cfd, TCFLSH, 2); > > /* tell the parent that we're done */ > - kill(parentpid, SIGUSR1); > - > + TST_CHECKPOINT_WAKE(checkpoint_child_ready); > return cfd; > } > > -/* > - * Define the signals handlers here. > - */ > -static void sigterm_handler(void) > -{ > - sigterm = 1; > -} > - > -static void sigusr1_handler(void) > -{ > - sigusr1 = 1; > -} > - > -static void sigusr2_handler(void) > -{ > - sigusr2 = 1; > -} > - > -static void help(void) > -{ > - printf(" -D <tty device> : for example, /dev/tty[0-9]\n"); > -} > - > static void setup(void) > { > - int fd; > - struct sigaction act; > + if (!device) > + tst_brk(TBROK, "You must specify a tty device with -D option"); > > /* XXX: TERRNO required all over the place */ > - fd = SAFE_OPEN(NULL, devname, O_RDWR, 0777); > + int fd = SAFE_OPEN(device, O_RDWR, 0777); > > /* Save the current device information - to be restored in cleanup() */ > - SAFE_IOCTL(cleanup, fd, TCGETA, &save_io); > + SAFE_IOCTL(fd, TCGETA, &save_io); > > /* Close the device */ > - SAFE_CLOSE(cleanup, fd); > - > - /* Set up the signal handlers */ > - act.sa_handler = (void *)sigterm_handler; > - act.sa_flags = 0; > - sigemptyset(&act.sa_mask); > - (void)sigaction(SIGTERM, &act, 0); > - > - act.sa_handler = (void *)sigusr1_handler; > - act.sa_flags = 0; > - (void)sigaction(SIGUSR1, &act, 0); > - > - act.sa_handler = (void *)sigusr2_handler; > - act.sa_flags = 0; > - (void)sigaction(SIGUSR2, &act, 0); > - > - act.sa_handler = SIG_IGN; > - act.sa_flags = 0; > - (void)sigaction(SIGTTOU, &act, 0); > - > - sigterm = sigusr1 = sigusr2 = 0; > - > - TEST_PAUSE; > + SAFE_CLOSE(fd); > } > > static void cleanup(void) > { > - if (!closed) { > - if (ioctl(parentfd, TCSETA, &save_io) == -1) > - tst_resm(TINFO, "ioctl restore failed in cleanup()"); > - if (close(parentfd) == -1) > - tst_resm(TINFO, "close() failed in cleanup()"); > - } > + if (parentfd >= 0) > + SAFE_IOCTL(parentfd, TCSETA, &save_io); What happened to SAFE_CLOSE() here? > } > + > +static struct tst_test test = { > + .needs_root = 1, > + .needs_checkpoints = 1, > + .forks_child = 1, > + .setup = setup, > + .cleanup = cleanup, > + .test_all = verify_ioctl, > + .options = (struct tst_option[]) { > + {"D:", &device, "Tty device. For example, /dev/tty[0-9]"}, > + {} > + } > +}; > \ No newline at end of file -- Martin Doucha mdoucha@suse.cz SW Quality Engineer SUSE LINUX, s.r.o. CORSO IIa Krizikova 148/34 186 00 Prague 8 Czech Republic -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 6+ messages in thread
* [LTP] [PATCH v4 2/2] Make checks for termio flags more strict 2023-09-18 8:55 [LTP] [PATCH v4 0/2] Improve ioctl02.c Marius Kittler 2023-09-18 8:55 ` [LTP] [PATCH v4 1/2] Refactor ioctl02.c to use the new test API Marius Kittler @ 2023-09-18 8:55 ` Marius Kittler 1 sibling, 0 replies; 6+ messages in thread From: Marius Kittler @ 2023-09-18 8:55 UTC (permalink / raw) To: ltp The checks for termio flags can actually use a `!=` check to also fail when any unexpected flags are present. Signed-off-by: Marius Kittler <mkittler@suse.de> --- testcases/kernel/syscalls/ioctl/ioctl02.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/testcases/kernel/syscalls/ioctl/ioctl02.c b/testcases/kernel/syscalls/ioctl/ioctl02.c index e5510124c..7b73c60d2 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl02.c +++ b/testcases/kernel/syscalls/ioctl/ioctl02.c @@ -189,24 +189,21 @@ static int chk_tty_parms(void) } } - if (! - (termio.c_lflag - && (ISIG | ICANON | XCASE | ECHO | ECHOE | NOFLSH))) { + if (termio.c_lflag != (ISIG | ICANON | XCASE | ECHO | ECHOE + | NOFLSH)) { tst_res(TINFO, "lflag has incorrect value. %o", termio.c_lflag); flag++; } - if (! - (termio.c_iflag - && (BRKINT | IGNPAR | INPCK | ISTRIP | ICRNL | IUCLC | IXON | IXANY - | IXOFF))) { + if (termio.c_iflag != (BRKINT | IGNPAR | INPCK | ISTRIP + | ICRNL | IUCLC | IXON | IXANY | IXOFF)) { tst_res(TINFO, "iflag has incorrect value. %o", termio.c_iflag); flag++; } - if (!(termio.c_oflag && (OPOST | OLCUC | ONLCR | ONOCR))) { + if (termio.c_oflag != (OPOST | OLCUC | ONLCR | ONOCR)) { tst_res(TINFO, "oflag has incorrect value. %o", termio.c_oflag); flag++; -- 2.42.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2023-09-18 15:37 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-09-18 8:55 [LTP] [PATCH v4 0/2] Improve ioctl02.c Marius Kittler 2023-09-18 8:55 ` [LTP] [PATCH v4 1/2] Refactor ioctl02.c to use the new test API Marius Kittler 2023-09-18 10:07 ` Petr Vorel 2023-09-18 13:14 ` Petr Vorel 2023-09-18 15:37 ` Martin Doucha 2023-09-18 8:55 ` [LTP] [PATCH v4 2/2] Make checks for termio flags more strict Marius Kittler
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox