Initial Commit
[Projects.git] / pkgbuilds / friidump / src / friidump-0.4.0 / friidump-0.4.0 / libfriidump / dumper.c
blobc283b86eb129bb2fbe11d4c308237aa58a97924c
1 /***************************************************************************
2 * Copyright (C) 2007 by Arep *
3 * Support is provided through the forums at *
4 * http://www.console-tribe.com *
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 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program 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 this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
20 ***************************************************************************/
22 #include "misc.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <multihash.h>
26 #include "constants.h"
27 #include "disc.h"
28 #include "dumper.h"
30 #ifndef WIN32
31 #include <unistd.h>
32 #include <sys/types.h>
33 #endif
35 struct dumper_s {
36 disc *dsk;
37 char *outfile_raw;
38 u_int32_t start_sector_raw;
39 FILE *fp_raw;
40 char *outfile_iso;
41 u_int32_t start_sector_iso;
42 FILE *fp_iso;
43 u_int32_t start_sector;
44 bool hashing;
45 bool flushing;
47 multihash hash_raw;
48 multihash hash_iso;
50 progress_func progress;
51 void *progress_data;
55 /**
56 * Tries to open the output file for writing and to find out if it contains valid data so that the dump can continue.
57 * @param dvd
58 * @param outfile
59 * @param[out] fp The file pointer to write to.
60 * @param[out] start_sector The sector to start reading from.
61 * @return true if the dumping can start/continue, false otherwise (for instance if outfile cannot be written to).
63 bool dumper_set_raw_output_file (dumper *dmp, char *outfile_raw, bool resume) {
64 bool out;
65 my_off_t filesize;
66 FILE *fp;
68 if (!outfile_raw) {
69 /* Raw output disabled */
70 out = true;
71 dmp -> start_sector_raw = -1;
72 my_free (dmp -> outfile_raw);
73 dmp -> outfile_raw = NULL;
74 } else if (dmp -> outfile_raw) {
75 error ("Raw output file already defined");
76 out = false;
77 } else if (!(fp = fopen (outfile_raw, "rb"))) { /** @todo Maybe we could not open file for permission problems */
78 /* Raw output file does not exist, start from scratch */
79 out = true;
80 dmp -> start_sector_raw = 0;
81 my_strdup (dmp -> outfile_raw, outfile_raw);
82 } else if (resume) {
83 /* Raw output file exists and resume was requested, so see how many dumped sectors it contains */
84 my_fseek (fp, 0, SEEK_END);
85 filesize = my_ftell (fp);
86 fclose (fp);
87 out = true;
88 dmp -> start_sector_raw = (u_int32_t) (filesize / RAW_SECTOR_SIZE / SECTORS_PER_BLOCK) * SECTORS_PER_BLOCK;
89 debug ("Raw output can restart from sector %u", dmp -> start_sector_raw);
90 my_strdup (dmp -> outfile_raw, outfile_raw);
91 } else {
92 /* Raw output file exists but resume was not requested, error */
93 fclose (fp);
94 error ("Raw output file exists, but resume was not requested.");
95 out = false;
96 dmp -> start_sector_raw = -1;
97 my_free (dmp -> outfile_raw);
98 dmp -> outfile_raw = NULL;
101 return (out);
105 bool dumper_set_iso_output_file (dumper *dmp, char *outfile_iso, bool resume) {
106 bool out;
107 my_off_t filesize;
108 FILE *fp;
110 if (!outfile_iso) {
111 /* Raw output disabled */
112 out = true;
113 dmp -> start_sector_iso = -1;
114 my_free (dmp -> outfile_iso);
115 dmp -> outfile_iso = NULL;
116 } else if (dmp -> outfile_iso) {
117 error ("ISO output file already defined");
118 out = false;
119 } else if (!(fp = fopen (outfile_iso, "rb"))) { /** @todo Maybe we could not open file for permission problems */
120 /* Raw output file does not exist, start from scratch */
121 out = true;
122 dmp -> start_sector_iso = 0;
123 my_strdup (dmp -> outfile_iso, outfile_iso);
124 } else if (resume) {
125 /* Raw output file exists and resume was requested, so see how many dumped sectors it contains */
126 my_fseek (fp, 0, SEEK_END);
127 filesize = my_ftell (fp);
128 fclose (fp);
129 out = true;
130 dmp -> start_sector_iso = (u_int32_t) (filesize / SECTOR_SIZE / SECTORS_PER_BLOCK) * SECTORS_PER_BLOCK;
131 debug ("ISO output can restart from sector %u", dmp -> start_sector_iso);
132 my_strdup (dmp -> outfile_iso, outfile_iso);
133 } else {
134 /* Raw output file exists but resume was not requested, error */
135 fclose (fp);
136 error ("ISO output file exists, but resume was not requested.");
137 out = false;
138 dmp -> start_sector_iso = -1;
139 my_free (dmp -> outfile_iso);
140 dmp -> outfile_iso = NULL;
143 return (out);
147 bool dumper_prepare (dumper *dmp) {
148 bool out;
149 u_int8_t buf[RAW_SECTOR_SIZE];
150 size_t r;
151 u_int32_t i;
153 /* Outputting to both files, resume must start from the file with the least sectors. Hopefully they will have the same number of sectors, anyway... */
154 if (dmp -> outfile_raw && dmp -> outfile_iso && dmp -> start_sector_raw != dmp -> start_sector_iso) {
155 if (dmp -> start_sector_raw < dmp -> start_sector_iso)
156 dmp -> start_sector = dmp -> start_sector_raw;
157 else
158 dmp -> start_sector = dmp -> start_sector_iso;
159 } else if (dmp -> outfile_raw) {
160 dmp -> start_sector = dmp -> start_sector_raw;
161 } else if (dmp -> outfile_iso) {
162 dmp -> start_sector = dmp -> start_sector_iso;
163 } else {
164 MY_ASSERT (0);
167 /* Prepare hashes */
168 if (dmp -> hashing) {
169 multihash_init (&(dmp -> hash_raw));
170 multihash_init (&(dmp -> hash_iso));
173 /* Setup raw output file */
174 if (dmp -> outfile_raw) {
175 dmp -> fp_raw = fopen (dmp -> outfile_raw, "a+b");
177 if (dmp -> hashing) {
178 debug ("Calculating hashes for pre-existing raw dump data");
179 if (dmp -> start_sector > 0) {
180 for (i = 0; i < dmp -> start_sector && (r = fread (buf, RAW_SECTOR_SIZE, 1, dmp -> fp_raw)) > 0; i++)
181 multihash_update (&(dmp -> hash_raw), buf, RAW_SECTOR_SIZE);
182 MY_ASSERT (r > 0);
186 /* Now call fseek as file will only be written, from now on */
187 if (my_fseek (dmp -> fp_raw, dmp -> start_sector * RAW_SECTOR_SIZE, SEEK_SET) == 0 &&
188 ftruncate (fileno (dmp -> fp_raw), dmp -> start_sector * RAW_SECTOR_SIZE) == 0) {
189 out = true;
190 debug ("Writing to file \"%s\" in raw format (fseeked() to %lld)", dmp -> outfile_raw, my_ftell (dmp -> fp_raw));
191 } else {
192 out = false;
193 fclose (dmp -> fp_raw);
194 dmp -> fp_raw = NULL;
196 } else {
197 dmp -> fp_raw = NULL;
200 /* Setup ISO output file */
201 if (dmp -> outfile_iso) {
202 dmp -> fp_iso = fopen (dmp -> outfile_iso, "a+b");
204 if (dmp -> hashing) {
205 debug ("Calculating hashes for pre-existing ISO dump data");
206 if (dmp -> start_sector > 0) {
207 for (i = 0; i < dmp -> start_sector && (r = fread (buf, SECTOR_SIZE, 1, dmp -> fp_iso)) > 0; i++)
208 multihash_update (&(dmp -> hash_iso), buf, SECTOR_SIZE);
209 MY_ASSERT (r > 0);
213 if (my_fseek (dmp -> fp_iso, dmp -> start_sector * SECTOR_SIZE, SEEK_SET) == 0 &&
214 ftruncate (fileno (dmp -> fp_iso), dmp -> start_sector * SECTOR_SIZE) == 0) {
215 out = true;
216 debug ("Writing to file \"%s\" in ISO format (fseeked() to %lld)", dmp -> outfile_iso, my_ftell (dmp -> fp_iso));
217 } else {
218 out = false;
219 fclose (dmp -> fp_iso);
220 dmp -> fp_iso = NULL;
222 } else {
223 dmp -> fp_iso = NULL;
226 return (out);
230 int dumper_dump (dumper *dmp) {
231 bool out;
232 u_int8_t *rawbuf, *isobuf;
233 u_int32_t i, sectors_no;
234 #ifdef DEBUGaa
235 bool no_unscrambling;
236 #endif
238 #ifdef DEBUGaa
239 no_unscrambling = dd -> no_unscrambling;
240 if (fp_iso && no_unscrambling) {
241 warning ("Output to ISO format requested, ignoring no_unscrambling!");
242 no_unscrambling = false;
244 #endif
246 sectors_no = disc_get_sectors_no (dmp -> dsk);
247 #if 0
248 if (dd -> start_sector != -1) {
249 if (dd -> start_sector >= sectors_no) {
250 error ("Cannot start dumping from sector %u as the inserted disc only has %u sectors\n", dd -> start_sector, sectors_no);
251 out = false;
252 } else {
253 warning ("Start sector forced to %u\n", dd -> start_sector);
254 ss = dd -> start_sector;
256 if (fp_iso)
257 fseek (fp_iso, ss * 2048, SEEK_SET);
258 if (fp_raw)
259 fseek (fp_raw, ss * 2064, SEEK_SET);
262 #endif
264 if (true) {
265 debug ("Starting dump process from sector %u...\n", dmp -> start_sector);
267 /* First call to progress function */
268 if (dmp -> progress)
269 dmp -> progress (true, dmp -> start_sector, sectors_no, dmp -> progress_data);
271 for (i = dmp -> start_sector, out = true; i < sectors_no && out; i++) {
272 disc_read_sector (dmp -> dsk, i, &isobuf, &rawbuf);
274 if (dmp -> fp_raw) {
275 clearerr (dmp -> fp_raw);
276 fwrite (rawbuf, RAW_SECTOR_SIZE, 1, dmp -> fp_raw);
277 if (ferror (dmp -> fp_raw)) {
278 error ("fwrite() to raw output file failed");
279 out = false;
282 if (dmp -> flushing)
283 fflush (dmp -> fp_raw);
285 if (dmp -> hashing)
286 multihash_update (&(dmp -> hash_raw), rawbuf, RAW_SECTOR_SIZE);
289 if (dmp -> fp_iso) {
290 clearerr (dmp -> fp_iso);
291 fwrite (isobuf, SECTOR_SIZE, 1, dmp -> fp_iso);
292 if (ferror (dmp -> fp_iso)) {
293 error ("fwrite() to ISO output file failed");
294 out = false;
297 if (dmp -> flushing)
298 fflush (dmp -> fp_iso);
300 if (dmp -> hashing)
301 multihash_update (&(dmp -> hash_iso), isobuf, SECTOR_SIZE);
304 if (dmp -> progress)
305 dmp -> progress (false, i + 1, sectors_no, dmp -> progress_data); /* i + 1 'cause sectors range from 0 to N */
308 if (dmp -> hashing) {
309 multihash_finish (&(dmp -> hash_raw));
310 multihash_finish (&(dmp -> hash_iso));
313 if (dmp -> fp_raw)
314 fclose (dmp -> fp_raw);
315 if (dmp -> fp_iso)
316 fclose (dmp -> fp_iso);
317 if (out) {
323 return (out);
327 dumper *dumper_new (disc *d) {
328 dumper *dmp;
330 dmp = (dumper *) malloc (sizeof (dumper));
331 memset (dmp, 0, sizeof (dumper));
332 dmp -> dsk = d;
333 dumper_set_hashing (dmp, true);
334 dumper_set_flushing (dmp, true);
336 return (dmp);
340 void dumper_set_progress_callback (dumper *dmp, progress_func progress, void *progress_data) {
341 dmp -> progress = progress;
342 dmp -> progress_data = progress_data;
344 return;
348 void dumper_set_hashing (dumper *dmp, bool h) {
349 dmp -> hashing = h;
350 debug ("Hashing %s", h ? "enabled" : "disabled");
352 return;
356 void dumper_set_flushing (dumper *dmp, bool f) {
357 dmp -> flushing = f;
358 debug ("Flushing %s", f ? "enabled" : "disabled");
360 return;
363 void *dumper_destroy (dumper *dmp) {
364 my_free (dmp -> outfile_raw);
365 my_free (dmp -> outfile_iso);
366 my_free (dmp);
368 return (NULL);
372 char *dumper_get_iso_crc32 (dumper *dmp) {
373 return ((dmp -> hash_iso).crc32_s);
377 char *dumper_get_raw_crc32 (dumper *dmp) {
378 return ((dmp -> hash_raw).crc32_s);
382 char *dumper_get_iso_md4 (dumper *dmp) {
383 return ((dmp -> hash_iso).md4_s);
387 char *dumper_get_raw_md4 (dumper *dmp) {
388 return ((dmp -> hash_raw).md4_s);
392 char *dumper_get_iso_md5 (dumper *dmp) {
393 return ((dmp -> hash_iso).md5_s);
397 char *dumper_get_raw_md5 (dumper *dmp) {
398 return ((dmp -> hash_raw).md5_s);
402 char *dumper_get_iso_ed2k (dumper *dmp) {
403 return ((dmp -> hash_iso).ed2k_s);
407 char *dumper_get_raw_ed2k (dumper *dmp) {
408 return ((dmp -> hash_raw).ed2k_s);
412 char *dumper_get_iso_sha1 (dumper *dmp) {
413 return ((dmp -> hash_iso).sha1_s);
417 char *dumper_get_raw_sha1 (dumper *dmp) {
418 return ((dmp -> hash_raw).sha1_s);