h_nullmnt.c revision 1.2
11.1Spgoyette#include <err.h> 21.1Spgoyette#include <fcntl.h> 31.1Spgoyette#include <stdlib.h> 41.1Spgoyette#include <unistd.h> 51.1Spgoyette 61.1Spgoyette#include <sys/event.h> 71.1Spgoyette#include <sys/time.h> 81.1Spgoyette 91.1Spgoyette/* 101.2Spgoyette * External test set-up code is expected to do the equivalent of 111.1Spgoyette * cd $TOPDIR 121.1Spgoyette * mkdir realdir 131.1Spgoyette * mkdir nulldir 141.1Spgoyette * mount -t null $TOPDIR/realdir $TOPDIR/nulldir 151.1Spgoyette * rm -f $TOPDIR/realdir/afile 161.1Spgoyette * touch $TOPDIR/realdir/afile 171.1Spgoyette * then execute this test program: 181.1Spgoyette * ./h_nullmnt $TOPDIR/realdir/afile $TOPDIR/nulldir/afile 191.1Spgoyette * 201.1Spgoyette * The expected result is that the write() to the nullfile will 211.1Spgoyette * queue up a preexisting kevent which will then be detected by 221.1Spgoyette * the (second) call to kevent(); the failure mode is that the 231.1Spgoyette * write()'s extension to the file is not seen, and the kevent 241.1Spgoyette * call times out after 5 seconds. 251.1Spgoyette * 261.1Spgoyette * Clean-up code should undo the null mount and delete everything 271.1Spgoyette * in the test directory. 281.1Spgoyette */ 291.1Spgoyette 301.1Spgoyetteint main(int argc, char **argv) 311.1Spgoyette{ 321.2Spgoyette int watch_file, write_file; 331.1Spgoyette int kq, nev, rsize; 341.1Spgoyette struct timespec timeout; 351.1Spgoyette struct kevent eventlist; 361.1Spgoyette const char outbuf[] = "new\n"; 371.1Spgoyette char inbuf[20]; 381.1Spgoyette 391.1Spgoyette if (argc <= 2) 401.1Spgoyette errx(EXIT_FAILURE, "insufficient args %d", argc); 411.1Spgoyette 421.2Spgoyette watch_file = open(argv[1], O_RDONLY); 431.2Spgoyette if (watch_file == -1) 441.2Spgoyette err(EXIT_FAILURE, "failed to open watch_file %s", 451.1Spgoyette argv[1]); 461.1Spgoyette 471.2Spgoyette write_file = open(argv[2], O_WRONLY, O_APPEND); 481.2Spgoyette if (write_file == -1) 491.2Spgoyette err(EXIT_FAILURE, "failed to open write_file %s", 501.1Spgoyette argv[2]); 511.1Spgoyette 521.1Spgoyette if ((kq = kqueue()) == -1) 531.1Spgoyette err(EXIT_FAILURE, "Cannot create kqueue"); 541.1Spgoyette 551.1Spgoyette timeout.tv_sec = 5; 561.1Spgoyette timeout.tv_nsec = 0; 571.1Spgoyette 581.2Spgoyette EV_SET(&eventlist, watch_file, 591.1Spgoyette EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, 601.1Spgoyette NOTE_WRITE | NOTE_EXTEND, 0, 0); 611.1Spgoyette if (kevent(kq, &eventlist, 1, NULL, 0, NULL) == -1) 621.1Spgoyette err(EXIT_FAILURE, "Failed to set eventlist for fd %d", 631.2Spgoyette watch_file); 641.1Spgoyette 651.2Spgoyette rsize = read(watch_file, &inbuf, sizeof(inbuf)); 661.1Spgoyette if (rsize) 671.1Spgoyette errx(EXIT_FAILURE, "Ooops we got %d bytes of data!\n", rsize); 681.1Spgoyette 691.2Spgoyette write(write_file, &outbuf, sizeof(outbuf) - 1); 701.1Spgoyette 711.1Spgoyette nev = kevent(kq, NULL, 0, &eventlist, 1, &timeout); 721.1Spgoyette if (nev == -1) 731.1Spgoyette err(EXIT_FAILURE, "Failed to retrieve event"); 741.1Spgoyette 751.1Spgoyette errx((nev == 0) ? EXIT_FAILURE : EXIT_SUCCESS, 761.1Spgoyette "Retrieved %d events, first 0x%x", nev, eventlist.flags); 771.1Spgoyette} 78