source: trunk/dll/copyf.c@ 1480

Last change on this file since 1480 was 1480, checked in by Gregg Young, 16 years ago

Fix failure to correctly check for large file support in FindSwapperDat fall back code minor streamling. Add LVM.EXE to partition submenu. Stop using xDosQueryAppType where the file name it is passed is already a local stack variable. Correct a typo in several file header comments.

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