Re: 1.2.14beta2 released (major bugfixes)

Peter Stuge <[email protected]> Sat, 24 Sep 2005 17:59:38 +0200
Newsgroups gmane.mail.imap.binc.devel
Message-ID <[email protected]>
--0F1p//8PRICkK4MW
Content-Type: text/plain; charset=iso-8859-1
Content-Disposition: inline
Content-Transfer-Encoding: 8bit

On Fri, Sep 23, 2005 at 08:37:58AM +0200, Jerry Lundström wrote:
> Peter Stuge wrote:
> >I'd instead vote for F_NOTIFY in Linux, which would make for great
> >performace. :) Only in Linux though. (See fcntl(2))
> 
> Interesting, I'll look into that.

I posted this code snippet to the list a while back, showing how it
works. Here's a slightly revised version.


//Peter

--0F1p//8PRICkK4MW
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="notify.c"

/*
 * Written by Peter Stuge <[email protected]>
 * This code is placed into the public domain.
 */

#define _GNU_SOURCE

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <stdarg.h>
#include <errno.h>

void xit(int doperror,unsigned char *s,...) {
  va_list ap;
  if(doperror) {
    perror("");
    if(s)
      fprintf(stderr,": ");
  }
  if(s) {
    va_start(ap,s);
    vfprintf(stderr,s,ap);
    va_end(ap);
  }
  fprintf(stderr,"\n");
  exit(1);
}

int fds[2];

static void sighandler(int signum) {
  switch(signum) {
    case SIGIO:
      write(fds[1],"r",1);
      break;
    case SIGINT:
    case SIGTERM:
      write(fds[1],"x",1);
      break;
  }
}

void setup_sigs() {
  struct sigaction sigact;
  sigact.sa_handler=sighandler;
  sigemptyset(&sigact.sa_mask);
  sigact.sa_flags=0;
  sigaction(SIGIO,&sigact,NULL);
  sigaction(SIGINT,&sigact,NULL);
  sigaction(SIGTERM,&sigact,NULL);
}

int main(int argc,char **argv) {
  char c;
  int i,done;
  fd_set rfds;

  if(argc<2)
    xit(0,"syntax: %s <dir_to_watch>",*argv);

  if((i=open(argv[1],O_RDONLY))==-1)
    xit(1,"open(%s)",argv[1]);

  if(pipe(fds))
    xit(1,"pipe");

  setup_sigs();

  fcntl(i,F_NOTIFY,DN_ACCESS|DN_CREATE|DN_DELETE|DN_RENAME|DN_MULTISHOT);

  for(done=0;!done;) {
    FD_ZERO(&rfds);
    FD_SET(fds[0],&rfds);
    if(select(fds[0]+1,&rfds,NULL,NULL,NULL)>0) {
      read(fds[0],&c,1);
      switch(c) {
      case 'r':
        fprintf(stderr,"the directory changed...\n");
        break;
      case 'x':
        done=1;
        break;
      }
    } else if(errno!=EINTR)
      perror("select");
  }

  close(i);
  return 0;
}

--0F1p//8PRICkK4MW--