I havn't tested this much any feedback would be good but after adding
100,000 uers and corrupting god knows how many .dir_control files it had
to be done : )

Eric


diff -rcN vpopmail-4.8.9.orig/bigdir.c vpopmail-4.8.9/bigdir.c
*** vpopmail-4.8.9.orig/bigdir.c        Wed Jun  7 21:00:59 2000
--- vpopmail-4.8.9/bigdir.c     Fri Aug 18 07:32:33 2000
***************
*** 25,31 ****
--- 25,34 ----
  #include <fcntl.h>
  #include <unistd.h>
  #include <string.h>
+ #include <errno.h>
+ 
  #include "bigdir.h"
+ #include "file_lock.h"
  #include "config.h"
  
  #define MAX_DIR_LIST 62
***************
*** 66,71 ****
--- 69,75 ----
  int read_dir_control(vdir_type *vdir)
  { 
   FILE *fs;
+  int try=0;
  
        if ( (fs = fopen(".dir-control", "r")) == NULL ) {
                int i;
***************
*** 83,88 ****
--- 87,112 ----
                vdir->the_dir[0] = 0;
                return(-1);
        } 
+ 
+       while(read_lock(fileno(fs), 0, SEEK_SET, 0) < 0)
+       {
+               if (errno == EAGAIN || errno == EACCES) 
+               {
+                       /* there might be other errors cases in which
+                       * you might try again. 
+                       */
+                       if (++try < MAX_TRY_RLOCK) {
+                               (void) sleep(2);
+                               continue;
+                       }
+                       (void) fprintf(stderr,"File busy try again later!\n");
+                       return(-1);
+               }
+ 
+               perror("fcntl");
+               exit(2);
+       }
+ 
        fscanf(fs, "%lu\n", &vdir->cur_users);
        fscanf(fs, "%d\n", &vdir->level_cur);
        fscanf(fs, "%d\n", &vdir->level_max);
***************
*** 104,109 ****
--- 128,135 ----
                &vdir->level_index[2]);
        fscanf(fs, "%s\n", vdir->the_dir); 
  
+       unlock_lock(fileno(fs), 0, SEEK_SET, 0);
+ 
        fclose(fs);
  
        return(0);
***************
*** 112,121 ****
--- 138,168 ----
  int write_dir_control(vdir_type *vdir)
  { 
   FILE *fs;
+  int try=0;
  
        if ( (fs = fopen(".dir-control", "w+")) == NULL ) {
                return(-1);
        } 
+ 
+       while(read_lock(fileno(fs), 0, SEEK_SET, 0) < 0)
+       {
+               if (errno == EAGAIN || errno == EACCES) 
+               {
+                       /* there might be other errors cases in which
+                       * you might try again. 
+                       */
+                       if (++try < MAX_TRY_RLOCK) {
+                               (void) sleep(2);
+                               continue;
+                       }
+                       (void) fprintf(stderr,"File busy try again later!\n");
+                       return(-1);
+               }
+ 
+               perror("fcntl");
+               exit(2);
+       }
+ 
        fprintf(fs, "%lu\n", vdir->cur_users);
        fprintf(fs, "%d\n", vdir->level_cur);
        fprintf(fs, "%d\n", vdir->level_max);
***************
*** 136,141 ****
--- 183,191 ----
                vdir->level_index[1],
                vdir->level_index[2]);
        fprintf(fs, "%s\n", vdir->the_dir); 
+ 
+       unlock_lock(fileno(fs), 0, SEEK_SET, 0);
+ 
        fclose(fs);
        chown(".dir-control",VPOPMAILUID, VPOPMAILGID);
        return(0);
diff -rcN vpopmail-4.8.9.orig/bigdir.h vpopmail-4.8.9/bigdir.h
*** vpopmail-4.8.9.orig/bigdir.h        Wed Jun  7 21:00:59 2000
--- vpopmail-4.8.9/bigdir.h     Fri Aug 18 07:32:33 2000
***************
*** 22,27 ****
--- 22,30 ----
  #define MAX_DIR_LEVELS        3
  #define MAX_USERS_PER_LEVEL 100
  
