1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2009-2021 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This library 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 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser 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 <string.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24
25 #include <mailutils/types.h>
26 #include <mailutils/alloc.h>
27 #include <mailutils/error.h>
28 #include <mailutils/errno.h>
29 #include <mailutils/nls.h>
30 #include <mailutils/stream.h>
31 #include <mailutils/sys/stream.h>
32 #include <mailutils/sys/temp_file_stream.h>
33 #include <mailutils/util.h>
34
35
36 static int
fd_temp_open(struct _mu_stream * str)37 fd_temp_open (struct _mu_stream *str)
38 {
39 struct _mu_temp_file_stream *fstr = (struct _mu_temp_file_stream *) str;
40 return mu_tempfile (&fstr->hints, fstr->hflags, &fstr->stream.fd, NULL);
41 }
42
43 static void
fd_temp_done(struct _mu_stream * str)44 fd_temp_done (struct _mu_stream *str)
45 {
46 struct _mu_temp_file_stream *fstr = (struct _mu_temp_file_stream *) str;
47 if (fstr->hflags & MU_TEMPFILE_TMPDIR)
48 free (fstr->hints.tmpdir);
49 if (fstr->hflags & MU_TEMPFILE_SUFFIX)
50 free (fstr->hints.suffix);
51 if (fstr->file_done)
52 fstr->file_done (&fstr->stream.stream);
53 }
54
55 int
mu_temp_file_stream_create(mu_stream_t * pstream,struct mu_tempfile_hints * hints,int flags)56 mu_temp_file_stream_create (mu_stream_t *pstream,
57 struct mu_tempfile_hints *hints, int flags)
58 {
59 int rc;
60 struct _mu_file_stream *str;
61 mu_stream_t stream;
62
63 if (flags && !hints)
64 return EINVAL;
65 rc = _mu_file_stream_create (&str,
66 sizeof (struct _mu_temp_file_stream),
67 NULL,
68 -1,
69 MU_STREAM_RDWR | MU_STREAM_SEEK |
70 MU_STREAM_CREAT);
71 if (rc == 0)
72 {
73 struct _mu_temp_file_stream *tstr = (struct _mu_temp_file_stream *)str;
74 tstr->stream.stream.open = fd_temp_open;
75 tstr->file_done = tstr->stream.stream.done;
76 tstr->stream.stream.done = fd_temp_done;
77
78 if ((flags & MU_TEMPFILE_TMPDIR) &&
79 (tstr->hints.tmpdir = strdup (hints->tmpdir)) == NULL)
80 {
81 mu_stream_unref ((mu_stream_t) str);
82 return ENOMEM;
83 }
84 if ((flags & MU_TEMPFILE_SUFFIX) &&
85 (tstr->hints.suffix = strdup (hints->suffix)) == NULL)
86 {
87 mu_stream_unref ((mu_stream_t) str);
88 return ENOMEM;
89 }
90 tstr->hflags = flags & ~MU_TEMPFILE_MKDIR;
91
92 str->flags = _MU_FILE_STREAM_TEMP;
93 stream = (mu_stream_t) str;
94 rc = mu_stream_open (stream);
95 if (rc)
96 mu_stream_unref (stream);
97 else
98 {
99 mu_stream_set_buffer (stream, mu_buffer_full, 0);
100 *pstream = stream;
101 }
102 }
103 return rc;
104 }
105