// This may look like C code, but it is really -*- C++ -*- // ------------------------------------------------------------------ // The Goldware Library // Copyright (C) 1990-1999 Odinn Sorensen // Copyright (C) 1999-2000 Alexander S. Aganichev // ------------------------------------------------------------------ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public // License along with this program; if not, write to the Free // Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, // MA 02111-1307, USA // ------------------------------------------------------------------ // $Id$ // ------------------------------------------------------------------ // File utility functions // ------------------------------------------------------------------ #include #ifndef __HAVE_DRIVES__ #include #endif #ifdef __WIN32__ #include #endif #include #include // ------------------------------------------------------------------ // Adds the directory-delimiter character into end of string ('\\' in DOS-based, '/' in unix-based OS) // Replace wrong directory-delimiter character with good. std::string& AddBackslash(std::string& p) { for(size_t posn = 0; (posn=p.find(GOLD_WRONG_SLASH_CHR, posn)) != p.npos; posn++) p[posn] = GOLD_SLASH_CHR; if(p[p.length()-1] != GOLD_SLASH_CHR) p += GOLD_SLASH_STR; return p; } // ------------------------------------------------------------------ // Remove one trailing directory-delimiter character ('\\' in DOS-based, '/' in unix-based OS) std::string& StripBackslash(std::string& p) { std::string::iterator pend = p.end(); if(isslash(*pend)) p.erase(pend); return p; } // ------------------------------------------------------------------ // Get size of file. Return values: // positive number or zero - size of file, // negative number - error (and error code is stored in errno) long GetFilesize(const std::string& filename) { if(filename.empty()) { errno = EINVAL; return -1; } struct stat info; if(stat(filename.c_str(), &info) == 0) return info.st_size; return -1; } // ------------------------------------------------------------------ // Add path to filename, if no path is set. Don't chech size of 'path', be careful! void MakePathname(std::string& pathname, const std::string& path, const std::string& name) { Path pn; MakePathname(pn, path.c_str(), name.c_str()); pathname = pn; } // ------------------------------------------------------------------ // Copy pathname with enviroment variables substitution and adds directory delimiter char. // Copy not more sizeof(Path) characters (__dst should be type "Path" or equvalence, size is GMAXPATH) void PathCopy(std::string& dst, const char* src) { dst = src; strschg_environ(dst); AddBackslash(dst); } void PathCopy(std::string& dst, const std::string& src) { dst = src; strschg_environ(dst); AddBackslash(dst); } // ------------------------------------------------------------------ // DOS-style enviroment variables substitution in string. // In unix-like enviroment also tilde substitution in string. int strschg_environ(std::string& s) { std::string fnd; int replaced = 0; size_t posn, posn1; if (s.length() > 1) { while(((posn=s.find('%')) != s.npos) and ((posn1=s.find('%', posn+1)) != s.npos)) { fnd = s.substr(posn+1, posn1-1-posn); const char* rep = getenv(fnd.c_str()); rep = rep ? rep : ""; s.replace(posn, posn1-posn+1, rep); replaced++; } } #ifndef __HAVE_DRIVES__ if( s[0] == '~' ) { struct passwd *pe=NULL; size_t slash = 1; if( (s.length() > 1) and not isslash(s[1]) ) { slash = s.find_first_of(GOLD_SLASH_STR GOLD_WRONG_SLASH_STR, 1); fnd.assign(s,1,slash-1); pe = getpwnam(fnd.c_str()); }else { pe = getpwuid(getuid()); } if(pe != NULL) { fnd.assign(pe->pw_dir); if ( slash != std::string::npos ) fnd += s.substr(slash); s=fnd; replaced++; } } #endif return replaced; } // ------------------------------------------------------------------ // Change dirname to real full pathname bool maketruepath(std::string &dirname) { bool ok = true; std::string ndirname; char cwd[GMAXPATH]; getcwd(cwd, GMAXPATH); #ifdef __HAVE_DRIVES__ #ifdef __WIN32__ char expanded[GMAXPATH]; char *k; if(GetFullPathName(dirname.c_str(), GMAXPATH, expanded, &k) == 0) { dirname = cwd; ok = false; } else { if(access(expanded, R_OK) == 0) dirname = expanded; else { dirname = cwd; ok = false; } } #elif defined __OS2__ char expanded[GMAXPATH]; if(_fullpath(expanded, dirname.c_str(), GMAXPATH) == 0) { if(access(expanded, R_OK) == 0) dirname = expanded; else { dirname = cwd; ok = false; } } else { dirname = cwd; ok = false; } #elif defined __DJGPP__ char expanded[GMAXPATH]; _fixpath(dirname.c_str(), expanded); if(access(expanded, R_OK) == 0) dirname = expanded; else { dirname = cwd; ok = false; } #else long inspos = -1; if((dirname.length() == 2) and (dirname[1] == ':')) inspos = 2; else if((dirname.length() < 2) or (dirname[1] != ':') or isslash(dirname[0])) inspos = 0; else if(not isslash(dirname[2])) inspos = 2; if(inspos != -1) { char chdrive[] = " :"; chdrive[0] = (inspos == 2) ? dirname[0] : cwd[0]; if(not chdir(chdrive)) { char dwd[GMAXPATH]; getcwd(dwd, GMAXPATH); if(isslash(dirname[0])) ndirname = chdrive; else { ndirname = dwd; ndirname += GOLD_SLASH_CHR; } ndirname += dirname.c_str() + inspos; dirname = ndirname; } else { dirname = cwd; ok = false; } chdir(cwd); } #endif #else if(not dirname.empty() and (dirname[0] == '~')) { char* lname; const char *p = dirname.c_str()+1; if((dirname.length() != 1) and not isslash(*p)) { while(*p and not isslash(*p)) ndirname += *p++; // get user name } else { if ((lname = getlogin()) == NULL) lname = getenv("LOGNAME"); ndirname = lname; // get current user name } struct passwd *pe = getpwnam(ndirname.c_str()); // get home if(pe != NULL) { ndirname = pe->pw_dir; ndirname += GOLD_SLASH_CHR; if(isslash(*p)) ++p; ndirname += p; dirname = ndirname; } else { dirname = cwd; ok = false; } } else if(not dirname.empty() and not isslash(dirname[0])) { ndirname = cwd; ndirname += GOLD_SLASH_CHR; ndirname += dirname; dirname = ndirname; } #endif size_t posn; for(posn = 0; (posn=dirname.find(GOLD_WRONG_SLASH_CHR, posn)) != dirname.npos; posn++) dirname[posn] = GOLD_SLASH_CHR; size_t skipfrom, skipto; #ifdef __HAVE_DRIVES__ /* Prevent from destroying UNC names */ if(dirname.length() > 1) { while((skipfrom=dirname.find("\\\\", 1)) != dirname.npos) dirname.erase(skipfrom, 1); } #endif size_t len = dirname.length(); #ifdef __HAVE_DRIVES__ while((len > 3) and isslash(dirname[--len])) #else while((len > 1) and isslash(dirname[--len])) #endif dirname.erase(len, 1); if(access(dirname.c_str(), R_OK)) { dirname = cwd; ok = false; } #ifdef __HAVE_DRIVES__ if((dirname.length() > 2) and (dirname[0] == '\\') and (dirname[1] == '\\')) posn = 2; else #endif posn = 0; for(; (posn=dirname.find('\\', posn)) != dirname.npos; posn++) dirname[posn] = '/'; while((skipto=dirname.find("/../")) != dirname.npos) { skipfrom = (skipto == 0) ? 0 : dirname.rfind('/', skipto-1); skipto += 2; dirname.erase(skipfrom, skipto-skipfrom+1); } while((skipfrom=dirname.find("/./")) != dirname.npos) dirname.erase(skipfrom, 2); len = dirname.length(); if(len > 2 and not strcmp(&(dirname.c_str()[len-2]), "/.")) dirname.erase(len-2, 2); len = dirname.length(); #ifdef __HAVE_DRIVES__ if((len > 3) and isslash(dirname[--len])) #else if((len > 1) and isslash(dirname[--len])) #endif dirname.erase(len, 1); return ok; } // ------------------------------------------------------------------