⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mix.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 5 页
字号:
/* MIX test for message file name * Accepts: candidate directory name * Returns: T if message file name, NIL otherwise * * ".mix" with no suffix was used by experimental versions */int mix_select (struct direct *name){  char c,*s;				/* make sure name has prefix */  if (mix_dirfmttest (name->d_name)) {    for (c = *(s = name->d_name + sizeof (MIXNAME) - 1); c && isxdigit (c);	 c = *s++);    if (!c) return T;		/* all-hex or no suffix */  }  return NIL;			/* not suffix or non-hex */}/* MIX msg file name comparision * Accepts: first candidate directory entry *	    second candidate directory entry * Returns: -1 if d1 < d2, 0 if d1 == d2, 1 d1 > d2 */int mix_msgfsort (const void *d1,const void *d2){  char *n1 = (*(struct direct **) d1)->d_name + sizeof (MIXNAME) - 1;  char *n2 = (*(struct direct **) d2)->d_name + sizeof (MIXNAME) - 1;  return compare_ulong (*n1 ? strtoul (n1,NIL,16) : 0,			*n2 ? strtoul (n2,NIL,16) : 0);}/* MIX add a range to a set * Accepts: pointer to set to add *	    start of set *	    size of set * Returns: T if success, set updated, NIL otherwise */long mix_addset (SEARCHSET **set,unsigned long start,unsigned long size){  SEARCHSET *s = *set;  if (start < s->last) {	/* sanity check */    char tmp[MAILTMPLEN];    sprintf (tmp,"Backwards-running mix index %lu < %lu",start,s->last);    MM_LOG (tmp,ERROR);    return NIL;  }				/* range initially empty? */  if (!s->last) s->first = start;  else if (start > s->last)	/* no, start new range if can't append */    (*set = s = s->next = mail_newsearchset ())->first = start;  s->last = start + size;	/* end of current range */  return LONGT;}/* MIX burp message file * Accepts: MAIL stream *	    current burp block for this message * Returns: T if successful, NIL if failed */static char *staterr = "Error in stat of mix message file %.80s: %.80s";static char *truncerr = "Error truncating mix message file %.80s: %.80s";long mix_burp (MAILSTREAM *stream,MIXBURP *burp,unsigned long *reclaimed){  MESSAGECACHE *elt;  SEARCHSET *set;  struct stat sbuf;  off_t rpos,wpos;  size_t size,wsize,wpending,written;  int fd;  FILE *f;  void *s;  unsigned long i;  long ret = NIL;				/* build file name */  mix_file_data (LOCAL->buf,stream->mailbox,burp->fileno);				/* need to burp at start or multiple ranges? */  if (!burp->set.first && !burp->set.next) {				/* easy case, single range at start of file */    if (stat (LOCAL->buf,&sbuf)) {      sprintf (LOCAL->buf,staterr,burp->name,strerror (errno));      MM_LOG (LOCAL->buf,ERROR);    }				/* is this range sane? */    else if (mix_burp_check (&burp->set,sbuf.st_size,LOCAL->buf)) {				/* if matches range then no burp needed! */      if (burp->set.last == sbuf.st_size) ret = LONGT;				/* just need to remove cruft at end */      else if (ret = !truncate (LOCAL->buf,burp->set.last))	*reclaimed += sbuf.st_size - burp->set.last;      else {	sprintf (LOCAL->buf,truncerr,burp->name,strerror (errno));	MM_LOG (LOCAL->buf,ERROR);      }    }  }				/* have to do more work, get the file */  else if (((fd = open (LOCAL->buf,O_RDWR,NIL)) < 0) ||	   !(f = fdopen (fd,"r+b"))) {    sprintf (LOCAL->buf,"Error opening mix message file %.80s: %.80s",	     burp->name,strerror (errno));    MM_LOG (LOCAL->buf,ERROR);    if (fd >= 0) close (fd);	/* in case fdopen() failure */  }  else if (fstat (fd,&sbuf)) {	/* get file size */    sprintf (LOCAL->buf,staterr,burp->name,strerror (errno));    MM_LOG (LOCAL->buf,ERROR);    fclose (f);  }				/* only if sane */  else if (mix_burp_check (&burp->set,sbuf.st_size,LOCAL->buf)) {				/* make sure each range starts with token */    for (set = &burp->set; set; set = set->next)      if (fseek (f,set->first,SEEK_SET) ||	  (fread (LOCAL->buf,1,MSGTSZ,f) != MSGTSZ) ||	  strncmp (LOCAL->buf,MSGTOK,MSGTSZ)) {	sprintf (LOCAL->buf,"Bad message token in mix message file at %lu",		 set->first);	MM_LOG (LOCAL->buf,ERROR);	fclose (f);	return NIL;		/* burp fails for this file */      }				/* burp out each old message */    for (set = &burp->set, wpos = 0; set; set = set->next) {				/* move down this range */      for (rpos = set->first, size = set->last - set->first;	   size; size -= wsize) {	if (rpos != wpos) {	/* data to skip at start? */				/* no, slide this buffer down */	  wsize = min (size,LOCAL->buflen);				/* failure is not an option here */	  while (fseek (f,rpos,SEEK_SET) ||		 (fread (LOCAL->buf,1,wsize,f) != wsize)) {	    MM_NOTIFY (stream,strerror (errno),WARN);	    MM_DISKERROR (stream,errno,T);	  }				/* nor here */	  while (fseek (f,wpos,SEEK_SET)) {	    MM_NOTIFY (stream,strerror (errno),WARN);	    MM_DISKERROR (stream,errno,T);	  }				/* and especially not here */	  for (s = LOCAL->buf, wpending = wsize; wpending; wpending -= written)	    if (!(written = fwrite (LOCAL->buf,1,wpending,f))) {	      MM_NOTIFY (stream,strerror (errno),WARN);	      MM_DISKERROR (stream,errno,T);	    }	}	else wsize = size;	/* nothing to skip, say we wrote it all */	rpos += wsize; wpos += wsize;      }    }    while (fflush (f)) {	/* failure also not an option here... */      MM_NOTIFY (stream,strerror (errno),WARN);      MM_DISKERROR (stream,errno,T);    }    if (ftruncate (fd,wpos)) {	/* flush cruft at end of file */      sprintf (LOCAL->buf,truncerr,burp->name,strerror (errno));      MM_LOG (LOCAL->buf,WARN);    }    else *reclaimed += rpos - wpos;    ret = !fclose (f);		/* close file */				/* slide down message positions in index */    for (i = 1,rpos = 0; i <= stream->nmsgs; ++i)      if ((elt = mail_elt (stream,i))->private.spare.data == burp->fileno) {	elt->private.special.offset = rpos;	rpos += elt->private.msg.header.offset + elt->rfc822_size;      }				/* debugging */    if (rpos != wpos) fatal ("burp size consistency check!");  }  return ret;}/* MIX burp sanity check to make sure not burping off end of file * Accepts: burp set *	    file size *	    file name * Returns: T if sane, NIL if insane */long mix_burp_check (SEARCHSET *set,size_t size,char *file){  do if (set->last > size) {	/* sanity check */    char tmp[MAILTMPLEN];    sprintf (tmp,"Unexpected short mix message file %.80s %lu < %lu",	     file,size,set->last);    MM_LOG (tmp,ERROR);    return NIL;			/* don't burp this file at all */  } while (set = set->next);  return LONGT;}/* MIX mail copy message(s) * Accepts: MAIL stream *	    sequence *	    destination mailbox *	    copy options * Returns: T if copy successful, else NIL */long mix_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options){  FDDATA d;  STRING st;  char tmp[2*MAILTMPLEN];  long ret = mix_isvalid (mailbox,LOCAL->buf);  mailproxycopy_t pc =    (mailproxycopy_t) mail_parameters (stream,GET_MAILPROXYCOPY,NIL);  MAILSTREAM *astream = NIL;  FILE *idxf = NIL;  FILE *msgf = NIL;  FILE *statf = NIL;  if (!ret) switch (errno) {	/* make sure valid mailbox */  case NIL:			/* no error in stat() */    if (pc) return (*pc) (stream,sequence,mailbox,options);    sprintf (tmp,"Not a MIX-format mailbox: %.80s",mailbox);    MM_LOG (tmp,ERROR);    break;  default:			/* some stat() error */    MM_NOTIFY (stream,"[TRYCREATE] Must create mailbox before copy",NIL);    break;  }				/* get sequence to copy */  else if (!(ret = ((options & CP_UID) ? mail_uid_sequence (stream,sequence) :		    mail_sequence (stream,sequence))));				/* acquire stream to append */  else if (ret = ((astream = mail_open (NIL,mailbox,OP_SILENT)) &&		  !astream->rdonly &&		  (((MIXLOCAL *) astream->local)->expok = T) &&		  (statf = mix_parse (astream,&idxf,LONGT,NIL))) ?	   LONGT : NIL) {    int fd;    unsigned long i;    MESSAGECACHE *elt;    unsigned long newsize,hdrsize,size;    MIXLOCAL *local = (MIXLOCAL *) astream->local;    unsigned long seq = mix_modseq (local->metaseq);				/* make sure new modseq fits */    if (local->indexseq > seq) seq = local->indexseq + 1;    if (local->statusseq > seq) seq = local->statusseq + 1;				/* calculate size of per-message header */    sprintf (local->buf,MSRFMT,MSGTOK,0,0,0,0,0,0,0,'+',0,0,0);    hdrsize = strlen (local->buf);    MM_CRITICAL (stream);	/* go critical */    astream->silent = T;	/* no events here */				/* calculate size that will be added */    for (i = 1, newsize = 0; i <= stream->nmsgs; ++i)      if ((elt = mail_elt (stream,i))->sequence)	newsize += hdrsize + elt->rfc822_size;				/* open data file */    if (msgf = mix_data_open (astream,&fd,&size,newsize)) {      char *t;      unsigned long j,uid,uidv;      copyuid_t cu = (copyuid_t) mail_parameters (NIL,GET_COPYUID,NIL);      SEARCHSET *source = cu ? mail_newsearchset () : NIL;      SEARCHSET *dest = cu ? mail_newsearchset () : NIL;      for (i = 1,uid = uidv = 0; ret && (i <= stream->nmsgs); ++i) 	if (((elt = mail_elt (stream,i))->sequence) && elt->rfc822_size) {				/* is message in current message file? */	  if ((LOCAL->msgfd < 0) ||	      (elt->private.spare.data != LOCAL->curmsg)) {	    if (LOCAL->msgfd >= 0) close (LOCAL->msgfd);	    if ((LOCAL->msgfd = open (mix_file_data (LOCAL->buf,						     stream->mailbox,						     elt->private.spare.data),				      O_RDONLY,NIL)) >= 0)	      LOCAL->curmsg = elt->private.spare.data;	  }	  if (LOCAL->msgfd < 0) ret = NIL;	  else {		/* got file */	    d.fd = LOCAL->msgfd;/* set up file descriptor */				/* start of message */	    d.pos = elt->private.special.offset +	      elt->private.msg.header.offset;	    d.chunk = LOCAL->buf;	    d.chunksize = CHUNKSIZE;	    INIT (&st,fd_string,&d,elt->rfc822_size);				/* init flag string */	    tmp[0] = tmp[1] = '\0';	    if (j = elt->user_flags) do	      if ((t = stream->user_flags[find_rightmost_bit (&j)]) && *t)		strcat (strcat (tmp," "),t);	    while (j);	    if (elt->seen) strcat (tmp," \\Seen");	    if (elt->deleted) strcat (tmp," \\Deleted");	    if (elt->flagged) strcat (tmp," \\Flagged");	    if (elt->answered) strcat (tmp," \\Answered");	    if (elt->draft) strcat (tmp," \\Draft");	    tmp[0] = '(';	/* wrap list */	    strcat (tmp,")");				/* if append OK, add to source set */	    if ((ret = mix_append_msg (astream,msgf,tmp,elt,&st,dest,				       seq)) &&	source)	      mail_append_set (source,mail_uid (stream,i));	  }	}				/* finish write if success */      if (ret && (ret = !fflush (msgf))) {	fclose (msgf);		/* all good, close the msg file now */				/* write new metadata, index, and status */	local->metaseq = local->indexseq = local->statusseq = seq;	if (ret = (mix_meta_update (astream) &&		   mix_index_update (astream,idxf,LONGT))) {				/* success, delete if doing a move */	  if (options & CP_MOVE)	    for (i = 1; i <= stream->nmsgs; i++)	      if ((elt = mail_elt (stream,i))->sequence) {		elt->deleted = T;		if (!stream->rdonly) elt->private.mod = LOCAL->statusseq = seq;		MM_FLAGS (stream,elt->msgno);	      }				/* done with status file now */	  mix_status_update (astream,statf,LONGT);				/* return sets if doing COPYUID */	  if (cu) (*cu) (stream,mailbox,astream->uid_validity,source,dest);	  source = dest = NIL;	/* don't free these sets now */	}      }      else {			/* error */	if (errno) {		/* output error message if system call error */	  sprintf (tmp,"Message copy failed: %.80s",strerror (errno));	  MM_LOG (tmp,ERROR);	}	ftruncate (fd,size);	/* revert file */	close (fd);		/* make sure that fclose doesn't corrupt us */	fclose (msgf);		/* free the stdio resources */      }				/* flush any sets remaining */      mail_free_searchset (&source);      mail_free_searchset (&dest);    }    else {			/* message file open failed */      sprintf (tmp,"Error opening copy message file: %.80s",	       strerror (errno));      MM_LOG (tmp,ERROR);      ret = NIL;    }    MM_NOCRITICAL (stream);  }  else MM_LOG ("Can't open copy mailbox",ERROR);  if (statf) fclose (statf);	/* close status if still open */  if (idxf) fclose (idxf);	/* close index if still open */				/* finished with append stream */  if (astream) mail_close (astream);  return ret;			/* return state */}/* MIX mail append message from stringstruct * Accepts: MAIL stream *	    destination mailbox *	    append callback *	    data for callback * Returns: T if append successful, else NIL */long mix_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data){  STRING *message;  char *flags,*date,tmp[MAILTMPLEN];				/* N.B.: can't use LOCAL->buf for tmp */  long ret = mix_isvalid (mailbox,tmp);				/* default stream to prototype */  if (!stream) stream = user_flags (&mixproto);  if (!ret) switch (errno) {	/* if not valid mailbox */  case ENOENT:			/* no such file? */    if (ret = compare_cstring (mailbox,"INBOX") ?	NIL : mix_create (NIL,"INBOX"))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -