source: trunk/dll/copyf.c@ 1627

Last change on this file since 1627 was 1627, checked in by Gregg Young, 14 years ago

Add a low mem version of xDosAlloc* wrappers; move error checking into all the xDosAlloc* wrappers. Ticket 471

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