?? arj_arcv.c
字號:
/* * $Id: arj_arcv.c,v 1.11 2003/07/15 16:35:17 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>=ARJSFXVstatic 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>=ARJstatic char *read_perms[]={m_rb, m_r}; /* For encoding only */#endif#if SFX_LEVEL>=ARJSFXVstatic char *sim_perms[]={m_rbp, m_rp};#endifstatic char *write_perms[]={m_wb, m_w};/* Index file IDs */#if SFX_LEVEL>=ARJstatic 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>=HSLIMIT_ARJ) end_pos=HSLIMIT_ARJ; } while(tmp_pos<end_pos) #else while(tmp_pos<HSLIMIT_ARJSFX) #endif { fseek(stream, tmp_pos, SEEK_SET); id=fget_byte(stream); #if SFX_LEVEL>=ARJSFXV while(tmp_pos<end_pos) #else while(tmp_pos<HSLIMIT_ARJSFX) #endif { if(id==HEADER_ID_LO) { if((id=fget_byte(stream))==HEADER_ID_HI) break; } else id=fget_byte(stream); tmp_pos++; } #if SFX_LEVEL>=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 (<name> 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>=ARJSFXVint read_header(int first, FILE *stream, char *name)#elseint 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<R9_HDR_SIZE) { if(arj_flags&EXTFILE_FLAG) { resume_position=hget_longword(); continued_prevvolume=1; mvfile_type=file_type; } } else /* v 2.62+ - resume position is stored anyway, atime/ctime follows it. */ { resume_position=hget_longword(); if(arj_flags&EXTFILE_FLAG) { continued_prevvolume=1; mvfile_type=file_type; } ts_store(&atime_stamp, host_os, hget_longword()); ts_store(&ctime_stamp, host_os, hget_longword()); hget_longword(); /* Reserved in revision 9 headers */ } } #endif if(check_file_size()) display_hdr_error(M_BAD_HEADER, NULL); #if SFX_LEVEL>=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)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -