source: trunk/dll/copyf.c@ 1710

Last change on this file since 1710 was 1710, checked in by Gregg Young, 12 years ago

Actually commit the fix for suppressing the readonly warning on temp archive files. Ticket 497

  • 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 1710 2014-02-09 20:07:48Z 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(FALSE, "%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(FALSE, "%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(BOOL ignorereadonly, 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
747 va_start(ap, string);
748 vsprintf(s, string, ap);
749 va_end(ap);
750
751 if (!*s)
752 return -1;
753 p = s;
754 while ((p = strchr(p, '/')) != NULL) {
755 *p = '\\';
756 p++;
757 }
758
759 str = xstrdup(s, pszSrcFile, __LINE__);
760 if (!str)
761 return -1;
762
763 {
764 // safety net -- disallow deleting a root dir or partial name
765 CHAR temp;
766 p = strrchr(str, '\\');
767 if (p) {
768 p++;
769 temp = *p;
770 *p = 0;
771 if (IsRoot(str) || !IsFullName(str)) {
772 // under no circumstances!
773 Runtime_Error(pszSrcFile, __LINE__, "bad name %s", str);
774 free(str);
775 return -1;
776 }
777 *p = temp;
778 }
779 }
780
781 p = s;
782 p = strrchr(s, '\\'); // strip s to just path
783 if (!p)
784 p = strrchr(s, ':');
785 if (p) {
786 p++;
787 strncpy(mask, p, 256);
788 mask[256] = 0;
789 *p = 0;
790 }
791 else {
792 *mask = 0;
793 *s = 0;
794 }
795
796 ss = xmalloc(CCHMAXPATH, pszSrcFile, __LINE__);
797 f = xmalloc(sizeof(FILEFINDBUF3), pszSrcFile, __LINE__);
798 if (!ss || !f) {
799 xfree(ss, pszSrcFile, __LINE__);
800 xfree(f, pszSrcFile, __LINE__);
801 free(str);
802 return -1;
803 }
804
805 search_handle = HDIR_CREATE;
806 num_matches = 1;
807
808 DosError(FERR_DISABLEHARDERR);
809 if (!DosFindFirst(str, &search_handle, FILE_NORMAL | FILE_DIRECTORY |
810 FILE_SYSTEM | FILE_READONLY | FILE_HIDDEN | FILE_ARCHIVED,
811 f, sizeof(FILEFINDBUF3), &num_matches, FIL_STANDARD)) {
812
813 strcpy(ss, s);
814 p = &ss[strlen(ss)];
815
816 do {
817 strcpy(p, f->achName);
818 if (f->attrFile & FILE_DIRECTORY) {
819 if (strcmp(f->achName, ".") && strcmp(f->achName, "..")) {
820 wipeallf(FALSE, "%s/%s", ss, mask); // recurse to wipe files
821 DosError(FERR_DISABLEHARDERR);
822 // remove directory
823 if (DosDeleteDir(ss)) {
824 make_deleteable(ss, -1, TRUE); // Try harder
825 DosError(FERR_DISABLEHARDERR);
826 DosDeleteDir(ss);
827 }
828 }
829 }
830 else {
831 APIRET error;
832
833 DosError(FERR_DISABLEHARDERR);
834 error = DosForceDelete(ss);
835 if (error) {
836 INT retrn = 0;
837
838 retrn = make_deleteable(ss, error, ignorereadonly);
839 if (retrn == 3)
840 continue;
841 else if (retrn == 1)
842 ignorereadonly = TRUE;
843 DosError(FERR_DISABLEHARDERR);
844 rc = (INT) DosForceDelete(ss);
845 if (rc)
846 return rc;
847 }
848 }
849 num_matches = 1;
850 DosError(FERR_DISABLEHARDERR);
851 } while (!DosFindNext(search_handle, f, sizeof(FILEFINDBUF3),
852 &num_matches));
853 DosFindClose(search_handle);
854 }
855
856 free(f);
857 free(ss);
858 free(str);
859 ignorereadonly = FALSE;
860 return 0;
861}
862
863#if 0 // JBS 11 Sep 08 fixme to be gone
864INT unlink_allf(CHAR * string, ...)
865{
866 // wildcard delete
867 FILEFINDBUF3 *f;
868 HDIR search_handle;
869 ULONG num_matches;
870 CHAR *p, *ss, *str;
871 CHAR s[CCHMAXPATH];
872 va_list ap;
873 va_start(ap, string);
874 vsprintf(s, string, ap);
875 va_end(ap);
876
877 if (!*s)
878 return -1;
879 p = s;
880 while ((p = strchr(p, '/')) != NULL) {
881 *p = '\\';
882 p++;
883 }
884
885 str = xstrdup(s, pszSrcFile, __LINE__);
886 if (!str)
887 return -1;
888
889 p = s;
890 p = strrchr(s, '\\'); // strip s to just path
891 if (!p)
892 p = strrchr(s, ':');
893 if (p) {
894 p++;
895 *p = 0;
896 }
897 else
898 *s = 0;
899
900 ss = xmalloc(CCHMAXPATH, pszSrcFile, __LINE__);
901 f = xmalloc(sizeof(FILEFINDBUF3), pszSrcFile, __LINE__);
902 if (!ss || !f) {
903 xfree(ss, pszSrcFile, __LINE__);
904 xfree(f, pszSrcFile, __LINE__);
905 free(str);
906 return -1;
907 }
908
909 search_handle = HDIR_CREATE;
910 num_matches = 1;
911
912 DosError(FERR_DISABLEHARDERR);
913 if (!DosFindFirst(str, &search_handle, FILE_NORMAL, f,
914 sizeof(FILEFINDBUF3), &num_matches, FIL_STANDARD)) {
915
916 strcpy(ss, s);
917 p = &ss[strlen(ss)];
918
919 do {
920 strcpy(p, f->achName);
921 unlinkf("%s", ss);
922 num_matches = 1;
923 DosError(FERR_DISABLEHARDERR);
924 } while (!DosFindNext(search_handle, f, sizeof(FILEFINDBUF3),
925 &num_matches));
926 DosFindClose(search_handle);
927 }
928
929 free(f);
930 free(ss);
931 free(str);
932 return 0;
933}
934#endif
935
936/**
937 * Delete file
938 * @return OS/2 API error code or 0 if OK
939 */
940
941INT unlinkf(CHAR *string)
942{
943 if (!strstr(string, ArcTempRoot)) {
944 DosError(FERR_DISABLEHARDERR);
945 if (DosDelete(string)) {
946 make_deleteable(string, -1, TRUE);
947 DosError(FERR_DISABLEHARDERR);
948 return DosDelete(string);
949 }
950 }
951 else {
952 APIRET error;
953
954 DosError(FERR_DISABLEHARDERR);
955 error = DosForceDelete(string);
956 if (error) {
957 make_deleteable(string, error, FALSE);
958 DosError(FERR_DISABLEHARDERR);
959 return DosForceDelete(string);
960 }
961 }
962 return 0;
963}
964
965#pragma alloc_text(LONGNAMES,TruncName,GetLongName,WriteLongName)
966#pragma alloc_text(LONGNAMES,ZapLongName,AdjustWildcardName)
967#pragma alloc_text(COPYF,default_disk,docopyf,MakeTempName)
968#pragma alloc_text(UNLINKF,unlinkf,unlink_allf,make_deleteable,wipeallf)
Note: See TracBrowser for help on using the repository browser.