source: trunk/dll/copyf.c@ 1844

Last change on this file since 1844 was 1803, checked in by Gregg Young, 10 years ago

Changes to allow a JAVA executable object to be created using "Real object" menu item on a jar file. (Ticket [37]) Eliminate redundant prompts and error messages when telling FM/2 not to delete a R/O file. (Ticket [548]) Limit attempts to unlock files to exes and dlls. (Ticket [549])

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