source: trunk/dll/copyf.c@ 1722

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

The rest of the files for CS 1721

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