1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2013, 2014, 2015 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
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, see <http://www.gnu.org/licenses/>. */
25 #include "data/any-reader.h"
26 #include "data/casereader.h"
27 #include "data/casewriter.h"
28 #include "data/csv-file-writer.h"
29 #include "data/encrypted-file.h"
30 #include "data/file-name.h"
31 #include "data/por-file-writer.h"
32 #include "data/settings.h"
33 #include "data/sys-file-writer.h"
34 #include "data/file-handle-def.h"
35 #include "libpspp/assertion.h"
36 #include "libpspp/cast.h"
37 #include "libpspp/i18n.h"
40 #include "gl/getpass.h"
41 #include "gl/progname.h"
42 #include "gl/version-etc.h"
45 #define _(msgid) gettext (msgid)
47 static void usage (void);
49 static void decrypt_file (struct encrypted_file *enc,
50 const char *input_filename,
51 const char *output_filename,
52 const char *password);
55 main (int argc, char *argv[])
57 const char *input_filename;
58 const char *output_filename;
60 long long int max_cases = LLONG_MAX;
61 struct dictionary *dict;
62 struct casereader *reader;
63 struct file_handle *input_fh;
64 const char *encoding = NULL;
65 struct encrypted_file *enc;
67 const char *output_format = NULL;
68 struct file_handle *output_fh;
69 struct casewriter *writer;
70 const char *password = NULL;
74 set_program_name (argv[0]);
81 static const struct option long_options[] =
83 { "cases", required_argument, NULL, 'c' },
84 { "encoding", required_argument, NULL, 'e' },
85 { "password", required_argument, NULL, 'p' },
87 { "output-format", required_argument, NULL, 'O' },
89 { "help", no_argument, NULL, 'h' },
90 { "version", no_argument, NULL, 'v' },
96 c = getopt_long (argc, argv, "c:e:p:O:hv", long_options, NULL);
103 max_cases = strtoull (optarg, NULL, 0);
115 output_format = optarg;
119 version_etc (stdout, "pspp-convert", PACKAGE_NAME, PACKAGE_VERSION,
120 "Ben Pfaff", "John Darrington", NULL_SENTINEL);
132 if (optind + 2 != argc)
133 error (1, 0, _("exactly two non-option arguments are required; "
134 "use --help for help"));
136 input_filename = argv[optind];
137 output_filename = argv[optind + 1];
138 if (output_format == NULL)
140 const char *dot = strrchr (output_filename, '.');
142 error (1, 0, _("%s: cannot guess output format (use -O option)"),
145 output_format = dot + 1;
148 if (encrypted_file_open (&enc, input_filename) > 0)
150 if (encrypted_file_is_sav (enc))
152 if (strcmp (output_format, "sav") && strcmp (output_format, "sys"))
153 error (1, 0, _("can only convert encrypted data file to sav or "
158 if (strcmp (output_format, "sps"))
159 error (1, 0, _("can only convert encrypted syntax file to sps "
163 decrypt_file (enc, input_filename, output_filename, password);
167 input_fh = fh_create_file (NULL, input_filename, NULL, fh_default_properties ());
168 reader = any_reader_open_and_decode (input_fh, encoding, &dict, NULL);
172 output_fh = fh_create_file (NULL, output_filename, NULL, fh_default_properties ());
173 if (!strcmp (output_format, "csv") || !strcmp (output_format, "txt"))
175 struct csv_writer_options options;
177 csv_writer_options_init (&options);
178 options.include_var_names = true;
179 writer = csv_writer_open (output_fh, dict, &options);
181 else if (!strcmp (output_format, "sav") || !strcmp (output_format, "sys"))
183 struct sfm_write_options options;
185 options = sfm_writer_default_options ();
186 writer = sfm_open_writer (output_fh, dict, options);
188 else if (!strcmp (output_format, "por"))
190 struct pfm_write_options options;
192 options = pfm_writer_default_options ();
193 writer = pfm_open_writer (output_fh, dict, options);
197 error (1, 0, _("%s: unknown output format (use -O option)"),
202 for (i = 0; i < max_cases; i++)
206 c = casereader_read (reader);
210 casewriter_write (writer, c);
213 if (!casereader_destroy (reader))
214 error (1, 0, _("%s: error reading input file"), input_filename);
215 if (!casewriter_destroy (writer))
216 error (1, 0, _("%s: error writing output file"), output_filename);
226 decrypt_file (struct encrypted_file *enc,
227 const char *input_filename,
228 const char *output_filename,
229 const char *password)
234 if (password == NULL)
236 password = getpass ("password: ");
237 if (password == NULL)
241 if (!encrypted_file_unlock (enc, password))
242 error (1, 0, _("sorry, wrong password"));
244 out = fn_open (output_filename, "wb");
246 error (1, errno, ("%s: error opening output file"), output_filename);
250 uint8_t buffer[1024];
253 n = encrypted_file_read (enc, buffer, sizeof buffer);
257 if (fwrite (buffer, 1, n, out) != n)
258 error (1, errno, ("%s: write error"), output_filename);
261 err = encrypted_file_close (enc);
263 error (1, err, ("%s: read error"), input_filename);
265 if (fflush (out) == EOF)
266 error (1, errno, ("%s: write error"), output_filename);
267 fn_close (output_filename, out);
274 %s, a utility for converting SPSS data files to other formats.\n\
275 Usage: %s [OPTION]... INPUT OUTPUT\n\
276 where INPUT is an SPSS data file or encrypted syntax file\n\
277 and OUTPUT is the name of the desired output file.\n\
279 The desired format of OUTPUT is by default inferred from its extension:\n\
280 csv txt comma-separated value\n\
281 sav sys SPSS system file\n\
282 por SPSS portable file\n\
283 sps SPSS syntax file (encrypted syntax input files only)\n\
286 -O, --output-format=FORMAT set specific output format, where FORMAT\n\
287 is one of the extensions listed above\n\
288 -e, --encoding=CHARSET override encoding of input data file\n\
289 -c MAXCASES limit number of cases to copy (default is all cases)\n\
290 -p PASSWORD password for encrypted files\n\
291 --help display this help and exit\n\
292 --version output version information and exit\n",
293 program_name, program_name);