]> wirehaze git hosting - MS-DOS.git/blob - v4.0/src/CMD/RESTORE/RTFILE1.C

wirehaze git hosting

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