source: trunk/dll/copyf.c@ 1877

Last change on this file since 1877 was 1877, checked in by Gregg Young, 10 years ago

Remove debug code

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