<html lang='en'>
<head>
<meta content='text/html; charset=utf-8' http-equiv='Content-Type'>
<title>
GitLab
</title>
</meta>
</head>
<style>
  img {
    max-width: 100%;
    height: auto;
  }
  p.details {
    font-style:italic;
    color:#777
  }
  .footer p {
    font-size:small;
    color:#777
  }
  pre.commit-message {
    white-space: pre-wrap;
  }
  .file-stats a {
    text-decoration: none;
  }
  .file-stats .new-file {
    color: #090;
  }
  .file-stats .deleted-file {
    color: #B00;
  }
</style>
<body>
<div class='content'>
<h3>Andrew Price pushed to branch master at <a href="https://projects.sucs.org/arthur/mw">Justin Mitchell / mw</a></h3>
<h4>
Commits:
</h4>
<ul>
<li>
<strong><a href="https://projects.sucs.org/arthur/mw/commit/6bcd1e4b0c822da6d36cb8258db699f72c46b808">6bcd1e4b</a></strong>
<div>
<span>by Andrew Price</span>
<i>at 2015-10-31T16:28:14Z</i>
</div>
<pre class='commit-message'>Folder file overhaul

This moves the folder index, text, moderation and tmp files into
directories corresponding to the file name suffixes currently in use.

Old                     New
---                     ---
STATEDIR/foo.i          STATEDIR/index/foo
STATEDIR/foo.i.m        STATEDIR/index/mod/foo
STATEDIR/foo.i.t        STATEDIR/index/new/foo
STATEDIR/foo.t          STATEDIR/text/foo
STATEDIR/foo.t.m        STATEDIR/text/mod/foo
STATEDIR/foo.t.t        STATEDIR/text/new/foo

This has the following advantages:
1. No more ugly folder path building all over the place
2. STATEDIR and PATHSIZE used in far fewer places
3. No longer assumes paths to folder files will fit in 256 chars
4. A tidier STATEDIR
5. Better separation of concerns (more folder stuff hidden in folders.c)
6. Should make it easier to move the folder stuff into the server
7. Improved error checking/reporting

This makes use of the *at family of syscalls so, instead of building
paths, we now use file descriptors.</pre>
</li>
<li>
<strong><a href="https://projects.sucs.org/arthur/mw/commit/0ac7489164c66a2566e8168a430c6c7aec37406d">0ac74891</a></strong>
<div>
<span>by Andrew Price</span>
<i>at 2015-10-31T16:28:51Z</i>
</div>
<pre class='commit-message'>Fix !folder name command

!folder name was not working because strlen("name") was expected to be
5. Expect it to be 4 instead.</pre>
</li>
<li>
<strong><a href="https://projects.sucs.org/arthur/mw/commit/3f71da2332897f7b51e860a188d847ecfa2aafad">3f71da23</a></strong>
<div>
<span>by Andrew Price</span>
<i>at 2015-10-31T16:29:03Z</i>
</div>
<pre class='commit-message'>Get rid of makepath, buildpath and PATHSIZE

Huzzah!</pre>
</li>
</ul>
<h4>17 changed files:</h4>
<ul>
<li class='file-stats'>
<a href='#diff-0'>
src/bb.h
</a>
</li>
<li class='file-stats'>
<a href='#diff-1'>
src/client/add.c
</a>
</li>
<li class='file-stats'>
<a href='#diff-2'>
src/client/edit.c
</a>
</li>
<li class='file-stats'>
<a href='#diff-3'>
src/client/edit.h
</a>
</li>
<li class='file-stats'>
<a href='#diff-4'>
src/client/main.c
</a>
</li>
<li class='file-stats'>
<a href='#diff-5'>
src/client/main.h
</a>
</li>
<li class='file-stats'>
<a href='#diff-6'>
src/client/mod.c
</a>
</li>
<li class='file-stats'>
<a href='#diff-7'>
src/client/new.c
</a>
</li>
<li class='file-stats'>
<a href='#diff-8'>
src/client/newmain.c
</a>
</li>
<li class='file-stats'>
<a href='#diff-9'>
src/client/read.c
</a>
</li>
<li class='file-stats'>
<a href='#diff-10'>
src/client/script.c
</a>
</li>
<li class='file-stats'>
<a href='#diff-11'>
src/client/strings.c
</a>
</li>
<li class='file-stats'>
<a href='#diff-12'>
src/client/strings.h
</a>
</li>
<li class='file-stats'>
<a href='#diff-13'>
src/client/talker.c
</a>
</li>
<li class='file-stats'>
<a href='#diff-14'>
src/folders.c
</a>
</li>
<li class='file-stats'>
<a href='#diff-15'>
src/folders.h
</a>
</li>
<li class='file-stats'>
<a href='#diff-16'>
src/server/servsock.c
</a>
</li>
</ul>
<h4>Changes:</h4>
<li id='diff-0'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-0'>
<strong>
src/bb.h
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/bb.h
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/bb.h
</span><span style="color: #aaaaaa">@@ -23,20 +23,19 @@
</span> #endif
 
 #define LOGFILE                LOGDIR"/log.bb"
<span style="color: #000000;background-color: #ffdddd">-#define LOGIN_BANNER    "login.banner"
</span><span style="color: #000000;background-color: #ddffdd">+#define LOGIN_BANNER    HOMEPATH"/login.banner"
</span> #define LOCKFILE  "/tmp/bb.locked"
 #define EDITOR         "/usr/bin/vim"
 #define SECUREEDITOR   "/bin/rnano"
 
<span style="color: #000000;background-color: #ffdddd">-#define HELPDIR         "help"
-#define WIZHELP                "wizhelp"
-#define SCRIPTHELP     "scripthelp"
-#define TALKHELP       "talkhelp"
</span><span style="color: #000000;background-color: #ddffdd">+#define HELPDIR         HOMEPATH"/help"
+#define WIZHELP         HOMEPATH"/wizhelp"
+#define SCRIPTHELP      HOMEPATH"/scripthelp"
+#define TALKHELP        HOMEPATH"/talkhelp"
</span> 
 #define TEXT_END       ".t"
 #define INDEX_END      ".i"
 #define MOD_END                ".m"
<span style="color: #000000;background-color: #ffdddd">-#define PATHSIZE        256
</span> 
 #define CMD_BOARD_STR  "!"
 #define CMD_TALK_STR   "."
</code></pre>

<br>
</li>
<li id='diff-1'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-1'>
<strong>
src/client/add.c
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/client/add.c
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/client/add.c
</span><span style="color: #aaaaaa">@@ -150,7 +150,8 @@ int add_msg(int folnum, struct user *user, int replyto)
</span>           long posn,tmppos;
                int headfile;
 
<span style="color: #000000;background-color: #ffdddd">-                if ((headfile=err_open(buildpath(STATEDIR,fol->name,INDEX_END,""),O_RDONLY,0))<0)
</span><span style="color: #000000;background-color: #ddffdd">+           headfile = open_folder_index(fol, FOL_LIVE, O_RDONLY, 0);
+               if (headfile < 0)
</span>           {
                        free(fol);
                        free(new);
<span style="color: #aaaaaa">@@ -384,16 +385,14 @@ int add_msg(int folnum, struct user *user, int replyto)
</span>   folderfile=openfolderfile(O_RDWR);
        Lock_File(folderfile);
 
<span style="color: #000000;background-color: #ffdddd">-        /* open files ready for saveing */
-
-       if ((i=err_open(buildpath(STATEDIR,fol->name,INDEX_END,is_moderated(fol,user)?MOD_END:""),O_CREAT|O_RDWR,0600))<0)
-       {
</span><span style="color: #000000;background-color: #ddffdd">+   /* open files ready for saving */
+       const char *subdir = is_moderated(fol, user) ? FOL_MOD : FOL_LIVE;
+       i = open_folder_index(fol, subdir, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
+       if (i < 0)
</span>           exit(-1);
<span style="color: #000000;background-color: #ffdddd">-        }
-       if ((data=err_open(buildpath(STATEDIR,fol->name,TEXT_END,is_moderated(fol,user)?MOD_END:""),O_APPEND|O_CREAT|O_WRONLY,0600))<0)
-       {
</span><span style="color: #000000;background-color: #ddffdd">+   data = open_folder_text(fol, subdir, O_WRONLY|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR);
+       if (data < 0)
</span>           exit(-1);
<span style="color: #000000;background-color: #ffdddd">-        }
</span>   Lock_File(folderfile);
        Lock_File(i);
        Lock_File(data);
</code></pre>

<br>
</li>
<li id='diff-2'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-2'>
<strong>
src/client/edit.c
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/client/edit.c
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/client/edit.c
</span><span style="color: #aaaaaa">@@ -675,34 +675,17 @@ void edit_folder(const char *args, const char *name)
</span>                   printf(_("Groups changed to [%s]\n"),tmp);
                }
        }else
