source: trunk/dll/copyf.c@ 1711

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

Actually commit the fix for suppressing the readonly warning on temp archive files. Ticket 497

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