static gint mh_remove_msgs(Folder *folder, FolderItem *item, MsgInfoList *msglist, GHashTable *relation) { gboolean need_scan = FALSE; gchar *path, *file; time_t last_mtime = (time_t)0; MsgInfoList *cur; gint total = 0, curnum = 0; cm_return_val_if_fail(item != NULL, -1); path = folder_item_get_path(item); need_scan = mh_scan_required(folder, item); last_mtime = item->mtime; total = g_slist_length(msglist); if (total > 100) { statusbar_print_all(_("Deleting messages...")); } for (cur = msglist; cur; cur = cur->next) { MsgInfo *msginfo = (MsgInfo *)cur->data; if (msginfo == NULL) continue; if (MSG_IS_MOVE(msginfo->flags) && MSG_IS_MOVE_DONE(msginfo->flags)) { msginfo->flags.tmp_flags &= ~MSG_MOVE_DONE; continue; } if (total > 100) { statusbar_progress_all(curnum, total, 100); if (curnum % 100 == 0) GTK_EVENTS_FLUSH(); curnum++; } file = g_strconcat(path, G_DIR_SEPARATOR_S, itos(msginfo->msgnum), NULL); if (file == NULL) continue; if (claws_unlink(file) < 0) { g_free(file); continue; } g_free(file); } if (total > 100) { statusbar_progress_all(0,0,0); statusbar_pop_all(); } if (item->mtime == last_mtime && !need_scan) { mh_set_mtime(folder, item); } g_free(path); return 0; }
static void send_cancel_button_cb(GtkWidget *widget, gpointer data) { SendProgressDialog *dialog = (SendProgressDialog *)data; statusbar_progress_all(0,0,0); dialog->cancelled = TRUE; }
static gboolean gtk_message_callback(gpointer data) { BsCbData *cbdata = (BsCbData *)data; if (cbdata->message) statusbar_print_all("%s", cbdata->message); else if (cbdata->total == 0) { statusbar_pop_all(); } if (cbdata->total && cbdata->done) statusbar_progress_all(cbdata->done, cbdata->total, 10); else statusbar_progress_all(0,0,0); g_free(cbdata->message); g_free(cbdata); GTK_EVENTS_FLUSH(); return FALSE; }
static gint mh_copy_msgs(Folder *folder, FolderItem *dest, MsgInfoList *msglist, GHashTable *relation) { gboolean dest_need_scan = FALSE; gboolean src_need_scan = FALSE; FolderItem *src = NULL; gchar *srcfile; gchar *destfile; FolderItemPrefs *prefs; MsgInfo *msginfo = NULL; MsgInfoList *cur = NULL; gint curnum = 0, total = 0; gchar *srcpath = NULL; gboolean full_fetch = FALSE; time_t last_dest_mtime = (time_t)0; time_t last_src_mtime = (time_t)0; cm_return_val_if_fail(dest != NULL, -1); cm_return_val_if_fail(msglist != NULL, -1); msginfo = (MsgInfo *)msglist->data; cm_return_val_if_fail(msginfo != NULL, -1); if (msginfo->folder == dest) { g_warning("the src folder is identical to the dest.\n"); return -1; } if (msginfo->folder->folder != dest->folder) full_fetch = TRUE; if (FOLDER_TYPE(msginfo->folder->folder) == F_MH) { src = msginfo->folder; } if (dest->last_num < 0) { mh_get_last_num(folder, dest); if (dest->last_num < 0) return -1; } prefs = dest->prefs; srcpath = folder_item_get_path(msginfo->folder); dest_need_scan = mh_scan_required(dest->folder, dest); last_dest_mtime = dest->mtime; if (src) { src_need_scan = mh_scan_required(src->folder, src); last_src_mtime = src->mtime; } total = g_slist_length(msglist); if (total > 100) { if (MSG_IS_MOVE(msginfo->flags)) statusbar_print_all(_("Moving messages...")); else statusbar_print_all(_("Copying messages...")); } for (cur = msglist; cur; cur = cur->next) { msginfo = (MsgInfo *)cur->data; if (!msginfo) { goto err_reset_status; } if (!full_fetch) { srcfile = g_strconcat(srcpath, G_DIR_SEPARATOR_S, itos(msginfo->msgnum), NULL); } else { srcfile = procmsg_get_message_file(msginfo); } if (!srcfile) { goto err_reset_status; } destfile = mh_get_new_msg_filename(dest); if (!destfile) { g_free(srcfile); goto err_reset_status; } if (total > 100) { statusbar_progress_all(curnum, total, 100); if (curnum % 100 == 0) GTK_EVENTS_FLUSH(); curnum++; } debug_print("Copying message %s%c%d to %s ...\n", msginfo->folder->path, G_DIR_SEPARATOR, msginfo->msgnum, dest->path); if (MSG_IS_MOVE(msginfo->flags)) { msginfo->flags.tmp_flags &= ~MSG_MOVE_DONE; if (move_file(srcfile, destfile, TRUE) < 0) { FILE_OP_ERROR(srcfile, "move"); if (copy_file(srcfile, destfile, TRUE) < 0) { FILE_OP_ERROR(srcfile, "copy"); g_free(srcfile); g_free(destfile); goto err_reset_status; } } else { /* say unlinking's not necessary */ msginfo->flags.tmp_flags |= MSG_MOVE_DONE; } } else if (copy_file(srcfile, destfile, TRUE) < 0) { FILE_OP_ERROR(srcfile, "copy"); g_free(srcfile); g_free(destfile); goto err_reset_status; } if (prefs && prefs->enable_folder_chmod && prefs->folder_chmod) { if (chmod(destfile, prefs->folder_chmod) < 0) FILE_OP_ERROR(destfile, "chmod"); } if (relation) { if (g_hash_table_lookup(relation, msginfo) != NULL) g_warning("already in : %p", msginfo); g_hash_table_insert(relation, msginfo, GINT_TO_POINTER(dest->last_num+1)); } g_free(srcfile); g_free(destfile); dest->last_num++; } g_free(srcpath); mh_write_sequences(dest, TRUE); if (dest->mtime == last_dest_mtime && !dest_need_scan) { mh_set_mtime(folder, dest); } if (src && src->mtime == last_src_mtime && !src_need_scan) { mh_set_mtime(folder, src); } if (total > 100) { statusbar_progress_all(0,0,0); statusbar_pop_all(); } return dest->last_num; err_reset_status: g_free(srcpath); mh_write_sequences(dest, TRUE); if (total > 100) { statusbar_progress_all(0,0,0); statusbar_pop_all(); } return -1; }
gint lock_mbox(const gchar *base, LockType type) { #ifdef G_OS_UNIX gint retval = 0; if (type == LOCK_FILE) { gchar *lockfile, *locklink; gint retry = 0; FILE *lockfp; lockfile = g_strdup_printf("%s.%d", base, getpid()); if ((lockfp = g_fopen(lockfile, "wb")) == NULL) { FILE_OP_ERROR(lockfile, "fopen"); g_warning("can't create lock file %s\n", lockfile); g_warning("use 'flock' instead of 'file' if possible.\n"); g_free(lockfile); return -1; } if (fprintf(lockfp, "%d\n", getpid()) < 0) { FILE_OP_ERROR(lockfile, "fprintf"); g_free(lockfile); fclose(lockfp); return -1; } if (fclose(lockfp) == EOF) { FILE_OP_ERROR(lockfile, "fclose"); g_free(lockfile); return -1; } locklink = g_strconcat(base, ".lock", NULL); while (link(lockfile, locklink) < 0) { FILE_OP_ERROR(lockfile, "link"); if (retry >= 5) { g_warning("can't create %s\n", lockfile); claws_unlink(lockfile); g_free(lockfile); return -1; } if (retry == 0) g_warning("mailbox is owned by another" " process, waiting...\n"); retry++; sleep(5); } claws_unlink(lockfile); g_free(lockfile); } else if (type == LOCK_FLOCK) { gint lockfd; gboolean fcntled = FALSE; #if HAVE_FCNTL_H && !defined(G_OS_WIN32) struct flock fl; fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; #endif #if HAVE_FLOCK if ((lockfd = g_open(base, O_RDWR, 0)) < 0) { #else if ((lockfd = g_open(base, O_RDWR, 0)) < 0) { #endif FILE_OP_ERROR(base, "open"); return -1; } #if HAVE_FCNTL_H && !defined(G_OS_WIN32) if (fcntl(lockfd, F_SETLK, &fl) == -1) { g_warning("can't fnctl %s (%s)", base, strerror(errno)); return -1; } else { fcntled = TRUE; } #endif #if HAVE_FLOCK if (flock(lockfd, LOCK_EX|LOCK_NB) < 0 && !fcntled) { perror("flock"); #else #if HAVE_LOCKF if (lockf(lockfd, F_TLOCK, 0) < 0 && !fcntled) { perror("lockf"); #else { #endif #endif /* HAVE_FLOCK */ g_warning("can't lock %s\n", base); if (close(lockfd) < 0) perror("close"); return -1; } retval = lockfd; } else { g_warning("invalid lock type\n"); return -1; } return retval; #else return -1; #endif /* G_OS_UNIX */ } gint unlock_mbox(const gchar *base, gint fd, LockType type) { if (type == LOCK_FILE) { gchar *lockfile; lockfile = g_strconcat(base, ".lock", NULL); if (claws_unlink(lockfile) < 0) { FILE_OP_ERROR(lockfile, "unlink"); g_free(lockfile); return -1; } g_free(lockfile); return 0; } else if (type == LOCK_FLOCK) { gboolean fcntled = FALSE; #if HAVE_FCNTL_H && !defined(G_OS_WIN32) struct flock fl; fl.l_type = F_UNLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; if (fcntl(fd, F_SETLK, &fl) == -1) { g_warning("can't fnctl %s", base); } else { fcntled = TRUE; } #endif #if HAVE_FLOCK if (flock(fd, LOCK_UN) < 0 && !fcntled) { perror("flock"); #else #if HAVE_LOCKF if (lockf(fd, F_ULOCK, 0) < 0 && !fcntled) { perror("lockf"); #else { #endif #endif /* HAVE_FLOCK */ g_warning("can't unlock %s\n", base); if (close(fd) < 0) perror("close"); return -1; } if (close(fd) < 0) { perror("close"); return -1; } return 0; } g_warning("invalid lock type\n"); return -1; } gint copy_mbox(gint srcfd, const gchar *dest) { FILE *dest_fp; ssize_t n_read; gchar buf[BUFSIZ]; gboolean err = FALSE; int save_errno = 0; if (srcfd < 0) { return -1; } if ((dest_fp = g_fopen(dest, "wb")) == NULL) { FILE_OP_ERROR(dest, "fopen"); return -1; } if (change_file_mode_rw(dest_fp, dest) < 0) { FILE_OP_ERROR(dest, "chmod"); g_warning("can't change file mode\n"); } while ((n_read = read(srcfd, buf, sizeof(buf))) > 0) { if (n_read == -1 && errno != 0) { save_errno = errno; break; } if (fwrite(buf, 1, n_read, dest_fp) < n_read) { g_warning("writing to %s failed.\n", dest); fclose(dest_fp); claws_unlink(dest); return -1; } } if (save_errno != 0) { g_warning("error %d reading mbox: %s\n", save_errno, strerror(save_errno)); err = TRUE; } if (fclose(dest_fp) == EOF) { FILE_OP_ERROR(dest, "fclose"); err = TRUE; } if (err) { claws_unlink(dest); return -1; } return 0; } void empty_mbox(const gchar *mbox) { FILE *fp; if ((fp = g_fopen(mbox, "wb")) == NULL) { FILE_OP_ERROR(mbox, "fopen"); g_warning("can't truncate mailbox to zero.\n"); return; } fclose(fp); } gint export_list_to_mbox(GSList *mlist, const gchar *mbox) /* return values: -2 skipped, -1 error, 0 OK */ { GSList *cur; MsgInfo *msginfo; FILE *msg_fp; FILE *mbox_fp; gchar buf[BUFFSIZE]; int err = 0; gint msgs = 1, total = g_slist_length(mlist); if (g_file_test(mbox, G_FILE_TEST_EXISTS) == TRUE) { if (alertpanel_full(_("Overwrite mbox file"), _("This file already exists. Do you want to overwrite it?"), GTK_STOCK_CANCEL, _("Overwrite"), NULL, FALSE, NULL, ALERT_WARNING, G_ALERTDEFAULT) != G_ALERTALTERNATE) { return -2; } } if ((mbox_fp = g_fopen(mbox, "wb")) == NULL) { FILE_OP_ERROR(mbox, "fopen"); alertpanel_error(_("Could not create mbox file:\n%s\n"), mbox); return -1; } #ifdef HAVE_FGETS_UNLOCKED flockfile(mbox_fp); #endif statuswindow_print_all(_("Exporting to mbox...")); for (cur = mlist; cur != NULL; cur = cur->next) { int len; gchar buft[BUFFSIZE]; msginfo = (MsgInfo *)cur->data; msg_fp = procmsg_open_message(msginfo); if (!msg_fp) { continue; } #ifdef HAVE_FGETS_UNLOCKED flockfile(msg_fp); #endif strncpy2(buf, msginfo->from ? msginfo->from : cur_account && cur_account->address ? cur_account->address : "unknown", sizeof(buf)); extract_address(buf); if (fprintf(mbox_fp, "From %s %s", buf, ctime_r(&msginfo->date_t, buft)) < 0) { err = -1; #ifdef HAVE_FGETS_UNLOCKED funlockfile(msg_fp); #endif fclose(msg_fp); goto out; } buf[0] = '\0'; /* write email to mboxrc */ while (SC_FGETS(buf, sizeof(buf), msg_fp) != NULL) { /* quote any From, >From, >>From, etc., according to mbox format specs */ int offset; offset = 0; /* detect leading '>' char(s) */ while ((buf[offset] == '>')) { offset++; } if (!strncmp(buf+offset, "From ", 5)) { if (SC_FPUTC('>', mbox_fp) == EOF) { err = -1; #ifdef HAVE_FGETS_UNLOCKED funlockfile(msg_fp); #endif fclose(msg_fp); goto out; } } if (SC_FPUTS(buf, mbox_fp) == EOF) { err = -1; #ifdef HAVE_FGETS_UNLOCKED funlockfile(msg_fp); #endif fclose(msg_fp); goto out; } } /* force last line to end w/ a newline */ len = strlen(buf); if (len > 0) { len--; if ((buf[len] != '\n') && (buf[len] != '\r')) { if (SC_FPUTC('\n', mbox_fp) == EOF) { err = -1; #ifdef HAVE_FGETS_UNLOCKED funlockfile(msg_fp); #endif fclose(msg_fp); goto out; } } } /* add a trailing empty line */ if (SC_FPUTC('\n', mbox_fp) == EOF) { err = -1; #ifdef HAVE_FGETS_UNLOCKED funlockfile(msg_fp); #endif fclose(msg_fp); goto out; } #ifdef HAVE_FGETS_UNLOCKED funlockfile(msg_fp); #endif fclose(msg_fp); statusbar_progress_all(msgs++,total, 500); if (msgs%500 == 0) GTK_EVENTS_FLUSH(); } out: statusbar_progress_all(0,0,0); statuswindow_pop_all(); #ifdef HAVE_FGETS_UNLOCKED funlockfile(mbox_fp); #endif fclose(mbox_fp); return err; }