/* ncbifile.c * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * File Name: ncbifile.c * * Author: Gish, Kans, Ostell, Schuler * * Version Creation Date: 3/4/91 * * $Revision: 6.46 $ * * File Description: * portable file routines * * Modifications: * -------------------------------------------------------------------------- * Date Name Description of modification * ------- ---------- ----------------------------------------------------- * * ========================================================================== */ #define THIS_MODULE g_corelib #define THIS_FILE _this_file #include #include #include "corepriv.h" #ifdef OS_MAC #ifdef OS_UNIX_DARWIN #include #endif #include #include #endif #ifdef OS_UNIX_SUN #define DEFAULT_CDROM "/dev/sr0" #define DEFAULT_RAW_CDROM "/dev/rsr0" #endif #if defined(PROC_MIPS) && !defined(OS_UNIX_LINUX) #define DEFAULT_CDROM "/dev/scsi/sc0d4l0" #endif #ifdef OS_UNIX #ifndef DEFAULT_CDROM #define DEFAULT_CDROM "/dev/cdrom" #endif #endif #if defined(OS_MSWIN) || defined (OS_NT) #ifdef COMP_MSC #ifndef mkdir #define mkdir _mkdir #endif #ifndef stat #define stat _stat #endif #endif #endif #ifdef OS_VMS #ifndef DEFAULT_CDROM #define DEFAULT_CDROM "cdrom:" #endif #endif extern char *g_corelib; static char * _this_file = __FILE__; #ifdef OS_MAC #define INLINE_MOREFILES /* #include "FullPath.h" */ /* #include "MoreFilesExtra.h" */ #ifdef INLINE_MOREFILES /* MoreFilesExtras.c */ /* ----------------- */ /* ** Apple Macintosh Developer Technical Support ** ** A collection of useful high-level File Manager routines. ** ** by Jim Luther, Apple Developer Technical Support Emeritus ** ** File: MoreFilesExtras.c ** ** Copyright (c) 1992-1999 Apple Computer, Inc. ** All rights reserved. ** ** You may incorporate this sample code into your applications without ** restriction, though the sample code has been provided "AS IS" and the ** responsibility for its operation is 100% yours. However, what you are ** not permitted to do is to redistribute the source as "DSC Sample Code" ** after having made changes. If you're going to re-distribute the source, ** we require that you make it clear in the source that the code was ** descended from Apple Sample Code, but that you've made changes. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define __COMPILINGMOREFILES #if 0 #include "MoreFiles.h" #include "MoreFilesExtras.h" #include "MoreDesktopMgr.h" #include "FSpCompat.h" #endif /* ** GetVolumeInfoNoName uses pathname and vRefNum to call PBHGetVInfoSync ** in cases where the returned volume name is not needed by the caller. ** The pathname and vRefNum parameters are not touched, and the pb ** parameter is initialized by PBHGetVInfoSync except that ioNamePtr in ** the parameter block is always returned as NULL (since it might point ** to the local tempPathname). ** ** I noticed using this code in several places, so here it is once. ** This reduces the code size of MoreFiles. */ static pascal OSErr GetVolumeInfoNoName(ConstStr255Param pathname, short vRefNum, HParmBlkPtr pb) { Str255 tempPathname; OSErr error; /* Make sure pb parameter is not NULL */ if ( pb != NULL ) { pb->volumeParam.ioVRefNum = vRefNum; if ( pathname == NULL ) { pb->volumeParam.ioNamePtr = NULL; pb->volumeParam.ioVolIndex = 0; /* use ioVRefNum only */ } else { BlockMoveData(pathname, tempPathname, pathname[0] + 1); /* make a copy of the string and */ pb->volumeParam.ioNamePtr = (StringPtr)tempPathname; /* use the copy so original isn't trashed */ pb->volumeParam.ioVolIndex = -1; /* use ioNamePtr/ioVRefNum combination */ } error = PBHGetVInfoSync(pb); pb->volumeParam.ioNamePtr = NULL; /* ioNamePtr may point to local tempPathname, so don't return it */ } else { error = paramErr; } return ( error ); } /*****************************************************************************/ static pascal OSErr DetermineVRefNum(ConstStr255Param pathname, short vRefNum, short *realVRefNum) { HParamBlockRec pb; OSErr error; error = GetVolumeInfoNoName(pathname,vRefNum, &pb); if ( error == noErr ) { *realVRefNum = pb.volumeParam.ioVRefNum; } return ( error ); } /*****************************************************************************/ static pascal OSErr GetCatInfoNoName(short vRefNum, long dirID, ConstStr255Param name, CInfoPBPtr pb) { Str31 tempName; OSErr error; /* Protection against File Sharing problem */ if ( (name == NULL) || (name[0] == 0) ) { tempName[0] = 0; pb->dirInfo.ioNamePtr = tempName; pb->dirInfo.ioFDirIndex = -1; /* use ioDirID */ } else { pb->dirInfo.ioNamePtr = (StringPtr)name; pb->dirInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ } pb->dirInfo.ioVRefNum = vRefNum; pb->dirInfo.ioDrDirID = dirID; error = PBGetCatInfoSync(pb); pb->dirInfo.ioNamePtr = NULL; return ( error ); } /*****************************************************************************/ static pascal OSErr GetDirectoryID(short vRefNum, long dirID, ConstStr255Param name, long *theDirID, Boolean *isDirectory) { CInfoPBRec pb; OSErr error; error = GetCatInfoNoName(vRefNum, dirID, name, &pb); if ( error == noErr ) { *isDirectory = (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0; if ( *isDirectory ) { *theDirID = pb.dirInfo.ioDrDirID; } else { *theDirID = pb.hFileInfo.ioFlParID; } } return ( error ); } /*****************************************************************************/ static pascal OSErr FSpGetDirectoryID(const FSSpec *spec, long *theDirID, Boolean *isDirectory) { return ( GetDirectoryID(spec->vRefNum, spec->parID, spec->name, theDirID, isDirectory) ); } #endif /* INLINE_MOREFILES */ #endif /* OS_MAC */ /***************************************************************************** * * Macintosh file utilities * *****************************************************************************/ #ifdef OS_MAC static OSErr MacPathname2FSSpec(const char *inPathname, FSSpec *outFSS) { OSErr err; size_t len; char *p; short vRefNum; long dirID; FSSpec fss; if (inPathname == NULL || outFSS == NULL) { return paramErr; } err = HGetVol(NULL, &vRefNum, &dirID); /* default volume and directory */ if (err != noErr) return err; len = strlen(inPathname); p = strchr(inPathname, ':'); if (p == NULL) { /* Partial pathname -- filename only */ Str31 filename; assert(len <= 31); c2pstrcpy(filename, inPathname); err = FSMakeFSSpec(vRefNum, dirID, filename, outFSS); } else { Str31 name; int nameLen; if (inPathname[0] == ':') { /* Relative pathname including directory path */ } else { /* Absolute pathname */ /* Str31 volName; We would use Str28 if it was defined -- 27, plus 1 for ':'. */ nameLen = p - inPathname; assert(nameLen <= 27); name[0] = nameLen + 1; memcpy(name + 1, inPathname, nameLen + 1); /* Copy the volume name and the colon. */ err = DetermineVRefNum(name, 0, &vRefNum); if (err != noErr) return err; dirID = 2; } /* vRefNum and dirID now specify the directory in which we should descend the path pointed to by p (pointing to the first colon). */ p++; while (p != NULL && *p != '\0') { char *q = strchr(p, ':'); if (q != NULL) { Boolean isDir; nameLen = q - p; assert(nameLen <= 31); name[0] = nameLen; memcpy(name + 1, p, nameLen); err = FSMakeFSSpec(vRefNum, dirID, name, &fss); if (err != noErr) return err; if (q[1] == '\0') { p = NULL; *outFSS = fss; } else { err = FSpGetDirectoryID(&fss, &dirID, &isDir); assert(isDir == true); if (err != noErr) return err; p = q + 1; } } else { q = strchr(p, '\0'); /* go to end of string */ nameLen = q - p; assert(nameLen > 0); assert(nameLen <= 31); c2pstrcpy(name, p); p = NULL; err = FSMakeFSSpec(vRefNum, dirID, name, outFSS); } } } return err; } #if 0 static OSErr MacFSSpec2FullPathname(const FSSpec *inFSS, char **outPathname) { OSErr err; Handle h; short fullPathLength; static char *fullPath = NULL; if (fullPath != NULL) { Nlm_Free(fullPath); fullPath = NULL; } err = FSpGetFullPath(inFSS, &fullPathLength, &h); if (err != noErr) return err; assert(fullPathLength >= 2); /* An absolute pathname must be at least two chars long */ fullPath = (char *)Nlm_Malloc(fullPathLength + 1); if (fullPath == NULL) { err = memFullErr; } else { strncpy(fullPath, *h, fullPathLength); } DisposeHandle(h); *outPathname = fullPath; return err; } #endif static OSErr MacCreateDirectory(const char *inPathname) { OSErr err; FSSpec fss; ScriptCode scriptTag = 0; long createdDirID; err = MacPathname2FSSpec(inPathname, &fss); if (err != noErr) return err; err = FSpDirCreate(&fss, scriptTag, &createdDirID); return err; } #endif /***************************************************************************** * * FileOpen(filename, mode) * if (filename == "stdin" or "stdout" or "stderr" * returns those predefined * streams on non-windowing systems) * *****************************************************************************/ /* p_churchill 12/99 removed MPW conditional compilation */ static Nlm_FileOpenHook _hookFile = NULL; NLM_EXTERN FILE * LIBCALL Nlm_FileOpen(const char *filename, const char *mode) { FILE *f = NULL; if ( _hookFile ) return _hookFile(filename, mode); #if defined(WIN_DUMB) if ( Nlm_HasConsole ) { if ( !StringCmp("stdin", filename)) f = stdin; else if ( !StringCmp("stdout", filename) ) f = stdout; else if ( !StringCmp("stderr", filename)) f = stderr; else f = fopen(filename, mode); #if defined(WIN32) && ! defined(COMP_METRO) if (strchr(mode, 'b') && (f == stdin || f == stdout || f == stderr)) setmode(fileno(f), O_BINARY); #endif } else f = fopen(filename, mode); #elif defined(OS_MAC) { OSType fCreator; Nlm_Int2 fError; FInfo fInfo; OSType fType; Nlm_Char temp [256]; Nlm_StringNCpy_0(temp, filename, sizeof(temp)); Nlm_CtoPstr ((Nlm_CharPtr) temp); fError = HGetFInfo( 0, 0, (StringPtr) temp, &fInfo); if (fError == noErr) { fCreator = fInfo.fdCreator; fType = fInfo.fdType; } else { fCreator = ' '; if (strchr(mode, 'b') != NULL) fType = ' '; else fType = 'TEXT'; } f = fopen( filename, mode); fError = HGetFInfo( 0, 0, (StringPtr) temp, &fInfo); if (fError == noErr) { fInfo.fdCreator = fCreator; fInfo.fdType = fType; fError = HSetFInfo ( 0, 0, (StringPtr) temp,&fInfo); } } /* def OS_MAC */ #elif defined(OS_VMS) && defined(DCC4DW12) /* never used */ f = fopen (filename, mode); if (f && fstat(fileno(f), &statbuf) == 0 && statbuf.st_fab_rfm == FAB$C_UDF) { fclose(f); f = fopen(filename,mode,"ctx=stm"); } #else f = fopen(filename, mode); #endif if (f == NULL) ErrPostEx(SEV_INFO, E_File, E_FOpen, "FileOpen(\"%s\",\"%s\") failed", filename, mode); return f; } /***************************************************************************** * * SetFileOpenHook(hook) * *****************************************************************************/ NLM_EXTERN void LIBCALL Nlm_SetFileOpenHook (Nlm_FileOpenHook hook) { _hookFile = hook; } /***************************************************************************** * * FileClose(fp) * *****************************************************************************/ NLM_EXTERN void LIBCALL Nlm_FileClose (FILE *stream) { if (stream == NULL) return; #ifdef WIN_DUMB if (stream == stdin || stream == stdout || stream == stderr) { #if defined(WIN32) && ! defined(COMP_METRO) setmode(fileno(stream), O_TEXT); #endif return; } #endif fclose(stream); } /***************************************************************************** * FileRead(buf, size, fp) *****************************************************************************/ NLM_EXTERN size_t LIBCALL Nlm_FileRead (void *ptr, size_t size, size_t n, FILE *stream) { if (n && (SIZE_MAX / n) < size) { ErrPostEx(SEV_WARNING,E_Programmer,0,"FileRead: size > SIZE_MAX"); return 0; } if (!ptr || !stream) return 0; return fread(ptr,size,n,stream); } /***************************************************************************** * FileWrite(buf, size, fp) *****************************************************************************/ NLM_EXTERN size_t LIBCALL Nlm_FileWrite (const void *ptr, size_t size, size_t n, FILE *stream) { size_t cnt; if (n && (SIZE_MAX / n) < size) { ErrPostEx(SEV_WARNING,E_Programmer,0,"FileWrite: size > SIZE_MAX"); return 0; } if (!ptr || !stream || !size) return 0; cnt = fwrite(ptr,size,n,stream); if (cnt != n) ErrPostEx(SEV_FATAL,E_File,E_FWrite,"File write error"); return cnt; } /***************************************************************************** * * FilePuts(ptr, fp) * *****************************************************************************/ NLM_EXTERN int LIBCALL Nlm_FilePuts (const char *ptr, FILE *fp) { int retval; if ((ptr == NULL) || (fp == NULL)) return EOF; if ((retval = fputs(ptr,fp)) ==EOF) ErrPostEx(SEV_FATAL,E_File,E_FWrite,"File write error"); return retval; } /***************************************************************************** * * FileGets() * *****************************************************************************/ NLM_EXTERN char * LIBCALL Nlm_FileGets (Nlm_CharPtr ptr, size_t size, FILE *fp) { #if defined(OS_MAC) || defined (OS_UNIX_DARWIN) int ch; int count; Nlm_CharPtr tmp; #endif if ((ptr == NULL) || (size < 1) || (fp == NULL)) return NULL; #if defined(OS_MAC) || defined (OS_UNIX_DARWIN) ch = fgetc (fp); count = 0; tmp = ptr; while (ch != EOF && ch != '\0' && ch != '\n' && ch != '\r' && count < size - 2) { *tmp = ch; tmp++; count++; ch = fgetc (fp); } if (ch == '\n' || ch == '\r') { *tmp = '\n'; tmp++; count++; } else if (ch != EOF && ch != '\0') { *tmp = ch; tmp++; count++; } *tmp = '\0'; if (count < 1) return NULL; return ptr; #else return fgets(ptr,size,fp); #endif } /***************************************************************************** * * FileBuildPath() * *****************************************************************************/ NLM_EXTERN Nlm_CharPtr LIBCALL Nlm_FileBuildPath (Nlm_CharPtr root, Nlm_CharPtr sub_path, Nlm_CharPtr filename) { Nlm_CharPtr tmp; Nlm_Boolean dir_start = FALSE; #ifdef OS_VMS Nlm_Boolean had_root = FALSE; #endif if (root == NULL) /* no place to put it */ return NULL; tmp = root; if (*tmp != '\0') /* if not empty */ { #ifndef OS_VMS dir_start = TRUE; #else had_root = TRUE; #endif while (*tmp != '\0') { #ifdef OS_VMS if (*tmp == '[') dir_start = TRUE; #endif tmp++; } if ((*(tmp - 1) != DIRDELIMCHR) && (dir_start)) { *tmp = DIRDELIMCHR; tmp++; *tmp = '\0'; } } if (sub_path != NULL) { #ifdef OS_VMS if (dir_start) { *(tmp-1) = '.'; if (*sub_path == '[') sub_path++; } else if ((had_root) && (*sub_path != '[')) { *tmp = '['; tmp++; *tmp = '\0'; } #else if ((dir_start) && (*sub_path == DIRDELIMCHR)) sub_path++; #endif tmp = StringMove(tmp, sub_path); if (*(tmp-1) != DIRDELIMCHR) { *tmp = DIRDELIMCHR; tmp++; *tmp = '\0'; } } if (filename != NULL) StringMove(tmp, filename); return root; } /***************************************************************************** * * FileNameFind() * *****************************************************************************/ NLM_EXTERN Nlm_CharPtr LIBCALL Nlm_FileNameFind (Nlm_CharPtr pathname) { Nlm_CharPtr filename; Nlm_Int2 len; if (pathname != NULL) { len = Nlm_StringLen (pathname); filename = &(pathname [len]); while (len > 0 && pathname [len - 1] != DIRDELIMCHR) { len--; filename--; } return filename; } else { return NULL; } } /***************************************************************************** * * FilePathFind() * *****************************************************************************/ NLM_EXTERN Nlm_CharPtr LIBCALL Nlm_FilePathFind(const Nlm_Char* fullname) { Nlm_CharPtr str; size_t len = Nlm_StringLen(fullname); if ( !len ) return 0; while (len && fullname[len] != DIRDELIMCHR) len--; str = (Nlm_Char*)Nlm_MemGet(len + 1, MGET_ERRPOST); Nlm_MemCpy(str, fullname, len); str[len] = '\0'; return str; } /***************************************************************************** * * FileLength() * *****************************************************************************/ NLM_EXTERN Nlm_Int8 LIBCALL Nlm_FileLength(Nlm_CharPtr fileName) { Nlm_Int8 file_len = Nlm_FileLengthEx(fileName); return (file_len > 0) ? file_len : 0; } /***************************************************************************** * * FileLengthEx() * *****************************************************************************/ NLM_EXTERN Nlm_Int8 LIBCALL Nlm_FileLengthEx(const Nlm_Char* fileName) { if (!fileName || !*fileName) return -1; #ifdef OS_MAC {{ OSErr err; HParamBlockRec params; Nlm_Char path[256]; Nlm_MemSet ((Nlm_VoidPtr) ¶ms, 0, sizeof (HParamBlockRec)); Nlm_StringNCpy_0(path, fileName, sizeof(path)); Nlm_CtoPstr((Nlm_CharPtr) path); params.fileParam.ioNamePtr = (StringPtr)path; params.fileParam.ioVRefNum = 0; params.fileParam.ioFDirIndex = 0; err = PBHGetFInfo(¶ms, FALSE); return (err == noErr) ? params.fileParam.ioFlLgLen : -1; }} #else {{ struct stat sbuf; return (stat(fileName, &sbuf) == 0) ? sbuf.st_size : -1; }} #endif } /***************************************************************************** * * FileDelete() * *****************************************************************************/ NLM_EXTERN Nlm_Boolean LIBCALL Nlm_FileRemove (Nlm_CharPtr fileName) { Nlm_Char local [256]; if (fileName != NULL && fileName [0] != '\0') { Nlm_StringNCpy_0(local, fileName, sizeof(local)); return (Nlm_Boolean) (remove (local) == 0); } else { return FALSE; } } /***************************************************************************** * * FileRename() * *****************************************************************************/ NLM_EXTERN Nlm_Boolean LIBCALL Nlm_FileRename (Nlm_CharPtr oldFileName, Nlm_CharPtr newFileName) { Nlm_Char localnew [256]; Nlm_Char localold [256]; if (oldFileName != NULL && oldFileName [0] != '\0' && newFileName != NULL && newFileName [0] != '\0') { Nlm_StringNCpy_0(localold, oldFileName, sizeof(localold)); Nlm_StringNCpy_0(localnew, newFileName, sizeof(localnew)); return (Nlm_Boolean) (rename (localold, localnew) == 0); } else { return FALSE; } } /***************************************************************************** * * FileCreate() * *****************************************************************************/ #ifdef OS_MAC static OSType Nlm_GetOSType (Nlm_CharPtr str, OSType dfault) { OSType rsult; rsult = dfault; if (str != NULL && str [0] != '\0') { rsult = *(OSType*) str; } return rsult; } #endif NLM_EXTERN void LIBCALL Nlm_FileCreate (Nlm_CharPtr fileName, Nlm_CharPtr type, Nlm_CharPtr creator) { #ifdef OS_MAC Nlm_Int2 fError; Nlm_Char temp [256]; OSType fType; OSType fCreator; FSSpec spec; #else FILE *fp; #endif if (fileName != NULL && fileName [0] != '\0') { #ifdef OS_MAC /* note: the following assumes either full pathname or that the current directory is the proper location to find/create the file */ Nlm_StringNCpy_0(temp, fileName, sizeof(temp)); Nlm_CtoPstr ( temp); fError = FSMakeFSSpec( 0, 0, (StringPtr)temp, &spec); /* file not found, so create it... */ if( fError == fnfErr){ fType = Nlm_GetOSType (type, 'TEXT'); fCreator = Nlm_GetOSType (creator, ' '); FSpCreate( &spec, fCreator, fType, smSystemScript); } #else fp = Nlm_FileOpen (fileName, "w"); if (fp != NULL) { Nlm_FileClose (fp); } #endif } } /***************************************************************************** * * CreateDir(pathname) * *****************************************************************************/ #ifdef OS_MAC NLM_EXTERN Nlm_Boolean LIBCALL Nlm_CreateDir (Nlm_CharPtr pathname) { if (pathname != NULL && pathname [0] != '\0') { OSErr err; err = MacCreateDirectory(pathname); return (Nlm_Boolean) (err == noErr || err == dupFNErr); } return FALSE; } #endif #ifndef OS_MAC NLM_EXTERN Nlm_Boolean LIBCALL Nlm_CreateDir (Nlm_CharPtr pathname) { #ifndef OS_VMS size_t len; Nlm_Char path[PATH_MAX]; #endif #ifdef OS_UNIX mode_t oldmask; #endif Nlm_Boolean rsult = FALSE; if (pathname != NULL && pathname [0] != '\0') { #if defined(OS_MSWIN) || defined(OS_NT) Nlm_StringNCpy_0(path, pathname, sizeof(path)); len = Nlm_StringLen (path); if (len > 0 && path [len - 1] == DIRDELIMCHR) { path [len - 1] = '\0'; } rsult = (Nlm_Boolean) (mkdir ((char *) path) == 0); if (errno == EACCES) { /* it's O.K. if it was already there */ rsult = TRUE; } #endif #ifdef OS_UNIX oldmask = umask (0000); Nlm_StringNCpy_0(path, pathname, sizeof(path)); len = Nlm_StringLen (path); if (len > 0 && path [len - 1] == DIRDELIMCHR) { path [len - 1] = '\0'; } rsult = (Nlm_Boolean) (mkdir ((char *) path, 0755) == 0); if (errno == EEXIST) { /* it's O.K. if it was already there */ rsult = TRUE; } umask (oldmask); #endif #ifdef OS_VMS rsult = (Nlm_Boolean) (mkdir ((char *) pathname, 0755) == 0); #endif } return rsult; } #endif /***************************************************************************** * * DirectoryContents() * *****************************************************************************/ #ifdef OS_UNIX_DARWIN #include #endif NLM_EXTERN ValNodePtr LIBCALL Nlm_DirCatalog (Nlm_CharPtr pathname) { #ifdef OS_MAC long dirID; OSErr err; short index; unsigned short num; Nlm_Char path[PATH_MAX]; CInfoPBRec pbc; HParamBlockRec pbh; short vRefNum; #endif #ifdef OS_UNIX Nlm_Uint1 choice; #ifdef OS_UNIX_DARWIN DIR *dirp; struct dirent *dep; #else Nlm_Char buf [256]; Nlm_Char ch; Nlm_Char cmmd [PATH_MAX + 20]; FILE *fp; Nlm_CharPtr ptr; #endif #endif ValNodePtr vnp = NULL; if (pathname != NULL && pathname [0] != '\0') { #ifdef OS_MAC Nlm_StringNCpy_0 (path, pathname, sizeof (path)); Nlm_CtoPstr ((Nlm_CharPtr) path); Nlm_MemSet ((Nlm_VoidPtr) (&pbh), 0, sizeof (HParamBlockRec)); pbh.volumeParam.ioNamePtr = (StringPtr) path; pbh.volumeParam.ioVolIndex = -1; err = PBHGetVInfo (&pbh, FALSE); if (err != noErr) return NULL; vRefNum = pbh.volumeParam.ioVRefNum; Nlm_StringNCpy_0 (path, pathname, sizeof (path)); Nlm_CtoPstr ((Nlm_CharPtr) path); Nlm_MemSet ((Nlm_VoidPtr) (&pbc), 0, sizeof (CInfoPBRec)); pbc.dirInfo.ioNamePtr = (StringPtr) path; pbc.dirInfo.ioVRefNum = vRefNum; err = PBGetCatInfo (&pbc, FALSE); if (err != noErr) return NULL; if (pbc.dirInfo.ioFlAttrib & 16) { num = pbc.dirInfo.ioDrNmFls; dirID = pbc.dirInfo.ioDrDirID; for (index = 1; index <= num; index++) { Nlm_MemSet ((Nlm_VoidPtr) (&pbc), 0, sizeof (CInfoPBRec)); pbc.dirInfo.ioNamePtr = (StringPtr) path; pbc.dirInfo.ioVRefNum = vRefNum; pbc.dirInfo.ioFDirIndex = index; pbc.dirInfo.ioDrDirID = dirID; pbc.dirInfo.ioACUser = 0; err = PBGetCatInfo (&pbc, FALSE); if (err == noErr) { Nlm_PtoCstr ((Nlm_CharPtr) path); if (pbc.dirInfo.ioFlAttrib & 16) { ValNodeCopyStr (&vnp, 1, path); } else { ValNodeCopyStr (&vnp, 0, path); } } } } #endif #if defined(WIN32) {{ Nlm_Char x_path[PATH_MAX]; WIN32_FIND_DATA fData; HANDLE hFindFile; Nlm_StringNCpy_0(x_path, pathname, sizeof(x_path) - 5); Nlm_StringCat(x_path, "\\*.*"); hFindFile = FindFirstFile(x_path, &fData); if (hFindFile == INVALID_HANDLE_VALUE) return 0; do { if (fData.cFileName[0] != '.' || (fData.cFileName[1] != '.' && fData.cFileName[1] != '\0')) ValNodeCopyStr (&vnp, (fData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0, fData.cFileName); } while ( FindNextFile(hFindFile, &fData) ); FindClose(hFindFile); }} #endif #ifdef OS_UNIX #ifdef OS_UNIX_DARWIN dirp = opendir(pathname); if (dirp == NULL) return NULL; while ((dep = readdir(dirp)) != NULL) { /* ignore 'invisible' files. */ if (dep->d_namlen < 1 || dep->d_name[0] == '.') continue; if (dep->d_type == DT_DIR) /* directory */ choice = 1; else /* all other file types. */ choice = 0; ValNodeCopyStr (&vnp, choice, dep->d_name); } closedir(dirp); #else sprintf (cmmd, "ls -1p %s 2>/dev/null", pathname); fp = popen (cmmd, "r"); if (fp == NULL) return NULL; while (Nlm_FileGets (buf, sizeof (buf), fp) != NULL) { ptr = buf; ch = *ptr; while (ch != '\0' && ch != '\n' && ch != '\r') { ptr++; ch = *ptr; } *ptr = '\0'; choice = 0; ptr = Nlm_StringChr (buf, '/'); if (ptr != NULL) { *ptr = '\0'; choice = 1; } ValNodeCopyStr (&vnp, choice, buf); } pclose (fp); #endif #endif #ifdef OS_VMS #endif } return vnp; } /***************************************************************************** * * general file recursion functio * *****************************************************************************/ NLM_EXTERN Nlm_Int4 Nlm_DirExplore ( Nlm_CharPtr directory, Nlm_CharPtr filter, Nlm_CharPtr suffix, Nlm_Boolean recurse, Nlm_DirExpProc proc, Nlm_VoidPtr userdata ) { Nlm_Int4 count = 0; Nlm_Char file [FILENAME_MAX], path [PATH_MAX]; size_t len, suflen = 0; Nlm_CharPtr ptr, str; ValNodePtr head, vnp; if (proc == NULL) return 0; if (Nlm_StringHasNoText (directory) /* || Nlm_StringHasNoText (suffix) */ ) return 0; if (Nlm_StringDoesHaveText (suffix)) { suflen = Nlm_StringLen (suffix); } /* get list of all files in source directory */ head = Nlm_DirCatalog (directory); for (vnp = head; vnp != NULL; vnp = vnp->next) { if (vnp->choice == 0) { str = (Nlm_CharPtr) vnp->data.ptrvalue; if (! Nlm_StringHasNoText (str)) { /* check end of filename for indicated suffix */ len = Nlm_StringLen (str); ptr = NULL; if (len > suflen) { if (Nlm_StringCmp (str + len - suflen, suffix) == 0) { ptr = str + len - suflen; *ptr = '\0'; } } if (Nlm_StringHasNoText (suffix) || ptr != NULL) { Nlm_StringNCpy_0 (path, directory, sizeof (path)); sprintf (file, "%s%s", str, suffix); Nlm_FileBuildPath (path, NULL, file); /* check file name (NOT full path) for desired filter */ if (Nlm_StringHasNoText (filter) || Nlm_StringStr (file, filter) != NULL) { /* process file that satisfies optional filter and suffix constraints */ proc (path, userdata); count++; } } } } else if (vnp->choice == 1 && recurse) { /* recurse into subdirectory */ Nlm_StringNCpy_0 (path, directory, sizeof (path)); str = (Nlm_CharPtr) vnp->data.ptrvalue; Nlm_FileBuildPath (path, str, NULL); count += Nlm_DirExplore (path, filter, suffix, recurse, proc, userdata); } } /* clean up file list */ ValNodeFreeData (head); return count; } /***************************************************************************** * * TmpNam() * *****************************************************************************/ NLM_EXTERN Nlm_CharPtr LIBCALL Nlm_TmpNam (Nlm_CharPtr s) { #ifdef TEMPNAM_AVAIL char *filename; static Nlm_Char save_filename[PATH_MAX]; /* emulate tmpnam(), except get the benefits of tempnam()'s ability to */ /* place the files in another directory specified by the environment */ /* variable TMPDIR */ #ifdef OS_UNIX_DARWIN filename = tempnam("/tmp", "ncbi."); #else filename = tempnam(NULL, NULL); #endif if (s == NULL) { /* return pointer to static string */ if (filename != NULL) { strcpy ((char *) save_filename, (char *) filename); free ((void *) filename); } else { save_filename [0] = '\0'; } return save_filename; } else { if (filename != NULL) { strcpy ((char *) save_filename, (char *) filename); Nlm_StrCpy (s, save_filename); free ((void *) filename); } else { *s = '\0'; } return s; } #else #ifdef OS_MAC static Nlm_Char directory [PATH_MAX]; OSErr err; long gesResponse; long newDirID; short newVRefNum; CInfoPBRec params; Nlm_Char temp [PATH_MAX]; Nlm_CharPtr tmp; Nlm_Boolean useTempFolder; char * filename; useTempFolder = FALSE; if (! Gestalt (gestaltFindFolderAttr, &gesResponse) && (gesResponse & (1 << gestaltFindFolderPresent))) { err = FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder, &newVRefNum, &newDirID); if (err == noErr) { useTempFolder = TRUE; } } filename = tmpnam (NULL); if (useTempFolder) { temp [0] = '\0'; params.dirInfo.ioNamePtr = (StringPtr) directory; params.dirInfo.ioDrParID = newDirID; do { params.dirInfo.ioVRefNum = newVRefNum; params.dirInfo.ioFDirIndex = -1; params.dirInfo.ioDrDirID = params.dirInfo.ioDrParID; err = PBGetCatInfo (¶ms, FALSE); Nlm_PtoCstr ((Nlm_CharPtr) directory); Nlm_StringCat (directory, DIRDELIMSTR); Nlm_StringCat (directory, temp); Nlm_StringCpy (temp, directory); } while (params.dirInfo.ioDrDirID != fsRtDirID); tmp = Nlm_StringMove (directory, temp); tmp = Nlm_StringMove (tmp, (Nlm_CharPtr) filename); if (s == NULL) { return (Nlm_CharPtr) directory; } else { s [0] = '\0'; Nlm_StringCpy (s, directory); return s; } } else { if (s == NULL) { return (Nlm_CharPtr) filename; } else { s [0] = '\0'; Nlm_StringCpy (s, filename); return s; } } #else char * filename; filename = tmpnam (NULL); if (s == NULL) { return (Nlm_CharPtr) filename; } else { s [0] = '\0'; Nlm_StringCpy (s, filename); return s; } #endif #endif } /* FileCache provides buffered text read for handling Unix, Mac, and DOS line endings gracefully */ /* attach file pointer (text read mode expected) to cache object (usually on stack) */ #ifdef OS_MSWIN #include #include #endif NLM_EXTERN Nlm_Boolean Nlm_FileCacheSetup ( Nlm_FileCache PNTR fcp, FILE *fp ) { if (fp == NULL || fcp == NULL) return FALSE; #ifdef OS_MSWIN _setmode (_fileno (fp), _O_BINARY); #endif MemSet ((Nlm_VoidPtr) fcp, 0, sizeof (Nlm_FileCache)); fcp->failed = FALSE; fcp->fp = fp; fcp->offset = ftell (fp); if (fcp->offset < 0) { fcp->failed = TRUE; return FALSE; } return TRUE; } static void Nlm_FileCacheReadBlock ( Nlm_FileCache PNTR fcp ) { int total; if (fcp == NULL || fcp->fp == NULL || fcp->failed) return; if (fcp->ctr >= fcp->total) { fcp->offset += (Nlm_Int4) fcp->total; fcp->ctr = 0; fcp->total = 0; if (fcp->offset < 0) { fcp->failed = TRUE; ErrPostEx(SEV_WARNING,E_Programmer,0,"FileCacheReadBlock negative position %ld", (long) (fcp->offset)); return; } fcp->buf [0] = '\0'; total = (int) Nlm_FileRead ((Nlm_VoidPtr) fcp->buf, sizeof (Nlm_Char), (size_t) 512, fcp->fp); if (total < 0 || total > 512) { total = 512; } fcp->buf [total] = '\0'; fcp->total = /* Nlm_StringLen (fcp->buf) */ total; } } /* equivalent of getc */ static Nlm_Char Nlm_FileCacheGetChar ( Nlm_FileCache PNTR fcp ) { Nlm_Char ch = '\0', nxt; if (fcp == NULL || fcp->fp == NULL || fcp->failed) return ch; /* read a fresh block if buffer is empty */ if (fcp->ctr >= fcp->total) { Nlm_FileCacheReadBlock (fcp); if (fcp->failed) return '\0'; } /* get next character in buffer */ if (fcp->ctr < fcp->total) { ch = fcp->buf [(int) fcp->ctr]; (fcp->ctr)++; } if (ch == '\n' || ch == '\r') { /* look for carriage return / linefeed pair - DOS file read on Mac or Unix platform */ if (fcp->ctr >= fcp->total) { Nlm_FileCacheReadBlock (fcp); if (fcp->failed) return '\0'; } if (fcp->ctr < fcp->total) { nxt = fcp->buf [(int) fcp->ctr]; /* advance past second character in cr/lf pair */ if (ch == '\n' && nxt == '\r') { (fcp->ctr)++; } else if (ch == '\r' && nxt == '\n') { (fcp->ctr)++; } } /* cr or lf returned as newline */ ch = '\n'; } else if (ch == '\0') { /* look for unicode carriage return / linefeed */ if (fcp->ctr >= fcp->total) { Nlm_FileCacheReadBlock (fcp); if (fcp->failed) return '\0'; } if (fcp->ctr < fcp->total) { nxt = fcp->buf [(int) fcp->ctr]; /* return newline if second character is cr or lf */ if (nxt == '\n' || nxt == '\r') { (fcp->ctr)++; ch = '\n'; } } } return ch; } /* equivalent of fgets, leaves /n at end of string */ NLM_EXTERN Nlm_CharPtr Nlm_FileCacheGetString ( Nlm_FileCache PNTR fcp, Nlm_CharPtr str, size_t size ) { Nlm_Char ch; Nlm_Uint2 count; Nlm_CharPtr ptr; if (fcp == NULL || fcp->fp == NULL || fcp->failed || str == NULL || size < 1) return NULL; ch = Nlm_FileCacheGetChar (fcp); if (fcp->failed) return NULL; count = 0; ptr = str; while (ch != '\0' && ch != '\n' && ch != '\r' && count < size - 2) { *ptr = ch; ptr++; count++; ch = Nlm_FileCacheGetChar (fcp); if (fcp->failed) return NULL; } if (ch == '\n' || ch == '\r') { *ptr = '\n'; ptr++; count++; } else if (ch != '\0') { *ptr = ch; ptr++; count++; } *ptr = '\0'; if (count < 1) return NULL; return str; } /* smarter fgets removes newline from end of string */ NLM_EXTERN Nlm_CharPtr Nlm_FileCacheReadLine ( Nlm_FileCache PNTR fcp, Nlm_CharPtr str, size_t size, Nlm_BoolPtr nonewline ) { Nlm_Char ch; Nlm_CharPtr ptr; Nlm_CharPtr tmp; if (fcp == NULL || fcp->fp == NULL || fcp->failed || str == NULL || size < 1) return NULL; *str = '\0'; tmp = Nlm_FileCacheGetString (fcp, str, size); if (fcp->failed) return NULL; if (tmp != NULL) { ptr = str; ch = *ptr; while (ch != '\0' && ch != '\n' && ch != '\r') { ptr++; ch = *ptr; } *ptr = '\0'; if (nonewline != NULL) { if (ch != '\n' && ch != '\r') { *nonewline = TRUE; } else { *nonewline = FALSE; } } } return tmp; } NLM_EXTERN void Nlm_FileCacheSeek ( Nlm_FileCache PNTR fcp, Nlm_Int4 pos ) { if (fcp == NULL || fcp->fp == NULL || fcp->failed) return; /* if (fcp->offset <= pos && fcp->offset + (Nlm_Int4) fcp->total >= pos) { fcp->ctr = (Nlm_Int2) (pos - fcp->offset); return; } */ fcp->ctr = 0; fcp->total = 0; fcp->offset = pos; if (fcp->offset < 0) { fcp->failed = TRUE; ErrPostEx(SEV_WARNING,E_Programmer,0,"FileCacheSeek negative position %ld", (long) (fcp->offset)); return; } fseek (fcp->fp, pos, SEEK_SET); } NLM_EXTERN Nlm_Int4 Nlm_FileCacheTell ( Nlm_FileCache PNTR fcp ) { Nlm_Int4 bytes; Nlm_Int4 offset; if (fcp == NULL || fcp->fp == NULL || fcp->failed) return 0L; offset = ftell (fcp->fp); bytes = (Nlm_Int4) (fcp->total - fcp->ctr); offset -= bytes; return offset; } NLM_EXTERN Nlm_Boolean Nlm_FileCacheFree ( Nlm_FileCache PNTR fcp, Nlm_Boolean restoreFilePos ) { Nlm_Int4 pos; if (fcp == NULL || fcp->fp == NULL || fcp->failed) return FALSE; if (restoreFilePos) { /* correct position of file pointer */ pos = Nlm_FileCacheTell (fcp); fseek (fcp->fp, pos, SEEK_SET); } MemSet ((Nlm_VoidPtr) fcp, 0, sizeof (Nlm_FileCache)); return TRUE; }