source: trunk/dll/copyf.c@ 1686

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

GKY Improvrd readonly check on delete to allow cancel and don't ask again options; Added saymsg2 for this purpose; Fixes to snapshot file. cs 1685 contained the COMP.C changes

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