/* PSPP - a program for statistical analysis.
- Copyright (C) 2013 Free Software Foundation, Inc.
+ Copyright (C) 2013, 2014 Free Software Foundation, Inc.
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 <config.h>
+#include <errno.h>
#include <getopt.h>
#include <limits.h>
#include <stdlib.h>
+#include <unistd.h>
#include "data/any-reader.h"
#include "data/casereader.h"
#include "data/casewriter.h"
#include "data/csv-file-writer.h"
+#include "data/file-name.h"
#include "data/por-file-writer.h"
#include "data/settings.h"
+#include "data/sys-file-encryption.h"
#include "data/sys-file-writer.h"
#include "data/file-handle-def.h"
#include "libpspp/assertion.h"
#include "libpspp/i18n.h"
#include "gl/error.h"
+#include "gl/getpass.h"
#include "gl/progname.h"
#include "gl/version-etc.h"
static void usage (void);
+static void decrypt_sav_file (struct encrypted_sys_file *enc,
+ const char *input_filename,
+ const char *output_filename,
+ const char *password);
+
int
main (int argc, char *argv[])
{
struct casereader *reader;
struct file_handle *input_fh;
const char *encoding = NULL;
+ struct encrypted_sys_file *enc;
const char *output_format = NULL;
struct file_handle *output_fh;
struct casewriter *writer;
+ const char *password = NULL;
long long int i;
{
{ "cases", required_argument, NULL, 'c' },
{ "encoding", required_argument, NULL, 'e' },
+ { "password", required_argument, NULL, 'p' },
{ "output-format", required_argument, NULL, 'O' },
int c;
- c = getopt_long (argc, argv, "c:e:O:hv", long_options, NULL);
+ c = getopt_long (argc, argv, "c:e:p:O:hv", long_options, NULL);
if (c == -1)
break;
encoding = optarg;
break;
+ case 'p':
+ password = optarg;
+ break;
+
case 'O':
output_format = optarg;
break;
output_format = dot + 1;
}
+ if (encrypted_sys_file_open (&enc, input_filename) > 0)
+ {
+ if (strcmp (output_format, "sav") && strcmp (output_format, "sys"))
+ error (1, 0, _("can only convert encrypted data file to sav or sys "
+ "format"));
+
+ decrypt_sav_file (enc, input_filename, output_filename, password);
+ goto exit;
+ }
+
input_fh = fh_create_file (NULL, input_filename, fh_default_properties ());
- reader = any_reader_open (input_fh, encoding, &dict);
+ reader = any_reader_open_and_decode (input_fh, encoding, &dict, NULL);
if (reader == NULL)
exit (1);
if (!casewriter_destroy (writer))
error (1, 0, _("%s: error writing output file"), output_filename);
+exit:
fh_done ();
i18n_done ();
return 0;
}
+static void
+decrypt_sav_file (struct encrypted_sys_file *enc,
+ const char *input_filename,
+ const char *output_filename,
+ const char *password)
+{
+ FILE *out;
+ int err;
+
+ if (password == NULL)
+ {
+ password = getpass ("password: ");
+ if (password == NULL)
+ exit (1);
+ }
+
+ if (!encrypted_sys_file_unlock (enc, password))
+ error (1, 0, _("sorry, wrong password"));
+
+ out = fn_open (output_filename, "wb");
+ if (out == NULL)
+ error (1, errno, ("%s: error opening output file"), output_filename);
+
+ for (;;)
+ {
+ uint8_t buffer[1024];
+ size_t n;
+
+ n = encrypted_sys_file_read (enc, buffer, sizeof buffer);
+ if (n == 0)
+ break;
+
+ if (fwrite (buffer, 1, n, out) != n)
+ error (1, errno, ("%s: write error"), output_filename);
+ }
+
+ err = encrypted_sys_file_close (enc);
+ if (err)
+ error (1, err, ("%s: read error"), input_filename);
+
+ if (fflush (out) == EOF)
+ error (1, errno, ("%s: write error"), output_filename);
+ fn_close (output_filename, out);
+}
+
static void
usage (void)
{
is one of the extensions listed above\n\
-e, --encoding=CHARSET override encoding of input data file\n\
-c MAXCASES limit number of cases to copy (default is all cases)\n\
+ -p PASSWORD password for encrypted .sav files\n\
--help display this help and exit\n\
--version output version information and exit\n",
program_name, program_name);