* [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 an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.