Line data Source code
1 : /* Functions for reading a writing resume file lines.
2 :
3 : Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2010, 2011, 2012
4 : Paul Zimmermann, Alexander Kruppa and Cyril Bouvier.
5 :
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or (at your
9 : option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful, but
12 : WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 : or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 : more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program; see the file COPYING. If not, see
18 : http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
19 : 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
20 :
21 : #include <stdio.h>
22 : #include <stdlib.h>
23 : #include <time.h>
24 : #include <math.h>
25 : #include <string.h>
26 : #if !defined (_MSC_VER)
27 : #include <unistd.h>
28 : #endif
29 : #include <gmp.h>
30 : #include "ecm.h"
31 : #include "ecm-ecm.h"
32 : #ifdef HAVE_FCNTL_H
33 : #include <fcntl.h>
34 : #endif
35 :
36 : #if defined (_MSC_VER) || defined (__MINGW32__)
37 : /* needed to declare GetComputerName() for write_resumefile_line() */
38 : #include <windows.h>
39 : #endif
40 :
41 : /* Reads a string of characters from fd while they match the string s.
42 : Returns the number of matching characters that were read.
43 : */
44 :
45 : static int
46 5546 : facceptstr (FILE *fd, char *s)
47 : {
48 : int c;
49 5546 : unsigned i = 0;
50 :
51 9495 : while (s[i] != 0 && (c = fgetc (fd)) != EOF)
52 : {
53 5584 : if (c != s[i++])
54 : {
55 1635 : ungetc (c, fd);
56 1635 : return i-1;
57 : }
58 : }
59 :
60 3911 : return i;
61 : }
62 :
63 : /* Accepts "\n" or "\r\n" or "\r".
64 : Returns 1 if any of the three was read, 0 otherwise */
65 :
66 : static int
67 6022 : facceptnl (FILE *fd)
68 : {
69 6022 : int c, r = 0;
70 :
71 6022 : c = fgetc (fd);
72 6022 : if (c == '\r')
73 : {
74 30 : c = fgetc (fd);
75 30 : r = 1;
76 : }
77 :
78 6022 : if (c == '\n')
79 277 : r = 1;
80 5745 : else if (c != EOF)
81 5538 : ungetc (c, fd);
82 :
83 6022 : return r;
84 : }
85 :
86 : /* Reads a string from fd until the character "delim" or newline is seen, or
87 : "len" characters have been written to "s" (including terminating null),
88 : or EOF is reached. The "delim" and newline characters are left on the
89 : stream.
90 : If s is NULL, characters are read from fd but not written anywhere.
91 : Returns the number of characters read.
92 : */
93 :
94 : static int
95 1586 : freadstrn (FILE *fd, char *s, char delim, unsigned int len)
96 : {
97 1586 : unsigned int i = 0;
98 : int c;
99 :
100 10747 : while (i + 1 < len && (c = fgetc (fd)) != EOF)
101 10717 : if (c == delim || IS_NEWLINE(c))
102 : {
103 1556 : ungetc (c, fd);
104 1556 : break;
105 : }
106 : else
107 9161 : if (s != NULL)
108 9161 : s[i++] = (char) c;
109 :
110 1586 : if (i < len && s != NULL)
111 1586 : s[i++] = 0;
112 :
113 1586 : return i;
114 : }
115 :
116 : /* Reads an assignment from a save file. Return 1 if an assignment was
117 : successfully read, 0 if there are no more lines to read (at EOF)
118 : */
119 :
120 : int
121 314 : read_resumefile_line (int *method, mpz_t x, mpz_t y, mpcandi_t *n,
122 : mpz_t sigma, mpz_t A,
123 : mpz_t x0, mpz_t y0, int *Etype, int *param,
124 : double *b1, char *program, char *who, char *rtime,
125 : char *comment, FILE *fd)
126 : {
127 : int a, have_method, have_x, have_y, have_z, have_n, have_sigma, have_a,
128 : have_b1, have_checksum, have_qx;
129 : unsigned int saved_checksum;
130 : char tag[16];
131 : mpz_t z;
132 :
133 484 : while (!feof (fd))
134 : {
135 : /* Ignore empty lines */
136 464 : if (facceptnl (fd))
137 20 : continue;
138 :
139 : /* Ignore lines beginning with '#'*/
140 444 : if (facceptstr (fd, "#"))
141 : {
142 460 : while (!facceptnl (fd) && !feof (fd))
143 450 : fgetc (fd);
144 10 : continue;
145 : }
146 :
147 434 : if (feof (fd))
148 187 : break;
149 :
150 247 : have_method = have_x = have_y = have_z = have_n = have_sigma = have_a =
151 247 : have_b1 = have_qx = have_checksum = 0;
152 :
153 : /* For compatibility reason, param = ECM_PARAM_SUYAMA by default */
154 247 : *param = ECM_PARAM_SUYAMA;
155 :
156 : /* default and compatibility reasons */
157 247 : *Etype = ECM_EC_TYPE_MONTGOMERY;
158 :
159 : /* Set optional fields to zero */
160 247 : mpz_set_ui (sigma, 0);
161 247 : mpz_set_ui (A, 0);
162 247 : if (program != NULL)
163 247 : program[0] = 0;
164 247 : if (who != NULL)
165 247 : who[0] = 0;
166 247 : if (rtime != NULL)
167 247 : rtime[0] = 0;
168 247 : if (comment != NULL)
169 247 : comment[0] = 0;
170 :
171 1498 : while (!facceptnl (fd) && !feof (fd))
172 : {
173 1351 : freadstrn (fd, tag, '=', 16);
174 :
175 1351 : if (!facceptstr (fd, "="))
176 : {
177 30 : printf ("Resume warning, skipping line with no '=' after: %s\n", tag);
178 30 : goto error;
179 : }
180 :
181 1321 : if (strcmp (tag, "METHOD") == 0)
182 : {
183 145 : if (facceptstr (fd, "ECM") == 3)
184 90 : *method = ECM_ECM;
185 55 : else if (facceptstr (fd, "P"))
186 : {
187 45 : a = facceptstr (fd, "-1");
188 45 : if (a == 2)
189 35 : *method = ECM_PM1;
190 10 : else if (a == 0 && facceptstr (fd, "+1") == 2)
191 10 : *method = ECM_PP1;
192 : else
193 0 : goto error;
194 : }
195 : else
196 10 : goto error;
197 :
198 135 : have_method = 1;
199 : }
200 1176 : else if (strcmp (tag, "X") == 0)
201 : {
202 115 : mpz_inp_str (x, fd, 0);
203 115 : have_x = 1;
204 : }
205 1061 : else if (strcmp (tag, "Y") == 0)
206 : {
207 75 : mpz_inp_str (y, fd, 0);
208 75 : have_y = 1;
209 : }
210 986 : else if (strcmp (tag, "Z") == 0)
211 : {
212 10 : mpz_init (z);
213 10 : mpz_inp_str (z, fd, 0);
214 10 : have_z = 1;
215 : }
216 976 : else if (strcmp (tag, "QX") == 0)
217 : {
218 42 : mpz_inp_str (x, fd, 0);
219 42 : have_qx = 1;
220 : }
221 934 : else if (strcmp (tag, "X0") == 0)
222 : {
223 75 : mpz_inp_str (x0, fd, 0);
224 : }
225 859 : else if (strcmp (tag, "Y0") == 0)
226 : {
227 75 : mpz_inp_str (y0, fd, 0);
228 : }
229 784 : else if (strcmp (tag, "CHECKSUM") == 0)
230 : {
231 85 : if (fscanf (fd, "%u", &saved_checksum) != 1)
232 10 : goto error;
233 75 : have_checksum = 1;
234 : }
235 699 : else if (strcmp (tag, "COMMENT") == 0)
236 : {
237 10 : freadstrn (fd, comment, ';', 255);
238 : }
239 689 : else if (strcmp (tag, "N") == 0)
240 : {
241 : /*mpz_inp_str (n, fd, 0);*/
242 : /* we want to "maintain" any expressions, which were possibly stored in the file for N */
243 157 : have_n = read_number (n, fd, 0);
244 : }
245 532 : else if (strcmp (tag, "SIGMA") == 0)
246 : {
247 52 : mpz_inp_str (sigma, fd, 0);
248 52 : have_sigma = 1;
249 : }
250 480 : else if (strcmp (tag, "PARAM") == 0)
251 : {
252 50 : if (fscanf (fd, "%d", param) != 1)
253 10 : goto error;
254 : }
255 430 : else if (strcmp (tag, "ETYPE") == 0)
256 : {
257 30 : if (fscanf (fd, "%d", Etype) != 1)
258 10 : goto error;
259 : }
260 400 : else if (strcmp (tag, "A") == 0)
261 : {
262 30 : mpz_inp_str (A, fd, 0);
263 30 : have_a = 1;
264 : }
265 370 : else if (strcmp (tag, "B1") == 0)
266 : {
267 135 : if (fscanf (fd, "%lf", b1) != 1)
268 10 : goto error;
269 125 : have_b1 = 1;
270 : }
271 235 : else if (strcmp (tag, "PROGRAM") == 0)
272 : {
273 75 : freadstrn (fd, program, ';', 255);
274 : }
275 160 : else if (strcmp (tag, "WHO") == 0)
276 : {
277 75 : freadstrn (fd, who, ';', 255);
278 : }
279 85 : else if (strcmp (tag, "TIME") == 0)
280 : {
281 75 : freadstrn (fd, rtime, ';', 255);
282 : }
283 : else /* Not a tag we know about */
284 : {
285 10 : printf ("Save file line has unknown tag: %s\n", tag);
286 10 : goto error;
287 : }
288 :
289 : /* Prime95 lines have no semicolon after SIGMA */
290 1261 : if (!facceptstr (fd, ";") && ! (have_qx && have_n && have_sigma))
291 : {
292 10 : printf ("%s field not followed by semicolon\n", tag);
293 10 : goto error;
294 : }
295 :
296 2235 : while (facceptstr (fd, " "));
297 : }
298 :
299 : /* Finished reading tags */
300 :
301 : /* Handle Prime95 v22 lines. These have no METHOD=ECM field and
302 : QX= instead of X= */
303 :
304 147 : if (have_qx)
305 : {
306 42 : if (have_n && have_sigma)
307 : {
308 22 : *method = ECM_ECM;
309 : /* *b1 = 1.0; */
310 22 : strcpy (program, "Prime95");
311 22 : mpz_mod (x, x, n->n);
312 22 : return 1;
313 : }
314 20 : goto error;
315 : }
316 :
317 : #ifdef DEBUG
318 : if (*method != ECM_ECM && (have_sigma || have_a || have_z))
319 : {
320 : int count = have_sigma + have_a + have_z;
321 : printf ("Warning: Save file line has");
322 : if (have_sigma)
323 : {
324 : printf (" SIGMA");
325 : mpz_set_ui (sigma, 0);
326 : if (--count > 1)
327 : printf (",");
328 : else if (count > 0)
329 : printf (" and");
330 : }
331 : if (have_a)
332 : {
333 : printf (" A");
334 : mpz_set_ui (A, 0);
335 : if (--count > 0)
336 : printf (" and");
337 : }
338 : if (have_z)
339 : {
340 : printf (" Z");
341 : mpz_clear (z);
342 : have_z = 0;
343 : }
344 : printf (" value for method other than ECM.\n");
345 : }
346 : #endif
347 :
348 105 : if (!have_method || !have_x || !have_n || !have_b1 ||
349 105 : (*method == ECM_ECM && !have_sigma && !have_a))
350 : {
351 10 : fprintf (stderr, "Save file line lacks fields\n");
352 10 : continue;
353 : }
354 :
355 95 : if (have_checksum)
356 : {
357 : mpz_t checksum;
358 :
359 65 : mpz_init (checksum);
360 65 : mpz_set_d (checksum, *b1);
361 65 : if (have_sigma)
362 30 : mpz_mul_ui (checksum, checksum, mpz_fdiv_ui (sigma, CHKSUMMOD));
363 65 : if (have_a)
364 20 : mpz_mul_ui (checksum, checksum, mpz_fdiv_ui (A, CHKSUMMOD));
365 65 : mpz_mul_ui (checksum, checksum, mpz_fdiv_ui (n->n, CHKSUMMOD));
366 65 : mpz_mul_ui (checksum, checksum, mpz_fdiv_ui (x, CHKSUMMOD));
367 65 : if (have_z)
368 0 : mpz_mul_ui (checksum, checksum, mpz_fdiv_ui (z, CHKSUMMOD));
369 65 : mpz_mul_ui (checksum, checksum, (*param+1)%CHKSUMMOD);
370 65 : if (mpz_fdiv_ui (checksum, CHKSUMMOD) != saved_checksum)
371 : {
372 10 : fprintf (stderr, "Resume file line has bad checksum %u, expected %u\n",
373 10 : saved_checksum, (unsigned int) mpz_fdiv_ui (checksum, CHKSUMMOD));
374 10 : mpz_clear (checksum);
375 10 : continue;
376 : }
377 55 : mpz_clear (checksum);
378 : }
379 :
380 85 : mpz_mod (x, x, n->n);
381 85 : if (have_y)
382 55 : mpz_mod(y, y, n->n);
383 85 : if (have_z) /* Must normalize */
384 : {
385 10 : if (!mpz_invert (z, z, n->n)) /* Factor found? */
386 : {
387 : /* Oh great. What do we do with it now? */
388 : /* mpres_gcd (f, z, n); */
389 0 : printf ("Oops, factor found while reading from save file.\n");
390 : }
391 10 : mpz_mul (z, z, x);
392 10 : mpz_mod (x, z, n->n);
393 10 : mpz_clear (z);
394 : }
395 :
396 85 : return 1;
397 :
398 120 : error:
399 : /* This can occur when reading Prime95 resume files,
400 : or files that have comment lines in them,
401 : or files that have a problem with the save line */
402 : /* In case of error, read rest of line and try next line */
403 3600 : while (!facceptnl (fd) && !feof (fd))
404 3480 : fgetc (fd);
405 : }
406 :
407 : /* We hit EOF without reading a proper save line */
408 207 : return 0;
409 : }
410 :
411 :
412 : /* Append a residue in file. */
413 : static void
414 55 : write_resumefile_line (FILE *file, int method, double B1, mpz_t sigma,
415 : int sigma_is_A, int Etype, int param, mpz_t x, mpz_t y,
416 : mpcandi_t *n, mpz_t x0, mpz_t y0, const char *comment)
417 : {
418 : mpz_t checksum;
419 : time_t t;
420 : char text[256];
421 : char *uname, mname[32];
422 :
423 55 : mpz_init (checksum);
424 55 : mpz_set_d (checksum, B1);
425 55 : fprintf (file, "METHOD=");
426 55 : if (method == ECM_PM1)
427 10 : fprintf (file, "P-1");
428 45 : else if (method == ECM_PP1)
429 5 : fprintf (file, "P+1");
430 : else
431 : {
432 40 : fprintf (file, "ECM");
433 40 : if (sigma_is_A == 0)
434 : {
435 20 : if (param != ECM_PARAM_DEFAULT)
436 20 : fprintf (file, "; PARAM=%d", param);
437 :
438 20 : fprintf (file, "; SIGMA=");
439 : }
440 : else
441 20 : fprintf (file, "; ETYPE=%d; A=", Etype);
442 :
443 40 : mpz_out_str (file, 10, sigma);
444 40 : mpz_mul_ui (checksum, checksum, mpz_fdiv_ui (sigma, CHKSUMMOD));
445 40 : if (param != ECM_PARAM_DEFAULT)
446 30 : mpz_mul_ui (checksum, checksum, (param+1)%CHKSUMMOD);
447 : }
448 :
449 55 : fprintf (file, "; B1=%.0f; N=", B1);
450 55 : if (n->cpExpr)
451 0 : fprintf(file, "%s", n->cpExpr);
452 : else
453 55 : mpz_out_str (file, 10, n->n);
454 55 : fprintf (file, "; X=0x");
455 55 : mpz_out_str (file, 16, x);
456 55 : mpz_mul_ui (checksum, checksum, mpz_fdiv_ui (n->n, CHKSUMMOD));
457 55 : mpz_mul_ui (checksum, checksum, mpz_fdiv_ui (x, CHKSUMMOD));
458 55 : fprintf (file, "; CHECKSUM=%u; PROGRAM=GMP-ECM %s;",
459 55 : (unsigned int) mpz_fdiv_ui (checksum, CHKSUMMOD), VERSION);
460 55 : mpz_clear (checksum);
461 55 : if (y != NULL)
462 : {
463 55 : fprintf (file, " Y=0x");
464 55 : mpz_out_str (file, 16, y);
465 55 : fprintf (file, ";");
466 : }
467 :
468 55 : if (x0 != NULL)
469 : {
470 55 : fprintf (file, " X0=0x");
471 55 : mpz_out_str (file, 16, x0);
472 55 : fprintf (file, ";");
473 : }
474 55 : if (y0 != NULL)
475 : {
476 55 : fprintf (file, " Y0=0x");
477 55 : mpz_out_str (file, 16, y0);
478 55 : fprintf (file, ";");
479 : }
480 :
481 : /* Try to get the users and his machines name */
482 : /* TODO: how to make portable? */
483 55 : uname = getenv ("LOGNAME");
484 55 : if (uname == NULL)
485 0 : uname = getenv ("USERNAME");
486 55 : if (uname == NULL)
487 0 : uname = "";
488 :
489 : #if defined (_MSC_VER) || defined (__MINGW32__)
490 : /* dummy block, so that the vars needed here don't need to
491 : "spill" over to the rest of the function. */
492 : {
493 : DWORD size;
494 : /* x86_64-w64-mingw32-gcc (GCC) 4.8.0 20121031 (experimental) has infinite
495 : for loop below with -O2, volatile seems to fix it */
496 : volatile size_t i;
497 : TCHAR T[MAX_COMPUTERNAME_LENGTH+2];
498 : size=MAX_COMPUTERNAME_LENGTH+1;
499 : if (!GetComputerName(T, &size))
500 : strcpy(mname, "localPC");
501 : else
502 : {
503 : if (size > sizeof(mname) - 1)
504 : size = sizeof(mname) - 1;
505 :
506 : for (i = 0; i < size; ++i)
507 : mname[i] = T[i];
508 : mname[i] = 0;
509 : }
510 : }
511 : #else
512 55 : if (gethostname (mname, 32) != 0)
513 0 : mname[0] = 0;
514 55 : mname[31] = 0; /* gethostname() may omit trailing 0 if hostname >31 chars */
515 : #endif
516 :
517 55 : if (uname[0] != 0 || mname[0] != 0)
518 : {
519 55 : fprintf (file, " WHO=%.233s@%.32s;", uname, mname);
520 : }
521 :
522 55 : if (comment[0] != 0)
523 0 : fprintf (file, " COMMENT=%.255s;", comment);
524 :
525 55 : t = time (NULL);
526 55 : strncpy (text, ctime (&t), 255);
527 55 : text[255] = 0;
528 55 : text[strlen (text) - 1] = 0; /* Remove newline */
529 55 : fprintf (file, " TIME=%s;", text);
530 55 : fprintf (file, "\n");
531 55 : fflush (file);
532 55 : }
533 :
534 : /* Call write_resumefile_line for each residue in x.
535 : x = x0 + x1*2^(bits) + ... + xk*2^(bits*k), xi are the residues (this is a hack for GPU)
536 : Returns 1 on success, 0 on error */
537 : int
538 55 : write_resumefile (char *fn, int method, mpz_t N, ecm_params params,
539 : mpcandi_t *n, mpz_t orig_x0, mpz_t orig_y0,
540 : const char *comment)
541 : {
542 : FILE *file;
543 55 : unsigned int i = 0;
544 : #if defined(HAVE_FCNTL) && defined(HAVE_FILENO)
545 : struct flock lock;
546 : int r, fd;
547 : #endif
548 : mpz_t tmp_x, tmp_y;
549 55 : mpz_init (tmp_x);
550 55 : mpz_init (tmp_y);
551 :
552 : /* first try to open the file */
553 : #ifdef DEBUG
554 : if (fn == NULL)
555 : {
556 : fprintf (stderr, "write_resumefile: fn == NULL\n");
557 : exit (EXIT_FAILURE);
558 : }
559 : #endif
560 :
561 55 : file = fopen (fn, "a");
562 55 : if (file == NULL)
563 : {
564 0 : fprintf (stderr, "Could not open file %s for writing\n", fn);
565 0 : return 0;
566 : }
567 :
568 : #if defined(HAVE_FCNTL) && defined(HAVE_FILENO)
569 : /* Try to get a lock on the file so several processes can append to
570 : the same file safely */
571 :
572 : /* Supposedly some implementations of fcntl() can get confused over
573 : garbage in unused fields in a flock struct, so zero it */
574 55 : memset (&lock, 0, sizeof (struct flock));
575 55 : fd = fileno (file);
576 55 : lock.l_type = F_WRLCK;
577 55 : lock.l_whence = SEEK_SET;
578 55 : lock.l_start = 0;
579 55 : lock.l_len = 1;
580 : /* F_SETLKW: blocking exclusive lock request */
581 55 : r = fcntl (fd, F_SETLKW, &lock);
582 55 : if (r != 0)
583 : {
584 0 : fclose (file);
585 0 : return 0;
586 : }
587 :
588 55 : fseek (file, 0, SEEK_END);
589 : #endif
590 :
591 :
592 : /* Now can call write_resumefile_line to write in the file */
593 55 : if (params->gpu == 0)
594 : {
595 : /* Reduce stage 1 residue wrt new cofactor, in case a factor was
596 : found */
597 55 : mpz_mod (tmp_x, params->x, n->n);
598 :
599 : /* We write the B1done value to the save file. This requires that
600 : a correct B1done is returned by the factoring functions. */
601 : /* FIXME: clang says that params->y == NULL is always false. */
602 55 : if (params->y == NULL)
603 : {
604 0 : write_resumefile_line (file, method, params->B1done, params->sigma,
605 0 : params->sigma_is_A, params->E->type,
606 : params->param,
607 : tmp_x, NULL, n, orig_x0, orig_y0,
608 : comment);
609 : }
610 : else
611 : {
612 55 : mpz_mod (tmp_y, params->y, n->n);
613 55 : write_resumefile_line (file, method, params->B1done, params->sigma,
614 55 : params->sigma_is_A, params->E->type,
615 : params->param,
616 : tmp_x, tmp_y, n, orig_x0, orig_y0,
617 : comment);
618 : }
619 : }
620 : else /* gpu case */
621 : {
622 0 : size_t n_bits = mpz_sizeinbase(N, 2);
623 0 : for (i = 0; i < params->gpu_number_of_curves; i++)
624 : {
625 0 : mpz_fdiv_r_2exp (tmp_x, params->x, n_bits);
626 0 : mpz_fdiv_q_2exp (params->x, params->x, n_bits);
627 0 : mpz_mod (tmp_x, tmp_x, n->n);
628 0 : write_resumefile_line (file, method, params->B1done, params->sigma,
629 0 : params->sigma_is_A, params->E->type,
630 : /* since the gpu version always uses -param 3,
631 : we hardcode it in the save file */
632 : ECM_PARAM_BATCH_32BITS_D,
633 : tmp_x, NULL, n, orig_x0, orig_y0,
634 : comment);
635 0 : mpz_add_ui (params->sigma, params->sigma, 1);
636 : }
637 : }
638 :
639 : /* closing the file */
640 : #if defined(HAVE_FCNTL) && defined(HAVE_FILENO)
641 55 : lock.l_type = F_UNLCK;
642 55 : lock.l_whence = SEEK_SET;
643 55 : lock.l_start = 0;
644 55 : lock.l_len = 1;
645 55 : fcntl (fd, F_SETLKW, &lock); /* F_SETLKW: blocking lock request */
646 : #endif
647 55 : fclose (file);
648 :
649 55 : mpz_clear (tmp_x);
650 55 : mpz_clear (tmp_y);
651 :
652 55 : return 0;
653 : }
654 :
655 :
656 : /* For the batch mode */
657 : /* Write the batch exponent s in a file */
658 : /* Return the number of bytes written */
659 : int
660 16 : write_s_in_file (char *fn, mpz_t s)
661 : {
662 : FILE *file;
663 16 : int ret = 0;
664 :
665 : #ifdef DEBUG
666 : if (fn == NULL)
667 : {
668 : fprintf (stderr, "write_s_in_file: fn == NULL\n");
669 : exit (EXIT_FAILURE);
670 : }
671 : #endif
672 :
673 16 : file = fopen (fn, "wb");
674 16 : if (file == NULL)
675 : {
676 0 : fprintf (stderr, "Could not open file %s for writing\n", fn);
677 0 : return 0;
678 : }
679 :
680 16 : ret = mpz_out_raw (file, s);
681 :
682 16 : fclose (file);
683 16 : return ret;
684 : }
685 :
686 : /* For the batch mode */
687 : /* read the batch exponent s from a file */
688 : int
689 56 : read_s_from_file (mpz_t s, char *fn, double B1)
690 : {
691 : FILE *file;
692 : mpz_t tmp, tmp2;
693 : unsigned int val2;
694 56 : int ret = 0;
695 :
696 : #ifdef DEBUG
697 : if (fn == NULL)
698 : {
699 : fprintf (stderr, "read_s_from_file: fn == NULL\n");
700 : return 1;
701 : }
702 : #endif
703 :
704 56 : file = fopen (fn, "rb");
705 56 : if (file == NULL)
706 : {
707 20 : fprintf (stderr, "Could not open file %s for reading\n", fn);
708 20 : return 1;
709 : }
710 :
711 36 : ret = mpz_inp_raw (s, file);
712 36 : if (ret == 0)
713 : {
714 20 : fprintf (stderr, "read_s_from_file: 0 bytes read from %s\n", fn);
715 20 : return 1;
716 : }
717 :
718 16 : fclose (file);
719 :
720 : /* Some elementaty check that it correspond to the actual B1 */
721 16 : mpz_init (tmp);
722 16 : mpz_init (tmp2);
723 : /* check that the valuation of 2 is correct */
724 16 : val2 = mpz_scan1 (s, 0);
725 16 : mpz_ui_pow_ui (tmp, 2, val2);
726 16 : mpz_ui_pow_ui (tmp2, 2, val2+1);
727 16 : if (mpz_cmp_d (tmp, B1) > 0 || mpz_cmp_d (tmp2, B1) <= 0)
728 : {
729 0 : fprintf (stderr, "Error, the value of the batch product in %s "
730 : "does not correspond to B1=%1.0f.\n", fn, B1);
731 0 : return 1;
732 : }
733 :
734 : /* Check that next_prime (B1) does not divide batch_s */
735 16 : mpz_set_d (tmp, B1);
736 16 : mpz_nextprime (tmp2, tmp);
737 16 : if (mpz_divisible_p (s, tmp2))
738 : {
739 0 : fprintf (stderr, "Error, the value of the batch product in %s "
740 : "does not correspond to B1=%1.0f.\n", fn, B1);
741 0 : return 1;
742 : }
743 :
744 : /* Check that next_prime (sqrt(B1)) divide batch_s only once */
745 16 : mpz_set_d (tmp, sqrt(B1));
746 16 : mpz_nextprime (tmp2, tmp);
747 16 : mpz_mul (tmp, tmp2, tmp2);
748 16 : if (!mpz_divisible_p (s, tmp2) || mpz_divisible_p (s, tmp))
749 : {
750 0 : fprintf (stderr, "Error, the value of the batch product in %s "
751 : "does not correspond to B1=%1.0f.\n", fn, B1);
752 0 : return 1;
753 : }
754 :
755 16 : mpz_clear (tmp);
756 16 : mpz_clear (tmp2);
757 :
758 16 : return 0;
759 : }
760 :
|