⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filelist.c

📁 arj source code
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: filelist.c,v 1.3 2003/04/24 11:18:15 andrew_belov Exp $ * --------------------------------------------------------------------------- * XMS routines and functions  for dealing  with file lists are located  here. * Note: the  current  caching algorithm  implies that  the filelist is  first * sequentially composed, then sequentially read. No random access. * */#include "arj.h"#ifndef SIMPLE_FLIST #include "arj_xms.h"#endifDEBUGHDR(__FILE__)                      /* Debug information block *//* This file actually consists of two completely different code groups, one   for ARJ full-featured filelists, and another one for simplified filelists   created by ARJSFX. */#ifndef SIMPLE_FLIST#define FLIST_BLOCK_INCREMENT     16    /* Number of blocks to preallocate                                           when a new block is allocated */#define L_ENTRIES_INCREMENT      512    /* # of entries to reserve at once */#if TARGET==DOS #define XMS_BLOCK_PREALLOC        2    /* Number of preallocated XMS blocks */ #define XMS_MULTIPLIER (FLIST_BLOCK_SIZE/1024)#endif/* Local far heap constants */#define FAR_PROBE             32000L    /* Amount of memory allocated to check                                           if we're still alive */#define FAR_HEAP_LOWBOUND     150000    /* If the amount of free memory goes                                           below this, the heap needs to be                                           relocated to XMS */#else                                   /* ARJSFX constants */#define FILES_PER_BLOCK            8#ifdef REARJ #define BLOCKS_LIMIT            512#else #define BLOCKS_LIMIT           1024#endif#endif/* Private CRC union - used for hash table calculation in ARJ. In SFX, we'll   use simple checksums instead. */#ifndef SIMPLE_FLISTstruct crc_words{ unsigned short lo; unsigned short hi;};union crc32{ unsigned long crc32; struct crc_words x; char low;};#endif#ifndef SIMPLE_FLIST/* Private data. Again, it has effect in ARJ only. */static FILE_COUNT flist_capacity;    	/* Filelist capacity (=const) */static unsigned long crc_matches, hash_matches;#endif/* From this point onward, #define REARJ means #define SIMPLE_FLIST   (although REARJ filelist model is far from SIMPLE) */#ifdef REARJ/* REARJ service routine - checks if a file is present in the exclusion list */static int is_excluded(char *name){ char tmp_name[CCHMAXPATH]; int tmp_entry, e_entry; FILE_COUNT i; tmp_entry=split_name(name, NULL, NULL); for(i=0; i<flist_exclusion.files; i++) {  retrieve_entry(tmp_name, &flist_exclusion, i);  e_entry=split_name(tmp_name, NULL, NULL);  if(e_entry!=0&&strlen(tmp_name)==e_entry&&!strncmp(tmp_name, name, e_entry))   return(1);  if(e_entry==0||(e_entry==tmp_entry&&!strncmp(tmp_name, name, e_entry)))  {   if(match_wildcard(name+tmp_entry, tmp_name+e_entry))    return(1);  } } return(0);}#endif/* Since SFX won't permit neither XMS nor disk storage, a big part of code is   skipped for it till find_match(). */#ifndef SIMPLE_FLIST/* A macro too free a block of XMS */#define xms_free(root) free_xms(root->table->xms_handle)/* Allocates a block of extended memory and stores its handle in the hash   table entry given. */#if TARGET==DOSstatic int xms_malloc(unsigned long size, struct flist_root *root){ unsigned short xmsize;                 /* Size of allocated XMS in blocks */ short handle; xmsize=(unsigned short)(size/(unsigned long)FLIST_BLOCK_SIZE); if(size%(unsigned long)FLIST_BLOCK_SIZE!=0L)  xmsize++; if(!allocate_xms(xmsize*XMS_MULTIPLIER, &handle))  return(0); root->table->xms_handle=handle; return(1);}#endif/* Reallocates a block of extended memory that belongs to the current hash   structure */#if TARGET==DOSstatic int xms_realloc(unsigned long size, struct flist_root *root){ struct xms_move xms_move; unsigned short xmsize;                 /* Size of allocated RAM in blocks */ short handle, old_handle; xmsize=(unsigned short)(size/(unsigned long)FLIST_BLOCK_SIZE); if(size%(unsigned long)FLIST_BLOCK_SIZE!=0L)  xmsize++; if(!allocate_xms(xmsize*XMS_MULTIPLIER, &handle))  return(0); xms_move.src_handle=old_handle=root->table->xms_handle; xms_move.src_offset=0L; xms_move.dest_handle=handle; xms_move.dest_offset=0L; xms_move.length=(unsigned long)root->table->xms_mem_blocks*(unsigned long)FLIST_BLOCK_SIZE; if(!move_xms(&xms_move))  return(0);                            /* Potential extended memory leak! */ free_xms(old_handle); root->table->xms_handle=handle; return(1);}#endif/* Creates a temporary swap file for holding file lists */static void create_swapfile(struct flist_root *root){ char *sf_name; sf_name=(char *)malloc_msg(CCHMAXPATH); sf_name[0]='\0'; if(swptr_hm[0]!='\0')  add_pathsep(strcpy(sf_name, swptr_hm)); strcat(sf_name, arjtemp_spec); find_tmp_filename(sf_name); root->table->sf_name=(char *)malloc_msg(strlen(sf_name)+2); strcpy(root->table->sf_name, sf_name); if((root->table->sf_stream=file_open(root->table->sf_name, m_wbp))==NULL)  error(M_CANTOPEN, root->table->sf_name); free(sf_name);}/* Reads the block given, moving it into the cache area */static void get_heap_block(unsigned int block, struct flist_root *root){ #if TARGET==DOS  struct xms_move xms_move; #endif char *tmp_block;                       /* For transfers from far RAM */ if(root->table->block!=block) {  if(root->storage==BST_FAR)   far_memmove((char FAR *)root->table->cache, (char FAR *)root->table->far_ptrs[block], FLIST_BLOCK_SIZE);  else if(root->storage==BST_DISK)  {   fseek(root->table->sf_stream, (unsigned long)block*FLIST_BLOCK_SIZE, SEEK_SET);   tmp_block=(char *)malloc_msg(FLIST_BLOCK_SIZE);   if(fread(tmp_block, 1, FLIST_BLOCK_SIZE, root->table->sf_stream)!=FLIST_BLOCK_SIZE)    error(M_CANTREAD);   far_memmove((char FAR *)root->table->cache, (char FAR *)tmp_block, FLIST_BLOCK_SIZE);   free(tmp_block);  } #if TARGET==DOS  else if(root->storage==BST_XMS)  {   xms_move.src_handle=root->table->xms_handle;   xms_move.src_offset=(unsigned long)block*FLIST_BLOCK_SIZE;   xms_move.dest_handle=0;   xms_move.dest_offset=(unsigned long)(char FAR *)root->table->cache;   xms_move.length=FLIST_BLOCK_SIZE;   if(!move_xms(&xms_move))    error(M_LISTING_XMS_ERROR, M_XMS_READ);  } #endif  root->table->block=block; }}/* Saves a cached block in the heap if it's necessary */static void save_heap_block(struct flist_root *root, char FAR *data){ #if TARGET==DOS  struct xms_move xms_move; #endif unsigned int block;                    /* Block number */ char *tmp_block;                       /* Temporary transfer area */ if(root->table->not_flushed) {  block=root->table->block_to_flush;  if(root->storage==BST_FAR)  {   if(root->table->far_ptrs[block]==NULL)    root->table->far_ptrs[block]=farmalloc_msg(FLIST_BLOCK_SIZE);   far_memmove(root->table->far_ptrs[block], data, FLIST_BLOCK_SIZE);  }  else if(root->storage==BST_DISK)  {   if(root->table->sf_stream==NULL)    create_swapfile(root);   fseek(root->table->sf_stream, (unsigned long)block*FLIST_BLOCK_SIZE, SEEK_SET);   tmp_block=malloc_msg(FLIST_BLOCK_SIZE);   far_memmove((char FAR *)tmp_block, data, FLIST_BLOCK_SIZE);   file_write(tmp_block, 1, FLIST_BLOCK_SIZE, root->table->sf_stream);   free(tmp_block);  } #if TARGET==DOS  else if(root->storage==BST_XMS)  {   /* If the block number exceeds the quantity of allocated XMS blocks, resize      XMS buffer */   if(block>=root->table->xms_mem_blocks)   {    if(!xms_realloc((unsigned long)(block+FLIST_BLOCK_INCREMENT)*FLIST_BLOCK_SIZE, root))     error(M_LISTING_XMS_ERROR, M_XMS_WRITE);    root->table->xms_mem_blocks=block+FLIST_BLOCK_INCREMENT;   }   xms_move.src_handle=0;   xms_move.src_offset=(unsigned long)data;   xms_move.dest_handle=root->table->xms_handle;   xms_move.dest_offset=(unsigned long)block*FLIST_BLOCK_SIZE;   xms_move.length=(unsigned long)FLIST_BLOCK_SIZE;   if(!move_xms(&xms_move))    error(M_LISTING_XMS_ERROR, M_XMS_WRITE);  } #endif  root->table->not_flushed=0; }}/* Swaps all members of the given heap to disk */static void relocate_heap(struct flist_root *root){ unsigned int hiblock, curblock; hiblock=root->table->hiblock; root->table->sf_stream=NULL; for(curblock=0; curblock<=hiblock; curblock++) {  root->storage=BST_FAR;  get_heap_block(curblock, root);  root->storage=BST_DISK;  root->table->block_to_flush=curblock;  root->table->not_flushed=1;  save_heap_block(root, (char FAR *)root->table->cache);  farfree(root->table->far_ptrs[curblock]); } farfree(root->table->far_ptrs); root->storage=BST_DISK;}/* Updates header CRCs */static void update_hcrc(struct flist_root *root, unsigned long crc){ unsigned short hr; union crc32 crc32; char h; crc32.crc32=crc; hr=65535-flist_capacity+1; hr=(hr<=crc32.x.lo)?crc32.x.lo-hr:crc32.x.lo; h=crc32.crc32>>29; root->table->hcrc[hr]|=(1<<h);}/* Reverts CRC, should return 0 if a hash match occured */static unsigned int revert_hcrc(struct flist_root *root, unsigned long crc){ unsigned short hr; union crc32 crc32; char h; crc32.crc32=crc; hr=65535-flist_capacity+1; hr=(hr<=crc32.x.lo)?crc32.x.lo-hr:crc32.x.lo; h=crc32.crc32>>29; return((unsigned int)root->table->hcrc[hr]&((unsigned char)1<<h));}#else/* Returns a checksum for the given string -- "simple" implementation uses   checksums rather than CRCs. */static char checksum(char *str){ char rc; rc=str[0]; while(*++str!='\0')  rc+=*str; return(rc);}#endif#ifdef REARJ/* (REARJ) looks for a name in backup filelist */static FILE_COUNT find_d_match(struct flist_root *root, char *name){ FILE_COUNT cur_file; if((cur_file=root->d_files)>0L) {  do  {   cur_file--;   if(!far_strccmp((char FAR *)name, root->d_names[cur_file]))    return(cur_file+1);  } while(cur_file!=0); } return(0);}#endif/* Finds if a filename is present in the given filelist */#ifndef REARJstatic int find_match(struct flist_root *root, char *name)#elsestatic int find_match(struct flist_root *root, char *name, FILE_COUNT instance)#endif{ #ifndef SIMPLE_FLIST  int cur_entry;  struct idblock FAR *idblock_ptr;  char FAR *fnm_ptr;                    /* Pointer to filename in ID block */  struct disk_file_info FAR *dptr;  union crc32 crc_term;  unsigned int crc_seed;  int curblock;  char *tmp_name; #else  FILE_COUNT cur_entry;  char c; #endif #ifndef SIMPLE_FLIST  crc32term=CRC_MASK;  tmp_name=malloc_str(name);  crc32_for_block(tmp_name, strlen(tmp_name));  free(tmp_name);  if(!revert_hcrc(root, crc_term.crc32=crc32term))   return(0);  hash_matches++;  crc_seed=crc_term.x.lo;  idblock_ptr=root->table->cache;  for(curblock=root->table->low_block; curblock<=root->table->hiblock; curblock++)  {   if(curblock!=root->table->block_to_flush)   {    get_heap_block(curblock, root);    for(cur_entry=0; cur_entry<idblock_ptr->total_entries; cur_entry++)    {     if(idblock_ptr->crc[cur_entry]==crc_seed)     {      crc_matches++;      dptr=(struct disk_file_info FAR *)&idblock_ptr->filler[idblock_ptr->sub_offset[cur_entry]];      fnm_ptr=dptr->name;      if(!far_strccmp(fnm_ptr, (char FAR *)name))      {       root->table->low_block=curblock;       return(1);                       /* Matched */      }     }    }   }  }  for(curblock=0; curblock<root->table->low_block; curblock++)  {   if(curblock!=root->table->block_to_flush)   {    get_heap_block(curblock, root);    for(cur_entry=0; cur_entry<idblock_ptr->total_entries; cur_entry++)    {     if(idblock_ptr->crc[cur_entry]==crc_seed)     {      crc_matches++;      dptr=(struct disk_file_info FAR *)&idblock_ptr->filler[idblock_ptr->sub_offset[cur_entry]];      fnm_ptr=dptr->name;      if(!far_strccmp(fnm_ptr, (char FAR *)name))      {       root->table->low_block=curblock;       return(1);                       /* Matched */      }     }    }   }  }  idblock_ptr=(struct idblock FAR *)root->table->sec_cache;  for(cur_entry=0; cur_entry<idblock_ptr->total_entries; cur_entry++)  {   if(idblock_ptr->crc[cur_entry]==crc_seed)   {    dptr=(struct disk_file_info FAR *)&idblock_ptr->filler[idblock_ptr->sub_offset[cur_entry]];    fnm_ptr=dptr->name;    if(!far_strccmp(fnm_ptr, (char FAR *)name))    {     root->table->low_block=curblock;     return(1);                         /* Matched */    }   }  } #else  c=checksum(name);  for(cur_entry=0; cur_entry<root->files; cur_entry++)  {   /* Return # of file + 1 if everything matched */   #ifndef REARJ    if(root->checksums[cur_entry]==c&&!far_strccmp(root->names[cur_entry], (char FAR *)name))     return(cur_entry+1);   #else    if(root->checksums[cur_entry]==c&&root->instances[cur_entry]==instance&&!far_strccmp(root->names[cur_entry], (char FAR *)name))     return(cur_entry+1);   #endif  } #endif return(0);}#ifndef SIMPLE_FLIST/* Frees memory structures associated with filelist search */static void cache_cleanup(struct flist_root *root){ if(!root->table->not_allocated) {  if(root->table->hiblock>0||root->table->block_to_flush>0)  {   save_heap_block(root, (char FAR *)root->table->sec_cache);   if(root->table->sec_cache!=NULL&&root->table->sec_cache!=root->table->cache)    farfree(root->table->sec_cache);   root->table->sec_cache=NULL;  }  if(root->table->hcrc!=NULL)   farfree(root->table->hcrc);  root->table->hcrc=NULL;  root->table->not_allocated=1; }}/* Invalidates and releases the filelist root */void flist_cleanup_proc(struct flist_root *root){ int block; if(root->table==NULL)  return; if(debug_enabled&&strchr(debug_opt, 'v')!=NULL) {  msg_cprintf(0, M_XLIST_BLOCKS, root->table->xlist_blocks);  if(root==&flist_main)   msg_cprintf(0, M_HASH_MATCHES, hash_matches, crc_matches); } if(root->storage==BST_FAR) {  for(block=0; block<root->table->xlist_blocks; block++)  {   if(root->table->far_ptrs[block]!=NULL)    farfree(root->table->far_ptrs[block]);  }  farfree(root->table->far_ptrs); } else if(root->storage==BST_DISK&&root->table->sf_stream!=NULL) {  fclose(root->table->sf_stream);  file_unlink(root->table->sf_name);  free(root->table->sf_name); }#if TARGET==DOS else if(root->storage==BST_XMS)  xms_free(root);#endif if(root->storage!=BST_NONE) {  if(root->table->enumerators!=NULL)   farfree(root->table->enumerators);  if(root->table->hcrc!=NULL)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -