LCOV - code coverage report
Current view: top level - ecm - resume.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 283 313 90.4 %
Date: 2022-03-21 11:19:20 Functions: 8 8 100.0 %

          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             : 

Generated by: LCOV version 1.14