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

📄 mbx.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 5 页
字号:
 * Accepts: MAIL stream *	    cache element * Returns: non-NIL if message expunged */unsigned long mbx_read_flags (MAILSTREAM *stream,MESSAGECACHE *elt){  unsigned long i;  struct stat sbuf;  fstat (LOCAL->fd,&sbuf);	/* get status */				/* make sure file size is good */  if (sbuf.st_size < LOCAL->filesize) {    sprintf (LOCAL->buf,"Mailbox shrank from %lu to %lu in flag read!",	     (unsigned long) LOCAL->filesize,(unsigned long) sbuf.st_size);    fatal (LOCAL->buf);  }				/* set the seek pointer */  lseek (LOCAL->fd,(off_t) elt->private.special.offset +	 elt->private.special.text.size - 24,L_SET);				/* read the new flags */  if (read (LOCAL->fd,LOCAL->buf,14) < 0) {    sprintf (LOCAL->buf,"Unable to read new status: %s",strerror (errno));    fatal (LOCAL->buf);  }  if ((LOCAL->buf[0] != ';') || (LOCAL->buf[13] != '-')) {    LOCAL->buf[14] = '\0';	/* tie off buffer for error message */    sprintf (LOCAL->buf+50,"Invalid flags for message %lu (%lu %lu): %s",	     elt->msgno,elt->private.special.offset,	     elt->private.special.text.size,(char *) LOCAL->buf);    fatal (LOCAL->buf+50);  }  LOCAL->buf[13] = '\0';	/* tie off buffer */				/* calculate system flags */  i = strtoul (LOCAL->buf+9,NIL,16);  elt->seen = i & fSEEN ? T : NIL;  elt->deleted = i & fDELETED ? T : NIL;  elt->flagged = i & fFLAGGED ? T : NIL;  elt->answered = i & fANSWERED ? T : NIL;  elt->draft = i & fDRAFT ? T : NIL;  LOCAL->expunged |= i & fEXPUNGED ? T : NIL;  LOCAL->buf[9] = '\0';		/* tie off flags */				/* get user flags value */  elt->user_flags = strtoul (LOCAL->buf+1,NIL,16);  elt->valid = T;		/* have valid flags now */  return i & fEXPUNGED;}/* MBX update header * Accepts: MAIL stream */#ifndef CYGKLUDGEOFFSET#define CYGKLUDGEOFFSET 0#endifvoid mbx_update_header (MAILSTREAM *stream){  int i;  char *s = LOCAL->buf;  memset (s,'\0',HDRSIZE);	/* initialize header */  sprintf (s,"*mbx*\015\012%08lx%08lx\015\012",	   stream->uid_validity,stream->uid_last);  for (i = 0; (i < NUSERFLAGS) && stream->user_flags[i]; ++i)    sprintf (s += strlen (s),"%s\015\012",stream->user_flags[i]);  LOCAL->ffuserflag = i;	/* first free user flag */				/* can we create more user flags? */  stream->kwd_create = (i < NUSERFLAGS) ? T : NIL;				/* write reserved lines */  while (i++ < NUSERFLAGS) strcat (s,"\015\012");  sprintf (LOCAL->buf + HDRSIZE - 10,"%08lx\015\012",LOCAL->lastpid);  while (T) {			/* rewind file */    lseek (LOCAL->fd,CYGKLUDGEOFFSET,L_SET);				/* write new header */    if (write (LOCAL->fd,LOCAL->buf + CYGKLUDGEOFFSET,	       HDRSIZE - CYGKLUDGEOFFSET) > 0) break;    MM_NOTIFY (stream,strerror (errno),WARN);    MM_DISKERROR (stream,errno,T);  }}/* MBX update status string * Accepts: MAIL stream *	    message number *	    flags */void mbx_update_status (MAILSTREAM *stream,unsigned long msgno,long flags){  struct stat sbuf;  MESSAGECACHE *elt = mail_elt (stream,msgno);				/* readonly */  if (stream->rdonly || !elt->valid) mbx_read_flags (stream,elt);  else {			/* readwrite */    fstat (LOCAL->fd,&sbuf);	/* get status */				/* make sure file size is good */    if (sbuf.st_size < LOCAL->filesize) {      sprintf (LOCAL->buf,"Mailbox shrank from %lu to %lu in flag update!",	       (unsigned long) LOCAL->filesize,(unsigned long) sbuf.st_size);      fatal (LOCAL->buf);    }				/* set the seek pointer */    lseek (LOCAL->fd,(off_t) elt->private.special.offset +	   elt->private.special.text.size - 24,L_SET);				/* read the new flags */    if (read (LOCAL->fd,LOCAL->buf,14) < 0) {      sprintf (LOCAL->buf,"Unable to read old status: %s",strerror (errno));      fatal (LOCAL->buf);    }    if ((LOCAL->buf[0] != ';') || (LOCAL->buf[13] != '-')) {      LOCAL->buf[14] = '\0';	/* tie off buffer for error message */      sprintf (LOCAL->buf+50,"Invalid flags for message %lu (%lu %lu): %s",	       elt->msgno,elt->private.special.offset,	       elt->private.special.text.size,(char *) LOCAL->buf);      fatal (LOCAL->buf+50);    }				/* print new flag string */    sprintf (LOCAL->buf,"%08lx%04x-%08lx",elt->user_flags,(unsigned)	     (((elt->deleted && flags) ?	       fEXPUNGED : (strtoul (LOCAL->buf+9,NIL,16)) & fEXPUNGED) +	      (fSEEN * elt->seen) + (fDELETED * elt->deleted) +	      (fFLAGGED * elt->flagged) + (fANSWERED * elt->answered) +	      (fDRAFT * elt->draft) + fOLD),elt->private.uid);    while (T) {			/* get to that place in the file */      lseek (LOCAL->fd,(off_t) elt->private.special.offset +	     elt->private.special.text.size - 23,L_SET);				/* write new flags and UID */      if (write (LOCAL->fd,LOCAL->buf,21) > 0) break;      MM_NOTIFY (stream,strerror (errno),WARN);      MM_DISKERROR (stream,errno,T);    }  }}/* MBX locate header for a message * Accepts: MAIL stream *	    message number *	    pointer to returned header size *	    pointer to possible returned header * Returns: position of header in file */#define HDRBUFLEN 16384		/* good enough for most headers */#define SLOP 4			/* CR LF CR LF */unsigned long mbx_hdrpos (MAILSTREAM *stream,unsigned long msgno,			  unsigned long *size,char **hdr){  unsigned long siz,done;  long i;  unsigned char *s,*t,*te;  MESSAGECACHE *elt = mail_elt (stream,msgno);  unsigned long ret = elt->private.special.offset +    elt->private.special.text.size;  if (hdr) *hdr = NIL;		/* assume no header returned */				/* is header size known? */   if (*size = elt->private.msg.header.text.size) return ret;				/* paranoia check */  if (LOCAL->buflen < (HDRBUFLEN + SLOP))    fatal ("LOCAL->buf smaller than HDRBUFLEN");  lseek (LOCAL->fd,ret,L_SET);	/* get to header position */				/* read HDRBUFLEN chunks with 4 byte slop */  for (done = siz = 0, s = LOCAL->buf;       (i = min ((long) (elt->rfc822_size - done),(long) HDRBUFLEN)) &&       (read (LOCAL->fd,s,i) == i);       done += i, siz += (t - LOCAL->buf) - SLOP, s = LOCAL->buf + SLOP) {    te = (t = s + i) - 12;	/* calculate end of fast scan */				/* fast scan for CR */    for (s = LOCAL->buf; s < te;)      if (((*s++ == '\015') || (*s++ == '\015') || (*s++ == '\015') ||	   (*s++ == '\015') || (*s++ == '\015') || (*s++ == '\015') ||	   (*s++ == '\015') || (*s++ == '\015') || (*s++ == '\015') ||	   (*s++ == '\015') || (*s++ == '\015') || (*s++ == '\015')) &&	  (*s == '\012') && (*++s == '\015') && (*++s == '\012')) {	*size = elt->private.msg.header.text.size = siz + (++s - LOCAL->buf);	if (hdr) *hdr = LOCAL->buf;	return ret;      }    for (te = t - 3; (s < te);)	/* final character-at-a-time scan */      if ((*s++ == '\015') && (*s == '\012') && (*++s == '\015') &&	  (*++s == '\012')) {	*size = elt->private.msg.header.text.size = siz + (++s - LOCAL->buf);	if (hdr) *hdr = LOCAL->buf;	return ret;      }    if (i <= SLOP) break;	/* end of data */				/* slide over last 4 bytes */    memmove (LOCAL->buf,t - SLOP,SLOP);    hdr = NIL;			/* can't return header this way */  }				/* not found: header consumes entire message */  elt->private.msg.header.text.size = *size = elt->rfc822_size;  if (hdr) *hdr = LOCAL->buf;	/* possibly return header too */  return ret;}/* MBX mail rewrite mailbox * Accepts: MAIL stream *	    pointer to return reclaimed size *	    flags (0 = no expunge, 1 = expunge deleted, -1 = expunge sequence) * Returns: number of expunged messages */unsigned long mbx_rewrite (MAILSTREAM *stream,unsigned long *reclaimed,			   long flags){  time_t tp[2];  struct stat sbuf;  off_t pos,ppos;  int ld;  unsigned long i,j,k,m,delta;  unsigned long n = *reclaimed = 0;  unsigned long recent = 0;  char lock[MAILTMPLEN];  MESSAGECACHE *elt;  blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);  /* The cretins who designed flock() created a window of vulnerability in   * upgrading locks from shared to exclusive or downgrading from exclusive   * to shared.  Rather than maintain the lock at shared status at a minimum,   * flock() actually *releases* the former lock.  Obviously they never talked   * to any database guys.  Fortunately, we have the parse/append permission   * lock.  If we require this lock before going exclusive on the mailbox,   * another process can not sneak in and steal the exclusive mailbox lock on   * us, because it will block on trying to get parse/append permission first.   */				/* get parse/append permission */  if ((ld = lockfd (LOCAL->fd,lock,LOCK_EX)) < 0) {    MM_LOG ("Unable to lock mailbox for rewrite",ERROR);    return 0;  }  fstat (LOCAL->fd,&sbuf);	/* get current write time */  if (LOCAL->filetime && !LOCAL->flagcheck &&      (LOCAL->filetime < sbuf.st_mtime)) LOCAL->flagcheck = T;  if (!mbx_parse (stream)) {	/* make sure see any newly-arrived messages */    unlockfd (ld,lock);		/* failed?? */    return 0;  }  if (LOCAL->flagcheck) {	/* sweep flags if need flagcheck */    LOCAL->filetime = sbuf.st_mtime;    for (i = 1; i <= stream->nmsgs; ++i) mbx_elt (stream,i,NIL);    LOCAL->flagcheck = NIL;  }				/* get exclusive access */  if (!flock (LOCAL->fd,LOCK_EX|LOCK_NB)) {    MM_CRITICAL (stream);	/* go critical */    for (i = 1,delta = 0,pos = ppos = HDRSIZE; i <= stream->nmsgs; ) {				/* note if message not at predicted location */      if (m = (elt = mbx_elt (stream,i,NIL))->private.special.offset - ppos) {	ppos = elt->private.special.offset;	*reclaimed += m;	/* note reclaimed message space */	delta += m;		/* and as expunge delta  */      }				/* number of bytes to smash or preserve */      ppos += (k = elt->private.special.text.size + elt->rfc822_size);				/* if need to expunge this message*/      if (flags && elt->deleted && ((flags > 0) || elt->sequence)) {	delta += k;		/* number of bytes to delete */	mail_expunged(stream,i);/* notify upper levels */	n++;			/* count up one more expunged message */      }      else {			/* preserved message */	i++;			/* count this message */	if (elt->recent) ++recent;	if (delta) {		/* moved, note first byte to preserve */	  j = elt->private.special.offset;	  do {			/* read from source position */	    m = min (k,LOCAL->buflen);	    lseek (LOCAL->fd,j,L_SET);	    read (LOCAL->fd,LOCAL->buf,m);	    pos = j - delta;	/* write to destination position */	    while (T) {	      lseek (LOCAL->fd,pos,L_SET);	      if (write (LOCAL->fd,LOCAL->buf,m) > 0) break;	      MM_NOTIFY (stream,strerror (errno),WARN);	      MM_DISKERROR (stream,errno,T);	    }	    pos += m;		/* new position */	    j += m;		/* next chunk, perhaps */	  } while (k -= m);	/* until done */				/* note the new address of this text */	  elt->private.special.offset -= delta;	}				/* preserved but no deleted messages yet */	else pos = elt->private.special.offset + k;      }    }				/* deltaed file size match position? */    if (m = (LOCAL->filesize -= delta) - pos) {      *reclaimed += m;		/* probably an fEXPUNGED msg */      LOCAL->filesize = pos;	/* set correct size */    }				/* truncate file after last message */    ftruncate (LOCAL->fd,LOCAL->filesize);    fsync (LOCAL->fd);		/* force disk update */    MM_NOCRITICAL (stream);	/* release critical */    (*bn) (BLOCK_FILELOCK,NIL);    flock (LOCAL->fd,LOCK_SH);	/* allow sharers again */    (*bn) (BLOCK_NONE,NIL);  }  else {			/* can't get exclusive */    (*bn) (BLOCK_FILELOCK,NIL);    flock (LOCAL->fd,LOCK_SH);	/* recover previous shared mailbox lock */    (*bn) (BLOCK_NONE,NIL);				/* do hide-expunge when shared */    if (flags) for (i = 1; i <= stream->nmsgs; ) {      if (elt = mbx_elt (stream,i,T)) {				/* make the message invisible */	if (elt->deleted && ((flags > 0) || elt->sequence)) {	  mbx_update_status (stream,elt->msgno,LONGT);				/* notify upper levels */	  mail_expunged (stream,i);	  n++;			/* count up one more expunged message */	}	else {	  i++;			/* preserved message */	  if (elt->recent) ++recent;	}      }      else n++;			/* count up one more expunged message */    }    fsync (LOCAL->fd);		/* force disk update */  }  fstat (LOCAL->fd,&sbuf);	/* get new write time */  tp[1] = LOCAL->filetime = sbuf.st_mtime;  tp[0] = time (0);		/* reset atime to now */  utime (stream->mailbox,tp);  unlockfd (ld,lock);		/* release exclusive parse/append permission */				/* notify upper level of new mailbox size */  mail_exists (stream,stream->nmsgs);  mail_recent (stream,recent);  return n;			/* return number of expunged messages */}/* MBX mail lock for flag updating * Accepts: stream * Returns: T if successful, NIL if failure */long mbx_flaglock (MAILSTREAM *stream){  struct stat sbuf;  unsigned long i;  int ld;  char lock[MAILTMPLEN];				/* no-op if readonly or already locked */  if (!stream->rdonly && LOCAL && (LOCAL->fd >= 0) && (LOCAL->ld < 0)) {				/* lock now */    if ((ld = lockfd (LOCAL->fd,lock,LOCK_EX)) < 0) return NIL;    if (!LOCAL->flagcheck) {	/* don't do this if flagcheck already needed */      if (LOCAL->filetime) {	/* know previous time? */	fstat (LOCAL->fd,&sbuf);/* get current write time */	if (LOCAL->filetime < sbuf.st_mtime) LOCAL->flagcheck = T;	LOCAL->filetime = 0;	/* don't do this test for any other messages */      }      if (!mbx_parse (stream)) {/* parse mailbox */	unlockfd (ld,lock);	/* shouldn't happen */	return NIL;      }      if (LOCAL->flagcheck)	/* invalidate cache if flagcheck */	for (i = 1; i <= stream->nmsgs; ++i) mail_elt (stream,i)->valid = NIL;    }    LOCAL->ld = ld;		/* copy to stream for subsequent calls */    memcpy (LOCAL->lock,lock,MAILTMPLEN);  }  return LONGT;}

⌨️ 快捷键说明

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