summaryrefslogtreecommitdiffstats
path: root/fastback.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'fastback.cpp')
-rw-r--r--fastback.cpp176
1 files changed, 166 insertions, 10 deletions
diff --git a/fastback.cpp b/fastback.cpp
index 7eb62d1..efe666e 100644
--- a/fastback.cpp
+++ b/fastback.cpp
@@ -38,6 +38,11 @@ The program keeps a log of all files uploaded, where they were uploaded to, encr
#endif
#include <string>
+#include <fstream>
+#include <sstream>
+#include <ext/stdio_filebuf.h>
+
+#include <iostream>
#include <sys/types.h>
#include <regex.h>
@@ -46,6 +51,11 @@ The program keeps a log of all files uploaded, where they were uploaded to, encr
#include <argp.h>
#include <curl/curl.h>
+#include <openssl/rand.h>
+
+typedef std::string string;
+
+
static const char fastback_name[] = "fastback";
// These are command line options
@@ -64,6 +74,12 @@ static bool fastback_verbose = false;
static bool fastback_logging = false;
+// if we need to create temporary files
+// first create a temporary directory, stick it's name here
+// and delete the whole tree when we are done
+static string fastback_tmpdir;
+
+
//static const char* fastback_default_URLDIR = "ftp://dropbox.redhat.com/incoming/";
static const char* fastback_default_URLDIR = "ftp://indus.usersys.redhat.com/incoming";
@@ -78,7 +94,7 @@ fastback_read(void *buffer, size_t size, size_t nmemb, void *userp)
}
static void
-show(FILE* file, std::string url)
+show(FILE* file, string url)
{
if (fastback_URLDIR)
fprintf(file,"fastback URLDIR: %s\n", fastback_URLDIR);
@@ -108,12 +124,12 @@ show(FILE* file, std::string url)
}
static void
-check_curl_error(CURLcode err, std::string url, const char* msg)
+check_curl_error(CURLcode err, string url, const char* msg)
{
if (err)
{
show(stderr, url);
- std::string tmsg = fastback_name;
+ string tmsg = fastback_name;
tmsg += ": error: ";
tmsg += msg;
tmsg += ": ";
@@ -254,7 +270,7 @@ parse_config(const char* filename)
file = fopen(filename,"r");
if (!file)
{
- std::string msg = fastback_name;
+ string msg = fastback_name;
msg += ": error: could not open: ";
msg += filename;
perror(msg.c_str());
@@ -334,7 +350,127 @@ parse_config(const char* filename)
return config_file_error;
}
+void Error(string func, string msg)
+{
+ std::cerr << func << msg << std::endl;
+ exit(4);
+}
+void RunCommand(string cmd)
+{
+ int retcode = system(cmd.c_str());
+ if (retcode == -1)
+ {
+ Error("RunCommand:", "error: could not start subshell: " + cmd);
+ }
+ if (retcode)
+ {
+ std::ostringstream msg;
+ msg << "error: subshell failed (rc=" << retcode << "):" << cmd;
+ Error("RunCommand:", msg.str());
+ }
+}
+
+string ReadCommand(string cmd)
+{
+ FILE* fp = popen(cmd.c_str(),"r");
+ if (!fp)
+ {
+ Error("ReadCommand:", "error: could not start subshell: " + cmd);
+ }
+
+ __gnu_cxx::stdio_filebuf<char> command_output_buffer(fp, std::ios_base::in);
+ std::ostringstream output_stream;
+ output_stream << &command_output_buffer;
+
+ int retcode = pclose(fp);
+ if (retcode)
+ {
+ std::ostringstream msg;
+ msg << "error: subshell failed (rc=" << retcode << "):" << cmd;
+ Error("ReadCommand:", msg.str());
+ }
+
+ return output_stream.str();
+}
+
+static string rand_base64(int i)
+{
+ // return a string of random base64 characters of 'i' length
+ //
+ // This should probably use the openssl library (or some other
+ // library directly, but it doesn't right now
+ std::ostringstream cmd;
+ cmd << "openssl rand -base64 " << i;
+ string r = ReadCommand(cmd.str());
+ return r.substr(0,r.length()-1);
+}
+
+
+static string
+randomize_filename(string filename)
+{
+ // create (max_rand_bytes * 8) random bits encoded as base64
+ // add those bits to the filename before the first dot if any.
+ const int max_rand_bytes = 3; // 24 random bits
+ string::size_type p = filename.find_first_of('.');
+ string r = rand_base64(max_rand_bytes);
+ if (p == string::npos)
+ return filename + '-' + r;
+ else
+ return filename.substr(0,p) + '-' + r + filename.substr(p,string::npos);
+}
+
+static bool
+is_compressed(const string& filename)
+{
+ string cmd = string("file ") + filename;
+ string output = ReadCommand(cmd);
+
+ return output.find("compressed") != string::npos;
+}
+
+
+static void
+compress(const string& in_filename, const string& out_filename)
+{
+ // compress file 'in_filename' into 'out_filename'
+ // again this should probably use a library, but doesn't yet
+ string cmd = string("gzip <") + in_filename + " >" + out_filename;
+ ReadCommand(cmd);
+}
+
+static bool
+readable(string filename)
+{
+ // is 'filename' readable by the running user
+ FILE* file = fopen(filename.c_str(),"r");
+ if (file)
+ {
+ fclose(file);
+ return true;
+ }
+ return false;
+}
+
+static string
+filename_basename(const string& filename)
+{
+ return basename(filename.c_str());
+}
+
+static string
+create_temporary_file(string filename)
+{
+ // create a filename in a temporary directory
+ // for now you must make sure that the name is unique to this run
+ if (fastback_tmpdir == "")
+ {
+ char TEMPLATE[] = "/tmp/fastbackXXXXXX";
+ fastback_tmpdir = mkdtemp(TEMPLATE);
+ }
+ return fastback_tmpdir + '/' + filename;
+}
static void
cleanup()
@@ -342,6 +478,9 @@ cleanup()
free(fastback_filename);
free(fastback_ticket);
free(fastback_URLDIR);
+
+ if (fastback_tmpdir != "")
+ RunCommand(string("rm -rf " + fastback_tmpdir));
}
@@ -355,7 +494,7 @@ main(int argc, char** argv)
{
if (errno == err)
{
- std::string msg = fastback_name;
+ string msg = fastback_name;
msg += ": error: argp_parse";
perror(msg.c_str());
}
@@ -382,19 +521,36 @@ main(int argc, char** argv)
if (!fastback_URLDIR)
fastback_URLDIR = strdup(fastback_default_URLDIR);
+ if (!readable(fastback_filename))
+ {
+ string msg = fastback_name;
+ msg += ": error: could not open: ";
+ msg += fastback_filename;
+ perror(msg.c_str());
+ exit(3);
+ }
+
+ string final_filename = fastback_filename;
+ if (!is_compressed(final_filename))
+ {
+ string compressed_filename =
+ create_temporary_file(filename_basename(final_filename) + ".gz");
+ compress(final_filename,compressed_filename);
+ final_filename = compressed_filename;
+ }
CURL* handle;
CURLcode curl_err;
FILE* file;
- std::string url;
+ string url;
- file = fopen(fastback_filename,"r");
+ file = fopen(final_filename.c_str(),"r");
if (!file)
{
- std::string msg = fastback_name;
+ string msg = fastback_name;
msg += ": error: could not open: ";
- msg += fastback_filename;
+ msg += final_filename;
perror(msg.c_str());
exit(3);
}
@@ -402,7 +558,7 @@ main(int argc, char** argv)
url = fastback_URLDIR;
if (url[url.length()-1] != '/')
url += '/';
- url += basename(fastback_filename);
+ url += randomize_filename(filename_basename(final_filename.c_str()));
if (fastback_verbose)
show(stdout,url);