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