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

📄 mtx.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 4 页
字号:
		   ",%lu;0000000000%02o\015\012",j,(unsigned)		   ((fSEEN * elt->seen) + (fDELETED * elt->deleted) +		    (fFLAGGED * elt->flagged) + (fANSWERED * elt->answered) +		    (fDRAFT * elt->draft)));				/* copy message */	  if ((write (LOCAL->fd,LOCAL->buf,strlen (LOCAL->buf)) < 0) ||	      (write (LOCAL->fd,hdr,hdrlen) < 0) ||	      (write (LOCAL->fd,txt,txtlen) < 0)) r = 0;	}	fs_give ((void **) &hdr);      }				/* make sure all the updates take */      if (fsync (LOCAL->fd)) r = 0;      if (r) {			/* delete all the messages we copied */	if (r == 1) strcpy (tmp,"1");	else sprintf (tmp,"1:%lu",r);	mail_flag (sysibx,tmp,"\\Deleted",ST_SET);	mail_expunge (sysibx);	/* now expunge all those messages */      }      else {	sprintf (LOCAL->buf,"Can't copy new mail: %s",strerror (errno));	MM_LOG (LOCAL->buf,WARN);	ftruncate (LOCAL->fd,sbuf.st_size);      }      fstat (LOCAL->fd,&sbuf);	/* yes, get current file size */      LOCAL->filetime = sbuf.st_mtime;    }    if (sysibx) mail_close (sysibx);    MM_NOCRITICAL (stream);	/* release critical */    unlockfd (ld,lock);		/* release exclusive parse/append permission */    LOCAL->lastsnarf = time (0);/* note time of last snarf */  }}/* MTX mail expunge mailbox * Accepts: MAIL stream *	    sequence to expunge if non-NIL *	    expunge options * Returns: T, always */long mtx_expunge (MAILSTREAM *stream,char *sequence,long options){  long ret;  time_t tp[2];  struct stat sbuf;  off_t pos = 0;  int ld;  unsigned long i = 1;  unsigned long j,k,m,recent;  unsigned long n = 0;  unsigned long delta = 0;  char lock[MAILTMPLEN];  MESSAGECACHE *elt;  blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);  if (!(ret = (sequence ? ((options & EX_UID) ?			   mail_uid_sequence (stream,sequence) :			   mail_sequence (stream,sequence)) : LONGT) &&	mtx_ping (stream)));	/* parse sequence if given, ping stream */  else if (stream->rdonly) MM_LOG ("Expunge ignored on readonly mailbox",WARN);  else {    if (LOCAL->filetime && !LOCAL->shouldcheck) {      fstat (LOCAL->fd,&sbuf);	/* get current write time */      if (LOCAL->filetime < sbuf.st_mtime) LOCAL->shouldcheck = T;    }  /* 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 exclusive parse/append permission */    if ((ld = lockfd (LOCAL->fd,lock,LOCK_EX)) < 0)      MM_LOG ("Unable to lock expunge mailbox",ERROR);				/* make sure see any newly-arrived messages */    else if (!mtx_parse (stream));				/* get exclusive access */    else if (flock (LOCAL->fd,LOCK_EX|LOCK_NB)) {      (*bn) (BLOCK_FILELOCK,NIL);      flock (LOCAL->fd,LOCK_SH);/* recover previous lock */      (*bn) (BLOCK_NONE,NIL);      MM_LOG ("Can't expunge because mailbox is in use by another process",	      ERROR);      unlockfd (ld,lock);	/* release exclusive parse/append permission */    }    else {      MM_CRITICAL (stream);	/* go critical */      recent = stream->recent;	/* get recent now that pinged and locked */				/* for each message */      while (i <= stream->nmsgs) {				/* get cache element */	elt = mtx_elt (stream,i);				/* number of bytes to smash or preserve */	k = elt->private.special.text.size + elt->rfc822_size;				/* if need to expunge this message */	if (elt->deleted && (sequence ? elt->sequence : T)) {				/* if recent, note one less recent message */	  if (elt->recent) --recent;	  delta += k;		/* number of bytes to delete */				/* notify upper levels */	  mail_expunged (stream,i);	  n++;			/* count up one more expunged message */	}	else if (i++ && delta) {/* preserved message */				/* 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 */	    lseek (LOCAL->fd,pos,L_SET);	    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 */	else pos = elt->private.special.offset + k;      }      if (n) {			/* truncate file after last message */	if (pos != (LOCAL->filesize -= delta)) {	  sprintf (LOCAL->buf,		   "Calculated size mismatch %lu != %lu, delta = %lu",		   (unsigned long) pos,(unsigned long) LOCAL->filesize,delta);	  MM_LOG (LOCAL->buf,WARN);	  LOCAL->filesize = pos;/* fix it then */	}	ftruncate (LOCAL->fd,LOCAL->filesize);	sprintf (LOCAL->buf,"Expunged %lu messages",n);				/* output the news */	MM_LOG (LOCAL->buf,(long) NIL);      }      else MM_LOG ("No messages deleted, so no update needed",(long) NIL);      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);      MM_NOCRITICAL (stream);	/* release critical */				/* notify upper level of new mailbox size */      mail_exists (stream,stream->nmsgs);      mail_recent (stream,recent);      (*bn) (BLOCK_FILELOCK,NIL);      flock (LOCAL->fd,LOCK_SH);/* allow sharers again */      (*bn) (BLOCK_NONE,NIL);      unlockfd (ld,lock);	/* release exclusive parse/append permission */    }  }  return ret;}/* MTX mail copy message(s) * Accepts: MAIL stream *	    sequence *	    destination mailbox *	    copy options * Returns: T if success, NIL if failed */long mtx_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options){  struct stat sbuf;  time_t tp[2];  MESSAGECACHE *elt;  unsigned long i,j,k;  long ret = LONGT;  int fd,ld;  char file[MAILTMPLEN],lock[MAILTMPLEN];  mailproxycopy_t pc =    (mailproxycopy_t) mail_parameters (stream,GET_MAILPROXYCOPY,NIL);				/* make sure valid mailbox */  if (!mtx_isvalid (mailbox,LOCAL->buf)) switch (errno) {  case ENOENT:			/* no such file? */    MM_NOTIFY (stream,"[TRYCREATE] Must create mailbox before copy",NIL);    return NIL;  case 0:			/* merely empty file? */    break;  case EACCES:			/* file protected */    sprintf (LOCAL->buf,"Can't access destination: %.80s",mailbox);    MM_LOG (LOCAL->buf,ERROR);    return NIL;  case EINVAL:    if (pc) return (*pc) (stream,sequence,mailbox,options);    sprintf (LOCAL->buf,"Invalid MTX-format mailbox name: %.80s",mailbox);    MM_LOG (LOCAL->buf,ERROR);    return NIL;  default:    if (pc) return (*pc) (stream,sequence,mailbox,options);    sprintf (LOCAL->buf,"Not a MTX-format mailbox: %.80s",mailbox);    MM_LOG (LOCAL->buf,ERROR);    return NIL;  }  if (!((options & CP_UID) ? mail_uid_sequence (stream,sequence) :	mail_sequence (stream,sequence))) return NIL;				/* got file? */    if ((fd = open (mtx_file (file,mailbox),O_RDWR,NIL)) < 0) {    sprintf (LOCAL->buf,"Unable to open copy mailbox: %s",strerror (errno));    MM_LOG (LOCAL->buf,ERROR);    return NIL;  }  MM_CRITICAL (stream);		/* go critical */				/* get exclusive parse/append permission */  if (flock (fd,LOCK_SH) || ((ld = lockfd (fd,lock,LOCK_EX)) < 0)) {    MM_LOG ("Unable to lock copy mailbox",ERROR);    MM_NOCRITICAL (stream);    return NIL;  }  fstat (fd,&sbuf);		/* get current file size */  lseek (fd,sbuf.st_size,L_SET);/* move to end of file */				/* for each requested message */  for (i = 1; ret && (i <= stream->nmsgs); i++)     if ((elt = mail_elt (stream,i))->sequence) {      lseek (LOCAL->fd,elt->private.special.offset,L_SET);				/* number of bytes to copy */      k = elt->private.special.text.size + elt->rfc822_size;      do {			/* read from source position */	j = min (k,LOCAL->buflen);	read (LOCAL->fd,LOCAL->buf,j);	if (write (fd,LOCAL->buf,j) < 0) ret = NIL;      } while (ret && (k -= j));/* until done */    }				/* make sure all the updates take */  if (!(ret && (ret = !fsync (fd)))) {    sprintf (LOCAL->buf,"Unable to write message: %s",strerror (errno));    MM_LOG (LOCAL->buf,ERROR);    ftruncate (fd,sbuf.st_size);  }  if (ret) tp[0] = time (0) - 1;/* set atime to now-1 if successful copy */				/* else preserve \Marked status */  else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0);  tp[1] = sbuf.st_mtime;	/* preserve mtime */  utime (file,tp);		/* set the times */  close (fd);			/* close the file */  unlockfd (ld,lock);		/* release exclusive parse/append permission */  MM_NOCRITICAL (stream);	/* release critical */				/* delete all requested messages */  if (ret && (options & CP_MOVE)) {    for (i = 1; i <= stream->nmsgs; i++)      if ((elt = mtx_elt (stream,i))->sequence) {	elt->deleted = T;	/* mark message deleted */				/* recalculate status */	mtx_update_status (stream,i,NIL);      }    if (!stream->rdonly) {	/* make sure the update takes */      fsync (LOCAL->fd);      fstat (LOCAL->fd,&sbuf);	/* get current write time */      tp[1] = LOCAL->filetime = sbuf.st_mtime;      tp[0] = time (0);		/* make sure atime remains greater */      utime (stream->mailbox,tp);    }  }  if (ret && mail_parameters (NIL,GET_COPYUID,NIL))    MM_LOG ("Can not return meaningful COPYUID with this mailbox format",WARN);  return ret;}/* MTX mail append message from stringstruct * Accepts: MAIL stream *	    destination mailbox *	    append callback *	    data for callback * Returns: T if append successful, else NIL */long mtx_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data){  struct stat sbuf;  int fd,ld,c;  char *flags,*date,tmp[MAILTMPLEN],file[MAILTMPLEN],lock[MAILTMPLEN];  time_t tp[2];  FILE *df;  MESSAGECACHE elt;  long f;  unsigned long i,uf;  STRING *message;  long ret = LONGT;				/* default stream to prototype */  if (!stream) stream = user_flags (&mtxproto);				/* make sure valid mailbox */  if (!mtx_isvalid (mailbox,tmp)) switch (errno) {  case ENOENT:			/* no such file? */    if (!compare_cstring (mailbox,"INBOX")) dummy_create (NIL,"INBOX.MTX");    else {      MM_NOTIFY (stream,"[TRYCREATE] Must create mailbox before append",NIL);      return NIL;    }				/* falls through */  case 0:			/* merely empty file? */    break;  case EACCES:			/* file protected */    sprintf (tmp,"Can't access destination: %.80s",mailbox);    MM_LOG (tmp,ERROR);    return NIL;  case EINVAL:    sprintf (tmp,"Invalid MTX-format mailbox name: %.80s",mailbox);    MM_LOG (tmp,ERROR);    return NIL;  default:    sprintf (tmp,"Not a MTX-format mailbox: %.80s",mailbox);    MM_LOG (tmp,ERROR);    return NIL;  }				/* get first message */  if (!MM_APPEND (af) (stream,data,&flags,&date,&message)) return NIL;				/* open destination mailbox */  if (((fd = open (mtx_file (file,mailbox),O_WRONLY|O_APPEND,NIL)) < 0) ||      !(df = fdopen (fd,"ab"))) {    sprintf (tmp,"Can't open append mailbox: %s",strerror (errno));    MM_LOG (tmp,ERROR);    return NIL;  }				/* get parse/append permission */  if (flock (fd,LOCK_SH) || ((ld = lockfd (fd,lock,LOCK_EX)) < 0)) {    MM_LOG ("Unable to lock append mailbox",ERROR);    close (fd);    return NIL;  }  MM_CRITICAL (stream);		/* go critical */  fstat (fd,&sbuf);		/* get current file size */  errno = 0;  do {				/* parse flags */    if (!SIZE (message)) {	/* guard against zero-length */      MM_LOG ("Append of zero-length message",ERROR);      ret = NIL;      break;    }    f = mail_parse_flags (stream,flags,&i);				/* reverse bits (dontcha wish we had CIRC?) */

⌨️ 快捷键说明

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