2
* $Id: rearj.c,v 1.10 2004/05/31 16:08:41 andrew_belov Exp $
3
* ---------------------------------------------------------------------------
4
* This is the main file of the REARJ utility.
24
DEBUGHDR(__FILE__) /* Debug information block */
26
/* Limits for "*.*"-alike processing */
28
#define LARGE_FLIST_SIZE 20000
29
#define EXCL_FLIST_SIZE 10000
31
#define LARGE_FLIST_SIZE FILELIST_CAPACITY
32
#define EXCL_FLIST_SIZE FILELIST_CAPACITY
35
#define MAX_SUFFIXES 25 /* Number of supported suffixes */
37
#define MAX_SUFFIX 3 /* Consider increasing... */
41
#define MAX_ARGS 100 /* Maximum # of command-line args */
44
#define REARJ_SWITCHAR "-"
46
#define REARJ_SWITCHAR "/"
49
/* Time output sequence */
51
#define timeseq (int)log_ts.ti_hour, (int)log_ts.ti_min, (int)log_ts.ti_sec
53
/* Configuration entry structure */
60
int hidden_supported; /* Consider making them chars */
61
int subdirs_supported;
62
/* The following is an ASR fix for REARJ v 2.42.05 (.tar.gz) */
63
int manual_deletion; /* Can't delete errorneous archives */
68
static int logging_enabled; /* 1 if actions are to be logged */
69
static struct time log_ts; /* Current time (for logging) */
70
static int total_suffixes; /* Number of suffixes in REARJ.CFG */
71
static struct archiver_entry archivers[MAX_SUFFIXES];
72
static int target_type; /* Target archive type */
73
static FILE *logstream; /* Log file */
74
static int ctrlc_busy; /* 1 if Ctrl+C can't be processed */
75
static int cnv_diskette_archives; /* Convert diskette archives (-f) */
76
static int internal_archives_only; /* Process only internal archive
78
static int update_with_backups; /* Allow updates of archives with
80
static int conversion_query; /* Query for conversion (-q) */
81
static int skip_size_check; /* Do not check total size and count */
82
static int run_preunpack_cmd; /* Run a cmd. before unpacking */
83
static int run_precount_cmd; /* 1 if a command must be run before
85
static int run_extract_cmd; /* Run a command when all files have
87
static int testing_mode; /* /Y testing mode */
88
static char *backup_extension; /* "BAK" (without a preceding dot) */
89
static char dot[]="."; /* Widely-used symbol */
90
static char work_dir[CCHMAXPATH]; /* Working directory */
91
static char name_fetch[CCHMAXPATH]; /* For parsing list files */
92
static int default_suffix; /* For non-standard extensions */
94
static char *preunpack_cmd_text;
95
static char *precount_cmd_text;
96
static char *extract_cmd_text;
97
static struct timestamp ts_newer;
98
static struct timestamp ts_older;
100
static int cleanup_initiated;
101
static int ctrlc_initiated;
102
static int skip_packing;
103
static int skip_rearj_sw;
104
static int skip_larger_output;
105
static int skip_timestamping;
106
static int pick_older; /* Pick older archives (/m) */
107
static int pick_newer; /* Pick newer archives (/n) */
108
static int exclusion_assigned; /* Never used but implemented (/x) */
109
static int convert_nested_archives;
110
static char *acc_nested_suffixes; /* Filter for nested archives */
111
static int delete_original_archives;
112
static unsigned long total_old_fsize, total_new_fsize;
114
static int chk_integrity;
115
static char *suffix_override;
116
static char *log_name;
117
static char *target_suffix;
118
static char *testing_marker; /* Text to write (/Y****) */
119
static char *timestr_older;
120
static char *timestr_newer;
121
static FILE *liststream;
122
static struct date x_date;
123
static int work_directory_assigned;
124
static int skip_count;
125
static int clear_tmp_dir; /* 1 if files in tmp. dir must be
126
removed upon shutdown */
127
static char *arg_ptr[MAX_ARGS]; /* Argument table */
128
static char u_strform[]="%S";
129
static char single_spc[]=" ";
131
static int tmpdir_malloced;
132
static char rearj_sw[]="REARJ_SW";
134
/* Filenames/extensions */
136
static char backup_ext[]="bak";
137
static char cfg_name[]="rearj.cfg";
138
static char rearj_log[]="rearj.log";
140
/* Pauses the execution and displays an error */
142
void pause_error(FMSG *msg)
145
msg_cprintf(H_ERR, msg);
146
exit(REARJ_ERL_WARNING);
149
/* Resets the attributes of all files in the current directory */
151
static void reset_attrs()
153
char tmp_name[CCHMAXPATH];
154
struct flist_root tmp_flist;
157
strcpy(tmp_name, all_wildcard);
158
flist_init(&tmp_flist, LARGE_FLIST_SIZE, 0, 0);
159
wild_list(&tmp_flist, tmp_name, FETCH_DIRS, 1, 1, NULL);
160
for(i=0; i<tmp_flist.files; i++)
162
retrieve_entry(tmp_name, &tmp_flist, i);
164
if(file_chmod(tmp_name, 1, 0)==-1)
165
error(M_CANT_CLEAR_ATTRS, tmp_name);
167
flist_cleanup_proc(&tmp_flist);
170
/* Returns total size of the files located in the current directory */
172
static unsigned long count_total_size()
174
char tmp_name[CCHMAXPATH];
175
struct flist_root tmp_flist;
180
strcpy(tmp_name, all_wildcard);
181
flist_init(&tmp_flist, LARGE_FLIST_SIZE, 0, 0);
182
wild_list(&tmp_flist, tmp_name, FETCH_DIRS, 1, 1, NULL);
183
for(i=0; i<tmp_flist.files; i++)
185
retrieve_entry(tmp_name, &tmp_flist, i);
187
rc+=(unsigned long)file_getfsize(tmp_name);
189
flist_cleanup_proc(&tmp_flist);
193
/* Copies one file to another with mandatory comparison */
195
static int file_copy_v(char *src, char *dest)
197
FILE *istream, *ostream;
198
char buf[CACHE_SIZE], dbuf[CACHE_SIZE];
201
istream=file_open(src, m_rb);
204
ostream=file_open(dest, m_wb);
214
if((bytes_read=fread(buf, 1, sizeof(buf), istream))==0)
216
} while(fwrite(buf, 1, bytes_read, ostream)==bytes_read);
224
istream=file_open(src, m_rb);
227
ostream=file_open(dest, m_rb);
236
if((bytes_read=fread(buf, 1, CACHE_SIZE, istream))==0)
238
if(fread(dbuf, 1, CACHE_SIZE, ostream)!=bytes_read)
240
if(memcmp(buf, dbuf, bytes_read))
246
return((bytes_read>0)?-1:0);
249
/* Returns total number of the files located in the current directory */
251
static FILE_COUNT count_files()
253
char tmp_name[CCHMAXPATH];
254
struct flist_root tmp_flist;
257
strcpy(tmp_name, all_wildcard);
258
flist_init(&tmp_flist, LARGE_FLIST_SIZE, 0, 0);
259
wild_list(&tmp_flist, tmp_name, FETCH_DIRS, 1, 1, NULL);
261
flist_cleanup_proc(&tmp_flist);
265
/* Recursively removes files and subdirectories */
267
static void recursive_unlink(char *name)
269
struct new_ffblk new_ffblk;
270
char tmp_name[CCHMAXPATH];
271
char subdir_wildcard[20];
275
attr_mask=STD_FI_ATTRS;
276
result=lfn_findfirst(name, &new_ffblk, attr_mask);
279
if(new_ffblk.ff_attrib&STD_DIR_ATTR)
281
if(strcmp(new_ffblk.ff_name, cur_dir_spec)&&strcmp(new_ffblk.ff_name, up_dir_spec))
283
split_name(name, tmp_name, subdir_wildcard);
284
if(strlen(new_ffblk.ff_name)+strlen(tmp_name)+strlen(subdir_wildcard)+2>=CCHMAXPATH)
285
error(M_MAXDIR_EXCEEDED, tmp_name);
286
strcat(tmp_name, new_ffblk.ff_name);
287
strcat(tmp_name, pathsep_str);
288
strcat(tmp_name, subdir_wildcard);
290
recursive_unlink(tmp_name);
291
/* Remove the directory itself */
292
split_name(name, tmp_name, NULL);
293
strcat(tmp_name, new_ffblk.ff_name);
295
file_chmod(tmp_name, 1, 0);
296
if(file_rmdir(tmp_name))
297
error(M_CANT_RMDIR, tmp_name);
302
split_name(name, tmp_name, NULL);
303
strcat(tmp_name, new_ffblk.ff_name);
306
file_chmod(tmp_name, 1, 0);
307
if(file_unlink(tmp_name))
308
error(M_CANT_UNLINK, tmp_name);
310
result=lfn_findnext(&new_ffblk);
312
lfn_findclose(&new_ffblk);
315
/* Releases the working directory -- ASR fix 14/11/2000 */
317
static void release_dir(char *dir)
322
if(dir[0]!='\0'&&dir[1]==':')
324
memcpy(tmp_name, dir, 2);
325
strcpy(tmp_name+2, pathsep_str);
328
strcpy(tmp_name, pathsep_str);
330
strcpy(tmp_name, pathsep_str);
332
file_chdir(tmp_name);
335
/* Removes all files on the specified drive/path */
337
static void unlink_all(char *path)
339
char tmp_path[CCHMAXPATH];
342
strcpy(tmp_path, path);
344
c=tmp_path[strlen(tmp_path)-1];
346
strcat(tmp_path, (c==PATHSEP_DEFAULT||c==':')?all_wildcard:root_wildcard);
348
strcat(tmp_path, (c==PATHSEP_DEFAULT)?all_wildcard:root_wildcard);
351
msg_cprintf(H_HL|H_NFMT, M_DELETING, tmp_path);
352
recursive_unlink(tmp_path);
355
/* Writes a "SKIPPED" log entry */
357
static void log_as_skipped(char *name, int reason)
361
arj_gettime(&log_ts);
362
if(fprintf(logstream, M_LOGENTRY_SKIP, timeseq, archivers[target_type].suffix, reason, name)<=0)
363
error(M_CANT_WRITE_LOG);
367
/* Checks if any subdirectories are present in the current directory */
369
static int check_for_dirs()
371
char tmp_name[CCHMAXPATH];
372
struct new_ffblk new_ffblk;
376
strcpy(tmp_name, all_wildcard);
377
attr_mask=STD_FI_ATTRS;
378
result=lfn_findfirst(tmp_name, &new_ffblk, attr_mask);
381
if(new_ffblk.ff_attrib&STD_DIR_ATTR&&strcmp(new_ffblk.ff_name, cur_dir_spec)&&strcmp(new_ffblk.ff_name, up_dir_spec))
383
lfn_findclose(&new_ffblk);
386
result=lfn_findnext(&new_ffblk);
388
lfn_findclose(&new_ffblk);
392
/* Checks if any files and/or subdirectories are present in the current
395
static int check_for_entries()
397
char tmp_name[CCHMAXPATH];
398
struct new_ffblk new_ffblk;
402
strcpy(tmp_name, all_wildcard);
403
attr_mask=STD_FI_ATTRS;
404
result=lfn_findfirst(tmp_name, &new_ffblk, attr_mask);
407
if(!(new_ffblk.ff_attrib&STD_DIR_ATTR))
409
lfn_findclose(&new_ffblk);
412
else if(strcmp(new_ffblk.ff_name, cur_dir_spec)&&strcmp(new_ffblk.ff_name, up_dir_spec))
414
lfn_findclose(&new_ffblk);
417
result=lfn_findnext(&new_ffblk);
419
lfn_findclose(&new_ffblk);
423
/* Returns a fully-qualified filename */
425
static int truename(char *dest, char *name)
427
char tmp_name[CCHMAXPATH], cur_dir[CCHMAXPATH];
433
tmp_entry=split_name(name, dest, tmp_name);
434
/* Verify if it's a root directory path or file path */
437
(dest[1]!=':'||dest[2]!='\0')&&
438
(dest[1]!=':'||dest[2]!=PATHSEP_DEFAULT||dest[3]!='\0')&&
440
(dest[0]!=PATHSEP_DEFAULT||dest[1]!='\0')&&
442
dest[tmp_entry-1]='\0';
446
setdisk(toupper(dest[0])-'A');
448
if(file_getcwd(cur_dir)==NULL)
450
msg_cprintf(0, M_GETCWD_FAILED);
455
(dest[1]!=':'||dest[2]!='\0')&&
461
msg_cprintf(H_HL|H_NFMT, M_PATH_NOT_FOUND, dest);
463
if(file_chdir(cur_dir))
464
error(M_CANT_CHDIR, cur_dir);
471
if(file_getcwd(dest)==NULL)
473
msg_cprintf(0, M_GETCWD_FAILED);
476
if(tmp_name[0]!='\0'&&dest[strlen(dest)-1]!=PATHSEP_DEFAULT)
477
strcat(dest, pathsep_str);
478
strcat(dest, tmp_name);
479
if(file_chdir(cur_dir))
480
error(M_CANT_CHDIR, cur_dir);
487
/* Runs an external command */
489
static int exec_cmd(char *cmd)
503
/* Runs an external executable */
505
static int exec_exe(char *cmd)
519
/* Archive conversion procedure */
521
static int convert_archive(char *name)
523
long old_fsize, new_fsize;
525
char full_name[CCHMAXPATH], target_name[CCHMAXPATH];
526
char bak_name[CCHMAXPATH];
527
char cnv_name[CCHMAXPATH]; /* Converted file in the work dir. */
535
struct timestamp old_ftime;
536
char cmd_buffer[400];
537
FILE_COUNT old_count=0, new_count;
538
char *nst_suf_wildcard;
539
unsigned long old_size=0, new_size;
542
int match, fspec_len, pattern_len;
547
if(truename(full_name, name))
549
msg_cprintf(H_HL|H_NFMT, M_SKIP_CANT_FIND, name);
550
return(REARJ_ERL_WARNING);
552
entry=split_name(full_name, NULL, filespec);
554
fspec_len=strlen(filespec);
556
dot_pos=strrchr(filespec, '.');
562
strcpy(target_name, full_name);
563
strcat(target_name, dot);
564
strcat(target_name, archivers[target_type].suffix);
565
strcpy(bak_name, full_name);
571
strcpy(extension, dot_pos);
573
strncpy(target_name, full_name, entry);
574
target_name[entry]='\0';
575
strcpy(bak_name, target_name);
577
strcat(target_name, filespec);
578
strcat(target_name, dot);
579
strcat(target_name, archivers[target_type].suffix);
581
strcat(bak_name, filespec);
583
strcat(bak_name, dot);
584
strcat(bak_name, backup_extension);
585
strcpy(cnv_name, work_dir);
586
strcat(cnv_name, pathsep_str);
587
strcat(cnv_name, filespec);
588
strcat(cnv_name, dot);
589
strcat(cnv_name, archivers[target_type].suffix);
590
repack=!strcmp_os(target_name, full_name);
591
tmp_name=cnv_diskette_archives?cnv_name:target_name;
593
for(i=0; i<total_suffixes; i++)
599
if(archivers[i].suffix[0]=='\0')
604
pattern_len=strlen(archivers[i].suffix);
605
if(fspec_len>pattern_len&&
606
filespec[fspec_len-pattern_len-1]=='.'&&
607
!strcmp_os(filespec+fspec_len-pattern_len, archivers[i].suffix))
610
strcat(target_name, filespec);
611
target_name[strlen(target_name)-pattern_len]='\0';
612
strcat(target_name, archivers[target_type].suffix);
618
if(!strcmp_os(extension, archivers[i].suffix))
623
src_type=default_suffix;
626
msg_cprintf(H_HL|H_NFMT, M_SKIP_UNKNOWN_TYPE, full_name);
627
return(REARJ_ERL_UNCONFIGURED);
629
old_fsize=file_getfsize(full_name);
630
if((!overwrite_existing&&!repack&&file_exists(target_name))||
631
(cnv_diskette_archives&&!overwrite_existing&&file_exists(cnv_name)))
633
msg_cprintf(H_HL|H_NFMT, M_SKIP_TGT_EXISTS, full_name);
634
return(REARJ_ERL_TGT_EXISTS);
636
if(!update_with_backups&&repack)
638
msg_cprintf(H_HL|H_NFMT, M_SKIP_REPACK, full_name);
639
return(REARJ_ERL_UPD_SKIPPED);
641
msg_cprintf(H_HL|H_NFMT, M_CONVERTING_ARCHIVE, full_name, archivers[src_type].suffix, archivers[target_type].suffix);
644
msg_cprintf(0, M_QUERY_CONVERT);
647
msg_cprintf(H_HL|H_NFMT, M_SKIPPING, full_name);
648
return(REARJ_ERL_UPD_SKIPPED);
651
if(overwrite_existing&&!repack&&file_exists(target_name)&&!no_file_activity)
652
if(file_unlink(target_name))
653
error(M_CANT_UNLINK, target_name);
654
if(cnv_diskette_archives&&overwrite_existing&&file_exists(cnv_name)&&!no_file_activity)
655
if(file_unlink(cnv_name))
656
error(M_CANT_UNLINK, cnv_name);
657
ts_store(&old_ftime, OS, file_getftime(full_name));
659
if(file_chdir(tmp_dir))
660
error(M_CANT_CHDIR, tmp_dir);
661
if(run_preunpack_cmd)
663
sprintf(cmd_buffer, "%s %s", preunpack_cmd_text, full_name);
664
msg_cprintf(H_HL|H_NFMT, M_EXECUTING_PRE, cmd_buffer);
665
exec_cmd(cmd_buffer);
667
sprintf(cmd_buffer, archivers[src_type].unpack_cmd, full_name);
668
msg_cprintf(H_HL|H_NFMT, M_EXECUTING, cmd_buffer);
669
exec_rc=exec_exe(cmd_buffer);
673
msg_cprintf(H_HL|H_NFMT, M_SKIP_EXE_MISSING, full_name);
675
msg_cprintf(H_HL|H_NFMT, M_SKIP_UNPACK_ERR, full_name, exec_rc);
676
return(REARJ_ERL_UNPACK);
678
if(!archivers[target_type].subdirs_supported&&check_for_dirs())
680
msg_cprintf(H_HL|H_NFMT, M_SKIP_UNSUPP_DIR, full_name);
681
return(REARJ_ERL_DIRECTORIES);
683
if(!check_for_entries())
685
msg_cprintf(H_HL|H_NFMT, M_SKIP_NO_FILES, full_name);
686
return(REARJ_ERL_UNPACK);
690
sprintf(cmd_buffer, "%s %s", precount_cmd_text, full_name);
691
msg_cprintf(H_HL|H_NFMT, M_EXECUTING_CNT, cmd_buffer);
692
exec_cmd(cmd_buffer);
695
old_count=count_files();
698
msg_cprintf(H_HL|H_NFMT, M_EXECUTING_EXTR, extract_cmd_text);
699
exec_rc=exec_exe(extract_cmd_text);
703
msg_cprintf(H_HL|H_NFMT, M_SKIP_V_EXE_MISSING, full_name);
705
msg_cprintf(H_HL|H_NFMT, M_SKIP_V_ERR, full_name, exec_rc);
706
return(REARJ_ERL_VIRUS);
709
if(convert_nested_archives)
711
nst_suf_wildcard=(acc_nested_suffixes!=NULL)?acc_nested_suffixes:archivers[src_type].suffix;
712
/* ASR FIX 30/12/1999: only 6 additional (%s) params in original REARJ v 2.42 */
714
"%s *.%s " REARJ_SWITCHAR "t%s " REARJ_SWITCHAR "d " REARJ_SWITCHAR "r " REARJ_SWITCHAR "a%s " REARJ_SWITCHAR "e%s%s%s%s%s%s%s",
717
archivers[target_type].suffix,
719
skip_size_check?" " REARJ_SWITCHAR "s":nullstr,
720
no_file_activity?" " REARJ_SWITCHAR "z":nullstr,
721
update_with_backups?" " REARJ_SWITCHAR "u":nullstr,
722
overwrite_existing?" " REARJ_SWITCHAR "o":nullstr,
723
run_extract_cmd?" " REARJ_SWITCHAR "v":nullstr,
724
skip_rearj_sw?" " REARJ_SWITCHAR "+":nullstr,
725
skip_packing?" " REARJ_SWITCHAR "g":nullstr);
726
msg_cprintf(H_HL|H_NFMT, M_EXECUTING, cmd_buffer);
727
exec_rc=exec_exe(cmd_buffer);
731
msg_cprintf(H_HL|H_NFMT, M_SKIP_REARJ_MISSING, full_name);
733
msg_cprintf(H_HL|H_NFMT, M_SKIP_REARJ_FAILED, full_name, exec_rc);
734
return(REARJ_ERL_INTERNAL);
741
arj_gettime(&log_ts);
742
if(fprintf(logstream, M_LOGENTRY_CONV, timeseq, archivers[target_type].suffix, old_fsize, 0L, 0L, full_name)<=0)
743
error(M_CANT_WRITE_LOG);
748
old_size=count_total_size();
749
if(!archivers[target_type].hidden_supported)
751
if(update_with_backups&&repack)
753
if(file_exists(bak_name)&&!no_file_activity)
754
if(file_unlink(bak_name))
755
error(M_CANT_UNLINK, bak_name);
756
if(!no_file_activity)
757
if(rename_with_check(full_name, bak_name))
759
msg_cprintf(H_HL|H_NFMT, M_SKIP_CANT_RENAME, full_name, bak_name);
760
return(REARJ_ERL_RENAME);
762
if(!no_file_activity)
763
msg_cprintf(H_HL|H_NFMT, M_BACKED_UP, full_name, bak_name);
765
sprintf(cmd_buffer, archivers[target_type].pack_cmd, tmp_name);
766
msg_cprintf(H_HL|H_NFMT, M_EXECUTING, cmd_buffer);
767
exec_rc=exec_exe(cmd_buffer);
770
if(update_with_backups&&repack)
772
if(file_exists(full_name)&&!no_file_activity)
773
if(file_unlink(full_name))
774
error(M_CANT_UNLINK, full_name);
775
if(!no_file_activity)
776
if(rename_with_check(bak_name, full_name))
777
error(M_CANTRENAME, bak_name, full_name);
780
msg_cprintf(H_HL|H_NFMT, M_SKIP_P_EXE_MISSING, full_name);
783
/* ASR fix for 2.42.05 -- unlink empty .tar.gz archives */
784
if(archivers[target_type].manual_deletion)
786
msg_cprintf(H_HL|H_NFMT, M_SKIP_PACK_ERR, full_name, exec_rc);
788
return(REARJ_ERL_PACK);
790
if(file_chdir(work_dir))
791
error(M_CANT_CHDIR, work_dir);
792
if(!file_exists(tmp_name))
794
if(update_with_backups&&repack)
796
if(file_exists(full_name)&&!no_file_activity)
797
if(file_unlink(full_name))
798
error(M_CANT_UNLINK, full_name);
799
if(!no_file_activity)
800
if(rename_with_check(bak_name, full_name))
801
error(M_CANTRENAME, bak_name, full_name);
803
msg_cprintf(H_HL|H_NFMT, M_SKIP_NOT_PACKED, full_name);
804
return(REARJ_ERL_PACK);
806
new_fsize=file_getfsize(tmp_name);
807
if(skip_larger_output&&old_fsize<new_fsize)
809
msg_cprintf(H_HL|H_NFMT, M_SKIP_LARGER, full_name);
810
if(!no_file_activity)
811
if(file_unlink(tmp_name))
812
error(M_CANT_UNLINK, tmp_name);
813
if(update_with_backups||!repack||no_file_activity)
814
return(REARJ_ERL_OVERGROW);
817
if(rename_with_check(bak_name, full_name))
818
return(REARJ_ERL_OVERGROW);
820
error(M_CANTRENAME, bak_name, full_name);
825
msg_cprintf(H_HL|H_NFMT, M_VERIFYING_SIZE, old_count, old_size);
827
if(file_chdir(tmp_dir))
828
error(M_CANT_CHDIR, tmp_dir);
829
sprintf(cmd_buffer, archivers[target_type].unpack_cmd, tmp_name);
830
msg_cprintf(H_HL|H_NFMT, M_EXECUTING, cmd_buffer);
831
exec_exe(cmd_buffer);
832
new_count=count_files();
833
new_size=count_total_size();
834
msg_cprintf(H_HL|H_NFMT, M_FOUND_SIZE, new_count, new_size);
835
if(old_count!=new_count)
837
msg_cprintf(H_HL|H_NFMT, M_SKIP_COUNT_MISMATCH, full_name);
838
if(!no_file_activity)
839
if(file_unlink(tmp_name))
840
error(M_CANT_UNLINK, tmp_name);
841
if(update_with_backups&&repack&&!no_file_activity)
842
if(rename_with_check(bak_name, full_name))
843
error(M_CANTRENAME, bak_name, full_name);
844
return(REARJ_ERL_COUNT);
846
if(old_size!=new_size)
848
msg_cprintf(H_HL|H_NFMT, M_SKIP_SIZE_MISMATCH, full_name);
849
if(!no_file_activity)
850
if(file_unlink(tmp_name))
851
error(M_CANT_UNLINK, tmp_name);
852
if(update_with_backups&&repack&&!no_file_activity)
853
if(rename_with_check(bak_name, full_name))
854
error(M_CANTRENAME, bak_name, full_name);
855
return(REARJ_ERL_SIZE);
857
msg_cprintf(H_HL, M_SIZE_VERIFIED);
858
if(file_chdir(work_dir))
859
error(M_CANT_CHDIR, work_dir);
861
if(cnv_diskette_archives)
863
if(file_getfree(full_name)+old_fsize<new_fsize)
865
msg_cprintf(H_HL|H_NFMT, M_SKIP_DISK_FULL, full_name);
866
if(!no_file_activity)
867
if(file_unlink(tmp_name))
868
error(M_CANT_UNLINK, tmp_name);
869
if(update_with_backups&&repack&&!no_file_activity)
870
if(rename_with_check(bak_name, full_name))
871
error(M_CANTRENAME, bak_name, full_name);
872
return(REARJ_ERL_DISK_FULL);
875
if(delete_original_archives)
879
msg_cprintf(H_HL|H_NFMT, M_DELETING_2, full_name);
880
if(!no_file_activity)
881
if(file_unlink(full_name))
882
error(M_CANT_UNLINK, full_name);
884
else if(cnv_diskette_archives&&update_with_backups)
886
msg_cprintf(H_HL|H_NFMT, M_DELETING_2, bak_name);
887
if(!no_file_activity)
888
if(file_unlink(bak_name))
889
error(M_CANT_UNLINK, bak_name);
892
if(cnv_diskette_archives)
894
if(!no_file_activity)
896
if(file_copy_v(cnv_name, target_name))
897
error(M_CANT_COPY, cnv_name, target_name);
899
if(!no_file_activity)
900
if(file_unlink(cnv_name))
901
error(M_CANT_UNLINK, cnv_name);
903
if(delete_original_archives&&!cnv_diskette_archives&&update_with_backups&&repack)
905
msg_cprintf(H_HL|H_NFMT, M_DELETING_2, bak_name);
906
if(!no_file_activity)
907
if(file_unlink(bak_name))
908
error(M_CANT_UNLINK, bak_name);
910
if(!skip_timestamping)
911
file_setftime(target_name, ts_native(&old_ftime, OS));
912
if(testing_mode&&!delete_original_archives)
914
if(update_with_backups&&repack)
916
if(file_exists(full_name))
917
if(file_unlink(full_name))
918
error(M_CANT_UNLINK, full_name);
919
msg_cprintf(H_HL|H_NFMT, M_RENAMING, bak_name, full_name);
920
if(!no_file_activity)
922
if(rename_with_check(bak_name, full_name))
923
error(M_CANTRENAME, bak_name, full_name);
928
msg_cprintf(H_HL|H_NFMT, M_DELETING_2, target_name);
929
if(!no_file_activity)
930
if(file_unlink(target_name))
931
error(M_CANT_UNLINK, target_name);
934
gain=(long)(old_fsize-new_fsize);
935
msg_cprintf(H_HL|H_NFMT, M_OLD_SIZE, old_fsize);
936
msg_cprintf(H_HL|H_NFMT, M_NEW_SIZE, new_fsize);
937
msg_cprintf(H_HL|H_NFMT, M_SAVINGS_SIZE, gain);
939
total_old_fsize+=old_fsize;
940
total_new_fsize+=new_fsize;
944
arj_gettime(&log_ts);
945
if(fprintf(logstream, M_LOGENTRY_CONV, timeseq, archivers[target_type].suffix, old_fsize, new_fsize, gain, full_name)<=0)
946
error(M_CANT_WRITE_LOG);
951
/* Adds a new file to the exclusion filelist */
953
static void submit_exclusion(char *name)
955
char tmp_name[CCHMAXPATH];
962
error(M_LISTFILE_MISSING);
963
if((stream=file_open(name, m_r))==NULL)
964
error(M_CANTOPEN, stream);
965
while(fgets(tmp_name, sizeof(tmp_name), stream)!=NULL)
967
tokenize_lf(tmp_name);
969
if(tmp_name[0]!='\0')
971
if(wild_list(&flist_exclusion, tmp_name, 0, 0, 0, NULL))
978
wild_list(&flist_exclusion, name, 0, 0, 0, NULL);
983
static void analyze_rearj_sw(char *arg)
991
if(sw=='D'&&*swptr=='\0')
992
delete_original_archives=1;
993
else if(sw=='E'&&*swptr=='\0')
994
internal_archives_only=1;
995
else if(sw=='F'&&*swptr=='\0')
996
cnv_diskette_archives=1;
997
else if(sw=='H'&&*swptr=='\0')
999
else if(sw=='O'&&*swptr=='\0')
1000
overwrite_existing=1;
1001
else if(sw=='P'&&*swptr=='\0')
1003
else if(sw=='Q'&&*swptr=='\0')
1005
else if(sw=='R'&&*swptr=='\0')
1007
else if(sw=='S'&&*swptr=='\0')
1009
else if(sw=='V'&&*swptr=='\0')
1011
else if(sw=='Z'&&*swptr=='\0')
1018
acc_nested_suffixes=swptr;
1020
convert_nested_archives=1;
1022
else if(sw=='B'&&*swptr!='\0')
1024
run_preunpack_cmd=1;
1025
preunpack_cmd_text=swptr;
1027
else if(sw=='C'&&*swptr!='\0')
1030
precount_cmd_text=swptr;
1041
else if(sw=='F'&&*swptr!='\0')
1045
suffix_override=swptr;
1056
else if(sw=='T'&&*swptr!='\0')
1060
target_suffix=swptr;
1067
backup_extension=swptr;
1069
update_with_backups=1;
1071
else if(sw=='W'&&*swptr!='\0')
1075
work_directory_assigned=1;
1077
else if(sw=='X'&&*swptr!='\0')
1078
submit_exclusion(swptr);
1079
else if(sw=='G'&&*swptr=='\0')
1081
else if(sw=='J'&&*swptr=='\0')
1082
skip_larger_output=1;
1083
else if(sw=='K'&&*swptr=='\0')
1084
skip_timestamping=1;
1085
else if(sw=='+'&&*swptr=='\0')
1090
timestr_older=swptr;
1095
timestr_newer=swptr;
1100
testing_marker=swptr;
1103
error(M_INVALID_SWITCH, arg);
1106
/* Parses REARJ.CFG */
1108
static void parse_rearj_cfg()
1113
char cfg_path[CCHMAXPATH];
1121
if((cfg_path=searchpath(cfg_name))==NULL)
1122
error(M_CANT_FIND_CONFIG, cfg_name);
1124
_searchenv(cfg_name, "PATH", cfg_path);
1125
if(cfg_path[0]=='\0')
1126
error(M_CANT_FIND_CONFIG, cfg_name);
1129
/* Attempt search in home directory first, then in /etc. */
1130
sprintf(cfg_path, "%s/.%s", getenv("HOME"), cfg_name);
1131
if((stream=file_open(cfg_path, m_r))!=NULL)
1134
sprintf(cfg_path, "/etc/%s", cfg_name);
1136
if((stream=file_open(cfg_path, m_r))==NULL)
1137
error(M_CANTOPEN, cfg_path);
1138
msg_cprintf(H_HL|H_NFMT, M_USING_CONFIG, cfg_path);
1139
if(fgets(tmp_line, sizeof(tmp_line), stream)==NULL)
1144
for(i=0; i<MAX_SUFFIXES; i++)
1146
/* ASR fix for 2.43, 24/01/2003 - the option strings may be placed before
1147
ANY extension command. */
1153
if(fgets(tmp_line, sizeof(tmp_line), stream)==NULL)
1155
archivers[i].hidden_supported=0;
1156
archivers[i].subdirs_supported=0;
1157
archivers[i].manual_deletion=0; /* ASR fix */
1158
tokenize_lf(tmp_line);
1160
} while (tmp_line[0]=='\0');
1163
if(!strnicmp(tmp_line, "COLORS ", 7))
1165
if(parse_colors(tmp_line+7))
1166
error(M_INVALID_PARAM_STR, tmp_line);
1170
if(!strnicmp(tmp_line, "VIRUS ", 6))
1172
if((extr_cmd_text=strdup(tmp_line+6))==NULL)
1173
error(M_OUT_OF_MEMORY);
1174
if(strchr(extr_cmd_text, PATHSEP_DEFAULT)==NULL)
1176
msg_cprintf(0, M_NO_ANTIVIRUS_PATH);
1177
msg_cprintf(0, M_IGNORED_FOR_COMP);
1183
} while(fakesuffix);
1184
if(strlen(tmp_line)>MAX_SUFFIX)
1185
error(M_INVALID_SUFFIX, tmp_line);
1186
if((archivers[i].suffix=strdup(tmp_line))==NULL)
1187
error(M_OUT_OF_MEMORY);
1189
if(fgets(tmp_line, sizeof(tmp_line), stream)==NULL)
1190
error(M_MISSING_PACK_CMD, archivers[i].suffix);
1191
tokenize_lf(tmp_line);
1193
if(strlen(tmp_line)==0)
1194
error(M_INVALID_PACK_CMD, tmp_line);
1195
if(strstr(tmp_line, strform)==NULL&&strstr(tmp_line, u_strform)==NULL)
1196
error(M_NO_PACK_STRFORM, tmp_line);
1197
if((archivers[i].pack_cmd=strdup(tmp_line))==NULL)
1198
error(M_OUT_OF_MEMORY);
1199
/* Unpack command */
1200
if(fgets(tmp_line, sizeof(tmp_line), stream)==NULL)
1201
error(M_MISSING_UNPACK_CMD, archivers[i].suffix);
1202
tokenize_lf(tmp_line);
1204
if(strlen(tmp_line)==0)
1205
error(M_INVALID_UNPACK_CMD, tmp_line);
1206
if(strstr(tmp_line, strform)==NULL&&strstr(tmp_line, u_strform)==NULL)
1207
error(M_NO_UNPACK_STRFORM, tmp_line);
1208
if((archivers[i].unpack_cmd=strdup(tmp_line))==NULL)
1209
error(M_OUT_OF_MEMORY);
1211
if(fgets(tmp_line, sizeof(tmp_line), stream)==NULL)
1212
error(M_MISSING_OPTIONS, archivers[i].suffix);
1213
tokenize_lf(tmp_line);
1215
if(strpbrk(tmp_line, "Aa")!=NULL)
1216
archivers[i].hidden_supported=1;
1217
if(strpbrk(tmp_line, "Dd")!=NULL)
1218
archivers[i].subdirs_supported=1;
1219
/* ASR fix for v 2.42.05 (.tar.gz): */
1220
if(strpbrk(tmp_line, "Tt")!=NULL)
1221
archivers[i].manual_deletion=1;
1229
/* atexit routine */
1231
static void final_cleanup(void)
1233
if(!cleanup_initiated)
1235
cleanup_initiated=1;
1237
release_dir(tmp_dir); /* ASR fix 14/11/2000 */
1238
if(work_dir[0]!='\0')
1239
file_chdir(work_dir);
1243
unlink_all(tmp_dir);
1244
if(!work_directory_assigned)
1245
file_rmdir(tmp_dir);
1248
free(tmp_dir); /* malloc'ed */
1258
/* Ctrl+C handler */
1260
static void ctrlc_handler(SIGHDLPARAMS)
1262
/* Check if we are able to honor the request. If we aren't, raise the
1263
signal again and make a speedy getaway. */
1269
signal(SIGINT, NULL); /* Restore default Ctrl+C handler */
1270
msg_cprintf(H_SIG, M_BREAK_SIGNALED);
1271
exit(REARJ_ERL_WARNING);
1277
int main(int argc, char **argv)
1279
int cnv_rc, exit_code;
1280
static char rearj_exe[CCHMAXPATH];
1285
FILE_COUNT cur_file;
1286
char tmp_name[CCHMAXPATH], src_name[CCHMAXPATH];
1289
char *env_ptr, *env_dup, *env_tail;
1290
struct timestamp timestamp;
1291
time_t start_time, end_time;
1292
unsigned long time_diff;
1295
no_colors=redirected=!is_tty(stdout);
1297
msg_cprintf(0, M_REARJ_BANNER, build_date);
1301
build_crc32_table();
1303
lfn_supported=LFN_NOT_SUPPORTED;
1304
convert_nested_archives=0;
1306
run_preunpack_cmd=0;
1310
delete_original_archives=0;
1311
skip_larger_output=0;
1312
cnv_diskette_archives=0;
1316
internal_archives_only=0;
1321
overwrite_existing=0;
1324
skip_timestamping=0;
1326
work_directory_assigned=0;
1328
update_with_backups=0;
1332
total_old_fsize=total_new_fsize=0L;
1334
ts_store(&ts_older, OS_SPECIAL, 0L);
1338
exit_code=REARJ_ERL_SUCCESS;
1341
backup_extension=backup_ext;
1342
#ifndef SKIP_GET_EXE_NAME
1343
get_exe_name(rearj_exe);
1345
get_exe_name(rearj_exe, argv[0]);
1349
suffix_override=NULL;
1350
extract_cmd_text=NULL;
1351
precount_cmd_text=NULL;
1352
preunpack_cmd_text=NULL;
1354
testing_marker=NULL;
1355
acc_nested_suffixes=NULL;
1357
timestr_older=timestr_newer=nullstr;
1358
flist_init(&flist_exclusion, EXCL_FLIST_SIZE, 0, 0);
1359
atexit(final_cleanup);
1362
is_registered=reg_validation(regdata+REG_KEY1_SHIFT, regdata+REG_KEY2_SHIFT, regdata+REG_NAME_SHIFT, regdata+REG_HDR_SHIFT);
1363
if(!is_registered&&!msg_strcmp((FMSG *)regdata+REG_KEY2_SHIFT, M_REG_TYPE))
1364
msg_cprintf(0, M_REGISTERED_TO, regdata+REG_NAME_SHIFT);
1367
if(signal(SIGINT, ctrlc_handler)==SIG_ERR)
1368
error(M_SIGNAL_FAILED);
1370
if(regdata[REG_NAME_SHIFT]=='\0')
1372
if(!reg_validation(single_spc, single_spc, single_spc, regdata+REG_HDR_SHIFT))
1375
switchar=get_sw_char();
1376
for(arg=1; arg<argc; arg++)
1379
if(aptr[0]==switchar&&aptr[1]=='+'&&aptr[2]=='\0')
1382
if((env_ptr=getenv(rearj_sw))!=NULL)
1384
env_dup=strdup(env_ptr);
1385
msg_cprintf(H_HL|H_NFMT, M_USING_REARJ_SW, env_dup);
1386
for(env_ptr=env_dup; *env_ptr!='\0'; env_ptr++)
1388
*env_ptr='\0'; /* Tokenize by spaces */
1391
while(env_ptr<env_tail)
1393
while(*env_ptr=='\0')
1395
if(env_ptr<env_tail)
1398
name_to_hdr(env_ptr);
1399
if(*env_ptr==switchar)
1400
analyze_rearj_sw(aptr);
1401
while(*env_ptr!='\0'&&env_ptr<env_tail)
1406
for(arg=1; arg<argc; arg++)
1411
if(aptr[0]==switchar)
1412
analyze_rearj_sw(aptr);
1415
if(n_args>=MAX_ARGS)
1416
error(M_ARGTABLE_OVERFLOW);
1417
arg_ptr[n_args++]=aptr;
1421
lfn_supported=LFN_NOT_SUPPORTED;
1423
exit(check_integrity(rearj_exe));
1424
if(help_issued||n_args==0)
1426
msg_cprintf(0, strform, M_REARJ_COMMANDS);
1427
msg_cprintf(0, strform, M_REARJ_RCODES);
1428
exit(REARJ_ERL_SUCCESS);
1430
if(delete_original_archives&&testing_mode)
1431
error(M_YD_CMD_CONFLICT);
1432
if(testing_mode&&testing_marker!=NULL&&!logging_enabled)
1435
if(run_extract_cmd&&extract_cmd_text==NULL)
1436
error(M_NO_V_CMD, cfg_name);
1437
if(suffix_override!=NULL)
1440
for(i=0; i<total_suffixes; i++)
1442
if(!strcmp_os(suffix_override, archivers[i].suffix))
1445
if(default_suffix<0)
1446
error(M_INVALID_F_SUFFIX, suffix_override);
1448
if(target_suffix!=NULL)
1451
for(i=limit; i<total_suffixes; i++)
1453
if(!strcmp_os(target_suffix, archivers[i].suffix))
1457
error(M_INVALID_T_SUFFIX, target_suffix);
1459
if(pick_older||pick_newer)
1461
if(timestr_older[0]!='\0')
1462
convert_strtime(&ts_older, timestr_older);
1463
if(timestr_newer[0]!='\0')
1464
convert_strtime(&ts_newer, timestr_newer);
1465
if(timestr_older[0]=='\0'||timestr_newer[0]=='\0')
1467
arj_getdate(&x_date);
1468
make_timestamp(×tamp, x_date.da_year, x_date.da_mon, x_date.da_day,
1470
if(timestr_newer[0]=='\0')
1472
if(timestr_older[0]=='\0')
1476
if(file_getcwd(work_dir)==NULL)
1477
error(M_GETCWD_FAILED);
1478
if(no_file_activity)
1479
msg_cprintf(0, M_SIMULATION_MODE);
1480
flist_init(&flist_main, LARGE_FLIST_SIZE, n_args>1, 1);
1481
for(i=limit; i<n_args; i++)
1484
if(arg_ptr[i][0]=='!')
1486
if(arg_ptr[i][1]=='\0')
1487
error(M_NO_LISTFILE);
1488
if((liststream=file_open(arg_ptr[i]+1, m_r))==NULL)
1489
error(M_CANTOPEN, arg_ptr[i]+1);
1490
while(fgets(name_fetch, CCHMAXPATH, liststream)!=NULL)
1492
tokenize_lf(name_fetch);
1493
alltrim(name_fetch);
1494
if(name_fetch[0]!='\0')
1496
strcpy(tmp_name, name_fetch);
1497
if(wild_list(&flist_main, tmp_name, 0, 1, recurse_subdirs, NULL))
1505
strcpy(tmp_name, arg_ptr[i]);
1506
if(wild_list(&flist_main, tmp_name, 0, 1, recurse_subdirs, NULL))
1510
if(flist_main.files==0)
1512
msg_cprintf(0, internal_archives_only?M_NO_FILES_INT:M_NO_FILES);
1513
exit(internal_archives_only?REARJ_ERL_SUCCESS:REARJ_ERL_WARNING);
1518
if((logstream=file_open(log_name, m_a))==NULL)
1519
error(M_CANTOPEN, log_name);
1520
arj_gettime(&log_ts);
1521
if(testing_marker!=NULL)
1522
if(fprintf(logstream, M_LOGENTRY_MARKER, timeseq, archivers[target_type].suffix, testing_marker)<=0)
1523
error(M_CANT_WRITE_LOG);
1524
if(fprintf(logstream, M_LOGENTRY_HEADER, timeseq, archivers[target_type].suffix)<=0)
1525
error(M_CANT_WRITE_LOG);
1527
if(cnv_diskette_archives&&count_files()>0)
1528
msg_cprintf(0, M_CWD_MUST_BE_EMPTY);
1531
/* BUGBUG: this comes from a NetBSD patch. Originally a check for NO_MKDTEMP
1532
was suggested, but where are we expected to define it under DOS? --
1533
ASR fix 25/01/2004 */
1535
tmp_dir=mkdtemp("/tmp/arj.XXXXXX"); /* BUGBUG: hardcoded location? */
1537
tmp_dir=tmpnam(NULL);
1538
if(file_mkdir(tmp_dir))
1539
error(M_CANT_MKDIR, tmp_dir);
1544
if(file_chdir(tmp_dir))
1545
error(M_CANT_CHDIR, tmp_dir);
1547
error(M_WORK_DIR_NOT_EMPTY, tmp_dir);
1548
if(file_chdir(work_dir))
1549
error(M_CANT_CHDIR, work_dir);
1551
if((fullpath=(char *)malloc(CCHMAXPATH))==NULL)
1552
error(M_OUT_OF_MEMORY);
1553
if(truename(fullpath, tmp_dir))
1554
error(M_CANT_GET_FULL_PATH);
1557
tmpdir_malloced=1; /* Introduced by ASR */
1558
for(cur_file=0; cur_file<flist_main.files; cur_file++)
1561
if(fetch_keystrokes())
1563
msg_cprintf(H_PROMPT, M_OK_TO_QUIT);
1566
msg_cprintf(H_OPER, M_QUITTING);
1567
exit(REARJ_ERL_WARNING);
1570
retrieve_entry(src_name, &flist_main, cur_file);
1571
ts_store(×tamp, OS, file_getftime(src_name));
1572
if((!pick_newer||!ts_valid(ts_newer)||ts_cmp(×tamp, &ts_newer)>=0)&&
1573
(!pick_older||!ts_valid(ts_older)||ts_cmp(×tamp, &ts_older)<0))
1575
cnv_rc=convert_archive(src_name);
1576
if(cnv_rc!=REARJ_ERL_SUCCESS)
1579
log_as_skipped(src_name, cnv_rc);
1580
if(exit_code==REARJ_ERL_SUCCESS&&(!internal_archives_only||cnv_rc!=REARJ_ERL_UNCONFIGURED))
1583
release_dir(tmp_dir); /* ASR fix 14/11/2000 */
1584
if(file_chdir(work_dir))
1585
error(M_CANT_CHDIR, work_dir);
1586
unlink_all(tmp_dir);
1587
if(file_rmdir(tmp_dir))
1588
msg_cprintf(H_ERR, M_CANT_RMDIR, tmp_dir);
1589
if(file_mkdir(tmp_dir))
1590
error(M_CANT_MKDIR, tmp_dir);
1593
if(!work_directory_assigned)
1595
if(file_rmdir(tmp_dir))
1596
msg_cprintf(H_ERR, M_CANT_RMDIR, tmp_dir);
1605
time_diff=sub_time(end_time, start_time);
1606
total_gain=(long)(total_old_fsize-total_new_fsize);
1607
msg_cprintf(H_HL|H_NFMT, M_TOTAL_SECONDS, time_diff);
1608
msg_cprintf(H_HL|H_NFMT, M_TOTAL_CONVERTED, total_files);
1609
msg_cprintf(H_HL|H_NFMT, M_TOTAL_SKIPPED, skip_count);
1610
msg_cprintf(H_HL|H_NFMT, M_OLD_SIZE, total_old_fsize);
1611
msg_cprintf(H_HL|H_NFMT, M_NEW_SIZE, total_new_fsize);
1612
msg_cprintf(H_HL|H_NFMT, M_SAVINGS_SIZE, total_gain);
1615
arj_gettime(&log_ts);
1616
if(fprintf(logstream, M_LOGENTRY_FOOTER, timeseq, archivers[target_type].suffix, total_old_fsize, total_new_fsize, total_gain, time_diff)<=0)
1617
error(M_CANT_WRITE_LOG);
1620
flist_cleanup_proc(&flist_main);
1621
flist_cleanup_proc(&flist_exclusion);
1622
return((skip_count>0)?exit_code:REARJ_ERL_SUCCESS);