source: trunk/dll/copyf.c@ 1664

Last change on this file since 1664 was 1664, checked in by Gregg Young, 13 years ago

Changes to use Unlock to unlock files if Unlock.exe is in path both from menu/toolbar and as part of copy, move and delete operations. Changes to allow copy and move over readonly files with a warning dialog; also added a warning dialog for delete of readonly files

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