Rewrite temporary file handling.
* include/mailutils/util.h (mu_make_file_name_suf): New proto. (mu_make_file_name): Replace with a macro. (MU_TEMPFILE_TMPDIR,MU_TEMPFILE_SUFFIX) (MU_TEMPFILE_MKDIR): New flags. (mu_tempfile_hints): New struct. (mu_tempfile): Change signature. * libmailutils/base/tempfile.c (mu_create_temp_file): New function. (mu_tempfile): Rewrite from scratch. Change signature. All callers changed. * libmailutils/string/mkfilename.c (mu_make_file_name): Remove. (mu_make_file_name_suf): New function. * libmailutils/stream/streamcpy.c (mu_stream_copy): Don't return EIO on EOF. * libmailutils/stream/file_stream.c (mu_fd_stream_create): If MU_STREAM_SEEK is set, position fd to 0. * guimb/collect.c: Update calls to mu_tempfile. * lib/mailcap.c: Likewise. * libmailutils/base/amd.c (_amd_tempfile): Rewrite using mu_tempfile. * libmailutils/tests/tempfile.c: New file. * libmailutils/tests/Makefile.am (noinst_PROGRAMS): Add tempfile.
Showing
13 changed files
with
425 additions
and
82 deletions
... | @@ -55,8 +55,7 @@ collect_open_mailbox_file () | ... | @@ -55,8 +55,7 @@ collect_open_mailbox_file () |
55 | int fd; | 55 | int fd; |
56 | 56 | ||
57 | /* Create input mailbox */ | 57 | /* Create input mailbox */ |
58 | fd = mu_tempfile (NULL, &temp_filename); | 58 | if (mu_tempfile (NULL, 0, &fd, &temp_filename)) |
59 | if (fd == -1) | ||
60 | exit (1); | 59 | exit (1); |
61 | 60 | ||
62 | temp_file = fdopen (fd, "w"); | 61 | temp_file = fdopen (fd, "w"); | ... | ... |
... | @@ -82,9 +82,27 @@ char *mu_tilde_expansion (const char *ref, const char *delim, | ... | @@ -82,9 +82,27 @@ char *mu_tilde_expansion (const char *ref, const char *delim, |
82 | int mu_readlink (const char *name, char **pbuf, size_t *psize, size_t *plen); | 82 | int mu_readlink (const char *name, char **pbuf, size_t *psize, size_t *plen); |
83 | int mu_unroll_symlink (const char *name, char **pout); | 83 | int mu_unroll_symlink (const char *name, char **pout); |
84 | char *mu_getcwd (void); | 84 | char *mu_getcwd (void); |
85 | int mu_tempfile (const char *tmpdir, char **namep); | 85 | char *mu_make_file_name_suf (const char *dir, const char *file, |
86 | const char *suf); | ||
87 | #define mu_make_file_name(dir, file) mu_make_file_name_suf (dir, file, NULL) | ||
88 | |||
89 | /* ------------------------ */ | ||
90 | /* Temporary file creation. */ | ||
91 | /* ------------------------ */ | ||
92 | #define MU_TEMPFILE_TMPDIR 0x01 /* tmpdir is set */ | ||
93 | #define MU_TEMPFILE_SUFFIX 0x02 /* suffix is set */ | ||
94 | #define MU_TEMPFILE_MKDIR 0x04 /* create a directory, not a file */ | ||
95 | |||
96 | struct mu_tempfile_hints | ||
97 | { | ||
98 | const char *tmpdir; | ||
99 | const char *suffix; | ||
100 | }; | ||
101 | |||
102 | /*int mu_tempfile (const char *tmpdir, char **namep);*/ | ||
103 | int mu_tempfile (struct mu_tempfile_hints *hints, int flags, | ||
104 | int *pfd, char **namep); | ||
86 | char *mu_tempname (const char *tmpdir); | 105 | char *mu_tempname (const char *tmpdir); |
87 | char *mu_make_file_name (const char *dir, const char *file); | ||
88 | 106 | ||
89 | /* ----------------------- */ | 107 | /* ----------------------- */ |
90 | /* Current user email. */ | 108 | /* Current user email. */ | ... | ... |
... | @@ -197,6 +197,7 @@ mime_context_get_content_type_value (struct mime_context *ctx, | ... | @@ -197,6 +197,7 @@ mime_context_get_content_type_value (struct mime_context *ctx, |
197 | return rc; | 197 | return rc; |
198 | } | 198 | } |
199 | 199 | ||
200 | /* FIXME: Rewrite via mu_stream_copy */ | ||
200 | static void | 201 | static void |
201 | mime_context_write_input (struct mime_context *ctx, int fd) | 202 | mime_context_write_input (struct mime_context *ctx, int fd) |
202 | { | 203 | { |
... | @@ -219,8 +220,8 @@ mime_context_get_temp_file (struct mime_context *ctx, char **ptr) | ... | @@ -219,8 +220,8 @@ mime_context_get_temp_file (struct mime_context *ctx, char **ptr) |
219 | { | 220 | { |
220 | if (!ctx->temp_file) | 221 | if (!ctx->temp_file) |
221 | { | 222 | { |
222 | int fd = mu_tempfile (NULL, &ctx->temp_file); | 223 | int fd; |
223 | if (fd == -1) | 224 | if (mu_tempfile (NULL, 0, &fd, &ctx->temp_file)) |
224 | return -1; | 225 | return -1; |
225 | mime_context_write_input (ctx, fd); | 226 | mime_context_write_input (ctx, fd); |
226 | close (fd); | 227 | close (fd); | ... | ... |
... | @@ -597,13 +597,18 @@ amd_quick_get_message (mu_mailbox_t mailbox, mu_message_qid_t qid, | ... | @@ -597,13 +597,18 @@ amd_quick_get_message (mu_mailbox_t mailbox, mu_message_qid_t qid, |
597 | return ENOSYS; | 597 | return ENOSYS; |
598 | } | 598 | } |
599 | 599 | ||
600 | static FILE * | 600 | static int |
601 | _amd_tempfile(struct _amd_data *amd, char **namep) | 601 | _amd_tempfile (struct _amd_data *amd, FILE **pfile, char **namep) |
602 | { | 602 | { |
603 | int fd = mu_tempfile (amd->name, namep); | 603 | struct mu_tempfile_hints hints; |
604 | if (fd == -1) | 604 | int fd, rc; |
605 | return NULL; | 605 | |
606 | return fdopen (fd, "w"); | 606 | hints.tmpdir = amd->name; |
607 | rc = mu_tempfile (&hints, MU_TEMPFILE_TMPDIR, &fd, namep); | ||
608 | if (rc == 0) | ||
609 | if ((*pfile = fdopen (fd, "w")) == NULL) | ||
610 | rc = errno; | ||
611 | return rc; | ||
607 | } | 612 | } |
608 | 613 | ||
609 | static int | 614 | static int |
... | @@ -658,11 +663,11 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, | ... | @@ -658,11 +663,11 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, |
658 | return status; | 663 | return status; |
659 | } | 664 | } |
660 | 665 | ||
661 | fp = _amd_tempfile (mhm->amd, &name); | 666 | status = _amd_tempfile (mhm->amd, &fp, &name); |
662 | if (!fp) | 667 | if (status) |
663 | { | 668 | { |
664 | free (msg_name); | 669 | free (msg_name); |
665 | return errno; | 670 | return status; |
666 | } | 671 | } |
667 | 672 | ||
668 | /* Try to allocate large buffer */ | 673 | /* Try to allocate large buffer */ | ... | ... |
... | @@ -22,6 +22,8 @@ | ... | @@ -22,6 +22,8 @@ |
22 | 22 | ||
23 | #include <sys/types.h> | 23 | #include <sys/types.h> |
24 | #include <sys/stat.h> | 24 | #include <sys/stat.h> |
25 | #include <sys/time.h> | ||
26 | #include <fcntl.h> | ||
25 | #include <errno.h> | 27 | #include <errno.h> |
26 | #include <unistd.h> | 28 | #include <unistd.h> |
27 | #include <stdlib.h> | 29 | #include <stdlib.h> |
... | @@ -33,62 +35,177 @@ | ... | @@ -33,62 +35,177 @@ |
33 | #include <mailutils/errno.h> | 35 | #include <mailutils/errno.h> |
34 | #include <mailutils/util.h> | 36 | #include <mailutils/util.h> |
35 | 37 | ||
36 | /* Create and open a temporary file. Be very careful about it, since we | ||
37 | may be running with extra privilege i.e setgid(). | ||
38 | Returns file descriptor of the open file. | ||
39 | If namep is not NULL, the pointer to the malloced file name will | ||
40 | be stored there. Otherwise, the file is unlinked right after open, | ||
41 | i.e. it will disappear after close(fd). */ | ||
42 | |||
43 | #ifndef P_tmpdir | 38 | #ifndef P_tmpdir |
44 | # define P_tmpdir "/tmp" | 39 | # define P_tmpdir "/tmp" |
45 | #endif | 40 | #endif |
46 | 41 | ||
42 | /* Lower level call. | ||
43 | |||
44 | Create a temporary file with the name according to the pattern FILENAME. | ||
45 | FILENAME must end with any amount of Xs, optionally followed by | ||
46 | SUFLEN other characters. | ||
47 | |||
48 | If ISDIR is not 0, create a directory (privileges 0700), otherwise | ||
49 | create a file (privileges 0600). | ||
50 | |||
51 | On success, return 0. If pfd is not NULL (and ISDIR is 0), open the | ||
52 | created file and store the descriptor in *PFD. Return actual file | ||
53 | name in FILENAME. | ||
54 | |||
55 | On error, return error code. | ||
56 | */ | ||
47 | int | 57 | int |
48 | mu_tempfile (const char *tmpdir, char **namep) | 58 | mu_create_temp_file (char *filename, size_t suflen, int *pfd, int isdir) |
49 | { | 59 | { |
50 | char *filename; | 60 | int rc; |
51 | int fd; | 61 | size_t len; |
62 | char *carrybuf; | ||
63 | char *p, *cp, *start, *end; | ||
64 | struct stat st; | ||
65 | static int first_call; | ||
66 | static char randstate[256]; | ||
67 | static const unsigned char alphabet[] = | ||
68 | "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | ||
69 | |||
70 | if (!first_call) | ||
71 | { | ||
72 | /* Initialize random number generator */ | ||
73 | struct timeval tv; | ||
74 | gettimeofday (&tv, NULL); | ||
75 | initstate (((unsigned long) tv.tv_usec << 16) ^ tv.tv_sec, | ||
76 | randstate, sizeof (randstate)); | ||
77 | first_call = 1; | ||
78 | } | ||
79 | setstate (randstate); | ||
52 | 80 | ||
53 | if (!tmpdir) | 81 | /* Start with the last filename character before suffix */ |
54 | tmpdir = (getenv ("TMPDIR")) ? getenv ("TMPDIR") : P_tmpdir; | 82 | end = filename + strlen (filename) - suflen - 1; |
55 | 83 | /* Fill X's with random characters */ | |
56 | filename = mu_make_file_name (tmpdir, "muXXXXXX"); | 84 | for (p = end; p >= filename && *p == 'X'; p--) |
57 | if (!filename) | 85 | *p = alphabet[random () % (sizeof (alphabet) - 1)]; |
86 | len = end - p; | ||
87 | if (len == 0) | ||
88 | return EINVAL; | ||
89 | start = p + 1; | ||
90 | |||
91 | carrybuf = malloc (len); | ||
92 | if (!carrybuf) | ||
93 | return ENOMEM; | ||
94 | |||
95 | /* Fill in the carry buffer */ | ||
96 | memcpy (carrybuf, start, len); | ||
97 | |||
98 | for (;;) | ||
58 | { | 99 | { |
59 | mu_diag_funcall (MU_DIAG_ERROR, "mu_make_file_name", NULL, ENOMEM); | 100 | if (isdir) |
60 | return -1; | 101 | { |
102 | if (mkdir (filename, 0700) == 0) | ||
103 | { | ||
104 | rc = 0; | ||
105 | break; | ||
106 | } | ||
107 | } | ||
108 | else if (pfd) | ||
109 | { | ||
110 | if ((*pfd = open (filename, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) | ||
111 | { | ||
112 | rc = 0; | ||
113 | break; | ||
114 | } | ||
115 | } | ||
116 | else if (lstat (filename, &st) && errno == ENOENT) | ||
117 | { | ||
118 | rc = 0; | ||
119 | break; | ||
120 | } | ||
121 | |||
122 | if (errno != EEXIST) | ||
123 | { | ||
124 | rc = errno; | ||
125 | break; | ||
126 | } | ||
127 | |||
128 | for (p = start, cp = carrybuf;; p++, cp++) | ||
129 | { | ||
130 | char *q; | ||
131 | |||
132 | if (p == end) | ||
133 | /* All permutation exhausted */ | ||
134 | return EEXIST; | ||
135 | q = strchr ((char*)alphabet, *p); | ||
136 | if (!q) | ||
137 | abort (); /* should not happen */ | ||
138 | *p = (q[1] == 0) ? alphabet[0] : q[1]; | ||
139 | if (*p != *cp) | ||
140 | break; | ||
141 | } | ||
61 | } | 142 | } |
143 | free (carrybuf); | ||
144 | return rc; | ||
145 | } | ||
62 | 146 | ||
63 | #ifdef HAVE_MKSTEMP | 147 | /* Create a temporary file according to HINTS. |
64 | { | 148 | |
65 | int save_mask = umask (077); | 149 | If MU_TEMPFILE_MKDIR flag is set, create a directory instead of file. |
66 | fd = mkstemp (filename); | 150 | |
67 | umask (save_mask); | 151 | On success, return 0. If PFD is not NULL (and MU_TEMPFILE_MKDIR flag |
68 | } | 152 | is not set), open the file and store its descriptor in *PFD. If |
69 | #else | 153 | NAMEP is not NULL, store there a pointer to the allocated file name. |
70 | if (mktemp (filename)) | 154 | At least one of PFD and NAMEP must be set, otherwise EINVAL is returned. |
71 | fd = open (filename, O_CREAT|O_EXCL|O_RDWR, 0600); | ||
72 | else | ||
73 | fd = -1; | ||
74 | #endif | ||
75 | 155 | ||
76 | if (fd == -1) | 156 | On error, returns error code describing the problem. |
157 | |||
158 | If hints is NULL, any flags except MU_TEMPFILE_MKDIR are ignored. | ||
159 | Otherwise: | ||
160 | |||
161 | * If MU_TEMPFILE_TMPDIR is set, hints->tmpdir points to the name of | ||
162 | a directory where to create the temporary. | ||
163 | * If MU_TEMPFILE_SUFFIX is set, hints->suffix defines a suffix to | ||
164 | append to the created file name. | ||
165 | */ | ||
166 | int | ||
167 | mu_tempfile (struct mu_tempfile_hints *hints, int flags, | ||
168 | int *pfd, char **namep) | ||
169 | { | ||
170 | char *filename; | ||
171 | const char *tmpdir = getenv ("TMPDIR"); | ||
172 | const char *suf = NULL; | ||
173 | int create_dir = 0; | ||
174 | int rc; | ||
175 | struct stat st; | ||
176 | |||
177 | if (pfd == NULL && namep == NULL) | ||
178 | return EINVAL; | ||
179 | if (hints) | ||
77 | { | 180 | { |
78 | mu_error (_("cannot open temporary file: %s"), mu_strerror (errno)); | 181 | if (flags & MU_TEMPFILE_TMPDIR) |
79 | free (filename); | 182 | tmpdir = hints->tmpdir; |
80 | return -1; | 183 | if (flags & MU_TEMPFILE_SUFFIX) |
184 | suf = hints->suffix; | ||
185 | create_dir = flags & MU_TEMPFILE_MKDIR; | ||
81 | } | 186 | } |
187 | |||
188 | if (!tmpdir) | ||
189 | tmpdir = P_tmpdir; | ||
190 | |||
191 | /* First, see if tmpdir exists */ | ||
192 | if (stat (tmpdir, &st)) | ||
193 | return errno; | ||
82 | 194 | ||
83 | if (namep) | 195 | /* Create a name template */ |
84 | *namep = filename; | 196 | filename = mu_make_file_name_suf (tmpdir, "muXXXXXX", suf); |
85 | else | 197 | rc = mu_create_temp_file (filename, suf ? strlen (suf) : 0, pfd, create_dir); |
198 | if (rc == 0) | ||
86 | { | 199 | { |
87 | unlink (filename); | 200 | if (namep) |
88 | free (filename); | 201 | *namep = filename; |
202 | else | ||
203 | { | ||
204 | unlink (filename); | ||
205 | free (filename); | ||
206 | } | ||
89 | } | 207 | } |
90 | 208 | return rc; | |
91 | return fd; | ||
92 | } | 209 | } |
93 | 210 | ||
94 | /* Create a unique temporary file name in tmpdir. The function | 211 | /* Create a unique temporary file name in tmpdir. The function |
... | @@ -100,10 +217,13 @@ mu_tempfile (const char *tmpdir, char **namep) | ... | @@ -100,10 +217,13 @@ mu_tempfile (const char *tmpdir, char **namep) |
100 | char * | 217 | char * |
101 | mu_tempname (const char *tmpdir) | 218 | mu_tempname (const char *tmpdir) |
102 | { | 219 | { |
220 | struct mu_tempfile_hints hints; | ||
103 | char *filename = NULL; | 221 | char *filename = NULL; |
104 | int fd = mu_tempfile (tmpdir, &filename); | 222 | int fd; |
223 | hints.tmpdir = tmpdir; | ||
224 | if (mu_tempfile (&hints, MU_TEMPFILE_TMPDIR, &fd, &filename)) | ||
225 | return NULL; | ||
105 | close (fd); | 226 | close (fd); |
106 | return filename; | 227 | return filename; |
107 | } | 228 | } |
108 | 229 | ||
109 | ... | ... |
... | @@ -388,9 +388,17 @@ int | ... | @@ -388,9 +388,17 @@ int |
388 | mu_fd_stream_create (mu_stream_t *pstream, char *filename, int fd, int flags) | 388 | mu_fd_stream_create (mu_stream_t *pstream, char *filename, int fd, int flags) |
389 | { | 389 | { |
390 | struct _mu_file_stream *fstr; | 390 | struct _mu_file_stream *fstr; |
391 | int rc = _mu_file_stream_create (&fstr, | 391 | int rc; |
392 | sizeof (struct _mu_file_stream), | 392 | |
393 | filename, fd, flags|_MU_STR_OPEN); | 393 | if (flags & MU_STREAM_SEEK) |
394 | { | ||
395 | if (lseek (fd, 0, SEEK_SET)) | ||
396 | return errno; | ||
397 | } | ||
398 | |||
399 | rc = _mu_file_stream_create (&fstr, | ||
400 | sizeof (struct _mu_file_stream), | ||
401 | filename, fd, flags|_MU_STR_OPEN); | ||
394 | if (rc == 0) | 402 | if (rc == 0) |
395 | { | 403 | { |
396 | mu_stream_t stream = (mu_stream_t) fstr; | 404 | mu_stream_t stream = (mu_stream_t) fstr; | ... | ... |
... | @@ -98,10 +98,7 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size, | ... | @@ -98,10 +98,7 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size, |
98 | if (status) | 98 | if (status) |
99 | break; | 99 | break; |
100 | if (n == 0) | 100 | if (n == 0) |
101 | { | 101 | break; |
102 | status = EIO; | ||
103 | break; | ||
104 | } | ||
105 | status = mu_stream_write (dst, buf, n, NULL); | 102 | status = mu_stream_write (dst, buf, n, NULL); |
106 | if (status) | 103 | if (status) |
107 | break; | 104 | break; |
... | @@ -120,6 +117,10 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size, | ... | @@ -120,6 +117,10 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size, |
120 | 117 | ||
121 | if (pcsz) | 118 | if (pcsz) |
122 | *pcsz = total; | 119 | *pcsz = total; |
120 | /* FIXME: When EOF error code is implemented: | ||
121 | else if (total == 0) | ||
122 | status = EIO; | ||
123 | */ | ||
123 | free (buf); | 124 | free (buf); |
124 | return status; | 125 | return status; |
125 | } | 126 | } | ... | ... |
... | @@ -37,11 +37,10 @@ static int | ... | @@ -37,11 +37,10 @@ static int |
37 | fd_temp_open (struct _mu_stream *str) | 37 | fd_temp_open (struct _mu_stream *str) |
38 | { | 38 | { |
39 | struct _mu_file_stream *fstr = (struct _mu_file_stream *) str; | 39 | struct _mu_file_stream *fstr = (struct _mu_file_stream *) str; |
40 | int fd = mu_tempfile (fstr->filename, NULL); | 40 | struct mu_tempfile_hints hints; |
41 | if (fd == -1) | 41 | |
42 | return errno; | 42 | hints.tmpdir = fstr->filename; |
43 | fstr->fd = fd; | 43 | return mu_tempfile (&hints, MU_TEMPFILE_TMPDIR, &fstr->fd, NULL); |
44 | return 0; | ||
45 | } | 44 | } |
46 | 45 | ||
47 | int | 46 | int | ... | ... |
... | @@ -25,22 +25,27 @@ | ... | @@ -25,22 +25,27 @@ |
25 | #include <mailutils/util.h> | 25 | #include <mailutils/util.h> |
26 | 26 | ||
27 | char * | 27 | char * |
28 | mu_make_file_name (const char *dir, const char *file) | 28 | mu_make_file_name_suf (const char *dir, const char *file, const char *suf) |
29 | { | 29 | { |
30 | char *tmp; | 30 | char *tmp; |
31 | size_t dirlen = strlen (dir); | 31 | size_t dirlen = strlen (dir); |
32 | size_t suflen = suf ? strlen (suf) : 0; | ||
33 | size_t fillen = strlen (file); | ||
32 | size_t len; | 34 | size_t len; |
33 | 35 | ||
34 | while (dirlen > 0 && dir[dirlen-1] == '/') | 36 | while (dirlen > 0 && dir[dirlen-1] == '/') |
35 | dirlen--; | 37 | dirlen--; |
36 | 38 | ||
37 | len = dirlen + 1 + strlen (file); | 39 | len = dirlen + 1 + fillen + suflen; |
38 | tmp = mu_alloc (len + 1); | 40 | tmp = mu_alloc (len + 1); |
39 | if (tmp) | 41 | if (tmp) |
40 | { | 42 | { |
41 | memcpy (tmp, dir, dirlen); | 43 | memcpy (tmp, dir, dirlen); |
42 | tmp[dirlen++] = '/'; | 44 | tmp[dirlen++] = '/'; |
43 | strcpy (tmp + dirlen, file); | 45 | memcpy (tmp + dirlen, file, fillen); |
46 | if (suf) | ||
47 | memcpy (tmp + dirlen + fillen, suf, suflen); | ||
48 | tmp[len] = 0; | ||
44 | } | 49 | } |
45 | return tmp; | 50 | return tmp; |
46 | } | 51 | } | ... | ... |
libmailutils/tests/tempfile.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2005, 2007, 2009, 2010 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <unistd.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <stdio.h> | ||
23 | #include <string.h> | ||
24 | #include <mailutils/util.h> | ||
25 | #include <mailutils/errno.h> | ||
26 | #include <mailutils/error.h> | ||
27 | #include <mailutils/stream.h> | ||
28 | |||
29 | char *progname; | ||
30 | |||
31 | void | ||
32 | usage (FILE *fp, int code) | ||
33 | { | ||
34 | fprintf (fp, | ||
35 | "usage: %s [-tmpdir=DIR] [-suffix=SUF] [-dry-run | -unlink] { file | dir }\n", | ||
36 | progname); | ||
37 | exit (code); | ||
38 | } | ||
39 | |||
40 | int | ||
41 | main (int argc, char **argv) | ||
42 | { | ||
43 | struct mu_tempfile_hints hints, *phints; | ||
44 | int flags = 0; | ||
45 | int fd; | ||
46 | int *pfd = &fd; | ||
47 | char *filename; | ||
48 | char **pname = &filename; | ||
49 | char *infile = NULL; | ||
50 | int verify = 0; | ||
51 | int verbose = 0; | ||
52 | |||
53 | progname = argv[0]; | ||
54 | |||
55 | if (argc == 1) | ||
56 | usage (stdout, 0); | ||
57 | |||
58 | while (--argc) | ||
59 | { | ||
60 | char *arg = *++argv; | ||
61 | |||
62 | if (strncmp (arg, "-tmpdir=", 8) == 0) | ||
63 | { | ||
64 | hints.tmpdir = arg + 8; | ||
65 | flags |= MU_TEMPFILE_TMPDIR; | ||
66 | } | ||
67 | else if (strncmp (arg, "-suffix=", 8) == 0) | ||
68 | { | ||
69 | hints.suffix = arg + 8; | ||
70 | flags |= MU_TEMPFILE_SUFFIX; | ||
71 | } | ||
72 | else if (strcmp (arg, "-dry-run") == 0) | ||
73 | pfd = NULL; | ||
74 | else if (strcmp (arg, "-unlink") == 0) | ||
75 | pname = NULL; | ||
76 | else if (strncmp (arg, "-infile=", 8) == 0) | ||
77 | infile = arg + 8; | ||
78 | else if (strncmp (arg, "-verify", 7) == 0) | ||
79 | verify = 1; | ||
80 | else if (strncmp (arg, "-verbose", 8) == 0) | ||
81 | verbose = 1; | ||
82 | else | ||
83 | break; | ||
84 | } | ||
85 | |||
86 | if (argv[0] == NULL) | ||
87 | usage (stderr, 1); | ||
88 | if (strcmp (argv[0], "file") == 0) | ||
89 | /* nothing */; | ||
90 | else if (strcmp (argv[0], "dir") == 0) | ||
91 | flags |= MU_TEMPFILE_MKDIR; | ||
92 | else | ||
93 | usage (stderr, 1); | ||
94 | |||
95 | if (pname == NULL && pfd == NULL) | ||
96 | { | ||
97 | mu_error ("both -unlink and -dry-run given"); | ||
98 | exit (1); | ||
99 | } | ||
100 | |||
101 | if (infile) | ||
102 | { | ||
103 | if (flags & MU_TEMPFILE_MKDIR) | ||
104 | { | ||
105 | mu_error ("-infile is useless with dir"); | ||
106 | exit (1); | ||
107 | } | ||
108 | else if (pfd == NULL) | ||
109 | { | ||
110 | mu_error ("-infile is useless with -dry-run"); | ||
111 | exit (1); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | if (verify && pfd == NULL) | ||
116 | { | ||
117 | mu_error ("-verify is useless with -dry-run"); | ||
118 | exit (1); | ||
119 | } | ||
120 | |||
121 | phints = flags ? &hints : NULL; | ||
122 | |||
123 | MU_ASSERT (mu_tempfile (phints, flags, pfd, pname)); | ||
124 | |||
125 | if (filename) | ||
126 | printf ("created file name %s\n", filename); | ||
127 | |||
128 | if (!pfd) | ||
129 | return 0; | ||
130 | |||
131 | if (infile) | ||
132 | { | ||
133 | mu_stream_t in, out; | ||
134 | mu_off_t size; | ||
135 | |||
136 | if (strcmp (infile, "-") == 0) | ||
137 | MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, 0)); | ||
138 | else | ||
139 | MU_ASSERT (mu_file_stream_create (&in, infile, MU_STREAM_READ)); | ||
140 | |||
141 | MU_ASSERT (mu_fd_stream_create (&out, filename, fd, MU_STREAM_WRITE)); | ||
142 | MU_ASSERT (mu_stream_copy (out, in, 0, &size)); | ||
143 | if (verbose) | ||
144 | printf ("copied %lu bytes to the temporary\n", (unsigned long) size); | ||
145 | mu_stream_unref (out); | ||
146 | mu_stream_unref (in); | ||
147 | } | ||
148 | |||
149 | if (verify) | ||
150 | { | ||
151 | mu_stream_t in, out; | ||
152 | mu_off_t size; | ||
153 | |||
154 | MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0)); | ||
155 | MU_ASSERT (mu_fd_stream_create (&in, filename, fd, | ||
156 | MU_STREAM_READ|MU_STREAM_SEEK)); | ||
157 | MU_ASSERT (mu_stream_copy (out, in, 0, &size)); | ||
158 | if (verbose) | ||
159 | printf ("dumped %lu bytes\n", (unsigned long) size); | ||
160 | mu_stream_unref (out); | ||
161 | mu_stream_unref (in); | ||
162 | } | ||
163 | |||
164 | close (fd); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 |
... | @@ -324,11 +324,19 @@ escape_run_editor (char *ed, int argc, char **argv, compose_env_t *env) | ... | @@ -324,11 +324,19 @@ escape_run_editor (char *ed, int argc, char **argv, compose_env_t *env) |
324 | if (!mailvar_get (NULL, "editheaders", mailvar_type_boolean, 0)) | 324 | if (!mailvar_get (NULL, "editheaders", mailvar_type_boolean, 0)) |
325 | { | 325 | { |
326 | char *filename; | 326 | char *filename; |
327 | int fd = mu_tempfile (NULL, &filename); | 327 | int fd; |
328 | FILE *fp = fdopen (fd, "w+"); | 328 | FILE *fp; |
329 | char buffer[512]; | 329 | char buffer[512]; |
330 | int rc; | 330 | int rc; |
331 | 331 | ||
332 | rc = mu_tempfile (NULL, 0, &fd, &filename); | ||
333 | if (rc) | ||
334 | { | ||
335 | mu_diag_funcall (MU_DIAG_ERROR, "mu_tempfile", NULL, rc); | ||
336 | return rc; | ||
337 | } | ||
338 | |||
339 | fp = fdopen (fd, "w+"); | ||
332 | dump_headers (fp, env); | 340 | dump_headers (fp, env); |
333 | 341 | ||
334 | rewind (env->file); | 342 | rewind (env->file); |
... | @@ -639,8 +647,7 @@ escape_pipe (int argc, char **argv, compose_env_t *env) | ... | @@ -639,8 +647,7 @@ escape_pipe (int argc, char **argv, compose_env_t *env) |
639 | return 1; | 647 | return 1; |
640 | } | 648 | } |
641 | 649 | ||
642 | fd = mu_tempfile (NULL, NULL); | 650 | if (mu_tempfile (NULL, 0, &fd, NULL)) |
643 | if (fd == -1) | ||
644 | return 1; | 651 | return 1; |
645 | 652 | ||
646 | if ((pid = fork ()) < 0) | 653 | if ((pid = fork ()) < 0) | ... | ... |
... | @@ -305,8 +305,18 @@ fill_body (mu_message_t msg, mu_stream_t instr) | ... | @@ -305,8 +305,18 @@ fill_body (mu_message_t msg, mu_stream_t instr) |
305 | mu_stream_t stream = NULL; | 305 | mu_stream_t stream = NULL; |
306 | mu_off_t n; | 306 | mu_off_t n; |
307 | 307 | ||
308 | mu_message_get_body (msg, &body); | 308 | rc = mu_message_get_body (msg, &body); |
309 | mu_body_get_streamref (body, &stream); | 309 | if (rc) |
310 | { | ||
311 | mu_error (_("cannot get message body: %s"), mu_strerror (rc)); | ||
312 | return 1; | ||
313 | } | ||
314 | rc = mu_body_get_streamref (body, &stream); | ||
315 | if (rc) | ||
316 | { | ||
317 | mu_error (_("cannot get body: %s"), mu_strerror (rc)); | ||
318 | return 1; | ||
319 | } | ||
310 | 320 | ||
311 | rc = mu_stream_copy (stream, instr, 0, &n); | 321 | rc = mu_stream_copy (stream, instr, 0, &n); |
312 | mu_stream_destroy (&stream); | 322 | mu_stream_destroy (&stream); |
... | @@ -428,16 +438,16 @@ int | ... | @@ -428,16 +438,16 @@ int |
428 | mail_send0 (compose_env_t * env, int save_to) | 438 | mail_send0 (compose_env_t * env, int save_to) |
429 | { | 439 | { |
430 | int done = 0; | 440 | int done = 0; |
431 | int fd; | 441 | int fd, rc; |
432 | char *filename; | 442 | char *filename; |
433 | char *savefile = NULL; | 443 | char *savefile = NULL; |
434 | int int_cnt; | 444 | int int_cnt; |
435 | char *escape; | 445 | char *escape; |
436 | 446 | ||
437 | fd = mu_tempfile (NULL, &filename); | 447 | rc = mu_tempfile (NULL, 0, &fd, &filename); |
438 | if (fd == -1) | 448 | if (rc) |
439 | { | 449 | { |
440 | util_error (_("Cannot open temporary file")); | 450 | util_error (_("Cannot open temporary file: %s"), mu_strerror (rc)); |
441 | return 1; | 451 | return 1; |
442 | } | 452 | } |
443 | 453 | ... | ... |
-
Please register or sign in to post a comment