<span style="color: #000000;background-color: #ffdddd">-        if (stringcmp(args,"name",5))
</span><span style="color: #000000;background-color: #ddffdd">+   if (stringcmp(args,"name",4))
</span>   {
                printf(_("Current folder name = %s\n"),fold.name);
                printf(_("Change to ? (%d chars): "),FOLNAMESIZE);
                get_str(tmp,FOLNAMESIZE);
<span style="color: #000000;background-color: #ffdddd">-                if (*tmp)
-               {
-                       char oldpath[PATHSIZE];
</span><span style="color: #000000;background-color: #ddffdd">+           if (*tmp == '\0' || strchr(tmp, '/') != NULL) {
+                       printf("Bad folder name\n");
+               } else {
</span>                   mwlog("FOLDER(RENAME) of %s to %s", fold.name, tmp);
<span style="color: #000000;background-color: #ffdddd">-
-                       sprintf(oldpath,"%s/%s%s",STATEDIR,fold.name,INDEX_END);
-                       sprintf(fullpath,"%s/%s%s",STATEDIR,tmp,INDEX_END);
-                       if (!access(oldpath,00)) rename(oldpath,fullpath);
-                       sprintf(oldpath,"%s/%s%s",STATEDIR,fold.name,TEXT_END);
-                       sprintf(fullpath,"%s/%s%s",STATEDIR,tmp,TEXT_END);
-                       if (!access(oldpath,00)) rename(oldpath,fullpath);
-                       if (f_moderated(fold.status)||f_moderated(fold.g_status))
-                       {
-                       sprintf(oldpath,"%s/%s%s%s",STATEDIR,fold.name,INDEX_END,MOD_END);
-                       sprintf(fullpath,"%s/%s%s%s",STATEDIR,tmp,INDEX_END,MOD_END);
-                       if (!access(oldpath,00)) rename(oldpath,fullpath);
-                       sprintf(oldpath,"%s/%s%s%s",STATEDIR,fold.name,TEXT_END,MOD_END);
-                       sprintf(fullpath,"%s/%s%s%s",STATEDIR,tmp,TEXT_END,MOD_END);
-                       if (!access(oldpath,00)) rename(oldpath,fullpath);
-                       }
-
-                       strcpy(fold.name,tmp);
-                       printf(_("Name changed to %s\n"),fold.name);
</span><span style="color: #000000;background-color: #ddffdd">+                   if (rename_folder(&fold, tmp) == 0)
+                               printf(_("Name changed to %s\n"), fold.name);
</span>           }
        }else
        if (stringcmp(args,"size",4))
<span style="color: #aaaaaa">@@ -755,17 +738,11 @@ void edit_folder(const char *args, const char *name)
</span>           get_str(tmp,4);
                if (stringcmp(tmp,"yes",-1))
                {
<span style="color: #000000;background-color: #ffdddd">-                        sprintf(fullpath,"%s/%s%s",STATEDIR,fold.name,INDEX_END);
-                       if (!access(fullpath,00)) if (unlink(fullpath)) {perror(fullpath);exit(-1);}
-                       sprintf(fullpath,"%s/%s%s",STATEDIR,fold.name,TEXT_END);
-                       if (!access(fullpath,00)) if (unlink(fullpath)) {perror(fullpath);exit(-1);}
-                       if (f_moderated(fold.status)||f_moderated(fold.g_status))
-                       {
-                       sprintf(fullpath,"%s/%s%s%s",STATEDIR,fold.name,INDEX_END,MOD_END);
-                       if (!access(fullpath,00)) if (unlink(fullpath)) {perror(fullpath);exit(-1);}
-                       sprintf(fullpath,"%s/%s%s%s",STATEDIR,fold.name,TEXT_END,MOD_END);
-                       if (!access(fullpath,00)) if (unlink(fullpath)) {perror(fullpath);exit(-1);}
-                       }
</span><span style="color: #000000;background-color: #ddffdd">+                   unsigned i;
+
+                       for (i = 0; i < (sizeof(folder_types)/sizeof(folder_types[0])); i++)
+                               remove_folder(&fold, folder_types[i]);
+
</span>                   fold.status=0;
                        fold.g_status=0;
                        fold.name[0]=0;
<span style="color: #aaaaaa">@@ -791,15 +768,17 @@ void edit_folder(const char *args, const char *name)
</span> const char *partlist_mesg[]={
 "edit", "to", "subject", "delete", "undelete", "status", NULL};
 
<span style="color: #000000;background-color: #ffdddd">-void mesg_edit(const char *args, char *foldername, int msgno, struct user *usr)
</span><span style="color: #000000;background-color: #ddffdd">+void mesg_edit(const char *args, struct folder *folder, int msgno, struct user *usr)
</span> {
        int fd, text;
        struct Header head;
        char *buff;
 
<span style="color: #000000;background-color: #ffdddd">-        if ((fd=err_open(buildpath(STATEDIR,foldername,INDEX_END,""),O_RDWR,0))<0)
</span><span style="color: #000000;background-color: #ddffdd">+   fd = open_folder_index(folder, FOL_LIVE, O_RDWR, 0);
+       if (fd < 0)
</span>           return;
<span style="color: #000000;background-color: #ffdddd">-        if ((text=err_open(buildpath(STATEDIR,foldername,TEXT_END,""),O_RDWR,0))<0)
</span><span style="color: #000000;background-color: #ddffdd">+   text = open_folder_text(folder, FOL_LIVE, O_RDWR, 0);
+       if (text < 0)
</span>           return;
 
        /* go and get message */
</code></pre>

<br>
</li>
<li id='diff-3'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-3'>
<strong>
src/client/edit.h
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/client/edit.h
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/client/edit.h
</span><span style="color: #aaaaaa">@@ -7,6 +7,6 @@ void time_on(long u);
</span> void edit_user(const char *args, const char *name);
 void edit_folder(const char *args, const char *name);
 void edit_contact(void);
<span style="color: #000000;background-color: #ffdddd">-void mesg_edit(const char *args, char *foldername, int msgno, struct user *usr);
</span><span style="color: #000000;background-color: #ddffdd">+void mesg_edit(const char *args, struct folder *folder, int msgno, struct user *usr);
</span> 
 #endif /* EDIT_H */
</code></pre>

<br>
</li>
<li id='diff-4'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-4'>
<strong>
src/client/main.c
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/client/main.c
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/client/main.c
</span><span style="color: #aaaaaa">@@ -378,6 +378,9 @@ int main(int argc, char **argv)
</span> 
        output=stdout;
 
<span style="color: #000000;background-color: #ddffdd">+        if (folders_init())
+               exit(1);
+
</span> #ifdef GNUTLS_VERSION_MAJOR
        /* Prior to 3.3.0 this is not thread safe
         * so should be done early to prevent a race.
<span style="color: #aaaaaa">@@ -611,7 +614,7 @@ int main(int argc, char **argv)
</span> 
        /* show login banner, and version info */
        /* allow disabling of banner in release version */
<span style="color: #000000;background-color: #ffdddd">-        if (!qflag) printfile(makepath(LOGIN_BANNER,"",""));
</span><span style="color: #000000;background-color: #ddffdd">+   if (!qflag) printfile(LOGIN_BANNER);
</span>   printf("%s\n",version);
 
        /* log the user in by asking for their name (and details) */
<span style="color: #aaaaaa">@@ -935,7 +938,7 @@ void close_down(int exitmode, char *sourceuser, char *reason)
</span>   exit(0);
 }
 
<span style="color: #000000;background-color: #ffdddd">-void printfile(char *filename)
</span><span style="color: #000000;background-color: #ddffdd">+void printfile(const char *filename)
</span> {
        FILE *afile;
        char *buff;
</code></pre>

<br>
</li>
<li id='diff-5'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-5'>
<strong>
src/client/main.h
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/client/main.h
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/client/main.h
</span><span style="color: #aaaaaa">@@ -4,7 +4,7 @@
</span> void close_down(int exitmode, char *sourceuser, char *reason);
 void display_message(const char *text, int beeps, int newline);
 void format_message(const char *format, ...) __attribute__((format(printf,1,0)));
<span style="color: #000000;background-color: #ffdddd">-void printfile(char *filename);
</span><span style="color: #000000;background-color: #ddffdd">+void printfile(const char *filename);
</span> void broadcast_onoffcode(int code, int method, const char *sourceuser, const char *reason);
 void reset_timeout(int secs);
 int idle(int fd, int millis);
</code></pre>

<br>
</li>
<li id='diff-6'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-6'>
<strong>
src/client/mod.c
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/client/mod.c
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/client/mod.c
</span><span style="color: #aaaaaa">@@ -19,16 +19,14 @@
</span> 
 static void add_message(struct folder *fold, struct Header *head, char *text)
 {
<span style="color: #000000;background-color: #ffdddd">-        char fullpath[PATHSIZE];
</span>   int modindex,modtext;
 
<span style="color: #000000;background-color: #ffdddd">-        /* files for general public to read */
-       sprintf(fullpath,"%s/%s%s",STATEDIR,fold->name,INDEX_END);
-       if ((modindex=open(fullpath,O_WRONLY|O_APPEND|O_CREAT,0600))<0)
-               {perror(fullpath);exit(-1);}
-       sprintf(fullpath,"%s/%s%s",STATEDIR,fold->name,TEXT_END);
-       if ((modtext=open(fullpath,O_WRONLY|O_CREAT,0600))<0)
-               {perror(fullpath);exit(-1);}
</span><span style="color: #000000;background-color: #ddffdd">+   modindex = open_folder_index(fold, FOL_LIVE, O_WRONLY|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR);
+       if (modindex < 0)
+               exit(-1);
+       modtext = open_folder_text(fold, FOL_LIVE, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
+       if (modtext < 0)
+               exit(-1);
</span>   Lock_File(modindex);
        Lock_File(modtext);
        head->Ref=fold->last;
<span style="color: #aaaaaa">@@ -44,16 +42,15 @@ static void add_message(struct folder *fold, struct Header *head, char *text)
</span> 
 static void put_back(struct folder *fold, struct Header *head, char *text)
 {
<span style="color: #000000;background-color: #ffdddd">-        char fullpath[PATHSIZE];
</span>   int newindex,newtext;
 
<span style="color: #000000;background-color: #ffdddd">-                /* files to put messages to be approved later */
-       sprintf(fullpath,"%s/%s%s%s",STATEDIR,fold->name,INDEX_END,MOD_END);
-       if ((newindex=open(fullpath,O_WRONLY|O_APPEND|O_CREAT,0600))<0)
-               {perror(fullpath);exit(-1);}
-       sprintf(fullpath,"%s/%s%s%s",STATEDIR,fold->name,TEXT_END,MOD_END);
-       if ((newtext=open(fullpath,O_WRONLY|O_APPEND|O_CREAT,0600))<0)
-               {perror(fullpath);exit(-1);}
</span><span style="color: #000000;background-color: #ddffdd">+   /* files to put messages to be approved later */
+       newindex = open_folder_index(fold, FOL_MOD, O_WRONLY|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR);
+       if (newindex < 0)
+               exit(-1);
+       newtext = open_folder_text(fold, FOL_MOD, O_WRONLY|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR);
+       if (newtext < 0)
+               exit(-1);
</span>   Lock_File(newindex);
        Lock_File(newtext);
        head->datafield=lseek(newtext,0,2);
<span style="color: #aaaaaa">@@ -70,10 +67,9 @@ static void store(struct folder *fold, struct Header *head, char *text)
</span> {
        int afile;
        char buff[128];
<span style="color: #000000;background-color: #ffdddd">-        char fullpath[PATHSIZE];
</span>   time_t head_date;
<span style="color: #000000;background-color: #ddffdd">+        const char *fullpath = STATEDIR"/mod.save";
</span> 
<span style="color: #000000;background-color: #ffdddd">-        sprintf(fullpath,"%s/%s",STATEDIR,"mod.save");
</span>   head_date = (time_t)head->date;
        if ((afile=open(fullpath,O_WRONLY|O_APPEND|O_CREAT,0600))<0)
                {perror(fullpath);exit(-1);}
<span style="color: #aaaaaa">@@ -89,7 +85,6 @@ static void store(struct folder *fold, struct Header *head, char *text)
</span> 
 void moderate(void)
 {
<span style="color: #000000;background-color: #ffdddd">-        char fullpath[PATHSIZE],oldpath[PATHSIZE];
</span>   struct folder fold;
        struct Header head;
        char *text;
<span style="color: #aaaaaa">@@ -104,25 +99,17 @@ void moderate(void)
</span> 
        while (get_folder_entry(f_file,&fold))
        {
<span style="color: #000000;background-color: #ffdddd">-                sprintf(oldpath,"%s/%s%s%s",STATEDIR,fold.name,INDEX_END,MOD_END);
-               if (access(oldpath,00))
</span><span style="color: #000000;background-color: #ddffdd">+           /* Move the folder mod queue to tmp */
+               if (move_folder(&fold, FOL_MOD, FOL_TMP) != 0)
</span>                   continue;
<span style="color: #000000;background-color: #ffdddd">-
</span>           printf(_("Changing to folder %s\n"),fold.name);
<span style="color: #000000;background-color: #ffdddd">-                /* move the unmoderated messages to a temporary file */
-               sprintf(fullpath,"%s/%s%s%s",STATEDIR,fold.name,INDEX_END,".tmp");
-               rename(oldpath,fullpath);
-               sprintf(oldpath,"%s/%s%s%s",STATEDIR,fold.name,TEXT_END,MOD_END);
-               sprintf(fullpath,"%s/%s%s%s",STATEDIR,fold.name,TEXT_END,".tmp");
-               rename(oldpath,fullpath);
</span> 
<span style="color: #000000;background-color: #ffdddd">-                /* files containing messages to be approved */
-               sprintf(fullpath,"%s/%s%s%s",STATEDIR,fold.name,INDEX_END,".tmp");
-               if ((tmpindex=open(fullpath,O_RDONLY))<0)
-                       {perror(fullpath);exit(-1);}
-               sprintf(fullpath,"%s/%s%s%s",STATEDIR,fold.name,TEXT_END,".tmp");
-               if ((tmptext=open(fullpath,O_RDONLY))<0)
-                       {perror(fullpath);exit(-1);}
</span><span style="color: #000000;background-color: #ddffdd">+           /* Open the tmp mod queue */
+               if ((tmpindex = open_folder_index(&fold, FOL_TMP, O_RDONLY, 0)) < 0)
+                       exit(-1);
+               if ((tmptext = open_folder_text(&fold, FOL_TMP, O_RDONLY, 0)) < 0)
+                       exit(-1);
+
</span>           while (get_data(tmpindex,&head))
                {
                        int foo;
<span style="color: #aaaaaa">@@ -163,10 +150,7 @@ void moderate(void)
</span>           printf(_("End of folder %s\n"),fold.name);
                close(tmpindex);
                close(tmptext);
<span style="color: #000000;background-color: #ffdddd">-                sprintf(fullpath,"%s/%s%s%s",STATEDIR,fold.name,INDEX_END,".tmp");
-               if (unlink(fullpath)) {perror(fullpath);exit(-1);}
-               sprintf(fullpath,"%s/%s%s%s",STATEDIR,fold.name,TEXT_END,".tmp");
-               if (unlink(fullpath)) {perror(fullpath);exit(-1);}
</span><span style="color: #000000;background-color: #ddffdd">+           remove_folder(&fold, FOL_TMP);
</span>   }
        close(f_file);
 }
</code></pre>

<br>
</li>
<li id='diff-7'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-7'>
<strong>
src/client/new.c
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/client/new.c
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/client/new.c
</span><span style="color: #aaaaaa">@@ -88,15 +88,16 @@ static int read_new(struct user *user, struct folder *data, int folnum)
</span>   struct Header head;
        char tmp[80];
 
<span style="color: #000000;background-color: #ffdddd">-        if (access(buildpath(STATEDIR,data->name,INDEX_END,""),0))
-               {printf(_("Error: cannot find index file for folder %s\n"),data->name);return(-1);}
-       if (access(buildpath(STATEDIR,data->name,TEXT_END,""),0))
-               {printf(_("Error: cannot find text file for folder %s\n"),data->name); return(-1);}
-       if ((indexfile=err_open(buildpath(STATEDIR,data->name,INDEX_END,""),O_RDONLY,0))<0)
-               {exit(-1);}
-       if ((datafile=err_open(buildpath(STATEDIR,data->name,TEXT_END,""),O_RDONLY,0))<0)
-               {exit(-1);}
-
</span><span style="color: #000000;background-color: #ddffdd">+   indexfile = open_folder_index(data, FOL_LIVE, O_RDONLY, 0);
+       if (indexfile < 0) {
+               printf(_("Error: cannot open index file for folder %s\n"), data->name);
+               return -1;
+       }
+       datafile = open_folder_text(data, FOL_LIVE, O_RDONLY, 0);
+       if (datafile < 0) {
+               printf(_("Error: cannot open text file for folder %s\n"), data->name);
+               return -1;
+       }
</span>   /* try jumping to expected location */
        posn = (urec->lastread[folnum] - data->first + 1) * sizeof(struct Header);
        lseek(indexfile, posn, 0);
<span style="color: #aaaaaa">@@ -232,41 +233,36 @@ void latest(struct user *user)
</span>   {
                if (f_active(fold.status) && allowed_r(&fold,user))
                {
<span style="color: #000000;background-color: #ffdddd">-                        char *x;
</span>                   time_t now, then;
                        struct tm *t_then;
<span style="color: #000000;background-color: #ddffdd">+                        struct Header hdr;
</span> 
<span style="color: #000000;background-color: #ffdddd">-                        x=buildpath(STATEDIR,fold.name,INDEX_END,"");
-                       printf("%*s  ",FOLNAMESIZE,fold.name);
-                       if (access(x,00))
</span><span style="color: #000000;background-color: #ddffdd">+                   printf("%*s  ", FOLNAMESIZE, fold.name);
+                       if ((ifile = open_folder_index(&fold, FOL_LIVE, O_RDONLY, 0)) < 0) {
</span>                           printf(_("            <empty>\n"));
<span style="color: #000000;background-color: #ffdddd">-                        else
-                       {
-                               struct Header hdr;
-                               if ((ifile=err_open(x,O_RDONLY,0))<0)
-                                       return;
-                               lseek(ifile,-1*sizeof(hdr),SEEK_END);
-                               read(ifile,&hdr,sizeof(hdr));
</span><span style="color: #000000;background-color: #ddffdd">+                           return;
+                       }
+                       lseek(ifile,-1*sizeof(hdr),SEEK_END);
+                       read(ifile,&hdr,sizeof(hdr));
</span> 
<span style="color: #000000;background-color: #ffdddd">-                                now=time(0);
-                               then = hdr.date;
-                               t_then=localtime(&then);
-                               if (t_then == NULL)
-                                       snprintf(datestr, 30, "Invalid Date");
-                               else
-                               if (now - hdr.date > 7776000)
-                               strftime(datestr, 30, "%a %b %d %Y ", t_then);
-                               else
-                               strftime(datestr, 30, "%a %b %d %H:%M", t_then);
</span><span style="color: #000000;background-color: #ddffdd">+                   now=time(0);
+                       then = hdr.date;
+                       t_then=localtime(&then);
+                       if (t_then == NULL)
+                               snprintf(datestr, 30, "Invalid Date");
+                       else
+                       if (now - hdr.date > 7776000)
+                       strftime(datestr, 30, "%a %b %d %Y ", t_then);
+                       else
+                       strftime(datestr, 30, "%a %b %d %H:%M", t_then);
</span> 
<span style="color: #000000;background-color: #ffdddd">-                                strncpy(sub,hdr.subject,30);
-                               sub[27]=0;
-                               if (strlen(hdr.subject)>30)
-                                       strcat(sub,"...");
-                               printf("%4d  %s  %*s  %s\n",fold.last,datestr,
-                               NAMESIZE,hdr.from,sub);
-                               close(ifile);
-                       }
</span><span style="color: #000000;background-color: #ddffdd">+                   strncpy(sub,hdr.subject,30);
+                       sub[27]=0;
+                       if (strlen(hdr.subject)>30)
+                               strcat(sub,"...");
+                       printf("%4d  %s  %*s  %s\n",fold.last,datestr,
+                       NAMESIZE,hdr.from,sub);
+                       close(ifile);
</span>           }
        }
        close(ffile);
</code></pre>

<br>
</li>
<li id='diff-8'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-8'>
<strong>
src/client/newmain.c
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/client/newmain.c
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/client/newmain.c
</span><span style="color: #aaaaaa">@@ -37,6 +37,7 @@
</span> #include "userio.h"
 #include "mesg.h"
 #include "incoming.h"
<span style="color: #000000;background-color: #ddffdd">+#include <util.h>
</span> 
 extern Alias alias_list;
 
<span style="color: #aaaaaa">@@ -53,8 +54,6 @@ extern void help_list(CommandList *cm, unsigned int hidestuff);
</span> static void help(const char *topic, int wiz)
 {
        CommandList     *c;
<span style="color: #000000;background-color: #ffdddd">-        char            *x = NULL;
-       int             found=false;
</span> 
        if (topic!=NULL && (strchr(topic,'.')!=NULL || strchr(topic,'/')!=NULL))
        {
<span style="color: #aaaaaa">@@ -65,29 +64,31 @@ static void help(const char *topic, int wiz)
</span>   /* not given any topic to look for, so display general help */
        if (topic==NULL)
        {
<span style="color: #000000;background-color: #ddffdd">+                const char *x = NULL;
+
</span>           /* allowed high-level help */
                if (wiz)
                {
                        /* search for best help file */
<span style="color: #000000;background-color: #ffdddd">-                        x = makepath(WIZHELP, "/", "general");
-                       if (!access(x, 00)) found=true;
</span><span style="color: #000000;background-color: #ddffdd">+                   x = WIZHELP"/general";
+                       if (!access(x, 00)) printfile(x);
</span>           }
                /* no high-level help allowed, or available */
<span style="color: #000000;background-color: #ffdddd">-                if (!found)
</span><span style="color: #000000;background-color: #ddffdd">+           if (x == NULL)
</span>           {
                        /* search for normal help */
<span style="color: #000000;background-color: #ffdddd">-                        x = makepath(HELPDIR, "/", "general");
-                       if (!access(x, 00)) found=true;
</span><span style="color: #000000;background-color: #ddffdd">+                   x = HELPDIR"/general";
+                       if (!access(x, 00)) printfile(x);
</span>           }
                /* display message as to whether help was found */
<span style="color: #000000;background-color: #ffdddd">-                if (found)
-                       printfile(x);
-               else
</span><span style="color: #000000;background-color: #ddffdd">+           if (x == NULL)
</span>                   printf(_("No general help available for talker commands.\n"));
        }
        /* a help topic was given */
        else
        {
<span style="color: #000000;background-color: #ddffdd">+                AUTOFREE_BUFFER x = NULL;
+
</span>           /* find the command in the list */
                c = table;
                while (c->Command && strcasecmp(c->Command, topic)) c++;
<span style="color: #aaaaaa">@@ -101,26 +102,22 @@ static void help(const char *topic, int wiz)
</span>                           return;
                        }
                }
<span style="color: #000000;background-color: #ffdddd">-
</span>           /* search for the high-level help file */
                if (wiz)
                {
                        /* search for the best topic help */
<span style="color: #000000;background-color: #ffdddd">-                        x = makepath(WIZHELP, "/", topic);
-                       if (!access(x, 00)) found=true;
</span><span style="color: #000000;background-color: #ddffdd">+                   asprintf(&x, WIZHELP"/%s", topic);
+                       if (x != NULL && !access(x, 00)) printfile(x);
</span>           }
                /* no high-level help allowed, or available */
<span style="color: #000000;background-color: #ffdddd">-                if (!found)
</span><span style="color: #000000;background-color: #ddffdd">+           if (x == NULL)
</span>           {
                        /* search for normal topic help */
<span style="color: #000000;background-color: #ffdddd">-                        x = makepath(HELPDIR, "/", topic);
-                       if (!access(x, 00)) found=true;
</span><span style="color: #000000;background-color: #ddffdd">+                   asprintf(&x, HELPDIR"/%s", topic);
+                       if (x != NULL && !access(x, 00)) printfile(x);
</span>           }
<span style="color: #000000;background-color: #ffdddd">-
</span>           /* display the file, or appropriate help message */
<span style="color: #000000;background-color: #ffdddd">-                if (found)
-                       printfile(x);
-               else
</span><span style="color: #000000;background-color: #ddffdd">+           if (x == NULL)
</span>                   printf(_("Sorry, no help available on that subject.\n"));
        }
 }
<span style="color: #aaaaaa">@@ -472,7 +469,7 @@ void c_mesg(CommandList *cm, int argc, const char **argv, char *args)
</span> {
        update_user(user);
        busy++;
<span style="color: #000000;background-color: #ffdddd">-        mesg_edit(argv[1],fold->name,atoi(argv[2]), user);
</span><span style="color: #000000;background-color: #ddffdd">+   mesg_edit(argv[1], fold, atoi(argv[2]), user);
</span>   busy--;
        mwlog("MESSAGE %s %s:%d",argv[1], fold->name, atoi(argv[2]));
 }
<span style="color: #aaaaaa">@@ -581,10 +578,10 @@ void c_ls(CommandList *cm, int argc, const char **argv, char *args)
</span> void c_topten(CommandList *cm, int argc, const char **argv, char *args)
 {
        struct listing *head=NULL;
<span style="color: #000000;background-color: #ffdddd">-        char fullpath[PATHSIZE];
</span>   struct Header hdr;
        struct listing *lnew;
        struct listing *ptr;
<span style="color: #000000;background-color: #ddffdd">+        struct folder folder;
</span>   int file;
        int count;
        char buff[10];
<span style="color: #aaaaaa">@@ -596,17 +593,11 @@ void c_topten(CommandList *cm, int argc, const char **argv, char *args)
</span>           return;
        }
 
<span style="color: #000000;background-color: #ffdddd">-        sprintf(fullpath,"%s/%s%s",STATEDIR,argv[1],INDEX_END);
-       if (access(fullpath,00))
-       {
-               printf("Folder %s not found.\n",argv[1]);
-               return;
-       }
-       if ((file=open(fullpath,O_RDONLY))<0)
-       {
-               perror("topten folder open");
</span><span style="color: #000000;background-color: #ddffdd">+   strncpy(folder.name, argv[1], FOLNAMESIZE);
+       folder.name[FOLNAMESIZE] = '\0';
+
+       if ((file = open_folder_index(&folder, FOL_LIVE, O_RDONLY, 0)) < 0)
</span>           return;
<span style="color: #000000;background-color: #ffdddd">-        }
</span>   lnew=(struct listing *)malloc(sizeof(*lnew));
        while(read(file,&hdr,sizeof(hdr))>0)
        {
<span style="color: #aaaaaa">@@ -631,7 +622,7 @@ void c_topten(CommandList *cm, int argc, const char **argv, char *args)
</span>   }
        head=Sort(head);
 
<span style="color: #000000;background-color: #ffdddd">-        printf("Top posters in folder %s\n",argv[1]);
</span><span style="color: #000000;background-color: #ddffdd">+   printf("Top posters in folder %s\n", folder.name);
</span>   printf("In order of Total size of text posted.\n");
 
        ptr=head;
<span style="color: #aaaaaa">@@ -652,7 +643,6 @@ void c_topten(CommandList *cm, int argc, const char **argv, char *args)
</span>   }
 }
 
<span style="color: #000000;background-color: #ffdddd">-#define NEW_END ".t"
</span> void c_tidyup(CommandList *cm, int argc, const char **argv, char *args)
 {
        struct Header idx;
<span style="color: #aaaaaa">@@ -671,9 +661,6 @@ void c_tidyup(CommandList *cm, int argc, const char **argv, char *args)
</span>   printf(_("         the bulletin board, please exercise caution.\n"));
        printf("\n");
 
<span style="color: #000000;background-color: #ffdddd">-        char fullpath[PATHSIZE];
-       char fullpath2[PATHSIZE];
-
</span>   if (argc!=3)
        {
                printf("Usage: tidyup <foldername> <mesg no>\n");
<span style="color: #aaaaaa">@@ -709,47 +696,23 @@ void c_tidyup(CommandList *cm, int argc, const char **argv, char *args)
</span>   }
 
        /* open relevant folder index */
<span style="color: #000000;background-color: #ffdddd">-        snprintf(fullpath,PATHSIZE-1,STATEDIR"/%s"INDEX_END,info.name);
-       if (access(fullpath,00))
-       {
-               printf("Folder %s not found.\n",info.name);
-               return;
-       }
-       if ((indexin=open(fullpath,O_RDONLY))<0)
-       {
-               perror("tidyup folder_index open");
</span><span style="color: #000000;background-color: #ddffdd">+   if ((indexin = open_folder_index(&info, FOL_LIVE, O_RDONLY, 0)) < 0)
</span>           return;
<span style="color: #000000;background-color: #ffdddd">-        }
</span>   Lock_File(indexin);
 
        /* open relevant folder text */
<span style="color: #000000;background-color: #ffdddd">-        snprintf(fullpath,PATHSIZE-1,STATEDIR"/%s"TEXT_END,info.name);
-       if (access(fullpath,00))
-       {
-               printf("Folder %s text file not found.\n",info.name);
-               return;
-       }
-       if ((textin=open(fullpath,O_RDONLY))<0)
-       {
-               perror("tidyup folder_text open");
</span><span style="color: #000000;background-color: #ddffdd">+   if ((textin = open_folder_text(&info, FOL_LIVE, O_RDONLY, 0)) < 0)
</span>           return;
<span style="color: #000000;background-color: #ffdddd">-        }
</span>   Lock_File(textin);
 
<span style="color: #000000;background-color: #ffdddd">-        snprintf(fullpath,PATHSIZE-1,STATEDIR"/%s"INDEX_END NEW_END,info.name);
-       if ((indexout=open(fullpath,O_WRONLY|O_CREAT,0600))<0)
-       {
-               perror(fullpath);
</span><span style="color: #000000;background-color: #ddffdd">+   indexout = open_folder_index(&info, FOL_NEW, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
+       if (indexout < 0)
</span>           exit(-1);
<span style="color: #000000;background-color: #ffdddd">-        }
</span>   Lock_File(indexout);
 
<span style="color: #000000;background-color: #ffdddd">-        snprintf(fullpath,PATHSIZE-1,STATEDIR"/%s"TEXT_END NEW_END,info.name);
-       if ((textout=open(fullpath,O_WRONLY|O_CREAT,0600))<0)
-       {
-               perror(fullpath);
</span><span style="color: #000000;background-color: #ddffdd">+   textout = open_folder_text(&info, FOL_NEW, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
+       if (textout < 0)
</span>           exit(-1);
<span style="color: #000000;background-color: #ffdddd">-        }
</span>   Lock_File(textout);
 
        printf("Copying all messages from number %d.\n", limit);
<span style="color: #aaaaaa">@@ -769,21 +732,21 @@ void c_tidyup(CommandList *cm, int argc, const char **argv, char *args)
</span>                   counter++;
                }
        }
<span style="color: #000000;background-color: #ddffdd">+        fsync(indexout);
+       Unlock_File(indexout);
+       close(indexout);
+       fsync(textout);
+       Unlock_File(textout);
+       close(textout);
+
</span>   printf("Copy complete, %d messages copied.\n",counter);
        printf("First message is now #%d\n",first);
        printf("Updating Real Folder...\n");
<span style="color: #000000;background-color: #ffdddd">-        close(indexout);
</span> 
<span style="color: #000000;background-color: #ffdddd">-        snprintf(fullpath,PATHSIZE-1,STATEDIR"/%s"INDEX_END,info.name);
-       snprintf(fullpath2,PATHSIZE-1,STATEDIR"/%s"INDEX_END NEW_END,info.name);
-       if (rename(fullpath2,fullpath)) perror("rename");
</span><span style="color: #000000;background-color: #ddffdd">+   move_folder(&info, FOL_NEW, FOL_LIVE);
+
</span>   Unlock_File(indexin);
        close(indexin);
<span style="color: #000000;background-color: #ffdddd">-
-       close(textout);
-       snprintf(fullpath,PATHSIZE-1,STATEDIR"/%s"TEXT_END,info.name);
-       snprintf(fullpath2,PATHSIZE-1,STATEDIR"/%s"TEXT_END NEW_END,info.name);
-       if (rename(fullpath2,fullpath)) perror("rename");
</span>   Unlock_File(textin);
        close(textin);
 
</code></pre>

<br>
</li>
<li id='diff-9'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-9'>
<strong>
src/client/read.c
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/client/read.c
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/client/read.c
</span><span style="color: #aaaaaa">@@ -104,7 +104,6 @@ int read_msg(int folnum, int msgnum, struct user *user)
</span>   struct Header head;
        int posn;
        long tmppos;
<span style="color: #000000;background-color: #ffdddd">-        char *x;
</span> 
        if (nofolders())
                {printf("There are no folders to read.\n");return(false);}
<span style="color: #aaaaaa">@@ -123,25 +122,12 @@ int read_msg(int folnum, int msgnum, struct user *user)
</span>           {printf("Folder %s is empty.\n",data.name);return(false);}
        if ( !u_god(user) && !allowed_r(&data,user))
                {printf("You are not permitted to read this folder.\n");return(false);}
<span style="color: #000000;background-color: #ffdddd">-
-       x=buildpath(STATEDIR,data.name,INDEX_END,"");
-       if (access(x,0))
-       {
-               printf("Error: cannot find index file for folder %s\n",data.name);
-               return(false);
-       }
-       if ((headfile=err_open(x,O_RDONLY,0))<0)
-               {exit(-1);}
-
-       x=buildpath(STATEDIR,data.name,TEXT_END,"");
-       if (access(x,0))
-       {
-               printf("Error: cannot find text file for folder %s\n",data.name);
</span><span style="color: #000000;background-color: #ddffdd">+   if ((headfile = open_folder_index(&data, FOL_LIVE, O_RDONLY, 0)) < 0)
+               return false;
+       if ((textfile = open_folder_text(&data, FOL_LIVE, O_RDONLY, 0)) < 0) {
</span>           close(headfile);
<span style="color: #000000;background-color: #ffdddd">-                return(false);
</span><span style="color: #000000;background-color: #ddffdd">+           return false;
</span>   }
<span style="color: #000000;background-color: #ffdddd">-        if ((textfile=err_open(x,O_RDONLY,0))<0)
-               {exit(-1);}
</span>   tmppos=lseek(headfile,0,2);
        posn=(msgnum - data.last - 1)*sizeof(struct Header);
        if (posn < -tmppos)
<span style="color: #aaaaaa">@@ -187,16 +173,8 @@ void ls(int folnum, struct user *user, int many)
</span>   if (!get_folder_number(&fold,folnum))
                return;
 
<span style="color: #000000;background-color: #ffdddd">-        AUTOFREE_BUFFER tmp;
-       if (asprintf(&tmp, "%s/%s%s", STATEDIR, fold.name, INDEX_END) < 0)
-       {
</span><span style="color: #000000;background-color: #ddffdd">+   if ((afile = open_folder_index(&fold, FOL_LIVE, O_RDONLY, 0)) < 0)
</span>           return;
<span style="color: #000000;background-color: #ffdddd">-        }
-       if ((afile=open(tmp,O_RDONLY))<0)
-       {
-               printf("There are no messages in folder %s\n",fold.name);
-               return;
-       }
</span>   if (many>0)
        {
                listpoint=fold.first+many;
<span style="color: #aaaaaa">@@ -289,7 +267,6 @@ int get_mesg_header(struct folder *data, int msgnum, struct Header *head)
</span>   int             headfile;
        int             posn;
        long            tmppos;
<span style="color: #000000;background-color: #ffdddd">-        char            *x;
</span> 
        /* folder data doesnt exist */
        if (!data) return(false);
<span style="color: #aaaaaa">@@ -301,11 +278,8 @@ int get_mesg_header(struct folder *data, int msgnum, struct Header *head)
</span>   /* empty folder */
        if (data->last < data->first || data->last == 0) return(false);
 
<span style="color: #000000;background-color: #ffdddd">-        x=buildpath(STATEDIR,data->name,INDEX_END,"");
-       /* no data file */
-       if (access(x,0)) return(false);
-       /* cant open file */
-       if ((headfile=err_open(x,O_RDONLY,0))<0) return(false);
</span><span style="color: #000000;background-color: #ddffdd">+   if ((headfile = open_folder_index(data, FOL_LIVE, O_RDONLY, 0)) < 0)
+               return false;
</span> 
        /* no message - file too small */
        tmppos = lseek(headfile, 0, 2);
</code></pre>

<br>
</li>
<li id='diff-10'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-10'>
<strong>
src/client/script.c
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/client/script.c
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/client/script.c
</span><span style="color: #aaaaaa">@@ -23,6 +23,7 @@
</span> #include "user.h"
 #include "userio.h"
 #include "who.h"
<span style="color: #000000;background-color: #ddffdd">+#include <util.h>
</span> 
 extern Alias bind_list;
 
<span style="color: #aaaaaa">@@ -479,9 +480,7 @@ void DestroyAllFunctions(int debug)
</span> 
 void scr_helpfile(const char *args)
 {
<span style="color: #000000;background-color: #ffdddd">-        char *x;
</span>   Instruction *inst;
<span style="color: #000000;background-color: #ffdddd">-        int found=false;
</span> 
        if (args!=NULL &&(strchr(args,'.')!=NULL || strchr(args,'/')!=NULL))
        {
<span style="color: #aaaaaa">@@ -491,13 +490,16 @@ void scr_helpfile(const char *args)
</span> 
        if (args==NULL)
        {
<span style="color: #000000;background-color: #ffdddd">-                x=makepath(SCRIPTHELP,"/","general");
</span><span style="color: #000000;background-color: #ddffdd">+           const char *x = SCRIPTHELP"/general";
+
</span>           if (!access(x,00))
                        printfile(x);
                else
                        printf("No general help available on scripts.\n");
        }else
        {
<span style="color: #000000;background-color: #ddffdd">+                AUTOFREE_BUFFER x = NULL;
+
</span>           inst=inst_table;
                while (inst->name != NULL && strcasecmp(inst->name, args)) {
                        inst++;
<span style="color: #aaaaaa">@@ -510,14 +512,10 @@ void scr_helpfile(const char *args)
</span>                           return;
                        }
                }
<span style="color: #000000;background-color: #ffdddd">-
-               x=makepath(SCRIPTHELP,"/",args);
-               if (!access(x,00))
-               {
</span><span style="color: #000000;background-color: #ddffdd">+           asprintf(&x, SCRIPTHELP"/%s", args);
+               if (x != NULL && !access(x,00))
</span>                   printfile(x);
<span style="color: #000000;background-color: #ffdddd">-                        found=true;
-               }
-               if (!found)
</span><span style="color: #000000;background-color: #ddffdd">+           else
</span>                   printf("No help available on that subject.\n");
        }
 }
</code></pre>

<br>
</li>
<li id='diff-11'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-11'>
<strong>
src/client/strings.c
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/client/strings.c
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/client/strings.c
</span><span style="color: #aaaaaa">@@ -64,15 +64,6 @@ void pop_cmd(char *string, int len, int *type)
</span> }
 
 /* common file functions */
<span style="color: #000000;background-color: #ffdddd">-
-char *buildpath(const char *a, const char *b, const char *c, const char *d)
-{
-       static char fullpath[PATHSIZE];
-
-       snprintf(fullpath, PATHSIZE-1, "%s/%s%s%s",a,b,c,d);
-       return(fullpath);
-}
-
</span> int err_open(const char *path,int type,int mode)
 {
        int x;
</code></pre>

<br>
</li>
<li id='diff-12'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-12'>
<strong>
src/client/strings.h
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/client/strings.h
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/client/strings.h
</span><span style="color: #aaaaaa">@@ -18,10 +18,6 @@ void stack_str(char *string);
</span> int is_stacked(void);
 void pop_cmd(char *string, int len, int *type);
 int pop_stack(char *string, int len);
<span style="color: #000000;background-color: #ffdddd">-
-char *buildpath(const char *a, const char *b, const char *c, const char *d);
-#define makepath(a,b,c) (buildpath(HOMEPATH,a,b,c))
-
</span> int err_open(const char *path,int type,int mode);
 
 #endif /* STRINGS_H */
</code></pre>

<br>
</li>
<li id='diff-13'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-13'>
<strong>
src/client/talker.c
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/client/talker.c
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/client/talker.c
</span><span style="color: #aaaaaa">@@ -1295,8 +1295,6 @@ void enter_talker(int logontype)
</span> void t_help(CommandList *cm, int argc, const char **argv, char *args)
 {
        CommandList     *c;
<span style="color: #000000;background-color: #ffdddd">-        char            *x;
-       int             found=false;
</span> 
        if (argc < 2)
        {
<span style="color: #aaaaaa">@@ -1312,13 +1310,16 @@ void t_help(CommandList *cm, int argc, const char **argv, char *args)
</span> 
        if (args==NULL)
        {
<span style="color: #000000;background-color: #ffdddd">-                x = makepath(TALKHELP,"/","general");
</span><span style="color: #000000;background-color: #ddffdd">+           const char *x = TALKHELP"/general";
+
</span>           if (!access(x,00))
                        printfile(x);
                else
                        printf("No general help available for talker commands.\n");
        }else
        {
<span style="color: #000000;background-color: #ddffdd">+                AUTOFREE_BUFFER x = NULL;
+
</span>           /* find the command in the list */
                c = chattable;
                while (c->Command && strcasecmp(c->Command, args)) c++;
<span style="color: #aaaaaa">@@ -1332,15 +1333,11 @@ void t_help(CommandList *cm, int argc, const char **argv, char *args)
</span>                           return;
                        }
                }
<span style="color: #000000;background-color: #ffdddd">-
-               /* display the file */
-               x=makepath(TALKHELP,"/",args);
-               if (!access(x,00))
-               {
</span><span style="color: #000000;background-color: #ddffdd">+           asprintf(&x, TALKHELP"/%s", args);
+               if (x != NULL && !access(x,00))
</span>                   printfile(x);
<span style="color: #000000;background-color: #ffdddd">-                        found=true;
-               }
-               if (!found) printf("Sorry, no help available on that subject.\n");
</span><span style="color: #000000;background-color: #ddffdd">+           else
+                       printf("Sorry, no help available on that subject.\n");
</span>   }
 }
 
</code></pre>

<br>
</li>
<li id='diff-14'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-14'>
<strong>
src/folders.c
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/folders.c
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/folders.c
</span><span style="color: #aaaaaa">@@ -6,10 +6,21 @@
</span> 
 #include "strings.h"
 #include "folders.h"
<span style="color: #000000;background-color: #ddffdd">+#include "perms.h"
</span> #include "files.h"
 
 #define FOLDERFILE  STATEDIR"/folders.bb"
 
<span style="color: #000000;background-color: #ddffdd">+int idx_fd = -1;
+int txt_fd = -1;
+
+const char *folder_types[] = {
+       FOL_LIVE,
+       FOL_MOD,
+       FOL_NEW,
+       FOL_TMP,
+};
+
</span> int openfolderfile(int mode)
 {
        int x;
<span style="color: #aaaaaa">@@ -106,3 +117,159 @@ int get_folder_number(struct folder *fol, int num)
</span>   close(file);
        return 1;
 }
<span style="color: #000000;background-color: #ddffdd">+
+int folders_init(void)
+{
+       /* Grab fds for the top bbs directories so we can use openat(), renameat(),
+          etc. later instead of building paths. */
+       idx_fd = open(FOL_IDX_DIR, O_RDONLY);
+       if (idx_fd < 0) {
+               perror(FOL_IDX_DIR);
+               return 1;
+       }
+       txt_fd = open(FOL_TXT_DIR, O_RDONLY);
+       if (txt_fd < 0) {
+               perror(FOL_TXT_DIR);
+               return 1;
+       }
+       return 0;
+}
+
+static int open_folder_path(int top_fd, struct folder *folder, const char *subdir, int flags, int mode)
+{
+       int fd;
+       int at_fd = top_fd;
+
+       if (subdir != NULL && *subdir != '\0') {
+               at_fd = openat(top_fd, subdir, O_RDONLY, 0);
+               if (at_fd < 0) {
+                       perror(subdir);
+                       return -1;
+               }
+       }
+       fd = openat(at_fd, folder->name, flags, mode);
+       if (at_fd != top_fd)
+               close(at_fd);
+       if (fd < 0)
+               perror(folder->name);
+       return fd;
+}
+
+int open_folder_index(struct folder *folder, const char *fol_type, int flags, int mode)
+{
+       return open_folder_path(idx_fd, folder, fol_type, flags, mode);
+}
+
+int open_folder_text(struct folder *folder, const char *fol_type, int flags, int mode)
+{
+       return open_folder_path(txt_fd, folder, fol_type, flags, mode);
+}
+
+int rename_folder(struct folder *folder, const char *newname)
+{
+       unsigned i;
+       int fds[] = {idx_fd, txt_fd, -1, -1, -1};
+
+       if (f_moderated(folder->status) || f_moderated(folder->g_status)) {
+               fds[2] = openat(idx_fd, FOL_MOD, O_RDONLY);
+               if (fds[2] < 0) {
+                       perror(FOL_IDX_DIR"/"FOL_MOD);
+                       return 1;
+               }
+               fds[3] = openat(txt_fd, FOL_MOD, O_RDONLY);
+               if (fds[3] < 0) {
+                       perror(FOL_TXT_DIR"/"FOL_MOD);
+                       close(fds[2]);
+                       return 1;
+               }
+       }
+       for (i = 0; fds[i] != -1; i++)
+               renameat(fds[i], folder->name, fds[i], newname);
+
+       close(fds[2]);
+       close(fds[3]);
+       strncpy(folder->name, newname, FOLNAMESIZE);
+       folder->name[FOLNAMESIZE] = '\0';
+       return 0;
+}
+
+int remove_folder(struct folder *folder, const char *fol_type)
+{
+       int _idx_fd = idx_fd;
+       int _txt_fd = txt_fd;
+
+       if (fol_type != FOL_LIVE) {
+               _idx_fd = openat(idx_fd, fol_type, O_RDONLY);
+               if (_idx_fd < 0 && errno != EEXIST) {
+                       fprintf(stderr, FOL_IDX_DIR"/%s: %s\n", fol_type, strerror(errno));
+                       return 1;
+               }
+               _txt_fd = openat(txt_fd, fol_type, O_RDONLY);
+               if (_txt_fd < 0 && errno != EEXIST) {
+                       fprintf(stderr, FOL_TXT_DIR"/%s: %s\n", fol_type, strerror(errno));
+                       close(_idx_fd);
+                       return 1;
+               }
+       }
+       unlinkat(_idx_fd, folder->name, 0);
+       unlinkat(_txt_fd, folder->name, 0);
+       return 0;
+}
+
+int move_folder(struct folder *folder, const char *from, const char *to)
+{
+       int idx_from_fd = idx_fd;
+       int idx_to_fd = idx_fd;
+       int txt_from_fd = txt_fd;
+       int txt_to_fd = txt_fd;
+       int ret = 1;
+
+       if (from != FOL_LIVE) {
+               idx_from_fd = openat(idx_fd, from, O_RDONLY);
+               if (idx_from_fd < 0) {
+                       fprintf(stderr, FOL_IDX_DIR"/%s: %s\n", from, strerror(errno));
+                       return 1;
+               }
+               txt_from_fd = openat(txt_fd, from, O_RDONLY);
+               if (txt_from_fd < 0) {
+                       fprintf(stderr, FOL_TXT_DIR"/%s: %s\n", from, strerror(errno));
+                       goto close_from_idx;
+               }
+       }
+       if (to != FOL_LIVE) {
+               idx_to_fd = openat(idx_fd, to, O_RDONLY);
+               if (idx_to_fd < 0) {
+                       fprintf(stderr, FOL_IDX_DIR"/%s: %s\n", to, strerror(errno));
+                       goto close_from_txt;
+               }
+               txt_to_fd = openat(txt_fd, to, O_RDONLY);
+               if (txt_to_fd < 0) {
+                       fprintf(stderr, FOL_TXT_DIR"/%s: %s\n", to, strerror(errno));
+                       goto close_to_idx;
+               }
+       }
+       ret = renameat(idx_from_fd, folder->name, idx_to_fd, folder->name);
+       if (ret != 0 && errno != ENOENT) {
+               perror("Failed to move folder index file");
+               goto close_to_txt;
+       }
+       fsync(idx_from_fd);
+       ret = renameat(txt_from_fd, folder->name, txt_to_fd, folder->name);
+       if (ret == 0)
+               fsync(txt_from_fd);
+       else if (errno != ENOENT)
+               perror("Failed to move folder text file");
+close_to_txt:
+       if (txt_to_fd != txt_fd)
+               close(txt_to_fd);
+close_to_idx:
+       if (idx_to_fd != idx_fd)
+               close(idx_to_fd);
+close_from_txt:
+       if (txt_from_fd != txt_fd)
+               close(txt_from_fd);
+close_from_idx:
+       if (idx_from_fd != idx_fd)
+               close(idx_from_fd);
+       return ret;
+}
</span></code></pre>

<br>
</li>
<li id='diff-15'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-15'>
<strong>
src/folders.h
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/folders.h
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/folders.h
</span><span style="color: #aaaaaa">@@ -2,6 +2,7 @@
</span> #define FOLDERS_H
 
 #include <stdint.h>
<span style="color: #000000;background-color: #ddffdd">+#include "user.h"
</span> 
 #define FOLNAMESIZE    10      /* length of folder names */
 #define TOPICSIZE      30      /* length of the topic of the folder */
<span style="color: #aaaaaa">@@ -47,11 +48,28 @@ bit    use
</span> #define f_private(stat)   (stat & (1 << MWFOLDR_PRIVATE))
 #define f_moderated(stat) (stat & (1 << MWFOLDR_MODERATED))
 
<span style="color: #000000;background-color: #ddffdd">+#define FOL_IDX_DIR   STATEDIR"/index"
+#define FOL_TXT_DIR   STATEDIR"/text"
+/* Subdirectories of TXT_DIR and IDX_DIR */
+/* Use these for the *_type arguments to the functions below */
+#define FOL_LIVE      NULL
+#define FOL_MOD       "mod"
+#define FOL_NEW       "new"
+#define FOL_TMP       "tmp"
+
+extern const char *folder_types[4];
+
</span> int openfolderfile(int mode);
 int nofolders(void);
 void create_folder_file(void);
 int foldernumber(const char *name);
 int get_folder_entry(int file, struct folder *tmp);
 int get_folder_number(struct folder *fol, int num);
<span style="color: #000000;background-color: #ddffdd">+int folders_init(void);
+int open_folder_index(struct folder *folder, const char *fol_type, int flags, int mode);
+int open_folder_text(struct folder *folder, const char *fol_type, int flags, int mode);
+int rename_folder(struct folder *folder, const char *newname);
+int remove_folder(struct folder *folder, const char *fol_type);
+int move_folder(struct folder *folder, const char *from_type, const char *to_type);
</span> 
 #endif /* FOLDERS_H */
</code></pre>

<br>
</li>
<li id='diff-16'>
<a href='https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad#diff-16'>
<strong>
src/server/servsock.c
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/src/server/servsock.c
</span><span style="color: #000000;background-color: #ddffdd">+++ b/src/server/servsock.c
</span><span style="color: #aaaaaa">@@ -4,6 +4,7 @@
</span> #include <sys/epoll.h>
 #include <sys/types.h>
 #include <sys/socket.h>
<span style="color: #000000;background-color: #ddffdd">+#include <sys/stat.h>
</span> #include <netinet/in.h>
 #include <string.h>
 #include <errno.h>
<span style="color: #aaaaaa">@@ -12,6 +13,7 @@
</span> #include <sys/time.h>
 #include <stdbool.h>
 #include <time.h>
<span style="color: #000000;background-color: #ddffdd">+#include <dirent.h>
</span> 
 #include <socket.h>
 #include <nonce.h>
<span style="color: #aaaaaa">@@ -23,6 +25,7 @@
</span> #include "servsock.h"
 #include "replay.h"
 #include "actions.h"
<span style="color: #000000;background-color: #ddffdd">+#include <folders.h>
</span> #include <gags.h>
 #include <perms.h>
 #include <special.h>
<span style="color: #aaaaaa">@@ -573,8 +576,105 @@ void msg_apply_gag(struct user *from, ipc_message_t * msg, const char * field)
</span>   json_decref(j);
 }
 
<span style="color: #000000;background-color: #ddffdd">+static char *has_suffix(char *str, const char *suffix)
+{
+       size_t len = strlen(suffix);
+
+       while((str = strstr(str, suffix)) != NULL)
+               if (*(str + len) == '\0')
+                       return str;
+               else
+                       str++;
+       return NULL;
+}
+
+static void migrate_old_folders(void)
+{
+       int dfd;
+       DIR *dirp;
+       unsigned i;
+       struct dirent entry, *dp;
+       const char *bbdirs[] = {
+               FOL_IDX_DIR,
+               FOL_IDX_DIR"/"FOL_NEW,
+               FOL_IDX_DIR"/"FOL_MOD,
+               FOL_IDX_DIR"/"FOL_TMP,
+               FOL_TXT_DIR,
+               FOL_TXT_DIR"/"FOL_NEW,
+               FOL_TXT_DIR"/"FOL_MOD,
+               FOL_TXT_DIR"/"FOL_TMP,
+       };
+       /* Set up required directory structure */
+       for (i = 0; i < (sizeof(bbdirs) / sizeof(bbdirs[0])); i++) {
+               int ret = mkdir(bbdirs[i], S_IRWXU|S_IXGRP|S_IXOTH);
+               if (ret == -1 && errno != EEXIST) {
+                       fprintf(stderr, "Failed to create directory '%s': %s\n",
+                               bbdirs[i], strerror(errno));
+                       return;
+               }
+       }
+       dirp = opendir(STATEDIR);
+       if (dirp == NULL) {
+               perror(STATEDIR);
+               return;
+       }
+       dfd = dirfd(dirp);
+       while (readdir_r(dirp, &entry, &dp) == 0) {
+               char *end, *path = NULL;
+
+               if (dp == NULL)
+                       break;
+               if ((end = has_suffix(entry.d_name, ".t.t"))) {
+                       *end = '\0';
+                       asprintf(&path, FOL_TXT_DIR"/"FOL_NEW"/%s", entry.d_name);
+                       *end = '.';
+                       printf("Migrating folder '%s' to '%s'\n", entry.d_name, path);
+                       renameat(dfd, entry.d_name, dfd, path);
+               }
+               else if ((end = has_suffix(entry.d_name, ".i.t"))) {
+                       *end = '\0';
+                       asprintf(&path, FOL_IDX_DIR"/"FOL_NEW"/%s", entry.d_name);
+                       *end = '.';
+                       printf("Migrating folder '%s' to '%s'\n", entry.d_name, path);
+                       renameat(dfd, entry.d_name, dfd, path);
+               }
+               else if ((end = has_suffix(entry.d_name, ".i.m"))) {
+                       *end = '\0';
+                       asprintf(&path, FOL_IDX_DIR"/"FOL_MOD"/%s", entry.d_name);
+                       *end = '.';
+                       printf("Migrating folder '%s' to '%s'\n", entry.d_name, path);
+                       renameat(dfd, entry.d_name, dfd, path);
+               }
+               else if ((end = has_suffix(entry.d_name, ".t.m"))) {
+                       *end = '\0';
+                       asprintf(&path, FOL_TXT_DIR"/"FOL_MOD"/%s", entry.d_name);
+                       *end = '.';
+                       printf("Migrating folder '%s' to '%s'\n", entry.d_name, path);
+                       renameat(dfd, entry.d_name, dfd, path);
+               }
+               else if ((end = has_suffix(entry.d_name, ".i"))) {
+                       *end = '\0';
+                       asprintf(&path, FOL_IDX_DIR"/%s", entry.d_name);
+                       *end = '.';
+                       printf("Migrating folder '%s' to '%s'\n", entry.d_name, path);
+                       renameat(dfd, entry.d_name, dfd, path);
+               }
+               else if ((end = has_suffix(entry.d_name, ".t"))) {
+                       *end = '\0';
+                       asprintf(&path, FOL_TXT_DIR"/%s", entry.d_name);
+                       *end = '.';
+                       printf("Migrating folder '%s' to '%s'\n", entry.d_name, path);
+                       renameat(dfd, entry.d_name, dfd, path);
+               }
+               if (path != NULL)
+                       free(path);
+       }
+}
+
</span> void init_server()
 {
<span style="color: #000000;background-color: #ddffdd">+        migrate_old_folders();
+
</span>   INIT_LIST_HEAD(&connection_list);
        if (pollfd == -1) {
                pollfd = epoll_create(30);
</code></pre>

<br>
</li>

</div>
<div class='footer' style='margin-top: 10px;'>
<p>

<br>
<a href="https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad">View it on GitLab</a>
<br>
You're receiving this email because of your account on <a href="https://projects.sucs.org/">projects.sucs.org</a>.
If you'd like to receive fewer emails, you can adjust your notification settings.
<script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","action":{"@type":"ViewAction","name":["merge_requests","issues","commit"],"url":"https://projects.sucs.org/arthur/mw/compare/b756151260266a14a023876ea40b0e51f24a71f2...3f71da2332897f7b51e860a188d847ecfa2aafad"}}</script>
</p>
</div>
</body>
</html>