source: trunk/dll/copyf.c@ 1722

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

The rest of the files for CS 1721

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