2
* $Id: misc.c,v 1.5 2004/05/31 16:08:41 andrew_belov Exp $
3
* ---------------------------------------------------------------------------
4
* Various system-independent routines are kept here. This module is needed if
5
* the ENVIRON.C is linked, since both of them cross-reference each other.
11
DEBUGHDR(__FILE__) /* Debug information block */
13
/* Compact filelist array */
15
#if SFX_LEVEL>=ARJSFXV
16
static unsigned char FAR * FAR *flist_array=NULL;
17
static FILE_COUNT cfa_allocated; /* # of allocated blocks */
20
/* Extended wildcard specifiers */
22
static char xwild_symbols[]="?*[]^";
24
/* Forward references */
26
static int xwild_propagate(char *wcstr, char *str);
30
/* Dumb extended wildcard lookup routine */
32
static int xwild_lookup(char *str)
37
for(p=str; *p!='\0'; p++)
40
if(c=='*'||c=='?'||c=='['||c=='^')
46
/* An extended wildcard parser */
48
static int xwild_parser(char *wcstr, int *rc)
54
for(p=wcstr; *p!='\0'; p++)
121
/* Extended wildcard expansion and matching routine */
123
static int xwild_match(char *wcstr, char *str)
132
char xc, xpc; /* Wildcard processed characters */
139
return((*wptr=='*'&&*++wptr=='\0')?XW_OK:XW_OWC);
144
return(xwild_propagate(wptr, sptr));
159
c=(*wptr=='^')?*++wptr:*wptr; /* Escape character */
180
if((xpc>=xc&&sc>=xc&&sc<=xpc)||(sc>=xpc&&sc<=xc))
189
if((xchar!=0&&unproc)||(xchar==0&&!unproc))
193
/* Skip the rest, applying usual check-ups */
207
break; /* Skip the comparison */
212
default: /* fallthru */
213
if(toupper(*wptr)!=toupper(*sptr))
220
return((*sptr=='\0')?XW_OK:XW_PREM_END);
223
/* Propagates (expands) wildcard markers */
225
static int xwild_propagate(char *wcstr, char *str)
230
while(*wcstr=='?'||*wcstr=='*')
243
if((c=*++wcstr)=='\0')
248
if(toupper(c)==toupper(*str)||c=='[')
249
rc=xwild_match(wcstr, str);
252
} while(rc!=XW_OK&&rc!=XW_OWC&&rc!=XW_TERM);
256
/* Wildcard matching routine wrapper (provides boolean RCs) */
258
static int xwild_compare(char *wcstr, char *str)
262
xrc=xwild_match(wcstr, str);
263
return((xrc==XW_OK)?XW_OK:XW_NONE);
266
/* Change all UNIX-style path specifiers to DOS-style ones in a given string */
268
void unix_path_to_dos(char *path)
271
if(translate_unix_paths)
275
if(path[i]==PATHSEP_UNIX)
276
path[i]=PATHSEP_DEFAULT;
284
#if SFX_LEVEL>=ARJSFXV
286
/* Allocate a block of memory that will exactly fit the length of string,
287
and copy the string into this newly-created block. */
289
void *malloc_str(char *str)
291
return(strcpy((char *)malloc_msg(strlen(str)+1), str));
298
/* The same as malloc_str, but it allocates near memory for far strings */
300
void *malloc_far_str(char FAR *str)
304
k=malloc_msg(far_strlen(str)+1);
305
far_strcpy((char FAR *)k, str);
313
/* Converts current time to a standard timestamp */
315
void cur_time_stamp(struct timestamp *dest)
319
cur_unixtime=time(NULL);
320
ts_store(dest, OS_UNIX, cur_unixtime);
323
/* A strchr() function for far strings */
325
#if COMPILER!=MSC&&defined(TILED)
326
char FAR *far_strchr(char FAR *str, char chr)
330
if(str[0]=='\0') return(NULL);
339
#if SFX_LEVEL>=ARJSFXV||defined(REARJ)
341
/* A strcmp() function for far strings */
343
#if COMPILER!=MSC&&defined(TILED)
344
int far_strcmp(char FAR *str1, char FAR *str2)
348
for(k=0; str1[k]!='\0'&&str2[k]!='\0'; k++);
349
return((int)(str1[k]-str2[k]));
353
/* A stricmp() function for far strings */
355
#if COMPILER!=MSC&&defined(TILED)
356
int far_stricmp(char FAR *str1, char FAR *str2)
360
for(k=0; toupper(str1[k]!='\0')&&toupper(str2[k]!='\0'); k++);
361
return(toupper(str1[k])-toupper(str2[k]));
367
#if SFX_LEVEL>=ARJ||defined(REARJ)
369
/* A strcat() function for far strings */
371
#if COMPILER!=MSC&&defined(TILED)
372
char FAR *far_strcat(char FAR *dest, char FAR *src)
377
while(tmp_dest[0]!='\0')
380
(tmp_dest++)[0]=src[0];
381
while((src++)[0]!='\0');
388
#if SFX_LEVEL>=ARJSFXV||defined(REARJ)
390
/* A strcpy() function for far strings */
392
#if COMPILER!=MSC&&defined(TILED)
393
char FAR *far_strcpy(char FAR *dest, char FAR *src)
397
for(k=0; src[k]!='\0'; k++)
408
/* A strlen() function for far strings */
410
#if COMPILER!=MSC&&defined(TILED)
411
unsigned int far_strlen(char FAR *str)
423
#if SFX_LEVEL>=ARJSFXV
425
/* Fills a buffer with the specified value */
427
#if COMPILER!=MSC&&defined(TILED)
428
void FAR *far_memset(void FAR *buf, int filler, unsigned int size)
434
for(l=0; l<size; l++)
442
#if SFX_LEVEL>=ARJSFXV
444
/* Copies at most n characters */
446
char FAR *far_strcpyn(char FAR *dest, char FAR *src, int limit)
450
for(k=1; k<limit&&src[0]!='\0'; k++)
452
(dest++)[0]=(src++)[0];
461
#if SFX_LEVEL>=ARJSFX
463
/* Converts the given string to 7-bit */
465
void to_7bit(char *str)
473
#if SFX_LEVEL>=ARJSFX||defined(REARJ)
475
/* Convert a string to uppercase, depending on locale */
477
void strupper(char *s)
479
#if SFX_LEVEL>=ARJSFXV||defined(REARJ)
480
toupper_loc(s, strlen(s));
492
#if SFX_LEVEL>=ARJSFXV
494
/* Convert a string to lowercase (note: no locale hack here - the one in
495
strupper() was made exclusively for filename matching under DOS) */
497
void strlower(char *s)
510
/* Finds an entry in the filelist, returns 1 if matched. Wildcards allowed. */
512
int flist_find(struct flist_root *root, char *name)
514
char tmp_name[FILENAME_MAX]; /* Hash filename storage */
515
char n_path[FILENAME_MAX], f_path[FILENAME_MAX];
518
int tmp_pathname_length;
522
pathname_length=split_name(name, n_path, NULL);
523
for(entry=0; entry<root->files; entry++)
525
flist_retrieve(tmp_name, NULL, root, entry);
526
tmp_pathname_length=split_name(tmp_name, f_path, NULL);
527
if(marksym_expansion)
529
if(tmp_pathname_length!=0&&strlen(tmp_name)==tmp_pathname_length&&xwild_compare(f_path, n_path)==XW_OK)
531
if(tmp_pathname_length==0||xwild_compare(f_path, n_path)==XW_OK)
533
if(xwild_compare(tmp_name+tmp_pathname_length, name+pathname_length)==XW_OK)
539
/* If it was a directory specification, return OK */
540
if(tmp_pathname_length!=0&&strlen(tmp_name)==tmp_pathname_length&&!strncmp_os(tmp_name, name, tmp_pathname_length))
542
/* For filename specifications, proceed with compare */
543
if(tmp_pathname_length==0||(tmp_pathname_length==pathname_length&&!strncmp_os(tmp_name, name, tmp_pathname_length)))
544
if(match_wildcard(&name[pathname_length], &tmp_name[tmp_pathname_length]))
551
/* Checks if a file already exists in the archive */
553
int flist_is_in_archive(struct flist_root *root, char *name)
555
char tmp_name[CCHMAXPATHCOMP]; /* For names retrieved from the hash */
556
char case_name[CCHMAXPATHCOMP]; /* and for converting them to u-case */
559
for(entry=0; entry<root->files; entry++)
561
if(cfa_get(entry)==FLFLAG_PROCESSED)
563
flist_retrieve(tmp_name, NULL, root, entry);
564
default_case_path(case_name, tmp_name);
565
if(!stricmp(name, case_name))
572
/* Returns 1 if the file properties given match the current search narrowing
573
criteria (such as "same or newer", and so on) */
575
int match_attrib(struct file_properties *properties)
579
/* First, check if the attributes match */
583
if(file_attr_mask&TAG_DIREC&&properties->type==ARJT_DIR)
585
if(file_attr_mask&TAG_UXSPECIAL&&properties->type==ARJT_UXSPECIAL)
587
if(file_attr_mask&TAG_NORMAL&&
588
!(properties->attrib&FATTR_DIREC)&&
589
!(properties->attrib&FATTR_RDONLY)&&
590
!(properties->attrib&FATTR_SYSTEM)&&
591
!(properties->attrib&FATTR_HIDDEN)&&
592
properties->type!=ARJT_UXSPECIAL)
594
if(file_attr_mask&TAG_RDONLY&&properties->attrib&FATTR_RDONLY)
596
if(file_attr_mask&TAG_HIDDEN&&properties->attrib&FATTR_HIDDEN)
598
if(file_attr_mask&TAG_SYSTEM&&properties->attrib&FATTR_SYSTEM)
600
if(file_attr_mask&TAG_ARCH&&!(properties->attrib&FATTR_ARCH))
602
if(file_attr_mask&TAG_NOT_ARCH&&properties->attrib&FATTR_ARCH)
607
if(filter_fa_arch==FAA_BACKUP||filter_fa_arch==FAA_BACKUP_CLEAR)
609
if(!properties->isarchive)
612
/* Now, check the file against the time limits for it */
614
if(ts_valid(tested_ftime_newer)&&(filter_same_or_newer==TCHECK_NDAYS||filter_same_or_newer==TCHECK_FTIME))
616
if(properties->ftime<ts_native(&tested_ftime_newer, OS))
619
if(ts_valid(tested_ftime_older)&&(filter_older==TCHECK_NDAYS||filter_older==TCHECK_FTIME))
621
if(properties->ftime>=ts_native(&tested_ftime_older, OS))
625
if(ts_valid(tested_ftime_newer)&&filter_same_or_newer==TCHECK_CTIME)
627
if(properties->ctime<ts_native(&tested_ftime_newer, OS))
630
if(ts_valid(tested_ftime_older)&&filter_older==TCHECK_CTIME)
632
if(properties->ctime>=ts_native(&tested_ftime_older, OS))
636
if(ts_valid(tested_ftime_newer)&&filter_same_or_newer==TCHECK_ATIME)
638
if(properties->atime<ts_native(&tested_ftime_newer, OS))
641
if(ts_valid(tested_ftime_older)&&filter_older==TCHECK_ATIME)
643
if(properties->atime>=ts_native(&tested_ftime_older, OS))
649
/* Frees memory allocated for the hash table */
651
void flist_cleanup(struct flist_root *root)
653
flist_cleanup_proc(root);
656
/* Adds an entry to the filelist if it does not already exist. Returns -1 if
659
int flist_add(struct flist_root *root, struct flist_root *search_flist, char *name, FILE_COUNT *count, struct file_properties *properties)
663
if(search_flist!=NULL)
665
/* If an existing entry has been found, don't add anything */
666
if(flist_find(search_flist, name))
673
if(root!=NULL&&root->fsptr!=NULL&&!xwild_compare(root->fsptr, name))
679
if(properties!=NULL&&root==&flist_main&&!match_attrib(properties))
686
/* Resolve hard links if there are any */
687
if(properties!=NULL&&
688
properties->l_search.refcount>1&&
690
link_search(&l_entries, &properties->l_search, properties, root->files);
692
return(add_entry(root, name, count, properties));
695
/* Initializes the filelist storage structures */
697
void flist_init(struct flist_root *root, FILE_COUNT maxfiles, char type)
699
flist_init_proc(root, maxfiles, type);
702
/* Retrieves an entry from the filelist */
704
void flist_retrieve(char *dest, struct file_properties *properties, struct flist_root *root, FILE_COUNT entry)
706
retrieve_entry(dest, properties, root, entry);
709
/* Converts an extended wildcard to canonical wildcard */
711
static void xwild_to_canonical(char *name)
717
tmp_name=malloc_str(name);
718
xwptr=strpbrk(tmp_name, xwild_symbols);
722
entry=split_name(tmp_name, NULL, NULL);
725
tmp_name[entry-1]='\0';
726
sprintf(name, "%s%c%s", tmp_name, PATHSEP_DEFAULT, all_wildcard);
729
strcpy(name, all_wildcard);
736
#if SFX_LEVEL>=ARJSFXV
738
/* Expands wildcards and prepares a file list */
740
int flist_add_files(struct flist_root *root, struct flist_root *search_flist, char *name, int expand_wildcards, int recurse_subdirs, int file_type, FILE_COUNT *count)
749
if(expand_wildcards&&marksym_expansion&&xwild_lookup(name)==XW_OK&&
750
xwild_parser(name, &parse_rc)==XW_OK)
752
/* ASR fix for variable all_wildcard length follows: */
753
tmp_name=(char *)malloc_msg(strlen(name)+strlen(all_wildcard)+1);
754
strcpy(tmp_name, name);
755
root->fsptr=malloc_str(tmp_name);
756
xwild_to_canonical(tmp_name);
757
result=wild_list(root, search_flist, tmp_name, expand_wildcards, recurse_subdirs, file_type, count);
763
result=wild_list(root, search_flist, name, expand_wildcards, recurse_subdirs, file_type, count);
767
if((tmp_name=(char *)malloc(strlen(name)+1))==NULL)
769
msg_cprintf(0, M_HASH_MEM_LACK, name);
775
strcpy(tmp_name, name);
777
if(add_entry(root, search_flist, tmp_name, count))
785
#if SFX_LEVEL>=ARJSFXV
787
/* Returns pointer to the idx-th element, enlarging the CFA if required */
789
static unsigned char FAR *cfa_get_index(FILE_COUNT idx)
793
if(flist_array==NULL)
795
fblock=idx/CFA_BLOCK_SIZE;
796
/* Enlarge the CFA */
797
if(fblock>=cfa_allocated)
799
flist_array=(unsigned char FAR * FAR *)
802
(fblock+1)*sizeof(char FAR *)
804
while(cfa_allocated<=fblock)
805
flist_array[cfa_allocated++]=NULL;
807
/* Allocate a new block if it has been empty before */
808
if(flist_array[fblock]==NULL)
809
flist_array[fblock]=(char FAR *)farmalloc_msg((CFA_BLOCK_SIZE+3)>>2);
810
return(flist_array[fblock]+((idx%CFA_BLOCK_SIZE)>>2));
813
/* Releases the CFA structure */
819
if(flist_array!=NULL)
821
for(i=0; i<cfa_allocated; i++)
823
if(flist_array[i]!=NULL)
825
farfree(flist_array[i]);
829
farfree(flist_array);
834
/* Retrieves a CFA element */
836
int cfa_get(FILE_COUNT num)
839
unsigned char bit_mask, value_bits;
841
pos_num=(int)(num%4)<<1;
842
bit_mask=(unsigned char)3<<pos_num;
843
value_bits=*cfa_get_index(num)&bit_mask;
844
return(value_bits>>pos_num);
847
/* Stores an element in the CFA */
849
void cfa_store(FILE_COUNT num, int value)
852
unsigned char bit_mask, value_bits;
853
unsigned char FAR *p;
855
pos_num=(int)(num%4)<<1;
856
bit_mask=(unsigned char)3<<pos_num;
857
value_bits=(unsigned char)value<<pos_num;
858
p=cfa_get_index(num);
859
*p=(*p&=~bit_mask)|value_bits;
862
/* Initializes the CFA structures */
864
int cfa_init(FILE_COUNT capacity)
869
bytes=(unsigned long)capacity>>2;
870
flist_array=farmalloc_msg(bytes+1);
871
for(i=0; i<capacity; i++)
872
cfa_store(i, FLFLAG_TO_PROCESS);
873
return(0); /* ASR fix for High C -- 01/04/2001 */
878
/* Allocates a block of memory, executes error stub if failed */
880
void *malloc_msg(unsigned int size)
885
if(debug_enabled&&strchr(debug_opt, 'm')!=NULL)
886
printf("(Nm%u", size);
888
if((tmp=malloc(size))==NULL)
889
error(M_OUT_OF_NEAR_MEMORY);
891
if(debug_enabled&&strchr(debug_opt, 'm')!=NULL)
899
#if SFX_LEVEL>=ARJSFXV||defined(ARJUTIL)
901
/* Allocates a block of far memory, executes error stub if failed.
902
Implementation-dependent (farmalloc for Borland, _fmalloc for MS C) */
904
void FAR *farmalloc_msg(unsigned long size)
908
#if defined(DEBUG)&&!defined(ARJUTIL)
909
if(debug_enabled&&strchr(debug_opt, 'm')!=NULL)
910
printf("(Fm%u", size);
912
if((tmp=farmalloc(size))==NULL)
915
printf("Failed to farmalloc(%lu)\n", size);
919
error(M_OUT_OF_MEMORY);
921
#if defined(DEBUG)&&!defined(ARJUTIL)
922
if(debug_enabled&&strchr(debug_opt, 'm')!=NULL)
930
#if SFX_LEVEL>=ARJSFX
932
/* Reallocates a block of far memory, executes error stub if failed.
933
Implementation-dependent (farrealloc for Borland, _frealloc for MS C) */
935
void FAR *farrealloc_msg(void FAR *memblock, unsigned long size)
939
if((tmp=farrealloc(memblock, size))==NULL)
940
error(M_OUT_OF_MEMORY);
948
/* Replaces all LF characters with 0's, returning the end of string */
950
char *tokenize_lf(char *str)