Back to index

glibc  2.9
tst-fork.c
Go to the documentation of this file.
00001 /* Tests for fork.
00002    Copyright (C) 2000 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <errno.h>
00022 #include <error.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include <unistd.h>
00026 #include <wait.h>
00027 
00028 
00029 static const char testdata[] = "This is a test";
00030 static const char testdata2[] = "And here we go again";
00031 
00032 
00033 int
00034 main (void)
00035 {
00036   const char *tmpdir = getenv ("TMPDIR");
00037   char buf[100];
00038   size_t tmpdirlen;
00039   char *name;
00040   int fd;
00041   pid_t pid;
00042   pid_t ppid;
00043   off_t off;
00044   int status;
00045 
00046   if (tmpdir == NULL || *tmpdir == '\0')
00047     tmpdir = "/tmp";
00048   tmpdirlen = strlen (tmpdir);
00049 
00050   name = (char *) malloc (tmpdirlen + strlen ("/forkXXXXXX") + 1);
00051   if (name == NULL)
00052     error (EXIT_FAILURE, errno, "cannot allocate file name");
00053 
00054   mempcpy (mempcpy (name, tmpdir, tmpdirlen),
00055           "/forkXXXXXX", sizeof ("/forkXXXXXX"));
00056 
00057   /* Open our test file.   */
00058   fd = mkstemp (name);
00059   if (fd == -1)
00060      error (EXIT_FAILURE, errno, "cannot open test file `%s'", name);
00061 
00062   /* Make sure it gets removed.  */
00063   unlink (name);
00064 
00065   /* Write some data.  */
00066   if (write (fd, testdata, strlen (testdata)) != strlen (testdata))
00067     error (EXIT_FAILURE, errno, "cannot write test data");
00068 
00069   /* Get the position in the stream.  */
00070   off = lseek (fd, 0, SEEK_CUR);
00071   if (off == (off_t) -1 || off != strlen (testdata))
00072     error (EXIT_FAILURE, errno, "wrong file position");
00073 
00074   /* Get the parent PID.  */
00075   ppid = getpid ();
00076 
00077   /* Now fork of the process.  */
00078   pid = fork ();
00079   if (pid == 0)
00080     {
00081       /* One little test first: the PID must have changed.  */
00082       if (getpid () == ppid)
00083        error (EXIT_FAILURE, 0, "child and parent have same PID");
00084 
00085       /* Test the `getppid' function.  */
00086       pid = getppid ();
00087       if (pid == (pid_t) -1 ? errno != ENOSYS : pid != ppid)
00088        error (EXIT_FAILURE, 0,
00089               "getppid returned wrong PID (%ld, should be %ld)",
00090               (long int) pid, (long int) ppid);
00091 
00092       /* This is the child.  First get the position of the descriptor.  */
00093       off = lseek (fd, 0, SEEK_CUR);
00094       if (off == (off_t) -1 || off != strlen (testdata))
00095        error (EXIT_FAILURE, errno, "wrong file position in child");
00096 
00097       /* Reset the position.  */
00098       if (lseek (fd, 0, SEEK_SET) != 0)
00099        error (EXIT_FAILURE, errno, "cannot reset position in child");
00100 
00101       /* Read the data.  */
00102       if (read (fd, buf, sizeof buf) != strlen (testdata))
00103        error (EXIT_FAILURE, errno, "cannot read data in child");
00104 
00105       /* Compare the data.  */
00106       if (memcmp (buf, testdata, strlen (testdata)) != 0)
00107        error (EXIT_FAILURE, 0, "data comparison failed in child");
00108 
00109       /* Reset position again.  */
00110       if (lseek (fd, 0, SEEK_SET) != 0)
00111        error (EXIT_FAILURE, errno, "cannot reset position again in child");
00112 
00113       /* Write new data.  */
00114       if (write (fd, testdata2, strlen (testdata2)) != strlen (testdata2))
00115        error (EXIT_FAILURE, errno, "cannot write new data in child");
00116 
00117       /* Close the file.  This must not remove it.  */
00118       close (fd);
00119 
00120       _exit (0);
00121     }
00122   else if (pid < 0)
00123     /* Something went wrong.  */
00124     error (EXIT_FAILURE, errno, "cannot fork");
00125 
00126   /* Wait for the child.  */
00127   if (waitpid (pid, &status, 0) != pid)
00128     error (EXIT_FAILURE, 0, "Oops, wrong test program terminated");
00129 
00130   if (WTERMSIG (status) != 0)
00131     error (EXIT_FAILURE, 0, "Child terminated incorrectly");
00132   status = WEXITSTATUS (status);
00133 
00134   if (status == 0)
00135     {
00136       /* Test whether the child wrote the right data.  First test the
00137         position.  It must be the same as in the child.  */
00138       if (lseek (fd, 0, SEEK_CUR) != strlen (testdata2))
00139        error (EXIT_FAILURE, 0, "file position not changed");
00140 
00141       if (lseek (fd, 0, SEEK_SET) != 0)
00142        error (EXIT_FAILURE, errno, "cannot reset file position");
00143 
00144       if (read (fd, buf, sizeof buf) != strlen (testdata2))
00145        error (EXIT_FAILURE, errno, "cannot read new data");
00146 
00147       if (memcmp (buf, testdata2, strlen (testdata2)) != 0)
00148        error (EXIT_FAILURE, 0, "new data not read correctly");
00149     }
00150 
00151   return status;
00152 }