Version:
~ [ 10.0 ] ~
** Warning: Cannot open xref database.
1
2 /* $Id: file.c,v 1.4 2005/01/11 22:48:05 andreradke 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 MACVERSION
32 #if TARGET_API_MAC_CARBON
33 #include "MoreFilesX.h"
34 #else
35 #include "MoreFilesExtras.h"
36 #endif
37 #endif
38
39 #include "filealias.h"
40 #include "cursor.h"
41 #include "dialogs.h"
42 #include "error.h"
43 #include "mac.h"
44 #include "memory.h"
45 #include "ops.h"
46 #include "quickdraw.h"
47 #include "resources.h"
48 #include "strings.h"
49 #include "frontierwindows.h"
50 #include "file.h"
51 #include "shell.h"
52 #include "shell.rsrc.h"
53 #include "langinternal.h" /*for langbackgroundtask*/
54
55
56 #ifdef MACVERSION
57 #ifdef flcomponent
58
59 #include "SetUpA5.h"
60
61 #endif
62 #endif
63
64
65
66 boolean equalfilespecs (const tyfilespec *fs1, const tyfilespec *fs2) {
67
68 /*
69 5.0a25 dmb: until we set the volumeID to zero for all Win fsspecs,
70 we must not compare them here
71 */
72
73 #ifdef MACVERSION
74 if ((*fs1).vRefNum != (*fs2).vRefNum)
75 return (false);
76
77 if ((*fs1).parID != (*fs2).parID)
78 return (false);
79
80 return (equalstrings ((ptrstring) fsname (fs1), (ptrstring) fsname (fs2)));
81 #endif
82 #ifdef WIN95VERSION
83 //if ((*fs1).volumeID != (*fs2).volumeID)
84 // return (false);
85
86 return (lstrcmp(fsname (fs1), fsname (fs2)) == 0);
87 #endif
88 } /*equalfilespecs*/
89
90
91 boolean filesetposition (hdlfilenum fnum, long position) {
92
93 /*
94 5.0.2b6 dmb: report errors
95 */
96
97 #ifdef MACVERSION
98 return (!oserror (SetFPos (fnum, fsFromStart, position)));
99 #endif
100
101 #ifdef WIN95VERSION
102 if (SetFilePointer (fnum, position, NULL, FILE_BEGIN) == -1L) {
103
104 winerror ();
105
106 return (false);
107 }
108
109 return (true);
110 #endif
111 } /*filesetposition*/
112
113
114 boolean filegetposition (hdlfilenum fnum, long *position) {
115
116 #ifdef MACVERSION
117 return (!oserror (GetFPos (fnum, position)));
118 #endif
119
120 #ifdef WIN95VERSION
121 *position = SetFilePointer (fnum, 0L, NULL, FILE_CURRENT);
122
123 if (*position == -1L) {
124
125 winerror ();
126
127 return (false);
128 }
129
130 return (true);
131 #endif
132 } /*filegetposition*/
133
134
135 boolean filegeteof (hdlfilenum fnum, long *position) {
136
137 #ifdef MACVERSION
138 /*
139 6/x/91 mao
140 */
141
142 return (!oserror (GetEOF (fnum, position)));
143 #endif
144
145 #ifdef WIN95VERSION
146 long origpos;
147
148 filegetposition (fnum, &origpos);
149
150 *position = SetFilePointer (fnum, 0L, NULL, FILE_END);
151
152 filesetposition (fnum, origpos);
153
154 if (*position == -1L) {
155
156 winerror ();
157
158 return (false);
159 }
160
161 return (true);
162 #endif
163 } /*filegeteof*/
164
165
166 boolean fileseteof (hdlfilenum fnum, long position) {
167
168 /*
169 5.0.2b6 dmb: report errors
170 */
171
172 #ifdef MACVERSION
173 return (!oserror (SetEOF (fnum, position)));
174 #endif
175
176 #ifdef WIN95VERSION
177 long currentPosition;
178
179 currentPosition = SetFilePointer (fnum, 0L, NULL, FILE_CURRENT);
180
181 if (currentPosition == -1L)
182 goto error;
183
184 if (SetFilePointer (fnum, position, NULL, FILE_BEGIN) == -1L)
185 goto error;
186
187 if (!SetEndOfFile (fnum))
188 goto error;
189
190 if (SetFilePointer (fnum, currentPosition, NULL, FILE_BEGIN) == -1L)
191 goto error;
192
193 return (true);
194
195 error:
196 winerror ();
197
198 return (false);
199 #endif
200 } /*fileseteof*/
201
202
203 long filegetsize (hdlfilenum fnum) {
204
205 /*
206 get the size of a file that's already open.
207 */
208
209 #ifdef MACVERSION
210 long filesize;
211
212 if (GetEOF (fnum, &filesize) != noErr)
213 filesize = 0;
214
215 return (filesize);
216 #endif
217
218 #ifdef WIN95VERSION
219 long filesize;
220
221 filesize = GetFileSize (fnum, NULL);
222 if (filesize == -1L)
223 filesize = 0L;
224
225 return (filesize);
226 #endif
227 } /*filegetsize*/
228
229
230 boolean filetruncate (hdlfilenum fnum) {
231
232 return (fileseteof (fnum, 0L));
233 } /*filetruncate*/
234
235
236 boolean filewrite (hdlfilenum fnum, long ctwrite, void *buffer) {
237
238 /*
239 write ctwrite bytes from buffer to the current position in file number
240 fnum. return true iff successful.
241 */
242
243 if (ctwrite > 0) {
244
245 #ifdef MACVERSION
246 if (oserror (FSWrite (fnum, &ctwrite, buffer)))
247 return (false);
248 #endif
249
250 #ifdef WIN95VERSION
251 DWORD numberBytesWritten;
252
253 if (WriteFile (fnum, buffer, ctwrite, &numberBytesWritten, NULL)) {
254
255 if ((DWORD)ctwrite == numberBytesWritten)
256 return (true);
257 }
258
259 winerror();
260
261 return (false);
262 #endif
263 }
264
265 return (true);
266 } /*filewrite*/
267
268
269 boolean filereaddata (hdlfilenum fnum, long ctread, long *ctactual, void *buffer) {
270
271 /*
272 lower level than fileread, we can read less than the number of
273 bytes requested.
274 */
275
276 *ctactual = ctread;
277
278 if (ctread > 0) {
279
280 #ifdef MACVERSION
281 OSErr ec = FSRead (fnum, ctactual, buffer);
282
283 if (ec != noErr && ec != eofErr) {
284
285 oserror (ec);
286
287 return (false);
288 }
289 #endif
290
291 #ifdef WIN95VERSION
292 if (!ReadFile (fnum, buffer, ctread, ctactual, NULL)) {
293
294 winerror ();
295
296 return (false);
297 }
298 #endif
299 }
300
301 return (true);
302 } /*filereaddata*/
303
304
305 boolean fileread (hdlfilenum fnum, long ctread, void *buffer) {
306
307 /*
308 read ctread bytes from the current position in file number fnum into
309 the buffer. return true iff successful.
310 */
311
312 long ctactual;
313
314 if (!filereaddata (fnum, ctread, &ctactual, buffer))
315 return (false);
316
317 if (ctactual < ctread) {
318
319 #ifdef MACVERSION
320 oserror (eofErr);
321 #endif
322 #ifdef WIN95VERSION
323 oserror (ERROR_HANDLE_EOF);
324 #endif
325
326 return (false);
327 }
328
329 return (true);
330 } /*fileread*/
331
332
333 boolean filegetchar (hdlfilenum fnum, char *ch) {
334
335 /*
336 long pos;
337
338 if (!filegetposition (fnum, &pos))
339 return (false);
340
341 if (pos >= filegetsize (fnum)) {
342
343 *fleof = true;
344
345 return (true);
346 }
347
348 *fleof = false;
349 */
350
351 return (fileread (fnum, (long) 1, ch));
352 } /*filegetchar*/
353
354
355 boolean fileputchar (hdlfilenum fnum, char ch) {
356
357 return (filewrite (fnum, (long) 1, &ch));
358 } /*fileputchar*/
359
360
361 boolean filewritehandle (hdlfilenum fnum, Handle h) {
362
363 /*
364 write the indicated handle to the open file indicated by fnum at the
365 current position in the file.
366 */
367
368 return (filewrite (fnum, gethandlesize (h), *h));
369 } /*filewritehandle*/
370
371
372 /*
373 static boolean filereadhandlebytes (short fnum, long ctbytes, Handle *hreturned) {
374
375 /%
376 6/x/91 mao
377 this one is parallel to filewritehandle
378 %/
379
380 register Handle h;
381
382 if (!newclearhandle (ctbytes, hreturned))
383 return (false);
384
385 h = *hreturned; /%copy into register%/
386
387 if (oserror (fileread (fnum, ctbytes, *h))) {
388
389 disposehandle (h);
390
391 return (false);
392 }
393
394 return (true);
395 } /%filereadhandlebytes%/
396 */
397
398
399 boolean filereadhandle (hdlfilenum fnum, Handle *hreturned) {
400
401 /*
402 not exactly parallel to filewritehandle. we read the whole file into the
403 indicated handle and return true if it worked.
404 */
405
406 register long filesize;
407 register Handle h;
408
409 filesize = filegetsize (fnum);
410
411 if (!newclearhandle (filesize, hreturned))
412 return (false);
413
414 h = *hreturned; /*copy into register*/
415
416 if (!fileread (fnum, filesize, *h)) {
417
418 disposehandle (h);
419
420 return (false);
421 }
422
423 return (true);
424 } /*filereadhandle*/
425
426
427 #ifdef MACVERSION
428
429 //Code change by Timothy Paustian Monday, June 19, 2000 3:15:01 PM
430 //Changed to Opaque call for Carbon
431
432 static pascal void iocompletion (ParmBlkPtr pb) {
433
434 DisposePtr ((Ptr) pb);
435 } /*iocompletion*/
436
437
438 #if TARGET_RT_MAC_CFM || TARGET_RT_MAC_MACHO
439
440 #if TARGET_API_MAC_CARBON
441
442 //looks like we need some kind of file UPP
443 //do we need to create a UPP, yes we do.
444 IOCompletionUPP iocompletionDesc = nil;
445
446 #define iocompletionUPP (iocompletionDesc)
447
448 #else
449
450 static RoutineDescriptor iocompletionDesc = BUILD_ROUTINE_DESCRIPTOR (uppIOCompletionProcInfo, iocompletion);
451
452 #define iocompletionUPP (&iocompletionDesc)
453
454 #endif
455
456 #else
457
458 static IOCompletionUPP iocompletionUPP = &iocompletion;
459
460 #endif
461
462 #endif //MACVERSION
463
464 boolean flushvolumechanges (const tyfilespec *fs, hdlfilenum fnum) {
465 #ifdef MACVERSION
466 /*
467 4.1b7 dmb: was -- FlushVol (nil, (*fs).vRefNum);
468
469 now use PB call to do asynch flush
470 */
471
472 ParamBlockRec *pb;
473
474 pb = (ParamBlockRec *) NewPtrClear (sizeof (ParamBlockRec));
475
476 (*pb).volumeParam.ioVRefNum = (*fs).vRefNum;
477
478 (*pb).volumeParam.ioCompletion = iocompletionUPP;
479
480 PBFlushVolAsync (pb);
481 #endif
482
483 #ifdef WIN95VERSION
484 if (fnum != NULL)
485 FlushFileBuffers (fnum);
486 #endif
487 return (true);
488 } /*flushvolumechanges*/
489
490 //Code change by Timothy Paustian Wednesday, July 26, 2000 10:52:49 PM
491 //new routine to create UPPS for the async file saves.
492 void fileinit (void) {
493 #if TARGET_API_MAC_CARBON
494 if(iocompletionDesc == nil)
495 iocompletionDesc = NewIOCompletionUPP(iocompletion);
496 #endif
497 } /*fileinit*/
498
499
500 void fileshutdown(void) {
501
502 #if TARGET_API_MAC_CARBON
503 if(iocompletionDesc != nil)
504 DisposeIOCompletionUPP(iocompletionDesc);
505 #endif
506 } /*fileshutdown*/
507
508
509 static boolean filecreateandopen (const tyfilespec *fs, OSType creator, OSType filetype, hdlfilenum *fnum) {
510 #ifdef MACVERSION
511 OSStatus err = noErr;
512 // char s[256];
513
514 setfserrorparam (fs);
515
516 if (oserror (FSpCreate (fs, creator, filetype, smSystemScript))) /*failed to open the file for writing*/
517 return (false);
518
519 if (oserror (FSpOpenDF (fs, fsRdWrPerm, fnum))) {
520
521 FSClose (*fnum);
522
523 deletefile (fs);
524
525 return (false); /*failed to open the file for writing*/
526 }
527
528 #if TARGET_API_MAC_CARBON
529 {
530 FSRef myRef;
531 err = FSpMakeFSRef (fs,&myRef);
532 if (!err)
533 FSSetNameLocked(&myRef);
534 }
535 #endif
536
537 return (true);
538 #endif
539
540 #ifdef WIN95VERSION
541 HANDLE fref;
542
543 fref = (Handle) CreateFile (stringbaseaddress (fsname (fs)), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
544 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
545 *fnum = 0;
546
547 if (fref == INVALID_HANDLE_VALUE) {
548
549 winfileerror (fs);
550
551 return (false);
552 }
553
554 *fnum = (hdlfilenum) fref;
555 return (true);
556 #endif
557 } /*filecreateandopen*/
558
559
560 boolean fileopenorcreate (const tyfilespec *fs, OSType creator, OSType filetype, hdlfilenum *fnum) {
561 #ifdef MACVERSION
562 /*
563 open or create a file indicated by fs. return with fnum set to the Mac
564 filesystem's file number for the file.
565
566 if we open a file, we takes what we get in the creator and filetype department.
567 however, if we create a file it's of the indicated filetype and creator.
568 */
569
570 if (FSpOpenDF (fs, fsRdWrPerm, fnum) == noErr) {
571 /*file exists and is open*/
572 #if TARGET_API_MAC_CARBON
573 FSRef myRef;
574 if (FSpMakeFSRef (fs,&myRef))
575 FSSetNameLocked(&myRef);
576 #else
577 FSpSetNameLocked(&fs);
578 #endif
579 return (true);
580 }
581 return (filecreateandopen (fs, creator, filetype, fnum));
582 #endif
583
584 #ifdef WIN95VERSION
585 HANDLE fref;
586 DWORD dAccess;
587 char fn[300];
588
589 dAccess = GENERIC_READ | GENERIC_WRITE;
590
591 copystring (fsname (fs), fn);
592
593 nullterminate (fn);
594
595 fref = (Handle) CreateFile (stringbaseaddress(fn), dAccess, FILE_SHARE_READ,
596 NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
597 *fnum = 0;
598
599 if (fref == INVALID_HANDLE_VALUE) {
600
601 winfileerror (fs);
602
603 return (false);
604 }
605
606 *fnum = (hdlfilenum) fref;
607 return (true);
608 #endif
609 } /*fileopenorcreate*/
610
611
612 boolean opennewfile (const tyfilespec *fs, OSType creator, OSType filetype, hdlfilenum *fnum) {
613
614 boolean flfolder;
615
616 if (fileexists (fs, &flfolder)) { /*file exists, delete it*/
617 //WriteToConsole("We're deleting a file that already exists. No idea why.");
618 if (!deletefile (fs))
619 return (false);
620 }
621
622 return (filecreateandopen (fs, creator, filetype, fnum));
623 } /*opennewfile*/
624
625
626 boolean openfile (const tyfilespec *fs, hdlfilenum *fnum, boolean flreadonly) {
627
628 #ifdef MACVERSION
629 /*
630 5/23/91 dmb: make sure we clear fnum on error; if file is already open,
631 FSOpen will set fnum to the existing channel
632
633 4.1b4 dmb: added flreadonly paramater
634 */
635
636 OSErr errcode;
637 OSErr err = noErr;
638 short perm;
639
640 setfserrorparam (fs); /*in case error message takes a filename parameter*/
641
642 if (flreadonly) perm = fsRdPerm;
643 else perm = fsRdWrPerm;
644
645
646 errcode = FSpOpenDF (fs, perm, fnum);
647
648 if (oserror (errcode)) {
649
650 *fnum = 0;
651
652 return (false);
653 }
654 #if TARGET_API_MAC_CARBON
655 {
656 FSRef myRef;
657 err = FSpMakeFSRef (fs,&myRef);
658 if (!err)
659 err = FSSetNameLocked(&myRef);
660 }
661 #else
662 err = FSpSetNameLocked(fs);
663 #endif
664
665 if (err!=noErr){
666 //sprintf(s,"error locking file name: %d",err);
667 //WriteToConsole(s);
668 }
669
670 return (true);
671 #endif
672
673 #ifdef WIN95VERSION
674 HANDLE fref;
675 DWORD dAccess;
676 char fn[300];
677
678 if (flreadonly)
679 dAccess = GENERIC_READ;
680 else
681 dAccess = GENERIC_READ | GENERIC_WRITE;
682
683 copystring (fsname (fs), fn);
684
685 nullterminate (fn);
686
687 fref = (Handle) CreateFile (stringbaseaddress(fn), dAccess, FILE_SHARE_READ,
688 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
689 *fnum = 0;
690
691 if (fref == INVALID_HANDLE_VALUE) {
692
693 winfileerror (fs);
694
695 return (false);
696 }
697
698 *fnum = (hdlfilenum) fref;
699 return (true);
700 #endif
701 } /*openfile*/
702
703 /*******
704
705 From MoreFilesExtras.
706 I'm going to use this to yank the fsspec back out from a refnum,
707 so that I can clear the finder name lock from the file prior to closing it.
708
709 *******/
710
711
712 boolean closefile (hdlfilenum fnum) {
713 #ifdef MACVERSION
714 OSStatus err = noErr;
715 // char s[256];
716
717 /*
718 dmb 8/20/90: check for 0.
719 */
720
721 if (fnum != 0) {
722 #if TARGET_API_MAC_CARBON
723 FSRef myRef;
724 err = FileRefNumGetFSRef (fnum, &myRef);
725 if (err == noErr) {
726 FSClearNameLocked (&myRef);
727 }
728 #else
729 FSSpec fs;
730 err = FSpGetFileLocation (fnum,&fs);
731 if (err==noErr) {
732 FSpClearNameLocked (&fs);
733 }
734 #endif
735 else {
736 //sprintf(s,"Error is %d",err);
737 //WriteToConsole(s);
738 }
739
740 return (!oserror (FSClose (fnum)));
741 }
742
743 return (true);
744 #endif
745
746 #ifdef WIN95VERSION
747 if (fnum != 0) {
748
749 if (!CloseHandle (fnum)) {
750
751 winerror ();
752
753 return (false);
754 }
755 }
756
757 return (true);
758 #endif
759 } /*closefile*/
760
761
762 boolean deletefile (const tyfilespec *fs) {
763
764 /*
765 2.1b2 dmb: new filespec-based version
766
767 5.0.1 dmb: always setsferror param
768 */
769
770 #ifdef MACVERSION
771 setfserrorparam (fs); /*in case error message takes a filename parameter*/
772 #if TARGET_API_MAC_CARBON
773 {
774 FSRef myRef;
775 if (FSpMakeFSRef (fs,&myRef))
776 FSClearNameLocked(&myRef);
777 }
778 #else
779 FSpClearNameLocked(fs);
780 #endif
781 return (!oserror (FSpDelete (fs)));
782 #endif
783
784 #ifdef WIN95VERSION
785 char fn[300];
786 boolean fldeletefolder;
787
788 setfserrorparam (fs); /*in case error message takes a filename parameter*/
789
790 copystring (fsname (fs), fn);
791
792 cleanendoffilename(fn);
793
794 nullterminate (fn);
795
796 if (!fileisfolder (fs, &fldeletefolder))
797 return (false);
798
799 if (fldeletefolder) {
800
801 if (RemoveDirectory (stringbaseaddress(fn)))
802 return (true);
803
804 goto error;
805 }
806
807 if (DeleteFile (stringbaseaddress(fn)))
808 return (true);
809
810 error:
811 winerror ();
812
813 return (false);
814 #endif
815 } /*deletefile*/
816
817
818
819 boolean fileexists (const tyfilespec *fs, boolean *flfolder) {
820 #ifdef MACVERSION
821 /*
822 we figure if we can get info on it, it must exist.
823
824 can't call filegetinfo because it has an error message if the file
825 isn't found.
826
827 7/1/91 dmb: special case empty string so we don't try to get info about
828 the default volume and return true.
829
830 2.1b2 dmb: filespec implementation
831
832 5.0.2b15 rab: return false to non-existent volume specs.
833 */
834
835 CInfoPBRec pb;
836
837 *flfolder = false;
838
839 if (isemptystring (fsname (fs)))
840 return (false);
841
842 clearbytes (&pb, sizeof (pb));
843
844 pb.hFileInfo.ioNamePtr = (StringPtr) fsname (fs);
845
846 pb.hFileInfo.ioVRefNum = (*fs).vRefNum;
847
848 pb.hFileInfo.ioDirID = (*fs).parID;
849
850 if (PBGetCatInfoSync (&pb) != noErr)
851 return (false);
852
853 *flfolder = foldertest (&pb);
854
855 return (true);
856 #endif
857 #ifdef WIN95VERSION
858 HANDLE ff;
859 WIN32_FIND_DATA ffd;
860 char fn[300];
861
862 *flfolder = false;
863
864 copystring (fsname (fs), fn);
865
866 /*if ends with \ get ride of it... and handle the root*/
867
868 cleanendoffilename (fn);
869
870 nullterminate (fn);
871
872 if (stringlength(fn) == 2) {
873 if (isalpha(fn[1]) && fn[2] == ':') {
874 *flfolder = true;
875 return (fileisvolume(fs));
876 }
877 }
878
879 ff = FindFirstFile (stringbaseaddress(fn), &ffd);
880
881 if (ff == INVALID_HANDLE_VALUE)
882 return (false);
883
884 *flfolder = ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY?true:false;
885
886 FindClose (ff);
887 return (true);
888 #endif
889 } /*fileexists*/
890
891
892 boolean filegetfilename (const tyfilespec *pfs, bigstring name) {
893
894 #if MACVERSION
895 /*
896 filespecs for volumes have their strings set to the empty string.
897 */
898
899 copystring (fsname (pfs), name);
900
901 if (stringlength (name) > 0)
902 return (true);
903
904 return (filegetvolumename ((*pfs).vRefNum, name));
905 #endif
906
907 #if WIN95VERSION
908 lastword ((ptrstring) fsname (pfs), '\\', name);
909
910 return (true);
911 #endif
912 } /*filegetfilename*/
913
914
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.