#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <string.h>
#ifndef IN_BSD_LAND
/* This is for flock() in Linux */
#include <sys/file.h>
#endif
void hang_out(int t)
{
int i = t;
/* There is a cleaner way to do this... It does not really matter. I just
do not want it to print the number we are starting with, and do not want
it to print 0. */
if(t >= 1)
sleep(1);
while(--i)
{
fprintf(stderr, "%d", i);
sleep(1);
}
}
int main(int argc, char *argv[])
{
int f, ff; /* File and FlagFile */
ssize_t rw;
char buf[16];
/* ======================================================================= */
if(argc != 2)
{
fprintf(stderr, "Unable to determine what mode I am in.\nExiting.\n");
return(1);
}
if((0 == strcmp(argv[1], "--help")) ||
(0 == strcmp(argv[1], "-h")) ||
(0 == strcmp(argv[1], "-H")))
{
printf("flock - An instructive file locking tool.\n");
printf(" Open two windows, and in the first window run \"flock first\", then in\n");
printf(" the second window run \"flock second\". The first will hold open the\n");
printf(" file with a shared lock for 10 seconds. The second will open the file\n");
printf(" with a shared lock then attempt to convert the lock to exclusive. The\n");
printf(" second will block waiting for the first to release the lock (when it\n");
printf(" closes the file). Remember: flock blocks!\n");
return(0);
}
/* ======================================================================= */
if(0 == strcmp(argv[1], "first"))
{
fprintf(stderr, "Removing any pre-existing flag file...");
remove("flag.file");
fprintf(stderr, "Done.\n");
#ifdef IN_BSD_LAND
fprintf(stderr, "Opening file with exclusive lock...");
if(-1 == (f = open("delete.me",
O_CREAT | O_WRONLY | O_APPEND | O_EXLOCK,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)))
{
fprintf(stderr, "Failed.\n");
return(1);
}
fprintf(stderr, "Done.\n");
#else
fprintf(stderr, "Opening file...");
if(-1 == (f = open("delete.me",
O_CREAT | O_WRONLY | O_APPEND,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)))
{
fprintf(stderr, "Failed.\n");
return(1);
}
fprintf(stderr, "Done.\n");
fprintf(stderr, "Setting an exclusive lock on the file...");
if(-1 == flock(f, LOCK_EX))
{
fprintf(stderr, "Failed.\n");
return(1);
}
fprintf(stderr, "Done.\n");
#endif
fprintf(stderr, "Writing some characters...");
rw = write(f, "some characters", 15);
if(rw == 15)
fprintf(stderr, "Done.\n");
else
{
fprintf(stderr, "Failed.\n");
return(1);
}
fprintf(stderr, "Waiting for \"second\" to start...");
while(-1 == (ff = open("flag.file",
O_RDONLY,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)))
{
fprintf(stderr, ".");
sleep(1);
}
rw = read(ff, buf, 16);
close(ff);
fprintf(stderr, "Started.");
if(rw > 0)
{
buf[rw] = 0;
fprintf(stderr, " PID=%s\n", buf);
}
else
fprintf(stderr, "\n");
fprintf(stderr, "Removing the flag file...");
remove("flag.file");
fprintf(stderr, "Done.\n");
fprintf(stderr, "Holding file open (exclusively) for 10 seconds...");
hang_out(10);
fprintf(stderr, "...Done.\n");
fprintf(stderr, "Closing the file...");
close(f);
fprintf(stderr, "Done.\n");
fprintf(stderr, "Waiting a second to insure that we are into next operation...");
sleep(1);
fprintf(stderr, "Done.\n");
#ifdef IN_BSD_LAND
fprintf(stderr, "Opening file again with shared lock...");
if(-1 == (f = open("delete.me",
O_CREAT | O_WRONLY | O_APPEND | O_SHLOCK,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)))
{
fprintf(stderr, "Failed.\n");
return(1);
}
fprintf(stderr, "Done.\n");
#else
fprintf(stderr, "Opening file again...");
if(-1 == (f = open("delete.me",
O_CREAT | O_WRONLY | O_APPEND,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)))
{
fprintf(stderr, "Failed.\n");
return(1);
}
fprintf(stderr, "Done.\n");
fprintf(stderr, "Setting a shared lock on the file...");
if(-1 == flock(f, LOCK_SH))
{
fprintf(stderr, "Failed.\n");
return(1);
}
fprintf(stderr, "Done.\n");
#endif
fprintf(stderr, "Closing the file...");
close(f);
fprintf(stderr, "Done.\n");
}
/* ======================================================================= */
if(0 == strcmp(argv[1], "second"))
{
fprintf(stderr, "Signaling that I have started...");
if(-1 == (ff = open("flag.file",
O_CREAT | O_TRUNC | O_WRONLY,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)))
{
fprintf(stderr, "Failed.");
return(1);
}
sprintf(buf, "%d", getpid());
/*fprintf(stderr, "[%s]", buf);*/
rw = write(ff, buf, strlen(buf));
close(ff);
if(rw == strlen(buf))
fprintf(stderr, "Done.\n");
else
fprintf(stderr, "Completed, with errors.\n");
#ifdef IN_BSD_LAND
fprintf(stderr, "Opening file with shared lock...");
if(-1 == (f = open("delete.me",
O_RDWR | O_SHLOCK,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)))
{
fprintf(stderr, "Failed.\n");
return(1);
}
fprintf(stderr, "Done.\n");
#else
fprintf(stderr, "Opening file...");
if(-1 == (f = open("delete.me",
O_RDWR,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)))
{
fprintf(stderr, "Failed.\n");
return(1);
}
fprintf(stderr, "Done.\n");
fprintf(stderr, "Setting a shared lock on the file...");
if(-1 == flock(f, LOCK_SH))
{
fprintf(stderr, "Failed.\n");
return(1);
}
fprintf(stderr, "Done.\n");
#endif
fprintf(stderr, "Reading some characters...");
rw = read(f, &buf, 15);
if(rw == 15)
fprintf(stderr, "Done.\n");
else
{
fprintf(stderr, "Failed.\n");
return(1);
}
fprintf(stderr, "Upgrading file lock to exclusive...");
if(-1 == flock(f, LOCK_EX))
{
fprintf(stderr, "Failed.\n");
return(1);
}
fprintf(stderr, "Done.\n");
fprintf(stderr, "Writing a character...");
rw = write(f, "\n", 1);
if(rw == 1)
fprintf(stderr, "Done.\n");
else
{
fprintf(stderr, "Failed.\n");
return(1);
}
fprintf(stderr, "Holding file open with exclusive lock for 10 seconds...");
hang_out(10);
fprintf(stderr, "...Done.\n");
fprintf(stderr, "Downgrading file lock to shared...");
if(-1 == flock(f, LOCK_SH))
{
fprintf(stderr, "Failed.\n");
return(1);
}
fprintf(stderr, "Done.\n");
fprintf(stderr, "Holding file open with shared lock for 10 seconds...");
hang_out(10);
fprintf(stderr, "...Done.\n");
fprintf(stderr, "Closing the file...");
close(f);
fprintf(stderr, "Done.\n");
}
return(0);
}