source: trunk/dll/copyf.c@ 1628

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

Hard coded the flags for the xDosAlloc* wrappers and added a description for each of them.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.3 KB
Line 
1
2/***********************************************************************
3
4 $Id: copyf.c 1628 2011-08-27 19:35:39Z 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, ealen + 32L, pszSrcFile, __LINE__))
331 return FALSE;
332 else {
333 memset(pfealist, 0, ealen + 1);
334 pfealist->cbList = ealen;
335 pfealist->list[0].oNextEntryOffset = 0;
336 pfealist->list[0].fEA = 0;
337 pfealist->list[0].cbName = 9;
338 strcpy(pfealist->list[0].szName, LONGNAME);
339 if (len) {
340 eaval = pfealist->list[0].szName + 10;
341 *(USHORT *) eaval = (USHORT) EAT_ASCII;
342 eaval += sizeof(USHORT);
343 *(USHORT *) eaval = (USHORT) len;
344 eaval += sizeof(USHORT);
345 memcpy(eaval, longname, len);
346 pfealist->list[0].cbValue = len + (sizeof(USHORT) * 2);
347 }
348 else
349 pfealist->list[0].cbValue = 0;
350 eaop.fpGEA2List = (PGEA2LIST) 0;
351 eaop.fpFEA2List = pfealist;
352 eaop.oError = 0L;
353 DosError(FERR_DISABLEHARDERR);
354 rc = xDosSetPathInfo(filename, FIL_QUERYEASIZE,
355 &eaop, sizeof(eaop), DSPI_WRTTHRU);
356 DosFreeMem(pfealist);
357 if (rc)
358 return FALSE;
359 }
360 return TRUE;
361}
362
363BOOL AdjustWildcardName(CHAR * oldname, CHAR * newname)
364{
365 BOOL ret = FALSE;
366
367 // NOTE: newname should be CCHMAXPATH chars long!
368
369 if (strchr(newname, '*') || strchr(newname, '?')) {
370
371 CHAR srce[CCHMAXPATHCOMP], dest[CCHMAXPATHCOMP], result[CCHMAXPATHCOMP],
372 *p;
373
374 p = strrchr(newname, '\\');
375 if (p && *(p + 1)) {
376 strcpy(dest, p + 1);
377 p = strrchr(oldname, '\\');
378 if (p && *(p + 1)) {
379 strcpy(srce, p + 1);
380 DosError(FERR_DISABLEHARDERR);
381 if (!DosEditName(1L, srce, dest, (PBYTE)result, (ULONG)sizeof(result))) {
382 p = strrchr(newname, '\\');
383 p++;
384 strcpy(p, result);
385 ret = TRUE;
386 }
387 }
388 }
389 }
390 return ret;
391}
392
393/** Copy/move file
394 * @param type is copy/move type
395 * @param oldname is fully qualified source file name
396 * @param newname is fully qualified destination file name
397 * @return
398 * 0: success
399 * -1: bad parameter(s)
400 * -2: source does not exist
401 * -3: bad copy/move type
402 * anything else: API return
403 */
404
405APIRET docopyf(INT type, CHAR *oldname, CHAR *newname)
406{
407 CHAR longname[CCHMAXPATH], shortname[CCHMAXPATH];
408 CHAR olddisk, newdisk, dir[CCHMAXPATH], *p, *pp;
409 APIRET ret = -1, rc;
410 FILESTATUS3L st, st2, dummy;
411 BOOL diskchange = FALSE, zaplong = FALSE;
412
413 *shortname = *dir = 0;
414
415 if (!oldname || !*oldname || !*newname)
416 return (APIRET)-1; // bad args
417
418 DosError(FERR_DISABLEHARDERR);
419 if (DosQueryPathInfo(oldname, FIL_STANDARDL, &st, sizeof(FILESTATUS3L)))
420 return (APIRET)-2; // can not access source
421
422 AdjustWildcardName(oldname, newname);
423 MakeFullName(oldname);
424 MakeFullName(newname);
425 olddisk = toupper(*oldname); // source drive
426 newdisk = toupper(*newname); // destination drive
427 if (!(driveflags[toupper(*oldname) - 'A'] & DRIVE_NOLONGNAMES))
428 *longname = 0;
429 else {
430 GetLongName(oldname, longname);
431 if (*longname) {
432 p = RootName(longname);
433 if (p != longname)
434 memmove(longname, p, strlen(p) + 1);
435 }
436 }
437 // If root name changed make sure longname EA goes away
438 if (*longname) {
439 p = RootName(oldname);
440 pp = RootName(longname);
441 if (stricmp(p, pp)) {
442 zaplong = TRUE;
443 }
444 }
445
446 DosError(FERR_DISABLEHARDERR);
447 switch (type) {
448 case WPSMOVE:
449 {
450 HOBJECT hobjsrc;
451 HOBJECT hobjdest;
452
453 ret = ERROR_FILE_NOT_FOUND;
454 hobjsrc = WinQueryObject(oldname);
455 if (hobjsrc) {
456 strcpy(dir, newname);
457 p = strrchr(dir, '\\');
458 if (p < dir + 3)
459 p++;
460 *p = 0;
461 ret = ERROR_PATH_NOT_FOUND;
462 hobjdest = WinQueryObject(dir);
463 if (hobjdest) {
464 ret = ERROR_GEN_FAILURE;
465 hobjsrc = WinMoveObject(hobjsrc, hobjdest, 0);
466 if (hobjsrc)
467 ret = 0;
468 }
469 }
470 }
471 return ret;
472
473 case WPSCOPY:
474 {
475 HOBJECT hobjsrc;
476 HOBJECT hobjdest;
477
478 ret = ERROR_FILE_NOT_FOUND;
479 hobjsrc = WinQueryObject(oldname);
480 if (hobjsrc) {
481 strcpy(dir, newname);
482 p = strrchr(dir, '\\');
483 if (p < dir + 3)
484 p++;
485 *p = 0;
486 ret = ERROR_PATH_NOT_FOUND;
487 hobjdest = WinQueryObject(dir);
488 if (hobjdest) {
489 ret = ERROR_GEN_FAILURE;
490 hobjsrc = WinCopyObject(hobjsrc, hobjdest, 0);
491 if (hobjsrc)
492 ret = 0;
493 }
494 }
495 }
496 return ret;
497
498 case MOVE:
499 *dir = 0;
500 if (olddisk == newdisk) {
501 // Moving to same drive
502 // make temporary copy in case move fails
503 if (IsFile(newname) != -1 && stricmp(oldname, newname)) {
504 // 19 Oct 09 SHL correct regression
505 strcpy(dir, newname);
506 p = strrchr(dir, '\\');
507 if (p)
508 *p = 0;
509 AddBackslashToPath(dir);
510 MakeTempName(dir, NULL, 0);
511 if (DosMove(newname, dir))
512 *dir = 0; // Avoid trying to restore bad copy
513 }
514 DosError(FERR_DISABLEHARDERR);
515 ret = DosMove(oldname, newname); // move it
516 if (ret && *dir) { // failed -- clean up
517 DosError(FERR_DISABLEHARDERR);
518 if (!DosMove(dir, newname))
519 Broadcast((HAB) 0, hwndMain, UM_UPDATERECORD, MPFROMP(dir), MPVOID);
520 }
521 else if (!ret && *dir) {
522 if (!IsFile(dir)) {
523 if (!strchr(dir, '?') && !strchr(dir, '*'))
524 wipeallf("%s\\*", dir);
525 DosError(FERR_DISABLEHARDERR);
526 if (DosDeleteDir(dir)) {
527 make_deleteable(dir);
528 DosDeleteDir(dir);
529 }
530 }
531 else if (IsFile(dir) > 0) {
532 DosError(FERR_DISABLEHARDERR);
533 if (DosForceDelete(dir)) {
534 make_deleteable(dir);
535 DosForceDelete(dir);
536 }
537 if (zaplong) {
538 ret = ZapLongName(dir);
539 }
540 Broadcast((HAB) 0, hwndMain, UM_UPDATERECORD, MPFROMP(dir), MPVOID);
541 }
542 }
543 }
544 else {
545 // Moving to different drive
546 DosError(FERR_DISABLEHARDERR);
547 ret = DosCopy(oldname, newname, DCPY_EXISTING); // <=-NOTE!
548 if (ret == ERROR_DISK_CHANGE) {
549 DosError(FERR_ENABLEHARDERR);
550 ret = DosCopy(oldname, newname, DCPY_EXISTING);
551 diskchange = TRUE;
552 }
553 if (ret == ERROR_INVALID_NAME || ret == ERROR_FILENAME_EXCED_RANGE) {
554 if (TruncName(newname, shortname)) {
555 // make 8.3 filename
556 DosError(FERR_DISABLEHARDERR);
557 ret = DosCopy(oldname, shortname, DCPY_EXISTING);
558 if (!ret) {
559 // success -- write longname ea
560 WriteLongName(shortname, newname);
561 strcpy(newname, shortname);
562 // broadcast fixup msg to windows
563 Broadcast((HAB) 0,
564 hwndMain, UM_UPDATERECORD, MPFROMP(shortname), MPVOID);
565 }
566 }
567 }
568 else if (!ret && *longname) {
569
570 CHAR fixname[CCHMAXPATH];
571
572 strcpy(fixname, newname);
573 p = strrchr(fixname, '\\');
574 if (p) {
575 p++;
576 *p = 0;
577 }
578 strcat(fixname, longname);
579 DosError(FERR_DISABLEHARDERR);
580 DosMove(newname, fixname);
581 strcpy(newname, fixname);
582 if (zaplong)
583 ZapLongName(fixname);
584 Broadcast((HAB) 0,
585 hwndMain, UM_UPDATERECORD, MPFROMP(fixname), MPVOID);
586 }
587 if (!ret) {
588 // double-check success
589 DosError(FERR_DISABLEHARDERR);
590 rc = DosQueryPathInfo(newname,
591 FIL_STANDARDL, &st2, sizeof(FILESTATUS3L));
592 if (rc == ERROR_DISK_CHANGE) {
593 DosError(FERR_ENABLEHARDERR);
594 rc = DosQueryPathInfo(newname,
595 FIL_STANDARDL, &st2, sizeof(FILESTATUS3L));
596 }
597 if (!rc && st2.cbFile == st.cbFile) {
598 // seems to have worked...
599 DosError(FERR_DISABLEHARDERR);
600 if (diskchange) {
601 DosError(FERR_ENABLEHARDERR);
602 DosQueryPathInfo(oldname, FIL_STANDARDL, &dummy, sizeof(FILESTATUS3L)); // force disk change
603 }
604 if (!(st2.attrFile & FILE_DIRECTORY))
605 unlinkf(oldname); // erase file
606 else {
607 // remove directory
608 wipeallf("%s\\*", oldname);
609 DosError(FERR_DISABLEHARDERR);
610 if (DosDeleteDir(oldname)) {
611 make_deleteable(oldname);
612 DosDeleteDir(oldname);
613 }
614 }
615 }
616 }
617 }
618 return ret;
619
620 case COPY:
621 DosError(FERR_DISABLEHARDERR);
622 ret = DosCopy(oldname, newname, DCPY_EXISTING); // <=-NOTE!
623 if (ret == ERROR_DISK_CHANGE) {
624 DosError(FERR_ENABLEHARDERR);
625 ret = DosCopy(oldname, newname, DCPY_EXISTING);
626 diskchange = TRUE;
627 }
628 if (ret == ERROR_INVALID_NAME || ret == ERROR_FILENAME_EXCED_RANGE) {
629 if (TruncName(newname, shortname)) {
630 DosError((diskchange) ? FERR_ENABLEHARDERR : FERR_DISABLEHARDERR);
631 ret = DosCopy(oldname, shortname, DCPY_EXISTING);
632 if (!ret) {
633 WriteLongName(shortname, newname);
634 strcpy(newname, shortname);
635 Broadcast((HAB) 0,
636 hwndMain, UM_UPDATERECORD, MPFROMP(shortname), MPVOID);
637 }
638 }
639 }
640 else if (!ret && *longname) {
641
642 CHAR fixname[CCHMAXPATH];
643
644 strcpy(fixname, newname);
645 p = strrchr(fixname, '\\');
646 if (p) {
647 p++;
648 *p = 0;
649 }
650 strcat(fixname, longname);
651 DosError(FERR_DISABLEHARDERR);
652 DosMove(newname, fixname);
653 if (zaplong)
654 ZapLongName(fixname);
655 Broadcast((HAB) 0, hwndMain, UM_UPDATERECORD, MPFROMP(fixname), MPVOID);
656 }
657 return ret;
658
659 default:
660 // shouldn't happen
661 Runtime_Error(pszSrcFile, __LINE__, "bad case %u", type);
662 break;
663 } // switch type
664 Runtime_Error(pszSrcFile, __LINE__, "copy/move type %u unexpected", type);
665 return (APIRET)-3; // bad copy/move type
666}
667
668INT make_deleteable(CHAR * filename)
669{
670 INT ret = -1;
671 FILESTATUS3 fsi;
672
673 DosError(FERR_DISABLEHARDERR);
674 if (!DosQueryPathInfo(filename, FIL_STANDARD, &fsi, sizeof(fsi))) {
675 fsi.attrFile = 0;
676 DosError(FERR_DISABLEHARDERR);
677 if (!xDosSetPathInfo(filename, FIL_STANDARD, &fsi, sizeof(fsi), 0))
678 ret = 0;
679 }
680 return ret;
681}
682
683/**
684 * unlink everything from directory on down...
685 */
686
687INT wipeallf(CHAR *string, ...)
688{
689 FILEFINDBUF3 *f;
690 HDIR search_handle;
691 ULONG num_matches;
692 CHAR *p, *ss, *str;
693 CHAR s[CCHMAXPATH], mask[257];
694 va_list ap;
695 INT rc;
696
697 va_start(ap, string);
698 vsprintf(s, string, ap);
699 va_end(ap);
700
701 if (!*s)
702 return -1;
703 p = s;
704 while ((p = strchr(p, '/')) != NULL) {
705 *p = '\\';
706 p++;
707 }
708
709 str = xstrdup(s, pszSrcFile, __LINE__);
710 if (!str)
711 return -1;
712
713 {
714 // safety net -- disallow deleting a root dir or partial name
715 CHAR temp;
716 p = strrchr(str, '\\');
717 if (p) {
718 p++;
719 temp = *p;
720 *p = 0;
721 if (IsRoot(str) || !IsFullName(str)) {
722 // under no circumstances!
723 Runtime_Error(pszSrcFile, __LINE__, "bad name %s", str);
724 free(str);
725 return -1;
726 }
727 *p = temp;
728 }
729 }
730
731 p = s;
732 p = strrchr(s, '\\'); // strip s to just path
733 if (!p)
734 p = strrchr(s, ':');
735 if (p) {
736 p++;
737 strncpy(mask, p, 256);
738 mask[256] = 0;
739 *p = 0;
740 }
741 else {
742 *mask = 0;
743 *s = 0;
744 }
745
746 ss = xmalloc(CCHMAXPATH, pszSrcFile, __LINE__);
747 f = xmalloc(sizeof(FILEFINDBUF3), pszSrcFile, __LINE__);
748 if (!ss || !f) {
749 xfree(ss, pszSrcFile, __LINE__);
750 xfree(f, pszSrcFile, __LINE__);
751 free(str);
752 return -1;
753 }
754
755 search_handle = HDIR_CREATE;
756 num_matches = 1;
757
758 DosError(FERR_DISABLEHARDERR);
759 if (!DosFindFirst(str, &search_handle, FILE_NORMAL | FILE_DIRECTORY |
760 FILE_SYSTEM | FILE_READONLY | FILE_HIDDEN | FILE_ARCHIVED,
761 f, sizeof(FILEFINDBUF3), &num_matches, FIL_STANDARD)) {
762
763 strcpy(ss, s);
764 p = &ss[strlen(ss)];
765
766 do {
767 strcpy(p, f->achName);
768 if (f->attrFile & FILE_DIRECTORY) {
769 if (strcmp(f->achName, ".") && strcmp(f->achName, "..")) {
770 wipeallf("%s/%s", ss, mask); // recurse to wipe files
771 DosError(FERR_DISABLEHARDERR);
772 // remove directory
773 if (DosDeleteDir(ss)) {
774 make_deleteable(ss); // Try harder
775 DosError(FERR_DISABLEHARDERR);
776 DosDeleteDir(ss);
777 }
778 }
779 }
780 else {
781 DosError(FERR_DISABLEHARDERR);
782 if (DosForceDelete(ss)) {
783 make_deleteable(ss);
784 DosError(FERR_DISABLEHARDERR);
785 rc = (INT) DosForceDelete(ss);
786 if (rc)
787 return rc;
788 }
789 }
790 num_matches = 1;
791 DosError(FERR_DISABLEHARDERR);
792 } while (!DosFindNext(search_handle, f, sizeof(FILEFINDBUF3),
793 &num_matches));
794 DosFindClose(search_handle);
795 }
796
797 free(f);
798 free(ss);
799 free(str);
800 return 0;
801}
802
803#if 0 // JBS 11 Sep 08 fixme to be gone
804INT unlink_allf(CHAR * string, ...)
805{
806 // wildcard delete
807 FILEFINDBUF3 *f;
808 HDIR search_handle;
809 ULONG num_matches;
810 CHAR *p, *ss, *str;
811 CHAR s[CCHMAXPATH];
812 va_list ap;
813 va_start(ap, string);
814 vsprintf(s, string, ap);
815 va_end(ap);
816
817 if (!*s)
818 return -1;
819 p = s;
820 while ((p = strchr(p, '/')) != NULL) {
821 *p = '\\';
822 p++;
823 }
824
825 str = xstrdup(s, pszSrcFile, __LINE__);
826 if (!str)
827 return -1;
828
829 p = s;
830 p = strrchr(s, '\\'); // strip s to just path
831 if (!p)
832 p = strrchr(s, ':');
833 if (p) {
834 p++;
835 *p = 0;
836 }
837 else
838 *s = 0;
839
840 ss = xmalloc(CCHMAXPATH, pszSrcFile, __LINE__);
841 f = xmalloc(sizeof(FILEFINDBUF3), pszSrcFile, __LINE__);
842 if (!ss || !f) {
843 xfree(ss, pszSrcFile, __LINE__);
844 xfree(f, pszSrcFile, __LINE__);
845 free(str);
846 return -1;
847 }
848
849 search_handle = HDIR_CREATE;
850 num_matches = 1;
851
852 DosError(FERR_DISABLEHARDERR);
853 if (!DosFindFirst(str, &search_handle, FILE_NORMAL, f,
854 sizeof(FILEFINDBUF3), &num_matches, FIL_STANDARD)) {
855
856 strcpy(ss, s);
857 p = &ss[strlen(ss)];
858
859 do {
860 strcpy(p, f->achName);
861 unlinkf("%s", ss);
862 num_matches = 1;
863 DosError(FERR_DISABLEHARDERR);
864 } while (!DosFindNext(search_handle, f, sizeof(FILEFINDBUF3),
865 &num_matches));
866 DosFindClose(search_handle);
867 }
868
869 free(f);
870 free(ss);
871 free(str);
872 return 0;
873}
874#endif
875
876/**
877 * Delete file
878 * @return OS/2 API error code or 0 if OK
879 */
880
881INT unlinkf(CHAR *string)
882{
883 if (!strstr(string, ArcTempRoot)) {
884 DosError(FERR_DISABLEHARDERR);
885 if (DosDelete(string)) {
886 make_deleteable(string);
887 DosError(FERR_DISABLEHARDERR);
888 return DosDelete(string);
889 }
890 }
891 else {
892 DosError(FERR_DISABLEHARDERR);
893 if (DosForceDelete(string)) {
894 make_deleteable(string);
895 DosError(FERR_DISABLEHARDERR);
896 return DosForceDelete(string);
897 }
898 }
899 return 0;
900}
901
902#pragma alloc_text(LONGNAMES,TruncName,GetLongName,WriteLongName)
903#pragma alloc_text(LONGNAMES,ZapLongName,AdjustWildcardName)
904#pragma alloc_text(COPYF,default_disk,docopyf,MakeTempName)
905#pragma alloc_text(UNLINKF,unlinkf,unlink_allf,make_deleteable,wipeallf)
Note: See TracBrowser for help on using the repository browser.