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 bool decrypt_file (struct encrypted_file *enc,
50 const struct file_handle *input_filename,
51 const struct file_handle *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 = NULL;
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 input_fh = fh_create_file (NULL, input_filename, NULL, fh_default_properties ());
140 if (output_format == NULL)
142 const char *dot = strrchr (output_filename, '.');
144 error (1, 0, _("%s: cannot guess output format (use -O option)"),
147 output_format = dot + 1;
150 output_fh = fh_create_file (NULL, output_filename, NULL, fh_default_properties ());
151 if (encrypted_file_open (&enc, input_fh) > 0)
153 if (encrypted_file_is_sav (enc))
155 if (strcmp (output_format, "sav") && strcmp (output_format, "sys"))
156 error (1, 0, _("can only convert encrypted data file to sav or "
161 if (strcmp (output_format, "sps"))
162 error (1, 0, _("can only convert encrypted syntax file to sps "
166 if (! decrypt_file (enc, input_fh, output_fh, password))
173 reader = any_reader_open_and_decode (input_fh, encoding, &dict, NULL);
177 if (!strcmp (output_format, "csv") || !strcmp (output_format, "txt"))
179 struct csv_writer_options options;
181 csv_writer_options_init (&options);
182 options.include_var_names = true;
183 writer = csv_writer_open (output_fh, dict, &options);
185 else if (!strcmp (output_format, "sav") || !strcmp (output_format, "sys"))
187 struct sfm_write_options options;
189 options = sfm_writer_default_options ();
190 writer = sfm_open_writer (output_fh, dict, options);
192 else if (!strcmp (output_format, "por"))
194 struct pfm_write_options options;
196 options = pfm_writer_default_options ();
197 writer = pfm_open_writer (output_fh, dict, options);
201 error (1, 0, _("%s: unknown output format (use -O option)"),
206 for (i = 0; i < max_cases; i++)
210 c = casereader_read (reader);
214 casewriter_write (writer, c);
217 if (!casereader_destroy (reader))
218 error (1, 0, _("%s: error reading input file"), input_filename);
219 if (!casewriter_destroy (writer))
220 error (1, 0, _("%s: error writing output file"), output_filename);
224 fh_unref (output_fh);
233 fh_unref (output_fh);
242 decrypt_file (struct encrypted_file *enc,
243 const struct file_handle *ifh,
244 const struct file_handle *ofh,
245 const char *password)
249 const char *input_filename = fh_get_file_name (ifh);
250 const char *output_filename = fh_get_file_name (ofh);
252 if (password == NULL)
254 password = getpass ("password: ");
255 if (password == NULL)
259 if (!encrypted_file_unlock (enc, password))
260 error (1, 0, _("sorry, wrong password"));
262 out = fn_open (ofh, "wb");
264 error (1, errno, ("%s: error opening output file"), output_filename);
268 uint8_t buffer[1024];
271 n = encrypted_file_read (enc, buffer, sizeof buffer);
275 if (fwrite (buffer, 1, n, out) != n)
276 error (1, errno, ("%s: write error"), output_filename);
279 err = encrypted_file_close (enc);
281 error (1, err, ("%s: read error"), input_filename);
283 if (fflush (out) == EOF)
284 error (1, errno, ("%s: write error"), output_filename);
294 %s, a utility for converting SPSS data files to other formats.\n\
295 Usage: %s [OPTION]... INPUT OUTPUT\n\
296 where INPUT is an SPSS data file or encrypted syntax file\n\
297 and OUTPUT is the name of the desired output file.\n\
299 The desired format of OUTPUT is by default inferred from its extension:\n\
300 csv txt comma-separated value\n\
301 sav sys SPSS system file\n\
302 por SPSS portable file\n\
303 sps SPSS syntax file (encrypted syntax input files only)\n\
306 -O, --output-format=FORMAT set specific output format, where FORMAT\n\
307 is one of the extensions listed above\n\
308 -e, --encoding=CHARSET override encoding of input data file\n\
309 -c MAXCASES limit number of cases to copy (default is all cases)\n\
310 -p PASSWORD password for encrypted files\n\
311 --help display this help and exit\n\
312 --version output version information and exit\n",
313 program_name, program_name);