-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathfix_copyright.c
367 lines (334 loc) · 8.1 KB
/
fix_copyright.c
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
/*
* $Id: fix_copyright.c,v 1.6 1995/02/10 19:55:35 limes Exp $
*/
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
/*
* fix_copyright: look through a bunch of files and replace the
* first ID string in the file with a copyright message.
*
* NOTE: only looks in the first FILECHUNK bytes of the file ...
*/
char *copyright[] =
{
"Copyright (C) 1995, an unpublished work by The 3DO Company. All rights reserved.",
"This material contains confidential information that is the property of The 3DO Company.",
"Any unauthorized duplication, disclosure or use is prohibited."
};
#define COPYR_LINES ((sizeof copyright) / (sizeof copyright[0]))
int verbose = 0;
int debug = 0;
int dryrun = 0;
char id_head[] = "$Id";
char id_tail[] = "$";
/*
* The file input buffer needs to be one byte larger than the number
* of bytes we read from the file at a time, so we can terminate the
* data with a NUL character if we need to.
*/
#define FILECHUNK 8192
char fbuf[FILECHUNK + 1];
/*
* MAXPATHLEN is generally defined in a system header file; if we did
* not get it, set up a sane default.
*/
#ifndef MAXPATHLEN
#define MAXPATHLEN 1024
#endif
int
dofile (char *ifn, int ifd)
{
int i;
int isz;
int ofd;
int osz;
char *efbuf;
char *id;
char *eid;
char *sol;
char *eol;
char ofn[MAXPATHLEN];
char tfn[MAXPATHLEN];
if (debug > 0)
fprintf (stderr, "dofile: ifn='%s' ifd=%d\n", ifn, ifd);
/*
* Get the first (up to) FILECHUNK bytes of the file, which should
* contain the ID string.
*/
isz = read (ifd, fbuf, FILECHUNK);
if (isz < 0)
{
perror (ifn);
return 0;
}
if (debug > 0)
fprintf (stderr, "dofile: got %d chars\n", isz);
/*
* Since we will be using string manipulation routines to search for
* our key patterns, terminate the data we got with a NUL character.
*/
fbuf[isz] = 0;
/*
* Do not whack binary files. Easiest way to see if we have a binary
* file is to check for a NUL character in the data we got; if there
* is one, then strlen() will return its index in the string. If not,
* it will find the sentinal NUL we planted above.
*/
if (strlen (fbuf) != isz)
{
if (debug > 0)
fprintf (stderr, "dofile: binary file (has a NULL)\n");
return 0;
}
/*
* keep a pointer to the end of the data,
* it makes some of the later code simpler.
*/
efbuf = fbuf + isz;
/*
* Scan the buffer looking for the ID string.
*/
id = strstr (fbuf, id_head);
if (id == (char *) 0)
{
if (debug > 0)
fprintf (stderr, "dofile: no opening '$Id'\n");
return 0;
}
/*
* See if the copyright string is already there; if it is,
* then do not modify this file.
*/
id[0] = 0;
if (strstr (fbuf, copyright[0]))
{
if (debug > 0)
fprintf (stderr, "dofile: this file has already been converted\n");
return 0;
}
id[0] = id_head[0];
/*
* Locate the start and end of the ID line.
*
* "sol" points to the first character on the ID line. So we drop
* a NUL byte at the ID and find the "rightmost" newline before
* it; if we find one, bump sol to the next byte, else the first byte
* on the line is the first byte of the buffer.
*/
*id = 0;
sol = strrchr (fbuf, '\n');
if (sol == (char *) 0)
sol = fbuf;
else
sol++;
*id = id_head[0];
/*
* "eol" points to the newline at the end of the ID line.
*/
eol = strchr (id, '\n');
if (eol == (char *) 0)
{
if (debug > 0)
fprintf (stderr, "dofile: unable to find end of ID line\n");
return 0;
}
/*
* Locate the end of the ID string, which will be the first instance
* of id_tail after id_head; this string must be before the end of the
* line. If the string is found, point "eid" to the next character
* after the closing string; otherwise, point it at the *newline*.
*/
*eol = 0;
eid = strstr (id + sizeof id_head, id_tail);
if (eid == (char *) 0)
eid = eol;
else
eid += sizeof id_tail - 1;
*eol = '\n';
/*
* If we are doing a "dry run" we now have enough information to tell
* the user what we would have actually done: we would have attempted
* to modify the file.
*/
if (dryrun)
return 1;
/*
* If we are reading stdin, send the output to stdout.
*/
if (ifd == 0)
ofd = 1;
else
{
/*
* Otherwise, generate a temporary file.
* XXX- may fail on silly file systems that limit the length of
* filename components.
*/
sprintf (ofn, "%s.fco.%d", ifn, getpid ());
sprintf (tfn, "%s.fct.%d", ifn, getpid ());
if (debug > 0)
fprintf (stderr, "dofile: creating file '%s'\n", ofn);
ofd = open (ofn, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (ofd < 0)
{
perror (ofn);
return 0;
}
}
if (debug > 0)
fprintf (stderr, "dofile: ofd is %d\n", ofd);
/*
* Construct the output file:
* - everything before the ID line
* - the copyright message (replacing the ID): for each line,
* - data on the ID line before the ID
* - a line of copyright message
* - data on the ID line after the ID
* - the original ID line, and the remainder of the file.
*/
if (sol > fbuf)
{
osz = write (ofd, fbuf, sol - fbuf);
if (osz < 0)
goto badwrite;
}
for (i = 0; i < COPYR_LINES; ++i)
{
osz = write (ofd, sol, id - sol);
if (osz < 0)
goto badwrite;
osz = write (ofd, copyright[i], strlen (copyright[i]));
if (osz < 0)
goto badwrite;
if (eol >= eid) {
osz = write (ofd, eid, eol - eid + 1);
if (osz < 0)
goto badwrite;
}
}
osz = write (ofd, sol, efbuf - sol);
if (osz < 0)
goto badwrite;
/*
* Copy the remainder of the file.
*/
while ((isz = read (ifd, fbuf, FILECHUNK)) > 0)
{
osz = write (ofd, fbuf, isz);
if (osz < 0)
goto badwrite;
}
if (debug > 0)
fprintf (stderr, "dofile: output file created\n");
if (ifd)
{
close (ofd);
/*
* move files around so the new data appears in place of the old data.
* NOTE: hardlinks to the original data will retain their old content
* NOTE: softlinks to the original data now refer to the new data
*/
if (rename (ifn, tfn) < 0) /* save original file */
{
perror (tfn);
return -1;
}
if (rename (ofn, ifn) < 0) /* move new file into place */
{
perror (ofn);
(void) rename (tfn, ifn); /* try to recover original data */
(void) unlink (ofn); /* try to discard temp file */
return -1;
}
if (unlink (tfn) < 0) /* original data no longer needed */
{
perror (tfn);
return -1;
}
if (debug > 0)
fprintf (stderr, "dofile: moved new file into place\n");
}
return 1;
badwrite:
perror (ofn);
nocando:
close (ofd);
unlink (ofn);
unlink (tfn);
return -1;
}
int
doname (char *ifn)
{
int ifd;
int rv;
if (debug > 0)
fprintf (stderr, "doname: ifn is '%s'\n", ifn);
ifd = open (ifn, O_RDONLY);
if (ifd < 0)
{
perror (ifn);
return -1;
}
rv = dofile (ifn, ifd);
close (ifd);
return rv;
}
int
main (int ac, char **av)
{
int dostdin = 1;
char *ap;
int r;
if (ac > 1)
{
while (ap = *++av)
{
if (*ap == '-')
{
while (ac = *++ap)
{
switch (ac)
{
case 'v':
++verbose;
break;
case 'd':
++debug;
fprintf (stderr, "debug level %d\n", debug);
break;
case 'n':
++dryrun;
break;
}
}
}
else
{
r = doname (ap);
if ((dryrun > 0) || (verbose > 0))
{
fprintf (stderr, "fix_copyright: %s '%s'\n",
r < 0 ? "unable to convert" :
r > 0 ? "converted" :
"no need to convert",
ap);
}
dostdin = 0;
}
}
}
if (dostdin)
{
r = dofile ("stdin", 0);
if ((dryrun > 0) || (verbose > 0))
{
fprintf (stderr, "fix_copyright: %s stdin\n",
r < 0 ? "unable to convert" :
r > 0 ? "converted" :
"no need to convert");
}
}
return 0;
}