po: Update translations from translationproject.org.
[pspp.git] / utilities / pspp-convert.c
blobebd340ec3599e3cf942fa0e015a09d51c4c10e56
1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2013, 2014 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/>. */
17 #include <config.h>
19 #include <errno.h>
20 #include <getopt.h>
21 #include <limits.h>
22 #include <stdlib.h>
23 #include <unistd.h>
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/file-name.h"
30 #include "data/por-file-writer.h"
31 #include "data/settings.h"
32 #include "data/sys-file-encryption.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"
39 #include "gl/error.h"
40 #include "gl/getpass.h"
41 #include "gl/progname.h"
42 #include "gl/version-etc.h"
44 #include "gettext.h"
45 #define _(msgid) gettext (msgid)
47 static void usage (void);
49 static void decrypt_sav_file (struct encrypted_sys_file *enc,
50 const char *input_filename,
51 const char *output_filename,
52 const char *password);
54 int
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_sys_file *enc;
67 const char *output_format = NULL;
68 struct file_handle *output_fh;
69 struct casewriter *writer;
70 const char *password = NULL;
72 long long int i;
74 set_program_name (argv[0]);
75 i18n_init ();
76 fh_init ();
77 settings_init ();
79 for (;;)
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' },
91 { NULL, 0, NULL, 0 },
94 int c;
96 c = getopt_long (argc, argv, "c:e:p:O:hv", long_options, NULL);
97 if (c == -1)
98 break;
100 switch (c)
102 case 'c':
103 max_cases = strtoull (optarg, NULL, 0);
104 break;
106 case 'e':
107 encoding = optarg;
108 break;
110 case 'p':
111 password = optarg;
112 break;
114 case 'O':
115 output_format = optarg;
116 break;
118 case 'v':
119 version_etc (stdout, "pspp-convert", PACKAGE_NAME, PACKAGE_VERSION,
120 "Ben Pfaff", "John Darrington", NULL_SENTINEL);
121 exit (EXIT_SUCCESS);
123 case 'h':
124 usage ();
125 exit (EXIT_SUCCESS);
127 default:
128 exit (EXIT_FAILURE);
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, '.');
141 if (dot == NULL)
142 error (1, 0, _("%s: cannot guess output format (use -O option)"),
143 output_filename);
145 output_format = dot + 1;
148 if (encrypted_sys_file_open (&enc, input_filename) > 0)
150 if (strcmp (output_format, "sav") && strcmp (output_format, "sys"))
151 error (1, 0, _("can only convert encrypted data file to sav or sys "
152 "format"));
154 decrypt_sav_file (enc, input_filename, output_filename, password);
155 goto exit;
158 input_fh = fh_create_file (NULL, input_filename, fh_default_properties ());
159 reader = any_reader_open_and_decode (input_fh, encoding, &dict, NULL);
160 if (reader == NULL)
161 exit (1);
163 output_fh = fh_create_file (NULL, output_filename, fh_default_properties ());
164 if (!strcmp (output_format, "csv") || !strcmp (output_format, "txt"))
166 struct csv_writer_options options;
168 csv_writer_options_init (&options);
169 options.include_var_names = true;
170 writer = csv_writer_open (output_fh, dict, &options);
172 else if (!strcmp (output_format, "sav") || !strcmp (output_format, "sys"))
174 struct sfm_write_options options;
176 options = sfm_writer_default_options ();
177 writer = sfm_open_writer (output_fh, dict, options);
179 else if (!strcmp (output_format, "por"))
181 struct pfm_write_options options;
183 options = pfm_writer_default_options ();
184 writer = pfm_open_writer (output_fh, dict, options);
186 else
188 error (1, 0, _("%s: unknown output format (use -O option)"),
189 output_filename);
190 NOT_REACHED ();
193 for (i = 0; i < max_cases; i++)
195 struct ccase *c;
197 c = casereader_read (reader);
198 if (c == NULL)
199 break;
201 casewriter_write (writer, c);
204 if (!casereader_destroy (reader))
205 error (1, 0, _("%s: error reading input file"), input_filename);
206 if (!casewriter_destroy (writer))
207 error (1, 0, _("%s: error writing output file"), output_filename);
209 exit:
210 fh_done ();
211 i18n_done ();
213 return 0;
216 static void
217 decrypt_sav_file (struct encrypted_sys_file *enc,
218 const char *input_filename,
219 const char *output_filename,
220 const char *password)
222 FILE *out;
223 int err;
225 if (password == NULL)
227 password = getpass ("password: ");
228 if (password == NULL)
229 exit (1);
232 if (!encrypted_sys_file_unlock (enc, password))
233 error (1, 0, _("sorry, wrong password"));
235 out = fn_open (output_filename, "wb");
236 if (out == NULL)
237 error (1, errno, ("%s: error opening output file"), output_filename);
239 for (;;)
241 uint8_t buffer[1024];
242 size_t n;
244 n = encrypted_sys_file_read (enc, buffer, sizeof buffer);
245 if (n == 0)
246 break;
248 if (fwrite (buffer, 1, n, out) != n)
249 error (1, errno, ("%s: write error"), output_filename);
252 err = encrypted_sys_file_close (enc);
253 if (err)
254 error (1, err, ("%s: read error"), input_filename);
256 if (fflush (out) == EOF)
257 error (1, errno, ("%s: write error"), output_filename);
258 fn_close (output_filename, out);
261 static void
262 usage (void)
264 printf ("\
265 %s, a utility for converting SPSS data files to other formats.\n\
266 Usage: %s [OPTION]... INPUT OUTPUT\n\
267 where INPUT is an SPSS system or portable file\n\
268 and OUTPUT is the name of the desired output file.\n\
270 The desired format of OUTPUT is by default inferred from its extension:\n\
271 csv txt comma-separated value\n\
272 sav sys SPSS system file\n\
273 por SPSS portable file\n\
275 Options:\n\
276 -O, --output-format=FORMAT set specific output format, where FORMAT\n\
277 is one of the extensions listed above\n\
278 -e, --encoding=CHARSET override encoding of input data file\n\
279 -c MAXCASES limit number of cases to copy (default is all cases)\n\
280 -p PASSWORD password for encrypted .sav files\n\
281 --help display this help and exit\n\
282 --version output version information and exit\n",
283 program_name, program_name);