source: trunk/dll/copyf.c@ 1740

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

Fix wipeallf to recurse properly

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