source: trunk/dll/copyf.c@ 1502

Last change on this file since 1502 was 1502, checked in by John Small, 15 years ago

Ticket 423: Correct MkeTempName to it creates 8.3 format names, not 8.4.

  • 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 1502 2010-03-31 14:54:58Z jbs $
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
30***********************************************************************/
31
32#include <stdlib.h>
33#include <string.h>
34#include <stdarg.h>
35#include <ctype.h>
36
37#define INCL_DOS
38#define INCL_DOSERRORS
39#define INCL_WIN
40#define INCL_LONGLONG
41
42#include "fm3dll.h"
43#include "fm3dll2.h" // #define's for UM_*, control id's, etc.
44#include "killproc.h" // Data declaration(s)
45#include "notebook.h" // Data declaration(s)
46#include "info.h" // Data declaration(s)
47#include "init.h" // Data declaration(s)
48#include "arccnrs.h"
49#include "fm3str.h"
50#include "errutil.h" // Dos_Error...
51#include "strutil.h" // GetPString
52#include "copyf.h"
53#include "literal.h" // fixup
54#include "misc.h" // Broadcast
55#include "valid.h" // MakeFullName
56#include "wrappers.h" // xDosSetPathInfo
57#include "strips.h" // bstrip
58#include "fortify.h"
59#include "pathutil.h" // AddBackslashToPath
60
61static PSZ pszSrcFile = __FILE__;
62
63static CHAR *GetLongName(CHAR * oldname, CHAR * buffer);
64static CHAR *TruncName(CHAR * oldname, CHAR * buffer);
65
66//static CHAR default_disk(VOID);
67//static INT unlink_allf(CHAR * string, ...);
68
69#ifndef WinMoveObject
70HOBJECT APIENTRY WinMoveObject(HOBJECT hObjectofObject,
71 HOBJECT hObjectofDest, ULONG ulReserved);
72#endif
73#ifndef WinCopyObject
74HOBJECT APIENTRY WinCopyObject(HOBJECT hObjectofObject,
75 HOBJECT hObjectofDest, ULONG ulReserved);
76#endif
77
78/**
79 * Make temporary file name
80 * @param buffer is input directory name and output file name buffer
81 * @param temproot is filename root used by type 2
82 * @param type is name style
83 * @return pointer to name in buffer or NULL if failed
84 * @note not MT safe
85 */
86
87PSZ MakeTempName(PSZ buffer, PSZ temproot, INT type)
88{
89 FILESTATUS3 fs3;
90 APIRET rc;
91 PSZ p;
92 PSZ o;
93
94 if (strlen(buffer) > 3)
95 AddBackslashToPath(buffer);
96 p = o = buffer + strlen(buffer);
97 switch (type) {
98 case 0:
99 sprintf(p, "%08lx.%03lx", mypid, rand() & 4095L); // 4095 = 0x0FFF
100 break;
101 case 1:
102 sprintf(p, "%s%04lx.%03lx", "$FM2", mypid, rand() & 4095L); // 4095 = 0x0FFF
103 break;
104 case 2:
105 sprintf(p, "%s.%03x", temproot, (rand() & 4095)); // 4095 = 0x0FFF
106 break;
107 default:
108 break;
109 }
110 p = buffer + (strlen(buffer) - 1);
111 for (;;) {
112 DosError(FERR_DISABLEHARDERR);
113 rc = DosQueryPathInfo(buffer, FIL_STANDARD, &fs3, sizeof(fs3));
114 if (rc == ERROR_DISK_CHANGE) {
115 DosError(FERR_ENABLEHARDERR);
116 rc = DosQueryPathInfo(buffer, FIL_STANDARD, &fs3, sizeof(fs3));
117 }
118 if (rc)
119 break;
120 Loop:
121 if (p < o) {
122 *buffer = 0;
123 return NULL;
124 }
125 if ((*p) + 1 < 'Z' + 1) {
126 (*p)++;
127 while (strchr("*?<>\":/\\|+=;,[]. ", *p))
128 (*p)++;
129 *p = toupper(*p);
130 }
131 else {
132 p--;
133 if (p >= o && *p == '.')
134 p--;
135 goto Loop;
136 }
137 }
138 return buffer;
139}
140
141CHAR *TruncName(CHAR * oldname, CHAR * buffer)
142{
143 CHAR *p, *f, *s, *o;
144 FILESTATUS3 fs3;
145 APIRET rc;
146
147 if (!buffer || !oldname || !*oldname) {
148 if (buffer)
149 *buffer = 0;
150 return NULL;
151 }
152 strcpy(buffer, oldname);
153 f = strrchr(buffer, '\\');
154 if (!f)
155 f = strrchr(buffer, '/');
156 if (!f)
157 f = buffer;
158 else
159 f++;
160 p = f;
161 o = p;
162 f = oldname + (f - buffer);
163 strupr(buffer);
164 while (*f == '.')
165 f++; // skip leading '.'s
166 s = f;
167 // skip past rootname
168 while (*f && *f != '.' && f < s + 8) {
169 *p = toupper(*f);
170 p++;
171 f++;
172 }
173 while (*f == '.')
174 f++;
175 s = f;
176 f = strrchr(f, '.');
177 if (f) {
178 while (*f == '.')
179 f++;
180 }
181 if (f && *(f + 1))
182 s = f;
183 else
184 f = s;
185 if (*f) {
186 *p = '.';
187 p++;
188 while (*f && *f != '.' && f < s + 3) {
189 *p = toupper(*f);
190 p++;
191 f++;
192 }
193 }
194 *p = 0;
195
196 p = o;
197 while (*p) {
198 if (strchr("*?<>\":/\\|+=;,[] ", *p) || *p < 0x20)
199 *p = '_';
200 if (*p == '.' && *(p + 1) == '.')
201 *(p + 1) = '_';
202 p++;
203 }
204
205 p = o + (strlen(o) - 1);
206 for (;;) {
207 DosError(FERR_DISABLEHARDERR);
208 rc = DosQueryPathInfo(buffer, FIL_STANDARD, &fs3, sizeof(fs3));
209 if (rc == ERROR_DISK_CHANGE) {
210 DosError(FERR_ENABLEHARDERR);
211 rc = DosQueryPathInfo(buffer, FIL_STANDARD, &fs3, sizeof(fs3));
212 }
213 if (rc)
214 break;
215 Loop:
216 if (p < o) {
217 *buffer = 0;
218 return NULL;
219 }
220 if ((*p) + 1 < 'Z' + 1) {
221 (*p)++;
222 while (strchr("*?<>\":/\\|+=;,[]. ", *p))
223 (*p)++;
224 *p = toupper(*p);
225 }
226 else {
227 p--;
228 if (p >= o && *p == '.')
229 p--;
230 goto Loop;
231 }
232 }
233 return buffer;
234}
235
236CHAR *GetLongName(CHAR * oldname, CHAR * longname)
237{
238 if (!longname)
239 return NULL;
240 *longname = 0;
241 if (!oldname || !*oldname)
242 return NULL;
243 if (IsFullName(oldname)) {
244
245 APIRET rc;
246 EAOP2 eaop;
247 PGEA2LIST pgealist;
248 PFEA2LIST pfealist;
249 PGEA2 pgea;
250 PFEA2 pfea;
251 CHAR *value;
252
253 strcpy(longname, oldname);
254 value = longname;
255 while (*value) {
256 if (*value == '/')
257 *value = '\\';
258 value++;
259 }
260 value = strrchr(longname, '\\');
261 if (value) {
262 value++;
263 *value = 0;
264 }
265 pgealist = xmallocz(sizeof(GEA2LIST) + 32, pszSrcFile, __LINE__);
266 if (pgealist) {
267 pgea = &pgealist->list[0];
268 strcpy(pgea->szName, LONGNAME);
269 pgea->cbName = strlen(pgea->szName);
270 pgea->oNextEntryOffset = 0L;
271 pgealist->cbList = (sizeof(GEA2LIST) + pgea->cbName);
272 pfealist = xmallocz(1536, pszSrcFile, __LINE__);
273 if (pfealist) {
274 pfealist->cbList = 1024;
275 eaop.fpGEA2List = pgealist;
276 eaop.fpFEA2List = pfealist;
277 eaop.oError = 0L;
278 DosError(FERR_DISABLEHARDERR);
279 rc = DosQueryPathInfo(oldname,
280 FIL_QUERYEASFROMLIST,
281 (PVOID) & eaop, (ULONG) sizeof(EAOP2));
282 if (!rc) {
283 pfea = &eaop.fpFEA2List->list[0];
284 value = pfea->szName + pfea->cbName + 1;
285 value[pfea->cbValue] = 0;
286 if (*(USHORT *) value == EAT_ASCII)
287 strncat(longname,
288 value + (sizeof(USHORT) * 2),
289 CCHMAXPATH - strlen(longname));
290 longname[CCHMAXPATH - 1] = 0;
291 }
292 free(pfealist);
293 }
294 free(pgealist);
295 }
296 }
297 return longname;
298}
299
300BOOL ZapLongName(PSZ filename)
301{
302 return WriteLongName(filename, NullStr);
303}
304
305BOOL WriteLongName(CHAR * filename, CHAR * longname)
306{
307 APIRET rc;
308 EAOP2 eaop;
309 PFEA2LIST pfealist = NULL;
310 ULONG ealen;
311 USHORT len;
312 CHAR *eaval, *p;
313
314 if (!filename || !*filename || !longname)
315 return FALSE;
316 p = strrchr(longname, '\\');
317 if (p)
318 memmove(longname, p + 1, strlen(p + 1) + 1);
319 p = strrchr(longname, '/');
320 if (p)
321 memmove(longname, p + 1, strlen(p + 1) + 1);
322 bstrip(longname);
323 len = strlen(longname);
324 if (len)
325 ealen = sizeof(FEA2LIST) + 10 + len + 4;
326 else
327 ealen = sizeof(FEALIST) + 10;
328 rc = xDosAllocMem((PPVOID) & pfealist,
329 ealen + 32L, PAG_COMMIT | PAG_READ | PAG_WRITE,
330 pszSrcFile, __LINE__);
331 if (rc)
332 Dos_Error(MB_CANCEL, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
333 GetPString(IDS_OUTOFMEMORY));
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.