source: trunk/dll/copyf.c@ 1878

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

Remove some dead code and comments source files starting with A-D

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