]> git.sesse.net Git - freerainbowtables/blob - Server Applications/rtperfectp/RTRead.cpp
initial
[freerainbowtables] / Server Applications / rtperfectp / RTRead.cpp
1 /*
2         Copyright (C) 2008 Steve Thomas <SMT837784@yahoo.com>
3
4         This file is part of RT Perfecter.
5
6         RT Perfecter 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
9         (at your option) any later version.
10
11         RT Perfecter is distributed in the hope that it will be useful,
12         but WITHOUT ANY WARRANTY; without even the implied warranty of
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14         GNU General Public License for more details.
15
16         You should have received a copy of the GNU General Public License
17         along with RT Perfecter.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <time.h>
23 #include <ctime>
24 #include <errno.h>
25 #include <stdlib.h>
26 #include "RTRead.h"
27
28 #ifdef HAVE_DIRENT_H
29         #include <dirent.h>
30 #else
31         // I know Microsoft's compiler, .Net 2005 or older, does not come with this file.
32         // You can use this if you don't have dirent.h: http://www.cs.fiu.edu/~weiss/cop4338_spr06/dirent.h
33         // Umm I'm not sure if the license on that file, which appears to be public domain, conflicts with GPL v3.
34         // So only use that if you need it and the licenses don't conflict.
35         #include "dirent.h"
36 #endif
37
38 #ifdef _WIN32
39         #include <conio.h>
40         #define DIRECTORY_SEPERATOR '\\'
41 #else
42         #include <fcntl.h>
43         #define DIRECTORY_SEPERATOR '/'
44 #endif
45
46 #ifndef NAME_MAX
47         #define NAME_MAX 256
48 #endif
49
50 #include "RTRead.h"
51
52 RTRead::RTRead(char *dir, uint64 maxIndex, int verbose)
53 {
54         int dirLen = strlen(dir), dirFileLen;
55         char *file = new char[dirLen + NAME_MAX + 2];
56         DIR *pDir;
57         struct dirent *pDirFile;
58         FileList *head = NULL, *current = NULL, *temp = new FileList;
59
60         // Init
61         m_verbose = verbose;
62         m_maxIndex = maxIndex;
63         m_chainsRead = 0;
64         m_chains = 0;
65         m_pqSize = 0;
66         m_pq = NULL;
67         temp->next = NULL;
68         strncpy(file, dir, dirLen);
69         if (dir[dirLen - 1] != DIRECTORY_SEPERATOR)
70         {
71                 file[dirLen] = DIRECTORY_SEPERATOR;
72                 dirLen++;
73         }
74
75         // Open directory
76         pDir = opendir(dir);
77         if (pDir == NULL)
78         {
79                 printf("Error #%u: Opening directory '%s'\n", errno, dir);
80                 exit(errno);
81         }
82
83         // Get files
84         for (pDirFile = readdir(pDir); pDirFile != NULL; pDirFile = readdir(pDir))
85         {
86                 dirFileLen = strlen(pDirFile->d_name);
87                 if (pDirFile->d_name[0] != '.' && dirFileLen > 5 &&
88                     pDirFile->d_name[dirFileLen - 5] == '.' &&
89                    (pDirFile->d_name[dirFileLen - 4] == 'p' || pDirFile->d_name[dirFileLen - 4] == 'P') &&
90                    (pDirFile->d_name[dirFileLen - 3] == 'a' || pDirFile->d_name[dirFileLen - 3] == 'A') &&
91                    (pDirFile->d_name[dirFileLen - 2] == 'r' || pDirFile->d_name[dirFileLen - 2] == 'R') &&
92                    (pDirFile->d_name[dirFileLen - 1] == 't' || pDirFile->d_name[dirFileLen - 1] == 'T'))
93
94                 {
95                         strcpy(file + dirLen, pDirFile->d_name);
96                         if (getInfo(file, dirLen + dirFileLen, temp) == 0)
97                         {
98                                 m_chains += temp->chains;
99                                 m_pqSize++;
100                                 if (head == NULL)
101                                 {
102                                         head = temp;
103                                         current = temp;
104                                 }
105                                 else
106                                 {
107                                         current->next = temp;
108                                         current = temp;
109                                 }
110                                 temp = new FileList;
111                                 temp->next = NULL;
112                         }
113                         else
114                         {
115                                 printf("Continue? (y/n): ");
116                                 int ch = 0;
117                                 while (ch != EOF && ch != 'y' && ch != 'Y' && ch != 'n' && ch != 'N')
118                                 {
119                                         ch = getchar();
120                                 }
121                                 if (ch != 'y' && ch != 'Y')
122                                 {
123                                         while (head != NULL)
124                                         {
125                                                 current = head;
126                                                 head = head->next;
127                                                 fclose(current->pFile);
128                                                 delete [] current->name;
129                                                 delete current;
130                                         }
131                                         delete [] file;
132                                         delete temp;
133                                         closedir(pDir);
134                                         exit(1);
135                                 }
136                         }
137                 }
138         }
139         delete [] file;
140         delete temp;
141         closedir(pDir);
142         if (head == NULL)
143         {
144                 printf("Error no '*.part' input files found in directory '%s'.\n", dir);
145                 exit(1);
146         }
147
148         // Push file list into priority queue
149         PriorityQueueNode tmpNode;
150         unsigned int i = 0, node, par;
151
152         m_pq = new PriorityQueueNode[m_pqSize];
153         while (head != NULL)
154         {
155                 if (readGoodChain(head->pFile, &(m_pq[i].chain)) == 0)
156                 {
157                         // Init priority queue node
158                         m_pq[i].pFile = head->pFile;
159                         m_pq[i].fName = head->name;
160
161                         // Insert into priority queue
162                         if (i != 0)
163                         {
164                                 node = i;
165                                 par = (node - 1) >> 1;
166                                 if (m_pq[par].chain.endpt > m_pq[node].chain.endpt)
167                                 {
168                                         tmpNode = m_pq[node];
169                                         do
170                                         {
171                                                 m_pq[node] = m_pq[par];
172                                                 node = par;
173                                                 if (par == 0)
174                                                 {
175                                                         break;
176                                                 }
177                                                 par = (node - 1) >> 1;
178                                         } while (m_pq[par].chain.endpt > tmpNode.chain.endpt);
179                                 }
180                                 if (i != node)
181                                 {
182                                         m_pq[node] = tmpNode;
183                                 }
184                         }
185                         i++;
186                 }
187                 else
188                 {
189                         m_pqSize--;
190                         printf("File had no valid chains '%s'\n", head->name);
191                         delete [] head->name;
192                 }
193
194                 // Delete file list node
195                 current = head;
196                 head = head->next;
197                 delete current;
198         }
199
200         printf("Starting with %u files.\n", m_pqSize);
201         m_startTime = clock();
202 }
203
204 RTRead::~RTRead()
205 {
206         if (m_pq != NULL)
207         {
208                 for (unsigned int i = 0; i < m_pqSize; i++)
209                 {
210                         if (m_pq[i].pFile != NULL)
211                         {
212                                 fclose(m_pq[i].pFile);
213                         }
214                         if (m_pq[i].fName != NULL)
215                         {
216                                 delete [] m_pq[i].fName;
217                         }
218                 }
219                 delete [] m_pq;
220         }
221 }
222
223 int RTRead::readChain(RTChainCP *chain)
224 {
225         PriorityQueueNode tmp;
226         unsigned int child, node;
227
228         if (m_pq == NULL)
229         {
230                 return 1;
231         }
232         *chain = m_pq[0].chain;
233         bool remove = (readGoodChain(m_pq[0].pFile, &(m_pq[0].chain)) != 0);
234
235         if (remove)
236         {
237                 if (m_verbose)
238                 {
239                         printf("Finished with file '%s'\n", m_pq[0].fName);
240                 }
241                 delete [] m_pq[0].fName;
242
243                 // Remove node from queue
244                 m_pqSize--;
245                 if (m_pqSize == 2)
246                 {
247                         if (m_pq[1].chain.endpt < m_pq[2].chain.endpt)
248                         {
249                                 m_pq[0] = m_pq[1];
250                                 m_pq[1] = m_pq[2];
251                         }
252                         else
253                         {
254                                 m_pq[0] = m_pq[2];
255                         }
256                         m_pq[2].fName = NULL;
257                         m_pq[2].pFile = NULL;
258                 }
259                 else if (m_pqSize == 1)
260                 {
261                         m_pq[0] = m_pq[1];
262                         m_pq[1].fName = NULL;
263                         m_pq[1].pFile = NULL;
264                 }
265                 else if (m_pqSize == 0)
266                 {
267                         delete [] m_pq;
268                         m_pq = NULL;
269                 }
270         }
271         if (m_pqSize > 2)
272         {
273                 if (remove)
274                 {
275                         tmp = m_pq[m_pqSize];
276                         m_pq[m_pqSize].fName = NULL;
277                         m_pq[m_pqSize].pFile = NULL;
278                 }
279                 else
280                 {                       
281                         tmp = m_pq[0];
282                 }
283                 // Move tmp node to proper posistion in queue
284                 node = 0;
285                 child = 1;
286                 if (m_pq[1].chain.endpt > m_pq[2].chain.endpt)
287                 {
288                         child = 2;
289                 }
290                 while (tmp.chain.endpt > m_pq[child].chain.endpt)
291                 {
292                         m_pq[node] = m_pq[child];
293                         node = child;
294                         // child = left node
295                         child = (node << 1) + 1;
296                         if (child >= m_pqSize)
297                         {
298                                 break;
299                         }
300                         if (child + 1 < m_pqSize && m_pq[child].chain.endpt > m_pq[child + 1].chain.endpt)
301                         {
302                                 // child = right node
303                                 child++;
304                         }
305                 }
306                 if (node != 0 || remove)
307                 {
308                         m_pq[node] = tmp;
309                 }
310         }
311         else if (m_pqSize == 2 && !remove)
312         {
313                 if (m_pq[0].chain.endpt > m_pq[1].chain.endpt)
314                 {
315                         tmp = m_pq[1];
316                         m_pq[1] = m_pq[0];
317                         m_pq[0] = tmp;
318                 }
319         }
320         return 0;
321 }
322
323 int RTRead::readGoodChain(FILE *pFile, RTChainCP *chain)
324 {
325         size_t ret;
326
327         if (pFile == NULL)
328         {
329                 return 1;
330         }
331         do
332         {
333                 ret = fread((void*)chain, 16, 1, pFile);
334                 if(ret == 1)
335                         ret = fread((void*)&chain->checkpoint, 2, 1, pFile);
336                 if (ret != 1)
337                 {
338                         if (ferror(pFile) != 0)
339                         {
340                                 printf("Error reading file.\n");
341                                 printf("Continue? (y/n): ");
342                                 int ch = 0;
343                                 while (ch != EOF && ch != 'y' && ch != 'Y' && ch != 'n' && ch != 'N')
344                                 {
345                                         ch = getchar();
346                                 }
347                                 if (ch != 'y' && ch != 'Y')
348                                 {
349                                         exit(1);
350                                 }
351                                 clearerr(pFile);
352                         }
353                         else if (feof(pFile) != 0)
354                         {
355                                 fclose(pFile);
356                                 return 1;
357                         }
358                 }
359                 else
360                 {
361                         m_chainsRead++;
362                 }
363         } while (ret != 1 || chain->startpt > m_maxIndex || chain->endpt > m_maxIndex);
364         return 0;
365 }
366
367 void RTRead::printStatus()
368 {
369         double percent = ((double) m_chainsRead / (double) m_chains) * 100.0;
370         double timeElapsed = (clock() - m_startTime) / (double)CLOCKS_PER_SEC;
371
372         printf("\n*** Status ***\n");
373 #ifdef _WIN32
374         printf("  Chains Read:   %I64u\n", m_chainsRead);
375         printf("  Total Chains:  %I64u\n", m_chains);
376 #else
377         printf("  Chains Read:   %llu\n", m_chainsRead);
378         printf("  Total Chains:  %llu\n", m_chains);
379 #endif
380         printf("  Files Open:    %u\n", m_pqSize);
381         printf("  Percent:       %0.1f\n", percent);
382         printf("  Time Elapsed:  %0.0f sec\n", timeElapsed);
383         printf("  Time Left:     %0.0f sec\n\n", timeElapsed / (percent / 100.0) - timeElapsed);
384 }
385
386 int RTRead::getInfo(char *file, int len, FileList *ret)
387 {
388         FILE *pFile;
389         unsigned int size;
390
391         if (m_verbose)
392         {
393                 printf("Opening file '%s'\n", file);
394         }
395         pFile = fopen(file, "rb");
396         if (pFile == NULL)
397         {
398                 perror(file);
399                 return 1;
400         }
401
402         // Get file size
403         fseek(pFile, 0, SEEK_END);
404         size = ftell(pFile);
405         if (size & 15 != 0)
406         {
407                 fclose(pFile);
408                 printf("Error file size of '%s' is not a multible of 16 bytes.\n", file);
409                 return 1;
410         }
411         fseek(pFile, 0, SEEK_SET);
412         ret->chains = size >> 4;
413         ret->pFile = pFile;
414
415         ret->name = new char[len + 1];
416         strncpy(ret->name, file, len);
417         ret->name[len] = '\0';
418         return 0;
419 }
420