📄 mh.c
字号:
maildir_move_to_context (ctx, &md); return 0;}/* read a maildir style mailbox */int maildir_read_dir (CONTEXT * ctx){ /* maildir looks sort of like MH, except that there are two subdirectories * of the main folder path from which to read messages */ if (mh_read_dir (ctx, "new") == -1 || mh_read_dir (ctx, "cur") == -1) return (-1); return 0;}/* * Open a new (temporary) message in an MH folder. */int mh_open_new_message (MESSAGE * msg, CONTEXT * dest, HEADER * hdr){ return mh_mkstemp (dest, &msg->fp, &msg->path);}int ch_compar (const void *a, const void *b){ return (int)( *((const char *) a) - *((const char *) b));}static void maildir_flags (char *dest, size_t destlen, HEADER * hdr){ *dest = '\0'; /* * The maildir specification requires that all files in the cur * subdirectory have the :unique string appeneded, regardless of whether * or not there are any flags. If .old is set, we know that this message * will end up in the cur directory, so we include it in the following * test even though there is no associated flag. */ if (hdr && (hdr->flagged || hdr->replied || hdr->read || hdr->deleted || hdr->old || hdr->maildir_flags)) { char tmp[LONG_STRING]; snprintf (tmp, sizeof (tmp), "%s%s%s%s%s", hdr->flagged ? "F" : "", hdr->replied ? "R" : "", hdr->read ? "S" : "", hdr->deleted ? "T" : "", NONULL(hdr->maildir_flags)); if (hdr->maildir_flags) qsort (tmp, strlen (tmp), 1, ch_compar); snprintf (dest, destlen, ":2,%s", tmp); }}/* * Open a new (temporary) message in a maildir folder. * * Note that this uses _almost_ the maildir file name format, but * with a {cur,new} prefix. * */int maildir_open_new_message (MESSAGE * msg, CONTEXT * dest, HEADER * hdr){ int fd; char path[_POSIX_PATH_MAX]; char suffix[16]; char subdir[16]; if (hdr) { short deleted = hdr->deleted; hdr->deleted = 0; maildir_flags (suffix, sizeof (suffix), hdr); hdr->deleted = deleted; } else *suffix = '\0'; if (hdr && (hdr->read || hdr->old)) strfcpy (subdir, "cur", sizeof (subdir)); else strfcpy (subdir, "new", sizeof (subdir)); FOREVER { snprintf (path, _POSIX_PATH_MAX, "%s/tmp/%s.%ld.%u_%d.%s%s", dest->path, subdir, time (NULL), (unsigned int)getpid (), Counter++, NONULL (Hostname), suffix); dprint (2, (debugfile, "maildir_open_new_message (): Trying %s.\n", path)); if ((fd = open (path, O_WRONLY | O_EXCL | O_CREAT, 0600)) == -1) { if (errno != EEXIST) { mutt_perror (path); return -1; } } else { dprint (2, (debugfile, "maildir_open_new_message (): Success.\n")); msg->path = safe_strdup (path); break; } } if ((msg->fp = fdopen (fd, "w")) == NULL) { FREE (&msg->path); close (fd); unlink (path); return (-1); } return 0;}/* * Commit a message to a maildir folder. * * msg->path contains the file name of a file in tmp/. We take the * flags from this file's name. * * ctx is the mail folder we commit to. * * hdr is a header structure to which we write the message's new * file name. This is used in the mh and maildir folder synch * routines. When this routine is invoked from mx_commit_message, * hdr is NULL. * * msg->path looks like this: * * tmp/{cur,new}.mutt-HOSTNAME-PID-COUNTER:flags * * See also maildir_open_new_message(). * */int maildir_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr){ char subdir[4]; char suffix[16]; char path[_POSIX_PATH_MAX]; char full[_POSIX_PATH_MAX]; char *s; if (safe_fclose (&msg->fp) != 0) return -1; /* extract the subdir */ s = strrchr (msg->path, '/') + 1; strfcpy (subdir, s, 4); /* extract the flags */ if ((s = strchr (s, ':'))) strfcpy (suffix, s, sizeof (suffix)); else suffix[0] = '\0'; /* construct a new file name. */ FOREVER { snprintf (path, _POSIX_PATH_MAX, "%s/%ld.%u_%d.%s%s", subdir, time (NULL), (unsigned int)getpid (), Counter++, NONULL (Hostname), suffix); snprintf (full, _POSIX_PATH_MAX, "%s/%s", ctx->path, path); dprint (2, (debugfile, "maildir_commit_message (): renaming %s to %s.\n", msg->path, full)); if (safe_rename (msg->path, full) == 0) { if (hdr) mutt_str_replace (&hdr->path, path); FREE (&msg->path); /* * Adjust the mtime on the file to match the time at which this * message was received. Currently this is only set when copying * messages between mailboxes, so we test to ensure that it is * actually set. */ if (msg->received) { struct utimbuf ut; ut.actime = msg->received; ut.modtime = msg->received; if (utime (full, &ut)) { mutt_perror (_("maildir_commit_message(): unable to set time on file")); return -1; } } return 0; } else if (errno != EEXIST) { mutt_perror (ctx->path); return -1; } }}/* * commit a message to an MH folder. * */static int _mh_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr, short updseq){ DIR *dirp; struct dirent *de; char *cp, *dep; unsigned int n, hi = 0; char path[_POSIX_PATH_MAX]; char tmp[16]; if (safe_fclose (&msg->fp) != 0) return -1; if ((dirp = opendir (ctx->path)) == NULL) { mutt_perror (ctx->path); return (-1); } /* figure out what the next message number is */ while ((de = readdir (dirp)) != NULL) { dep = de->d_name; if (*dep == ',') dep++; cp = dep; while (*cp) { if (!isdigit ((unsigned char) *cp)) break; cp++; } if (!*cp) { n = atoi (dep); if (n > hi) hi = n; } } closedir (dirp); /* * Now try to rename the file to the proper name. * * Note: We may have to try multiple times, until we find a free * slot. */ FOREVER { hi++; snprintf (tmp, sizeof (tmp), "%d", hi); snprintf (path, sizeof (path), "%s/%s", ctx->path, tmp); if (safe_rename (msg->path, path) == 0) { if (hdr) mutt_str_replace (&hdr->path, tmp); FREE (&msg->path); break; } else if (errno != EEXIST) { mutt_perror (ctx->path); return -1; } } if (updseq) mh_sequences_add_one (ctx, hi, !msg->flags.read, msg->flags.flagged, msg->flags.replied); return 0;}int mh_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr){ return _mh_commit_message (ctx, msg, hdr, 1);}/* Sync a message in an MH folder. * * This code is also used for attachment deletion in maildir * folders. */static int mh_rewrite_message (CONTEXT * ctx, int msgno){ HEADER *h = ctx->hdrs[msgno]; MESSAGE *dest; int rc; short restore = 1; char oldpath[_POSIX_PATH_MAX]; char newpath[_POSIX_PATH_MAX]; char partpath[_POSIX_PATH_MAX]; long old_body_offset = h->content->offset; long old_body_length = h->content->length; long old_hdr_lines = h->lines; if ((dest = mx_open_new_message (ctx, h, 0)) == NULL) return -1; if ((rc = mutt_copy_message (dest->fp, ctx, h, M_CM_UPDATE, CH_UPDATE | CH_UPDATE_LEN)) == 0) { snprintf (oldpath, _POSIX_PATH_MAX, "%s/%s", ctx->path, h->path); strfcpy (partpath, h->path, _POSIX_PATH_MAX); if (ctx->magic == M_MAILDIR) rc = maildir_commit_message (ctx, dest, h); else rc = _mh_commit_message (ctx, dest, h, 0); mx_close_message (&dest); if (rc == 0) { unlink (oldpath); restore = 0; } /* * Try to move the new message to the old place. * (MH only.) * * This is important when we are just updating flags. * * Note that there is a race condition against programs which * use the first free slot instead of the maximum message * number. Mutt does _not_ behave like this. * * Anyway, if this fails, the message is in the folder, so * all what happens is that a concurrently runnung mutt will * lose flag modifications. */ if (ctx->magic == M_MH && rc == 0) { snprintf (newpath, _POSIX_PATH_MAX, "%s/%s", ctx->path, h->path); if ((rc = safe_rename (newpath, oldpath)) == 0) mutt_str_replace (&h->path, partpath); } } else mx_close_message (&dest); if (rc == -1 && restore) { h->content->offset = old_body_offset; h->content->length = old_body_length; h->lines = old_hdr_lines; } mutt_free_body (&h->content->parts); return rc;}static int mh_sync_message (CONTEXT * ctx, int msgno){ HEADER *h = ctx->hdrs[msgno]; if (h->attach_del || (h->env && (h->env->refs_changed || h->env->irt_changed))) if (mh_rewrite_message (ctx, msgno) != 0) return -1; return 0;}static int maildir_sync_message (CONTEXT * ctx, int msgno){ HEADER *h = ctx->hdrs[msgno]; if (h->attach_del || (h->env && (h->env->refs_changed || h->env->irt_changed))) { /* when doing attachment deletion/rethreading, fall back to the MH case. */ if (mh_rewrite_message (ctx, msgno) != 0) return (-1); } else { /* we just have to rename the file. */ char newpath[_POSIX_PATH_MAX]; char partpath[_POSIX_PATH_MAX]; char fullpath[_POSIX_PATH_MAX]; char oldpath[_POSIX_PATH_MAX]; char suffix[16]; char *p; if ((p = strrchr (h->path, '/')) == NULL) { dprint (1, (debugfile, "maildir_sync_message: %s: unable to find subdir!\n", h->path)); return (-1); } p++; strfcpy (newpath, p, sizeof (newpath)); /* kill the previous flags */ if ((p = strchr (newpath, ':')) != NULL) *p = 0; maildir_flags (suffix, sizeof (suffix), h); snprintf (partpath, sizeof (partpath), "%s/%s%s", (h->read || h->old) ? "cur" : "new", newpath, suffix); snprintf (fullpath, sizeof (fullpath), "%s/%s", ctx->path, partpath); snprintf (oldpath, sizeof (oldpath), "%s/%s", ctx->path, h->path); if (mutt_strcmp (fullpath, oldpath) == 0) { /* message hasn't really changed */ return 0; } /* record that the message is possibly marked as trashed on disk */ h->trash = h->deleted; if (rename (oldpath, fullpath) != 0) { mutt_perror ("rename"); return (-1); } mutt_str_replace (&h->path, partpath); } return (0);}int mh_sync_mailbox (CONTEXT * ctx, int *index_hint){ char path[_POSIX_PATH_MAX], tmp[_POSIX_PATH_MAX]; int i, j;#if USE_HCACHE header_cache_t *hc = NULL;#endif /* USE_HCACHE */ if (ctx->magic == M_MH) i = mh_check_mailbox (ctx, index_hint); else i = maildir_check_mailbox (ctx, index_hint); if (i != 0) return i;#if USE_HCACHE if (ctx->magic == M_MAILDIR || ctx->magic == M_MH) hc = mutt_hcache_open(HeaderCache, ctx->path);#endif /* USE_HCACHE */ for (i = 0; i < ctx->msgcount; i++) { if (ctx->hdrs[i]->deleted && (ctx->magic != M_MAILDIR || !option (OPTMAILDIRTRASH))) { snprintf (path, sizeof (path), "%s/%s", ctx->path, ctx->hdrs[i]->path); if (ctx->magic == M_MAILDIR || (option (OPTMHPURGE) && ctx->magic == M_MH)) {#if USE_HCACHE if (ctx->magic == M_MAILDIR) mutt_hcache_delete (hc, ctx->hdrs[i]->path + 3, &maildir_hcache_keylen); else if (ctx->magic == M_MH) mutt_hcache_delete (hc, ctx->hdrs[i]->path, strlen);#endif /* USE_HCACHE */ unlink (path); } else if (ctx->magic == M_MH) { /* MH just moves files out of the way when you delete them */ if (*ctx->hdrs[i]->path != ',') { snprintf (tmp, sizeof (tmp), "%s/,%s", ctx->path, ctx->hdrs[i]->path); unlink (tmp); rename (path, tmp); } } } else if (ctx->hdrs[i]->changed || ctx->hdrs[i]->attach_del || (ctx->magic == M_MAILDIR && (option (OPTMAILDIRTRASH) || ctx->hdrs[i]->trash) && (ctx->hdrs[i]->deleted != ctx->hdrs[i]->trash))) { if (ctx->magic == M_MAILDIR) { if (maildir_sync_message (ctx, i) == -1) goto err; } else { if (mh_sync_message (ctx, i) == -1) goto err; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -