]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | Because they are parsed from the end, Canon CRW files | |
3 | become unreadable if garbage data is appended to them, as | |
4 | often happens when files are recovered from damaged media. | |
5 | This program truncates CRW files to the correct size. | |
6 | ||
7 | Copyright 2005 by Dave Coffin, dcoffin a cybercom o net | |
8 | Free for all uses. | |
9 | ||
10 | $Revision$ | |
11 | $Date$ | |
12 | */ | |
13 | ||
14 | #include <stdio.h> | |
15 | #include <stdlib.h> | |
16 | #include <string.h> | |
17 | ||
18 | unsigned char *buffer; | |
19 | ||
20 | int get4 (int i) | |
21 | { | |
22 | if (buffer[0] == 'I') | |
23 | return buffer[i+3] << 24 | buffer[i+2] << 16 | buffer[i+1] << 8 | buffer[i]; | |
24 | else | |
25 | return buffer[i] << 24 | buffer[i+1] << 16 | buffer[i+2] << 8 | buffer[i+3]; | |
26 | } | |
27 | ||
28 | int main (int argc, char **argv) | |
29 | { | |
30 | int arg, size, end, diff, status=1; | |
31 | unsigned char *fname; | |
32 | FILE *fp; | |
33 | ||
34 | if (argc == 1) | |
35 | fprintf (stderr, "Usage: %s crw_0001.crw crw_0002.crw ...\n", argv[0]); | |
36 | ||
37 | for (arg=1; arg < argc; arg++) { | |
38 | status = 1; | |
39 | fp = fopen (argv[arg], "rb"); | |
40 | fseek (fp, 0, SEEK_END); | |
41 | size = ftell(fp); | |
42 | buffer = malloc (size + strlen(argv[arg]) + 10); | |
43 | if (!buffer) { | |
44 | fprintf (stderr, "Cannot allocate memory!\n"); | |
45 | return 2; | |
46 | } | |
47 | fname = buffer + size; | |
48 | sprintf (fname, "%s.clean", argv[arg]); | |
49 | fseek (fp, 0, SEEK_SET); | |
50 | fread (buffer, 1, size, fp); | |
51 | fclose (fp); | |
52 | if (strncmp (buffer, "II\x1a\0\0\0HEAPCCDR", 14) && | |
53 | strncmp (buffer, "MM\0\0\0\x1aHEAPCCDR", 14)) { | |
54 | fprintf (stderr, "%s is not a CRW file!\n", argv[arg]); | |
55 | free (buffer); | |
56 | continue; | |
57 | } | |
58 | for (end=size; end > 0xa0000; end--) { | |
59 | diff = end - get4(end-4); | |
60 | if (diff > 50 && diff < 120 && diff % 10 == 2) { | |
61 | status = 0; | |
62 | break; | |
63 | } | |
64 | } | |
65 | if (status) | |
66 | fprintf (stderr, "Failed to clean %s\n", argv[arg]); | |
67 | else { | |
68 | if ((fp = fopen (fname, "wb"))) { | |
69 | fprintf (stderr, "Writing %s\n", fname); | |
70 | fwrite (buffer, 1, end, fp); | |
71 | fclose (fp); | |
72 | } else { | |
73 | perror (fname); | |
74 | status = 1; | |
75 | } | |
76 | } | |
77 | free (buffer); | |
78 | } | |
79 | return status; | |
80 | } |