source: trunk/dll/copyf.c@ 1741

Last change on this file since 1741 was 1741, checked in by Gregg Young, 12 years ago

Fix warn readonly yes don't ask to work when recursing directories.

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