forked from uncrustify/uncrustify
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbackup.cpp
More file actions
161 lines (141 loc) · 4.16 KB
/
backup.cpp
File metadata and controls
161 lines (141 loc) · 4.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/**
* @file backup.cpp
* Make a backup of a source file
* The current plans are to use two files.
*
* - A '.unc-backup~' file that contains the original contents
* - A '.unc-backup-md5~' file that contains the MD5 over the last output
* that uncrustify generated
*
* The logic goes like this:
* 1. If there isn't a .backup-md5 or the md5 over the input file doesn't
* match what is in .backup-md5, then copy the source file to .backup.
*
* 2. Create the output file.
*
* 3. Calculate the md5 over the output file.
* Create the .backup-md5 file.
*
* This will let you run uncrustify multiple times over the same file without
* losing the original file. If you edit the file, then a new backup is made.
*
* @author Ben Gardner
* @license GPL v2+
*/
#include "prototypes.h"
#include "backup.h"
#include "md5.h"
#include "logger.h"
#include <cstdio>
#include <cerrno>
#include "unc_ctype.h"
#include <cstring>
/**
* Check the backup-md5 file and copy the input file to a backup if needed.
*/
int backup_copy_file(const char *filename, const vector<UINT8>& data)
{
char newpath[1024];
char buffer[128];
char md5_str_in[33];
char md5_str[33];
UINT8 dig[16];
md5_str_in[0] = 0;
MD5::Calc(&data[0], data.size(), dig);
snprintf(md5_str, sizeof(md5_str),
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
dig[0], dig[1], dig[2], dig[3],
dig[4], dig[5], dig[6], dig[7],
dig[8], dig[9], dig[10], dig[11],
dig[12], dig[13], dig[14], dig[15]);
/* Create the backup-md5 filename, open it and read the md5 */
snprintf(newpath, sizeof(newpath), "%s%s", filename, UNC_BACKUP_MD5_SUFFIX);
FILE *thefile = fopen(newpath, "rb");
if (thefile != NULL)
{
if (fgets(buffer, sizeof(buffer), thefile) != NULL)
{
for (int i = 0; buffer[i] != 0; i++)
{
if (unc_isxdigit(buffer[i]))
{
md5_str_in[i] = unc_tolower(buffer[i]);
}
else
{
md5_str_in[i] = 0;
break;
}
}
}
fclose(thefile);
}
/* if the MD5s match, then there is no need to back up the file */
if (memcmp(md5_str, md5_str_in, 32) == 0)
{
LOG_FMT(LNOTE, "%s: MD5 match for %s\n", __func__, filename);
return(SUCCESS);
}
LOG_FMT(LNOTE, "%s: MD5 mismatch - backing up %s\n", __func__, filename);
/* Create the backup file */
snprintf(newpath, sizeof(newpath), "%s%s", filename, UNC_BACKUP_SUFFIX);
thefile = fopen(newpath, "wb");
if (thefile != NULL)
{
int retval = fwrite(&data[0], data.size(), 1, thefile);
int my_errno = errno;
fclose(thefile);
if (retval == 1)
{
return(SUCCESS);
}
LOG_FMT(LERR, "fwrite(%s) failed: %s (%d)\n",
newpath, strerror(my_errno), my_errno);
}
else
{
LOG_FMT(LERR, "fopen(%s) failed: %s (%d)\n",
newpath, strerror(errno), errno);
}
return(FAILURE);
}
/**
* This should be called after the file was written to disk.
* It will be read back and an md5 will be calculated over it.
*/
void backup_create_md5_file(const char *filename)
{
UINT8 dig[16];
MD5 md5;
FILE *thefile;
UINT8 buf[4096];
INT32 len;
char newpath[1024];
md5.Init();
thefile = fopen(filename, "rb");
if (thefile == NULL)
{
LOG_FMT(LERR, "%s: fopen(%s) failed: %s (%d)\n",
__func__, filename, strerror(errno), errno);
return;
}
while ((len = fread(buf, 1, sizeof(buf), thefile)) > 0)
{
md5.Update(buf, len);
}
fclose(thefile);
md5.Final(dig);
snprintf(newpath, sizeof(newpath), "%s%s", filename, UNC_BACKUP_MD5_SUFFIX);
thefile = fopen(newpath, "wb");
if (thefile != NULL)
{
fprintf(thefile,
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %s\n",
dig[0], dig[1], dig[2], dig[3],
dig[4], dig[5], dig[6], dig[7],
dig[8], dig[9], dig[10], dig[11],
dig[12], dig[13], dig[14], dig[15],
path_basename(filename));
fclose(thefile);
}
}