diff options
Diffstat (limited to 'v4.0/src/CMD/BACKUP/BACKUP.C')
| -rw-r--r-- | v4.0/src/CMD/BACKUP/BACKUP.C | 4385 |
1 files changed, 4385 insertions, 0 deletions
diff --git a/v4.0/src/CMD/BACKUP/BACKUP.C b/v4.0/src/CMD/BACKUP/BACKUP.C new file mode 100644 index 0000000..2f2805a --- /dev/null +++ b/v4.0/src/CMD/BACKUP/BACKUP.C | |||
| @@ -0,0 +1,4385 @@ | |||
| 1 | /* 0 */ | ||
| 2 | |||
| 3 | /************************************************************ | ||
| 4 | /* | ||
| 5 | /* UTILITY NAME: BACKUP.COM | ||
| 6 | /* | ||
| 7 | /* SOURCE FILE NAME: BACKUP.C | ||
| 8 | /* | ||
| 9 | /* DESCRIPTIVE NAME: | ||
| 10 | /* DOS Backup Utility Program | ||
| 11 | /* | ||
| 12 | /* STATUS: BACKUP utility, DOS Version 4.00 | ||
| 13 | /* Written using the C programming language. | ||
| 14 | /* | ||
| 15 | /* | ||
| 16 | /* COMPILER/LINKER INVOCATION: | ||
| 17 | /* | ||
| 18 | /* cc /AS /Os /Zep /W3 /DLINT_ARGS /UDEBUG backup.c; | ||
| 19 | /* link backup,,,mapper+comsubs | ||
| 20 | /* | ||
| 21 | /* Note: You MUST(!) use the PACKED option (/Zp) to make sure data structures | ||
| 22 | /* are not aligned !!! | ||
| 23 | /* | ||
| 24 | /* FUNCTION: | ||
| 25 | /* BACKUP will back up files from one disk(ette) to another. Accepts | ||
| 26 | /* global characters, other parameters are defined to allow a more | ||
| 27 | /* restrictive BACKUP procedure. Compacts data into one large file and | ||
| 28 | /* a control file containing directory information. Allows FORMATTING | ||
| 29 | /* target diskette, intelligent error recovery, and proper handling of | ||
| 30 | /* file sharing and sharing errors. Optionally creates a log file for | ||
| 31 | /* tracking purposes. Sets errorlevels on termination to indicate | ||
| 32 | /* result. | ||
| 33 | /* | ||
| 34 | /* RESTRICTIONS: | ||
| 35 | /* The BACKUP Utility program will be version checked to run ONLY on | ||
| 36 | /* DOS version 4.00. BACKUP performs a file by file backup using the | ||
| 37 | /* DOS file system, ie. it is not an image type backup. | ||
| 38 | /* | ||
| 39 | /* | ||
| 40 | /* SYNTAX: | ||
| 41 | /* | ||
| 42 | /* BACKUP [d:][path] filename [.ext]] d: [/S] [/F[:size]] | ||
| 43 | /* [/L[:fn]] [/M] [/A] [T:hh:mm:ss] [/D:mm-dd-yy] | ||
| 44 | /* | ||
| 45 | /* [/F[:size]] undocumented | ||
| 46 | /* | ||
| 47 | /* SOURCE HISTORY: | ||
| 48 | /* | ||
| 49 | /* New for DOS 3.3 and OS/2 | ||
| 50 | /* | ||
| 51 | /* Modification History: | ||
| 52 | /* | ||
| 53 | /* ;AN000; Code added in DOS 4.0 | ||
| 54 | /* 6-05-87 RW | ||
| 55 | /* ;AN000;1 No BACKUP of SYSTEM files | ||
| 56 | /* ;AN000;2 Support for APPEND /X deactivation | ||
| 57 | /* ;AN000;3 Support for Extended Attributes | ||
| 58 | /* ;AN000;4 Support for PARSE service routines | ||
| 59 | /* ;AN000;5 Support for code page file tags | ||
| 60 | /* ;AN000;6 Support for MESSAGE retriever | ||
| 61 | /* ;AN000;7 Allow logfile to go on BACKUP target drive | ||
| 62 | /* ;AN000;8 Eliminate double prompting on single diskette drive systems | ||
| 63 | /* ;AN000;9 Put error message in logfile on share error | ||
| 64 | /* ;AN000;10 Make diskette formatting the default (DCR 177) | ||
| 65 | /* ;AN000;d178 DCR 178 Find FORMAT.COM before beginning | ||
| 66 | /* ;AN001; DCR 434 - Allow /F:size to specify format size | ||
| 67 | /* ;AN002; Don't use "C" routines to find PATH in environment | ||
| 68 | /* ;AN003; Make BACKUP handle UNC format returned from XLAT | ||
| 69 | /* ;AN004; Add CR, LF to end of command line (p3646) | ||
| 70 | /* ;AN005; Make sure no bogus BACKUP and CONTROL files are left in case of error exit | ||
| 71 | /* ;AN006; Make sure we don't try to BACKUP logfile | ||
| 72 | /* ;AN007; Make sure ABORT responses to critical errors are aborted | ||
| 73 | /* ;AN008; Make PARSE errors messages display the offending parameter | ||
| 74 | /* ;AN009; Fix parser | ||
| 75 | /* ;AN010; Don't find FORMAT.COM on target drive | ||
| 76 | /* ;AN011; Make BACKUP handle disk full properly on fixed disk | ||
| 77 | /***************************************************************** | ||
| 78 | |||
| 79 | /* "C" supplied include files */ | ||
| 80 | #include <process.h> | ||
| 81 | #include <malloc.h> | ||
| 82 | #include <direct.h> /*;AN000;*/ | ||
| 83 | #include <string.h> | ||
| 84 | #include <dos.h> | ||
| 85 | #include <stdlib.h> /*;AN000;d178*/ | ||
| 86 | |||
| 87 | #include <doscalls.h> /* OS/2 Include file */ | ||
| 88 | |||
| 89 | #include "backup.h" /* BACKUP structures, defines, ...*/ | ||
| 90 | #include "backpars.h" /* DEFINEs and STRUCTs for the DOS Parse service routines */ | ||
| 91 | |||
| 92 | #include <version.h> /* symbol defns to determine degree of compatibility */ | ||
| 93 | |||
| 94 | /**********************************/ | ||
| 95 | /* DATA STRUCTURES */ | ||
| 96 | /**********************************/ | ||
| 97 | WORD rc; /* Return code from DOS calls */ | ||
| 98 | |||
| 99 | unsigned selector; /* Kinda like a segment address */ | ||
| 100 | |||
| 101 | struct node *curr_node; /* Pointer to "node" structure for the */ | ||
| 102 | /* directory currently being processed */ | ||
| 103 | |||
| 104 | struct node *last_child; /* Pointer to "node" structure for the */ | ||
| 105 | /* last directory discovered in the */ | ||
| 106 | /* directory currently being processed */ | ||
| 107 | |||
| 108 | struct subst_list sublist; /*;AN000;6 Message substitution list */ | ||
| 109 | |||
| 110 | struct p_parms parms; /*;AN000;4 Parser data structure */ | ||
| 111 | struct p_parmsx parmsx; /*;AN000;4 Parser data structure */ | ||
| 112 | struct p_pos_blk pos1; /*;AN000;4 Parser data structure */ | ||
| 113 | struct p_pos_blk pos2; /*;AN000;4 Parser data structure */ | ||
| 114 | struct p_sw_blk sw1; /*;AN000;4 Parser data structure */ | ||
| 115 | struct p_sw_blk sw2; /*;AN000;4 Parser data structure */ | ||
| 116 | struct p_sw_blk sw3; /*;AN000;4 Parser data structure */ | ||
| 117 | struct p_sw_blk sw4; /*;AN000;4 Parser data structure */ | ||
| 118 | struct p_sw_blk sw5; /*;AN001;DCR 434 Parser data structure */ | ||
| 119 | |||
| 120 | struct p_result_blk pos_buff; /*;AN000;4 Parsr data structure */ | ||
| 121 | struct switchbuff sw_buff; /*;AN000;4 Parsr data structure */ | ||
| 122 | struct timebuff time_buff; /*;AN000;4 Parsr data structure */ | ||
| 123 | struct datebuff date_buff; /*;AN000;4 Parsr data structure */ | ||
| 124 | struct val_list_struct value_list; /*;AN001;DCR 434*/ | ||
| 125 | struct val_table_struct value_table; /*;AN001;DCR 434*/ | ||
| 126 | char curr_parm[128]; /*;AN009; Current parameter being parsed*/ | ||
| 127 | |||
| 128 | DWORD noval = 0; /*;AN000;4 Value list for PARSR */ | ||
| 129 | |||
| 130 | struct FileFindBuf dta; /* Return area for Find First/Next*/ | ||
| 131 | struct FileFindBuf *dta_addr; /* Pointer to above */ | ||
| 132 | union REGS inregs, outregs; /*;AN000;2 Register set */ | ||
| 133 | |||
| 134 | /**********************************/ | ||
| 135 | /* DATA AREAS */ | ||
| 136 | /**********************************/ | ||
| 137 | WORD dirhandle; /* Dirhandle field, for Find First, Find Next */ | ||
| 138 | BYTE dirhandles_open = FALSE; /* Flag indicating at least 1 open dirhandle */ | ||
| 139 | |||
| 140 | WORD def_drive; /* Storage for default drive (1=A,2=B,...) */ | ||
| 141 | BYTE src_drive_letter; /* ASCII drive letter, source drive */ | ||
| 142 | BYTE tgt_drive_letter; /* ASCII drive letter, target drive */ | ||
| 143 | BYTE src_def_dir[PATHLEN+20]; /* default dir on source, drive letter omitted */ | ||
| 144 | |||
| 145 | BYTE src_drive_path_fn[PATHLEN+20]; /* D:\path\fn - The fully qualified spec to be backed up*/ | ||
| 146 | BYTE src_drive_path[PATHLEN+20]; /* D:\path - Fully qualified drive and path to be backed up */ | ||
| 147 | BYTE src_fn[PATHLEN]; /* fn - File spec to be backed up. Set to *.* if no filespec entered. */ | ||
| 148 | BYTE ext[3]; /* Filename extension */ | ||
| 149 | |||
| 150 | WORD files_backed_up = 0; /* Counter for number files backed up on current target */ | ||
| 151 | BYTE diskettes_complete = 0; /* Number of diskettes already filled and complete */ | ||
| 152 | DWORD curr_db_begin_offset; /* Offset within the control file of the current Directory Block */ | ||
| 153 | DWORD curr_fh_begin_offset; /* Offset within the control file of the current File Header */ | ||
| 154 | WORD handle_source = 0xffff; /* Handle for source file */ | ||
| 155 | WORD handle_target = 0xffff; /* Handle for target file */ | ||
| 156 | WORD handle_control = 0xffff; /* Handle for control file */ | ||
| 157 | WORD handle_logfile = 0xffff; /* Handle for log file */ | ||
| 158 | DWORD part_size; /* Number of bytes from a file on the disk (for files that span) */ | ||
| 159 | DWORD cumul_part_size; /* Number of bytes from all disks for a particular file */ | ||
| 160 | |||
| 161 | BYTE logfile_path[PATHLEN+20]; /* D:\path\filename - drive,path, and name */ | ||
| 162 | BYTE format_path[PATHLEN+20]; /*;AN000;d178 Full path to FORMAT.COM */ | ||
| 163 | BYTE format_size[128]; /*;AN001;DCR 434 If user enters "/F:size" this will be "size" */ | ||
| 164 | |||
| 165 | /**********************************/ | ||
| 166 | /* PROGRAM CONTROL FLAGS */ | ||
| 167 | /**********************************/ | ||
| 168 | BYTE do_subdirs = FALSE; /* User parameters, /S */ | ||
| 169 | BYTE do_add = FALSE; /* User parameters, /A */ | ||
| 170 | BYTE do_modified = FALSE; /* User parameters, /M */ | ||
| 171 | BYTE do_format_parms = FALSE; /* User parameters, /F ;AN000;d177 */ | ||
| 172 | BYTE do_logfile = FALSE; /* User parameters, /L */ | ||
| 173 | BYTE do_time = FALSE; /* User parameters, /T */ | ||
| 174 | BYTE do_date = FALSE; /* User parameters, /D */ | ||
| 175 | |||
| 176 | BYTE buffers_allocated = FALSE; /* Indicates if file buffers were allocated */ | ||
| 177 | BYTE curr_dir_set = FALSE; /* Indicates if the current directory on source was changed */ | ||
| 178 | BYTE def_drive_set = FALSE; /* Indicates if the default drive was changed */ | ||
| 179 | |||
| 180 | BYTE control_opened = FALSE; /* Indicates if file opened or not */ | ||
| 181 | BYTE logfile_opened = FALSE; /*;AN000;7 Indicates if logfile file is opened */ | ||
| 182 | BYTE source_opened = FALSE; /* Indicates if file opened or not */ | ||
| 183 | BYTE target_opened = FALSE; /* Indicates if file opened or not */ | ||
| 184 | |||
| 185 | BYTE doing_first_target = TRUE; /* Indicates that first target is being processed */ | ||
| 186 | BYTE got_first_target = FALSE; /* Indicates that first target is being processed */ | ||
| 187 | |||
| 188 | BYTE source_removable; /* Indicates if the source drive is removable */ | ||
| 189 | BYTE target_removable; /* Indicates if the target drive is removable */ | ||
| 190 | |||
| 191 | BYTE file_spans_target; /* Indicates that first target is being processed */ | ||
| 192 | BYTE disk_full = FALSE; /* Flag indicating the disk is full */ | ||
| 193 | BYTE logfile_on_target = FALSE; /*;AN000;7 Flag telling if user wants logfile on target drive */ | ||
| 194 | BYTE got_path_validity = FALSE; /*;AN000;4 Flag indicating we have not verified input path*/ | ||
| 195 | BYTE checking_target = FALSE; /*;AN007; Indicates if we are checking target diskette to determine if it is formatted */ | ||
| 196 | |||
| 197 | BYTE new_directory = TRUE; /* Indicates that file to be backed up is in a different directory */ | ||
| 198 | BYTE found_a_file = FALSE; /* Indicates if a file was found to be backed up */ | ||
| 199 | BYTE back_it_up = FALSE; /* Indicates if a file was found and conforms to specified parameters */ char author[45]=" Program Author: W. Russell Whitehead "; | ||
| 200 | /**********************************/ | ||
| 201 | /* EXTENDED ATTRIBUTES */ | ||
| 202 | /**********************************/ | ||
| 203 | /*EAEA BYTE ext_attrib_flg = FALSE; /*;AN000;3 Indicates there are extended attributes*/ | ||
| 204 | /*EAEA WORD ext_attrib_len; /*;AN000;3 Length of extended attributes*/ | ||
| 205 | /*EAEA BYTE ext_attrib_buff[EXTATTBUFLEN]; /*;AN000;3 Buffer for extended attributes*/ | ||
| 206 | BYTE ext_attrib_buff[3]; /*;AN000;3 Buffer for extended attributes*/ | ||
| 207 | struct parm_list ea_parmlist; /*;AN000;3 Parameter list for extended open*/ | ||
| 208 | |||
| 209 | /**********************************/ | ||
| 210 | /* APPEND STUFF */ | ||
| 211 | /**********************************/ | ||
| 212 | BYTE append_indicator = 0xff; /*;AN000;2 Indicates if support for APPEND /X is active */ | ||
| 213 | WORD original_append_func; /*;AN000;2 APPEND functions on program entry, restored on program exit */ | ||
| 214 | |||
| 215 | /**********************************/ | ||
| 216 | /* OTHER STUFF */ | ||
| 217 | /**********************************/ | ||
| 218 | BYTE span_seq_num; /* Counter indicating which part of a spanning file is on current target */ | ||
| 219 | |||
| 220 | WORD data_file_alloc_size = 0xffff; /* Number of paragraphs to initially try to allocate for data file */ | ||
| 221 | |||
| 222 | DWORD data_file_tot_len = 0; /* Storage area for data file current length */ | ||
| 223 | DWORD ctl_file_tot_len = 0; /* Storage area for control file current length on the disk */ | ||
| 224 | |||
| 225 | WORD ctry_date_fmt; | ||
| 226 | BYTE ctry_time_fmt; | ||
| 227 | WORD ctry_date_sep; | ||
| 228 | WORD ctry_time_sep; | ||
| 229 | |||
| 230 | WORD user_specified_time = 0; /* Time user entered in response to /T parameter */ | ||
| 231 | WORD user_specified_date = 0; /* Date user entered in response to /T parameter */ | ||
| 232 | |||
| 233 | BYTE return_code = RETCODE_NO_ERROR; /* Save area for DOS ErrorLevel */ | ||
| 234 | |||
| 235 | /*************************************************/ | ||
| 236 | /* | ||
| 237 | /* SUBROUTINE NAME: main | ||
| 238 | /* | ||
| 239 | /* FUNCTION: | ||
| 240 | /* | ||
| 241 | /* Backs up files from source to target drive | ||
| 242 | /* | ||
| 243 | /***************************************************/ | ||
| 244 | main(argc,argv) | ||
| 245 | int argc; | ||
| 246 | char *argv[]; | ||
| 247 | { | ||
| 248 | init(); /*;AN000;6 Mundane initializization of data structures, */ | ||
| 249 | /* check DOS version,preload messages */ | ||
| 250 | def_drive = get_current_drive(); /* Save default drive number*/ | ||
| 251 | check_drive_validity(argc,argv); /* Check for validity of input drive(s) */ | ||
| 252 | get_drive_types(); /* Find out if source and target are removable */ | ||
| 253 | get_country_info(); /* Get country dependent information */ | ||
| 254 | parser(argc,argv); /*;AN000;4 Parse input line, init switches and flags*/ | ||
| 255 | check_path_validity(argv); /*;AN000;4 Verify that the source filespec is valid */ | ||
| 256 | if (target_removable) /*;AN000;d178 If target drive is diskette */ | ||
| 257 | find_format(); /*;AN000;d178 Find FORMAT.COM and build path to it*/ | ||
| 258 | save_current_dirs(); /* Save default directories on def drive, source and target */ | ||
| 259 | alloc_buffer(); /* Allocate IO buffer */ | ||
| 260 | check_appendX(); /*;AN000;2 Check APPEND /X status, turn off if active */ | ||
| 261 | set_vectors(); /* Set vectors for Int 23h and 24h */ | ||
| 262 | do_backup(); /* Do the BACKUP */ | ||
| 263 | |||
| 264 | return(0); | ||
| 265 | } /* end main */ | ||
| 266 | |||
| 267 | /*************************************************/ | ||
| 268 | /* | ||
| 269 | /* SUBROUTINE NAME: init | ||
| 270 | /* | ||
| 271 | /* FUNCTION: | ||
| 272 | /* Preload messages | ||
| 273 | /* Check DOS version | ||
| 274 | /* Mundane initializization of data structures | ||
| 275 | /* | ||
| 276 | /**************************************************/ | ||
| 277 | void init() /*;AN000;6*/ | ||
| 278 | { /*;AN000;6*/ | ||
| 279 | |||
| 280 | /**********************************/ | ||
| 281 | /** PRELOAD MESSAGES **/ | ||
| 282 | /**********************************/ | ||
| 283 | sysloadmsg(&inregs,&outregs); /*;AN000;6 Preload messages, check DOS version */ | ||
| 284 | |||
| 285 | if (outregs.x.cflag & CARRY) /*;AN000;6 If there was an error */ | ||
| 286 | { /*;AN000;6*/ | ||
| 287 | sysdispmsg(&outregs,&outregs); /*;AN000;6 Display the error message (Use OUTREGS as input*/ | ||
| 288 | return_code = RETCODE_ERROR; /*;AN000;6 Set the return code */ | ||
| 289 | terminate(); /*;AN000;6 and terminate */ | ||
| 290 | } /*;AN000;6*/ | ||
| 291 | |||
| 292 | /**********************************/ | ||
| 293 | /** SETUP MESSAGE SUBST LIST **/ | ||
| 294 | /**********************************/ | ||
| 295 | sublist.sl_size1= SUBLIST_SIZE; /*;AN000;6 Initialize subst list for message retriever*/ | ||
| 296 | sublist.sl_size2= SUBLIST_SIZE; /*;AN000;6*/ | ||
| 297 | sublist.one = 1; /*;AN000;6*/ | ||
| 298 | sublist.two = 2; /*;AN000;6*/ | ||
| 299 | sublist.zero1 = 0; /*;AN000;6*/ | ||
| 300 | sublist.zero2 = 0; /*;AN000;6*/ | ||
| 301 | |||
| 302 | ext_attrib_buff[0] = 0; /*;AN000;3*/ | ||
| 303 | ext_attrib_buff[1] = 0; /*;AN000;3*/ | ||
| 304 | |||
| 305 | date_buff.month = 0; /*;AN000;3*/ | ||
| 306 | date_buff.day = 0; /*;AN000;3*/ | ||
| 307 | date_buff.year = 0; /*;AN000;3*/ | ||
| 308 | |||
| 309 | time_buff.hours = 0; /*;AN000;3*/ | ||
| 310 | time_buff.minutes = 0; /*;AN000;3*/ | ||
| 311 | time_buff.seconds = 0; /*;AN000;3*/ | ||
| 312 | time_buff.hundreds= 0; /*;AN000;3*/ | ||
| 313 | |||
| 314 | dta_addr = (struct FileFindBuf *)&dta; /* Get address of FindFile buffer */ | ||
| 315 | |||
| 316 | return; /*;AN000;6*/ | ||
| 317 | } /*;AN000;6*/ | ||
| 318 | |||
| 319 | |||
| 320 | /*************************************************/ | ||
| 321 | /* | ||
| 322 | /* SUBROUTINE NAME: parser | ||
| 323 | /* | ||
| 324 | /* FUNCTION: | ||
| 325 | /* | ||
| 326 | /* Parse the command line | ||
| 327 | /* | ||
| 328 | /**************************************************/ | ||
| 329 | void parser(argc,argv) /*;AN000;4*/ | ||
| 330 | int argc; /*;AN000;4*/ | ||
| 331 | char *argv[]; /*;AN000;4*/ | ||
| 332 | { /*;AN000;4*/ | ||
| 333 | char cmd_line[128]; /*;AN000;4*/ | ||
| 334 | char not_finished = TRUE; /*;AN000;4*/ | ||
| 335 | int x; /*;AN000;4*/ | ||
| 336 | |||
| 337 | parse_init(); /* Initialize parser data structures*//*;AN000;4*/ | ||
| 338 | |||
| 339 | /* Copy command line parameters to local area */ | ||
| 340 | cmd_line[0] = NUL; /*;AN000;4*/ | ||
| 341 | for (x=1; x<=argc; x++) /*;AN000;4*/ | ||
| 342 | { /*;AN000;4*/ | ||
| 343 | strcat(cmd_line,argv[x]); /*;AN000;4*/ | ||
| 344 | if (x != argc) strcat(cmd_line," "); /*;AN000;4*/ | ||
| 345 | } /*;AN000;4*/ | ||
| 346 | |||
| 347 | strcat(cmd_line,"\r"); /*;AN004;*/ | ||
| 348 | |||
| 349 | inregs.x.si = (WORD)&cmd_line[0]; /*DS:SI points to cmd line*//*;AN000;4*/ | ||
| 350 | |||
| 351 | |||
| 352 | |||
| 353 | while (not_finished) /*;AN000;4 For all strings in command line */ | ||
| 354 | { /*;AN000;4*/ | ||
| 355 | inregs.x.dx = 0; /*;AN000;4 RESERVED */ | ||
| 356 | inregs.x.di = (WORD)&parms; /*ES:DI*/ /*;AN000;4 address of parm list */ | ||
| 357 | |||
| 358 | parse(&inregs,&outregs); /*;AN000;4 Call DOS SYSPARSE service routines*/ | ||
| 359 | |||
| 360 | x=0; /* Save the parsed parameter */ /*;AN009;*/ | ||
| 361 | for (inregs.x.si; inregs.x.si<outregs.x.si; inregs.x.si++) /*;AN009;*/ | ||
| 362 | { /*;AN009;*/ | ||
| 363 | curr_parm[x] = *(char *)inregs.x.si; /*;AN009;*/ | ||
| 364 | x++; /*;AN009;*/ | ||
| 365 | } /*;AN009;*/ | ||
| 366 | |||
| 367 | curr_parm[x] = NUL; /*;AN009;*/ | ||
| 368 | |||
| 369 | inregs = outregs; /*;AN000;4 Reset registers*/ | ||
| 370 | |||
| 371 | if (outregs.x.ax!=(WORD)NOERROR) /*;AN000;4*/ | ||
| 372 | { /*;AN000;4*/ | ||
| 373 | if (outregs.x.ax!=(WORD)EOL) /*;AN000;4*/ | ||
| 374 | parse_error(outregs.x.ax,outregs.x.dx); /*;AN000;4*//*;AN008;*/ | ||
| 375 | not_finished = FALSE; /*;AN000;4*/ | ||
| 376 | } /*;AN000;4*/ | ||
| 377 | |||
| 378 | if (not_finished) /*;AN000;4 If there was not an error*/ | ||
| 379 | { /*;AN000;4*/ | ||
| 380 | if (outregs.x.dx == (WORD)&sw_buff) /*;AN000;4*/ | ||
| 381 | process_switch(); /*;AN000;4 Its a switch*//*;AN008;*/ | ||
| 382 | |||
| 383 | if (outregs.x.dx == (WORD)&time_buff) /*;AN000;4*/ | ||
| 384 | { /*;AN000;4 Its a TIME parameter*/ | ||
| 385 | if (do_time) /*;AN000;4*/ | ||
| 386 | parse_error(outregs.x.ax,outregs.x.dx); /*;AN000;4*//*;AN008;*/ | ||
| 387 | |||
| 388 | check_time(time_buff.hours,time_buff.minutes,time_buff.seconds,time_buff.hundreds);/*;AN000;4*/ | ||
| 389 | time_buff.seconds = time_buff.seconds / 2; /*;AN000;4 See "NOTE FROM PARSER SUBROUTINE" in backup.h */ | ||
| 390 | user_specified_time = (time_buff.hours*0x800) + (time_buff.minutes*32) + time_buff.seconds;/*;AN000;4 TIME bit format hhhhhmmmmmmxxxxx */ | ||
| 391 | } /*;AN000;4*/ | ||
| 392 | |||
| 393 | if (outregs.x.dx == (WORD)&date_buff) /*;AN000;4*/ | ||
| 394 | { /*;AN000;4*/ | ||
| 395 | if (do_date) /*;AN000;4*/ | ||
| 396 | parse_error(outregs.x.ax,outregs.x.dx); /*;AN000;4*//*;AN008;*/ | ||
| 397 | |||
| 398 | check_date(date_buff.year,date_buff.month,date_buff.day);/*;AN000;4*/ | ||
| 399 | user_specified_date = ((date_buff.year-1980)*512) + (date_buff.month*32) + (date_buff.day); /*;AN000;4 DATE bit format yyyyyyymmmmddddd */ | ||
| 400 | } /*;AN000;4*/ | ||
| 401 | |||
| 402 | } /* end not_finished */ /*;AN000;4*/ | ||
| 403 | |||
| 404 | } /* end WHILE */ /*;AN000;4*/ | ||
| 405 | |||
| 406 | if (strlen(argv[1]) >= 5) /*;AN000;p2592*/ | ||
| 407 | check_for_device_names(argv); /*;AN000;p2592*/ | ||
| 408 | |||
| 409 | return; /*;AN000;4 Return to caller*/ | ||
| 410 | } /* end parser */ /*;AN000;4*/ | ||
| 411 | /*************************************************/ | ||
| 412 | /* | ||
| 413 | /* SUBROUTINE NAME: parse_error | ||
| 414 | /* | ||
| 415 | /* FUNCTION: | ||
| 416 | /* | ||
| 417 | /* There was a parse error. Display appropriate | ||
| 418 | /* error message and terminate. | ||
| 419 | /* | ||
| 420 | /**************************************************/ | ||
| 421 | void parse_error(ax,dx) /*;AN000;4*/ | ||
| 422 | WORD ax; /*;AN000;4*/ | ||
| 423 | WORD dx; /*;AN000;4*/ | ||
| 424 | { /*;AN000;4*/ | ||
| 425 | sublist.value1 = &curr_parm[0]; /*;AN008;*/ | ||
| 426 | sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN008;*/ | ||
| 427 | sublist.pad_char1 = ' '; /*;AN008;*/ | ||
| 428 | sublist.one = 0; /*;AN008;*/ | ||
| 429 | sublist.max_width1 = (BYTE)strlen(curr_parm); /*;AN008;*/ | ||
| 430 | sublist.min_width1 = sublist.max_width1; /*;AN008;*/ | ||
| 431 | |||
| 432 | if (dx == (WORD)&time_buff) /*;AN000;4*/ | ||
| 433 | display_it(INV_TIME,STDERR,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;4*/ | ||
| 434 | else /*;AN000;4*/ | ||
| 435 | if (dx == (WORD)&date_buff) /*;AN000;4*/ | ||
| 436 | display_it(INV_DATE,STDERR,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;4*/ | ||
| 437 | else /*;AN000;4*/ | ||
| 438 | display_it (ax,STDERR,1,NOWAIT,(BYTE)PARSEERROR); /*;AN000;6*/ | ||
| 439 | |||
| 440 | return_code = RETCODE_ERROR; /*;AN000;4*/ | ||
| 441 | clean_up_and_exit(); /*;AN000;4*/ | ||
| 442 | |||
| 443 | return; /*;AN000;4*/ | ||
| 444 | } /* end parse_error */ /*;AN000;4*/ | ||
| 445 | |||
| 446 | /*************************************************/ | ||
| 447 | /* | ||
| 448 | /* SUBROUTINE NAME: check_date | ||
| 449 | /* | ||
| 450 | /* FUNCTION: | ||
| 451 | /* | ||
| 452 | /* A date parameter was entered. Validate it | ||
| 453 | /* | ||
| 454 | /**************************************************/ | ||
| 455 | void check_date(year,month,day) /*;AN000;4*/ | ||
| 456 | WORD year; /*;AN000;4*/ | ||
| 457 | BYTE month; /*;AN000;4*/ | ||
| 458 | BYTE day; /*;AN000;4*/ | ||
| 459 | { /*;AN000;4*/ | ||
| 460 | if (year > 2099 || year < 1980) /*;AC000;4*/ | ||
| 461 | error_exit(INV_DATE); /*;AC000;4*/ | ||
| 462 | |||
| 463 | if (month > 12 || month < 1) /*;AC000;4*/ | ||
| 464 | error_exit(INV_DATE); /*;AC000;4*/ | ||
| 465 | |||
| 466 | if (day > 31 || day < 1) /*;AC000;4*/ | ||
| 467 | error_exit(INV_DATE); /*;AC000;4*/ | ||
| 468 | |||
| 469 | /* Verify day not greater then 30 if Apr,Jun,Sep,Nov */ | ||
| 470 | if ((day>30) && (month==4 || month==6 || month==9 || month==11))/*;AC000;4*/ | ||
| 471 | error_exit(INV_DATE); /*;AC000;4*/ | ||
| 472 | |||
| 473 | if (month == 2) /* Deal with February */ /*;AC000;4*/ | ||
| 474 | { /*;AC000;4*/ | ||
| 475 | if (day > 29) /* if Feb 30 or above */ /*;AC000;4*/ | ||
| 476 | error_exit(INV_DATE); /* then Bad Date */ /*;AC000;4*/ | ||
| 477 | |||
| 478 | if ((year % 4) != 0) /* If not a leap year */ /*;AC000;4*/ | ||
| 479 | if (day > 28) /* if Feb 29 or above */ /*;AC000;4*/ | ||
| 480 | error_exit(INV_DATE); /* then Bad Date */ /*;AC000;4*/ | ||
| 481 | } /*;AC000;4*/ | ||
| 482 | |||
| 483 | do_date = TRUE; /*;AN000;4*/ | ||
| 484 | |||
| 485 | return; /*;AN000;4*/ | ||
| 486 | } /* end check_date */ /*;AN000;4*/ | ||
| 487 | |||
| 488 | /*************************************************/ | ||
| 489 | /* | ||
| 490 | /* SUBROUTINE NAME: check_time | ||
| 491 | /* | ||
| 492 | /* FUNCTION: | ||
| 493 | /* | ||
| 494 | /* A time parameter was entered. Validate it | ||
| 495 | /* | ||
| 496 | /**************************************************/ | ||
| 497 | void check_time(hours,minutes,seconds,hundreds) /*;AN000;4*/ | ||
| 498 | BYTE hours; /*;AN000;4*/ | ||
| 499 | BYTE minutes; /*;AN000;4*/ | ||
| 500 | BYTE seconds; /*;AN000;4*/ | ||
| 501 | BYTE hundreds; /*;AN000;4*/ | ||
| 502 | { /*;AN000;4*/ | ||
| 503 | if (hours > 23 || hours < 0) /*;AC000;4*/ | ||
| 504 | error_exit(INV_TIME); /*;AC000;4*/ | ||
| 505 | |||
| 506 | if (minutes >= 60 || minutes < 0) /*;AC000;4*/ | ||
| 507 | error_exit(INV_TIME); /*;AC000;4*/ | ||
| 508 | |||
| 509 | if (seconds >= 60 || seconds < 0) /*;AC000;4*/ | ||
| 510 | error_exit(INV_TIME); /*;AC000;4*/ | ||
| 511 | |||
| 512 | if (hundreds > 99 || hundreds < 0) /*;AC000;4*/ | ||
| 513 | error_exit(INV_TIME); /*;AC000;4*/ | ||
| 514 | |||
| 515 | do_time = TRUE; /*;AN000;4*/ | ||
| 516 | |||
| 517 | return; /*;AN000;4*/ | ||
| 518 | } /* end check_time */ /*;AN000;4*/ | ||
| 519 | |||
| 520 | /*************************************************/ | ||
| 521 | /* | ||
| 522 | /* SUBROUTINE NAME: parse_init | ||
| 523 | /* | ||
| 524 | /* FUNCTION: | ||
| 525 | /* | ||
| 526 | /* Initialize the parser data structures | ||
| 527 | /* | ||
| 528 | /**************************************************/ | ||
| 529 | void parse_init() /*;AN000;4*/ | ||
| 530 | { /* Initialize PARMS data structure */ /*;AN000;4*/ | ||
| 531 | parms.parmsx_ptr = (WORD)&parmsx; /*;AN000;4*/ | ||
| 532 | parms.p_num_extra = 1; /*;AN000;4*/ | ||
| 533 | parms.p_len_extra_delim = 1; /*;AN000;4*/ | ||
| 534 | parms.p_extra_delim[0] = ';'; /*;AN000;4*/ | ||
| 535 | parms.p_extra_delim[1] = NUL; /*;AN000;4 */ | ||
| 536 | |||
| 537 | /* Initialize PARMSX data structure */ | ||
| 538 | parmsx.p_minpos= 2; /*;AN000;4*/ | ||
| 539 | parmsx.p_maxpos= 2; /*;AN000;4*/ | ||
| 540 | parmsx.pos1_ptr= (WORD)&pos1; /*;AN000;4*/ | ||
| 541 | parmsx.pos2_ptr= (WORD)&pos2; /*;AN000;4*/ | ||
| 542 | parmsx.num_sw = 5; /*;AN000;4*/ | ||
| 543 | parmsx.sw1_ptr = (WORD)&sw1; /*;AN000;4*/ | ||
| 544 | parmsx.sw2_ptr = (WORD)&sw2; /*;AN000;4*/ | ||
| 545 | parmsx.sw3_ptr = (WORD)&sw3; /*;AN000;4*/ | ||
| 546 | parmsx.sw4_ptr = (WORD)&sw4; /*;AN000;4*/ | ||
| 547 | parmsx.sw5_ptr = (WORD)&sw5; /*;AN001;DCR 434*/ | ||
| 548 | parmsx.num_keywords = 0; /*;AN000;4*/ | ||
| 549 | |||
| 550 | /* Initialize POS1 data structure */ | ||
| 551 | pos1.match_flag = FILESPEC; /*;AN000;4*/ | ||
| 552 | pos1.function_flag = 0; /*;AN000;4*/ | ||
| 553 | pos1.result_buf = (WORD)&pos_buff; /*;AN000;4*/ | ||
| 554 | pos1.value_list = (WORD)&noval; /*;AN000;4*/ | ||
| 555 | pos1.nid = 0; /*;AN000;4*/ | ||
| 556 | |||
| 557 | /* Initialize POS2 data structure */ | ||
| 558 | pos2.match_flag = DRIVELETTER; /*;AN000;4*/ | ||
| 559 | pos2.function_flag = 0; /*;AN000;4*/ | ||
| 560 | pos2.result_buf = (WORD)&pos_buff; /*;AN000;4*/ | ||
| 561 | pos2.value_list = (WORD)&noval; /*;AN000;4*/ | ||
| 562 | pos2.nid = 0; /*;AN000;4*/ | ||
| 563 | |||
| 564 | /* Initialize SW1 data structure */ | ||
| 565 | sw1.p_match_flag = 0; /*;AN000;4*/ | ||
| 566 | sw1.p_function_flag = 0; /*;AN000;4*/ | ||
| 567 | sw1.p_result_buf = (WORD)&sw_buff; /*;AN000;4*/ | ||
| 568 | sw1.p_value_list = (WORD)&noval; /*;AN000;4*/ | ||
| 569 | sw1.p_nid = 4; /*;AN000;4*/ | ||
| 570 | strcpy(sw1.switch1,"/S"); /*;AN000;4*/ | ||
| 571 | strcpy(sw1.switch2,"/M"); /*;AN000;4*/ | ||
| 572 | strcpy(sw1.switch3,"/A"); /*;AN000;4*/ | ||
| 573 | |||
| 574 | /* Initialize SW2 data structure */ | ||
| 575 | sw2.p_match_flag = DATESTRING; /*;AN000;4*/ | ||
| 576 | sw2.p_function_flag = 0; /*;AN000;4*/ | ||
| 577 | sw2.p_result_buf = (WORD)&date_buff; /*;AN000;4*/ | ||
| 578 | sw2.p_value_list = (WORD)&noval; /*;AN000;4*/ | ||
| 579 | sw2.p_nid = 1; /*;AN000;4*/ | ||
| 580 | strcpy(sw2.switch1,"/D"); /*;AN000;4*/ | ||
| 581 | |||
| 582 | /* Initialize SW3 data structure */ | ||
| 583 | sw3.p_match_flag = TIMESTRING; /*;AN000;4*/ | ||
| 584 | sw3.p_function_flag = 0; /*;AN000;4*/ | ||
| 585 | sw3.p_result_buf = (WORD)&time_buff; /*;AN000;4*/ | ||
| 586 | sw3.p_value_list = (WORD)&noval; /*;AN000;4*/ | ||
| 587 | sw3.p_nid = 1; /*;AN000;4*/ | ||
| 588 | strcpy(sw3.switch1,"/T"); /*;AN000;4*/ | ||
| 589 | |||
| 590 | /* Initialize SW4 data structure */ | ||
| 591 | sw4.p_match_flag = SSTRING + OPTIONAL; /*;AN000;4*/ | ||
| 592 | sw4.p_function_flag = CAP_FILETABLE; /*;AN000;4*/ | ||
| 593 | sw4.p_result_buf = (WORD)&sw_buff; /*;AN000;4*/ | ||
| 594 | sw4.p_value_list = (WORD)&noval; /*;AN000;4*/ | ||
| 595 | sw4.p_nid = 1; /*;AN000;4*/ | ||
| 596 | strcpy(sw4.switch1,"/L"); /*;AN000;4*/ | ||
| 597 | |||
| 598 | /* Initialize SW5 data structure */ | ||
| 599 | sw5.p_match_flag = SSTRING + OPTIONAL; /*;AN001;DCR 434*/ | ||
| 600 | sw5.p_function_flag = CAP_CHARTABLE; /*;AN001;DCR 434*/ | ||
| 601 | sw5.p_result_buf = (WORD)&sw_buff; /*;AN001;DCR 434*/ | ||
| 602 | sw5.p_value_list = (WORD)&value_list; /*;AN001;DCR 434*/ | ||
| 603 | sw5.p_nid = 1; /*;AN001;DCR 434*/ | ||
| 604 | strcpy(sw5.switch1,"/F"); /*;AN001;DCR 434*/ | ||
| 605 | |||
| 606 | /* Initialize value list data structure */ | ||
| 607 | value_list.nval = 3; /*;AN001;DCR 434*/ | ||
| 608 | value_list.num_ranges = 0; /*;AN001;DCR 434*/ | ||
| 609 | value_list.num_choices = 0; /*;AN001;DCR 434*/ | ||
| 610 | value_list.num_strings = 27; /*;AN001;DCR 434*/ | ||
| 611 | value_list.val01 = (WORD)&value_table.val01[0]; /*;AN001;DCR 434*/ | ||
| 612 | value_list.val02 = (WORD)&value_table.val02[0]; /*;AN001;DCR 434*/ | ||
| 613 | value_list.val03 = (WORD)&value_table.val03[0]; /*;AN001;DCR 434*/ | ||
| 614 | value_list.val04 = (WORD)&value_table.val04[0]; /*;AN001;DCR 434*/ | ||
| 615 | value_list.val05 = (WORD)&value_table.val05[0]; /*;AN001;DCR 434*/ | ||
| 616 | value_list.val06 = (WORD)&value_table.val06[0]; /*;AN001;DCR 434*/ | ||
| 617 | value_list.val07 = (WORD)&value_table.val07[0]; /*;AN001;DCR 434*/ | ||
| 618 | value_list.val08 = (WORD)&value_table.val08[0]; /*;AN001;DCR 434*/ | ||
| 619 | value_list.val09 = (WORD)&value_table.val09[0]; /*;AN001;DCR 434*/ | ||
| 620 | value_list.val10 = (WORD)&value_table.val10[0]; /*;AN001;DCR 434*/ | ||
| 621 | value_list.val11 = (WORD)&value_table.val11[0]; /*;AN001;DCR 434*/ | ||
| 622 | value_list.val12 = (WORD)&value_table.val12[0]; /*;AN001;DCR 434*/ | ||
| 623 | value_list.val13 = (WORD)&value_table.val13[0]; /*;AN001;DCR 434*/ | ||
| 624 | value_list.val14 = (WORD)&value_table.val14[0]; /*;AN001;DCR 434*/ | ||
| 625 | value_list.val15 = (WORD)&value_table.val15[0]; /*;AN001;DCR 434*/ | ||
| 626 | value_list.val16 = (WORD)&value_table.val16[0]; /*;AN001;DCR 434*/ | ||
| 627 | value_list.val17 = (WORD)&value_table.val17[0]; /*;AN001;DCR 434*/ | ||
| 628 | value_list.val18 = (WORD)&value_table.val18[0]; /*;AN001;DCR 434*/ | ||
| 629 | value_list.val19 = (WORD)&value_table.val19[0]; /*;AN001;DCR 434*/ | ||
| 630 | value_list.val20 = (WORD)&value_table.val20[0]; /*;AN001;DCR 434*/ | ||
| 631 | value_list.val21 = (WORD)&value_table.val21[0]; /*;AN001;DCR 434*/ | ||
| 632 | value_list.val22 = (WORD)&value_table.val22[0]; /*;AN001;DCR 434*/ | ||
| 633 | value_list.val23 = (WORD)&value_table.val23[0]; /*;AN001;DCR 434*/ | ||
| 634 | value_list.val24 = (WORD)&value_table.val24[0]; /*;AN001;DCR 434*/ | ||
| 635 | value_list.val25 = (WORD)&value_table.val25[0]; /*;AN001;DCR 434*/ | ||
| 636 | value_list.val26 = (WORD)&value_table.val26[0]; /*;AN001;DCR 434*/ | ||
| 637 | value_list.val27 = (WORD)&value_table.val27[0]; /*;AN001;DCR 434*/ | ||
| 638 | |||
| 639 | /* Initialize FORMAT value table */ | ||
| 640 | strcpy(value_table.val01,"160"); /*;AN001;DCR 434*/ | ||
| 641 | strcpy(value_table.val02,"160K"); /*;AN001;DCR 434*/ | ||
| 642 | strcpy(value_table.val03,"160KB"); /*;AN001;DCR 434*/ | ||
| 643 | strcpy(value_table.val04,"180"); /*;AN001;DCR 434*/ | ||
| 644 | strcpy(value_table.val05,"180K"); /*;AN001;DCR 434*/ | ||
| 645 | strcpy(value_table.val06,"180KB"); /*;AN001;DCR 434*/ | ||
| 646 | strcpy(value_table.val07,"320"); /*;AN001;DCR 434*/ | ||
| 647 | strcpy(value_table.val08,"320K"); /*;AN001;DCR 434*/ | ||
| 648 | strcpy(value_table.val09,"320KB"); /*;AN001;DCR 434*/ | ||
| 649 | strcpy(value_table.val10,"360"); /*;AN001;DCR 434*/ | ||
| 650 | strcpy(value_table.val11,"360K"); /*;AN001;DCR 434*/ | ||
| 651 | strcpy(value_table.val12,"360KB"); /*;AN001;DCR 434*/ | ||
| 652 | strcpy(value_table.val13,"720"); /*;AN001;DCR 434*/ | ||
| 653 | strcpy(value_table.val14,"720K"); /*;AN001;DCR 434*/ | ||
| 654 | strcpy(value_table.val15,"720KB"); /*;AN001;DCR 434*/ | ||
| 655 | strcpy(value_table.val16,"1200"); /*;AN001;DCR 434*/ | ||
| 656 | strcpy(value_table.val17,"1200K"); /*;AN001;DCR 434*/ | ||
| 657 | strcpy(value_table.val18,"1200KB"); /*;AN001;DCR 434*/ | ||
| 658 | strcpy(value_table.val19,"1.2"); /*;AN001;DCR 434*/ | ||
| 659 | strcpy(value_table.val20,"1.2M"); /*;AN001;DCR 434*/ | ||
| 660 | strcpy(value_table.val21,"1.2MB"); /*;AN001;DCR 434*/ | ||
| 661 | strcpy(value_table.val22,"1440"); /*;AN001;DCR 434*/ | ||
| 662 | strcpy(value_table.val23,"1440K"); /*;AN001;DCR 434*/ | ||
| 663 | strcpy(value_table.val24,"1440KB"); /*;AN001;DCR 434*/ | ||
| 664 | strcpy(value_table.val25,"1.44"); /*;AN001;DCR 434*/ | ||
| 665 | strcpy(value_table.val26,"1.44M"); /*;AN001;DCR 434*/ | ||
| 666 | strcpy(value_table.val27,"1.44MB"); /*;AN001;DCR 434*/ | ||
| 667 | |||
| 668 | return; /*;AN000;4*/ | ||
| 669 | } /*;AN000;4*/ | ||
| 670 | /*************************************************/ | ||
| 671 | /* | ||
| 672 | /* SUBROUTINE NAME: find_format | ||
| 673 | /* | ||
| 674 | /* FUNCTION: | ||
| 675 | /* | ||
| 676 | /* Search for the FORMAT utility. If found, then | ||
| 677 | /* build a full path to it from the root. If not | ||
| 678 | /* found, tell the user and terminate. | ||
| 679 | /* | ||
| 680 | /***************************************************/ | ||
| 681 | void find_format() /*;AN000;d178*/ | ||
| 682 | { /*;AN000;d178*/ | ||
| 683 | BYTE found_it= FALSE; /*;AN000;d178*/ | ||
| 684 | BYTE no_more = FALSE; /*;AN000;d178*/ | ||
| 685 | int findex,pindex; /*;AN002;*/ | ||
| 686 | BYTE done = FALSE; /*;AN002;*/ | ||
| 687 | char path[130]; /*;AN002;*/ | ||
| 688 | |||
| 689 | /*******************************/ | ||
| 690 | /* First try current directory */ | ||
| 691 | format_path[0] = '.'; /*;AN000;d178*/ | ||
| 692 | format_path[1] = NUL; /*;AN000;d178*/ | ||
| 693 | |||
| 694 | /* Build full path */ | ||
| 695 | xlat(format_path,format_path); /*;AN000;d178*/ | ||
| 696 | |||
| 697 | /* If at root, remove trailing backslash */ | ||
| 698 | if (strlen(format_path)==3 && format_path[1]==':') /*;AN000;p1900*/ | ||
| 699 | format_path[2] = NUL; /*;AN000;p1900*/ | ||
| 700 | |||
| 701 | strcat(format_path,"\\FORMAT.COM"); /*;AN000;d178*/ | ||
| 702 | |||
| 703 | /* Now look for it */ | ||
| 704 | if (format_path[0] == tgt_drive_letter) /*;AN010;*/ | ||
| 705 | if (target_removable) /*;AN010;*/ | ||
| 706 | format_path[0] = NUL; /*;AN010;*/ | ||
| 707 | |||
| 708 | if (exist(format_path)) /*;AN000;d178*/ | ||
| 709 | found_it = TRUE; /*;AN000;d178*/ | ||
| 710 | else /*;AN000;d178*/ | ||
| 711 | { | ||
| 712 | get_path(path); /*;AN002;*/ | ||
| 713 | |||
| 714 | if (strlen(path)==0 || path[0]==NUL) /*;AN002;*/ | ||
| 715 | error_exit(CANT_FIND_FORMAT); /*;AN002;*/ | ||
| 716 | } | ||
| 717 | |||
| 718 | pindex = 0; | ||
| 719 | while (!found_it && path[pindex] != NUL) | ||
| 720 | { | ||
| 721 | for (findex=0; path[pindex]!=NUL && path[pindex]!=';'; pindex++) /*;AN002;*/ | ||
| 722 | { /*;AN002;*/ | ||
| 723 | format_path[findex] = path[pindex]; /*;AN002;*/ | ||
| 724 | findex++; /*;AN002;*/ | ||
| 725 | } /*;AN002;*/ | ||
| 726 | |||
| 727 | if (path[pindex]==';') | ||
| 728 | pindex++; | ||
| 729 | |||
| 730 | format_path[findex] = NUL; /*;AN002;*/ | ||
| 731 | |||
| 732 | xlat(format_path,format_path); /*;AN002;*/ | ||
| 733 | |||
| 734 | if (strlen(format_path)==3 && format_path[1]==':') /*;AN000;p1900*/ | ||
| 735 | format_path[2] = NUL; /*;AN000;p1900*/ | ||
| 736 | |||
| 737 | strcat(format_path,"\\FORMAT.COM"); /*;AN000;d178*/ | ||
| 738 | |||
| 739 | if (format_path[0] == tgt_drive_letter) /*;AN010;*/ | ||
| 740 | if (target_removable) /*;AN010;*/ | ||
| 741 | format_path[0] = NUL; /*;AN010;*/ | ||
| 742 | |||
| 743 | if (exist(format_path)) /*;AN000;d178*/ | ||
| 744 | found_it = TRUE; /*;AN000;d178*/ | ||
| 745 | } /*;AN000;d178*/ | ||
| 746 | |||
| 747 | if (!found_it) /*;AN000;d178*/ | ||
| 748 | error_exit(CANT_FIND_FORMAT); /*;AN000;d178*/ | ||
| 749 | |||
| 750 | return; /*;AN000;d178*/ | ||
| 751 | } /*;AN000;d178*/ | ||
| 752 | /*************************************************/ | ||
| 753 | /* | ||
| 754 | /* SUBROUTINE NAME: get_path | ||
| 755 | /* | ||
| 756 | /* FUNCTION: | ||
| 757 | /* Finds the environment pointer in the PSP, and | ||
| 758 | /* searches the envirnment for a PATH statement. | ||
| 759 | /* If found, copies it to the buffer address passed in. | ||
| 760 | /* | ||
| 761 | /***************************************************/ | ||
| 762 | void get_path(p) /*;AN002;*/ | ||
| 763 | char *p; /*;AN002;*/ | ||
| 764 | { /*;AN002;*/ | ||
| 765 | char far * env_ptr; /*;AN002;*/ | ||
| 766 | WORD env_seg; /*;AN002;*/ | ||
| 767 | BYTE got_path = FALSE; /*;AN002;*/ | ||
| 768 | BYTE done = FALSE; /*;AN002;*/ | ||
| 769 | union REGS xregs; /*;AN002;*/ | ||
| 770 | char path[130]; /*;AN002;*/ | ||
| 771 | |||
| 772 | /* First find PSP */ | ||
| 773 | xregs.x.ax = 0x6200; /* Get PSP Address */ /*;AN002;*/ | ||
| 774 | intdos(&xregs,&xregs); /* Returned in BX */ /*;AN002;*/ | ||
| 775 | |||
| 776 | /* Build pointer to env ptr from PSP+2c */ | ||
| 777 | env_ptr = far_ptr(xregs.x.bx,0x2c); /*;AN002;*/ | ||
| 778 | env_seg = *(WORD far *)env_ptr; /*;AN002;*/ | ||
| 779 | env_ptr = far_ptr(env_seg,0); /*;AN002;*/ | ||
| 780 | *p = NUL; /*;AN002;*/ | ||
| 781 | |||
| 782 | /* Search for PATH in the environment */ | ||
| 783 | while (!done) /*;AN002;*/ | ||
| 784 | { /*;AN002;*/ | ||
| 785 | if /*;AN002;*/ | ||
| 786 | (*env_ptr == 'P' && /*;AN002;*/ | ||
| 787 | *(env_ptr+1) == 'A' && /*;AN002;*/ | ||
| 788 | *(env_ptr+2) == 'T' && /*;AN002;*/ | ||
| 789 | *(env_ptr+3) == 'H' && /*;AN002;*/ | ||
| 790 | *(env_ptr+4) == '=' /*;AN002;*/ | ||
| 791 | ) /*;AN002;*/ | ||
| 792 | { /*;AN002;*/ | ||
| 793 | done = TRUE; /*;AN002;*/ | ||
| 794 | got_path = TRUE; /*;AN002;*/ | ||
| 795 | } /*;AN002;*/ | ||
| 796 | else /*;AN002;*/ | ||
| 797 | if (*env_ptr == NUL && *(env_ptr+1) == NUL) /*;AN002;*/ | ||
| 798 | done = TRUE; /*;AN002;*/ | ||
| 799 | |||
| 800 | if (!done) /*;AN002;*/ | ||
| 801 | env_ptr++; /*;AN002;*/ | ||
| 802 | } /*;AN002;*/ | ||
| 803 | |||
| 804 | /* Copy path to desired buffer */ | ||
| 805 | if (got_path) /*;AN002;*/ | ||
| 806 | { /*;AN002;*/ | ||
| 807 | env_ptr += 5; /* Skip over "PATH=" */ /*;AN002;*/ | ||
| 808 | for (; *env_ptr!=NUL; env_ptr++) /*;AN002;*/ | ||
| 809 | { /*;AN002;*/ | ||
| 810 | *p = *env_ptr; /*;AN002;*/ | ||
| 811 | p++; /*;AN002;*/ | ||
| 812 | } /*;AN002;*/ | ||
| 813 | |||
| 814 | *p = NUL; /*;AN002;*/ | ||
| 815 | } /*;AN002;*/ | ||
| 816 | |||
| 817 | return; /*;AN002;*/ | ||
| 818 | } /*;AN002;*/ | ||
| 819 | |||
| 820 | /*************************************************/ | ||
| 821 | /* | ||
| 822 | /* SUBROUTINE NAME: xlat | ||
| 823 | /* | ||
| 824 | /* FUNCTION: | ||
| 825 | /* | ||
| 826 | /* Performs name translate function. Calls DOS function | ||
| 827 | /* call 60h to build full path from root using the "src" | ||
| 828 | /* passed in, places resultant path at "tgt". | ||
| 829 | /* | ||
| 830 | /***************************************************/ | ||
| 831 | void xlat(tgt,src) /*;AN000;*/ | ||
| 832 | char * tgt; /*;AN000;*/ | ||
| 833 | char * src; /*;AN000;*/ | ||
| 834 | { /*;AN000;*/ | ||
| 835 | union REGS xregs; | ||
| 836 | |||
| 837 | xregs.x.ax = 0x6000; /* Name Xlat*/ /*;AN000;*/ | ||
| 838 | xregs.x.bx = 0; /* Drive*/ /*;AN000;*/ | ||
| 839 | xregs.x.si = (WORD)src; /* Source*/ /*;AN000;*/ | ||
| 840 | xregs.x.di = (WORD)tgt; /* Target*/ /*;AN000;*/ | ||
| 841 | intdos(&xregs,&xregs); /* Blammo!*/ /*;AN000;*/ | ||
| 842 | |||
| 843 | return; /*;AN000;*/ | ||
| 844 | } /*;AN000;*/ | ||
| 845 | /*************************************************/ | ||
| 846 | /* | ||
| 847 | /* SUBROUTINE NAME: check_drive_validity | ||
| 848 | /* | ||
| 849 | /* FUNCTION: | ||
| 850 | /* | ||
| 851 | /* Verify that at least the target drive letter is | ||
| 852 | /* is entered. Verify that they are valid drives. | ||
| 853 | /* | ||
| 854 | /***************************************************/ | ||
| 855 | void check_drive_validity(argc,argv) | ||
| 856 | int argc; | ||
| 857 | char *argv[]; | ||
| 858 | { | ||
| 859 | char *t; | ||
| 860 | int i; | ||
| 861 | BYTE specified_drive; | ||
| 862 | |||
| 863 | if (argc < 2) | ||
| 864 | error_exit(NO_SOURCE); | ||
| 865 | |||
| 866 | /*********************/ | ||
| 867 | /* Verify the source */ | ||
| 868 | /*********************/ | ||
| 869 | *argv[1] = (BYTE)com_toupper(*argv[1]); | ||
| 870 | |||
| 871 | |||
| 872 | t = argv[1]; | ||
| 873 | t++; | ||
| 874 | if (*t == ':') /* Check specified source drive */ /*;AC000;p2671*/ | ||
| 875 | { /*;AN000;p2671*/ | ||
| 876 | if (*argv[1] < 'A') /*;AN000;p2671*/ | ||
| 877 | error_exit(INV_DRIVE); /*;AN000;p2671*/ | ||
| 878 | if (*argv[1] > 'Z') /*;AN000;p2671*/ | ||
| 879 | error_exit(INV_DRIVE); /*;AN000;p2671*/ | ||
| 880 | src_drive_letter = *argv[1]; /*;AN000;p2671*/ | ||
| 881 | } /* Use default drive for source */ /*;AN000;p2671*/ | ||
| 882 | else /*;AN000;p2671*/ | ||
| 883 | src_drive_letter = (BYTE)def_drive + 'A' - 1; /*;AN000;p2671*/ | ||
| 884 | |||
| 885 | /*********************/ | ||
| 886 | /* Verify the target */ | ||
| 887 | /*********************/ | ||
| 888 | if (argc < 3 ) | ||
| 889 | error_exit(NO_TARGET); | ||
| 890 | |||
| 891 | *argv[2] = (BYTE)com_toupper(*argv[2]); | ||
| 892 | |||
| 893 | if (*argv[2] < 'A') | ||
| 894 | error_exit(INV_DRIVE); | ||
| 895 | if (*argv[2] > 'Z') | ||
| 896 | error_exit(INV_DRIVE); | ||
| 897 | |||
| 898 | /* Verify drive letter followed by ":" */ | ||
| 899 | t = argv[2]; | ||
| 900 | t++; | ||
| 901 | if (*t != ':') | ||
| 902 | error_exit(NO_TARGET); | ||
| 903 | |||
| 904 | /* Make sure drive letters are different */ | ||
| 905 | if (src_drive_letter == *argv[2]) /*;AN000;p2671*/ | ||
| 906 | error_exit(SRC_AND_TGT_SAME); | ||
| 907 | |||
| 908 | /* Is source a valid drive? */ | ||
| 909 | specified_drive = src_drive_letter - 'A' + 1; | ||
| 910 | set_default_drive(specified_drive); | ||
| 911 | if (get_current_drive() != specified_drive) | ||
| 912 | error_exit(INV_DRIVE); | ||
| 913 | |||
| 914 | /* Is target a valid drive? */ | ||
| 915 | specified_drive = *argv[2] - 'A' + 1; | ||
| 916 | set_default_drive(specified_drive); | ||
| 917 | if (get_current_drive() != specified_drive) | ||
| 918 | error_exit(INV_DRIVE); | ||
| 919 | |||
| 920 | set_default_drive(def_drive); /* Reset default drive to original one */ | ||
| 921 | def_drive_set = FALSE; | ||
| 922 | |||
| 923 | tgt_drive_letter = *argv[2]; | ||
| 924 | |||
| 925 | return; | ||
| 926 | } /* end check_drive_validity */ | ||
| 927 | |||
| 928 | /*************************************************/ | ||
| 929 | /* | ||
| 930 | /* SUBROUTINE NAME: check_for_device_names | ||
| 931 | /* | ||
| 932 | /* FUNCTION: | ||
| 933 | /* | ||
| 934 | /* Make sure user not trying to restore a reserved device name | ||
| 935 | /* | ||
| 936 | /**************************************************/ | ||
| 937 | #define INVPARM 10 /*;AN000;4*/ | ||
| 938 | void check_for_device_names(argv) /*;AN000;p2592*/ | ||
| 939 | char *argv[]; /*;AN000;p2592*/ | ||
| 940 | { /*;AN000;p2592*/ | ||
| 941 | union REGS qregs; /*;AN000;p2592*/ | ||
| 942 | char target[128]; /*;AN000;p2592*/ | ||
| 943 | char *t; /*;AN000;p2592*/ | ||
| 944 | |||
| 945 | #define CAPITALIZE_STRING 0x6521 /*;AN000;p2592*/ | ||
| 946 | |||
| 947 | qregs.x.ax = CAPITALIZE_STRING; /*;AN000;p2592*/ | ||
| 948 | qregs.x.dx = (WORD)argv[1]; /*;AN000;p2592*/ | ||
| 949 | strcpy(target,argv[1]); /*;AN000;p2592*/ | ||
| 950 | qregs.x.cx = strlen(target); /*;AN000;p2592*/ | ||
| 951 | intdos(&qregs,&qregs); /*;AN000;p2592*/ | ||
| 952 | strcpy(target,argv[1]); /*;AN000;p2592*/ | ||
| 953 | |||
| 954 | for (t=&target[0]; *t!=NUL; t++) | ||
| 955 | if /*;AN000;p2592*/ | ||
| 956 | ( strcmp(t,"LPT1")==0 || /*;AN000;p2592*/ | ||
| 957 | strcmp(t,"LPT2")==0 || /*;AN000;p2592*/ | ||
| 958 | strcmp(t,"PRN")==0 || /*;AN000;p2592*/ | ||
| 959 | strcmp(t,"CON")==0 || /*;AN000;p2592*/ | ||
| 960 | strcmp(t,"NUL")==0 || /*;AN000;p2592*/ | ||
| 961 | strcmp(t,"AUX")==0 || /*;AN000;p2592*/ | ||
| 962 | strcmp(t,"LPT1:")==0 || /*;AN000;p2592*/ | ||
| 963 | strcmp(t,"LPT2:")==0 || /*;AN000;p2592*/ | ||
| 964 | strcmp(t,"PRN:")==0 || /*;AN000;p2592*/ | ||
| 965 | strcmp(t,"CON:")==0 || /*;AN000;p2592*/ | ||
| 966 | strcmp(t,"NUL:")==0 || /*;AN000;p2592*/ | ||
| 967 | strcmp(t,"AUX:")==0 /*;AN000;p2592*/ | ||
| 968 | ) /*;AN000;p2592*/ | ||
| 969 | { /*;AN000;p2592*/ | ||
| 970 | sublist.value1 = (char far *)t; /*;AN000;p2592*/ | ||
| 971 | sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;p2592*/ | ||
| 972 | sublist.one = 0; /*;AN000;p2592*/ | ||
| 973 | sublist.max_width1 = (BYTE)strlen(t); /*;AN000;p2592*/ | ||
| 974 | sublist.min_width1 = sublist.max_width1; /*;AN000;p2592*/ | ||
| 975 | |||
| 976 | display_it (INVPARM,STDERR,1,NOWAIT,(BYTE)PARSEERROR); /*;AN000;p2592*/ | ||
| 977 | return_code = RETCODE_ERROR; /*;AN000;4*/ | ||
| 978 | clean_up_and_exit(); /*;AN000;4*/ | ||
| 979 | } /*;AN000;p2592*/ | ||
| 980 | |||
| 981 | |||
| 982 | return; /*;AN000;p2592*/ | ||
| 983 | } /*;AN000;p2592*/ | ||
| 984 | |||
| 985 | |||
| 986 | /*************************************************/ | ||
| 987 | /* | ||
| 988 | /* SUBROUTINE NAME: check_path_validity | ||
| 989 | /* | ||
| 990 | /* FUNCTION: | ||
| 991 | /* | ||
| 992 | /* Verify that the path entered by the user exists. | ||
| 993 | /* Build a full path from the root, place it in | ||
| 994 | /* src_drive_path. Extract filespec and place it | ||
| 995 | /* in user_filespec. | ||
| 996 | /* | ||
| 997 | /***************************************************/ | ||
| 998 | void check_path_validity(argv) | ||
| 999 | char *argv[]; | ||
| 1000 | { | ||
| 1001 | WORD dhandle; | ||
| 1002 | char temppath[PATHLEN+20]; | ||
| 1003 | char temppath2[PATHLEN+20]; | ||
| 1004 | char globals = FALSE; | ||
| 1005 | int x; /*;AN000;p2943*/ | ||
| 1006 | char *foo,*foo2; /*;AN003;*/ | ||
| 1007 | union REGS qregs; /*;AC000;8*/ | ||
| 1008 | |||
| 1009 | strcpy(src_drive_path_fn,argv[1]); /* Copy argv[1] to string area */ | ||
| 1010 | |||
| 1011 | for (x=0; x<strlen(src_drive_path_fn); x++) /*;AN000;p2943*/ | ||
| 1012 | if (src_drive_path_fn[x] == BACKSLASH) /*;AN000;p2943*/ | ||
| 1013 | if (src_drive_path_fn[x+1] == BACKSLASH) /*;AN000;p2943*/ | ||
| 1014 | error_exit(INV_PATH); /*;AN000;p2943*/ | ||
| 1015 | |||
| 1016 | if (strlen(src_drive_path_fn) == 2) /* If only a drive letter entered, make it d:*.* */ | ||
| 1017 | if (src_drive_path_fn[1] == ':') /*;AN000;p2671*/ | ||
| 1018 | strcat(src_drive_path_fn,"*.*"); | ||
| 1019 | |||
| 1020 | if (src_drive_path_fn[strlen(src_drive_path_fn)-1] == BACKSLASH)/*;AN000;p2671*/ | ||
| 1021 | strcat(src_drive_path_fn,"*.*"); /*;AN000;p2671*/ | ||
| 1022 | |||
| 1023 | xlat(src_drive_path_fn,src_drive_path_fn); /*;AN000;p2671*/ | ||
| 1024 | |||
| 1025 | /* Handle UNC format ( \\srv\name\path\path\file ) (Remote drive) */ | ||
| 1026 | if (src_drive_path_fn[0] == BACKSLASH) /*;AN003;*/ | ||
| 1027 | if (src_drive_path_fn[1] == BACKSLASH) /*;AN003;*/ | ||
| 1028 | { /*;AN003;*/ | ||
| 1029 | foo = strchr(src_drive_path_fn+3,BACKSLASH); /*;AN003;*/ | ||
| 1030 | if (foo == NUL) /*;AN003;*/ | ||
| 1031 | error_exit(INV_PATH); /*;AN003;*/ | ||
| 1032 | |||
| 1033 | foo2 = foo + 1; /*;AN003;*/ | ||
| 1034 | foo = strchr(foo2,BACKSLASH); /*;AN003;*/ | ||
| 1035 | if (foo == NUL) /*;AN003;*/ | ||
| 1036 | error_exit(INV_PATH); /*;AN003;*/ | ||
| 1037 | |||
| 1038 | sprintf(src_drive_path_fn,"%c:%s",src_drive_letter,foo); /*;AN003;*/ | ||
| 1039 | } /*;AN003;*/ | ||
| 1040 | |||
| 1041 | /* See if there are global characters specified */ | ||
| 1042 | if (com_strchr(src_drive_path_fn,'?') != NUL) | ||
| 1043 | globals = TRUE; | ||
| 1044 | else | ||
| 1045 | if (com_strchr(src_drive_path_fn,'*') != NUL) | ||
| 1046 | globals = TRUE; | ||
| 1047 | |||
| 1048 | |||
| 1049 | if (src_drive_path_fn[3] == BACKSLASH) /* Don't let user entered d:\\ */ | ||
| 1050 | if (src_drive_path_fn[2] == BACKSLASH) | ||
| 1051 | error_exit(INV_PATH); | ||
| 1052 | |||
| 1053 | if (source_removable) /* If backing up from a diskette */ | ||
| 1054 | { | ||
| 1055 | display_msg(INSERTSOURCE); /* Ask user for diskette and wait for input*/ | ||
| 1056 | /*wait_for_keystroke(); /* Let user "Strike any key when ready" */ | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | |||
| 1060 | /* If single drive system, eliminates double prompting */ | ||
| 1061 | /* for user to "Insert diskette for drive %1" */ | ||
| 1062 | qregs.x.ax = SETLOGICALDRIVE; /*;AN000;8*/ | ||
| 1063 | qregs.h.bl = src_drive_letter - 'A' + 1; /*;AN000;8*/ | ||
| 1064 | intdos(&qregs,&qregs); /*;AN000;8*/ | ||
| 1065 | |||
| 1066 | find_first /* Check for Invalid Path */ | ||
| 1067 | ( /* Also figure out if it is file or directory */ | ||
| 1068 | &src_drive_path_fn[0], | ||
| 1069 | &dhandle, | ||
| 1070 | dta_addr, | ||
| 1071 | (SUBDIR + SYSTEM + HIDDEN) | ||
| 1072 | ); | ||
| 1073 | |||
| 1074 | if (rc != NOERROR) /* If there was an error */ | ||
| 1075 | if (rc == 3) /* If it was Path Not Found */ | ||
| 1076 | error_exit(INV_PATH); /* Terminate */ | ||
| 1077 | |||
| 1078 | if (rc == NOERROR) | ||
| 1079 | findclose(dhandle); | ||
| 1080 | |||
| 1081 | if ((dta.attributes & SUBDIR) == SUBDIR) /* If they entered a subdirectory name, */ | ||
| 1082 | if (dta.file_name[0] != '.') /* add to the end of it "\*.*" */ | ||
| 1083 | if (!globals) /* But only if there are no global chars */ | ||
| 1084 | strcat(src_drive_path_fn,"\\*.*"); | ||
| 1085 | |||
| 1086 | |||
| 1087 | /************************/ | ||
| 1088 | /* Build src_drive_FN **/ | ||
| 1089 | strcpy(src_drive_path,src_drive_path_fn); | ||
| 1090 | |||
| 1091 | /* Remove last BACKSLASH to get the pathname */ | ||
| 1092 | foo = com_strrchr(src_drive_path,BACKSLASH); | ||
| 1093 | |||
| 1094 | if (foo != NUL) | ||
| 1095 | if ((foo - src_drive_path) > 2) | ||
| 1096 | *foo = NUL; | ||
| 1097 | else | ||
| 1098 | { /* foo must = 2 */ | ||
| 1099 | foo++; | ||
| 1100 | *foo = NUL; | ||
| 1101 | } | ||
| 1102 | |||
| 1103 | /************************/ | ||
| 1104 | /* Build src_fn **/ | ||
| 1105 | foo = com_strrchr(src_drive_path_fn,BACKSLASH); /*;AN000;p2341*/ | ||
| 1106 | |||
| 1107 | if (foo == NUL) /*;AN000;p2341*/ | ||
| 1108 | foo = &src_drive_path_fn[2]; /*;AN000;p2341*/ | ||
| 1109 | else /*;AN000;p2341*/ | ||
| 1110 | foo++; /* Skip over last non-DBCS char */ /*;AN000;p2341*/ | ||
| 1111 | |||
| 1112 | strcpy(src_fn,foo); /*;AN003;*/ | ||
| 1113 | |||
| 1114 | got_path_validity = TRUE; /*;AN000;4*/ | ||
| 1115 | |||
| 1116 | return; | ||
| 1117 | } /* end check_path_validity */ | ||
| 1118 | |||
| 1119 | /*************************************************/ | ||
| 1120 | /* | ||
| 1121 | /* SUBROUTINE NAME: alloc_buffers | ||
| 1122 | /* | ||
| 1123 | /* FUNCTION: | ||
| 1124 | /* Attempt to allocate a (64k-1) buffer. If | ||
| 1125 | /* fails, decrement buff size by 512 and keep | ||
| 1126 | /* trying. If can't get at least a 2k buffer, | ||
| 1127 | /* give up. | ||
| 1128 | /* | ||
| 1129 | /***************************************************/ | ||
| 1130 | void alloc_buffer() | ||
| 1131 | { | ||
| 1132 | alloc_seg(); | ||
| 1133 | |||
| 1134 | while ((rc != NOERROR) && (data_file_alloc_size > 2048)) | ||
| 1135 | { | ||
| 1136 | data_file_alloc_size = data_file_alloc_size - 512; | ||
| 1137 | alloc_seg(); | ||
| 1138 | } | ||
| 1139 | |||
| 1140 | if (rc == NOERROR && data_file_alloc_size > 2048) | ||
| 1141 | buffers_allocated = TRUE; | ||
| 1142 | else | ||
| 1143 | error_exit(INSUFF_MEMORY); | ||
| 1144 | |||
| 1145 | return; | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | /*************************************************/ | ||
| 1149 | /* | ||
| 1150 | /* SUBROUTINE NAME: process_switch | ||
| 1151 | /* | ||
| 1152 | /* FUNCTION: | ||
| 1153 | /* | ||
| 1154 | /* Identify the parameter and set program control | ||
| 1155 | /* flags as appropriate. | ||
| 1156 | /* | ||
| 1157 | /***************************************************/ | ||
| 1158 | void process_switch() /*;AN000;4*/ | ||
| 1159 | { /*;AN000;4*/ | ||
| 1160 | char far * y; /*;AN000;4*/ | ||
| 1161 | int i = 0; /*;AN000;4*/ | ||
| 1162 | char temp_str[PATHLEN+20]; /*;AN000;7*/ | ||
| 1163 | |||
| 1164 | if (sw_buff.sw_synonym_ptr == (WORD)&sw1.switch1[0]) /* /S */ /*;AN000;4 /S */ | ||
| 1165 | { /*;AN000;4*/ | ||
| 1166 | do_subdirs=TRUE; /*;AN000;4*/ | ||
| 1167 | } /*;AN000;4*/ | ||
| 1168 | |||
| 1169 | if (sw_buff.sw_synonym_ptr == (WORD)&sw5.switch1[0]) /* /F */ /*;AN001;DCR 434 /F */ | ||
| 1170 | { /*;AN001;DCR 434*/ | ||
| 1171 | if (!target_removable) /*;AN001;DCR 434*/ | ||
| 1172 | error_exit(CANT_FORMAT_HARDFILE); /*;AN001;DCR 434*/ | ||
| 1173 | |||
| 1174 | do_format_parms=TRUE; /*;AN001;DCR 434*/ | ||
| 1175 | format_size[0] = ' '; /* Can't do STRCPY during PARSE */ /*;AN001;DCR 434*/ | ||
| 1176 | format_size[1] = '/'; /*;AN001;DCR 434*/ | ||
| 1177 | format_size[2] = 'F'; /*;AN001;DCR 434*/ | ||
| 1178 | format_size[3] = ':'; /*;AN001;DCR 434*/ | ||
| 1179 | format_size[4] = NUL; /*;AN001;DCR 434*/ | ||
| 1180 | |||
| 1181 | i = 4; /* Copy size */ /*;AN001;DCR 434*/ | ||
| 1182 | for (y=(char *)sw_buff.sw_string_ptr; *y!=NUL; y++) /*;AN001;DCR 434*/ | ||
| 1183 | { /*;AN001;DCR 434*/ | ||
| 1184 | format_size[i] = (BYTE)*y; /*;AN001;DCR 434*/ | ||
| 1185 | i++; /*;AN001;DCR 434*/ | ||
| 1186 | } /*;AN001;DCR 434*/ | ||
| 1187 | |||
| 1188 | /* Handle case where user only enters /F */ | ||
| 1189 | if ( | ||
| 1190 | format_size[4] == NUL || /*;AN001;DCR 434*/ | ||
| 1191 | format_size[4] < '0' || /*;AN001;DCR 434*/ | ||
| 1192 | format_size[4] > '9' /*;AN001;DCR 434*/ | ||
| 1193 | ) /*;AN001;DCR 434*/ | ||
| 1194 | format_size[0] = NUL; /*;AN001;DCR 434*/ | ||
| 1195 | |||
| 1196 | } /*;AN001;DCR 434*/ | ||
| 1197 | |||
| 1198 | if (sw_buff.sw_synonym_ptr == (WORD)&sw1.switch2[0]) /* /M */ /*;AN000;4 /M */ | ||
| 1199 | { /*;AN000;4*/ | ||
| 1200 | do_modified=TRUE; /*;AN000;4*/ | ||
| 1201 | } /*;AN000;4*/ | ||
| 1202 | |||
| 1203 | if (sw_buff.sw_synonym_ptr == (WORD)&sw1.switch3[0]) /* /A */ /*;AN000;4 /A */ | ||
| 1204 | { /*;AN000;4*/ | ||
| 1205 | do_add=TRUE; /*;AN000;4*/ | ||
| 1206 | } /*;AN000;4*/ | ||
| 1207 | |||
| 1208 | if (sw_buff.sw_synonym_ptr == (WORD)&sw4.switch1[0]) /* /L */ /*;AN000;4 /L */ | ||
| 1209 | { /*;AN000;4*/ | ||
| 1210 | do_logfile = TRUE; /*;AN000;4*/ | ||
| 1211 | i = 0; /* Copy filespec */ /*;AN000;4*/ | ||
| 1212 | for (y=(char far *)sw_buff.sw_string_ptr; *y!=NUL; y++) /*;AN000;4*/ | ||
| 1213 | { /*;AN000;4*/ | ||
| 1214 | temp_str[i] = (BYTE)*y; /*;AN000;4*/ | ||
| 1215 | i++; /*;AN000;4*/ | ||
| 1216 | } /*;AN000;4*/ | ||
| 1217 | |||
| 1218 | temp_str[i] = NUL; /*;AN000;4*/ | ||
| 1219 | |||
| 1220 | if (strlen(temp_str) == 0) /* Use default logfile? */ /*;AN000;7 Is default logfile?*/ | ||
| 1221 | sprintf(temp_str,"%c:\\BACKUP.LOG",src_drive_letter); /*;AN000;7*/ | ||
| 1222 | |||
| 1223 | xlat(logfile_path,temp_str); /*;AN000;7*/ | ||
| 1224 | |||
| 1225 | if ((BYTE)logfile_path[0] == tgt_drive_letter) /*;AN000;7*/ | ||
| 1226 | logfile_on_target = TRUE; /*;AN000;7*/ | ||
| 1227 | } /*;AN000;4*/ | ||
| 1228 | |||
| 1229 | return; /*;AN000;4*/ | ||
| 1230 | } /* end process_switch */ /*;AN000;4*/ | ||
| 1231 | |||
| 1232 | |||
| 1233 | /*************************************************/ | ||
| 1234 | /* | ||
| 1235 | /* SUBROUTINE NAME: save_current_dirs | ||
| 1236 | /* | ||
| 1237 | /* FUNCTION: | ||
| 1238 | /* | ||
| 1239 | /* Save the current directory on default drive. | ||
| 1240 | /* Later when we terminate we must restore it. | ||
| 1241 | /* | ||
| 1242 | /***************************************************/ | ||
| 1243 | void save_current_dirs() | ||
| 1244 | { | ||
| 1245 | |||
| 1246 | src_def_dir[0] = BACKSLASH; | ||
| 1247 | get_current_dir(src_drive_letter -'A'+1,&src_def_dir[1]); | ||
| 1248 | |||
| 1249 | return; | ||
| 1250 | } /* end save_current_dirs */ | ||
| 1251 | /*************************************************/ | ||
| 1252 | /* | ||
| 1253 | /* SUBROUTINE NAME: open_logfile | ||
| 1254 | /* | ||
| 1255 | /* FUNCTION: | ||
| 1256 | /* User specified the /L parameter for a BACKUP | ||
| 1257 | /* log file. First try to open it. If it doesn't | ||
| 1258 | /* exist then create it. | ||
| 1259 | /* | ||
| 1260 | /***************************************************/ | ||
| 1261 | void open_logfile() | ||
| 1262 | { | ||
| 1263 | int x; /*;AN000;7*/ | ||
| 1264 | |||
| 1265 | handle_logfile = /*;AN000;5*/ | ||
| 1266 | extended_open /*;AN000;5*/ | ||
| 1267 | (OPEN_IT, /* Flag;AN000;5*/ | ||
| 1268 | 0, /* attr;AN000;5*/ | ||
| 1269 | (char far *)logfile_path, /* path;AN000;5*/ | ||
| 1270 | (WORD)(DENYWRITE+WRITEACCESS) /* mode;AN000;5*/ | ||
| 1271 | ); /*;AN000;5*/ | ||
| 1272 | |||
| 1273 | if (rc == NOERROR) | ||
| 1274 | lseek(handle_logfile,EOFILE,(DWORD)0); | ||
| 1275 | else /* If you didn't, create the file */ | ||
| 1276 | handle_logfile = /*;AN000;5*/ | ||
| 1277 | extended_open /*;AN000;5*/ | ||
| 1278 | ( CREATE_IT, /*;AN000;5*/ | ||
| 1279 | (WORD)ARCHIVE, /*;AN000;5*/ | ||
| 1280 | (char far *)logfile_path, /*;AN000;5*/ | ||
| 1281 | (WORD)(WRITEACCESS) /*;AN000;5*/ | ||
| 1282 | ); /*;AN000;5*/ | ||
| 1283 | |||
| 1284 | if (rc != NOERROR) /* Terminate if can't open logfile */ | ||
| 1285 | error_exit(CANT_OPEN_LOGFILE); | ||
| 1286 | |||
| 1287 | display_msg(LOGGING); /* Tell user where we are logging */ | ||
| 1288 | |||
| 1289 | datetime(); /* Put date and time of BACKUP in logfile */ | ||
| 1290 | |||
| 1291 | logfile_opened = TRUE; /*;AN000;7 The logfile is open */ | ||
| 1292 | |||
| 1293 | return; | ||
| 1294 | } /* end open_logfile */ | ||
| 1295 | |||
| 1296 | /*************************************************/ | ||
| 1297 | /* | ||
| 1298 | /* SUBROUTINE NAME: set_vectors | ||
| 1299 | /* | ||
| 1300 | /* FUNCTION: | ||
| 1301 | /* Hook control break and critical vector to | ||
| 1302 | /* allow BACKUP to gracefully terminate. | ||
| 1303 | /* | ||
| 1304 | /***************************************************/ | ||
| 1305 | void set_vectors() | ||
| 1306 | { | ||
| 1307 | |||
| 1308 | setsignal(ACTIONHOOK,CTRLC); /* Handle CTRL_C */ | ||
| 1309 | setsignal(ACTIONHOOK,CTRLBREAK); /* Handle CTRL_BREAK */ | ||
| 1310 | set_int24_vector(); /*;AN000; Set Critical error vector (int 24h) */ | ||
| 1311 | |||
| 1312 | return; | ||
| 1313 | } /* end set_vectors */ | ||
| 1314 | |||
| 1315 | /*************************************************/ | ||
| 1316 | /* | ||
| 1317 | /* SUBROUTINE NAME: check_appendX | ||
| 1318 | /* | ||
| 1319 | /* FUNCTION: | ||
| 1320 | /* Check APPEND /X status. If it is not active, | ||
| 1321 | /* do nothing. If it is active, then turn it off | ||
| 1322 | /* and set flag indicating that we must reset it later. | ||
| 1323 | /* | ||
| 1324 | /***************************************************/ | ||
| 1325 | void check_appendX() /*;AN000;2*/ | ||
| 1326 | { /*;AN000;2*/ | ||
| 1327 | union REGS gregs; /*;AN000;2 Register set */ | ||
| 1328 | |||
| 1329 | gregs.x.ax = INSTALL_CHECK; /*;AN000;2 Get installed state*/ | ||
| 1330 | int86(0x2f,&gregs,&gregs); /*;AN000;2*/ | ||
| 1331 | |||
| 1332 | /*****************************************************/ | ||
| 1333 | /* 1) See if append is active | ||
| 1334 | /* 2) If so, figure out if DOS or PCNET version | ||
| 1335 | /*****************************************************/ | ||
| 1336 | if (gregs.h.al == 0) /*;AN000;2 Zero if not installed*/ | ||
| 1337 | append_indicator = NOT_INSTALLED; /*;AN000;2 */ | ||
| 1338 | else /*;AN000;2 See which APPEND it is*/ | ||
| 1339 | { /*;AN000;2*/ | ||
| 1340 | gregs.x.ax = GET_APPEND_VER; /*;AN000;2*/ | ||
| 1341 | int86(0x2f,&gregs,&gregs); /*;AN000;2*/ | ||
| 1342 | |||
| 1343 | if (gregs.h.al == (BYTE)-1) /*;AN000;2 -1 if DOS version*/ | ||
| 1344 | append_indicator = DOS_APPEND; /*;AN000;2*/ | ||
| 1345 | else /*;AN000;2*/ | ||
| 1346 | append_indicator = NET_APPEND; /*;AN000;2*/ | ||
| 1347 | } /*;AN000;2*/ | ||
| 1348 | |||
| 1349 | /*****************************************************/ | ||
| 1350 | /* If it is the DOS append | ||
| 1351 | /* 1) Get the current append functions (returned in BX) | ||
| 1352 | /* 2) Reset append with /X support off | ||
| 1353 | /*****************************************************/ | ||
| 1354 | if (append_indicator == DOS_APPEND) /*;AN000;2*/ | ||
| 1355 | { /*;AN000;2*/ | ||
| 1356 | gregs.x.ax = GET_STATE; /*;AN000;2 Get active APPEND functions*/ | ||
| 1357 | int86(0x2f,&gregs,&gregs); /*;AN000;2*/ | ||
| 1358 | original_append_func = gregs.x.bx; /*;AN000;2*/ | ||
| 1359 | |||
| 1360 | gregs.x.ax = SET_STATE; /*;AN000;2*/ | ||
| 1361 | gregs.x.bx = gregs.x.bx & (!APPEND_X_BIT); /*;AN000;2*/ | ||
| 1362 | int86(0x2f,&gregs,&gregs); /*;AN000;2*/ | ||
| 1363 | |||
| 1364 | } /*;AN000;2*/ | ||
| 1365 | |||
| 1366 | return; /*;AN000;2*/ | ||
| 1367 | } /*;AN000;2*/ | ||
| 1368 | |||
| 1369 | /*************************************************/ | ||
| 1370 | /* | ||
| 1371 | /* SUBROUTINE NAME: get_drive_types | ||
| 1372 | /* | ||
| 1373 | /* FUNCTION: | ||
| 1374 | /* For the source and target drives, figure out | ||
| 1375 | /* if they are removable or not. | ||
| 1376 | /* | ||
| 1377 | /***************************************************/ | ||
| 1378 | void get_drive_types() /* Check if the source and target drive are removable*/ | ||
| 1379 | { | ||
| 1380 | #define REMOVABLE 0 | ||
| 1381 | |||
| 1382 | WORD drivehandle; | ||
| 1383 | char drive_spec[3]; | ||
| 1384 | |||
| 1385 | /* Check Source drive */ | ||
| 1386 | drive_spec[0] = src_drive_letter; | ||
| 1387 | drive_spec[1] = ':'; | ||
| 1388 | drive_spec[2] = NUL; | ||
| 1389 | |||
| 1390 | /* Device open, source drive */ | ||
| 1391 | drivehandle = handle_open(drive_spec,OPENDASD+DENYNONE) ; | ||
| 1392 | |||
| 1393 | /* Now see if it is removable */ | ||
| 1394 | if (ioctl(drivehandle) == REMOVABLE) | ||
| 1395 | source_removable = TRUE; | ||
| 1396 | else | ||
| 1397 | source_removable = FALSE; | ||
| 1398 | |||
| 1399 | close_file(drivehandle); | ||
| 1400 | |||
| 1401 | /* Check Target drive */ | ||
| 1402 | drive_spec[0] = tgt_drive_letter; | ||
| 1403 | drive_spec[1] = ':'; | ||
| 1404 | drive_spec[2] = NUL; | ||
| 1405 | |||
| 1406 | drivehandle = handle_open(drive_spec,OPENDASD+DENYNONE) ; | ||
| 1407 | |||
| 1408 | if (ioctl(drivehandle) == REMOVABLE) | ||
| 1409 | target_removable = TRUE; | ||
| 1410 | else | ||
| 1411 | target_removable = FALSE; | ||
| 1412 | |||
| 1413 | close_file(drivehandle); | ||
| 1414 | |||
| 1415 | return; | ||
| 1416 | } /* end get_drive_types */ | ||
| 1417 | |||
| 1418 | /*************************************************/ | ||
| 1419 | /* | ||
| 1420 | /* SUBROUTINE NAME: do_backup | ||
| 1421 | /* | ||
| 1422 | /* FUNCTION: | ||
| 1423 | /* | ||
| 1424 | /* BACKUP all files that should be backed up | ||
| 1425 | /* | ||
| 1426 | /***************************************************/ | ||
| 1427 | void do_backup() | ||
| 1428 | { | ||
| 1429 | set_default_dir(); /* Set default dir to one where source files are */ | ||
| 1430 | |||
| 1431 | find_first_file(); /* Find first file to be backed up */ | ||
| 1432 | if (back_it_up) /* If you found one.... */ | ||
| 1433 | { /* then */ | ||
| 1434 | get_first_target(); /* get the first diskette (or last if /A specified!) */ | ||
| 1435 | do /* Repeat this */ | ||
| 1436 | { | ||
| 1437 | open_source_file(); /* Open the file we found */ | ||
| 1438 | if (source_opened) /* If succeessful open of source */ | ||
| 1439 | do_copy(); /* Copy it to the target drive. Handle files that span diskettes. */ | ||
| 1440 | find_next_file(); /* Search for another file */ | ||
| 1441 | } | ||
| 1442 | while (back_it_up); /* While there are file to back up */ | ||
| 1443 | display_msg(CRLF); | ||
| 1444 | } | ||
| 1445 | else /* otherwise */ | ||
| 1446 | { | ||
| 1447 | display_msg(NONEFNDMSG); | ||
| 1448 | return_code = RETCODE_NO_FILES;/* there were no files to be backed up */ | ||
| 1449 | } | ||
| 1450 | |||
| 1451 | clean_up_and_exit(); | ||
| 1452 | |||
| 1453 | return; | ||
| 1454 | } /* end do_backup */ | ||
| 1455 | /*************************************************/ | ||
| 1456 | /* | ||
| 1457 | /* SUBROUTINE NAME: find_first_file | ||
| 1458 | /* | ||
| 1459 | /* FUNCTION: | ||
| 1460 | /* | ||
| 1461 | /* Find the first file conforming to user entered spec. | ||
| 1462 | /* If necessary, look on other directory levels also. | ||
| 1463 | /* | ||
| 1464 | /***************************************************/ | ||
| 1465 | void find_first_file() | ||
| 1466 | { | ||
| 1467 | char loop_done = FALSE; | ||
| 1468 | |||
| 1469 | back_it_up = FALSE; /* Havn't found a file yet ! */ | ||
| 1470 | find_the_first(); /* Sets the "found_a_file" flag */ | ||
| 1471 | |||
| 1472 | if (found_a_file) /* If you find a file, do this stuff */ | ||
| 1473 | do | ||
| 1474 | { | ||
| 1475 | if (found_a_file) /* If you got one, then */ | ||
| 1476 | see_if_it_should_be_backed_up(); /* Check it against user entered parameters */ | ||
| 1477 | |||
| 1478 | if (!back_it_up) /* If it shouldn't be processed... */ | ||
| 1479 | find_the_next(); /* then find another (sets the "found_a_file" flag) */ | ||
| 1480 | else | ||
| 1481 | loop_done = TRUE; /* Otherwise your done here */ | ||
| 1482 | |||
| 1483 | if (!found_a_file) /* Don't remove this ! */ | ||
| 1484 | loop_done = TRUE; /* This has gotta stay ! */ | ||
| 1485 | } | ||
| 1486 | while (!loop_done); | ||
| 1487 | |||
| 1488 | return; | ||
| 1489 | } /* end find_first_file */ | ||
| 1490 | |||
| 1491 | /***********************************************/ | ||
| 1492 | /* | ||
| 1493 | /* SUBROUTINE NAME: find_next_file | ||
| 1494 | /* | ||
| 1495 | /* FUNCTION: | ||
| 1496 | /* | ||
| 1497 | /* Find the next file conforming to user entered spec | ||
| 1498 | /* | ||
| 1499 | /************************************************/ | ||
| 1500 | void find_next_file() | ||
| 1501 | { | ||
| 1502 | char loop_done = FALSE; | ||
| 1503 | |||
| 1504 | back_it_up = FALSE; | ||
| 1505 | |||
| 1506 | do | ||
| 1507 | { | ||
| 1508 | find_the_next(); | ||
| 1509 | if (found_a_file) | ||
| 1510 | { | ||
| 1511 | see_if_it_should_be_backed_up(); | ||
| 1512 | if (back_it_up) | ||
| 1513 | loop_done = TRUE; | ||
| 1514 | } | ||
| 1515 | else | ||
| 1516 | loop_done = TRUE; | ||
| 1517 | } | ||
| 1518 | while (!loop_done); | ||
| 1519 | |||
| 1520 | return; | ||
| 1521 | } /* end find_next_file */ | ||
| 1522 | |||
| 1523 | /***********************************************/ | ||
| 1524 | /* | ||
| 1525 | /* SUBROUTINE NAME: find_the_first | ||
| 1526 | /* | ||
| 1527 | /* FUNCTION: | ||
| 1528 | /* | ||
| 1529 | /* Find the first file conforming to user entered spec. | ||
| 1530 | /* Searches in current directory, if one not found then | ||
| 1531 | /* goes to the next level and repeats. | ||
| 1532 | /* | ||
| 1533 | /************************************************/ | ||
| 1534 | void find_the_first() | ||
| 1535 | { | ||
| 1536 | char loop_done = FALSE; | ||
| 1537 | char file_spec[PATHLEN]; | ||
| 1538 | |||
| 1539 | found_a_file = FALSE; | ||
| 1540 | sprintf(file_spec,"%c:%s",src_drive_letter,src_fn); | ||
| 1541 | |||
| 1542 | do | ||
| 1543 | { | ||
| 1544 | find_first /* Find file conforming to user-entered file spec */ | ||
| 1545 | ( | ||
| 1546 | &file_spec[0], | ||
| 1547 | &dirhandle, | ||
| 1548 | dta_addr, | ||
| 1549 | (SYSTEM + HIDDEN) | ||
| 1550 | ); | ||
| 1551 | |||
| 1552 | if (rc == NOERROR) | ||
| 1553 | { /* If no error */ | ||
| 1554 | found_a_file = TRUE; /* then we found a file */ | ||
| 1555 | loop_done = TRUE; /* and we are done here */ | ||
| 1556 | } | ||
| 1557 | else /* If there was an error */ | ||
| 1558 | if (do_subdirs) /* and if user said /S */ | ||
| 1559 | { | ||
| 1560 | change_levels(); /* Change DIR (Sets NewDirectory if level changed) */ | ||
| 1561 | if (!new_directory) /* If there ain't none */ | ||
| 1562 | loop_done = TRUE; /* then were done */ | ||
| 1563 | } | ||
| 1564 | else | ||
| 1565 | loop_done = TRUE; | ||
| 1566 | } | ||
| 1567 | while (!loop_done); | ||
| 1568 | |||
| 1569 | return; | ||
| 1570 | } /* end find_the_first */ | ||
| 1571 | /*************************************************/ | ||
| 1572 | /* | ||
| 1573 | /* SUBROUTINE NAME: find_the_next | ||
| 1574 | /* | ||
| 1575 | /* FUNCTION: | ||
| 1576 | /* | ||
| 1577 | /* Find the next file conforming to user entered spec | ||
| 1578 | /* | ||
| 1579 | /***************************************************/ | ||
| 1580 | void find_the_next() | ||
| 1581 | { | ||
| 1582 | char loop_done = FALSE; | ||
| 1583 | |||
| 1584 | found_a_file = FALSE; | ||
| 1585 | |||
| 1586 | find_next(dirhandle,dta_addr); | ||
| 1587 | |||
| 1588 | if (rc == NOERROR) | ||
| 1589 | { | ||
| 1590 | found_a_file = TRUE; | ||
| 1591 | loop_done = TRUE; | ||
| 1592 | } | ||
| 1593 | else | ||
| 1594 | do | ||
| 1595 | { | ||
| 1596 | if (do_subdirs) | ||
| 1597 | { | ||
| 1598 | change_levels(); /* Change DIR to next dir level */ | ||
| 1599 | if (!new_directory) /* If we were successful */ | ||
| 1600 | loop_done = TRUE; /* Then indicate that fact */ | ||
| 1601 | else /* otherwise */ | ||
| 1602 | { | ||
| 1603 | find_the_first(); /* Look for first file at this level */ | ||
| 1604 | loop_done = TRUE; | ||
| 1605 | } | ||
| 1606 | } | ||
| 1607 | else | ||
| 1608 | loop_done = TRUE; | ||
| 1609 | } | ||
| 1610 | while (!loop_done); | ||
| 1611 | |||
| 1612 | return; | ||
| 1613 | } /* end find_the_next */ | ||
| 1614 | |||
| 1615 | /*************************************************/ | ||
| 1616 | /* | ||
| 1617 | /* SUBROUTINE NAME: change_levels | ||
| 1618 | /* | ||
| 1619 | /* FUNCTION: | ||
| 1620 | /* Change directory to next one in the linked list | ||
| 1621 | /* of directories to be processed. | ||
| 1622 | /* | ||
| 1623 | /***************************************************/ | ||
| 1624 | void change_levels() | ||
| 1625 | { | ||
| 1626 | new_directory = FALSE; | ||
| 1627 | remove_node(); | ||
| 1628 | return; | ||
| 1629 | } /* end change_levels */ | ||
| 1630 | |||
| 1631 | /*************************************************/ | ||
| 1632 | /* | ||
| 1633 | /* SUBROUTINE NAME: alloc_node | ||
| 1634 | /* | ||
| 1635 | /* FUNCTION: | ||
| 1636 | /* Allocates a node for the linked list of subdirectories | ||
| 1637 | /* to be processed. | ||
| 1638 | /* | ||
| 1639 | /***************************************************/ | ||
| 1640 | struct node * alloc_node(path_len) | ||
| 1641 | unsigned int path_len; | ||
| 1642 | { | ||
| 1643 | struct node *pointer; | ||
| 1644 | unsigned int malloc_size; | ||
| 1645 | |||
| 1646 | malloc_size = (unsigned int) (sizeof(struct node far *) + path_len + 2); | ||
| 1647 | #if defined(DEBUG) | ||
| 1648 | printf("\nMALLOCING NODE, SIZE=%04Xh...",malloc_size); | ||
| 1649 | #endif | ||
| 1650 | |||
| 1651 | pointer = (struct node *)malloc(malloc_size); | ||
| 1652 | |||
| 1653 | #if defined(DEBUG) | ||
| 1654 | if (pointer != NUL) | ||
| 1655 | printf("SUCCESSFUL, PTR=%u",(unsigned)pointer); | ||
| 1656 | else | ||
| 1657 | printf("ERROR, PTR=%u",(unsigned)pointer); | ||
| 1658 | #endif | ||
| 1659 | |||
| 1660 | if (pointer == NUL) | ||
| 1661 | error_exit(INSUFF_MEMORY); | ||
| 1662 | else | ||
| 1663 | return(pointer); | ||
| 1664 | |||
| 1665 | } /* end alloc_node */ | ||
| 1666 | |||
| 1667 | |||
| 1668 | /*************************************************/ | ||
| 1669 | /* | ||
| 1670 | /* SUBROUTINE NAME: alloc_first_node | ||
| 1671 | /* | ||
| 1672 | /* FUNCTION: | ||
| 1673 | /* | ||
| 1674 | /* Allocate the first node in the linked list. | ||
| 1675 | /* | ||
| 1676 | /***************************************************/ | ||
| 1677 | void alloc_first_node() | ||
| 1678 | { | ||
| 1679 | #if defined(DEBUG) | ||
| 1680 | printf("\nINSERTING FIRST NODE=%s",src_drive_path); | ||
| 1681 | #endif | ||
| 1682 | |||
| 1683 | curr_node = alloc_node(strlen(src_drive_path+1)); | ||
| 1684 | last_child = curr_node; | ||
| 1685 | strcpy(curr_node->path,src_drive_path); | ||
| 1686 | curr_node->np = NUL; | ||
| 1687 | |||
| 1688 | return; | ||
| 1689 | } /* end alloc_first_node */ | ||
| 1690 | |||
| 1691 | |||
| 1692 | /*************************************************/ | ||
| 1693 | /* | ||
| 1694 | /* SUBROUTINE NAME: insert_node | ||
| 1695 | /* | ||
| 1696 | /* FUNCTION: | ||
| 1697 | /* | ||
| 1698 | /* Insert next node in the linked list of subdirectories | ||
| 1699 | /* to be processed. | ||
| 1700 | /* | ||
| 1701 | /***************************************************/ | ||
| 1702 | void insert_node(path_addr) | ||
| 1703 | char *path_addr; | ||
| 1704 | { | ||
| 1705 | struct node *temp; /* temporary pointer to a node */ | ||
| 1706 | struct node *newnode; /* same thing */ | ||
| 1707 | |||
| 1708 | #if defined(DEBUG) | ||
| 1709 | printf("\nINSERTING NODE=%s",*path_addr); | ||
| 1710 | #endif | ||
| 1711 | temp = last_child->np; | ||
| 1712 | newnode = alloc_node(strlen(path_addr)); | ||
| 1713 | last_child->np = newnode; | ||
| 1714 | newnode->np = temp; | ||
| 1715 | strcpy(newnode->path,path_addr); | ||
| 1716 | last_child = newnode; | ||
| 1717 | |||
| 1718 | return; | ||
| 1719 | } /* end insert_node */ | ||
| 1720 | |||
| 1721 | /*************************************************/ | ||
| 1722 | /* | ||
| 1723 | /* SUBROUTINE NAME: remove_node | ||
| 1724 | /* | ||
| 1725 | /* FUNCTION: | ||
| 1726 | /* CHDIR to the next level to be processed. | ||
| 1727 | /* Release the node for that directory | ||
| 1728 | /* | ||
| 1729 | /***************************************************/ | ||
| 1730 | void remove_node() | ||
| 1731 | { | ||
| 1732 | struct node *temp; | ||
| 1733 | |||
| 1734 | temp = curr_node; | ||
| 1735 | last_child = curr_node->np; | ||
| 1736 | if (curr_node->np != NUL) | ||
| 1737 | { | ||
| 1738 | rc = chdir(last_child->path); | ||
| 1739 | if (rc == NOERROR) | ||
| 1740 | { | ||
| 1741 | new_directory = TRUE; | ||
| 1742 | strcpy(src_drive_path,last_child->path); | ||
| 1743 | |||
| 1744 | #if defined(DEBUG) | ||
| 1745 | printf("\nFREE NODE %u",(unsigned)curr_node); | ||
| 1746 | #endif | ||
| 1747 | free((char *)curr_node); | ||
| 1748 | curr_node = last_child; | ||
| 1749 | |||
| 1750 | if (do_subdirs) /* Place all subdirs in linked list */ | ||
| 1751 | find_all_subdirs(); | ||
| 1752 | } | ||
| 1753 | } | ||
| 1754 | return; | ||
| 1755 | } /* end remove_node */ | ||
| 1756 | |||
| 1757 | /*************************************************/ | ||
| 1758 | /* | ||
| 1759 | /* SUBROUTINE NAME: find_all_subdirs | ||
| 1760 | /* | ||
| 1761 | /* FUNCTION: | ||
| 1762 | /* User entered "/S" parameter. Search for all | ||
| 1763 | /* subdirectory entries at this level. Place | ||
| 1764 | /* them all in the linked list of directories to | ||
| 1765 | /* be processed. | ||
| 1766 | /***************************************************/ | ||
| 1767 | void find_all_subdirs() | ||
| 1768 | { | ||
| 1769 | WORD dhandle; | ||
| 1770 | char global[6]; | ||
| 1771 | char full_path[PATHLEN+20]; | ||
| 1772 | struct FileFindBuf tempdta; | ||
| 1773 | |||
| 1774 | sprintf(global,"%c:*.*",src_drive_letter); | ||
| 1775 | |||
| 1776 | find_first /* Find all subdirectory entries in current directory. */ | ||
| 1777 | ( | ||
| 1778 | &global[0], | ||
| 1779 | &dhandle, | ||
| 1780 | &tempdta, | ||
| 1781 | (SUBDIR + SYSTEM + HIDDEN) | ||
| 1782 | ); | ||
| 1783 | |||
| 1784 | while (rc == NOERROR) | ||
| 1785 | { | ||
| 1786 | if ((tempdta.attributes & SUBDIR) == SUBDIR) /* If its a subdirectory */ | ||
| 1787 | if (tempdta.file_name[0] != '.') /* But not "." or ".." */ | ||
| 1788 | { | ||
| 1789 | if (src_drive_path[strlen(src_drive_path)-1] != BACKSLASH) | ||
| 1790 | sprintf(full_path,"%s\\%s",src_drive_path,tempdta.file_name); | ||
| 1791 | else | ||
| 1792 | sprintf(full_path,"%s%s", src_drive_path,tempdta.file_name); | ||
| 1793 | |||
| 1794 | insert_node((char *)full_path); /* Save it in the linked list */ | ||
| 1795 | } | ||
| 1796 | |||
| 1797 | find_next(dhandle,&tempdta); | ||
| 1798 | } | ||
| 1799 | |||
| 1800 | return; | ||
| 1801 | } | ||
| 1802 | |||
| 1803 | /*************************************************/ | ||
| 1804 | /* | ||
| 1805 | /* SUBROUTINE NAME: get_first_target | ||
| 1806 | /* | ||
| 1807 | /* FUNCTION: | ||
| 1808 | /* We are ready for the target disk. If it is a | ||
| 1809 | /* diskette, ask user to put one in. Remember | ||
| 1810 | /* to correctly handle /A if user wants it. | ||
| 1811 | /* | ||
| 1812 | /***************************************************/ | ||
| 1813 | void get_first_target() | ||
| 1814 | { | ||
| 1815 | if (target_removable) | ||
| 1816 | get_diskette(); | ||
| 1817 | else | ||
| 1818 | get_hardfile(); | ||
| 1819 | |||
| 1820 | if (do_logfile) | ||
| 1821 | open_logfile(); /*;AN000;7 Open or create logfile*/ | ||
| 1822 | |||
| 1823 | if (!do_add) | ||
| 1824 | put_disk_header(); | ||
| 1825 | |||
| 1826 | return; | ||
| 1827 | } /* end get_first_target */ | ||
| 1828 | |||
| 1829 | /*************************************************/ | ||
| 1830 | /* | ||
| 1831 | /* SUBROUTINE NAME: get_next_target | ||
| 1832 | /* | ||
| 1833 | /* FUNCTION: | ||
| 1834 | /* We are ready for the next target diskette. | ||
| 1835 | /* Ask user to insert it. Format if required. | ||
| 1836 | /* Create files, reset variables. | ||
| 1837 | /* | ||
| 1838 | /***************************************************/ | ||
| 1839 | void get_next_target() | ||
| 1840 | { | ||
| 1841 | |||
| 1842 | doing_first_target = FALSE; | ||
| 1843 | files_backed_up = 0; | ||
| 1844 | display_msg(CRLF); | ||
| 1845 | |||
| 1846 | get_diskette(); /* Get it */ | ||
| 1847 | |||
| 1848 | disk_full = FALSE; | ||
| 1849 | |||
| 1850 | if (do_logfile) | ||
| 1851 | { | ||
| 1852 | if (logfile_on_target) /*;AN000;7 and if logfile on the target drive*/ | ||
| 1853 | open_logfile(); /*;AN000;7 Open or create it*/ | ||
| 1854 | } | ||
| 1855 | |||
| 1856 | if (file_spans_target) | ||
| 1857 | show_path(); /* Display to stdout and logfile the full path from root */ | ||
| 1858 | |||
| 1859 | put_disk_header(); | ||
| 1860 | put_new_fh(); | ||
| 1861 | |||
| 1862 | return; | ||
| 1863 | } /* end get_next_target */ | ||
| 1864 | |||
| 1865 | /*************************************************/ | ||
| 1866 | /* | ||
| 1867 | /* SUBROUTINE NAME: see_if_it_should_be_backed_up | ||
| 1868 | /* | ||
| 1869 | /* FUNCTION: | ||
| 1870 | /* We found a file, its directory information is | ||
| 1871 | /* at the DTA structure. Don't backup a subdirectory | ||
| 1872 | /* or volume label. If /M specified, only backup files | ||
| 1873 | /* with archive bit set. Don't BACKUP 0 length files. | ||
| 1874 | /* If /D: and/or /T: specified, only backup appropriate files. | ||
| 1875 | /* | ||
| 1876 | /***************************************************/ | ||
| 1877 | void see_if_it_should_be_backed_up() | ||
| 1878 | { | ||
| 1879 | BYTE temp[PATHLEN+20]; /*;AN006;*/ | ||
| 1880 | |||
| 1881 | back_it_up = TRUE; | ||
| 1882 | |||
| 1883 | if ((dta.attributes & SUBDIR) == SUBDIR) /* Is it a directory name ? */ | ||
| 1884 | back_it_up = FALSE; /* Indicate that we don't want to back it up */ | ||
| 1885 | |||
| 1886 | if ((dta.attributes & VOLLABEL) == VOLLABEL) /* Is it a volumelabel ? */ | ||
| 1887 | back_it_up = FALSE; /* Indicate that we don't want to back it up */ | ||
| 1888 | |||
| 1889 | if (do_modified) /* Check ARCHIVE bit */ | ||
| 1890 | if ((dta.attributes & ARCHIVE) != ARCHIVE) | ||
| 1891 | back_it_up = FALSE; | ||
| 1892 | |||
| 1893 | if (do_time) /* Check TIME parameter */ | ||
| 1894 | { | ||
| 1895 | if (do_date) | ||
| 1896 | { /* If user entered a date, only files modified */ | ||
| 1897 | if (dta.write_date == user_specified_date) /* after specified time AND ON THE DATE ENTERED */ | ||
| 1898 | if (dta.write_time < user_specified_time) /* will be processed. Files dated after that will */ | ||
| 1899 | back_it_up = FALSE; /* ignore time parm */ | ||
| 1900 | } | ||
| 1901 | else /* If user entered time with NO DATE PARM, then */ | ||
| 1902 | if (dta.write_time < user_specified_time) /* files modifed on or after specified time will be */ | ||
| 1903 | back_it_up = FALSE; /* processed, regardless of date */ | ||
| 1904 | } | ||
| 1905 | |||
| 1906 | if (do_date) /* Check DATE parameter */ | ||
| 1907 | { | ||
| 1908 | if (dta.write_date < user_specified_date) | ||
| 1909 | back_it_up = FALSE; | ||
| 1910 | } | ||
| 1911 | |||
| 1912 | #define SAME 0 | ||
| 1913 | |||
| 1914 | if (strcmp(src_drive_path+2,"\\") == SAME) /*;AN000;1 If we are processing the root directory */ | ||
| 1915 | if /*;AN000;1 and if we are looking at any of these files */ | ||
| 1916 | (strcmp(dta.file_name,"IBMBIO.COM") == SAME || /*;AN000;1*/ | ||
| 1917 | strcmp(dta.file_name,"IBMDOS.COM") == SAME || /*;AN000;1*/ | ||
| 1918 | #if ! IBMCOPYRIGHT | ||
| 1919 | strcmp(dta.file_name,"IO.SYS") == SAME || /*;AN000;1*/ | ||
| 1920 | strcmp(dta.file_name,"MSDOS.SYS") == SAME || /*;AN000;1*/ | ||
| 1921 | #endif | ||
| 1922 | strcmp(dta.file_name,"COMMAND.COM") == SAME || /*;AN000;1*/ | ||
| 1923 | strcmp(dta.file_name,"CMD.EXE") == SAME /*;AN000;1*/ | ||
| 1924 | ) /*;AN000;1*/ | ||
| 1925 | back_it_up = FALSE; /*;AN000;1 then do not back them up! */ | ||
| 1926 | |||
| 1927 | |||
| 1928 | |||
| 1929 | if (do_logfile) /*;AN006;*/ | ||
| 1930 | { /*;AN006;*/ | ||
| 1931 | strcpy(temp,src_drive_path); /*;AN006;*/ | ||
| 1932 | |||
| 1933 | if (strlen(temp) == 3) /*;AN006;*/ | ||
| 1934 | temp[2] = NUL; /*;AN006;*/ | ||
| 1935 | |||
| 1936 | sprintf(temp,"%s\\%s",temp,dta.file_name); /*;AN006;*/ | ||
| 1937 | |||
| 1938 | if (strcmp(logfile_path,temp) == SAME)/*;AN006;*/ | ||
| 1939 | back_it_up = FALSE; /*;AN006;*/ | ||
| 1940 | } /*;AN006;*/ | ||
| 1941 | |||
| 1942 | return; | ||
| 1943 | } /* end see_if_it_should_be_backed_up */ | ||
| 1944 | |||
| 1945 | /*************************************************/ | ||
| 1946 | /* | ||
| 1947 | /* SUBROUTINE NAME: get_diskette | ||
| 1948 | /* | ||
| 1949 | /* FUNCTION: | ||
| 1950 | /* Get the diskette from user. If unformatted | ||
| 1951 | /* and user entered /F, then try to FORMAT it. | ||
| 1952 | /* Create target files on root of diskette. | ||
| 1953 | /**************************************************/ | ||
| 1954 | void get_diskette() | ||
| 1955 | { | ||
| 1956 | union REGS qregs; /*;AN000;8*/ | ||
| 1957 | |||
| 1958 | if (!do_add) | ||
| 1959 | { | ||
| 1960 | display_msg(INSERTTARGET); | ||
| 1961 | display_msg(ERASEMSG); | ||
| 1962 | } | ||
| 1963 | else | ||
| 1964 | if (doing_first_target) | ||
| 1965 | display_msg(LASTDISKMSG); | ||
| 1966 | else | ||
| 1967 | { | ||
| 1968 | display_msg(INSERTTARGET); | ||
| 1969 | display_msg(ERASEMSG); | ||
| 1970 | } | ||
| 1971 | |||
| 1972 | got_first_target = TRUE; /*;AN000;*/ | ||
| 1973 | |||
| 1974 | /*wait_for_keystroke(); /* Let user "Strike any key when ready" */ | ||
| 1975 | |||
| 1976 | /* If single drive system, eliminates double prompting */ | ||
| 1977 | /* for user to "Insert diskette for drive %1" */ | ||
| 1978 | qregs.x.ax = SETLOGICALDRIVE; /*;AN000;8*/ | ||
| 1979 | qregs.h.bl = tgt_drive_letter - 'A' + 1; /*;AN000;8*/ | ||
| 1980 | intdos(&qregs,&qregs); /*;AN000;8*/ | ||
| 1981 | |||
| 1982 | if (target_removable) /*;AN000;d177*/ | ||
| 1983 | format_target(); | ||
| 1984 | |||
| 1985 | if (do_add) /* If we are adding files */ | ||
| 1986 | if (doing_first_target) /* and if its the first target */ | ||
| 1987 | check_last_target(); /* verify that its a valid one */ | ||
| 1988 | |||
| 1989 | display_msg(BUDISKMSG); | ||
| 1990 | display_msg(SEQUENCEMSG); | ||
| 1991 | delete_files(ROOTDIR); /* Delete all files in the root dir of target drive */ | ||
| 1992 | |||
| 1993 | create_target(); /* Create target files */ | ||
| 1994 | |||
| 1995 | return; | ||
| 1996 | } /* end get_diskette */ | ||
| 1997 | |||
| 1998 | /*************************************************/ | ||
| 1999 | /* | ||
| 2000 | /* SUBROUTINE NAME: get_hardfile | ||
| 2001 | /* | ||
| 2002 | /* FUNCTION: | ||
| 2003 | /* Target is a hardfile. FORMATTING hardfile is | ||
| 2004 | /* not allowed by BACKUP. Create target files | ||
| 2005 | /* in BACKUP directory of disk. | ||
| 2006 | /***************************************************/ | ||
| 2007 | void get_hardfile() | ||
| 2008 | { | ||
| 2009 | char dirname[15]; | ||
| 2010 | |||
| 2011 | sprintf(dirname,"%c:\\BACKUP\\*.*",tgt_drive_letter); | ||
| 2012 | if (exist(&dirname[0])) | ||
| 2013 | { | ||
| 2014 | if (!do_add) | ||
| 2015 | { | ||
| 2016 | display_msg(FERASEMSG); | ||
| 2017 | /*wait_for_keystroke(); /* Let user "Strike any key when ready" */ | ||
| 2018 | } | ||
| 2019 | delete_files(BACKUPDIR); /* Delete \BACKUP\*.* of target drive if not do_add */ | ||
| 2020 | } | ||
| 2021 | else | ||
| 2022 | { | ||
| 2023 | sprintf(dirname,"%c:\\BACKUP",tgt_drive_letter); | ||
| 2024 | mkdir(dirname); | ||
| 2025 | } | ||
| 2026 | |||
| 2027 | display_msg(BUDISKMSG); | ||
| 2028 | create_target(); | ||
| 2029 | |||
| 2030 | return; | ||
| 2031 | } /* end get_hardfile */ | ||
| 2032 | |||
| 2033 | |||
| 2034 | /*************************************************/ | ||
| 2035 | /* | ||
| 2036 | /* SUBROUTINE NAME: check_last_target | ||
| 2037 | /* | ||
| 2038 | /* FUNCTION: | ||
| 2039 | /* User entered /A parameter. Make sure that | ||
| 2040 | /* we are not adding to a BACKUP diskette created | ||
| 2041 | /* with the disgusting old BACKUP format. | ||
| 2042 | /* Make sure there is a BACKUP.xxx and CONTROL.xxx | ||
| 2043 | /* file out there. Make sure it was the last target | ||
| 2044 | /* and get the sequence number. | ||
| 2045 | /***************************************************/ | ||
| 2046 | void check_last_target() | ||
| 2047 | { | ||
| 2048 | WORD dhandle; | ||
| 2049 | WORD bytes_read; | ||
| 2050 | BYTE flag; | ||
| 2051 | char path[25]; | ||
| 2052 | char current_file[25]; | ||
| 2053 | |||
| 2054 | struct FileFindBuf tempdta; | ||
| 2055 | |||
| 2056 | if (target_removable) /* Make sure there is no old BACKUP on here */ | ||
| 2057 | sprintf(path,"%c:\\BACKUPID.@@@",tgt_drive_letter); | ||
| 2058 | else | ||
| 2059 | sprintf(path,"%c:\\BACKUP\\BACKUPID.@@@",tgt_drive_letter); | ||
| 2060 | |||
| 2061 | if (exist(path)) | ||
| 2062 | error_exit(INVTARGET); | ||
| 2063 | |||
| 2064 | if (target_removable) /* Build path to control file */ | ||
| 2065 | sprintf(path,"%c:\\CONTROL.*",tgt_drive_letter); | ||
| 2066 | else | ||
| 2067 | sprintf(path,"%c:\\BACKUP\CONTROL.*",tgt_drive_letter); | ||
| 2068 | |||
| 2069 | find_first /* Find the control file */ | ||
| 2070 | ( | ||
| 2071 | &path[0], | ||
| 2072 | &dhandle, | ||
| 2073 | &tempdta, | ||
| 2074 | (SYSTEM + HIDDEN) | ||
| 2075 | ); | ||
| 2076 | |||
| 2077 | if (rc != NOERROR) /* If you got one, then close dirhandle */ | ||
| 2078 | error_exit(NOTLASTMSG); | ||
| 2079 | |||
| 2080 | findclose(dhandle); | ||
| 2081 | |||
| 2082 | |||
| 2083 | /* Add drive letter to control file name */ | ||
| 2084 | sprintf(path,"%c:%s",tgt_drive_letter,tempdta.file_name); | ||
| 2085 | |||
| 2086 | handle_control = /* Open the control file;AN000;5*/ | ||
| 2087 | extended_open /*;AN000;5*/ | ||
| 2088 | (OPEN_IT, /*;AN000;5*/ | ||
| 2089 | 0, /*;AN000;5*/ | ||
| 2090 | (char far *)path, /*;AN000;5*/ | ||
| 2091 | (WORD)(DENYWRITE+READACCESS) /*;AN000;5*/ | ||
| 2092 | ); /*;AN000;5*/ | ||
| 2093 | |||
| 2094 | if (rc != NOERROR) /* If can't open it, strange error */ | ||
| 2095 | error_exit(NOTLASTMSG); | ||
| 2096 | |||
| 2097 | /* Get diskette sequence number */ | ||
| 2098 | lseek(handle_control,BOFILE,(DWORD)9); | ||
| 2099 | bytes_read = handle_read(handle_control,1,(char far *)&diskettes_complete); | ||
| 2100 | diskettes_complete--; /* This diskette is not longer "complete" */ | ||
| 2101 | |||
| 2102 | /* Seek to DH_LastDisk and read that byte */ | ||
| 2103 | lseek(handle_control,BOFILE,(DWORD)138); /* Check DH_LastDisk flag in control file */ | ||
| 2104 | bytes_read = handle_read(handle_control,1,(char far *)&flag); | ||
| 2105 | |||
| 2106 | if (flag != LAST_TARGET) /* If wasn't last target, terminate */ | ||
| 2107 | error_exit(NOTLASTMSG); | ||
| 2108 | |||
| 2109 | close_file(handle_control); /* Close the control file */ | ||
| 2110 | control_opened = FALSE; /*;AN005; And say it isn't open */ | ||
| 2111 | |||
| 2112 | return; | ||
| 2113 | } /* end check_last_target */ | ||
| 2114 | /*************************************************/ | ||
| 2115 | /* | ||
| 2116 | /* SUBROUTINE NAME: format_target | ||
| 2117 | /* | ||
| 2118 | /* FUNCTION: | ||
| 2119 | /* See if the target is formatted. If not, try | ||
| 2120 | /* to format it. | ||
| 2121 | /* | ||
| 2122 | /***************************************************/ | ||
| 2123 | void format_target() | ||
| 2124 | { | ||
| 2125 | #define HOOK 0 | ||
| 2126 | #define UNHOOK 1 | ||
| 2127 | |||
| 2128 | WORD bfree; | ||
| 2129 | char format_parms[35]; /*;AC000;8*/ | ||
| 2130 | WORD temp_rc; /*;AN000;p2631 Return code from DOS calls */ | ||
| 2131 | |||
| 2132 | if (do_add) | ||
| 2133 | if (doing_first_target) | ||
| 2134 | return; | ||
| 2135 | |||
| 2136 | /**********************************/ | ||
| 2137 | /* See if diskette is unformatted */ | ||
| 2138 | /**********************************/ | ||
| 2139 | do_dos_error(HOOK); /* Replace hard error handler */ | ||
| 2140 | rc = NOERROR; /* Reset return code */ | ||
| 2141 | checking_target = TRUE; /*;AN007;*/ | ||
| 2142 | bfree = (WORD)disk_free_space();/* If this generates hard error, then format target */ | ||
| 2143 | checking_target = FALSE; /*;AN007;*/ | ||
| 2144 | |||
| 2145 | temp_rc = rc; /*;AN000;p2631*/ | ||
| 2146 | do_dos_error(UNHOOK); /*;AN000;p2631 Unhook hard error handler */ | ||
| 2147 | rc = temp_rc; /*;AN000;p2631*/ | ||
| 2148 | |||
| 2149 | if (rc != NOERROR) /* If there was a hard error... */ | ||
| 2150 | { /* Then FORMAT the target */ | ||
| 2151 | display_msg(CRLF); | ||
| 2152 | |||
| 2153 | sprintf(format_parms,"%c:",tgt_drive_letter); | ||
| 2154 | |||
| 2155 | if (do_format_parms) /*;AN001;DCR 434*/ | ||
| 2156 | if (format_size[0] != NUL) /*;AN001;DCR 434*/ | ||
| 2157 | strcat(format_parms,format_size); /*;AN001;DCR 434*/ | ||
| 2158 | |||
| 2159 | strcat(format_parms," /BACKUP /V:BACKUP"); /*;AN000;8*/ | ||
| 2160 | |||
| 2161 | if (spawnlp(P_WAIT,format_path,"FORMAT",format_parms,NUL) == NOERROR) /*;AC000;d178*/ | ||
| 2162 | { | ||
| 2163 | display_msg(CRLF); /* Skip a line */ | ||
| 2164 | } | ||
| 2165 | else | ||
| 2166 | { | ||
| 2167 | display_msg(ERR_EXEC_FORMAT); /* Display "Error executing FORMAT" */ | ||
| 2168 | display_msg(INSERTTARGET); /* And give another chance */ | ||
| 2169 | display_msg(ERASEMSG); | ||
| 2170 | /*wait_for_keystroke(); */ | ||
| 2171 | } | ||
| 2172 | |||
| 2173 | } | ||
| 2174 | |||
| 2175 | return; | ||
| 2176 | } /* end format_target */ | ||
| 2177 | |||
| 2178 | /*************************************************/ | ||
| 2179 | /* | ||
| 2180 | /* SUBROUTINE NAME: set_default_dir | ||
| 2181 | /* | ||
| 2182 | /* FUNCTION: | ||
| 2183 | /* | ||
| 2184 | /* | ||
| 2185 | /* | ||
| 2186 | /***************************************************/ | ||
| 2187 | void set_default_dir() | ||
| 2188 | { | ||
| 2189 | if (com_strchr(src_drive_path,BACKSLASH) != NUL) /* if there IS a backslash... */ | ||
| 2190 | if (strlen(src_drive_path) >= 3) /* if length is greater than 3... */ | ||
| 2191 | { | ||
| 2192 | rc = chdir(src_drive_path); /* then change dir to there. */ | ||
| 2193 | if (rc == NOERROR) | ||
| 2194 | { | ||
| 2195 | src_drive_path[2] = BACKSLASH; | ||
| 2196 | get_current_dir(src_drive_letter-'A'+1,&src_drive_path[3]); | ||
| 2197 | } | ||
| 2198 | else | ||
| 2199 | error_exit(INV_PATH); | ||
| 2200 | } | ||
| 2201 | |||
| 2202 | curr_dir_set = TRUE; | ||
| 2203 | |||
| 2204 | if (do_subdirs) /* If we are processing subdirectories too, */ | ||
| 2205 | { | ||
| 2206 | alloc_first_node(); /* then put current level in linked list */ | ||
| 2207 | find_all_subdirs(); /* And get all directory entries in that level */ | ||
| 2208 | } | ||
| 2209 | |||
| 2210 | return; | ||
| 2211 | } /* end set_default_dir */ | ||
| 2212 | |||
| 2213 | /*************************************************/ | ||
| 2214 | /* | ||
| 2215 | /* SUBROUTINE NAME: label_target_drive | ||
| 2216 | /* | ||
| 2217 | /* FUNCTION: | ||
| 2218 | /* Create volume label BACKUP.xxx on target | ||
| 2219 | /* diskette drive. | ||
| 2220 | /* | ||
| 2221 | /***************************************************/ | ||
| 2222 | void label_target_drive() /* Create Volume label BACKUP.XXX on target */ | ||
| 2223 | { | ||
| 2224 | |||
| 2225 | char fsbuf[20]; | ||
| 2226 | WORD handle; | ||
| 2227 | |||
| 2228 | build_ext(diskettes_complete + 1); | ||
| 2229 | |||
| 2230 | sprintf(fsbuf,"%c:BACKUP.%s",tgt_drive_letter,ext); | ||
| 2231 | |||
| 2232 | replace_volume_label(&fsbuf[0]); | ||
| 2233 | |||
| 2234 | return; | ||
| 2235 | } /* end label_target_drive */ | ||
| 2236 | |||
| 2237 | /*************************************************/ | ||
| 2238 | /* | ||
| 2239 | /* SUBROUTINE NAME: build_ext | ||
| 2240 | /* | ||
| 2241 | /* FUNCTION: | ||
| 2242 | /* | ||
| 2243 | /* | ||
| 2244 | /* | ||
| 2245 | /***************************************************/ | ||
| 2246 | void build_ext(num) | ||
| 2247 | int num; | ||
| 2248 | { | ||
| 2249 | if (num < 10) | ||
| 2250 | sprintf(ext,"00%u",num); | ||
| 2251 | else | ||
| 2252 | if (num < 100) | ||
| 2253 | sprintf(ext,"0%u",num); | ||
| 2254 | else | ||
| 2255 | sprintf(ext,"%u",num); | ||
| 2256 | |||
| 2257 | return; | ||
| 2258 | } /* end build_ext */ | ||
| 2259 | |||
| 2260 | /*************************************************/ | ||
| 2261 | /* | ||
| 2262 | /* SUBROUTINE NAME: create_target | ||
| 2263 | /* | ||
| 2264 | /* FUNCTION: | ||
| 2265 | /* | ||
| 2266 | /* | ||
| 2267 | /* | ||
| 2268 | /***************************************************/ | ||
| 2269 | void create_target() | ||
| 2270 | { | ||
| 2271 | char path[25]; | ||
| 2272 | |||
| 2273 | if (do_add) | ||
| 2274 | if (doing_first_target) | ||
| 2275 | { | ||
| 2276 | open_target(); | ||
| 2277 | return; | ||
| 2278 | } | ||
| 2279 | |||
| 2280 | build_ext(diskettes_complete + 1); | ||
| 2281 | |||
| 2282 | if (target_removable) | ||
| 2283 | sprintf(path,"%c:\\BACKUP.%s",tgt_drive_letter,ext); | ||
| 2284 | else | ||
| 2285 | sprintf(path,"%c:\\BACKUP\\BACKUP.%s",tgt_drive_letter,ext); | ||
| 2286 | |||
| 2287 | handle_target = /*;AN000;5*/ | ||
| 2288 | extended_open /*;AN000;5*/ | ||
| 2289 | ( /*;AN000;5*/ | ||
| 2290 | CREATE_IT, /*;AN000;5*/ | ||
| 2291 | (WORD)ARCHIVE, /*;AN000;5*/ | ||
| 2292 | (char far *)path, /*;AN000;5*/ | ||
| 2293 | (WORD)(READWRITE) /*;AN000;5*/ | ||
| 2294 | ); /*;AN000;5*/ | ||
| 2295 | |||
| 2296 | if (rc == NOERROR) | ||
| 2297 | target_opened = TRUE; | ||
| 2298 | else | ||
| 2299 | error_exit(INVTARGET); | ||
| 2300 | |||
| 2301 | if (target_removable) | ||
| 2302 | sprintf(path,"%c:\\CONTROL.%s",tgt_drive_letter,ext); | ||
| 2303 | else | ||
| 2304 | sprintf(path,"%c:\\BACKUP\\CONTROL.%s",tgt_drive_letter,ext); | ||
| 2305 | |||
| 2306 | handle_control = /*;AN000;5*/ | ||
| 2307 | extended_open /*;AN000;5*/ | ||
| 2308 | ( /*;AN000;5*/ | ||
| 2309 | CREATE_IT, /*;AN000;5*/ | ||
| 2310 | (WORD)ARCHIVE, /*;AN000;5*/ | ||
| 2311 | (char far *)path, /*;AN000;5*/ | ||
| 2312 | (WORD)(READWRITE) /*;AN000;5*/ | ||
| 2313 | ); /*;AN000;5*/ | ||
| 2314 | |||
| 2315 | if (rc == NOERROR) | ||
| 2316 | control_opened = TRUE; | ||
| 2317 | else | ||
| 2318 | error_exit(INVTARGET); | ||
| 2319 | |||
| 2320 | data_file_tot_len = (DWORD)0; | ||
| 2321 | ctl_file_tot_len = (DWORD)0; | ||
| 2322 | |||
| 2323 | return; | ||
| 2324 | } /* end create_target */ | ||
| 2325 | |||
| 2326 | /*************************************************/ | ||
| 2327 | /* | ||
| 2328 | /* SUBROUTINE NAME: open_target | ||
| 2329 | /* | ||
| 2330 | /* FUNCTION: | ||
| 2331 | /* | ||
| 2332 | /* | ||
| 2333 | /* | ||
| 2334 | /***************************************************/ | ||
| 2335 | void open_target() /* Done only if /A and it is the first target */ | ||
| 2336 | { | ||
| 2337 | |||
| 2338 | char path[PATHLEN+20]; | ||
| 2339 | |||
| 2340 | /* Open BACKUP.xxx File */ | ||
| 2341 | build_ext(diskettes_complete+1); | ||
| 2342 | |||
| 2343 | if (target_removable) | ||
| 2344 | sprintf(path,"%c:\\BACKUP.%s",tgt_drive_letter,ext); | ||
| 2345 | else | ||
| 2346 | sprintf(path,"%c:\\BACKUP\\BACKUP.%s",tgt_drive_letter,ext); | ||
| 2347 | |||
| 2348 | /* Turn off readonly bit on BACKUP.xxx */ | ||
| 2349 | set_attribute(path,(WORD)(get_attribute(path) & (WORD)READONLYOFF)); | ||
| 2350 | /* Open it */ | ||
| 2351 | handle_target = /*;AN000;5*/ | ||
| 2352 | extended_open /*;AN000;5*/ | ||
| 2353 | ( OPEN_IT, /*;AN000;5*/ | ||
| 2354 | 0, /*;AN000;5*/ | ||
| 2355 | (char far *)path, /*;AN000;5*/ | ||
| 2356 | (WORD)(DENYALL+READWRITE) /*;AN000;5*/ | ||
| 2357 | ); /*;AN000;5*/ | ||
| 2358 | |||
| 2359 | if (rc == NOERROR) | ||
| 2360 | target_opened = TRUE; | ||
| 2361 | else | ||
| 2362 | error_exit(INVTARGET); | ||
| 2363 | /* Open CONTROL.xxx File */ | ||
| 2364 | if (target_removable) | ||
| 2365 | sprintf(path,"%c:\\CONTROL.%s",tgt_drive_letter,ext); | ||
| 2366 | else | ||
| 2367 | sprintf(path,"%c:\\BACKUP\\CONTROL.%s",tgt_drive_letter,ext); | ||
| 2368 | |||
| 2369 | set_attribute(path,(WORD)(get_attribute(path) & (WORD)READONLYOFF)); | ||
| 2370 | |||
| 2371 | handle_control = /*;AN000;5*/ | ||
| 2372 | extended_open /*;AN000;5*/ | ||
| 2373 | ( OPEN_IT, /*;AN000;5*/ | ||
| 2374 | 0, /*;AN000;5*/ | ||
| 2375 | (char far *)path, /*;AN000;5*/ | ||
| 2376 | (WORD)(DENYALL+READWRITE) /*;AN000;5*/ | ||
| 2377 | ); /*;AN000;5*/ | ||
| 2378 | |||
| 2379 | if (rc == NOERROR) | ||
| 2380 | control_opened = TRUE; | ||
| 2381 | else | ||
| 2382 | error_exit(INVTARGET); | ||
| 2383 | |||
| 2384 | data_file_tot_len = (DWORD)lseek(handle_target ,EOFILE,(DWORD)0); | ||
| 2385 | ctl_file_tot_len = (DWORD)lseek(handle_control,EOFILE,(DWORD)0); | ||
| 2386 | |||
| 2387 | return; | ||
| 2388 | } /* end open_target */ | ||
| 2389 | |||
| 2390 | /*************************************************/ | ||
| 2391 | /* | ||
| 2392 | /* SUBROUTINE NAME: delete_files | ||
| 2393 | /* | ||
| 2394 | /* FUNCTION: | ||
| 2395 | /* Delete all files in the root directory of target | ||
| 2396 | /* diskette, or in the BACKUP directory of the target | ||
| 2397 | /* hardfile. If error occurs deleting file, try to | ||
| 2398 | /* reset the attribute to 0 and try it again. | ||
| 2399 | /* | ||
| 2400 | /* | ||
| 2401 | /***************************************************/ | ||
| 2402 | void delete_files(dirlevel) | ||
| 2403 | char dirlevel; | ||
| 2404 | { | ||
| 2405 | BYTE delete_path[25]; | ||
| 2406 | struct FileFindBuf tempdta; | ||
| 2407 | struct FileFindBuf *tempdta_addr; | ||
| 2408 | WORD dhandle; | ||
| 2409 | BYTE delete_it; /*;AN000;7*/ | ||
| 2410 | |||
| 2411 | if (do_add) /* Don't delete files if we */ | ||
| 2412 | if (doing_first_target) /* are adding files to an existing */ | ||
| 2413 | return; /* BACKUP and this is the first target */ | ||
| 2414 | |||
| 2415 | tempdta_addr = (struct FileFindBuf *)&tempdta; | ||
| 2416 | |||
| 2417 | if (dirlevel == ROOTDIR) | ||
| 2418 | sprintf(delete_path,"%c:\\*.*",tgt_drive_letter); | ||
| 2419 | else | ||
| 2420 | sprintf(delete_path,"%c:\\BACKUP\\*.*",tgt_drive_letter); | ||
| 2421 | |||
| 2422 | find_first /* Find a file to delete */ | ||
| 2423 | ( | ||
| 2424 | (char *)&delete_path[0], | ||
| 2425 | &dhandle, | ||
| 2426 | tempdta_addr, | ||
| 2427 | (SYSTEM + HIDDEN) | ||
| 2428 | ); | ||
| 2429 | |||
| 2430 | while (rc == NOERROR) | ||
| 2431 | { | ||
| 2432 | delete_it = TRUE; /*;AN000;7*/ | ||
| 2433 | |||
| 2434 | if (dirlevel == ROOTDIR) | ||
| 2435 | sprintf(delete_path,"%c:\\%s",tgt_drive_letter,tempdta.file_name); | ||
| 2436 | else | ||
| 2437 | sprintf(delete_path,"%c:\\BACKUP\\%s",tgt_drive_letter,tempdta.file_name); | ||
| 2438 | |||
| 2439 | if (logfile_on_target) /*;AN000;7*/ | ||
| 2440 | if (strcmp(delete_path,logfile_path) == SAME) /*;AN000;7*/ | ||
| 2441 | delete_it = FALSE; /*;AN000;7*/ | ||
| 2442 | |||
| 2443 | if (delete_it == TRUE) /*;AN000;7*/ | ||
| 2444 | { /*;AN000;7*/ | ||
| 2445 | delete(delete_path); | ||
| 2446 | |||
| 2447 | if (rc != NOERROR) | ||
| 2448 | { | ||
| 2449 | set_attribute(delete_path,(WORD)0); | ||
| 2450 | delete(delete_path); | ||
| 2451 | } | ||
| 2452 | } /*;AN000;7*/ | ||
| 2453 | |||
| 2454 | find_next(dhandle,tempdta_addr); | ||
| 2455 | } | ||
| 2456 | |||
| 2457 | return; | ||
| 2458 | } /* end delete_files */ | ||
| 2459 | |||
| 2460 | /*************************************************/ | ||
| 2461 | /* | ||
| 2462 | /* SUBROUTINE NAME: exist | ||
| 2463 | /* | ||
| 2464 | /* FUNCTION: | ||
| 2465 | /* Does a FIND FIRST of the filespec passed at PATH_ADDR. | ||
| 2466 | /* If so, returns TRUE, otherwise returns FALSE. | ||
| 2467 | /* | ||
| 2468 | /***************************************************/ | ||
| 2469 | WORD exist(path_addr) /* Return TRUE if specified epath exists, FALSE other */ | ||
| 2470 | char *path_addr; | ||
| 2471 | { | ||
| 2472 | WORD dhandle; | ||
| 2473 | WORD temprc; | ||
| 2474 | struct FileFindBuf tempdta; | ||
| 2475 | |||
| 2476 | find_first /* DOS Find First */ | ||
| 2477 | ( | ||
| 2478 | path_addr, | ||
| 2479 | &dhandle, | ||
| 2480 | &tempdta, | ||
| 2481 | (SUBDIR + SYSTEM + HIDDEN) | ||
| 2482 | ); | ||
| 2483 | |||
| 2484 | temprc = rc; | ||
| 2485 | if (rc == NOERROR) findclose(dhandle); | ||
| 2486 | |||
| 2487 | if (temprc != NOERROR) | ||
| 2488 | return(FALSE); | ||
| 2489 | else | ||
| 2490 | return(TRUE); | ||
| 2491 | |||
| 2492 | } /* end exist */ | ||
| 2493 | |||
| 2494 | /*************************************************/ | ||
| 2495 | /* | ||
| 2496 | /* SUBROUTINE NAME: open_source_file | ||
| 2497 | /* | ||
| 2498 | /* FUNCTION: | ||
| 2499 | /* Try to open the source file at the DTA structure. | ||
| 2500 | /* If after MAX_RETRY_OPEN_COUNT attempts you cannot | ||
| 2501 | /* open it, then display an appropriate message and | ||
| 2502 | /* continue. If it was opened, then get the files | ||
| 2503 | /* extended attributes. | ||
| 2504 | /* | ||
| 2505 | /***************************************************/ | ||
| 2506 | void open_source_file() | ||
| 2507 | { | ||
| 2508 | int num_attempts = 0; | ||
| 2509 | char done = FALSE; | ||
| 2510 | char file_to_be_backup[20]; | ||
| 2511 | |||
| 2512 | source_opened = FALSE; /* Source is not opened yet */ | ||
| 2513 | file_spans_target = FALSE; /* File does not spans diskettes */ | ||
| 2514 | span_seq_num = 1; /* Indicate that this is the first diskette containing part of this file*/ | ||
| 2515 | show_path(); /* Display to stdout/logfile the full path from root */ | ||
| 2516 | sprintf(file_to_be_backup,"%c:%s",src_drive_letter,dta.file_name); | ||
| 2517 | |||
| 2518 | do | ||
| 2519 | { /*;AN000;5*/ /* Attempt open */ | ||
| 2520 | handle_source = /*;AN000;5*/ | ||
| 2521 | extended_open /*;AN000;5*/ | ||
| 2522 | ( /*;AN000;5*/ | ||
| 2523 | OPEN_IT, /*;AN000;5*/ | ||
| 2524 | 0, /*;AN000;5*/ | ||
| 2525 | (char far *)file_to_be_backup, /*;AN000;5*/ | ||
| 2526 | (WORD)(DENYWRITE+READACCESS) /*;AN000;5*/ | ||
| 2527 | ); /*;AN000;5*/ | ||
| 2528 | |||
| 2529 | if (rc != NOERROR) /* Check for error */ | ||
| 2530 | { /* Handle Share Errors */ | ||
| 2531 | num_attempts++; /* Increment number of attempts */ | ||
| 2532 | if (num_attempts == MAX_RETRY_OPEN_COUNT)/* Compare with max number of retries to perform */ | ||
| 2533 | { | ||
| 2534 | file_sharing_error(); /*;AN000;9 There was a share error opening the file*/ | ||
| 2535 | done = TRUE; | ||
| 2536 | } | ||
| 2537 | } | ||
| 2538 | else | ||
| 2539 | { | ||
| 2540 | source_opened = TRUE; /* Set flag indicating file is opened */ | ||
| 2541 | done = TRUE; /* We are done in this loop */ | ||
| 2542 | |||
| 2543 | /*EAEAEAEAEA get_extended_attributes(handle_source); /*;AN000;3 Get extended attributes for this file */ | ||
| 2544 | |||
| 2545 | put_new_fh(); /* Write the file header to the control file */ | ||
| 2546 | |||
| 2547 | /*EAEAEAEAE if (ext_attrib_flg) /*;AN000;3 If the file has extended attributes */ | ||
| 2548 | /*EAEAEAEAE write_extended_attributes(); /*;AN000;3then write them to BACKUP file */ | ||
| 2549 | } | ||
| 2550 | } | ||
| 2551 | while (!done); | ||
| 2552 | |||
| 2553 | return; | ||
| 2554 | } /* end open_source_file */ | ||
| 2555 | |||
| 2556 | /*************************************************/ | ||
| 2557 | /* | ||
| 2558 | /* SUBROUTINE NAME: file_sharing_error | ||
| 2559 | /* | ||
| 2560 | /* FUNCTION: | ||
| 2561 | /* | ||
| 2562 | /* Handle the file sharing error that just occurred | ||
| 2563 | /* | ||
| 2564 | /***************************************************/ | ||
| 2565 | void file_sharing_error() /*;AN000;9*/ | ||
| 2566 | { /*;AN000;9*/ | ||
| 2567 | union REGS reg; /*;AN000;9*/ | ||
| 2568 | |||
| 2569 | display_msg(CRLF); | ||
| 2570 | display_msg(CONFLICTMSG); /* Say "Last file not backed */ | ||
| 2571 | return_code = RETCODE_SHARE_ERROR; /* Set errorlevel */ | ||
| 2572 | |||
| 2573 | if (do_logfile) /*;AN000;9*/ | ||
| 2574 | { /*;AN000;9*/ | ||
| 2575 | reg.x.ax = LASTNOTBACKUP; /*;AN000;9*/ | ||
| 2576 | reg.x.bx = handle_logfile; /*;AN000;9*/ | ||
| 2577 | #define MSG_LEN 33 /*;AN000;9*/ | ||
| 2578 | reg.x.cx = (WORD)MSG_LEN; /*;AN000;9*/ | ||
| 2579 | update_logfile(®,®); /* In source file _msgret.sal /*;AN000;9*/ | ||
| 2580 | } /*;AN000;9*/ | ||
| 2581 | |||
| 2582 | return; /*;AN000;9*/ | ||
| 2583 | } /*;AN000;9*/ | ||
| 2584 | |||
| 2585 | /*************************************************/ | ||
| 2586 | /* | ||
| 2587 | /* SUBROUTINE NAME: far_ptr | ||
| 2588 | /* | ||
| 2589 | /* FUNCTION: | ||
| 2590 | /* | ||
| 2591 | /* | ||
| 2592 | /* | ||
| 2593 | /***************************************************/ | ||
| 2594 | char far *far_ptr(seg,off) | ||
| 2595 | WORD seg; | ||
| 2596 | WORD off; | ||
| 2597 | { | ||
| 2598 | char far *p; | ||
| 2599 | |||
| 2600 | PUT_SEG(p,seg); | ||
| 2601 | PUT_OFF(p,off); | ||
| 2602 | |||
| 2603 | return(p); | ||
| 2604 | } | ||
| 2605 | |||
| 2606 | /*************************************************/ | ||
| 2607 | /* | ||
| 2608 | /* SUBROUTINE NAME: do_copy | ||
| 2609 | /* | ||
| 2610 | /* FUNCTION: | ||
| 2611 | /* Copy the source file to the BACKUP.xxx file | ||
| 2612 | /* If there are extended attributes, write them | ||
| 2613 | /* to the BACKUP.xxx file. | ||
| 2614 | /***************************************************/ | ||
| 2615 | void do_copy() | ||
| 2616 | { | ||
| 2617 | WORD bytes_read; | ||
| 2618 | WORD bytes_to_read = data_file_alloc_size; /* Read size = buffer size */ | ||
| 2619 | char done = FALSE; | ||
| 2620 | char file_to_be_backup[20]; | ||
| 2621 | |||
| 2622 | part_size = (DWORD)0; | ||
| 2623 | cumul_part_size = (DWORD)0; | ||
| 2624 | |||
| 2625 | if (source_opened) | ||
| 2626 | { | ||
| 2627 | do | ||
| 2628 | { | ||
| 2629 | bytes_read = | ||
| 2630 | handle_read | ||
| 2631 | ( | ||
| 2632 | handle_source, | ||
| 2633 | bytes_to_read, | ||
| 2634 | far_ptr(selector,0) | ||
| 2635 | ); | ||
| 2636 | |||
| 2637 | if (bytes_read == 0) | ||
| 2638 | done = TRUE; | ||
| 2639 | else | ||
| 2640 | write_to_target(bytes_read); | ||
| 2641 | |||
| 2642 | if (bytes_read < bytes_to_read) | ||
| 2643 | done = TRUE; | ||
| 2644 | } | ||
| 2645 | while (!done); | ||
| 2646 | |||
| 2647 | close_file(handle_source); /* Close the source file handle */ | ||
| 2648 | source_opened = FALSE; /* Indicate that the source is not opened */ | ||
| 2649 | sprintf(file_to_be_backup,"%c:%s",src_drive_letter,dta.file_name); | ||
| 2650 | reset_archive_bit(file_to_be_backup);/* Reset the archive bit on the source file */ | ||
| 2651 | files_backed_up++; /* Increment number of files backed up */ | ||
| 2652 | } | ||
| 2653 | |||
| 2654 | return; | ||
| 2655 | } /* end do_copy */ | ||
| 2656 | |||
| 2657 | /*************************************************/ | ||
| 2658 | /* | ||
| 2659 | /* SUBROUTINE NAME: write_extended_attributes | ||
| 2660 | /* | ||
| 2661 | /* FUNCTION: | ||
| 2662 | /* There are extended attributes for the file | ||
| 2663 | /* just backed up. Write the length of the | ||
| 2664 | /* extended attributes to the BACKUP.xxx file, | ||
| 2665 | /* then write the extended attributes the that file. | ||
| 2666 | /* | ||
| 2667 | /**************************************************/ | ||
| 2668 | /*#define WRITE_LENGTH 2 | ||
| 2669 | /* | ||
| 2670 | /*void write_extended_attributes() /*;AN000;3*/ | ||
| 2671 | /*{ /*;AN000;3*/ | ||
| 2672 | /* WORD written; /*;AN000;3*/ | ||
| 2673 | /* /*******************************************/ | ||
| 2674 | /* /* Write the length of extended attributes */ | ||
| 2675 | /* /*******************************************/ | ||
| 2676 | /* written = | ||
| 2677 | /* handle_write | ||
| 2678 | /* ( | ||
| 2679 | /* handle_target, | ||
| 2680 | /* WRITE_LENGTH, | ||
| 2681 | /* (char far *)&ext_attrib_len | ||
| 2682 | /* ); /*;AN000;3*/ | ||
| 2683 | /* | ||
| 2684 | /* if (written == WRITE_LENGTH ) /*;AN000;3*/ | ||
| 2685 | /* data_file_tot_len += WRITE_LENGTH; /*;AN000;3*/ | ||
| 2686 | /* | ||
| 2687 | /* /*********************************/ | ||
| 2688 | /* /* Write the extended attributes */ | ||
| 2689 | /* /*********************************/ | ||
| 2690 | /* written = handle_write(handle_target,ext_attrib_len,(char far *)ext_attrib_buff); /*;AN000;3*/ | ||
| 2691 | /* if (written == ext_attrib_len) /*;AN000;3*/ | ||
| 2692 | /* data_file_tot_len += (DWORD)written; /*;AN000;3*/ | ||
| 2693 | /* | ||
| 2694 | /* ext_attrib_buff[0] = 0; /*;AN000;3*/ | ||
| 2695 | /* ext_attrib_buff[1] = 0; /*;AN000;3*/ | ||
| 2696 | /* return; /*;AN000;3*/ | ||
| 2697 | /*} /*;AN000;3*/ | ||
| 2698 | |||
| 2699 | /*************************************************/ | ||
| 2700 | /* | ||
| 2701 | /* SUBROUTINE NAME: show_path | ||
| 2702 | /* | ||
| 2703 | /* FUNCTION: | ||
| 2704 | /* Display to stdout the full path from root. | ||
| 2705 | /* If we are logging, put full path there too. | ||
| 2706 | /* | ||
| 2707 | /***************************************************/ | ||
| 2708 | void show_path() | ||
| 2709 | { | ||
| 2710 | char done_path[PATHLEN+20]; | ||
| 2711 | char logfile_entry[PATHLEN+22]; | ||
| 2712 | WORD written = 0; | ||
| 2713 | |||
| 2714 | if (src_drive_path[strlen(src_drive_path) - 1] != BACKSLASH) | ||
| 2715 | sprintf(done_path,"%s\\%s",src_drive_path,dta.file_name); | ||
| 2716 | else | ||
| 2717 | sprintf(done_path,"%s%s",src_drive_path,dta.file_name); | ||
| 2718 | |||
| 2719 | done_path[0] = 0xd; | ||
| 2720 | done_path[1] = 0xa; | ||
| 2721 | /* Display logfile path on screen */ | ||
| 2722 | handle_write(STDOUT,strlen(done_path),(char far *)&done_path[0]); | ||
| 2723 | |||
| 2724 | if (do_logfile) | ||
| 2725 | { | ||
| 2726 | build_ext(diskettes_complete+1); | ||
| 2727 | sprintf(logfile_entry,"\15\12%s %s",ext,&done_path[2]); | ||
| 2728 | written = handle_write(handle_logfile,strlen(logfile_entry),(char far *)&logfile_entry[0]); | ||
| 2729 | if (written != strlen(logfile_entry) || (rc != NOERROR) ) | ||
| 2730 | { | ||
| 2731 | display_msg(LOGFILE_TARGET_FULL); | ||
| 2732 | /*wait_for_keystroke();*/ | ||
| 2733 | do_logfile = FALSE; | ||
| 2734 | } | ||
| 2735 | } | ||
| 2736 | |||
| 2737 | return; | ||
| 2738 | } /* end show_path */ | ||
| 2739 | |||
| 2740 | /*************************************************/ | ||
| 2741 | /* | ||
| 2742 | /* SUBROUTINE NAME: reset_archive_bit | ||
| 2743 | /* | ||
| 2744 | /* FUNCTION: | ||
| 2745 | /* Sets the attribute of the source file to what | ||
| 2746 | /* it was before, except the archive bit is reset. | ||
| 2747 | /* | ||
| 2748 | /***************************************************/ | ||
| 2749 | void reset_archive_bit(path_addr) | ||
| 2750 | char *path_addr; | ||
| 2751 | #define ARCHIVE_MASK 223 | ||
| 2752 | { | ||
| 2753 | WORD attrib; | ||
| 2754 | |||
| 2755 | attrib = get_attribute(path_addr); | ||
| 2756 | attrib = attrib & (WORD)ARCHIVE_MASK; | ||
| 2757 | set_attribute(path_addr,attrib); | ||
| 2758 | |||
| 2759 | return; | ||
| 2760 | } /* end reset_archive_bit */ | ||
| 2761 | |||
| 2762 | /*************************************************/ | ||
| 2763 | /* | ||
| 2764 | /* SUBROUTINE NAME: write_to_target | ||
| 2765 | /* | ||
| 2766 | /* FUNCTION: | ||
| 2767 | /* Write a specified # of bytes to | ||
| 2768 | /* target. Handle disk full conditions | ||
| 2769 | /* and everything else. | ||
| 2770 | /***************************************************/ | ||
| 2771 | void write_to_target(bytes_to_write) | ||
| 2772 | WORD bytes_to_write; | ||
| 2773 | { | ||
| 2774 | WORD bytes_written; | ||
| 2775 | WORD written; | ||
| 2776 | |||
| 2777 | bytes_written = handle_write(handle_target,bytes_to_write,far_ptr(selector,0)); | ||
| 2778 | written = bytes_written; | ||
| 2779 | |||
| 2780 | if (bytes_written == bytes_to_write) /* If we wrote it all... */ | ||
| 2781 | { | ||
| 2782 | part_size += (DWORD)written; /* Update size of this part. */ | ||
| 2783 | cumul_part_size += (DWORD)written; /* Update size of this part. */ | ||
| 2784 | data_file_tot_len += (DWORD)written; /* Update length of BACKUP.xxx file */ | ||
| 2785 | } | ||
| 2786 | else | ||
| 2787 | { | ||
| 2788 | written = write_till_target_full(bytes_to_write,0); /* Fill up current target */ | ||
| 2789 | bytes_written += written; /* Update # bytes written */ | ||
| 2790 | part_size += (DWORD)written; /* Update size of this part. */ | ||
| 2791 | cumul_part_size += (DWORD)written; /* Update size of this part. */ | ||
| 2792 | data_file_tot_len += (DWORD)written; /* Update length of BACKUP.xxx file */ | ||
| 2793 | close_out_current_target(); /* Update CONTROL.xxx file, close files */ | ||
| 2794 | get_next_target(); /* Get next diskette from user * | ||
| 2795 | /* Write rest of buffer */ | ||
| 2796 | written = handle_write(handle_target,bytes_to_write-bytes_written,far_ptr(selector,bytes_written)); | ||
| 2797 | bytes_written += written; /* Update # bytes written */ | ||
| 2798 | part_size = (DWORD)written; /* Update size of this part. */ | ||
| 2799 | cumul_part_size += (DWORD)written; /* Update size of this part. */ | ||
| 2800 | data_file_tot_len += (DWORD)written; /* Update length of BACKUP.xxx file */ | ||
| 2801 | } | ||
| 2802 | |||
| 2803 | return; | ||
| 2804 | } /* end write_to_target */ | ||
| 2805 | |||
| 2806 | /*************************************************/ | ||
| 2807 | /* | ||
| 2808 | /* SUBROUTINE NAME: write_till_target_full | ||
| 2809 | /* | ||
| 2810 | /* FUNCTION: | ||
| 2811 | /* Find out how much space is left on the disk, | ||
| 2812 | /* and use it all up. | ||
| 2813 | /* | ||
| 2814 | /***************************************************/ | ||
| 2815 | WORD write_till_target_full(bytes_to_write,begin_offset) | ||
| 2816 | WORD bytes_to_write; | ||
| 2817 | WORD begin_offset; | ||
| 2818 | { | ||
| 2819 | WORD written; | ||
| 2820 | WORD bfree; | ||
| 2821 | |||
| 2822 | bfree = (unsigned) disk_free_space(); | ||
| 2823 | written = handle_write(handle_target,bfree,far_ptr(selector,begin_offset)); | ||
| 2824 | |||
| 2825 | return(written); | ||
| 2826 | } /* end write_till_target_full */ | ||
| 2827 | |||
| 2828 | /*************************************************/ | ||
| 2829 | /* | ||
| 2830 | /* SUBROUTINE NAME: close_out_current_target | ||
| 2831 | /* | ||
| 2832 | /* FUNCTION: | ||
| 2833 | /* Update CONTROL.xxx file, close it, close BACKUP.xxx, | ||
| 2834 | /* make files READONLY, die if backing up to hardfile. | ||
| 2835 | /* | ||
| 2836 | /***************************************************/ | ||
| 2837 | void close_out_current_target() | ||
| 2838 | { | ||
| 2839 | BYTE last = LAST_TARGET; /*;AN011;*/ | ||
| 2840 | |||
| 2841 | disk_full = TRUE; /* Yes, the disk is full */ | ||
| 2842 | |||
| 2843 | if (part_size != 0) /* If we wrote something...*/ | ||
| 2844 | { | ||
| 2845 | file_spans_target = TRUE; /* Say "Hey, this file spans diskettes !" */ | ||
| 2846 | files_backed_up++; /* Increment number files backed up on this target */ | ||
| 2847 | } | ||
| 2848 | |||
| 2849 | if (files_backed_up > 0) /* If we backed up something */ | ||
| 2850 | update_db_entries(files_backed_up); /* Increment Num_Entries field in directory block and NextDB field */ | ||
| 2851 | |||
| 2852 | update_fh_entries(); /* Update the fields in file header */ | ||
| 2853 | |||
| 2854 | if (!target_removable) /*;AN011;*/ | ||
| 2855 | { /*;AN011;*/ | ||
| 2856 | /* Update DH_LastDisk == LAST_DISK */ | ||
| 2857 | lseek(handle_control,BOFILE,(DWORD)(DHLENGTH - 1)); /*;AN011;*/ | ||
| 2858 | handle_write(handle_control,1,(char far *)&last); /*;AN011;*/ | ||
| 2859 | } /*;AN011;*/ | ||
| 2860 | |||
| 2861 | if (control_opened) /* If the control file is open */ | ||
| 2862 | { | ||
| 2863 | close_file(handle_control); /* Close it */ | ||
| 2864 | control_opened = FALSE; /* And say it isn't open */ | ||
| 2865 | } | ||
| 2866 | |||
| 2867 | if (target_opened) | ||
| 2868 | close_file(handle_target); /* Close files */ | ||
| 2869 | |||
| 2870 | target_opened = FALSE; /* Indicate that target is not opened */ | ||
| 2871 | |||
| 2872 | if (file_spans_target) /* If file spans to another diskette */ | ||
| 2873 | span_seq_num++; /* then increment the sequence number */ | ||
| 2874 | |||
| 2875 | mark_files_read_only(); /* Set ReadOnly Attribute of BACKUP/CONTROL files */ | ||
| 2876 | |||
| 2877 | if (logfile_on_target) /*;AN000;7 If logfile resides on target drive */ | ||
| 2878 | { /*;AN000;7 */ | ||
| 2879 | close_file(handle_logfile); /*;AN000;7 Then close it */ | ||
| 2880 | logfile_opened = FALSE; /*;AN000;7 and set flag indicating that */ | ||
| 2881 | } /*;AN000;7 */ | ||
| 2882 | |||
| 2883 | if (!target_removable) /* If target is a hardfile */ | ||
| 2884 | { | ||
| 2885 | display_msg(LASTNOTBACKUP); /* Say "Last file not backed up */ | ||
| 2886 | error_exit(FDISKFULLMSG); /* then give error message and quit */ | ||
| 2887 | } | ||
| 2888 | |||
| 2889 | diskettes_complete++; /* Increment number of diskettes complete */ | ||
| 2890 | return; | ||
| 2891 | } /* end close_out_current_target */ | ||
| 2892 | |||
| 2893 | /*************************************************/ | ||
| 2894 | /* | ||
| 2895 | /* SUBROUTINE NAME: mark_as_not_last_target | ||
| 2896 | /* | ||
| 2897 | /* FUNCTION: | ||
| 2898 | /* Sets the field in the disk header indicating | ||
| 2899 | /* this is not the last target | ||
| 2900 | /* | ||
| 2901 | /***************************************************/ | ||
| 2902 | void mark_as_not_last_target() | ||
| 2903 | { | ||
| 2904 | BYTE last = NOT_LAST_TARGET; | ||
| 2905 | DWORD db_offset; | ||
| 2906 | DWORD pointer; | ||
| 2907 | |||
| 2908 | /* Update DH_LastDisk = NOT_LAST_TARGET */ | ||
| 2909 | lseek(handle_control,BOFILE,(DWORD)(DHLENGTH - 1)); | ||
| 2910 | handle_write(handle_control,1,(char far *)&last); | ||
| 2911 | |||
| 2912 | /* Get first DB_NextDB */ | ||
| 2913 | pointer = lseek(handle_control,BOFILE,(DWORD)(DHLENGTH+66)); | ||
| 2914 | handle_read(handle_control,4,(char far *)&db_offset); | ||
| 2915 | |||
| 2916 | /* Get offset of last Dir Block */ | ||
| 2917 | while (db_offset != (DWORD)LAST_DB) | ||
| 2918 | { | ||
| 2919 | pointer = lseek(handle_control,BOFILE,(DWORD)db_offset+66); | ||
| 2920 | handle_read(handle_control,4,(char far *)&db_offset); | ||
| 2921 | } | ||
| 2922 | |||
| 2923 | /* Change DB_NextDB field to point to EOF */ | ||
| 2924 | lseek(handle_control,BOFILE,(DWORD)pointer); | ||
| 2925 | handle_write(handle_control,4,(char far *)&ctl_file_tot_len); | ||
| 2926 | |||
| 2927 | lseek(handle_control,EOFILE,(DWORD)0); | ||
| 2928 | return; | ||
| 2929 | } /* end mark_as_not_last_target */ | ||
| 2930 | |||
| 2931 | /*************************************************/ | ||
| 2932 | /* | ||
| 2933 | /* SUBROUTINE NAME: mark_as_last_target | ||
| 2934 | /* | ||
| 2935 | /* FUNCTION: | ||
| 2936 | /* Sets the field in the disk header indicating | ||
| 2937 | /* this is the last target. Also updates the | ||
| 2938 | /* directory block to indicate the number of | ||
| 2939 | /* files that are backed up. | ||
| 2940 | /* | ||
| 2941 | /***************************************************/ | ||
| 2942 | void mark_as_last_target() | ||
| 2943 | { | ||
| 2944 | BYTE last = LAST_TARGET; | ||
| 2945 | |||
| 2946 | /* Update DH_LastDisk == LAST_DISK */ | ||
| 2947 | lseek(handle_control,BOFILE,(DWORD)(DHLENGTH - 1)); | ||
| 2948 | handle_write(handle_control,1,(char far *)&last); | ||
| 2949 | |||
| 2950 | /* Update DB_NumEntries == FILES_BACKED_UP */ | ||
| 2951 | lseek(handle_control,BOFILE,(DWORD)(curr_db_begin_offset + 64)); | ||
| 2952 | handle_write(handle_control,2,(char far *)&files_backed_up); | ||
| 2953 | |||
| 2954 | /* Update FH Entries */ | ||
| 2955 | update_fh_entries(); | ||
| 2956 | |||
| 2957 | return; | ||
| 2958 | } /* end mark_as_last_target */ | ||
| 2959 | |||
| 2960 | /*************************************************/ | ||
| 2961 | /* | ||
| 2962 | /* SUBROUTINE NAME: update_db_entries | ||
| 2963 | /* | ||
| 2964 | /* FUNCTION: | ||
| 2965 | /* | ||
| 2966 | /* | ||
| 2967 | /* | ||
| 2968 | /***************************************************/ | ||
| 2969 | void update_db_entries(entries) | ||
| 2970 | WORD entries; | ||
| 2971 | { | ||
| 2972 | lseek(handle_control,BOFILE,(DWORD)(curr_db_begin_offset+64)); | ||
| 2973 | |||
| 2974 | /* Update DB_num_entries */ | ||
| 2975 | handle_write(handle_control,2,(char far *)&entries); | ||
| 2976 | |||
| 2977 | if (!disk_full) /* Update DB_NextDB only if we are not at the end of a disk */ | ||
| 2978 | handle_write(handle_control,4,(char far *)&ctl_file_tot_len); | ||
| 2979 | |||
| 2980 | lseek(handle_control,EOFILE,(DWORD)0); | ||
| 2981 | |||
| 2982 | return; | ||
| 2983 | } /* end update_db_entries */ | ||
| 2984 | |||
| 2985 | /*************************************************/ | ||
| 2986 | /* | ||
| 2987 | /* SUBROUTINE NAME: update_fh_entries | ||
| 2988 | /* | ||
| 2989 | /* FUNCTION: | ||
| 2990 | /* Update following fields in Current File Header: | ||
| 2991 | /* | ||
| 2992 | /* FH_Flags: Indicate file successfully processed. | ||
| 2993 | /* Indicate if this is last part or not. | ||
| 2994 | /* | ||
| 2995 | /* FH_PartSize: Indicate number of bytes written | ||
| 2996 | /* | ||
| 2997 | /***************************************************/ | ||
| 2998 | void update_fh_entries() | ||
| 2999 | { | ||
| 3000 | BYTE flag; | ||
| 3001 | |||
| 3002 | if (!file_spans_target) | ||
| 3003 | flag = (BYTE)(LASTPART + SUCCESSFUL); | ||
| 3004 | else | ||
| 3005 | flag = (BYTE)(NOTLASTPART + SUCCESSFUL); | ||
| 3006 | |||
| 3007 | /*EAEA if (ext_attrib_flg) /*;AN000;3 If there are extended attributes */ | ||
| 3008 | /*EAEA if (span_seq_num == 1) /*;AN000;3 If its the first part of file */ | ||
| 3009 | /*EAEA flag += EXT_ATTR; /*;AN000;3 set flag indicating extended attributes exist */ | ||
| 3010 | |||
| 3011 | if (!target_removable) /*;AN011;*/ | ||
| 3012 | if (disk_full) /*;AN011;*/ | ||
| 3013 | { /*;AN011;*/ | ||
| 3014 | flag = (BYTE)(LASTPART + NOTSUCCESSFUL); /*;AN011;*/ | ||
| 3015 | } /*;AN011;*/ | ||
| 3016 | |||
| 3017 | /* Go to FLAG field */ | ||
| 3018 | lseek(handle_control,BOFILE,(DWORD)(curr_fh_begin_offset+13)); | ||
| 3019 | /* Write the FLAG field to control file */ | ||
| 3020 | handle_write(handle_control,1,(BYTE far *)&flag); | ||
| 3021 | |||
| 3022 | /* Go to PARTSIZE field */ | ||
| 3023 | lseek(handle_control,CURRPOS,(DWORD)10); | ||
| 3024 | /* Write the PARTSIZE field to control file */ | ||
| 3025 | handle_write(handle_control,4,(char far *)&part_size); | ||
| 3026 | |||
| 3027 | lseek(handle_control,EOFILE,(DWORD)0); /* Go back to end-of-file */ | ||
| 3028 | |||
| 3029 | return; | ||
| 3030 | } /* end update_fh_entries */ | ||
| 3031 | |||
| 3032 | /*************************************************/ | ||
| 3033 | /* | ||
| 3034 | /* SUBROUTINE NAME: mark_files_read_only | ||
| 3035 | /* | ||
| 3036 | /* FUNCTION: | ||
| 3037 | /* Set the READ-ONLY attribute on BACKUP.xxx and CONTROL.xx | ||
| 3038 | /* | ||
| 3039 | /* | ||
| 3040 | /***************************************************/ | ||
| 3041 | void mark_files_read_only() | ||
| 3042 | { | ||
| 3043 | char path[25]; | ||
| 3044 | |||
| 3045 | build_ext(diskettes_complete + 1); | ||
| 3046 | |||
| 3047 | if (target_removable) | ||
| 3048 | { | ||
| 3049 | sprintf(path,"%c:\\CONTROL.%s",tgt_drive_letter,ext); | ||
| 3050 | set_attribute(path,(WORD)(ARCHIVE + READONLY)); | ||
| 3051 | sprintf(path,"%c:\\BACKUP.%s",tgt_drive_letter,ext); | ||
| 3052 | set_attribute(path,(WORD)(ARCHIVE + READONLY)); | ||
| 3053 | } | ||
| 3054 | else | ||
| 3055 | { | ||
| 3056 | sprintf(path,"%c:\\BACKUP\\CONTROL.%s",tgt_drive_letter,ext); | ||
| 3057 | set_attribute(path,(WORD)(ARCHIVE + READONLY)); | ||
| 3058 | sprintf(path,"%c:\\BACKUP\\BACKUP.%s",tgt_drive_letter,ext); | ||
| 3059 | set_attribute(path,(WORD)(ARCHIVE + READONLY)); | ||
| 3060 | } | ||
| 3061 | |||
| 3062 | if (target_removable) | ||
| 3063 | label_target_drive(); | ||
| 3064 | |||
| 3065 | return; | ||
| 3066 | } | ||
| 3067 | |||
| 3068 | /*************************************************/ | ||
| 3069 | /* | ||
| 3070 | /* SUBROUTINE NAME: put_disk_header | ||
| 3071 | /* | ||
| 3072 | /* FUNCTION: | ||
| 3073 | /* | ||
| 3074 | /* | ||
| 3075 | /* | ||
| 3076 | /***************************************************/ | ||
| 3077 | void put_disk_header() | ||
| 3078 | { | ||
| 3079 | struct Disk_Header dh; | ||
| 3080 | int i; | ||
| 3081 | |||
| 3082 | dh.DH_Length = DHLENGTH; /* DH_Length */ | ||
| 3083 | |||
| 3084 | strcpy(dh.DH_Identifier,"BACKUP "); /* DH_Identifier */ | ||
| 3085 | dh.DH_Sequence = diskettes_complete + 1; /* DH_Sequence */ | ||
| 3086 | for (i=0; i<=128; i++) dh.DH_reserved[i] = NUL; /* DH_Reserved */ | ||
| 3087 | dh.DH_LastDisk = NOT_LAST_TARGET; /* DH_LastDisk - Assume NOT THE LAST TARGET */ | ||
| 3088 | |||
| 3089 | write_to_control_file((char far *)&dh,DHLENGTH); | ||
| 3090 | put_new_db(); | ||
| 3091 | |||
| 3092 | return; | ||
| 3093 | } /* end put_disk_header */ | ||
| 3094 | |||
| 3095 | /*************************************************/ | ||
| 3096 | /* | ||
| 3097 | /* SUBROUTINE NAME: put_new_db | ||
| 3098 | /* | ||
| 3099 | /* FUNCTION: | ||
| 3100 | /* | ||
| 3101 | /* | ||
| 3102 | /* | ||
| 3103 | /***************************************************/ | ||
| 3104 | void put_new_db() | ||
| 3105 | { | ||
| 3106 | struct Dir_Block db; | ||
| 3107 | int i; | ||
| 3108 | |||
| 3109 | if (files_backed_up > 0) | ||
| 3110 | update_db_entries(files_backed_up); /* Update entries in previous db */ | ||
| 3111 | |||
| 3112 | curr_db_begin_offset = ctl_file_tot_len; /* Save this for updating when done with current dir */ | ||
| 3113 | |||
| 3114 | db.DB_Length = DBLENGTH; /* LENGTH, IN BYTES, OF DIR BLOCK */ | ||
| 3115 | for (i=0; i<=63; i++) | ||
| 3116 | db.DB_Path[i]=NUL; /* ASCII PATH OF THIS DIRECTORY, DRIVE OMITTED*/ | ||
| 3117 | |||
| 3118 | strcpy(db.DB_Path,&src_drive_path[3]); | ||
| 3119 | db.DB_NumEntries = 0; /* NUM OF FILENAMES CURRENTLY IN LIST */ | ||
| 3120 | db.DB_NextDB = (DWORD)LAST_DB; /* OFFSET OF NEXT DIRECTORY BLOCK */ | ||
| 3121 | |||
| 3122 | write_to_control_file((char far *)&db,DBLENGTH); | ||
| 3123 | new_directory = FALSE; | ||
| 3124 | files_backed_up = 0; | ||
| 3125 | |||
| 3126 | return; | ||
| 3127 | } /* end put_new_db */ | ||
| 3128 | |||
| 3129 | /*************************************************/ | ||
| 3130 | /* | ||
| 3131 | /* SUBROUTINE NAME: put_new_fh | ||
| 3132 | /* | ||
| 3133 | /* FUNCTION: | ||
| 3134 | /* We are about to backup a file. Write the | ||
| 3135 | /* file header to the control file. | ||
| 3136 | /* | ||
| 3137 | /***************************************************/ | ||
| 3138 | void put_new_fh() | ||
| 3139 | { | ||
| 3140 | struct File_Header fh; | ||
| 3141 | int i; /*;AN000;3*/ | ||
| 3142 | |||
| 3143 | if (do_add) /* If we are adding files */ | ||
| 3144 | if (doing_first_target) /* and it is the last diskette from previous backup */ | ||
| 3145 | if (files_backed_up == 0) /* and we have not backed up ANY yet */ | ||
| 3146 | mark_as_not_last_target(); /* then mark this diskette as NOT the last */ | ||
| 3147 | |||
| 3148 | if (new_directory) /* If this file resides in a different directory */ | ||
| 3149 | put_new_db(); /* then create new directory block. */ | ||
| 3150 | |||
| 3151 | curr_fh_begin_offset = ctl_file_tot_len; | ||
| 3152 | |||
| 3153 | fh.FH_Length = FHLENGTH; /* LENGTH, IN BYTES, OF FILE HEADER */ | ||
| 3154 | for (i=0; i<=11; i++) fh.FH_FName[i]=NUL; /*;AN000;3*/ | ||
| 3155 | strcpy(fh.FH_FName,dta.file_name); /* ASCII FILE NAME */ | ||
| 3156 | |||
| 3157 | fh.FH_FLength = (DWORD)dta.file_size; /* Length of file */ | ||
| 3158 | fh.FH_FSequence = span_seq_num; /* Sequence #, for files that span */ | ||
| 3159 | fh.FH_BeginOffset=data_file_tot_len; /* OFFSET WHERE THIS SEGMENT BEGINS */ | ||
| 3160 | fh.FH_Attribute = dta.attributes; /* FILE ATTRIBUTE FROM DIRECTORY */ | ||
| 3161 | fh.FH_FTime = dta.write_time; /* TIME WHEN FILE WAS LAST MODIFIED */ | ||
| 3162 | fh.FH_FDate = dta.write_date; /* DATE WHEN FILE WAS LAST MODIFIED */ | ||
| 3163 | /*EAEA fh.FH_EA_offset = 0; /*;AN000;3 Otherwise set to zero */ | ||
| 3164 | fh.FH_Flags = LASTPART + SUCCESSFUL; | ||
| 3165 | |||
| 3166 | /*EAEA if (ext_attrib_flg) /*;AN000;3 If there are extended attributes */ | ||
| 3167 | /*EAEA if (!file_spans_target) /*;AN000;3*/ | ||
| 3168 | /*EAEA if (span_seq_num == 1) /*;AN000;3 If its the first part of file */ | ||
| 3169 | /*EAEA { /*;AN000;3*/ | ||
| 3170 | /*EAEA fh.FH_Flags += EXT_ATTR; /*;AN000;3 set flag indicating extended attributes exist */ | ||
| 3171 | /*EAEA fh.FH_EA_offset = data_file_tot_len; /*;AN000;3 OFFSET WHERE EXTENDED ATTRIBUTES BEGIN */ | ||
| 3172 | /*EAEA fh.FH_BeginOffset += ext_attrib_len+2; /*;AN000;3*/ | ||
| 3173 | /*EAEA } /*;AN000;3*/ | ||
| 3174 | |||
| 3175 | if (file_spans_target) | ||
| 3176 | { | ||
| 3177 | fh.FH_PartSize = (DWORD)(dta.file_size - cumul_part_size); /*LENGTH OF THIS PART OF FILE */ | ||
| 3178 | file_spans_target = FALSE; | ||
| 3179 | } | ||
| 3180 | else | ||
| 3181 | fh.FH_PartSize = (DWORD)dta.file_size;/* LENGTH OF THIS PART OF FILE */ | ||
| 3182 | |||
| 3183 | write_to_control_file((char far *)&fh,FHLENGTH); | ||
| 3184 | |||
| 3185 | return; | ||
| 3186 | } /* end put_new_fh */ | ||
| 3187 | |||
| 3188 | /*************************************************/ | ||
| 3189 | /* | ||
| 3190 | /* SUBROUTINE NAME: write_to_control_file | ||
| 3191 | /* | ||
| 3192 | /* FUNCTION: | ||
| 3193 | /* Write to the control file and update | ||
| 3194 | /* counters | ||
| 3195 | /* | ||
| 3196 | /***************************************************/ | ||
| 3197 | void write_to_control_file(address,len) | ||
| 3198 | char far * address; | ||
| 3199 | unsigned short len; | ||
| 3200 | { | ||
| 3201 | WORD written; | ||
| 3202 | |||
| 3203 | written = handle_write(handle_control,len,address); | ||
| 3204 | ctl_file_tot_len = ctl_file_tot_len + (DWORD)written; | ||
| 3205 | |||
| 3206 | return; | ||
| 3207 | } /* end write_to_control_file */ | ||
| 3208 | |||
| 3209 | /*************************************************/ | ||
| 3210 | /* | ||
| 3211 | /* SUBROUTINE NAME: control_break_handler | ||
| 3212 | /* | ||
| 3213 | /* FUNCTION: | ||
| 3214 | /* Set errorlevel and call routines to | ||
| 3215 | /* close files and terminate. | ||
| 3216 | /* | ||
| 3217 | /***************************************************/ | ||
| 3218 | void control_break_handler() | ||
| 3219 | { | ||
| 3220 | return_code = RETCODE_CTL_BREAK; | ||
| 3221 | clean_up_and_exit(); | ||
| 3222 | return; | ||
| 3223 | } | ||
| 3224 | |||
| 3225 | |||
| 3226 | /************************************************************/ | ||
| 3227 | /* | ||
| 3228 | /* SUBROUTINE NAME: display_it | ||
| 3229 | /* | ||
| 3230 | /* SUBROUTINE FUNCTION: | ||
| 3231 | /* Display the requested message to the standard output device. | ||
| 3232 | /* | ||
| 3233 | /* INPUT: | ||
| 3234 | /* 1) (WORD) Number of the message to be displayed. | ||
| 3235 | /* 2) (WORD) Handle to be written to. | ||
| 3236 | /* 3) (WORD) Substitution Count | ||
| 3237 | /* 4) (WORD) Flag indicating user should "Strike any key..." | ||
| 3238 | /* 5) (WORD) Num indicating message class | ||
| 3239 | /* | ||
| 3240 | /* OUTPUT: | ||
| 3241 | /* The message corresponding to the requested msg number will | ||
| 3242 | /* be written to the requested handle. If requested, substitution | ||
| 3243 | /* text will be inserted as required. The Substitution List | ||
| 3244 | /* is global and, if used, will be initialized by DISPLAY_MSG | ||
| 3245 | /* before calling this routine. | ||
| 3246 | /* | ||
| 3247 | /* NORMAL EXIT: | ||
| 3248 | /* Message will be successfully written to requested handle. | ||
| 3249 | /* | ||
| 3250 | /* ERROR EXIT: | ||
| 3251 | /* None. Note that theoretically an error can be returned from | ||
| 3252 | /* SYSDISPMSG, but there is nothing that the application can do. | ||
| 3253 | /* | ||
| 3254 | /* INTERNAL REFERENCES: | ||
| 3255 | /* System Display Message service routine SYSDISPMSG | ||
| 3256 | /* | ||
| 3257 | /* EXTERNAL REFERENCES: | ||
| 3258 | /* None | ||
| 3259 | /* | ||
| 3260 | /************************************************************/ | ||
| 3261 | void display_it(msg_number,handle,subst_count,waitflag,class)/*;AN000;6*/ | ||
| 3262 | |||
| 3263 | int msg_number; /*;AN000;6*/ | ||
| 3264 | WORD handle; /*;AN000;6*/ | ||
| 3265 | int subst_count; /*;AN000;6*/ | ||
| 3266 | BYTE waitflag; /*;AN000;6*/ | ||
| 3267 | BYTE class; /*;AN000;6 1=DOSerror, 2=PARSE,-1=Utility msg*/ | ||
| 3268 | { /*;AN000;6*/ | ||
| 3269 | inregs.x.ax = msg_number; /*;AN000;6*/ | ||
| 3270 | inregs.x.bx = handle; /*;AN000;6*/ | ||
| 3271 | inregs.x.cx = subst_count; /*;AN000;6*/ | ||
| 3272 | inregs.h.dh = class; /*;AN000;6*/ | ||
| 3273 | inregs.h.dl = (BYTE)waitflag; /*;AN000;6*/ | ||
| 3274 | inregs.x.si = (WORD)(char far *)&sublist; /*;AN000;6*/ | ||
| 3275 | |||
| 3276 | sysdispmsg(&inregs,&outregs); /*;AN000;6*/ | ||
| 3277 | |||
| 3278 | return; /*;AN000;6*/ | ||
| 3279 | } /*;AN000;6*/ | ||
| 3280 | /*************************************************/ | ||
| 3281 | /* | ||
| 3282 | /* SUBROUTINE NAME: display_msg | ||
| 3283 | /* | ||
| 3284 | /* FUNCTION: | ||
| 3285 | /* Display the messages referenced by | ||
| 3286 | /* variable MSG_NUM to either STDOUT or | ||
| 3287 | /* STDERR. In some cases insert text into | ||
| 3288 | /* the body of the message. | ||
| 3289 | /* | ||
| 3290 | /***************************************************/ | ||
| 3291 | |||
| 3292 | void display_msg(msg_num) | ||
| 3293 | int msg_num; | ||
| 3294 | { | ||
| 3295 | |||
| 3296 | switch (msg_num) | ||
| 3297 | { | ||
| 3298 | case NONEFNDMSG : { display_it (msg_num,STDOUT,0,NOWAIT,(BYTE)UTIL_MSG); break; } /*;AN000;6*/ | ||
| 3299 | |||
| 3300 | case INSUFF_MEMORY : /*;AN000;6*/ | ||
| 3301 | case ERR_EXEC_FORMAT : /*;AN000;d178*/ | ||
| 3302 | case INV_PATH : /*;AN000;6*/ | ||
| 3303 | case INV_DATE : /*;AN000;6*/ | ||
| 3304 | case INV_TIME : /*;AN000;6*/ | ||
| 3305 | case NO_SOURCE : /*;AN000;6*/ | ||
| 3306 | case NO_TARGET : /*;AN000;6*/ | ||
| 3307 | case SRC_AND_TGT_SAME : /*;AN000;6*/ | ||
| 3308 | case BAD_DOS_VER : /*;AN000;6*/ | ||
| 3309 | case INV_DRIVE : /*;AN000;6*/ | ||
| 3310 | case CANT_OPEN_LOGFILE: /*;AN000;6*/ | ||
| 3311 | case INVTARGET : /*;AN000;6*/ | ||
| 3312 | case NOTLASTMSG : /*;AN000;6*/ | ||
| 3313 | case CONFLICTMSG : /*;AN000;6*/ | ||
| 3314 | case CRLF : | ||
| 3315 | case CANT_FIND_FORMAT : | ||
| 3316 | case LASTNOTBACKUP :{ /*;AN000;6*/ | ||
| 3317 | display_it (msg_num,STDERR,0,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ | ||
| 3318 | break; /*;AN000;6*/ | ||
| 3319 | } /*;AN000;6*/ | ||
| 3320 | |||
| 3321 | case LOGFILE_TARGET_FULL:{ | ||
| 3322 | display_it (msg_num,STDERR,0,NOWAIT,(BYTE)UTIL_MSG);/*;AN000;6*/ | ||
| 3323 | display_it (PRESS_ANY_KEY,STDERR,0,WAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ | ||
| 3324 | break; | ||
| 3325 | } | ||
| 3326 | |||
| 3327 | case LOGGING : { | ||
| 3328 | sublist.value1 = (char far *)&logfile_path[0]; /*;AN000;6*/ | ||
| 3329 | sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ | ||
| 3330 | sublist.pad_char1 = ' '; /*;AN000;6*/ | ||
| 3331 | sublist.max_width1 = (BYTE)strlen(logfile_path); /*;AN000;6*/ | ||
| 3332 | sublist.min_width1 = sublist.max_width1; /*;AN000;6*/ | ||
| 3333 | display_it (msg_num,STDOUT,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ | ||
| 3334 | break; | ||
| 3335 | } | ||
| 3336 | |||
| 3337 | case CANT_FORMAT_HARDFILE : | ||
| 3338 | { sublist.value1 = (char far *)&tgt_drive_letter; /*;AN000;6*/ | ||
| 3339 | sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ | ||
| 3340 | sublist.pad_char1 = ' '; /*;AN000;6*/ | ||
| 3341 | sublist.max_width1 = 1; /*;AN000;6*/ | ||
| 3342 | sublist.min_width1 = 1; /*;AN000;6*/ | ||
| 3343 | display_it (msg_num,STDERR,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ | ||
| 3344 | break; | ||
| 3345 | } | ||
| 3346 | |||
| 3347 | case BUDISKMSG : /*;AN000;6*/ | ||
| 3348 | case FDISKFULLMSG : /*;AN000;6*/ | ||
| 3349 | { sublist.value1 = (char far *)&tgt_drive_letter; /*;AN000;6*/ | ||
| 3350 | sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ | ||
| 3351 | sublist.pad_char1 = ' '; /*;AN000;6*/ | ||
| 3352 | sublist.max_width1 = 1; /*;AN000;6*/ | ||
| 3353 | sublist.min_width1 = 1; /*;AN000;6*/ | ||
| 3354 | display_it (msg_num,STDERR,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ | ||
| 3355 | break; | ||
| 3356 | } | ||
| 3357 | |||
| 3358 | |||
| 3359 | case ERASEMSG : /*;AN000;6*/ | ||
| 3360 | case FERASEMSG : /*;AN000;6*/ | ||
| 3361 | case LASTDISKMSG : /*;AN000;6*/ | ||
| 3362 | { sublist.value1 = (char far *)&tgt_drive_letter; /*;AN000;6*/ | ||
| 3363 | sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ | ||
| 3364 | sublist.pad_char1 = ' '; /*;AN000;6*/ | ||
| 3365 | sublist.max_width1 = 1; /*;AN000;6*/ | ||
| 3366 | sublist.min_width1 = 1; /*;AN000;6*/ | ||
| 3367 | display_it (msg_num,STDERR,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ | ||
| 3368 | display_it (PRESS_ANY_KEY,STDERR,0,WAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ | ||
| 3369 | break; | ||
| 3370 | } | ||
| 3371 | |||
| 3372 | |||
| 3373 | case INSERTSOURCE : { | ||
| 3374 | sublist.value1 = (char far *)&src_drive_letter; /*;AN000;6*/ | ||
| 3375 | sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ | ||
| 3376 | sublist.pad_char1 = ' '; /*;AN000;6*/ | ||
| 3377 | sublist.max_width1 = 1; /*;AN000;6*/ | ||
| 3378 | sublist.min_width1 = 1; /*;AN000;6*/ | ||
| 3379 | display_it (msg_num,STDERR,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ | ||
| 3380 | display_it (PRESS_ANY_KEY,STDERR,0,WAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ | ||
| 3381 | break; | ||
| 3382 | } | ||
| 3383 | |||
| 3384 | |||
| 3385 | case SEQUENCEMSG : { | ||
| 3386 | build_ext(diskettes_complete+1); | ||
| 3387 | if (diskettes_complete+1 < 100) | ||
| 3388 | { | ||
| 3389 | sublist.value1 = (char far *)&ext[1]; /*;AN000;6*/ | ||
| 3390 | sublist.max_width1 = 2; /*;AN000;6*/ | ||
| 3391 | } | ||
| 3392 | else | ||
| 3393 | { | ||
| 3394 | sublist.value1 = (char far *)&ext[0]; /*;AN000;6*/ | ||
| 3395 | sublist.max_width1 = 3; /*;AN000;6*/ | ||
| 3396 | } | ||
| 3397 | sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ | ||
| 3398 | sublist.pad_char1 = ' '; /*;AN000;6*/ | ||
| 3399 | sublist.min_width1 = sublist.max_width1; /*;AN000;6*/ | ||
| 3400 | display_it (msg_num,STDOUT,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ | ||
| 3401 | break; | ||
| 3402 | } | ||
| 3403 | |||
| 3404 | |||
| 3405 | case INSERTTARGET : { | ||
| 3406 | build_ext(diskettes_complete+1); | ||
| 3407 | if (diskettes_complete+1 < 100) | ||
| 3408 | { | ||
| 3409 | sublist.value1 = (char far *)&ext[1]; /*;AN000;6*/ | ||
| 3410 | sublist.max_width1 = 2; /*;AN000;6*/ | ||
| 3411 | } | ||
| 3412 | else | ||
| 3413 | { | ||
| 3414 | sublist.value1 = (char far *)&ext[0]; /*;AN000;6*/ | ||
| 3415 | sublist.max_width1 = 3; /*;AN000;6*/ | ||
| 3416 | } | ||
| 3417 | |||
| 3418 | sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ | ||
| 3419 | sublist.pad_char1 = ' '; /*;AN000;6*/ | ||
| 3420 | sublist.min_width1 = sublist.max_width1; /*;AN000;6*/ | ||
| 3421 | |||
| 3422 | sublist.value2 = (char far *)&tgt_drive_letter; /*;AN000;6*/ | ||
| 3423 | sublist.flags2 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ | ||
| 3424 | sublist.pad_char2 = ' '; /*;AN000;6*/ | ||
| 3425 | sublist.max_width2 = 1; /*;AN000;6*/ | ||
| 3426 | sublist.min_width2 = 1; /*;AN000;6*/ | ||
| 3427 | |||
| 3428 | display_it (msg_num,STDERR,2,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ | ||
| 3429 | break; | ||
| 3430 | } | ||
| 3431 | |||
| 3432 | } | ||
| 3433 | |||
| 3434 | return; | ||
| 3435 | } /* end display_msg */ | ||
| 3436 | |||
| 3437 | /*************************************************/ | ||
| 3438 | /* | ||
| 3439 | /* SUBROUTINE NAME: error_exit | ||
| 3440 | /* | ||
| 3441 | /* FUNCTION: | ||
| 3442 | /* Display appropriate error message, set | ||
| 3443 | /* the return code, and call clean_up_and_exit. | ||
| 3444 | /* | ||
| 3445 | /***************************************************/ | ||
| 3446 | void error_exit(error_type) | ||
| 3447 | int error_type; | ||
| 3448 | { | ||
| 3449 | display_msg(error_type); | ||
| 3450 | return_code = RETCODE_ERROR; | ||
| 3451 | clean_up_and_exit(); | ||
| 3452 | |||
| 3453 | return; | ||
| 3454 | } /* end error_exit */ | ||
| 3455 | |||
| 3456 | /*************************************************/ | ||
| 3457 | /* | ||
| 3458 | /* SUBROUTINE NAME: restore_default_directories | ||
| 3459 | /* | ||
| 3460 | /* FUNCTION: | ||
| 3461 | /* Restore the original current directory on | ||
| 3462 | /* the source drive. | ||
| 3463 | /* | ||
| 3464 | /***************************************************/ | ||
| 3465 | void restore_default_directories() | ||
| 3466 | { | ||
| 3467 | char path[PATHLEN+20]; | ||
| 3468 | |||
| 3469 | sprintf(path,"%c:%s",src_drive_letter,src_def_dir); | ||
| 3470 | chdir(path); | ||
| 3471 | |||
| 3472 | return; | ||
| 3473 | } /* end restore_default_directories */ | ||
| 3474 | |||
| 3475 | /**************************************************/ | ||
| 3476 | /* | ||
| 3477 | /* SUBROUTINE NAME: clean_up_and_exit | ||
| 3478 | /* | ||
| 3479 | /* FUNCTION: | ||
| 3480 | /* Update BACKUP and CONTROL files. | ||
| 3481 | /* Close open files. | ||
| 3482 | /* Mark BACKUP, CONTROL file read only | ||
| 3483 | /* Restore default drive and directories | ||
| 3484 | /* Deallocate buffers | ||
| 3485 | /***************************************************/ | ||
| 3486 | void clean_up_and_exit() | ||
| 3487 | { | ||
| 3488 | char name[15]; /*;AN000;p2652*/ | ||
| 3489 | |||
| 3490 | if (source_opened) | ||
| 3491 | { | ||
| 3492 | close_file(handle_source); | ||
| 3493 | source_opened = FALSE; /* Indicate that source is not opened */ | ||
| 3494 | } | ||
| 3495 | |||
| 3496 | if (target_opened) | ||
| 3497 | { | ||
| 3498 | close_file(handle_target); | ||
| 3499 | target_opened = FALSE; /* Indicate that target is not opened */ | ||
| 3500 | } | ||
| 3501 | |||
| 3502 | if (control_opened) | ||
| 3503 | { | ||
| 3504 | mark_as_last_target(); | ||
| 3505 | close_file(handle_control); | ||
| 3506 | control_opened = FALSE; /*;AN005;*/ | ||
| 3507 | mark_files_read_only(); | ||
| 3508 | } | ||
| 3509 | |||
| 3510 | if (logfile_opened) | ||
| 3511 | { | ||
| 3512 | close_file(handle_logfile); | ||
| 3513 | logfile_opened = FALSE; | ||
| 3514 | } | ||
| 3515 | |||
| 3516 | if (files_backed_up == 0 && !checking_target) /*;AN000;p2652*//*;AN007;*/ | ||
| 3517 | { /*;AN005;*/ | ||
| 3518 | if (!do_add) /*;AN000;p2652*/ | ||
| 3519 | { /*;AN000;p2652*/ | ||
| 3520 | if (target_removable && got_first_target) /*;AN000;p2652*/ | ||
| 3521 | { /*;AN005;*/ | ||
| 3522 | build_ext(diskettes_complete + 1); /*;AN005;*/ | ||
| 3523 | sprintf(name,"%c:\\BACKUP.%s",tgt_drive_letter,ext); /*;AN005;*/ | ||
| 3524 | set_attribute(name,(WORD)0); /*;AN005;*/ | ||
| 3525 | delete(name); /*;AN005;*/ | ||
| 3526 | /*;AN005;*/ | ||
| 3527 | sprintf(name,"%c:\\CONTROL.%s",tgt_drive_letter,ext); /*;AN005;*/ | ||
| 3528 | set_attribute(name,(WORD)0); /*;AN005;*/ | ||
| 3529 | delete(name); /*;AN005;*/ | ||
| 3530 | } /*;AN005;*/ | ||
| 3531 | |||
| 3532 | if (!target_removable) | ||
| 3533 | delete_files(BACKUPDIR); /*;AN000;p2652*/ | ||
| 3534 | |||
| 3535 | } /*;AN000;p2652*/ | ||
| 3536 | |||
| 3537 | if (!target_removable) /*;AN005;*/ | ||
| 3538 | { /*;AN005;*/ | ||
| 3539 | sprintf(name,"%c:\\BACKUP",tgt_drive_letter); /*;AN000;p2652*/ | ||
| 3540 | rmdir(name); /*;AN000;p2652*/ | ||
| 3541 | } /*;AN005;*/ | ||
| 3542 | } /*;AN005;*/ | ||
| 3543 | |||
| 3544 | if (def_drive_set) | ||
| 3545 | { | ||
| 3546 | set_default_drive(def_drive); | ||
| 3547 | } | ||
| 3548 | |||
| 3549 | if (curr_dir_set) | ||
| 3550 | { | ||
| 3551 | restore_default_directories(); | ||
| 3552 | } | ||
| 3553 | |||
| 3554 | if (buffers_allocated) | ||
| 3555 | free_seg(selector); | ||
| 3556 | |||
| 3557 | terminate(); | ||
| 3558 | |||
| 3559 | return; | ||
| 3560 | } /* end clean_up_and_exit */ | ||
| 3561 | |||
| 3562 | |||
| 3563 | |||
| 3564 | /*************************************************/ | ||
| 3565 | /* DOS FAMILY API CALLS */ | ||
| 3566 | /**************************************************/ | ||
| 3567 | |||
| 3568 | WORD handle_open(path_addr,mode) | ||
| 3569 | char *path_addr; | ||
| 3570 | WORD mode; | ||
| 3571 | { | ||
| 3572 | WORD handle; | ||
| 3573 | WORD action; | ||
| 3574 | |||
| 3575 | #if defined(DEBUG) | ||
| 3576 | printf("\nDOSOPEN FILE=%s, MODE=%04Xh...",path_addr,mode); | ||
| 3577 | #endif | ||
| 3578 | |||
| 3579 | rc = | ||
| 3580 | DOSOPEN | ||
| 3581 | ( | ||
| 3582 | (char far *)path_addr, /* Path address */ | ||
| 3583 | (unsigned far *)&handle, /* Return area for handle */ | ||
| 3584 | (unsigned far *)&action, /* Return area for action performed */ | ||
| 3585 | (DWORD)0, /* File Size */ | ||
| 3586 | (WORD)0, /* File attribute */ | ||
| 3587 | (WORD)1, /* Flag: Only open file if it exists */ | ||
| 3588 | (WORD)mode, /* Mode */ | ||
| 3589 | (DWORD)0 /* Reserved */ | ||
| 3590 | ); | ||
| 3591 | |||
| 3592 | #if defined(DEBUG) | ||
| 3593 | if (rc == NOERROR) | ||
| 3594 | printf("SUCCESSFUL, HANDLE=%04Xh",handle); | ||
| 3595 | else | ||
| 3596 | printf("ERROR, RC=%04Xh",rc); | ||
| 3597 | #endif | ||
| 3598 | |||
| 3599 | return(handle); | ||
| 3600 | } /* end handle_open */ | ||
| 3601 | |||
| 3602 | |||
| 3603 | /*************************************************/ | ||
| 3604 | DWORD lseek(handle,method,distance) | ||
| 3605 | WORD handle; | ||
| 3606 | BYTE method; /* 0=BOF+Offset, 1=CurrPos+Offset, 2=EOF+Offset */ | ||
| 3607 | DWORD distance; | ||
| 3608 | { | ||
| 3609 | DWORD pointer; | ||
| 3610 | |||
| 3611 | #if defined(DEBUG) | ||
| 3612 | printf("\nDOSCHGFILEPTR HANDLE=%04Xh, METHOD=%02Xh, DIST=%08lXh...",handle,method,distance); | ||
| 3613 | #endif | ||
| 3614 | |||
| 3615 | rc = | ||
| 3616 | DOSCHGFILEPTR | ||
| 3617 | ( | ||
| 3618 | handle, | ||
| 3619 | distance, | ||
| 3620 | method, | ||
| 3621 | (DWORD far *)&pointer | ||
| 3622 | ); | ||
| 3623 | |||
| 3624 | #if defined(DEBUG) | ||
| 3625 | if (rc == NOERROR) | ||
| 3626 | printf("SUCCESSFUL, POINTER=%08lXh",pointer); | ||
| 3627 | else | ||
| 3628 | printf("ERROR, RC=%04Xh",rc); | ||
| 3629 | #endif | ||
| 3630 | |||
| 3631 | return((DWORD)pointer); | ||
| 3632 | } /* end lseek */ | ||
| 3633 | |||
| 3634 | /*************************************************/ | ||
| 3635 | WORD handle_read(handle,length,address) | ||
| 3636 | WORD handle; | ||
| 3637 | WORD length; | ||
| 3638 | char far *address; | ||
| 3639 | { | ||
| 3640 | WORD num_read; | ||
| 3641 | |||
| 3642 | #if defined(DEBUG) | ||
| 3643 | printf("\nDOSREAD HANDLE=%04Xh, BYTES=%04Xh, ADDR(off:seg)=%04X:%04X...",handle,length,address); | ||
| 3644 | #endif | ||
| 3645 | |||
| 3646 | rc = | ||
| 3647 | DOSREAD | ||
| 3648 | ( | ||
| 3649 | handle, | ||
| 3650 | address, | ||
| 3651 | length, | ||
| 3652 | (unsigned far *)&num_read | ||
| 3653 | ); | ||
| 3654 | |||
| 3655 | #if defined(DEBUG) | ||
| 3656 | if (rc == NOERROR) | ||
| 3657 | printf("READ %04Xh",num_read); | ||
| 3658 | else | ||
| 3659 | printf("ERROR, RC=%04Xh",rc); | ||
| 3660 | #endif | ||
| 3661 | |||
| 3662 | return(num_read); | ||
| 3663 | } /* end handle_read */ | ||
| 3664 | /*************************************************/ | ||
| 3665 | WORD handle_write(handle,length,address) | ||
| 3666 | WORD handle; | ||
| 3667 | WORD length; | ||
| 3668 | char far *address; | ||
| 3669 | { | ||
| 3670 | WORD written; | ||
| 3671 | |||
| 3672 | #if defined(DEBUG) | ||
| 3673 | printf("\nDOSWRITE HANDLE=%04Xh, BYTES=%04Xh, ADDR(off:seg)=%04X:%04X...",handle,length,address); | ||
| 3674 | #endif | ||
| 3675 | |||
| 3676 | if (length != 0) | ||
| 3677 | rc = | ||
| 3678 | DOSWRITE | ||
| 3679 | ( | ||
| 3680 | handle, | ||
| 3681 | address, | ||
| 3682 | length, | ||
| 3683 | (unsigned far *)&written | ||
| 3684 | ); | ||
| 3685 | else | ||
| 3686 | { | ||
| 3687 | written = 0; | ||
| 3688 | rc = NOERROR; | ||
| 3689 | } | ||
| 3690 | |||
| 3691 | #if defined(DEBUG) | ||
| 3692 | if (rc == NOERROR) | ||
| 3693 | printf("WROTE %04Xh",written); | ||
| 3694 | else | ||
| 3695 | printf("ERROR, RC=%04Xh",rc); | ||
| 3696 | #endif | ||
| 3697 | |||
| 3698 | return(written); | ||
| 3699 | } /* end handle_write */ | ||
| 3700 | |||
| 3701 | /*************************************************/ | ||
| 3702 | void close_file(handle) /* Close the file handle specified. */ | ||
| 3703 | WORD handle; | ||
| 3704 | { | ||
| 3705 | #if defined(DEBUG) | ||
| 3706 | printf("\nDOSCLOSE HANDLE=%04Xh...",handle); | ||
| 3707 | #endif | ||
| 3708 | |||
| 3709 | rc = DOSCLOSE(handle); | ||
| 3710 | |||
| 3711 | #if defined(DEBUG) | ||
| 3712 | if (rc == NOERROR) | ||
| 3713 | printf("SUCCESSFUL"); | ||
| 3714 | else | ||
| 3715 | printf("ERROR, RC=%04Xh",rc); | ||
| 3716 | #endif | ||
| 3717 | |||
| 3718 | return; | ||
| 3719 | } /* end close_file */ | ||
| 3720 | |||
| 3721 | /*************************************************/ | ||
| 3722 | WORD get_attribute(path_addr) | ||
| 3723 | char *path_addr; | ||
| 3724 | { | ||
| 3725 | WORD attribute; | ||
| 3726 | |||
| 3727 | #if defined(DEBUG) | ||
| 3728 | printf("\nDOSQFILEMODE %s...",path_addr); | ||
| 3729 | #endif | ||
| 3730 | |||
| 3731 | rc = DOSQFILEMODE((char far *)path_addr,(unsigned far *)&attribute,(DWORD)0); | ||
| 3732 | |||
| 3733 | #if defined(DEBUG) | ||
| 3734 | if (rc == NOERROR) | ||
| 3735 | printf("SUCCESSFUL, ATTRIB=%04Xh",attribute); | ||
| 3736 | else | ||
| 3737 | printf("ERROR, RC=%04Xh",rc); | ||
| 3738 | #endif | ||
| 3739 | |||
| 3740 | return(attribute); | ||
| 3741 | } | ||
| 3742 | |||
| 3743 | /*************************************************/ | ||
| 3744 | void set_attribute(path_addr,attribute) | ||
| 3745 | char *path_addr; | ||
| 3746 | WORD attribute; | ||
| 3747 | { | ||
| 3748 | #if defined(DEBUG) | ||
| 3749 | printf("\nDOSSETFILEMODE FILE=%s, ATTRIB=%04Xh...",path_addr,attribute); | ||
| 3750 | #endif | ||
| 3751 | |||
| 3752 | rc = DOSSETFILEMODE((char far *)path_addr,attribute,(DWORD)0); | ||
| 3753 | |||
| 3754 | #if defined(DEBUG) | ||
| 3755 | if (rc == NOERROR) | ||
| 3756 | printf("SUCCESSFUL"); | ||
| 3757 | else | ||
| 3758 | printf("ERROR, RC=%04Xh",rc); | ||
| 3759 | #endif | ||
| 3760 | |||
| 3761 | return; | ||
| 3762 | } | ||
| 3763 | /*************************************************/ | ||
| 3764 | WORD get_current_drive() | ||
| 3765 | { | ||
| 3766 | WORD drive; /* 1=a */ | ||
| 3767 | DWORD drivemap; | ||
| 3768 | |||
| 3769 | #if defined(DEBUG) | ||
| 3770 | printf("\nDOSQCURDISK DRIVE (1=A)..."); | ||
| 3771 | #endif | ||
| 3772 | |||
| 3773 | rc = DOSQCURDISK | ||
| 3774 | ( | ||
| 3775 | (unsigned far *)&drive, | ||
| 3776 | (DWORD far *)&drivemap | ||
| 3777 | ); | ||
| 3778 | |||
| 3779 | #if defined(DEBUG) | ||
| 3780 | if (rc == NOERROR) | ||
| 3781 | printf("SUCCESSFUL, DRIVE=%04Xh",drive); | ||
| 3782 | else | ||
| 3783 | printf("ERROR, RC=%04Xh",rc); | ||
| 3784 | #endif | ||
| 3785 | |||
| 3786 | return(drive); | ||
| 3787 | } | ||
| 3788 | |||
| 3789 | /*************************************************/ | ||
| 3790 | void set_default_drive(drive) /* Change the current drive (1=A,2=B) */ | ||
| 3791 | WORD drive; | ||
| 3792 | { | ||
| 3793 | #if defined(DEBUG) | ||
| 3794 | printf("\nDOSSELECTDISK (1=A) TO %04Xh...",drive); | ||
| 3795 | #endif | ||
| 3796 | |||
| 3797 | rc = DOSSELECTDISK(drive); | ||
| 3798 | |||
| 3799 | if (rc == NOERROR) | ||
| 3800 | def_drive_set = TRUE; | ||
| 3801 | |||
| 3802 | #if defined(DEBUG) | ||
| 3803 | if (rc == NOERROR) | ||
| 3804 | printf("SUCCESSFUL"); | ||
| 3805 | else | ||
| 3806 | printf("ERROR, RC=%04Xh",rc); | ||
| 3807 | #endif | ||
| 3808 | |||
| 3809 | return; | ||
| 3810 | } /* end set_default_drive */ | ||
| 3811 | |||
| 3812 | /*************************************************/ | ||
| 3813 | void get_current_dir(drive,path_addr) | ||
| 3814 | WORD drive; /* 0=default, 1=a, . . . */ | ||
| 3815 | char *path_addr; /* Pointer to path buffer */ | ||
| 3816 | { | ||
| 3817 | WORD path_buff_len = PATHLEN+20; | ||
| 3818 | |||
| 3819 | #if defined(DEBUG) | ||
| 3820 | printf("\nDOSQCURDIR DRIVE (0=def) %04Xh...",drive); | ||
| 3821 | #endif | ||
| 3822 | |||
| 3823 | rc = | ||
| 3824 | DOSQCURDIR | ||
| 3825 | ( | ||
| 3826 | drive, | ||
| 3827 | (char far *)path_addr, | ||
| 3828 | (unsigned far *)&path_buff_len | ||
| 3829 | ); | ||
| 3830 | |||
| 3831 | #if defined(DEBUG) | ||
| 3832 | if (rc == NOERROR) | ||
| 3833 | printf("SUCCESSFUL, CURRENT DIR IS = \\%s",path_addr); | ||
| 3834 | else | ||
| 3835 | printf("ERROR, RC=%04Xh",rc); | ||
| 3836 | #endif | ||
| 3837 | |||
| 3838 | return; | ||
| 3839 | } /* end get_current_dir */ | ||
| 3840 | |||
| 3841 | /*************************************************/ | ||
| 3842 | void find_first(path_addr,dirhandle_addr,dta_address,attrib) | ||
| 3843 | char *path_addr; | ||
| 3844 | WORD *dirhandle_addr; | ||
| 3845 | struct FileFindBuf *dta_address; | ||
| 3846 | WORD attrib; | ||
| 3847 | { | ||
| 3848 | WORD numentries = 1; | ||
| 3849 | WORD temprc; | ||
| 3850 | |||
| 3851 | *dirhandle_addr = 0xffff; | ||
| 3852 | |||
| 3853 | |||
| 3854 | #if defined(DEBUG) | ||
| 3855 | printf("\nDOSFINDFIRST DIRH=%04Xh, FILE=%s...",*dirhandle_addr,path_addr); | ||
| 3856 | #endif | ||
| 3857 | |||
| 3858 | rc = | ||
| 3859 | DOSFINDFIRST | ||
| 3860 | ( | ||
| 3861 | (char far *)path_addr, | ||
| 3862 | (unsigned far *)dirhandle_addr, | ||
| 3863 | attrib, | ||
| 3864 | (struct FileFindBuf far *)dta_address, | ||
| 3865 | (WORD)(sizeof(struct FileFindBuf)), | ||
| 3866 | (unsigned far *)&numentries, | ||
| 3867 | (DWORD)0 | ||
| 3868 | ); | ||
| 3869 | |||
| 3870 | #if defined(DEBUG) | ||
| 3871 | if (rc == NOERROR) | ||
| 3872 | printf("SUCCESSFUL, NAME=%s, ATTR=%04Xh, SIZE=%08lXh, DIRH=%04Xh",(*dta_address).file_name,(*dta_address).attributes,(*dta_address).file_size,*dirhandle_addr); | ||
| 3873 | else | ||
| 3874 | printf("ERROR, DIRH=%04Xh, RC=%04Xh",*dirhandle_addr,rc); | ||
| 3875 | #endif | ||
| 3876 | |||
| 3877 | if (rc != NOERROR) | ||
| 3878 | { | ||
| 3879 | temprc=rc; | ||
| 3880 | findclose(*dirhandle_addr); | ||
| 3881 | rc = temprc; | ||
| 3882 | } | ||
| 3883 | |||
| 3884 | return; | ||
| 3885 | } /* end find_first */ | ||
| 3886 | |||
| 3887 | /*************************************************/ | ||
| 3888 | void find_next(dirhandle,dta_address) | ||
| 3889 | WORD dirhandle; | ||
| 3890 | struct FileFindBuf *dta_address; | ||
| 3891 | { | ||
| 3892 | WORD temprc; | ||
| 3893 | WORD numentries = 1; | ||
| 3894 | |||
| 3895 | #if defined(DEBUG) | ||
| 3896 | printf("\nDOSFINDNEXT, DIRH=%04Xh...",dirhandle); | ||
| 3897 | #endif | ||
| 3898 | |||
| 3899 | rc = | ||
| 3900 | DOSFINDNEXT | ||
| 3901 | ( | ||
| 3902 | dirhandle, | ||
| 3903 | (struct FileFindBuf far *)dta_address, | ||
| 3904 | (WORD)(sizeof(struct FileFindBuf)+12), | ||
| 3905 | (unsigned far *)&numentries | ||
| 3906 | ); | ||
| 3907 | |||
| 3908 | #if defined(DEBUG) | ||
| 3909 | if (rc == NOERROR) | ||
| 3910 | printf("SUCCESSFUL, NAME=%s, DIRH=%04Xh",(*dta_address).file_name,dirhandle); | ||
| 3911 | else | ||
| 3912 | printf("ERROR, RC=%04Xh",rc); | ||
| 3913 | #endif | ||
| 3914 | |||
| 3915 | if (rc != NOERROR) | ||
| 3916 | { | ||
| 3917 | temprc=rc; | ||
| 3918 | findclose(dirhandle); | ||
| 3919 | rc = temprc; | ||
| 3920 | } | ||
| 3921 | |||
| 3922 | return; | ||
| 3923 | } /* end find_next */ | ||
| 3924 | /*************************************************/ | ||
| 3925 | void findclose(dirhandle) | ||
| 3926 | WORD dirhandle; | ||
| 3927 | { | ||
| 3928 | |||
| 3929 | #if defined(DEBUG) | ||
| 3930 | printf("\nDOSFINDCLOSE DIRH=%04Xh...",dirhandle); | ||
| 3931 | #endif | ||
| 3932 | |||
| 3933 | rc = DOSFINDCLOSE(dirhandle); | ||
| 3934 | |||
| 3935 | dirhandles_open = FALSE; | ||
| 3936 | |||
| 3937 | #if defined(DEBUG) | ||
| 3938 | if (rc == NOERROR) | ||
| 3939 | printf("SUCCESSFUL"); | ||
| 3940 | else | ||
| 3941 | printf("ERROR, RC=%04Xh",rc); | ||
| 3942 | #endif | ||
| 3943 | |||
| 3944 | return; | ||
| 3945 | } /* end findclose */ | ||
| 3946 | /*************************************************/ | ||
| 3947 | void delete(path_addr) | ||
| 3948 | char *path_addr; | ||
| 3949 | { | ||
| 3950 | #if defined(DEBUG) | ||
| 3951 | printf("\nDOSDELETE FILE %s...",path_addr); | ||
| 3952 | #endif | ||
| 3953 | |||
| 3954 | rc = DOSDELETE((char far *)path_addr,(DWORD)0); | ||
| 3955 | |||
| 3956 | #if defined(DEBUG) | ||
| 3957 | if (rc == NOERROR) | ||
| 3958 | printf("SUCCESSFUL"); | ||
| 3959 | else | ||
| 3960 | printf("ERROR, RC=%04Xh",rc); | ||
| 3961 | #endif | ||
| 3962 | |||
| 3963 | return; | ||
| 3964 | } /* end delete */ | ||
| 3965 | /*************************************************/ | ||
| 3966 | long disk_free_space() | ||
| 3967 | { | ||
| 3968 | struct FSAllocate fsa; | ||
| 3969 | |||
| 3970 | #if defined(DEBUG) | ||
| 3971 | printf("\nDOSQFSINFO (0=def) DRIVE=%04Xh...",tgt_drive_letter-'A'+1); | ||
| 3972 | #endif | ||
| 3973 | |||
| 3974 | rc = | ||
| 3975 | DOSQFSINFO | ||
| 3976 | ( | ||
| 3977 | (WORD)tgt_drive_letter - 'A' + 1, /* Drive 0=def, 1=a... */ | ||
| 3978 | (WORD)1, /* Level */ | ||
| 3979 | (char far *)&fsa, /* Return info */ | ||
| 3980 | (WORD)(sizeof(struct FSAllocate)) /* Size of return info buffer */ | ||
| 3981 | ); | ||
| 3982 | |||
| 3983 | #if defined(DEBUG) | ||
| 3984 | if (rc == NOERROR) | ||
| 3985 | printf("SUCCESSFUL, FREESPACE=%08lXh",fsa.sec_per_unit * fsa.avail_units * fsa.bytes_sec); | ||
| 3986 | else | ||
| 3987 | printf("ERROR, RC=%04Xh",rc); | ||
| 3988 | #endif | ||
| 3989 | |||
| 3990 | return((DWORD)(fsa.sec_per_unit * fsa.avail_units * fsa.bytes_sec)); | ||
| 3991 | } | ||
| 3992 | /*************************************************/ | ||
| 3993 | void replace_volume_label(label_addr) | ||
| 3994 | char *label_addr; | ||
| 3995 | { | ||
| 3996 | #if defined(DEBUG) | ||
| 3997 | printf("\nDOSSETFSINFO (0=def) DRIVE=%04Xh, LEN=%04Xh...",tgt_drive_letter-'A'+1,label_addr[0]); | ||
| 3998 | #endif | ||
| 3999 | |||
| 4000 | rc = DOSSETFSINFO | ||
| 4001 | ( | ||
| 4002 | (WORD)tgt_drive_letter-'A'+1, /* Drive 0=def, 1=a... */ | ||
| 4003 | (WORD)2, /* Level */ | ||
| 4004 | (char far *)label_addr, /* Buffer */ | ||
| 4005 | (WORD)LABELLEN+1 /* Buffer size */ | ||
| 4006 | ); | ||
| 4007 | |||
| 4008 | #if defined(DEBUG) | ||
| 4009 | if (rc == NOERROR) | ||
| 4010 | printf("SUCCESSFUL"); | ||
| 4011 | else | ||
| 4012 | printf("ERROR, RC=%04Xh",rc); | ||
| 4013 | #endif | ||
| 4014 | |||
| 4015 | return; | ||
| 4016 | } /* end replace_volume_label */ | ||
| 4017 | |||
| 4018 | /*************************************************/ | ||
| 4019 | #define TERMINATE 0x4C00 | ||
| 4020 | void terminate() /* Terminate process, return errorlevel to DOS */ | ||
| 4021 | { | ||
| 4022 | |||
| 4023 | if (append_indicator == DOS_APPEND) /*;AN000;2 If append /x was reset*/ | ||
| 4024 | { /*;AN000;2*/ | ||
| 4025 | #if defined(DEBUG) | ||
| 4026 | printf("\nINT2Fh,(SET APPEND) AX=%04Xh TO %04Xh...",SET_STATE,original_append_func); | ||
| 4027 | #endif | ||
| 4028 | inregs.x.ax = SET_STATE; /*;AN000;2*/ | ||
| 4029 | inregs.x.bx = original_append_func; /*;AN000;2*/ | ||
| 4030 | int86(0x2f,&inregs,&outregs); /*;AN000;2*/ | ||
| 4031 | } /*;AN000;2*/ | ||
| 4032 | |||
| 4033 | exit(return_code); /*;AN000;p972*/ | ||
| 4034 | |||
| 4035 | return; | ||
| 4036 | } /* end terminate */ | ||
| 4037 | /*************************************************/ | ||
| 4038 | WORD ioctl(devhandle) | ||
| 4039 | WORD devhandle; | ||
| 4040 | { | ||
| 4041 | #define ISDEVREMOVABL 0x20 | ||
| 4042 | #define CATEGORY 8 /*1=serial,3=display,5=printer,8=disk*/ | ||
| 4043 | |||
| 4044 | BYTE data_area; | ||
| 4045 | |||
| 4046 | #if defined(DEBUG) | ||
| 4047 | printf("\nDOSDEVIOCTL HANDLE=%04Xh...",devhandle); | ||
| 4048 | #endif | ||
| 4049 | |||
| 4050 | rc = | ||
| 4051 | DOSDEVIOCTL | ||
| 4052 | ( | ||
| 4053 | (char far *)&data_area, /* Data Area */ | ||
| 4054 | (char far *)&data_area, /* Parameter list */ | ||
| 4055 | (WORD)ISDEVREMOVABL, /* Device Function = 20 hex */ | ||
| 4056 | (WORD)CATEGORY, /* Device Category = 8 hex */ | ||
| 4057 | (WORD)devhandle /* Device Handle */ | ||
| 4058 | ); | ||
| 4059 | |||
| 4060 | #if defined(DEBUG) | ||
| 4061 | if (rc == NOERROR) | ||
| 4062 | printf("SUCCESSFUL, DATA_AREA(0=REMOVABLE) SET TO %02Xh",data_area); | ||
| 4063 | else | ||
| 4064 | printf("ERROR, RC=%04Xh",rc); | ||
| 4065 | #endif | ||
| 4066 | |||
| 4067 | return(data_area); | ||
| 4068 | } /* end IOCTL */ | ||
| 4069 | |||
| 4070 | /*************************************************/ | ||
| 4071 | void alloc_seg() | ||
| 4072 | { | ||
| 4073 | #if defined(DEBUG) | ||
| 4074 | printf("\nDOSALLOCSEG SIZE=%04Xh...",data_file_alloc_size); | ||
| 4075 | #endif | ||
| 4076 | |||
| 4077 | rc = | ||
| 4078 | DOSALLOCSEG | ||
| 4079 | ( | ||
| 4080 | (WORD)data_file_alloc_size, /* Bytes to allocate */ | ||
| 4081 | (unsigned far *)&selector, /* Address of selector */ | ||
| 4082 | (WORD)0 /* Share indicator, sez DON'T SHARE */ | ||
| 4083 | ); | ||
| 4084 | |||
| 4085 | #if defined(DEBUG) | ||
| 4086 | if (rc == NOERROR) | ||
| 4087 | printf("SUCCESSFUL, SELECTOR=%04Xh, SIZE=%04Xh",selector,data_file_alloc_size); | ||
| 4088 | else | ||
| 4089 | printf("ERROR, RC=%04Xh",rc); | ||
| 4090 | #endif | ||
| 4091 | |||
| 4092 | return; | ||
| 4093 | } | ||
| 4094 | |||
| 4095 | /*************************************************/ | ||
| 4096 | void free_seg(selector) | ||
| 4097 | unsigned selector; | ||
| 4098 | { | ||
| 4099 | #if defined(DEBUG) | ||
| 4100 | printf("\nDOSFREESEG (%04Xh)...",selector); | ||
| 4101 | #endif | ||
| 4102 | |||
| 4103 | rc = DOSFREESEG(selector); /* Address of selector */ | ||
| 4104 | |||
| 4105 | #if defined(DEBUG) | ||
| 4106 | if (rc == NOERROR) | ||
| 4107 | printf("SUCCESSFUL"); | ||
| 4108 | else | ||
| 4109 | printf("ERROR, RC=%04Xh",rc); | ||
| 4110 | #endif | ||
| 4111 | |||
| 4112 | return; | ||
| 4113 | } | ||
| 4114 | |||
| 4115 | /*************************************************/ | ||
| 4116 | void setsignal(action,signum) | ||
| 4117 | WORD action; | ||
| 4118 | WORD signum; | ||
| 4119 | { | ||
| 4120 | DWORD old_sig_handler; | ||
| 4121 | WORD old_sig_action; | ||
| 4122 | |||
| 4123 | #if defined(DEBUG) | ||
| 4124 | printf("\nDOSSETSIGHANDLER ACTION=%04Xh,SIGNUM=%04Xh...",action,signum); | ||
| 4125 | #endif | ||
| 4126 | |||
| 4127 | rc = | ||
| 4128 | DOSSETSIGHANDLER | ||
| 4129 | ( | ||
| 4130 | (void far *)control_break_handler, /* Signal handler address */ | ||
| 4131 | (DWORD far *)&old_sig_handler, /* Address of previous handler */ | ||
| 4132 | (unsigned far *)&old_sig_action, /* Address of previous action */ | ||
| 4133 | action, /* Indicate request type (2=hook) */ | ||
| 4134 | signum /* Signal number */ | ||
| 4135 | ); | ||
| 4136 | |||
| 4137 | #if defined(DEBUG) | ||
| 4138 | if (rc == NOERROR) | ||
| 4139 | printf("SUCCESSFUL"); | ||
| 4140 | else | ||
| 4141 | printf("ERROR, RC=%04Xh",rc); | ||
| 4142 | #endif | ||
| 4143 | |||
| 4144 | return; | ||
| 4145 | } /* end setsignal */ | ||
| 4146 | |||
| 4147 | /*************************************************/ | ||
| 4148 | void do_dos_error(flag) | ||
| 4149 | WORD flag; | ||
| 4150 | { | ||
| 4151 | #if defined(DEBUG) | ||
| 4152 | printf("\nDOSERROR, FLAG=%04Xh...",flag); | ||
| 4153 | #endif | ||
| 4154 | |||
| 4155 | rc = DOSERROR(flag); | ||
| 4156 | |||
| 4157 | #if defined(DEBUG) | ||
| 4158 | if (rc == NOERROR) | ||
| 4159 | printf("SUCCESSFUL"); | ||
| 4160 | else | ||
| 4161 | printf("ERROR, RC=%04Xh",rc); | ||
| 4162 | #endif | ||
| 4163 | |||
| 4164 | return; | ||
| 4165 | } | ||
| 4166 | /*************************************************/ | ||
| 4167 | void get_country_info() | ||
| 4168 | { | ||
| 4169 | #define USACOUNTRY 1 | ||
| 4170 | #define DEFAULT_COUNTRY 0 | ||
| 4171 | #define DEFAULT_CODEPAGE 0 | ||
| 4172 | |||
| 4173 | struct ctry_info_blk buff; | ||
| 4174 | struct countrycode ctrystuff; /* Added for CPDOS 1.1 */ | ||
| 4175 | WORD data_len; | ||
| 4176 | |||
| 4177 | ctrystuff.country = (WORD)DEFAULT_COUNTRY; | ||
| 4178 | ctrystuff.codepage= (WORD)DEFAULT_CODEPAGE; | ||
| 4179 | |||
| 4180 | #if defined(DEBUG) | ||
| 4181 | printf("\nDOSGETCTRYINFO COUNTRY=%04Xh...",ctrystuff.country); | ||
| 4182 | #endif | ||
| 4183 | |||
| 4184 | rc = | ||
| 4185 | DOSGETCTRYINFO | ||
| 4186 | ( | ||
| 4187 | (unsigned)sizeof(struct ctry_info_blk), /* Length of return area */ | ||
| 4188 | (struct countrycode far *)&ctrystuff, /* Country Code */ | ||
| 4189 | (char far *)&buff, /* Return area */ | ||
| 4190 | (unsigned far *)&data_len /* Len of returned area */ | ||
| 4191 | ); | ||
| 4192 | |||
| 4193 | #if defined(DEBUG) | ||
| 4194 | if (rc == NOERROR) | ||
| 4195 | printf("SUCCESSFUL"); | ||
| 4196 | else | ||
| 4197 | printf("ERROR, RC=%04Xh",rc); | ||
| 4198 | #endif | ||
| 4199 | |||
| 4200 | if (rc == NOERROR) | ||
| 4201 | { | ||
| 4202 | ctry_date_fmt = buff.date_format; | ||
| 4203 | ctry_time_fmt = buff.time_format; | ||
| 4204 | ctry_date_sep = buff.date_separator; | ||
| 4205 | ctry_time_sep = buff.time_separator; | ||
| 4206 | #if defined(DEBUG) | ||
| 4207 | printf("\nDATE SEPERATOR=%c",ctry_date_sep); | ||
| 4208 | printf("\nTIME SEPERATOR=%c",ctry_time_sep); | ||
| 4209 | printf("\nDATE FORMAT=%u",ctry_date_fmt); | ||
| 4210 | printf("\nTIME FORMAT=%u",ctry_time_fmt); | ||
| 4211 | #endif | ||
| 4212 | } | ||
| 4213 | |||
| 4214 | |||
| 4215 | return; | ||
| 4216 | } /* end get_country_info */ | ||
| 4217 | |||
| 4218 | /*************************************************/ | ||
| 4219 | void datetime() /* Put date and time in logfile */ | ||
| 4220 | { | ||
| 4221 | struct DateTime buff; | ||
| 4222 | char date[12]; | ||
| 4223 | char time[12]; | ||
| 4224 | char datetimestring[25]; | ||
| 4225 | WORD written = 0; | ||
| 4226 | |||
| 4227 | #if defined(DEBUG) | ||
| 4228 | printf("\nDOSGETDATETIME..."); | ||
| 4229 | #endif | ||
| 4230 | |||
| 4231 | rc = DOSGETDATETIME((struct DateTime far *)&buff); | ||
| 4232 | |||
| 4233 | #if defined(DEBUG) | ||
| 4234 | if (rc == NOERROR) | ||
| 4235 | printf("SUCCESSFUL"); | ||
| 4236 | else | ||
| 4237 | printf("ERROR, RC=%04Xh",rc); | ||
| 4238 | #endif | ||
| 4239 | |||
| 4240 | /* Build time string */ | ||
| 4241 | sprintf(time,"%u%c%02u%c%02u",buff.hour,ctry_time_sep,buff.minutes,ctry_time_sep,buff.seconds); | ||
| 4242 | |||
| 4243 | /* Build date string */ | ||
| 4244 | switch (ctry_date_fmt) | ||
| 4245 | { | ||
| 4246 | case USA: | ||
| 4247 | sprintf(date,"%u%c%02u%c%04u",buff.month,ctry_date_sep,buff.day,ctry_date_sep,buff.year); | ||
| 4248 | break; | ||
| 4249 | |||
| 4250 | case EUR: | ||
| 4251 | sprintf(date,"%u%c%02u%c%04u",buff.day,ctry_date_sep,buff.month,ctry_date_sep,buff.year); | ||
| 4252 | break; | ||
| 4253 | |||
| 4254 | case JAP: | ||
| 4255 | sprintf(date,"%04u%c%02u%c%02u",buff.year,ctry_date_sep,buff.month,ctry_date_sep,buff.day); | ||
| 4256 | break; | ||
| 4257 | |||
| 4258 | default: | ||
| 4259 | break; | ||
| 4260 | } | ||
| 4261 | |||
| 4262 | datetimestring[0] = 0x0d; | ||
| 4263 | datetimestring[1] = 0x0a; | ||
| 4264 | sprintf(datetimestring+2,"%s %s",date,time); | ||
| 4265 | |||
| 4266 | written = handle_write(handle_logfile,strlen(datetimestring),(char far *)&datetimestring[0]); | ||
| 4267 | if (written != strlen(datetimestring) || (rc != NOERROR) ) | ||
| 4268 | { | ||
| 4269 | display_msg(LOGFILE_TARGET_FULL); | ||
| 4270 | /* wait_for_keystroke(); */ | ||
| 4271 | do_logfile = FALSE; | ||
| 4272 | } | ||
| 4273 | |||
| 4274 | return; | ||
| 4275 | } /* end datetime */ | ||
| 4276 | |||
| 4277 | |||
| 4278 | |||
| 4279 | |||
| 4280 | |||
| 4281 | |||
| 4282 | |||
| 4283 | |||
| 4284 | |||
| 4285 | |||
| 4286 | |||
| 4287 | |||
| 4288 | /*************************************************/ | ||
| 4289 | /*void get_extended_attributes(handle) /*;AN000;3*/ | ||
| 4290 | /*WORD handle; /*;AN000;3*/ | ||
| 4291 | /*{ /*;AN000;3*/ | ||
| 4292 | /*#if defined(DEBUG) | ||
| 4293 | /* printf("\nGET EXTENDED ATTRIBUTE LENGTH..."); | ||
| 4294 | /*#endif | ||
| 4295 | /* ext_attrib_flg = TRUE; /*Assume ext attrib exist*/ /*;AN000;3*/ | ||
| 4296 | /* | ||
| 4297 | /* /* GET EXTENDED ATTRIBUTE LENGTH */ | ||
| 4298 | /* inregs.x.ax = 0x5702; /*;AN000;3*/ | ||
| 4299 | /* inregs.x.bx = handle; /*;AN000;3*/ | ||
| 4300 | /* inregs.x.cx = 0; /*;AN000;3*/ | ||
| 4301 | /* inregs.x.si = 0xffff; /*;AN000;3*/ | ||
| 4302 | /* intdos(&inregs,&outregs); /*;AN000;3*/ | ||
| 4303 | /* | ||
| 4304 | /*#if defined(DEBUG) | ||
| 4305 | /* if (outregs.x.cflag & CARRY) | ||
| 4306 | /* printf("ERROR, RC=%04Xh",outregs.x.ax); | ||
| 4307 | /* else | ||
| 4308 | /* printf("SUCCESSFUL, LEN=%04Xh",outregs.x.cx); | ||
| 4309 | /*#endif | ||
| 4310 | /* | ||
| 4311 | /* if (!(outregs.x.cflag & CARRY)) /*;AN000;3*/ | ||
| 4312 | /* ext_attrib_len = outregs.x.cx; /*;AN000;3*/ | ||
| 4313 | /* else /*;AN000;3*/ | ||
| 4314 | /* ext_attrib_flg = FALSE; /*;AN000;3 Set flag indicating no extended attributes*/ | ||
| 4315 | /* | ||
| 4316 | /* | ||
| 4317 | /*#if defined(DEBUG) | ||
| 4318 | /* printf("\nGET EXTENDED ATTRIBUTES..."); | ||
| 4319 | /*#endif | ||
| 4320 | /* | ||
| 4321 | /* /* GET EXTENDED ATTRIBUTES */ | ||
| 4322 | /* if (ext_attrib_flg) | ||
| 4323 | /* { /*;AN000;3*/ | ||
| 4324 | /* inregs.x.ax = 0x5702; /*;AN000;3*/ | ||
| 4325 | /* inregs.x.bx = handle; /*;AN000;3*/ | ||
| 4326 | /* inregs.x.cx = outregs.x.cx; /*;AN000;3*/ | ||
| 4327 | /* inregs.x.di = (unsigned)&ext_attrib_buff[0]; /*;AN000;3*/ | ||
| 4328 | /* inregs.x.si = 0xffff; /*;AN000;3*/ | ||
| 4329 | /* intdos(&inregs,&outregs); /*;AN000;3*/ | ||
| 4330 | /* | ||
| 4331 | /* if (outregs.x.cflag & CARRY) /*;AN000;3*/ | ||
| 4332 | /* ext_attrib_flg = FALSE; /*;AN000;3*/ | ||
| 4333 | /* | ||
| 4334 | /*#if defined(DEBUG) | ||
| 4335 | /* if (outregs.x.cflag & CARRY) | ||
| 4336 | /* printf("ERROR, RC=%04Xh",outregs.x.ax); | ||
| 4337 | /* else | ||
| 4338 | /* printf("SUCCESSFUL"); | ||
| 4339 | /*#endif | ||
| 4340 | /* } | ||
| 4341 | /* | ||
| 4342 | /* return; /*;AN000;3*/ | ||
| 4343 | /*} /* end get_extended_attributes */ /*;AN000;3*/ | ||
| 4344 | /**************************************************/ | ||
| 4345 | #define EXTENDEDOPEN 0x6c00 /*;AN000;3*/ | ||
| 4346 | |||
| 4347 | WORD extended_open(flag,attr,path_addr,mode) /*;AN000;3*/ | ||
| 4348 | WORD flag; /*;AN000;3*/ | ||
| 4349 | WORD attr; /*;AN000;3*/ | ||
| 4350 | char far *path_addr; /*;AN000;3*/ | ||
| 4351 | WORD mode; /*;AN000;3*/ | ||
| 4352 | { /*;AN000;3*/ | ||
| 4353 | union REGS inreg,outreg; /*;AN000;3*/ | ||
| 4354 | |||
| 4355 | ea_parmlist.ext_attr_addr = (DWORD)(char far *)&ext_attrib_buff[0];/*;AN000;3*/ | ||
| 4356 | ea_parmlist.num_additional = 0; /*;AN000;3*/ | ||
| 4357 | |||
| 4358 | #if defined(DEBUG) | ||
| 4359 | if (flag == CREATE_IT) printf("\nEXTENDED OPEN - CREATE, FILE %s...",path_addr); | ||
| 4360 | else printf("\nEXTENDED OPEN - OPEN, FILE %s...",path_addr); | ||
| 4361 | #endif | ||
| 4362 | |||
| 4363 | rc = NOERROR; /*;AN000;3*/ | ||
| 4364 | inreg.x.ax = EXTENDEDOPEN; /*;AN000;3*/ | ||
| 4365 | inreg.x.bx = mode + NO_INHERIT; /*;AN000;3*/ | ||
| 4366 | inreg.x.cx = attr; /*;AN000;3*/ | ||
| 4367 | inreg.x.dx = flag + NO_CP_CHECK; /*;AN000;3*/ | ||
| 4368 | inreg.x.si = (WORD)path_addr; /*;AN000;3*/ | ||
| 4369 | |||
| 4370 | inreg.x.di = (WORD)&ea_parmlist; /*;AN000;3*/ | ||
| 4371 | |||
| 4372 | intdos(&inreg,&outreg); /*;AN000;3*/ | ||
| 4373 | if (outreg.x.cflag & CARRY) /* If there was an error /*;AN000;3*/ | ||
| 4374 | rc = outreg.x.ax; /* then set return code /*;AN000;3*/ | ||
| 4375 | |||
| 4376 | #if defined(DEBUG) | ||
| 4377 | if (outreg.x.cflag & CARRY) | ||
| 4378 | printf("ERROR, RC=%04Xh",outreg.x.ax); | ||
| 4379 | else | ||
| 4380 | printf("SUCCESSFUL, HANDLE=%04Xh",outreg.x.ax); | ||
| 4381 | #endif | ||
| 4382 | |||
| 4383 | return(outreg.x.ax); /*;AN000;3*/ | ||
| 4384 | } /* end extended_open */ /*;AN000;3*/ | ||
| 4385 | \ No newline at end of file | ||