2 * Copyright (C) 2013 Jeremy Kerr <jk@ozlabs.org>
3 * Copyright (C) 2016 Raptor Engineering, LLC
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
9 * This program 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.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <sys/types.h>
26 #include <talloc/talloc.h>
31 #define MAX_FILENAME_SIZE 8192
32 #define FILE_XFER_BUFFER_SIZE 8192
34 static const int max_file_size = 1024 * 1024;
36 int copy_file_secure_dest(void *ctx,
37 const char *source_file, char **destination_file) {
39 char template[] = "/tmp/petitbootXXXXXX";
40 char dest_filename[MAX_FILENAME_SIZE] = "";
41 FILE *source_handle = fopen(source_file, "r");
42 int destination_fd = mkstemp(template);
43 FILE *destination_handle = fdopen(destination_fd, "w");
44 if (!source_handle || !(destination_handle)) {
46 pb_log("%s: failed: unable to open source file '%s'\n",
47 __func__, source_file);
52 unsigned char *buffer;
53 buffer = talloc_array(ctx, unsigned char, FILE_XFER_BUFFER_SIZE);
55 pb_log("%s: failed: unable to allocate file transfer buffer\n",
61 while ((l1 = fread(buffer, 1, sizeof buffer, source_handle)) > 0) {
62 size_t l2 = fwrite(buffer, 1, l1, destination_handle);
64 if (ferror(destination_handle)) {
67 pb_log("%s: failed: unknown fault\n", __func__);
70 /* No space on destination device */
72 pb_log("%s: failed: temporary storage full\n",
82 dest_filename[0] = '\0';
86 char readlink_buffer[MAX_FILENAME_SIZE];
87 snprintf(readlink_buffer, MAX_FILENAME_SIZE, "/proc/self/fd/%d",
89 r = readlink(readlink_buffer, dest_filename,
94 pb_log("%s: failed: unable to obtain temporary filename"
97 dest_filename[r] = '\0';
100 fclose(source_handle);
101 fclose(destination_handle);
103 *destination_file = talloc_strdup(ctx, dest_filename);
108 int read_file(void *ctx, const char *filename, char **bufp, int *lenp)
114 fd = open(filename, O_RDONLY);
118 rc = fstat(fd, &statbuf);
122 len = statbuf.st_size;
123 if (len > max_file_size)
126 buf = talloc_array(ctx, char, len + 1);
130 for (i = 0; i < len; i += rc) {
131 rc = read(fd, buf + i, len - i);
133 /* unexpected EOF: trim and return */
158 static int write_fd(int fd, char *buf, int len)
162 for (i = 0; i < len; i += rc) {
163 rc = write(fd, buf + i, len - i);
164 if (rc < 0 && errno != -EINTR)
171 int replace_file(const char *filename, char *buf, int len)
177 tempfile = talloc_asprintf(NULL, "%s.XXXXXX", filename);
179 oldmask = umask(0644);
180 fd = mkstemp(tempfile);
183 talloc_free(tempfile);
187 rc = write_fd(fd, buf, len);
191 rc = rename(tempfile, filename);
194 talloc_free(tempfile);