/* * $Id: arj_proc.c,v 1.18 2005/06/21 19:53:13 andrew_belov Exp $ * --------------------------------------------------------------------------- * This file contains many of the functions that are called by various ARJ * modules. Everything is OS-independent, all OS-dependent procedures must be * moved to ENVIRON.C. * */ #include "arj.h" DEBUGHDR(__FILE__) /* Debug information block */ /* Other defines */ #define FNAME_FLEN 27 /* Length of formatted filename */ /* String table (may need some localization in the future...) */ #if SFX_LEVEL>=ARJ||defined(REARJ) static char strtime_filler[]="00000000000000"; #endif #if SFX_LEVEL>=ARJ static char time_tail_pattern[]="%04d%02d%02d%03d%02d%02d%02d"; static char date_digit_format[]="%04d%02d%02d"; static char allowed_attrs[]=TAG_LIST; static char vol_st_id[]=" - "; /* A substring of M_NEXT_VOL_STATS */ #endif #if SFX_LEVEL>=ARJSFXV static char nonexistent_name[]="..."; #endif #if SFX_LEVEL>=ARJSFXV||defined(REARJ) /* The first byte in integrity_pattern[] is changed to avoid confusion with the pattern to search */ static unsigned char integrity_pattern[]={0xB1, 0x03, 0xB0, 0x02, 0xB0, 0x03, 0xB0, 0x04, 0xB0, 0x05, 0}; #endif #if SFX_LEVEL>=ARJ static int hswitch; /* Indicates that we have a "-h..." */ static int jswitch; /* Indicates that we have a "-j..." */ static int os2switch; /* ARJ/2 switches (-h2, -2) */ static int noswitch; #endif #if SFX_LEVEL>=ARJ static int *sw_index[]={&jswitch, &hswitch, &allow_any_attrs, &filter_fa_arch, &skip_ts_check, &delete_processed, &exclude_paths, &freshen_criteria, &garble_enabled, &indicator_style, &keep_bak, &create_list_file, &custom_method, &new_files_only, &filter_same_or_newer, &fnm_matching, &query_for_each_file, &recurse_subdirs, ×tamp_override, &type_override, &update_criteria, &multivolume_option, &assign_work_directory, &exclude_files, &yes_on_all_queries, &use_comment, &help_issued, &listchars_allowed, &handle_labels, &disable_arj_sw, &select_by_number, &install_errhdl, &quiet_mode, &rsp_per_line, &noswitch, &lowercase_names, NULL}; static int *jsw_index[]={&jswitch, &comment_display, &chapter_mode, &exit_after_count, &chk_free_space, &create_sfx, &validate_style, &select_backup_files, &jh_enabled, &create_index, &keep_tmp_archive, &show_filenames_only, &max_compression, &restart_at_filename, &serialize_exts, &prompt_for_more, &set_string_parameter, &ignore_crc_errors, &store_by_suffix, &test_archive_crc, &translate_unix_paths, &verbose_display, &extract_to_file, &start_at_ext_pos, &assume_yes, &supply_comment_file, &hollow_mode, &skip_time_attrs, NULL}; static int *hsw_index[]={&hswitch, &clear_archive_bit, &filter_attrs, &run_cmd_at_start, &debug_enabled, &arjsec_opt, &lfn_mode, &gost_cipher, &detailed_index, &protfile_option, &listfile_err_opt, &filelist_storage, &nonexist_filespec, &extm_mode, &arjdisp_enabled, &ignore_open_errors, &ignore_archive_errors, &disable_sharing, &set_target_directory, &allow_mv_update, &chk_arj_version, &search_mode, &override_archive_exts, &use_ansi_cp, &sign_with_arjsec, &append_curtime, &marksym_expansion, &force_lfn, &noswitch, NULL}; static int *os2sw_index[]={&os2switch, &arcmail_sw, &noswitch, &crit_eas, &dos_host, &include_eas, &disable_comment_series, &suppress_hardlinks, &start_with_seek, &skip_century, &fix_longnames, &do_chown, &priority.class, &recursion_order, &symlink_accuracy, &noswitch, &exclude_eas, NULL}; static int *jysw_index[]={&skip_append_query, &prompt_for_mkdir, &query_delete, &skip_space_query, &skip_rename_prompt, &overwrite_existing, &kbd_cleanup_on_input, &skip_scanned_query, &skip_next_vol_query, &accept_shortcut_keys, NULL}; #elif SFX_LEVEL==ARJSFXV static int *sw_index[]={&skip_integrity_test, &prompt_for_directory, &skip_ts_check, &chk_free_space, &extract_expath, &freshen_criteria, &garble_enabled, &help_issued, &indicator_style, &process_lfn_archive, &skip_preset_options, &list_sfx_cmd, &overwrite_ro, &new_files_only, &gost_cipher, &fnm_matching, &ignore_crc_errors, &disable_sharing, &test_sfx_cmd, &update_criteria, &verbose_list, &extract_to_file, &extract_cmd, &yes_on_all_queries, &assume_yes, &help_issued, &skip_volumes, &debug_enabled, &quiet_mode, &handle_labels, &arjdisp_enabled, &execute_extr_cmd, &lowercase_names, NULL}; static int *jysw_index[]={&skip_append_query, &prompt_for_mkdir, &skip_space_query, &skip_extract_query, &skip_rename_prompt, &overwrite_existing, &kbd_cleanup_on_input, &skip_next_vol_query, NULL}; #elif SFX_LEVEL==ARJSFX static int *sw_index[]={&extract_expath, &list_sfx_cmd, &test_sfx_cmd, &verbose_list, &extract_cmd, &show_ansi_comments, &prompt_for_directory, &skip_ts_check, &arjdisp_enabled, &freshen_criteria, &garble_enabled, &indicator_style, &process_lfn_archive, &verbose_display, &make_directories, &new_files_only, &overwrite_existing, &fnm_matching, &skip_integrity_test, &update_criteria, &skip_extract_query, &yes_on_all_queries, &quiet_mode, &help_issued, &help_issued, &execute_extr_cmd}; #endif /* Local functions */ #if SFX_LEVEL>=ARJ static int compare_exts(char *name, char *pad); #endif #if SFX_LEVEL>=ARJ /* Encodes a block of data */ void garble_encode_stub(char *data, int len) { garble_encode(data, len); } /* Decodes a block of data */ void garble_decode_stub(char *data, int len) { garble_decode(data, len); } #endif #if SFX_LEVEL>=ARJ /* Returns day of year */ static int day_of_year(struct tm *tms) { int m, y, rc; rc=0; for(m=tms->tm_mon; m>0; m--) { switch(m) { case 1: rc+=31; break; case 2: rc+=28; y=tms->tm_year+1900; if((y%4==0)&&(y%100!=0||y%400==0)) rc++; break; case 3: rc+=31; break; case 4: rc+=30; break; case 5: rc+=31; break; case 6: rc+=30; break; case 7: rc+=31; break; case 8: rc+=31; break; case 9: rc+=30; break; case 10: rc+=31; break; case 11: rc+=30; break; } } return(rc+tms->tm_mday); } /* Appends current date/time to the archive filename in accordance with the "-h#" option */ void append_curtime_proc() { time_t curtime; struct tm *tms; char time_pad[19]; char ext[32]; char *ext_pos; char *aptr, *tptr; char *dptr=time_pad; /* ASR fix for High C -- 29/03/2001 */ int l, lim; int doy; /* Day of year */ curtime=time(NULL); tms=arj_localtime(&curtime); doy=day_of_year(tms); sprintf(time_pad, time_tail_pattern, tms->tm_year+1900, tms->tm_mon+1, tms->tm_mday, doy, tms->tm_hour, tms->tm_min, tms->tm_sec); if((ext_pos=strchr(archive_name+split_name(archive_name, NULL, NULL), '.'))!=NULL) { strncpy(ext, ext_pos, sizeof(ext)); *ext_pos='\0'; } else ext[0]='\0'; if(time_str[0]=='\0') { if(append_curtime==ATS_DUAL) strcat(archive_name, time_pad+7); else if(append_curtime==ATS_TIME) strcat(archive_name, time_pad+8); else if(append_curtime==ATS_DATE) { time_pad[8]='\0'; strcat(archive_name, time_pad+2); } } else /* Custom format */ { l=strlen(time_str); aptr=archive_name+strlen(archive_name)+l; *aptr='\0'; lim=0; for(tptr=time_str+l-1; (tptr-time_str)>=0; tptr--) { if(*tptr==*(tptr+1)) *(--aptr)=(lim>0)?dptr[--lim]:*tptr; else { switch(*tptr) { case 'Y': dptr=time_pad; lim=4; *(--aptr)=dptr[--lim]; break; case 'M': dptr=time_pad+4; lim=2; *(--aptr)=dptr[--lim]; break; case 'D': dptr=time_pad+6; lim=2; *(--aptr)=dptr[--lim]; break; case 'N': dptr=time_pad+8; lim=3; *(--aptr)=dptr[--lim]; break; case 'h': dptr=time_pad+11; lim=2; *(--aptr)=dptr[--lim]; break; case 'm': dptr=time_pad+13; lim=2; *(--aptr)=dptr[--lim]; break; case 's': dptr=time_pad+15; lim=2; *(--aptr)=dptr[--lim]; break; default: *(--aptr)=*tptr; } } } } strcat(archive_name, ext); } /* Adds an ending backslash to the given pathname if it doesn't contain one */ void add_pathsep(char *path) { int len; if((len=strlen(path))==0) /* Maybe current path? */ return; if(strchr(path_separators, path[len-1])==NULL) { path[len]=PATHSEP_DEFAULT; path[len+1]='\0'; } } /* Converts the timestamps given by the user to the internal storage format */ void convert_time_limits() { char *cptr; time_t tmp_ts; time_t ts; struct tm *tms; struct timestamp arj_ts; /* ARJ-format timestamp storage */ if(filter_same_or_newer==TCHECK_NDAYS) { tmp_ts=strtoul(timestr_newer, &cptr, 10)*(-86400L); ts=sum_time(tmp_ts, time(NULL)); tms=arj_localtime(&ts); if(tms==NULL) /* ASR fix 21/02/2001 -- IBM LIBC */ error(M_INVALID_DATE); sprintf(misc_buf, date_digit_format, tms->tm_year+1900, tms->tm_mon+1, tms->tm_mday); timestr_newer=malloc_str(misc_buf); /* MEMORY LEAK! (Never freed) */ } if(filter_older==TCHECK_NDAYS) { tmp_ts=strtoul(timestr_older, &cptr, 10)*(-86400L); ts=sum_time(tmp_ts, time(NULL)); tms=arj_localtime(&ts); if(tms==NULL) /* ASR fix 21/02/2001 -- IBM LIBC */ error(M_INVALID_DATE); sprintf(misc_buf, date_digit_format, tms->tm_year+1900, tms->tm_mon+1, tms->tm_mday); timestr_older=malloc_str(misc_buf); /* MEMORY LEAK! (Never freed) */ } if(timestr_older[0]!='\0') convert_strtime(&tested_ftime_older, timestr_older); if(timestr_newer[0]!='\0') convert_strtime(&tested_ftime_newer, timestr_newer); if(timestr_older[0]=='\0'&×tr_newer[0]=='\0') { ts=time(NULL); tms=arj_localtime(&ts); make_timestamp(&arj_ts, tms->tm_year, tms->tm_mon+1, tms->tm_mday, 0, 0, 0); if(timestr_newer[0]=='\0') tested_ftime_newer=arj_ts; if(timestr_older[0]=='\0') tested_ftime_older=arj_ts; } } /* Analyzes ARJ_SW settings */ void parse_arj_sw(int cmd, char *arj_sw, char *dest) { int use_file; /* 1 if ARJ_SW represents a file */ char *buf; char *dptr, *varname; char *sptr; FILE *stream; char *sw, *sw_p; use_file=0; while(arj_sw[0]==' ') arj_sw++; if(strchr(switch_chars, arj_sw[0])==NULL) { buf=dest; dptr=dest+FILENAME_MAX+1; sptr=dest+FILENAME_MAX*2+2; sptr[0]='\0'; dptr[0]='\0'; stream=file_open_noarch(arj_sw, m_r); while(fgets(buf, FILENAME_MAX, stream)!=NULL) { strip_lf(buf); if(buf[0]=='#') continue; else if(!use_file&&buf[0]=='+'&&buf[1]==' ') { strcpy(sptr, buf+1); use_file=1; } else if(!use_file&&buf[0]=='-'&&buf[1]==' ') { strcat(dptr, buf+2); strcat(dptr, " "); use_file=1; } else if((cmd==ARJ_CMD_ADDC&&!strnicmp(buf, "AC ", 3))|| (cmd==ARJ_CMD_CNVC&&!strnicmp(buf, "CC ", 3))|| (cmd==ARJ_CMD_DELC&&!strnicmp(buf, "DC ", 3))) { strcpy(dptr, buf+3); use_file=1; break; } else { if(toupper((int)buf[0])==cmd&&buf[1]==' ') { strcpy(dptr, buf+2); use_file=1; break; } } } fclose(stream); strcat(dptr, sptr); sw=malloc_str(dptr); } else sw=malloc_str(arj_sw); varname=use_file?arj_sw:arj_env_name; sw_p=malloc_str(sw); /* Tokenize switch */ for(dptr=sw; *dptr!='\0'; dptr++) if(*dptr==' ') *dptr='\0'; sptr=dptr; dptr=sw; while((dptr-sptr)<0) { while(*dptr=='\0') dptr++; if((dptr-sptr)<0) { if(is_switch(dptr)) analyze_arg(dptr); while(*dptr!='\0'&&(dptr-sptr)<0) dptr++; } } if(!translate_unix_paths) switch_char=0; msg_cprintf(H_HL|H_NFMT, M_USING_ENV_VAR, varname, sw_p); free(sw_p); } /* Copies a part of archive */ void copy_bytes(unsigned long nbytes) { char *buf; unsigned int fetch_size; buf=malloc_msg(PROC_BLOCK_SIZE); fseek(aistream, 0L, SEEK_SET); while(nbytes>0L) { fetch_size=(unsigned int)min(PROC_BLOCK_SIZE, nbytes); if(fread(buf, 1, fetch_size, aistream)!=fetch_size) error(M_CANTREAD); if(fwrite(buf, 1, fetch_size, aostream)!=fetch_size) error(M_DISK_FULL); nbytes-=(unsigned long)fetch_size; } free(buf); } /* Returns 1 if the given filename did not contain any UNIX-style ('/') path separators, and all native path separators have been converted to UNIX-style ones ('/'). 0 is returned if the filename initially contained a UNIX-style separator. When it returns 1, the PATHSYM_FLAG in arj_flags is set by parent procedure. */ int translate_path(char *name) { int i; if(strchr(name, PATHSEP_UNIX)!=NULL) return(0); for(i=0; name[i]!=0; i++) if(name[i]==PATHSEP_DEFAULT) name[i]=PATHSEP_UNIX; return(1); } /* Restarts archive processing from the specified file */ void restart_proc(char *dest) { char *r_name, *c_name; char *dptr; char vol_stats[40]; char *vs_ptr; int i; int vs_match; int vn=0, vc=0; /* ASR fix for High C -- 29/03/2001 */ unsigned long vs=0; /* ASR fix for High C -- 29/03/2001 */ FILE_COUNT cur_file; int nd; dptr=dest; r_name=malloc_msg(FILENAME_MAX); c_name=malloc_msg(FILENAME_MAX); strcpy(r_name, filename_to_restart); msg_strcpy(vol_stats, M_NEXT_VOLUME_STATS); vs_ptr=vol_stats; i=0; while(*vs_ptr!='\0') { if(!strncmp(vs_ptr, vol_st_id, sizeof(vol_st_id)-1)) break; i++; vs_ptr++; } i+=sizeof(vol_st_id)-1; if(filename_to_restart[0]=='\0'&&index_name[0]!='\0') { vs_match=0; r_name[0]='\0'; idxstream=file_open_noarch(index_name, m_r); while(fgets(dptr, FILENAME_MAX, idxstream)!=NULL) { strip_lf(dptr); if(!memcmp(dptr, vol_stats, i)) { vs_match=1; vn=atoi(dptr+i); vc=atoi(dptr+i+4); vs=atoi(dptr+i+6); strcpy(r_name, dptr+i+17); } } fclose(idxstream); if(vs_match==0) error(M_RESTART_INFO_NF); else { resume_volume_num=vn; if(vc==1) { start_at_ext_pos=1; ext_pos=vs; } else if(vc==2) error(M_NOTHING_TO_DO); } } for(cur_file=0L; cur_file=flist_main.files) error(M_CANT_FIND_RST_FILE, r_name); free(c_name); free(r_name); if(create_sfx) { nd=split_name(archive_name, NULL, NULL); vs_ptr=strchr(archive_name+nd, '.'); if(vs_ptr==NULL) msg_strcat(archive_name, M_EXE_EXT); else msg_strcpy(vs_ptr, M_EXE_EXT); } } /* Looks for an extension of the given filename in the extension list */ int search_for_extension(char *name, char *ext_list) { int match; char *endptr; char ext_pad[EXTENSION_MAX+1]; char *t_ptr; int i; match=0; endptr=&ext_list[strlen(ext_list)]; t_ptr=ext_list; while(t_ptr!=endptr) { if(*t_ptr=='.') t_ptr++; ext_pad[0]='.'; for(i=0; iremain&&bufsiz>MIN_CRITICAL_BUFSIZ) bufsiz>>=1; if(bufsiz0) inc=remain; if(inc<=0) { volume_flag_set=1; return(0); } if((long)increment*2L>remain) { if(inc>1000) rc=(inc-inc%500)>>1; else if(inc>2000) rc=inc-1000; else rc=(inc>512)?inc>>1:inc; } /* Mistrust the return value. That would help to get around certain compiler optimization bugs (as with OpenWatcom v 1.1RC) - at least the wrong value won't be passed to fread() causing buffer overrun. */ return(min(rc, increment)); } /* Compares the extension from pad with the file's extension. Returns 1 if there was a match. */ static int compare_exts(char *name, char *pad) { int k; /* si = name, di = pad */ if(strlen(pad)==1&&strchr(name, '.')==NULL) return(1); k=strlen(name)-strlen(pad); if(k<0) return(0); else return(strcmp_os(name+k, pad)==0); } /* "Stores" a file by simply copying it */ void store() { int fetch_size; unsigned int mem_size; char *fetch; int to_read; fetch=(char *)malloc_msg(PROC_BLOCK_SIZE); mem_stats(); origsize=0L; cpos=0; ext_voldata=0; display_indicator(0L); crc32term=CRC_MASK; to_read=PROC_BLOCK_SIZE; if(multivolume_option&&file_packing) to_read=check_multivolume(to_read); if(file_packing) { while((fetch_size=fread_crc(fetch, to_read, encstream))>0) { if(garble_enabled) garble_encode_stub(fetch, fetch_size); if(!no_file_activity) { file_write(fetch, 1, fetch_size, aostream); } display_indicator(origsize); if(multivolume_option) to_read=check_multivolume(to_read); } } else { while(encmem_remain!=0) { mem_size=min((unsigned int)PROC_BLOCK_SIZE, encmem_remain); far_memmove((char FAR *)fetch, encblock_ptr, mem_size); crc32_for_block(fetch, mem_size); if(garble_enabled) garble_encode_stub(fetch, mem_size); far_memmove(packblock_ptr, (char FAR *)fetch, mem_size); encblock_ptr+=mem_size; packblock_ptr+=mem_size; origsize+=mem_size; encmem_remain-=mem_size; /* Changed this order. This is an ASR fix for High C beta -- 05/04/2001 */ } } free(fetch); compsize=origsize; } /* Performs a "hollow" file processing (just calculates the CRC) */ void hollow_encode() { int fetch_size; char *fetch; fetch=(char *)malloc_msg(PROC_BLOCK_SIZE); mem_stats(); origsize=0L; out_bytes=0; cpos=0; ext_voldata=0; display_indicator(0L); crc32term=CRC_MASK; fetch_size=PROC_BLOCK_SIZE; while(fread_crc(fetch, fetch_size, encstream)!=0) display_indicator(origsize); free(fetch); compsize=0L; } #endif #if SFX_LEVEL>=ARJ||defined(REARJ) /* Retrieves a pair of decimal digits from the given pointer */ static int get_dec_pair(char *str) { if(str[0]=='\0') return(0); if(str[1]=='\0') return((int)str[0]-'0'); return((int)(str[0]-'0')*10+(int)(str[1]-'0')); } /* Converts the given time string ("yyyymmddhhmmss") to the internal timestamp format */ void convert_strtime(struct timestamp *dest, char *str) { char tmp_strtime[30]; int y, m, d, hh, mm, ss; /* Timestamp components */ strncpy(tmp_strtime, str, 14); tmp_strtime[14]='\0'; strcat(tmp_strtime, strtime_filler); y=get_dec_pair(tmp_strtime); if(y>=19&&y<80) { y=y*100+get_dec_pair(tmp_strtime+2); m=get_dec_pair(tmp_strtime+4); d=get_dec_pair(tmp_strtime+6); hh=get_dec_pair(tmp_strtime+8); mm=get_dec_pair(tmp_strtime+10); ss=get_dec_pair(tmp_strtime+12); } else { m=get_dec_pair(tmp_strtime+2); d=get_dec_pair(tmp_strtime+4); hh=get_dec_pair(tmp_strtime+6); mm=get_dec_pair(tmp_strtime+8); ss=get_dec_pair(tmp_strtime+10); y+=(y>=80)?1900:2000; } if(m<1||m>12||d<1||d>31||hh>23||mm>59||ss>59) error(M_INVALID_DATE_STRING, str); make_timestamp(dest, y, m, d, hh, mm, ss); } #endif #if SFX_LEVEL>=ARJSFXV||defined(REARJ) /* Checks integrity of the executable file */ int check_integrity(char *name) { #if SFX_LEVEL>=ARJ char *buf; int f_len=PROC_BLOCK_SIZE; #else char buf[CACHE_SIZE]; int f_len=CACHE_SIZE; #endif FILE *stream; int p_len; int fetch, i; int c; char *bptr; unsigned long wr_pos; unsigned long fsize, cur_pos; char pattern[20]; unsigned long st_crc, st_fsize; /* Stored parameters */ #if SFX_LEVEL>=ARJ buf=(char *)malloc_msg(f_len); #endif stream=file_open(name, m_rb); if(stream==NULL) { msg_cprintf(H_ERR, M_CANTOPEN, name); #if SFX_LEVEL>=ARJ nputlf(); return(0); #else return(1); #endif } strcpy(pattern, (char *)integrity_pattern); pattern[0]--; p_len=strlen(pattern); fseek(stream, 0L, SEEK_END); fsize=ftell(stream); fseek(stream, 0L, SEEK_SET); crc32term=CRC_MASK; cur_pos=0L; while(1) { fseek(stream, cur_pos, SEEK_SET); fetch=fread(buf, 1, f_len, stream); if(fetch==0) #if SFX_LEVEL>=ARJSFXV error(M_CANTREAD); #else pause_error(M_NO_INTEGRITY_PATTERN); #endif fetch-=p_len; bptr=buf; for(i=0; i=ARJSFXV error(M_CANTREAD); #else pause_error(M_NO_INTEGRITY_PATTERN); #endif if(fread(&st_fsize, 1, 4, stream)!=4) #if SFX_LEVEL>=ARJSFXV error(M_CANTREAD); #else pause_error(M_NO_INTEGRITY_PATTERN); #endif #ifdef WORDS_BIGENDIAN /* Another dirty hack */ st_crc = mget_dword((char*) &st_crc); st_fsize = mget_dword((char*) &st_fsize); #endif crc32term=CRC_MASK; fseek(stream, 0L, SEEK_SET); for(cur_pos=0L; cur_pos=ARJSFXV error(M_CANTREAD); #else pause_error(M_NO_INTEGRITY_PATTERN); #endif crc32term=crc32_for_char(crc32term, (unsigned char)c); } cur_pos+=8L; fseek(stream, cur_pos, SEEK_SET); while(cur_pos=ARJSFXV error(M_CANTREAD); #else pause_error(M_NO_INTEGRITY_PATTERN); #endif crc32term=crc32_for_char(crc32term, (unsigned char)c); cur_pos++; } fsize+=2L; #if SFX_LEVEL>=ARJ free(buf); #endif fclose(stream); #if SFX_LEVEL>=ARJSFXV return(crc32term==st_crc&&fsize==st_fsize); #else if(crc32term==st_crc&&fsize==st_fsize) msg_cprintf(0, M_INTEGRITY_OK); else pause_error(M_INTEGRITY_VIOLATED); return(0); #endif } #endif /* Converts a filename to the format used in current OS (simply substitutes the UNIX separators with DOS ones) */ void name_to_hdr(char *name) { int i; for(i=0; name[i]!='\0'; i++) { if(name[i]==PATHSEP_UNIX) name[i]=PATHSEP_DEFAULT; } } #if SFX_LEVEL>=ARJSFXV /* Formats the given filename to look properly in the "Adding..." and other messages. */ char *format_filename(char *name) { int f_pos, tf_pos; char *result; int ctr; /* Path delimiter counter */ int len; static char name_holder[FNAME_FLEN+1]; int i; if(show_filenames_only) f_pos=split_name(name, NULL, NULL); else f_pos=0; tf_pos=f_pos; ctr=1; while(name[tf_pos]!='\0') { if(tf_pos>0&&name[tf_pos]==PATHSEP_DEFAULT) ctr++; tf_pos++; } len=ctr*CCHMAXPATH+ctr; if(len>FNAME_FLEN-1) len=FNAME_FLEN-1; result=&name[f_pos]; if(strlen(result)=ARJ /* Parses the given argument to a file attribute bitmap */ static void parse_attrs(char *str) { char *sptr, *attrptr; char *g_attr; char c; int attrno; file_attr_mask=TAG_FILES; if(*str=='\0') file_attr_mask=TAG_RDONLY|TAG_SYSTEM|TAG_HIDDEN|TAG_DIREC|TAG_LABEL| TAG_CHAPTER|TAG_NORMAL|TAG_WINLFN; else { sptr=str; attrptr=allowed_attrs; while((c=*sptr++)!='\0') { c=toupper(c); if((g_attr=strchr(attrptr, c))==NULL) error(M_INVALID_SWITCH, str); attrno=g_attr-attrptr-1; if(attrno>=0) file_attr_mask|=1<=ARJSFXV /* Returns 1 if the switch has a "tail" of extra dataa */ static int get_switch_state(char *sw) { if(sw[0]=='\0') return(0); if((sw[0]=='+'||sw[0]=='-')&&sw[1]=='\0') return(0); return(1); } /* Parses query list given by -jy for ARJ and -y for ARJSFX */ static void parse_yes_queries(char *sw) { char *swptr; unsigned int c; int **index; FMSG *table; FMSG *entry; int num; swptr=sw; while((c=(unsigned int)*(swptr++))!='\0') { c=toupper(c); index=jysw_index; table=M_JYSW_TABLE; if((entry=msg_strchr(table, (char)c))==NULL) error(M_INVALID_SWITCH, sw); num=entry-table; if(*swptr=='+') { *index[num]=1; swptr++; } else if(*swptr=='-') { *index[num]=0; swptr++; } *index[num]=!*index[num]; } } #endif #if SFX_LEVEL>=ARJ&&TARGET==UNIX /* Disables/enables archiving for a particular block device */ static void add_blkdev_spec(char *swptr) { int is_excl=0; char *fnm; if(swptr[0]=='-') { is_excl=1; swptr++; } else if(swptr[0]=='+') swptr++; fnm=(swptr[0]=='\0')?".":swptr; set_dev_mode(is_excl); if(add_dev(fnm)) msg_cprintf(H_ALERT, M_BAD_DEV_SPEC, fnm); } #endif #if SFX_LEVEL>=ARKSFXV /* A user-friendly strtoul(). Can tell between hex and decimal notations */ unsigned long stoul(char *p, char **rp) { unsigned int radix; unsigned long rc; char c; if(rp==NULL) rp=&p; if(p==NULL) { *rp=p; return(0); } if(p[0]=='0'&&p[1]=='x') { p+=2; radix=16; } else radix=10; rc=strtoul(p, rp, radix); c=toupper(**rp); if(c=='K') { *rp++; rc*=1000L; } else if(c=='M') { *rp++; rc*=1000000L; } else if(c=='G') { *rp++; rc*=1000000000L; } else if(c=='T'||c=='P'||c=='E') /* BUGBUG: Reserved */ { *rp++; rc*=0xFFFFFFFF; } return(rc); } #endif #if SFX_LEVEL>=ARJSFXJR /* Sets internal variables depending on the switch given */ void analyze_arg(char *sw) { char *swptr; unsigned int c; FMSG *entry; int num; /* Switch number within the table */ #if SFX_LEVEL>=ARJSFXV int done; FMSG *table; FMSG *params; int **index; char lim; int sw_tail; #endif #if SFX_LEVEL>=ARJ int type; char vol_sw; /* -v... subswitch storage */ int p_len; char *p_ptr; unsigned long cnv_num; #endif swptr=sw; if(swptr[0]==swptr[1]&&swptr[2]=='\0') skip_switch_processing=1; else { swptr++; #if SFX_LEVEL>=ARJ hswitch=jswitch=os2switch=0; if(toupper(*swptr)=='H'&&*(swptr+1)=='2') swptr++; if(*swptr=='2') { os2switch=1; swptr++; } #endif #if SFX_LEVEL>=ARJSFXV done=0; #endif while((c=(unsigned int)*(swptr++))!='\0') { c=toupper(c); #if SFX_LEVEL>=ARJ if(jswitch) { table=M_JSW_TABLE; params=M_JSW_PARAMS; index=jsw_index; } else if(hswitch) { table=M_HSW_TABLE; params=M_HSW_PARAMS; index=hsw_index; } else if(os2switch) { table=M_OS2SW_TABLE; params=M_OS2SW_PARAMS; index=os2sw_index; } else { table=M_SW_TABLE; params=M_SW_PARAMS; index=sw_index; } #elif SFX_LEVEL>=ARJSFXV table=M_SW_TABLE; params=M_SW_PARAMS; index=sw_index; #endif #if SFX_LEVEL>=ARJSFXV entry=msg_strchr(table, (char)c); #else entry=msg_strchr(M_SW_TABLE, (char)c); #endif if(entry==NULL) { #if SFX_LEVEL>=ARJSFXV error(M_INVALID_SWITCH, sw); #else msg_cprintf(0, M_ARJSFX_BANNER, exe_name); msg_cprintf(0, M_INVALID_SWITCH, (char)c); check_fmsg(CHKMSG_NOSKIP); exit(ARJSFX_ERL_ERROR); #endif } #if SFX_LEVEL>=ARJSFXV num=entry-table; #else num=entry-M_SW_TABLE; #endif #if SFX_LEVEL>=ARJSFXV lim=params[num]; sw_tail=get_switch_state(swptr); #endif /* ARJ parameters */ #if SFX_LEVEL>=ARJ if(!jswitch&&!hswitch&&!os2switch&&c=='G'&&sw_tail) { done=1; garble_enabled=1; garble_password=swptr; } else if(!jswitch&&!hswitch&&!os2switch&&c=='E'&&sw_tail) { done=1; left_trim=(unsigned int)stoul(swptr, &swptr); exclude_paths=(left_trim==0)?EP_PATH:EP_BASEDIR; } else if(!jswitch&&!hswitch&&!os2switch&&c=='L'&&sw_tail) { done=1; create_list_file=1; list_file=swptr; } else if(!jswitch&&!hswitch&&!os2switch&&c=='O'&&sw_tail) { done=1; if(toupper(*swptr)=='B') { if(*++swptr=='-') filter_older=TCHECK_NOTHING; else { filter_older=TCHECK_FTIME; timestr_older=swptr; } } else if(toupper(*swptr)=='D') { swptr++; if(*swptr=='-') filter_same_or_newer=TCHECK_NOTHING; else if(toupper(*swptr)=='B') { filter_older=TCHECK_NDAYS; swptr++; timestr_older=swptr; } else { filter_same_or_newer=TCHECK_NDAYS; timestr_newer=swptr; } } else if(toupper(*swptr)=='C') { swptr++; if(toupper(*swptr)=='B') { filter_older=TCHECK_CTIME; swptr++; timestr_older=swptr; } else { filter_same_or_newer=TCHECK_CTIME; timestr_newer=swptr; } } else if(toupper(*swptr)=='A') { swptr++; if(toupper(*swptr)=='B') { filter_older=TCHECK_ATIME; swptr++; timestr_older=swptr; } else { filter_same_or_newer=TCHECK_ATIME; timestr_newer=swptr; } } else { filter_same_or_newer=TCHECK_FTIME; timestr_newer=swptr; } } else if(!jswitch&&!hswitch&&!os2switch&&c=='T'&&sw_tail) { done=1; type_override=FT_BINARY; type=(int)(*swptr-'0'); if(type!=ARJT_BINARY&&type!=ARJT_TEXT) error(M_INVALID_SWITCH, sw); swptr++; /* ASR fix 25/01/2004: the "-t1gf" combination was the only way to enforce "text with graphics" which was not trivial. Now "-t1g" should do it as well. */ if(type==ARJT_TEXT) type_override=FT_TEXT; while((c=toupper(*swptr))=='G'||c=='F') { if(c=='G') type_override=FT_TEXT_GRAPHICS; else if(c=='F'&&type_override2) error(M_INVALID_SWITCH, sw); if(swptr[1]!=':'&&swptr[1]!='\0') error(M_INVALID_SWITCH, sw); } else if(!jswitch&&!hswitch&&!os2switch&&c=='+'&&sw_tail) done=1; else if(hswitch&&c=='B') { done=1; filter_attrs=1; parse_attrs(swptr); } else if(hswitch&&c=='C'&&sw_tail) { done=1; run_cmd_at_start=1; start_cmd=swptr; } else if(hswitch&&c=='D') { if(*swptr=='\0') error(M_INVALID_SWITCH, sw); done=1; debug_enabled=1; debug_opt=swptr; } else if(hswitch&&c=='G') { done=1; gost_cipher=GOST256; if(*swptr=='!'&&swptr[1]=='\0') gost_cipher=GOST40; else arjcrypt_name=swptr; } else if(hswitch&&c=='M') { done=1; filelist_storage=BST_DISK; max_filenames=(FILE_COUNT)stoul(swptr, &swptr); if(max_filenames==0) max_filenames=EXT_FILELIST_CAPACITY; if(*swptr=='!'&&swptr[1]!='\0') swptr_hm=++swptr; #if TARGET==DOS else if(*swptr=='!'&&swptr[1]=='\0') filelist_storage=BST_XMS; #endif } else if(hswitch&&c=='N') { done=1; nonexist_filespec=1; nonexist_name=swptr; } else if(hswitch&&c=='P') { done=1; arjdisp_enabled=1; arjdisp_ptr=swptr; } else if(hswitch&&c=='T') { done=1; set_target_directory=1; p_len=strlen(swptr); p_ptr=&swptr[p_len-1]; while(*p_ptr==' ') p_ptr--; if(strchr(path_separators, *p_ptr)!=NULL) target_dir=swptr; else { strcpy(target_dir=malloc_msg(p_len+2), swptr); target_dir[p_len]=PATHSEP_DEFAULT; target_dir[p_len+1]='\0'; } } else if(hswitch&&c=='V') { done=1; chk_arj_version=1; swptr_hv=swptr; } else if(hswitch&&c=='X') { done=1; override_archive_exts=1; archive_ext_list=swptr; if(swptr[0]!='.'||swptr[1]=='\0') error(M_INVALID_SWITCH, sw); } else if(hswitch&&c=='Z') { done=1; sign_with_arjsec=1; arjsec_env_name=swptr; } else if(hswitch&&c=='#'&&*swptr!='\0'&&!isdigit(*swptr)) { done=1; append_curtime=1; time_str=swptr; } else if(jswitch&&c=='C'&&sw_tail) { done=1; exit_after_count=1; exit_count=(FILE_COUNT)stoul(swptr, &swptr); } else if(jswitch&&c=='D'&&sw_tail) { done=1; chk_free_space=1; minfree=stoul(swptr, &swptr); } else if(jswitch&&c=='B'&&sw_tail) { done=1; chapter_mode=CHAP_USE; if(*swptr=='*') { swptr++; current_chapter=1; chapter_to_process=RESERVED_CHAPTER; } else { cnv_num=stoul(swptr, &swptr); chapter_to_process=current_chapter=(int)cnv_num; if(*swptr++=='-') { if(*swptr=='\0') chapter_to_process=RESERVED_CHAPTER; else { cnv_num=stoul(swptr, &swptr); chapter_to_process=(int)cnv_num; if(chapter_to_process>CHAPTERS_MAX) error(M_INVALID_SWITCH, sw); } } if(current_chapter==0&&chapter_to_process==0) chapter_mode=CHAP_REMOVE; } } else if(jswitch&&c=='H'&&sw_tail) { done=1; jh_enabled=1; cnv_num=stoul(swptr, &swptr); if(cnv_num<(unsigned long)MIN_BUFSIZ||cnv_num>(unsigned long)MAX_USER_BUFSIZ) error(M_INVALID_SWITCH, sw); #if MAX_BUFSIZ(unsigned long)MAX_BUFSIZ) cnv_num=MAX_BUFSIZ; #endif user_bufsiz=(unsigned int)cnv_num; } else if(jswitch&&c=='I'&&sw_tail) { done=1; create_index=1; index_name=swptr; } else if(jswitch&&c=='N'&&sw_tail) { done=1; restart_at_filename=1; filename_to_restart=swptr; } else if(jswitch&&c=='Q'&&sw_tail) { done=1; set_string_parameter=1; string_parameter=swptr; } else if(jswitch&&c=='P'&&sw_tail) { done=1; prompt_for_more=1; cnv_num=stoul(swptr, &swptr); if(cnv_num>0L) lines_per_page=(int)cnv_num; } else if(jswitch&&c=='S'&&sw_tail) { done=1; store_by_suffix=1; free_fmsg(archive_suffixes); archive_suffixes=swptr; } else if(jswitch&&c=='W'&&sw_tail) { done=1; extract_to_file=1; extraction_filename=swptr; } else if(jswitch&&c=='X'&&sw_tail) { done=1; start_at_ext_pos=1; ext_pos=stoul(swptr, &swptr); } else if(jswitch&&c=='Y'&&sw_tail) { done=1; assume_yes=1; yes_query_list=swptr; parse_yes_queries(yes_query_list); } else if(jswitch&&c=='Z'&&sw_tail) { done=1; supply_comment_file=1; comment_file=swptr; } #if TARGET==UNIX else if(os2switch&&c=='B') { done=1; add_blkdev_spec(swptr); } #endif else if(os2switch&&c=='E') { done=1; if(!sw_tail) ea_supported=0; else { include_eas=1; #if defined(HAVE_EAS) flist_add_files(&flist_ea, NULL, swptr, 0, 0, 0, NULL); #endif } } else if(os2switch&&c=='I'&&sw_tail) { done=1; start_with_seek=1; arcv_ext_pos=stoul(swptr, &swptr); } else if(os2switch&&c=='P') { if(!sw_tail) error(M_INVALID_SWITCH, sw); priority.class=stoul(swptr, &swptr); if(priority.class<1||priority.class>PRIORITY_CLASSES) error(M_INVALID_SWITCH, sw); #if TARGET==OS2||TARGET==WIN32 if((p_ptr=strchr(swptr, ':'))==NULL) priority.delta=0; else { swptr=p_ptr+1; priority.delta=stoul(swptr, &swptr); #if TARGET==OS2 if(priority.delta<-31||priority.delta>31) #elif TARGET==WIN32 if(priority.delta<-2||priority.delta>2) #else #error No priority delta limits! #endif error(M_INVALID_SWITCH, sw); } #else priority.delta=0; #endif } #ifdef COLOR_OUTPUT else if(os2switch&&c=='T') { done=!parse_colors(swptr); if(!done) error(M_INVALID_SWITCH, sw); } #endif else if(os2switch&&c=='X') { done=1; if(!sw_tail) error(M_MISSING_FILENAME_ARG, "-2x"); else { exclude_eas=1; #if defined(HAVE_EAS) flist_add_files(&flist_xea, NULL, swptr, 0, 0, 0, NULL); #endif } } else if(*swptr=='+') { *index[num]=1; swptr++; } else if(*swptr=='-') { *index[num]=0; swptr++; } else if(*swptr>='0'&&*swptr<='9') { if(!debug_enabled||strchr(debug_opt, 's')==NULL) { if(*swptr>lim) error(M_INVALID_SWITCH, sw); } *index[num]=(int)(*(swptr++)+1-'0'); } else *index[num]=!*index[num]; /* ARJSFXV parameters */ #elif SFX_LEVEL==ARJSFXV if(c=='G'&&sw_tail) { done=1; garble_enabled=1; garble_password=swptr; } else if(c=='+'&&sw_tail) done=1; else if(c=='&') { if(*swptr=='\0') error(M_INVALID_SWITCH, sw); done=1; debug_enabled=1; debug_opt=swptr; } else if(c=='@') { done=1; arjdisp_enabled=1; arjdisp_ptr=swptr; } else if(c=='!') { done=1; execute_extr_cmd=1; extr_cmd_text=swptr; } else if(c=='$'&&sw_tail) { done=1; handle_labels=1; label_drive=toupper(*swptr); if(!isalpha(*swptr)||strlen(swptr)>2) error(M_INVALID_SWITCH, sw); if(swptr[1]!=':'&&swptr[1]!='\0') error(M_INVALID_SWITCH, sw); } else if(c=='W'&&sw_tail) { done=1; extract_to_file=1; extraction_filename=swptr; } else if(c=='D'&&sw_tail) { done=1; chk_free_space=1; minfree=stoul(swptr, &swptr); } else if(c=='#'&&sw_tail) { done=1; skip_volumes=1; first_volume_number=stoul(swptr, &swptr); } else if(c=='O'&&sw_tail) { done=1; gost_cipher=GOST256; arjcrypt_name=swptr; } else if(c=='Z'&&sw_tail) { done=1; assume_yes=1; yes_query_list=swptr; parse_yes_queries(yes_query_list); } else if(*swptr=='+') { *index[num]=1; swptr++; } else if(*swptr=='-') { *index[num]=0; swptr++; } else if(*swptr>='0'&&*swptr<='3') { if(!debug_enabled||strchr(debug_opt, 's')==NULL) { if(*swptr>lim) error(M_INVALID_SWITCH, sw); } *index[num]=(int)(*(swptr++)+1-'0'); } else *index[num]=!*index[num]; /* ARJSFX parameters */ #elif SFX_LEVEL==ARJSFX *sw_index[num]=1; if(c=='G'&&*swptr!='\0') { garble_password=swptr; while(*swptr!='\0') swptr++; } if(c=='!') { extr_cmd_text=swptr; while(*swptr!='\0') swptr++; } #endif #if SFX_LEVEL>=ARJSFXV if(done) { while(*swptr!='\0') swptr++; } #endif } } } #endif #if SFX_LEVEL>=ARJSFXV /* Initializes system variables with default settings prior to setup procedures */ void init() { unsigned int i; #if SFX_LEVEL>=ARJ multivolume_option=0; #else multivolume_option=1; #endif #if SFX_LEVEL>=ARJ for(i=0; i=ARJ for(i=0; i=ARJ primary_file_type=ARJT_BINARY; #endif listchar=LISTCHAR_DEFAULT; #if SFX_LEVEL>=ARJ lines_per_page=query_screen_height(); #endif listchars_allowed=1; ctrlc_not_busy=1; #if SFX_LEVEL>=ARJ file_args=-1; #else file_args=0; #endif #if SFX_LEVEL<=ARJSFXV extract_expath=0; extract_cmd=0; list_sfx_cmd=0; verbose_list=0; test_sfx_cmd=0; error_occured=0; licensed_sfx=0; logo_shown=0; #endif #if SFX_LEVEL>=ARJ max_filenames=EXT_FILELIST_CAPACITY; ctrlc_processing=0; display_totals=0; lines_scrolled=0; #endif errors=0; #if SFX_LEVEL>=ARJ ts_store(&tested_ftime_newer, OS_SPECIAL, 0); ts_store(&tested_ftime_older, OS_SPECIAL, 0); last_hdr_offset=0L; tmp_archive_used=0; arch_wildcard_allowed=0; file_attr_mask=TAG_FILES; recursion_order=RO_LAST; encryption_id=0; use_ansi_cp=0; filter_fa_arch=0; serialize_exts=0; #else file_garbled=0; #endif allow_any_attrs=0; #if SFX_LEVEL>=ARJ set_target_directory=0; chapter_mode=0; #endif install_errhdl=0; #if SFX_LEVEL<=ARJSFXV prompt_for_directory=0; #endif debug_enabled=0; #if SFX_LEVEL>=ARJ delete_processed=0; run_cmd_at_start=0; arjsec_opt=0; exclude_paths=0; execute_cmd=0; start_at_ext_pos=0; start_with_seek=0; arcv_ext_pos=0; subdir_extraction=0; extm_mode=0; override_archive_exts=0; disable_comment_series=0; skip_century=CENT_DEFAULT; show_filenames_only=0; force_lfn=0; chk_free_space=0; freshen_criteria=FC_NONE; validate_style=0; jh_enabled=0; clear_archive_bit=0; ignore_archive_errors=0; ignore_open_errors=0; detailed_index=0; create_index=0; keep_bak=0; keep_tmp_archive=0; sign_with_arjsec=0; handle_labels=0; listfile_err_opt=0; create_list_file=0; std_list_cmd=0; filelist_storage=0; max_compression=0; custom_method=0; skip_time_attrs=0; indicator_style=0; yes_on_all_queries=0; disable_sharing=0; skip_switch_processing=0; no_file_activity=0; new_files_only=0; filter_same_or_newer=0; rsp_per_line=0; gost_cipher=0; marksym_expansion=0; fnm_matching=0; arcmail_sw=0; dos_host=0; priority.class=priority.delta=0; #endif arjdisp_enabled=0; #if SFX_LEVEL<=ARJSFXV subdir_extraction=0; execute_cmd=0; show_filenames_only=0; chk_free_space=0; freshen_criteria=FC_NONE; validate_style=VALIDATE_ALL; garble_enabled=0; overwrite_ro=0; handle_labels=0; listfile_err_opt=0; std_list_cmd=0; indicator_style=0; yes_on_all_queries=0; disable_sharing=1; skip_switch_processing=0; new_files_only=0; fnm_matching=0; execute_extr_cmd=0; #endif #if SFX_LEVEL>=ARJ protfile_option=0; query_for_each_file=0; set_string_parameter=0; lowercase_names=0; #endif ignore_crc_errors=0; recurse_subdirs=0; quiet_mode=0; #if SFX_LEVEL<=ARJSFXV skip_volumes=0; #endif keep_tmp_file=0; print_with_more=0; #if SFX_LEVEL<=ARJSFXV valid_envelope=0; process_lfn_archive=0; skip_preset_options=0; #endif #if SFX_LEVEL>=ARJ search_mode=0; select_backup_files=0; filter_attrs=0; create_sfx=0; lfn_mode=0; comment_display=0; #endif skip_ts_check=0; #if SFX_LEVEL>=ARJ store_by_suffix=0; test_archive_crc=0; timestamp_override=0; type_override=0; translate_unix_paths=0; #endif update_criteria=UC_NONE; #if SFX_LEVEL>=ARJ verbose_display=0; chk_arj_version=0; beep_between_volumes=0; allow_mv_update=0; mv_cmd_state=0; whole_files_in_mv=0; #endif #if SFX_LEVEL>=ARJSFXV /* To keep v 2.71 order */ use_sfxstub=0; #endif #if SFX_LEVEL>=ARJ assign_work_directory=0; #endif extract_to_file=0; assume_yes=0; kbd_cleanup_on_input=0; skip_append_query=0; prompt_for_mkdir=0; #if SFX_LEVEL>=ARJ query_delete=0; #endif skip_space_query=0; skip_rename_prompt=0; overwrite_existing=0; #if SFX_LEVEL>=ARJ skip_scanned_query=0; #endif skip_next_vol_query=0; #if SFX_LEVEL>=ARJ accept_shortcut_keys=0; #else reg_id=0; first_volume_number=0; #endif #if SFX_LEVEL>=ARJ use_comment=0; supply_comment_file=0; current_chapter=0; chapter_to_process=0; resume_volume_num=0; exit_count=0; left_trim=0; ext_pos=0; #endif label_drive=0; minfree=0L; #if SFX_LEVEL>=ARJ volume_limit=0L; mv_reserve_space=0L; t_volume_offset=0L; #endif av_uncompressed=0L; av_compressed=0L; av_total_files=0; av_total_longnames=0; #if SFX_LEVEL>=ARJ total_size=0L; user_bufsiz=current_bufsiz=BUFSIZ_DEFAULT; ntext=NULL; /* ASR fix for 2.76.06 */ #if TARGET==UNIX sl_entries.list=l_entries.list=NULL; sl_entries.total=sl_entries.alloc=l_entries.total=l_entries.alloc=0; #endif #endif nonexist_name=nonexistent_name; archive_suffixes=malloc_fmsg(M_ARCHIVE_SUFFIXES); #if SFX_LEVEL>=ARJ swptr_t=nullstr; work_directory=nullstr; #endif target_dir=nullstr; #if SFX_LEVEL>=ARJ swptr_hm=nullstr; start_cmd=nullstr; cmd_to_exec=nullstr; archive_ext_list=nullstr; index_name=nullstr; #endif debug_opt=nullstr; #if SFX_LEVEL>=ARJ timestr_newer=nullstr; timestr_older=nullstr; #else extr_cmd_text=nullstr; garble_password=nullstr; #endif arjdisp_ptr=nullstr; #if SFX_LEVEL>=ARJ filename_to_restart=nullstr; mv_cmd=nullstr; arjsec_env_name=nullstr; list_file=nullstr; arjcrypt_name=nullstr; string_parameter=nullstr; swptr_hv=nullstr; time_str=nullstr; #endif extraction_filename=nullstr; yes_query_list=nullstr; #if SFX_LEVEL>=ARJ archive_cmt_name=nullstr; comment_file=nullstr; #endif tmp_tmp_filename[0]='\0'; archive_name[0]='\0'; #if SFX_LEVEL<=ARJSFXV aistream=NULL; atstream=NULL; #endif file_packing=1; #if SFX_LEVEL>=ARJSFXV eh=NULL; valid_ext_hdr=0; #endif #if SFX_LEVEL>=ARJ include_eas=0; exclude_eas=0; crit_eas=0; fix_longnames=0; symlink_accuracy=0; do_chown=0; suppress_hardlinks=0; #endif } /* Returns 1 if the given argument is a command-line switch */ int is_switch(char *arg) { int rc; if(!skip_switch_processing&&switch_char!=0&&(int)arg[0]==switch_char) rc=1; else if(!skip_switch_processing&&switch_char==0) rc=(strchr(switch_chars, arg[0])==NULL)?0:1; else rc=0; if(rc&&switch_char==0) switch_char=(int)arg[0]; return(rc); } #endif #if SFX_LEVEL>=ARJ /* Performs general command-line analysis and returns the command being requested. */ int preprocess_cmdline(int argc, char *argv[]) { int i; int cmd; char *arg; cmd=0; new_stdout=stdout; disable_arj_sw=0; skip_switch_processing=0; rsp_name=nullstr; /* ASR fix -- 15/10/2000 (ARJ/2-32) */ switch_char=0; install_errhdl=0; quiet_mode=0; use_ansi_cp=0; file_garbled=0; garble_enabled=0; garble_password=nullstr; arj_env_name=malloc_fmsg(M_ARJ_SW); for(i=1; i=ARJSFX||defined(REARJ) /* Splits the given name to pathname and filename. On return, pathname contains ASCIIZ path specification including path terminator, filename contains ASCIIZ filename (with no preceding path terminators), and the return value is the offset of filename within the given name. */ #if SFX_LEVEL>=ARJSFXV||defined(REARJ) int split_name(char *name, char *pathname, char *filename) #else int split_name(char *name) #endif { char *f_sep, *last_sep; int i, sep_offset; last_sep=NULL; for(i=0; path_separators[i]!='\0'; i++) { if((f_sep=strrchr(name, path_separators[i]))!=NULL) { if(last_sep==NULL||f_sep>last_sep) last_sep=f_sep; } } sep_offset=(last_sep==NULL)?0:last_sep-name+1; #if SFX_LEVEL>=ARJSFXV||defined(REARJ) if(pathname!=NULL) strcpyn(pathname, name, sep_offset+1); if(filename!=NULL) strcpy(filename, name+sep_offset); #endif return(sep_offset); } #endif #if SFX_LEVEL>=ARJSFXV /* Returns the error code for error message given */ int subclass_errors(FMSG *errmsg) { if(errmsg==M_OUT_OF_MEMORY||errmsg==M_OUT_OF_NEAR_MEMORY) return(ARJ_ERL_NO_MEMORY); if(errmsg==M_HEADER_CRC_ERROR||errmsg==M_CRC_ERROR) return(ARJ_ERL_CRC_ERROR); #if SFX_LEVEL>=ARJ if(errmsg==M_DAMAGED_SEC_ARCHIVE||errmsg==M_CANT_UPDATE_SEC||errmsg==M_SKIPPING_SEC) return(ARJ_ERL_ARJSEC_ERROR); #endif if(errmsg==M_DISK_FULL) return(ARJ_ERL_DISK_FULL); if(errmsg==M_CANTOPEN) return(ARJ_ERL_CANTOPEN); if(errmsg==M_NOT_ARJ_ARCHIVE) return(ARJ_ERL_NOT_ARJ_ARCHIVE); #if SFX_LEVEL>=ARJ #if TARGET==DOS if(errmsg==M_LISTING_XMS_ERROR) return(ARJ_ERL_XMS_ERROR); #endif if(errmsg==M_TOO_MANY_CHAPTERS) return(ARJ_ERL_TOO_MANY_CHAPTERS); #endif if(errmsg==M_INVALID_SWITCH||errmsg==M_ARGTABLE_OVERFLOW||errmsg==M_NO_FILE_GIVEN|| #if SFX_LEVEL>=ARJ errmsg==M_NO_DELETE_ARG||errmsg==M_INVALID_VOL_SIZE|| errmsg==M_NO_STR_ENTERED||errmsg==M_JT_UNUSABLE|| #endif errmsg==M_NO_PWD_OPTION|| errmsg==M_MISSING_FILENAME_ARG||errmsg==M_INVALID_DATE_STRING||errmsg==M_BAD_SYNTAX) return(ARJ_ERL_USER_ERROR); return(ARJ_ERL_FATAL_ERROR); } #endif #if SFX_LEVEL>=ARJ /* Retrieves search data from string parameter given by -jq */ static int get_str_from_jq() { char *sptr, *tsptr; char *endptr; int patterns; char pt; sptr=string_parameter; if(sptr[0]!='+'&&sptr[0]!='-') error(M_INVALID_PARAM_STR, sptr); ignore_pcase=sptr[0]=='+'; fdisp_lines=(int)stoul(sptr, &sptr); patterns=0; if(*sptr!='\0') { pt=*sptr; sptr++; /* Tokenize string_parameter */ for(tsptr=sptr; *tsptr!='\0'; tsptr++) if(*tsptr==pt) *tsptr='\0'; endptr=tsptr; tsptr=sptr; while((unsigned int)tsptr<(unsigned int)endptr&&patterns=ARJSFXV /* Performs an optimized seek operation */ void file_seek(FILE *stream, long offset, int whence) { char *buffer; if(whence==SEEK_CUR&&offset>=0L&&offset<=(long)CACHE_SIZE) { buffer=malloc_msg(CACHE_SIZE); if(offset>0L) fread(buffer, 1, (int)offset, stream); free(buffer); } else fseek(stream, offset, whence); } #endif #if SFX_LEVEL>=ARJ /* Performs a search operation set-up */ void search_setup() { char entry[INPUT_LENGTH]; int patterns; if(set_string_parameter&&string_parameter[0]!='\0') patterns=get_str_from_jq(); else { ignore_pcase=query_action(REPLY_NO, QUERY_CRITICAL, M_QUERY_CASE_IGNORE); msg_cprintf(0, M_ENTER_NUM_MATCHES); read_line(entry, sizeof(entry)); fdisp_lines=stoul(entry, NULL); msg_cprintf(0, M_ENTER_SEARCH_STR, SEARCH_STR_MAX); for(patterns=0; patterns0) { if(ignore_pcase) strupper(search_str[patterns]); } if(fdisp_lines!=0) indicator_style=IND_NONE; reserve_size=0; search_reserve=malloc_msg(sizeof(entry)*2); } #endif #if (SFX_LEVEL>=ARJSFX)||defined(ARJDISP) /* Based on the unsigned long values given, calculates their proportion (per mille, so 42.3% is returned as 423). */ int calc_percentage(unsigned long partial, unsigned long total) { int dec; for(dec=0; dec<3; dec++) { if(partial<=0x19999999) partial*=10L; else total/=10L; } if(partial+total/2<=partial) { partial/=2; total/=2; } if(total==0) return(0); else return((partial+total/2)/total); } #endif #if SFX_LEVEL>=ARJSFXV /* Performs a "smart" seeking, depending on file type (special handling is performed for text files) */ void smart_seek(unsigned long position, FILE *stream) { char *tmp_buf; int fetch_size; fseek(stream, 0L, SEEK_SET); if(position>0L) { if(file_type==ARJT_BINARY) fseek(stream, position, SEEK_SET); else { tmp_buf=(char *)malloc_msg(PROC_BLOCK_SIZE); while(position>0L) { fetch_size=(int)min(position, (unsigned long)PROC_BLOCK_SIZE); if(fread(tmp_buf, 1, fetch_size, stream)!=fetch_size) error(M_SEEK_FAILED); position-=(unsigned long)fetch_size; } fseek(stream, 0L, SEEK_CUR); free(tmp_buf); } } } #endif #if SFX_LEVEL>=ARJSFX||defined(REARJ)||defined(REGISTER) /* This procedure trims the extra spaces and tabs at the left and right of line given */ void alltrim(char *cmd) { int fchars; char *lpos; lpos=cmd; for(fchars=strlen(cmd)-1; fchars>=0; fchars--) { if(cmd[fchars]!='\x09'&&cmd[fchars]!=' ') break; } if(fchars>=0) { while(lpos[0]=='\x09'||lpos[0]==' ') { lpos++; fchars--; } while(fchars>=0) { (cmd++)[0]=(lpos++)[0]; fchars--; } } cmd[0]='\0'; } #endif #if SFX_LEVEL>=ARJSFX /* Extracts a stored file */ void unstore(int action) { char *fetch; #if SFX_LEVEL>=ARJSFXV unsigned int fetch_size; unsigned long cur_pos; #endif unsigned long bytes_written; int count; #if SFX_LEVEL>=ARJSFXV fetch=NULL; for(fetch_size=PROC_BLOCK_SIZE; fetch_size>=512; fetch_size-=512) { if((fetch=(char *)malloc(fetch_size))!=NULL) break; } if(fetch==NULL) error(M_OUT_OF_MEMORY); mem_stats(); #else fetch=dec_text; #endif display_indicator(bytes_written=0L); #if SFX_LEVEL>=ARJSFXV if(file_packing) { cur_pos=ftell(aistream); count=min(fetch_size-(cur_pos%fetch_size), compsize); } else count=min(fetch_size, compsize); #else count=min(DICSIZ, compsize); #endif while(compsize>0L) { if(file_packing) { if(fread(fetch, 1, count, aistream)!=count) error(M_CANTREAD); } else { far_memmove((char FAR *)fetch, packblock_ptr, count); packblock_ptr+=count; packmem_remain-=count; } if(file_garbled) #if SFX_LEVEL>=ARJ garble_decode_stub(fetch, count); #else garble_decode(fetch, count); #endif bytes_written+=(unsigned long)count; display_indicator(bytes_written); compsize-=(unsigned long)count; if(extraction_stub(fetch, count, action)) break; #if SFX_LEVEL>=ARJSFXV count=min(fetch_size, compsize); #else count=min(DICSIZ, compsize); #endif } #if SFX_LEVEL>=ARJSFXV free(fetch); #endif } #endif #if SFX_LEVEL>=ARJ /* Performs a "hollow" file decoding (compares the CRC if requested to do so, otherwise quits). */ void hollow_decode(int action) { char *fetch; unsigned long bytes_written; unsigned long cur_pos; int count; if(action==BOP_COMPARE) { fetch=(char *)malloc_msg(PROC_BLOCK_SIZE); mem_stats(); display_indicator(bytes_written=0L); cur_pos=origsize; count=min(cur_pos, (unsigned long)PROC_BLOCK_SIZE); while(cur_pos>0L) { if(fread(fetch, 1, count, tstream)!=count) { identical_filedata=0; break; } crc32_for_block(fetch, count); bytes_written+=(unsigned long)count; display_indicator(bytes_written); cur_pos-=(unsigned long)count; count=min(PROC_BLOCK_SIZE, cur_pos); } free(fetch); } } #endif #if SFX_LEVEL>=ARJ /* Packs a memory block. The destination area must be large enough to hold an unpacked copy. */ void pack_mem(struct mempack *mempack) { unsigned long s_compsize, s_origsize; int s_method, s_packing; int s_type; unsigned long c_t; s_compsize=compsize; s_origsize=origsize; s_method=method; s_packing=file_packing; s_type=file_type; origsize=mempack->origsize; compsize=0L; method=mempack->method; encblock_ptr=mempack->orig; packblock_ptr=mempack->comp+MEMPACK_OVERHEAD; encmem_remain=mempack->origsize; packmem_remain=0; unpackable=0; file_packing=0; file_type=ARJT_BINARY; if(garble_enabled) garble_init(password_modifier); crc32term=CRC_MASK; if(method==1||method==2||method==3) encode_stub(method); else if(method==4) encode_f_stub(); if(unpackable) /* Fall back to method #0 */ { encblock_ptr=mempack->orig; packblock_ptr=mempack->comp+MEMPACK_OVERHEAD; encmem_remain=mempack->origsize; method=0; if(garble_enabled) garble_init(password_modifier); crc32term=CRC_MASK; } if(method==0) store(); c_t=crc32term^CRC_MASK; mempack->comp[0]=c_t&0x000000FF; mempack->comp[1]=(c_t&0x0000FF00)>>8; mempack->comp[2]=(c_t&0x00FF0000)>>16; mempack->comp[3]=(c_t&0xFF000000)>>24; mempack->compsize=compsize+MEMPACK_OVERHEAD; mempack->method=method; file_type=s_type; file_packing=s_packing; compsize=s_compsize; origsize=s_origsize; method=s_method; } #endif #if SFX_LEVEL>=ARJSFXV /* Unpacks a memory block. The destination area must be large enough to hold an unpacked copy. */ void unpack_mem(struct mempack *mempack) { unsigned long s_compsize, s_origsize; int s_method, s_packing, s_type; unsigned long c_t; s_type=file_type; s_compsize=compsize; s_origsize=origsize; s_method=method; s_packing=file_packing; file_type=ARJT_BINARY; origsize=mempack->origsize; encmem_limit=mempack->origsize; compsize=mempack->compsize-MEMPACK_OVERHEAD; method=mempack->method; encblock_ptr=mempack->orig; packblock_ptr=mempack->comp+MEMPACK_OVERHEAD; encmem_remain=0; file_packing=0; packmem_remain=mempack->compsize-MEMPACK_OVERHEAD; /* v 2.76.04+ - to allow for ARJCRYPT modules within SFXV, we reinitialize the encryption only for garbled files (was for garble_enabled until now) */ if(file_garbled) garble_init(password_modifier); crc32term=CRC_MASK; if(method==1||method==2||method==3) decode(BOP_NONE); #if SFX_LEVEL>=ARJ else if(method==4) decode_f(BOP_NONE); #endif else if(method==0) unstore(BOP_NONE); c_t=(unsigned long)((unsigned char)mempack->comp[0])+ ((unsigned long)((unsigned char)mempack->comp[1])<<8)+ ((unsigned long)((unsigned char)mempack->comp[2])<<16)+ ((unsigned long)((unsigned char)mempack->comp[3])<<24); if(c_t!=(crc32term^CRC_MASK)) error(M_CRC_ERROR); file_type=s_type; file_packing=s_packing; compsize=s_compsize; origsize=s_origsize; method=s_method; } #endif /* Strips ending LF character from the given string */ #if SFX_LEVEL>=ARJSFX||defined(REGISTER)||defined(REARJ) void strip_lf(char *str) { int i; if((i=strlen(str))>0) { if(str[i-1]==LF) str[i-1]='\0'; } } #endif /* Trims leftmost spaces */ #if SFX_LEVEL>=ARJ||defined(REGISTER)||defined(REARJ) char *ltrim(char *str) { char *rc; for(rc=str; *rc==' '; rc++); return(rc); } #endif #if defined(WORDS_BIGENDIAN)&&!defined(ARJDISP)&&!defined(REGISTER) /* Model-independent routine to get 2 bytes from far RAM */ unsigned int mget_word(char FAR *p) { unsigned int b0, b1; b0=mget_byte(p); b1=mget_byte(p+1); return (b1<<8)|b0; } /* Model-independent routine to get 4 bytes from far RAM */ unsigned long mget_dword(char FAR *p) { unsigned long w0, w1; w0=mget_word(p); w1=mget_word(p+2); return (w1<<16)|w0; } /* Model-independent routine to store 2 bytes in far RAM */ void mput_word(unsigned int w, char FAR *p) { mput_byte(w&0xFF, p); mput_byte(w>>8 , p+1); } /* Model-independent routine to store 4 bytes in far RAM */ void mput_dword(unsigned long d, char FAR *p) { mput_word(d&0xFFFF, p); mput_word(d>>16 , p+2); } #endif