+ #define MAX_TRY_RLOCK 10
+ #define MAX_TRY_WLOCK 15
+ 
  #define MAX_DIR_NAME  300
  typedef struct {
        int level_cur;
diff -rcN vpopmail-4.8.9.orig/file_lock.c vpopmail-4.8.9/file_lock.c
*** vpopmail-4.8.9.orig/file_lock.c     Wed Dec 31 19:00:00 1969
--- vpopmail-4.8.9/file_lock.c  Fri Aug 18 07:32:33 2000
***************
*** 0 ****
--- 1,50 ----
+ /*
+ file_lock.c
+ 
+ functions straight out of Richard Steven's 
+ "Advanced Programming in the UNIX Environment"
+ 
+ Translated into bytes by Eric Peters ([EMAIL PROTECTED])
+       August 19, 2000
+ 
+ */
+ 
+ #include <sys/types.h>
+ #include <stdio.h>    /* for perror() */
+ #include <errno.h>    /* for perror() */
+ #include <fcntl.h>
+ 
+ int
+ lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
+ {
+       struct flock    lock;
+ 
+       lock.l_type     = type;         /* F_RDLCK, F_WRLCK, F_UNLCK */
+       lock.l_start    = offset;       /* byte offset, relative to l_whence */
+       lock.l_whence   = whence;       /* SEEK_SET, SEEK_CUR, SEEK_END */
+       lock.l_len      = len;          /* #bytes (0 means to EOF) */
+ 
+       return( fcntl(fd, cmd, &lock) );
+ }
+ 
+ 
+ pid_t
+ lock_test(int fd, int type, off_t offset, int whence, off_t len)
+ {
+       struct flock    lock;
+ 
+       lock.l_type     = type;         /* F_RDLCK, F_WRLCK, F_UNLCK */
+       lock.l_start    = offset;       /* byte offset, relative to l_whence */
+       lock.l_whence   = whence;       /* SEEK_SET, SEEK_CUR, SEEK_END */
+       lock.l_len      = len;          /* #bytes (0 means to EOF) */
+ 
+       if (fcntl(fd, F_GETLK, &lock) < 0)
+       {
+               perror("fcntl error");
+               return(0);
+       }
+ 
+       if (lock.l_type == F_UNLCK)
+               return(0);      /* false, region is not locked yb another proc */
+       return(lock.l_pid);     /* true, return pid of lock owner */
+ }
diff -rcN vpopmail-4.8.9.orig/file_lock.h vpopmail-4.8.9/file_lock.h
*** vpopmail-4.8.9.orig/file_lock.h     Wed Dec 31 19:00:00 1969
--- vpopmail-4.8.9/file_lock.h  Fri Aug 18 07:32:33 2000
***************
*** 0 ****
--- 1,38 ----
+ /*
+ file_lock.h
+ 
+ functions straight out of Richard Steven's 
+ "Advanced Programming in the UNIX Environment"
+ 
+ Translated into bytes by Eric Peters ([EMAIL PROTECTED])
+       August 19, 2000
+ 
+ */
+ 
+ int
+ lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len);
+ 
+ #define read_lock(fd, offset, whence, len) \
+               lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, len)
+ 
+ #define readw_lock(fd, offset, whence, len) \
+               lock_reg(fd, F_SETLKW, F_RDLCK, offset, whence, len)
+ 
+ #define write_lock(fd, offset, whence, len) \
+               lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len)
+ 
+ #define writew_lock(fd, offset, whence, len) \
+               lock_reg(fd, F_SETLKW, F_WRLCK, offset, whence, len)
+ 
+ #define unlock_lock(fd, offset, whence, len) \
+               lock_reg(fd, F_SETLK, F_UNLCK, offset, whence, len)
+ 
+ 
+ pid_t
+ lock_test(int fd, int type, off_t offset, int whence, off_t len);
+ 
+ #define is_readlock(fd, offset, whence, len) \
+               lock_test(fd, F_RDLCK, offset, whence, len)
+ 
+ #define is_writelock(fd, offset, whence, len) \
+               lock_test(fd, F_WRLCK, offset, whence, len)

Reply via email to