]> git.ipfire.org Git - thirdparty/mlmmj.git/commitdiff
mlmmj-unsub: convert to use filedescriptors
authorBaptiste Daroussin <bapt@FreeBSD.org>
Thu, 28 Oct 2021 11:53:27 +0000 (13:53 +0200)
committerBaptiste Daroussin <bapt@FreeBSD.org>
Thu, 28 Oct 2021 11:53:39 +0000 (13:53 +0200)
While here, use O_EXLOCK to obtain the lock

src/mlmmj-unsub.c

index 33cb17825ba89a9196725ce3ee33aabee6a542e8..8f35f7d7f2357e7d85d8ddfb32769e31034e6c8c 100644 (file)
@@ -155,7 +155,7 @@ static void generate_unsubconfirm(struct mlmmj_list *list, const char *subaddr,
                 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));
@@ -320,123 +320,67 @@ static void generate_notsubscribed(struct mlmmj_list *list, const char *subaddr,
 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;
@@ -448,34 +392,30 @@ static void unsubscribe_type(struct mlmmj_list *list,
                        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);
 
         }