+
+ssize_t m_file_fmt(char *dst, ssize_t n, const char *fmt, const char *src)
+{
+ ssize_t pos = 0;
+ const char *p;
+ int hadfname = 0;
+
+ for (p = strchr(fmt, '%'); p; p = strchr(fmt, '%')) {
+ if (p[1] == 's') {
+ pos += m_strncpy(dst + pos, n - pos, fmt, p - fmt);
+ pos += m_strcpy(dst + pos, n - pos, src);
+ fmt = p + 2;
+ hadfname = 1;
+ } else {
+ pos += m_strncpy(dst + pos, n - pos, fmt, p + 1 - fmt);
+ fmt = p + 1 + (p[1] == '%');
+ }
+ }
+ pos += m_strcpy(dst + pos, n - pos, fmt);
+
+ if (!hadfname)
+ pos += snprintf(dst + pos, n - pos, " %s", src);
+
+ return pos;
+}
+
+ssize_t
+m_quotefile_fmt(char *dst, ssize_t n, const char *fmt, const char *src)
+{
+ char tmp[LONG_STRING];
+ mutt_quote_filename(tmp, sizeof(tmp), src);
+ return m_file_fmt(dst, n, fmt, tmp);
+}
+
+static ssize_t
+m_tempftplize(char *dst, ssize_t dlen, const char *fmt, const char *s)
+{
+ const char *p;
+
+ while ((p = strchr(fmt, '/'))) {
+ fmt = p + 1;
+ }
+
+ if (!*fmt)
+ return m_strcpy(dst, dlen, s);
+
+ for (p = strchr(fmt, '%'); p; p = strchr(p, '%')) {
+ if (p[1] == 's')
+ return m_file_fmt(dst, dlen, fmt, s);
+
+ p += 1 + (p[1] == '%');
+ }
+
+ p = strrchr(fmt, '.');
+ if (p) {
+ return snprintf(dst, dlen, "%s%s", s, p);
+ } else {
+ return snprintf(dst, dlen, "%s.%s", s, fmt);
+ }
+}
+
+int m_tempfd(char *dst, ssize_t n, const char *dir, const char *fmt)
+{
+ char raw[_POSIX_PATH_MAX], tpl[_POSIX_PATH_MAX];
+ const char *path = fmt ? tpl : raw;
+ int fd;
+
+ rand_again:
+ snprintf(raw, sizeof(raw), "%s/madmutt-%04x-%04x-%08x",
+ dir, (int)getuid(), (int)getpid(), (int)rand());
+
+ if (fmt) {
+ m_tempftplize(tpl, sizeof(tpl), fmt, raw);
+ }
+
+ fd = open(path, O_CREAT | O_EXCL | O_RDWR | O_NOFOLLOW, 0600);
+
+ if (fd < 0) {
+ if (errno == EEXIST)
+ goto rand_again;
+ return -1;
+ }
+
+ m_strcpy(dst, n, path);
+ return fd;
+}
+
+FILE *m_tempfile(char *dst, ssize_t n, const char *dir, const char *fmt)
+{
+ int fd = m_tempfd(dst, n, dir, fmt);
+ return fd < 0 ? NULL : fdopen(fd, "w+");
+}
+
+/****************************************************************************/
+/* misc */
+/****************************************************************************/
+
+/* Decrease a file's modification time by 1 second */
+time_t m_decrease_mtime(const char *path, struct stat *st)
+{
+ struct utimbuf utim;
+ struct stat _st;
+ time_t mtime;
+
+ if (!st) {
+ if (stat(path, &_st) == -1)
+ return -1;
+ st = &_st;
+ }
+
+ if ((mtime = st->st_mtime) == time(NULL)) {
+ mtime -= 1;
+ utim.actime = mtime;
+ utim.modtime = mtime;
+ utime(path, &utim);
+ }
+
+ return mtime;
+}
+