source: trunk/dll/copyf.c@ 1849

Last change on this file since 1849 was 1849, checked in by John Small, 10 years ago

Ticket 522: Change calls to "highmem-unsafe" Dos... functions to wrapped xDos...

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