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, const char *source_file,
37 char **destination_file)
39 char readlink_buffer[MAX_FILENAME_SIZE + 1];
40 char dest_filename[MAX_FILENAME_SIZE] = "";
41 char template[] = "/tmp/petitbootXXXXXX";
42 FILE *destination_handle, *source_handle;
43 int destination_fd, result = 0;
44 unsigned char *buffer;
49 source_handle = fopen(source_file, "r");
51 pb_log("%s: unable to open source file '%s': %m\n",
52 __func__, source_file);
56 oldmask = umask(0644);
57 destination_fd = mkstemp(template);
59 if (destination_fd < 0) {
60 pb_log("%s: unable to create temp file, %m\n", __func__);
61 fclose(source_handle);
64 destination_handle = fdopen(destination_fd, "w");
65 if (!destination_handle) {
66 pb_log("%s: unable to open destination file, %m\n", __func__);
67 fclose(source_handle);
68 close(destination_fd);
72 buffer = talloc_array(ctx, unsigned char, FILE_XFER_BUFFER_SIZE);
74 pb_log("%s: failed: unable to allocate file transfer buffer\n",
81 while ((l1 = fread(buffer, 1, FILE_XFER_BUFFER_SIZE, source_handle)) > 0) {
82 size_t l2 = fwrite(buffer, 1, l1, destination_handle);
84 if (ferror(destination_handle)) {
87 pb_log("%s: failed: unknown fault\n", __func__);
90 /* No space on destination device */
92 pb_log("%s: failed: temporary storage full\n",
100 *destination_file = NULL;
104 snprintf(readlink_buffer, MAX_FILENAME_SIZE, "/proc/self/fd/%d",
106 r = readlink(readlink_buffer, dest_filename, MAX_FILENAME_SIZE);
108 /* readlink failed */
111 pb_log("%s: failed: unable to obtain temporary filename\n",
114 dest_filename[r] = '\0';
116 *destination_file = talloc_strdup(ctx, dest_filename);
119 fclose(source_handle);
120 fclose(destination_handle);
121 close(destination_fd);
125 int read_file(void *ctx, const char *filename, char **bufp, int *lenp)
131 fd = open(filename, O_RDONLY);
135 rc = fstat(fd, &statbuf);
139 len = statbuf.st_size;
140 if (len > max_file_size)
143 buf = talloc_array(ctx, char, len + 1);
147 for (i = 0; i < len; i += rc) {
148 rc = read(fd, buf + i, len - i);
150 /* unexpected EOF: trim and return */
175 static int write_fd(int fd, char *buf, int len)
179 for (i = 0; i < len; i += rc) {
180 rc = write(fd, buf + i, len - i);
181 if (rc < 0 && errno != -EINTR)
188 int replace_file(const char *filename, char *buf, int len)
194 tempfile = talloc_asprintf(NULL, "%s.XXXXXX", filename);
196 oldmask = umask(0644);
197 fd = mkstemp(tempfile);
200 talloc_free(tempfile);
204 rc = write_fd(fd, buf, len);
208 rc = rename(tempfile, filename);
211 talloc_free(tempfile);