1 /* ncbifile.c
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * File Name: ncbifile.c
27 *
28 * Author: Gish, Kans, Ostell, Schuler
29 *
30 * Version Creation Date: 3/4/91
31 *
32 * $Revision: 6.46 $
33 *
34 * File Description:
35 * portable file routines
36 *
37 * Modifications:
38 * --------------------------------------------------------------------------
39 * Date Name Description of modification
40 * ------- ---------- -----------------------------------------------------
41 *
42 * ==========================================================================
43 */
44
45 #define THIS_MODULE g_corelib
46 #define THIS_FILE _this_file
47
48 #include <ncbilcl.h>
49 #include <assert.h>
50
51 #include "corepriv.h"
52 #ifdef OS_MAC
53 #ifdef OS_UNIX_DARWIN
54 #include <Carbon.h>
55 #endif
56 #include <Navigation.h>
57 #include <Script.h>
58 #endif
59
60 #ifdef OS_UNIX_SUN
61 #define DEFAULT_CDROM "/dev/sr0"
62 #define DEFAULT_RAW_CDROM "/dev/rsr0"
63 #endif
64
65 #if defined(PROC_MIPS) && !defined(OS_UNIX_LINUX)
66 #define DEFAULT_CDROM "/dev/scsi/sc0d4l0"
67 #endif
68
69 #ifdef OS_UNIX
70 #ifndef DEFAULT_CDROM
71 #define DEFAULT_CDROM "/dev/cdrom"
72 #endif
73 #endif
74
75 #if defined(OS_MSWIN) || defined (OS_NT)
76 #ifdef COMP_MSC
77 #ifndef mkdir
78 #define mkdir _mkdir
79 #endif
80 #ifndef stat
81 #define stat _stat
82 #endif
83 #endif
84 #endif
85
86 #ifdef OS_VMS
87 #ifndef DEFAULT_CDROM
88 #define DEFAULT_CDROM "cdrom:"
89 #endif
90 #endif
91
92 extern char *g_corelib;
93 static char * _this_file = __FILE__;
94
95 #ifdef OS_MAC
96 #define INLINE_MOREFILES
97 /* #include "FullPath.h" */
98 /* #include "MoreFilesExtra.h" */
99 #ifdef INLINE_MOREFILES
100
101 /* MoreFilesExtras.c */
102 /* ----------------- */
103
104 /*
105 ** Apple Macintosh Developer Technical Support
106 **
107 ** A collection of useful high-level File Manager routines.
108 **
109 ** by Jim Luther, Apple Developer Technical Support Emeritus
110 **
111 ** File: MoreFilesExtras.c
112 **
113 ** Copyright (c) 1992-1999 Apple Computer, Inc.
114 ** All rights reserved.
115 **
116 ** You may incorporate this sample code into your applications without
117 ** restriction, though the sample code has been provided "AS IS" and the
118 ** responsibility for its operation is 100% yours. However, what you are
119 ** not permitted to do is to redistribute the source as "DSC Sample Code"
120 ** after having made changes. If you're going to re-distribute the source,
121 ** we require that you make it clear in the source that the code was
122 ** descended from Apple Sample Code, but that you've made changes.
123 */
124
125 #include <Types.h>
126 #include <Traps.h>
127 #include <OSUtils.h>
128 #include <Errors.h>
129 #include <Files.h>
130 #include <Devices.h>
131 #include <Finder.h>
132 #include <Folders.h>
133 #include <FSM.h>
134 #include <Disks.h>
135 #include <Gestalt.h>
136 #include <TextUtils.h>
137 #include <Script.h>
138 #include <Math64.h>
139 #include <CodeFragments.h>
140 #include <stddef.h>
141
142 #define __COMPILINGMOREFILES
143
144 #if 0
145 #include "MoreFiles.h"
146 #include "MoreFilesExtras.h"
147 #include "MoreDesktopMgr.h"
148 #include "FSpCompat.h"
149 #endif
150
151 /*
152 ** GetVolumeInfoNoName uses pathname and vRefNum to call PBHGetVInfoSync
153 ** in cases where the returned volume name is not needed by the caller.
154 ** The pathname and vRefNum parameters are not touched, and the pb
155 ** parameter is initialized by PBHGetVInfoSync except that ioNamePtr in
156 ** the parameter block is always returned as NULL (since it might point
157 ** to the local tempPathname).
158 **
159 ** I noticed using this code in several places, so here it is once.
160 ** This reduces the code size of MoreFiles.
161 */
GetVolumeInfoNoName(ConstStr255Param pathname,short vRefNum,HParmBlkPtr pb)162 static pascal OSErr GetVolumeInfoNoName(ConstStr255Param pathname,
163 short vRefNum,
164 HParmBlkPtr pb)
165 {
166 Str255 tempPathname;
167 OSErr error;
168
169 /* Make sure pb parameter is not NULL */
170 if ( pb != NULL )
171 {
172 pb->volumeParam.ioVRefNum = vRefNum;
173 if ( pathname == NULL )
174 {
175 pb->volumeParam.ioNamePtr = NULL;
176 pb->volumeParam.ioVolIndex = 0; /* use ioVRefNum only */
177 }
178 else
179 {
180 BlockMoveData(pathname, tempPathname, pathname[0] + 1); /* make a copy of the string and */
181 pb->volumeParam.ioNamePtr = (StringPtr)tempPathname; /* use the copy so original isn't trashed */
182 pb->volumeParam.ioVolIndex = -1; /* use ioNamePtr/ioVRefNum combination */
183 }
184 error = PBHGetVInfoSync(pb);
185 pb->volumeParam.ioNamePtr = NULL; /* ioNamePtr may point to local tempPathname, so don't return it */
186 }
187 else
188 {
189 error = paramErr;
190 }
191 return ( error );
192 }
193
194 /*****************************************************************************/
195
DetermineVRefNum(ConstStr255Param pathname,short vRefNum,short * realVRefNum)196 static pascal OSErr DetermineVRefNum(ConstStr255Param pathname,
197 short vRefNum,
198 short *realVRefNum)
199 {
200 HParamBlockRec pb;
201 OSErr error;
202
203 error = GetVolumeInfoNoName(pathname,vRefNum, &pb);
204 if ( error == noErr )
205 {
206 *realVRefNum = pb.volumeParam.ioVRefNum;
207 }
208 return ( error );
209 }
210
211 /*****************************************************************************/
212
GetCatInfoNoName(short vRefNum,long dirID,ConstStr255Param name,CInfoPBPtr pb)213 static pascal OSErr GetCatInfoNoName(short vRefNum,
214 long dirID,
215 ConstStr255Param name,
216 CInfoPBPtr pb)
217 {
218 Str31 tempName;
219 OSErr error;
220
221 /* Protection against File Sharing problem */
222 if ( (name == NULL) || (name[0] == 0) )
223 {
224 tempName[0] = 0;
225 pb->dirInfo.ioNamePtr = tempName;
226 pb->dirInfo.ioFDirIndex = -1; /* use ioDirID */
227 }
228 else
229 {
230 pb->dirInfo.ioNamePtr = (StringPtr)name;
231 pb->dirInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
232 }
233 pb->dirInfo.ioVRefNum = vRefNum;
234 pb->dirInfo.ioDrDirID = dirID;
235 error = PBGetCatInfoSync(pb);
236 pb->dirInfo.ioNamePtr = NULL;
237 return ( error );
238 }
239
240 /*****************************************************************************/
241
GetDirectoryID(short vRefNum,long dirID,ConstStr255Param name,long * theDirID,Boolean * isDirectory)242 static pascal OSErr GetDirectoryID(short vRefNum,
243 long dirID,
244 ConstStr255Param name,
245 long *theDirID,
246 Boolean *isDirectory)
247 {
248 CInfoPBRec pb;
249 OSErr error;
250
251 error = GetCatInfoNoName(vRefNum, dirID, name, &pb);
252 if ( error == noErr )
253 {
254 *isDirectory = (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0;
255 if ( *isDirectory )
256 {
257 *theDirID = pb.dirInfo.ioDrDirID;
258 }
259 else
260 {
261 *theDirID = pb.hFileInfo.ioFlParID;
262 }
263 }
264
265 return ( error );
266 }
267
268 /*****************************************************************************/
269
FSpGetDirectoryID(const FSSpec * spec,long * theDirID,Boolean * isDirectory)270 static pascal OSErr FSpGetDirectoryID(const FSSpec *spec,
271 long *theDirID,
272 Boolean *isDirectory)
273 {
274 return ( GetDirectoryID(spec->vRefNum, spec->parID, spec->name,
275 theDirID, isDirectory) );
276 }
277
278 #endif /* INLINE_MOREFILES */
279 #endif /* OS_MAC */
280
281 /*****************************************************************************
282 *
283 * Macintosh file utilities
284 *
285 *****************************************************************************/
286
287 #ifdef OS_MAC
288
MacPathname2FSSpec(const char * inPathname,FSSpec * outFSS)289 static OSErr MacPathname2FSSpec(const char *inPathname, FSSpec *outFSS)
290 {
291 OSErr err;
292 size_t len;
293 char *p;
294 short vRefNum;
295 long dirID;
296 FSSpec fss;
297
298 if (inPathname == NULL || outFSS == NULL) {
299 return paramErr;
300 }
301
302 err = HGetVol(NULL, &vRefNum, &dirID); /* default volume and directory */
303 if (err != noErr) return err;
304
305 len = strlen(inPathname);
306
307 p = strchr(inPathname, ':');
308 if (p == NULL) {
309 /* Partial pathname -- filename only */
310 Str31 filename;
311 assert(len <= 31);
312 c2pstrcpy(filename, inPathname);
313 err = FSMakeFSSpec(vRefNum, dirID, filename, outFSS);
314 } else {
315 Str31 name;
316 int nameLen;
317 if (inPathname[0] == ':') {
318 /* Relative pathname including directory path */
319
320 } else {
321 /* Absolute pathname */
322 /* Str31 volName; We would use Str28 if it was defined -- 27, plus 1 for ':'. */
323 nameLen = p - inPathname;
324 assert(nameLen <= 27);
325 name[0] = nameLen + 1;
326 memcpy(name + 1, inPathname, nameLen + 1); /* Copy the volume name and the colon. */
327 err = DetermineVRefNum(name, 0, &vRefNum);
328 if (err != noErr) return err;
329 dirID = 2;
330 }
331 /* vRefNum and dirID now specify the directory in which we should descend
332 the path pointed to by p (pointing to the first colon). */
333 p++;
334 while (p != NULL && *p != '\0') {
335 char *q = strchr(p, ':');
336 if (q != NULL) {
337 Boolean isDir;
338 nameLen = q - p;
339 assert(nameLen <= 31);
340 name[0] = nameLen;
341 memcpy(name + 1, p, nameLen);
342 err = FSMakeFSSpec(vRefNum, dirID, name, &fss);
343 if (err != noErr) return err;
344 if (q[1] == '\0') {
345 p = NULL;
346 *outFSS = fss;
347 } else {
348 err = FSpGetDirectoryID(&fss, &dirID, &isDir);
349 assert(isDir == true);
350 if (err != noErr) return err;
351 p = q + 1;
352 }
353 } else {
354 q = strchr(p, '\0'); /* go to end of string */
355 nameLen = q - p;
356 assert(nameLen > 0);
357 assert(nameLen <= 31);
358 c2pstrcpy(name, p);
359 p = NULL;
360 err = FSMakeFSSpec(vRefNum, dirID, name, outFSS);
361 }
362 }
363 }
364 return err;
365 }
366
367 #if 0
368 static OSErr MacFSSpec2FullPathname(const FSSpec *inFSS, char **outPathname)
369 {
370 OSErr err;
371 Handle h;
372 short fullPathLength;
373 static char *fullPath = NULL;
374
375 if (fullPath != NULL) {
376 Nlm_Free(fullPath);
377 fullPath = NULL;
378 }
379 err = FSpGetFullPath(inFSS, &fullPathLength, &h);
380 if (err != noErr) return err;
381
382 assert(fullPathLength >= 2); /* An absolute pathname must be at least two chars long */
383 fullPath = (char *)Nlm_Malloc(fullPathLength + 1);
384 if (fullPath == NULL) {
385 err = memFullErr;
386 } else {
387 strncpy(fullPath, *h, fullPathLength);
388 }
389
390 DisposeHandle(h);
391
392 *outPathname = fullPath;
393 return err;
394 }
395 #endif
396
MacCreateDirectory(const char * inPathname)397 static OSErr MacCreateDirectory(const char *inPathname)
398 {
399 OSErr err;
400 FSSpec fss;
401 ScriptCode scriptTag = 0;
402 long createdDirID;
403
404 err = MacPathname2FSSpec(inPathname, &fss);
405 if (err != noErr) return err;
406
407 err = FSpDirCreate(&fss, scriptTag, &createdDirID);
408 return err;
409 }
410
411 #endif
412
413 /*****************************************************************************
414 *
415 * FileOpen(filename, mode)
416 * if (filename == "stdin" or "stdout" or "stderr"
417 * returns those predefined
418 * streams on non-windowing systems)
419 *
420 *****************************************************************************/
421
422 /* p_churchill 12/99 removed MPW conditional compilation
423 */
424
425 static Nlm_FileOpenHook _hookFile = NULL;
426
427
Nlm_FileOpen(const char * filename,const char * mode)428 NLM_EXTERN FILE * LIBCALL Nlm_FileOpen(const char *filename, const char *mode)
429 {
430 FILE *f = NULL;
431
432 if ( _hookFile )
433 return _hookFile(filename, mode);
434
435 #if defined(WIN_DUMB)
436 if ( Nlm_HasConsole )
437 {
438 if ( !StringCmp("stdin", filename))
439 f = stdin;
440 else if ( !StringCmp("stdout", filename) )
441 f = stdout;
442 else if ( !StringCmp("stderr", filename))
443 f = stderr;
444 else
445 f = fopen(filename, mode);
446
447 #if defined(WIN32) && ! defined(COMP_METRO)
448 if (strchr(mode, 'b') &&
449 (f == stdin || f == stdout || f == stderr))
450 setmode(fileno(f), O_BINARY);
451 #endif
452 }
453 else
454 f = fopen(filename, mode);
455
456 #elif defined(OS_MAC)
457 {
458 OSType fCreator;
459 Nlm_Int2 fError;
460 FInfo fInfo;
461 OSType fType;
462 Nlm_Char temp [256];
463
464 Nlm_StringNCpy_0(temp, filename, sizeof(temp));
465 Nlm_CtoPstr ((Nlm_CharPtr) temp);
466 fError = HGetFInfo( 0, 0, (StringPtr) temp, &fInfo);
467 if (fError == noErr) {
468 fCreator = fInfo.fdCreator;
469 fType = fInfo.fdType;
470 } else {
471 fCreator = ' ';
472 if (strchr(mode, 'b') != NULL)
473 fType = ' ';
474 else
475 fType = 'TEXT';
476 }
477 f = fopen( filename, mode);
478
479 fError = HGetFInfo( 0, 0, (StringPtr) temp, &fInfo);
480 if (fError == noErr) {
481 fInfo.fdCreator = fCreator;
482 fInfo.fdType = fType;
483 fError = HSetFInfo ( 0, 0, (StringPtr) temp,&fInfo);
484 }
485 } /* def OS_MAC */
486
487 #elif defined(OS_VMS) && defined(DCC4DW12)
488 /* never used */
489 f = fopen (filename, mode);
490 if (f &&
491 fstat(fileno(f), &statbuf) == 0 &&
492 statbuf.st_fab_rfm == FAB$C_UDF)
493 {
494 fclose(f);
495 f = fopen(filename,mode,"ctx=stm");
496 }
497
498 #else
499 f = fopen(filename, mode);
500 #endif
501
502 if (f == NULL)
503 ErrPostEx(SEV_INFO, E_File, E_FOpen, "FileOpen(\"%s\",\"%s\") failed",
504 filename, mode);
505
506 return f;
507 }
508
509 /*****************************************************************************
510 *
511 * SetFileOpenHook(hook)
512 *
513 *****************************************************************************/
514
Nlm_SetFileOpenHook(Nlm_FileOpenHook hook)515 NLM_EXTERN void LIBCALL Nlm_SetFileOpenHook (Nlm_FileOpenHook hook)
516 {
517 _hookFile = hook;
518 }
519
520 /*****************************************************************************
521 *
522 * FileClose(fp)
523 *
524 *****************************************************************************/
525
Nlm_FileClose(FILE * stream)526 NLM_EXTERN void LIBCALL Nlm_FileClose (FILE *stream)
527 {
528 if (stream == NULL)
529 return;
530
531 #ifdef WIN_DUMB
532 if (stream == stdin || stream == stdout || stream == stderr)
533 {
534 #if defined(WIN32) && ! defined(COMP_METRO)
535 setmode(fileno(stream), O_TEXT);
536 #endif
537 return;
538 }
539 #endif
540
541 fclose(stream);
542 }
543
544 /*****************************************************************************
545 * FileRead(buf, size, fp)
546 *****************************************************************************/
Nlm_FileRead(void * ptr,size_t size,size_t n,FILE * stream)547 NLM_EXTERN size_t LIBCALL Nlm_FileRead
548 (void *ptr, size_t size, size_t n, FILE *stream)
549 {
550 if (n && (SIZE_MAX / n) < size) {
551 ErrPostEx(SEV_WARNING,E_Programmer,0,"FileRead: size > SIZE_MAX");
552 return 0;
553 }
554 if (!ptr || !stream)
555 return 0;
556
557 return fread(ptr,size,n,stream);
558 }
559
560 /*****************************************************************************
561 * FileWrite(buf, size, fp)
562 *****************************************************************************/
Nlm_FileWrite(const void * ptr,size_t size,size_t n,FILE * stream)563 NLM_EXTERN size_t LIBCALL Nlm_FileWrite
564 (const void *ptr, size_t size, size_t n, FILE *stream)
565 {
566 size_t cnt;
567 if (n && (SIZE_MAX / n) < size) {
568 ErrPostEx(SEV_WARNING,E_Programmer,0,"FileWrite: size > SIZE_MAX");
569 return 0;
570 }
571 if (!ptr || !stream || !size)
572 return 0;
573
574 cnt = fwrite(ptr,size,n,stream);
575 if (cnt != n)
576 ErrPostEx(SEV_FATAL,E_File,E_FWrite,"File write error");
577
578 return cnt;
579 }
580
581 /*****************************************************************************
582 *
583 * FilePuts(ptr, fp)
584 *
585 *****************************************************************************/
Nlm_FilePuts(const char * ptr,FILE * fp)586 NLM_EXTERN int LIBCALL Nlm_FilePuts (const char *ptr, FILE *fp)
587 {
588 int retval;
589
590 if ((ptr == NULL) || (fp == NULL))
591 return EOF;
592 if ((retval = fputs(ptr,fp)) ==EOF)
593 ErrPostEx(SEV_FATAL,E_File,E_FWrite,"File write error");
594 return retval;
595 }
596
597 /*****************************************************************************
598 *
599 * FileGets()
600 *
601 *****************************************************************************/
Nlm_FileGets(Nlm_CharPtr ptr,size_t size,FILE * fp)602 NLM_EXTERN char * LIBCALL Nlm_FileGets (Nlm_CharPtr ptr, size_t size, FILE *fp)
603 {
604 #if defined(OS_MAC) || defined (OS_UNIX_DARWIN)
605 int ch;
606 int count;
607 Nlm_CharPtr tmp;
608 #endif
609
610 if ((ptr == NULL) || (size < 1) || (fp == NULL))
611 return NULL;
612 #if defined(OS_MAC) || defined (OS_UNIX_DARWIN)
613 ch = fgetc (fp);
614 count = 0;
615 tmp = ptr;
616 while (ch != EOF && ch != '\0' && ch != '\n' && ch != '\r' && count < size - 2) {
617 *tmp = ch;
618 tmp++;
619 count++;
620 ch = fgetc (fp);
621 }
622 if (ch == '\n' || ch == '\r') {
623 *tmp = '\n';
624 tmp++;
625 count++;
626 } else if (ch != EOF && ch != '\0') {
627 *tmp = ch;
628 tmp++;
629 count++;
630 }
631 *tmp = '\0';
632 if (count < 1)
633 return NULL;
634 return ptr;
635 #else
636 return fgets(ptr,size,fp);
637 #endif
638 }
639
640
641 /*****************************************************************************
642 *
643 * FileBuildPath()
644 *
645 *****************************************************************************/
Nlm_FileBuildPath(Nlm_CharPtr root,Nlm_CharPtr sub_path,Nlm_CharPtr filename)646 NLM_EXTERN Nlm_CharPtr LIBCALL Nlm_FileBuildPath (Nlm_CharPtr root, Nlm_CharPtr sub_path, Nlm_CharPtr filename)
647
648 {
649 Nlm_CharPtr tmp;
650 Nlm_Boolean dir_start = FALSE;
651 #ifdef OS_VMS
652 Nlm_Boolean had_root = FALSE;
653 #endif
654
655 if (root == NULL) /* no place to put it */
656 return NULL;
657
658 tmp = root;
659 if (*tmp != '\0') /* if not empty */
660 {
661 #ifndef OS_VMS
662 dir_start = TRUE;
663 #else
664 had_root = TRUE;
665 #endif
666 while (*tmp != '\0')
667 {
668 #ifdef OS_VMS
669 if (*tmp == '[')
670 dir_start = TRUE;
671 #endif
672 tmp++;
673 }
674
675 if ((*(tmp - 1) != DIRDELIMCHR) && (dir_start))
676 {
677 *tmp = DIRDELIMCHR;
678 tmp++; *tmp = '\0';
679 }
680 }
681
682 if (sub_path != NULL)
683 {
684 #ifdef OS_VMS
685 if (dir_start)
686 {
687 *(tmp-1) = '.';
688 if (*sub_path == '[')
689 sub_path++;
690 }
691 else if ((had_root) && (*sub_path != '['))
692 {
693 *tmp = '[';
694 tmp++; *tmp = '\0';
695 }
696 #else
697 if ((dir_start) && (*sub_path == DIRDELIMCHR))
698 sub_path++;
699 #endif
700 tmp = StringMove(tmp, sub_path);
701 if (*(tmp-1) != DIRDELIMCHR)
702 {
703 *tmp = DIRDELIMCHR;
704 tmp++; *tmp = '\0';
705 }
706 }
707
708 if (filename != NULL)
709 StringMove(tmp, filename);
710
711 return root;
712 }
713
714 /*****************************************************************************
715 *
716 * FileNameFind()
717 *
718 *****************************************************************************/
Nlm_FileNameFind(Nlm_CharPtr pathname)719 NLM_EXTERN Nlm_CharPtr LIBCALL Nlm_FileNameFind (Nlm_CharPtr pathname)
720
721 {
722 Nlm_CharPtr filename;
723 Nlm_Int2 len;
724
725 if (pathname != NULL) {
726 len = Nlm_StringLen (pathname);
727 filename = &(pathname [len]);
728 while (len > 0 && pathname [len - 1] != DIRDELIMCHR) {
729 len--;
730 filename--;
731 }
732 return filename;
733 } else {
734 return NULL;
735 }
736 }
737
738
739 /*****************************************************************************
740 *
741 * FilePathFind()
742 *
743 *****************************************************************************/
Nlm_FilePathFind(const Nlm_Char * fullname)744 NLM_EXTERN Nlm_CharPtr LIBCALL Nlm_FilePathFind(const Nlm_Char* fullname)
745 {
746 Nlm_CharPtr str;
747 size_t len = Nlm_StringLen(fullname);
748 if ( !len )
749 return 0;
750
751 while (len && fullname[len] != DIRDELIMCHR)
752 len--;
753
754 str = (Nlm_Char*)Nlm_MemGet(len + 1, MGET_ERRPOST);
755 Nlm_MemCpy(str, fullname, len);
756 str[len] = '\0';
757 return str;
758 }
759
760
761 /*****************************************************************************
762 *
763 * FileLength()
764 *
765 *****************************************************************************/
Nlm_FileLength(Nlm_CharPtr fileName)766 NLM_EXTERN Nlm_Int8 LIBCALL Nlm_FileLength(Nlm_CharPtr fileName)
767 {
768 Nlm_Int8 file_len = Nlm_FileLengthEx(fileName);
769 return (file_len > 0) ? file_len : 0;
770 }
771
772
773 /*****************************************************************************
774 *
775 * FileLengthEx()
776 *
777 *****************************************************************************/
Nlm_FileLengthEx(const Nlm_Char * fileName)778 NLM_EXTERN Nlm_Int8 LIBCALL Nlm_FileLengthEx(const Nlm_Char* fileName)
779 {
780 if (!fileName || !*fileName)
781 return -1;
782
783 #ifdef OS_MAC
784 {{
785 OSErr err;
786 HParamBlockRec params;
787 Nlm_Char path[256];
788
789 Nlm_MemSet ((Nlm_VoidPtr) ¶ms, 0, sizeof (HParamBlockRec));
790 Nlm_StringNCpy_0(path, fileName, sizeof(path));
791 Nlm_CtoPstr((Nlm_CharPtr) path);
792 params.fileParam.ioNamePtr = (StringPtr)path;
793 params.fileParam.ioVRefNum = 0;
794 params.fileParam.ioFDirIndex = 0;
795 err = PBHGetFInfo(¶ms, FALSE);
796 return (err == noErr) ?
797 params.fileParam.ioFlLgLen : -1;
798 }}
799 #else
800 {{
801 struct stat sbuf;
802 return (stat(fileName, &sbuf) == 0) ? sbuf.st_size : -1;
803 }}
804 #endif
805 }
806
807
808 /*****************************************************************************
809 *
810 * FileDelete()
811 *
812 *****************************************************************************/
Nlm_FileRemove(Nlm_CharPtr fileName)813 NLM_EXTERN Nlm_Boolean LIBCALL Nlm_FileRemove (Nlm_CharPtr fileName)
814
815 {
816 Nlm_Char local [256];
817
818 if (fileName != NULL && fileName [0] != '\0') {
819 Nlm_StringNCpy_0(local, fileName, sizeof(local));
820 return (Nlm_Boolean) (remove (local) == 0);
821 } else {
822 return FALSE;
823 }
824 }
825
826 /*****************************************************************************
827 *
828 * FileRename()
829 *
830 *****************************************************************************/
Nlm_FileRename(Nlm_CharPtr oldFileName,Nlm_CharPtr newFileName)831 NLM_EXTERN Nlm_Boolean LIBCALL Nlm_FileRename (Nlm_CharPtr oldFileName, Nlm_CharPtr newFileName)
832
833 {
834 Nlm_Char localnew [256];
835 Nlm_Char localold [256];
836
837 if (oldFileName != NULL && oldFileName [0] != '\0'
838 && newFileName != NULL && newFileName [0] != '\0') {
839 Nlm_StringNCpy_0(localold, oldFileName, sizeof(localold));
840 Nlm_StringNCpy_0(localnew, newFileName, sizeof(localnew));
841 return (Nlm_Boolean) (rename (localold, localnew) == 0);
842 } else {
843 return FALSE;
844 }
845 }
846
847 /*****************************************************************************
848 *
849 * FileCreate()
850 *
851 *****************************************************************************/
852 #ifdef OS_MAC
Nlm_GetOSType(Nlm_CharPtr str,OSType dfault)853 static OSType Nlm_GetOSType (Nlm_CharPtr str, OSType dfault)
854
855 {
856 OSType rsult;
857
858 rsult = dfault;
859 if (str != NULL && str [0] != '\0') {
860 rsult = *(OSType*) str;
861 }
862 return rsult;
863 }
864 #endif
865
Nlm_FileCreate(Nlm_CharPtr fileName,Nlm_CharPtr type,Nlm_CharPtr creator)866 NLM_EXTERN void LIBCALL Nlm_FileCreate (Nlm_CharPtr fileName, Nlm_CharPtr type, Nlm_CharPtr creator)
867
868 {
869 #ifdef OS_MAC
870 Nlm_Int2 fError;
871 Nlm_Char temp [256];
872 OSType fType;
873 OSType fCreator;
874 FSSpec spec;
875 #else
876 FILE *fp;
877 #endif
878
879 if (fileName != NULL && fileName [0] != '\0') {
880
881 #ifdef OS_MAC
882 /* note: the following assumes either full pathname or that the current
883 directory is the proper location to find/create the file */
884
885 Nlm_StringNCpy_0(temp, fileName, sizeof(temp));
886 Nlm_CtoPstr ( temp);
887 fError = FSMakeFSSpec( 0, 0, (StringPtr)temp, &spec);
888
889 /* file not found, so create it... */
890 if( fError == fnfErr){
891 fType = Nlm_GetOSType (type, 'TEXT');
892 fCreator = Nlm_GetOSType (creator, ' ');
893 FSpCreate( &spec, fCreator, fType, smSystemScript);
894 }
895 #else
896 fp = Nlm_FileOpen (fileName, "w");
897 if (fp != NULL) {
898 Nlm_FileClose (fp);
899 }
900 #endif
901 }
902 }
903
904 /*****************************************************************************
905 *
906 * CreateDir(pathname)
907 *
908 *****************************************************************************/
909
910 #ifdef OS_MAC
Nlm_CreateDir(Nlm_CharPtr pathname)911 NLM_EXTERN Nlm_Boolean LIBCALL Nlm_CreateDir (Nlm_CharPtr pathname)
912 {
913 if (pathname != NULL && pathname [0] != '\0') {
914 OSErr err;
915 err = MacCreateDirectory(pathname);
916 return (Nlm_Boolean) (err == noErr || err == dupFNErr);
917 }
918 return FALSE;
919 }
920 #endif
921
922 #ifndef OS_MAC
Nlm_CreateDir(Nlm_CharPtr pathname)923 NLM_EXTERN Nlm_Boolean LIBCALL Nlm_CreateDir (Nlm_CharPtr pathname)
924 {
925 #ifndef OS_VMS
926 size_t len;
927 Nlm_Char path[PATH_MAX];
928 #endif
929 #ifdef OS_UNIX
930 mode_t oldmask;
931 #endif
932 Nlm_Boolean rsult = FALSE;
933
934 if (pathname != NULL && pathname [0] != '\0') {
935 #if defined(OS_MSWIN) || defined(OS_NT)
936 Nlm_StringNCpy_0(path, pathname, sizeof(path));
937 len = Nlm_StringLen (path);
938 if (len > 0 && path [len - 1] == DIRDELIMCHR) {
939 path [len - 1] = '\0';
940 }
941 rsult = (Nlm_Boolean) (mkdir ((char *) path) == 0);
942 if (errno == EACCES) { /* it's O.K. if it was already there */
943 rsult = TRUE;
944 }
945 #endif
946 #ifdef OS_UNIX
947 oldmask = umask (0000);
948 Nlm_StringNCpy_0(path, pathname, sizeof(path));
949 len = Nlm_StringLen (path);
950 if (len > 0 && path [len - 1] == DIRDELIMCHR) {
951 path [len - 1] = '\0';
952 }
953 rsult = (Nlm_Boolean) (mkdir ((char *) path, 0755) == 0);
954 if (errno == EEXIST) { /* it's O.K. if it was already there */
955 rsult = TRUE;
956 }
957 umask (oldmask);
958 #endif
959 #ifdef OS_VMS
960 rsult = (Nlm_Boolean) (mkdir ((char *) pathname, 0755) == 0);
961 #endif
962 }
963 return rsult;
964 }
965 #endif
966
967 /*****************************************************************************
968 *
969 * DirectoryContents()
970 *
971 *****************************************************************************/
972
973 #ifdef OS_UNIX_DARWIN
974 #include <dirent.h>
975 #endif
976
Nlm_DirCatalog(Nlm_CharPtr pathname)977 NLM_EXTERN ValNodePtr LIBCALL Nlm_DirCatalog (Nlm_CharPtr pathname)
978
979 {
980 #ifdef OS_MAC
981 long dirID;
982 OSErr err;
983 short index;
984 unsigned short num;
985 Nlm_Char path[PATH_MAX];
986 CInfoPBRec pbc;
987 HParamBlockRec pbh;
988 short vRefNum;
989 #endif
990 #ifdef OS_UNIX
991 Nlm_Uint1 choice;
992 #ifdef OS_UNIX_DARWIN
993 DIR *dirp;
994 struct dirent *dep;
995 #else
996 Nlm_Char buf [256];
997 Nlm_Char ch;
998 Nlm_Char cmmd [PATH_MAX + 20];
999 FILE *fp;
1000 Nlm_CharPtr ptr;
1001 #endif
1002 #endif
1003 ValNodePtr vnp = NULL;
1004
1005 if (pathname != NULL && pathname [0] != '\0') {
1006 #ifdef OS_MAC
1007 Nlm_StringNCpy_0 (path, pathname, sizeof (path));
1008 Nlm_CtoPstr ((Nlm_CharPtr) path);
1009 Nlm_MemSet ((Nlm_VoidPtr) (&pbh), 0, sizeof (HParamBlockRec));
1010 pbh.volumeParam.ioNamePtr = (StringPtr) path;
1011 pbh.volumeParam.ioVolIndex = -1;
1012 err = PBHGetVInfo (&pbh, FALSE);
1013 if (err != noErr) return NULL;
1014 vRefNum = pbh.volumeParam.ioVRefNum;
1015 Nlm_StringNCpy_0 (path, pathname, sizeof (path));
1016 Nlm_CtoPstr ((Nlm_CharPtr) path);
1017 Nlm_MemSet ((Nlm_VoidPtr) (&pbc), 0, sizeof (CInfoPBRec));
1018 pbc.dirInfo.ioNamePtr = (StringPtr) path;
1019 pbc.dirInfo.ioVRefNum = vRefNum;
1020 err = PBGetCatInfo (&pbc, FALSE);
1021 if (err != noErr) return NULL;
1022 if (pbc.dirInfo.ioFlAttrib & 16) {
1023 num = pbc.dirInfo.ioDrNmFls;
1024 dirID = pbc.dirInfo.ioDrDirID;
1025 for (index = 1; index <= num; index++) {
1026 Nlm_MemSet ((Nlm_VoidPtr) (&pbc), 0, sizeof (CInfoPBRec));
1027 pbc.dirInfo.ioNamePtr = (StringPtr) path;
1028 pbc.dirInfo.ioVRefNum = vRefNum;
1029 pbc.dirInfo.ioFDirIndex = index;
1030 pbc.dirInfo.ioDrDirID = dirID;
1031 pbc.dirInfo.ioACUser = 0;
1032 err = PBGetCatInfo (&pbc, FALSE);
1033 if (err == noErr) {
1034 Nlm_PtoCstr ((Nlm_CharPtr) path);
1035 if (pbc.dirInfo.ioFlAttrib & 16) {
1036 ValNodeCopyStr (&vnp, 1, path);
1037 } else {
1038 ValNodeCopyStr (&vnp, 0, path);
1039 }
1040 }
1041 }
1042 }
1043 #endif
1044 #if defined(WIN32)
1045 {{
1046 Nlm_Char x_path[PATH_MAX];
1047 WIN32_FIND_DATA fData;
1048 HANDLE hFindFile;
1049 Nlm_StringNCpy_0(x_path, pathname, sizeof(x_path) - 5);
1050 Nlm_StringCat(x_path, "\\*.*");
1051 hFindFile = FindFirstFile(x_path, &fData);
1052 if (hFindFile == INVALID_HANDLE_VALUE)
1053 return 0;
1054 do {
1055 if (fData.cFileName[0] != '.' ||
1056 (fData.cFileName[1] != '.' && fData.cFileName[1] != '\0'))
1057 ValNodeCopyStr
1058 (&vnp, (fData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0,
1059 fData.cFileName);
1060 } while ( FindNextFile(hFindFile, &fData) );
1061 FindClose(hFindFile);
1062 }}
1063 #endif
1064 #ifdef OS_UNIX
1065 #ifdef OS_UNIX_DARWIN
1066 dirp = opendir(pathname);
1067 if (dirp == NULL) return NULL;
1068 while ((dep = readdir(dirp)) != NULL) {
1069 /* ignore 'invisible' files. */
1070 if (dep->d_namlen < 1 || dep->d_name[0] == '.')
1071 continue;
1072 if (dep->d_type == DT_DIR) /* directory */
1073 choice = 1;
1074 else /* all other file types. */
1075 choice = 0;
1076 ValNodeCopyStr (&vnp, choice, dep->d_name);
1077 }
1078 closedir(dirp);
1079 #else
1080 sprintf (cmmd, "ls -1p %s 2>/dev/null", pathname);
1081 fp = popen (cmmd, "r");
1082 if (fp == NULL) return NULL;
1083 while (Nlm_FileGets (buf, sizeof (buf), fp) != NULL) {
1084 ptr = buf;
1085 ch = *ptr;
1086 while (ch != '\0' && ch != '\n' && ch != '\r') {
1087 ptr++;
1088 ch = *ptr;
1089 }
1090 *ptr = '\0';
1091 choice = 0;
1092 ptr = Nlm_StringChr (buf, '/');
1093 if (ptr != NULL) {
1094 *ptr = '\0';
1095 choice = 1;
1096 }
1097 ValNodeCopyStr (&vnp, choice, buf);
1098 }
1099 pclose (fp);
1100 #endif
1101 #endif
1102 #ifdef OS_VMS
1103 #endif
1104 }
1105 return vnp;
1106 }
1107
1108 /*****************************************************************************
1109 *
1110 * general file recursion functio
1111 *
1112 *****************************************************************************/
1113
Nlm_DirExplore(Nlm_CharPtr directory,Nlm_CharPtr filter,Nlm_CharPtr suffix,Nlm_Boolean recurse,Nlm_DirExpProc proc,Nlm_VoidPtr userdata)1114 NLM_EXTERN Nlm_Int4 Nlm_DirExplore (
1115 Nlm_CharPtr directory,
1116 Nlm_CharPtr filter,
1117 Nlm_CharPtr suffix,
1118 Nlm_Boolean recurse,
1119 Nlm_DirExpProc proc,
1120 Nlm_VoidPtr userdata
1121 )
1122
1123 {
1124 Nlm_Int4 count = 0;
1125 Nlm_Char file [FILENAME_MAX], path [PATH_MAX];
1126 size_t len, suflen = 0;
1127 Nlm_CharPtr ptr, str;
1128 ValNodePtr head, vnp;
1129
1130 if (proc == NULL) return 0;
1131 if (Nlm_StringHasNoText (directory) /* || Nlm_StringHasNoText (suffix) */ ) return 0;
1132
1133 if (Nlm_StringDoesHaveText (suffix)) {
1134 suflen = Nlm_StringLen (suffix);
1135 }
1136
1137 /* get list of all files in source directory */
1138
1139 head = Nlm_DirCatalog (directory);
1140
1141 for (vnp = head; vnp != NULL; vnp = vnp->next) {
1142 if (vnp->choice == 0) {
1143 str = (Nlm_CharPtr) vnp->data.ptrvalue;
1144 if (! Nlm_StringHasNoText (str)) {
1145
1146 /* check end of filename for indicated suffix */
1147
1148 len = Nlm_StringLen (str);
1149 ptr = NULL;
1150 if (len > suflen) {
1151 if (Nlm_StringCmp (str + len - suflen, suffix) == 0) {
1152 ptr = str + len - suflen;
1153 *ptr = '\0';
1154 }
1155 }
1156
1157 if (Nlm_StringHasNoText (suffix) || ptr != NULL) {
1158
1159 Nlm_StringNCpy_0 (path, directory, sizeof (path));
1160 sprintf (file, "%s%s", str, suffix);
1161 Nlm_FileBuildPath (path, NULL, file);
1162
1163 /* check file name (NOT full path) for desired filter */
1164
1165 if (Nlm_StringHasNoText (filter) || Nlm_StringStr (file, filter) != NULL) {
1166
1167 /* process file that satisfies optional filter and suffix constraints */
1168
1169 proc (path, userdata);
1170 count++;
1171 }
1172 }
1173 }
1174 } else if (vnp->choice == 1 && recurse) {
1175
1176 /* recurse into subdirectory */
1177
1178 Nlm_StringNCpy_0 (path, directory, sizeof (path));
1179 str = (Nlm_CharPtr) vnp->data.ptrvalue;
1180 Nlm_FileBuildPath (path, str, NULL);
1181
1182 count += Nlm_DirExplore (path, filter, suffix, recurse, proc, userdata);
1183 }
1184 }
1185
1186 /* clean up file list */
1187
1188 ValNodeFreeData (head);
1189
1190 return count;
1191 }
1192
1193 /*****************************************************************************
1194 *
1195 * TmpNam()
1196 *
1197 *****************************************************************************/
Nlm_TmpNam(Nlm_CharPtr s)1198 NLM_EXTERN Nlm_CharPtr LIBCALL Nlm_TmpNam (Nlm_CharPtr s)
1199
1200 {
1201 #ifdef TEMPNAM_AVAIL
1202 char *filename;
1203 static Nlm_Char save_filename[PATH_MAX];
1204
1205 /* emulate tmpnam(), except get the benefits of tempnam()'s ability to */
1206 /* place the files in another directory specified by the environment */
1207 /* variable TMPDIR */
1208 #ifdef OS_UNIX_DARWIN
1209 filename = tempnam("/tmp", "ncbi.");
1210 #else
1211 filename = tempnam(NULL, NULL);
1212 #endif
1213 if (s == NULL)
1214 { /* return pointer to static string */
1215 if (filename != NULL) {
1216 strcpy ((char *) save_filename, (char *) filename);
1217 free ((void *) filename);
1218 } else {
1219 save_filename [0] = '\0';
1220 }
1221 return save_filename;
1222 } else {
1223 if (filename != NULL) {
1224 strcpy ((char *) save_filename, (char *) filename);
1225 Nlm_StrCpy (s, save_filename);
1226 free ((void *) filename);
1227 } else {
1228 *s = '\0';
1229 }
1230 return s;
1231 }
1232 #else
1233 #ifdef OS_MAC
1234 static Nlm_Char directory [PATH_MAX];
1235 OSErr err;
1236 long gesResponse;
1237 long newDirID;
1238 short newVRefNum;
1239 CInfoPBRec params;
1240 Nlm_Char temp [PATH_MAX];
1241 Nlm_CharPtr tmp;
1242 Nlm_Boolean useTempFolder;
1243 char * filename;
1244
1245 useTempFolder = FALSE;
1246 if (! Gestalt (gestaltFindFolderAttr, &gesResponse) &&
1247 (gesResponse & (1 << gestaltFindFolderPresent))) {
1248 err = FindFolder(kOnSystemDisk, kTemporaryFolderType,
1249 kCreateFolder, &newVRefNum, &newDirID);
1250 if (err == noErr) {
1251 useTempFolder = TRUE;
1252 }
1253 }
1254 filename = tmpnam (NULL);
1255 if (useTempFolder) {
1256 temp [0] = '\0';
1257 params.dirInfo.ioNamePtr = (StringPtr) directory;
1258 params.dirInfo.ioDrParID = newDirID;
1259 do {
1260 params.dirInfo.ioVRefNum = newVRefNum;
1261 params.dirInfo.ioFDirIndex = -1;
1262 params.dirInfo.ioDrDirID = params.dirInfo.ioDrParID;
1263 err = PBGetCatInfo (¶ms, FALSE);
1264 Nlm_PtoCstr ((Nlm_CharPtr) directory);
1265 Nlm_StringCat (directory, DIRDELIMSTR);
1266 Nlm_StringCat (directory, temp);
1267 Nlm_StringCpy (temp, directory);
1268 } while (params.dirInfo.ioDrDirID != fsRtDirID);
1269 tmp = Nlm_StringMove (directory, temp);
1270 tmp = Nlm_StringMove (tmp, (Nlm_CharPtr) filename);
1271 if (s == NULL) {
1272 return (Nlm_CharPtr) directory;
1273 } else {
1274 s [0] = '\0';
1275 Nlm_StringCpy (s, directory);
1276 return s;
1277 }
1278 } else {
1279 if (s == NULL) {
1280 return (Nlm_CharPtr) filename;
1281 } else {
1282 s [0] = '\0';
1283 Nlm_StringCpy (s, filename);
1284 return s;
1285 }
1286 }
1287 #else
1288 char * filename;
1289
1290 filename = tmpnam (NULL);
1291 if (s == NULL) {
1292 return (Nlm_CharPtr) filename;
1293 } else {
1294 s [0] = '\0';
1295 Nlm_StringCpy (s, filename);
1296 return s;
1297 }
1298 #endif
1299 #endif
1300 }
1301
1302 /* FileCache provides buffered text read for handling Unix, Mac, and DOS line endings gracefully */
1303
1304 /* attach file pointer (text read mode expected) to cache object (usually on stack) */
1305
1306 #ifdef OS_MSWIN
1307 #include <fcntl.h>
1308 #include <io.h>
1309 #endif
1310
Nlm_FileCacheSetup(Nlm_FileCache PNTR fcp,FILE * fp)1311 NLM_EXTERN Nlm_Boolean Nlm_FileCacheSetup (
1312 Nlm_FileCache PNTR fcp,
1313 FILE *fp
1314 )
1315
1316 {
1317 if (fp == NULL || fcp == NULL) return FALSE;
1318
1319 #ifdef OS_MSWIN
1320 _setmode (_fileno (fp), _O_BINARY);
1321 #endif
1322
1323 MemSet ((Nlm_VoidPtr) fcp, 0, sizeof (Nlm_FileCache));
1324
1325 fcp->failed = FALSE;
1326
1327 fcp->fp = fp;
1328 fcp->offset = ftell (fp);
1329
1330 if (fcp->offset < 0) {
1331 fcp->failed = TRUE;
1332 return FALSE;
1333 }
1334
1335 return TRUE;
1336 }
1337
Nlm_FileCacheReadBlock(Nlm_FileCache PNTR fcp)1338 static void Nlm_FileCacheReadBlock (
1339 Nlm_FileCache PNTR fcp
1340 )
1341
1342 {
1343 int total;
1344
1345 if (fcp == NULL || fcp->fp == NULL || fcp->failed) return;
1346
1347 if (fcp->ctr >= fcp->total) {
1348 fcp->offset += (Nlm_Int4) fcp->total;
1349 fcp->ctr = 0;
1350 fcp->total = 0;
1351
1352 if (fcp->offset < 0) {
1353 fcp->failed = TRUE;
1354 ErrPostEx(SEV_WARNING,E_Programmer,0,"FileCacheReadBlock negative position %ld", (long) (fcp->offset));
1355 return;
1356 }
1357
1358 fcp->buf [0] = '\0';
1359 total = (int) Nlm_FileRead ((Nlm_VoidPtr) fcp->buf, sizeof (Nlm_Char), (size_t) 512, fcp->fp);
1360 if (total < 0 || total > 512) {
1361 total = 512;
1362 }
1363
1364 fcp->buf [total] = '\0';
1365 fcp->total = /* Nlm_StringLen (fcp->buf) */ total;
1366 }
1367 }
1368
1369 /* equivalent of getc */
1370
Nlm_FileCacheGetChar(Nlm_FileCache PNTR fcp)1371 static Nlm_Char Nlm_FileCacheGetChar (
1372 Nlm_FileCache PNTR fcp
1373 )
1374
1375 {
1376 Nlm_Char ch = '\0', nxt;
1377
1378 if (fcp == NULL || fcp->fp == NULL || fcp->failed) return ch;
1379
1380 /* read a fresh block if buffer is empty */
1381
1382 if (fcp->ctr >= fcp->total) {
1383 Nlm_FileCacheReadBlock (fcp);
1384 if (fcp->failed) return '\0';
1385 }
1386
1387 /* get next character in buffer */
1388
1389 if (fcp->ctr < fcp->total) {
1390 ch = fcp->buf [(int) fcp->ctr];
1391 (fcp->ctr)++;
1392 }
1393
1394 if (ch == '\n' || ch == '\r') {
1395
1396 /* look for carriage return / linefeed pair - DOS file read on Mac or Unix platform */
1397
1398 if (fcp->ctr >= fcp->total) {
1399 Nlm_FileCacheReadBlock (fcp);
1400 if (fcp->failed) return '\0';
1401 }
1402 if (fcp->ctr < fcp->total) {
1403
1404 nxt = fcp->buf [(int) fcp->ctr];
1405
1406 /* advance past second character in cr/lf pair */
1407
1408 if (ch == '\n' && nxt == '\r') {
1409 (fcp->ctr)++;
1410 } else if (ch == '\r' && nxt == '\n') {
1411 (fcp->ctr)++;
1412 }
1413 }
1414
1415 /* cr or lf returned as newline */
1416
1417 ch = '\n';
1418
1419 } else if (ch == '\0') {
1420
1421 /* look for unicode carriage return / linefeed */
1422
1423 if (fcp->ctr >= fcp->total) {
1424 Nlm_FileCacheReadBlock (fcp);
1425 if (fcp->failed) return '\0';
1426 }
1427 if (fcp->ctr < fcp->total) {
1428
1429 nxt = fcp->buf [(int) fcp->ctr];
1430
1431 /* return newline if second character is cr or lf */
1432
1433 if (nxt == '\n' || nxt == '\r') {
1434 (fcp->ctr)++;
1435 ch = '\n';
1436 }
1437 }
1438 }
1439
1440 return ch;
1441 }
1442
1443 /* equivalent of fgets, leaves /n at end of string */
1444
Nlm_FileCacheGetString(Nlm_FileCache PNTR fcp,Nlm_CharPtr str,size_t size)1445 NLM_EXTERN Nlm_CharPtr Nlm_FileCacheGetString (
1446 Nlm_FileCache PNTR fcp,
1447 Nlm_CharPtr str,
1448 size_t size
1449 )
1450
1451 {
1452 Nlm_Char ch;
1453 Nlm_Uint2 count;
1454 Nlm_CharPtr ptr;
1455
1456 if (fcp == NULL || fcp->fp == NULL || fcp->failed || str == NULL || size < 1) return NULL;
1457
1458 ch = Nlm_FileCacheGetChar (fcp);
1459 if (fcp->failed) return NULL;
1460 count = 0;
1461 ptr = str;
1462
1463 while (ch != '\0' && ch != '\n' && ch != '\r' && count < size - 2) {
1464 *ptr = ch;
1465 ptr++;
1466 count++;
1467 ch = Nlm_FileCacheGetChar (fcp);
1468 if (fcp->failed) return NULL;
1469 }
1470
1471 if (ch == '\n' || ch == '\r') {
1472 *ptr = '\n';
1473 ptr++;
1474 count++;
1475 } else if (ch != '\0') {
1476 *ptr = ch;
1477 ptr++;
1478 count++;
1479 }
1480 *ptr = '\0';
1481
1482 if (count < 1) return NULL;
1483
1484 return str;
1485 }
1486
1487 /* smarter fgets removes newline from end of string */
1488
Nlm_FileCacheReadLine(Nlm_FileCache PNTR fcp,Nlm_CharPtr str,size_t size,Nlm_BoolPtr nonewline)1489 NLM_EXTERN Nlm_CharPtr Nlm_FileCacheReadLine (
1490 Nlm_FileCache PNTR fcp,
1491 Nlm_CharPtr str,
1492 size_t size,
1493 Nlm_BoolPtr nonewline
1494 )
1495
1496 {
1497 Nlm_Char ch;
1498 Nlm_CharPtr ptr;
1499 Nlm_CharPtr tmp;
1500
1501 if (fcp == NULL || fcp->fp == NULL || fcp->failed || str == NULL || size < 1) return NULL;
1502 *str = '\0';
1503 tmp = Nlm_FileCacheGetString (fcp, str, size);
1504 if (fcp->failed) return NULL;
1505 if (tmp != NULL) {
1506 ptr = str;
1507 ch = *ptr;
1508 while (ch != '\0' && ch != '\n' && ch != '\r') {
1509 ptr++;
1510 ch = *ptr;
1511 }
1512 *ptr = '\0';
1513 if (nonewline != NULL) {
1514 if (ch != '\n' && ch != '\r') {
1515 *nonewline = TRUE;
1516 } else {
1517 *nonewline = FALSE;
1518 }
1519 }
1520 }
1521 return tmp;
1522 }
1523
Nlm_FileCacheSeek(Nlm_FileCache PNTR fcp,Nlm_Int4 pos)1524 NLM_EXTERN void Nlm_FileCacheSeek (
1525 Nlm_FileCache PNTR fcp,
1526 Nlm_Int4 pos
1527 )
1528
1529 {
1530 if (fcp == NULL || fcp->fp == NULL || fcp->failed) return;
1531
1532 /*
1533 if (fcp->offset <= pos && fcp->offset + (Nlm_Int4) fcp->total >= pos) {
1534 fcp->ctr = (Nlm_Int2) (pos - fcp->offset);
1535 return;
1536 }
1537 */
1538
1539 fcp->ctr = 0;
1540 fcp->total = 0;
1541 fcp->offset = pos;
1542
1543 if (fcp->offset < 0) {
1544 fcp->failed = TRUE;
1545 ErrPostEx(SEV_WARNING,E_Programmer,0,"FileCacheSeek negative position %ld", (long) (fcp->offset));
1546 return;
1547 }
1548
1549 fseek (fcp->fp, pos, SEEK_SET);
1550 }
1551
Nlm_FileCacheTell(Nlm_FileCache PNTR fcp)1552 NLM_EXTERN Nlm_Int4 Nlm_FileCacheTell (
1553 Nlm_FileCache PNTR fcp
1554 )
1555
1556 {
1557 Nlm_Int4 bytes;
1558 Nlm_Int4 offset;
1559
1560 if (fcp == NULL || fcp->fp == NULL || fcp->failed) return 0L;
1561
1562 offset = ftell (fcp->fp);
1563 bytes = (Nlm_Int4) (fcp->total - fcp->ctr);
1564 offset -= bytes;
1565
1566 return offset;
1567 }
1568
Nlm_FileCacheFree(Nlm_FileCache PNTR fcp,Nlm_Boolean restoreFilePos)1569 NLM_EXTERN Nlm_Boolean Nlm_FileCacheFree (
1570 Nlm_FileCache PNTR fcp,
1571 Nlm_Boolean restoreFilePos
1572 )
1573
1574 {
1575 Nlm_Int4 pos;
1576
1577 if (fcp == NULL || fcp->fp == NULL || fcp->failed) return FALSE;
1578
1579 if (restoreFilePos) {
1580
1581 /* correct position of file pointer */
1582
1583 pos = Nlm_FileCacheTell (fcp);
1584 fseek (fcp->fp, pos, SEEK_SET);
1585 }
1586
1587 MemSet ((Nlm_VoidPtr) fcp, 0, sizeof (Nlm_FileCache));
1588
1589 return TRUE;
1590 }
1591
1592