]> git.ozlabs.org Git - petitboot/blobdiff - lib/file/file.c
configure.ac: Fix unmatched brackets
[petitboot] / lib / file / file.c
index 1bde9fb805ba906c95ca4ec24df9d1dc921994af..0d187887c701f75183fcec4550f33cb292a9198a 100644 (file)
@@ -1,5 +1,6 @@
 /*
  *  Copyright (C) 2013 Jeremy Kerr <jk@ozlabs.org>
+ *  Copyright (C) 2016 Raptor Engineering, LLC
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
 #include <sys/types.h>
 
 #include <talloc/talloc.h>
+#include <log/log.h>
 
 #include "file.h"
 
+#define MAX_FILENAME_SIZE      8192
+#define FILE_XFER_BUFFER_SIZE  8192
+
 static const int max_file_size = 1024 * 1024;
 
+int copy_file_secure_dest(void *ctx, const char *source_file,
+               char **destination_file)
+{
+       char readlink_buffer[MAX_FILENAME_SIZE + 1];
+       char dest_filename[MAX_FILENAME_SIZE] = "";
+       char template[] = "/tmp/petitbootXXXXXX";
+       FILE *destination_handle, *source_handle;
+       int destination_fd, result = 0;
+       unsigned char *buffer;
+       ssize_t r;
+       size_t l1;
+       mode_t oldmask;
+
+       source_handle = fopen(source_file, "r");
+       if (!source_handle) {
+               pb_log("%s: unable to open source file '%s': %m\n",
+                       __func__, source_file);
+                       return -1;
+       }
+
+       oldmask = umask(0644);
+       destination_fd = mkstemp(template);
+       umask(oldmask);
+       if (destination_fd < 0) {
+               pb_log("%s: unable to create temp file, %m\n", __func__);
+               fclose(source_handle);
+               return -1;
+       }
+       destination_handle = fdopen(destination_fd, "w");
+       if (!destination_handle) {
+               pb_log("%s: unable to open destination file, %m\n", __func__);
+               fclose(source_handle);
+               close(destination_fd);
+               return -1;
+       }
+
+       buffer = talloc_array(ctx, unsigned char, FILE_XFER_BUFFER_SIZE);
+       if (!buffer) {
+               pb_log("%s: failed: unable to allocate file transfer buffer\n",
+                       __func__);
+               result = -1;
+               goto out;
+       }
+
+       /* Copy data */
+       while ((l1 = fread(buffer, 1, FILE_XFER_BUFFER_SIZE, source_handle)) > 0) {
+               size_t l2 = fwrite(buffer, 1, l1, destination_handle);
+               if (l2 < l1) {
+                       if (ferror(destination_handle)) {
+                               /* General error */
+                               result = -1;
+                               pb_log("%s: failed: unknown fault\n", __func__);
+                       }
+                       else {
+                               /* No space on destination device */
+                               result = -1;
+                               pb_log("%s: failed: temporary storage full\n",
+                                       __func__);
+                       }
+                       break;
+               }
+       }
+
+       if (result) {
+               *destination_file = NULL;
+               goto out;
+       }
+
+       snprintf(readlink_buffer, MAX_FILENAME_SIZE, "/proc/self/fd/%d",
+               destination_fd);
+       r = readlink(readlink_buffer, dest_filename, MAX_FILENAME_SIZE);
+       if (r < 0) {
+               /* readlink failed */
+               result = -1;
+               r = 0;
+               pb_log("%s: failed: unable to obtain temporary filename\n",
+                       __func__);
+       }
+       dest_filename[r] = '\0';
+
+       *destination_file = talloc_strdup(ctx, dest_filename);
+out:
+       talloc_free(buffer);
+       fclose(source_handle);
+       fclose(destination_handle);
+       close(destination_fd);
+       return result;
+}
+
 int read_file(void *ctx, const char *filename, char **bufp, int *lenp)
 {
        struct stat statbuf;