1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * This proram is used by open_downgrade.ksh script to generate a scenario
  29  * where OPEN_DOWNGRADE operation is performed on a stale file handler.
  30  *
  31  * In the comments on 6282664, Eric suggested a way to generate the scenario:
  32  *
  33  *     1) client# mount server:/expor
  34  *     2) client# fd1 = open(file, RD_ONLY)
  35  *     3) client# fd2 = open(file, WR_ONLY)
  36  *     4) server# rm /export/file
  37  *     5) server# unshare /export
  38  *     6) server# share /export
  39  *     7) client# close(fd1)
  40  *
  41  * This program does step 2, 3, and 7. open_downgrade.ksh does step 1, 4, 5,
  42  * and 6.
  43  */
  44 
  45 #include <stdio.h>
  46 #include <stdlib.h>
  47 #include <sys/types.h>
  48 #include <sys/stat.h>
  49 #include <fcntl.h>
  50 #include <signal.h>
  51 #include <unistd.h>
  52 #include <errno.h>
  53 
  54 int fd1, fd2;
  55 
  56 void
  57 handler(int sig)
  58 {
  59         switch (sig) {
  60         case SIGUSR1:
  61                 /* close fd1 */
  62                 if (close(fd1) < 0 && errno == ESTALE) {
  63                         printf("Received NFS4ERR_STALE on close(fd1)\n");
  64                         fflush(stdout);
  65                 }
  66                 fd1 = 0;
  67 
  68                 break;
  69         case SIGUSR2:
  70                 /* close fd2 */
  71                 if (close(fd2) < 0 && errno == ESTALE) {
  72                         printf("Received NFS4ERR_STALE on close(fd2)\n");
  73                         fflush(stdout);
  74                 }
  75                 fd2 = 0;
  76 
  77                 break;
  78         default:
  79                 /* shouldn't be reached */
  80                 exit(1);
  81         }
  82 }
  83 
  84 int
  85 main(int argc, char **argv)
  86 {
  87         if (argc != 2) {
  88                 printf("Usage: %s <filename>\n", argv[0]);
  89                 exit(1);
  90         }
  91 
  92         (void) signal(SIGUSR1, handler);
  93         (void) signal(SIGUSR2, handler);
  94 
  95         /* open file with O_RDONLY */
  96         fd1 = open(argv[1], O_RDONLY);
  97 
  98         if (fd1 < 0) {
  99                 perror("open(file, O_RDONLY)");
 100                 exit(1);
 101         }
 102 
 103         /* open the same file with O_WRONLY */
 104         fd2 = open(argv[1], O_WRONLY);
 105 
 106         if (fd2 < 0) {
 107                 perror("open(file, O_WRONLY)");
 108                 exit(1);
 109         }
 110 
 111         printf("fd1 and fd2 were opened.\n");
 112         fflush(stdout);
 113 
 114         /* sleep until further notification */
 115         while (fd1 != 0 || fd2 != 0) {
 116                 pause();
 117         }
 118 
 119         return (errno);
 120 }