/* * $Id: arj_arcv.c,v 1.16 2005/06/21 19:53:13 andrew_belov Exp $ * --------------------------------------------------------------------------- * Archive management routines are stored here (all these have nothing to do * neither with commands nor with the "user" part). * */ #include "arj.h" DEBUGHDR(__FILE__) /* Debug information block */ #define MAX_COMMENT_LINES 25 /* As stated in the documentation */ #define SECURED_MODE 0x78 /* file_mode of ARJ SECURITY headers */ /* Ways of processing for the extended header structure */ #define EHUF_WRITE 0x0001 /* Write the header */ #define EHUF_COMMIT 0x0002 /* Advance the pointer(s) */ #define EHUF_SETFLAGS 0x0004 /* Set the volume flag */ /* * Local variables */ static char *tmp_comment=NULL; /* Temporary comment storage */ static char *tmp_hptr; /* Pointer to parts of header */ static char arjdisp_default[]="arjdisp" EXE_EXTENSION; /* External display module */ #if SFX_LEVEL>=ARJSFXV static unsigned char ea_pwd_modifier; /* For garbled EAs */ static char arjprot_id; /* Identifies ARJ-PROTECT block in the main header */ #endif /* A table of permissions for binary/text files */ #if SFX_LEVEL>=ARJ static char *read_perms[]={m_rb, m_r}; /* For encoding only */ #endif #if SFX_LEVEL>=ARJSFXV static char *sim_perms[]={m_rbp, m_rp}; #endif static char *write_perms[]={m_wb, m_w}; /* Index file IDs */ #if SFX_LEVEL>=ARJ static char idxid_fault[]="?"; #endif /* * A set of macros and functions to read the header */ /* These macros read and write a byte from the header */ #define setup_hget(ptr) (tmp_hptr=(ptr)) #define setup_hput(ptr) (tmp_hptr=(ptr)) #define hget_byte() (*(tmp_hptr++)&0xFF) #define hput_byte(c) (*(tmp_hptr++)=(char) (c)) /* Reads two bytes from the header, incrementing the pointer */ static unsigned int hget_word() { unsigned int result; result=mget_word(tmp_hptr); tmp_hptr+=sizeof(short); return result; } /* Reads four bytes from the header, incrementing the pointer */ static unsigned long hget_longword() { unsigned long result; result=mget_dword(tmp_hptr); tmp_hptr+=sizeof(unsigned long); return result; } #if SFX_LEVEL>=ARJ /* Writes two bytes to the header, incrementing the pointer */ static void hput_word(unsigned int w) { mput_word(w,tmp_hptr); tmp_hptr+=sizeof(unsigned short); } /* Writes four bytes to the header, incrementing the pointer */ static void hput_longword(unsigned long l) { mput_dword(l,tmp_hptr); tmp_hptr+=sizeof(unsigned long); } /* Calculates and stores the basic header size */ static void calc_basic_hdr_size() { basic_hdr_size=(unsigned int)first_hdr_size+strlen(hdr_filename)+1+ strlen(hdr_comment)+1; } #endif #if SFX_LEVEL>=ARJSFXV /* Calculates and stores the offset of comment within a preallocated header */ static void calc_comment_offset() { hdr_comment=&header[(int)first_hdr_size+strlen(hdr_filename)+1]; } #endif #if SFX_LEVEL>=ARJ /* Allocates near memory for a temporary comment image, and copies the comment to this area. */ static void replicate_comment() { tmp_comment=malloc_msg(COMMENT_MAX); far_strcpy((char FAR *)tmp_comment, comment); } /* Removes the temporary comment from memory, copying its contents to original comment storage area (the one in the FAR memory). */ static void dump_tmp_comment() { if(tmp_comment!=NULL) { far_strcpy(comment, (char FAR *)tmp_comment); free(tmp_comment); } } /* Returns 1 if the given type is a file type, not a comment */ static int is_file_type(int t) { return((t==ARJT_BINARY||t==ARJT_TEXT||t==ARJT_DIR||file_type==ARJT_UXSPECIAL||t==ARJT_LABEL)?1:0); } #endif /* Finds archive header, returning its offset within file, or -1 if it can't be located. search_all is used to search through the entire file. */ long find_header(int search_all, FILE *stream) { long end_pos; long tmp_pos; int id; tmp_pos=ftell(stream); #if SFX_LEVEL>=ARJSFXV if(archive_size==0L) { fseek(stream, 0L, SEEK_END); archive_size=ftell(stream)-2L; #if SFX_LEVEL<=ARJSFXV fseek(stream, tmp_pos, SEEK_SET); #endif } end_pos=archive_size; if(!search_all) { if(end_pos>=tmp_pos+HSLIMIT_ARJ) end_pos=tmp_pos+HSLIMIT_ARJ; } while(tmp_pos=ARJSFXV while(tmp_pos=ARJSFXV if(tmp_pos>=end_pos) return(-1); #endif if((basic_hdr_size=fget_word(stream))<=HEADERSIZE_MAX) { crc32term=CRC_MASK; fread_crc(header, basic_hdr_size, stream); #if SFX_LEVEL>=ARJ if(fget_longword(stream)==(crc32term^CRC_MASK)||ignore_crc_errors==ICE_CRC) #else if(fget_longword(stream)==(crc32term^CRC_MASK)) #endif { fseek(stream, tmp_pos, SEEK_SET); return(tmp_pos); } } tmp_pos++; } return(-1); } #if SFX_LEVEL>=ARJ /* Displays a header error */ static void display_hdr_error_proc(FMSG *errmsg, char *name, unsigned int l) { #ifdef DEBUG debug_report(dbg_cur_file, l, 'V'); #endif if(!ignore_archive_errors) error(errmsg, name); msg_cprintf(0, errmsg, name); nputlf(); } #define display_hdr_error(errmsg, name) display_hdr_error_proc(errmsg, name, __LINE__) #else #define display_hdr_error(errmsg, dptr) error(errmsg, dptr) #endif /* Checks size of compressed files for abnormal effects (e.g. size<0) */ static int check_file_size() { return((long)origsize<0||(long)compsize<0); } /* Reads an archive or file header ( is archive filename just for user interface, and first, when == 0, specifies that the archive header is being read). Returns 0 if the end of archive has been reached. */ #if SFX_LEVEL>=ARJSFXV int read_header(int first, FILE *stream, char *name) #else int read_header(int first) #define stream aistream #endif { unsigned short header_id; #if SFX_LEVEL>=ARJSFXV char id; /* Extended header identifier */ char is_continued; struct ext_hdr FAR *tmp_eh; unsigned int remainder, fetch_size; char FAR *dptr; char transfer_buf[64]; #endif #if SFX_LEVEL>=ARJSFXV flush_kbd(); if(ignore_crc_errors!=ICE_NONE) { if(ignore_crc_errors==ICE_FORMAT) /* Allow malformed header signatures */ { cur_header_pos=ftell(stream); if((header_id=fget_word(stream))==HEADER_ID) { if((basic_hdr_size=fget_word(stream))==0) return(0); } fseek(stream, cur_header_pos, SEEK_SET); } if(find_header(1, stream)<0L) { display_hdr_error(M_BAD_HEADER, NULL); return(0); } } cur_header_pos=ftell(stream); #endif /* Strictly check the header ID */ if((header_id=fget_word(stream))!=HEADER_ID) { #if SFX_LEVEL>=ARJSFXV if(first!=0) display_hdr_error(M_NOT_ARJ_ARCHIVE, name); else #endif display_hdr_error(M_BAD_HEADER, NULL); return(0); } if((basic_hdr_size=fget_word(stream))==0) return(0); if(basic_hdr_size>HEADERSIZE_MAX) { display_hdr_error(M_BAD_HEADER, NULL); return(0); } crc32term=CRC_MASK; fread_crc(header, basic_hdr_size, stream); if((header_crc=fget_longword(stream))!=(crc32term^CRC_MASK)) { display_hdr_error(M_HEADER_CRC_ERROR, NULL); #if SFX_LEVEL>=ARJSFXV return(0); #endif } setup_hget(header); first_hdr_size=hget_byte(); arj_nbr=hget_byte(); arj_x_nbr=hget_byte(); host_os=hget_byte(); arj_flags=hget_byte(); method=hget_byte(); file_type=hget_byte(); password_modifier=hget_byte(); ts_store(&ftime_stamp, host_os, hget_longword()); compsize=hget_longword(); origsize=hget_longword(); file_crc=hget_longword(); entry_pos=hget_word(); fm_store(&file_mode, host_os, hget_word()); #if SFX_LEVEL>=ARJSFXV /* Before v 2.50, we could only read host data here. With the introduction of chapter archives, chapter numbers are stored in this field. NOTE: it will be wise to check that the compressor's version (arj_nbr) is >= 7 ... */ ext_flags=hget_byte(); chapter_number=hget_byte(); #if SFX_LEVEL>=ARJ if(modify_command&&ts_cmp(&ftime_stamp, &ftime_max)>0&&is_file_type(file_type)) ftime_max=ftime_stamp; #else if(ts_cmp(&ftime_stamp, &ftime_max)>0&&file_type!=ARJT_COMMENT) ftime_max=ftime_stamp; #endif resume_position=0L; continued_prevvolume=0; /* v 2.62+ - reset ext. timestamps */ ts_store(&atime_stamp, OS_SPECIAL, 0L); if(first) { arjprot_id=0; #if SFX_LEVEL>=ARJ prot_blocks=0; #endif if(first_hdr_size>=FIRST_HDR_SIZE_V) { #if SFX_LEVEL>=ARJ prot_blocks=hget_byte(); #else hget_byte(); #endif arjprot_id=hget_byte(); hget_word(); if(arjprot_id&SFXSTUB_FLAG) use_sfxstub=1; } } else { if(first_hdr_size=ARJSFXV file_garbled=(arj_flags&GARBLED_FLAG)?1:0; garble_ftime=ts_native(&ftime_stamp, host_os); #endif hdr_filename=&header[first_hdr_size]; /* To conserve space, the calc_comment_offset() is placed in-line */ #if SFX_LEVEL>=ARJSFXV calc_comment_offset(); #else hdr_comment=&header[(int)first_hdr_size+strlen(hdr_filename)+1]; #endif #if SFX_LEVEL>=ARJSFXV far_strcpyn((char FAR *)filename, (char FAR *)hdr_filename, FILENAME_MAX); far_strcpyn(comment, (char FAR *)hdr_comment, COMMENT_MAX); #else strncpy(filename, hdr_filename, FILENAME_MAX); strncpy(comment, hdr_comment, COMMENT_MAX); #endif if(first==0&&lfn_supported==LFN_SUPPORTED&&dual_name) { #if SFX_LEVEL>=ARJSFXV far_strcpyn((char FAR *)filename, (char FAR *)hdr_comment, FILENAME_MAX); far_strcpyn(comment, (char FAR *)hdr_filename, COMMENT_MAX); #else strncpy(filename, hdr_comment, FILENAME_MAX); strncpy(comment, hdr_filename, COMMENT_MAX); #endif } filename[FILENAME_MAX-1]='\0'; comment[COMMENT_MAX-1]='\0'; #if SFX_LEVEL>=ARJSFXV if(!test_host_os((int)host_os)&&file_type==ARJT_TEXT) #else if(!test_host_os((int)host_os)) #endif to_7bit(filename); if(arj_flags&PATHSYM_FLAG) name_to_hdr(filename); if(test_host_os((int)host_os)) #if SFX_LEVEL>=ARJSFXV entry_pos=split_name(filename, NULL, NULL); #else entry_pos=split_name(filename); #endif #if SFX_LEVEL<=ARJSFX list_adapted_name=filename+entry_pos; #endif #if SFX_LEVEL>=ARJ /* Convert the comment to 7 bits if the host OS is unknown to us */ if(!test_host_os(host_os)) { replicate_comment(); to_7bit(tmp_comment); dump_tmp_comment(); } #elif SFX_LEVEL==ARJSFX if(!test_host_os(host_os)) to_7bit(comment); /* The advantage of NEAR memory... */ #endif #if SFX_LEVEL>=ARJ /* This was a stub initially, and, anyway, is no longer applicable -- ASR 16/02/2001 */ /* ftime_stamp=import_timestamp(ftime_stamp); */ #endif #if SFX_LEVEL<=ARJSFX file_garbled=(arj_flags&GARBLED_FLAG)?1:0; #endif if(first!=0) { #if SFX_LEVEL>=ARJ if(arj_flags&GARBLED_FLAG) encryption_applied=1; #endif #if SFX_LEVEL>=ARJSFXV continued_nextvolume=(arj_flags&VOLUME_FLAG)?1:0; #endif if(arj_flags&SECURED_FLAG) { security_state=ARJSEC_SECURED; #if SFX_LEVEL>=ARJ secured_size=origsize; #endif arjsec_offset=file_crc; } #if SFX_LEVEL>=ARJSFXV ext_hdr_flags=ext_flags&0x0F; /* Mask only the currently supported values */ #endif if(arj_flags&DUAL_NAME_FLAG) dual_name=1; #if SFX_LEVEL>=ARJSFXV if(arj_flags&ANSICP_FLAG) ansi_codepage=1; #if SFX_LEVEL>=ARJ if(arj_flags&PROT_FLAG) arjprot_tail=1; /* Chapter-archive specific processing */ if(first==1&&chapter_number>0) { if(add_command&¤t_chapter<=CHAPTERS_MAX) { chapter_number++; comment_entries++; } if(!first_vol_passed) total_chapters=chapter_number; else chapter_number=total_chapters; if(total_chapters>CHAPTERS_MAX) error(M_TOO_MANY_CHAPTERS, CHAPTERS_MAX); } #endif #endif } #if SFX_LEVEL>=ARJSFXV else { if(arj_flags&VOLUME_FLAG) #if SFX_LEVEL>=ARJ volume_flag_set=force_volume_flag=1; #else volume_flag_set=1; #endif else volume_flag_set=0; } #endif #if SFX_LEVEL>=ARJ if(file_type==ARJT_CHAPTER&&chapter_number>recent_chapter) recent_chapter=chapter_number; /* ARJSFX/ARJSFXV archives have some limitations, check it here */ if(create_sfx!=SFXCRT_NONE||(sfx_desc_word!=0&&modify_command)) { if(method==4) error(M_INVALID_METHOD_SFX); if(total_chapters>0) error(M_CHAPTER_SFX_CREATION); if(!multivolume_option&&file_type==ARJT_LABEL) error(M_NO_LABELS_IN_SFX); if(!win32_platform&&create_sfx&&!multivolume_option&& ext_hdr_flags>ENCRYPT_GOST256L) error(M_WRONG_ENC_VERSION, ext_hdr_flags); /* ARJSFXJR archives have yet more limitations that need to be checked */ if(create_sfx==SFXCRT_SFXJR||sfx_desc_word==SFXDESC_SFXJR) { #if TARGET==UNIX if(file_type==ARJT_TEXT) #else if(file_type==ARJT_TEXT||lfn_supported!=LFN_NOT_SUPPORTED) #endif error(M_TEXTMODE_LFN_SFXJR); #if defined(HAVE_EAS) if(ea_supported) error(M_TEXTMODE_LFN_SFXJR); #endif /* Check for systems that are hostile to ARJSFXJR */ #if TARGET==DOS if(host_os!=OS) error(M_TEXTMODE_LFN_SFXJR); #elif TARGET!=UNIX if(!test_host_os(host_os)) error(M_TEXTMODE_LFN_SFXJR); #endif if(arj_flags&GARBLED_FLAG) error(M_NO_GARBLE_IN_SFXJR); } } #endif #if SFX_LEVEL>=ARJSFXV /* Reset the extended header buffers for noncontinued files */ if(!(arj_flags&EXTFILE_FLAG)&&cur_header_pos!=main_hdr_offset) { if(eh!=NULL) { eh_release(eh); eh=NULL; valid_ext_hdr=0; } ea_pwd_modifier=password_modifier; } #endif /* Process extended headers, if any */ while((header_id=fget_word(stream))!=0) { #if SFX_LEVEL>=ARJSFXV crc32term=CRC_MASK; if(fread(&id, 1, 1, stream)==0) error(M_CANTREAD); crc32_for_block(&id, 1); valid_ext_hdr=1; /* Skip the extended headers if the file is continued from the previous volume and we haven't caught the beginning */ if((arj_flags&EXTFILE_FLAG)&&eh==NULL) { fseek(stream, (long)header_id+3L, SEEK_CUR); valid_ext_hdr=0; } else { /* Perform early allocation of the extended header block */ if(eh==NULL) eh=eh_alloc(); /* Get the continuation flag */ if(fread(&is_continued, 1, 1, stream)==0) error(M_CANTREAD); crc32_for_block(&is_continued, 1); /* Collect the scattered data */ remainder=header_id-2; tmp_eh=eh_append(eh, id, NULL, remainder); dptr=tmp_eh->raw+(tmp_eh->size-remainder); tmp_eh->flags=is_continued?EH_PROCESSING:EH_UNPROCESSED; while(remainder>0) { fetch_size=min(remainder, sizeof(transfer_buf)); if(fread(transfer_buf, 1, fetch_size, stream)!=fetch_size) error(M_CANTREAD); far_memmove(dptr, transfer_buf, fetch_size); crc32_for_block(transfer_buf, fetch_size); remainder-=fetch_size; dptr+=fetch_size; } if(fget_longword(stream)!=(crc32term^CRC_MASK)) { if(ignore_crc_errors!=ICE_CRC) error(M_BAD_HEADER); else { eh_release(eh); eh=NULL; } } } #else fseek(stream, (long)header_id+4L, SEEK_CUR); #endif } return(1); } #if SFX_LEVEL<=ARJSFX #undef stream #endif #if SFX_LEVEL>=ARJ /* Fill general purpose header fields */ static void fill_general_hdr() { arj_nbr=ARJ_VERSION; arj_x_nbr=ARJ_X_VERSION; if(file_type==ARJT_DIR) arj_x_nbr=ARJ_XD_VERSION; else if(file_type==ARJT_UXSPECIAL) arj_x_nbr=ARJ_XU_VERSION; #if TARGET==DOS host_os=OS; #else host_os=(dos_host==CHO_USE_DOS)?OS_DOS:OS; #endif /* If LFNs are supported, stamp Win95 or WinNT/Win32 OS code */ #if TARGET==DOS if(lfn_supported!=LFN_NOT_SUPPORTED) { host_os=OS_WIN95; if(win32_platform) if(test_for_winnt()) host_os=OS_WINNT; /* Same as OS_WIN32 */ } #endif } /* Fills the basic header */ void create_header(int first) { setup_hput(header); hput_byte(first_hdr_size); hput_byte(arj_nbr); hput_byte(arj_x_nbr); if(first&&dos_host==CHO_COMMENT) host_os=OS_DOS; hput_byte(host_os); hput_byte(arj_flags); hput_byte((char)method); hput_byte((char)file_type); hput_byte((!ts_valid(secondary_ftime))?password_modifier:0); if(ts_valid(secondary_ftime)) { hput_longword(ts_native(&secondary_ftime, OS)); garble_ftime=ts_native(&secondary_ftime, OS); } else { garble_ftime=ts_native(&ftime_stamp, host_os); hput_longword(garble_ftime); } hput_longword(compsize); hput_longword(origsize); hput_longword(file_crc); hput_word(entry_pos); hput_word(fm_native(&file_mode, host_os)); hput_byte(ext_flags); hput_byte(chapter_number); if(first) { if(first_hdr_size>=FIRST_HDR_SIZE_V) { hput_byte((char)prot_blocks); hput_byte(arjprot_id); hput_word(0); } } else { if(first_hdr_size0&&(p_eh=eh_find_pending(p_eh))!=NULL) { rem_size=p_eh->size-p_eh->cur_offset; if((unsigned long)cur_capacity+2<=rem_size) { if(action&EHUF_COMMIT) { p_eh->flags=EH_PROCESSING; p_eh->cur_offset+=ext_hdr_capacity; } remainder=min(cur_capacity, rem_size); cont_id=1; cur_capacity=0; } else { if(action&EHUF_COMMIT) p_eh->flags=EH_FINALIZED; remainder=rem_size; /* ASR fix 15/05/2003 */ /* Take out the ID/length/CRC32 and the data */ cur_capacity-=rem_size+EXT_HDR_OVERHEAD; cont_id=0; } if(action&EHUF_WRITE) { fput_word(remainder+2, aostream); crc32term=CRC_MASK; id=p_eh->tag; fwrite_crc(&id, 1, aostream); fwrite_crc(&cont_id, 1, aostream); dptr=p_eh->raw+p_eh->cur_offset; while(remainder>0) { fetch_size=min(sizeof(transfer_buf), remainder); far_memmove((char FAR *)transfer_buf, dptr, fetch_size); fwrite_crc(transfer_buf, fetch_size, aostream); dptr+=fetch_size; remainder-=fetch_size; } fput_dword(crc32term^CRC_MASK, aostream); } p_eh=p_eh->next; } if(multivolume_option&&p_eh!=NULL&&cur_capacity<=0&&(action&EHUF_SETFLAGS)) volume_flag_set=1; if(action&EHUF_COMMIT) ext_hdr_capacity=cur_capacity; } /* Writes the archive header to the aostream, calculating its CRC */ void write_header() { unsigned long hdr_offset; hdr_offset=ftell(aostream); if(ts_cmp(&ftime_stamp, &ftime_max)>0&&is_file_type(file_type)) ftime_max=ftime_stamp; fput_word(HEADER_ID, aostream); fput_word(basic_hdr_size, aostream); if(fflush(aostream)) error(M_DISK_FULL); if(hdr_offset>last_hdr_offset) last_hdr_offset=hdr_offset; if(file_type!=ARJT_COMMENT&&chapter_number>max_chapter) max_chapter=chapter_number; crc32term=CRC_MASK; fwrite_crc(header, basic_hdr_size, aostream); fput_dword(header_crc=crc32term^CRC_MASK, aostream); /* Store a portion or the entire extended header */ if(eh!=NULL&&hdr_offset!=main_hdr_offset) proc_ext_hdr(EHUF_WRITE|EHUF_SETFLAGS); fput_word(0, aostream); } /* Renames a file in archive. Returns 1 if a header update occured, 0 if not (no filename entered) */ int rename_file() { msg_cprintf(H_HL|H_NFMT, M_CURRENT_FILENAME, filename); msg_cprintf(0, M_ENTER_NEW_FILENAME); read_line(filename, FILENAME_MAX); alltrim(filename); if(filename[0]=='\0') return(0); far_strcpyn(comment, (char FAR *)hdr_comment, COMMENT_MAX); strcpy(hdr_filename, filename); case_path(hdr_filename); entry_pos=split_name(hdr_filename, NULL, NULL); if(translate_path(hdr_filename)) arj_flags|=PATHSYM_FLAG; else arj_flags&=~PATHSYM_FLAG; calc_comment_offset(); far_strcpyn((char FAR *)hdr_comment, comment, COMMENT_MAX); create_header(0); calc_basic_hdr_size(); return(1); } /* Reads a comment from the given file and stores it in the buffer. Supplying a null filename to it will strip the comment (note that null filename is NUL in DOS and /dev/null under UNIX) */ static void read_comment(char *buffer, char *name) { FILE *stream; int llen; /* Length of last read line */ if(!strcmp_os(buffer, dev_null)) return; stream=file_open_noarch(name, m_r); while(fgets(buffer, COMMENT_MAX, stream)!=NULL) { if((llen=strlen(buffer))+strlen(tmp_comment)+4>=COMMENT_MAX) break; strcat(tmp_comment, buffer); } fclose(stream); } /* A routine to supply comments */ int supply_comment(char *cmtname, char *name) { char *tmp_cmtline; int maxlines; int curline; tmp_cmtline=malloc_msg(COMMENT_MAX+1); replicate_comment(); msg_cprintf(H_HL|H_NFMT, M_CURRENT_COMMENT, name); display_comment(comment); /* ASR enhancement -- 09/01/2001 */ if(disable_comment_series&&first_vol_passed) { comment[0]='\0'; calc_basic_hdr_size(); return(1); } /* If the filename given is blank, enter the comment manually */ if(cmtname[0]=='\0') { maxlines=MAX_COMMENT_LINES; msg_cprintf(H_HL|H_NFMT, M_ENTER_COMMENT, maxlines, name); for(curline=0; curline0) { msg_strcpy(strcpy_buf, M_EMPTY_COMMENT); /* Strip blank comments */ if(!far_strcmp(comment, (char FAR *)strcpy_buf)) comment[0]='\0'; far_strcpyn((char FAR *)hdr_comment, comment, COMMENT_MAX); calc_basic_hdr_size(); return(1); } else return(0); } /* Fills the basic archive header with needed information */ void fill_archive_header() { first_hdr_size=FIRST_HDR_SIZE_V; cur_time_stamp(&ftime_stamp); compsize=ts_native(&ftime_stamp, host_os); if(ts_valid(secondary_ftime)) compsize=ts_native(&secondary_ftime, host_os); file_type=ARJT_COMMENT; method=0; entry_pos=0; origsize=0L; file_crc=0L; fm_store(&file_mode, OS_DOS, 0); host_data=0; ext_flags=0; chapter_number=0; if(chapter_mode!=0) { if(total_chapters==0) chapter_number=total_chapters=1; else chapter_number=total_chapters; } else { if(total_chapters!=0) chapter_number=total_chapters; } arj_flags=0; if(multivolume_option) arj_flags|=VOLUME_FLAG; if(add_command&&lfn_supported!=LFN_NOT_SUPPORTED&&(lfn_mode==LFN_DUAL_EXT||lfn_mode==LFN_DUAL)) arj_flags|=DUAL_NAME_FLAG; if(add_command&&use_ansi_cp) arj_flags|=ANSICP_FLAG; arjprot_id=use_sfxstub?SFXSTUB_FLAG:0; password_modifier=(char)ts_native(&ftime_stamp, OS_SPECIAL); ext_hdr_flags=0; if(garble_enabled) { arj_flags|=GARBLED_FLAG; encryption_applied=1; ext_hdr_flags=ENCRYPT_STD; if(gost_cipher==GOST256) ext_hdr_flags=ENCRYPT_UNK; else if(gost_cipher==GOST40) ext_hdr_flags=ENCRYPT_GOST40; } hdr_filename=&header[first_hdr_size]; split_name(archive_name, NULL, hdr_filename); if(translate_path(hdr_filename)) arj_flags|=PATHSYM_FLAG; calc_comment_offset(); hdr_comment[0]='\0'; fill_general_hdr(); create_header(1); calc_basic_hdr_size(); } /* Final header pass: occurs at update of multivolume archives and those containing ARJ SECURITY. The operation variable specifies the action (one of FP_*) to be made. */ void final_header(int operation) { unsigned long tmp_resume_position; int tmp_multivolume; /* Indicates that the file is continued on the next volume */ int tmp_cont_prev; /* Indicates that the file is continued from the previous volume */ unsigned long cur_pos; int cur_ext_hdr_flags; int tmp_prot_blocks; tmp_prot_blocks=prot_blocks; tmp_resume_position=resume_position; tmp_cont_prev=continued_prevvolume; tmp_multivolume=mvfile_type; cur_ext_hdr_flags=ext_hdr_flags; cur_pos=ftell(aostream); fseek(aostream, main_hdr_offset, SEEK_SET); read_header(2, aostream, archive_name); fseek(aostream, main_hdr_offset, SEEK_SET); if(operation==FP_SECURITY&&is_registered) { origsize=secured_size; file_crc=arjsec_offset; arj_flags|=SECURED_FLAG; method=2; fm_store(&file_mode, OS_SPECIAL, SECURED_MODE); } else if(operation==FP_PROT) { arj_flags|=PROT_FLAG; prot_blocks=tmp_prot_blocks; /* ASR fix - the original (v 3.02) checks for ==0 only */ if(file_crc==0L||file_crc>arjsec_offset||(arjsec_offset-file_crc)>=CACHE_SIZE) file_crc=arjsec_offset; } else if(operation==FP_VOLUME) arj_flags&=~VOLUME_FLAG; else if(operation==FP_CHAPTER) chapter_number=max_chapter; else if(operation==FP_GARBLE) { arj_flags|=GARBLED_FLAG; ext_flags=(ext_flags&0xF0)|(cur_ext_hdr_flags&0x0F); } create_header(1); write_header(); fseek(aostream, cur_pos, SEEK_SET); prot_blocks=tmp_prot_blocks; resume_position=tmp_resume_position; continued_prevvolume=tmp_cont_prev; mvfile_type=tmp_multivolume; comment[0]='\0'; /* ASR fix - the original is somewhere else */ } #endif /* Skips over the compressed data in the input file */ void skip_compdata() { #if SFX_LEVEL>=ARJSFXV if(compsize!=0L) file_seek(aistream, compsize, SEEK_CUR); #else fseek(aistream, compsize, SEEK_CUR); #endif } /* Skips over the compressed data, prompting the user */ void skip_file() { #if SFX_LEVEL>=ARJSFXV msg_cprintf(H_HL|H_NFMT, M_SKIPPED, filename); #else msg_cprintf(H_HL|H_NFMT, M_SKIPPED, filename); #endif skip_compdata(); } /* Displays ARJ$DISP screen */ void arjdisp_scrn(unsigned long bytes) { char *arjdisp_name; #if SFX_LEVEL<=ARJSFX char cmd_buf[CCHMAXPATH]; #endif #if SFX_LEVEL>=ARJSFXV ctrlc_not_busy=0; arjdisp_name=arjdisp_ptr; if(arjdisp_name[0]=='\0') arjdisp_name=arjdisp_default; #else arjdisp_name=arjdisp_default; #endif if(strcmp_os(filename, arjdisp_name)) { #if SFX_LEVEL>=ARJSFXV msg_sprintf(misc_buf, M_ARJDISP_INVOCATION, arjdisp_name, archive_name, filename, uncompsize, bytes, compsize, cmd_verb); system_cmd(misc_buf); #else msg_sprintf(cmd_buf, M_ARJDISP_INVOCATION, arjdisp_name, archive_name, filename, uncompsize, bytes, compsize, cmd_verb); system_cmd(cmd_buf); #endif } #if SFX_LEVEL>=ARJSFXV ctrlc_not_busy=1; #endif } #if SFX_LEVEL>=ARJ /* Returns CRC-32 ofthe given file */ static unsigned long crc32_for_file(char *name) { FILE *stream; char *buffer; int block_size; crc32term=CRC_MASK; if((stream=file_open(name, m_rb))!=NULL) { buffer=malloc_msg(CACHE_SIZE); while((block_size=fread(buffer, 1, CACHE_SIZE, stream))!=0) crc32_for_block(buffer, block_size); free(buffer); fclose(stream); } return(crc32term^CRC_MASK); } /* Issues various actions on currently processed file in archive */ void special_processing(int action, FILE *stream) { int garble_task; struct timestamp gtime; char *pbuf; unsigned long cur_pos; int count; char *tmp_name; garble_task=0; /* Initally, no garble post-processing is considered. */ switch(action) { case CFA_UNMARK: msg_cprintf(H_HL|H_NFMT, M_UNMARKING, filename); if((int)chapter_number!=total_chapters) error(M_CHAPTER_ERROR, 1); chapter_number--; create_header(0); break; case CFA_MARK: msg_cprintf(H_HL|H_NFMT, M_MARKING, filename); if((int)chapter_number!=total_chapters) error(M_CHAPTER_ERROR, 1); ext_flags=(unsigned char)total_chapters; create_header(0); break; case CFA_MARK_INCREMENT: msg_cprintf(H_HL|H_NFMT, M_MARKING, filename); if((int)chapter_number+1!=total_chapters) error(M_CHAPTER_ERROR, 1); chapter_number=(unsigned char)total_chapters; create_header(0); total_files++; if(host_os==OS_WIN95||host_os==OS_WINNT) { total_longnames++; if(volume_flag_set) split_longnames++; } break; case CFA_REMPATH: msg_cprintf(H_HL|H_NFMT, M_REMOVING_PATH, filename); far_strcpyn(comment, (char FAR *)hdr_comment, COMMENT_MAX); tmp_name=malloc_str(hdr_filename); split_name(tmp_name, NULL, hdr_filename); free(tmp_name); entry_pos=0; arj_flags&=~PATHSYM_FLAG; calc_comment_offset(); far_strcpyn((char FAR *)hdr_comment, comment, COMMENT_MAX); if(dual_name) { tmp_name=malloc_str(hdr_comment); split_name(tmp_name, NULL, hdr_comment); free(tmp_name); } create_header(0); calc_basic_hdr_size(); total_files++; break; case CFA_MARK_EXT: msg_cprintf(H_HL|H_NFMT, M_MARKING, filename); if(ext_flags==0) ext_flags=(unsigned char)total_chapters; if(chapter_number==0) chapter_number=(unsigned char)total_chapters; create_header(0); total_files++; break; case CFA_UNMARK_EXT: msg_cprintf(H_HL|H_NFMT, M_UNMARKING, filename); ext_flags=0; chapter_number=0; create_header(0); total_files++; break; case CFA_GARBLE: if(!(arj_flags&GARBLED_FLAG)) { msg_cprintf(H_HL|H_NFMT, M_GARBLING, filename); arj_flags|=GARBLED_FLAG; cur_time_stamp(>ime); password_modifier=ts_native(>ime, OS); garble_task=1; create_header(0); total_files++; } break; case CFA_UNGARBLE: if(arj_flags&GARBLED_FLAG) { msg_cprintf(H_HL|H_NFMT, M_UNGARBLING, filename); arj_flags&=~GARBLED_FLAG; garble_task=2; create_header(0); total_files++; } break; } if(arj_flags&GARBLED_FLAG) encryption_id=ENCID_GARBLE; write_header(); if(garble_task) garble_init(password_modifier); pbuf=(char *)malloc_msg(PROC_BLOCK_SIZE); cur_pos=ftell(stream); count=min(CACHE_SIZE-(cur_pos%CACHE_SIZE), compsize); while(compsize>0L) { if(fread(pbuf, 1, count, stream)!=count) error(M_CANTREAD); if(garble_task==1) garble_encode_stub(pbuf, count); else if(garble_task==2) garble_decode_stub(pbuf, count); if(!no_file_activity) file_write(pbuf, 1, count, aostream); compsize-=(unsigned long)count; count=min(PROC_BLOCK_SIZE, compsize); } free(pbuf); } /* Prints an "Adding..." message */ static void addition_msg(int is_update, int is_replace, char *filespec) { /* -hdx will turn off these messages */ if(!debug_enabled||strchr(debug_opt, 'x')==NULL) { if(is_update) msg_cprintf(H_HL, M_UPDATING); else if(is_replace) msg_cprintf(H_HL, M_REPLACING); else msg_cprintf(H_HL, M_ADDING); if(verbose_display==VERBOSE_STD) { if(file_type==ARJT_BINARY) msg_cprintf(0, M_BINARY_FILE); else if(file_type==ARJT_TEXT) msg_cprintf(0, M_TEXT_FILE); else if(file_type==ARJT_DIR) msg_cprintf(0, M_DIRECTORY); else if(file_type==ARJT_UXSPECIAL) msg_cprintf(0, M_UXSPECIAL_FILE); } if(continued_prevvolume&&eh_find_pending(eh)==NULL) msg_cprintf(H_HL|H_NFMT, M_AT_POSITION, format_filename(filespec), resume_position); else msg_cprintf(0, (FMSG *)strform, format_filename(filespec)); if(!verbose_display) msg_cprintf(0, (FMSG *)vd_space); else { nputlf(); if(method==0) msg_cprintf(0, M_STORING); else msg_cprintf(H_HL|H_NFMT, M_COMPRESSING, method); msg_cprintf(H_HL|H_NFMT, M_N_BYTES, uncompsize); } } } /* Initializes global variables and performs general set-up before packing a file. */ void init_packing(unsigned long offset, int is_mv) { unpackable=0; volume_flag_set=0; ext_voldata=0; compsize=origsize=0L; if(garble_enabled) garble_init(password_modifier); crc32term=CRC_MASK; if(file_type==ARJT_BINARY||file_type==ARJT_TEXT) { if(!is_mv||resume_position>0) smart_seek(resume_position, encstream); } if(!is_mv&!no_file_activity) fseek(aostream, offset, SEEK_SET); } /* Stores or compresses a single file */ static void pack_file_proc(unsigned long offset) { if(method==1||method==2||method==3) encode_stub(method); else if(method==4) encode_f_stub(); else if(method==9) hollow_encode(); if(unpackable) /* Fall back to method #0 */ { if(verbose_display==VERBOSE_STD) { msg_cprintf(0, (FMSG *)" \r"); msg_cprintf(0, M_STORING); msg_cprintf(H_HL|H_NFMT, M_N_BYTES, uncompsize); } method=0; init_packing(offset, 0); } if(method==0) store(); display_indicator(uncompsize); } /* Opens the file for encoding */ static int open_input_file() { int e; /* Error indicator */ if((encstream=file_open(filename, read_perms[file_type%2]))!=NULL) return(0); error_report(); msg_cprintf(H_ERR, M_CANTOPEN, filename); nputlf(); e=1; if(no_inarch) { if((ignore_open_errors==IAE_ACCESS&&errno==EACCES)|| (ignore_open_errors==IAE_NOTFOUND&&errno==ENOENT)|| (ignore_open_errors==IAE_ALL&&(errno==EACCES||errno==ENOENT))) e=0; } if(e) errors++; write_index_entry(idxid_fault); return(1); } /* Packs a single file, involving all neccessary checks. Returns 1 if it got packed, 0 if not, -1 in case of an error. */ int pack_file(int is_update, int is_replace) { struct timestamp ftime, atime, ctime, cur_time; unsigned long fsize; int volume_file; /* 1 if file spans across volumes */ int needs_skip; /* 1 if the file needs to be skipped */ int err_id; ATTRIB attrib; int fb; unsigned int total_chars, nd_chars; int textf=0; /* 1 if the file seems to be text */ int fetch_size; unsigned long cur_pos=0; /* Current position in output file */ int lfn; unsigned long data_pos=0; unsigned long st_ticks=0; /* Start time (used for profiling) */ unsigned int bck_method; int ratio; char timetext[20]; char FAR *raw_eh; struct mempack mempack; int lfn_xlated; char ea_res[FILENAME_MAX]; int res_len=0; char FAR *ea_blk; struct ext_hdr FAR *p_eh; if(is_replace&&new_files_only) return(0); if(!match_attrib(&properties)) { error(M_SELECTION_ERROR); return(-1); } ts_store(&ftime, OS, properties.ftime); ts_store(&atime, OS, properties.atime); ts_store(&ctime, OS, properties.ctime); if(is_update&&!skip_ts_check) { fsize=properties.fsize; volume_file=arj_flags&VOLUME_FLAG||arj_flags&EXTFILE_FLAG; needs_skip=0; if(update_criteria==UC_NEW_OR_CRC||freshen_criteria==FC_CRC) { if(!volume_file&&fsize==origsize) { if(crc32_for_file(filename)==file_crc) needs_skip=1; } } else if(update_criteria==UC_NEW_OR_DIFFERENT||freshen_criteria==FC_DIFFERENT) { if(!volume_file&&!ts_cmp(&ftime_stamp, &ftime)&&fsize==origsize) needs_skip=1; } else if(update_criteria==UC_NEW_OR_OLDER||freshen_criteria==FC_OLDER) { if(ts_cmp(&ftime, &ftime_stamp)>=0) needs_skip=1; } else if(update_criteria==UC_NEW_OR_NEWER||freshen_criteria==FC_EXISTING) { if(ts_cmp(&ftime, &ftime_stamp)<=0) needs_skip=1; } if(needs_skip) { if(verbose_display) { msg_cprintf(H_HL|H_NFMT, M_NO_CHANGE, format_filename(filename)); } special_processing((total_chapters!=0)?CFA_MARK_INCREMENT:CFA_NONE, aistream); return(1); } } if(query_for_each_file) { msg_sprintf(misc_buf, is_update?M_QUERY_UPDATE:M_QUERY_ADD, filename); if(!query_action(REPLY_YES, QUERY_ARCH_OP, (char FAR *)misc_buf)) return(0); } if(is_replace) { if(total_chapters>0) special_processing(CFA_NONE, aistream); else skip_compdata(); if(multivolume_option) { total_files++; return(2); } } else { file_type=ARJT_BINARY; first_hdr_size=continued_prevvolume?FIRST_HDR_SIZE_V:STD_HDR_SIZE; if(lfn_supported!=LFN_NOT_SUPPORTED&&!skip_time_attrs) first_hdr_size=R9_HDR_SIZE; hdr_filename=&header[first_hdr_size]; hdr_filename[0]='\0'; calc_comment_offset(); hdr_comment[0]='\0'; } method=custom_method?method_specifier:1; uncompsize=properties.fsize; attrib=properties.attrib; if(clear_archive_bit) attrib&=~FATTR_RDONLY; garble_ftime=ts_native(&ftime, OS); if(type_override) { file_type=primary_file_type; if(*swptr_t!='\0') if(search_for_extension(filename, swptr_t)) file_type=secondary_file_type; } if(continued_prevvolume&&mvfile_type>=0) file_type=mvfile_type; if(!is_filename_valid(filename)) error(M_CANTOPEN, filename); if(properties.type==ARJT_DIR) file_type=ARJT_DIR; else if(properties.type==ARJT_UXSPECIAL) file_type=ARJT_UXSPECIAL; volume_flag_set=0; user_wants_fail=0; err_id=0; if(hollow_mode!=HM_NO_CRC) { if(file_type==ARJT_DIR||file_type==ARJT_UXSPECIAL) method=0; else if(file_type==ARJT_BINARY||file_type==ARJT_TEXT) { if(open_input_file()) return(0); current_bufsiz=jh_enabled?user_bufsiz:BUFSIZ_DEFAULT; if(file_type==ARJT_TEXT) { nd_chars=0; textf=1; fetch_size=CACHE_SIZE; total_chars=0; while((fb=fgetc(encstream))!=EOF) { if(fbTEXT_UCHAR) nd_chars++; total_chars++; if(total_chars>=fetch_size) break; } if(total_chars>0) rewind(encstream); /* Select files that meet size requirements... */ if(type_override=(unsigned long)MIN_TEXT_SIZE&& total_chars0L) uncompsize-=resume_position; } } if(store_by_suffix) if(search_for_extension(filename, archive_suffixes)) method=0; if(properties.fsize==0L) method=0; if(hollow_mode==HM_CRC) method=9; else if(hollow_mode==HM_NO_CRC) method=8; if(!no_file_activity) cur_pos=ftell(aostream); cur_time_stamp(&cur_time); password_modifier=(char)ts_native(&cur_time, OS); arj_flags=0; far_strcpyn(comment, (char FAR *)hdr_comment, COMMENT_MAX); if(continued_prevvolume&&first_hdr_size=MIN_TEXT_SIZE&&origsize*5L0) { if(!no_file_activity) file_chsize(aostream, cur_pos); msg_cprintf(H_HL, M_FSTAT_1); comment_entries++; origsize=0L; resume_position=0L; continued_prevvolume=0; return(1); } write_header(); if(!no_file_activity) fseek(aostream, data_pos, SEEK_SET); if(volume_flag_set) { resume_position+=origsize; continued_prevvolume=1; mvfile_type=file_type; } else { resume_position=0L; continued_prevvolume=0; } total_uncompressed+=origsize; total_compressed+=compsize; ratio=calc_percentage(compsize, origsize); if(!debug_enabled||strchr(debug_opt, 'x')==NULL) { msg_cprintf(H_HL, M_FSTAT_2, ratio/10, ratio%10); #if defined(HAVE_EAS) if(ea_supported&&!volume_flag_set&&ea_size!=0) msg_cprintf(H_HL, M_EA_STATS_STG, ea_size); #endif if(file_type==ARJT_UXSPECIAL&&eh_lookup(eh, UXSPECIAL_ID)!=NULL) { raw_eh=eh_lookup(eh, UXSPECIAL_ID)->raw; uxspecial_stats(raw_eh, UXSTATS_SHORT); } msg_cprintf(0, lf); } if(err_id==0&&user_wants_fail) { errors++; error_report(); write_index_entry(idxid_fault); } if(create_index) { if(detailed_index) { timestamp_to_str(timetext, &ftime_stamp); if(msg_fprintf(idxstream, M_IDX_FIELD, timetext, origsize, compsize, ratio/1000, ratio%1000, filename)<0) error(M_DISK_FULL); } else { if(msg_fprintf(idxstream, M_FILENAME_FORM, filename)<0) error(M_DISK_FULL); } } total_files++; if(host_os==OS_WIN95||host_os==OS_WINNT) total_longnames++; if(eh!=NULL) proc_ext_hdr(EHUF_COMMIT); return(1); } /* Packs a file, with statistics update */ int pack_file_stub(int is_update, int is_replace) { int rc; rc=pack_file(is_update, is_replace); if(rc==1) total_written+=origsize; else { total_size-=origsize; if(rc==-1) rc=0; } return(rc); } /* Inserts a chapter mark into the archive */ int create_chapter_mark() { if(multivolume_option&&get_volfree(MULTIVOLUME_INCREMENT)=ARJ_NEWCRYPT_VERSION&&ext_hdr_flags==0&&enc_type!=ENCRYPT_OLD) { encryption_id=ENCID_GARBLE; ext_hdr_flags=enc_type; } while(read_header(0, arc, name)) { msg_cprintf(H_HL, M_ADDING); msg_cprintf(H_HL|H_NFMT, M_FILENAME_FORM, filename); write_index_entry(nullstr); special_processing(CFA_NONE, arc); rc++; } cfa_store(i, FLFLAG_PROCESSED); } fclose(arc); } return(rc); } #endif /* Inserts base directory into filespec */ void add_base_dir(char *name) { #if SFX_LEVEL>=ARJ char *tmp; #else char tmp[FILENAME_MAX]; #endif if(target_dir[0]!='\0') { #if SFX_LEVEL>=ARJ tmp=malloc_str(name); strcpy(name, target_dir); strcat(name, tmp); free(tmp); #else strcpy(tmp, name); strcpy(name, target_dir); strcat(name, tmp); #endif } } /* Checks if the file can be unpacked */ static int test_unpack_condition(char *name) { int answer; /* Reply to overwrite/append queries */ int fr; struct timestamp ftime; unsigned long fsize; int volume_file; unsigned long append_pos; #if SFX_LEVEL>=ARJSFXV char *fname; /* Formatted name */ char arc_time[22], disk_time[22]; struct file_properties properties; #endif #if SFX_LEVEL>=ARJSFXV fname=format_filename(name); #endif if(!file_exists(name)) { #if SFX_LEVEL>=ARJSFXV if(freshen_criteria!=FC_NONE||continued_prevvolume) { #if SFX_LEVEL>=ARJ if(continued_prevvolume&&start_at_ext_pos&&ext_pos!=0L) { answer=yes_on_all_queries||skip_append_query; if(answer==0) { msg_cprintf(H_HL|H_NFMT, M_NOT_EXISTS, fname); answer=query_action(REPLY_YES, QUERY_APPEND, M_QUERY_CONTINUE); if(answer==1) { resume_position=0L; continued_prevvolume=0; create_subdir_tree(name, yes_on_all_queries, file_type); return(0); } } } #endif msg_cprintf(H_HL|H_NFMT, M_NOT_EXISTS, fname); return(1); } create_subdir_tree(name, yes_on_all_queries, file_type); return(0); #else if(freshen_criteria!=FC_NONE) { msg_cprintf(H_HL|H_NFMT, M_NOT_EXISTS, name); return(1); } else { create_subdir_tree(name, file_type); return(0); } #endif } #if SFX_LEVEL>=ARJSFXV fr=file_find(name, &properties); if(fr||(properties.type!=ARJT_DIR&& properties.type!=ARJT_BINARY&& properties.type!=ARJT_UXSPECIAL)) { msg_cprintf(H_ERR, M_CANTOPEN, name); msg_cprintf(0, (FMSG *)", "); return(2); } #endif if(new_files_only) { #if SFX_LEVEL>=ARJSFXV msg_cprintf(H_HL|H_NFMT, M_EXISTS, name); #else msg_cprintf(H_HL|H_NFMT, M_EXISTS, name); #endif return(1); } #if SFX_LEVEL>=ARJSFXV ts_store(&ftime, OS, properties.ftime); #else ts_store(&ftime, OS, file_getftime(name)); #endif if(!skip_ts_check) { #if SFX_LEVEL>=ARJ fsize=properties.fsize; volume_file=0; if(arj_flags&VOLUME_FLAG||arj_flags&EXTFILE_FLAG) { fsize=origsize; volume_file=1; } if(update_criteria==UC_NEW_OR_CRC||freshen_criteria==FC_CRC) { if(!volume_file&&fsize==origsize) { if(crc32_for_file(filename)==file_crc) { msg_cprintf(H_HL|H_NFMT, M_IS_SAME, fname); return(1); } } } else if(update_criteria==UC_NEW_OR_DIFFERENT||freshen_criteria==FC_DIFFERENT) { if(!ts_cmp(&ftime_stamp, &ftime)&&fsize==origsize) { msg_cprintf(H_HL|H_NFMT, M_IS_SAME, fname); return(1); } } else if(update_criteria==UC_NEW_OR_OLDER||freshen_criteria==FC_OLDER) { if(ts_cmp(&ftime, &ftime_stamp)<=0) { msg_cprintf(H_HL|H_NFMT, M_IS_SAME_OR_OLDER, fname); return(1); } } else if(update_criteria==UC_NEW_OR_NEWER||freshen_criteria==FC_EXISTING) { if(ts_cmp(&ftime, &ftime_stamp)>=0) { msg_cprintf(H_HL|H_NFMT, M_IS_SAME_OR_NEWER, fname); return(1); } } #else if(update_criteria!=UC_NONE&&freshen_criteria!=FC_NONE) { if(ts_cmp(&ftime, &ftime_stamp)>=0) { #if SFX_LEVEL>=ARJSFXV msg_cprintf(H_HL|H_NFMT, M_IS_SAME_OR_NEWER, fname); #else msg_cprintf(H_HL|H_NFMT, M_IS_SAME_OR_NEWER, name); #endif return(1); } } #endif } #if SFX_LEVEL>=ARJSFXV if(yes_on_all_queries&&!skip_ts_check&&continued_prevvolume&& (file_type==ARJT_TEXT||file_type==ARJT_BINARY)&&!ts_cmp(&ftime_stamp, &ftime)&& eh_find_pending(eh)!=NULL) { msg_cprintf(H_HL|H_NFMT, M_IS_NOT_SAME_DATE, fname); return(2); } #endif #if SFX_LEVEL>=ARJ if(serialize_exts!=EXT_NO_SERIALIZE) return(find_num_ext(name, serialize_exts)?2:0); if(arcmail_sw) return(find_arcmail_name(name)?2:0); #endif #if SFX_LEVEL>=ARJSFXV if(yes_on_all_queries) return(0); #else if(yes_on_all_queries||overwrite_existing) return(0); #endif /* Multivolume preprocessing */ #if SFX_LEVEL>=ARJSFXV #if SFX_LEVEL>=ARJ if(continued_prevvolume||start_at_ext_pos) #else if(continued_prevvolume) #endif { if(skip_append_query||(file_type!=ARJT_BINARY&&file_type!=ARJT_TEXT)) return(0); msg_cprintf(0, (!ts_cmp(&ftime_stamp, &ftime))?M_EXISTS:M_IS_NOT_SAME_DATE, fname); #if SFX_LEVEL>=ARJ append_pos=start_at_ext_pos?ext_pos:resume_position; #else append_pos=resume_position; #endif msg_sprintf(misc_buf, M_QUERY_APPEND, append_pos); return(query_action(REPLY_YES, QUERY_APPEND, (FMSG *)misc_buf)?0:-1); } #endif #if SFX_LEVEL>=ARJSFXV if(overwrite_existing /* ASR fix 31/03/2003: for new recursion order, skip directory overwrite prompt unless the user has specified "-2r". */ #if SFX_LEVEL>=ARJ ||(properties.type==ARJT_DIR&&!recursion_order) #endif ) return(0); timestamp_to_str(arc_time, &ftime_stamp); timestamp_to_str(disk_time, &ftime); msg_cprintf(H_HL|H_NFMT, M_ARJ_VS_DISK, origsize, arc_time+2, properties.fsize, disk_time+2); msg_cprintf(0, (ts_cmp(&ftime, &ftime_stamp)>=0)?M_IS_SAME_OR_NEWER:M_EXISTS, fname); return(query_action(REPLY_YES, QUERY_OVERWRITE, M_QUERY_OVERWRITE)?0:-1); #else msg_cprintf(0, (ts_cmp(&ftime_stamp, &ftime)>0)?M_EXISTS:M_IS_SAME_OR_NEWER, name); msg_cprintf(0, M_QUERY_OVERWRITE); return(query_action()?0:-1); #endif } #if SFX_LEVEL>=ARJSFXV /* Queries the user about renaming the file and performs neccessary checks */ static int query_for_rename(char *name) { if(!query_action(REPLY_YES, QUERY_EXTRACT_RENAME, M_QUERY_EXTRACT_RENAME)) { skip_file(); errors++; return(0); } if(kbd_cleanup_on_input) fetch_keystrokes(); msg_cprintf(0, M_ENTER_NEW_FILENAME); if(read_line(name, FILENAME_MAX)==0) { skip_file(); errors++; return(0); } #if SFX_LEVEL>=ARJ if(translate_unix_paths) unix_path_to_dos(name); #endif case_path(name); if(test_unpack_condition(name)) { skip_file(); errors++; return(0); } else return(1); } #endif /* Checks if the OS and current conditions allow unpacking */ #if SFX_LEVEL>=ARJ static int test_unpack_env(int disk_touched) #else static int test_unpack_env() #endif { /* The text below is NOT a typo, this check is really used in ARJSFXV (since headers may be damaged, and so on...) */ #if SFX_LEVEL>=ARJSFXV if(arj_x_nbr>EXTR_LEVEL) { msg_cprintf(H_HL|H_NFMT, M_UNKNOWN_VERSION, (int)arj_x_nbr); skip_file(); return(-1); } #endif if(file_garbled&&!garble_enabled) { #if SFX_LEVEL>=ARJSFXV msg_cprintf(0, M_FILE_IS_GARBLED); #else msg_cprintf(0, M_FILE_IS_GARBLED); #endif skip_file(); return(-1); } #if SFX_LEVEL>=ARJSFXV #if SFX_LEVEL>=ARJ if((method>MAXMETHOD&&method<8)||(method==MAXMETHOD&&arj_nbr==1)) #else if(method>3) #endif { /* ARJ 0.xx -m4 is not supported */ msg_cprintf(H_HL|H_NFMT, M_UNKNOWN_METHOD, (int)method); skip_file(); return(-1); } #if SFX_LEVEL>=ARJ if(file_type!=ARJT_BINARY&&file_type!=ARJT_TEXT&&file_type!=ARJT_DIR&& file_type!=ARJT_COMMENT&&file_type!=ARJT_LABEL&&file_type!=ARJT_CHAPTER&& file_type!=ARJT_UXSPECIAL) #else if(file_type!=ARJT_BINARY&&file_type!=ARJT_TEXT&&file_type!=ARJT_DIR&& file_type!=ARJT_LABEL&&file_type!=ARJT_UXSPECIAL) #endif { msg_cprintf(H_HL|H_NFMT, M_UNKNOWN_FILE_TYPE, file_type); skip_file(); return(-1); } #endif /* Check for ability to extract Windows 95 LFNs */ #if TARGET==DOS #if SFX_LEVEL>=ARJ if(disk_touched&&(host_os==OS_WIN95||host_os==OS_WINNT)) { if(lfn_supported==LFN_NOT_SUPPORTED&&lfn_mode<=LFN_NONE) { msg_cprintf(0, M_REQUIRES_WIN95); skip_file(); return(-1); } } #else if(host_os==OS_WIN95&&lfn_supported==LFN_NOT_SUPPORTED&&!process_lfn_archive) { #if SFX_LEVEL>=ARJSFXV msg_cprintf(0, M_REQUIRES_WIN95); #else msg_cprintf(0, M_REQUIRES_WIN95); #endif skip_file(); return(-1); } #endif #endif return(0); } /* Unpacks a single file (NOT the main extraction routine; see below) */ static void unpack_file(int action) { unsigned long st_ticks=0; #if SFX_LEVEL>=ARJSFXV uncompsize=origsize; #endif /* Verbose display option is missing from ARJSFXV but is supported by ARJSFX */ #if SFX_LEVEL==ARJSFX if(verbose_display) msg_cprintf(H_HL|H_NFMT, M_N_BYTES, origsize); #endif crc32term=CRC_MASK; #if SFX_LEVEL>=ARJSFXV if(debug_enabled&&strchr(debug_opt, 't')!=NULL) st_ticks=get_ticks(); #endif #if SFX_LEVEL>=ARJSFXV if(file_type==ARJT_BINARY||file_type==ARJT_TEXT) #else if(file_type!=ARJT_DIR&&file_type!=ARJT_UXSPECIAL) #endif { #if SFX_LEVEL>=ARJ if(hollow_mode==HM_CRC||method==9) hollow_decode(action); else if(method!=8&&test_archive_crc!=TC_ATTRIBUTES) { if(method==0) unstore(action); else if(method>=1&&method<=3) decode(action); else if(method==4) decode_f(action); } #else #if SFX_LEVEL<=ARJSFX garble_init(password_modifier); uncompsize=origsize; #endif if(method==0) unstore(action); else decode(action); #endif } display_indicator(uncompsize); #if SFX_LEVEL>=ARJSFXV skip_compdata(); #endif #if SFX_LEVEL>=ARJSFXV if(debug_enabled) { #if SFX_LEVEL>=ARJ if(strchr(debug_opt, 'k')!=NULL) compsize=0L; #endif if(strchr(debug_opt, 't')!=NULL) msg_cprintf(H_HL|H_NFMT, M_N_TICKS, st_ticks=get_ticks()-st_ticks); } #endif #if SFX_LEVEL<=ARJSFX if((crc32term^CRC_MASK)==file_crc) msg_cprintf(0, M_OK); else { msg_cprintf(H_ALERT, M_CRC_ERROR); errors++; } #endif } /* Test/search routine */ #if SFX_LEVEL>=ARJ int unpack_validation(int cmd) #else int unpack_validation() #endif { int action; #if SFX_LEVEL>=ARJSFXV int found; /* 1 if the file is present */ int errflag; int nf_error; /* Non-fatal error */ int pattern; /* Current search pattern */ #endif #if SFX_LEVEL>=ARJ struct file_properties properties; #endif #if SFX_LEVEL>=ARJ found=1; errflag=nf_error=0; pattern_found=0; identical_filedata=1; if(test_unpack_env(0)) return(0); #else if(test_unpack_env()) return(0); #endif #if SFX_LEVEL>=ARJ if(cmd==ARJ_CMD_WHERE) { action=BOP_SEARCH; msg_sprintf(misc_buf, M_SEARCHING, filename); if(search_mode==SEARCH_DEFAULT||search_mode==SEARCH_SHOW_NAMES) alltrim(misc_buf); if(search_mode<=SEARCH_BRIEF) { msg_cprintf(0, (FMSG *)strform, misc_buf); if(search_mode==SEARCH_DEFAULT) msg_cprintf(0, (FMSG *)lf); if(search_mode==SEARCH_BRIEF) msg_cprintf(0, (FMSG *)cr); } for(pattern=0; pattern=TC_CRC_AND_CONTENTS) { if(test_archive_crc==TC_CRC_AND_CONTENTS||total_chapters==0||((unsigned int)ext_flags<=total_chapters&&(unsigned int)chapter_number>=total_chapters)) { if(test_archive_crc!=TC_ADDED_FILES||flist_is_in_archive(&flist_main, filename)) { if(test_archive_crc!=TC_ADDED_FILES||total_chapters==0||(unsigned int)chapter_number==total_chapters) { if(method==8||test_archive_crc==TC_ATTRIBUTES) { action=BOP_COMPARE; if(file_find(filename, &properties)) found=0; } else { if(file_type==ARJT_BINARY||file_type==ARJT_TEXT) { action=BOP_COMPARE; if((tstream=file_open(filename, read_perms[file_type%2]))==NULL) { action=BOP_NONE; found=0; errflag=1; if((ignore_open_errors==IAE_ACCESS&&errno==EACCES)|| (ignore_open_errors==IAE_NOTFOUND&&errno==ENOENT)|| (ignore_open_errors==IAE_ALL&&(errno==EACCES||errno==ENOENT))) errflag=0; } else smart_seek(resume_position, tstream); } else if(file_type==ARJT_DIR) { if(!is_directory(filename)) { errflag=1; found=0; } } } } } } } } #else action=BOP_NONE; #if SFX_LEVEL>=ARJSFXV msg_cprintf(H_HL|H_NFMT, M_TESTING, format_filename(filename)); msg_cprintf(0, (FMSG *)vd_space); #else msg_cprintf(H_HL|H_NFMT, M_TESTING, filename); #endif #endif atstream=NULL; #if SFX_LEVEL>=ARJSFXV if(file_garbled) garble_init(password_modifier); #endif unpack_file(action); #if SFX_LEVEL>=ARJ if(!found) { msg_cprintf(0, M_NOT_FOUND); if(errflag) { if(errorlevel==ARJ_ERL_SUCCESS) errorlevel=ARJ_ERL_CRC_ERROR; errors++; } nf_error=1; } if(action==BOP_COMPARE&&(method==8||test_archive_crc==TC_ATTRIBUTES)) { compsize=0L; crc32term=file_crc^CRC_MASK; if(ts_native(&ftime_stamp, OS)==properties.ftime&&origsize==properties.fsize) msg_cprintf(0, M_MATCHED); else { if(verbose_display) { if(ts_native(&ftime_stamp, OS)!=properties.ftime) msg_cprintf(0, M_BY_DATE); if(origsize!=properties.fsize) msg_cprintf(0, M_BY_SIZE); } msg_cprintf(0, M_NOT_MATCHED); if(errorlevel==ARJ_ERL_SUCCESS) errorlevel=ARJ_ERL_CRC_ERROR; errors++; nf_error=1; } } else if(action==BOP_COMPARE) { if(verbose_display) { file_find(filename, &properties); if(ts_native(&ftime_stamp, OS)!=properties.ftime) msg_cprintf(0, M_BY_DATE); if(origsize!=properties.fsize) msg_cprintf(0, M_BY_SIZE); } if(identical_filedata&&!volume_flag_set&&fgetc(tstream)==EOF) msg_cprintf(0, M_MATCHED); else if(identical_filedata&&volume_flag_set) msg_cprintf(0, M_MATCHED); else { if(verbose_display) msg_cprintf(0, M_BY_DATA); msg_cprintf(0, M_NOT_MATCHED); if(errorlevel==ARJ_ERL_SUCCESS) errorlevel=ARJ_ERL_CRC_ERROR; errors++; nf_error=1; } fclose(tstream); } #endif #if SFX_LEVEL>=ARJSFXV if(file_crc==(crc32term^CRC_MASK)&&compsize==0L) { #if SFX_LEVEL>=ARJ if(cmd!=ARJ_CMD_WHERE) msg_cprintf(0, M_OK); #else msg_cprintf(0, M_OK); #endif } else { msg_cprintf(H_ALERT, M_CRC_ERROR); if(errorlevel==ARJ_ERL_SUCCESS) errorlevel=ARJ_ERL_CRC_ERROR; errors++; #if SFX_LEVEL>=ARJ nf_error=1; #endif } #endif #if SFX_LEVEL>=ARJ if(cmd==ARJ_CMD_WHERE) { for(pattern=0; pattern0) { nf_error=1; msg_cprintf(H_OPER, M_FOUND_N_OCCURENCES, search_occurences[pattern], search_str[pattern]); } } } if(nf_error) write_index_entry(idxid_fault); return(((pattern_found&&extm_mode==EXTM_MATCHING)||(!pattern_found&&extm_mode==EXTM_MISMATCHING))?2:1); #endif #if SFX_LEVEL<=ARJSFXV return(1); #endif } #if SFX_LEVEL>=ARJ /* Checks filename upon extraction */ static int extract_fn_proc() { char tmp_name[FILENAME_MAX], efn[FILENAME_MAX]; int entry; skip_compdata(); strcpy(tmp_name, filename); entry=entry_pos; if(subdir_extraction) { strcpy(efn, target_dir); default_case_path(efn+strlen(efn), tmp_name+(exclude_paths?left_trim:0)); } else { strcpy(efn, target_dir); strcat(efn, tmp_name+entry); } if(!file_exists(efn)) { msg_cprintf(H_HL|H_NFMT, M_SKIPPED, efn); errors++; write_index_entry(idxid_fault); return(0); } if(show_filenames_only||!strcmp_os(filename, efn)) msg_cprintf(H_HL|H_NFMT, M_RESTORING_PROPERTIES, efn); else { msg_cprintf(H_HL|H_NFMT, M_RESTORING_PROPERTIES, format_filename(filename)); msg_cprintf(H_HL|H_NFMT, M_TO, format_filename(efn)); } if(!test_host_os((int)host_os)&&file_type==ARJT_BINARY) msg_cprintf(0, M_FOREIGN_BINARY); nputlf(); if(test_host_os((int)host_os)&&(hollow_mode==HM_RESTORE_ATTRS||hollow_mode==HM_RESTORE_ALL)) dos_chmod(efn, file_mode.native); if(hollow_mode==HM_RESTORE_DATES||hollow_mode==HM_RESTORE_ALL) { file_setftime(efn, ts_native(&ftime_stamp, OS)); if(lfn_supported!=LFN_NOT_SUPPORTED&&ts_valid(atime_stamp)) { file_setctime(efn, ts_native(&ctime_stamp, OS)); file_setatime(efn, ts_native(&atime_stamp, OS)); } } return(1); } #endif #if SFX_LEVEL>=ARJSFXV /* Allocates memory for and unpacks extended attributes */ char FAR *unpack_ea(struct ext_hdr FAR *eh) { char FAR *raw_eh; struct mempack mempack; unsigned char p_modifier; char FAR *ea_blk; p_modifier=password_modifier; password_modifier=ea_pwd_modifier; ea_blk=eh->raw; mempack.origsize=(unsigned int)((unsigned char)ea_blk[2])*256U+(unsigned char)ea_blk[1]; raw_eh=(char FAR *)farmalloc_msg(mempack.origsize); mempack.compsize=eh->size-3; mempack.method=ea_blk[0]; mempack.comp=ea_blk+3; mempack.orig=raw_eh; unpack_mem(&mempack); password_modifier=p_modifier; return(raw_eh); } #endif /* Unpacks a single file */ #if SFX_LEVEL>=ARJ int unpack_file_proc(int to_console, FILE_COUNT num) #else int unpack_file_proc() #endif { #if SFX_LEVEL>=ARJSFXV int action; /* Passed to the decoding routines */ int disk_touched; /* Indicates if the output is directed to a file, not to console */ char *fname; /* Formatted filename */ unsigned long tmp_compsize; unsigned long cur_pos; unsigned long alloc_size; /* Size of file rounded up to the next allocation unit boundary */ struct ext_hdr FAR *p_eh; int uxspec_rc; #endif char tmp_name[FILENAME_MAX]; char FAR *raw_eh; #if SFX_LEVEL>=ARJSFXV char out_name[FILENAME_MAX]; int tmp_entry, out_entry; char subdir[8]; int dir_num; int trim; unsigned long tmp_crc; #endif #if SFX_LEVEL>=ARJ action=BOP_NONE; #endif #if SFX_LEVEL>=ARJSFXV if(!handle_labels&&file_type==ARJT_LABEL) { skip_compdata(); return(0); } #endif #if SFX_LEVEL>=ARJ disk_touched=!to_console; if(!debug_enabled||strchr(debug_opt, 'x')==NULL) { if(hollow_mode>HM_NO_CRC) return(extract_fn_proc()); if(method==8||method==9||test_unpack_env(disk_touched)) { errors++; write_index_entry(idxid_fault); return(0); } } #else if(test_unpack_env()) { #if SFX_LEVEL>=ARJSFXV errors++; #endif return(0); } #endif #if SFX_LEVEL>=ARJ if(file_type==ARJT_CHAPTER) { fname=format_filename(filename); msg_cprintf(H_HL|H_NFMT, M_EXTRACTING, fname); msg_cprintf(0, (FMSG *)vd_space); msg_cprintf(0, M_OK); } else { #endif #if SFX_LEVEL>=ARJ if(extm_mode!=EXTM_NONE) { tmp_compsize=compsize; cur_pos=ftell(aistream); if(unpack_validation(ARJ_CMD_WHERE)!=2) return(0); fseek(aistream, cur_pos, SEEK_SET); compsize=tmp_compsize; } #endif #if SFX_LEVEL>=ARJSFXV if(chk_free_space) { alloc_size=((origsize+(unsigned long)alloc_unit_size-1L)/(unsigned long)alloc_unit_size)*(unsigned long)alloc_unit_size; if(file_getfree(target_dir)=ARJ msg_cprintf(0, M_NOT_ENOUGH_SPACE); #else msg_sprintf(misc_buf, M_NOT_ENOUGH_SPACE, filename); if(!query_action(REPLY_YES, QUERY_CRITICAL, (FMSG *)misc_buf)) exit(ARJSFX_ERL_ERROR); #endif skip_file(); errors++; #if SFX_LEVEL>=ARJ write_index_entry(idxid_fault); #endif return(0); } } #endif #if SFX_LEVEL>=ARJSFXV #if SFX_LEVEL>=ARJ if(execute_cmd&&file_type!=ARJT_BINARY&&file_type!=ARJT_TEXT) return(0); strcpy(tmp_name, filename); tmp_entry=entry_pos; if(to_console) { if(comment_display==CMTD_PCMD) action=BOP_DISPLAY; atstream=stdout; file_settype(atstream, file_type); if(!help_issued) msg_cprintf(H_NFMT, M_EXTRACTING_1_TO_2, format_filename(filename), "STDOUT"); } else { #endif if(file_type==ARJT_LABEL) { #ifdef HAVE_DRIVES #if SFX_LEVEL>=ARJ msg_cprintf(H_HL|H_NFMT, M_EXTRACTING, fname=format_filename(filename)); #else msg_cprintf(H_HL|H_NFMT, M_EXTRACTING, format_filename(filename)); #endif msg_cprintf(0, (FMSG *)vd_space); if(!file_setlabel(filename, label_drive, file_mode.native, ts_native(&ftime_stamp, OS))) { msg_cprintf(0, M_OK); return(1); } else { msg_cprintf(0, M_SET_LABEL_ERROR); errors++; #if SFX_LEVEL>=ARJ write_index_entry(idxid_fault); #endif return(0); } #else skip_file(); #endif } #if SFX_LEVEL>=ARJ if((host_os==OS_WIN95||host_os==OS_WINNT)&&lfn_mode==LFN_DUAL_EXT) { msg_sprintf(tmp_name, M_WIN95_LFN_TRANSL, (int)(num%1000)); tmp_entry=split_name(tmp_name, NULL, NULL); } subdir[0]='\0'; if(current_chapter!=chapter_to_process) { dir_num=(int)max(ext_flags, current_chapter); sprintf(subdir, "%03d%c", dir_num, PATHSEP_DEFAULT); } #endif if(extract_to_file) strcpy(out_name, extraction_filename); else { if(lowercase_names) { #if SFX_LEVEL>=ARJ strlower(tmp_name); #else strlower(filename); #endif } #if SFX_LEVEL>=ARJ if(subdir_extraction) #else if(!subdir_extraction) #endif { strcpy(out_name, (target_dir[0]=='\0')?nullstr:target_dir); #if SFX_LEVEL>=ARJ strcat(out_name, subdir); out_entry=strlen(out_name); trim=exclude_paths?left_trim:0; default_case_path(out_name+out_entry, tmp_name+trim); #else strcat(out_name, filename); #endif } else { strcpy(out_name, target_dir); #if SFX_LEVEL>=ARJ strcat(out_name, subdir); strcat(out_name, tmp_name+tmp_entry); #else strcat(out_name, filename+entry_pos); #endif } } if(continued_prevvolume&&ofstream!=NULL) { crc32term=CRC_MASK; crc32_for_string(filename+entry_pos); if(crc32term!=volume_crc) error(M_INVALID_MV_SEQ); far_strcpy((char FAR *)tmp_tmp_filename, tmp_filename); atstream=ofstream; ofstream=NULL; tmp_filename[0]='\0'; } else { disk_touched=test_unpack_condition(out_name); if(disk_touched) { if(disk_touched==1||disk_touched==2||skip_rename_prompt) { if(disk_touched==2) errors++; skip_file(); #if SFX_LEVEL>=ARJ write_index_entry(idxid_fault); #endif return(0); } else { if(!query_for_rename(out_name)) { #if SFX_LEVEL>=ARJ write_index_entry(idxid_fault); #endif return(0); } } } if(file_type==ARJT_BINARY||file_type==ARJT_TEXT) { cycle:; #if SFX_LEVEL>=ARJ if(clear_archive_bit) dos_chmod(out_name, STD_FATTR_NOARCH); #else if(overwrite_ro) dos_chmod(out_name, STD_FATTR_NOARCH); #endif #if SFX_LEVEL>=ARJ atstream=file_open(out_name, (continued_prevvolume||ext_pos>0L)?sim_perms[file_type%2]:write_perms[file_type%2]); #else atstream=file_open(out_name, continued_prevvolume?sim_perms[file_type%2]:write_perms[file_type%2]); #endif if(atstream!=NULL&&!extract_to_file&&is_file(atstream)) { file_close(atstream); atstream=NULL; } if(atstream==NULL) { #if SFX_LEVEL>=ARJ error_report(); #endif msg_cprintf(H_ERR, M_CANTOPEN, out_name); nputlf(); if(yes_on_all_queries||skip_rename_prompt) { skip_file(); errors++; #if SFX_LEVEL>=ARJ write_index_entry(idxid_fault); #endif return(0); } if(!query_for_rename(out_name)) { #if SFX_LEVEL>=ARJ write_index_entry(idxid_fault); #endif return(0); } else goto cycle; } #if SFX_LEVEL>=ARJ if(start_at_ext_pos) { fseek(atstream, 0L, SEEK_END); if(ftell(atstream)>ext_pos) fseek(atstream, ext_pos, SEEK_SET); } else smart_seek(resume_position, atstream); #else smart_seek(resume_position, atstream); #endif } strcpy(tmp_tmp_filename, out_name); } if(show_filenames_only||!strcmp_os(filename, tmp_tmp_filename)) msg_cprintf(H_HL|H_NFMT, M_EXTRACTING, format_filename(filename)); else { strcpy(out_name, format_filename(tmp_tmp_filename)); msg_cprintf(H_HL|H_NFMT, M_EXTRACTING_1_TO_2, format_filename(filename), out_name); } #if SFX_LEVEL>=ARJ if((continued_prevvolume||start_at_ext_pos)&&eh_find_pending(eh)==NULL) #elif SFX_LEVEL>=ARJSFXV if(continued_prevvolume&&eh_find_pending(eh)==NULL) #else if(continued_prevvolume) #endif msg_cprintf(H_HL|H_NFMT, M_AT_POSITION_N, ftell(atstream)); #if SFX_LEVEL>=ARJ } #endif #endif /* For ARJSFX, use a simplified algorithm... */ #if SFX_LEVEL==ARJSFX if(test_unpack_env()) return(0); strcpy(tmp_name, target_dir); strcat(tmp_name, test_mode?filename:list_adapted_name); if(test_unpack_condition(tmp_name)) { skip_file(); return(0); } strcpy(tmp_tmp_filename, tmp_name); if(file_type!=ARJT_DIR&&file_type!=ARJT_UXSPECIAL) { if((atstream=file_open(tmp_tmp_filename, write_perms[file_type%2]))==NULL) { msg_cprintf(H_ERR, M_CANTOPEN, tmp_tmp_filename); fputc(LF, stdout); skip_file(); errors++; return(0); } } if(strcmp_os(filename, tmp_tmp_filename)) msg_cprintf(H_HL|H_NFMT, M_EXTRACTING_1_TO_2, filename, tmp_tmp_filename); else msg_cprintf(H_HL|H_NFMT, M_EXTRACTING, filename); if(verbose_display) { if(file_type==ARJT_BINARY&&!test_host_os(host_os)) msg_cprintf(0, M_FOREIGN_BINARY); else fputc(LF, stdout); msg_cprintf(0, method==0?M_UNSTORING:M_UNCOMPRESSING); } unpack_file(BOP_NONE); if(file_type!=ARJT_DIR&&file_type!=ARJT_UXSPECIAL) fclose(atstream); file_setftime(tmp_tmp_filename, ts_native(&ftime_stamp, OS)); if(test_host_os(host_os)) dos_chmod(tmp_tmp_filename, file_mode.native); atstream=NULL; #endif /* ...and the rest may be safely omitted for ARJSFX modules */ #if SFX_LEVEL>=ARJSFXV if(!test_host_os((int)host_os)&&file_type==ARJT_BINARY) msg_cprintf(0, M_FOREIGN_BINARY); #if SFX_LEVEL>=ARJ if(!verbose_display) msg_cprintf(0, (FMSG *)vd_space); else { nputlf(); if(method==0) msg_cprintf(0, M_UNSTORING); else msg_cprintf(H_HL|H_NFMT, M_UNCOMPRESSING, method); msg_cprintf(H_HL|H_NFMT, M_N_BYTES, origsize); } #else msg_cprintf(0, (FMSG *)vd_space); #endif if(file_garbled) garble_init(password_modifier); #if SFX_LEVEL<=ARJSFXV action=BOP_NONE; #endif if(print_with_more) action=BOP_LIST; unpack_file(action); tmp_crc=crc32term^CRC_MASK; #if SFX_LEVEL>=ARJ if(to_console) { file_settype(atstream, ARJT_TEXT); /* This way, pipe redirections can't be tracked under UNIX, e.g. "arj p test.arj myfile>newfile" will not set the timestamp of newfile to the one of test.arj->myfile. */ #if TARGET!=UNIX file_setftime_on_stream(atstream, ts_native(&ftime_stamp, OS)); #endif atstream=NULL; } else { #endif if(volume_flag_set) { ofstream=atstream; atstream=NULL; crc32term=CRC_MASK; crc_for_string(filename+entry_pos); volume_crc=crc32term; far_strcpy(tmp_filename, (char FAR *)tmp_tmp_filename); volume_ftime=ftime_stamp; msg_cprintf(0, M_CONTINUED_NEXTVOL); } else { if(file_type==ARJT_BINARY||file_type==ARJT_TEXT) { fclose(atstream); atstream=NULL; } /* Process the extended header information */ if(valid_ext_hdr) { /* Create UNIX special files if able to */ #if TARGET==UNIX if(file_type==ARJT_UXSPECIAL&&(p_eh=eh_lookup(eh, UXSPECIAL_ID))!=NULL) { raw_eh=p_eh->raw; /* No unpacking, etc. (for now) */ if((uxspec_rc=set_uxspecial(raw_eh, tmp_tmp_filename))!=0) { switch(uxspec_rc) { #if TARGET==UNIX case UXSPEC_RC_FOREIGN_OS: msg_cprintf(H_ALERT, M_FOREIGN_SYSTEM); break; case UXSPEC_RC_NOLINK: msg_cprintf(H_ALERT, M_NO_LINKING); break; #if SFX_LEVEL>=ARJ case UXSPEC_RC_SUPPRESSED: msg_cprintf(H_ALERT, M_UXSPEC_SUPPRESSED); break; #endif #endif default: msg_cprintf(H_ERR, M_CANT_SET_UXSPECIAL); break; } if(errorlevel==ARJ_ERL_SUCCESS) errorlevel=ARJ_ERL_WARNING; } else uxspecial_stats(raw_eh, UXSTATS_SHORT); } #else if(file_type==ARJT_UXSPECIAL) { msg_cprintf(H_ALERT, M_UXSPECIAL_UNSUPP); msg_cprintf(0, (FMSG *)vd_space); } #endif /* Restore the file owner */ #if TARGET==UNIX if(((p_eh=eh_lookup(eh, OWNER_ID))!=NULL|| (p_eh=eh_lookup(eh, OWNER_ID_NUM))!=NULL) #if SFX_LEVEL>=ARJ &&do_chown #endif ) { raw_eh=p_eh->raw; /* No unpacking, etc. (for now) */ if(set_owner(raw_eh, tmp_tmp_filename, (p_eh->tag==OWNER_ID))) { msg_cprintf(H_ERR, M_CANT_CHOWN); if(errorlevel==ARJ_ERL_SUCCESS) errorlevel=ARJ_ERL_WARNING; } } #endif /* Deflate and store the extended attributes */ #ifdef HAVE_EAS if(ea_supported&&(p_eh=eh_lookup(eh, EA_ID))!=NULL) { raw_eh=unpack_ea(p_eh); if(set_ea(raw_eh, tmp_tmp_filename)) { msg_cprintf(H_ALERT, M_CANT_SET_EA); if(errorlevel==ARJ_ERL_SUCCESS) errorlevel=ARJ_ERL_WARNING; } else { ea_size=get_ea_size(tmp_tmp_filename); if(ea_size>0) { msg_cprintf(H_HL, M_EA_STATS_STG, ea_size); msg_cprintf(0, (FMSG *)vd_space); } } farfree(raw_eh); } #endif } /* Set the timestamps, since the file won't be affected by any modifications anymore */ file_setftime(tmp_tmp_filename, ts_native(&ftime_stamp, OS)); if(lfn_supported!=LFN_NOT_SUPPORTED&&ts_valid(atime_stamp)) { file_setctime(tmp_tmp_filename, ts_native(&ctime_stamp, OS)); file_setatime(tmp_tmp_filename, ts_native(&atime_stamp, OS)); } /* Finalize by restoring the attirbutes */ if(test_host_os(host_os)&&!execute_cmd) { #if SFX_LEVEL>=ARJ if(filter_fa_arch<=FAA_RESTORE_CLEAR) dos_chmod(tmp_tmp_filename, file_mode.native); if(filter_fa_arch==FAA_RESTORE_CLEAR||filter_fa_arch==FAA_EXCL_CLEAR) dos_clear_arch_attr(tmp_tmp_filename); #else dos_chmod(tmp_tmp_filename, file_mode.native); #endif } } #if SFX_LEVEL>=ARJ } #endif if(tmp_crc==file_crc&&compsize==0L) { #if SFX_LEVEL>=ARJ if(!help_issued) { msg_cprintf(0, M_OK); write_index_entry(((host_os==OS_WIN95||host_os==OS_WINNT)&&lfn_mode==LFN_DUAL_EXT)?tmp_name:nullstr); } #else msg_cprintf(0, M_OK); #endif } else { if(!print_with_more) { msg_cprintf(H_ALERT, M_CRC_ERROR); if(errorlevel==ARJ_ERL_SUCCESS) errorlevel=ARJ_ERL_CRC_ERROR; errors++; if(!ignore_crc_errors) { file_unlink(tmp_tmp_filename); tmp_tmp_filename[0]='\0'; return(0); } #if SFX_LEVEL>=ARJ else write_index_entry(idxid_fault); #endif } } #if SFX_LEVEL>=ARJ if(execute_cmd) { exec_cmd(cmd_to_exec); file_unlink(tmp_tmp_filename); } #endif #endif tmp_tmp_filename[0]='\0'; #if SFX_LEVEL>=ARJ } #endif return(1); } /* Looks for the requested file in the filelist */ #if SFX_LEVEL>=ARJ FILE_COUNT flist_lookup(FILE_COUNT tag) #else FILE_COUNT flist_lookup() #endif { char tmp_name[FILENAME_MAX]; FILE_COUNT i; int tmp_entry; #if SFX_LEVEL>=ARJSFXV int flag; char *nptr; int lp_entry, st_entry; char lp_name[FILENAME_MAX], st_name[FILENAME_MAX]; FILE_COUNT num, ubound; /* For by-number tagging */ int n_st, n_tmp; #endif #if SFX_LEVEL>=ARJ if(add_command&&total_chapters!=0&&chapter_number=ARJSFXV for(i=0; i=ARJ if((!add_command||flag==FLFLAG_TO_PROCESS)&& (!order_command||flag==FLFLAG_TO_PROCESS)&& (flag==FLFLAG_TO_PROCESS||flag==FLFLAG_PROCESSED)) #else if(flag==FLFLAG_TO_PROCESS||flag==FLFLAG_PROCESSED) #endif { #if SFX_LEVEL>=ARJ flist_retrieve(tmp_name, NULL, &flist_main, i); #else retrieve_entry(tmp_name, &flist_main, i); #endif #if SFX_LEVEL>=ARJ if(add_command) { if(debug_enabled&&strchr(debug_opt, 'y')!=NULL) { strcpy(lp_name, tmp_name); strcpy(st_name, filename); } else { default_case_path(lp_name, tmp_name); default_case_path(st_name, filename); } tmp_entry=split_name(lp_name, NULL, NULL); st_entry=split_name(st_name, NULL, NULL); if(exclude_paths==EP_PATH) { if(match_wildcard(st_name, lp_name+tmp_entry)) return(i+1); } else if(tmp_entry-lp_entry==st_entry) { if(!strncmp_os(st_name, lp_name+lp_entry, st_entry)) { if(match_wildcard(st_name+st_entry, lp_name+tmp_entry)) return(i+1); } } } else { #endif #if SFX_LEVEL>=ARJ if(debug_enabled&&strchr(debug_opt, 'y')!=NULL) { default_case_path(lp_name, tmp_name); default_case_path(st_name, filename); } else { #endif strcpy(lp_name, tmp_name); strcpy(st_name, filename); #if SFX_LEVEL>=ARJ } #endif tmp_entry=split_name(lp_name, NULL, NULL); st_entry=split_name(st_name, NULL, NULL); #if SFX_LEVEL>=ARJ if(select_by_number) { nptr=tmp_name; num=(unsigned int)strtoul(nptr, &nptr, 10); if(num==tag) return(i+1); if(*nptr=='-') { nptr++; ubound=(unsigned int)strtoul(nptr, &nptr, 10); if(ubound==0) ubound=EXT_FILELIST_CAPACITY; if(num<=tag&&tag<=ubound) return(i+1); } } else { if(total_chapters!=0) { if(current_chapter==RESERVED_CHAPTER&&(int)ext_flags==total_chapters&&(int)chapter_number==total_chapters) return(0); if(current_chapter==0&&(int)ext_flags<=total_chapters&&(int)chapter_numberchapter_to_process||(int)chapter_number=ARJ } #endif #if SFX_LEVEL>=ARJ } #endif } } #else for(i=0; i=ARJ /* Deletes a file from the archive */ int arcv_delete(FILE_COUNT num) { char del_action; unsigned long cur_pos; if(query_for_each_file) { msg_sprintf(misc_buf, M_QUERY_DELETE, filename); if(!query_action(REPLY_YES, QUERY_ARCH_OP, (char FAR *)misc_buf)) return(0); } if(file_type==ARJT_CHAPTER&&chapter_number!=0&&chapter_mode!=CHAP_NONE&¤t_chapter<=CHAPTERS_MAX) return(0); del_action=1; if(delete_processed==DP_EXTRACT) { cur_pos=(unsigned long)ftell(aistream); if(!unpack_file_proc(0, num)) { fseek(aistream, cur_pos, SEEK_SET); return(0); } } else { if(!destfile_extr_validation()) return(0); if(total_chapters!=0&¤t_chapter==RESERVED_CHAPTER&&(int)chapter_number==total_chapters) { special_processing(CFA_MARK, aistream); del_action=0; } else { if((total_chapters!=0&¤t_chapter==RESERVED_CHAPTER&&(int)chapter_number0) error(M_FOUND_N_ERRORS, errors); } #endif