confirmfilename = concatstr(3, list->dir, "/unsubconf/",
randomstr);
- subconffd = open(confirmfilename, O_RDWR|O_CREAT|O_EXCL,
+ subconffd = open(confirmfilename, O_RDWR|O_CREAT|O_EXLOCK,
S_IRUSR|S_IWUSR);
} while ((subconffd < 0) && (errno == EEXIST));
static void unsubscribe_type(struct mlmmj_list *list,
char *address, char *mlmmjsend,
enum subtype typesub, enum subreason reasonsub) {
- char *subdir, *subddirname, *sublockname;
- char *subreadname = NULL, *subwritename;
- int subread, subwrite, rlock, wlock;
- int sublock, sublockfd;
+ const char *subdir;
+ char *sublockname;
+ char *subwritename;
+ int subread, subwrite, sublockfd;
int groupwritable = 0;
int unsubres;
struct stat st;
DIR *subddir;
struct dirent *dp;
off_t suboff;
+ int subdirfd;
- switch(typesub) {
- default:
- case SUB_NORMAL:
- subdir = "/subscribers.d/";
- break;
- case SUB_DIGEST:
- subdir = "/digesters.d/";
- break;
- case SUB_NOMAIL:
- subdir = "/nomailsubs.d/";
- break;
- }
-
- subddirname = concatstr(2, list->dir, subdir);
- if (stat(subddirname, &st) == 0) {
+ subdirfd = open_subscriber_directory(list, typesub, &subdir);
+ if (fstat(subdirfd, &st) == 0) {
if(st.st_mode & S_IWGRP) {
groupwritable = S_IRGRP|S_IWGRP;
umask(S_IWOTH);
}
}
- if((subddir = opendir(subddirname)) == NULL) {
- log_error(LOG_ARGS, "Could not opendir(%s)",
- subddirname);
- myfree(subddirname);
+ if((subddir = fdopendir(subdirfd)) == NULL) {
+ log_error(LOG_ARGS, "Could not opendir(%s/%s)",
+ list->dir, subdir);
exit(EXIT_FAILURE);
}
- myfree(subddirname);
-
while((dp = readdir(subddir)) != NULL) {
if(!strcmp(dp->d_name, "."))
continue;
if(!strcmp(dp->d_name, ".."))
continue;
-
- subreadname = concatstr(3, list->dir, subdir, dp->d_name);
- subread = open(subreadname, O_RDWR);
- if(subread == -1) {
- myfree(subreadname);
+ subread = openat(subdirfd, dp->d_name, O_RDWR|O_EXLOCK);
+ if(subread == -1)
continue;
- }
suboff = find_subscriber(subread, address);
if(suboff == -1) {
close(subread);
- myfree(subreadname);
continue;
}
/* create a .name.lock file and aquire the lock */
- sublockname = concatstr(5, list->dir, subdir, ".", dp->d_name,
- ".lock");
- sublockfd = open(sublockname, O_RDWR | O_CREAT,
+ myasprintf(&sublockname, ".%s.lock", dp->d_name);
+ sublockfd = open(sublockname, O_RDWR | O_CREAT | O_EXLOCK,
S_IRUSR | S_IWUSR);
- if(sublockfd < 0) {
- log_error(LOG_ARGS, "Error opening lock file %s",
- sublockname);
+ if (sublockfd < 0) {
+ log_error(LOG_ARGS, "Error opening lock file %s/%s/%s",
+ list->dir, subdir, sublockname);
myfree(sublockname);
continue;
}
- sublock = myexcllock(sublockfd);
- if(sublock < 0) {
- log_error(LOG_ARGS, "Error locking '%s' file",
- sublockname);
- myfree(sublockname);
- close(sublockfd);
- continue;
- }
-
- rlock = myexcllock(subread);
- if(rlock < 0) {
- log_error(LOG_ARGS, "Error locking '%s' file",
- subreadname);
- close(subread);
- close(sublockfd);
- myfree(subreadname);
- myfree(sublockname);
- continue;
- }
-
- subwritename = concatstr(2, subreadname, ".new");
-
- subwrite = open(subwritename, O_RDWR | O_CREAT | O_TRUNC,
+ myasprintf(&subwritename, "%s.new", dp->d_name);
+ subwrite = openat(subdirfd, subwritename, O_RDWR | O_CREAT | O_TRUNC | O_EXLOCK,
S_IRUSR | S_IWUSR | groupwritable);
if(subwrite == -1){
- log_error(LOG_ARGS, "Could not open '%s'",
- subwritename);
- close(subread);
- close(sublockfd);
- myfree(subreadname);
- myfree(subwritename);
- myfree(sublockname);
- continue;
- }
-
- wlock = myexcllock(subwrite);
- if(wlock < 0) {
- log_error(LOG_ARGS, "Error locking '%s'",
- subwritename);
+ log_error(LOG_ARGS, "Could not open '%s/%s/%s'",
+ list->dir, subdir, subwritename);
close(subread);
- close(subwrite);
close(sublockfd);
- myfree(subreadname);
myfree(subwritename);
myfree(sublockname);
continue;
close(subwrite);
close(sublockfd);
unlink(subwritename);
- myfree(subreadname);
myfree(subwritename);
myfree(sublockname);
continue;
}
if(unsubres > 0) {
- if(rename(subwritename, subreadname) < 0) {
+ if(renameat(subdirfd, subwritename, subdirfd, dp->d_name) < 0) {
log_error(LOG_ARGS,
"Could not rename '%s' to '%s'",
- subwritename, subreadname);
+ subwritename, dp->d_name);
close(subread);
close(subwrite);
- myfree(subreadname);
myfree(subwritename);
continue;
}
} else { /* unsubres == 0, no subscribers left */
- unlink(subwritename);
- unlink(subreadname);
+ unlinkat(subdirfd, subwritename, 0);
}
close(subread);
close(subwrite);
close(sublockfd);
- myfree(subreadname);
myfree(subwritename);
- unlink(sublockname);
+ unlinkat(subdirfd, sublockname, 0);
myfree(sublockname);
}