Home | History | Annotate | Download | only in tests
      1 /** Test program for POSIX advisory record locking. See also #164669
      2  *  (http://bugs.kde.org/show_bug.cgi?id=164669).
      3  *  See also http://www.opengroup.org/onlinepubs/007908799/xsh/fcntl.html.
      4  */
      5 
      6 
      7 #include <assert.h>
      8 #include <errno.h>
      9 #include <fcntl.h>
     10 #include <stdio.h>
     11 #include <stdlib.h>
     12 #include "tests/sys_mman.h"
     13 #include <sys/stat.h>
     14 #include <sys/types.h>
     15 #include <sys/wait.h>
     16 #include <unistd.h>
     17 #include <unistd.h>
     18 
     19 
     20 /** Lock an entire file exclusively.
     21  *
     22  *  @return 1 upon success, 0 upon failure.
     23  */
     24 static int lock_file(const int fd)
     25 {
     26   struct flock fl;
     27 
     28   fl.l_type   = F_WRLCK;  /* exclusive lock */
     29   fl.l_whence = SEEK_SET;
     30   fl.l_start  = 0;
     31   fl.l_len    = 0;        /* lock entire file */
     32   fl.l_pid    = 0;
     33   return fcntl(fd, F_SETLK, &fl) >= 0;
     34 }
     35 
     36 static int open_lock_and_map(const char* const process_name,
     37                              const char* const filename)
     38 {
     39   int fd;
     40   int flags;
     41 
     42   fd = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
     43   if (fd < 0)
     44   {
     45     perror("open");
     46     goto err1;
     47   }
     48 
     49   flags = fcntl(fd, F_GETFD);
     50   assert(flags >= 0);
     51   if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
     52     assert(0);
     53 
     54   fprintf(stderr, "%s: about to lock file for writing.\n", process_name);
     55   if (! lock_file(fd))
     56   {
     57     perror("fcntl");
     58     goto err2;
     59   }
     60 
     61   fprintf(stderr, "%s: file locking attempt succeeded.\n", process_name);
     62   if (mmap(NULL, 1, PROT_WRITE, MAP_SHARED, fd, 0) == 0)
     63   {
     64     perror("mmap");
     65     goto err2;
     66   }
     67 
     68   goto out;
     69 
     70 err2:
     71   close(fd);
     72 err1:
     73 out:
     74   return fd;
     75 }
     76 
     77 int main(int argc, char *argv[])
     78 {
     79   int fd1;
     80   int fd2;
     81   int exitcode = 1;
     82   char filename[256];
     83 
     84   snprintf(filename, sizeof(filename), "/tmp/valgrind-file-locking-test.%ld",
     85            (long) getpid());
     86 
     87   unlink(filename);
     88 
     89   if ((fd1 = open_lock_and_map("parent", filename)) >= 0)
     90   {
     91     pid_t fork_result;
     92 
     93     fork_result = fork();
     94     switch (fork_result)
     95     {
     96     case -1:
     97       perror("fork");
     98       break;
     99 
    100     case 0:
    101       /* child */
    102       fd2 = open_lock_and_map("child", filename);
    103       if (fd2 >= 0)
    104       {
    105         close(fd2);
    106       }
    107       exit(0);
    108       break;
    109 
    110     default:
    111       /* parent */
    112       {
    113         int child_status;
    114         int wait_result;
    115 
    116         wait_result = wait4(fork_result, &child_status, 0, 0);
    117         assert(wait_result >= 0);
    118       }
    119     }
    120   }
    121 
    122   close(fd1);
    123 
    124   unlink(filename);
    125 
    126   fprintf(stderr, "Test finished.\n");
    127 
    128   return exitcode;
    129 }
    130