/* Tests for fork. Copyright (C) 2000-2016 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2000. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see . */ #include #include #include #include #include #include static const char testdata[] = "This is a test"; static const char testdata2[] = "And here we go again"; int main (void) { const char *tmpdir = getenv ("TMPDIR"); char buf[100]; size_t tmpdirlen; char *name; int fd; pid_t pid; pid_t ppid; off_t off; int status; if (tmpdir == NULL || *tmpdir == '\0') tmpdir = "/tmp"; tmpdirlen = strlen (tmpdir); name = (char *) malloc (tmpdirlen + strlen ("/forkXXXXXX") + 1); if (name == NULL) error (EXIT_FAILURE, errno, "cannot allocate file name"); mempcpy (mempcpy (name, tmpdir, tmpdirlen), "/forkXXXXXX", sizeof ("/forkXXXXXX")); /* Open our test file. */ fd = mkstemp (name); if (fd == -1) error (EXIT_FAILURE, errno, "cannot open test file `%s'", name); /* Make sure it gets removed. */ unlink (name); /* Write some data. */ if (write (fd, testdata, strlen (testdata)) != strlen (testdata)) error (EXIT_FAILURE, errno, "cannot write test data"); /* Get the position in the stream. */ off = lseek (fd, 0, SEEK_CUR); if (off == (off_t) -1 || off != strlen (testdata)) error (EXIT_FAILURE, errno, "wrong file position"); /* Get the parent PID. */ ppid = getpid (); /* Now fork of the process. */ pid = fork (); if (pid == 0) { /* One little test first: the PID must have changed. */ if (getpid () == ppid) error (EXIT_FAILURE, 0, "child and parent have same PID"); /* Test the `getppid' function. */ pid = getppid (); if (pid == (pid_t) -1 ? errno != ENOSYS : pid != ppid) error (EXIT_FAILURE, 0, "getppid returned wrong PID (%ld, should be %ld)", (long int) pid, (long int) ppid); /* This is the child. First get the position of the descriptor. */ off = lseek (fd, 0, SEEK_CUR); if (off == (off_t) -1 || off != strlen (testdata)) error (EXIT_FAILURE, errno, "wrong file position in child"); /* Reset the position. */ if (lseek (fd, 0, SEEK_SET) != 0) error (EXIT_FAILURE, errno, "cannot reset position in child"); /* Read the data. */ if (read (fd, buf, sizeof buf) != strlen (testdata)) error (EXIT_FAILURE, errno, "cannot read data in child"); /* Compare the data. */ if (memcmp (buf, testdata, strlen (testdata)) != 0) error (EXIT_FAILURE, 0, "data comparison failed in child"); /* Reset position again. */ if (lseek (fd, 0, SEEK_SET) != 0) error (EXIT_FAILURE, errno, "cannot reset position again in child"); /* Write new data. */ if (write (fd, testdata2, strlen (testdata2)) != strlen (testdata2)) error (EXIT_FAILURE, errno, "cannot write new data in child"); /* Close the file. This must not remove it. */ close (fd); _exit (0); } else if (pid < 0) /* Something went wrong. */ error (EXIT_FAILURE, errno, "cannot fork"); /* Wait for the child. */ if (waitpid (pid, &status, 0) != pid) error (EXIT_FAILURE, 0, "Oops, wrong test program terminated"); if (WTERMSIG (status) != 0) error (EXIT_FAILURE, 0, "Child terminated incorrectly"); status = WEXITSTATUS (status); if (status == 0) { /* Test whether the child wrote the right data. First test the position. It must be the same as in the child. */ if (lseek (fd, 0, SEEK_CUR) != strlen (testdata2)) error (EXIT_FAILURE, 0, "file position not changed"); if (lseek (fd, 0, SEEK_SET) != 0) error (EXIT_FAILURE, errno, "cannot reset file position"); if (read (fd, buf, sizeof buf) != strlen (testdata2)) error (EXIT_FAILURE, errno, "cannot read new data"); if (memcmp (buf, testdata2, strlen (testdata2)) != 0) error (EXIT_FAILURE, 0, "new data not read correctly"); } return status; }