source: trunk/dll/copyf.c@ 1712

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

Added comments

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