source: trunk/dll/copyf.c@ 1740

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

Fix wipeallf to recurse properly

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