NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
compress.c File Reference

Compressed mbox local mailbox type. More...

#include "config.h"
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "lib.h"
#include "format_flags.h"
#include "hook.h"
#include "mutt_commands.h"
#include "mutt_globals.h"
#include "muttlib.h"
#include "mx.h"
#include "protos.h"
+ Include dependency graph for compress.c:

Go to the source code of this file.

Functions

void mutt_comp_init (void)
 Setup feature commands. More...
 
static bool lock_realpath (struct Mailbox *m, bool excl)
 Try to lock the ctx->realpath. More...
 
static void unlock_realpath (struct Mailbox *m)
 Unlock the mailbox->realpath. More...
 
static int setup_paths (struct Mailbox *m)
 Set the mailbox paths. More...
 
static void store_size (const struct Mailbox *m)
 Save the size of the compressed file. More...
 
static struct CompressInfoset_compress_info (struct Mailbox *m)
 Find the compress hooks for a mailbox. More...
 
static void compress_info_free (struct Mailbox *m)
 Frees the compress info members and structure. More...
 
static const char * compress_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Expand the filenames in a command string - Implements format_t -
Expando Description
%f Compressed file
%t Plaintext, temporary file
More...
 
static void expand_command_str (const struct Mailbox *m, const char *cmd, char *buf, int buflen)
 Expand placeholders in command string. More...
 
static int execute_command (struct Mailbox *m, const char *command, const char *progress)
 Run a system command. More...
 
bool mutt_comp_can_append (struct Mailbox *m)
 Can we append to this path? More...
 
bool mutt_comp_can_read (const char *path)
 Can we read from this file? More...
 
int mutt_comp_valid_command (const char *cmd)
 Is this command string allowed? More...
 
static bool comp_ac_owns_path (struct Account *a, const char *path)
 Check whether an Account owns a Mailbox path - Implements MxOps::ac_owns_path() -. More...
 
static bool comp_ac_add (struct Account *a, struct Mailbox *m)
 Add a Mailbox to an Account - Implements MxOps::ac_add() -. More...
 
static enum MxOpenReturns comp_mbox_open (struct Mailbox *m)
 Open a Mailbox - Implements MxOps::mbox_open() -Set up a compressed mailbox to be read. More...
 
static bool comp_mbox_open_append (struct Mailbox *m, OpenMailboxFlags flags)
 Open a Mailbox for appending - Implements MxOps::mbox_open_append() -flags may also contain MUTT_NEWFOLDER. More...
 
static enum MxStatus comp_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
static enum MxStatus comp_mbox_sync (struct Mailbox *m)
 Save changes to the Mailbox - Implements MxOps::mbox_sync() -Changes in NeoMutt only affect the tmp file. More...
 
static enum MxStatus comp_mbox_close (struct Mailbox *m)
 Close a Mailbox - Implements MxOps::mbox_close() -If the mailbox has been changed then re-compress the tmp file. More...
 
static bool comp_msg_open (struct Mailbox *m, struct Message *msg, int msgno)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -. More...
 
static bool comp_msg_open_new (struct Mailbox *m, struct Message *msg, const struct Email *e)
 Open a new message in a Mailbox - Implements MxOps::msg_open_new() -. More...
 
static int comp_msg_commit (struct Mailbox *m, struct Message *msg)
 Save changes to an email - Implements MxOps::msg_commit() -. More...
 
static int comp_msg_close (struct Mailbox *m, struct Message *msg)
 Close an email - Implements MxOps::msg_close() -. More...
 
static int comp_msg_padding_size (struct Mailbox *m)
 Bytes of padding between messages - Implements MxOps::msg_padding_size() -. More...
 
static int comp_msg_save_hcache (struct Mailbox *m, struct Email *e)
 Save message to the header cache - Implements MxOps::msg_save_hcache() -. More...
 
static int comp_tags_edit (struct Mailbox *m, const char *tags, char *buf, size_t buflen)
 Prompt and validate new messages tags - Implements MxOps::tags_edit() -. More...
 
static int comp_tags_commit (struct Mailbox *m, struct Email *e, char *buf)
 Save the tags to a message - Implements MxOps::tags_commit() -. More...
 
static enum MailboxType comp_path_probe (const char *path, const struct stat *st)
 Is this a compressed Mailbox? - Implements MxOps::path_probe() -. More...
 
static int comp_path_canon (char *buf, size_t buflen)
 Canonicalise a Mailbox path - Implements MxOps::path_canon() -. More...
 
static int comp_path_pretty (char *buf, size_t buflen, const char *folder)
 Abbreviate a Mailbox path - Implements MxOps::path_pretty() -. More...
 
static int comp_path_parent (char *buf, size_t buflen)
 Find the parent of a Mailbox path - Implements MxOps::path_parent() -. More...
 

Variables

static const struct Command comp_commands []
 
struct MxOps MxCompOps
 Compressed Mailbox - Implements MxOps -Compress only uses open, close and check. More...
 

Detailed Description

Compressed mbox local mailbox type.

Authors
  • Alain Penders
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file compress.c.

Function Documentation

◆ mutt_comp_init()

void mutt_comp_init ( void  )

Setup feature commands.

Definition at line 69 of file compress.c.

70 {
72 }
#define COMMANDS_REGISTER(cmds)
Definition: mutt_commands.h:82
static const struct Command comp_commands[]
Definition: compress.c:58
+ Here is the caller graph for this function:

◆ lock_realpath()

static bool lock_realpath ( struct Mailbox m,
bool  excl 
)
static

Try to lock the ctx->realpath.

Parameters
mMailbox to lock
exclLock exclusively?
Return values
trueSuccess (locked or readonly)
falseError (can't lock the file)

Try to (exclusively) lock the mailbox. If we succeed, then we mark the mailbox as locked. If we fail, but we didn't want exclusive rights, then the mailbox will be marked readonly.

Definition at line 85 of file compress.c.

86 {
87  if (!m || !m->compress_info)
88  return false;
89 
90  struct CompressInfo *ci = m->compress_info;
91 
92  if (ci->locked)
93  return true;
94 
95  if (excl)
96  ci->fp_lock = fopen(m->realpath, "a");
97  else
98  ci->fp_lock = fopen(m->realpath, "r");
99  if (!ci->fp_lock)
100  {
101  mutt_perror(m->realpath);
102  return false;
103  }
104 
105  int r = mutt_file_lock(fileno(ci->fp_lock), excl, true);
106  if (r == 0)
107  ci->locked = true;
108  else if (excl)
109  {
111  m->readonly = true;
112  return true;
113  }
114 
115  return r == 0;
116 }
FILE * fp_lock
fp used for locking
Definition: lib.h:54
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
bool locked
if realpath is locked
Definition: lib.h:53
#define mutt_perror(...)
Definition: logging.h:89
int mutt_file_lock(int fd, bool excl, bool timeout)
(try to) lock a file using fcntl()
Definition: file.c:1178
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:119
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
Private data for compress.
Definition: lib.h:46
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:124
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unlock_realpath()

static void unlock_realpath ( struct Mailbox m)
static

Unlock the mailbox->realpath.

Parameters
mMailbox to unlock

Unlock a mailbox previously locked by lock_mailbox().

Definition at line 124 of file compress.c.

125 {
126  if (!m || !m->compress_info)
127  return;
128 
129  struct CompressInfo *ci = m->compress_info;
130 
131  if (!ci->locked)
132  return;
133 
134  mutt_file_unlock(fileno(ci->fp_lock));
135 
136  ci->locked = false;
138 }
FILE * fp_lock
fp used for locking
Definition: lib.h:54
bool locked
if realpath is locked
Definition: lib.h:53
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
Definition: file.c:1226
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
Private data for compress.
Definition: lib.h:46
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:124
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setup_paths()

static int setup_paths ( struct Mailbox m)
static

Set the mailbox paths.

Parameters
mMailbox to modify
Return values
0Success
-1Error

Save the compressed filename in mailbox->realpath. Create a temporary filename and put its name in mailbox->path. The temporary file is created to prevent symlink attacks.

Definition at line 150 of file compress.c.

151 {
152  if (!m)
153  return -1;
154 
155  /* Setup the right paths */
157 
158  /* We will uncompress to TMPDIR */
159  struct Buffer *buf = mutt_buffer_pool_get();
160  mutt_buffer_mktemp(buf);
161  mutt_buffer_copy(&m->pathbuf, buf);
163 
164  FILE *fp = mutt_file_fopen(mailbox_path(m), "w");
165  if (!fp)
166  return -1;
167 
168  mutt_file_fclose(&fp);
169  return 0;
170 }
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:215
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer&#39;s contents to another Buffer.
Definition: buffer.c:445
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
struct Buffer pathbuf
Definition: mailbox.h:83
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ store_size()

static void store_size ( const struct Mailbox m)
static

Save the size of the compressed file.

Parameters
mMailbox

Save the compressed file size in the compress_info struct.

Definition at line 178 of file compress.c.

179 {
180  if (!m || !m->compress_info)
181  return;
182 
183  struct CompressInfo *ci = m->compress_info;
184 
185  ci->size = mutt_file_get_size(m->realpath);
186 }
long mutt_file_get_size(const char *path)
Get the size of a file.
Definition: file.c:1498
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
long size
size of the compressed file
Definition: lib.h:51
Private data for compress.
Definition: lib.h:46
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:124
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_compress_info()

static struct CompressInfo* set_compress_info ( struct Mailbox m)
static

Find the compress hooks for a mailbox.

Parameters
mMailbox to examine
Return values
ptrCompressInfo Hook info for the mailbox's path
NULLError

When a mailbox is opened, we check if there are any matching hooks.

Definition at line 196 of file compress.c.

197 {
198  if (!m)
199  return NULL;
200 
201  if (m->compress_info)
202  return m->compress_info;
203 
204  /* Open is compulsory */
205  const char *o = mutt_find_hook(MUTT_OPEN_HOOK, mailbox_path(m));
206  if (!o)
207  return NULL;
208 
209  const char *c = mutt_find_hook(MUTT_CLOSE_HOOK, mailbox_path(m));
210  const char *a = mutt_find_hook(MUTT_APPEND_HOOK, mailbox_path(m));
211 
212  struct CompressInfo *ci = mutt_mem_calloc(1, sizeof(struct CompressInfo));
213  m->compress_info = ci;
214 
215  ci->cmd_open = mutt_str_dup(o);
216  ci->cmd_close = mutt_str_dup(c);
217  ci->cmd_append = mutt_str_dup(a);
218 
219  return ci;
220 }
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:215
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
const char * cmd_append
append-hook command
Definition: lib.h:48
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
const char * cmd_close
close-hook command
Definition: lib.h:49
#define MUTT_APPEND_HOOK
append-hook: append to a compressed mailbox
Definition: hook.h:53
char * mutt_find_hook(HookFlags type, const char *pat)
Find a matching hook.
Definition: hook.c:577
#define MUTT_CLOSE_HOOK
close-hook: write to a compressed mailbox
Definition: hook.h:54
#define MUTT_OPEN_HOOK
open-hook: to read a compressed mailbox
Definition: hook.h:52
Private data for compress.
Definition: lib.h:46
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:124
const char * cmd_open
open-hook command
Definition: lib.h:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compress_info_free()

static void compress_info_free ( struct Mailbox m)
static

Frees the compress info members and structure.

Parameters
mMailbox to free compress_info for

Definition at line 226 of file compress.c.

227 {
228  if (!m || !m->compress_info)
229  return;
230 
231  struct CompressInfo *ci = m->compress_info;
232  FREE(&ci->cmd_open);
233  FREE(&ci->cmd_close);
234  FREE(&ci->cmd_append);
235 
236  unlock_realpath(m);
237 
238  FREE(&m->compress_info);
239 }
const char * cmd_append
append-hook command
Definition: lib.h:48
const char * cmd_close
close-hook command
Definition: lib.h:49
static void unlock_realpath(struct Mailbox *m)
Unlock the mailbox->realpath.
Definition: compress.c:124
Private data for compress.
Definition: lib.h:46
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:124
#define FREE(x)
Definition: memory.h:40
const char * cmd_open
open-hook command
Definition: lib.h:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ expand_command_str()

static void expand_command_str ( const struct Mailbox m,
const char *  cmd,
char *  buf,
int  buflen 
)
static

Expand placeholders in command string.

Parameters
mMailbox for paths
cmdTemplate command to be expanded
bufBuffer to store the command
buflenSize of the buffer

This function takes a hook command and expands the filename placeholders within it. The function calls mutt_expando_format() to do the replacement which calls our callback function compress_format_str(). e.g.

Template command: gzip -cd 'f' > 't'

Result: gzip -dc '~/mail/abc.gz' > '/tmp/xyz'

Definition at line 299 of file compress.c.

300 {
301  if (!m || !cmd || !buf)
302  return;
303 
304  mutt_expando_format(buf, buflen, 0, buflen, cmd, compress_format_str,
305  (intptr_t) m, MUTT_FORMAT_NO_FLAGS);
306 }
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string -.
Definition: muttlib.c:780
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
static const char * compress_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Expand the filenames in a command string - Implements format_t -Expando Description %f Compressed fi...
Definition: compress.c:249
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ execute_command()

static int execute_command ( struct Mailbox m,
const char *  command,
const char *  progress 
)
static

Run a system command.

Parameters
mMailbox to work with
commandCommand string to execute
progressMessage to show the user
Return values
1Success
0Failure

Run the supplied command, taking care of all the NeoMutt requirements, such as locking files and blocking signals.

Definition at line 319 of file compress.c.

320 {
321  if (!m || !command || !progress)
322  return 0;
323 
324  if (m->verbose)
325  mutt_message(progress, m->realpath);
326 
327  int rc = 1;
328  char sys_cmd[STR_COMMAND];
329 
330  mutt_sig_block();
331  endwin();
332  fflush(stdout);
333 
334  expand_command_str(m, command, sys_cmd, sizeof(sys_cmd));
335 
336  if (mutt_system(sys_cmd) != 0)
337  {
338  rc = 0;
340  mutt_error(_("Error running \"%s\""), sys_cmd);
341  }
342 
344 
345  return rc;
346 }
void mutt_sig_unblock(void)
Restore previously blocked signals.
Definition: signal.c:168
#define mutt_error(...)
Definition: logging.h:88
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
#define _(a)
Definition: message.h:28
bool verbose
Display status messages?
Definition: mailbox.h:118
#define STR_COMMAND
Enough space for a long command line.
Definition: string2.h:35
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:455
#define mutt_message(...)
Definition: logging.h:87
void mutt_sig_block(void)
Block signals during critical operations.
Definition: signal.c:150
static void expand_command_str(const struct Mailbox *m, const char *cmd, char *buf, int buflen)
Expand placeholders in command string.
Definition: compress.c:299
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_comp_can_append()

bool mutt_comp_can_append ( struct Mailbox m)

Can we append to this path?

Parameters
mMailbox
Return values
trueYes, we can append to the file
falseNo, appending isn't possible

To append to a file we can either use an 'append-hook' or a combination of 'open-hook' and 'close-hook'.

A match means it's our responsibility to append to the file.

Definition at line 359 of file compress.c.

360 {
361  if (!m)
362  return false;
363 
364  /* If this succeeds, we know there's an open-hook */
365  struct CompressInfo *ci = set_compress_info(m);
366  if (!ci)
367  return false;
368 
369  /* We have an open-hook, so to append we need an append-hook,
370  * or a close-hook. */
371  if (ci->cmd_append || ci->cmd_close)
372  return true;
373 
374  mutt_error(_("Can't append without an append-hook or close-hook : %s"), mailbox_path(m));
375  return false;
376 }
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:215
const char * cmd_append
append-hook command
Definition: lib.h:48
#define mutt_error(...)
Definition: logging.h:88
#define _(a)
Definition: message.h:28
const char * cmd_close
close-hook command
Definition: lib.h:49
static struct CompressInfo * set_compress_info(struct Mailbox *m)
Find the compress hooks for a mailbox.
Definition: compress.c:196
Private data for compress.
Definition: lib.h:46
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_comp_can_read()

bool mutt_comp_can_read ( const char *  path)

Can we read from this file?

Parameters
pathPathname of file to be tested
Return values
trueYes, we can read the file
falseNo, we can't read the file

Search for an 'open-hook' with a regex that matches the path.

A match means it's our responsibility to open the file.

Definition at line 388 of file compress.c.

389 {
390  if (!path)
391  return false;
392 
393  if (mutt_find_hook(MUTT_OPEN_HOOK, path))
394  return true;
395 
396  return false;
397 }
char * mutt_find_hook(HookFlags type, const char *pat)
Find a matching hook.
Definition: hook.c:577
#define MUTT_OPEN_HOOK
open-hook: to read a compressed mailbox
Definition: hook.h:52
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_comp_valid_command()

int mutt_comp_valid_command ( const char *  cmd)

Is this command string allowed?

Parameters
cmdCommand string
Return values
1Valid command
0"%f" and/or "%t" is missing

A valid command string must have both "%f" (from file) and "%t" (to file). We don't check if we can actually run the command.

Definition at line 408 of file compress.c.

409 {
410  if (!cmd)
411  return 0;
412 
413  return strstr(cmd, "%f") && strstr(cmd, "%t");
414 }
+ Here is the caller graph for this function:

Variable Documentation

◆ comp_commands

const struct Command comp_commands[]
static
Initial value:
= {
{ "append-hook", mutt_parse_hook, MUTT_APPEND_HOOK },
{ "close-hook", mutt_parse_hook, MUTT_CLOSE_HOOK },
{ "open-hook", mutt_parse_hook, MUTT_OPEN_HOOK },
}
enum CommandResult mutt_parse_hook(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;hook&#39; family of commands - Implements Command::parse() -This is used by &#39;account-hook&#39;...
Definition: hook.c:82
#define MUTT_APPEND_HOOK
append-hook: append to a compressed mailbox
Definition: hook.h:53
#define MUTT_CLOSE_HOOK
close-hook: write to a compressed mailbox
Definition: hook.h:54
#define MUTT_OPEN_HOOK
open-hook: to read a compressed mailbox
Definition: hook.h:52

Definition at line 58 of file compress.c.