~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Frontier Kernel
Frontier/Common/source/fileops.c

Version: ~ [ 10.0 ] ~

** Warning: Cannot open xref database.

1 2 /* $Id: fileops.c,v 1.6 2005/01/24 22:52:21 icreedon Exp $ */ 3 4 /****************************************************************************** 5 6 UserLand Frontier(tm) -- High performance Web content management, 7 object database, system-level and Internet scripting environment, 8 including source code editing and debugging. 9 10 Copyright (C) 1992-2004 UserLand Software, Inc. 11 12 This program is free software; you can redistribute it and/or modify 13 it under the terms of the GNU General Public License as published by 14 the Free Software Foundation; either version 2 of the License, or 15 (at your option) any later version. 16 17 This program is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 GNU General Public License for more details. 21 22 You should have received a copy of the GNU General Public License 23 along with this program; if not, write to the Free Software 24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 26 ******************************************************************************/ 27 28 #include "frontier.h" 29 #include "standard.h" 30 31 #ifdef WIN95VERSION 32 #include "winregistry.h" 33 #endif 34 35 #include "filealias.h" 36 #include "cursor.h" 37 #include "dialogs.h" 38 #include "error.h" 39 #include "memory.h" 40 #include "ops.h" 41 #include "quickdraw.h" 42 #include "resources.h" 43 #include "strings.h" 44 #include "timedate.h" 45 #include "frontierwindows.h" 46 #include "file.h" 47 #include "shell.h" 48 #include "shell.rsrc.h" 49 #include "langinternal.h" /*for langbackgroundtask*/ 50 51 #ifdef MACVERSION 52 53 #if TARGET_API_MAC_CARBON 54 #include "MoreFilesX.h" 55 #else 56 pascal OSErr XGetVInfo(short volReference, StringPtr volName, short *vRefNum, 57 UInt64 *freeBytes, UInt64 *totalBytes); 58 #endif 59 60 #ifdef flcomponent 61 #include "SetUpA5.h" 62 #endif 63 64 #define hasOpenDeny(volParms) (((volParms).vMAttrib & (1L << bHasOpenDeny)) != 0) 65 66 #ifndef __MOREFILESEXTRAS__ 67 enum { /*permissions used by MoreFile 1.1 code*/ 68 dmNone = 0x0000, 69 dmNoneDenyRd = 0x0010, 70 dmNoneDenyWr = 0x0020, 71 dmNoneDenyRdWr = 0x0030, 72 dmRd = 0x0001, /* Single writer, multiple readers; the readers */ 73 dmRdDenyRd = 0x0011, 74 dmRdDenyWr = 0x0021, /* Browsing - equivalent to fsRdPerm */ 75 dmRdDenyRdWr = 0x0031, 76 dmWr = 0x0002, 77 dmWrDenyRd = 0x0012, 78 dmWrDenyWr = 0x0022, 79 dmWrDenyRdWr = 0x0032, 80 dmRdWr = 0x0003, /* Shared access - equivalent to fsRdWrShPerm */ 81 dmRdWrDenyRd = 0x0013, 82 dmRdWrDenyWr = 0x0023, /* Single writer, multiple readers; the writer */ 83 dmRdWrDenyRdWr = 0x0033 /* Exclusive access - equivalent to fsRdWrPerm */ 84 }; 85 #endif 86 87 #endif 88 89 90 #ifdef flsystem6 91 92 static short applicationvolnum = 0; 93 94 #endif 95 96 static short applicationresnum = -1; 97 98 #ifdef MACVERSION 99 static OSType specialfolders [] = { 100 101 0, /*make 1-based*/ 102 103 #if TARGET_API_MAC_CARBON //macs is not working right now. This is not a good substitute, nice hack eh? 104 'pref', 105 #else 106 'macs', /*system*/ 107 #endif 108 'desk', /*desktop*/ 109 110 'trsh', /*trash*/ 111 112 'empt', /*shared trash*/ 113 114 'prnt', /*printmonitor documents*/ 115 116 'strt', /*startup items*/ 117 118 'amnu', /*apple menu items*/ 119 120 'ctrl', /*control panels*/ 121 122 'extn', /*extensions*/ 123 124 'pref', /*preferences*/ 125 126 'temp', /*temporary items*/ 127 128 'font' /*Fonts*/ 129 }; 130 #endif 131 132 133 typedef struct tyfileinfo tyvolinfo; 134 135 136 void setfserrorparam (const tyfilespec *fs) { 137 138 /* 139 bigstring bs; 140 141 if (!filespectopath (fs, bs)) 142 copystring ((ptrstring) (*fs).name, bs); 143 144 setoserrorparam (bs); 145 */ 146 147 setoserrorparam ((ptrstring) fsname (fs)); 148 } /*setfserrorparam*/ 149 150 151 boolean endswithpathsep (bigstring bs) { 152 /* return true if the ending character is a path sepatator character*/ 153 char ch; 154 155 ch = getstringcharacter(bs, stringlength(bs)-1); 156 157 #ifdef MACVERSION 158 if (ch == ':') 159 return (true); 160 #endif 161 162 #ifdef WIN95VERSION 163 if (ch == '\\') 164 return (true); 165 166 if (ch == '/') 167 return (true); 168 #endif 169 170 return (false); 171 } /*endswithpathsep*/ 172 173 boolean cleanendoffilename (bigstring bs) { 174 if (endswithpathsep(bs)) { 175 setstringlength (bs, stringlength(bs) - 1); 176 return (true); 177 } 178 179 return (false); 180 } /*cleanendoffilename*/ 181 182 183 boolean getmachinename (bigstring bsname) { 184 185 boolean fl; 186 187 #ifdef WIN95VERSION 188 DWORD len; 189 190 len = sizeof(bigstring) - 2; 191 192 fl = GetComputerName (stringbaseaddress(bsname), &len); 193 194 if (fl) 195 setstringlength (bsname, len); 196 else 197 setemptystring (bsname); 198 #endif 199 200 #ifdef MACVERSION 201 StringHandle hstring = GetString (-16413); 202 203 fl = hstring != nil; 204 205 if (fl) 206 texthandletostring ((Handle) hstring, bsname); 207 else 208 setemptystring (bsname); 209 #endif 210 211 return (fl); 212 } /*getmachinename*/ 213 214 215 #ifdef MACVERSION 216 boolean foldertest (CInfoPBRec *pb) { 217 218 /* 219 return true if pb holds info describing a folder. 220 221 4/26/96 dmb: use mask, not BitTst (a toolbox call) 222 */ 223 224 /* 225 return (BitTst (&pb->dirInfo.ioFlAttrib, 3)); 226 */ 227 return ((pb->dirInfo.ioFlAttrib & ioDirMask) != 0); 228 } /*foldertest*/ 229 230 231 static void filebeachball (void) { 232 233 /* 234 roll the beachball cursor if there is one. 235 */ 236 237 if (beachballcursor ()) 238 rollbeachball (); 239 } /*filebeachball*/ 240 241 242 boolean getmacfileinfo (const tyfilespec *fs, CInfoPBRec *pb) { 243 244 /* 245 2.1b2 dmb: new fsspec-based version 246 */ 247 248 setoserrorparam ((ptrstring) (*fs).name); /*in case error message takes a filename parameter*/ 249 250 clearbytes (pb, sizeof (*pb)); 251 252 (*pb).hFileInfo.ioNamePtr = (StringPtr) (*fs).name; 253 254 (*pb).hFileInfo.ioVRefNum = (*fs).vRefNum; 255 256 (*pb).hFileInfo.ioDirID = (*fs).parID; 257 258 return (!oserror (PBGetCatInfoSync (pb))); 259 } /*getmacfileinfo*/ 260 261 262 static boolean setmacfileinfo (const tyfilespec *fs, CInfoPBRec *pb) { 263 264 /* 265 2.1b2 dmb: new fsspec-based version 266 */ 267 268 setoserrorparam ((ptrstring) (*fs).name); /*in case error message takes a filename parameter*/ 269 270 (*pb).hFileInfo.ioNamePtr = (StringPtr) (*fs).name; 271 272 (*pb).hFileInfo.ioVRefNum = (*fs).vRefNum; 273 274 (*pb).hFileInfo.ioDirID = (*fs).parID; 275 276 return (!oserror (PBSetCatInfoSync (pb))); 277 } /*setmacfileinfo*/ 278 279 280 static boolean touchparentfolder (const tyfilespec *fs) { 281 282 /* 283 touch the file date of the parent folder of fs 284 */ 285 286 FSSpec fsfolder; 287 288 if (FSMakeFSSpec ((*fs).vRefNum, (*fs).parID, nil, &fsfolder) != noErr) 289 return (false); 290 291 setfilemodified (&fsfolder, timenow ()); 292 293 return (true); 294 } /*touchparentfolder*/ 295 #endif 296 297 298 #ifdef WIN95VERSION 299 300 boolean winfileerror (const tyfilespec *fs) { 301 302 DWORD err = GetLastError (); 303 304 setfserrorparam (fs); 305 306 return (oserror (err)); 307 } /*winfileerror*/ 308 309 #endif 310 311 #ifdef MACVERSION // 1/29/97 dmb: adopt applet toolkit version 312 313 static boolean getinfofromvolpb (const HVolumeParam *pb, tyfileinfo *info) { 314 315 /* 316 dmb 9/21/93: for a volume, dirid should be fsRtParID, not fsRtDirID. 317 */ 318 319 short drivenum; 320 #if !TARGET_API_MAC_CARBON 321 QHdrPtr dqtop; 322 QElemPtr dqelem; 323 #endif 324 325 326 clearbytes (info, sizeof (tyfileinfo)); 327 328 (*info).vnum = (*pb).ioVRefNum; 329 330 (*info).dirid = fsRtParID; /*fsRtDirID*/ 331 332 (*info).flvolume = true; 333 334 (*info).flfolder = true; 335 336 (*info).timecreated = (*pb).ioVCrDate; 337 338 (*info).timemodified = (*pb).ioVLsMod; 339 340 (*info).fllocked = ((*pb).ioVAtrb & 0x8000) != 0; 341 342 (*info).flhardwarelock = ((*pb).ioVAtrb & 0x0080) != 0; 343 344 if ((*info).flhardwarelock) 345 (*info).fllocked = true; 346 347 (*info).ctfreebytes = (*pb).ioVAlBlkSiz * (*pb).ioVFrBlk; 348 349 (*info).cttotalbytes = (*pb).ioVAlBlkSiz * (*pb).ioVNmAlBlks; 350 351 (*info).blocksize = (*pb).ioVAlBlkSiz; 352 353 (*info).ctfiles = (*pb).ioVFilCnt; 354 355 (*info).ctfolders = (*pb).ioVDirCnt; 356 357 drivenum = (*pb).ioVDrvInfo; 358 359 //Code change by Timothy Paustian Sunday, June 25, 2000 9:17:36 PM 360 //The below code is to figure out if a volume is ejectable. I don't think 361 //you can do this in carbon, so just set it to false. 362 #if TARGET_API_MAC_CARBON == 1 363 (*info).flejectable = false; 364 #else 365 366 dqtop = GetDrvQHdr (); 367 368 dqelem = (*dqtop).qHead; 369 370 while (true) { 371 372 if (dqelem == nil) { /*volume is no longer in a drive; it must be ejectable!*/ 373 374 (*info).flejectable = true; 375 376 break; 377 } 378 379 if ((*(DrvQEl *)dqelem).dQDrive == drivenum) { 380 381 byte driveflag = *((byte *) dqelem - 3); 382 383 (*info).flejectable = ((driveflag != 8) && (driveflag != 0x48)); /*IM IV-181*/ 384 385 break; 386 } 387 388 dqelem = (*dqelem).qLink; 389 } /*while*/ 390 #endif 391 392 393 return (true); 394 } /*getinfofromvolpb*/ 395 396 397 boolean filegetvolumeinfo (short vnum, tyfileinfo *info) { 398 399 /* 400 dmb 9/21/93: take vnum as parameter, not volname. otherwise, 401 we can't distinguish between two vols w/the same name. 402 */ 403 404 HVolumeParam pb; 405 406 clearbytes (&pb, sizeof (pb)); /*init all fields to zero*/ 407 408 pb.ioVRefNum = vnum; 409 410 if (oserror (PBHGetVInfoSync ((HParmBlkPtr) &pb))) 411 return (false); 412 413 clearbytes (info, sizeof (tyfileinfo)); /*init all fields to zero*/ 414 415 getinfofromvolpb (&pb, info); 416 417 /*DW 9/7/93: determine if it's a network volume*/ { 418 419 HParamBlockRec pb; 420 GetVolParmsInfoBuffer buffer; 421 OSErr ec; 422 423 clearbytes (&pb, sizeof (pb)); /*init all fields to zero*/ 424 425 pb.ioParam.ioVRefNum = (*info).vnum; 426 427 pb.ioParam.ioBuffer = (Ptr) &buffer; 428 429 pb.ioParam.ioReqCount = sizeof (buffer); 430 431 ec = PBHGetVolParmsSync (&pb); 432 433 if (ec == noErr) 434 (*info).flremotevolume = buffer.vMServerAdr != 0; /*see Apple TN-Files docviewer doc*/ 435 } 436 437 return (true); 438 } /*filegetvolumeinfo*/ 439 440 441 void filegetinfofrompb (CInfoPBRec *pb, tyfileinfo *info) { 442 443 /* 444 dmb 9/24/93: handle volumes here, combining vol info with root 445 directory folder info. I'm not sure if a volume lock is always 446 reflected in the root directory, so don't set fllocked false 447 if the attribute isn't set in the pb. (it starts out cleared anyway.) 448 449 5.1.4 dmb: set finderbits for folders too. 450 */ 451 452 short finderbits; 453 454 clearbytes (info, sizeof (tyfileinfo)); /*init all fields to zero*/ 455 456 (*info).vnum = (*pb).hFileInfo.ioVRefNum; 457 458 (*info).dirid = (*pb).hFileInfo.ioFlParID; 459 460 if ((*info).dirid == fsRtParID) 461 filegetvolumeinfo ((*info).vnum, info); 462 else 463 (*info).flvolume = false; 464 465 if (BitTst (&(*pb).dirInfo.ioFlAttrib, 7)) /*if it's a volume, fllocked may already be set*/ 466 (*info).fllocked = true; 467 468 // (*info).flfolder = BitTst (&(*pb).dirInfo.ioFlAttrib, 3); 469 (*info).flfolder = (((*pb).dirInfo.ioFlAttrib & ioDirMask) != 0); 470 471 (*info).ixlabel = ((*pb).hFileInfo.ioFlFndrInfo.fdFlags & 0x000E) >> 1; 472 473 if ((*info).flfolder) { 474 475 /*Folders are considered "busy" if there are any files within the folder */ 476 477 (*info).flbusy = (*pb).dirInfo.ioDrNmFls > 0; 478 479 (*info).filecreator = (*info).filetype = ' '; 480 481 if (!(*info).flvolume) { /*these aren't the same for a volume & its root dir*/ 482 483 (*info).timecreated = (*pb).dirInfo.ioDrCrDat; 484 485 (*info).timemodified = (*pb).dirInfo.ioDrMdDat; 486 487 (*info).ctfiles = (*pb).dirInfo.ioDrNmFls; 488 } 489 490 (*info).iconposition = (*pb).dirInfo.ioDrUsrWds.frLocation; 491 492 (*info).folderview = (tyfolderview) ((*pb).dirInfo.ioDrUsrWds.frView >> 8); 493 494 finderbits = (*pb).dirInfo.ioDrUsrWds.frFlags; 495 } 496 else { /*fill in fields for a file, somewhat different format than a folder*/ 497 498 (*info).flbusy = BitTst (&(*pb).hFileInfo.ioFlAttrib, 0); 499 500 (*info).filecreator = (*pb).hFileInfo.ioFlFndrInfo.fdCreator; 501 502 (*info).filetype = (*pb).hFileInfo.ioFlFndrInfo.fdType; 503 504 (*info).timecreated = (*pb).hFileInfo.ioFlCrDat; 505 506 (*info).timemodified = (*pb).hFileInfo.ioFlMdDat; 507 508 (*info).sizedatafork = (*pb).hFileInfo.ioFlLgLen; 509 510 (*info).sizeresourcefork = (*pb).hFileInfo.ioFlRLgLen; 511 512 (*info).iconposition = (*pb).hFileInfo.ioFlFndrInfo.fdLocation; 513 514 finderbits = (*pb).hFileInfo.ioFlFndrInfo.fdFlags; 515 } 516 517 /*copy from the finder bits into the record*/ { 518 519 (*info).flalias = (finderbits & kIsAlias) != 0; 520 521 (*info).flbundle = (finderbits & kHasBundle) != 0; 522 523 (*info).flinvisible = (finderbits & kIsInvisible) != 0; 524 525 (*info).flstationery = (finderbits & kIsStationery) != 0; 526 527 (*info).flshared = (finderbits & kIsShared) != 0; 528 529 (*info).flnamelocked = (finderbits & kNameLocked) != 0; 530 531 (*info).flcustomicon = (finderbits & kHasCustomIcon) != 0; 532 } 533 } /*filegetinfofrompb*/ 534 #endif 535 536 #ifdef MACVERSION 537 #define filegetfsvolumeinfo(fs, info) filegetvolumeinfo((*fs).vRefNum, info) 538 #endif 539 540 #ifdef WIN95VERSION 541 static boolean filegetfsvolumeinfo (const tyfilespec *fs, tyfileinfo *info) { 542 DWORD sectorsPerCluster, bytesPerSector, numberOfFreeClusters, totalNumberOfClusters; 543 UINT drivetype; 544 bigstring volname; 545 bigstring errmsg; 546 547 clearbytes (info, sizeof (tyfileinfo)); /*init all fields to zero*/ 548 549 if (fileisvolume (fs)) { 550 info->flvolume = true; 551 info->flbusy = true; 552 553 copystring (fsname(fs), volname); 554 cleanendoffilename (volname); 555 pushchar ('\\', volname); 556 nullterminate (volname); 557 558 // if (GetVolumeInformation (stringbaseaddress (volname), stringbaseaddress(volnamebuf), 559 // sizeof(volnamebuf)-2, &volserial, &maxfilelen, &filesystemflags, 560 // stringbaseaddress(filesystemnamebuffer), sizeof (filesystemnamebuffer)) { 561 // 562 // } 563 564 if (GetDiskFreeSpace (stringbaseaddress (volname), &sectorsPerCluster, &bytesPerSector, 565 &numberOfFreeClusters, &totalNumberOfClusters)) { 566 567 DWORD bytesPerCluster; 568 DWORD numberOfClustersIn2GB; 569 570 bytesPerCluster = bytesPerSector * sectorsPerCluster; 571 572 numberOfClustersIn2GB = 0x7FFFFFFFL / bytesPerCluster; 573 574 info->ctfreebytes = (numberOfFreeClusters <= numberOfClustersIn2GB) 575 ? (numberOfFreeClusters * bytesPerCluster) 576 : (numberOfClustersIn2GB * bytesPerCluster); 577 578 info->cttotalbytes = (totalNumberOfClusters <= numberOfClustersIn2GB) 579 ? (totalNumberOfClusters * bytesPerCluster) 580 : (numberOfClustersIn2GB * bytesPerCluster); 581 582 info->blocksize = bytesPerCluster; 583 } 584 585 drivetype = GetDriveType (stringbaseaddress(volname)); 586 587 if ((drivetype == DRIVE_REMOVABLE) || (drivetype == DRIVE_CDROM)) { 588 info->flejectable = true; 589 } 590 591 if (drivetype == DRIVE_REMOTE) { 592 info->flremotevolume = true; 593 } 594 595 return (true); 596 } 597 598 wsprintf (stringbaseaddress(errmsg), "Can't complete function because \"%s\" is not a valid volume name.", stringbaseaddress(fsname(fs))); 599 600 setstringlength (errmsg, strlen(stringbaseaddress(errmsg))); 601 602 shellerrormessage (errmsg); 603 604 return (false); 605 } /*filegetfsvolumeinfo*/ 606 607 608 void winsetfileinfo (WIN32_FIND_DATA * fileinfo, tyfileinfo *info) { 609 610 FILETIME localFileTime; 611 bigstring bs, bsext; 612 613 clearbytes (info, sizeof (tyfileinfo)); /*init all fields to zero*/ 614 info->filecreator = ' '; 615 info->filetype = ' '; 616 617 618 info->flfolder = fileinfo->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY?true:false; 619 info->fllocked = fileinfo->dwFileAttributes & FILE_ATTRIBUTE_READONLY?true:false; 620 info->flbundle = false; 621 info->flbusy = false; 622 info->flalias = false; 623 info->flinvisible = fileinfo->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN?true:false; 624 info->flsystem = fileinfo->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM?true:false; 625 info->flarchive = fileinfo->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE?true:false; 626 info->flcompressed = fileinfo->dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED?true:false; 627 info->fltemp = fileinfo->dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY?true:false; 628 629 FileTimeToLocalFileTime (&fileinfo->ftCreationTime, &localFileTime); 630 info->timecreated = filetimetoseconds (&localFileTime); 631 632 FileTimeToLocalFileTime (&fileinfo->ftLastWriteTime, &localFileTime); 633 info->timemodified = filetimetoseconds (&localFileTime); 634 635 FileTimeToLocalFileTime (&fileinfo->ftLastAccessTime, &localFileTime); 636 info->timeaccessed = filetimetoseconds (&localFileTime); 637 638 info->sizedatafork = fileinfo->nFileSizeLow; 639 info->sizeresourcefork = 0; 640 info->sizedataforkhigh = fileinfo->nFileSizeHigh; 641 642 copyctopstring (fileinfo->cFileName, bs); 643 644 lastword (bs, '.', bsext); 645 646 if ((stringlength (bs) == stringlength (bsext)) || (stringlength (bsext) > 4)) { /* no extension */ 647 stringtoostype ("\x04" "????", &info->filetype); 648 } 649 else { 650 stringtoostype (bsext, &info->filetype); 651 } 652 653 } /*winsetfileinfo*/ 654 655 #endif 656 657 658 boolean filegetinfo (const tyfilespec *fs, tyfileinfo *info) { 659 660 #ifdef MACVERSION 661 /* 662 dmb 9/24/93: let filegetinfofrompb take care of volumes 663 */ 664 665 CInfoPBRec pb; 666 667 /* 668 if (isvolumefilespec (pfs)) { 669 670 return (filegetfsvolumeinfo (pfs, info)); 671 } 672 */ 673 674 if (!getmacfileinfo (fs, &pb)) 675 return (false); 676 677 filegetinfofrompb (&pb, info); 678 #endif 679 680 #ifdef WIN95VERSION 681 HANDLE findHandle; 682 HANDLE fref; 683 WIN32_FIND_DATA fileinfo; 684 char fn[300]; 685 686 clearbytes (info, sizeof (tyfileinfo)); /*init all fields to zero*/ 687 info->filecreator = ' '; 688 info->filetype = ' '; 689 690 if (fileisvolume (fs)) { 691 return (filegetfsvolumeinfo (fs, info)); 692 } 693 694 copystring (fsname (fs), fn); 695 696 /*if ends with \ get ride of it... and handle the root*/ 697 698 cleanendoffilename (fn); 699 700 nullterminate (fn); 701 702 703 findHandle = FindFirstFile (stringbaseaddress(fn), &fileinfo); 704 705 if (findHandle == INVALID_HANDLE_VALUE) { 706 707 winfileerror (fs); 708 709 return (false); 710 } 711 712 winsetfileinfo (&fileinfo, info); 713 714 FindClose(findHandle); 715 716 //Set the file busy flag (this should be in winsetfileinfo, but we do not have the filename there) 717 if (info->flfolder) { 718 strcat (stringbaseaddress (fn), "\\*"); 719 720 info->flbusy = false; //presume empty folder (not busy) 721 722 findHandle = FindFirstFile (stringbaseaddress(fn), &fileinfo); 723 724 if (findHandle != INVALID_HANDLE_VALUE) { 725 info->flbusy = true; //Found something 726 727 while ((strcmp (fileinfo.cFileName, ".") == 0) || (strcmp (fileinfo.cFileName, "..") == 0)) { 728 info->flbusy = false; // Just . or .. 729 730 if (FindNextFile (findHandle, &fileinfo)) 731 info->flbusy = true; //Found something else... 732 else 733 break; //exit while loop if FindNext fails (this is normal) 734 } 735 736 FindClose (findHandle); 737 } 738 } 739 else { 740 fref = (Handle) CreateFile (stringbaseaddress(fn), GENERIC_READ | GENERIC_WRITE, 0, 741 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 742 743 if (fref == INVALID_HANDLE_VALUE) { 744 info->flbusy = true; 745 } 746 else { 747 info->flbusy = false; 748 verify (CloseHandle (fref)); 749 } 750 } 751 752 #endif 753 return (true); 754 } /*filegetinfo*/ 755 756 757 758 boolean filegetvolumename (short vnum, bigstring volname) { 759 #ifdef MACVERSION 760 HVolumeParam pb; 761 OSErr ec; 762 763 clearbytes (&pb, sizeof (pb)); /*init all fields to zero*/ 764 765 pb.ioNamePtr = volname; 766 767 pb.ioVRefNum = vnum; 768 769 ec = PBHGetVInfoSync ((HParmBlkPtr) &pb); 770 771 if (ec != noErr) { 772 773 setstringlength (volname, 0); 774 775 return (false); 776 } 777 778 return (true); 779 #endif 780 781 #ifdef WIN95VERSION 782 char szVol[30]; 783 DWORD serialNum, maxComponentLen, fileSystemFlags; 784 boolean res; 785 786 if ((vnum > 26) || (vnum < 0)) 787 return (false); 788 789 if (vnum != 0) { 790 strcpy (szVol, "A:\\"); 791 szVol[0] = szVol[0] + (vnum - 1); 792 } 793 794 res = GetVolumeInformation (vnum==0?NULL:szVol, stringbaseaddress(volname), sizeof(volname)-2, 795 &serialNum, &maxComponentLen, &fileSystemFlags, NULL, 0); 796 797 if (res) { 798 setstringlength (volname, strlen(stringbaseaddress(volname))); 799 } 800 801 return (res); 802 #endif 803 } /*filegetvolumename*/ 804 805 806 807 boolean fileisbusy (const tyfilespec *fs, boolean *flbusy) { 808 809 /* 810 6/x/91 mao 811 */ 812 813 tyfileinfo info; 814 815 if (!filegetinfo (fs, &info)) 816 return (false); 817 818 *flbusy = info.flbusy; 819 820 return (true); 821 } /*fileisbusy*/ 822 823 824 boolean filehasbundle (const tyfilespec *fs, boolean *flbundle) { 825 826 /* 827 6/x/91 mao 828 */ 829 830 tyfileinfo info; 831 832 if (!filegetinfo (fs, &info)) 833 return (false); 834 835 *flbundle = info.flbundle; 836 837 return (true); 838 } /*filehasbundle*/ 839 840 841 boolean filesetbundle (const tyfilespec *fs, boolean flbundle) { 842 #ifdef MACVERSION 843 /* 844 8/10/92 dmb 845 */ 846 847 CInfoPBRec pb; 848 849 if (!getmacfileinfo (fs, &pb)) 850 return (false); 851 852 if (flbundle) 853 pb.hFileInfo.ioFlFndrInfo.fdFlags |= kHasBundle; /*turn on*/ 854 else 855 pb.hFileInfo.ioFlFndrInfo.fdFlags &= ~kHasBundle; /*turn off*/ 856 857 return (setmacfileinfo (fs, &pb)); 858 #endif 859 860 #ifdef WIN95VERSION 861 return (false); 862 #endif 863 } /*filesetbundle*/ 864 865 866 boolean fileisalias (const tyfilespec *fs, boolean *flalias) { 867 868 /* 869 6/x/91 mao 870 */ 871 872 tyfileinfo info; 873 874 if (!filegetinfo (fs, &info)) 875 return (false); 876 877 *flalias = info.flalias; 878 879 return (true); 880 } /*fileisalias*/ 881 882 883 boolean fileisvisible (const tyfilespec *fs, boolean *flvisible) { 884 885 /* 886 6/9/92 dmb 887 */ 888 889 tyfileinfo info; 890 891 if (!filegetinfo (fs, &info)) 892 return (false); 893 894 *flvisible = !info.flinvisible; 895 896 return (true); 897 } /*fileisvisible*/ 898 899 900 boolean filesetvisible (const tyfilespec *fs, boolean flvisible) { 901 #ifdef MACVERSION 902 /* 903 6/9/92 dmb 904 */ 905 906 CInfoPBRec pb; 907 908 if (!getmacfileinfo (fs, &pb)) 909 return (false); 910 911 if (flvisible) 912 pb.hFileInfo.ioFlFndrInfo.fdFlags &= ~kIsInvisible; /*turn off*/ 913 else 914 pb.hFileInfo.ioFlFndrInfo.fdFlags |= kIsInvisible; /*turn on*/ 915 916 if (!setmacfileinfo (fs, &pb)) 917 return (false); 918 919 touchparentfolder (fs); 920 #endif 921 922 #ifdef WIN95VERSION 923 tyfileinfo info; 924 DWORD attr; 925 926 if (!filegetinfo (fs, &info)) 927 return (false); 928 929 if (info.flinvisible == flvisible) /*check if we need to do anything first*/ 930 { 931 attr = GetFileAttributes (stringbaseaddress (fsname (fs))); 932 933 if (attr == 0xFFFFFFFF) 934 return (false); 935 936 attr = attr & (~FILE_ATTRIBUTE_HIDDEN); 937 938 if (! flvisible) 939 attr = attr | FILE_ATTRIBUTE_HIDDEN; 940 941 return(SetFileAttributes (stringbaseaddress (fsname (fs)), attr)); 942 } 943 #endif 944 return (true); 945 } /*filesetvisible*/ 946 947 948 949 boolean getfiletype (const tyfilespec *fs, OSType *type) { 950 951 tyfileinfo info; 952 953 *type = ' '; 954 955 if (!filegetinfo (fs, &info)) 956 return (false); 957 958 *type = info.filetype; 959 960 return (true); 961 } /*getfiletype*/ 962 963 964 boolean getfilecreator (const tyfilespec *fs, OSType *creator) { 965 966 tyfileinfo info; 967 968 *creator = ' '; 969 970 if (!filegetinfo (fs, &info)) 971 return (false); 972 973 *creator = info.filecreator; 974 975 return (true); 976 } /*getfilecreator*/ 977 978 979 980 boolean filesize (const tyfilespec *fs, long *size) { 981 982 tyfileinfo info; 983 984 if (!filegetinfo (fs, &info)) 985 return (false); 986 987 *size = info.sizedatafork + info.sizeresourcefork; 988 989 return (true); 990 } /*filesize*/ 991 992 993 boolean fileisfolder (const tyfilespec *fs, boolean *flfolder) { 994 995 tyfileinfo info; 996 997 #ifdef WIN95VERSION 998 /* special case the root directory on Windows */ 999 char fn[300]; 1000 1001 copystring (fsname (fs), fn); 1002 1003 if (fn[2] == ':' && isalpha(fn[1])) { 1004 1005 if ((stringlength(fn) == 2) || ((stringlength(fn) == 3) && (fn[3] == '\\'))) { 1006 1007 if (fileisvolume (fs)) { 1008 1009 *flfolder = true; 1010 1011 return (true); 1012 } 1013 } 1014 } 1015 1016 #endif 1017 1018 if (!filegetinfo (fs, &info)) 1019 return (false); 1020 1021 *flfolder = info.flfolder; 1022 1023 return (true); 1024 } /*fileisfolder*/ 1025 1026 1027 boolean fileisvolume (const tyfilespec *fs) { 1028 #ifdef MACVERSION 1029 if (isemptystring ((*fs).name)) 1030 return (false); 1031 1032 return ((*fs).parID == fsRtParID); 1033 #endif 1034 1035 #ifdef WIN95VERSION 1036 bigstring bsvol; 1037 short drivenum; 1038 DWORD drivemap, drivemask; 1039 1040 copystring (fsname(fs), bsvol); 1041 1042 switch (stringlength (bsvol)) { 1043 1044 case 3: 1045 if (getstringcharacter(bsvol, 2) != '\\') 1046 return (false); 1047 1048 case 2: 1049 if (getstringcharacter(bsvol, 1) != ':') 1050 return (false); 1051 1052 if (! isalpha (getstringcharacter(bsvol, 0))) 1053 return (false); 1054 1055 drivenum = getlower(getstringcharacter(bsvol, 0)) - 'a'; 1056 break; 1057 1058 default: 1059 return (false); 1060 } 1061 1062 drivemap = GetLogicalDrives(); 1063 1064 drivemask = 1 << drivenum; 1065 1066 return ((drivemap & drivemask) == drivemask); 1067 #endif 1068 } /*fileisvolume*/ 1069 1070 1071 boolean fileislocked (const tyfilespec *fs, boolean *fllocked) { 1072 1073 tyfileinfo info; 1074 1075 if (!filegetinfo (fs, &info)) 1076 return (false); 1077 1078 *fllocked = info.fllocked; 1079 1080 return (true); 1081 } /*fileislocked*/ 1082 1083 1084 boolean getfiledates (const tyfilespec *fs, unsigned long *datecreated, unsigned long *datemodified) { 1085 1086 tyfileinfo info; 1087 1088 if (!filegetinfo (fs, &info)) 1089 return (false); 1090 1091 *datecreated = info.timecreated; 1092 1093 *datemodified = info.timemodified; 1094 1095 return (true); 1096 } /*getfiledates*/ 1097 1098 1099 boolean setfiledates (const tyfilespec *fs, unsigned long datecreated, unsigned long datemodified) { 1100 #ifdef MACVERSION 1101 /* 1102 6/x/91 mao: modified to work with new getmacilfeinfo/setmacfileinfo. 1103 */ 1104 1105 CInfoPBRec pb; 1106 1107 if (!getmacfileinfo (fs, &pb)) 1108 return (false); 1109 1110 if (foldertest (&pb)) { 1111 1112 pb.dirInfo.ioDrCrDat = datecreated; 1113 1114 pb.dirInfo.ioDrMdDat = datemodified; 1115 } 1116 else { 1117 1118 pb.hFileInfo.ioFlCrDat = datecreated; 1119 1120 pb.hFileInfo.ioFlMdDat = datemodified; 1121 } 1122 1123 return (setmacfileinfo (fs, &pb)); 1124 #endif 1125 1126 #ifdef WIN95VERSION 1127 HANDLE h; 1128 FILETIME modtime, createtime, temp; 1129 char fn[300]; 1130 DWORD err; 1131 boolean fl; 1132 1133 secondstofiletime (datecreated, &temp); 1134 LocalFileTimeToFileTime (&temp, &createtime); 1135 1136 secondstofiletime (datemodified, &temp); 1137 LocalFileTimeToFileTime (&temp, &modtime); 1138 1139 copystring (fsname (fs), fn); 1140 1141 nullterminate (fn); 1142 1143 h = CreateFile (stringbaseaddress(fn), GENERIC_READ | GENERIC_WRITE, 1144 FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 1145 1146 if (h == INVALID_HANDLE_VALUE) { 1147 1148 winfileerror (fs); 1149 1150 return (false); 1151 } 1152 1153 1154 //We do not alter the accessed time. 1155 fl = SetFileTime (h, &createtime, NULL, &modtime); 1156 1157 if (!fl) 1158 err = GetLastError(); 1159 1160 verify (CloseHandle (h)); 1161 1162 if (fl) 1163 return (true); 1164 1165 oserror(err); 1166 return (false); 1167 #endif 1168 } /*setfiledates*/ 1169 1170 1171 #ifdef MACVERSION 1172 boolean getfilepos (const tyfilespec *fs, Point *pt) { 1173 1174 /* 1175 mao 6/x/91: modified to work with new getmacilfeinfo/setmacfileinfo. 1176 */ 1177 1178 CInfoPBRec pb; 1179 1180 if (!getmacfileinfo (fs, &pb)) 1181 return (false); 1182 1183 if (foldertest (&pb)) 1184 *pt = pb.dirInfo.ioDrUsrWds.frLocation; 1185 else 1186 *pt = pb.hFileInfo.ioFlFndrInfo.fdLocation; 1187 1188 return (true); 1189 } /*getfilepos*/ 1190 1191 1192 boolean setfilepos (const tyfilespec *fs, Point pt) { 1193 1194 /* 1195 6/x/91 mao: modified to work with new getmacilfeinfo/setmacfileinfo. 1196 */ 1197 1198 CInfoPBRec pb; 1199 1200 if (!getmacfileinfo (fs, &pb)) 1201 return (false); 1202 1203 if (foldertest (&pb)) 1204 pb.dirInfo.ioDrUsrWds.frLocation = pt; 1205 else 1206 pb.hFileInfo.ioFlFndrInfo.fdLocation = pt; 1207 1208 return (setmacfileinfo (fs, &pb)); 1209 } /*setfilepos*/ 1210 #endif 1211 1212 boolean setfilecreated (const tyfilespec *fs, long when) { 1213 1214 /* 1215 7/31/91 dmb: created 1216 */ 1217 1218 unsigned long datecreated, datemodified; 1219 1220 if (!getfiledates (fs, &datecreated, &datemodified)) 1221 return (false); 1222 1223 return (setfiledates (fs, when, datemodified)); 1224 } /*setfilecreated*/ 1225 1226 1227 boolean setfilemodified (const tyfilespec *fs, long when) { 1228 1229 /* 1230 7/31/91 dmb: created 1231 */ 1232 1233 unsigned long datecreated, datemodified; 1234 1235 if (!getfiledates (fs, &datecreated, &datemodified)) 1236 return (false); 1237 1238 return (setfiledates (fs, datecreated, when)); 1239 } /*setfilemodified*/ 1240 1241 1242 #ifdef MACVERSION 1243 boolean setfiletype (const tyfilespec *fs, OSType filetype) { 1244 1245 /* 1246 6/x/91 mao: modified to work with new getmacilfeinfo/setmacfileinfo. 1247 */ 1248 1249 CInfoPBRec pb; 1250 1251 if (!getmacfileinfo (fs, &pb)) 1252 return (false); 1253 1254 if (foldertest (&pb)) 1255 return (false); 1256 1257 pb.hFileInfo.ioFlFndrInfo.fdType = filetype; 1258 1259 return (setmacfileinfo (fs, &pb)); 1260 } /*setfiletype*/ 1261 1262 1263 boolean setfilecreator (const tyfilespec *fs, OSType filecreator) { 1264 1265 /* 1266 6/x/91 mao: modified to work with new getmacilfeinfo/setmacfileinfo. Also, makes sure 1267 folders aren't operated on 1268 */ 1269 1270 CInfoPBRec pb; 1271 1272 if (!getmacfileinfo (fs, &pb)) 1273 return (false); 1274 1275 if (foldertest (&pb)) 1276 return (false); 1277 1278 pb.hFileInfo.ioFlFndrInfo.fdCreator = filecreator; 1279 1280 return (setmacfileinfo (fs, &pb)); 1281 } /*setfilecreator*/ 1282 #endif 1283 1284 #ifdef MACVERSION 1285 static boolean copyfork (hdlfilenum fsource, hdlfilenum fdest, Handle hbuffer) { 1286 1287 /* 1288 copy either the data fork or resource fork of the indicated file. 1289 1290 return true iff the file copy was successful. 1291 1292 5/19/92 dmb: call langbackgroundtask when a script is running to make it more 1293 likely that we'll yield the processor to another app. also, only allow 1294 background tasks if fork is larger than a single buffer. note that if a script 1295 is copying a bunch of files in a loop, the interpreter is already allowing 1296 backgrounding between files. 1297 */ 1298 1299 register long buffersize = GetHandleSize (hbuffer); 1300 long ctbytes; 1301 register OSErr errcode; 1302 1303 SetFPos (fsource, fsFromStart, 0L); 1304 1305 SetFPos (fdest, fsFromStart, 0L); 1306 1307 while (true) { 1308 1309 ctbytes = buffersize; 1310 1311 HLock (hbuffer); 1312 1313 errcode = FSRead (fsource, &ctbytes, *hbuffer); 1314 1315 HUnlock (hbuffer); 1316 1317 if ((errcode != noErr) && (errcode != eofErr)) { 1318 1319 oserror (errcode); 1320 1321 return (false); 1322 } 1323 1324 if (ctbytes == 0) /*last read got no bytes*/ 1325 return (true); 1326 1327 HLock (hbuffer); 1328 1329 errcode = FSWrite (fdest, &ctbytes, *hbuffer); 1330 1331 HUnlock (hbuffer); 1332 1333 if (oserror (errcode)) 1334 return (false); 1335 1336 if (ctbytes < buffersize) /*copy of fork is finished*/ 1337 return (true); 1338 1339 if (flscriptrunning) 1340 langbackgroundtask (false); 1341 else 1342 shellbackgroundtask (); /*give background processes a chance*/ 1343 1344 filebeachball (); /*roll the beachball cursor if there is one*/ 1345 } /*while*/ 1346 } /*copyfork*/ 1347 1348 1349 #endif 1350 1351 boolean largefilebuffer (Handle *hbuffer) { 1352 1353 /* 1354 allocate a "large" buffer for a file copy or some kind of transfer. 1355 1356 we ask for a block the size of half of the current free space. if we can't 1357 get it, we'll ask for the largest free block. in any case, we fail if 1358 we can't get a block of at least a K 1359 1360 3/16/92 dmb: total rewrite; old version _always_ compacted the heap, 1361 resulting in poor performance. 1362 */ 1363 1364 register long ctbytes; 1365 register Handle h; 1366 1367 *hbuffer = nil; /*default return*/ 1368 1369 #ifdef MACVERSION 1370 ctbytes = FreeMem () / 2; 1371 1372 if (ctbytes < 1024) { /*no enough memory to work with*/ 1373 1374 memoryerror (); 1375 1376 return (false); 1377 } 1378 1379 ctbytes &= ~(1024 - 1); /*fast round down to nearest multiple of 1024*/ 1380 1381 h = NewHandle (ctbytes); 1382 1383 if (h != nil) { 1384 1385 *hbuffer = h; 1386 1387 return (true); 1388 } 1389 1390 /*allocation failed; heap has been compacted; find largest block size*/ 1391 1392 ctbytes = CompactMem (maxSize); /*recompact the heap, finding out size of largest block*/ 1393 1394 if (ctbytes < 1024) { /*largest block is too small to use*/ 1395 1396 memoryerror (); 1397 1398 return (false); 1399 } 1400 1401 #endif 1402 1403 #ifdef WIN95VERSION 1404 DBG_UNREFERENCED_LOCAL_VARIABLE(h); 1405 1406 ctbytes = 0x00020000L; /* 128K buffer */ 1407 #endif 1408 1409 ctbytes &= ~(1024 - 1); /*fast round down to nearest multiple of 1024*/ 1410 1411 return (newhandle (ctbytes, hbuffer)); /*shouldn't fail at this point, but let's be sure*/ 1412 } /*largefilebuffer*/ 1413 1414 1415 #ifdef MACVERSION 1416 1417 static pascal OSErr FSpCreateMinimum (const FSSpec *fs) 1418 { 1419 HParamBlockRec pb; 1420 1421 pb.fileParam.ioNamePtr = (StringPtr)(*fs).name; 1422 1423 pb.fileParam.ioVRefNum = (*fs).vRefNum; 1424 1425 pb.ioParam.ioVersNum = 0; 1426 1427 pb.fileParam.ioDirID = (*fs).parID; 1428 1429 return (PBHCreateSync (&pb)); 1430 } /*FSpCreateMinimum*/ 1431 1432 1433 static pascal OSErr FSpOpenAware (const tyfilespec *fs, boolean flresource, short denyModes, hdlfilenum *refNum) { 1434 1435 /* 1436 3.0.2 dmb: customized version of HOpenAware from MoreFiles 1.1 1437 */ 1438 1439 HParamBlockRec pb; 1440 OSErr err; 1441 GetVolParmsInfoBuffer volParmsInfo; 1442 long infoSize = sizeof (GetVolParmsInfoBuffer); 1443 1444 pb.ioParam.ioNamePtr = (StringPtr) (*fs).name; 1445 pb.ioParam.ioVRefNum = (*fs).vRefNum; 1446 pb.ioParam.ioVersNum = 0; 1447 pb.ioParam.ioMisc = nil; 1448 1449 /* 1450 get volume attributes 1451 this preflighting is needed because Foreign File Access based file systems don't 1452 return the correct error result to the OpenDeny call 1453 */ 1454 pb.ioParam.ioBuffer = (Ptr) &volParmsInfo; 1455 pb.ioParam.ioReqCount = infoSize; 1456 1457 err = PBHGetVolParmsSync (&pb); 1458 1459 pb.fileParam.ioDirID = (*fs).parID; 1460 1461 /* 1462 err = HGetVolParms ((StringPtr) (*fs).name, (*fs).vRefNum, &volParmsInfo, &infoSize); 1463 */ 1464 1465 if (err == noErr) { 1466 1467 /* if volume supports OpenDeny, use it and return */ 1468 if (hasOpenDeny (volParmsInfo)) { 1469 1470 pb.accessParam.ioDenyModes = denyModes; 1471 1472 if (flresource) 1473 err = PBHOpenRFDenySync (&pb); 1474 else 1475 err = PBHOpenDenySync (&pb); 1476 1477 *refNum = pb.ioParam.ioRefNum; 1478 1479 return (err); 1480 } 1481 } 1482 else 1483 if (err != paramErr) /* paramErr is OK, it just means this volume doesn't support GetVolParms */ 1484 return (err); 1485 1486 /* 1487 OpenDeny isn't supported, so try File Manager Open functions 1488 Set File Manager permissions to closest thing possible 1489 */ 1490 pb.ioParam.ioPermssn = ((denyModes == dmWr) || (denyModes == dmRdWr)) ? (fsRdWrShPerm) : (denyModes % 4); 1491 1492 if (flresource) 1493 err = PBHOpenRFSync (&pb); 1494 1495 else { 1496 1497 err = PBHOpenDFSync (&pb); /* Try OpenDF */ 1498 1499 if (err == paramErr) 1500 err = PBHOpenSync (&pb); /* OpenDF not supported, so try Open */ 1501 } 1502 1503 *refNum = pb.ioParam.ioRefNum; 1504 1505 return (err); 1506 } /*FSpOpenAware*/ 1507 1508 1509 static boolean copyfileattrs (const tyfilespec *fsource, const tyfilespec *fdest, boolean flcopylockbit) { 1510 1511 CInfoPBRec pb; 1512 OSErr err; 1513 boolean flfolder; 1514 1515 pb.hFileInfo.ioVRefNum = (*fsource).vRefNum; 1516 pb.hFileInfo.ioDirID = (*fsource).parID; 1517 pb.hFileInfo.ioNamePtr = (StringPtr) (*fsource).name; 1518 pb.hFileInfo.ioFDirIndex = 0; 1519 1520 err = PBGetCatInfoSync(&pb); 1521 1522 if (err == noErr) { 1523 1524 flfolder = (pb.hFileInfo.ioFlAttrib & 0x10); 1525 1526 pb.hFileInfo.ioVRefNum = (*fdest).vRefNum; 1527 pb.hFileInfo.ioDirID = (*fdest).parID; 1528 pb.hFileInfo.ioNamePtr = (StringPtr) (*fdest).name; 1529 1530 /* don't copy the hasBeenInited bit */ 1531 pb.hFileInfo.ioFlFndrInfo.fdFlags = (pb.hFileInfo.ioFlFndrInfo.fdFlags & 0xfeff); 1532 1533 err = PBSetCatInfoSync(&pb); 1534 1535 if ((err == noErr) && (flcopylockbit) && (pb.hFileInfo.ioFlAttrib & 0x01)) { 1536 1537 err = PBHSetFLockSync ((HParmBlkPtr) &pb); 1538 1539 if ((err != noErr) && (flfolder)) 1540 err = noErr; /* ignore lock errors if destination is directory */ 1541 } 1542 } 1543 1544 return (err); 1545 } /*copyfileattrs*/ 1546 1547 1548 boolean copyfile (const tyfilespec *fsource, const tyfilespec *fdest, boolean fldata, boolean flresources) { 1549 1550 /* 1551 create a copy of the indicated file in the destination volume, with the indicated 1552 name. 1553 1554 we allocate a good-sized buffer in the heap, then open and copy the data fork then 1555 open and copy the resource fork of the source file. 1556 1557 return true if the operation was successful, false otherwise. 1558 1559 7/27/90 DW: add fldata, flresources -- allows selective copying of the two 1560 forks of each file. we assume one of these two booleans is true. 1561 1562 3/16/92 dmb: maintain all public Finder flags, not just creator/type & dates 1563 1564 3.0.2 dmb: use CreateMinimum and do things in special order for drop-box copies. 1565 For details, see MoreFiles:FileCopy.c on the Reference Library CD. note that 1566 there are more details handled by the sample code that we're ignoring here. one 1567 is using CopyFile if src and dst are on the same server and the server supports 1568 that function. another is to open forks with deny modes set. maybe next time... 1569 also, we now handle folders, so file.copy can retain folder attributes. 1570 */ 1571 1572 Handle hbuffer = nil; 1573 short sourcefnum = 0, sourcernum = 0; 1574 short destfnum = 0, destrnum = 0; 1575 boolean fldestcreated = false; 1576 boolean flsourcefolder, fldestfolder; 1577 1578 if (!fileisfolder (fsource, &flsourcefolder)) 1579 return (false); 1580 1581 if (flsourcefolder) 1582 fldata = flresources = false; 1583 1584 else { 1585 1586 if (!largefilebuffer (&hbuffer)) 1587 return (false); 1588 } 1589 1590 if (fldata) { 1591 1592 if (oserror (FSpOpenAware (fsource, false, dmRdDenyWr, &sourcefnum))) 1593 goto error; 1594 } 1595 1596 if (flresources) { 1597 1598 if (oserror (FSpOpenAware (fsource, true, dmRdDenyWr, &sourcernum))) 1599 goto error; 1600 } 1601 1602 if (fileexists (fdest, &fldestfolder)) { /*file exists, delete it*/ 1603 1604 if (!deletefile (fdest)) 1605 goto error; 1606 } 1607 1608 setfserrorparam (fdest); /*in case error message takes a filename parameter*/ 1609 1610 if (flsourcefolder) { 1611 1612 if (!newfolder (fdest)) 1613 goto error; 1614 } 1615 else { 1616 1617 if (oserror (FSpCreateMinimum (fdest))) 1618 goto error; 1619 } 1620 1621 fldestcreated = true; 1622 1623 if (oserror (copyfileattrs (fsource, fdest, false))) 1624 goto error; 1625 1626 if (fldata) { 1627 1628 if (oserror (FSpOpenAware (fdest, false, dmWrDenyRdWr, &destfnum))) 1629 goto error; 1630 } 1631 1632 if (flresources) { 1633 1634 if (oserror (FSpOpenAware (fdest, true, dmWrDenyRdWr, &destrnum))) 1635 goto error; 1636 } 1637 1638 if (fldata) { 1639 1640 if (!copyfork (sourcefnum, destfnum, hbuffer)) /*copy data fork*/ 1641 goto error; 1642 1643 closefile (sourcefnum); 1644 1645 closefile (destfnum); 1646 1647 sourcefnum = 0; 1648 1649 destfnum = 0; 1650 } 1651 1652 if (flresources) { 1653 1654 if (!copyfork (sourcernum, destrnum, hbuffer)) /*copy resource fork*/ 1655 goto error; 1656 1657 closefile (sourcernum); 1658 1659 closefile (destrnum); 1660 1661 sourcernum = 0; 1662 1663 destrnum = 0; 1664 } 1665 1666 disposehandle (hbuffer); 1667 1668 hbuffer = nil; /*if error don't dispose of it again*/ 1669 1670 copyfileattrs (fsource, fdest, true); /*ignore error*/ 1671 1672 return (true); /*the file copy was successful*/ 1673 1674 error: /*goto here to release the buffer, close files and return false*/ 1675 1676 if (hbuffer != nil) 1677 disposehandle (hbuffer); 1678 1679 if (sourcefnum != 0) 1680 closefile (sourcefnum); 1681 1682 if (sourcernum != 0) 1683 closefile (sourcernum); 1684 1685 if (destfnum != 0) 1686 closefile (destfnum); 1687 1688 if (destrnum != 0) 1689 closefile (destrnum); 1690 1691 if (fldestcreated) 1692 deletefile (fdest); /*no file created on error*/ 1693 1694 return (false); 1695 } /*copyfile*/ 1696 #endif 1697 1698 1699 #ifdef WIN95VERSION 1700 boolean copyfile (const tyfilespec *fsource, const tyfilespec *fdest, boolean fldata, boolean flresources) { 1701 1702 /* 1703 5.0.1 dmb: if the file exists, overwrite it. 1704 */ 1705 1706 char fn[300]; 1707 char fn2[300]; 1708 boolean flcreatefolder; 1709 boolean fldestfolder; 1710 1711 copystring (fsname (fsource), fn); 1712 copystring (fsname (fdest), fn2); 1713 1714 cleanendoffilename (fn); 1715 cleanendoffilename (fn2); 1716 1717 nullterminate (fn); 1718 nullterminate (fn2); 1719 1720 if (!fileisfolder (fsource, &flcreatefolder)) 1721 return (false); 1722 1723 if (flcreatefolder) { 1724 1725 if (fileexists (fdest, &fldestfolder)) { /*file exists, delete it*/ 1726 1727 if (!deletefile (fdest)) 1728 return (false); 1729 } 1730 1731 if (CreateDirectoryEx (stringbaseaddress(fn), stringbaseaddress(fn2), NULL)) 1732 return (true); 1733 1734 winfileerror (fdest); 1735 1736 return (false); 1737 } 1738 1739 if (CopyFile (stringbaseaddress (fn), stringbaseaddress(fn2), false)) 1740 return (true); 1741 1742 winfileerror (fdest); 1743 1744 return (false); 1745 } /*copyfile*/ 1746 #endif 1747 1748 short filegetapplicationrnum (void) { 1749 1750 return (applicationresnum); 1751 } /*filegetapplicationrnum*/ 1752 1753 1754 #ifdef flsystem6 1755 1756 short filegetapplicationvnum (void) { 1757 1758 return (applicationvolnum); 1759 } /*filegetapplicationvnum*/ 1760 1761 1762 short filegetsystemvnum (void) { 1763 1764 SysEnvRec env; 1765 1766 SysEnvirons (1, &env); 1767 1768 return (env.sysVRefNum); 1769 } /*filegetsystemvnum*/ 1770 1771 #endif 1772 1773 #ifdef MACVERSION 1774 static boolean pathtovolume (bigstring bspath, short *vnum) { 1775 1776 if (countwords (bspath, chpathseparator) > 1) { 1777 1778 oserror (errorVolume); /*no such volume*/ 1779 1780 return (false); 1781 } 1782 1783 if (!fileparsevolname (bspath, vnum, nil)) { 1784 1785 oserror (errorVolume); /*no such volume*/ 1786 1787 return (false); 1788 } 1789 1790 return (true); 1791 } /*pathtovolume*/ 1792 #endif 1793 1794 //Timothy Paustian's comments 1795 //warning the values returned by getspecialfolderpath on OS X are very different 1796 //than classic Mac OS 1797 boolean getspecialfolderpath (bigstring bsvol, bigstring bsfolder, boolean flcreate, tyfilespec *fs) { 1798 1799 #ifdef MACVERSION 1800 /* 1801 9/1/92 dmb: last new verb for 2.0. (?) 1802 */ 1803 1804 short vnum; 1805 short ixlist; 1806 long dirid; 1807 OSType foldertype; 1808 long attrs; 1809 OSErr errcode = errorNone; 1810 bigstring bsfirst; 1811 1812 if (!(gestalt (gestaltFindFolderAttr, &attrs) && (attrs & (1 << gestaltFindFolderPresent)))) 1813 return (false); 1814 1815 if (isemptystring (bsvol)) 1816 1817 #if TARGET_API_MAC_CARBON 1818 vnum = kUserDomain; 1819 #else 1820 vnum = kOnSystemDisk; 1821 #endif 1822 else { 1823 if (!pathtovolume (bsvol, &vnum)) 1824 return (false); 1825 } 1826 1827 setoserrorparam (bsfolder); 1828 1829 if (stringlength (bsfolder) == sizeof (OSType)) /*received folder type code*/ 1830 stringtoostype (bsfolder, &foldertype); 1831 1832 else { 1833 firstword (bsfolder, chspace, bsfirst); 1834 1835 if (findstringlist (bsfirst, specialfolderlistnumber, &ixlist)) 1836 { 1837 foldertype = specialfolders [ixlist]; 1838 #if TARGET_API_MAC_CARBON 1839 //temp items, we want to redirect to the users domain. 1840 //if we don't do this then it is a read only directory at the root. 1841 if (ixlist == 11) 1842 vnum = kUserDomain; 1843 #endif 1844 } 1845 else 1846 errcode = dirNFErr; 1847 } 1848 1849 if (errcode == noErr) 1850 errcode = FindFolder (vnum, foldertype, flcreate, &vnum, &dirid); 1851 1852 1853 if (errcode == noErr) { 1854 1855 errcode = FSMakeFSSpec (vnum, dirid, nil, fs); 1856 1857 /* 1858 if (!directorytopath (dirid, vnum, bspath)) /%shouldn't fail%/ 1859 errcode = dirNFErr; 1860 */ 1861 } 1862 1863 return (!oserror (errcode)); 1864 #endif 1865 1866 #ifdef WIN95VERSION 1867 int nFolder = -1; 1868 int res; 1869 ITEMIDLIST * il; 1870 // Global pointer to the shell's IMalloc interface. 1871 LPMALLOC g_pMalloc = NULL; 1872 1873 1874 if (equalidentifiers ("\x6" "system", bsfolder)) { 1875 unsigned char str[MAX_PATH]; 1876 1877 res = GetSystemDirectory (str, MAX_PATH); 1878 if (res == 0) { 1879 return (! oserror(GetLastError())); 1880 } 1881 1882 if (res > 255) 1883 res = 255; 1884 1885 memmove (stringbaseaddress(fsname(fs)), str, res); 1886 setstringlength(fsname(fs), res); 1887 pushchar ('\\', fsname(fs)); 1888 nullterminate (fsname(fs)); 1889 return (true); 1890 } 1891 1892 if (equalidentifiers ("\x7" "windows", bsfolder)) { 1893 unsigned char str[MAX_PATH]; 1894 1895 res = GetWindowsDirectory (str, MAX_PATH); 1896 if (res == 0) { 1897 return (! oserror(GetLastError())); 1898 } 1899 1900 if (res > 255) 1901 res = 255; 1902 1903 memmove (stringbaseaddress(fsname(fs)), str, res); 1904 setstringlength(fsname(fs), res); 1905 pushchar ('\\', fsname(fs)); 1906 nullterminate (fsname(fs)); 1907 return (true); 1908 } 1909 1910 if (equalidentifiers ("\x9" "bitbucket", bsfolder)) 1911 nFolder = CSIDL_BITBUCKET; 1912 else if (equalidentifiers ("\x8" "controls", bsfolder)) 1913 nFolder = CSIDL_CONTROLS; 1914 else if (equalidentifiers ("\x7" "desktop", bsfolder)) 1915 nFolder = CSIDL_DESKTOP; 1916 else if (equalidentifiers ("\x10" "desktopdirectory", bsfolder)) 1917 nFolder = CSIDL_DESKTOPDIRECTORY; 1918 else if (equalidentifiers ("\x6" "drives", bsfolder)) 1919 nFolder = CSIDL_DRIVES; 1920 else if (equalidentifiers ("\x5" "fonts", bsfolder)) 1921 nFolder = CSIDL_FONTS; 1922 else if (equalidentifiers ("\x7" "nethood", bsfolder)) 1923 nFolder = CSIDL_NETHOOD; 1924 else if (equalidentifiers ("\x7" "network", bsfolder)) 1925 nFolder = CSIDL_NETWORK; 1926 else if (equalidentifiers ("\x8" "personal", bsfolder)) 1927 nFolder = CSIDL_PERSONAL; 1928 else if (equalidentifiers ("\x8" "printers", bsfolder)) 1929 nFolder = CSIDL_PRINTERS; 1930 else if (equalidentifiers ("\x8" "programs", bsfolder)) 1931 nFolder = CSIDL_PROGRAMS; 1932 else if (equalidentifiers ("\x6" "recent", bsfolder)) 1933 nFolder = CSIDL_RECENT; 1934 else if (equalidentifiers ("\x6" "sendto", bsfolder)) 1935 nFolder = CSIDL_SENDTO; 1936 else if (equalidentifiers ("\x9" "startmenu", bsfolder)) 1937 nFolder = CSIDL_STARTMENU; 1938 else if (equalidentifiers ("\x7" "startup", bsfolder)) 1939 nFolder = CSIDL_STARTUP; 1940 else if (equalidentifiers ("\x9" "templates", bsfolder)) 1941 nFolder = CSIDL_TEMPLATES; 1942 1943 if(nFolder != -1) { 1944 // Get the shell's allocator. 1945 if (!SUCCEEDED(SHGetMalloc(&g_pMalloc))) { 1946 oserror (ERROR_INVALID_FUNCTION); 1947 return (false); 1948 } 1949 1950 if (SHGetSpecialFolderLocation (NULL, nFolder, &il) == NOERROR) { 1951 /*process itemlist */ 1952 if (SHGetPathFromIDList (il, stringbaseaddress(fsname(fs)))) { 1953 setstringlength (fsname(fs), strlen(stringbaseaddress(fsname(fs)))); 1954 pushchar ('\\', fsname(fs)); 1955 nullterminate (fsname(fs)); 1956 1957 // Free the PIDL 1958 g_pMalloc->lpVtbl->Free(g_pMalloc, il); 1959 1960 // Release the shell's allocator. 1961 g_pMalloc->lpVtbl->Release(g_pMalloc); 1962 return (true); 1963 } 1964 } 1965 } 1966 1967 // Release the shell's allocator. mnbmj 1968 if (g_pMalloc != NULL) 1969 g_pMalloc->lpVtbl->Release(g_pMalloc); 1970 1971 oserror (ERROR_INVALID_FUNCTION); 1972 return (false); 1973 #endif 1974 } /*getspecialfolderpath*/ 1975 1976 1977 #ifdef MACVERSION 1978 boolean ejectvol (const tyfilespec *fs) { 1979 1980 /* 1981 6/x/91 mao 1982 */ 1983 1984 #if TARGET_API_MAC_CARBON 1985 return false; 1986 #else 1987 tyvolinfo volinfo; 1988 1989 if (!filegetfsvolumeinfo (fs, &volinfo)) 1990 return (false); 1991 1992 if (!volinfo.flejectable) 1993 return (false); 1994 1995 return (!oserror (Eject (nil, (*fs).vRefNum))); 1996 #endif 1997 } /*ejectvol*/ 1998 #endif 1999 2000 2001 boolean isejectable (const tyfilespec *fs, boolean *flejectable) { 2002 2003 tyvolinfo volinfo; 2004 2005 if (!filegetfsvolumeinfo (fs, &volinfo)) 2006 return (false); 2007 2008 *flejectable = volinfo.flejectable; 2009 2010 return (true); 2011 } /*isejectable*/ 2012 2013 2014 boolean getfreespace (const tyfilespec *fs, long *ctfreebytes) { 2015 2016 /* 2017 6/x/91 mao 2018 */ 2019 2020 tyvolinfo volinfo; 2021 2022 if (!filegetfsvolumeinfo (fs, &volinfo)) 2023 return (false); 2024 2025 *ctfreebytes = volinfo.ctfreebytes; 2026 2027 return (true); 2028 } /*getfreespace*/ 2029 2030 2031 static void volumeinfoerror (OSErr errnum) { 2032 2033 bigstring bserr, bserrnum; 2034 2035 copystring ("\x42" "Can't get volume information because an error of type ^0 occurred.", bserr); 2036 2037 numbertostring (errnum, bserrnum); 2038 2039 parsedialogstring (bserr, bserrnum, nil, nil, nil, bserr); 2040 2041 shellerrormessage (bserr); 2042 }/*volumeinfoerror*/ 2043 2044 2045 boolean langgetextendedvolumeinfo (const tyfilespec *fs, double *totalbytes, double *freebytes) { 2046 2047 /* 2048 6.1b16 AR: Return number of free bytes and total number of bytes for the volume. 2049 This code is supposed to work flawlessly with volumes over 2 GB. 2050 2051 For the Mac version, we delegate the actual work to XGetVInfo in MoreFilesExtras.h. 2052 2053 For the Windows version, we use GetFreeDiskSpaceEx if available. Otherwise we fall 2054 back to GetFreeDiskSpace. According to MSDN info that's probably neccessary if we 2055 run on Win95 Release 1 which didn't support volume sizes over 2 GB. 2056 2057 flsupportslargevolumes is initialized in filestartup in fileverbs.c. (Win32 only) 2058 */ 2059 2060 OSErr errnum = noErr; 2061 bigstring volname; 2062 #ifdef MACVERSION 2063 UInt64 ui64totalbytes, ui64freebytes; 2064 #if !TARGET_API_MAC_CARBON 2065 short vrefnum; 2066 #endif 2067 #endif 2068 2069 *totalbytes = 0.0; 2070 2071 *freebytes = 0.0; 2072 2073 copystring (fsname(fs), volname); 2074 2075 2076 /* JES 12/09/2002 -- 9.1b2 -- Don't do this test, since it fails on builds made with CW8 2077 2078 if (!fileisvolume (fs)) { 2079 2080 bigstring bserr; 2081 2082 copystring ("\x45" "Can't get volume information because \"^0\" is not a valid volume name.", bserr); 2083 2084 parsedialogstring (bserr, volname, nil, nil, nil, bserr); 2085 2086 shellerrormessage (bserr); 2087 2088 return (false); 2089 } 2090 */ 2091 2092 #ifdef MACVERSION 2093 2094 /* 2005-01-24 creedon - reversed free and total parameters to match FSGetVInfo and XGetVInfo functions < http://groups.yahoo.com/group/frontierkernel/message/846 > */ 2095 #if TARGET_API_MAC_CARBON 2096 errnum = FSGetVInfo (fs->vRefNum, nil, &ui64freebytes, &ui64totalbytes); 2097 #else 2098 errnum = XGetVInfo (fs->vRefNum, nil, &vrefnum, &ui64freebytes, &ui64totalbytes); 2099 #endif 2100 2101 if (errnum != noErr) { 2102 volumeinfoerror (errnum); 2103 return (false); 2104 } 2105 2106 *totalbytes = (double) ui64totalbytes; 2107 *freebytes = (double) ui64freebytes; 2108 2109 #endif 2110 2111 2112 #ifdef WIN95VERSION 2113 2114 cleanendoffilename (volname); 2115 2116 pushchar ('\\', volname); 2117 2118 nullterminate (volname); 2119 2120 if (flsupportslargevolumes) { 2121 2122 ULARGE_INTEGER freeBytesAvailableToCaller, totalNumberOfBytes, totalNumberOfFreeBytes; 2123 2124 if ((*adrGetDiskFreeSpaceEx) ((unsigned short *) stringbaseaddress (volname), &freeBytesAvailableToCaller, 2125 &totalNumberOfBytes, &totalNumberOfFreeBytes)) { 2126 2127 *totalbytes = (double) (LONGLONG) totalNumberOfBytes.QuadPart; 2128 2129 *freebytes = (double) (LONGLONG) freeBytesAvailableToCaller.QuadPart; 2130 } 2131 2132 else 2133 if (GetLastError () == ERROR_CALL_NOT_IMPLEMENTED) 2134 flsupportslargevolumes = false; 2135 } 2136 2137 if (!flsupportslargevolumes) { 2138 2139 DWORD sectorsPerCluster, bytesPerSector, numberOfFreeClusters, totalNumberOfClusters; 2140 2141 if (GetDiskFreeSpace (stringbaseaddress (volname), &sectorsPerCluster, &bytesPerSector, 2142 &numberOfFreeClusters, &totalNumberOfClusters)) { 2143 2144 double bytespercluster = (double) sectorsPerCluster * (double) bytesPerSector; 2145 2146 *totalbytes = bytespercluster * (double) totalNumberOfClusters; 2147 2148 *freebytes = bytespercluster * (double) numberOfFreeClusters; 2149 } 2150 } 2151 #endif 2152 2153 return (true); 2154 }/*getextendedvolumeinfo*/ 2155 2156 2157 boolean getvolumesize (const tyfilespec *fs, long *ctbytes) { 2158 2159 tyvolinfo volinfo; 2160 2161 if (!filegetfsvolumeinfo (fs, &volinfo)) 2162 return (false); 2163 2164 *ctbytes = volinfo.cttotalbytes; 2165 2166 return (true); 2167 } /*getvolumesize*/ 2168 2169 2170 boolean getvolumeblocksize (const tyfilespec *fs, long *ctbytes) { 2171 2172 tyvolinfo volinfo; 2173 2174 if (!filegetfsvolumeinfo (fs, &volinfo)) 2175 return (false); 2176 2177 *ctbytes = volinfo.blocksize; 2178 2179 return (true); 2180 } /*getvolumeblocksize*/ 2181 2182 2183 boolean filesonvolume (const tyfilespec *fs, long *ctfiles) { 2184 2185 /* 2186 6/x/91 mao 2187 */ 2188 2189 tyvolinfo volinfo; 2190 2191 if (!filegetfsvolumeinfo (fs, &volinfo)) 2192 return (false); 2193 2194 *ctfiles = volinfo.ctfiles; 2195 2196 return (true); 2197 } /*filesonvolume*/ 2198 2199 2200 boolean foldersonvolume (const tyfilespec *fs, long *ctfolders) { 2201 2202 tyvolinfo volinfo; 2203 2204 if (!filegetfsvolumeinfo (fs, &volinfo)) 2205 return (false); 2206 2207 *ctfolders = volinfo.ctfolders; 2208 2209 return (true); 2210 } /*foldersonvolume*/ 2211 2212 2213 boolean isvolumelocked (const tyfilespec *fs, boolean *fllocked) { 2214 2215 /* 2216 6/x/91 mao 2217 */ 2218 2219 tyvolinfo volinfo; 2220 2221 if (!filegetfsvolumeinfo (fs, &volinfo)) 2222 return (false); 2223 2224 *fllocked = volinfo.fllocked; 2225 2226 return (true); 2227 } /*isvolumelocked*/ 2228 2229 2230 boolean volumecreated (const tyfilespec *fs, unsigned long *createdate) { 2231 2232 tyvolinfo volinfo; 2233 2234 if (!filegetfsvolumeinfo (fs, &volinfo)) 2235 return (false); 2236 2237 *createdate = volinfo.timecreated; 2238 2239 return (true); 2240 } /*volumecreated*/ 2241 2242 2243 boolean lockvolume (const tyfilespec *fs, boolean fllock) { 2244 #ifdef MACVERSION 2245 //Code change by Timothy Paustian Sunday, June 25, 2000 9:19:49 PM 2246 //can't lock volumes in carbon. 2247 #if TARGET_API_MAC_CARBON == 1 2248 return false; 2249 #else 2250 2251 short vnum; 2252 QHdrPtr vqtop; 2253 QElemPtr vqelem; 2254 2255 vnum = (*fs).vRefNum; 2256 2257 vqtop = GetVCBQHdr (); 2258 2259 vqelem = (*vqtop).qHead; 2260 2261 while (true) { 2262 2263 if (((VCB *)vqelem)->vcbVRefNum == vnum) { 2264 2265 if (fllock) 2266 BitSet (&(*(VCB *)vqelem).vcbAtrb, 0); 2267 else 2268 BitClr (&(*(VCB *)vqelem).vcbAtrb, 0); 2269 2270 return (true); 2271 } 2272 2273 if (vqelem == (*vqtop).qTail) { /*reached end of list -- shouldn't happen*/ 2274 2275 oserror (errorVolume); /*no such volume*/ 2276 2277 return (false); 2278 } 2279 2280 vqelem = (*vqelem).qLink; 2281 2282 } 2283 #endif//end non-carbon code 2284 #endif 2285 #ifdef WIN95VERSION 2286 return (false); 2287 #endif 2288 } /*lockvolume*/ 2289 2290 2291 #ifdef WIN95VERSION 2292 boolean findapplication (OSType creator, tyfilespec *fsapp) { 2293 2294 /* 2295 5.0.1 dmb: implemented for Win using the registry 2296 */ 2297 2298 byte bsextension [8]; 2299 bigstring bsregpath, bsoptions; 2300 2301 ostypetostring (creator, bsextension); 2302 2303 poptrailingwhitespace (bsextension); 2304 2305 insertchar ('.', bsextension); 2306 2307 pushchar (chnul, bsextension); 2308 2309 // copyctopstring ("software\\Microsoft\\Windows\\CurrentVersion", bsregpath); 2310 2311 if (!getRegKeyString ((Handle) HKEY_CLASSES_ROOT, bsextension, NULL, bsregpath)) 2312 return (false); 2313 2314 pushstring ("\x13\\shell\\open\\command", bsregpath); 2315 2316 if (!getRegKeyString ((Handle) HKEY_CLASSES_ROOT, bsregpath, NULL, bsregpath)) 2317 return (false); 2318 2319 if (getstringcharacter (bsregpath, 0) == '"') { 2320 2321 popleadingchars (bsregpath, '"'); 2322 2323 firstword (bsregpath, '"', bsregpath); 2324 } 2325 else { 2326 2327 lastword (bsregpath, ' ', bsoptions); 2328 2329 if (stringlength (bsoptions) < stringlength (bsregpath)) 2330 deletestring (bsregpath, stringlength (bsregpath) - stringlength (bsoptions) + 1, stringlength (bsoptions)); 2331 } 2332 2333 return (pathtofilespec (bsregpath, fsapp)); 2334 } /*findapplication*/ 2335 #endif 2336 2337 2338 #ifdef MACVERSION 2339 boolean unmountvolume (const tyfilespec *fs) { 2340 2341 /* 2342 12/5/91 dmb 2343 */ 2344 2345 return (!oserror (UnmountVol (nil, (*fs).vRefNum))); 2346 } /*unmountvolume*/ 2347 2348 2349 boolean drivenumtovolname (short drivenum, bigstring bsvol) { 2350 2351 HParamBlockRec pb; 2352 2353 clearbytes (&pb, sizeof (pb)); 2354 2355 pb.volumeParam.ioNamePtr = bsvol; 2356 2357 pb.volumeParam.ioVRefNum = drivenum; 2358 //Code change by Timothy Paustian Sunday, June 25, 2000 9:21:31 PM 2359 //Updated call for carbon 2360 return (PBHGetVInfoSync (&pb) == noErr); 2361 2362 /* 2363 return (GetVInfo (drivenum, bsvol, &vnum, &freebytes) == noErr); 2364 */ 2365 } /*drivenumtovolname*/ 2366 2367 2368 static boolean hasdesktopmanager (short vnum) { 2369 2370 GetVolParmsInfoBuffer volparms; 2371 HParamBlockRec pb; 2372 2373 pb.volumeParam.ioVRefNum = vnum; 2374 2375 pb.volumeParam.ioNamePtr = nil; 2376 2377 pb.ioParam.ioBuffer = (Ptr) &volparms; 2378 2379 pb.ioParam.ioReqCount = sizeof (volparms); 2380 2381 if (PBHGetVolParmsSync (&pb) != noErr) 2382 return (false); 2383 2384 return ((volparms.vMAttrib & (1 << bHasDesktopMgr)) != 0); 2385 } /*hasdesktopmanager*/ 2386 2387 2388 boolean findapplication (OSType creator, tyfilespec *fsapp) { 2389 2390 /* 2391 12/5/91 dmb. 2392 2393 9/7/92 dmb: make two passes, skipping volumes mounted with a foreign 2394 file system the first time through. note: if this turns out not to be 2395 the best criteria, we could check for shared volumes instead by testing 2396 vMLocalHand in hasdesktopmanager. 2397 2398 also: since we don't maintain the desktop DB when we delete files, we 2399 need to verify that the file we locate still exists. added fileexists 2400 call before returning true. 2401 2402 2.1b11 dmb: loop through all files in each db if necessary to find one 2403 that's actually an application 2404 */ 2405 2406 bigstring bsapp; 2407 DTPBRec dt; 2408 HParamBlockRec pb; 2409 OSType type; 2410 register OSErr errcode; 2411 boolean fltryremote = false; 2412 boolean flremote; 2413 2414 clearbytes (&pb, sizeof (pb)); 2415 2416 while (true) { 2417 2418 ++pb.volumeParam.ioVolIndex; 2419 2420 errcode = PBHGetVInfoSync (&pb); 2421 2422 if (errcode == nsvErr) { /*index out of range*/ 2423 2424 if (fltryremote) /*we've tried everything*/ 2425 return (false); 2426 2427 pb.volumeParam.ioVolIndex = 0; /*reset*/ 2428 2429 fltryremote = true; 2430 2431 continue; 2432 } 2433 2434 if (errcode != noErr) 2435 return (false); 2436 2437 flremote = pb.volumeParam.ioVFSID != 0; /*actually means foreign file system*/ 2438 2439 if (fltryremote != flremote) 2440 continue; 2441 2442 if (!hasdesktopmanager (pb.volumeParam.ioVRefNum)) 2443 continue; 2444 2445 dt.ioNamePtr = NULL; 2446 dt.ioVRefNum = pb.volumeParam.ioVRefNum; 2447 2448 if (PBDTGetPath (&dt) != noErr) 2449 return (false); 2450 2451 dt.ioNamePtr = (StringPtr) &bsapp; 2452 dt.ioIndex = 0; 2453 dt.ioFileCreator = creator; 2454 2455 for (dt.ioIndex = 0; ; ++dt.ioIndex) { 2456 2457 if (PBDTGetAPPLSync (&dt) != noErr) /*go to next volume*/ 2458 break; 2459 2460 if (FSMakeFSSpec (pb.volumeParam.ioVRefNum, dt.ioAPPLParID, bsapp, fsapp) != noErr) 2461 continue; 2462 2463 if (!getfiletype (fsapp, &type)) 2464 return (false); 2465 2466 if (type == 'APPL') /*desktop db can contain references to non-apps*/ 2467 return (true); 2468 } 2469 2470 /* 2471 if (PBDTGetAPPLSync (&dt) == noErr) { 2472 2473 if (FSMakeFSSpec (pb.volumeParam.ioVRefNum, dt.ioAPPLParID, bsapp, fsapp) == noErr) 2474 return (true); 2475 } 2476 */ 2477 } 2478 } /*findapplication*/ 2479 2480 2481 #if 0 2482 2483 static boolean getdesktopdatabasepath (short vnum, DTPBRec *dt) { 2484 2485 if (!hasdesktopmanager (vnum)) 2486 return (false); 2487 2488 dt.ioVRefNum = vnum; 2489 2490 return (PBDTGetPath (&dt) == noErr); 2491 } /*getdesktopdatabasepath*/ 2492 2493 #endif 2494 2495 2496 boolean getfilecomment (const tyfilespec *fs, bigstring bscomment) { 2497 2498 /* 2499 12/5/91 dmb 2500 2501 2.1b1 dmb: set reqCount; w/out it, works locally but not remotely 2502 */ 2503 2504 DTPBRec dt; 2505 2506 clearbytes (&dt, sizeof (dt)); 2507 2508 setemptystring (bscomment); /*default return*/ 2509 2510 if (!surefile (fs)) 2511 return (false); 2512 2513 if (!hasdesktopmanager ((*fs).vRefNum)) 2514 return (false); 2515 2516 dt.ioVRefNum = (*fs).vRefNum; 2517 2518 if (PBDTGetPath (&dt) != noErr) 2519 return (false); 2520 2521 dt.ioNamePtr = (StringPtr) (*fs).name; 2522 2523 dt.ioDirID = (*fs).parID; 2524 2525 dt.ioDTBuffer = (Ptr) bscomment + 1; 2526 2527 dt.ioDTReqCount = lenbigstring; 2528 2529 if (PBDTGetCommentSync (&dt) != noErr) 2530 return (false); 2531 2532 setstringlength (bscomment, dt.ioDTActCount); 2533 2534 return (true); 2535 } /*getfilecomment*/ 2536 2537 2538 boolean setfilecomment (const tyfilespec *fs, bigstring bscomment) { 2539 2540 /* 2541 12/5/91 dmb 2542 */ 2543 2544 DTPBRec dt; 2545 2546 clearbytes (&dt, sizeof (dt)); 2547 2548 if (!surefile (fs)) 2549 return (false); 2550 2551 if (!hasdesktopmanager ((*fs).vRefNum)) 2552 return (false); 2553 2554 dt.ioVRefNum = (*fs).vRefNum; 2555 2556 if (PBDTGetPath (&dt) != noErr) 2557 return (false); 2558 2559 dt.ioNamePtr = (StringPtr) (*fs).name; 2560 2561 dt.ioDirID = (*fs).parID; 2562 2563 dt.ioDTBuffer = (Ptr) bscomment + 1; 2564 2565 dt.ioDTReqCount = stringlength (bscomment); 2566 2567 if (PBDTSetCommentSync (&dt) != noErr) 2568 return (false); 2569 2570 PBDTFlushSync (&dt); 2571 2572 return (true); 2573 } /*setfilecomment*/ 2574 2575 2576 static boolean index2label (short ixlabel, bigstring bslabel) { 2577 2578 /* 2579 new: pascal OSErr GetLabel(short labelNumber, RGBColor *labelColor, Str255 labelString) 2580 = {0x303c, 0x050B, 0xABC9}; 2581 */ 2582 2583 Handle hlabel; 2584 2585 setemptystring (bslabel); 2586 2587 if ((ixlabel < 0) || (ixlabel > 7)) 2588 return (false); 2589 2590 hlabel = GetResource ('lstr', -16392 + ixlabel); 2591 2592 if (hlabel == nil) 2593 return (false); 2594 2595 copyheapstring ((hdlstring) hlabel, bslabel); 2596 2597 return (true); 2598 } /*index2label*/ 2599 2600 2601 static boolean label2index (bigstring bslabel, short *ixlabel) { 2602 2603 register short ix; 2604 Handle hlabel; 2605 2606 for (ix = 0; ix < 8; ++ix) { 2607 2608 hlabel = GetResource ('lstr', -16392 + ix); 2609 2610 if (hlabel == nil) 2611 continue; 2612 2613 if (RelString ((ptrstring) *hlabel, bslabel, false, false) == 0) { 2614 2615 *ixlabel = ix; 2616 2617 return (true); 2618 } 2619 } 2620 2621 return (false); 2622 } /*label2index*/ 2623 2624 2625 boolean getfilelabel (const tyfilespec *fs, bigstring bslabel) { 2626 2627 tyfileinfo info; 2628 2629 if (!filegetinfo (fs, &info)) 2630 return (false); 2631 2632 return (index2label (info.ixlabel, bslabel)); 2633 } /*getfilelabel*/ 2634 2635 2636 boolean setfilelabel (const tyfilespec *fs, bigstring bslabel) { 2637 2638 CInfoPBRec pb; 2639 register short flags; 2640 short ixlabel; 2641 2642 if (!label2index (bslabel, &ixlabel)) 2643 return (false); 2644 2645 if (!getmacfileinfo (fs, &pb)) 2646 return (false); 2647 2648 flags = pb.hFileInfo.ioFlFndrInfo.fdFlags; 2649 2650 flags &= 0xFFF1; /*clear out old index*/ 2651 2652 flags |= ixlabel << 1; /*slam in new index*/ 2653 2654 pb.hFileInfo.ioFlFndrInfo.fdFlags = flags; 2655 2656 return (setmacfileinfo (fs, &pb)); 2657 } /*setfilelabel*/ 2658 2659 2660 boolean mountvolume (bigstring volumepath, bigstring username, bigstring password) { 2661 2662 /* 2663 2/20/92 dmb: initial code. this really should be "mount server volume"; 2664 mounting a volume is something else, really. 2665 2666 4/16/92 dmb: check for already-mounted error code, and treat it as no error. 2667 2668 2.1b12 dmb: if volumepath is improperly formed, generate informative message 2669 instead of failing silently 2670 */ 2671 2672 AFPVolMountInfo info; 2673 bigstring bsitem; 2674 short ixdata; 2675 ParamBlockRec pb; 2676 OSErr errcode; 2677 2678 clearbytes (&info, sizeof (info)); 2679 2680 ixdata = (char *) &info.AFPData - (char *) &info; 2681 2682 info.media = AppleShareMediaType; 2683 2684 if (isemptystring (username)) 2685 info.uamType = kNoUserAuthentication; 2686 else 2687 info.uamType = kPassword; 2688 2689 2690 firstword (volumepath, ':', bsitem); /*get the zone name*/ 2691 2692 info.zoneNameOffset = ixdata; 2693 2694 copystring (bsitem, (ptrstring) &info + ixdata); 2695 2696 ixdata += stringsize (bsitem); 2697 2698 2699 nthword (volumepath, 2, ':', bsitem); /*get the server name*/ 2700 2701 info.serverNameOffset = ixdata; 2702 2703 copystring (bsitem, (ptrstring) &info + ixdata); 2704 2705 ixdata += stringsize (bsitem); 2706 2707 2708 nthword (volumepath, 3, ':', bsitem); /*get the volume name*/ 2709 2710 info.volNameOffset = ixdata; 2711 2712 copystring (bsitem, (ptrstring) &info + ixdata); 2713 2714 ixdata += stringsize (bsitem); 2715 2716 2717 info.userNameOffset = ixdata; /*set the user name*/ 2718 2719 copystring (username, (ptrstring) &info + ixdata); 2720 2721 ixdata += stringsize (username); 2722 2723 2724 info.userPasswordOffset = ixdata; /*set the password*/ 2725 2726 copystring (password, (ptrstring) &info + ixdata); 2727 2728 ixdata += stringsize (password); 2729 2730 2731 info.length = ixdata; 2732 2733 2734 clearbytes (&pb, sizeof (pb)); 2735 2736 pb.ioParam.ioBuffer = (Ptr) &info; 2737 2738 errcode = PBVolumeMount (&pb); 2739 2740 if (errcode == -5062) /*volume is already mounted*/ 2741 return (true); 2742 2743 return (!oserror (errcode)); 2744 } /*mountvolume*/ 2745 #endif 2746 2747 2748 #ifdef NEWFILESPECTYPE 2749 boolean fileparsevolname (bigstring bspath, long *vnum, bigstring bsvol) 2750 #else 2751 boolean fileparsevolname (bigstring bspath, short *vnum, bigstring bsvol) 2752 #endif 2753 { 2754 /* 2755 convert a full path, which might contain a volume name at the beginning 2756 to a path with no volume name, and it's associated volume number in vnum. 2757 2758 example: "RoverŠ:MORE Work" will return with bspath = "MORE Work" and 2759 vnum = -2 (the Macintosh vrefnum for the second mounted drive). 2760 2761 this combination of information plugs nicely into a lot of the file 2762 manager routines. 2763 2764 2.1b8 dmb: handle drive numbers 2765 2766 2.1b11 dmb: return the vol name in bsvol if non-nil, along with the vnum 2767 2768 5.0.2 rab: initialize ix to zero 2769 */ 2770 2771 #ifdef MACVERSION 2772 2773 short ix = 1; 2774 bigstring bsvolname; 2775 HParamBlockRec pb; 2776 short drivenum; 2777 bigstring bs; 2778 OSErr err; 2779 2780 copystring (bspath, bs); /*work on a copy*/ 2781 2782 if (isemptystring (bs)) 2783 return (false); 2784 2785 if (!scanstring (chpathseparator, bs, &ix)) { /*no colon, the whole thing is a volname*/ 2786 2787 copystring (bs, bsvolname); 2788 2789 pushchar (chpathseparator, bsvolname); 2790 2791 setemptystring (bs); 2792 } 2793 else { 2794 midstring (bs, 1, ix, bsvolname); /*pick off the vol name and the colon*/ 2795 2796 deletestring (bs, 1, ix); 2797 } 2798 2799 clearbytes (&pb, sizeof (pb)); 2800 2801 pb.volumeParam.ioNamePtr = bsvolname; 2802 2803 pb.volumeParam.ioVolIndex = -1; /*force him to use the name pointer only*/ 2804 //Code change by Timothy Paustian Sunday, June 25, 2000 9:21:59 PM 2805 //Updated call for carbon 2806 err = PBHGetVInfoSync (&pb); 2807 2808 if (err != noErr) { 2809 2810 setstringlength (bsvolname, stringlength (bsvolname) - 1); /*pop last char -- the colon*/ 2811 2812 if (isallnumeric (bsvolname) && stringtoshort (bsvolname, &drivenum)) { /*it's a number*/ 2813 2814 /* 2815 pb.volumeParam.ioNamePtr = nil; 2816 */ 2817 2818 pb.volumeParam.ioVRefNum = drivenum; 2819 //Code change by Timothy Paustian Sunday, June 25, 2000 9:24:35 PM 2820 //updated for carbon 2821 err = PBHGetVInfoSync (&pb); 2822 } 2823 2824 if (err != noErr) 2825 return (false); 2826 } 2827 2828 *vnum = pb.volumeParam.ioVRefNum; 2829 2830 if (bsvol != nil) 2831 copystring (bsvolname, bsvol); 2832 #endif 2833 2834 #ifdef WIN95VERSION 2835 bigstring bsvolname, bs; 2836 short ix = 0; 2837 2838 *vnum = 0; 2839 copystring (bspath, bs); /*work on a copy*/ 2840 2841 if (isemptystring (bs)) 2842 return (false); 2843 2844 if (!scanstring (':', bs, &ix)) { /*no colon, No volume?*/ 2845 return (false); 2846 } 2847 else { 2848 midstring (bs, 1, ix, bsvolname); /*pick off the vol name and the colon*/ 2849 2850 deletestring (bs, 1, ix); 2851 } 2852 2853 if (bsvol != nil) 2854 { 2855 copystring (bsvolname, bsvol); 2856 2857 nullterminate (bsvol); 2858 } 2859 2860 #endif 2861 return (true); 2862 } /*fileparsevolname*/ 2863 2864 2865 2866 #ifdef MACVERSION 2867 2868 boolean fileresolvealias (tyfilespec *fs) { 2869 2870 Boolean flfolder, flalias; 2871 OSErr err; 2872 2873 setoserrorparam ((ptrstring) (*fs).name); 2874 2875 err = ResolveAliasFile (fs, true, &flfolder, &flalias); 2876 2877 return (!oserror (err)); 2878 } /*fileresolvealias*/ 2879 #endif 2880 2881 2882 boolean filefrompath (bigstring path, bigstring fname) { 2883 2884 /* 2885 return all the characters to the right of the colon in the path. 2886 2887 example: "Work Disk #1:MORE Work:Status Center" returns "Status Center". 2888 */ 2889 2890 #ifdef MACVERSION 2891 return (lastword (path, chpathseparator, fname)); 2892 #endif 2893 2894 #ifdef WIN95VERSION 2895 char fn[300]; 2896 char * fileptr; 2897 tyfilespec fs; 2898 2899 copystring (path, fsname (&fs)); 2900 2901 if (stringlength (path) >= 255) { /* RAB 4/27/98 fix for to long a filename conversion attempt*/ 2902 setemptystring (fname); 2903 return (true); 2904 } 2905 2906 if (isemptystring (path) || fileisvolume (&fs)) { 2907 2908 copystring (path, fname); 2909 2910 return (true); 2911 } 2912 2913 nullterminate (path); 2914 2915 GetFullPathName (stringbaseaddress(path), 298, fn, &fileptr); 2916 2917 /*the comparison of fileptr within the legal range of fn is a kludge 2918 but if fixes GetFullPathName which goes wild on some strings and 2919 there is no other way of determining that it has gone wild. 2920 RAB 4/27/98 */ 2921 2922 if ((fileptr == NULL) || (fileptr < fn) || (fileptr > (fn + 298))) 2923 setemptystring (fname); 2924 else 2925 copyctopstring (fileptr, fname); 2926 2927 // strcpy (stringbaseaddress(fname), fileptr); 2928 // setstringlength (fname, strlen (fileptr)); 2929 2930 return (true); 2931 #endif 2932 } /*filefrompath*/ 2933 2934 2935 boolean folderfrompath (bigstring path, bigstring folder) { 2936 2937 /* 2938 return all the characters to the left of the colon, and the colon. 2939 2940 example: "Work Disk #1:MORE Work:Status Center" returns "Work Disk #1:MORE Work:". 2941 2942 5.0.2 dmb: call filefrompath instead of lastword to maintain symmetry on Win 2943 */ 2944 2945 bigstring bs; 2946 2947 filefrompath (path, bs); /*kind of inefficient, but ensures symmetry*/ 2948 2949 copystring (path, folder); 2950 2951 setstringlength (folder, stringlength (folder) - stringlength (bs)); 2952 2953 return (true); 2954 } /*folderfrompath*/ 2955 2956 2957 #ifdef MACVERSION 2958 boolean getfileparentfolder (const tyfilespec *fs, tyfilespec *fsparent) { 2959 2960 long dirid = (*fs).parID; 2961 2962 if (isemptystring ((*fs).name) || (dirid == fsRtParID)) { /*null or disk spec*/ 2963 2964 clearbytes (fsparent, sizeof (tyfilespec)); 2965 2966 return (true); 2967 } 2968 2969 return (!oserror (FSMakeFSSpec ((*fs).vRefNum, dirid, nil, fsparent))); 2970 } /*getfileparentfolder*/ 2971 2972 2973 #if 0 2974 2975 boolean getdefaultpath (bigstring bs) { 2976 2977 ParamBlockRec pb; 2978 OSErr errcode; 2979 2980 setstringlength (bs, 0); 2981 2982 clearbytes (&pb, sizeof (pb)); 2983 2984 errcode = PBGetVolSync (&pb); 2985 2986 if (oserror (errcode)) 2987 return (false); 2988 2989 return (filegetpath (pb.fileParam.ioVRefNum, bs)); 2990 } /*getdefaultpath*/ 2991 2992 #endif 2993 2994 2995 #endif 2996 2997 boolean movefile (const tyfilespec *fs, const tyfilespec *fsto) { 2998 #ifdef MACVERSION 2999 /* 3000 moves a file or folder speied in fs to the fcifolder specified by fsto. 3001 make sure that the new path is really a folder. 3002 3003 8/2/91 dmb: corrected error message params 3004 3005 3.0.2 dmb: setoserrorparam to source file before catmove 3006 */ 3007 3008 CInfoPBRec pb; 3009 3010 setfserrorparam (fsto); /*in case error message takes a filename parameter*/ 3011 3012 if (!getmacfileinfo (fsto, &pb)) 3013 return (false); 3014 3015 if (!pb.dirInfo.ioFlAttrib & ioDirMask) { /*if newpath isn't a folder, get out*/ 3016 3017 oserror (errorParam); /*not the best error message, but...*/ 3018 3019 return (false); 3020 } 3021 3022 setfserrorparam (fs); /*3.0.2*/ 3023 3024 return (!oserror (FSpCatMove (fs, fsto))); 3025 #endif 3026 3027 #ifdef WIN95VERSION 3028 char fn1[300]; 3029 char fn2[300]; 3030 boolean fl; 3031 bigstring filename; 3032 3033 copystring (fsname (fs), fn1); 3034 copystring (fsname (fsto), fn2); 3035 3036 if (endswithpathsep (fn1)) 3037 setstringlength (fn1, stringlength (fn1) - 1); 3038 3039 nullterminate (fn1); 3040 nullterminate (fn2); 3041 3042 if (!fileisfolder (fsto, &fl)) 3043 return (false); 3044 3045 if (fl) { 3046 filefrompath (fn1, filename); 3047 3048 cleanendoffilename(fn2); 3049 3050 appendcstring (fn2, "\\"); 3051 3052 pushstring (filename, fn2); 3053 3054 nullterminate (fn2); 3055 } 3056 3057 if (MoveFile (stringbaseaddress (fn1), stringbaseaddress(fn2))) 3058 return (true); 3059 3060 winfileerror (fs); 3061 3062 return (false); 3063 #endif 3064 } /*movefile*/ 3065 3066 3067 void filenotfounderror (bigstring bs) { 3068 3069 /* 3070 generate a "file not found" or a "folder not found" error 3071 */ 3072 3073 OSErr errcode; 3074 3075 setoserrorparam (bs); 3076 #ifdef MACVERSION 3077 if (lastchar (bs) == chpathseparator) 3078 errcode = errorDirNotFound; 3079 else 3080 errcode = errorFileNotFound; 3081 #endif 3082 #ifdef WIN95VERSION 3083 errcode = errorFileNotFound; 3084 #endif 3085 oserror (errcode); 3086 } /*filenotfounderror*/ 3087 3088 3089 boolean surefile (const tyfilespec *fs) { 3090 3091 boolean flfolder; 3092 3093 if (fileexists (fs, &flfolder)) 3094 return (true); 3095 3096 filenotfounderror ((ptrstring) fsname (fs)); 3097 3098 return (false); 3099 } /*surefile*/ 3100 3101 3102 boolean renamefile (const tyfilespec *fs, bigstring bsnew) { 3103 3104 #ifdef MACVERSION 3105 /* 3106 we expect a full path specifying the file to be renamed. bsnew must not 3107 hold a path -- it's the new name of the file. the Mac OS wants a full path 3108 for the new name, it makes no sense to us. but we are obedient! 3109 3110 6/x/91 mao: PBHRename used, will now rename folders 3111 3112 7/30/91 dmb: reworked code to work properly with volumes and folder paths 3113 ending in colons 3114 3115 9/4/91 dmb: only look at filename part of bsnew 3116 3117 12/1/92 dmb: if bsnew is a valid path (same folder), use it as is. this 3118 fixes bug when it's a path to a folder. 3119 */ 3120 3121 if (!surefile (fs)) /*file doesn't exist -- catch error*/ 3122 return (false); 3123 3124 filefrompath (bsnew, bsnew); 3125 3126 setoserrorparam (bsnew); /*only likely errors from here on relate to new name*/ 3127 3128 if (oserror (FSpRename (fs, bsnew))) 3129 return (false); 3130 3131 touchparentfolder (fs); 3132 3133 return (true); 3134 #endif 3135 3136 #ifdef WIN95VERSION 3137 char fn[300]; 3138 bigstring bsfolder; 3139 3140 if (!surefile (fs)) /*file doesn't exist -- catch error*/ 3141 return (false); 3142 3143 filefrompath (bsnew, bsnew); 3144 3145 copystring (fsname (fs), fn); 3146 3147 nullterminate (fn); 3148 3149 folderfrompath (fn, bsfolder); 3150 3151 pushstring (bsnew, bsfolder); 3152 3153 nullterminate (bsfolder); 3154 3155 if (MoveFile (stringbaseaddress (fn), stringbaseaddress(bsfolder))) 3156 return (true); 3157 3158 winfileerror (fs); 3159 3160 return (false); 3161 #endif 3162 } /*renamefile*/ 3163 3164 3165 boolean lockfile (const tyfilespec *fs) { 3166 3167 #ifdef MACVERSION 3168 setfserrorparam (fs); /*in case error message takes a filename parameter*/ 3169 3170 return (!oserror (FSpSetFLock (fs))); 3171 #endif 3172 3173 #ifdef WIN95VERSION 3174 DWORD attr; 3175 3176 attr = GetFileAttributes (stringbaseaddress (fsname (fs))); 3177 3178 if (attr == 0xFFFFFFFF) 3179 goto error; 3180 3181 attr = attr | FILE_ATTRIBUTE_READONLY; 3182 3183 if (SetFileAttributes (stringbaseaddress (fsname (fs)), attr)) 3184 return (true); 3185 3186 error: 3187 3188 winfileerror (fs); 3189 3190 return (false); 3191 #endif 3192 } /*lockfile*/ 3193 3194 3195 boolean unlockfile (const tyfilespec *fs) { 3196 #ifdef MACVERSION 3197 setfserrorparam (fs); 3198 3199 return (!oserror (FSpRstFLock (fs))); 3200 #endif 3201 3202 #ifdef WIN95VERSION 3203 DWORD attr; 3204 3205 attr = GetFileAttributes (stringbaseaddress (fsname (fs))); 3206 3207 if (attr == 0xFFFFFFFF) 3208 goto error; 3209 3210 attr = attr & ~FILE_ATTRIBUTE_READONLY; 3211 3212 if (SetFileAttributes (stringbaseaddress(fsname (fs)), attr)) 3213 return (true); 3214 3215 error: 3216 3217 winfileerror (fs); 3218 3219 return (false); 3220 #endif 3221 } /*unlockfile*/ 3222 3223 3224 boolean newfolder (const tyfilespec *fs) { 3225 #ifdef MACVERSION 3226 /* 3227 2.1b2 dmb: use filespecs. 3228 */ 3229 3230 long dirid; 3231 3232 setfserrorparam (fs); 3233 3234 return (!oserror (FSpDirCreate (fs, smSystemScript, &dirid))); 3235 #endif 3236 3237 #ifdef WIN95VERSION 3238 if (CreateDirectory (stringbaseaddress (fsname (fs)), NULL)) 3239 return (true); 3240 3241 winfileerror (fs); 3242 3243 return (false); 3244 #endif 3245 } /*newfolder*/ 3246 3247 3248 boolean newfile (const tyfilespec *fs, OSType creator, OSType filetype) { 3249 #ifdef MACVERSION 3250 setfserrorparam (fs); 3251 3252 return (!oserror (FSpCreate (fs, creator, filetype, smSystemScript))); 3253 #endif 3254 3255 #ifdef WIN95VERSION 3256 HANDLE f; 3257 char fn[300]; 3258 3259 copystring (fsname (fs), fn); 3260 3261 nullterminate (fn); 3262 3263 f = CreateFile (stringbaseaddress(fn), GENERIC_READ | GENERIC_WRITE, 3264 FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); 3265 3266 if (f == INVALID_HANDLE_VALUE) { 3267 3268 winfileerror (fs); 3269 3270 return (false); 3271 } 3272 3273 verify (CloseHandle (f)); 3274 return (true); 3275 #endif 3276 } /*newfile*/ 3277 3278 3279 #ifdef MACVERSION 3280 3281 boolean getfullfilepath (bigstring bspath) { 3282 3283 FSSpec fs; 3284 3285 setoserrorparam (bspath); /*in case error message takes a filename parameter*/ 3286 3287 if (oserror (FSMakeFSSpec (0, 0, bspath, &fs))) 3288 return (false); 3289 3290 return (filespectopath (&fs, bspath)); 3291 } /*getfullfilepath*/ 3292 3293 3294 boolean filemakespec (short vnum, long dirid, bigstring fname, ptrfilespec pfs) { 3295 3296 OSErr ec; 3297 3298 ec = FSMakeFSSpec (vnum, dirid, fname, pfs); 3299 3300 return ((ec == noErr) || (ec == fnfErr)); 3301 } /*filemakespec*/ 3302 3303 #endif /*MACVERSION*/ 3304 3305 3306 boolean initfile (void) { 3307 3308 /* 3309 call this before you do any setvol's. 3310 3311 get me the volume id of the application that's running. 3312 3313 useful for opening data files that are located in the same folder as 3314 the application itself. 3315 3316 11/8/90 dmb: new implementation 3317 */ 3318 3319 #ifdef MACVERSION 3320 3321 initfiledialog (); 3322 3323 #endif 3324 3325 #ifdef flsystem6 3326 3327 GetVol (nil, &applicationvolnum); 3328 3329 #endif 3330 3331 #ifdef MACVERSION 3332 #ifdef flcomponent 3333 3334 #if !TARGET_API_MAC_CARBON 3335 RememberA5 (); 3336 #endif /*for hook*/ 3337 3338 #endif 3339 3340 applicationresnum = CurResFile (); 3341 #endif 3342 return (true); 3343 } /*initfile*/ 3344 3345 3346 3347

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.