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