source: trunk/dll/copyf.c@ 1712

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

Added comments

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