X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmsgbase.c;h=a88a76369b5622251daf366d98fa0564bfd8b199;hb=e047988e5cb07d89edeec13afea5c25a52ef26c6;hp=6db04f8a1b326ecc919d57e4f7bf40ca4e312ec0;hpb=c750a06a241dc2737fa68c24b340a1bd82894f74;p=citadel.git diff --git a/citadel/msgbase.c b/citadel/msgbase.c index 6db04f8a1..a88a76369 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -1,7 +1,7 @@ /* * Implements the message store. * - * Copyright (c) 1987-2017 by the citadel.org team + * Copyright (c) 1987-2018 by the citadel.org team * * This program is open source software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3. @@ -35,10 +35,6 @@ struct addresses_to_be_filed *atbf = NULL; -/* This temp file holds the queue of operations for AdjRefCount() */ -static FILE *arcfp = NULL; -void AdjRefCountList(long *msgnum, long nmsg, int incr); - /* * These are the four-character field headers we use when outputting * messages in Citadel format (as opposed to RFC822 format). @@ -55,23 +51,23 @@ char *msgkeys[91] = { NULL, "from", /* A -> eAuthor */ NULL, /* B -> eBig_message */ - NULL, /* C -> eRemoteRoom */ - NULL, /* D -> eDestination */ + NULL, /* C -> eRemoteRoom FIXME no more ignet */ + NULL, /* D -> eDestination FIXME no more ignet */ "exti", /* E -> eXclusivID */ "rfca", /* F -> erFc822Addr */ NULL, /* G */ - "hnod", /* H -> eHumanNode */ + "hnod", /* H -> eHumanNode FIXME no more ignet */ "msgn", /* I -> emessageId */ "jrnl", /* J -> eJournal */ "rep2", /* K -> eReplyTo */ "list", /* L -> eListID */ "text", /* M -> eMesageText */ - "node", /* N -> eNodeName */ + "node", /* N -> eNodeName FIXME no more ignet */ "room", /* O -> eOriginalRoom */ "path", /* P -> eMessagePath */ NULL, /* Q */ "rcpt", /* R -> eRecipient */ - "spec", /* S -> eSpecialField */ + "spec", /* S -> eSpecialField FIXME we might not be using this anymore */ "time", /* T -> eTimestamp */ "subj", /* U -> eMsgSubject */ "nvto", /* V -> eenVelopeTo */ @@ -147,22 +143,25 @@ eMsgField FieldOrder[] = { static const long NDiskFields = sizeof(FieldOrder) / sizeof(eMsgField); + int CM_IsEmpty(struct CtdlMessage *Msg, eMsgField which) { - return !((Msg->cm_fields[which] != NULL) && - (Msg->cm_fields[which][0] != '\0')); + return !((Msg->cm_fields[which] != NULL) && (Msg->cm_fields[which][0] != '\0')); } + void CM_SetField(struct CtdlMessage *Msg, eMsgField which, const char *buf, long length) { - if (Msg->cm_fields[which] != NULL) + if (Msg->cm_fields[which] != NULL) { free (Msg->cm_fields[which]); + } Msg->cm_fields[which] = malloc(length + 1); memcpy(Msg->cm_fields[which], buf, length); Msg->cm_fields[which][length] = '\0'; Msg->cm_lengths[which] = length; } + void CM_SetFieldLONG(struct CtdlMessage *Msg, eMsgField which, long lvalue) { char buf[128]; @@ -170,6 +169,8 @@ void CM_SetFieldLONG(struct CtdlMessage *Msg, eMsgField which, long lvalue) len = snprintf(buf, sizeof(buf), "%ld", lvalue); CM_SetField(Msg, which, buf, len); } + + void CM_CutFieldAt(struct CtdlMessage *Msg, eMsgField WhichToCut, long maxlen) { if (Msg->cm_fields[WhichToCut] == NULL) @@ -182,6 +183,7 @@ void CM_CutFieldAt(struct CtdlMessage *Msg, eMsgField WhichToCut, long maxlen) } } + void CM_FlushField(struct CtdlMessage *Msg, eMsgField which) { if (Msg->cm_fields[which] != NULL) @@ -189,35 +191,37 @@ void CM_FlushField(struct CtdlMessage *Msg, eMsgField which) Msg->cm_fields[which] = NULL; Msg->cm_lengths[which] = 0; } + + void CM_Flush(struct CtdlMessage *Msg) { int i; - if (CM_IsValidMsg(Msg) == 0) + if (CM_IsValidMsg(Msg) == 0) { return; + } - for (i = 0; i < 256; ++i) - { + for (i = 0; i < 256; ++i) { CM_FlushField(Msg, i); } } + void CM_CopyField(struct CtdlMessage *Msg, eMsgField WhichToPutTo, eMsgField WhichtToCopy) { long len; - if (Msg->cm_fields[WhichToPutTo] != NULL) + if (Msg->cm_fields[WhichToPutTo] != NULL) { free (Msg->cm_fields[WhichToPutTo]); + } - if (Msg->cm_fields[WhichtToCopy] != NULL) - { + if (Msg->cm_fields[WhichtToCopy] != NULL) { len = Msg->cm_lengths[WhichtToCopy]; Msg->cm_fields[WhichToPutTo] = malloc(len + 1); memcpy(Msg->cm_fields[WhichToPutTo], Msg->cm_fields[WhichtToCopy], len); Msg->cm_fields[WhichToPutTo][len] = '\0'; Msg->cm_lengths[WhichToPutTo] = len; } - else - { + else { Msg->cm_fields[WhichToPutTo] = NULL; Msg->cm_lengths[WhichToPutTo] = 0; } @@ -249,48 +253,53 @@ void CM_PrependToField(struct CtdlMessage *Msg, eMsgField which, const char *buf } } + void CM_SetAsField(struct CtdlMessage *Msg, eMsgField which, char **buf, long length) { - if (Msg->cm_fields[which] != NULL) + if (Msg->cm_fields[which] != NULL) { free (Msg->cm_fields[which]); + } Msg->cm_fields[which] = *buf; *buf = NULL; Msg->cm_lengths[which] = length; } + void CM_SetAsFieldSB(struct CtdlMessage *Msg, eMsgField which, StrBuf **buf) { - if (Msg->cm_fields[which] != NULL) + if (Msg->cm_fields[which] != NULL) { free (Msg->cm_fields[which]); + } Msg->cm_lengths[which] = StrLength(*buf); Msg->cm_fields[which] = SmashStrBuf(buf); } + void CM_GetAsField(struct CtdlMessage *Msg, eMsgField which, char **ret, long *retlen) { - if (Msg->cm_fields[which] != NULL) - { + if (Msg->cm_fields[which] != NULL) { *retlen = Msg->cm_lengths[which]; *ret = Msg->cm_fields[which]; Msg->cm_fields[which] = NULL; Msg->cm_lengths[which] = 0; } - else - { + else { *ret = NULL; *retlen = 0; } } + /* * Returns 1 if the supplied pointer points to a valid Citadel message. * If the pointer is NULL or the magic number check fails, returns 0. */ int CM_IsValidMsg(struct CtdlMessage *msg) { - if (msg == NULL) + if (msg == NULL) { return 0; + } if ((msg->cm_magic) != CTDLMESSAGE_MAGIC) { syslog(LOG_WARNING, "msgbase: CM_IsValidMsg() self-check failed"); return 0; @@ -298,6 +307,7 @@ int CM_IsValidMsg(struct CtdlMessage *msg) { return 1; } + void CM_FreeContents(struct CtdlMessage *msg) { int i; @@ -310,13 +320,14 @@ void CM_FreeContents(struct CtdlMessage *msg) msg->cm_magic = 0; /* just in case */ } + + /* * 'Destructor' for struct CtdlMessage */ void CM_Free(struct CtdlMessage *msg) { - if (CM_IsValidMsg(msg) == 0) - { + if (CM_IsValidMsg(msg) == 0) { if (msg != NULL) free (msg); return; } @@ -324,40 +335,42 @@ void CM_Free(struct CtdlMessage *msg) free(msg); } + int CM_DupField(eMsgField i, struct CtdlMessage *OrgMsg, struct CtdlMessage *NewMsg) { long len; len = OrgMsg->cm_lengths[i]; NewMsg->cm_fields[i] = malloc(len + 1); - if (NewMsg->cm_fields[i] == NULL) + if (NewMsg->cm_fields[i] == NULL) { return 0; + } memcpy(NewMsg->cm_fields[i], OrgMsg->cm_fields[i], len); NewMsg->cm_fields[i][len] = '\0'; NewMsg->cm_lengths[i] = len; return 1; } + struct CtdlMessage * CM_Duplicate(struct CtdlMessage *OrgMsg) { int i; struct CtdlMessage *NewMsg; - if (CM_IsValidMsg(OrgMsg) == 0) + if (CM_IsValidMsg(OrgMsg) == 0) { return NULL; + } NewMsg = (struct CtdlMessage *)malloc(sizeof(struct CtdlMessage)); - if (NewMsg == NULL) + if (NewMsg == NULL) { return NULL; + } memcpy(NewMsg, OrgMsg, sizeof(struct CtdlMessage)); memset(&NewMsg->cm_fields, 0, sizeof(char*) * 256); - for (i = 0; i < 256; ++i) - { - if (OrgMsg->cm_fields[i] != NULL) - { - if (!CM_DupField(i, OrgMsg, NewMsg)) - { + for (i = 0; i < 256; ++i) { + if (OrgMsg->cm_fields[i] != NULL) { + if (!CM_DupField(i, OrgMsg, NewMsg)) { CM_Free(NewMsg); return NULL; } @@ -368,9 +381,6 @@ struct CtdlMessage * CM_Duplicate(struct CtdlMessage *OrgMsg) } - - - /* Determine if a given message matches the fields in a message template. * Return 0 for a successful match. */ @@ -403,7 +413,6 @@ int CtdlMsgCmp(struct CtdlMessage *msg, struct CtdlMessage *template) { } - /* * Retrieve the "seen" message list for the current room. */ @@ -413,14 +422,15 @@ void CtdlGetSeen(char *buf, int which_set) { /* Learn about the user and room in question */ CtdlGetRelationship(&vbuf, &CC->user, &CC->room); - if (which_set == ctdlsetseen_seen) + if (which_set == ctdlsetseen_seen) { safestrncpy(buf, vbuf.v_seen, SIZ); - if (which_set == ctdlsetseen_answered) + } + if (which_set == ctdlsetseen_answered) { safestrncpy(buf, vbuf.v_answered, SIZ); + } } - /* * Manipulate the "seen msgs" string (or other message set strings) */ @@ -432,7 +442,7 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, int is_seen = 0; int was_seen = 0; long lo = (-1L); - long hi = (-1L); /// TODO: we just write here. y? + long hi = (-1L); visit vbuf; long *msglist; int num_msgs = 0; @@ -538,7 +548,6 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, FreeStrBuf(&lostr); FreeStrBuf(&histr); - /* Now translate the array of booleans back into a sequence set */ FlushStrBuf(vset); was_seen = 0; @@ -843,12 +852,15 @@ int CtdlForEachMessage(int mode, long ref, char *search_string, ) ) { if ((mode == MSGS_NEW) && (CC->user.flags & US_LASTOLD) && (lastold > 0L) && (printed_lastold == 0) && (!is_seen)) { - if (CallBack) + if (CallBack) { CallBack(lastold, userdata); + } printed_lastold = 1; ++num_processed; } - if (CallBack) CallBack(thismsg, userdata); + if (CallBack) { + CallBack(thismsg, userdata); + } ++num_processed; } } @@ -872,7 +884,6 @@ int CtdlForEachMessage(int mode, long ref, char *search_string, } - /* * memfmout() - Citadel text formatter and paginator. * Although the original purpose of this routine was to format @@ -895,14 +906,12 @@ void memfmout( while (ch=*(mptr++), ch != 0) { if (ch == '\n') { - if (client_write(outbuf, len) == -1) - { + if (client_write(outbuf, len) == -1) { syslog(LOG_ERR, "msgbase: memfmout() aborting due to write failure"); return; } len = 0; - if (client_write(nl, nllen) == -1) - { + if (client_write(nl, nllen) == -1) { syslog(LOG_ERR, "msgbase: memfmout() aborting due to write failure"); return; } @@ -913,14 +922,12 @@ void memfmout( } else if (isspace(ch)) { if (column > 72) { /* Beyond 72 columns, break on the next space */ - if (client_write(outbuf, len) == -1) - { + if (client_write(outbuf, len) == -1) { syslog(LOG_ERR, "msgbase: memfmout() aborting due to write failure"); return; } len = 0; - if (client_write(nl, nllen) == -1) - { + if (client_write(nl, nllen) == -1) { syslog(LOG_ERR, "msgbase: memfmout() aborting due to write failure"); return; } @@ -935,14 +942,12 @@ void memfmout( outbuf[len++] = ch; ++column; if (column > 1000) { /* Beyond 1000 columns, break anywhere */ - if (client_write(outbuf, len) == -1) - { + if (client_write(outbuf, len) == -1) { syslog(LOG_ERR, "msgbase: memfmout() aborting due to write failure"); return; } len = 0; - if (client_write(nl, nllen) == -1) - { + if (client_write(nl, nllen) == -1) { syslog(LOG_ERR, "msgbase: memfmout(): aborting due to write failure"); return; } @@ -951,8 +956,7 @@ void memfmout( } } if (len) { - if (client_write(outbuf, len) == -1) - { + if (client_write(outbuf, len) == -1) { syslog(LOG_ERR, "msgbase: memfmout() aborting due to write failure"); return; } @@ -962,7 +966,6 @@ void memfmout( } - /* * Callback function for mime parser that simply lists the part */ @@ -986,6 +989,7 @@ void list_this_part(char *name, char *filename, char *partnum, char *disp, } } + /* * Callback function for multipart prefix */ @@ -1005,6 +1009,7 @@ void list_this_pref(char *name, char *filename, char *partnum, char *disp, } } + /* * Callback function for multipart sufffix */ @@ -1066,7 +1071,6 @@ void mime_download(char *name, char *filename, char *partnum, char *disp, } - /* * Callback function for mime parser that outputs a section all at once. * We can specify the desired section by part number *or* content-id. @@ -1093,6 +1097,7 @@ void mime_spew_section(char *name, char *filename, char *partnum, char *disp, } } + struct CtdlMessage *CtdlDeserializeMessage(long msgnum, int with_body, const char *Buffer, long Length) { struct CtdlMessage *ret = NULL; @@ -1132,8 +1137,7 @@ struct CtdlMessage *CtdlDeserializeMessage(long msgnum, int with_body, const cha long len; /* work around possibly buggy messages: */ - while (field_header == '\0') - { + while (field_header == '\0') { if (mptr >= upper_bound) { break; } @@ -1174,8 +1178,7 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body, int run_msg_hoo return NULL; } - if (dmsgtext->ptr[dmsgtext->len - 1] != '\0') - { + if (dmsgtext->ptr[dmsgtext->len - 1] != '\0') { syslog(LOG_ERR, "msgbase: CtdlFetchMessage(%ld, %d) Forcefully terminating message!!", msgnum, with_body); dmsgtext->ptr[dmsgtext->len - 1] = '\0'; } @@ -1214,7 +1217,6 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body, int run_msg_hoo } - /* * Pre callback function for multipart/alternative * @@ -1242,6 +1244,7 @@ void fixed_output_pre(char *name, char *filename, char *partnum, char *disp, } } + /* * Post callback function for multipart/alternative */ @@ -1262,6 +1265,7 @@ void fixed_output_post(char *name, char *filename, char *partnum, char *disp, } } + /* * Inline callback function for mime parser that wants to display text */ @@ -1328,6 +1332,7 @@ void fixed_output(char *name, char *filename, char *partnum, char *disp, } } + /* * The client is elegant and sophisticated and wants to be choosy about * MIME content types, so figure out which multipart/alternative part @@ -1349,11 +1354,6 @@ void choose_preferred(char *name, char *filename, char *partnum, char *disp, ma = (struct ma_info *)cbuserdata; - // NOTE: REMOVING THIS CONDITIONAL FIXES BUG 220 - // http://bugzilla.citadel.org/show_bug.cgi?id=220 - // I don't know if there are any side effects! Please TEST TEST TEST - //if (ma->is_ma > 0) { - for (i=0; ipreferred_formats, '|'); ++i) { extract_token(buf, CC->preferred_formats, i, '|', sizeof buf); if ( (!strcasecmp(buf, cbtype)) && (!ma->freeze) ) { @@ -1366,6 +1366,7 @@ void choose_preferred(char *name, char *filename, char *partnum, char *disp, } } + /* * Now that we've chosen our preferred part, output it. */ @@ -1531,7 +1532,6 @@ int check_cached_msglist(long msgnum) { } - /* * Get a message off disk. (returns om_* values found in msgbase.h) * @@ -1688,7 +1688,6 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ } - void OutputCtdlMsgHeaders( struct CtdlMessage *TheMessage, int do_proto) /* do Citadel protocol responses? */ @@ -1725,9 +1724,7 @@ void OutputCtdlMsgHeaders( * local Citadel network. */ suppress_f = 0; - if (!CM_IsEmpty(TheMessage, eNodeName) && - (haschar(TheMessage->cm_fields[eNodeName], '.') == 0)) - { + if (!CM_IsEmpty(TheMessage, eNodeName) && (haschar(TheMessage->cm_fields[eNodeName], '.') == 0)) { suppress_f = 1; } @@ -1753,17 +1750,16 @@ void OutputCtdlMsgHeaders( } /* Masquerade display name if needed */ else { - if (do_proto) cprintf("%s=%s\n", - msgkeys[Field], - TheMessage->cm_fields[Field] - ); + if (do_proto) { + cprintf("%s=%s\n", msgkeys[Field], TheMessage->cm_fields[Field]); + } } } } } - } + void OutputRFC822MsgHeaders( struct CtdlMessage *TheMessage, int flags, /* should the bessage be exported clean */ @@ -1817,27 +1813,20 @@ void OutputRFC822MsgHeaders( subject_found = 1; break; case emessageId: - safestrncpy(mid, mptr, sizeof_mid); /// TODO: detect @ here and copy @nodename in if not found. + safestrncpy(mid, mptr, sizeof_mid); break; case erFc822Addr: safestrncpy(fuser, mptr, sizeof_fuser); - /* case eOriginalRoom: - cprintf("X-Citadel-Room: %s%s", - mptr, nl) - break; - ; */ case eNodeName: safestrncpy(snode, mptr, sizeof_snode); break; case eRecipient: - if (haschar(mptr, '@') == 0) - { + if (haschar(mptr, '@') == 0) { sanitize_truncated_recipient(mptr); cprintf("To: %s@%s", mptr, CtdlGetConfigStr("c_fqdn")); cprintf("%s", nl); } - else - { + else { if ((flags & QP_EADDR) != 0) { mptr = qp_encode_email_addrs(mptr); } @@ -1847,8 +1836,7 @@ void OutputRFC822MsgHeaders( } break; case eTimestamp: - datestring(datestamp, sizeof datestamp, - atol(mptr), DATESTRING_RFC822); + datestring(datestamp, sizeof datestamp, atol(mptr), DATESTRING_RFC822); cprintf("Date: %s%s", datestamp, nl); break; case eWeferences: @@ -1888,10 +1876,10 @@ void OutputRFC822MsgHeaders( case eVltMsgNum: /* these don't map to mime message headers. */ break; - } - if (mptr != mpptr) + if (mptr != mpptr) { free (mptr); + } } } if (subject_found == 0) { @@ -1904,7 +1892,6 @@ void Dump_RFC822HeadersBody( struct CtdlMessage *TheMessage, int headers_only, /* eschew the message body? */ int flags, /* should the bessage be exported clean? */ - const char *nl, int nlen) { cit_uint8_t prev_ch; @@ -1918,7 +1905,6 @@ void Dump_RFC822HeadersBody( mptr = TheMessage->cm_fields[eMesageText]; - prev_ch = '\0'; while (*mptr != '\0') { if (*mptr == '\r') { @@ -1942,7 +1928,7 @@ void Dump_RFC822HeadersBody( ((headers_only == HEADERS_ONLY) && (mptr < StartOfText)) || ((headers_only != HEADERS_NONE) && (headers_only != HEADERS_ONLY)) - ) { + ) { if (*mptr == '\n') { memcpy(&outbuf[outlen], nl, nllen); outlen += nllen; @@ -1953,20 +1939,15 @@ void Dump_RFC822HeadersBody( } } } - if (flags & ESC_DOT) - { - if ((prev_ch == '\n') && - (*mptr == '.') && - ((*(mptr+1) == '\r') || (*(mptr+1) == '\n'))) - { + if (flags & ESC_DOT) { + if ((prev_ch == '\n') && (*mptr == '.') && ((*(mptr+1) == '\r') || (*(mptr+1) == '\n'))) { outbuf[outlen++] = '.'; } prev_ch = *mptr; } ++mptr; if (outlen > 1000) { - if (client_write(outbuf, outlen) == -1) - { + if (client_write(outbuf, outlen) == -1) { syslog(LOG_ERR, "msgbase: Dump_RFC822HeadersBody() aborting due to write failure"); return; } @@ -1983,7 +1964,6 @@ void Dump_RFC822HeadersBody( } - /* If the format type on disk is 1 (fixed-format), then we want * everything to be output completely literally ... regardless of * what message transfer format is in use. @@ -2026,20 +2006,18 @@ void DumpFormatFixed( ch = '\r'; } } - /* if we reach the outer bounds of our buffer, - abort without respect what whe purge. */ - if (xlline && - ((isspace(ch)) || - (buflen > SIZ - nllen - 2))) + + /* if we reach the outer bounds of our buffer, abort without respect for what we purge. */ + if (xlline && ((isspace(ch)) || (buflen > SIZ - nllen - 2))) { ch = '\r'; + } if (ch == '\r') { memcpy (&buf[buflen], nl, nllen); buflen += nllen; buf[buflen] = '\0'; - if (client_write(buf, buflen) == -1) - { + if (client_write(buf, buflen) == -1) { syslog(LOG_ERR, "msgbase: DumpFormatFixed() aborting due to write failure"); return; } @@ -2052,10 +2030,12 @@ void DumpFormatFixed( } } buf[buflen] = '\0'; - if (!IsEmptyStr(buf)) + if (!IsEmptyStr(buf)) { cprintf("%s%s", buf, nl); + } } + /* * Get a message off disk. (returns om_* values found in msgbase.h) */ @@ -3500,14 +3480,11 @@ int CtdlDeleteMessages(const char *room_name, /* which room */ } - - /* * GetMetaData() - Get the supplementary record for a message */ void GetMetaData(struct MetaData *smibuf, long msgnum) { - struct cdbdata *cdbsmi; long TheIndex; @@ -3520,11 +3497,12 @@ void GetMetaData(struct MetaData *smibuf, long msgnum) cdbsmi = cdb_fetch(CDB_MSGMAIN, &TheIndex, sizeof(long)); if (cdbsmi == NULL) { - return; /* record not found; go with defaults */ + return; /* record not found; leave it alone */ } memcpy(smibuf, cdbsmi->ptr, ((cdbsmi->len > sizeof(struct MetaData)) ? - sizeof(struct MetaData) : cdbsmi->len)); + sizeof(struct MetaData) : cdbsmi->len) + ); cdb_free(cdbsmi); return; } @@ -3542,176 +3520,29 @@ void PutMetaData(struct MetaData *smibuf) cdb_store(CDB_MSGMAIN, &TheIndex, (int)sizeof(long), - smibuf, (int)sizeof(struct MetaData)); - + smibuf, (int)sizeof(struct MetaData) + ); } + /* - * AdjRefCount - submit an adjustment to the reference count for a message. - * (These are just queued -- we actually process them later.) + * Convenience function to process a big block of AdjRefCount() operations */ -void AdjRefCount(long msgnum, int incr) -{ - struct arcq new_arcq; - int rv = 0; - - syslog(LOG_DEBUG, "msgbase: AdjRefCount() msg %ld ref count delta %+d", msgnum, incr); - - begin_critical_section(S_SUPPMSGMAIN); - if (arcfp == NULL) { - arcfp = fopen(file_arcq, "ab+"); - chown(file_arcq, CTDLUID, (-1)); - chmod(file_arcq, 0600); - } - end_critical_section(S_SUPPMSGMAIN); - - /* msgnum < 0 means that we're trying to close the file */ - if (msgnum < 0) { - syslog(LOG_DEBUG, "msgbase: closing the AdjRefCount queue file"); - begin_critical_section(S_SUPPMSGMAIN); - if (arcfp != NULL) { - fclose(arcfp); - arcfp = NULL; - } - end_critical_section(S_SUPPMSGMAIN); - return; - } - - /* - * If we can't open the queue, perform the operation synchronously. - */ - if (arcfp == NULL) { - TDAP_AdjRefCount(msgnum, incr); - return; - } - - new_arcq.arcq_msgnum = msgnum; - new_arcq.arcq_delta = incr; - rv = fwrite(&new_arcq, sizeof(struct arcq), 1, arcfp); - if (rv == -1) { - syslog(LOG_EMERG, "%s: %m", file_arcq); - } - fflush(arcfp); - - return; -} - void AdjRefCountList(long *msgnum, long nmsg, int incr) { - long i, the_size, offset; - struct arcq *new_arcq; - int rv = 0; - - syslog(LOG_DEBUG, "msgbase: AdjRefCountList() msg %ld ref count delta %+d", nmsg, incr); - - begin_critical_section(S_SUPPMSGMAIN); - if (arcfp == NULL) { - arcfp = fopen(file_arcq, "ab+"); - chown(file_arcq, CTDLUID, (-1)); - chmod(file_arcq, 0600); - } - end_critical_section(S_SUPPMSGMAIN); - - /* - * If we can't open the queue, perform the operation synchronously. - */ - if (arcfp == NULL) { - for (i = 0; i < nmsg; i++) - TDAP_AdjRefCount(msgnum[i], incr); - return; - } + long i; - the_size = sizeof(struct arcq) * nmsg; - new_arcq = malloc(the_size); for (i = 0; i < nmsg; i++) { - new_arcq[i].arcq_msgnum = msgnum[i]; - new_arcq[i].arcq_delta = incr; - } - rv = 0; - offset = 0; - while ((rv >= 0) && (offset < the_size)) - { - rv = fwrite(new_arcq + offset, 1, the_size - offset, arcfp); - if (rv == -1) { - syslog(LOG_ERR, "%s: %m", file_arcq); - } - else { - offset += rv; - } - } - free(new_arcq); - fflush(arcfp); - - return; -} - - -/* - * TDAP_ProcessAdjRefCountQueue() - * - * Process the queue of message count adjustments that was created by calls - * to AdjRefCount() ... by reading the queue and calling TDAP_AdjRefCount() - * for each one. This should be an "off hours" operation. - */ -int TDAP_ProcessAdjRefCountQueue(void) -{ - char file_arcq_temp[PATH_MAX]; - int r; - FILE *fp; - struct arcq arcq_rec; - int num_records_processed = 0; - - snprintf(file_arcq_temp, sizeof file_arcq_temp, "%s.%04x", file_arcq, rand()); - - begin_critical_section(S_SUPPMSGMAIN); - if (arcfp != NULL) { - fclose(arcfp); - arcfp = NULL; - } - - r = link(file_arcq, file_arcq_temp); - if (r != 0) { - syslog(LOG_ERR, "%s: %m", file_arcq_temp); - end_critical_section(S_SUPPMSGMAIN); - return(num_records_processed); - } - - unlink(file_arcq); - end_critical_section(S_SUPPMSGMAIN); - - fp = fopen(file_arcq_temp, "rb"); - if (fp == NULL) { - syslog(LOG_ERR, "%s: %m", file_arcq_temp); - return(num_records_processed); + AdjRefCount(msgnum[i], incr); } - - while (fread(&arcq_rec, sizeof(struct arcq), 1, fp) == 1) { - TDAP_AdjRefCount(arcq_rec.arcq_msgnum, arcq_rec.arcq_delta); - ++num_records_processed; - } - - fclose(fp); - r = unlink(file_arcq_temp); - if (r != 0) { - syslog(LOG_ERR, "%s: %m", file_arcq_temp); - } - - return(num_records_processed); } - /* - * TDAP_AdjRefCount - adjust the reference count for a message. - * This one does it "for real" because it's called by - * the autopurger function that processes the queue - * created by AdjRefCount(). If a message's reference - * count becomes zero, we also delete the message from - * disk and de-index it. + * AdjRefCount - adjust the reference count for a message. We need to delete from disk any message whose reference count reaches zero. */ -void TDAP_AdjRefCount(long msgnum, int incr) +void AdjRefCount(long msgnum, int incr) { - struct MetaData smi; long delnum; @@ -3724,12 +3555,9 @@ void TDAP_AdjRefCount(long msgnum, int incr) smi.meta_refcount += incr; PutMetaData(&smi); end_critical_section(S_SUPPMSGMAIN); - syslog(LOG_DEBUG, "msgbase: TDAP_AdjRefCount() msg %ld ref count delta %+d, is now %d", - msgnum, incr, smi.meta_refcount - ); + syslog(LOG_DEBUG, "msgbase: AdjRefCount() msg %ld ref count delta %+d, is now %d", msgnum, incr, smi.meta_refcount); - /* If the reference count is now zero, delete the message - * (and its supplementary record as well). + /* If the reference count is now zero, delete both the message and its metadata record. */ if (smi.meta_refcount == 0) { syslog(LOG_DEBUG, "msgbase: deleting message <%ld>", msgnum); @@ -3746,9 +3574,9 @@ void TDAP_AdjRefCount(long msgnum, int incr) delnum = (0L - msgnum); cdb_delete(CDB_MSGMAIN, &delnum, (int)sizeof(long)); } - } + /* * Write a generic object to this room * @@ -3757,12 +3585,12 @@ void TDAP_AdjRefCount(long msgnum, int incr) */ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ char *content_type, /* MIME type of this object */ - char *raw_message, /* Data to be written */ - off_t raw_length, /* Size of raw_message */ + char *raw_message, /* Data to be written */ + off_t raw_length, /* Size of raw_message */ struct ctdluser *is_mailbox, /* Mailbox room? */ int is_binary, /* Is encoding necessary? */ int is_unique, /* Del others of this type? */ - unsigned int flags /* Internal save flags */ + unsigned int flags /* Internal save flags */ ) { struct ctdlroom qrbuf; @@ -3820,9 +3648,7 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ /* Create the requested room if we have to. */ if (CtdlGetRoom(&qrbuf, roomname) != 0) { - CtdlCreateRoom(roomname, - ( (is_mailbox != NULL) ? 5 : 3 ), - "", 0, 1, 0, VIEW_BBS); + CtdlCreateRoom(roomname, ( (is_mailbox != NULL) ? 5 : 3 ), "", 0, 1, 0, VIEW_BBS); } /* If the caller specified this object as unique, delete all * other objects of this type that are currently in the room. @@ -3838,10 +3664,9 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ } - -/*****************************************************************************/ -/* MODULE INITIALIZATION STUFF */ -/*****************************************************************************/ +/************************************************************************/ +/* MODULE INITIALIZATION */ +/************************************************************************/ CTDL_MODULE_INIT(msgbase) { @@ -3849,6 +3674,6 @@ CTDL_MODULE_INIT(msgbase) FillMsgKeyLookupTable(); } - /* return our Subversion id for the Log */ + /* return our module id for the log */ return "msgbase"; }