summaryrefslogtreecommitdiff
path: root/contrib/untgz/untgz.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/untgz/untgz.c')
-rw-r--r--contrib/untgz/untgz.c507
1 files changed, 258 insertions, 249 deletions
diff --git a/contrib/untgz/untgz.c b/contrib/untgz/untgz.c
index 4a431ff..478d744 100644
--- a/contrib/untgz/untgz.c
+++ b/contrib/untgz/untgz.c
@@ -21,6 +21,7 @@
21#include "zlib.h" 21#include "zlib.h"
22 22
23#ifdef WIN32 23#ifdef WIN32
24#include <windows.h>
24# ifndef F_OK 25# ifndef F_OK
25# define F_OK (0) 26# define F_OK (0)
26# endif 27# endif
@@ -39,37 +40,37 @@
39 40
40/* Values used in typeflag field. */ 41/* Values used in typeflag field. */
41 42
42#define REGTYPE '0' /* regular file */ 43#define REGTYPE '0' /* regular file */
43#define AREGTYPE '\0' /* regular file */ 44#define AREGTYPE '\0' /* regular file */
44#define LNKTYPE '1' /* link */ 45#define LNKTYPE '1' /* link */
45#define SYMTYPE '2' /* reserved */ 46#define SYMTYPE '2' /* reserved */
46#define CHRTYPE '3' /* character special */ 47#define CHRTYPE '3' /* character special */
47#define BLKTYPE '4' /* block special */ 48#define BLKTYPE '4' /* block special */
48#define DIRTYPE '5' /* directory */ 49#define DIRTYPE '5' /* directory */
49#define FIFOTYPE '6' /* FIFO special */ 50#define FIFOTYPE '6' /* FIFO special */
50#define CONTTYPE '7' /* reserved */ 51#define CONTTYPE '7' /* reserved */
51 52
52#define BLOCKSIZE 512 53#define BLOCKSIZE 512
53 54
54struct tar_header 55struct tar_header
55{ /* byte offset */ 56{ /* byte offset */
56 char name[100]; /* 0 */ 57 char name[100]; /* 0 */
57 char mode[8]; /* 100 */ 58 char mode[8]; /* 100 */
58 char uid[8]; /* 108 */ 59 char uid[8]; /* 108 */
59 char gid[8]; /* 116 */ 60 char gid[8]; /* 116 */
60 char size[12]; /* 124 */ 61 char size[12]; /* 124 */
61 char mtime[12]; /* 136 */ 62 char mtime[12]; /* 136 */
62 char chksum[8]; /* 148 */ 63 char chksum[8]; /* 148 */
63 char typeflag; /* 156 */ 64 char typeflag; /* 156 */
64 char linkname[100]; /* 157 */ 65 char linkname[100]; /* 157 */
65 char magic[6]; /* 257 */ 66 char magic[6]; /* 257 */
66 char version[2]; /* 263 */ 67 char version[2]; /* 263 */
67 char uname[32]; /* 265 */ 68 char uname[32]; /* 265 */
68 char gname[32]; /* 297 */ 69 char gname[32]; /* 297 */
69 char devmajor[8]; /* 329 */ 70 char devmajor[8]; /* 329 */
70 char devminor[8]; /* 337 */ 71 char devminor[8]; /* 337 */
71 char prefix[155]; /* 345 */ 72 char prefix[155]; /* 345 */
72 /* 500 */ 73 /* 500 */
73}; 74};
74 75
75union tar_buffer { 76union tar_buffer {
@@ -79,42 +80,43 @@ union tar_buffer {
79 80
80enum { TGZ_EXTRACT = 0, TGZ_LIST }; 81enum { TGZ_EXTRACT = 0, TGZ_LIST };
81 82
82static char *TGZfname OF((const char *)); 83static char *TGZfname OF((const char *));
83void TGZnotfound OF((const char *)); 84void TGZnotfound OF((const char *));
84 85
85int getoct OF((char *, int)); 86int getoct OF((char *, int));
86char *strtime OF((time_t *)); 87char *strtime OF((time_t *));
87int ExprMatch OF((char *,char *)); 88int setftime OF((char *, time_t));
89int ExprMatch OF((char *, char *));
88 90
89int makedir OF((char *)); 91int makedir OF((char *));
90int matchname OF((int,int,char **,char *)); 92int matchname OF((int, int, char **, char *));
91 93
92void error OF((const char *)); 94void error OF((const char *));
93int tar OF((gzFile, int, int, int, char **)); 95int tar OF((gzFile, int, int, int, char **));
94 96
95void help OF((int)); 97void help OF((int));
96int main OF((int, char **)); 98int main OF((int, char **));
97 99
98char *prog; 100char *prog;
99 101
100/* This will give a benign warning */ 102/* This will give a benign warning */
101 103
102static char *TGZprefix[] = { "\0", ".tgz", ".tar.gz", ".tar", NULL }; 104static char *TGZsuffix[] = { "\0", ".tar", ".tar.gz", ".taz", ".tgz", NULL };
103 105
104/* Return the real name of the TGZ archive */ 106/* Return the real name of the TGZ archive */
105/* or NULL if it does not exist. */ 107/* or NULL if it does not exist. */
106 108
107static char *TGZfname OF((const char *fname)) 109static char *TGZfname (const char *fname)
108{ 110{
109 static char buffer[1024]; 111 static char buffer[1024];
110 int origlen,i; 112 int origlen,i;
111 113
112 strcpy(buffer,fname); 114 strcpy(buffer,fname);
113 origlen = strlen(buffer); 115 origlen = strlen(buffer);
114 116
115 for (i=0; TGZprefix[i]; i++) 117 for (i=0; TGZsuffix[i]; i++)
116 { 118 {
117 strcpy(buffer+origlen,TGZprefix[i]); 119 strcpy(buffer+origlen,TGZsuffix[i]);
118 if (access(buffer,F_OK) == 0) 120 if (access(buffer,F_OK) == 0)
119 return buffer; 121 return buffer;
120 } 122 }
@@ -123,33 +125,33 @@ static char *TGZfname OF((const char *fname))
123 125
124/* error message for the filename */ 126/* error message for the filename */
125 127
126void TGZnotfound OF((const char *fname)) 128void TGZnotfound (const char *fname)
127{ 129{
128 int i; 130 int i;
129 131
130 fprintf(stderr,"%s : couldn't find ",prog); 132 fprintf(stderr,"%s : couldn't find ",prog);
131 for (i=0;TGZprefix[i];i++) 133 for (i=0;TGZsuffix[i];i++)
132 fprintf(stderr,(TGZprefix[i+1]) ? "%s%s, " : "or %s%s\n", 134 fprintf(stderr,(TGZsuffix[i+1]) ? "%s%s, " : "or %s%s\n",
133 fname, 135 fname,
134 TGZprefix[i]); 136 TGZsuffix[i]);
135 exit(1); 137 exit(1);
136} 138}
137 139
138 140
139/* help functions */ 141/* help functions */
140 142
141int getoct(char *p,int width) 143int getoct (char *p,int width)
142{ 144{
143 int result = 0; 145 int result = 0;
144 char c; 146 char c;
145 147
146 while (width --) 148 while (width --)
147 { 149 {
148 c = *p++; 150 c = *p++;
149 if (c == ' ') 151 if (c == ' ')
150 continue; 152 continue;
151 if (c == 0) 153 if (c == 0)
152 break; 154 break;
153 result = result * 8 + (c - '0'); 155 result = result * 8 + (c - '0');
154 } 156 }
155 return result; 157 return result;
@@ -162,9 +164,49 @@ char *strtime (time_t *t)
162 164
163 local = localtime(t); 165 local = localtime(t);
164 sprintf(result,"%2d/%02d/%4d %02d:%02d:%02d", 166 sprintf(result,"%2d/%02d/%4d %02d:%02d:%02d",
165 local->tm_mday, local->tm_mon+1, local->tm_year+1900, 167 local->tm_mday, local->tm_mon+1, local->tm_year+1900,
166 local->tm_hour, local->tm_min, local->tm_sec); 168 local->tm_hour, local->tm_min, local->tm_sec);
169 return result;
170}
171
172int setftime (char *fname,time_t ftime)
173{
174#ifdef WIN32
175 SYSTEMTIME st;
176 FILETIME locft, modft;
177 struct tm *loctm;
178 HANDLE hFile;
179 int result;
180
181 loctm = localtime(&ftime);
182 if (loctm == NULL)
183 return -1;
184
185 st.wYear = (WORD)loctm->tm_year + 1900;
186 st.wMonth = (WORD)loctm->tm_mon + 1;
187 st.wDayOfWeek = (WORD)loctm->tm_wday;
188 st.wDay = (WORD)loctm->tm_mday;
189 st.wHour = (WORD)loctm->tm_hour;
190 st.wMinute = (WORD)loctm->tm_min;
191 st.wSecond = (WORD)loctm->tm_sec;
192 st.wMilliseconds = 0;
193 if (!SystemTimeToFileTime(&st, &locft) ||
194 !LocalFileTimeToFileTime(&locft, &modft))
195 return -1;
196
197 hFile = CreateFile(fname, GENERIC_READ | GENERIC_WRITE,
198 0, NULL, OPEN_EXISTING, 0, 0);
199 if (hFile == INVALID_HANDLE_VALUE)
200 return -1;
201 result = SetFileTime(hFile, NULL, NULL, &modft) ? 0 : -1;
202 CloseHandle(hFile);
167 return result; 203 return result;
204#else
205 struct utimbuf settime;
206
207 settime.actime = settime.modtime = ftime;
208 return utime(fname,&settime);
209#endif
168} 210}
169 211
170 212
@@ -172,35 +214,35 @@ char *strtime (time_t *t)
172 214
173#define ISSPECIAL(c) (((c) == '*') || ((c) == '/')) 215#define ISSPECIAL(c) (((c) == '*') || ((c) == '/'))
174 216
175int ExprMatch(char *string,char *expr) 217int ExprMatch (char *string,char *expr)
176{ 218{
177 while (1) 219 while (1)
178 { 220 {
179 if (ISSPECIAL(*expr)) 221 if (ISSPECIAL(*expr))
180 { 222 {
181 if (*expr == '/') 223 if (*expr == '/')
182 { 224 {
183 if (*string != '\\' && *string != '/') 225 if (*string != '\\' && *string != '/')
184 return 0; 226 return 0;
185 string ++; expr++; 227 string ++; expr++;
186 } 228 }
187 else if (*expr == '*') 229 else if (*expr == '*')
188 { 230 {
189 if (*expr ++ == 0) 231 if (*expr ++ == 0)
190 return 1; 232 return 1;
191 while (*++string != *expr) 233 while (*++string != *expr)
192 if (*string == 0) 234 if (*string == 0)
193 return 0; 235 return 0;
194 } 236 }
195 } 237 }
196 else 238 else
197 { 239 {
198 if (*string != *expr) 240 if (*string != *expr)
199 return 0; 241 return 0;
200 if (*expr++ == 0) 242 if (*expr++ == 0)
201 return 1; 243 return 1;
202 string++; 244 string++;
203 } 245 }
204 } 246 }
205} 247}
206 248
@@ -216,7 +258,7 @@ int makedir (char *newdir)
216 char *buffer = strdup(newdir); 258 char *buffer = strdup(newdir);
217 char *p; 259 char *p;
218 int len = strlen(buffer); 260 int len = strlen(buffer);
219 261
220 if (len <= 0) { 262 if (len <= 0) {
221 free(buffer); 263 free(buffer);
222 return 0; 264 return 0;
@@ -234,19 +276,19 @@ int makedir (char *newdir)
234 while (1) 276 while (1)
235 { 277 {
236 char hold; 278 char hold;
237 279
238 while(*p && *p != '\\' && *p != '/') 280 while(*p && *p != '\\' && *p != '/')
239 p++; 281 p++;
240 hold = *p; 282 hold = *p;
241 *p = 0; 283 *p = 0;
242 if ((mkdir(buffer, 0775) == -1) && (errno == ENOENT)) 284 if ((mkdir(buffer, 0775) == -1) && (errno == ENOENT))
243 { 285 {
244 fprintf(stderr,"%s: couldn't create directory %s\n",prog,buffer); 286 fprintf(stderr,"%s: couldn't create directory %s\n",prog,buffer);
245 free(buffer); 287 free(buffer);
246 return 0; 288 return 0;
247 } 289 }
248 if (hold == 0) 290 if (hold == 0)
249 break; 291 break;
250 *p++ = hold; 292 *p++ = hold;
251 } 293 }
252 free(buffer); 294 free(buffer);
@@ -255,7 +297,7 @@ int makedir (char *newdir)
255 297
256int matchname (int arg,int argc,char **argv,char *fname) 298int matchname (int arg,int argc,char **argv,char *fname)
257{ 299{
258 if (arg == argc) /* no arguments given (untgz tgzarchive) */ 300 if (arg == argc) /* no arguments given (untgz tgzarchive) */
259 return 1; 301 return 1;
260 302
261 while (arg < argc) 303 while (arg < argc)
@@ -278,144 +320,111 @@ int tar (gzFile in,int action,int arg,int argc,char **argv)
278 FILE *outfile = NULL; 320 FILE *outfile = NULL;
279 char fname[BLOCKSIZE]; 321 char fname[BLOCKSIZE];
280 time_t tartime; 322 time_t tartime;
281 323
282 if (action == TGZ_LIST) 324 if (action == TGZ_LIST)
283 printf(" day time size file\n" 325 printf(" day time size file\n"
284 " ---------- -------- --------- -------------------------------------\n"); 326 " ---------- -------- --------- -------------------------------------\n");
285 while (1) 327 while (1)
286 { 328 {
287 len = gzread(in, &buffer, BLOCKSIZE); 329 len = gzread(in, &buffer, BLOCKSIZE);
288 if (len < 0) 330 if (len < 0)
289 error (gzerror(in, &err)); 331 error (gzerror(in, &err));
290 /* 332 /*
291 * Always expect complete blocks to process 333 * Always expect complete blocks to process
292 * the tar information. 334 * the tar information.
293 */ 335 */
294 if (len != BLOCKSIZE) 336 if (len != BLOCKSIZE)
295 error("gzread: incomplete block read"); 337 error("gzread: incomplete block read");
296 338
297 /* 339 /*
298 * If we have to get a tar header 340 * If we have to get a tar header
299 */ 341 */
300 if (getheader == 1) 342 if (getheader == 1)
301 { 343 {
302 /* 344 /*
303 * if we met the end of the tar 345 * if we met the end of the tar
304 * or the end-of-tar block, 346 * or the end-of-tar block,
305 * we are done 347 * we are done
306 */ 348 */
307 if ((len == 0) || (buffer.header.name[0]== 0)) break; 349 if ((len == 0) || (buffer.header.name[0]== 0)) break;
308 350
309 tartime = (time_t)getoct(buffer.header.mtime,12); 351 tartime = (time_t)getoct(buffer.header.mtime,12);
310 strcpy(fname,buffer.header.name); 352 strcpy(fname,buffer.header.name);
311 353
312 switch (buffer.header.typeflag) 354 switch (buffer.header.typeflag)
313 { 355 {
314 case DIRTYPE: 356 case DIRTYPE:
315 if (action == TGZ_LIST) 357 if (action == TGZ_LIST)
316 printf(" %s <dir> %s\n",strtime(&tartime),fname); 358 printf(" %s <dir> %s\n",strtime(&tartime),fname);
317 if (action == TGZ_EXTRACT) 359 if (action == TGZ_EXTRACT)
318 makedir(fname); 360 makedir(fname);
319 break; 361 break;
320 case REGTYPE: 362 case REGTYPE:
321 case AREGTYPE: 363 case AREGTYPE:
322 remaining = getoct(buffer.header.size,12); 364 remaining = getoct(buffer.header.size,12);
323 if (action == TGZ_LIST) 365 if (action == TGZ_LIST)
324 printf(" %s %9d %s\n",strtime(&tartime),remaining,fname); 366 printf(" %s %9d %s\n",strtime(&tartime),remaining,fname);
325 if (action == TGZ_EXTRACT) 367 if (action == TGZ_EXTRACT)
326 { 368 {
327 if ((remaining) && (matchname(arg,argc,argv,fname))) 369 if ((remaining) && (matchname(arg,argc,argv,fname)))
328 { 370 {
329 outfile = fopen(fname,"wb"); 371 outfile = fopen(fname,"wb");
330 if (outfile == NULL) { 372 if (outfile == NULL) {
331 /* try creating directory */ 373 /* try creating directory */
332 char *p = strrchr(fname, '/'); 374 char *p = strrchr(fname, '/');
333 if (p != NULL) { 375 if (p != NULL) {
334 *p = '\0'; 376 *p = '\0';
335 makedir(fname); 377 makedir(fname);
336 *p = '/'; 378 *p = '/';
337 outfile = fopen(fname,"wb"); 379 outfile = fopen(fname,"wb");
338 } 380 }
339 } 381 }
340 fprintf(stderr, 382 fprintf(stderr,
341 "%s %s\n", 383 "%s %s\n",
342 (outfile) ? "Extracting" : "Couldn't create", 384 (outfile) ? "Extracting" : "Couldn't create",
343 fname); 385 fname);
344 } 386 }
345 else 387 else
346 outfile = NULL; 388 outfile = NULL;
347 } 389 }
348 /* 390 /*
349 * could have no contents 391 * could have no contents
350 */ 392 */
351 getheader = (remaining) ? 0 : 1; 393 getheader = (remaining) ? 0 : 1;
352 break; 394 break;
353 default: 395 default:
354 if (action == TGZ_LIST) 396 if (action == TGZ_LIST)
355 printf(" %s <---> %s\n",strtime(&tartime),fname); 397 printf(" %s <---> %s\n",strtime(&tartime),fname);
356 break; 398 break;
357 } 399 }
358 } 400 }
359 else 401 else
360 { 402 {
361 unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining; 403 unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining;
362 404
363 if ((action == TGZ_EXTRACT) && (outfile != NULL)) 405 if ((action == TGZ_EXTRACT) && (outfile != NULL))
364 { 406 {
365 if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes) 407 if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes)
366 { 408 {
367 fprintf(stderr,"%s : error writing %s skipping...\n",prog,fname); 409 fprintf(stderr,"%s : error writing %s skipping...\n",prog,fname);
368 fclose(outfile); 410 fclose(outfile);
369 unlink(fname); 411 unlink(fname);
370 } 412 }
371 } 413 }
372 remaining -= bytes; 414 remaining -= bytes;
373 if (remaining == 0) 415 if (remaining == 0)
374 { 416 {
375 getheader = 1; 417 getheader = 1;
376 if ((action == TGZ_EXTRACT) && (outfile != NULL)) 418 if ((action == TGZ_EXTRACT) && (outfile != NULL))
377 { 419 {
378#ifdef WIN32 420 fclose(outfile);
379 HANDLE hFile; 421 outfile = NULL;
380 FILETIME ftm,ftLocal; 422 setftime(fname,tartime);
381 SYSTEMTIME st; 423 }
382 struct tm localt; 424 }
383 425 }
384 fclose(outfile);
385
386 localt = *localtime(&tartime);
387
388 hFile = CreateFile(fname, GENERIC_READ | GENERIC_WRITE,
389 0, NULL, OPEN_EXISTING, 0, NULL);
390
391 st.wYear = (WORD)localt.tm_year+1900;
392 st.wMonth = (WORD)localt.tm_mon;
393 st.wDayOfWeek = (WORD)localt.tm_wday;
394 st.wDay = (WORD)localt.tm_mday;
395 st.wHour = (WORD)localt.tm_hour;
396 st.wMinute = (WORD)localt.tm_min;
397 st.wSecond = (WORD)localt.tm_sec;
398 st.wMilliseconds = 0;
399 SystemTimeToFileTime(&st,&ftLocal);
400 LocalFileTimeToFileTime(&ftLocal,&ftm);
401 SetFileTime(hFile,&ftm,NULL,&ftm);
402 CloseHandle(hFile);
403
404 outfile = NULL;
405#else
406 struct utimbuf settime;
407
408 settime.actime = settime.modtime = tartime;
409
410 fclose(outfile);
411 outfile = NULL;
412 utime(fname,&settime);
413#endif
414 }
415 }
416 }
417 } 426 }
418 427
419 if (gzclose(in) != Z_OK) 428 if (gzclose(in) != Z_OK)
420 error("failed gzclose"); 429 error("failed gzclose");
421 430
@@ -428,12 +437,12 @@ int tar (gzFile in,int action,int arg,int argc,char **argv)
428void help(int exitval) 437void help(int exitval)
429{ 438{
430 fprintf(stderr, 439 fprintf(stderr,
431 "untgz v 0.1\n" 440 "untgz version 0.1\n"
432 " an sample application of zlib 1.0.4\n\n" 441 " a sample application of zlib\n\n"
433 "Usage : untgz TGZfile to extract all files\n" 442 "Usage : untgz file.tgz to extract all files\n"
434 " untgz TGZfile fname ... to extract selected files\n" 443 " untgz file.tgz fname ... to extract selected files\n"
435 " untgz -l TGZfile to list archive contents\n" 444 " untgz -l file.tgz to list archive contents\n"
436 " untgz -h to display this help\n\n"); 445 " untgz -h to display this help\n\n");
437 exit(exitval); 446 exit(exitval);
438} 447}
439 448
@@ -446,50 +455,50 @@ void error(const char *msg)
446 455
447/* ====================================================================== */ 456/* ====================================================================== */
448 457
449int _CRT_glob = 0; /* disable globbing of the arguments */ 458int _CRT_glob = 0; /* disable globbing of the arguments */
450 459
451int main(int argc,char **argv) 460int main(int argc,char **argv)
452{ 461{
453 int action = TGZ_EXTRACT; 462 int action = TGZ_EXTRACT;
454 int arg = 1; 463 int arg = 1;
455 char *TGZfile; 464 char *TGZfile;
456 gzFile *f; 465 gzFile *f;
457 466
458 467
459 prog = strrchr(argv[0],'\\'); 468 prog = strrchr(argv[0],'\\');
460 if (prog == NULL) 469 if (prog == NULL)
461 { 470 {
462 prog = strrchr(argv[0],'/'); 471 prog = strrchr(argv[0],'/');
463 if (prog == NULL) 472 if (prog == NULL)
464 { 473 {
465 prog = strrchr(argv[0],':'); 474 prog = strrchr(argv[0],':');
466 if (prog == NULL) 475 if (prog == NULL)
467 prog = argv[0]; 476 prog = argv[0];
468 else 477 else
469 prog++; 478 prog++;
470 } 479 }
471 else 480 else
472 prog++; 481 prog++;
473 } 482 }
474 else 483 else
475 prog++; 484 prog++;
476 485
477 if (argc == 1) 486 if (argc == 1)
478 help(0); 487 help(0);
479 488
480 if (strcmp(argv[arg],"-l") == 0) 489 if (strcmp(argv[arg],"-l") == 0)
481 { 490 {
482 action = TGZ_LIST; 491 action = TGZ_LIST;
483 if (argc == ++arg) 492 if (argc == ++arg)
484 help(0); 493 help(0);
485 } 494 }
486 else if (strcmp(argv[arg],"-h") == 0) 495 else if (strcmp(argv[arg],"-h") == 0)
487 { 496 {
488 help(0); 497 help(0);
489 } 498 }
490 499
491 if ((TGZfile = TGZfname(argv[arg])) == NULL) 500 if ((TGZfile = TGZfname(argv[arg])) == NULL)
492 TGZnotfound(argv[arg]); 501 TGZnotfound(argv[arg]);
493 502
494 ++arg; 503 ++arg;
495 if ((action == TGZ_LIST) && (arg != argc)) 504 if ((action == TGZ_LIST) && (arg != argc))
@@ -502,20 +511,20 @@ int main(int argc,char **argv)
502 { 511 {
503 case TGZ_LIST: 512 case TGZ_LIST:
504 case TGZ_EXTRACT: 513 case TGZ_EXTRACT:
505 f = gzopen(TGZfile,"rb"); 514 f = gzopen(TGZfile,"rb");
506 if (f == NULL) 515 if (f == NULL)
507 { 516 {
508 fprintf(stderr,"%s: Couldn't gzopen %s\n", 517 fprintf(stderr,"%s: Couldn't gzopen %s\n",
509 prog, 518 prog,
510 TGZfile); 519 TGZfile);
511 return 1; 520 return 1;
512 } 521 }
513 exit(tar(f, action, arg, argc, argv)); 522 exit(tar(f, action, arg, argc, argv));
514 break; 523 break;
515 524
516 default: 525 default:
517 error("Unknown option!"); 526 error("Unknown option!");
518 exit(1); 527 exit(1);
519 } 528 }
520 529
521 return 0; 530 return 0;