/*------------------------------- /* SOURCE FILE NAME: RTOLD1.C /*------------------------------- /*  0 */ #include "rt.h" #include "rt1.h" #include "rt2.h" #include "restpars.h" /*;AN000;4*/ #include "string.h" #include "dos.h" /*;AN000;2*/ #include "comsub.h" /* common subroutine def'n */ #include "doscalls.h" #include "error.h" #include "stdio.h" extern BYTE rtswitch; extern BYTE control_flag; extern BYTE control_flag2; extern char far *buf_pointer; extern unsigned src_file_handle; extern struct FileFindBuf filefindbuf; extern struct FileFindBuf dfilefindbuf; BYTE src_fname[MAXFNAME]; extern struct subst_list sublist; /*;AN000;6 Message substitution list */ extern char response_buff[5]; /*;AN000;6*/ struct file_header_old fheadold; /*;AN000;*/ /***************** START OF SPECIFICATION ******************************** /* /* SUBROUTINE NAME : pathmatch /* /* DESCRIPTIVE NAME : Compare two paths and return TRUE or FALSE /* according to whether they match or not. /* /* NOTES: Global characters * and ? are meaningless in the file path name /* Assume both path pattern and path subject are not end with \ /* /* INPUT: (PARAMETERS) /* subject - the file path to be compared. /* pattern - the file path to be compared against. /* /********************** END OF SPECIFICATIONS *******************************/ WORD pathmatch(patterns,subjects) BYTE *patterns; /* the string to be matched with */ BYTE *subjects; /* the string to be matched */ { BYTE *pattern; /* the working pointer to point to the pattern */ BYTE *subject; /* the working pointer to point to the subject */ int z; /*save the pointers to both strings*/ pattern = patterns; subject = subjects; /* loop until matched or unmatched is determined */ for (;;) { if (*pattern == *subject) { if (*pattern != NULLC) /* not finish scanning yet*/ { pattern+=1; /* advance the pointer by 1 */ subject+=1; /* advance the pointer by 1 */ continue; /* continue on comparing again */ } else return(TRUE); } else { /* if subject is longer than pattern and SUB flag in rtswitches is on */ if (set_reset_test_flag(&rtswitch, SUB, TEST)==TRUE) { if ((*pattern == NULLC && *subject == '\\') || (patterns[0] == '\\' && patterns[1] == NULLC)) return(TRUE); else return(FALSE); } else return(FALSE); } } return(TRUE); /*;AN000;*/ } /***************** START OF SPECIFICATION ******************************** /* /* SUBROUTINE NAME : fspecmatch /* /* DESCRIPTIVE NAME : Compare two file spec. and return TRUE or FALSE /* according to whether they match or not. /* /* FUNCTION: This subroutine compare the file names and file extensions /* to determine whether they are match or not. /* TRUE is returned if they are match, otherwise, FALSE /* is returned. /* /* NOTES: * and ? are acceptable in the file name and file extension. /* /********************** END OF SPECIFICATIONS *******************************/ fspecmatch(patterns, subjects) char *patterns; char *subjects; { char *pattern; char *subject; int z; pattern = patterns; subject = subjects; for (;;) { if (*pattern == '*') { /*advance pointer in pattern until find '.' or nullc*/ for (;*pattern != '.' && *pattern != NULLC; ++pattern); if (*pattern == NULLC) { /* pattern has no extension, so make sure subject doesn't either */ /* find end or '.' in subject */ for (;*subject != '.' && *subject != NULLC; ++subject); if (*subject == NULLC || *(subject+1) == '.') return(TRUE); else /* subject has extension, so return FALSE */ return(FALSE); } else { if ( *(pattern+1) == '*') return(TRUE); else { /*advance pointer in subject until find '.' or nullc*/ for (;*subject != '.' && *subject != NULLC; ++subject); if (*subject == NULLC ) { if (*(pattern+1) != NULLC) return(FALSE); else return(TRUE); } else { pattern+=1; subject+=1; continue; } /*end of if *subject is not NULL*/ } /*end of if *(pattern+1) is not '*' */ } /*end of if *pattern == NULLC */ } else { if (*pattern == *subject || *pattern == '?') { if (*pattern != NULLC) { pattern+=1; subject+=1; continue; } else return(TRUE); } else if (*pattern == '.' && *(pattern+1) == '*' && *subject == NULLC) return(TRUE); else return(FALSE); } } /*end of for loop*/ } /*end of subroutine */ /***************** START OF SPECIFICATION ******************************** /* /* SUBROUTINE NAME : switchmatch /* /* DESCRIPTIVE NAME : Check the file attributes, and/or file modes /* against the switches set in the input command /* line. /* /* FUNCTION: this subroutine search the hard disk for the dest /* file first. If dest file is found, the attributs of the /* destination file will be used for checking. /* /* Check the switches set in the input command line one by /* one, whenever a switch not match is found, FALSE is returne /* In the case a switch is match, TRUE is not returned until al /* switches is checked. /* /* /********************** END OF SPECIFICATIONS *******************************/ WORD switchmatch(finfo, srcd, destd, td) struct file_info *finfo; BYTE srcd; BYTE destd; struct timedate *td; { WORD yy; WORD mm; WORD dd; WORD hh; WORD mn; WORD ss; WORD action; unsigned file_pointer; WORD retcode; int z; /*declaration for dosqfileinfo*/ struct FileStatus fileinfo_buf; WORD destdnum; WORD buflen = sizeof(struct FileStatus); unsigned attributes; /*declaration for dosfindfirst */ unsigned ddirhandle = 0xffff; unsigned attribute = NOTV; unsigned search_cnt = 1; unsigned buf_len = sizeof(struct FileFindBuf); BYTE search_string[MAXPATHF+2]; /*end decleration for ffirst and fnext*/ /***********************************************************************/ /* Search hard file for the path and name of file about to be restored */ /* and get the file information of the file on the hard disk */ /***********************************************************************/ search_string[0] = destd; search_string[1] = ':'; search_string[2] = NULLC; strcat(search_string, finfo->path); if (strlen(finfo->path) != 1) strcat(search_string, "\\"); strcat(search_string, finfo->fname); retcode = DOSOPEN( (char far *)&search_string[0], (unsigned far *)&file_pointer, (unsigned far *)&action, (DWORD)0, /*file size*/ 0, /*file attribute*/ 0x01, /*if file exist, open*/ /*if file not exist, fail*/ 0x00c0, /*deny write, read write access*/ (DWORD)0 ); /*reserved*/ /***********************************************************************/ /*if open fail (means the file does not exist on the hard disk), then */ /* return true */ /***********************************************************************/ if (retcode != NOERROR) { /*set flag CREATIT*/ set_reset_test_flag(&control_flag,CREATIT,SET); /*return TRUE*/ return (TRUE); } /*********************************************************************/ /* call DosQFileInfo: Request date and time of the dest file */ /*********************************************************************/ retcode = DOSQFILEINFO ( (unsigned)file_pointer, /* File handle */ (unsigned)1, /* File info data required */ (char far *)&fileinfo_buf, /* File info buffer */ (unsigned)buflen); /* File info buffer size */ if (retcode != NOERROR) { com_msg(retcode); unexperror(retcode); } if ((retcode = DOSQFILEMODE((char far *)&search_string[0], (unsigned far *) &attributes, (DWORD) 0)) !=0) { com_msg(retcode); unexperror(retcode); } DOSCLOSE(file_pointer); /***********************************************************************/ /*if NOTEXIST flag is on */ /***********************************************************************/ if (set_reset_test_flag(&rtswitch,NOTEXIST,TEST) == TRUE) { return(FALSE); } /***********************************************************************/ /*if BEFORE or AFTER is on, convert date into integer form */ /***********************************************************************/ if (set_reset_test_flag(&rtswitch,BEFORE,TEST) == TRUE || set_reset_test_flag(&rtswitch,AFTER,TEST) == TRUE ) { /*convert the input date into correct numbers.*/ /*Both new and old format have date in the form of date returned from*/ /*ffirst*/ /*the input date is in the form of: yyyyyyymmmmddddd*/ yy = (fileinfo_buf.write_date >> YRSHIFT & YRMASK) + LOYR; mm = fileinfo_buf.write_date >> MOSHIFT & MOMASK; dd = fileinfo_buf.write_date & DYMASK; } /*endif*/ /***********************************************************************/ /*if BEFORE flag is on */ /***********************************************************************/ if (set_reset_test_flag(&rtswitch,BEFORE,TEST) == TRUE) { if ( yy > td->before_year ) { return(FALSE); } if (yy == td->before_year && mm > td->before_month) { return(FALSE); } if (yy == td->before_year && mm == td->before_month && dd > td->before_day) { return(FALSE); } } /*endif*/ /***********************************************************************/ /*if AFTER flag is on */ /***********************************************************************/ if (set_reset_test_flag(&rtswitch,AFTER,TEST) == TRUE) { if (yy < td->after_year ) { return(FALSE); } if (yy == td->after_year && mm < td->after_month) { return(FALSE); } if (yy == td->after_year && mm == td->after_month && dd < td->after_day) { return(FALSE); } } /*endif*/ /***********************************************************************/ /*if EARLIER or LATER is on, convert date time into integer form */ /***********************************************************************/ if (set_reset_test_flag(&rtswitch,EARLIER,TEST) == TRUE || set_reset_test_flag(&rtswitch,LATER,TEST) == TRUE) { /* convert the input time into correct numbers. */ /* Both new and old format have time in the form of date returned */ /* from ffirst. */ /* the input time is in the form of: hhhhhmmmmmmsssss */ hh = fileinfo_buf.write_time >> HRSHIFT & HRMASK; mn = fileinfo_buf.write_time >> MNSHIFT & MNMASK; ss = fileinfo_buf.write_time & SCMASK; } /*endif*/ /***********************************************************************/ /*if EARLIER flag is on */ /***********************************************************************/ if (set_reset_test_flag(&rtswitch,EARLIER,TEST) == TRUE) { if (hh > td->earlier_hour) { return(FALSE); } if (hh == td->earlier_hour && mn > td->earlier_minute) { return(FALSE); } if (hh == td->earlier_hour && mn == td->earlier_minute && ss > td->earlier_second) { return(FALSE); } } /*endif*/ /***********************************************************************/ /*if LATER flag is on */ /***********************************************************************/ if (set_reset_test_flag(&rtswitch,LATER,TEST) == TRUE) { if (hh < td->later_hour) { return(FALSE); } if (hh == td->later_hour && mn < td->later_minute) { return(FALSE); } if (hh == td->later_hour && mn == td->later_minute && ss < td->later_second) { return(FALSE); } } /*endif*/ /*************************************************************************/ /* if Revised flag is on and fileinfo->attrib indicate file has not */ /* been Revised, return FALSE */ /*************************************************************************/ if (set_reset_test_flag(&rtswitch,Revised,TEST) == TRUE) { if((retcode = attributes & 0x0020) != 0x0020) { return(FALSE); } } /*endif*/ /***********************************************************************/ /* if PROMPT and fileinfo->file_attrib indicate READONLY, or CHANGED*/ /***********************************************************************/ if ((set_reset_test_flag(&rtswitch,PROMPT,TEST) == TRUE) && (((retcode = attributes & 0x0001) == 0x0001) || ((retcode = attributes & 0x0020) == 0x0020) )) { /*call subroutine to ask whether the user really wants to restore */ retcode = readonly_or_changed(attributes,destd,finfo->fname,finfo->path); if (retcode == FALSE) { return(FALSE); } /*endif*/ } /*endif*/ /***********************************************************************/ /* if pass all the switch testing, return TRUE */ /***********************************************************************/ return(TRUE); } /*end of subroutine switch_match */ /***************** START OF SPECIFICATION ******************************** /* /* SUBROUTINE NAME : check_flheader_old /* /* DESCRIPTIVE NAME : Check the information in the file header of /* the file to be restored. /* /* FUNCTION: For old format only, Open the file to be restored, get /* header informtion /* /* /********************** END OF SPECIFICATIONS *******************************/ int check_flheader_old ( finfo,f_name,f_date,f_time,f_attrib,f_len, file_seq_num,srcd,destd,infspec,inpath,dnumwant ) struct file_info *finfo; unsigned char *f_name; /* name string */ unsigned f_date; /* file's date */ unsigned f_time; /* file's time */ unsigned f_attrib; /* file's attribute */ unsigned long f_len; /* file length */ unsigned int file_seq_num; BYTE srcd; BYTE destd; BYTE *infspec; BYTE *inpath; unsigned int *dnumwant; { WORD temp_dnumwant; WORD numread; WORD action; BYTE file_to_be_opened[15]; BYTE string_to_be_separate[79]; BYTE path[65]; BYTE name[9]; BYTE ext[4]; BYTE spec[13]; WORD i; /*loop counter*/ WORD retcode; int z; temp_dnumwant = *dnumwant; /*to fix a bug that dosread change the value of dnumwant */ /***********************************************************************/ /*open the file to be restored as deny write and read access */ /***********************************************************************/ strcpy(src_fname,f_name); file_to_be_opened[0] = srcd; file_to_be_opened[1] = ':'; file_to_be_opened[2] = NULLC; strcat(file_to_be_opened,f_name); retcode = DOSOPEN( (char far *)&file_to_be_opened[0], (unsigned far *)&src_file_handle, (unsigned far *)&action, (DWORD)0, /*file size*/ 0, /*file attribute*/ 0x01, /*if file exist, open it*/ /*if file not exist, fail it*/ 0x00c0, /*deny write, read only*/ (DWORD)0 ); /*reserved*/ /*if open fail*/ if (retcode != 0) { /****not able to restore the file****/ display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ unexperror(retcode); } /*endif*/ /***********************************************************************/ /*read 128 bytes header information from the file into fheadold */ /***********************************************************************/ retcode = DOSREAD( src_file_handle, (char far *)&fheadold, HEADLEN, (unsigned far *)&numread); /*if read fail*/ if (retcode != 0 ) { display_it(NOT_ABLE_TO_RESTORE_FILE,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ unexperror(retcode); } /*end of if read fail */ /*if the number of read is less than HEADLEN, return FALSE */ if (numread != HEADLEN) return(FALSE); /* save disk number */ finfo->dnum = fheadold.disknum[1]* 10 + fheadold.disknum[0]; if (fheadold.wherefrom[0] != '\\') return(FALSE); strcpy(string_to_be_separate,fheadold.wherefrom); separate(string_to_be_separate,path,name,ext,spec); /***********************************************************************/ /* match the path and file spec. */ /***********************************************************************/ if ( pathmatch(inpath,path) == FALSE || fspecmatch(infspec,spec) == FALSE ) { *dnumwant = temp_dnumwant; return(FALSE); } /***********************************************************************/ /*Store some information from filefindbuf into finfo */ /***********************************************************************/ finfo->ftime = f_time; finfo->fdate = f_date; finfo->attrib = f_attrib; finfo->partsize = f_len; /***********************************************************************/ /*Store filename and path information from fheadold into finfo */ /***********************************************************************/ strcpy(finfo->fname,spec); strcpy(finfo->path,path); /***********************************************************************/ /* store some other information from fheadold to finfo */ /***********************************************************************/ if (fheadold.headflg == 0xff) finfo->fflag= LAST_PART; else finfo->fflag= 0; *dnumwant = temp_dnumwant; return(TRUE); /*return nothing*/ } /*end of subroutine*/ /***************** START OF SPECIFICATION ******************************** /* /* SUBROUTINE NAME : readonly_or_changed /* /* DESCRIPTIVE NAME : handle the situration that a read only file /* or is found, or the file has been Revised. /* /* FUNCTION: In the case that a readonly file is found, or the file /* on the destination disk has been Revised since last backup, /* this subroutine output a warning message to the user, and /* prompt for user to enter yes or no depending on whether /* the user wants to proceed restoring the file. /* /* /********************* END OF SPECIFICATIONS ********************************/ #define CHECK_YES_NO 0x6523 /*;AN000;6*/ #define YES_NO_RESPTYPE 0xc1 /*;AN000;6*/ #define YES 1 /*;AN000;6*/ int readonly_or_changed(attrib,destd,fspec,fpath) unsigned attrib; unsigned char destd; unsigned char *fspec; unsigned char *fpath; { union REGS inregs, outregs; /*;AN000;6 Register set */ WORD retcode; char file_to_be_chmode[MAXPATHF+2]; DWORD dw = 0L; int z; sublist.value1 = (char far *)fspec; /*;AN000;6 */ sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6 */ sublist.max_width1 = (BYTE)strlen(fspec); /*;AN000;6 */ sublist.min_width1 = sublist.max_width1; /*;AN000;6 */ /***********************************************************************/ /* if readonly, output msg and wait for user's prompt */ /***********************************************************************/ do /*;AN000;6*/ { /*;AN000;6*/ if((retcode = attrib & 0x0001) == 0x0001) display_it(FILE_IS_READONLY,STND_ERR_DEV,1,YES_NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ else display_it(FILE_WAS_CHANGED,STND_ERR_DEV,1,YES_NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ inregs.x.ax = (unsigned)CHECK_YES_NO; /*;AN000;6*/ inregs.h.dl = response_buff[0]; /*;AN000;6*/ int86(0x21,&inregs,&outregs); /*;AN000;6*/ display_it(CRLF,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/ } /*;AN000;6*/ while (outregs.h.al > 1); /*;AN000;6*/ /***********************************************************************/ /* if user's input is 'Y', return TRUE, else return FALSE */ /***********************************************************************/ if (outregs.x.ax == YES) /*;AN000;6*/ { file_to_be_chmode[0] = destd; file_to_be_chmode[1] = ':'; file_to_be_chmode[2] = NULLC; strcat(file_to_be_chmode,fpath); if (strlen(fpath) != 1) { strcat(file_to_be_chmode,"\\"); } strcat(file_to_be_chmode,fspec); /* change the file attribute to be 0, that is, reset it */ if ((retcode = DOSSETFILEMODE((char far *)file_to_be_chmode,(unsigned) 0x00, dw)) != 0) { com_msg(retcode); unexperror(retcode); } return(TRUE); } else { return(FALSE); } /* endif */ } /* end of subroutine readonly_or_changed */