2 * $Id: filelist.c,v 1.4 2004/04/14 20:54:21 andrew_belov Exp $
3 * ---------------------------------------------------------------------------
4 * XMS routines and functions for dealing with file lists are located here.
5 * Note: the current caching algorithm implies that the filelist is first
6 * sequentially composed, then sequentially read. No random access.
15 DEBUGHDR(__FILE__) /* Debug information block */
17 /* This file actually consists of two completely different code groups, one
18 for ARJ full-featured filelists, and another one for simplified filelists
23 #define FLIST_BLOCK_INCREMENT 16 /* Number of blocks to preallocate
24 when a new block is allocated */
25 #define L_ENTRIES_INCREMENT 512 /* # of entries to reserve at once */
28 #define XMS_BLOCK_PREALLOC 2 /* Number of preallocated XMS blocks */
29 #define XMS_MULTIPLIER (FLIST_BLOCK_SIZE/1024)
32 /* Local far heap constants */
34 #define FAR_PROBE 32000L /* Amount of memory allocated to check
35 if we're still alive */
36 #define FAR_HEAP_LOWBOUND 150000 /* If the amount of free memory goes
37 below this, the heap needs to be
40 #else /* ARJSFX constants */
42 #define FILES_PER_BLOCK 8
44 #define BLOCKS_LIMIT 512
46 #define BLOCKS_LIMIT 1024
51 /* Private CRC union - used for hash table calculation in ARJ. In SFX, we'll
52 use simple checksums instead. */
73 /* Private data. Again, it has effect in ARJ only. */
75 static FILE_COUNT flist_capacity; /* Filelist capacity (=const) */
76 static unsigned long crc_matches, hash_matches;
80 /* From this point onward, #define REARJ means #define SIMPLE_FLIST
81 (although REARJ filelist model is far from SIMPLE) */
85 /* REARJ service routine - checks if a file is present in the exclusion list */
87 static int is_excluded(char *name)
89 char tmp_name[CCHMAXPATH];
90 int tmp_entry, e_entry;
93 tmp_entry=split_name(name, NULL, NULL);
94 for(i=0; i<flist_exclusion.files; i++)
96 retrieve_entry(tmp_name, &flist_exclusion, i);
97 e_entry=split_name(tmp_name, NULL, NULL);
98 if(e_entry!=0&&strlen(tmp_name)==e_entry&&!strncmp(tmp_name, name, e_entry))
100 if(e_entry==0||(e_entry==tmp_entry&&!strncmp(tmp_name, name, e_entry)))
102 if(match_wildcard(name+tmp_entry, tmp_name+e_entry))
111 /* Since SFX won't permit neither XMS nor disk storage, a big part of code is
112 skipped for it till find_match(). */
116 /* A macro too free a block of XMS */
118 #define xms_free(root) free_xms(root->table->xms_handle)
120 /* Allocates a block of extended memory and stores its handle in the hash
121 table entry given. */
124 static int xms_malloc(unsigned long size, struct flist_root *root)
126 unsigned short xmsize; /* Size of allocated XMS in blocks */
129 xmsize=(unsigned short)(size/(unsigned long)FLIST_BLOCK_SIZE);
130 if(size%(unsigned long)FLIST_BLOCK_SIZE!=0L)
132 if(!allocate_xms(xmsize*XMS_MULTIPLIER, &handle))
134 root->table->xms_handle=handle;
139 /* Reallocates a block of extended memory that belongs to the current hash
143 static int xms_realloc(unsigned long size, struct flist_root *root)
145 struct xms_move xms_move;
146 unsigned short xmsize; /* Size of allocated RAM in blocks */
147 short handle, old_handle;
149 xmsize=(unsigned short)(size/(unsigned long)FLIST_BLOCK_SIZE);
150 if(size%(unsigned long)FLIST_BLOCK_SIZE!=0L)
152 if(!allocate_xms(xmsize*XMS_MULTIPLIER, &handle))
154 xms_move.src_handle=old_handle=root->table->xms_handle;
155 xms_move.src_offset=0L;
156 xms_move.dest_handle=handle;
157 xms_move.dest_offset=0L;
158 xms_move.length=(unsigned long)root->table->xms_mem_blocks*(unsigned long)FLIST_BLOCK_SIZE;
159 if(!move_xms(&xms_move))
160 return(0); /* Potential extended memory leak! */
161 free_xms(old_handle);
162 root->table->xms_handle=handle;
167 /* Creates a temporary swap file for holding file lists */
169 static void create_swapfile(struct flist_root *root)
173 sf_name=(char *)malloc_msg(CCHMAXPATH);
175 if(swptr_hm[0]!='\0')
176 add_pathsep(strcpy(sf_name, swptr_hm));
177 strcat(sf_name, arjtemp_spec);
178 find_tmp_filename(sf_name);
179 root->table->sf_name=(char *)malloc_msg(strlen(sf_name)+2);
180 strcpy(root->table->sf_name, sf_name);
181 if((root->table->sf_stream=file_open(root->table->sf_name, m_wbp))==NULL)
182 error(M_CANTOPEN, root->table->sf_name);
186 /* Reads the block given, moving it into the cache area */
188 static void get_heap_block(unsigned int block, struct flist_root *root)
191 struct xms_move xms_move;
193 char *tmp_block; /* For transfers from far RAM */
195 if(root->table->block!=block)
197 if(root->storage==BST_FAR)
198 far_memmove((char FAR *)root->table->cache, (char FAR *)root->table->far_ptrs[block], FLIST_BLOCK_SIZE);
199 else if(root->storage==BST_DISK)
201 fseek(root->table->sf_stream, (unsigned long)block*FLIST_BLOCK_SIZE, SEEK_SET);
202 tmp_block=(char *)malloc_msg(FLIST_BLOCK_SIZE);
203 if(fread(tmp_block, 1, FLIST_BLOCK_SIZE, root->table->sf_stream)!=FLIST_BLOCK_SIZE)
205 far_memmove((char FAR *)root->table->cache, (char FAR *)tmp_block, FLIST_BLOCK_SIZE);
209 else if(root->storage==BST_XMS)
211 xms_move.src_handle=root->table->xms_handle;
212 xms_move.src_offset=(unsigned long)block*FLIST_BLOCK_SIZE;
213 xms_move.dest_handle=0;
214 xms_move.dest_offset=(unsigned long)(char FAR *)root->table->cache;
215 xms_move.length=FLIST_BLOCK_SIZE;
216 if(!move_xms(&xms_move))
217 error(M_LISTING_XMS_ERROR, M_XMS_READ);
220 root->table->block=block;
224 /* Saves a cached block in the heap if it's necessary */
226 static void save_heap_block(struct flist_root *root, char FAR *data)
229 struct xms_move xms_move;
231 unsigned int block; /* Block number */
232 char *tmp_block; /* Temporary transfer area */
234 if(root->table->not_flushed)
236 block=root->table->block_to_flush;
237 if(root->storage==BST_FAR)
239 if(root->table->far_ptrs[block]==NULL)
240 root->table->far_ptrs[block]=farmalloc_msg(FLIST_BLOCK_SIZE);
241 far_memmove(root->table->far_ptrs[block], data, FLIST_BLOCK_SIZE);
243 else if(root->storage==BST_DISK)
245 if(root->table->sf_stream==NULL)
246 create_swapfile(root);
247 fseek(root->table->sf_stream, (unsigned long)block*FLIST_BLOCK_SIZE, SEEK_SET);
248 tmp_block=malloc_msg(FLIST_BLOCK_SIZE);
249 far_memmove((char FAR *)tmp_block, data, FLIST_BLOCK_SIZE);
250 file_write(tmp_block, 1, FLIST_BLOCK_SIZE, root->table->sf_stream);
254 else if(root->storage==BST_XMS)
256 /* If the block number exceeds the quantity of allocated XMS blocks, resize
258 if(block>=root->table->xms_mem_blocks)
260 if(!xms_realloc((unsigned long)(block+FLIST_BLOCK_INCREMENT)*FLIST_BLOCK_SIZE, root))
261 error(M_LISTING_XMS_ERROR, M_XMS_WRITE);
262 root->table->xms_mem_blocks=block+FLIST_BLOCK_INCREMENT;
264 xms_move.src_handle=0;
265 xms_move.src_offset=(unsigned long)data;
266 xms_move.dest_handle=root->table->xms_handle;
267 xms_move.dest_offset=(unsigned long)block*FLIST_BLOCK_SIZE;
268 xms_move.length=(unsigned long)FLIST_BLOCK_SIZE;
269 if(!move_xms(&xms_move))
270 error(M_LISTING_XMS_ERROR, M_XMS_WRITE);
273 root->table->not_flushed=0;
277 /* Swaps all members of the given heap to disk */
279 static void relocate_heap(struct flist_root *root)
281 unsigned int hiblock, curblock;
283 hiblock=root->table->hiblock;
284 root->table->sf_stream=NULL;
285 for(curblock=0; curblock<=hiblock; curblock++)
287 root->storage=BST_FAR;
288 get_heap_block(curblock, root);
289 root->storage=BST_DISK;
290 root->table->block_to_flush=curblock;
291 root->table->not_flushed=1;
292 save_heap_block(root, (char FAR *)root->table->cache);
293 farfree(root->table->far_ptrs[curblock]);
295 farfree(root->table->far_ptrs);
296 root->storage=BST_DISK;
299 /* Updates header CRCs */
301 static void update_hcrc(struct flist_root *root, unsigned long crc)
308 hr=65535-flist_capacity+1;
309 hr=(hr<=crc32.x.lo)?crc32.x.lo-hr:crc32.x.lo;
311 root->table->hcrc[hr]|=(1<<h);
314 /* Reverts CRC, should return 0 if a hash match occured */
316 static unsigned int revert_hcrc(struct flist_root *root, unsigned long crc)
323 hr=65535-flist_capacity+1;
324 hr=(hr<=crc32.x.lo)?crc32.x.lo-hr:crc32.x.lo;
326 return((unsigned int)root->table->hcrc[hr]&((unsigned char)1<<h));
331 /* Returns a checksum for the given string -- "simple" implementation uses
332 checksums rather than CRCs. */
334 static char checksum(char *str)
348 /* (REARJ) looks for a name in backup filelist */
350 static FILE_COUNT find_d_match(struct flist_root *root, char *name)
354 if((cur_file=root->d_files)>0L)
359 if(!far_strccmp((char FAR *)name, root->d_names[cur_file]))
361 } while(cur_file!=0);
368 /* Finds if a filename is present in the given filelist */
371 static int find_match(struct flist_root *root, char *name)
373 static int find_match(struct flist_root *root, char *name, FILE_COUNT instance)
378 struct idblock FAR *idblock_ptr;
379 char FAR *fnm_ptr; /* Pointer to filename in ID block */
380 struct disk_file_info FAR *dptr;
381 union crc32 crc_term;
382 unsigned int crc_seed;
386 FILE_COUNT cur_entry;
392 tmp_name=malloc_str(name);
393 crc32_for_block(tmp_name, strlen(tmp_name));
395 if(!revert_hcrc(root, crc_term.crc32=crc32term))
398 crc_seed=crc_term.x.lo;
399 idblock_ptr=root->table->cache;
400 for(curblock=root->table->low_block; curblock<=root->table->hiblock; curblock++)
402 if(curblock!=root->table->block_to_flush)
404 get_heap_block(curblock, root);
405 for(cur_entry=0; cur_entry<idblock_ptr->total_entries; cur_entry++)
407 if(idblock_ptr->crc[cur_entry]==crc_seed)
410 dptr=(struct disk_file_info FAR *)&idblock_ptr->filler[idblock_ptr->sub_offset[cur_entry]];
412 if(!far_strccmp(fnm_ptr, (char FAR *)name))
414 root->table->low_block=curblock;
415 return(1); /* Matched */
421 for(curblock=0; curblock<root->table->low_block; curblock++)
423 if(curblock!=root->table->block_to_flush)
425 get_heap_block(curblock, root);
426 for(cur_entry=0; cur_entry<idblock_ptr->total_entries; cur_entry++)
428 if(idblock_ptr->crc[cur_entry]==crc_seed)
431 dptr=(struct disk_file_info FAR *)&idblock_ptr->filler[idblock_ptr->sub_offset[cur_entry]];
433 if(!far_strccmp(fnm_ptr, (char FAR *)name))
435 root->table->low_block=curblock;
436 return(1); /* Matched */
442 idblock_ptr=(struct idblock FAR *)root->table->sec_cache;
443 for(cur_entry=0; cur_entry<idblock_ptr->total_entries; cur_entry++)
445 if(idblock_ptr->crc[cur_entry]==crc_seed)
447 dptr=(struct disk_file_info FAR *)&idblock_ptr->filler[idblock_ptr->sub_offset[cur_entry]];
449 if(!far_strccmp(fnm_ptr, (char FAR *)name))
451 root->table->low_block=curblock;
452 return(1); /* Matched */
458 for(cur_entry=0; cur_entry<root->files; cur_entry++)
460 /* Return # of file + 1 if everything matched */
462 if(root->checksums[cur_entry]==c&&!far_strccmp(root->names[cur_entry], (char FAR *)name))
465 if(root->checksums[cur_entry]==c&&root->instances[cur_entry]==instance&&!far_strccmp(root->names[cur_entry], (char FAR *)name))
475 /* Frees memory structures associated with filelist search */
477 static void cache_cleanup(struct flist_root *root)
479 if(!root->table->not_allocated)
481 if(root->table->hiblock>0||root->table->block_to_flush>0)
483 save_heap_block(root, (char FAR *)root->table->sec_cache);
484 if(root->table->sec_cache!=NULL&&root->table->sec_cache!=root->table->cache)
485 farfree(root->table->sec_cache);
486 root->table->sec_cache=NULL;
488 if(root->table->hcrc!=NULL)
489 farfree(root->table->hcrc);
490 root->table->hcrc=NULL;
491 root->table->not_allocated=1;
495 /* Invalidates and releases the filelist root */
497 void flist_cleanup_proc(struct flist_root *root)
501 if(root->table==NULL)
503 if(debug_enabled&&strchr(debug_opt, 'v')!=NULL)
505 msg_cprintf(0, M_XLIST_BLOCKS, root->table->xlist_blocks);
506 if(root==&flist_main)
507 msg_cprintf(0, M_HASH_MATCHES, hash_matches, crc_matches);
509 if(root->storage==BST_FAR)
511 for(block=0; block<root->table->xlist_blocks; block++)
513 if(root->table->far_ptrs[block]!=NULL)
514 farfree(root->table->far_ptrs[block]);
516 farfree(root->table->far_ptrs);
518 else if(root->storage==BST_DISK&&root->table->sf_stream!=NULL)
520 fclose(root->table->sf_stream);
521 file_unlink(root->table->sf_name);
522 free(root->table->sf_name);
525 else if(root->storage==BST_XMS)
528 if(root->storage!=BST_NONE)
530 if(root->table->enumerators!=NULL)
531 farfree(root->table->enumerators);
532 if(root->table->hcrc!=NULL)
533 farfree(root->table->hcrc);
534 if(root->table->sec_cache!=NULL&&root->table->sec_cache!=root->table->cache)
535 farfree(root->table->sec_cache);
536 if(root->table->cache!=NULL)
537 farfree(root->table->cache);
539 if(root->fsptr!=NULL)
542 root->storage=BST_NONE;
545 #elif defined(REARJ) /* REARJ-only version of cleanup proc. */
547 void flist_cleanup_proc(struct flist_root *root)
553 for(i=0; i<root->files; i++)
554 farfree(root->names[i]);
555 for(i=0; i<root->d_files; i++)
556 farfree(root->d_names[i]);
557 farfree(root->names);
558 farfree(root->instances);
559 if(root->d_names!=NULL)
560 farfree(root->d_names);
561 if(root->checksums!=NULL)
562 farfree(root->checksums);
569 /* Retrieves a filename with given entry code from the list. Two implemenations
574 void retrieve_entry(char *dest, struct file_properties *properties, struct flist_root *root, FILE_COUNT entry)
576 struct idblock FAR *idblock_ptr; /* Temporary cache pointer */
577 struct disk_file_info FAR *dptr;
578 int idx; /* Temporary idblock index */
581 idblock_ptr=root->table->cache;
582 /* If there are unfreed locations, do neccessary cleanup */
583 if(!root->table->not_allocated)
585 if(root->table->hiblock<=0)
588 idblock_ptr=root->table->sec_cache;
592 for(curblock=0; curblock<=root->table->hiblock; curblock++)
594 if(root->table->enumerators[curblock]>entry)
599 get_heap_block(curblock, root);
601 idx=idblock_ptr->sub_offset[entry-root->table->enumerators[curblock]];
602 dptr=(struct disk_file_info FAR *)&idblock_ptr->filler[idx];
603 /* Allow NULL destinations for hardlink search -- ASR fix 24/08/2001 */
605 far_strcpy((char FAR *)dest, (char FAR *)dptr->name);
607 far_memmove((char FAR *)properties, (char FAR *)&dptr->file_properties, sizeof(struct file_properties));
612 /* Retrieves a filelist entry */
614 void retrieve_entry(char *dest, struct flist_root *root, FILE_COUNT num)
621 instance=root->instances[num];
622 far_strcpy((char FAR *)dest, root->d_names[instance-1]);
623 far_strcat((char FAR *)dest, root->names[num]);
625 far_strcpy((char FAR *)dest, root->names[num]);
631 /* Adds an entry to the hash. Returns -1 if there was an error. There are two
632 implementations of it. */
636 int add_entry(struct flist_root *root, char *name, FILE_COUNT *count, struct file_properties *properties)
638 struct idblock FAR *idblock_ptr;
639 struct disk_file_info FAR *dptr;
641 void FAR *tmp_ptr; /* Used for heap allocation test */
643 unsigned long tmp_crc;
644 long tmp_offset; /* Offset to fileinfo in blocks */
645 int new_blocks; /* New qty of XList blocks */
646 int old_blocks; /* Old qty of XList blocks */
647 int curblock; /* Cleanup loop variable */
648 int index; /* Index in ID block */
649 FILE_COUNT tmp_files;
651 int extend_len; /* Number of bytes to reserve */
653 if(root->files>=root->maxfiles)
655 #if SFX_LEVEL>=ARJSFXV
656 msg_cprintf(0, M_NAMES_LIMIT, root->maxfiles, name);
658 msg_cprintf(0, M_NAMES_LIMIT, root->maxfiles, name);
662 if((idblock_ptr=root->table->sec_cache)==NULL)
664 if(root->type!=FL_STANDARD)
665 root->table->sec_cache=farmalloc_msg(FLIST_BLOCK_SIZE);
667 root->table->sec_cache=root->table->cache;
668 idblock_ptr=root->table->sec_cache;
669 idblock_ptr->total_entries=0;
672 /* ASR fix -- debug enhancement 03/10/2001 */
673 if(debug_enabled&&strchr(debug_opt, '.')!=NULL)
674 msg_cprintf(0, M_TOKEN, name);
675 if(root->type!=FL_STANDARD&&root->no_dupl)
677 if(find_match(root, name))
684 tmp_hiblock=root->table->hiblock;
685 extend_len=strlen(name)+sizeof(struct file_properties);
686 tmp_files=root->files;
687 tmp_offset=(long)idblock_ptr->size;
688 /* Check against limits */
689 if(idblock_ptr->total_entries+1>ENTRIES_PER_BLOCK||(tmp_offset+(long)extend_len+1>(long)(FLIST_BLOCK_SIZE-sizeof(struct idblock)-2)))
691 save_heap_block(root, (char FAR *)root->table->sec_cache);
692 /* WARNING: compiler-dependent... */
694 if((tmp_ptr=farmalloc(FAR_PROBE))==NULL)
696 msg_cprintf(0, M_HASH_MEM_LACK, name);
701 /* If the far heap has overgrown its limits, relocate it to XMS ASAP */
702 if(root->storage==BST_FAR&&filelist_storage!=BST_NONE)
704 if(root->files>max_filenames||farcoreleft()<FAR_HEAP_LOWBOUND)
707 root->table->block_to_flush++;
709 /* Reallocate the block if it's needed */
710 if(tmp_hiblock+1>=root->table->xlist_blocks)
712 old_blocks=root->table->xlist_blocks;
713 root->table->xlist_blocks=new_blocks=old_blocks+FLIST_BLOCK_INCREMENT;
714 root->table->enumerators=farrealloc_msg(root->table->enumerators, (unsigned long)new_blocks*sizeof(unsigned long));
715 if(root->storage==BST_FAR)
717 root->table->far_ptrs=farrealloc_msg(root->table->far_ptrs, (unsigned long)new_blocks*sizeof(char FAR *));
718 /* Reset the newly created pointers to NULL */
719 for(curblock=old_blocks; curblock<new_blocks; curblock++)
720 root->table->far_ptrs[curblock]=NULL;
723 /* New block starts, with no file entries yet */
724 idblock_ptr->total_entries=0;
727 root->table->hiblock=tmp_hiblock;
728 root->table->enumerators[tmp_hiblock]=tmp_files;
729 root->table->enumerators[tmp_hiblock+1]=FLS_END;
731 root->table->not_flushed=1;
732 dptr=(struct disk_file_info FAR *)&idblock_ptr->filler[tmp_offset];
733 far_strcpy(dptr->name, (char FAR *)name);
735 far_memmove((char FAR *)&dptr->file_properties, (char FAR *)properties, sizeof(struct file_properties));
736 index=tmp_files-root->table->enumerators[tmp_hiblock];
737 idblock_ptr->sub_offset[index]=(int)tmp_offset;
738 idblock_ptr->size=tmp_offset+extend_len+1;
739 idblock_ptr->total_entries++;
741 if(root->type!=FL_STANDARD)
744 crc32_for_block(name, strlen(name));
746 update_hcrc(root, tmp_crc);
747 idblock_ptr->crc[index]=(char)tmp_crc;
757 int add_entry(struct flist_root *root, char *name, FILE_COUNT *count)
759 int add_entry(struct flist_root *root, struct flist_root *search_flist, char *name, FILE_COUNT *count)
763 char FAR * FAR *names_ptr;
766 unsigned int nblocks;
767 char FAR *checksums_ptr;
770 char tmp_name[CCHMAXPATH];
771 char pathname[CCHMAXPATH];
774 FILE_COUNT FAR *instances_ptr;
777 if(root->files>=root->maxfiles)
779 #if SFX_LEVEL>=ARJSFXV
780 msg_cprintf(0, M_NAMES_LIMIT, root->maxfiles, name);
782 msg_cprintf(0, M_NAMES_LIMIT, root->maxfiles, name);
787 if(root->check_excl&&is_excluded(name))
789 tmp_entry=split_name(name, NULL, tmp_name);
791 strncpy(pathname, name, tmp_entry);
792 pathname[tmp_entry]='\0';
793 dir_num=find_d_match(root, pathname);
794 if(root->no_dupl&&dir_num!=0&&find_match(root, tmp_name, dir_num))
797 if(root->no_dupl&&find_match(root, name))
804 /* Separate directory storage is available in (and required by) REARJ only */
808 if(root->d_files>=root->d_boundary)
810 diff=(long)root->maxfiles-root->d_files;
812 diff+=(long)root->d_files;
813 if((names_ptr=(char FAR * FAR *)farrealloc(root->d_names, diff*sizeof(char FAR *)))==NULL)
815 #if SFX_LEVEL>=ARJSFXV
816 msg_cprintf(0, M_HASH_MEM_LACK, name);
818 msg_cprintf(0, M_HASH_MEM_LACK, name);
822 root->d_names=names_ptr;
823 root->d_boundary=(FILE_COUNT)diff;
826 if((nptr=(char FAR *)farmalloc(nl+1))==NULL)
828 #if SFX_LEVEL>=ARJSFXV
829 msg_cprintf(0, M_HASH_MEM_LACK, name);
831 msg_cprintf(0, M_HASH_MEM_LACK, name);
835 root->d_names[root->d_files]=nptr;
836 far_strcpy(nptr, (char FAR *)pathname);
837 dir_num=++root->d_files;
840 if(root->files>=root->boundary)
842 nblocks=root->maxfiles/FILES_PER_BLOCK;
843 if(nblocks>BLOCKS_LIMIT)
844 nblocks=BLOCKS_LIMIT;
845 diff=(long)root->maxfiles-root->files;
846 if((long)nblocks<diff)
848 diff+=(long)root->files;
849 if((names_ptr=(char FAR * FAR *)farrealloc(root->names, diff*sizeof(char FAR *)))==NULL)
851 #if SFX_LEVEL>=ARJSFXV
852 msg_cprintf(0, M_HASH_MEM_LACK, name);
854 msg_cprintf(0, M_HASH_MEM_LACK, name);
861 if((checksums_ptr=(char FAR *)farrealloc(root->checksums, diff*sizeof(FILE_COUNT)))==NULL)
863 #if SFX_LEVEL>=ARJSFXV
864 msg_cprintf(0, M_HASH_MEM_LACK, name);
866 msg_cprintf(0, M_HASH_MEM_LACK, name);
872 if((instances_ptr=(FILE_COUNT FAR *)farrealloc(root->instances, diff*sizeof(FILE_COUNT)))==NULL)
874 #if SFX_LEVEL>=ARJSFXV
875 msg_cprintf(0, M_HASH_MEM_LACK, name);
877 msg_cprintf(0, M_HASH_MEM_LACK, name);
882 root->names=names_ptr;
883 root->checksums=checksums_ptr;
885 root->instances=instances_ptr;
887 root->boundary=(FILE_COUNT)diff;
894 if((nptr=(char FAR *)farmalloc(nl+1))==NULL)
896 #if SFX_LEVEL>=ARJSFXV
897 msg_cprintf(0, M_HASH_MEM_LACK, name);
899 msg_cprintf(0, M_HASH_MEM_LACK, name);
904 root->names[nfiles]=nptr;
906 far_strcpy(nptr, (char FAR *)tmp_name);
908 far_strcpy(nptr, (char FAR *)name);
911 root->instances[nfiles]=dir_num;
913 root->checksums[nfiles]=checksum(tmp_name);
916 root->checksums[nfiles]=checksum(name);
926 /* Initializes the filelist storage */
929 void flist_init_proc(struct flist_root *root, FILE_COUNT maxfiles, char type)
931 void flist_init(struct flist_root *root, FILE_COUNT maxfiles, int no_dupl, int check_excl)
933 void flist_init(struct flist_root *root, FILE_COUNT maxfiles, char no_dupl)
937 int curblock, cur_entry;
940 root->storage=BST_NONE;
941 root->maxfiles=maxfiles;
949 if(root==&flist_main)
950 hash_matches=crc_matches=0;
951 if(debug_enabled&&strchr(debug_opt, 'v')!=NULL)
952 msg_cprintf(0, M_SEARCH_FLAG, type);
953 root->table=malloc_msg(sizeof(struct flist_table));
955 if(detect_xms()&&filelist_storage==BST_XMS)
957 root->storage=BST_XMS;
959 if(!xms_malloc(XMS_BLOCK_PREALLOC*FLIST_BLOCK_SIZE, root))
960 error(M_LISTING_XMS_ERROR, M_XMS_INIT);
961 root->table->xms_mem_blocks=XMS_BLOCK_PREALLOC;
965 if(filelist_storage!=BST_NONE&&max_filenames<50)
967 root->storage=BST_DISK;
968 root->table->sf_stream=NULL;
972 root->storage=BST_FAR;
973 root->table->far_ptrs=farmalloc_msg((unsigned long)FLIST_BLOCK_INCREMENT*sizeof(void FAR *));
974 for(curblock=0; curblock<FLIST_BLOCK_INCREMENT; curblock++)
975 root->table->far_ptrs[curblock]=NULL;
977 root->table->cache=farmalloc_msg(FLIST_BLOCK_SIZE);
978 root->table->sec_cache=NULL;
979 root->table->block=-1;
980 root->table->block_to_flush=0;
981 root->table->low_block=0;
982 root->table->not_flushed=0;
983 root->table->not_allocated=0;
984 root->table->xlist_blocks=FLIST_BLOCK_INCREMENT;
985 root->table->enumerators=farmalloc_msg((unsigned long)FLIST_BLOCK_INCREMENT*sizeof(FILE_COUNT));
986 root->table->enumerators[0]=0;
987 root->table->enumerators[1]=FLS_END;
988 root->table->hiblock=0;
989 root->table->hcrc=NULL;
990 flist_capacity=FILELIST_CAPACITY;
991 if(debug_enabled&&(cptr=strchr(debug_opt, 'z'))!=NULL)
992 flist_capacity=(FILE_COUNT)strtol(cptr, &cptr, 10);
993 if(root->type!=FL_STANDARD)
995 root->table->hcrc=farmalloc_msg((FILE_COUNT)flist_capacity);
996 for(cur_entry=0; cur_entry<flist_capacity; cur_entry++)
997 root->table->hcrc[cur_entry]=0;
1000 root->maxfiles=maxfiles;
1001 root->no_dupl=(int)no_dupl;
1004 root->checksums=NULL;
1007 root->check_excl=check_excl;
1011 root->instances=NULL;
1016 #if SFX_LEVEL>=ARJ&&TARGET==UNIX
1018 /* [Hard]link search routine. Either returns a pointer to an existing
1019 entry in l_search structure, or creates a new entry. May operate
1020 with symlinks too (e.g. elimination of circular links) */
1022 FILE_COUNT link_search(struct l_entries *entries, struct l_search *l_search, struct file_properties *properties, FILE_COUNT ref)
1026 for(i=0; i<entries->total; i++)
1028 /* The refcount values are not compared, since these may vary */
1029 if(!far_memcmp(&l_search->dev, (void FAR *)&entries->list[i].dev, sizeof(dev_t))&&
1030 l_search->inode==entries->list[i].inode)
1032 if(properties!=NULL)
1034 properties->islink=1;
1035 properties->l_search.ref=entries->list[i].ref;
1036 properties->type=ARJT_UXSPECIAL;
1037 properties->fsize=0L;
1042 if(entries->total>=entries->alloc)
1044 entries->alloc+=L_ENTRIES_INCREMENT;
1045 entries->list=(struct l_search FAR *)farrealloc_msg(entries->list, entries->alloc*sizeof(struct l_search));
1047 entries->list[i]=*l_search;
1048 entries->list[i].ref=ref;