#include <errno.h>
#include <string.h>
#include <sys/stat.h>
-#include <sys/time.h>
#include "autocrypt_private.h"
#include "mutt/mutt.h"
#include "address/lib.h"
int mutt_autocrypt_process_autocrypt_header(struct Email *e, struct Envelope *env)
{
struct AutocryptHeader *valid_ac_hdr = NULL;
- struct timeval now;
struct AutocryptPeer *peer = NULL;
struct AutocryptPeerHistory *peerhist = NULL;
struct Buffer *keyid = NULL;
/* Ignore emails that appear to be more than a week in the future,
* since they can block all future updates during that time. */
- gettimeofday(&now, NULL);
- if (e->date_sent > (now.tv_sec + 7 * 24 * 60 * 60))
+ if (e->date_sent > (mutt_date_epoch_ms() / 1000 + (7 * 24 * 60 * 60)))
return 0;
for (struct AutocryptHeader *ac_hdr = env->autocrypt; ac_hdr; ac_hdr = ac_hdr->next)
*/
int mutt_autocrypt_process_gossip_header(struct Email *e, struct Envelope *prot_headers)
{
- struct timeval now;
struct AutocryptPeer *peer = NULL;
struct AutocryptGossipHistory *gossip_hist = NULL;
struct Address *peer_addr = NULL;
/* Ignore emails that appear to be more than a week in the future,
* since they can block all future updates during that time. */
- gettimeofday(&now, NULL);
- if (e->date_sent > (now.tv_sec + (7 * 24 * 60 * 60)))
+ if (e->date_sent > (mutt_date_epoch_ms() / 1000 + (7 * 24 * 60 * 60)))
return 0;
struct Buffer *keyid = mutt_buffer_pool_get();
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
-#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include "mutt/mutt.h"
{
fd_set rfds;
unsigned long wait_millis;
- struct timeval tv, pre_t, post_t;
+ struct timeval tv;
+ size_t pre_t, post_t;
if (conn->fd < 0)
return -1;
FD_ZERO(&rfds);
FD_SET(conn->fd, &rfds);
- gettimeofday(&pre_t, NULL);
+ pre_t = mutt_date_epoch_ms();
const int rc = select(conn->fd + 1, &rfds, NULL, NULL, &tv);
- gettimeofday(&post_t, NULL);
+ post_t = mutt_date_epoch_ms();
if ((rc > 0) || ((rc < 0) && (errno != EINTR)))
return rc;
if (SigInt)
mutt_query_exit();
- wait_millis += (pre_t.tv_sec * 1000UL) + (pre_t.tv_usec / 1000);
- const unsigned long post_t_millis = (post_t.tv_sec * 1000UL) + (post_t.tv_usec / 1000);
- if (wait_millis <= post_t_millis)
+ wait_millis += pre_t;
+ if (wait_millis <= post_t)
return 0;
- wait_millis -= post_t_millis;
+ wait_millis -= post_t;
}
}
if (!d)
return false;
- unsigned int mycrc = *(unsigned int *) (d + sizeof(union Validate));
+ unsigned int mycrc = *(unsigned int *) (d + sizeof(size_t));
return crc == mycrc;
}
*/
typedef int (*hcache_namer_t)(const char *path, char *dest, size_t dlen);
-/**
- * union Validate - Header cache validity
- */
-union Validate {
- struct timeval timeval;
- unsigned int uidvalidity;
-};
-
/* These Config Variables are only used in hcache/hcache.c */
extern char *C_HeaderCacheBackend;
#!/bin/sh
-BASEVERSION=3
+BASEVERSION=4
STRUCTURES="Address Body Buffer Email Envelope ListNode Parameter"
cleanstruct () {
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/time.h>
#include <sys/types.h>
#include "mutt/mutt.h"
#include "address/lib.h"
return d;
}
+/**
+ * serial_dump_size_t - Pack a size_t into a binary blob
+ * @param s Size_t to save
+ * @param d Binary blob to add to
+ * @param off Offset into the blob
+ * @retval ptr End of the newly packed binary
+ */
+unsigned char *serial_dump_size_t(size_t s, unsigned char *d, int *off)
+{
+ lazy_realloc(&d, *off + sizeof(size_t));
+ memcpy(d + *off, &s, sizeof(size_t));
+ (*off) += sizeof(size_t);
+
+ return d;
+}
+
/**
* serial_restore_int - Unpack an integer from a binary blob
* @param i Integer to write to
* This function transforms a e into a char so that it is usable by
* db_store.
*/
-void *mutt_hcache_dump(header_cache_t *hc, const struct Email *e, int *off, unsigned int uidvalidity)
+void *mutt_hcache_dump(header_cache_t *hc, const struct Email *e, int *off, size_t uidvalidity)
{
struct Email nh;
bool convert = !CharsetIsUtf8;
*off = 0;
unsigned char *d = mutt_mem_malloc(4096);
- if (uidvalidity == 0)
- {
- struct timeval now;
- gettimeofday(&now, NULL);
- memcpy(d, &now, sizeof(struct timeval));
- }
- else
- memcpy(d, &uidvalidity, sizeof(uidvalidity));
- *off += sizeof(union Validate);
-
+ d = serial_dump_size_t((uidvalidity != 0) ? uidvalidity : mutt_date_epoch_ms(), d, off);
d = serial_dump_int(hc->crc, d, off);
lazy_realloc(&d, *off + sizeof(struct Email));
bool convert = !CharsetIsUtf8;
/* skip validate */
- off += sizeof(union Validate);
+ off += sizeof(size_t);
/* skip crc */
off += sizeof(unsigned int);
unsigned char *serial_dump_char_size(char *c, unsigned char *d, int *off, ssize_t size, bool convert);
unsigned char *serial_dump_envelope(struct Envelope *e, unsigned char *d, int *off, bool convert);
unsigned char *serial_dump_int(unsigned int i, unsigned char *d, int *off);
+unsigned char *serial_dump_size_t(size_t s, unsigned char *d, int *off);
unsigned char *serial_dump_parameter(struct ParameterList *pl, unsigned char *d, int *off, bool convert);
unsigned char *serial_dump_stailq(struct ListHead *l, unsigned char *d, int *off, bool convert);
void serial_restore_parameter(struct ParameterList *pl, const unsigned char *d, int *off, bool convert);
void serial_restore_stailq(struct ListHead *l, const unsigned char *d, int *off, bool convert);
-void * mutt_hcache_dump(header_cache_t *hc, const struct Email *e, int *off, unsigned int uidvalidity);
+void * mutt_hcache_dump(header_cache_t *hc, const struct Email *e, int *off, size_t uidvalidity);
struct Email *mutt_hcache_restore(const unsigned char *d);
#endif /* MUTT_HCACHE_SERIALIZE_H */
void *uv = mutt_hcache_fetch(mdata->hcache, key, mutt_str_strlen(key));
if (uv)
{
- if (*(unsigned int *) uv == mdata->uid_validity)
+ const size_t *const uid_validity = uv;
+ if (*uid_validity == mdata->uid_validity)
e = mutt_hcache_restore(uv);
else
- mutt_debug(LL_DEBUG3, "hcache uidvalidity mismatch: %u\n", *(unsigned int *) uv);
+ mutt_debug(LL_DEBUG3, "hcache uidvalidity mismatch: %zu\n", *uid_validity);
mutt_hcache_free(mdata->hcache, &uv);
}
keylen = maildir_hcache_keylen(key);
}
void *data = mutt_hcache_fetch(hc, key, keylen);
- struct timeval *when = data;
+ size_t *when = data;
- if (data && !ret && (lastchanged.st_mtime <= when->tv_sec))
+ if (data && !ret && (lastchanged.st_mtime <= (*when / 1000)))
{
struct Email *e = mutt_hcache_restore((unsigned char *) data);
e->old = p->email->old;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/time.h>
#include <time.h>
#include "date.h"
#include "logging.h"
return -1; /* error */
}
+/**
+ * mutt_date_epoch_ms - Return the number of milliseconds since the Unix epoch
+ * @retval ms The number of ms since the Unix epoch, or 0 on failure
+ */
+size_t mutt_date_epoch_ms(void)
+{
+ struct timeval tv = { 0, 0 };
+ gettimeofday(&tv, NULL);
+ /* We assume that gettimeofday doesn't modify its first argument on failure.
+ * We also kind of assume that gettimeofday does not fail. */
+ return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
/**
* mutt_date_is_day_name - Is the string a valid day name
* @param s String to check
struct tm tm = mutt_date_localtime(t);
return strftime(buf, buflen, format, &tm);
}
+
+/**
+ * mutt_date_sleep_ms - Sleep for milliseconds
+ * @param ms Number of milliseconds to sleep
+ */
+void mutt_date_sleep_ms(size_t ms)
+{
+ const struct timespec sleep = {
+ .tv_sec = ms / 1000,
+ .tv_nsec = (ms % 1000) * 1000000UL,
+ };
+ nanosleep(&sleep, NULL);
+}
time_t mutt_date_add_timeout(time_t now, long timeout);
int mutt_date_check_month(const char *s);
+size_t mutt_date_epoch_ms(void);
struct tm mutt_date_gmtime(time_t t);
bool mutt_date_is_day_name(const char *s);
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t);
void mutt_date_normalize_time(struct tm *tm);
time_t mutt_date_parse_date(const char *s, struct Tz *tz_out);
time_t mutt_date_parse_imap(const char *s);
+void mutt_date_sleep_ms(size_t ms);
#endif /* MUTT_LIB_DATE_H */
#include <stdint.h>
#include <stdio.h>
#include <string.h>
-#include <sys/time.h>
-#include <time.h>
#include "mutt/mutt.h"
#include "config/lib.h"
#include "curs_lib.h"
#include "muttlib.h"
#include "options.h"
-struct timeval LastError = { 0 };
+size_t LastError = 0; ///< Time of the last error message (in milliseconds since the Unix epoch)
short C_DebugLevel = 0; ///< Config: Logging level for debug logs
char *C_DebugFile = NULL; ///< Config: File to save debug logs
char *CurrentFile = NULL; /**< The previous log file name */
const int NumOfLogs = 5; /**< How many log files to rotate */
-#define S_TO_NS 1000000000UL
-#define S_TO_US 1000000UL
-#define US_TO_NS 1000UL
-
-/**
- * micro_elapsed - Number of microseconds between two timevals
- * @param begin Begin time
- * @param end End time
- * @retval num Microseconds elapsed
- * @retval LONG_MAX Begin time was zero
- */
-static long micro_elapsed(const struct timeval *begin, const struct timeval *end)
-{
- if ((begin->tv_sec == 0) && (end->tv_sec != 0))
- return LONG_MAX;
-
- return (end->tv_sec - begin->tv_sec) * S_TO_US + (end->tv_usec - begin->tv_usec);
-}
+#define S_TO_MS 1000L
/**
* error_pause - Wait for an error message to be read
*/
static void error_pause(void)
{
- struct timeval now = { 0 };
-
- if (gettimeofday(&now, NULL) < 0)
- {
- mutt_debug(LL_DEBUG1, "gettimeofday failed: %d\n", errno);
- return;
- }
-
- unsigned long sleep = C_SleepTime * S_TO_NS;
- long micro = micro_elapsed(&LastError, &now);
- if ((micro * US_TO_NS) >= sleep)
+ const size_t elapsed = mutt_date_epoch_ms() - LastError;
+ const size_t sleep = C_SleepTime * S_TO_MS;
+ if ((LastError == 0) || (elapsed >= sleep))
return;
- sleep -= (micro * US_TO_NS);
-
- struct timespec wait = {
- .tv_sec = (sleep / S_TO_NS),
- .tv_nsec = (sleep % S_TO_NS),
- };
-
mutt_refresh();
- nanosleep(&wait, NULL);
+ mutt_date_sleep_ms(sleep - elapsed);
}
/**
if ((level <= LL_ERROR) && !dupe)
{
OptMsgErr = true;
- if (gettimeofday(&LastError, NULL) < 0)
- mutt_debug(LL_DEBUG1, "gettimeofday failed: %d\n", errno);
+ LastError = mutt_date_epoch_ms();
}
else
{
OptMsgErr = false;
- LastError.tv_sec = 0;
+ LastError = 0;
}
return ret;
#include <stdbool.h>
#include <stdio.h>
#include <sys/stat.h>
-#include <time.h>
#include "notmuch_private.h"
#include "mutt/mutt.h"
#include "email/lib.h"
const notmuch_database_mode_t mode =
writable ? NOTMUCH_DATABASE_MODE_READ_WRITE : NOTMUCH_DATABASE_MODE_READ_ONLY;
- const struct timespec wait = {
- .tv_sec = 0, .tv_nsec = 500000000, /* Half a second */
- };
-
do
{
#if LIBNOTMUCH_CHECK_VERSION(4, 2, 0)
if (verbose && ct && ((ct % 2) == 0))
mutt_error(_("Waiting for notmuch DB... (%d sec)"), ct / 2);
- nanosleep(&wait, NULL);
+ mutt_date_sleep_ms(500000); /* Half a second */
ct++;
} while (true);