source: trunk/dll/copyf.c@ 1844

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

Changes to allow a JAVA executable object to be created using "Real object" menu item on a jar file. (Ticket [37]) Eliminate redundant prompts and error messages when telling FM/2 not to delete a R/O file. (Ticket [548]) Limit attempts to unlock files to exes and dlls. (Ticket [549])

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