3 /************************************************************
5 /* UTILITY NAME: BACKUP.COM
7 /* SOURCE FILE NAME: BACKUP.C
10 /* DOS Backup Utility Program
12 /* STATUS: BACKUP utility, DOS Version 4.00
13 /* Written using the C programming language.
16 /* COMPILER/LINKER INVOCATION:
18 /* cc /AS /Os /Zep /W3 /DLINT_ARGS /UDEBUG backup.c;
19 /* link backup,,,mapper+comsubs
21 /* Note: You MUST(!) use the PACKED option (/Zp) to make sure data structures
22 /* are not aligned !!!
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
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.
42 /* BACKUP [d:][path] filename [.ext]] d: [/S] [/F[:size]]
43 /* [/L[:fn]] [/M] [/A] [T:hh:mm:ss] [/D:mm-dd-yy]
45 /* [/F[:size]] undocumented
49 /* New for DOS 3.3 and OS/2
51 /* Modification History:
53 /* ;AN000; Code added in DOS 4.0
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
75 /* ;AN010; Don't find FORMAT.COM on target drive
76 /* ;AN011; Make BACKUP handle disk full properly on fixed disk
77 /*****************************************************************
79 /* "C" supplied include files */
82 #include <direct.h> /*;AN000;*/
85 #include <stdlib.h> /*;AN000;d178*/
87 #include <doscalls.h> /* OS/2 Include file */
89 #include "backup.h" /* BACKUP structures, defines, ...*/
90 #include "backpars.h" /* DEFINEs and STRUCTs for the DOS Parse service routines */
92 #include <version.h> /* symbol defns to determine degree of compatibility */
94 /**********************************/
96 /**********************************/
97 WORD rc; /* Return code from DOS calls */
99 unsigned selector; /* Kinda like a segment address */
101 struct node *curr_node; /* Pointer to "node" structure for the */
102 /* directory currently being processed */
104 struct node *last_child; /* Pointer to "node" structure for the */
105 /* last directory discovered in the */
106 /* directory currently being processed */
108 struct subst_list sublist; /*;AN000;6 Message substitution list */
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 */
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*/
128 DWORD noval = 0; /*;AN000;4 Value list for PARSR */
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 */
134 /**********************************/
136 /**********************************/
137 WORD dirhandle; /* Dirhandle field, for Find First, Find Next */
138 BYTE dirhandles_open = FALSE; /* Flag indicating at least 1 open dirhandle */
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 */
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 */
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 */
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" */
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 */
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 */
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 */
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 */
188 BYTE source_removable; /* Indicates if the source drive is removable */
189 BYTE target_removable; /* Indicates if the target drive is removable */
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 */
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*/
209 /**********************************/
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 */
215 /**********************************/
217 /**********************************/
218 BYTE span_seq_num; /* Counter indicating which part of a spanning file is on current target */
220 WORD data_file_alloc_size = 0xffff; /* Number of paragraphs to initially try to allocate for data file */
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 */
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 */
233 BYTE return_code = RETCODE_NO_ERROR; /* Save area for DOS ErrorLevel */
235 /**
\f***********************************************/
237 /* SUBROUTINE NAME: main
241 /* Backs up files from source to target drive
243 /***************************************************/
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 */
267 /**
\f***********************************************/
269 /* SUBROUTINE NAME: init
274 /* Mundane initializization of data structures
276 /**************************************************/
277 void init() /*;AN000;6*/
280 /**********************************/
281 /** PRELOAD MESSAGES **/
282 /**********************************/
283 sysloadmsg(&inregs,&outregs); /*;AN000;6 Preload messages, check DOS version */
285 if (outregs.x.cflag & CARRY) /*;AN000;6 If there was an error */
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 */
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*/
302 ext_attrib_buff[0] = 0; /*;AN000;3*/
303 ext_attrib_buff[1] = 0; /*;AN000;3*/
305 date_buff.month = 0; /*;AN000;3*/
306 date_buff.day = 0; /*;AN000;3*/
307 date_buff.year = 0; /*;AN000;3*/
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*/
314 dta_addr = (struct FileFindBuf *)&dta; /* Get address of FindFile buffer */
320 /**
\f***********************************************/
322 /* SUBROUTINE NAME: parser
326 /* Parse the command line
328 /**************************************************/
329 void parser(argc,argv) /*;AN000;4*/
330 int argc; /*;AN000;4*/
331 char *argv[]; /*;AN000;4*/
333 char cmd_line[128]; /*;AN000;4*/
334 char not_finished = TRUE; /*;AN000;4*/
337 parse_init(); /* Initialize parser data structures*//*;AN000;4*/
339 /* Copy command line parameters to local area */
340 cmd_line[0] = NUL; /*;AN000;4*/
341 for (x=1; x<=argc; x++) /*;AN000;4*/
343 strcat(cmd_line,argv[x]); /*;AN000;4*/
344 if (x != argc) strcat(cmd_line," "); /*;AN000;4*/
347 strcat(cmd_line,"\r"); /*;AN004;*/
349 inregs.x.si = (WORD)&cmd_line[0]; /*DS:SI points to cmd line*//*;AN000;4*/
353 while (not_finished) /*;AN000;4 For all strings in command line */
355 inregs.x.dx = 0; /*;AN000;4 RESERVED */
356 inregs.x.di = (WORD)&parms; /*ES:DI*/ /*;AN000;4 address of parm list */
358 parse(&inregs,&outregs); /*;AN000;4 Call DOS SYSPARSE service routines*/
360 x=0; /* Save the parsed parameter */ /*;AN009;*/
361 for (inregs.x.si; inregs.x.si<outregs.x.si; inregs.x.si++) /*;AN009;*/
363 curr_parm[x] = *(char *)inregs.x.si; /*;AN009;*/
367 curr_parm[x] = NUL; /*;AN009;*/
369 inregs = outregs; /*;AN000;4 Reset registers*/
371 if (outregs.x.ax!=(WORD)NOERROR) /*;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*/
378 if (not_finished) /*;AN000;4 If there was not an error*/
380 if (outregs.x.dx == (WORD)&sw_buff) /*;AN000;4*/
381 process_switch(); /*;AN000;4 Its a switch*//*;AN008;*/
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;*/
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 */
393 if (outregs.x.dx == (WORD)&date_buff) /*;AN000;4*/
395 if (do_date) /*;AN000;4*/
396 parse_error(outregs.x.ax,outregs.x.dx); /*;AN000;4*//*;AN008;*/
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 */
402 } /* end not_finished */ /*;AN000;4*/
404 } /* end WHILE */ /*;AN000;4*/
406 if (strlen(argv[1]) >= 5) /*;AN000;p2592*/
407 check_for_device_names(argv); /*;AN000;p2592*/
409 return; /*;AN000;4 Return to caller*/
410 } /* end parser */ /*;AN000;4*/
411 /**
\f***********************************************/
413 /* SUBROUTINE NAME: parse_error
417 /* There was a parse error. Display appropriate
418 /* error message and terminate.
420 /**************************************************/
421 void parse_error(ax,dx) /*;AN000;4*/
422 WORD ax; /*;AN000;4*/
423 WORD dx; /*;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;*/
432 if (dx == (WORD)&time_buff) /*;AN000;4*/
433 display_it(INV_TIME,STDERR,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;4*/
435 if (dx == (WORD)&date_buff) /*;AN000;4*/
436 display_it(INV_DATE,STDERR,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;4*/
438 display_it (ax,STDERR,1,NOWAIT,(BYTE)PARSEERROR); /*;AN000;6*/
440 return_code = RETCODE_ERROR; /*;AN000;4*/
441 clean_up_and_exit(); /*;AN000;4*/
444 } /* end parse_error */ /*;AN000;4*/
446 /**
\f***********************************************/
448 /* SUBROUTINE NAME: check_date
452 /* A date parameter was entered. Validate it
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*/
460 if (year > 2099 || year < 1980) /*;AC000;4*/
461 error_exit(INV_DATE); /*;AC000;4*/
463 if (month > 12 || month < 1) /*;AC000;4*/
464 error_exit(INV_DATE); /*;AC000;4*/
466 if (day > 31 || day < 1) /*;AC000;4*/
467 error_exit(INV_DATE); /*;AC000;4*/
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*/
473 if (month == 2) /* Deal with February */ /*;AC000;4*/
475 if (day > 29) /* if Feb 30 or above */ /*;AC000;4*/
476 error_exit(INV_DATE); /* then Bad Date */ /*;AC000;4*/
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*/
483 do_date = TRUE; /*;AN000;4*/
486 } /* end check_date */ /*;AN000;4*/
488 /**
\f***********************************************/
490 /* SUBROUTINE NAME: check_time
494 /* A time parameter was entered. Validate it
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*/
503 if (hours > 23 || hours < 0) /*;AC000;4*/
504 error_exit(INV_TIME); /*;AC000;4*/
506 if (minutes >= 60 || minutes < 0) /*;AC000;4*/
507 error_exit(INV_TIME); /*;AC000;4*/
509 if (seconds >= 60 || seconds < 0) /*;AC000;4*/
510 error_exit(INV_TIME); /*;AC000;4*/
512 if (hundreds > 99 || hundreds < 0) /*;AC000;4*/
513 error_exit(INV_TIME); /*;AC000;4*/
515 do_time = TRUE; /*;AN000;4*/
518 } /* end check_time */ /*;AN000;4*/
520 /**
\f***********************************************/
522 /* SUBROUTINE NAME: parse_init
526 /* Initialize the parser data structures
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 */
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*/
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*/
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*/
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*/
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*/
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*/
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*/
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*/
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*/
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*/
670 /**
\f***********************************************/
672 /* SUBROUTINE NAME: find_format
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.
680 /***************************************************/
681 void find_format() /*;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;*/
689 /*******************************/
690 /* First try current directory */
691 format_path[0] = '.'; /*;AN000;d178*/
692 format_path[1] = NUL; /*;AN000;d178*/
694 /* Build full path */
695 xlat(format_path,format_path); /*;AN000;d178*/
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*/
701 strcat(format_path,"\\FORMAT.COM"); /*;AN000;d178*/
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;*/
708 if (exist(format_path)) /*;AN000;d178*/
709 found_it = TRUE; /*;AN000;d178*/
712 get_path(path); /*;AN002;*/
714 if (strlen(path)==0 || path[0]==NUL) /*;AN002;*/
715 error_exit(CANT_FIND_FORMAT); /*;AN002;*/
719 while (!found_it && path[pindex] != NUL)
721 for (findex=0; path[pindex]!=NUL && path[pindex]!=';'; pindex++) /*;AN002;*/
723 format_path[findex] = path[pindex]; /*;AN002;*/
724 findex++; /*;AN002;*/
727 if (path[pindex]==';')
730 format_path[findex] = NUL; /*;AN002;*/
732 xlat(format_path,format_path); /*;AN002;*/
734 if (strlen(format_path)==3 && format_path[1]==':') /*;AN000;p1900*/
735 format_path[2] = NUL; /*;AN000;p1900*/
737 strcat(format_path,"\\FORMAT.COM"); /*;AN000;d178*/
739 if (format_path[0] == tgt_drive_letter) /*;AN010;*/
740 if (target_removable) /*;AN010;*/
741 format_path[0] = NUL; /*;AN010;*/
743 if (exist(format_path)) /*;AN000;d178*/
744 found_it = TRUE; /*;AN000;d178*/
747 if (!found_it) /*;AN000;d178*/
748 error_exit(CANT_FIND_FORMAT); /*;AN000;d178*/
750 return; /*;AN000;d178*/
752 /**
\f***********************************************/
754 /* SUBROUTINE NAME: get_path
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.
761 /***************************************************/
762 void get_path(p) /*;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;*/
773 xregs.x.ax = 0x6200; /* Get PSP Address */ /*;AN002;*/
774 intdos(&xregs,&xregs); /* Returned in BX */ /*;AN002;*/
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;*/
782 /* Search for PATH in the environment */
783 while (!done) /*;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;*/
793 done = TRUE; /*;AN002;*/
794 got_path = TRUE; /*;AN002;*/
797 if (*env_ptr == NUL && *(env_ptr+1) == NUL) /*;AN002;*/
798 done = TRUE; /*;AN002;*/
800 if (!done) /*;AN002;*/
801 env_ptr++; /*;AN002;*/
804 /* Copy path to desired buffer */
805 if (got_path) /*;AN002;*/
807 env_ptr += 5; /* Skip over "PATH=" */ /*;AN002;*/
808 for (; *env_ptr!=NUL; env_ptr++) /*;AN002;*/
810 *p = *env_ptr; /*;AN002;*/
814 *p = NUL; /*;AN002;*/
820 /**
\f***********************************************/
822 /* SUBROUTINE NAME: xlat
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".
830 /***************************************************/
831 void xlat(tgt,src) /*;AN000;*/
832 char * tgt; /*;AN000;*/
833 char * src; /*;AN000;*/
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;*/
845 /**
\f***********************************************/
847 /* SUBROUTINE NAME: check_drive_validity
851 /* Verify that at least the target drive letter is
852 /* is entered. Verify that they are valid drives.
854 /***************************************************/
855 void check_drive_validity(argc,argv)
861 BYTE specified_drive;
864 error_exit(NO_SOURCE);
866 /*********************/
867 /* Verify the source */
868 /*********************/
869 *argv[1] = (BYTE)com_toupper(*argv[1]);
874 if (*t == ':') /* Check specified source drive */ /*;AC000;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*/
885 /*********************/
886 /* Verify the target */
887 /*********************/
889 error_exit(NO_TARGET);
891 *argv[2] = (BYTE)com_toupper(*argv[2]);
894 error_exit(INV_DRIVE);
896 error_exit(INV_DRIVE);
898 /* Verify drive letter followed by ":" */
902 error_exit(NO_TARGET);
904 /* Make sure drive letters are different */
905 if (src_drive_letter == *argv[2]) /*;AN000;p2671*/
906 error_exit(SRC_AND_TGT_SAME);
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);
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);
920 set_default_drive(def_drive); /* Reset default drive to original one */
921 def_drive_set = FALSE;
923 tgt_drive_letter = *argv[2];
926 } /* end check_drive_validity */
928 /**
\f***********************************************/
930 /* SUBROUTINE NAME: check_for_device_names
934 /* Make sure user not trying to restore a reserved device name
936 /**************************************************/
937 #define INVPARM 10 /*;AN000;4*/
938 void check_for_device_names(argv) /*;AN000;p2592*/
939 char *argv[]; /*;AN000;p2592*/
941 union REGS qregs; /*;AN000;p2592*/
942 char target[128]; /*;AN000;p2592*/
943 char *t; /*;AN000;p2592*/
945 #define CAPITALIZE_STRING 0x6521 /*;AN000;p2592*/
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*/
954 for (t=&target[0]; *t!=NUL; t++)
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*/
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*/
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*/
982 return; /*;AN000;p2592*/
986 /**
\f***********************************************/
988 /* SUBROUTINE NAME: check_path_validity
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
997 /***************************************************/
998 void check_path_validity(argv)
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*/
1009 strcpy(src_drive_path_fn,argv[1]); /* Copy argv[1] to string area */
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*/
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,"*.*");
1020 if (src_drive_path_fn[strlen(src_drive_path_fn)-1] == BACKSLASH)/*;AN000;p2671*/
1021 strcat(src_drive_path_fn,"*.*"); /*;AN000;p2671*/
1023 xlat(src_drive_path_fn,src_drive_path_fn); /*;AN000;p2671*/
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;*/
1029 foo = strchr(src_drive_path_fn+3,BACKSLASH); /*;AN003;*/
1030 if (foo == NUL) /*;AN003;*/
1031 error_exit(INV_PATH); /*;AN003;*/
1033 foo2 = foo + 1; /*;AN003;*/
1034 foo = strchr(foo2,BACKSLASH); /*;AN003;*/
1035 if (foo == NUL) /*;AN003;*/
1036 error_exit(INV_PATH); /*;AN003;*/
1038 sprintf(src_drive_path_fn,"%c:%s",src_drive_letter,foo); /*;AN003;*/
1041 /* See if there are global characters specified */
1042 if (com_strchr(src_drive_path_fn,'?') != NUL)
1045 if (com_strchr(src_drive_path_fn,'*') != NUL)
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);
1053 if (source_removable) /* If backing up from a diskette */
1055 display_msg(INSERTSOURCE); /* Ask user for diskette and wait for input*/
1056 /*wait_for_keystroke(); /* Let user "Strike any key when ready" */
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*/
1066 find_first /* Check for Invalid Path */
1067 ( /* Also figure out if it is file or directory */
1068 &src_drive_path_fn[0],
1071 (SUBDIR + SYSTEM + HIDDEN)
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 */
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,"\\*.*");
1087 /************************/
1088 /* Build src_drive_FN **/
1089 strcpy(src_drive_path,src_drive_path_fn);
1091 /* Remove last BACKSLASH to get the pathname */
1092 foo = com_strrchr(src_drive_path,BACKSLASH);
1095 if ((foo - src_drive_path) > 2)
1098 { /* foo must = 2 */
1103 /************************/
1105 foo = com_strrchr(src_drive_path_fn,BACKSLASH); /*;AN000;p2341*/
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*/
1112 strcpy(src_fn,foo); /*;AN003;*/
1114 got_path_validity = TRUE; /*;AN000;4*/
1117 } /* end check_path_validity */
1119 /**
\f***********************************************/
1121 /* SUBROUTINE NAME: alloc_buffers
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,
1129 /***************************************************/
1134 while ((rc != NOERROR) && (data_file_alloc_size > 2048))
1136 data_file_alloc_size = data_file_alloc_size - 512;
1140 if (rc == NOERROR && data_file_alloc_size > 2048)
1141 buffers_allocated = TRUE;
1143 error_exit(INSUFF_MEMORY);
1148 /**
\f***********************************************/
1150 /* SUBROUTINE NAME: process_switch
1154 /* Identify the parameter and set program control
1155 /* flags as appropriate.
1157 /***************************************************/
1158 void process_switch() /*;AN000;4*/
1160 char far * y; /*;AN000;4*/
1161 int i = 0; /*;AN000;4*/
1162 char temp_str[PATHLEN+20]; /*;AN000;7*/
1164 if (sw_buff.sw_synonym_ptr == (WORD)&sw1.switch1[0]) /* /S */ /*;AN000;4 /S */
1166 do_subdirs=TRUE; /*;AN000;4*/
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*/
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*/
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*/
1188 /* Handle case where user only enters /F */
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*/
1196 } /*;AN001;DCR 434*/
1198 if (sw_buff.sw_synonym_ptr == (WORD)&sw1.switch2[0]) /* /M */ /*;AN000;4 /M */
1200 do_modified=TRUE; /*;AN000;4*/
1203 if (sw_buff.sw_synonym_ptr == (WORD)&sw1.switch3[0]) /* /A */ /*;AN000;4 /A */
1205 do_add=TRUE; /*;AN000;4*/
1208 if (sw_buff.sw_synonym_ptr == (WORD)&sw4.switch1[0]) /* /L */ /*;AN000;4 /L */
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*/
1214 temp_str[i] = (BYTE)*y; /*;AN000;4*/
1218 temp_str[i] = NUL; /*;AN000;4*/
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*/
1223 xlat(logfile_path,temp_str); /*;AN000;7*/
1225 if ((BYTE)logfile_path[0] == tgt_drive_letter) /*;AN000;7*/
1226 logfile_on_target = TRUE; /*;AN000;7*/
1229 return; /*;AN000;4*/
1230 } /* end process_switch */ /*;AN000;4*/
1233 /**
\f***********************************************/
1235 /* SUBROUTINE NAME: save_current_dirs
1239 /* Save the current directory on default drive.
1240 /* Later when we terminate we must restore it.
1242 /***************************************************/
1243 void save_current_dirs()
1246 src_def_dir[0] = BACKSLASH;
1247 get_current_dir(src_drive_letter -'A'+1,&src_def_dir[1]);
1250 } /* end save_current_dirs */
1251 /**
\f***********************************************/
1253 /* SUBROUTINE NAME: open_logfile
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.
1260 /***************************************************/
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*/
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*/
1284 if (rc != NOERROR) /* Terminate if can't open logfile */
1285 error_exit(CANT_OPEN_LOGFILE);
1287 display_msg(LOGGING); /* Tell user where we are logging */
1289 datetime(); /* Put date and time of BACKUP in logfile */
1291 logfile_opened = TRUE; /*;AN000;7 The logfile is open */
1294 } /* end open_logfile */
1296 /**
\f***********************************************/
1298 /* SUBROUTINE NAME: set_vectors
1301 /* Hook control break and critical vector to
1302 /* allow BACKUP to gracefully terminate.
1304 /***************************************************/
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) */
1313 } /* end set_vectors */
1315 /**
\f***********************************************/
1317 /* SUBROUTINE NAME: check_appendX
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.
1324 /***************************************************/
1325 void check_appendX() /*;AN000;2*/
1327 union REGS gregs; /*;AN000;2 Register set */
1329 gregs.x.ax = INSTALL_CHECK; /*;AN000;2 Get installed state*/
1330 int86(0x2f,&gregs,&gregs); /*;AN000;2*/
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*/
1340 gregs.x.ax = GET_APPEND_VER; /*;AN000;2*/
1341 int86(0x2f,&gregs,&gregs); /*;AN000;2*/
1343 if (gregs.h.al == (BYTE)-1) /*;AN000;2 -1 if DOS version*/
1344 append_indicator = DOS_APPEND; /*;AN000;2*/
1346 append_indicator = NET_APPEND; /*;AN000;2*/
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*/
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*/
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*/
1366 return; /*;AN000;2*/
1369 /**
\f***********************************************/
1371 /* SUBROUTINE NAME: get_drive_types
1374 /* For the source and target drives, figure out
1375 /* if they are removable or not.
1377 /***************************************************/
1378 void get_drive_types() /* Check if the source and target drive are removable*/
1385 /* Check Source drive */
1386 drive_spec[0] = src_drive_letter;
1387 drive_spec[1] = ':';
1388 drive_spec[2] = NUL;
1390 /* Device open, source drive */
1391 drivehandle = handle_open(drive_spec,OPENDASD+DENYNONE) ;
1393 /* Now see if it is removable */
1394 if (ioctl(drivehandle) == REMOVABLE)
1395 source_removable = TRUE;
1397 source_removable = FALSE;
1399 close_file(drivehandle);
1401 /* Check Target drive */
1402 drive_spec[0] = tgt_drive_letter;
1403 drive_spec[1] = ':';
1404 drive_spec[2] = NUL;
1406 drivehandle = handle_open(drive_spec,OPENDASD+DENYNONE) ;
1408 if (ioctl(drivehandle) == REMOVABLE)
1409 target_removable = TRUE;
1411 target_removable = FALSE;
1413 close_file(drivehandle);
1416 } /* end get_drive_types */
1418 /**
\f***********************************************/
1420 /* SUBROUTINE NAME: do_backup
1424 /* BACKUP all files that should be backed up
1426 /***************************************************/
1429 set_default_dir(); /* Set default dir to one where source files are */
1431 find_first_file(); /* Find first file to be backed up */
1432 if (back_it_up) /* If you found one.... */
1434 get_first_target(); /* get the first diskette (or last if /A specified!) */
1435 do /* Repeat this */
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 */
1442 while (back_it_up); /* While there are file to back up */
1445 else /* otherwise */
1447 display_msg(NONEFNDMSG);
1448 return_code = RETCODE_NO_FILES;/* there were no files to be backed up */
1451 clean_up_and_exit();
1454 } /* end do_backup */
1455 /**
\f***********************************************/
1457 /* SUBROUTINE NAME: find_first_file
1461 /* Find the first file conforming to user entered spec.
1462 /* If necessary, look on other directory levels also.
1464 /***************************************************/
1465 void find_first_file()
1467 char loop_done = FALSE;
1469 back_it_up = FALSE; /* Havn't found a file yet ! */
1470 find_the_first(); /* Sets the "found_a_file" flag */
1472 if (found_a_file) /* If you find a file, do this stuff */
1475 if (found_a_file) /* If you got one, then */
1476 see_if_it_should_be_backed_up(); /* Check it against user entered parameters */
1478 if (!back_it_up) /* If it shouldn't be processed... */
1479 find_the_next(); /* then find another (sets the "found_a_file" flag) */
1481 loop_done = TRUE; /* Otherwise your done here */
1483 if (!found_a_file) /* Don't remove this ! */
1484 loop_done = TRUE; /* This has gotta stay ! */
1489 } /* end find_first_file */
1491 /**
\f*********************************************/
1493 /* SUBROUTINE NAME: find_next_file
1497 /* Find the next file conforming to user entered spec
1499 /************************************************/
1500 void find_next_file()
1502 char loop_done = FALSE;
1511 see_if_it_should_be_backed_up();
1521 } /* end find_next_file */
1523 /**
\f*********************************************/
1525 /* SUBROUTINE NAME: find_the_first
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.
1533 /************************************************/
1534 void find_the_first()
1536 char loop_done = FALSE;
1537 char file_spec[PATHLEN];
1539 found_a_file = FALSE;
1540 sprintf(file_spec,"%c:%s",src_drive_letter,src_fn);
1544 find_first /* Find file conforming to user-entered file spec */
1554 found_a_file = TRUE; /* then we found a file */
1555 loop_done = TRUE; /* and we are done here */
1557 else /* If there was an error */
1558 if (do_subdirs) /* and if user said /S */
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 */
1570 } /* end find_the_first */
1571 /**
\f***********************************************/
1573 /* SUBROUTINE NAME: find_the_next
1577 /* Find the next file conforming to user entered spec
1579 /***************************************************/
1580 void find_the_next()
1582 char loop_done = FALSE;
1584 found_a_file = FALSE;
1586 find_next(dirhandle,dta_addr);
1590 found_a_file = TRUE;
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 */
1603 find_the_first(); /* Look for first file at this level */
1613 } /* end find_the_next */
1615 /**
\f***********************************************/
1617 /* SUBROUTINE NAME: change_levels
1620 /* Change directory to next one in the linked list
1621 /* of directories to be processed.
1623 /***************************************************/
1624 void change_levels()
1626 new_directory = FALSE;
1629 } /* end change_levels */
1631 /**
\f***********************************************/
1633 /* SUBROUTINE NAME: alloc_node
1636 /* Allocates a node for the linked list of subdirectories
1639 /***************************************************/
1640 struct node * alloc_node(path_len)
1641 unsigned int path_len;
1643 struct node *pointer;
1644 unsigned int malloc_size;
1646 malloc_size = (unsigned int) (sizeof(struct node far *) + path_len + 2);
1648 printf("\nMALLOCING NODE, SIZE=%04Xh...",malloc_size);
1651 pointer = (struct node *)malloc(malloc_size);
1655 printf("SUCCESSFUL, PTR=%u",(unsigned)pointer);
1657 printf("ERROR, PTR=%u",(unsigned)pointer);
1661 error_exit(INSUFF_MEMORY);
1665 } /* end alloc_node */
1668 /**
\f***********************************************/
1670 /* SUBROUTINE NAME: alloc_first_node
1674 /* Allocate the first node in the linked list.
1676 /***************************************************/
1677 void alloc_first_node()
1680 printf("\nINSERTING FIRST NODE=%s",src_drive_path);
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;
1689 } /* end alloc_first_node */
1692 /**
\f***********************************************/
1694 /* SUBROUTINE NAME: insert_node
1698 /* Insert next node in the linked list of subdirectories
1701 /***************************************************/
1702 void insert_node(path_addr)
1705 struct node *temp; /* temporary pointer to a node */
1706 struct node *newnode; /* same thing */
1709 printf("\nINSERTING NODE=%s",*path_addr);
1711 temp = last_child->np;
1712 newnode = alloc_node(strlen(path_addr));
1713 last_child->np = newnode;
1715 strcpy(newnode->path,path_addr);
1716 last_child = newnode;
1719 } /* end insert_node */
1721 /**
\f***********************************************/
1723 /* SUBROUTINE NAME: remove_node
1726 /* CHDIR to the next level to be processed.
1727 /* Release the node for that directory
1729 /***************************************************/
1735 last_child = curr_node->np;
1736 if (curr_node->np != NUL)
1738 rc = chdir(last_child->path);
1741 new_directory = TRUE;
1742 strcpy(src_drive_path,last_child->path);
1745 printf("\nFREE NODE %u",(unsigned)curr_node);
1747 free((char *)curr_node);
1748 curr_node = last_child;
1750 if (do_subdirs) /* Place all subdirs in linked list */
1755 } /* end remove_node */
1757 /**
\f***********************************************/
1759 /* SUBROUTINE NAME: find_all_subdirs
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
1766 /***************************************************/
1767 void find_all_subdirs()
1771 char full_path[PATHLEN+20];
1772 struct FileFindBuf tempdta;
1774 sprintf(global,"%c:*.*",src_drive_letter);
1776 find_first /* Find all subdirectory entries in current directory. */
1781 (SUBDIR + SYSTEM + HIDDEN)
1784 while (rc == NOERROR)
1786 if ((tempdta.attributes & SUBDIR) == SUBDIR) /* If its a subdirectory */
1787 if (tempdta.file_name[0] != '.') /* But not "." or ".." */
1789 if (src_drive_path[strlen(src_drive_path)-1] != BACKSLASH)
1790 sprintf(full_path,"%s\\%s",src_drive_path,tempdta.file_name);
1792 sprintf(full_path,"%s%s", src_drive_path,tempdta.file_name);
1794 insert_node((char *)full_path); /* Save it in the linked list */
1797 find_next(dhandle,&tempdta);
1803 /**
\f***********************************************/
1805 /* SUBROUTINE NAME: get_first_target
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.
1812 /***************************************************/
1813 void get_first_target()
1815 if (target_removable)
1821 open_logfile(); /*;AN000;7 Open or create logfile*/
1827 } /* end get_first_target */
1829 /**
\f***********************************************/
1831 /* SUBROUTINE NAME: get_next_target
1834 /* We are ready for the next target diskette.
1835 /* Ask user to insert it. Format if required.
1836 /* Create files, reset variables.
1838 /***************************************************/
1839 void get_next_target()
1842 doing_first_target = FALSE;
1843 files_backed_up = 0;
1846 get_diskette(); /* Get it */
1852 if (logfile_on_target) /*;AN000;7 and if logfile on the target drive*/
1853 open_logfile(); /*;AN000;7 Open or create it*/
1856 if (file_spans_target)
1857 show_path(); /* Display to stdout and logfile the full path from root */
1863 } /* end get_next_target */
1865 /**
\f***********************************************/
1867 /* SUBROUTINE NAME: see_if_it_should_be_backed_up
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.
1876 /***************************************************/
1877 void see_if_it_should_be_backed_up()
1879 BYTE temp[PATHLEN+20]; /*;AN006;*/
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 */
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 */
1889 if (do_modified) /* Check ARCHIVE bit */
1890 if ((dta.attributes & ARCHIVE) != ARCHIVE)
1893 if (do_time) /* Check TIME parameter */
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 */
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 */
1906 if (do_date) /* Check DATE parameter */
1908 if (dta.write_date < user_specified_date)
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*/
1919 strcmp(dta.file_name,"IO.SYS") == SAME || /*;AN000;1*/
1920 strcmp(dta.file_name,"MSDOS.SYS") == SAME || /*;AN000;1*/
1922 strcmp(dta.file_name,"COMMAND.COM") == SAME || /*;AN000;1*/
1923 strcmp(dta.file_name,"CMD.EXE") == SAME /*;AN000;1*/
1925 back_it_up = FALSE; /*;AN000;1 then do not back them up! */
1929 if (do_logfile) /*;AN006;*/
1931 strcpy(temp,src_drive_path); /*;AN006;*/
1933 if (strlen(temp) == 3) /*;AN006;*/
1934 temp[2] = NUL; /*;AN006;*/
1936 sprintf(temp,"%s\\%s",temp,dta.file_name); /*;AN006;*/
1938 if (strcmp(logfile_path,temp) == SAME)/*;AN006;*/
1939 back_it_up = FALSE; /*;AN006;*/
1943 } /* end see_if_it_should_be_backed_up */
1945 /**
\f***********************************************/
1947 /* SUBROUTINE NAME: get_diskette
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 /**************************************************/
1956 union REGS qregs; /*;AN000;8*/
1960 display_msg(INSERTTARGET);
1961 display_msg(ERASEMSG);
1964 if (doing_first_target)
1965 display_msg(LASTDISKMSG);
1968 display_msg(INSERTTARGET);
1969 display_msg(ERASEMSG);
1972 got_first_target = TRUE; /*;AN000;*/
1974 /*wait_for_keystroke(); /* Let user "Strike any key when ready" */
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*/
1982 if (target_removable) /*;AN000;d177*/
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 */
1989 display_msg(BUDISKMSG);
1990 display_msg(SEQUENCEMSG);
1991 delete_files(ROOTDIR); /* Delete all files in the root dir of target drive */
1993 create_target(); /* Create target files */
1996 } /* end get_diskette */
1998 /**
\f***********************************************/
2000 /* SUBROUTINE NAME: get_hardfile
2003 /* Target is a hardfile. FORMATTING hardfile is
2004 /* not allowed by BACKUP. Create target files
2005 /* in BACKUP directory of disk.
2006 /***************************************************/
2011 sprintf(dirname,"%c:\\BACKUP\\*.*",tgt_drive_letter);
2012 if (exist(&dirname[0]))
2016 display_msg(FERASEMSG);
2017 /*wait_for_keystroke(); /* Let user "Strike any key when ready" */
2019 delete_files(BACKUPDIR); /* Delete \BACKUP\*.* of target drive if not do_add */
2023 sprintf(dirname,"%c:\\BACKUP",tgt_drive_letter);
2027 display_msg(BUDISKMSG);
2031 } /* end get_hardfile */
2034 /**
\f***********************************************/
2036 /* SUBROUTINE NAME: check_last_target
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()
2052 char current_file[25];
2054 struct FileFindBuf tempdta;
2056 if (target_removable) /* Make sure there is no old BACKUP on here */
2057 sprintf(path,"%c:\\BACKUPID.@@@",tgt_drive_letter);
2059 sprintf(path,"%c:\\BACKUP\\BACKUPID.@@@",tgt_drive_letter);
2062 error_exit(INVTARGET);
2064 if (target_removable) /* Build path to control file */
2065 sprintf(path,"%c:\\CONTROL.*",tgt_drive_letter);
2067 sprintf(path,"%c:\\BACKUP\CONTROL.*",tgt_drive_letter);
2069 find_first /* Find the control file */
2077 if (rc != NOERROR) /* If you got one, then close dirhandle */
2078 error_exit(NOTLASTMSG);
2083 /* Add drive letter to control file name */
2084 sprintf(path,"%c:%s",tgt_drive_letter,tempdta.file_name);
2086 handle_control = /* Open the control file;AN000;5*/
2087 extended_open /*;AN000;5*/
2088 (OPEN_IT, /*;AN000;5*/
2090 (char far *)path, /*;AN000;5*/
2091 (WORD)(DENYWRITE+READACCESS) /*;AN000;5*/
2094 if (rc != NOERROR) /* If can't open it, strange error */
2095 error_exit(NOTLASTMSG);
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" */
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);
2106 if (flag != LAST_TARGET) /* If wasn't last target, terminate */
2107 error_exit(NOTLASTMSG);
2109 close_file(handle_control); /* Close the control file */
2110 control_opened = FALSE; /*;AN005; And say it isn't open */
2113 } /* end check_last_target */
2114 /**
\f***********************************************/
2116 /* SUBROUTINE NAME: format_target
2119 /* See if the target is formatted. If not, try
2122 /***************************************************/
2123 void format_target()
2129 char format_parms[35]; /*;AC000;8*/
2130 WORD temp_rc; /*;AN000;p2631 Return code from DOS calls */
2133 if (doing_first_target)
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;*/
2145 temp_rc = rc; /*;AN000;p2631*/
2146 do_dos_error(UNHOOK); /*;AN000;p2631 Unhook hard error handler */
2147 rc = temp_rc; /*;AN000;p2631*/
2149 if (rc != NOERROR) /* If there was a hard error... */
2150 { /* Then FORMAT the target */
2153 sprintf(format_parms,"%c:",tgt_drive_letter);
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*/
2159 strcat(format_parms," /BACKUP /V:BACKUP"); /*;AN000;8*/
2161 if (spawnlp(P_WAIT,format_path,"FORMAT",format_parms,NUL) == NOERROR) /*;AC000;d178*/
2163 display_msg(CRLF); /* Skip a line */
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(); */
2176 } /* end format_target */
2178 /**
\f***********************************************/
2180 /* SUBROUTINE NAME: set_default_dir
2186 /***************************************************/
2187 void set_default_dir()
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... */
2192 rc = chdir(src_drive_path); /* then change dir to there. */
2195 src_drive_path[2] = BACKSLASH;
2196 get_current_dir(src_drive_letter-'A'+1,&src_drive_path[3]);
2199 error_exit(INV_PATH);
2202 curr_dir_set = TRUE;
2204 if (do_subdirs) /* If we are processing subdirectories too, */
2206 alloc_first_node(); /* then put current level in linked list */
2207 find_all_subdirs(); /* And get all directory entries in that level */
2211 } /* end set_default_dir */
2213 /**
\f***********************************************/
2215 /* SUBROUTINE NAME: label_target_drive
2218 /* Create volume label BACKUP.xxx on target
2221 /***************************************************/
2222 void label_target_drive() /* Create Volume label BACKUP.XXX on target */
2228 build_ext(diskettes_complete + 1);
2230 sprintf(fsbuf,"%c:BACKUP.%s",tgt_drive_letter,ext);
2232 replace_volume_label(&fsbuf[0]);
2235 } /* end label_target_drive */
2237 /**
\f***********************************************/
2239 /* SUBROUTINE NAME: build_ext
2245 /***************************************************/
2250 sprintf(ext,"00%u",num);
2253 sprintf(ext,"0%u",num);
2255 sprintf(ext,"%u",num);
2258 } /* end build_ext */
2260 /**
\f***********************************************/
2262 /* SUBROUTINE NAME: create_target
2268 /***************************************************/
2269 void create_target()
2274 if (doing_first_target)
2280 build_ext(diskettes_complete + 1);
2282 if (target_removable)
2283 sprintf(path,"%c:\\BACKUP.%s",tgt_drive_letter,ext);
2285 sprintf(path,"%c:\\BACKUP\\BACKUP.%s",tgt_drive_letter,ext);
2287 handle_target = /*;AN000;5*/
2288 extended_open /*;AN000;5*/
2290 CREATE_IT, /*;AN000;5*/
2291 (WORD)ARCHIVE, /*;AN000;5*/
2292 (char far *)path, /*;AN000;5*/
2293 (WORD)(READWRITE) /*;AN000;5*/
2297 target_opened = TRUE;
2299 error_exit(INVTARGET);
2301 if (target_removable)
2302 sprintf(path,"%c:\\CONTROL.%s",tgt_drive_letter,ext);
2304 sprintf(path,"%c:\\BACKUP\\CONTROL.%s",tgt_drive_letter,ext);
2306 handle_control = /*;AN000;5*/
2307 extended_open /*;AN000;5*/
2309 CREATE_IT, /*;AN000;5*/
2310 (WORD)ARCHIVE, /*;AN000;5*/
2311 (char far *)path, /*;AN000;5*/
2312 (WORD)(READWRITE) /*;AN000;5*/
2316 control_opened = TRUE;
2318 error_exit(INVTARGET);
2320 data_file_tot_len = (DWORD)0;
2321 ctl_file_tot_len = (DWORD)0;
2324 } /* end create_target */
2326 /**
\f***********************************************/
2328 /* SUBROUTINE NAME: open_target
2334 /***************************************************/
2335 void open_target() /* Done only if /A and it is the first target */
2338 char path[PATHLEN+20];
2340 /* Open BACKUP.xxx File */
2341 build_ext(diskettes_complete+1);
2343 if (target_removable)
2344 sprintf(path,"%c:\\BACKUP.%s",tgt_drive_letter,ext);
2346 sprintf(path,"%c:\\BACKUP\\BACKUP.%s",tgt_drive_letter,ext);
2348 /* Turn off readonly bit on BACKUP.xxx */
2349 set_attribute(path,(WORD)(get_attribute(path) & (WORD)READONLYOFF));
2351 handle_target = /*;AN000;5*/
2352 extended_open /*;AN000;5*/
2353 ( OPEN_IT, /*;AN000;5*/
2355 (char far *)path, /*;AN000;5*/
2356 (WORD)(DENYALL+READWRITE) /*;AN000;5*/
2360 target_opened = TRUE;
2362 error_exit(INVTARGET);
2363 /* Open CONTROL.xxx File */
2364 if (target_removable)
2365 sprintf(path,"%c:\\CONTROL.%s",tgt_drive_letter,ext);
2367 sprintf(path,"%c:\\BACKUP\\CONTROL.%s",tgt_drive_letter,ext);
2369 set_attribute(path,(WORD)(get_attribute(path) & (WORD)READONLYOFF));
2371 handle_control = /*;AN000;5*/
2372 extended_open /*;AN000;5*/
2373 ( OPEN_IT, /*;AN000;5*/
2375 (char far *)path, /*;AN000;5*/
2376 (WORD)(DENYALL+READWRITE) /*;AN000;5*/
2380 control_opened = TRUE;
2382 error_exit(INVTARGET);
2384 data_file_tot_len = (DWORD)lseek(handle_target ,EOFILE,(DWORD)0);
2385 ctl_file_tot_len = (DWORD)lseek(handle_control,EOFILE,(DWORD)0);
2388 } /* end open_target */
2390 /**
\f***********************************************/
2392 /* SUBROUTINE NAME: delete_files
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.
2401 /***************************************************/
2402 void delete_files(dirlevel)
2405 BYTE delete_path[25];
2406 struct FileFindBuf tempdta;
2407 struct FileFindBuf *tempdta_addr;
2409 BYTE delete_it; /*;AN000;7*/
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 */
2415 tempdta_addr = (struct FileFindBuf *)&tempdta;
2417 if (dirlevel == ROOTDIR)
2418 sprintf(delete_path,"%c:\\*.*",tgt_drive_letter);
2420 sprintf(delete_path,"%c:\\BACKUP\\*.*",tgt_drive_letter);
2422 find_first /* Find a file to delete */
2424 (char *)&delete_path[0],
2430 while (rc == NOERROR)
2432 delete_it = TRUE; /*;AN000;7*/
2434 if (dirlevel == ROOTDIR)
2435 sprintf(delete_path,"%c:\\%s",tgt_drive_letter,tempdta.file_name);
2437 sprintf(delete_path,"%c:\\BACKUP\\%s",tgt_drive_letter,tempdta.file_name);
2439 if (logfile_on_target) /*;AN000;7*/
2440 if (strcmp(delete_path,logfile_path) == SAME) /*;AN000;7*/
2441 delete_it = FALSE; /*;AN000;7*/
2443 if (delete_it == TRUE) /*;AN000;7*/
2445 delete(delete_path);
2449 set_attribute(delete_path,(WORD)0);
2450 delete(delete_path);
2454 find_next(dhandle,tempdta_addr);
2458 } /* end delete_files */
2460 /**
\f***********************************************/
2462 /* SUBROUTINE NAME: exist
2465 /* Does a FIND FIRST of the filespec passed at PATH_ADDR.
2466 /* If so, returns TRUE, otherwise returns FALSE.
2468 /***************************************************/
2469 WORD exist(path_addr) /* Return TRUE if specified epath exists, FALSE other */
2474 struct FileFindBuf tempdta;
2476 find_first /* DOS Find First */
2481 (SUBDIR + SYSTEM + HIDDEN)
2485 if (rc == NOERROR) findclose(dhandle);
2487 if (temprc != NOERROR)
2494 /**
\f***********************************************/
2496 /* SUBROUTINE NAME: open_source_file
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.
2505 /***************************************************/
2506 void open_source_file()
2508 int num_attempts = 0;
2510 char file_to_be_backup[20];
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);
2519 { /*;AN000;5*/ /* Attempt open */
2520 handle_source = /*;AN000;5*/
2521 extended_open /*;AN000;5*/
2523 OPEN_IT, /*;AN000;5*/
2525 (char far *)file_to_be_backup, /*;AN000;5*/
2526 (WORD)(DENYWRITE+READACCESS) /*;AN000;5*/
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 */
2534 file_sharing_error(); /*;AN000;9 There was a share error opening the file*/
2540 source_opened = TRUE; /* Set flag indicating file is opened */
2541 done = TRUE; /* We are done in this loop */
2543 /*EAEAEAEAEA get_extended_attributes(handle_source); /*;AN000;3 Get extended attributes for this file */
2545 put_new_fh(); /* Write the file header to the control file */
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 */
2554 } /* end open_source_file */
2556 /**
\f***********************************************/
2558 /* SUBROUTINE NAME: file_sharing_error
2562 /* Handle the file sharing error that just occurred
2564 /***************************************************/
2565 void file_sharing_error() /*;AN000;9*/
2567 union REGS reg; /*;AN000;9*/
2570 display_msg(CONFLICTMSG); /* Say "Last file not backed */
2571 return_code = RETCODE_SHARE_ERROR; /* Set errorlevel */
2573 if (do_logfile) /*;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*/
2582 return; /*;AN000;9*/
2585 /**
\f***********************************************/
2587 /* SUBROUTINE NAME: far_ptr
2593 /***************************************************/
2594 char far *far_ptr(seg,off)
2606 /**
\f***********************************************/
2608 /* SUBROUTINE NAME: do_copy
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 /***************************************************/
2618 WORD bytes_to_read = data_file_alloc_size; /* Read size = buffer size */
2620 char file_to_be_backup[20];
2622 part_size = (DWORD)0;
2623 cumul_part_size = (DWORD)0;
2637 if (bytes_read == 0)
2640 write_to_target(bytes_read);
2642 if (bytes_read < bytes_to_read)
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 */
2657 /**
\f***********************************************/
2659 /* SUBROUTINE NAME: write_extended_attributes
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.
2667 /**************************************************/
2668 /*#define WRITE_LENGTH 2
2670 /*void write_extended_attributes() /*;AN000;3*/
2672 /* WORD written; /*;AN000;3*/
2673 /* /*******************************************/
2674 /* /* Write the length of extended attributes */
2675 /* /*******************************************/
2681 /* (char far *)&ext_attrib_len
2684 /* if (written == WRITE_LENGTH ) /*;AN000;3*/
2685 /* data_file_tot_len += WRITE_LENGTH; /*;AN000;3*/
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*/
2694 /* ext_attrib_buff[0] = 0; /*;AN000;3*/
2695 /* ext_attrib_buff[1] = 0; /*;AN000;3*/
2696 /* return; /*;AN000;3*/
2699 /**
\f***********************************************/
2701 /* SUBROUTINE NAME: show_path
2704 /* Display to stdout the full path from root.
2705 /* If we are logging, put full path there too.
2707 /***************************************************/
2710 char done_path[PATHLEN+20];
2711 char logfile_entry[PATHLEN+22];
2714 if (src_drive_path[strlen(src_drive_path) - 1] != BACKSLASH)
2715 sprintf(done_path,"%s\\%s",src_drive_path,dta.file_name);
2717 sprintf(done_path,"%s%s",src_drive_path,dta.file_name);
2721 /* Display logfile path on screen */
2722 handle_write(STDOUT,strlen(done_path),(char far *)&done_path[0]);
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) )
2731 display_msg(LOGFILE_TARGET_FULL);
2732 /*wait_for_keystroke();*/
2738 } /* end show_path */
2740 /**
\f***********************************************/
2742 /* SUBROUTINE NAME: reset_archive_bit
2745 /* Sets the attribute of the source file to what
2746 /* it was before, except the archive bit is reset.
2748 /***************************************************/
2749 void reset_archive_bit(path_addr)
2751 #define ARCHIVE_MASK 223
2755 attrib = get_attribute(path_addr);
2756 attrib = attrib & (WORD)ARCHIVE_MASK;
2757 set_attribute(path_addr,attrib);
2760 } /* end reset_archive_bit */
2762 /**
\f***********************************************/
2764 /* SUBROUTINE NAME: write_to_target
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;
2777 bytes_written = handle_write(handle_target,bytes_to_write,far_ptr(selector,0));
2778 written = bytes_written;
2780 if (bytes_written == bytes_to_write) /* If we wrote it all... */
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 */
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 */
2804 } /* end write_to_target */
2806 /**
\f***********************************************/
2808 /* SUBROUTINE NAME: write_till_target_full
2811 /* Find out how much space is left on the disk,
2812 /* and use it all up.
2814 /***************************************************/
2815 WORD write_till_target_full(bytes_to_write,begin_offset)
2816 WORD bytes_to_write;
2822 bfree = (unsigned) disk_free_space();
2823 written = handle_write(handle_target,bfree,far_ptr(selector,begin_offset));
2826 } /* end write_till_target_full */
2828 /**
\f***********************************************/
2830 /* SUBROUTINE NAME: close_out_current_target
2833 /* Update CONTROL.xxx file, close it, close BACKUP.xxx,
2834 /* make files READONLY, die if backing up to hardfile.
2836 /***************************************************/
2837 void close_out_current_target()
2839 BYTE last = LAST_TARGET; /*;AN011;*/
2841 disk_full = TRUE; /* Yes, the disk is full */
2843 if (part_size != 0) /* If we wrote something...*/
2845 file_spans_target = TRUE; /* Say "Hey, this file spans diskettes !" */
2846 files_backed_up++; /* Increment number files backed up on this target */
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 */
2852 update_fh_entries(); /* Update the fields in file header */
2854 if (!target_removable) /*;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;*/
2861 if (control_opened) /* If the control file is open */
2863 close_file(handle_control); /* Close it */
2864 control_opened = FALSE; /* And say it isn't open */
2868 close_file(handle_target); /* Close files */
2870 target_opened = FALSE; /* Indicate that target is not opened */
2872 if (file_spans_target) /* If file spans to another diskette */
2873 span_seq_num++; /* then increment the sequence number */
2875 mark_files_read_only(); /* Set ReadOnly Attribute of BACKUP/CONTROL files */
2877 if (logfile_on_target) /*;AN000;7 If logfile resides on target drive */
2879 close_file(handle_logfile); /*;AN000;7 Then close it */
2880 logfile_opened = FALSE; /*;AN000;7 and set flag indicating that */
2883 if (!target_removable) /* If target is a hardfile */
2885 display_msg(LASTNOTBACKUP); /* Say "Last file not backed up */
2886 error_exit(FDISKFULLMSG); /* then give error message and quit */
2889 diskettes_complete++; /* Increment number of diskettes complete */
2891 } /* end close_out_current_target */
2893 /**
\f***********************************************/
2895 /* SUBROUTINE NAME: mark_as_not_last_target
2898 /* Sets the field in the disk header indicating
2899 /* this is not the last target
2901 /***************************************************/
2902 void mark_as_not_last_target()
2904 BYTE last = NOT_LAST_TARGET;
2908 /* Update DH_LastDisk = NOT_LAST_TARGET */
2909 lseek(handle_control,BOFILE,(DWORD)(DHLENGTH - 1));
2910 handle_write(handle_control,1,(char far *)&last);
2912 /* Get first DB_NextDB */
2913 pointer = lseek(handle_control,BOFILE,(DWORD)(DHLENGTH+66));
2914 handle_read(handle_control,4,(char far *)&db_offset);
2916 /* Get offset of last Dir Block */
2917 while (db_offset != (DWORD)LAST_DB)
2919 pointer = lseek(handle_control,BOFILE,(DWORD)db_offset+66);
2920 handle_read(handle_control,4,(char far *)&db_offset);
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);
2927 lseek(handle_control,EOFILE,(DWORD)0);
2929 } /* end mark_as_not_last_target */
2931 /**
\f***********************************************/
2933 /* SUBROUTINE NAME: mark_as_last_target
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.
2941 /***************************************************/
2942 void mark_as_last_target()
2944 BYTE last = LAST_TARGET;
2946 /* Update DH_LastDisk == LAST_DISK */
2947 lseek(handle_control,BOFILE,(DWORD)(DHLENGTH - 1));
2948 handle_write(handle_control,1,(char far *)&last);
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);
2954 /* Update FH Entries */
2955 update_fh_entries();
2958 } /* end mark_as_last_target */
2960 /**
\f***********************************************/
2962 /* SUBROUTINE NAME: update_db_entries
2968 /***************************************************/
2969 void update_db_entries(entries)
2972 lseek(handle_control,BOFILE,(DWORD)(curr_db_begin_offset+64));
2974 /* Update DB_num_entries */
2975 handle_write(handle_control,2,(char far *)&entries);
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);
2980 lseek(handle_control,EOFILE,(DWORD)0);
2983 } /* end update_db_entries */
2985 /**
\f***********************************************/
2987 /* SUBROUTINE NAME: update_fh_entries
2990 /* Update following fields in Current File Header:
2992 /* FH_Flags: Indicate file successfully processed.
2993 /* Indicate if this is last part or not.
2995 /* FH_PartSize: Indicate number of bytes written
2997 /***************************************************/
2998 void update_fh_entries()
3002 if (!file_spans_target)
3003 flag = (BYTE)(LASTPART + SUCCESSFUL);
3005 flag = (BYTE)(NOTLASTPART + SUCCESSFUL);
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 */
3011 if (!target_removable) /*;AN011;*/
3012 if (disk_full) /*;AN011;*/
3014 flag = (BYTE)(LASTPART + NOTSUCCESSFUL); /*;AN011;*/
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);
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);
3027 lseek(handle_control,EOFILE,(DWORD)0); /* Go back to end-of-file */
3030 } /* end update_fh_entries */
3032 /**
\f***********************************************/
3034 /* SUBROUTINE NAME: mark_files_read_only
3037 /* Set the READ-ONLY attribute on BACKUP.xxx and CONTROL.xx
3040 /***************************************************/
3041 void mark_files_read_only()
3045 build_ext(diskettes_complete + 1);
3047 if (target_removable)
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));
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));
3062 if (target_removable)
3063 label_target_drive();
3068 /**
\f***********************************************/
3070 /* SUBROUTINE NAME: put_disk_header
3076 /***************************************************/
3077 void put_disk_header()
3079 struct Disk_Header dh;
3082 dh.DH_Length = DHLENGTH; /* DH_Length */
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 */
3089 write_to_control_file((char far *)&dh,DHLENGTH);
3093 } /* end put_disk_header */
3095 /**
\f***********************************************/
3097 /* SUBROUTINE NAME: put_new_db
3103 /***************************************************/
3106 struct Dir_Block db;
3109 if (files_backed_up > 0)
3110 update_db_entries(files_backed_up); /* Update entries in previous db */
3112 curr_db_begin_offset = ctl_file_tot_len; /* Save this for updating when done with current dir */
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*/
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 */
3122 write_to_control_file((char far *)&db,DBLENGTH);
3123 new_directory = FALSE;
3124 files_backed_up = 0;
3127 } /* end put_new_db */
3129 /**
\f***********************************************/
3131 /* SUBROUTINE NAME: put_new_fh
3134 /* We are about to backup a file. Write the
3135 /* file header to the control file.
3137 /***************************************************/
3140 struct File_Header fh;
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 */
3148 if (new_directory) /* If this file resides in a different directory */
3149 put_new_db(); /* then create new directory block. */
3151 curr_fh_begin_offset = ctl_file_tot_len;
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 */
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;
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*/
3175 if (file_spans_target)
3177 fh.FH_PartSize = (DWORD)(dta.file_size - cumul_part_size); /*LENGTH OF THIS PART OF FILE */
3178 file_spans_target = FALSE;
3181 fh.FH_PartSize = (DWORD)dta.file_size;/* LENGTH OF THIS PART OF FILE */
3183 write_to_control_file((char far *)&fh,FHLENGTH);
3186 } /* end put_new_fh */
3188 /**
\f***********************************************/
3190 /* SUBROUTINE NAME: write_to_control_file
3193 /* Write to the control file and update
3196 /***************************************************/
3197 void write_to_control_file(address,len)
3203 written = handle_write(handle_control,len,address);
3204 ctl_file_tot_len = ctl_file_tot_len + (DWORD)written;
3207 } /* end write_to_control_file */
3209 /**
\f***********************************************/
3211 /* SUBROUTINE NAME: control_break_handler
3214 /* Set errorlevel and call routines to
3215 /* close files and terminate.
3217 /***************************************************/
3218 void control_break_handler()
3220 return_code = RETCODE_CTL_BREAK;
3221 clean_up_and_exit();
3226 /************************************************************/
3228 /* SUBROUTINE NAME: display_it
3230 /* SUBROUTINE FUNCTION:
3231 /* Display the requested message to the standard output device.
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
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.
3248 /* Message will be successfully written to requested handle.
3251 /* None. Note that theoretically an error can be returned from
3252 /* SYSDISPMSG, but there is nothing that the application can do.
3254 /* INTERNAL REFERENCES:
3255 /* System Display Message service routine SYSDISPMSG
3257 /* EXTERNAL REFERENCES:
3260 /************************************************************/
3261 void display_it(msg_number,handle,subst_count,waitflag,class)/*;AN000;6*/
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*/
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*/
3276 sysdispmsg(&inregs,&outregs); /*;AN000;6*/
3278 return; /*;AN000;6*/
3280 /**
\f***********************************************/
3282 /* SUBROUTINE NAME: display_msg
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.
3290 /***************************************************/
3292 void display_msg(msg_num)
3298 case NONEFNDMSG : { display_it (msg_num,STDOUT,0,NOWAIT,(BYTE)UTIL_MSG); break; } /*;AN000;6*/
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*/
3315 case CANT_FIND_FORMAT :
3316 case LASTNOTBACKUP :{ /*;AN000;6*/
3317 display_it (msg_num,STDERR,0,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/
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*/
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*/
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*/
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*/
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*/
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*/
3385 case SEQUENCEMSG : {
3386 build_ext(diskettes_complete+1);
3387 if (diskettes_complete+1 < 100)
3389 sublist.value1 = (char far *)&ext[1]; /*;AN000;6*/
3390 sublist.max_width1 = 2; /*;AN000;6*/
3394 sublist.value1 = (char far *)&ext[0]; /*;AN000;6*/
3395 sublist.max_width1 = 3; /*;AN000;6*/
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*/
3405 case INSERTTARGET : {
3406 build_ext(diskettes_complete+1);
3407 if (diskettes_complete+1 < 100)
3409 sublist.value1 = (char far *)&ext[1]; /*;AN000;6*/
3410 sublist.max_width1 = 2; /*;AN000;6*/
3414 sublist.value1 = (char far *)&ext[0]; /*;AN000;6*/
3415 sublist.max_width1 = 3; /*;AN000;6*/
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*/
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*/
3428 display_it (msg_num,STDERR,2,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/
3435 } /* end display_msg */
3437 /**
\f***********************************************/
3439 /* SUBROUTINE NAME: error_exit
3442 /* Display appropriate error message, set
3443 /* the return code, and call clean_up_and_exit.
3445 /***************************************************/
3446 void error_exit(error_type)
3449 display_msg(error_type);
3450 return_code = RETCODE_ERROR;
3451 clean_up_and_exit();
3454 } /* end error_exit */
3456 /**
\f***********************************************/
3458 /* SUBROUTINE NAME: restore_default_directories
3461 /* Restore the original current directory on
3462 /* the source drive.
3464 /***************************************************/
3465 void restore_default_directories()
3467 char path[PATHLEN+20];
3469 sprintf(path,"%c:%s",src_drive_letter,src_def_dir);
3473 } /* end restore_default_directories */
3475 /**************************************************/
3477 /* SUBROUTINE NAME: clean_up_and_exit
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()
3488 char name[15]; /*;AN000;p2652*/
3492 close_file(handle_source);
3493 source_opened = FALSE; /* Indicate that source is not opened */
3498 close_file(handle_target);
3499 target_opened = FALSE; /* Indicate that target is not opened */
3504 mark_as_last_target();
3505 close_file(handle_control);
3506 control_opened = FALSE; /*;AN005;*/
3507 mark_files_read_only();
3512 close_file(handle_logfile);
3513 logfile_opened = FALSE;
3516 if (files_backed_up == 0 && !checking_target) /*;AN000;p2652*//*;AN007;*/
3518 if (!do_add) /*;AN000;p2652*/
3520 if (target_removable && got_first_target) /*;AN000;p2652*/
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;*/
3527 sprintf(name,"%c:\\CONTROL.%s",tgt_drive_letter,ext); /*;AN005;*/
3528 set_attribute(name,(WORD)0); /*;AN005;*/
3529 delete(name); /*;AN005;*/
3532 if (!target_removable)
3533 delete_files(BACKUPDIR); /*;AN000;p2652*/
3537 if (!target_removable) /*;AN005;*/
3539 sprintf(name,"%c:\\BACKUP",tgt_drive_letter); /*;AN000;p2652*/
3540 rmdir(name); /*;AN000;p2652*/
3546 set_default_drive(def_drive);
3551 restore_default_directories();
3554 if (buffers_allocated)
3560 } /* end clean_up_and_exit */
3564 /**
\f***********************************************/
3565 /* DOS FAMILY API CALLS */
3566 /**************************************************/
3568 WORD handle_open(path_addr,mode)
3576 printf("\nDOSOPEN FILE=%s, MODE=%04Xh...",path_addr,mode);
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 */
3594 printf("SUCCESSFUL, HANDLE=%04Xh",handle);
3596 printf("ERROR, RC=%04Xh",rc);
3600 } /* end handle_open */
3603 /**
\f***********************************************/
3604 DWORD lseek(handle,method,distance)
3606 BYTE method; /* 0=BOF+Offset, 1=CurrPos+Offset, 2=EOF+Offset */
3612 printf("\nDOSCHGFILEPTR HANDLE=%04Xh, METHOD=%02Xh, DIST=%08lXh...",handle,method,distance);
3621 (DWORD far *)&pointer
3626 printf("SUCCESSFUL, POINTER=%08lXh",pointer);
3628 printf("ERROR, RC=%04Xh",rc);
3631 return((DWORD)pointer);
3634 /**
\f***********************************************/
3635 WORD handle_read(handle,length,address)
3643 printf("\nDOSREAD HANDLE=%04Xh, BYTES=%04Xh, ADDR(off:seg)=%04X:%04X...",handle,length,address);
3652 (unsigned far *)&num_read
3657 printf("READ %04Xh",num_read);
3659 printf("ERROR, RC=%04Xh",rc);
3663 } /* end handle_read */
3664 /**
\f***********************************************/
3665 WORD handle_write(handle,length,address)
3673 printf("\nDOSWRITE HANDLE=%04Xh, BYTES=%04Xh, ADDR(off:seg)=%04X:%04X...",handle,length,address);
3683 (unsigned far *)&written
3693 printf("WROTE %04Xh",written);
3695 printf("ERROR, RC=%04Xh",rc);
3699 } /* end handle_write */
3701 /**
\f***********************************************/
3702 void close_file(handle) /* Close the file handle specified. */
3706 printf("\nDOSCLOSE HANDLE=%04Xh...",handle);
3709 rc = DOSCLOSE(handle);
3713 printf("SUCCESSFUL");
3715 printf("ERROR, RC=%04Xh",rc);
3719 } /* end close_file */
3721 /**
\f***********************************************/
3722 WORD get_attribute(path_addr)
3728 printf("\nDOSQFILEMODE %s...",path_addr);
3731 rc = DOSQFILEMODE((char far *)path_addr,(unsigned far *)&attribute,(DWORD)0);
3735 printf("SUCCESSFUL, ATTRIB=%04Xh",attribute);
3737 printf("ERROR, RC=%04Xh",rc);
3743 /**
\f***********************************************/
3744 void set_attribute(path_addr,attribute)
3749 printf("\nDOSSETFILEMODE FILE=%s, ATTRIB=%04Xh...",path_addr,attribute);
3752 rc = DOSSETFILEMODE((char far *)path_addr,attribute,(DWORD)0);
3756 printf("SUCCESSFUL");
3758 printf("ERROR, RC=%04Xh",rc);
3763 /**
\f***********************************************/
3764 WORD get_current_drive()
3766 WORD drive; /* 1=a */
3770 printf("\nDOSQCURDISK DRIVE (1=A)...");
3775 (unsigned far *)&drive,
3776 (DWORD far *)&drivemap
3781 printf("SUCCESSFUL, DRIVE=%04Xh",drive);
3783 printf("ERROR, RC=%04Xh",rc);
3789 /**
\f***********************************************/
3790 void set_default_drive(drive) /* Change the current drive (1=A,2=B) */
3794 printf("\nDOSSELECTDISK (1=A) TO %04Xh...",drive);
3797 rc = DOSSELECTDISK(drive);
3800 def_drive_set = TRUE;
3804 printf("SUCCESSFUL");
3806 printf("ERROR, RC=%04Xh",rc);
3810 } /* end set_default_drive */
3812 /**
\f***********************************************/
3813 void get_current_dir(drive,path_addr)
3814 WORD drive; /* 0=default, 1=a, . . . */
3815 char *path_addr; /* Pointer to path buffer */
3817 WORD path_buff_len = PATHLEN+20;
3820 printf("\nDOSQCURDIR DRIVE (0=def) %04Xh...",drive);
3827 (char far *)path_addr,
3828 (unsigned far *)&path_buff_len
3833 printf("SUCCESSFUL, CURRENT DIR IS = \\%s",path_addr);
3835 printf("ERROR, RC=%04Xh",rc);
3839 } /* end get_current_dir */
3841 /**
\f***********************************************/
3842 void find_first(path_addr,dirhandle_addr,dta_address,attrib)
3844 WORD *dirhandle_addr;
3845 struct FileFindBuf *dta_address;
3848 WORD numentries = 1;
3851 *dirhandle_addr = 0xffff;
3855 printf("\nDOSFINDFIRST DIRH=%04Xh, FILE=%s...",*dirhandle_addr,path_addr);
3861 (char far *)path_addr,
3862 (unsigned far *)dirhandle_addr,
3864 (struct FileFindBuf far *)dta_address,
3865 (WORD)(sizeof(struct FileFindBuf)),
3866 (unsigned far *)&numentries,
3872 printf("SUCCESSFUL, NAME=%s, ATTR=%04Xh, SIZE=%08lXh, DIRH=%04Xh",(*dta_address).file_name,(*dta_address).attributes,(*dta_address).file_size,*dirhandle_addr);
3874 printf("ERROR, DIRH=%04Xh, RC=%04Xh",*dirhandle_addr,rc);
3880 findclose(*dirhandle_addr);
3885 } /* end find_first */
3887 /**
\f***********************************************/
3888 void find_next(dirhandle,dta_address)
3890 struct FileFindBuf *dta_address;
3893 WORD numentries = 1;
3896 printf("\nDOSFINDNEXT, DIRH=%04Xh...",dirhandle);
3903 (struct FileFindBuf far *)dta_address,
3904 (WORD)(sizeof(struct FileFindBuf)+12),
3905 (unsigned far *)&numentries
3910 printf("SUCCESSFUL, NAME=%s, DIRH=%04Xh",(*dta_address).file_name,dirhandle);
3912 printf("ERROR, RC=%04Xh",rc);
3918 findclose(dirhandle);
3923 } /* end find_next */
3924 /**
\f***********************************************/
3925 void findclose(dirhandle)
3930 printf("\nDOSFINDCLOSE DIRH=%04Xh...",dirhandle);
3933 rc = DOSFINDCLOSE(dirhandle);
3935 dirhandles_open = FALSE;
3939 printf("SUCCESSFUL");
3941 printf("ERROR, RC=%04Xh",rc);
3945 } /* end findclose */
3946 /**
\f***********************************************/
3947 void delete(path_addr)
3951 printf("\nDOSDELETE FILE %s...",path_addr);
3954 rc = DOSDELETE((char far *)path_addr,(DWORD)0);
3958 printf("SUCCESSFUL");
3960 printf("ERROR, RC=%04Xh",rc);
3965 /**
\f***********************************************/
3966 long disk_free_space()
3968 struct FSAllocate fsa;
3971 printf("\nDOSQFSINFO (0=def) DRIVE=%04Xh...",tgt_drive_letter-'A'+1);
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 */
3985 printf("SUCCESSFUL, FREESPACE=%08lXh",fsa.sec_per_unit * fsa.avail_units * fsa.bytes_sec);
3987 printf("ERROR, RC=%04Xh",rc);
3990 return((DWORD)(fsa.sec_per_unit * fsa.avail_units * fsa.bytes_sec));
3992 /**
\f***********************************************/
3993 void replace_volume_label(label_addr)
3997 printf("\nDOSSETFSINFO (0=def) DRIVE=%04Xh, LEN=%04Xh...",tgt_drive_letter-'A'+1,label_addr[0]);
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 */
4010 printf("SUCCESSFUL");
4012 printf("ERROR, RC=%04Xh",rc);
4016 } /* end replace_volume_label */
4018 /**
\f***********************************************/
4019 #define TERMINATE 0x4C00
4020 void terminate() /* Terminate process, return errorlevel to DOS */
4023 if (append_indicator == DOS_APPEND) /*;AN000;2 If append /x was reset*/
4026 printf("\nINT2Fh,(SET APPEND) AX=%04Xh TO %04Xh...",SET_STATE,original_append_func);
4028 inregs.x.ax = SET_STATE; /*;AN000;2*/
4029 inregs.x.bx = original_append_func; /*;AN000;2*/
4030 int86(0x2f,&inregs,&outregs); /*;AN000;2*/
4033 exit(return_code); /*;AN000;p972*/
4036 } /* end terminate */
4037 /**
\f***********************************************/
4038 WORD ioctl(devhandle)
4041 #define ISDEVREMOVABL 0x20
4042 #define CATEGORY 8 /*1=serial,3=display,5=printer,8=disk*/
4047 printf("\nDOSDEVIOCTL HANDLE=%04Xh...",devhandle);
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 */
4062 printf("SUCCESSFUL, DATA_AREA(0=REMOVABLE) SET TO %02Xh",data_area);
4064 printf("ERROR, RC=%04Xh",rc);
4070 /**
\f***********************************************/
4074 printf("\nDOSALLOCSEG SIZE=%04Xh...",data_file_alloc_size);
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 */
4087 printf("SUCCESSFUL, SELECTOR=%04Xh, SIZE=%04Xh",selector,data_file_alloc_size);
4089 printf("ERROR, RC=%04Xh",rc);
4095 /**
\f***********************************************/
4096 void free_seg(selector)
4100 printf("\nDOSFREESEG (%04Xh)...",selector);
4103 rc = DOSFREESEG(selector); /* Address of selector */
4107 printf("SUCCESSFUL");
4109 printf("ERROR, RC=%04Xh",rc);
4115 /**
\f***********************************************/
4116 void setsignal(action,signum)
4120 DWORD old_sig_handler;
4121 WORD old_sig_action;
4124 printf("\nDOSSETSIGHANDLER ACTION=%04Xh,SIGNUM=%04Xh...",action,signum);
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 */
4139 printf("SUCCESSFUL");
4141 printf("ERROR, RC=%04Xh",rc);
4145 } /* end setsignal */
4147 /**
\f***********************************************/
4148 void do_dos_error(flag)
4152 printf("\nDOSERROR, FLAG=%04Xh...",flag);
4155 rc = DOSERROR(flag);
4159 printf("SUCCESSFUL");
4161 printf("ERROR, RC=%04Xh",rc);
4166 /**
\f***********************************************/
4167 void get_country_info()
4169 #define USACOUNTRY 1
4170 #define DEFAULT_COUNTRY 0
4171 #define DEFAULT_CODEPAGE 0
4173 struct ctry_info_blk buff;
4174 struct countrycode ctrystuff; /* Added for CPDOS 1.1 */
4177 ctrystuff.country = (WORD)DEFAULT_COUNTRY;
4178 ctrystuff.codepage= (WORD)DEFAULT_CODEPAGE;
4181 printf("\nDOSGETCTRYINFO COUNTRY=%04Xh...",ctrystuff.country);
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 */
4195 printf("SUCCESSFUL");
4197 printf("ERROR, RC=%04Xh",rc);
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;
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);
4216 } /* end get_country_info */
4218 /**
\f***********************************************/
4219 void datetime() /* Put date and time in logfile */
4221 struct DateTime buff;
4224 char datetimestring[25];
4228 printf("\nDOSGETDATETIME...");
4231 rc = DOSGETDATETIME((struct DateTime far *)&buff);
4235 printf("SUCCESSFUL");
4237 printf("ERROR, RC=%04Xh",rc);
4240 /* Build time string */
4241 sprintf(time,"%u%c%02u%c%02u",buff.hour,ctry_time_sep,buff.minutes,ctry_time_sep,buff.seconds);
4243 /* Build date string */
4244 switch (ctry_date_fmt)
4247 sprintf(date,"%u%c%02u%c%04u",buff.month,ctry_date_sep,buff.day,ctry_date_sep,buff.year);
4251 sprintf(date,"%u%c%02u%c%04u",buff.day,ctry_date_sep,buff.month,ctry_date_sep,buff.year);
4255 sprintf(date,"%04u%c%02u%c%02u",buff.year,ctry_date_sep,buff.month,ctry_date_sep,buff.day);
4262 datetimestring[0] = 0x0d;
4263 datetimestring[1] = 0x0a;
4264 sprintf(datetimestring+2,"%s %s",date,time);
4266 written = handle_write(handle_logfile,strlen(datetimestring),(char far *)&datetimestring[0]);
4267 if (written != strlen(datetimestring) || (rc != NOERROR) )
4269 display_msg(LOGFILE_TARGET_FULL);
4270 /* wait_for_keystroke(); */
4275 } /* end datetime */
4288 /**
\f***********************************************/
4289 /*void get_extended_attributes(handle) /*;AN000;3*/
4290 /*WORD handle; /*;AN000;3*/
4292 /*#if defined(DEBUG)
4293 /* printf("\nGET EXTENDED ATTRIBUTE LENGTH...");
4295 /* ext_attrib_flg = TRUE; /*Assume ext attrib exist*/ /*;AN000;3*/
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*/
4304 /*#if defined(DEBUG)
4305 /* if (outregs.x.cflag & CARRY)
4306 /* printf("ERROR, RC=%04Xh",outregs.x.ax);
4308 /* printf("SUCCESSFUL, LEN=%04Xh",outregs.x.cx);
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*/
4317 /*#if defined(DEBUG)
4318 /* printf("\nGET EXTENDED ATTRIBUTES...");
4321 /* /* GET EXTENDED ATTRIBUTES */
4322 /* if (ext_attrib_flg)
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*/
4331 /* if (outregs.x.cflag & CARRY) /*;AN000;3*/
4332 /* ext_attrib_flg = FALSE; /*;AN000;3*/
4334 /*#if defined(DEBUG)
4335 /* if (outregs.x.cflag & CARRY)
4336 /* printf("ERROR, RC=%04Xh",outregs.x.ax);
4338 /* printf("SUCCESSFUL");
4342 /* return; /*;AN000;3*/
4343 /*} /* end get_extended_attributes */ /*;AN000;3*/
4344 /**
\f************************************************/
4345 #define EXTENDEDOPEN 0x6c00 /*;AN000;3*/
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*/
4353 union REGS inreg,outreg; /*;AN000;3*/
4355 ea_parmlist.ext_attr_addr = (DWORD)(char far *)&ext_attrib_buff[0];/*;AN000;3*/
4356 ea_parmlist.num_additional = 0; /*;AN000;3*/
4359 if (flag == CREATE_IT) printf("\nEXTENDED OPEN - CREATE, FILE %s...",path_addr);
4360 else printf("\nEXTENDED OPEN - OPEN, FILE %s...",path_addr);
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*/
4370 inreg.x.di = (WORD)&ea_parmlist; /*;AN000;3*/
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*/
4377 if (outreg.x.cflag & CARRY)
4378 printf("ERROR, RC=%04Xh",outreg.x.ax);
4380 printf("SUCCESSFUL, HANDLE=%04Xh",outreg.x.ax);
4383 return(outreg.x.ax); /*;AN000;3*/
4384 } /* end extended_open */ /*;AN000;3*/