source: trunk/dll/copyf.c@ 1785

Last change on this file since 1785 was 1785, checked in by Gregg Young, 11 years ago

Comments for 1784

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.2 KB
Line 
1
2/***********************************************************************
3
4 $Id: copyf.c 1785 2014-07-19 21:18:34Z gyoung $
5
6 Copy functions
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2001, 2009 Steven H.Levine
10
11 14 Sep 02 SHL Drop obsolete debug code
12 14 Oct 02 SHL Drop obsolete debug code
13 10 Nov 02 SHL docopyf - don't forget to terminate longname
14 optimize longname logic
15 01 Aug 04 SHL Rework lstrip/rstrip usage
16 28 May 05 SHL Drop debug code
17 14 Jul 06 SHL Use Runtime_Error
18 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
19 01 Sep 07 GKY Use xDosSetPathInfo to fix case where FS3 buffer crosses 64k boundry
20 29 Feb 08 GKY Use xfree where appropriate
21 19 Jul 08 GKY Modify MakeTempName for use making temp directory names
22 08 Mar 09 GKY Removed variable aurguments from docopyf and unlinkf (not used)
23 28 Jun 09 GKY Added AddBackslashToPath() to remove repeatative code.
24 12 Jul 09 GKY Add xDosQueryAppType and xDosAlloc... to allow FM/2 to load in high memory
25 13 Jul 09 SHL Drop obsolete code
26 22 Jul 09 GKY Delete .LONGNAME EA if it becomes the filename on a copy or move.
27 19 Oct 09 SHL Correct copyf regression when moving to save volume
28 31 Mar 10 JBS Correct copyf which was creating 8.4, not 8.3, temporary names
29 26 Aug 11 GKY Add a low mem version of xDosAlloc* wrappers; move error checking into all the
30 xDosAlloc* wrappers.
31 04 Aug 12 GKY Changes to use Unlock to unlock files if Unlock.exe is in path both from menu/toolbar and as part of copy, move and
32 delete operations
33 04 Aug 12 GKY Changes to allow copy and move over readonly files with a warning dialog; also added a warning dialog for delete of
34 readonly files
35 10 Mar 13 GKY Improvrd readonly check on delete to allow cancel and don't ask again options
36 09 Feb 14 GKY Modified wipeallf to allow suppression of the readonly warning on delete
37 of temporary files
38 16 Feb 14 GKY Rework readonly check on delete code so it actually works in a logical way
39 and so it works with move to trashcan inabled.
40 22 Feb 14 GKY Fix wipeallf to recurss properly
41 22 Feb 14 GKY Fix warn readonly yes don't ask to work when recursing directories.
42 19 Jul 14 GKY Fix redundant error message following selection of no for unlocking a file
43
44***********************************************************************/
45
46#include <stdlib.h>
47#include <string.h>
48#include <stdarg.h>
49#include <ctype.h>
50
51#define INCL_DOS
52#define INCL_DOSERRORS
53#define INCL_WIN
54#define INCL_LONGLONG
55
56#include "fm3dll.h"
57#include "fm3dll2.h" // #define's for UM_*, control id's, etc.
58#include "killproc.h" // Data declaration(s)
59#include "notebook.h" // Data declaration(s)
60#include "info.h" // Data declaration(s)
61#include "init.h" // Data declaration(s)
62#include "arccnrs.h"
63#include "fm3str.h"
64#include "errutil.h" // Dos_Error...
65#include "strutil.h" // GetPString
66#include "copyf.h"
67#include "literal.h" // fixup
68#include "misc.h" // Broadcast
69#include "valid.h" // MakeFullName
70#include "wrappers.h" // xDosSetPathInfo
71#include "strips.h" // bstrip
72#include "fortify.h"
73#include "pathutil.h" // AddBackslashToPath
74#include "worker.h"
75#include "systemf.h"
76
77static PSZ pszSrcFile = __FILE__;
78
79static CHAR *GetLongName(CHAR * oldname, CHAR * buffer);
80static CHAR *TruncName(CHAR * oldname, CHAR * buffer);
81
82BOOL ignorereadonly = FALSE;
83
84//static CHAR default_disk(VOID);
85//static INT unlink_allf(CHAR * string, ...);
86
87#ifndef WinMoveObject
88HOBJECT APIENTRY WinMoveObject(HOBJECT hObjectofObject,
89 HOBJECT hObjectofDest, ULONG ulReserved);
90#endif
91#ifndef WinCopyObject
92HOBJECT APIENTRY WinCopyObject(HOBJECT hObjectofObject,
93 HOBJECT hObjectofDest, ULONG ulReserved);
94#endif
95
96/**
97 * Make temporary file name
98 * @param buffer is input directory name and output file name buffer
99 * @param temproot is filename root used by type 2
100 * @param type is name style
101 * @return pointer to name in buffer or NULL if failed
102 * @note not MT safe
103 */
104
105PSZ MakeTempName(PSZ buffer, PSZ temproot, INT type)
106{
107 FILESTATUS3 fs3;
108 APIRET rc;
109 PSZ p;
110 PSZ o;
111
112 if (strlen(buffer) > 3)
113 AddBackslashToPath(buffer);
114 p = o = buffer + strlen(buffer);
115 switch (type) {
116 case 0:
117 sprintf(p, "%08lx.%03lx", (UINT)mypid, (UINT)rand() & 4095L); // 4095 = 0x0FFF
118 break;
119 case 1:
120 sprintf(p, "%s%04lx.%03lx", "$FM2", (UINT)mypid, (UINT)rand() & 4095L); // 4095 = 0x0FFF
121 break;
122 case 2:
123 sprintf(p, "%s.%03x", temproot, (UINT)(rand() & 4095)); // 4095 = 0x0FFF
124 break;
125 default:
126 break;
127 }
128 p = buffer + (strlen(buffer) - 1);
129 for (;;) {
130 DosError(FERR_DISABLEHARDERR);
131 rc = DosQueryPathInfo(buffer, FIL_STANDARD, &fs3, sizeof(fs3));
132 if (rc == ERROR_DISK_CHANGE) {
133 DosError(FERR_ENABLEHARDERR);
134 rc = DosQueryPathInfo(buffer, FIL_STANDARD, &fs3, sizeof(fs3));
135 }
136 if (rc)
137 break;
138 Loop:
139 if (p < o) {
140 *buffer = 0;
141 return NULL;
142 }
143 if ((*p) + 1 < 'Z' + 1) {
144 (*p)++;
145 while (strchr("*?<>\":/\\|+=;,[]. ", *p))
146 (*p)++;
147 *p = toupper(*p);
148 }
149 else {
150 p--;
151 if (p >= o && *p == '.')
152 p--;
153 goto Loop;
154 }
155 }
156 return buffer;
157}
158
159CHAR *TruncName(CHAR * oldname, CHAR * buffer)
160{
161 CHAR *p, *f, *s, *o;
162 FILESTATUS3 fs3;
163 APIRET rc;
164
165 if (!buffer || !oldname || !*oldname) {
166 if (buffer)
167 *buffer = 0;
168 return NULL;
169 }
170 strcpy(buffer, oldname);
171 f = strrchr(buffer, '\\');
172 if (!f)
173 f = strrchr(buffer, '/');
174 if (!f)
175 f = buffer;
176 else
177 f++;
178 p = f;
179 o = p;
180 f = oldname + (f - buffer);
181 strupr(buffer);
182 while (*f == '.')
183 f++; // skip leading '.'s
184 s = f;
185 // skip past rootname
186 while (*f && *f != '.' && f < s + 8) {
187 *p = toupper(*f);
188 p++;
189 f++;
190 }
191 while (*f == '.')
192 f++;
193 s = f;
194 f = strrchr(f, '.');
195 if (f) {
196 while (*f == '.')
197 f++;
198 }
199 if (f && *(f + 1))
200 s = f;
201 else
202 f = s;
203 if (*f) {
204 *p = '.';
205 p++;
206 while (*f && *f != '.' && f < s + 3) {
207 *p = toupper(*f);
208 p++;
209 f++;
210 }
211 }
212 *p = 0;
213
214 p = o;
215 while (*p) {
216 if (strchr("*?<>\":/\\|+=;,[] ", *p) || *p < 0x20)
217 *p = '_';
218 if (*p == '.' && *(p + 1) == '.')
219 *(p + 1) = '_';
220 p++;
221 }
222
223 p = o + (strlen(o) - 1);
224 for (;;) {
225 DosError(FERR_DISABLEHARDERR);
226 rc = DosQueryPathInfo(buffer, FIL_STANDARD, &fs3, sizeof(fs3));
227 if (rc == ERROR_DISK_CHANGE) {
228 DosError(FERR_ENABLEHARDERR);
229 rc = DosQueryPathInfo(buffer, FIL_STANDARD, &fs3, sizeof(fs3));
230 }
231 if (rc)
232 break;
233 Loop:
234 if (p < o) {
235 *buffer = 0;
236 return NULL;
237 }
238 if ((*p) + 1 < 'Z' + 1) {
239 (*p)++;
240 while (strchr("*?<>\":/\\|+=;,[]. ", *p))
241 (*p)++;
242 *p = toupper(*p);
243 }
244 else {
245 p--;
246 if (p >= o && *p == '.')
247 p--;
248 goto Loop;
249 }
250 }
251 return buffer;
252}
253
254CHAR *GetLongName(CHAR * oldname, CHAR * longname)
255{
256 if (!longname)
257 return NULL;
258 *longname = 0;
259 if (!oldname || !*oldname)
260 return NULL;
261 if (IsFullName(oldname)) {
262
263 APIRET rc;
264 EAOP2 eaop;
265 PGEA2LIST pgealist;
266 PFEA2LIST pfealist;
267 PGEA2 pgea;
268 PFEA2 pfea;
269 CHAR *value;
270
271 strcpy(longname, oldname);
272 value = longname;
273 while (*value) {
274 if (*value == '/')
275 *value = '\\';
276 value++;
277 }
278 value = strrchr(longname, '\\');
279 if (value) {
280 value++;
281 *value = 0;
282 }
283 pgealist = xmallocz(sizeof(GEA2LIST) + 32, pszSrcFile, __LINE__);
284 if (pgealist) {
285 pgea = &pgealist->list[0];
286 strcpy(pgea->szName, LONGNAME);
287 pgea->cbName = strlen(pgea->szName);
288 pgea->oNextEntryOffset = 0L;
289 pgealist->cbList = (sizeof(GEA2LIST) + pgea->cbName);
290 pfealist = xmallocz(1536, pszSrcFile, __LINE__);
291 if (pfealist) {
292 pfealist->cbList = 1024;
293 eaop.fpGEA2List = pgealist;
294 eaop.fpFEA2List = pfealist;
295 eaop.oError = 0L;
296 DosError(FERR_DISABLEHARDERR);
297 rc = DosQueryPathInfo(oldname,
298 FIL_QUERYEASFROMLIST,
299 (PVOID) & eaop, (ULONG) sizeof(EAOP2));
300 if (!rc) {
301 pfea = &eaop.fpFEA2List->list[0];
302 value = pfea->szName + pfea->cbName + 1;
303 value[pfea->cbValue] = 0;
304 if (*(USHORT *) value == EAT_ASCII)
305 strncat(longname,
306 value + (sizeof(USHORT) * 2),
307 CCHMAXPATH - strlen(longname));
308 longname[CCHMAXPATH - 1] = 0;
309 }
310 free(pfealist);
311 }
312 free(pgealist);
313 }
314 }
315 return longname;
316}
317
318BOOL ZapLongName(PSZ filename)
319{
320 return WriteLongName(filename, NullStr);
321}
322
323BOOL WriteLongName(CHAR * filename, CHAR * longname)
324{
325 APIRET rc;
326 EAOP2 eaop;
327 PFEA2LIST pfealist = NULL;
328 ULONG ealen;
329 USHORT len;
330 CHAR *eaval, *p;
331
332 if (!filename || !*filename || !longname)
333 return FALSE;
334 p = strrchr(longname, '\\');
335 if (p)
336 memmove(longname, p + 1, strlen(p + 1) + 1);
337 p = strrchr(longname, '/');
338 if (p)
339 memmove(longname, p + 1, strlen(p + 1) + 1);
340 bstrip(longname);
341 len = strlen(longname);
342 if (len)
343 ealen = sizeof(FEA2LIST) + 10 + len + 4;
344 else
345 ealen = sizeof(FEALIST) + 10;
346 if (xDosAllocMem((PPVOID) &pfealist, ealen + 32L, pszSrcFile, __LINE__))
347 return FALSE;
348 else {
349 memset(pfealist, 0, ealen + 1);
350 pfealist->cbList = ealen;
351 pfealist->list[0].oNextEntryOffset = 0;
352 pfealist->list[0].fEA = 0;
353 pfealist->list[0].cbName = 9;
354 strcpy(pfealist->list[0].szName, LONGNAME);
355 if (len) {
356 eaval = pfealist->list[0].szName + 10;
357 *(USHORT *) eaval = (USHORT) EAT_ASCII;
358 eaval += sizeof(USHORT);
359 *(USHORT *) eaval = (USHORT) len;
360 eaval += sizeof(USHORT);
361 memcpy(eaval, longname, len);
362 pfealist->list[0].cbValue = len + (sizeof(USHORT) * 2);
363 }
364 else
365 pfealist->list[0].cbValue = 0;
366 eaop.fpGEA2List = (PGEA2LIST) 0;
367 eaop.fpFEA2List = pfealist;
368 eaop.oError = 0L;
369 DosError(FERR_DISABLEHARDERR);
370 rc = xDosSetPathInfo(filename, FIL_QUERYEASIZE,
371 &eaop, sizeof(eaop), DSPI_WRTTHRU);
372 DosFreeMem(pfealist);
373 if (rc)
374 return FALSE;
375 }
376 return TRUE;
377}
378
379BOOL AdjustWildcardName(CHAR * oldname, CHAR * newname)
380{
381 BOOL ret = FALSE;
382
383 // NOTE: newname should be CCHMAXPATH chars long!
384
385 if (strchr(newname, '*') || strchr(newname, '?')) {
386
387 CHAR srce[CCHMAXPATHCOMP], dest[CCHMAXPATHCOMP], result[CCHMAXPATHCOMP],
388 *p;
389
390 p = strrchr(newname, '\\');
391 if (p && *(p + 1)) {
392 strcpy(dest, p + 1);
393 p = strrchr(oldname, '\\');
394 if (p && *(p + 1)) {
395 strcpy(srce, p + 1);
396 DosError(FERR_DISABLEHARDERR);
397 if (!DosEditName(1L, srce, dest, (PBYTE)result, (ULONG)sizeof(result))) {
398 p = strrchr(newname, '\\');
399 p++;
400 strcpy(p, result);
401 ret = TRUE;
402 }
403 }
404 }
405 }
406 return ret;
407}
408
409/** Copy/move file
410 * @param type is copy/move type
411 * @param oldname is fully qualified source file name
412 * @param newname is fully qualified destination file name
413 * @return
414 * 0: success
415 * -1: bad parameter(s)
416 * -2: source does not exist
417 * -3: bad copy/move type
418 * anything else: API return
419 */
420
421APIRET docopyf(INT type, CHAR *oldname, CHAR *newname)
422{
423 CHAR longname[CCHMAXPATH], shortname[CCHMAXPATH];
424 CHAR olddisk, newdisk, dir[CCHMAXPATH], *p, *pp;
425 APIRET ret = -1, rc;
426 FILESTATUS3L st, st2, dummy;
427 BOOL diskchange = FALSE, zaplong = FALSE;
428
429 *shortname = *dir = 0;
430
431 if (!oldname || !*oldname || !*newname)
432 return (APIRET)-1; // bad args
433
434 DosError(FERR_DISABLEHARDERR);
435 if (DosQueryPathInfo(oldname, FIL_STANDARDL, &st, sizeof(FILESTATUS3L)))
436 return (APIRET)-2; // can not access source
437
438 AdjustWildcardName(oldname, newname);
439 MakeFullName(oldname);
440 MakeFullName(newname);
441 olddisk = toupper(*oldname); // source drive
442 newdisk = toupper(*newname); // destination drive
443 if (!(driveflags[toupper(*oldname) - 'A'] & DRIVE_NOLONGNAMES))
444 *longname = 0;
445 else {
446 GetLongName(oldname, longname);
447 if (*longname) {
448 p = RootName(longname);
449 if (p != longname)
450 memmove(longname, p, strlen(p) + 1);
451 }
452 }
453 // If root name changed make sure longname EA goes away
454 if (*longname) {
455 p = RootName(oldname);
456 pp = RootName(longname);
457 if (stricmp(p, pp)) {
458 zaplong = TRUE;
459 }
460 }
461
462 DosError(FERR_DISABLEHARDERR);
463 switch (type) {
464 case WPSMOVE:
465 {
466 HOBJECT hobjsrc;
467 HOBJECT hobjdest;
468
469 ret = ERROR_FILE_NOT_FOUND;
470 hobjsrc = WinQueryObject(oldname);
471 if (hobjsrc) {
472 strcpy(dir, newname);
473 p = strrchr(dir, '\\');
474 if (p < dir + 3)
475 p++;
476 *p = 0;
477 ret = ERROR_PATH_NOT_FOUND;
478 hobjdest = WinQueryObject(dir);
479 if (hobjdest) {
480 ret = ERROR_GEN_FAILURE;
481 hobjsrc = WinMoveObject(hobjsrc, hobjdest, 0);
482 if (hobjsrc)
483 ret = 0;
484 }
485 }
486 }
487 return ret;
488
489 case WPSCOPY:
490 {
491 HOBJECT hobjsrc;
492 HOBJECT hobjdest;
493
494 ret = ERROR_FILE_NOT_FOUND;
495 hobjsrc = WinQueryObject(oldname);
496 if (hobjsrc) {
497 strcpy(dir, newname);
498 p = strrchr(dir, '\\');
499 if (p < dir + 3)
500 p++;
501 *p = 0;
502 ret = ERROR_PATH_NOT_FOUND;
503 hobjdest = WinQueryObject(dir);
504 if (hobjdest) {
505 ret = ERROR_GEN_FAILURE;
506 hobjsrc = WinCopyObject(hobjsrc, hobjdest, 0);
507 if (hobjsrc)
508 ret = 0;
509 }
510 }
511 }
512 return ret;
513
514 case MOVE:
515 *dir = 0;
516 if (olddisk == newdisk) {
517 // Moving to same drive
518 // make temporary copy in case move fails
519 if (IsFile(newname) != -1 && stricmp(oldname, newname)) {
520 // 19 Oct 09 SHL correct regression
521 strcpy(dir, newname);
522 p = strrchr(dir, '\\');
523 if (p)
524 *p = 0;
525 AddBackslashToPath(dir);
526 MakeTempName(dir, NULL, 0);
527 if (DosMove(newname, dir))
528 *dir = 0; // Avoid trying to restore bad copy
529 }
530 DosError(FERR_DISABLEHARDERR);
531 ret = DosMove(oldname, newname); // move it
532 if (ret && *dir) { // failed -- clean up
533 DosError(FERR_DISABLEHARDERR);
534 if (!DosMove(dir, newname))
535 Broadcast((HAB) 0, hwndMain, UM_UPDATERECORD, MPFROMP(dir), MPVOID);
536 }
537 else if (!ret && *dir) {
538 if (!IsFile(dir)) {
539 if (!strchr(dir, '?') && !strchr(dir, '*'))
540 wipeallf(TRUE, "%s\\*", dir);
541 DosError(FERR_DISABLEHARDERR);
542 if (DosDeleteDir(dir)) {
543 make_deleteable(dir, -1, TRUE);
544 DosDeleteDir(dir);
545 }
546 }
547 else if (IsFile(dir) > 0) {
548 APIRET error;
549
550 DosError(FERR_DISABLEHARDERR);
551 error = DosForceDelete(dir);
552 if (error) {
553 make_deleteable(dir, error, TRUE);
554 DosForceDelete(dir);
555 }
556 if (zaplong) {
557 ret = ZapLongName(dir);
558 }
559 Broadcast((HAB) 0, hwndMain, UM_UPDATERECORD, MPFROMP(dir), MPVOID);
560 }
561 }
562 }
563 else {
564 // Moving to different drive
565 DosError(FERR_DISABLEHARDERR);
566 ret = DosCopy(oldname, newname, DCPY_EXISTING); // <=-NOTE!
567 if (ret == ERROR_DISK_CHANGE) {
568 DosError(FERR_ENABLEHARDERR);
569 ret = DosCopy(oldname, newname, DCPY_EXISTING);
570 diskchange = TRUE;
571 }
572 if (ret == ERROR_INVALID_NAME || ret == ERROR_FILENAME_EXCED_RANGE) {
573 if (TruncName(newname, shortname)) {
574 // make 8.3 filename
575 DosError(FERR_DISABLEHARDERR);
576 ret = DosCopy(oldname, shortname, DCPY_EXISTING);
577 if (!ret) {
578 // success -- write longname ea
579 WriteLongName(shortname, newname);
580 strcpy(newname, shortname);
581 // broadcast fixup msg to windows
582 Broadcast((HAB) 0,
583 hwndMain, UM_UPDATERECORD, MPFROMP(shortname), MPVOID);
584 }
585 }
586 }
587 else if (!ret && *longname) {
588
589 CHAR fixname[CCHMAXPATH];
590
591 strcpy(fixname, newname);
592 p = strrchr(fixname, '\\');
593 if (p) {
594 p++;
595 *p = 0;
596 }
597 strcat(fixname, longname);
598 DosError(FERR_DISABLEHARDERR);
599 DosMove(newname, fixname);
600 strcpy(newname, fixname);
601 if (zaplong)
602 ZapLongName(fixname);
603 Broadcast((HAB) 0,
604 hwndMain, UM_UPDATERECORD, MPFROMP(fixname), MPVOID);
605 }
606 if (!ret) {
607 // double-check success
608 DosError(FERR_DISABLEHARDERR);
609 rc = DosQueryPathInfo(newname,
610 FIL_STANDARDL, &st2, sizeof(FILESTATUS3L));
611 if (rc == ERROR_DISK_CHANGE) {
612 DosError(FERR_ENABLEHARDERR);
613 rc = DosQueryPathInfo(newname,
614 FIL_STANDARDL, &st2, sizeof(FILESTATUS3L));
615 }
616 if (!rc && st2.cbFile == st.cbFile) {
617 // seems to have worked...
618 DosError(FERR_DISABLEHARDERR);
619 if (diskchange) {
620 DosError(FERR_ENABLEHARDERR);
621 DosQueryPathInfo(oldname, FIL_STANDARDL, &dummy, sizeof(FILESTATUS3L)); // force disk change
622 }
623 if (!(st2.attrFile & FILE_DIRECTORY))
624 unlinkf(oldname); // erase file
625 else {
626 // remove directory
627 wipeallf(TRUE, "%s\\*", oldname);
628 DosError(FERR_DISABLEHARDERR);
629 if (DosDeleteDir(oldname)) {
630 make_deleteable(oldname, -1, TRUE);
631 DosDeleteDir(oldname);
632 }
633 }
634 }
635 }
636 }
637 return ret;
638
639 case COPY:
640 DosError(FERR_DISABLEHARDERR);
641 ret = DosCopy(oldname, newname, DCPY_EXISTING); // <=-NOTE!
642 if (ret == ERROR_DISK_CHANGE) {
643 DosError(FERR_ENABLEHARDERR);
644 ret = DosCopy(oldname, newname, DCPY_EXISTING);
645 diskchange = TRUE;
646 }
647 if (ret == ERROR_INVALID_NAME || ret == ERROR_FILENAME_EXCED_RANGE) {
648 if (TruncName(newname, shortname)) {
649 DosError((diskchange) ? FERR_ENABLEHARDERR : FERR_DISABLEHARDERR);
650 ret = DosCopy(oldname, shortname, DCPY_EXISTING);
651 if (!ret) {
652 WriteLongName(shortname, newname);
653 strcpy(newname, shortname);
654 Broadcast((HAB) 0,
655 hwndMain, UM_UPDATERECORD, MPFROMP(shortname), MPVOID);
656 }
657 }
658 }
659 else if (!ret && *longname) {
660
661 CHAR fixname[CCHMAXPATH];
662
663 strcpy(fixname, newname);
664 p = strrchr(fixname, '\\');
665 if (p) {
666 p++;
667 *p = 0;
668 }
669 strcat(fixname, longname);
670 DosError(FERR_DISABLEHARDERR);
671 DosMove(newname, fixname);
672 if (zaplong)
673 ZapLongName(fixname);
674 Broadcast((HAB) 0, hwndMain, UM_UPDATERECORD, MPFROMP(fixname), MPVOID);
675 }
676 return ret;
677
678 default:
679 // shouldn't happen
680 Runtime_Error(pszSrcFile, __LINE__, "bad case %u", type);
681 break;
682 } // switch type
683 Runtime_Error(pszSrcFile, __LINE__, "copy/move type %u unexpected", type);
684 return (APIRET)-3; // bad copy/move type
685}
686
687INT make_deleteable(CHAR * filename, INT error, BOOL Dontcheckreadonly)
688{
689 APIRET rc;
690 INT ret = -1;
691 INT retrn;
692 FILESTATUS3 fsi;
693
694 //DbgMsg(pszSrcFile, __LINE__, "error %i ", error);
695 DosError(FERR_DISABLEHARDERR);
696 rc = DosQueryPathInfo(filename, FIL_STANDARD, &fsi, sizeof(fsi));
697 if (!rc) {
698 if (fsi.attrFile & 0x00000001) {
699 if (fWarnReadOnly && !Dontcheckreadonly) {
700 retrn = saymsg2(NULL, 3,
701 HWND_DESKTOP,
702 GetPString(IDS_READONLYFILEWARNINGTITLE),
703 GetPString(IDS_READONLYFILEWARNING),
704 filename);
705 //DbgMsg(pszSrcFile, __LINE__, "retrn %x ", retrn);
706 ret = retrn;
707 if (retrn == SM2_YES || retrn == SM2_DONTASK)
708 fsi.attrFile = 0;
709 DosError(FERR_DISABLEHARDERR);
710 if (xDosSetPathInfo(filename, FIL_STANDARD, &fsi, sizeof(fsi), 0))
711 ret = -1; // failed
712 }
713 else {
714 fsi.attrFile = 0;
715 DosError(FERR_DISABLEHARDERR);
716 if (!xDosSetPathInfo(filename, FIL_STANDARD, &fsi, sizeof(fsi), 0))
717 ret = 0;
718 }
719 }
720 }
721 if (error == ERROR_SHARING_VIOLATION && fUnlock) {
722 retrn = saymsg(MB_YESNO | MB_DEFBUTTON2,
723 HWND_DESKTOP,
724 GetPString(IDS_LOCKEDFILEWARNINGTITLE),
725 GetPString(IDS_LOCKEDFILEWARNING),
726 filename);
727 if (retrn == MBID_YES) {
728 runemf2(SEPARATE | INVISIBLE | BACKGROUND | WAIT,
729 HWND_DESKTOP, pszSrcFile, __LINE__,
730 NULL, NULL, "%s %s", PCSZ_UNLOCKEXE, filename);
731 }
732 else
733 ret = SM2_NO;
734 }
735 //DbgMsg(pszSrcFile, __LINE__, "retrn %x ", ret);
736 return ret;
737}
738
739/**
740 * unlink everything from directory on down...
741 */
742
743INT wipeallf(BOOL ignorereadonly, CHAR *string, ...)
744{
745 FILEFINDBUF3 *f;
746 HDIR search_handle;
747 ULONG num_matches;
748 CHAR *p, *ss, *str;
749 CHAR s[CCHMAXPATH], mask[257];
750 va_list ap;
751 INT rc;
752
753 va_start(ap, string);
754 vsprintf(s, string, ap);
755 va_end(ap);
756
757 if (!*s)
758 return -1;
759 p = s;
760 while ((p = strchr(p, '/')) != NULL) {
761 *p = '\\';
762 p++;
763 }
764
765 str = xstrdup(s, pszSrcFile, __LINE__);
766 if (!str)
767 return -1;
768
769 {
770 // safety net -- disallow deleting a root dir or partial name
771 CHAR temp;
772 p = strrchr(str, '\\');
773 if (p) {
774 p++;
775 temp = *p;
776 *p = 0;
777 if (IsRoot(str) || !IsFullName(str)) {
778 // under no circumstances!
779 Runtime_Error(pszSrcFile, __LINE__, "bad name %s", str);
780 free(str);
781 return -1;
782 }
783 *p = temp;
784 }
785 }
786
787 p = s;
788 p = strrchr(s, '\\'); // strip s to just path
789 if (!p)
790 p = strrchr(s, ':');
791 if (p) {
792 p++;
793 strncpy(mask, p, 256);
794 mask[256] = 0;
795 *p = 0;
796 }
797 else {
798 *mask = 0;
799 *s = 0;
800 }
801
802 ss = xmalloc(CCHMAXPATH, pszSrcFile, __LINE__);
803 f = xmalloc(sizeof(FILEFINDBUF3), pszSrcFile, __LINE__);
804 if (!ss || !f) {
805 xfree(ss, pszSrcFile, __LINE__);
806 xfree(f, pszSrcFile, __LINE__);
807 free(str);
808 return -1;
809 }
810
811 search_handle = HDIR_CREATE;
812 num_matches = 1;
813
814 DosError(FERR_DISABLEHARDERR);
815 if (!DosFindFirst(str, &search_handle, FILE_NORMAL | FILE_DIRECTORY |
816 FILE_SYSTEM | FILE_READONLY | FILE_HIDDEN | FILE_ARCHIVED,
817 f, sizeof(FILEFINDBUF3), &num_matches, FIL_STANDARD)) {
818
819 strcpy(ss, s);
820 p = &ss[strlen(ss)];
821
822 do {
823 strcpy(p, f->achName);
824 if (f->attrFile & FILE_DIRECTORY) {
825 if (strcmp(f->achName, ".") && strcmp(f->achName, "..")) {
826 wipeallf(ignorereadonly, "%s/%s", ss, mask); // recurse to wipe files
827 DosError(FERR_DISABLEHARDERR);
828 // remove directory
829 if (DosDeleteDir(ss)) {
830 make_deleteable(ss, -1, TRUE); // Try harder
831 DosError(FERR_DISABLEHARDERR);
832 DosDeleteDir(ss);
833 }
834 }
835 }
836 else {
837 APIRET error;
838
839 DosError(FERR_DISABLEHARDERR);
840 error = DosForceDelete(ss);
841 if (error) {
842 INT retrn = 0;
843
844 retrn = make_deleteable(ss, error, ignorereadonly);
845 if (retrn == SM2_NO)
846 continue;
847 else if (retrn == SM2_DONTASK)
848 ignorereadonly = TRUE;
849 else if (retrn == SM2_CANCEL)
850 break;
851 DosError(FERR_DISABLEHARDERR);
852 rc = (INT) DosForceDelete(ss);
853 if (rc)
854 return rc;
855 }
856 }
857 num_matches = 1;
858 DosError(FERR_DISABLEHARDERR);
859 } while (!DosFindNext(search_handle, f, sizeof(FILEFINDBUF3),
860 &num_matches));
861 DosFindClose(search_handle);
862 }
863
864 free(f);
865 free(ss);
866 free(str);
867 ignorereadonly = FALSE;
868 return 0;
869}
870
871#if 0 // JBS 11 Sep 08 fixme to be gone
872INT unlink_allf(CHAR * string, ...)
873{
874 // wildcard delete
875 FILEFINDBUF3 *f;
876 HDIR search_handle;
877 ULONG num_matches;
878 CHAR *p, *ss, *str;
879 CHAR s[CCHMAXPATH];
880 va_list ap;
881 va_start(ap, string);
882 vsprintf(s, string, ap);
883 va_end(ap);
884
885 if (!*s)
886 return -1;
887 p = s;
888 while ((p = strchr(p, '/')) != NULL) {
889 *p = '\\';
890 p++;
891 }
892
893 str = xstrdup(s, pszSrcFile, __LINE__);
894 if (!str)
895 return -1;
896
897 p = s;
898 p = strrchr(s, '\\'); // strip s to just path
899 if (!p)
900 p = strrchr(s, ':');
901 if (p) {
902 p++;
903 *p = 0;
904 }
905 else
906 *s = 0;
907
908 ss = xmalloc(CCHMAXPATH, pszSrcFile, __LINE__);
909 f = xmalloc(sizeof(FILEFINDBUF3), pszSrcFile, __LINE__);
910 if (!ss || !f) {
911 xfree(ss, pszSrcFile, __LINE__);
912 xfree(f, pszSrcFile, __LINE__);
913 free(str);
914 return -1;
915 }
916
917 search_handle = HDIR_CREATE;
918 num_matches = 1;
919
920 DosError(FERR_DISABLEHARDERR);
921 if (!DosFindFirst(str, &search_handle, FILE_NORMAL, f,
922 sizeof(FILEFINDBUF3), &num_matches, FIL_STANDARD)) {
923
924 strcpy(ss, s);
925 p = &ss[strlen(ss)];
926
927 do {
928 strcpy(p, f->achName);
929 unlinkf("%s", ss);
930 num_matches = 1;
931 DosError(FERR_DISABLEHARDERR);
932 } while (!DosFindNext(search_handle, f, sizeof(FILEFINDBUF3),
933 &num_matches));
934 DosFindClose(search_handle);
935 }
936
937 free(f);
938 free(ss);
939 free(str);
940 return 0;
941}
942#endif
943
944/**
945 * Delete file
946 * @return OS/2 API error code or 0 if OK
947 */
948
949INT unlinkf(CHAR *string)
950{
951 if (!strstr(string, ArcTempRoot)) {
952 DosError(FERR_DISABLEHARDERR);
953 if (DosDelete(string)) {
954 make_deleteable(string, -1, TRUE);
955 DosError(FERR_DISABLEHARDERR);
956 return DosDelete(string);
957 }
958 }
959 else {
960 APIRET error;
961 INT ret;
962
963 DosError(FERR_DISABLEHARDERR);
964 error = DosForceDelete(string);
965 if (error) {
966 ret = make_deleteable(string, error, FALSE);
967 if (ret == SM2_CANCEL || ret == SM2_NO)
968 return 0;
969 DosError(FERR_DISABLEHARDERR);
970 return DosForceDelete(string);
971 }
972 }
973 return 0;
974}
975
976#pragma alloc_text(LONGNAMES,TruncName,GetLongName,WriteLongName)
977#pragma alloc_text(LONGNAMES,ZapLongName,AdjustWildcardName)
978#pragma alloc_text(COPYF,default_disk,docopyf,MakeTempName)
979#pragma alloc_text(UNLINKF,unlinkf,unlink_allf,make_deleteable,wipeallf)
Note: See TracBrowser for help on using the repository browser.