Skip to content
Commits on Source (3)
  • Andrew Price's avatar
    Folder file overhaul · 6bcd1e4b
    Andrew Price authored
    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.
    6bcd1e4b
  • Andrew Price's avatar
    Fix !folder name command · 0ac74891
    Andrew Price authored
    !folder name was not working because strlen("name") was expected to be
    5. Expect it to be 4 instead.
    0ac74891
  • Andrew Price's avatar
    Get rid of makepath, buildpath and PATHSIZE · 3f71da23
    Andrew Price authored
    Huzzah!
    3f71da23
......@@ -23,20 +23,19 @@
#endif
#define LOGFILE LOGDIR"/log.bb"
#define LOGIN_BANNER "login.banner"
#define LOGIN_BANNER HOMEPATH"/login.banner"
#define LOCKFILE "/tmp/bb.locked"
#define EDITOR "/usr/bin/vim"
#define SECUREEDITOR "/bin/rnano"
#define HELPDIR "help"
#define WIZHELP "wizhelp"
#define SCRIPTHELP "scripthelp"
#define TALKHELP "talkhelp"
#define HELPDIR HOMEPATH"/help"
#define WIZHELP HOMEPATH"/wizhelp"
#define SCRIPTHELP HOMEPATH"/scripthelp"
#define TALKHELP HOMEPATH"/talkhelp"
#define TEXT_END ".t"
#define INDEX_END ".i"
#define MOD_END ".m"
#define PATHSIZE 256
#define CMD_BOARD_STR "!"
#define CMD_TALK_STR "."
......
......@@ -150,7 +150,8 @@ int add_msg(int folnum, struct user *user, int replyto)
long posn,tmppos;
int headfile;
if ((headfile=err_open(buildpath(STATEDIR,fol->name,INDEX_END,""),O_RDONLY,0))<0)
headfile = open_folder_index(fol, FOL_LIVE, O_RDONLY, 0);
if (headfile < 0)
{
free(fol);
free(new);
......@@ -384,16 +385,14 @@ int add_msg(int folnum, struct user *user, int replyto)
folderfile=openfolderfile(O_RDWR);
Lock_File(folderfile);
/* 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)
{
/* 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)
exit(-1);
}
if ((data=err_open(buildpath(STATEDIR,fol->name,TEXT_END,is_moderated(fol,user)?MOD_END:""),O_APPEND|O_CREAT|O_WRONLY,0600))<0)
{
data = open_folder_text(fol, subdir, O_WRONLY|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR);
if (data < 0)
exit(-1);
}
Lock_File(folderfile);
Lock_File(i);
Lock_File(data);
......
......@@ -675,34 +675,17 @@ void edit_folder(const char *args, const char *name)
printf(_("Groups changed to [%s]\n"),tmp);
}
}else
if (stringcmp(args,"name",5))
if (stringcmp(args,"name",4))
{
printf(_("Current folder name = %s\n"),fold.name);
printf(_("Change to ? (%d chars): "),FOLNAMESIZE);
get_str(tmp,FOLNAMESIZE);
if (*tmp)
{
char oldpath[PATHSIZE];
if (*tmp == '\0' || strchr(tmp, '/') != NULL) {
printf("Bad folder name\n");
} else {
mwlog("FOLDER(RENAME) of %s to %s", fold.name, tmp);
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);
if (rename_folder(&fold, tmp) == 0)
printf(_("Name changed to %s\n"), fold.name);
}
}else
if (stringcmp(args,"size",4))
......@@ -755,17 +738,11 @@ void edit_folder(const char *args, const char *name)
get_str(tmp,4);
if (stringcmp(tmp,"yes",-1))
{
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);}
}
unsigned i;
for (i = 0; i < (sizeof(folder_types)/sizeof(folder_types[0])); i++)
remove_folder(&fold, folder_types[i]);
fold.status=0;
fold.g_status=0;
fold.name[0]=0;
......@@ -791,15 +768,17 @@ void edit_folder(const char *args, const char *name)
const char *partlist_mesg[]={
"edit", "to", "subject", "delete", "undelete", "status", NULL};
void mesg_edit(const char *args, char *foldername, int msgno, struct user *usr)
void mesg_edit(const char *args, struct folder *folder, int msgno, struct user *usr)
{
int fd, text;
struct Header head;
char *buff;
if ((fd=err_open(buildpath(STATEDIR,foldername,INDEX_END,""),O_RDWR,0))<0)
fd = open_folder_index(folder, FOL_LIVE, O_RDWR, 0);
if (fd < 0)
return;
if ((text=err_open(buildpath(STATEDIR,foldername,TEXT_END,""),O_RDWR,0))<0)
text = open_folder_text(folder, FOL_LIVE, O_RDWR, 0);
if (text < 0)
return;
/* go and get message */
......
......@@ -7,6 +7,6 @@ void time_on(long u);
void edit_user(const char *args, const char *name);
void edit_folder(const char *args, const char *name);
void edit_contact(void);
void mesg_edit(const char *args, char *foldername, int msgno, struct user *usr);
void mesg_edit(const char *args, struct folder *folder, int msgno, struct user *usr);
#endif /* EDIT_H */
......@@ -378,6 +378,9 @@ int main(int argc, char **argv)
output=stdout;
if (folders_init())
exit(1);
#ifdef GNUTLS_VERSION_MAJOR
/* Prior to 3.3.0 this is not thread safe
* so should be done early to prevent a race.
......@@ -611,7 +614,7 @@ int main(int argc, char **argv)
/* show login banner, and version info */
/* allow disabling of banner in release version */
if (!qflag) printfile(makepath(LOGIN_BANNER,"",""));
if (!qflag) printfile(LOGIN_BANNER);
printf("%s\n",version);
/* log the user in by asking for their name (and details) */
......@@ -935,7 +938,7 @@ void close_down(int exitmode, char *sourceuser, char *reason)
exit(0);
}
void printfile(char *filename)
void printfile(const char *filename)
{
FILE *afile;
char *buff;
......
......@@ -4,7 +4,7 @@
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)));
void printfile(char *filename);
void printfile(const char *filename);
void broadcast_onoffcode(int code, int method, const char *sourceuser, const char *reason);
void reset_timeout(int secs);
int idle(int fd, int millis);
......
......@@ -19,16 +19,14 @@
static void add_message(struct folder *fold, struct Header *head, char *text)
{
char fullpath[PATHSIZE];
int modindex,modtext;
/* 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);}
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);
Lock_File(modindex);
Lock_File(modtext);
head->Ref=fold->last;
......@@ -44,16 +42,15 @@ static void add_message(struct folder *fold, struct Header *head, char *text)
static void put_back(struct folder *fold, struct Header *head, char *text)
{
char fullpath[PATHSIZE];
int newindex,newtext;
/* 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);}
/* 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);
Lock_File(newindex);
Lock_File(newtext);
head->datafield=lseek(newtext,0,2);
......@@ -70,10 +67,9 @@ static void store(struct folder *fold, struct Header *head, char *text)
{
int afile;
char buff[128];
char fullpath[PATHSIZE];
time_t head_date;
const char *fullpath = STATEDIR"/mod.save";
sprintf(fullpath,"%s/%s",STATEDIR,"mod.save");
head_date = (time_t)head->date;
if ((afile=open(fullpath,O_WRONLY|O_APPEND|O_CREAT,0600))<0)
{perror(fullpath);exit(-1);}
......@@ -89,7 +85,6 @@ static void store(struct folder *fold, struct Header *head, char *text)
void moderate(void)
{
char fullpath[PATHSIZE],oldpath[PATHSIZE];
struct folder fold;
struct Header head;
char *text;
......@@ -104,25 +99,17 @@ void moderate(void)
while (get_folder_entry(f_file,&fold))
{
sprintf(oldpath,"%s/%s%s%s",STATEDIR,fold.name,INDEX_END,MOD_END);
if (access(oldpath,00))
/* Move the folder mod queue to tmp */
if (move_folder(&fold, FOL_MOD, FOL_TMP) != 0)
continue;
printf(_("Changing to folder %s\n"),fold.name);
/* 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);
/* 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);}
/* 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);
while (get_data(tmpindex,&head))
{
int foo;
......@@ -163,10 +150,7 @@ void moderate(void)
printf(_("End of folder %s\n"),fold.name);
close(tmpindex);
close(tmptext);
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);}
remove_folder(&fold, FOL_TMP);
}
close(f_file);
}
......
......@@ -88,15 +88,16 @@ static int read_new(struct user *user, struct folder *data, int folnum)
struct Header head;
char tmp[80];
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);}
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;
}
/* try jumping to expected location */
posn = (urec->lastread[folnum] - data->first + 1) * sizeof(struct Header);
lseek(indexfile, posn, 0);
......@@ -232,41 +233,36 @@ void latest(struct user *user)
{
if (f_active(fold.status) && allowed_r(&fold,user))
{
char *x;
time_t now, then;
struct tm *t_then;
struct Header hdr;
x=buildpath(STATEDIR,fold.name,INDEX_END,"");
printf("%*s ",FOLNAMESIZE,fold.name);
if (access(x,00))
printf("%*s ", FOLNAMESIZE, fold.name);
if ((ifile = open_folder_index(&fold, FOL_LIVE, O_RDONLY, 0)) < 0) {
printf(_(" <empty>\n"));
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));
return;
}
lseek(ifile,-1*sizeof(hdr),SEEK_END);
read(ifile,&hdr,sizeof(hdr));
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);
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);
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);
}
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);
}
}
close(ffile);
......
......@@ -37,6 +37,7 @@
#include "userio.h"
#include "mesg.h"
#include "incoming.h"
#include <util.h>
extern Alias alias_list;
......@@ -53,8 +54,6 @@ extern void help_list(CommandList *cm, unsigned int hidestuff);
static void help(const char *topic, int wiz)
{
CommandList *c;
char *x = NULL;
int found=false;
if (topic!=NULL && (strchr(topic,'.')!=NULL || strchr(topic,'/')!=NULL))
{
......@@ -65,29 +64,31 @@ static void help(const char *topic, int wiz)
/* not given any topic to look for, so display general help */
if (topic==NULL)
{
const char *x = NULL;
/* allowed high-level help */
if (wiz)
{
/* search for best help file */
x = makepath(WIZHELP, "/", "general");
if (!access(x, 00)) found=true;
x = WIZHELP"/general";
if (!access(x, 00)) printfile(x);
}
/* no high-level help allowed, or available */
if (!found)
if (x == NULL)
{
/* search for normal help */
x = makepath(HELPDIR, "/", "general");
if (!access(x, 00)) found=true;
x = HELPDIR"/general";
if (!access(x, 00)) printfile(x);
}
/* display message as to whether help was found */
if (found)
printfile(x);
else
if (x == NULL)
printf(_("No general help available for talker commands.\n"));
}
/* a help topic was given */
else
{
AUTOFREE_BUFFER x = NULL;
/* find the command in the list */
c = table;
while (c->Command && strcasecmp(c->Command, topic)) c++;
......@@ -101,26 +102,22 @@ static void help(const char *topic, int wiz)
return;
}
}
/* search for the high-level help file */
if (wiz)
{
/* search for the best topic help */
x = makepath(WIZHELP, "/", topic);
if (!access(x, 00)) found=true;
asprintf(&x, WIZHELP"/%s", topic);
if (x != NULL && !access(x, 00)) printfile(x);
}
/* no high-level help allowed, or available */
if (!found)
if (x == NULL)
{
/* search for normal topic help */
x = makepath(HELPDIR, "/", topic);
if (!access(x, 00)) found=true;
asprintf(&x, HELPDIR"/%s", topic);
if (x != NULL && !access(x, 00)) printfile(x);
}
/* display the file, or appropriate help message */
if (found)
printfile(x);
else
if (x == NULL)
printf(_("Sorry, no help available on that subject.\n"));
}
}
......@@ -472,7 +469,7 @@ void c_mesg(CommandList *cm, int argc, const char **argv, char *args)
{
update_user(user);
busy++;
mesg_edit(argv[1],fold->name,atoi(argv[2]), user);
mesg_edit(argv[1], fold, atoi(argv[2]), user);
busy--;
mwlog("MESSAGE %s %s:%d",argv[1], fold->name, atoi(argv[2]));
}
......@@ -581,10 +578,10 @@ void c_ls(CommandList *cm, int argc, const char **argv, char *args)
void c_topten(CommandList *cm, int argc, const char **argv, char *args)
{
struct listing *head=NULL;
char fullpath[PATHSIZE];
struct Header hdr;
struct listing *lnew;
struct listing *ptr;
struct folder folder;
int file;
int count;
char buff[10];
......@@ -596,17 +593,11 @@ void c_topten(CommandList *cm, int argc, const char **argv, char *args)
return;
}
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");
strncpy(folder.name, argv[1], FOLNAMESIZE);
folder.name[FOLNAMESIZE] = '\0';
if ((file = open_folder_index(&folder, FOL_LIVE, O_RDONLY, 0)) < 0)
return;
}
lnew=(struct listing *)malloc(sizeof(*lnew));
while(read(file,&hdr,sizeof(hdr))>0)
{
......@@ -631,7 +622,7 @@ void c_topten(CommandList *cm, int argc, const char **argv, char *args)
}
head=Sort(head);
printf("Top posters in folder %s\n",argv[1]);
printf("Top posters in folder %s\n", folder.name);
printf("In order of Total size of text posted.\n");
ptr=head;
......@@ -652,7 +643,6 @@ void c_topten(CommandList *cm, int argc, const char **argv, char *args)
}
}
#define NEW_END ".t"
void c_tidyup(CommandList *cm, int argc, const char **argv, char *args)
{
struct Header idx;
......@@ -671,9 +661,6 @@ void c_tidyup(CommandList *cm, int argc, const char **argv, char *args)
printf(_(" the bulletin board, please exercise caution.\n"));
printf("\n");
char fullpath[PATHSIZE];
char fullpath2[PATHSIZE];
if (argc!=3)
{
printf("Usage: tidyup <foldername> <mesg no>\n");
......@@ -709,47 +696,23 @@ void c_tidyup(CommandList *cm, int argc, const char **argv, char *args)
}
/* open relevant folder index */
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");
if ((indexin = open_folder_index(&info, FOL_LIVE, O_RDONLY, 0)) < 0)
return;
}
Lock_File(indexin);
/* open relevant folder text */
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");
if ((textin = open_folder_text(&info, FOL_LIVE, O_RDONLY, 0)) < 0)
return;
}
Lock_File(textin);
snprintf(fullpath,PATHSIZE-1,STATEDIR"/%s"INDEX_END NEW_END,info.name);
if ((indexout=open(fullpath,O_WRONLY|O_CREAT,0600))<0)
{
perror(fullpath);
indexout = open_folder_index(&info, FOL_NEW, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
if (indexout < 0)
exit(-1);
}
Lock_File(indexout);
snprintf(fullpath,PATHSIZE-1,STATEDIR"/%s"TEXT_END NEW_END,info.name);
if ((textout=open(fullpath,O_WRONLY|O_CREAT,0600))<0)
{
perror(fullpath);
textout = open_folder_text(&info, FOL_NEW, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
if (textout < 0)
exit(-1);
}
Lock_File(textout);
printf("Copying all messages from number %d.\n", limit);
......@@ -769,21 +732,21 @@ void c_tidyup(CommandList *cm, int argc, const char **argv, char *args)
counter++;
}
}
fsync(indexout);
Unlock_File(indexout);
close(indexout);
fsync(textout);
Unlock_File(textout);
close(textout);
printf("Copy complete, %d messages copied.\n",counter);
printf("First message is now #%d\n",first);
printf("Updating Real Folder...\n");
close(indexout);
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");
move_folder(&info, FOL_NEW, FOL_LIVE);
Unlock_File(indexin);
close(indexin);
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");
Unlock_File(textin);
close(textin);
......
......@@ -104,7 +104,6 @@ int read_msg(int folnum, int msgnum, struct user *user)
struct Header head;
int posn;
long tmppos;
char *x;
if (nofolders())
{printf("There are no folders to read.\n");return(false);}
......@@ -123,25 +122,12 @@ int read_msg(int folnum, int msgnum, struct user *user)
{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);}
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);
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) {
close(headfile);
return(false);
return false;
}
if ((textfile=err_open(x,O_RDONLY,0))<0)
{exit(-1);}
tmppos=lseek(headfile,0,2);
posn=(msgnum - data.last - 1)*sizeof(struct Header);
if (posn < -tmppos)
......@@ -187,16 +173,8 @@ void ls(int folnum, struct user *user, int many)
if (!get_folder_number(&fold,folnum))
return;
AUTOFREE_BUFFER tmp;
if (asprintf(&tmp, "%s/%s%s", STATEDIR, fold.name, INDEX_END) < 0)
{
if ((afile = open_folder_index(&fold, FOL_LIVE, O_RDONLY, 0)) < 0)
return;
}
if ((afile=open(tmp,O_RDONLY))<0)
{
printf("There are no messages in folder %s\n",fold.name);
return;
}
if (many>0)
{
listpoint=fold.first+many;
......@@ -289,7 +267,6 @@ int get_mesg_header(struct folder *data, int msgnum, struct Header *head)
int headfile;
int posn;
long tmppos;
char *x;
/* folder data doesnt exist */
if (!data) return(false);
......@@ -301,11 +278,8 @@ int get_mesg_header(struct folder *data, int msgnum, struct Header *head)
/* empty folder */
if (data->last < data->first || data->last == 0) return(false);
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);
if ((headfile = open_folder_index(data, FOL_LIVE, O_RDONLY, 0)) < 0)
return false;
/* no message - file too small */
tmppos = lseek(headfile, 0, 2);
......
......@@ -23,6 +23,7 @@
#include "user.h"
#include "userio.h"
#include "who.h"
#include <util.h>
extern Alias bind_list;
......@@ -479,9 +480,7 @@ void DestroyAllFunctions(int debug)
void scr_helpfile(const char *args)
{
char *x;
Instruction *inst;
int found=false;
if (args!=NULL &&(strchr(args,'.')!=NULL || strchr(args,'/')!=NULL))
{
......@@ -491,13 +490,16 @@ void scr_helpfile(const char *args)
if (args==NULL)
{
x=makepath(SCRIPTHELP,"/","general");
const char *x = SCRIPTHELP"/general";
if (!access(x,00))
printfile(x);
else
printf("No general help available on scripts.\n");
}else
{
AUTOFREE_BUFFER x = NULL;
inst=inst_table;
while (inst->name != NULL && strcasecmp(inst->name, args)) {
inst++;
......@@ -510,14 +512,10 @@ void scr_helpfile(const char *args)
return;
}
}
x=makepath(SCRIPTHELP,"/",args);
if (!access(x,00))
{
asprintf(&x, SCRIPTHELP"/%s", args);
if (x != NULL && !access(x,00))
printfile(x);
found=true;
}
if (!found)
else
printf("No help available on that subject.\n");
}
}
......
......@@ -64,15 +64,6 @@ void pop_cmd(char *string, int len, int *type)
}
/* common file functions */
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);
}
int err_open(const char *path,int type,int mode)
{
int x;
......
......@@ -18,10 +18,6 @@ void stack_str(char *string);
int is_stacked(void);
void pop_cmd(char *string, int len, int *type);
int pop_stack(char *string, int len);
char *buildpath(const char *a, const char *b, const char *c, const char *d);
#define makepath(a,b,c) (buildpath(HOMEPATH,a,b,c))
int err_open(const char *path,int type,int mode);
#endif /* STRINGS_H */
......@@ -1295,8 +1295,6 @@ void enter_talker(int logontype)
void t_help(CommandList *cm, int argc, const char **argv, char *args)
{
CommandList *c;
char *x;
int found=false;
if (argc < 2)
{
......@@ -1312,13 +1310,16 @@ void t_help(CommandList *cm, int argc, const char **argv, char *args)
if (args==NULL)
{
x = makepath(TALKHELP,"/","general");
const char *x = TALKHELP"/general";
if (!access(x,00))
printfile(x);
else
printf("No general help available for talker commands.\n");
}else
{
AUTOFREE_BUFFER x = NULL;
/* find the command in the list */
c = chattable;
while (c->Command && strcasecmp(c->Command, args)) c++;
......@@ -1332,15 +1333,11 @@ void t_help(CommandList *cm, int argc, const char **argv, char *args)
return;
}
}
/* display the file */
x=makepath(TALKHELP,"/",args);
if (!access(x,00))
{
asprintf(&x, TALKHELP"/%s", args);
if (x != NULL && !access(x,00))
printfile(x);
found=true;
}
if (!found) printf("Sorry, no help available on that subject.\n");
else
printf("Sorry, no help available on that subject.\n");
}
}
......
......@@ -6,10 +6,21 @@
#include "strings.h"
#include "folders.h"
#include "perms.h"
#include "files.h"
#define FOLDERFILE STATEDIR"/folders.bb"
int idx_fd = -1;
int txt_fd = -1;
const char *folder_types[] = {
FOL_LIVE,
FOL_MOD,
FOL_NEW,
FOL_TMP,
};
int openfolderfile(int mode)
{
int x;
......@@ -106,3 +117,159 @@ int get_folder_number(struct folder *fol, int num)
close(file);
return 1;
}
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;
}
......@@ -2,6 +2,7 @@
#define FOLDERS_H
#include <stdint.h>
#include "user.h"
#define FOLNAMESIZE 10 /* length of folder names */
#define TOPICSIZE 30 /* length of the topic of the folder */
......@@ -47,11 +48,28 @@ bit use
#define f_private(stat) (stat & (1 << MWFOLDR_PRIVATE))
#define f_moderated(stat) (stat & (1 << MWFOLDR_MODERATED))
#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];
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);
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);
#endif /* FOLDERS_H */
......@@ -4,6 +4,7 @@
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
......@@ -12,6 +13,7 @@
#include <sys/time.h>
#include <stdbool.h>
#include <time.h>
#include <dirent.h>
#include <socket.h>
#include <nonce.h>
......@@ -23,6 +25,7 @@
#include "servsock.h"
#include "replay.h"
#include "actions.h"
#include <folders.h>
#include <gags.h>
#include <perms.h>
#include <special.h>
......@@ -573,8 +576,105 @@ void msg_apply_gag(struct user *from, ipc_message_t * msg, const char * field)
json_decref(j);
}
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);
}
}
void init_server()
{
migrate_old_folders();
INIT_LIST_HEAD(&connection_list);
if (pollfd == -1) {
pollfd = epoll_create(30);
......