fileops.c

Go to the documentation of this file.
00001 
00002 /*  $Id: fileops.c 1329 2006-04-24 21:40:07Z creecode $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #ifdef WIN95VERSION
00032 #include "winregistry.h"
00033 #endif
00034 
00035 #include "filealias.h"
00036 #include "cursor.h"
00037 #include "dialogs.h"
00038 #include "error.h"
00039 #include "memory.h"
00040 #include "ops.h"
00041 #include "quickdraw.h"
00042 #include "resources.h"
00043 #include "strings.h"
00044 #include "timedate.h"
00045 #include "frontierwindows.h"
00046 #include "file.h"
00047 #include "shell.h"
00048 #include "shell.rsrc.h"
00049 #include "langinternal.h" /*for langbackgroundtask*/
00050 
00051 #ifdef MACVERSION
00052 
00053     #if TARGET_API_MAC_CARBON
00054         #include "MoreFilesX.h"
00055     #else
00056         pascal OSErr XGetVInfo(short volReference, StringPtr volName, short *vRefNum, UInt64 *freeBytes,
00057             UInt64 *totalBytes);
00058     #endif
00059     
00060     #ifdef flcomponent
00061         #include "SetUpA5.h"
00062     #endif
00063 
00064     #define hasOpenDeny(volParms)       (((volParms).vMAttrib & (1L << bHasOpenDeny)) != 0)
00065     
00066     #ifndef __MOREFILESEXTRAS__
00067         enum { /*permissions used by MoreFile 1.1 code*/
00068             dmNone      = 0x0000,
00069             dmNoneDenyRd    = 0x0010,
00070             dmNoneDenyWr    = 0x0020,
00071             dmNoneDenyRdWr  = 0x0030,
00072             dmRd            = 0x0001,   /* Single writer, multiple readers; the readers */
00073             dmRdDenyRd      = 0x0011,
00074             dmRdDenyWr      = 0x0021,   /* Browsing - equivalent to fsRdPerm */
00075             dmRdDenyRdWr    = 0x0031,
00076             dmWr            = 0x0002,
00077             dmWrDenyRd      = 0x0012,
00078             dmWrDenyWr  = 0x0022,
00079             dmWrDenyRdWr    = 0x0032,
00080             dmRdWr      = 0x0003,   /* Shared access - equivalent to fsRdWrShPerm */
00081             dmRdWrDenyRd    = 0x0013,
00082             dmRdWrDenyWr    = 0x0023,   /* Single writer, multiple readers; the writer */
00083             dmRdWrDenyRdWr  = 0x0033    /* Exclusive access - equivalent to fsRdWrPerm */
00084             };
00085     #endif
00086     
00087 #endif
00088 
00089 
00090 #ifdef flsystem6
00091 
00092 static short applicationvolnum = 0;
00093 
00094 #endif
00095 
00096 static short applicationresnum = -1;
00097 
00098 #ifdef MACVERSION
00099 static OSType specialfolders [] = {
00100     
00101     0, /*make 1-based*/
00102     
00103     #if TARGET_API_MAC_CARBON //macs is not working right now. This is not a good substitute, nice hack eh?
00104     'pref',
00105     #else
00106     'macs', /*system*/
00107     #endif
00108     'desk', /*desktop*/
00109     
00110     'trsh', /*trash*/
00111     
00112     'empt', /*shared trash*/
00113     
00114     'prnt', /*printmonitor documents*/
00115     
00116     'strt', /*startup items*/
00117     
00118     'amnu', /*apple menu items*/
00119     
00120     'ctrl', /*control panels*/
00121     
00122     'extn', /*extensions*/
00123     
00124     'pref', /*preferences*/
00125     
00126     'temp',  /*temporary items*/
00127     
00128     'font'  /*Fonts*/
00129     };
00130 #endif
00131 
00132 
00133 typedef struct tyfileinfo tyvolinfo;
00134 
00135 
00136 void setfserrorparam (const tyfilespec *fs) {
00137     
00138     /*
00139     bigstring bs;
00140     
00141     if (!filespectopath (fs, bs))
00142         copystring ((ptrstring) (*fs).name, bs);
00143     
00144     setoserrorparam (bs);
00145     */
00146     
00147     setoserrorparam ((ptrstring) fsname (fs));
00148     } /*setfserrorparam*/
00149 
00150 
00151 boolean endswithpathsep (bigstring bs) {
00152     /* return true if the ending character is a path sepatator character*/
00153     char ch;
00154 
00155     ch = getstringcharacter(bs, stringlength(bs)-1);
00156 
00157 #ifdef MACVERSION
00158     if (ch == ':')
00159         return (true);
00160 #endif
00161 
00162 #ifdef WIN95VERSION
00163     if (ch == '\\')
00164         return (true);
00165 
00166     if (ch == '/')
00167         return (true);
00168 #endif
00169 
00170     return (false);
00171     } /*endswithpathsep*/
00172 
00173 
00174 boolean cleanendoffilename (bigstring bs) {
00175     if (endswithpathsep(bs)) {
00176         setstringlength (bs, stringlength(bs) - 1);
00177         return (true);
00178         }
00179 
00180     return (false);
00181     } /*cleanendoffilename*/
00182 
00183 
00184 boolean getmachinename (bigstring bsname) {
00185 
00186     boolean fl;
00187     
00188     #ifdef WIN95VERSION
00189         DWORD len;
00190 
00191         len = sizeof(bigstring) - 2;
00192 
00193         fl = GetComputerName (stringbaseaddress(bsname), &len);
00194 
00195         if (fl)
00196             setstringlength (bsname, len);
00197         else
00198             setemptystring (bsname);
00199     #endif
00200     
00201     #ifdef MACVERSION
00202         StringHandle hstring = GetString (-16413);
00203         
00204         fl = hstring != nil;
00205         
00206         if (fl)
00207             texthandletostring ((Handle) hstring, bsname);
00208         else
00209             setemptystring (bsname);
00210     #endif
00211 
00212     return (fl);
00213     } /*getmachinename*/
00214 
00215 
00216 #ifdef MACVERSION
00217 boolean foldertest (CInfoPBRec *pb) {
00218     
00219     /*
00220     return true if pb holds info describing a folder.
00221     
00222     4/26/96 dmb: use mask, not BitTst (a toolbox call)
00223     */
00224     
00225     /*
00226     return (BitTst (&pb->dirInfo.ioFlAttrib, 3));
00227     */
00228     return ((pb->dirInfo.ioFlAttrib & ioDirMask) != 0);
00229     } /*foldertest*/
00230 
00231 
00232 static void filebeachball (void) {
00233     
00234     /*
00235     roll the beachball cursor if there is one.
00236     */
00237     
00238     if (beachballcursor ())
00239         rollbeachball ();
00240     } /*filebeachball*/
00241     
00242 
00243 boolean getmacfileinfo (const tyfilespec *fs, CInfoPBRec *pb) {
00244     
00245     /* 
00246     2.1b2 dmb: new fsspec-based version
00247     */
00248     
00249     setoserrorparam ((ptrstring) (*fs).name); /*in case error message takes a filename parameter*/
00250     
00251     clearbytes (pb, sizeof (*pb));
00252     
00253     (*pb).hFileInfo.ioNamePtr = (StringPtr) (*fs).name;
00254     
00255     (*pb).hFileInfo.ioVRefNum = (*fs).vRefNum;
00256     
00257     (*pb).hFileInfo.ioDirID = (*fs).parID;
00258     
00259     return (!oserror (PBGetCatInfoSync (pb)));
00260     } /*getmacfileinfo*/
00261 
00262 
00263 static boolean setmacfileinfo (const tyfilespec *fs, CInfoPBRec *pb) {
00264     
00265     /* 
00266     2.1b2 dmb: new fsspec-based version
00267     */
00268     
00269     setoserrorparam ((ptrstring) (*fs).name); /*in case error message takes a filename parameter*/
00270     
00271     (*pb).hFileInfo.ioNamePtr = (StringPtr) (*fs).name;
00272     
00273     (*pb).hFileInfo.ioVRefNum = (*fs).vRefNum;
00274     
00275     (*pb).hFileInfo.ioDirID = (*fs).parID;
00276     
00277     return (!oserror (PBSetCatInfoSync (pb)));
00278     } /*setmacfileinfo*/
00279 
00280 
00281 static boolean touchparentfolder (const tyfilespec *fs) {
00282     
00283     /*
00284     touch the file date of the parent folder of fs
00285     */
00286     
00287     FSSpec fsfolder;
00288     
00289     if (FSMakeFSSpec ((*fs).vRefNum, (*fs).parID, nil, &fsfolder) != noErr)
00290         return (false);
00291     
00292     setfilemodified (&fsfolder, timenow ());
00293     
00294     return (true);
00295     } /*touchparentfolder*/
00296 #endif
00297 
00298 
00299 #ifdef WIN95VERSION
00300 
00301 boolean winfileerror (const tyfilespec *fs) {
00302     
00303     DWORD err = GetLastError ();
00304 
00305     setfserrorparam (fs);
00306     
00307     return (oserror (err));
00308     } /*winfileerror*/
00309 
00310 #endif
00311 
00312 #ifdef MACVERSION // 1/29/97 dmb: adopt applet toolkit version
00313 
00314 static boolean getinfofromvolpb (const HVolumeParam *pb, tyfileinfo *info) {
00315     
00316     /*
00317     dmb 9/21/93: for a volume, dirid should be fsRtParID, not fsRtDirID.
00318     */
00319     
00320     short drivenum;
00321     #if !TARGET_API_MAC_CARBON
00322     QHdrPtr dqtop;
00323     QElemPtr dqelem;
00324     #endif
00325 
00326     
00327     clearbytes (info, sizeof (tyfileinfo));
00328     
00329     (*info).vnum = (*pb).ioVRefNum;
00330     
00331     (*info).dirid = fsRtParID; /*fsRtDirID*/
00332     
00333     (*info).flvolume = true;
00334     
00335     (*info).flfolder = true;
00336     
00337     (*info).timecreated = (*pb).ioVCrDate;
00338     
00339     (*info).timemodified = (*pb).ioVLsMod;
00340     
00341     (*info).fllocked = ((*pb).ioVAtrb & 0x8000) != 0;
00342     
00343     (*info).flhardwarelock = ((*pb).ioVAtrb & 0x0080) != 0;
00344     
00345     if ((*info).flhardwarelock)
00346         (*info).fllocked = true;
00347     
00348     (*info).ctfreebytes = (*pb).ioVAlBlkSiz * (*pb).ioVFrBlk;
00349     
00350     (*info).cttotalbytes = (*pb).ioVAlBlkSiz * (*pb).ioVNmAlBlks;
00351     
00352     (*info).blocksize = (*pb).ioVAlBlkSiz;
00353     
00354     (*info).ctfiles = (*pb).ioVFilCnt;
00355     
00356     (*info).ctfolders = (*pb).ioVDirCnt;
00357     
00358     drivenum = (*pb).ioVDrvInfo;
00359     
00360     //Code change by Timothy Paustian Sunday, June 25, 2000 9:17:36 PM
00361     //The below code is to figure out if a volume is ejectable. I don't think
00362     //you can do this in carbon, so just set it to false.
00363     #if TARGET_API_MAC_CARBON == 1
00364     (*info).flejectable = false;
00365     #else
00366         
00367     dqtop = GetDrvQHdr ();
00368     
00369     dqelem = (*dqtop).qHead;
00370     
00371     while (true) {
00372         
00373         if (dqelem == nil) { /*volume is no longer in a drive; it must be ejectable!*/
00374             
00375             (*info).flejectable = true;
00376             
00377             break;
00378             }
00379         
00380         if ((*(DrvQEl *)dqelem).dQDrive == drivenum) {
00381             
00382             byte driveflag = *((byte *) dqelem - 3);
00383             
00384             (*info).flejectable = ((driveflag != 8) && (driveflag != 0x48)); /*IM IV-181*/
00385             
00386             break;
00387             }
00388         
00389         dqelem = (*dqelem).qLink;
00390         } /*while*/
00391         #endif
00392         
00393     
00394     return (true);
00395     } /*getinfofromvolpb*/
00396 
00397 
00398 boolean filegetvolumeinfo (short vnum, tyfileinfo *info) {
00399     
00400     /*
00401     dmb 9/21/93: take vnum as parameter, not volname. otherwise, 
00402     we can't distinguish between two vols w/the same name.
00403     */
00404     
00405     HVolumeParam pb;
00406     
00407     clearbytes (&pb, sizeof (pb)); /*init all fields to zero*/
00408     
00409     pb.ioVRefNum = vnum;
00410     
00411     if (oserror (PBHGetVInfoSync ((HParmBlkPtr) &pb)))
00412         return (false);
00413     
00414     clearbytes (info, sizeof (tyfileinfo)); /*init all fields to zero*/
00415     
00416     getinfofromvolpb (&pb, info);
00417     
00418     /*DW 9/7/93: determine if it's a network volume*/ {
00419         
00420         HParamBlockRec lpb;
00421         GetVolParmsInfoBuffer buffer;
00422         OSErr ec;
00423         
00424         clearbytes (&lpb, sizeof (lpb)); /*init all fields to zero*/
00425         
00426         lpb.ioParam.ioVRefNum = (*info).vnum;
00427         
00428         lpb.ioParam.ioBuffer = (Ptr) &buffer;
00429         
00430         lpb.ioParam.ioReqCount = sizeof (buffer);
00431         
00432         ec = PBHGetVolParmsSync (&lpb); 
00433     
00434         if (ec == noErr) 
00435             (*info).flremotevolume = buffer.vMServerAdr != 0; /*see Apple TN-Files docviewer doc*/
00436         }
00437     
00438     return (true);
00439     } /*filegetvolumeinfo*/
00440 
00441 
00442 void filegetinfofrompb (CInfoPBRec *pb, tyfileinfo *info) {
00443     
00444     /*
00445     dmb 9/24/93: handle volumes here, combining vol info with root 
00446     directory folder info. I'm not sure if a volume lock is always 
00447     reflected in the root directory, so don't set fllocked false 
00448     if the attribute isn't set in the pb. (it starts out cleared anyway.)
00449     
00450     5.1.4 dmb: set finderbits for folders too.
00451     */
00452     
00453     short finderbits;
00454     
00455     clearbytes (info, sizeof (tyfileinfo)); /*init all fields to zero*/
00456     
00457     (*info).vnum = (*pb).hFileInfo.ioVRefNum;
00458     
00459     (*info).dirid = (*pb).hFileInfo.ioFlParID;
00460     
00461     if ((*info).dirid == fsRtParID)
00462         filegetvolumeinfo ((*info).vnum, info);
00463     else
00464         (*info).flvolume = false;
00465     
00466     if (BitTst (&(*pb).dirInfo.ioFlAttrib, 7)) /*if it's a volume, fllocked may already be set*/
00467         (*info).fllocked = true;
00468     
00469 //  (*info).flfolder = BitTst (&(*pb).dirInfo.ioFlAttrib, 3);
00470     (*info).flfolder = (((*pb).dirInfo.ioFlAttrib & ioDirMask) != 0);
00471     
00472     (*info).ixlabel = ((*pb).hFileInfo.ioFlFndrInfo.fdFlags & 0x000E) >> 1;
00473     
00474     if ((*info).flfolder) {
00475 
00476         /*Folders are considered "busy" if there are any files within the folder */
00477         
00478         (*info).flbusy = (*pb).dirInfo.ioDrNmFls > 0;
00479         
00480         (*info).filecreator = (*info).filetype = '    ';
00481         
00482         if (!(*info).flvolume) { /*these aren't the same for a volume & its root dir*/
00483             
00484             (*info).timecreated = (*pb).dirInfo.ioDrCrDat;
00485             
00486             (*info).timemodified = (*pb).dirInfo.ioDrMdDat;
00487             
00488             (*info).ctfiles = (*pb).dirInfo.ioDrNmFls;
00489             }
00490         
00491         (*info).iconposition = (*pb).dirInfo.ioDrUsrWds.frLocation;
00492         
00493         (*info).folderview = (tyfolderview) ((*pb).dirInfo.ioDrUsrWds.frView >> 8);
00494         
00495         finderbits = (*pb).dirInfo.ioDrUsrWds.frFlags;
00496         }
00497     else { /*fill in fields for a file, somewhat different format than a folder*/
00498     
00499         (*info).flbusy = BitTst (&(*pb).hFileInfo.ioFlAttrib, 0);
00500             
00501         (*info).filecreator = (*pb).hFileInfo.ioFlFndrInfo.fdCreator;
00502         
00503         (*info).filetype = (*pb).hFileInfo.ioFlFndrInfo.fdType;
00504         
00505         (*info).timecreated = (*pb).hFileInfo.ioFlCrDat;
00506 
00507         (*info).timemodified = (*pb).hFileInfo.ioFlMdDat;
00508         
00509         (*info).sizedatafork = (*pb).hFileInfo.ioFlLgLen;
00510         
00511         (*info).sizeresourcefork = (*pb).hFileInfo.ioFlRLgLen;
00512         
00513         (*info).iconposition = (*pb).hFileInfo.ioFlFndrInfo.fdLocation;
00514         
00515         finderbits = (*pb).hFileInfo.ioFlFndrInfo.fdFlags;
00516         }
00517 
00518     /*copy from the finder bits into the record*/ {
00519     
00520         (*info).flalias = (finderbits & kIsAlias) != 0;
00521         
00522         (*info).flbundle = (finderbits & kHasBundle) != 0;
00523         
00524         (*info).flinvisible = (finderbits & kIsInvisible) != 0;
00525         
00526         (*info).flstationery = (finderbits & kIsStationery) != 0;
00527         
00528         (*info).flshared = (finderbits & kIsShared) != 0;
00529         
00530         (*info).flnamelocked = (finderbits & kNameLocked) != 0;
00531         
00532         (*info).flcustomicon = (finderbits & kHasCustomIcon) != 0;
00533         }
00534     } /*filegetinfofrompb*/
00535 #endif  
00536 
00537 #ifdef MACVERSION
00538 #define filegetfsvolumeinfo(fs, info) filegetvolumeinfo((*fs).vRefNum, info)
00539 #endif
00540 
00541 #ifdef WIN95VERSION
00542 static boolean filegetfsvolumeinfo (const tyfilespec *fs, tyfileinfo *info) {
00543     DWORD sectorsPerCluster, bytesPerSector, numberOfFreeClusters, totalNumberOfClusters;
00544     UINT drivetype;
00545     bigstring volname;
00546     bigstring errmsg;
00547 
00548     clearbytes (info, sizeof (tyfileinfo)); /*init all fields to zero*/
00549 
00550     if (fileisvolume (fs)) {
00551         info->flvolume = true;
00552         info->flbusy = true;
00553 
00554         copystring (fsname(fs), volname);
00555         cleanendoffilename (volname);
00556         pushchar ('\\', volname);
00557         nullterminate (volname);
00558 
00559 //      if (GetVolumeInformation (stringbaseaddress (volname), stringbaseaddress(volnamebuf), 
00560 //          sizeof(volnamebuf)-2, &volserial, &maxfilelen, &filesystemflags, 
00561 //          stringbaseaddress(filesystemnamebuffer), sizeof (filesystemnamebuffer)) {
00562 //              
00563 //          }
00564 
00565         if (GetDiskFreeSpace (stringbaseaddress (volname), &sectorsPerCluster, &bytesPerSector,
00566             &numberOfFreeClusters, &totalNumberOfClusters)) {
00567 
00568             DWORD bytesPerCluster;
00569             DWORD numberOfClustersIn2GB;
00570 
00571             bytesPerCluster = bytesPerSector * sectorsPerCluster;
00572 
00573             numberOfClustersIn2GB = 0x7FFFFFFFL / bytesPerCluster;
00574 
00575             info->ctfreebytes = (numberOfFreeClusters <= numberOfClustersIn2GB)
00576                 ? (numberOfFreeClusters * bytesPerCluster)
00577                 : (numberOfClustersIn2GB * bytesPerCluster);
00578 
00579             info->cttotalbytes = (totalNumberOfClusters <= numberOfClustersIn2GB)
00580                 ? (totalNumberOfClusters * bytesPerCluster)
00581                 : (numberOfClustersIn2GB * bytesPerCluster);
00582 
00583             info->blocksize = bytesPerCluster;
00584             }
00585 
00586         drivetype = GetDriveType (stringbaseaddress(volname));
00587 
00588         if ((drivetype == DRIVE_REMOVABLE) || (drivetype == DRIVE_CDROM)) {
00589             info->flejectable = true;
00590             }
00591 
00592         if (drivetype == DRIVE_REMOTE) {
00593             info->flremotevolume = true;
00594             }
00595 
00596         return (true);
00597         }
00598 
00599     wsprintf (stringbaseaddress (errmsg), "Can't complete function because \"%s\" is not a valid volume name.",
00600         stringbaseaddress (fsname (fs)));
00601 
00602     setstringlength (errmsg, strlen (stringbaseaddress (errmsg)));
00603 
00604     shellerrormessage (errmsg);
00605 
00606     return (false); 
00607     } /*filegetfsvolumeinfo*/
00608 
00609 
00610 void winsetfileinfo (WIN32_FIND_DATA * fileinfo, tyfileinfo *info) {
00611     
00612     FILETIME localFileTime;
00613     bigstring bs, bsext;
00614 
00615     clearbytes (info, sizeof (tyfileinfo)); /*init all fields to zero*/
00616     info->filecreator = '    ';     
00617     info->filetype = '    ';
00618 
00619 
00620     info->flfolder = fileinfo->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY?true:false;
00621     info->fllocked = fileinfo->dwFileAttributes & FILE_ATTRIBUTE_READONLY?true:false;
00622     info->flbundle = false;
00623     info->flbusy = false;
00624     info->flalias = false;
00625     info->flinvisible = fileinfo->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN?true:false;
00626     info->flsystem = fileinfo->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM?true:false;
00627     info->flarchive = fileinfo->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE?true:false;
00628     info->flcompressed = fileinfo->dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED?true:false;
00629     info->fltemp = fileinfo->dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY?true:false;
00630 
00631     FileTimeToLocalFileTime (&fileinfo->ftCreationTime, &localFileTime);
00632     info->timecreated = filetimetoseconds (&localFileTime);
00633 
00634     FileTimeToLocalFileTime (&fileinfo->ftLastWriteTime, &localFileTime);
00635     info->timemodified = filetimetoseconds (&localFileTime);
00636 
00637     FileTimeToLocalFileTime (&fileinfo->ftLastAccessTime, &localFileTime);
00638     info->timeaccessed = filetimetoseconds (&localFileTime);
00639 
00640     info->sizedatafork = fileinfo->nFileSizeLow;
00641     info->sizeresourcefork = 0;
00642     info->sizedataforkhigh = fileinfo->nFileSizeHigh;
00643 
00644     copyctopstring (fileinfo->cFileName, bs);
00645 
00646     lastword (bs, '.', bsext);
00647 
00648     if ((stringlength (bs) == stringlength (bsext)) || (stringlength (bsext) > 4)) {    /* no extension */
00649         stringtoostype ("\x04" "????", &info->filetype);
00650         }
00651     else {
00652         stringtoostype (bsext, &info->filetype);
00653         }
00654 
00655     } /*winsetfileinfo*/
00656 
00657 #endif
00658 
00659 
00660 boolean filegetinfo (const tyfilespec *fs, tyfileinfo *info) {
00661 
00662 #ifdef MACVERSION   
00663     /*
00664     dmb 9/24/93: let filegetinfofrompb take care of volumes
00665     */
00666     
00667     CInfoPBRec pb;
00668     
00669     /*
00670     if (isvolumefilespec (pfs)) {
00671         
00672         return (filegetfsvolumeinfo (pfs, info));
00673         }
00674     */
00675     
00676     if (!getmacfileinfo (fs, &pb))
00677         return (false);
00678     
00679     filegetinfofrompb (&pb, info);
00680 #endif
00681     
00682 #ifdef WIN95VERSION
00683     HANDLE findHandle;
00684     HANDLE fref;
00685     WIN32_FIND_DATA fileinfo;
00686     char fn[300];
00687     
00688     clearbytes (info, sizeof (tyfileinfo)); /*init all fields to zero*/
00689     info->filecreator = '    ';     
00690     info->filetype = '    ';
00691 
00692     if (fileisvolume (fs)) {
00693         return (filegetfsvolumeinfo (fs, info));
00694         }
00695 
00696     copystring (fsname (fs), fn);
00697     
00698     /*if ends with \ get ride of it... and handle the root*/
00699 
00700     cleanendoffilename (fn);
00701 
00702     nullterminate (fn);
00703 
00704 
00705     findHandle = FindFirstFile (stringbaseaddress(fn), &fileinfo);
00706 
00707     if (findHandle == INVALID_HANDLE_VALUE) {
00708         
00709         winfileerror (fs);
00710 
00711         return (false);
00712         }
00713 
00714     winsetfileinfo (&fileinfo, info);
00715 
00716     FindClose(findHandle);
00717 
00718     //Set the file busy flag (this should be in winsetfileinfo, but we do not have the filename there)
00719     if (info->flfolder) {
00720         strcat (stringbaseaddress (fn), "\\*");
00721 
00722         info->flbusy = false; //presume empty folder (not busy)
00723 
00724         findHandle = FindFirstFile (stringbaseaddress(fn), &fileinfo);
00725 
00726         if (findHandle != INVALID_HANDLE_VALUE) {
00727             info->flbusy = true;                //Found something
00728 
00729             while ((strcmp (fileinfo.cFileName, ".") == 0) || (strcmp (fileinfo.cFileName, "..") == 0)) {
00730                 info->flbusy = false;           // Just . or ..
00731 
00732                 if (FindNextFile (findHandle, &fileinfo))
00733                     info->flbusy = true;        //Found something else...
00734                 else
00735                     break;      //exit while loop if FindNext fails (this is normal)
00736                 }
00737 
00738             FindClose (findHandle);
00739             }
00740         }
00741     else {
00742         fref = (Handle) CreateFile (stringbaseaddress (fn), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
00743             FILE_ATTRIBUTE_NORMAL, NULL);
00744 
00745         if (fref == INVALID_HANDLE_VALUE) {
00746             info->flbusy = true;
00747             }
00748         else {
00749             info->flbusy = false;
00750             verify (CloseHandle (fref));
00751             }
00752         }
00753 
00754 #endif
00755     return (true);
00756     } /*filegetinfo*/
00757         
00758     
00759 boolean filegetvolumename (short vnum, bigstring volname) {
00760 #ifdef MACVERSION   
00761     HVolumeParam pb;
00762     OSErr ec;
00763     
00764     clearbytes (&pb, sizeof (pb)); /*init all fields to zero*/
00765     
00766     pb.ioNamePtr = volname;
00767     
00768     pb.ioVRefNum = vnum;
00769     
00770     ec = PBHGetVInfoSync ((HParmBlkPtr) &pb);
00771     
00772     if (ec != noErr) {
00773         
00774         setstringlength (volname, 0);
00775         
00776         return (false);
00777         }
00778         
00779     return (true);
00780 #endif
00781 
00782 #ifdef WIN95VERSION
00783     char szVol[30];
00784     DWORD serialNum, maxComponentLen, fileSystemFlags;
00785     boolean res;
00786 
00787     if ((vnum > 26) || (vnum < 0))
00788         return (false);
00789 
00790     if (vnum != 0) {
00791         strcpy (szVol, "A:\\");
00792         szVol[0] = szVol[0] + (vnum - 1);
00793         }
00794 
00795     res = GetVolumeInformation (vnum==0?NULL:szVol, stringbaseaddress(volname), sizeof(volname)-2,
00796                     &serialNum, &maxComponentLen, &fileSystemFlags, NULL, 0);
00797 
00798     if (res) {
00799         setstringlength (volname, strlen(stringbaseaddress(volname)));
00800         }
00801 
00802     return (res);
00803 #endif
00804     } /*filegetvolumename*/
00805     
00806     
00807 boolean fileisbusy (const tyfilespec *fs, boolean *flbusy) {
00808     
00809     /*
00810     6/x/91 mao
00811     */
00812     
00813     tyfileinfo info;
00814     
00815     if (!filegetinfo (fs, &info))
00816         return (false);
00817     
00818     *flbusy = info.flbusy;
00819     
00820     return (true);
00821     } /*fileisbusy*/
00822     
00823 
00824 boolean filehasbundle (const tyfilespec *fs, boolean *flbundle) {
00825     
00826     /*
00827     6/x/91 mao
00828     */
00829     
00830     tyfileinfo info;
00831     
00832     if (!filegetinfo (fs, &info))
00833         return (false);
00834     
00835     *flbundle = info.flbundle;
00836     
00837     return (true);
00838     } /*filehasbundle*/
00839 
00840 
00841 boolean filesetbundle (const tyfilespec *fs, boolean flbundle) {
00842 #ifdef MACVERSION
00843     /*
00844     8/10/92 dmb
00845     */
00846     
00847     CInfoPBRec pb;
00848     
00849     if (!getmacfileinfo (fs, &pb)) 
00850         return (false);
00851     
00852     if (flbundle) 
00853         pb.hFileInfo.ioFlFndrInfo.fdFlags |= kHasBundle; /*turn on*/
00854     else
00855         pb.hFileInfo.ioFlFndrInfo.fdFlags &= ~kHasBundle; /*turn off*/
00856     
00857     return (setmacfileinfo (fs, &pb));
00858 #endif
00859 
00860 #ifdef WIN95VERSION
00861     return (false);
00862 #endif
00863     } /*filesetbundle*/
00864 
00865 
00866 boolean fileisalias (const tyfilespec *fs, boolean *flalias) {
00867     
00868     /*
00869     6/x/91 mao
00870     */
00871     
00872     tyfileinfo info;
00873     
00874     if (!filegetinfo (fs, &info))
00875         return (false);
00876     
00877     *flalias = info.flalias;
00878     
00879     return (true);
00880     } /*fileisalias*/
00881 
00882 
00883 boolean fileisvisible (const tyfilespec *fs, boolean *flvisible) {
00884     
00885     /*
00886     6/9/92 dmb
00887     */
00888     
00889     tyfileinfo info;
00890     
00891     if (!filegetinfo (fs, &info))
00892         return (false);
00893     
00894     *flvisible = !info.flinvisible;
00895     
00896     return (true);
00897     } /*fileisvisible*/
00898 
00899 
00900 boolean filesetvisible (const tyfilespec *fs, boolean flvisible) {
00901 #ifdef MACVERSION
00902     /*
00903     6/9/92 dmb
00904     */
00905     
00906     CInfoPBRec pb;
00907     
00908     if (!getmacfileinfo (fs, &pb)) 
00909         return (false);
00910     
00911     if (flvisible) 
00912         pb.hFileInfo.ioFlFndrInfo.fdFlags &= ~kIsInvisible; /*turn off*/
00913     else
00914         pb.hFileInfo.ioFlFndrInfo.fdFlags |= kIsInvisible; /*turn on*/
00915     
00916     if (!setmacfileinfo (fs, &pb))
00917         return (false);
00918     
00919     touchparentfolder (fs);
00920 #endif  
00921     
00922 #ifdef WIN95VERSION
00923     tyfileinfo info;
00924     DWORD attr;
00925     
00926     if (!filegetinfo (fs, &info))
00927         return (false);
00928 
00929     if (info.flinvisible == flvisible) /*check if we need to do anything first*/
00930         {
00931         attr = GetFileAttributes (stringbaseaddress (fsname (fs)));
00932 
00933         if (attr == 0xFFFFFFFF)
00934             return (false);
00935 
00936         attr = attr & (~FILE_ATTRIBUTE_HIDDEN);
00937 
00938         if (! flvisible)
00939             attr = attr | FILE_ATTRIBUTE_HIDDEN;
00940 
00941         return(SetFileAttributes (stringbaseaddress (fsname (fs)), attr));
00942         }
00943 #endif
00944     return (true);
00945     } /*filesetvisible*/
00946 
00947 
00948 boolean getfiletype (const tyfilespec *fs, OSType *type) {
00949     
00950     tyfileinfo info;
00951     
00952     *type = '    ';
00953     
00954     if (!filegetinfo (fs, &info))
00955         return (false);
00956         
00957     *type = info.filetype;
00958     
00959     return (true);
00960     } /*getfiletype*/
00961 
00962     
00963 boolean getfilecreator (const tyfilespec *fs, OSType *creator) {
00964     
00965     tyfileinfo info;
00966     
00967     *creator = '    ';
00968     
00969     if (!filegetinfo (fs, &info))
00970         return (false);
00971         
00972     *creator = info.filecreator;
00973     
00974     return (true);
00975     } /*getfilecreator*/
00976 
00977 
00978 boolean filesize (const tyfilespec *fs, long *size) {
00979     
00980     tyfileinfo info;
00981     
00982     if (!filegetinfo (fs, &info))
00983         return (false);
00984     
00985     *size = info.sizedatafork + info.sizeresourcefork;
00986     
00987     return (true);
00988     } /*filesize*/
00989     
00990     
00991 boolean fileisfolder (const tyfilespec *fs, boolean *flfolder) {
00992     
00993     tyfileinfo info;
00994 
00995     #ifdef WIN95VERSION
00996         /* special case the root directory on Windows */
00997         char fn[300];
00998 
00999         copystring (fsname (fs), fn);
01000         
01001         if (fn[2] == ':' && isalpha(fn[1])) {
01002 
01003             if ((stringlength(fn) == 2) || ((stringlength(fn) == 3) && (fn[3] == '\\'))) {
01004                 
01005                 if (fileisvolume (fs)) {
01006                     
01007                     *flfolder = true;
01008 
01009                     return (true);
01010                     }
01011                 }
01012             }
01013 
01014     #endif
01015     
01016     if (!filegetinfo (fs, &info))
01017         return (false);
01018     
01019     *flfolder = info.flfolder;
01020     
01021     return (true);
01022     } /*fileisfolder*/
01023 
01024 
01025 boolean fileisvolume (const tyfilespec *fs) {
01026 #ifdef MACVERSION   
01027     if (isemptystring ((*fs).name))
01028         return (false);
01029     
01030     return ((*fs).parID == fsRtParID);
01031 #endif
01032 
01033 #ifdef WIN95VERSION
01034     bigstring bsvol;
01035     short drivenum;
01036     DWORD drivemap, drivemask;
01037 
01038     copystring (fsname(fs), bsvol);
01039 
01040     switch (stringlength (bsvol)) {
01041         
01042         case 3:
01043             if (getstringcharacter(bsvol, 2) != '\\')
01044                 return (false);
01045 
01046         case 2:
01047             if (getstringcharacter(bsvol, 1) != ':')
01048                 return (false);
01049 
01050             if (! isalpha (getstringcharacter(bsvol, 0)))
01051                 return (false);
01052 
01053             drivenum = getlower(getstringcharacter(bsvol, 0)) - 'a';
01054             break;
01055 
01056         default:
01057             return (false);
01058         }
01059 
01060     drivemap = GetLogicalDrives();
01061     
01062     drivemask = 1 << drivenum;
01063 
01064     return ((drivemap & drivemask) == drivemask);
01065 #endif
01066     } /*fileisvolume*/
01067 
01068 
01069 boolean fileislocked (const tyfilespec *fs, boolean *fllocked) {
01070     
01071     tyfileinfo info;
01072     
01073     if (!filegetinfo (fs, &info))
01074         return (false);
01075     
01076     *fllocked = info.fllocked;
01077     
01078     return (true);
01079     } /*fileislocked*/
01080     
01081     
01082 boolean getfiledates (const tyfilespec *fs, unsigned long *datecreated, unsigned long *datemodified) {
01083     
01084     tyfileinfo info;
01085     
01086     if (!filegetinfo (fs, &info))
01087         return (false);
01088     
01089     *datecreated = info.timecreated;
01090     
01091     *datemodified = info.timemodified;
01092     
01093     return (true);
01094     } /*getfiledates*/
01095 
01096 
01097 boolean setfiledates (const tyfilespec *fs, unsigned long datecreated, unsigned long datemodified) {
01098 #ifdef MACVERSION   
01099     /*
01100     6/x/91 mao: modified to work with new getmacilfeinfo/setmacfileinfo.
01101     */
01102     
01103     CInfoPBRec pb;
01104     
01105     if (!getmacfileinfo (fs, &pb)) 
01106         return (false);
01107     
01108     if (foldertest (&pb)) {
01109         
01110         pb.dirInfo.ioDrCrDat = datecreated;
01111         
01112         pb.dirInfo.ioDrMdDat = datemodified;
01113         }
01114     else {
01115         
01116         pb.hFileInfo.ioFlCrDat = datecreated;
01117     
01118         pb.hFileInfo.ioFlMdDat = datemodified;
01119         }
01120     
01121     return (setmacfileinfo (fs, &pb));
01122 #endif
01123 
01124 #ifdef WIN95VERSION
01125     HANDLE h;
01126     FILETIME modtime, createtime, temp;
01127     char fn[300];
01128     DWORD err;
01129     boolean fl;
01130 
01131     secondstofiletime (datecreated, &temp);
01132     LocalFileTimeToFileTime (&temp, &createtime);
01133 
01134     secondstofiletime (datemodified, &temp);
01135     LocalFileTimeToFileTime (&temp, &modtime);
01136 
01137     copystring (fsname (fs), fn);
01138     
01139     nullterminate (fn);
01140     
01141     h = CreateFile (stringbaseaddress(fn), GENERIC_READ | GENERIC_WRITE,
01142                 FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
01143 
01144     if (h == INVALID_HANDLE_VALUE) {
01145         
01146         winfileerror (fs);
01147 
01148         return (false);
01149         }
01150 
01151 
01152     //We do not alter the accessed time.
01153     fl = SetFileTime (h, &createtime, NULL, &modtime);
01154 
01155     if (!fl)
01156         err = GetLastError();
01157 
01158     verify (CloseHandle (h));
01159     
01160     if (fl)
01161         return (true);
01162 
01163     oserror(err);
01164     return (false);
01165 #endif
01166     } /*setfiledates*/
01167 
01168 
01169 #ifdef MACVERSION
01170 boolean getfilepos (const tyfilespec *fs, Point *pt) {
01171     
01172     /*
01173     mao 6/x/91: modified to work with new getmacilfeinfo/setmacfileinfo.
01174     */
01175     
01176     CInfoPBRec pb;
01177     
01178     if (!getmacfileinfo (fs, &pb)) 
01179         return (false);
01180     
01181     if (foldertest (&pb)) 
01182         *pt = pb.dirInfo.ioDrUsrWds.frLocation;
01183     else    
01184         *pt = pb.hFileInfo.ioFlFndrInfo.fdLocation;
01185     
01186     return (true);
01187     } /*getfilepos*/
01188 
01189 
01190 boolean setfilepos (const tyfilespec *fs, Point pt) {
01191 
01192     /*
01193     6/x/91 mao: modified to work with new getmacilfeinfo/setmacfileinfo.
01194     */
01195     
01196     CInfoPBRec pb;
01197     
01198     if (!getmacfileinfo (fs, &pb)) 
01199         return (false);
01200     
01201     if (foldertest (&pb)) 
01202         pb.dirInfo.ioDrUsrWds.frLocation = pt;
01203     else
01204         pb.hFileInfo.ioFlFndrInfo.fdLocation = pt;
01205     
01206     return (setmacfileinfo (fs, &pb));
01207     } /*setfilepos*/
01208 #endif
01209 
01210 boolean setfilecreated (const tyfilespec *fs, long when) {
01211     
01212     /*
01213     7/31/91 dmb: created
01214     */
01215     
01216     unsigned long datecreated, datemodified;
01217     
01218     if (!getfiledates (fs, &datecreated, &datemodified))
01219         return (false);
01220     
01221     return (setfiledates (fs, when, datemodified));
01222     } /*setfilecreated*/
01223 
01224 
01225 boolean setfilemodified (const tyfilespec *fs, long when) {
01226     
01227     /*
01228     7/31/91 dmb: created
01229     */
01230     
01231     unsigned long datecreated, datemodified;
01232     
01233     if (!getfiledates (fs, &datecreated, &datemodified))
01234         return (false);
01235     
01236     return (setfiledates (fs, datecreated, when));
01237     } /*setfilemodified*/
01238 
01239 
01240 #ifdef MACVERSION
01241 boolean setfiletype (const tyfilespec *fs, OSType filetype) {
01242     
01243     /*
01244     6/x/91 mao: modified to work with new getmacilfeinfo/setmacfileinfo.
01245     */
01246     
01247     CInfoPBRec pb;
01248     
01249     if (!getmacfileinfo (fs, &pb)) 
01250         return (false);
01251     
01252     if (foldertest (&pb)) 
01253         return (false);
01254     
01255     pb.hFileInfo.ioFlFndrInfo.fdType = filetype;
01256     
01257     return (setmacfileinfo (fs, &pb));
01258     } /*setfiletype*/
01259 
01260 
01261 boolean setfilecreator (const tyfilespec *fs, OSType filecreator) {
01262     
01263     /*
01264     6/x/91 mao: modified to work with new getmacilfeinfo/setmacfileinfo. Also, makes sure
01265     folders aren't operated on
01266     */
01267     
01268     CInfoPBRec pb;
01269     
01270     if (!getmacfileinfo (fs, &pb)) 
01271         return (false);
01272         
01273     if (foldertest (&pb)) 
01274         return (false);
01275     
01276     pb.hFileInfo.ioFlFndrInfo.fdCreator = filecreator;
01277     
01278     return (setmacfileinfo (fs, &pb));
01279     } /*setfilecreator*/
01280 #endif
01281 
01282 #ifdef MACVERSION
01283 static boolean copyfork (hdlfilenum fsource, hdlfilenum fdest, Handle hbuffer) {
01284     
01285     /*
01286     copy either the data fork or resource fork of the indicated file.
01287     
01288     return true iff the file copy was successful.
01289     
01290     5/19/92 dmb: call langbackgroundtask when a script is running to make it more 
01291     likely that we'll yield the processor to another app.  also, only allow 
01292     background tasks if fork is larger than a single buffer.  note that if a script 
01293     is copying a bunch of files in a loop, the interpreter is already allowing 
01294     backgrounding between files.
01295     */
01296 
01297     register long buffersize = GetHandleSize (hbuffer);
01298     long ctbytes;
01299     register OSErr errcode;
01300     
01301     SetFPos (fsource, fsFromStart, 0L); 
01302     
01303     SetFPos (fdest, fsFromStart, 0L);
01304     
01305     while (true) { 
01306         
01307         ctbytes = buffersize;
01308         
01309         HLock (hbuffer);
01310         
01311         errcode = FSRead (fsource, &ctbytes, *hbuffer);
01312         
01313         HUnlock (hbuffer);
01314         
01315         if ((errcode != noErr) && (errcode != eofErr)) {
01316             
01317             oserror (errcode);
01318             
01319             return (false);
01320             }
01321             
01322         if (ctbytes == 0) /*last read got no bytes*/
01323             return (true);
01324         
01325         HLock (hbuffer);
01326         
01327         errcode = FSWrite (fdest, &ctbytes, *hbuffer);
01328         
01329         HUnlock (hbuffer);
01330         
01331         if (oserror (errcode))
01332             return (false);
01333         
01334         if (ctbytes < buffersize) /*copy of fork is finished*/
01335             return (true);
01336         
01337         if (flscriptrunning)
01338             langbackgroundtask (false);
01339         else
01340             shellbackgroundtask (); /*give background processes a chance*/
01341         
01342         filebeachball (); /*roll the beachball cursor if there is one*/
01343         } /*while*/
01344     } /*copyfork*/
01345 
01346 
01347 #endif
01348 
01349 boolean largefilebuffer (Handle *hbuffer) {
01350     
01351     /*
01352     allocate a "large" buffer for a file copy or some kind of transfer.
01353     
01354     we ask for a block the size of half of the current free space.  if we can't 
01355     get it, we'll ask for the largest free block.  in any case, we fail if 
01356     we can't get a block of at least a K
01357     
01358     3/16/92 dmb: total rewrite; old version _always_ compacted the heap, 
01359     resulting in poor performance.
01360     */
01361     
01362     register long ctbytes;
01363     register Handle h;
01364     
01365     *hbuffer = nil; /*default return*/
01366 
01367 #ifdef MACVERSION
01368     ctbytes = FreeMem () / 2;
01369     
01370     if (ctbytes < 1024) { /*no enough memory to work with*/
01371         
01372         memoryerror ();
01373         
01374         return (false);
01375         }
01376     
01377     ctbytes &= ~(1024 - 1); /*fast round down to nearest multiple of 1024*/
01378     
01379     h = NewHandle (ctbytes);
01380     
01381     if (h != nil) {
01382         
01383         *hbuffer = h;
01384         
01385         return (true);
01386         }
01387     
01388     /*allocation failed; heap has been compacted; find largest block size*/
01389     
01390     ctbytes = CompactMem (maxSize); /*recompact the heap, finding out size of largest block*/
01391     
01392     if (ctbytes < 1024) { /*largest block is too small to use*/
01393         
01394         memoryerror ();
01395         
01396         return (false);
01397         }
01398     
01399 #endif
01400 
01401 #ifdef WIN95VERSION
01402     DBG_UNREFERENCED_LOCAL_VARIABLE(h);
01403     
01404     ctbytes = 0x00020000L;      /* 128K buffer */
01405 #endif
01406 
01407     ctbytes &= ~(1024 - 1); /*fast round down to nearest multiple of 1024*/
01408     
01409     return (newhandle (ctbytes, hbuffer)); /*shouldn't fail at this point, but let's be sure*/
01410     } /*largefilebuffer*/
01411 
01412 
01413 #ifdef MACVERSION
01414 
01415 static pascal OSErr FSpCreateMinimum (const FSSpec *fs)
01416 {
01417     HParamBlockRec pb;
01418     
01419     pb.fileParam.ioNamePtr = (StringPtr)(*fs).name;
01420     
01421     pb.fileParam.ioVRefNum = (*fs).vRefNum;
01422     
01423     pb.ioParam.ioVersNum = 0;
01424     
01425     pb.fileParam.ioDirID = (*fs).parID;
01426     
01427     return (PBHCreateSync (&pb));
01428     } /*FSpCreateMinimum*/
01429 
01430 
01431 static pascal OSErr FSpOpenAware (const tyfilespec *fs, boolean flresource, short denyModes, hdlfilenum *refNum) {
01432     
01433     /*
01434     3.0.2 dmb: customized version of HOpenAware from MoreFiles 1.1
01435     */
01436     
01437     HParamBlockRec pb;
01438     OSErr err;
01439     GetVolParmsInfoBuffer volParmsInfo;
01440     long infoSize = sizeof (GetVolParmsInfoBuffer);
01441     
01442     pb.ioParam.ioNamePtr = (StringPtr) (*fs).name;
01443     pb.ioParam.ioVRefNum = (*fs).vRefNum;
01444     pb.ioParam.ioVersNum = 0;
01445     pb.ioParam.ioMisc = nil;
01446     
01447     /* 
01448     get volume attributes
01449     this preflighting is needed because Foreign File Access based file systems don't
01450     return the correct error result to the OpenDeny call
01451     */
01452     pb.ioParam.ioBuffer = (Ptr) &volParmsInfo;
01453     pb.ioParam.ioReqCount = infoSize;
01454     
01455     err = PBHGetVolParmsSync (&pb);
01456     
01457     pb.fileParam.ioDirID = (*fs).parID;
01458     
01459     /*
01460     err = HGetVolParms ((StringPtr) (*fs).name, (*fs).vRefNum, &volParmsInfo, &infoSize);
01461     */
01462     
01463     if (err == noErr) {
01464         
01465         /* if volume supports OpenDeny, use it and return */
01466         if (hasOpenDeny (volParmsInfo)) {
01467             
01468             pb.accessParam.ioDenyModes = denyModes;
01469             
01470             if (flresource)
01471                 err = PBHOpenRFDenySync (&pb);
01472             else
01473                 err = PBHOpenDenySync (&pb);
01474             
01475             *refNum = pb.ioParam.ioRefNum;
01476             
01477             return (err);
01478             }
01479         }
01480     else
01481         if (err != paramErr)    /* paramErr is OK, it just means this volume doesn't support GetVolParms */
01482             return (err);
01483     
01484     /*
01485     OpenDeny isn't supported, so try File Manager Open functions
01486     Set File Manager permissions to closest thing possible
01487     */
01488     pb.ioParam.ioPermssn = ((denyModes == dmWr) || (denyModes == dmRdWr)) ? (fsRdWrShPerm) : (denyModes % 4);
01489     
01490     if (flresource)
01491         err = PBHOpenRFSync (&pb);
01492     
01493     else {
01494         
01495         err = PBHOpenDFSync (&pb);              /* Try OpenDF */
01496         
01497         if (err == paramErr)
01498             err = PBHOpenSync (&pb);            /* OpenDF not supported, so try Open */
01499         }
01500     
01501     *refNum = pb.ioParam.ioRefNum;
01502     
01503     return (err);
01504     } /*FSpOpenAware*/
01505 
01506 
01507 static boolean copyfileattrs (const tyfilespec *fsource, const tyfilespec *fdest, boolean flcopylockbit) {
01508     
01509     CInfoPBRec pb;
01510     OSErr err;
01511     boolean flfolder;
01512     
01513     pb.hFileInfo.ioVRefNum = (*fsource).vRefNum;
01514     pb.hFileInfo.ioDirID = (*fsource).parID;
01515     pb.hFileInfo.ioNamePtr = (StringPtr) (*fsource).name;
01516     pb.hFileInfo.ioFDirIndex = 0;
01517     
01518     err = PBGetCatInfoSync(&pb);
01519     
01520     if (err == noErr) {
01521         
01522         flfolder = (pb.hFileInfo.ioFlAttrib & 0x10);
01523         
01524         pb.hFileInfo.ioVRefNum = (*fdest).vRefNum;
01525         pb.hFileInfo.ioDirID = (*fdest).parID;
01526         pb.hFileInfo.ioNamePtr = (StringPtr) (*fdest).name;
01527         
01528         /* don't copy the hasBeenInited bit */
01529         pb.hFileInfo.ioFlFndrInfo.fdFlags = (pb.hFileInfo.ioFlFndrInfo.fdFlags & 0xfeff);
01530         
01531         err = PBSetCatInfoSync(&pb);
01532         
01533         if ((err == noErr) && (flcopylockbit) && (pb.hFileInfo.ioFlAttrib & 0x01)) {
01534             
01535             err = PBHSetFLockSync ((HParmBlkPtr) &pb);
01536             
01537             if ((err != noErr) && (flfolder))
01538                 err = noErr; /* ignore lock errors if destination is directory */
01539             }
01540         }
01541     
01542     return (err);
01543     } /*copyfileattrs*/
01544 
01545 
01546 boolean copyfile (const tyfilespec *fsource, const tyfilespec *fdest, boolean fldata, boolean flresources) {
01547 
01548     /*
01549     create a copy of the indicated file in the destination volume, with the indicated
01550     name.  
01551     
01552     we allocate a good-sized buffer in the heap, then open and copy the data fork then
01553     open and copy the resource fork of the source file.
01554     
01555     return true if the operation was successful, false otherwise.
01556     
01557     7/27/90 DW: add fldata, flresources -- allows selective copying of the two
01558     forks of each file.  we assume one of these two booleans is true.
01559     
01560     3/16/92 dmb: maintain all public Finder flags, not just creator/type & dates
01561     
01562     3.0.2 dmb: use CreateMinimum and do things in special order for drop-box copies.
01563     For details, see MoreFiles:FileCopy.c on the Reference Library CD. note that 
01564     there are more details handled by the sample code that we're ignoring here. one 
01565     is using CopyFile if src and dst are on the same server and the server supports 
01566     that function. another is to open forks with deny modes set. maybe next time...
01567     also, we now handle folders, so file.copy can retain folder attributes.
01568     */
01569     
01570     Handle hbuffer = nil;
01571     short sourcefnum = 0, sourcernum = 0;
01572     short destfnum = 0, destrnum = 0;
01573     boolean fldestcreated = false;
01574     boolean flsourcefolder, fldestfolder;
01575     
01576     if (!fileisfolder (fsource, &flsourcefolder))
01577         return (false);
01578     
01579     if (flsourcefolder)
01580         fldata = flresources = false;
01581     
01582     else {
01583         
01584         if (!largefilebuffer (&hbuffer)) 
01585             return (false);
01586         }
01587     
01588     if (fldata) {
01589         
01590         if (oserror (FSpOpenAware (fsource, false, dmRdDenyWr, &sourcefnum)))
01591             goto error;
01592         }
01593     
01594     if (flresources) {
01595         
01596         if (oserror (FSpOpenAware (fsource, true, dmRdDenyWr, &sourcernum)))
01597             goto error;
01598         }
01599     
01600     if (fileexists (fdest, &fldestfolder)) { /*file exists, delete it*/
01601         
01602         if (!deletefile (fdest))
01603             goto error;
01604         }
01605     
01606     setfserrorparam (fdest); /*in case error message takes a filename parameter*/
01607     
01608     if (flsourcefolder) {
01609         
01610         if (!newfolder (fdest))
01611             goto error;
01612         }
01613     else {
01614         
01615         if (oserror (FSpCreateMinimum (fdest)))
01616             goto error;
01617         }
01618     
01619     fldestcreated = true;
01620     
01621     if (oserror (copyfileattrs (fsource, fdest, false)))
01622         goto error;
01623     
01624     if (fldata) {
01625         
01626         if (oserror (FSpOpenAware (fdest, false, dmWrDenyRdWr, &destfnum)))
01627             goto error;
01628         }
01629     
01630     if (flresources) {
01631         
01632         if (oserror (FSpOpenAware (fdest, true, dmWrDenyRdWr, &destrnum)))
01633             goto error;
01634         }
01635     
01636     if (fldata) {
01637         
01638         if (!copyfork (sourcefnum, destfnum, hbuffer)) /*copy data fork*/
01639             goto error;
01640         
01641         closefile (sourcefnum); 
01642         
01643         closefile (destfnum); 
01644         
01645         sourcefnum = 0;
01646         
01647         destfnum = 0;
01648         }
01649     
01650     if (flresources) {
01651         
01652         if (!copyfork (sourcernum, destrnum, hbuffer)) /*copy resource fork*/
01653             goto error;
01654         
01655         closefile (sourcernum);
01656             
01657         closefile (destrnum); 
01658         
01659         sourcernum = 0;
01660         
01661         destrnum = 0;
01662         }
01663     
01664     disposehandle (hbuffer);
01665     
01666     hbuffer = nil; /*if error don't dispose of it again*/
01667     
01668     copyfileattrs (fsource, fdest, true); /*ignore error*/
01669     
01670     return (true); /*the file copy was successful*/
01671     
01672     error: /*goto here to release the buffer, close files and return false*/
01673     
01674     if (hbuffer != nil)
01675         disposehandle (hbuffer);
01676     
01677     if (sourcefnum != 0)
01678         closefile (sourcefnum);
01679     
01680     if (sourcernum != 0)
01681         closefile (sourcernum);
01682     
01683     if (destfnum != 0)
01684         closefile (destfnum);
01685     
01686     if (destrnum != 0)
01687         closefile (destrnum);
01688     
01689     if (fldestcreated)
01690         deletefile (fdest); /*no file created on error*/
01691     
01692     return (false);
01693     } /*copyfile*/
01694 #endif
01695 
01696 
01697 #ifdef WIN95VERSION
01698 boolean copyfile (const tyfilespec *fsource, const tyfilespec *fdest, boolean fldata, boolean flresources) {
01699     
01700     /*
01701     5.0.1 dmb: if the file exists, overwrite it.
01702     */
01703 
01704     char fn[300];
01705     char fn2[300];
01706     boolean flcreatefolder;
01707     boolean fldestfolder;
01708 
01709     copystring (fsname (fsource), fn);
01710     copystring (fsname (fdest), fn2);
01711 
01712     cleanendoffilename (fn);
01713     cleanendoffilename (fn2);
01714 
01715     nullterminate (fn);
01716     nullterminate (fn2);
01717 
01718     if (!fileisfolder (fsource, &flcreatefolder))
01719         return (false);
01720 
01721     if (flcreatefolder) {
01722         
01723         if (fileexists (fdest, &fldestfolder)) { /*file exists, delete it*/
01724             
01725             if (!deletefile (fdest))
01726                 return (false);
01727             }
01728         
01729         if (CreateDirectoryEx (stringbaseaddress(fn), stringbaseaddress(fn2), NULL))
01730             return (true);
01731 
01732         winfileerror (fdest);
01733 
01734         return (false);
01735         }
01736     
01737     if (CopyFile (stringbaseaddress (fn), stringbaseaddress(fn2), false))
01738         return (true);
01739 
01740     winfileerror (fdest);
01741 
01742     return (false);
01743     } /*copyfile*/
01744 #endif
01745 
01746 short filegetapplicationrnum (void) {
01747 
01748     return (applicationresnum);
01749     } /*filegetapplicationrnum*/
01750 
01751 
01752 #ifdef flsystem6
01753 
01754 short filegetapplicationvnum (void) {
01755 
01756     return (applicationvolnum);
01757     } /*filegetapplicationvnum*/
01758 
01759 
01760 short filegetsystemvnum (void) {
01761 
01762     SysEnvRec env;
01763     
01764     SysEnvirons (1, &env);
01765     
01766     return (env.sysVRefNum);
01767     } /*filegetsystemvnum*/
01768 
01769 #endif
01770 
01771 #ifdef MACVERSION
01772 static boolean pathtovolume (bigstring bspath, short *vnum) {
01773     
01774     if (countwords (bspath, chpathseparator) > 1) {
01775         
01776         oserror (errorVolume); /*no such volume*/
01777         
01778         return (false);
01779         }
01780     
01781     if (!fileparsevolname (bspath, vnum, nil)) {
01782         
01783         oserror (errorVolume); /*no such volume*/
01784         
01785         return (false);
01786         }
01787     
01788     return (true);
01789     } /*pathtovolume*/
01790 #endif
01791 
01792 //Timothy Paustian's comments
01793 //warning the values returned by getspecialfolderpath on OS X are very different
01794 //than classic Mac OS
01795 
01796 boolean getspecialfolderpath (bigstring bsvol, bigstring bsfolder, boolean flcreate, tyfilespec *fs) {
01797     /*
01798     2006-04-11 creedon: windows now honors flcreate
01799                    for windows added; CSIDL_PROGRAM_FILES, CSIDL_MYDOCUMENTS, CSIDL_MYMUSIC,
01800                         CSIDL_MYPICTURES, CSIDL_MYVIDEO;
01801                    for windows replaced more complex code with CSIDL_SYSTEM, CSIDL_WINDOWS
01802     */
01803 
01804 #ifdef MACVERSION
01805     /*
01806     9/1/92 dmb: last new verb for 2.0.  (?)
01807     */
01808     
01809     short vnum;
01810     short ixlist;
01811     long dirid;
01812     OSType foldertype;
01813     long attrs;
01814     OSErr errcode = errorNone;
01815     bigstring bsfirst;
01816     
01817     if (!(gestalt (gestaltFindFolderAttr, &attrs) && (attrs & (1 << gestaltFindFolderPresent))))
01818         return (false);
01819     
01820     if (isemptystring (bsvol))
01821 
01822         #if TARGET_API_MAC_CARBON
01823         vnum = kUserDomain;
01824         #else
01825         vnum = kOnSystemDisk;
01826         #endif
01827     else {
01828         if (!pathtovolume (bsvol, &vnum))
01829             return (false);
01830         }
01831     
01832     setoserrorparam (bsfolder);
01833     
01834     if (stringlength (bsfolder) == sizeof (OSType)) /*received folder type code*/
01835         stringtoostype (bsfolder, &foldertype);
01836     
01837     else {
01838         firstword (bsfolder, chspace, bsfirst);
01839         
01840         if (findstringlist (bsfirst, specialfolderlistnumber, &ixlist))
01841         {
01842             foldertype = specialfolders [ixlist];
01843             #if TARGET_API_MAC_CARBON
01844             //temp items, we want to redirect to the users domain.
01845             //if we don't do this then it is a read only directory at the root.
01846             if (ixlist == 11)
01847                 vnum = kUserDomain;
01848             #endif
01849         }
01850         else
01851             errcode = dirNFErr;
01852     }
01853     
01854     if (errcode == noErr)
01855         errcode = FindFolder (vnum, foldertype, flcreate, &vnum, &dirid);
01856 
01857     
01858     if (errcode == noErr) {
01859         
01860         errcode = FSMakeFSSpec (vnum, dirid, nil, fs);
01861         
01862         /*
01863         if (!directorytopath (dirid, vnum, bspath)) /%shouldn't fail%/
01864             errcode = dirNFErr;
01865         */
01866         }
01867     
01868     return (!oserror (errcode));
01869 #endif
01870 
01871 #ifdef WIN95VERSION
01872     int nFolder = -1;
01873     // int res;
01874     ITEMIDLIST * il;
01875     // Global pointer to the shell's IMalloc interface.  
01876     LPMALLOC g_pMalloc = NULL;  
01877 
01878     /* if (equalidentifiers ("\x6" "system", bsfolder)) {
01879         unsigned char str[MAX_PATH];
01880 
01881         res = GetSystemDirectory (str, MAX_PATH);
01882         if (res == 0) {
01883             return (! oserror(GetLastError()));
01884             }
01885         
01886         if (res > 255)
01887             res = 255;
01888 
01889         memmove (stringbaseaddress(fsname(fs)), str, res);
01890         setstringlength(fsname(fs), res);
01891         pushchar ('\\', fsname(fs));
01892         nullterminate (fsname(fs));
01893         return (true);
01894         }
01895 
01896     if (equalidentifiers ("\x7" "windows", bsfolder)) {
01897         unsigned char str[MAX_PATH];
01898 
01899         res = GetWindowsDirectory (str, MAX_PATH);
01900         if (res == 0) {
01901             return (! oserror(GetLastError()));
01902             }
01903 
01904         if (res > 255)
01905             res = 255;
01906 
01907         memmove (stringbaseaddress(fsname(fs)), str, res);
01908         setstringlength(fsname(fs), res);
01909         pushchar ('\\', fsname(fs));
01910         nullterminate (fsname(fs));
01911         return (true);
01912         } */
01913 
01914     if (equalidentifiers ("\x9" "bitbucket", bsfolder))
01915         nFolder = CSIDL_BITBUCKET;
01916     else if (equalidentifiers ("\x8" "controls", bsfolder))
01917         nFolder = CSIDL_CONTROLS;
01918     else if (equalidentifiers ("\x7" "desktop", bsfolder))
01919         nFolder = CSIDL_DESKTOP;
01920     else if (equalidentifiers ("\x10" "desktopdirectory", bsfolder))
01921         nFolder = CSIDL_DESKTOPDIRECTORY;
01922     else if (equalidentifiers ("\x6" "drives", bsfolder))
01923         nFolder = CSIDL_DRIVES;
01924     else if (equalidentifiers ("\x5" "fonts", bsfolder))
01925         nFolder = CSIDL_FONTS;
01926     else if (equalidentifiers ("\x7" "nethood", bsfolder))
01927         nFolder = CSIDL_NETHOOD;
01928     else if (equalidentifiers ("\x7" "network", bsfolder))
01929         nFolder = CSIDL_NETWORK;
01930     else if (equalidentifiers ("\x8" "personal", bsfolder))
01931         nFolder = CSIDL_PERSONAL;
01932     else if (equalidentifiers ("\x8" "printers", bsfolder))
01933         nFolder = CSIDL_PRINTERS;
01934     else if (equalidentifiers ("\x8" "programs", bsfolder))
01935         nFolder = CSIDL_PROGRAMS;
01936     else if (equalidentifiers ("\x6" "recent", bsfolder))
01937         nFolder = CSIDL_RECENT;
01938     else if (equalidentifiers ("\x6" "sendto", bsfolder))
01939         nFolder = CSIDL_SENDTO;
01940     else if (equalidentifiers ("\x9" "startmenu", bsfolder))
01941         nFolder = CSIDL_STARTMENU;
01942     else if (equalidentifiers ("\x7" "startup", bsfolder))
01943         nFolder = CSIDL_STARTUP;
01944     else if (equalidentifiers ("\x9" "templates", bsfolder))
01945         nFolder = CSIDL_TEMPLATES;
01946     else if (equalidentifiers ("\xD" "program files", bsfolder))
01947         nFolder = CSIDL_PROGRAM_FILES;
01948     else if (equalidentifiers ("\x6" "system", bsfolder))
01949         nFolder = CSIDL_SYSTEM;
01950     else if (equalidentifiers ("\x7" "windows", bsfolder))
01951         nFolder = CSIDL_WINDOWS;
01952     else if (equalidentifiers ("\xC" "my documents", bsfolder))
01953         nFolder = CSIDL_MYDOCUMENTS;
01954     else if (equalidentifiers ("\x8" "my music", bsfolder))
01955         nFolder = CSIDL_MYMUSIC;
01956     else if (equalidentifiers ("\xB" "my pictures", bsfolder))
01957         nFolder = CSIDL_MYPICTURES;
01958     else if (equalidentifiers ("\x8" "my video", bsfolder))
01959         nFolder = CSIDL_MYVIDEO;
01960 
01961     if (flcreate)
01962         nFolder += CSIDL_FLAG_CREATE;
01963 
01964 if (nFolder != -1) {
01965         // Get the shell's allocator. 
01966         if (!SUCCEEDED(SHGetMalloc(&g_pMalloc))) {
01967             oserror (ERROR_INVALID_FUNCTION);
01968             return (false); 
01969             }
01970 
01971         if (SHGetSpecialFolderLocation (NULL, nFolder, &il) == NOERROR) {
01972             /*process itemlist */
01973             if (SHGetPathFromIDList (il, stringbaseaddress(fsname(fs)))) {
01974                 setstringlength (fsname(fs), strlen(stringbaseaddress(fsname(fs))));
01975                 pushchar ('\\', fsname(fs));
01976                 nullterminate (fsname(fs));
01977 
01978                 // Free the PIDL 
01979                 g_pMalloc->lpVtbl->Free(g_pMalloc, il); 
01980 
01981                 // Release the shell's allocator. 
01982                 g_pMalloc->lpVtbl->Release(g_pMalloc); 
01983                 return (true);
01984                 }
01985             }
01986         }
01987 
01988     // Release the shell's allocator. mnbmj
01989     if (g_pMalloc != NULL)
01990         g_pMalloc->lpVtbl->Release(g_pMalloc); 
01991 
01992     oserror (ERROR_INVALID_FUNCTION);
01993     return (false);
01994 #endif
01995     } /*getspecialfolderpath*/
01996 
01997 
01998 #ifdef MACVERSION
01999 boolean ejectvol (const tyfilespec *fs) {
02000 #if TARGET_API_MAC_CARBON
02001 #pragma unused (fs)
02002     return false;
02003 #else
02004     
02005     /*
02006     6/x/91 mao
02007     */
02008 
02009     tyvolinfo volinfo;
02010     
02011     if (!filegetfsvolumeinfo (fs, &volinfo))
02012         return (false);
02013         
02014     if (!volinfo.flejectable)
02015         return (false);
02016         
02017     return (!oserror (Eject (nil, (*fs).vRefNum)));
02018     #endif
02019 } /*ejectvol*/
02020 #endif
02021     
02022     
02023 boolean isejectable (const tyfilespec *fs, boolean *flejectable) {
02024     
02025     tyvolinfo volinfo;
02026     
02027     if (!filegetfsvolumeinfo (fs, &volinfo))
02028         return (false);
02029         
02030     *flejectable = volinfo.flejectable;
02031     
02032     return (true);
02033     } /*isejectable*/
02034 
02035     
02036 boolean getfreespace (const tyfilespec *fs, long *ctfreebytes) {
02037 
02038     /*
02039     6/x/91 mao
02040     */
02041 
02042     tyvolinfo volinfo;
02043     
02044     if (!filegetfsvolumeinfo (fs, &volinfo))
02045         return (false);
02046 
02047     *ctfreebytes = volinfo.ctfreebytes;
02048     
02049     return (true);
02050     } /*getfreespace*/
02051 
02052 
02053 static void volumeinfoerror (OSErr errnum) {
02054 
02055     bigstring bserr, bserrnum;
02056 
02057     copystring (BIGSTRING ("\x42" "Can't get volume information because an error of type ^0 occurred."), bserr);
02058 
02059     numbertostring (errnum, bserrnum);
02060 
02061     parsedialogstring (bserr, bserrnum, nil, nil, nil, bserr);
02062 
02063     shellerrormessage (bserr);
02064     }/*volumeinfoerror*/
02065 
02066 
02067 boolean langgetextendedvolumeinfo (const tyfilespec *fs, double *totalbytes, double *freebytes) {
02068 
02069     /*
02070     6.1b16 AR: Return number of free bytes and total number of bytes for the volume.
02071     This code is supposed to work flawlessly with volumes over 2 GB.
02072     
02073     For the Mac version, we delegate the actual work to XGetVInfo in MoreFilesExtras.h.
02074     
02075     For the Windows version, we use GetFreeDiskSpaceEx if available. Otherwise we fall
02076     back to GetFreeDiskSpace. According to MSDN info that's probably neccessary if we
02077     run on Win95 Release 1 which didn't support volume sizes over 2 GB.
02078     
02079     flsupportslargevolumes is initialized in filestartup in fileverbs.c. (Win32 only)
02080     */
02081 
02082     OSErr errnum = noErr;
02083     bigstring volname;
02084 #ifdef MACVERSION
02085     UInt64 ui64totalbytes, ui64freebytes;
02086     #if !TARGET_API_MAC_CARBON
02087         short vrefnum;
02088     #endif
02089 #endif
02090 
02091     *totalbytes = 0.0;
02092 
02093     *freebytes = 0.0;
02094 
02095     copystring (fsname(fs), volname);
02096 
02097 
02098 /*  JES 12/09/2002 -- 9.1b2 -- Don't do this test, since it fails on builds made with CW8
02099 
02100     if (!fileisvolume (fs)) {
02101     
02102         bigstring bserr;
02103 
02104         copystring ("\x45" "Can't get volume information because \"^0\" is not a valid volume name.", bserr);
02105 
02106         parsedialogstring (bserr, volname, nil, nil, nil, bserr);
02107 
02108         shellerrormessage (bserr);
02109         
02110         return (false);
02111         }
02112 */
02113 
02114 #ifdef MACVERSION
02115 
02116      /*
02117      2005-01-24 creedon - reversed free and total parameters to match FSGetVInfo and XGetVInfo functions
02118         < http://groups.yahoo.com/group/frontierkernel/message/846 >
02119     */
02120     
02121     #if TARGET_API_MAC_CARBON
02122         errnum = FSGetVInfo (fs->vRefNum, nil, &ui64freebytes, &ui64totalbytes);
02123     #else
02124         errnum = XGetVInfo (fs->vRefNum, nil, &vrefnum, &ui64freebytes, &ui64totalbytes);
02125     #endif
02126 
02127     if (errnum != noErr) {
02128         volumeinfoerror (errnum);
02129         return (false);
02130         }
02131 
02132     *totalbytes = (double) ui64totalbytes;
02133     *freebytes = (double) ui64freebytes;
02134 
02135 #endif
02136 
02137 
02138 #ifdef WIN95VERSION
02139 
02140     cleanendoffilename (volname);
02141     
02142     pushchar ('\\', volname);
02143     
02144     nullterminate (volname);
02145 
02146     if (flsupportslargevolumes) {
02147 
02148         ULARGE_INTEGER freeBytesAvailableToCaller, totalNumberOfBytes, totalNumberOfFreeBytes;
02149 
02150         if ((*adrGetDiskFreeSpaceEx) ((unsigned short *) stringbaseaddress (volname), &freeBytesAvailableToCaller,
02151                 &totalNumberOfBytes, &totalNumberOfFreeBytes)) {
02152 
02153             *totalbytes = (double) (LONGLONG) totalNumberOfBytes.QuadPart;
02154             
02155             *freebytes = (double) (LONGLONG) freeBytesAvailableToCaller.QuadPart;
02156             }
02157 
02158         else
02159             if (GetLastError () == ERROR_CALL_NOT_IMPLEMENTED)
02160                 flsupportslargevolumes = false;
02161         }
02162 
02163     if (!flsupportslargevolumes) {
02164 
02165         DWORD sectorsPerCluster, bytesPerSector, numberOfFreeClusters, totalNumberOfClusters;
02166         
02167         if (GetDiskFreeSpace (stringbaseaddress (volname), &sectorsPerCluster, &bytesPerSector,
02168                 &numberOfFreeClusters, &totalNumberOfClusters)) {
02169 
02170             double bytespercluster = (double) sectorsPerCluster * (double) bytesPerSector;
02171 
02172             *totalbytes = bytespercluster * (double) totalNumberOfClusters;
02173 
02174             *freebytes = bytespercluster * (double) numberOfFreeClusters;
02175             }
02176         }
02177 #endif
02178 
02179     return (true);
02180     }/*getextendedvolumeinfo*/
02181 
02182 
02183 boolean getvolumesize (const tyfilespec *fs, long *ctbytes) {
02184     
02185     tyvolinfo volinfo;
02186     
02187     if (!filegetfsvolumeinfo (fs, &volinfo))
02188         return (false);
02189     
02190     *ctbytes = volinfo.cttotalbytes;
02191     
02192     return (true);
02193     } /*getvolumesize*/
02194 
02195 
02196 boolean getvolumeblocksize (const tyfilespec *fs, long *ctbytes) {
02197     
02198     tyvolinfo volinfo;
02199     
02200     if (!filegetfsvolumeinfo (fs, &volinfo))
02201         return (false);
02202     
02203     *ctbytes = volinfo.blocksize;
02204     
02205     return (true);
02206     } /*getvolumeblocksize*/
02207     
02208     
02209 boolean filesonvolume (const tyfilespec *fs, long *ctfiles) {
02210 
02211     /*
02212     6/x/91 mao
02213     */
02214 
02215     tyvolinfo volinfo;
02216     
02217     if (!filegetfsvolumeinfo (fs, &volinfo))
02218         return (false);
02219     
02220     *ctfiles = volinfo.ctfiles;
02221     
02222     return (true);
02223     } /*filesonvolume*/
02224 
02225 
02226 boolean foldersonvolume (const tyfilespec *fs, long *ctfolders) {
02227     
02228     tyvolinfo volinfo;
02229         
02230     if (!filegetfsvolumeinfo (fs, &volinfo))
02231         return (false);
02232     
02233     *ctfolders = volinfo.ctfolders;
02234     
02235     return (true);
02236     } /*foldersonvolume*/
02237 
02238 
02239 boolean isvolumelocked (const tyfilespec *fs, boolean *fllocked) {
02240     
02241     /*
02242     6/x/91 mao
02243     */
02244     
02245     tyvolinfo volinfo;
02246     
02247     if (!filegetfsvolumeinfo (fs, &volinfo))
02248         return (false);
02249     
02250     *fllocked = volinfo.fllocked;
02251     
02252     return (true);
02253     } /*isvolumelocked*/
02254 
02255 
02256 boolean volumecreated (const tyfilespec *fs, unsigned long *createdate) {
02257     
02258     tyvolinfo volinfo;
02259     
02260     if (!filegetfsvolumeinfo (fs, &volinfo))
02261         return (false);
02262     
02263     *createdate = volinfo.timecreated;
02264     
02265     return (true);
02266     } /*volumecreated*/
02267 
02268 
02269 boolean lockvolume (const tyfilespec *fs, boolean fllock) {
02270 #ifdef MACVERSION
02271 #if TARGET_API_MAC_CARBON == 1
02272 #pragma unused (fs, fllock)
02273     //Code change by Timothy Paustian Sunday, June 25, 2000 9:19:49 PM
02274     //can't lock volumes in carbon.
02275     return false;
02276 #else
02277     short vnum;
02278     QHdrPtr vqtop;
02279     QElemPtr vqelem;
02280     
02281     vnum = (*fs).vRefNum;
02282     
02283     vqtop = GetVCBQHdr ();
02284     
02285     vqelem = (*vqtop).qHead;
02286     
02287     while (true) {
02288         
02289         if (((VCB *)vqelem)->vcbVRefNum == vnum) {
02290             
02291             if (fllock)
02292                 BitSet (&(*(VCB *)vqelem).vcbAtrb, 0);
02293             else
02294                 BitClr (&(*(VCB *)vqelem).vcbAtrb, 0);
02295             
02296             return (true);
02297             }
02298         
02299         if (vqelem == (*vqtop).qTail) { /*reached end of list -- shouldn't happen*/
02300             
02301             oserror (errorVolume); /*no such volume*/
02302             
02303             return (false);
02304             }
02305         
02306         vqelem = (*vqelem).qLink;
02307         
02308         }
02309 #endif
02310 #endif
02311 #ifdef WIN95VERSION
02312     return (false);
02313 #endif
02314     } /*lockvolume*/
02315 
02316 
02317 #ifdef MACVERSION
02318 
02319 boolean unmountvolume (const tyfilespec *fs) {
02320     
02321     /*
02322     12/5/91 dmb
02323     */
02324     
02325     return (!oserror (UnmountVol (nil, (*fs).vRefNum)));
02326     } /*unmountvolume*/
02327 
02328 
02329 boolean drivenumtovolname (short drivenum, bigstring bsvol) {
02330     
02331     HParamBlockRec pb;
02332     
02333     clearbytes (&pb, sizeof (pb));
02334     
02335     pb.volumeParam.ioNamePtr = bsvol;
02336     
02337     pb.volumeParam.ioVRefNum = drivenum;
02338     //Code change by Timothy Paustian Sunday, June 25, 2000 9:21:31 PM
02339     //Updated call for carbon
02340     return (PBHGetVInfoSync (&pb) == noErr);
02341     
02342     /*
02343     return (GetVInfo (drivenum, bsvol, &vnum, &freebytes) == noErr);
02344     */
02345     } /*drivenumtovolname*/
02346 
02347 
02348 static boolean hasdesktopmanager (short vnum) {
02349     
02350     GetVolParmsInfoBuffer volparms;
02351     HParamBlockRec pb;
02352     
02353     pb.volumeParam.ioVRefNum = vnum;
02354     
02355     pb.volumeParam.ioNamePtr = nil;
02356     
02357     pb.ioParam.ioBuffer = (Ptr) &volparms;
02358     
02359     pb.ioParam.ioReqCount = sizeof (volparms);
02360     
02361     if (PBHGetVolParmsSync (&pb) != noErr)
02362         return (false);
02363     
02364     return ((volparms.vMAttrib & (1 << bHasDesktopMgr)) != 0);
02365     } /*hasdesktopmanager*/
02366 
02367 
02368 #if 0
02369 
02370 static boolean getdesktopdatabasepath (short vnum, DTPBRec *dt) {
02371     
02372     if (!hasdesktopmanager (vnum))
02373         return (false);
02374     
02375     dt.ioVRefNum = vnum;
02376     
02377     return (PBDTGetPath (&dt) == noErr);
02378     } /*getdesktopdatabasepath*/
02379 
02380 #endif
02381 
02382 
02383 boolean getfilecomment (const tyfilespec *fs, bigstring bscomment) {
02384     
02385     /*
02386     12/5/91 dmb
02387     
02388     2.1b1 dmb: set reqCount; w/out it, works locally but not remotely
02389     */
02390     
02391     DTPBRec dt;
02392     
02393     clearbytes (&dt, sizeof (dt));
02394     
02395     setemptystring (bscomment); /*default return*/
02396     
02397     if (!surefile (fs))
02398         return (false);
02399     
02400     if (!hasdesktopmanager ((*fs).vRefNum))
02401         return (false);
02402     
02403     dt.ioVRefNum = (*fs).vRefNum;
02404     
02405     if (PBDTGetPath (&dt) != noErr)
02406         return (false);
02407     
02408     dt.ioNamePtr = (StringPtr) (*fs).name;
02409     
02410     dt.ioDirID = (*fs).parID;
02411     
02412     dt.ioDTBuffer = (Ptr) bscomment + 1;
02413     
02414     dt.ioDTReqCount = lenbigstring;
02415     
02416     if (PBDTGetCommentSync (&dt) != noErr)
02417         return (false);
02418     
02419     setstringlength (bscomment, dt.ioDTActCount);
02420     
02421     return (true);
02422     } /*getfilecomment*/
02423 
02424 
02425 boolean setfilecomment (const tyfilespec *fs, bigstring bscomment) {
02426     
02427     /*
02428     12/5/91 dmb
02429     */
02430     
02431     DTPBRec dt;
02432     
02433     clearbytes (&dt, sizeof (dt));
02434     
02435     if (!surefile (fs))
02436         return (false);
02437     
02438     if (!hasdesktopmanager ((*fs).vRefNum))
02439         return (false);
02440     
02441     dt.ioVRefNum = (*fs).vRefNum;
02442     
02443     if (PBDTGetPath (&dt) != noErr)
02444         return (false);
02445     
02446     dt.ioNamePtr = (StringPtr) (*fs).name;
02447     
02448     dt.ioDirID = (*fs).parID;
02449     
02450     dt.ioDTBuffer = (Ptr) bscomment + 1;
02451     
02452     dt.ioDTReqCount = stringlength (bscomment);
02453     
02454     if (PBDTSetCommentSync (&dt) != noErr)
02455         return (false);
02456     
02457     PBDTFlushSync (&dt);
02458     
02459     return (true);
02460     } /*setfilecomment*/
02461 
02462 
02463 static boolean index2label (short ixlabel, bigstring bslabel) {
02464     
02465     /*
02466     2006-04-24 creedon: use GetLabel instead of looking for resources that don't exists on Mac OS X
02467                    deleted old code see revision 1268
02468     */
02469     
02470     if ((ixlabel < 0) || (ixlabel > 7))
02471         return (false);
02472     
02473     RGBColor labelcolor; // we don't use the value we put into here
02474     
02475     if (GetLabel (ixlabel, &labelcolor, bslabel) != noErr)
02476         return (false); 
02477         
02478     return (true);
02479     } /* index2label */
02480 
02481 
02482 static boolean label2index (bigstring bslabel, short *ixlabel) {
02483     
02484     /*
02485     2006-04-24 creedon: use GetLabel instead of looking for resources that don't exists on Mac OS X
02486                    deleted old code see revision 1268
02487     */
02488     
02489     register short ix;
02490     RGBColor labelcolor; // we don't use the value we put into here
02491     bigstring bs;
02492     
02493     for (ix = 0; ix < 8; ++ix) {
02494         
02495         if (GetLabel (ix, &labelcolor, bs) != noErr)
02496         
02497             return (false);
02498             
02499         if (RelString (bslabel, bs, false, false) == 0) {
02500             
02501             *ixlabel = ix;
02502             
02503             return (true);
02504             }
02505         }
02506     
02507     return (false);
02508     } /* label2index */
02509 
02510 
02511 boolean getfilelabel (const tyfilespec *fs, bigstring bslabel) {
02512     
02513     tyfileinfo info;
02514     
02515     if (!filegetinfo (fs, &info))
02516         return (false);
02517     
02518     return (index2label (info.ixlabel, bslabel));
02519     } /*getfilelabel*/
02520 
02521 
02522 boolean setfilelabel (const tyfilespec *fs, bigstring bslabel) {
02523     
02524     /*
02525     2006-04-24 creedon: factored most of the code into setfilelabelindex function
02526                    code deleted see revision 1268
02527     */
02528     
02529     short ixlabel;
02530     
02531     if (!label2index (bslabel, &ixlabel))
02532         return (false);
02533     
02534     return (setfilelabelindex (fs, ixlabel, false));
02535     } /* setfilelabel */
02536 
02537 
02538 boolean mountvolume (bigstring volumepath, bigstring username, bigstring password) {
02539     
02540     /*
02541     2/20/92 dmb: initial code.  this really should be "mount server volume";
02542     mounting a volume is something else, really.
02543     
02544     4/16/92 dmb: check for already-mounted error code, and treat it as no error.
02545     
02546     2.1b12 dmb: if volumepath is improperly formed, generate informative message 
02547     instead of failing silently
02548     */
02549     
02550     AFPVolMountInfo info;
02551     bigstring bsitem;
02552     short ixdata;
02553     ParamBlockRec pb;
02554     OSErr errcode;
02555     
02556     clearbytes (&info, sizeof (info));
02557     
02558     ixdata = (char *) &info.AFPData - (char *) &info;
02559     
02560     info.media = AppleShareMediaType;
02561     
02562     if (isemptystring (username))
02563         info.uamType = kNoUserAuthentication;
02564     else
02565         info.uamType = kPassword;
02566     
02567     
02568     firstword (volumepath, ':', bsitem); /*get the zone name*/
02569     
02570     info.zoneNameOffset = ixdata;
02571     
02572     copystring (bsitem, (ptrstring) &info + ixdata);
02573     
02574     ixdata += stringsize (bsitem);
02575     
02576     
02577     nthword (volumepath, 2, ':', bsitem); /*get the server name*/
02578     
02579     info.serverNameOffset = ixdata;
02580     
02581     copystring (bsitem, (ptrstring) &info + ixdata);
02582     
02583     ixdata += stringsize (bsitem);
02584     
02585     
02586     nthword (volumepath, 3, ':', bsitem); /*get the volume name*/
02587     
02588     info.volNameOffset = ixdata;
02589     
02590     copystring (bsitem, (ptrstring) &info + ixdata);
02591     
02592     ixdata += stringsize (bsitem);
02593     
02594     
02595     info.userNameOffset = ixdata; /*set the user name*/
02596     
02597     copystring (username, (ptrstring) &info + ixdata);
02598     
02599     ixdata += stringsize (username);
02600     
02601     
02602     info.userPasswordOffset = ixdata; /*set the password*/
02603     
02604     copystring (password, (ptrstring) &info + ixdata);
02605     
02606     ixdata += stringsize (password);
02607     
02608     
02609     info.length = ixdata;
02610     
02611     
02612     clearbytes (&pb, sizeof (pb));
02613     
02614     pb.ioParam.ioBuffer = (Ptr) &info;
02615     
02616     errcode = PBVolumeMount (&pb);
02617     
02618     if (errcode == -5062) /*volume is already mounted*/
02619         return (true);
02620     
02621     return (!oserror (errcode));
02622     } /*mountvolume*/
02623 
02624 
02625 short getfilelabelindex (const tyfilespec *fs, short *ixlabel) {
02626 
02627     /*
02628     2006-04-23 creedon: created, cribbed from getfilelabel function
02629     */
02630     
02631     tyfileinfo info;
02632     short maptouserinterfaceindex [8] = {0, 7, 4, 6, 5, 3, 1, 2};
02633     
02634     if (!filegetinfo (fs, &info))
02635         return (false);
02636     
02637     *ixlabel = maptouserinterfaceindex [info.ixlabel];
02638     
02639     return (true);
02640     } /* getfilelabelindex */
02641 
02642 
02643 boolean setfilelabelindex (const tyfilespec *fs, short ixlabel, boolean flmapfromuserinterfaceindex) {
02644 
02645     /*
02646     2006-04-24 creedon: created, cribbed from setfilelabel function
02647     */
02648     
02649     CInfoPBRec pb;
02650     register short flags;
02651 
02652     if ((ixlabel < 0) || (ixlabel > 7))
02653         return (false);
02654     
02655     if (!getmacfileinfo (fs, &pb)) 
02656         return (false);
02657     
02658     flags = pb.hFileInfo.ioFlFndrInfo.fdFlags;
02659     
02660     flags &= 0xFFF1; // clear out old index
02661     
02662     if (flmapfromuserinterfaceindex) {
02663         short mapfromuserinterfaceindex [8] = {0, 6, 7, 5, 2, 4, 3, 1};
02664 
02665         ixlabel = mapfromuserinterfaceindex [ixlabel];
02666         }
02667     
02668     flags |= ixlabel << 1; // slam in new index
02669     
02670     pb.hFileInfo.ioFlFndrInfo.fdFlags = flags;
02671     
02672     return (setmacfileinfo (fs, &pb));
02673     } /* setfilelabelindex */
02674 
02675 #endif
02676 
02677 
02678 #ifdef NEWFILESPECTYPE
02679 boolean fileparsevolname (bigstring bspath, long *vnum, bigstring bsvol)
02680 #else
02681 boolean fileparsevolname (bigstring bspath, short *vnum, bigstring bsvol)
02682 #endif
02683     {
02684     /*
02685     convert a full path, which might contain a volume name at the beginning
02686     to a path with no volume name, and it's associated volume number in vnum.
02687     
02688     example: "RoverŠ:MORE Work" will return with bspath = "MORE Work" and
02689     vnum = -2 (the Macintosh vrefnum for the second mounted drive).  
02690     
02691     this combination of information plugs nicely into a lot of the file 
02692     manager routines.
02693     
02694     2.1b8 dmb: handle drive numbers
02695     
02696     2.1b11 dmb: return the vol name in bsvol if non-nil, along with the vnum
02697 
02698     5.0.2 rab: initialize ix to zero
02699     */
02700     
02701 #ifdef MACVERSION
02702     
02703     short ix = 1;
02704     bigstring bsvolname;
02705     HParamBlockRec pb;
02706     short drivenum;
02707     bigstring bs;
02708     OSErr err;
02709     
02710     copystring (bspath, bs); /*work on a copy*/
02711     
02712     if (isemptystring (bs))
02713         return (false);
02714     
02715     if (!scanstring (chpathseparator, bs, &ix)) { /*no colon, the whole thing is a volname*/
02716         
02717         copystring (bs, bsvolname);
02718         
02719         pushchar (chpathseparator, bsvolname);
02720         
02721         setemptystring (bs);
02722         }
02723     else {
02724         midstring (bs, 1, ix, bsvolname); /*pick off the vol name and the colon*/
02725         
02726         deletestring (bs, 1, ix);
02727         }
02728     
02729     clearbytes (&pb, sizeof (pb));
02730     
02731     pb.volumeParam.ioNamePtr = bsvolname;
02732     
02733     pb.volumeParam.ioVolIndex = -1; /*force him to use the name pointer only*/
02734     //Code change by Timothy Paustian Sunday, June 25, 2000 9:21:59 PM
02735     //Updated call for carbon
02736     err = PBHGetVInfoSync (&pb);
02737     
02738     if (err != noErr) {
02739         
02740         setstringlength (bsvolname, stringlength (bsvolname) - 1); /*pop last char -- the colon*/
02741         
02742         if (isallnumeric (bsvolname) && stringtoshort (bsvolname, &drivenum)) { /*it's a number*/
02743             
02744             /*
02745             pb.volumeParam.ioNamePtr = nil;
02746             */
02747             
02748             pb.volumeParam.ioVRefNum = drivenum;
02749             //Code change by Timothy Paustian Sunday, June 25, 2000 9:24:35 PM
02750             //updated for carbon
02751             err = PBHGetVInfoSync (&pb);
02752             }
02753         
02754         if (err != noErr)
02755             return (false);
02756         }
02757     
02758     *vnum = pb.volumeParam.ioVRefNum;
02759     
02760     if (bsvol != nil)
02761         copystring (bsvolname, bsvol);
02762 #endif
02763     
02764 #ifdef WIN95VERSION
02765     bigstring bsvolname, bs;
02766     short ix = 0;
02767 
02768     *vnum = 0;
02769     copystring (bspath, bs); /*work on a copy*/
02770     
02771     if (isemptystring (bs))
02772         return (false);
02773     
02774     if (!scanstring (':', bs, &ix)) { /*no colon, No volume?*/
02775         return (false);     
02776         }
02777     else {
02778         midstring (bs, 1, ix, bsvolname); /*pick off the vol name and the colon*/
02779         
02780         deletestring (bs, 1, ix);
02781         }
02782     
02783     if (bsvol != nil)
02784         {
02785         copystring (bsvolname, bsvol);
02786         
02787         nullterminate (bsvol);
02788         }
02789 
02790 #endif
02791     return (true);
02792     } /*fileparsevolname*/
02793 
02794 
02795 #ifdef MACVERSION
02796 
02797 boolean fileresolvealias (tyfilespec *fs) {
02798     
02799     Boolean flfolder, flalias;
02800     OSErr err;
02801     
02802     setoserrorparam ((ptrstring) (*fs).name);
02803     
02804     err = ResolveAliasFile (fs, true, &flfolder, &flalias);
02805     
02806     return (!oserror (err));
02807     } /*fileresolvealias*/
02808 #endif
02809 
02810 
02811 boolean filefrompath (bigstring path, bigstring fname) {
02812     
02813     /*
02814     return all the characters to the right of the colon in the path.
02815     
02816     example: "Work Disk #1:MORE Work:Status Center" returns "Status Center".
02817     */
02818 
02819     #ifdef MACVERSION   
02820         return (lastword (path, chpathseparator, fname));
02821     #endif
02822 
02823     #ifdef WIN95VERSION
02824         char fn[300];
02825         char * fileptr;
02826         tyfilespec fs;
02827         
02828         copystring (path, fsname (&fs));
02829 
02830         if (stringlength (path) >= 255) {       /* RAB 4/27/98 fix for to long a filename conversion attempt*/
02831             setemptystring (fname);
02832             return (true);
02833             }
02834 
02835         if (isemptystring (path) || fileisvolume (&fs)) {
02836             
02837             copystring (path, fname);
02838 
02839             return (true);
02840             }
02841 
02842         nullterminate (path);
02843         
02844         GetFullPathName (stringbaseaddress(path), 298, fn, &fileptr);   
02845 
02846         /*the comparison of fileptr within the legal range of fn is a kludge
02847         but if fixes GetFullPathName which goes wild on some strings and 
02848         there is no other way of determining that it has gone wild.
02849         RAB 4/27/98 */
02850 
02851         if ((fileptr == NULL) || (fileptr < fn) || (fileptr > (fn + 298)))
02852             setemptystring (fname);
02853         else
02854             copyctopstring (fileptr, fname);
02855             
02856         //  strcpy (stringbaseaddress(fname), fileptr);
02857         //  setstringlength (fname, strlen (fileptr));
02858         
02859         return (true);
02860     #endif
02861     } /*filefrompath*/
02862 
02863 
02864 boolean folderfrompath (bigstring path, bigstring folder) {
02865     
02866     /*
02867     return all the characters to the left of the colon, and the colon.
02868     
02869     example: "Work Disk #1:MORE Work:Status Center" returns "Work Disk #1:MORE Work:".
02870 
02871     5.0.2 dmb: call filefrompath instead of lastword to maintain symmetry on Win
02872     */
02873     
02874     bigstring bs;
02875     
02876     filefrompath (path, bs); /*kind of inefficient, but ensures symmetry*/
02877     
02878     copystring (path, folder);
02879     
02880     setstringlength (folder, stringlength (folder) - stringlength (bs));
02881     
02882     return (true);
02883     } /*folderfrompath*/
02884 
02885 
02886 #ifdef MACVERSION
02887 boolean getfileparentfolder (const tyfilespec *fs, tyfilespec *fsparent) {
02888     
02889     long dirid = (*fs).parID;
02890     
02891     if (isemptystring ((*fs).name) || (dirid == fsRtParID)) { /*null or disk spec*/
02892         
02893         clearbytes (fsparent, sizeof (tyfilespec));
02894         
02895         return (true);
02896         }
02897     
02898     return (!oserror (FSMakeFSSpec ((*fs).vRefNum, dirid, nil, fsparent)));
02899     } /*getfileparentfolder*/
02900 
02901 
02902 #if 0
02903 
02904 boolean getdefaultpath (bigstring bs) {
02905 
02906     ParamBlockRec pb;
02907     OSErr errcode;
02908     
02909     setstringlength (bs, 0);
02910     
02911     clearbytes (&pb, sizeof (pb));
02912         
02913     errcode = PBGetVolSync (&pb);
02914     
02915     if (oserror (errcode))
02916         return (false);
02917     
02918     return (filegetpath (pb.fileParam.ioVRefNum, bs));
02919     } /*getdefaultpath*/
02920 
02921 #endif
02922 
02923 
02924 #endif
02925 
02926 boolean movefile (const tyfilespec *fs, const tyfilespec *fsto) {
02927 #ifdef MACVERSION
02928     /*
02929     moves a file or folder speied in fs to the fcifolder specified by fsto.
02930     make sure that the new path is really a folder.
02931     
02932     8/2/91 dmb: corrected error message params
02933     
02934     3.0.2 dmb: setoserrorparam to source file before catmove
02935     */
02936 
02937     CInfoPBRec pb; 
02938     
02939     setfserrorparam (fsto); /*in case error message takes a filename parameter*/
02940     
02941     if (!getmacfileinfo (fsto, &pb))
02942         return (false);
02943     
02944     if (!pb.dirInfo.ioFlAttrib & ioDirMask) { /*if newpath isn't a folder, get out*/
02945         
02946         oserror (errorParam); /*not the best error message, but...*/
02947         
02948         return (false);
02949         }
02950     
02951     setfserrorparam (fs); /*3.0.2*/
02952     
02953     return (!oserror (FSpCatMove (fs, fsto)));
02954 #endif
02955     
02956 #ifdef WIN95VERSION
02957     char fn1[300];
02958     char fn2[300];
02959     boolean fl;
02960     bigstring filename;
02961 
02962     copystring (fsname (fs), fn1);
02963     copystring (fsname (fsto), fn2);
02964 
02965     if (endswithpathsep (fn1))
02966         setstringlength (fn1, stringlength (fn1) - 1);
02967 
02968     nullterminate (fn1);
02969     nullterminate (fn2);
02970     
02971     if (!fileisfolder (fsto, &fl))
02972         return (false);
02973     
02974     if (fl) {
02975         filefrompath (fn1, filename);
02976         
02977         cleanendoffilename(fn2);
02978         
02979         appendcstring (fn2, "\\");
02980         
02981         pushstring (filename, fn2);
02982         
02983         nullterminate (fn2);
02984         }
02985 
02986     if (MoveFile (stringbaseaddress (fn1), stringbaseaddress(fn2)))
02987         return (true);
02988 
02989     winfileerror (fs);
02990 
02991     return (false);
02992 #endif
02993     } /*movefile*/
02994 
02995 
02996 void filenotfounderror (bigstring bs) {
02997     
02998     /*
02999     generate a "file not found" or a "folder not found" error
03000     */
03001     
03002     OSErr errcode;
03003     
03004     setoserrorparam (bs);
03005 #ifdef MACVERSION   
03006     if (lastchar (bs) == chpathseparator)
03007         errcode = errorDirNotFound;
03008     else
03009         errcode = errorFileNotFound;
03010 #endif
03011 #ifdef WIN95VERSION
03012     errcode = errorFileNotFound;
03013 #endif
03014     oserror (errcode);
03015     } /*filenotfounderror*/
03016 
03017 
03018 boolean surefile (const tyfilespec *fs) {
03019     
03020     boolean flfolder;
03021     
03022     if (fileexists (fs, &flfolder))
03023         return (true);
03024     
03025     filenotfounderror ((ptrstring) fsname (fs));
03026     
03027     return (false);
03028     } /*surefile*/
03029 
03030 
03031 boolean renamefile (const tyfilespec *fs, bigstring bsnew) {
03032 
03033     #ifdef MACVERSION   
03034         /*
03035         we expect a full path specifying the file to be renamed.  bsnew must not
03036         hold a path -- it's the new name of the file.  the Mac OS wants a full path
03037         for the new name, it makes no sense to us.  but we are obedient!
03038         
03039         6/x/91 mao: PBHRename used, will now rename folders
03040         
03041         7/30/91 dmb: reworked code to work properly with volumes and folder paths 
03042         ending in colons
03043         
03044         9/4/91 dmb: only look at filename part of bsnew
03045         
03046         12/1/92 dmb: if bsnew is a valid path (same folder), use it as is. this 
03047         fixes bug when it's a path to a folder.
03048         */
03049         
03050         if (!surefile (fs)) /*file doesn't exist -- catch error*/
03051             return (false);
03052         
03053         filefrompath (bsnew, bsnew);
03054         
03055         setoserrorparam (bsnew); /*only likely errors from here on relate to new name*/
03056         
03057         if (oserror (FSpRename (fs, bsnew)))
03058             return (false);
03059         
03060         touchparentfolder (fs);
03061         
03062         return (true);
03063     #endif
03064 
03065     #ifdef WIN95VERSION
03066         char fn [300];
03067         bigstring bsfolder;
03068 
03069         if (!surefile (fs)) /*file doesn't exist -- catch error*/
03070             return (false);
03071         
03072         filefrompath (bsnew, bsnew);
03073         
03074         copystring (fsname (fs), fn);
03075 
03076         nullterminate (fn);
03077         
03078         folderfrompath (fn, bsfolder);
03079         
03080         pushstring (bsnew, bsfolder);
03081 
03082         nullterminate (bsfolder);
03083 
03084         if (MoveFile (stringbaseaddress (fn), stringbaseaddress (bsfolder)))
03085             return (true);
03086         
03087         winfileerror (fs);
03088 
03089         return (false);
03090     #endif
03091     } /*renamefile*/
03092 
03093 
03094 boolean lockfile (const tyfilespec *fs) {
03095 
03096     #ifdef MACVERSION   
03097         setfserrorparam (fs); /*in case error message takes a filename parameter*/
03098         
03099         return (!oserror (FSpSetFLock (fs)));
03100     #endif
03101 
03102     #ifdef WIN95VERSION
03103         DWORD attr;
03104         
03105         attr = GetFileAttributes (stringbaseaddress (fsname (fs)));
03106 
03107         if (attr == 0xFFFFFFFF)
03108             goto error;
03109 
03110         attr = attr | FILE_ATTRIBUTE_READONLY;
03111 
03112         if (SetFileAttributes (stringbaseaddress (fsname (fs)), attr))
03113             return (true);
03114 
03115         error:
03116 
03117         winfileerror (fs);
03118 
03119         return (false);
03120     #endif
03121     } /*lockfile*/
03122 
03123 
03124 boolean unlockfile (const tyfilespec *fs) {
03125 #ifdef MACVERSION   
03126     setfserrorparam (fs);
03127     
03128     return (!oserror (FSpRstFLock (fs)));
03129 #endif
03130 
03131 #ifdef WIN95VERSION
03132     DWORD attr;
03133     
03134     attr = GetFileAttributes (stringbaseaddress (fsname (fs)));
03135 
03136     if (attr == 0xFFFFFFFF)
03137         goto error;
03138 
03139     attr = attr & ~FILE_ATTRIBUTE_READONLY;
03140 
03141     if (SetFileAttributes (stringbaseaddress(fsname (fs)), attr))
03142         return (true);
03143 
03144     error:
03145 
03146     winfileerror (fs);
03147     
03148     return (false);
03149 #endif
03150     } /*unlockfile*/
03151 
03152 
03153 boolean newfolder (const tyfilespec *fs) {
03154 #ifdef MACVERSION   
03155     /*
03156     2.1b2 dmb: use filespecs.
03157     */
03158     
03159     long dirid;
03160     
03161     setfserrorparam (fs);
03162     
03163     return (!oserror (FSpDirCreate (fs, smSystemScript, &dirid)));
03164 #endif
03165 
03166 #ifdef WIN95VERSION
03167     if (CreateDirectory (stringbaseaddress (fsname (fs)), NULL))
03168         return (true);
03169     
03170     winfileerror (fs);
03171 
03172     return (false);
03173 #endif
03174     } /*newfolder*/
03175 
03176 
03177 boolean newfile (const tyfilespec *fs, OSType creator, OSType filetype) {
03178 #ifdef MACVERSION   
03179     setfserrorparam (fs);
03180     
03181     return (!oserror (FSpCreate (fs, creator, filetype, smSystemScript)));
03182 #endif
03183 
03184 #ifdef WIN95VERSION
03185     HANDLE f;
03186     char fn[300];
03187 
03188     copystring (fsname (fs), fn);
03189     
03190     nullterminate (fn);
03191     
03192     f = CreateFile (stringbaseaddress(fn), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW,
03193         FILE_ATTRIBUTE_NORMAL, NULL);
03194 
03195     if (f == INVALID_HANDLE_VALUE) {
03196         
03197         winfileerror (fs);
03198 
03199         return (false);
03200         }
03201 
03202     verify (CloseHandle (f));
03203     return (true);
03204 #endif
03205     } /*newfile*/
03206 
03207 
03208 #ifdef MACVERSION
03209 
03210 boolean getfullfilepath (bigstring bspath) {
03211     
03212     FSSpec fs;
03213     
03214     setoserrorparam (bspath); /*in case error message takes a filename parameter*/
03215     
03216     if (oserror (FSMakeFSSpec (0, 0, bspath, &fs)))
03217         return (false);
03218     
03219     return (filespectopath (&fs, bspath));
03220     } /*getfullfilepath*/
03221 
03222 
03223 boolean filemakespec (short vnum, long dirid, bigstring fname, ptrfilespec pfs) {
03224 
03225     OSErr ec;
03226     
03227     ec = FSMakeFSSpec (vnum, dirid, fname, pfs);
03228     
03229     return ((ec == noErr) || (ec == fnfErr));
03230     } /*filemakespec*/
03231 
03232 #endif /*MACVERSION*/
03233 
03234 
03235 boolean initfile (void) {
03236 
03237     /*
03238     call this before you do any setvol's.
03239     
03240     get me the volume id of the application that's running.
03241     
03242     useful for opening data files that are located in the same folder as
03243     the application itself.
03244     
03245     11/8/90 dmb: new implementation
03246     */
03247     
03248     #ifdef MACVERSION
03249     
03250     initfiledialog ();
03251     
03252     #endif
03253     
03254     #ifdef flsystem6
03255     
03256     GetVol (nil, &applicationvolnum);
03257     
03258     #endif
03259 
03260 #ifdef MACVERSION
03261     #ifdef flcomponent
03262     
03263     #if !TARGET_API_MAC_CARBON
03264     RememberA5 ();
03265     #endif /*for hook*/
03266     
03267     #endif
03268     
03269     applicationresnum = CurResFile ();
03270 #endif  
03271     return (true);
03272     } /*initfile*/
03273 
03274 
03275 boolean findapplication (OSType creator, tyfilespec *fsapp) {
03276     
03277     /*
03278     2006-04-10 creedon: deleted old code, see revision 1246 for old code
03279     
03280     2006-04-09 creedon: use LSFindApplicationForInfo if available
03281     
03282     5.0.1 dmb: implemented for Win using the registry
03283 
03284     2.1b11 dmb: loop through all files in each db if necessary to find one that's actually an application
03285 
03286     9/7/92 dmb: make two passes, skipping volumes mounted with a foreign 
03287     file system the first time through. note: if this turns out not to be 
03288     the best criteria, we could check for shared volumes instead by testing  
03289     vMLocalHand in hasdesktopmanager.
03290     
03291     also: since we don't maintain the desktop DB when we delete files, we 
03292     need to verify that the file we locate still exists. added fileexists 
03293     call before returning true.
03294     
03295     12/5/91 dmb
03296     */
03297     
03298     #ifdef MACVERSION
03299 
03300          if ((UInt32) LSFindApplicationForInfo == (UInt32) kUnresolvedCFragSymbolAddress)
03301             return (false);
03302         
03303         FSRef myRef;
03304         
03305         if (LSFindApplicationForInfo (creator, NULL, NULL, &myRef, NULL) != noErr)
03306             return (false);
03307                 
03308         if (FSRefMakeFSSpec (&myRef, fsapp) != noErr)
03309             return (false);
03310                 
03311         return (true);
03312     
03313     #endif /* MACVERSION */
03314 
03315     #ifdef WIN95VERSION
03316 
03317         byte bsextension [8];
03318         bigstring bsregpath, bsoptions;
03319 
03320         ostypetostring (creator, bsextension);
03321 
03322         poptrailingwhitespace (bsextension);
03323 
03324         insertchar ('.', bsextension);
03325         
03326         pushchar (chnul, bsextension);
03327         
03328         // copyctopstring ("software\\Microsoft\\Windows\\CurrentVersion", bsregpath);
03329 
03330         if (!getRegKeyString ((Handle) HKEY_CLASSES_ROOT, bsextension, NULL, bsregpath))
03331             return (false);
03332         
03333         pushstring ("\x13\\shell\\open\\command", bsregpath);
03334 
03335         if (!getRegKeyString ((Handle) HKEY_CLASSES_ROOT, bsregpath, NULL, bsregpath))
03336             return (false);
03337         
03338         if (getstringcharacter (bsregpath, 0) == '"') {
03339             
03340             popleadingchars (bsregpath, '"');
03341 
03342             firstword (bsregpath, '"', bsregpath);
03343             }
03344         else {
03345             
03346             lastword (bsregpath, ' ', bsoptions);
03347 
03348             if (stringlength (bsoptions) < stringlength (bsregpath))
03349                 deletestring (bsregpath, stringlength (bsregpath) - stringlength (bsoptions) + 1, stringlength (bsoptions));
03350             }
03351         
03352         return (pathtofilespec (bsregpath, fsapp));
03353 
03354     #endif /* WIN95VERSION */
03355 
03356     } /* findapplication */
03357 

Generated on Wed May 31 18:19:47 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6