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)