1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
|
/*------------------------------
/* SOURCE FILE NAME: rtfile1.c
/*------------------------------
/* 0 */
#include "rt.h"
#include "rt1.h"
#include "rt2.h"
#include "restpars.h" /*;AN000;4*/
#include "direct.h"
#include "string.h"
#include "dos.h" /*;AN000;2*/
#include "comsub.h" /* common subroutine def'n */
#include "doscalls.h"
#include "error.h"
char ext_attrib_buff[4086]; /*;AN000;3*/
extern BYTE rtswitch;
extern BYTE control_flag;
extern BYTE control_flag2;
extern unsigned dest_file_handle;
extern unsigned src_file_handle;
extern BYTE far *buf_pointer;
extern BYTE dest_file_spec[MAXFSPEC+3];
extern struct FileFindBuf filefindbuf;
extern struct file_header_new far *fheadnew; /*;AN000;3 */
/**************** START OF SPECIFICATION ********************************
/*
/* SUBROUTINE NAME : open_dest_file
/*
/* DESCRIPTIVE NAME : open the destination file and build a path to it
/* if necessary.
/*
/* FUNCTION: Try to change the current directory of the destination disk
/* to be the one the file is to be restored. If not able to
/* do it because the directory does not exist, call
/* build_path_create_file subroutine to build path,
/* create the destination file and return a handle on it.
/* If file can not be created, find out whether it is caused
/* by file sharing error, or caused by disk full.
/*
/*
/********************** END OF SPECIFICATIONS ******************************/
WORD open_dest_file(finfo,destd)
struct file_info *finfo;
BYTE destd;
{
BYTE fname[MAXFSPEC+2];
BYTE path_to_be_chdir[MAXPATH+2];
WORD rc;
WORD retcode;
/*declaration for dosfindfirst */
unsigned dirhandle = 0xffff;
unsigned attribute = NOTV;
unsigned search_cnt = 1;
unsigned buf_len = sizeof(struct FileFindBuf);
BYTE search_string[MAXPATHF+2];
/*end decleration for ffirst and fnext*/
/*************************************************************************
/*if current directory is not where the file wants to be restored and
/* (the file is not to be restored in root or the current directory is
/* not root). This is to avoid building path if the the current
/* directory already got updated to be the right directory (in dorestore),
/* or both current directory and the requested directory are root
/* directory
/**************************************************************************/
if (strcmp(finfo->path,finfo->curdir)!=0)
{
/* Change to finfo->path. If error, create the directory */
strcpy(finfo->curdir,finfo->path);
path_to_be_chdir[0] = destd;
path_to_be_chdir[1] = ':';
path_to_be_chdir[2] = NULLC;
strcat(path_to_be_chdir,finfo->curdir);
if(chdir(path_to_be_chdir)!=0)
{
build_path_create_file(finfo->path,destd,finfo->fflag,finfo->ea_offset); /*;AC000;3*/
if (dest_file_handle != NULLC)
return(TRUE);
}
}
/* Current directory is the one where files are to be restored to*/
retcode = create_the_file(finfo->fflag,finfo->ea_offset); /*;AN000;3*/
if (retcode == NOERROR)
return(TRUE);
/*----------------------------------------*/
/*- There was an error creating target -*/
/*- file. Reset attribute and try again -*/
/*----------------------------------------*/
retcode =
DOSSETFILEMODE
(
(char far *)&dest_file_spec[0],
(unsigned) 0x00,
(DWORD) 0
);
retcode = create_the_file(finfo->fflag,finfo->ea_offset); /*;AN000;3*/
if (retcode == NOERROR)
return(TRUE);
else
return(FALSE); /*;AC000;p1102*/
} /*end of subroutine*/
/**************** START OF SPECIFICATION ********************************
/*
/* SUBROUTINE NAME : build_path_create_file
/*
/* DESCRIPTIVE NAME : Build path for the destination file, and create
/* the file in the current direactory.
/*
/* FUNCTION: Rebuild the path of the file about to be restored by
/* recreating all subdirectories needed to complete the path.
/* Then chdir to the one which is to reside and create the
/* file.
/*
/********************* END OF SPECIFICATIONS ********************************/
void build_path_create_file(in_path,destd,fflag,ea_offset)
BYTE *in_path;
BYTE destd;
BYTE fflag; /*;AN000;3*/
DWORD ea_offset; /*;AN000;3*/
{
WORD array[20];
int i,j;
BYTE path[MAXPATH+2];
WORD retcode;
BYTE cant_make = FFALSE; /*;AN000;10*/
path[0] = destd;
path[1] = ':';
path[2] = NULLC;
strcat(path,in_path);
i = strlen(path);
j = -1;
/* Create the path for destination file */
/*Loop until mkdir(path) is successful*/
while (mkdir(path) && !cant_make) /*;AC000;10*/
{
/*scan path backward until find a \ */
for (; path[i] != '\\'; i--)
if (i < 0)
{ display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;9*/
cant_make = TTRUE; /*;AN000;10*/
break; /*;AN000;10*/
}
/*obtain the last subdir from the path */
path[i] = NULLC;
j++;
/*save the location of the last \ in an array of \ locations */
array[j] = i;
}
/*loop through the array of \ locations*/
i = j;
for (;;)
{
if (i >= 0 && !cant_make) /*;AC000;10*/
{
path[array[i]] = '\\';
if (mkdir(path))
{ display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG);/*;AN000;6*/
display_it(PRESS_ANY_KEY,STND_ERR_DEV,0,ANY_KEY_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;9*/
cant_make = TTRUE; /*;AN000;10*/
break; /*;AN000;10*/
}
--i;
}
else
break;
} /*end for loop */
chdir(path); /*;AN000;3*/
retcode = create_the_file(fflag,ea_offset); /*;AN000;3*/
return; /* wrw! */
}
/********************************************************/
/*
/* SUBROUTINE NAME: create_the_file
/*
/* DESCRIPTIVE NAME : Create the target file.
/* Use DOS 4.00 Extended Create Function 6C00h
/* Remember to handle Extended Attributes!
/*
/********************************************************/
#define EXTENDEDOPEN 0x6c00 /*;AN000;3*/
WORD create_the_file(fflag,ea_offset) /*;AN000;3*/
BYTE fflag; /*;AN000;3*/
DWORD ea_offset; /*;AN000;3*/
{ /*;AN000;3*/
WORD action; /*;AN000;3*/
WORD retcode; /*;AN000;3*/
union REGS reg; /*;AN000;3*/
struct parm_list ea_parmlist; /*;AN000;3 Parameter list for extended open*/
if ((fflag & EXT_ATTR_FLAG) == EXT_ATTR_FLAG) /*;AN000;3*/
read_the_extended_attributes(ea_offset); /*;AN000;3*/
ea_parmlist.ext_attr_addr = (DWORD)(char far *)&ext_attrib_buff[0];/*;AN000;3*/
ea_parmlist.num_additional = 0; /*;AN000;3*/
retcode = NOERROR; /*;AN000;3*/
reg.x.ax = EXTENDEDOPEN; /* Function */ /*;AN000;3*/
reg.x.bx = 0x2011; /* Mode */ /*;AN000;3*/
reg.x.bx = 0x0081; /* Mode */ /*;AN000;3*/
reg.x.cx = 0; /* Attribute */ /*;AN000;3*/
reg.x.dx = 0x112; /* Flag */ /*;AN000;3*/
reg.x.si = (WORD)&dest_file_spec[0]; /* Filename */ /*;AN000;3*/
if ((fflag & EXT_ATTR_FLAG) == EXT_ATTR_FLAG) /*;AN000;3*/
reg.x.di = (WORD)&ea_parmlist; /* Parmlist */ /*;AN000;3*/
else
reg.x.di = 0xffff; /* No parmlist */ /*;AN000;3*/
intdos(®,®); /*;AN000;3*/
if (reg.x.cflag & CARRY) /* If there was an error /*;AN000;3*/
retcode = reg.x.ax; /* then set return code /*;AN000;3*/
dest_file_handle = reg.x.ax; /*;AN000;3*/
return(retcode); /*;AN000;3*/
} /*;AN000;3*/
/********************************************************/
/*
/* SUBROUTINE NAME: read_the_extended_attributes
/*
/* DESCRIPTIVE NAME : reads in the extended attributes
/*
/********************************************************/
void read_the_extended_attributes(ea_offset) /*;AN000;3*/
DWORD ea_offset; /*;AN000;3*/
{ /*;AN000;3*/
WORD ea_len; /*;AN000;3*/
DWORD file_position; /*;AN000;3*/
WORD read_count; /*;AN000;3*/
WORD retcode; /*;AN000;3*/
/*******************************/
/* Seek to Extended Attributes */
retcode = /*;AN000;3*/
DOSCHGFILEPTR /*;AN000;3*/
( /*;AN000;3*/
src_file_handle, /* Handle */ /*;AN000;3*/
ea_offset, /* New location */ /*;AN000;3*/
(BYTE)0, /* MOVE METHOD */ /*;AN000;3*/
(DWORD far *)&file_position /*;AN000;3*/
); /*;AN000;3*/
/*************************************/
/* Read in Extended Attribute length */
retcode = /*;AN000;3*/
DOSREAD /*;AN000;3*/
( /*;AN000;3*/
src_file_handle, /*;AN000;3*/
(char far *)&ea_len, /*;AN000;3*/
(unsigned short)2, /*;AN000;3*/
(unsigned far *)&read_count /*;AN000;3*/
); /*;AN000;3*/
/***********************************/
/* Read in the Extended Attributes */
retcode = /*;AN000;3*/
DOSREAD /*;AN000;3*/
( /*;AN000;3*/
src_file_handle, /*;AN000;3*/
(char far *)&ext_attrib_buff[0], /*;AN000;3*/
(unsigned short)ea_len, /*;AN000;3*/
(unsigned far *)&read_count /*;AN000;3*/
); /*;AN000;3*/
return; /*;AN000;3*/
} /*;AN000;3*/
/**************** START OF SPECIFICATION ********************************
/*
/* SUBROUTINE NAME : set_attributes_and_close
/*
/* DESCRIPTIVE NAME : Set the file attributes and close the file
/*
/* FUNCTION: Set the attributes and last write date/time of the file just
/* restored to be like those of the backup file.
/*
/********************* END OF SPECIFICATIONS ********************************/
int set_attributes_and_close(finfo,destd)
struct file_info *finfo;
BYTE destd;
{
struct FileStatus fileinfo_buf;
WORD destdnum;
WORD buflen = sizeof(struct FileStatus);
WORD retcode;
destdnum = destd - 'A' + 1;
/************************************************************************/
/* call DosQFileInfo: Request date and time of the dest file */
/************************************************************************/
retcode = DOSQFILEINFO (
(unsigned)dest_file_handle, /* File handle */
(unsigned)1, /* File info data required */
(char far *)&fileinfo_buf, /* File info buffer */
(unsigned)buflen); /* File info buffer size */
/*if fail, unexperror "file creation error"*/
if (retcode != NOERROR)
{ display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
usererror(retcode);
}
/************************************************************************/
/* call DosSetFileInfo: Set date and time in dest file as the same date */
/* and time in finfo */
/************************************************************************/
fileinfo_buf.write_date = finfo->fdate;
fileinfo_buf.write_time = finfo->ftime;
retcode = DOSSETFILEINFO (
(unsigned)dest_file_handle, /* File handle */
(unsigned)1, /* File info data required */
(char far *)&fileinfo_buf, /* File info buffer */
(unsigned)buflen); /* File info buffer size */
/*if fail, unexperror "file creation error"*/
if (retcode != NOERROR)
{ display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
usererror(retcode);
}
/******************************************************************/
/*close dest file */
/******************************************************************/
DOSCLOSE(dest_file_handle);
/******************************************************************/
/*DosSetFileMode to set file attrib of d:infspec(from input line) */
/*to be the attrib in finfo structure */
/******************************************************************/
finfo->attrib = finfo->attrib & 0xffdf;
retcode =
DOSSETFILEMODE
(
(char far *)dest_file_spec,
(unsigned) finfo->attrib, (DWORD) 0
);
/******************************************************************/
/*reset flag PARTIAL */
/******************************************************************/
set_reset_test_flag(&control_flag,PARTIAL,RESET);
return(0); /* wrw! */
} /*end of subroutine*/
/**************** START OF SPECIFICATION ********************************
/*
/* SUBROUTINE NAME : dos_write_error
/*
/* DESCRIPTIVE NAME : Determine the cause of the error during
/* DOS write, and output message according to it.
/*
/* FUNCTION: If error returned from get free space of the disk
/* is caused by disk full, a message "target disk is
/* full" is output to the user.
/* Otherwise, the error is caused by other reason, and
/* a message "file creation error" is output to the user.
/*
/*
/********************** END OF SPECIFICATIONS *******************************/
int dos_write_error(buf_size,destd)
DWORD buf_size;
BYTE destd;
{
DWORD free_space;
WORD drive_num;
struct fsinfo *fsinfo_buf;
WORD retcode;
/******************************************************************/
/*DosQFsinfo: get free space in the hard disk */
/******************************************************************/
drive_num = destd - 'A' + 1;
retcode = DOSQFSINFO
((unsigned)drive_num, /* Drive number - 0=default, 1=A, etc */
(unsigned)1, /* File system info required */
(char far *)fsinfo_buf, /* File system info buffer */
(unsigned)FSINFO_BYTES /* File system info buffer size */
);
free_space = fsinfo_buf->sectors_per_alloc_unit *
fsinfo_buf->available_alloc_unit *
fsinfo_buf->bytes_per_sector;
/******************************************************************/
/*if the free space left is less than buffer size for file read */
/* and write, output msg "target is full", and "file creation */
/* error", otherwise, output "file creation error". */
/******************************************************************/
if ( free_space < buf_size)
{ display_it(TARGET_IS_FULL,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
/*close dest file*/
DOSCLOSE(dest_file_handle);
if ((retcode = DOSDELETE((char far *)&dest_file_spec[0],
(DWORD)0)) != 0)
{
/*set file mode to 0*/
retcode =
DOSSETFILEMODE
(
(char far *)&dest_file_spec[0],
(unsigned) 0x00,
(DWORD)0
);
/* delete the partially completed destination file*/
retcode = DOSDELETE((char far *) dest_file_spec,(DWORD)0);
}
display_it(LAST_FILE_NOT_RESTORED,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
usererror(TARGETFULL);
}
else
{ display_it(FILE_CREATION_ERROR,STND_ERR_DEV,0,NO_RESPTYPE,(BYTE)UTIL_MSG); /*;AN000;6*/
usererror(CREATIONERROR);
}
/*endif*/
return(0); /* wrw! */
}/*end of subroutine*/
|