source: trunk/dll/copyf.c@ 1849

Last change on this file since 1849 was 1849, checked in by John Small, 10 years ago

Ticket 522: Change calls to "highmem-unsafe" Dos... functions to wrapped xDos...

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