source: trunk/dll/copyf.c@ 1784

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

Eliminate redundant error message following selecting not to unlock a file. Ticket [542]

  • 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 1784 2014-07-19 21:16:11Z 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 else
732 ret = SM2_NO;
733 }
734 //DbgMsg(pszSrcFile, __LINE__, "retrn %x ", ret);
735 return ret;
736}
737
738/**
739 * unlink everything from directory on down...
740 */
741
742INT wipeallf(BOOL ignorereadonly, CHAR *string, ...)
743{
744 FILEFINDBUF3 *f;
745 HDIR search_handle;
746 ULONG num_matches;
747 CHAR *p, *ss, *str;
748 CHAR s[CCHMAXPATH], mask[257];
749 va_list ap;
750 INT rc;
751
752 va_start(ap, string);
753 vsprintf(s, string, ap);
754 va_end(ap);
755
756 if (!*s)
757 return -1;
758 p = s;
759 while ((p = strchr(p, '/')) != NULL) {
760 *p = '\\';
761 p++;
762 }
763
764 str = xstrdup(s, pszSrcFile, __LINE__);
765 if (!str)
766 return -1;
767
768 {
769 // safety net -- disallow deleting a root dir or partial name
770 CHAR temp;
771 p = strrchr(str, '\\');
772 if (p) {
773 p++;
774 temp = *p;
775 *p = 0;
776 if (IsRoot(str) || !IsFullName(str)) {
777 // under no circumstances!
778 Runtime_Error(pszSrcFile, __LINE__, "bad name %s", str);
779 free(str);
780 return -1;
781 }
782 *p = temp;
783 }
784 }
785
786 p = s;
787 p = strrchr(s, '\\'); // strip s to just path
788 if (!p)
789 p = strrchr(s, ':');
790 if (p) {
791 p++;
792 strncpy(mask, p, 256);
793 mask[256] = 0;
794 *p = 0;
795 }
796 else {
797 *mask = 0;
798 *s = 0;
799 }
800
801 ss = xmalloc(CCHMAXPATH, pszSrcFile, __LINE__);
802 f = xmalloc(sizeof(FILEFINDBUF3), pszSrcFile, __LINE__);
803 if (!ss || !f) {
804 xfree(ss, pszSrcFile, __LINE__);
805 xfree(f, pszSrcFile, __LINE__);
806 free(str);
807 return -1;
808 }
809
810 search_handle = HDIR_CREATE;
811 num_matches = 1;
812
813 DosError(FERR_DISABLEHARDERR);
814 if (!DosFindFirst(str, &search_handle, FILE_NORMAL | FILE_DIRECTORY |
815 FILE_SYSTEM | FILE_READONLY | FILE_HIDDEN | FILE_ARCHIVED,
816 f, sizeof(FILEFINDBUF3), &num_matches, FIL_STANDARD)) {
817
818 strcpy(ss, s);
819 p = &ss[strlen(ss)];
820
821 do {
822 strcpy(p, f->achName);
823 if (f->attrFile & FILE_DIRECTORY) {
824 if (strcmp(f->achName, ".") && strcmp(f->achName, "..")) {
825 wipeallf(ignorereadonly, "%s/%s", ss, mask); // recurse to wipe files
826 DosError(FERR_DISABLEHARDERR);
827 // remove directory
828 if (DosDeleteDir(ss)) {
829 make_deleteable(ss, -1, TRUE); // Try harder
830 DosError(FERR_DISABLEHARDERR);
831 DosDeleteDir(ss);
832 }
833 }
834 }
835 else {
836 APIRET error;
837
838 DosError(FERR_DISABLEHARDERR);
839 error = DosForceDelete(ss);
840 if (error) {
841 INT retrn = 0;
842
843 retrn = make_deleteable(ss, error, ignorereadonly);
844 if (retrn == SM2_NO)
845 continue;
846 else if (retrn == SM2_DONTASK)
847 ignorereadonly = TRUE;
848 else if (retrn == SM2_CANCEL)
849 break;
850 DosError(FERR_DISABLEHARDERR);
851 rc = (INT) DosForceDelete(ss);
852 if (rc)
853 return rc;
854 }
855 }
856 num_matches = 1;
857 DosError(FERR_DISABLEHARDERR);
858 } while (!DosFindNext(search_handle, f, sizeof(FILEFINDBUF3),
859 &num_matches));
860 DosFindClose(search_handle);
861 }
862
863 free(f);
864 free(ss);
865 free(str);
866 ignorereadonly = FALSE;
867 return 0;
868}
869
870#if 0 // JBS 11 Sep 08 fixme to be gone
871INT unlink_allf(CHAR * string, ...)
872{
873 // wildcard delete
874 FILEFINDBUF3 *f;
875 HDIR search_handle;
876 ULONG num_matches;
877 CHAR *p, *ss, *str;
878 CHAR s[CCHMAXPATH];
879 va_list ap;
880 va_start(ap, string);
881 vsprintf(s, string, ap);
882 va_end(ap);
883
884 if (!*s)
885 return -1;
886 p = s;
887 while ((p = strchr(p, '/')) != NULL) {
888 *p = '\\';
889 p++;
890 }
891
892 str = xstrdup(s, pszSrcFile, __LINE__);
893 if (!str)
894 return -1;
895
896 p = s;
897 p = strrchr(s, '\\'); // strip s to just path
898 if (!p)
899 p = strrchr(s, ':');
900 if (p) {
901 p++;
902 *p = 0;
903 }
904 else
905 *s = 0;
906
907 ss = xmalloc(CCHMAXPATH, pszSrcFile, __LINE__);
908 f = xmalloc(sizeof(FILEFINDBUF3), pszSrcFile, __LINE__);
909 if (!ss || !f) {
910 xfree(ss, pszSrcFile, __LINE__);
911 xfree(f, pszSrcFile, __LINE__);
912 free(str);
913 return -1;
914 }
915
916 search_handle = HDIR_CREATE;
917 num_matches = 1;
918
919 DosError(FERR_DISABLEHARDERR);
920 if (!DosFindFirst(str, &search_handle, FILE_NORMAL, f,
921 sizeof(FILEFINDBUF3), &num_matches, FIL_STANDARD)) {
922
923 strcpy(ss, s);
924 p = &ss[strlen(ss)];
925
926 do {
927 strcpy(p, f->achName);
928 unlinkf("%s", ss);
929 num_matches = 1;
930 DosError(FERR_DISABLEHARDERR);
931 } while (!DosFindNext(search_handle, f, sizeof(FILEFINDBUF3),
932 &num_matches));
933 DosFindClose(search_handle);
934 }
935
936 free(f);
937 free(ss);
938 free(str);
939 return 0;
940}
941#endif
942
943/**
944 * Delete file
945 * @return OS/2 API error code or 0 if OK
946 */
947
948INT unlinkf(CHAR *string)
949{
950 if (!strstr(string, ArcTempRoot)) {
951 DosError(FERR_DISABLEHARDERR);
952 if (DosDelete(string)) {
953 make_deleteable(string, -1, TRUE);
954 DosError(FERR_DISABLEHARDERR);
955 return DosDelete(string);
956 }
957 }
958 else {
959 APIRET error;
960 INT ret;
961
962 DosError(FERR_DISABLEHARDERR);
963 error = DosForceDelete(string);
964 if (error) {
965 ret = make_deleteable(string, error, FALSE);
966 if (ret == SM2_CANCEL || ret == SM2_NO)
967 return 0;
968 DosError(FERR_DISABLEHARDERR);
969 return DosForceDelete(string);
970 }
971 }
972 return 0;
973}
974
975#pragma alloc_text(LONGNAMES,TruncName,GetLongName,WriteLongName)
976#pragma alloc_text(LONGNAMES,ZapLongName,AdjustWildcardName)
977#pragma alloc_text(COPYF,default_disk,docopyf,MakeTempName)
978#pragma alloc_text(UNLINKF,unlinkf,unlink_allf,make_deleteable,wipeallf)
Note: See TracBrowser for help on using the repository browser.