View Issue Details

IDProjectCategoryView StatusLast Update
0001944OpenFOAMBugpublic2016-02-02 18:30
Reporteruser1281Assigned Tohenry  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionunable to reproduce 
PlatformGNU/LinuxOSUbuntuOS Version12.04
Summary0001944: foamToEnsight induces core dumped error if case is in a very long directory
Description1) if the case is in a short directory, let's say /home/case, then foamToEnsight can make the data conversion.

1) if the case is in a very long directory, let's say /home/OpenFOAM/OpenFOAM-2.3.0/run/...very long directory.../case, then foamToEnsight always gives:


#0 Foam::error::printStack(Foam::Ostream&) in "/home/yk/OpenFOAM/OpenFOAM-2.3.0/platforms/linux64GccDPOpt/lib/libOpenFOAM.so"
#1 Foam::sigFpe::sigHandler(int) in "/home/yk/OpenFOAM/OpenFOAM-2.3.0/platforms/linux64GccDPOpt/lib/libOpenFOAM.so"
#2 in "/lib/x86_64-linux-gnu/libc.so.6"
#3
 in "/home/yk/OpenFOAM/OpenFOAM-2.3.0/platforms/linux64GccDPOpt/bin/foamToEnsight"
#4
 at foamToEnsight.C:0
#5
 in "/home/yk/OpenFOAM/OpenFOAM-2.3.0/platforms/linux64GccDPOpt/bin/foamToEnsight"
#6
 in "/home/yk/OpenFOAM/OpenFOAM-2.3.0/platforms/linux64GccDPOpt/bin/foamToEnsight"
#7
 in "/home/yk/OpenFOAM/OpenFOAM-2.3.0/platforms/linux64GccDPOpt/bin/foamToEnsight"
#8 __libc_start_main in "/lib/x86_64-linux-gnu/libc.so.6"
#9
Steps To Reproducei attached my simple case.

1.Unzip it and move it to a very short directory and run foamToEnsight. this will finish with success.

2.move the case to a directory as long as possible and run foamToEnsight. i got the float point exception error.
TagsNo tags attached.

Activities

user1281

2015-12-09 10:55

 

channelToEnsight.zip (34,957 bytes)

wyldckat

2015-12-10 21:08

updater   ~0005731

I've tried to reproduce the error you've reported and I haven't managed to do it yet.
I have a folder named "~/Desktop/mantis/bug1944/mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm" and the conversion worked without problems for an adaptation of the tutorial "incompressible/pimpleFoam/channel395", while using OpenFOAM 2.3.0.


I tried using the case you provided, but I got the following error:

  --> FOAM FATAL IO ERROR:
  Cannot open file.

  file: /home/ofuser/OpenFOAM/ofuser-2.3.0/run/river/river1/rawData/upZeta.txt at line 1.


Please provide the complete details which can be used to reproduce the same exact error, as well as the missing files, if possible. Otherwise it's not possible to reproduce the error.

user1281

2015-12-11 02:24

 

upZeta.txt (1,081 bytes)   
51
(
(0	0)
(1800	0.124344942)
(3600	0.240876833)
(5400	0.342273548)
(7200	0.422163958)
(9000	0.475528255)
(10800	0.499013363)
(12600	0.491143628)
(14400	0.452413534)
(16200	0.385256634)
(18000	0.293892643)
(19800	0.184062298)
(21600	0.062666642)
(23400	-0.062666589)
(25200	-0.184062248)
(27000	-0.2938926)
(28800	-0.3852566)
(30600	-0.452413511)
(32400	-0.491143618)
(34200	-0.499013367)
(36000	-0.475528271)
(37800	-0.422163987)
(39600	-0.342273587)
(41400	-0.24087688)
(43200	-0.124344993)
(45000	-5.35898E-08)
(46800	0.12434489)
(48600	0.240876786)
(50400	0.342273509)
(52200	0.422163929)
(54000	0.475528238)
(55800	0.49901336)
(57600	0.491143638)
(59400	0.452413556)
(61200	0.385256668)
(63000	0.293892687)
(64800	0.184062348)
(66600	0.062666695)
(68400	-0.062666536)
(70200	-0.184062199)
(72000	-0.293892557)
(73800	-0.385256565)
(75600	-0.452413488)
(77400	-0.491143608)
(79200	-0.49901337)
(81000	-0.475528288)
(82800	-0.422164016)
(84600	-0.342273626)
(86400	-0.240876927)
(88200	-0.124345045)
(90000	-1.0718E-07)

)
upZeta.txt (1,081 bytes)   

user1281

2015-12-11 02:36

  ~0005732

thanks for pointing out my missing, Bruno. now the file is uploaded and you may need to change 0/zeta.boundaryField.inlet dict for the location of the file.

and on my platform i can solve the case without problems but failed to make the data conversion. if there is still any problem about the file, please let me know.

thanks again!

wyldckat

2015-12-13 15:54

updater   ~0005739

When you wrote: "move the case to a directory as long as possible" - you should have been specific about the exact number of characters you used. But I should have also been specific in asking about the exact number of characters... so we were both vague about the details :)

Anyway, I've finally managed to reproduce the problem. A path with 254 characters in total is able to trigger this error, when using OpenFOAM 2.3.0. When using 3.0.x, I got this:

  --> FOAM FATAL IO ERROR:
  keyword uniformValueCoeffs is undefined in dictionary "/home/user/Desktop/mantis/bug1944/aaaaaaaaaaaaa/bbbbbbbbbbbbbbb/cccccccccccccccc/ddddddddddddddd/eeeeeeeeeeee/ffffffffffffffffff/gggggggggggggggggg/hhhhhhhhhhhhhhhhhh/iiiiiiiiiiiiiiiiiii/jjjjjjjjjjjjj/mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm/0/zeta.boundaryField.inlet"

  file: /home/user/Desktop/mantis/bug1944/aaaaaaaaaaaaa/bbbbbbbbbbbbbbb/cccccccccccccccc/ddddddddddddddd/eeeeeeeeeeee/ffffffffffffffffff/gggggggggggggggggg/hhhhhhhhhhhhhhhhhh/iiiiiiiiiiiiiiiiiii/jjjjjjjjjjjjj/mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm/0/zeta.boundaryField.inlet from line 36 to line 41.

      From function dictionary::subDict(const word& keyword) const
      in file db/dictionary/dictionary.C at line 648.

  FOAM exiting


Using a symbolic link for the case folder also doesn't solve the problem, given that the real path is unpacked from the symbolic link.

Using a path with 256 or more characters can lead any version of OpenFOAM to complaining about not being able to get the path, given the hard-coded 256 character limit in "Foam::cwd":

  --> FOAM FATAL ERROR:
  Couldn't get the current working directory

      From function Foam::cwd()
      in file POSIX.C at line 256.

  FOAM exiting


I'm going to look into how to fix this properly, but I have to ask: Why exactly do you need a path so long?
Is it because of the folder name for identifying the case? Or is it the path to the folder that is very long, due to the machine you're using being shared with several people?

wyldckat

2015-12-13 16:59

updater  

POSIX.C (29,928 bytes)   
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
     \\/     M anipulation  |
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    OpenFOAM 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 General Public License
    for more details.

    You should have received a copy of the GNU General Public License
    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.

Description
    POSIX versions of the functions declared in OSspecific.H

\*---------------------------------------------------------------------------*/

#ifdef solarisGcc
# define _SYS_VNODE_H
#endif

#include "OSspecific.H"
#include "POSIX.H"
#include "foamVersion.H"
#include "fileName.H"
#include "fileStat.H"
#include "timer.H"
#include "IFstream.H"
#include "DynamicList.H"

#include <fstream>
#include <cstdlib>
#include <cctype>

#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netdb.h>
#include <dlfcn.h>
#include <link.h>

#include <netinet/in.h>

#ifdef USE_RANDOM
#   include <climits>
#   if INT_MAX    != 2147483647
#       error "INT_MAX    != 2147483647"
#       error "The random number generator may not work!"
#   endif
#endif

// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

namespace Foam
{
    defineTypeNameAndDebug(POSIX, 0);
}


// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

pid_t Foam::pid()
{
    return ::getpid();
}


pid_t Foam::ppid()
{
    return ::getppid();
}


pid_t Foam::pgid()
{
    return ::getpgrp();
}


bool Foam::env(const word& envName)
{
    return ::getenv(envName.c_str()) != NULL;
}


Foam::string Foam::getEnv(const word& envName)
{
    char* env = ::getenv(envName.c_str());

    if (env)
    {
        return string(env);
    }
    else
    {
        // Return null-constructed string rather than string::null
        // to avoid cyclic dependencies in the construction of globals
        return string();
    }
}


bool Foam::setEnv
(
    const word& envName,
    const std::string& value,
    const bool overwrite
)
{
    return setenv(envName.c_str(), value.c_str(), overwrite) == 0;
}


Foam::string Foam::hostName(bool full)
{
    char buf[128];
    ::gethostname(buf, sizeof(buf));

    // implementation as per hostname from net-tools
    if (full)
    {
        struct hostent *hp = ::gethostbyname(buf);
        if (hp)
        {
            return hp->h_name;
        }
    }

    return buf;
}


Foam::string Foam::domainName()
{
    char buf[128];
    ::gethostname(buf, sizeof(buf));

    // implementation as per hostname from net-tools
    struct hostent *hp = ::gethostbyname(buf);
    if (hp)
    {
        char *p = ::strchr(hp->h_name, '.');
        if (p)
        {
            ++p;
            return p;
        }
    }

    return string::null;
}


Foam::string Foam::userName()
{
    struct passwd* pw = ::getpwuid(::getuid());

    if (pw != NULL)
    {
        return pw->pw_name;
    }
    else
    {
        return string::null;
    }
}


bool Foam::isAdministrator()
{
    return (::geteuid() == 0);
}


// use $HOME environment variable or passwd info
Foam::fileName Foam::home()
{
    char* env = ::getenv("HOME");

    if (env != NULL)
    {
        return fileName(env);
    }
    else
    {
        struct passwd* pw = ::getpwuid(getuid());

        if (pw != NULL)
        {
            return pw->pw_dir;
        }
        else
        {
            return fileName::null;
        }
    }
}


Foam::fileName Foam::home(const string& userName)
{
    struct passwd* pw;

    if (userName.size())
    {
        pw = ::getpwnam(userName.c_str());
    }
    else
    {
        char* env = ::getenv("HOME");

        if (env != NULL)
        {
            return fileName(env);
        }

        pw = ::getpwuid(::getuid());
    }

    if (pw != NULL)
    {
        return pw->pw_dir;
    }
    else
    {
        return fileName::null;
    }
}


Foam::fileName Foam::cwd()
{
    // Common path limit
    const label pathLengthChunk = 256;
    label pathLengthLimit = pathLengthChunk;
    List<char> dynamicPath;

    // The objective is to dynamically increase the path length until its
    // possible to load the full path. This is because 256 characters is
    // becoming insufficient for "big data" use scenarios

    dynamicPath.setSize(pathLengthLimit);

    while(pathLengthLimit == dynamicPath.size())
    {
        if (::getcwd(dynamicPath.data(), dynamicPath.size()))
        {
            return dynamicPath.data();
        }
        else if(errno == ERANGE)
        {
            // Doubling the size on each iteration could have catastrophic
            // consequences
            pathLengthLimit += pathLengthChunk;

            dynamicPath.setSize(pathLengthLimit);
        }
        else
        {
            break;
        }
    }

    FatalErrorInFunction
        << "Couldn't get the current working directory"
        << exit(FatalError);

    return fileName::null;
}


bool Foam::chDir(const fileName& dir)
{
    return ::chdir(dir.c_str()) == 0;
}


Foam::fileNameList Foam::findEtcFiles
(
    const fileName& name,
    bool mandatory,
    bool findFirst
)
{
    fileNameList results;

    // Search for user files in
    // * ~/.OpenFOAM/VERSION
    // * ~/.OpenFOAM
    //
    fileName searchDir = home()/".OpenFOAM";
    if (isDir(searchDir))
    {
        fileName fullName = searchDir/FOAMversion/name;
        if (isFile(fullName))
        {
            results.append(fullName);
            if (findFirst)
            {
                return results;
            }
        }

        fullName = searchDir/name;
        if (isFile(fullName))
        {
            results.append(fullName);
            if (findFirst)
            {
                return results;
            }
        }
    }

    // Search for group (site) files in
    // * $WM_PROJECT_SITE/VERSION
    // * $WM_PROJECT_SITE
    //
    searchDir = getEnv("WM_PROJECT_SITE");
    if (searchDir.size())
    {
        if (isDir(searchDir))
        {
            fileName fullName = searchDir/FOAMversion/name;
            if (isFile(fullName))
            {
                results.append(fullName);
                if (findFirst)
                {
                    return results;
                }
            }

            fullName = searchDir/name;
            if (isFile(fullName))
            {
                results.append(fullName);
                if (findFirst)
                {
                    return results;
                }
            }
        }
    }
    else
    {
        // OR search for group (site) files in
        // * $WM_PROJECT_INST_DIR/site/VERSION
        // * $WM_PROJECT_INST_DIR/site
        //
        searchDir = getEnv("WM_PROJECT_INST_DIR");
        if (isDir(searchDir))
        {
            fileName fullName = searchDir/"site"/FOAMversion/name;
            if (isFile(fullName))
            {
                results.append(fullName);
                if (findFirst)
                {
                    return results;
                }
            }

            fullName = searchDir/"site"/name;
            if (isFile(fullName))
            {
                results.append(fullName);
                if (findFirst)
                {
                    return results;
                }
            }
        }
    }

    // Search for other (shipped) files in
    // * $WM_PROJECT_DIR/etc
    //
    searchDir = getEnv("WM_PROJECT_DIR");
    if (isDir(searchDir))
    {
        fileName fullName = searchDir/"etc"/name;
        if (isFile(fullName))
        {
            results.append(fullName);
            if (findFirst)
            {
                return results;
            }
        }
    }

    // Not found
    if (results.empty())
    {
        // Abort if the file is mandatory, otherwise return null
        if (mandatory)
        {
            std::cerr
                << "--> FOAM FATAL ERROR in Foam::findEtcFiles() :"
                   " could not find mandatory file\n    '"
                << name.c_str() << "'\n\n" << std::endl;
            ::exit(1);
        }
    }

    // Return list of matching paths or empty list if none found
    return results;
}


Foam::fileName Foam::findEtcFile(const fileName& name, bool mandatory)
{
    fileNameList results(findEtcFiles(name, mandatory, true));

    if (results.size())
    {
        return results[0];
    }
    else
    {
        return fileName();
    }
}


bool Foam::mkDir(const fileName& pathName, mode_t mode)
{
    // empty names are meaningless
    if (pathName.empty())
    {
        return false;
    }

    // Construct instance path directory if does not exist
    if (::mkdir(pathName.c_str(), mode) == 0)
    {
        // Directory made OK so return true
        return true;
    }
    else
    {
        switch (errno)
        {
            case EPERM:
            {
                FatalErrorInFunction
                    << "The filesystem containing " << pathName
                    << " does not support the creation of directories."
                    << exit(FatalError);

                return false;
            }

            case EEXIST:
            {
                // Directory already exists so simply return true
                return true;
            }

            case EFAULT:
            {
                FatalErrorInFunction
                    << "" << pathName
                    << " points outside your accessible address space."
                    << exit(FatalError);

                return false;
            }

            case EACCES:
            {
                FatalErrorInFunction
                    << "The parent directory does not allow write "
                       "permission to the process,"<< nl
                    << "or one of the directories in " << pathName
                    << " did not allow search (execute) permission."
                    << exit(FatalError);

                return false;
            }

            case ENAMETOOLONG:
            {
                FatalErrorInFunction
                    << "" << pathName << " is too long."
                    << exit(FatalError);

                return false;
            }

            case ENOENT:
            {
                // Part of the path does not exist so try to create it
                if (pathName.path().size() && mkDir(pathName.path(), mode))
                {
                    return mkDir(pathName, mode);
                }
                else
                {
                    FatalErrorInFunction
                        << "Couldn't create directory " << pathName
                        << exit(FatalError);

                    return false;
                }
            }

            case ENOTDIR:
            {
                FatalErrorInFunction
                    << "A component used as a directory in " << pathName
                    << " is not, in fact, a directory."
                    << exit(FatalError);

                return false;
            }

            case ENOMEM:
            {
                FatalErrorInFunction
                    << "Insufficient kernel memory was available to make "
                       "directory " << pathName << '.'
                    << exit(FatalError);

                return false;
            }

            case EROFS:
            {
                FatalErrorInFunction
                    << "" << pathName
                    << " refers to a file on a read-only filesystem."
                    << exit(FatalError);

                return false;
            }

            case ELOOP:
            {
                FatalErrorInFunction
                    << "Too many symbolic links were encountered in resolving "
                    << pathName << '.'
                    << exit(FatalError);

                return false;
            }

            case ENOSPC:
            {
                FatalErrorInFunction
                    << "The device containing " << pathName
                    << " has no room for the new directory or "
                    << "the user's disk quota is exhausted."
                    << exit(FatalError);

                return false;
            }

            default:
            {
                FatalErrorInFunction
                    << "Couldn't create directory " << pathName
                    << exit(FatalError);

                return false;
            }
        }
    }
}


// Set the file mode
bool Foam::chMod(const fileName& name, const mode_t m)
{
    return ::chmod(name.c_str(), m) == 0;
}


// Return the file mode
mode_t Foam::mode(const fileName& name)
{
    fileStat fileStatus(name);
    if (fileStatus.isValid())
    {
        return fileStatus.status().st_mode;
    }
    else
    {
        return 0;
    }
}


// Return the file type: FILE or DIRECTORY
Foam::fileName::Type Foam::type(const fileName& name)
{
    mode_t m = mode(name);

    if (S_ISREG(m))
    {
        return fileName::FILE;
    }
    else if (S_ISDIR(m))
    {
        return fileName::DIRECTORY;
    }
    else
    {
        return fileName::UNDEFINED;
    }
}


// Does the name exist in the filing system?
bool Foam::exists(const fileName& name, const bool checkGzip)
{
    return mode(name) || isFile(name, checkGzip);
}


// Does the directory exist?
bool Foam::isDir(const fileName& name)
{
    return S_ISDIR(mode(name));
}


// Does the file exist?
bool Foam::isFile(const fileName& name, const bool checkGzip)
{
    return S_ISREG(mode(name)) || (checkGzip && S_ISREG(mode(name + ".gz")));
}


// Return size of file
off_t Foam::fileSize(const fileName& name)
{
    fileStat fileStatus(name);
    if (fileStatus.isValid())
    {
        return fileStatus.status().st_size;
    }
    else
    {
        return -1;
    }
}


// Return time of last file modification
time_t Foam::lastModified(const fileName& name)
{
    fileStat fileStatus(name);
    if (fileStatus.isValid())
    {
        return fileStatus.status().st_mtime;
    }
    else
    {
        return 0;
    }
}


// Read a directory and return the entries as a string list
Foam::fileNameList Foam::readDir
(
    const fileName& directory,
    const fileName::Type type,
    const bool filtergz
)
{
    // Initial filename list size
    // also used as increment if initial size found to be insufficient
    static const int maxNnames = 100;

    if (POSIX::debug)
    {
        Info<< "readDir(const fileName&, const fileType, const bool filtergz)"
            << " : reading directory " << directory << endl;
    }

    // Setup empty string list MAXTVALUES long
    fileNameList dirEntries(maxNnames);

    // Pointers to the directory entries
    DIR *source;
    struct dirent *list;

    // Temporary variables and counters
    label nEntries = 0;

    // Attempt to open directory and set the structure pointer
    if ((source = ::opendir(directory.c_str())) == NULL)
    {
        dirEntries.setSize(0);

        if (POSIX::debug)
        {
            Info<< "readDir(const fileName&, const fileType, "
                   "const bool filtergz) : cannot open directory "
                << directory << endl;
        }
    }
    else
    {
        // Read and parse all the entries in the directory
        while ((list = ::readdir(source)) != NULL)
        {
            fileName fName(list->d_name);

            // ignore files begining with ., i.e. '.', '..' and '.*'
            if (fName.size() && fName[0] != '.')
            {
                word fExt = fName.ext();

                if
                (
                    (type == fileName::DIRECTORY)
                 ||
                    (
                        type == fileName::FILE
                     && fName[fName.size()-1] != '~'
                     && fExt != "bak"
                     && fExt != "BAK"
                     && fExt != "old"
                     && fExt != "save"
                    )
                )
                {
                    if ((directory/fName).type() == type)
                    {
                        if (nEntries >= dirEntries.size())
                        {
                            dirEntries.setSize(dirEntries.size() + maxNnames);
                        }

                        if (filtergz && fExt == "gz")
                        {
                            dirEntries[nEntries++] = fName.lessExt();
                        }
                        else
                        {
                            dirEntries[nEntries++] = fName;
                        }
                    }
                }
            }
        }

        // Reset the length of the entries list
        dirEntries.setSize(nEntries);

        ::closedir(source);
    }

    return dirEntries;
}


// Copy, recursively if necessary, the source to the destination
bool Foam::cp(const fileName& src, const fileName& dest)
{
    // Make sure source exists.
    if (!exists(src))
    {
        return false;
    }

    fileName destFile(dest);

    // Check type of source file.
    if (src.type() == fileName::FILE)
    {
        // If dest is a directory, create the destination file name.
        if (destFile.type() == fileName::DIRECTORY)
        {
            destFile = destFile/src.name();
        }

        // Make sure the destination directory exists.
        if (!isDir(destFile.path()) && !mkDir(destFile.path()))
        {
            return false;
        }

        // Open and check streams.
        std::ifstream srcStream(src.c_str());
        if (!srcStream)
        {
            return false;
        }

        std::ofstream destStream(destFile.c_str());
        if (!destStream)
        {
            return false;
        }

        // Copy character data.
        char ch;
        while (srcStream.get(ch))
        {
            destStream.put(ch);
        }

        // Final check.
        if (!srcStream.eof() || !destStream)
        {
            return false;
        }
    }
    else if (src.type() == fileName::DIRECTORY)
    {
        // If dest is a directory, create the destination file name.
        if (destFile.type() == fileName::DIRECTORY)
        {
            destFile = destFile/src.component(src.components().size() -1);
        }

        // Make sure the destination directory exists.
        if (!isDir(destFile) && !mkDir(destFile))
        {
            return false;
        }

        // Copy files
        fileNameList contents = readDir(src, fileName::FILE, false);
        forAll(contents, i)
        {
            if (POSIX::debug)
            {
                Info<< "Copying : " << src/contents[i]
                    << " to " << destFile/contents[i] << endl;
            }

            // File to file.
            cp(src/contents[i], destFile/contents[i]);
        }

        // Copy sub directories.
        fileNameList subdirs = readDir(src, fileName::DIRECTORY);
        forAll(subdirs, i)
        {
            if (POSIX::debug)
            {
                Info<< "Copying : " << src/subdirs[i]
                    << " to " << destFile << endl;
            }

            // Dir to Dir.
            cp(src/subdirs[i], destFile);
        }
    }

    return true;
}


// Create a softlink. dst should not exist. Returns true if successful.
bool Foam::ln(const fileName& src, const fileName& dst)
{
    if (POSIX::debug)
    {
        Info<< "Create softlink from : " << src << " to " << dst
            << endl;
    }

    if (exists(dst))
    {
        WarningInFunction
            << "destination " << dst << " already exists. Not linking."
            << endl;
        return false;
    }

    if (src.isAbsolute() && !exists(src))
    {
        WarningInFunction
            << "source " << src << " does not exist." << endl;
        return false;
    }

    if (::symlink(src.c_str(), dst.c_str()) == 0)
    {
        return true;
    }
    else
    {
        WarningInFunction
            << "symlink from " << src << " to " << dst << " failed." << endl;
        return false;
    }
}


// Rename srcFile dstFile
bool Foam::mv(const fileName& src, const fileName& dst)
{
    if (POSIX::debug)
    {
        Info<< "Move : " << src << " to " << dst << endl;
    }

    if
    (
        dst.type() == fileName::DIRECTORY
     && src.type() != fileName::DIRECTORY
    )
    {
        const fileName dstName(dst/src.name());

        return ::rename(src.c_str(), dstName.c_str()) == 0;
    }
    else
    {
        return ::rename(src.c_str(), dst.c_str()) == 0;
    }
}


//- Rename to a corresponding backup file
//  If the backup file already exists, attempt with "01" .. "99" index
bool Foam::mvBak(const fileName& src, const std::string& ext)
{
    if (POSIX::debug)
    {
        Info<< "mvBak : " << src << " to extension " << ext << endl;
    }

    if (exists(src, false))
    {
        const int maxIndex = 99;
        char index[3];

        for (int n = 0; n <= maxIndex; n++)
        {
            fileName dstName(src + "." + ext);
            if (n)
            {
                sprintf(index, "%02d", n);
                dstName += index;
            }

            // avoid overwriting existing files, except for the last
            // possible index where we have no choice
            if (!exists(dstName, false) || n == maxIndex)
            {
                return ::rename(src.c_str(), dstName.c_str()) == 0;
            }

        }
    }

    // fall-through: nothing to do
    return false;
}


// Remove a file, returning true if successful otherwise false
bool Foam::rm(const fileName& file)
{
    if (POSIX::debug)
    {
        Info<< "Removing : " << file << endl;
    }

    // Try returning plain file name; if not there, try with .gz
    if (remove(file.c_str()) == 0)
    {
        return true;
    }
    else
    {
        return ::remove(string(file + ".gz").c_str()) == 0;
    }
}


// Remove a dirctory and its contents
bool Foam::rmDir(const fileName& directory)
{
    if (POSIX::debug)
    {
        Info<< "rmDir(const fileName&) : "
            << "removing directory " << directory << endl;
    }

    // Pointers to the directory entries
    DIR *source;
    struct dirent *list;

    // Attempt to open directory and set the structure pointer
    if ((source = ::opendir(directory.c_str())) == NULL)
    {
        WarningInFunction
            << "cannot open directory " << directory << endl;

        return false;
    }
    else
    {
        // Read and parse all the entries in the directory
        while ((list = ::readdir(source)) != NULL)
        {
            fileName fName(list->d_name);

            if (fName != "." && fName != "..")
            {
                fileName path = directory/fName;

                if (path.type() == fileName::DIRECTORY)
                {
                    if (!rmDir(path))
                    {
                        WarningInFunction
                            << "failed to remove directory " << fName
                            << " while removing directory " << directory
                            << endl;

                        ::closedir(source);

                        return false;
                    }
                }
                else
                {
                    if (!rm(path))
                    {
                        WarningInFunction
                            << "failed to remove file " << fName
                            << " while removing directory " << directory
                            << endl;

                        ::closedir(source);

                        return false;
                    }
                }
            }

        }

        if (!rm(directory))
        {
            WarningInFunction
                << "failed to remove directory " << directory << endl;

            ::closedir(source);

            return false;
        }

        ::closedir(source);

        return true;
    }
}


unsigned int Foam::sleep(const unsigned int s)
{
    return ::sleep(s);
}


void Foam::fdClose(const int fd)
{
    if (close(fd) != 0)
    {
        FatalErrorInFunction
            << "close error on " << fd << endl
            << abort(FatalError);
    }
}


bool Foam::ping
(
    const string& destName,
    const label destPort,
    const label timeOut
)
{
    struct hostent *hostPtr;
    volatile int sockfd;
    struct sockaddr_in destAddr;      // will hold the destination addr
    u_int addr;

    if ((hostPtr = ::gethostbyname(destName.c_str())) == NULL)
    {
        FatalErrorInFunction
            << "gethostbyname error " << h_errno << " for host " << destName
            << abort(FatalError);
    }

    // Get first of the SLL of addresses
    addr = (reinterpret_cast<struct in_addr*>(*(hostPtr->h_addr_list)))->s_addr;

    // Allocate socket
    sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        FatalErrorInFunction
            << "socket error"
            << abort(FatalError);
    }

    // Fill sockaddr_in structure with dest address and port
    memset(reinterpret_cast<char *>(&destAddr), '\0', sizeof(destAddr));
    destAddr.sin_family = AF_INET;
    destAddr.sin_port = htons(ushort(destPort));
    destAddr.sin_addr.s_addr = addr;


    timer myTimer(timeOut);

    if (timedOut(myTimer))
    {
        // Setjmp from timer jumps back to here
        fdClose(sockfd);
        return false;
    }

    if
    (
        ::connect
        (
            sockfd,
            reinterpret_cast<struct sockaddr*>(&destAddr),
            sizeof(struct sockaddr)
        ) != 0
    )
    {
        // Connection refused. Check if network was actually used or not.

        int connectErr = errno;

        fdClose(sockfd);

        if (connectErr == ECONNREFUSED)
        {
            return true;
        }
        //perror("connect");

        return false;
    }

    fdClose(sockfd);

    return true;
}


bool Foam::ping(const string& hostname, const label timeOut)
{
    return ping(hostname, 222, timeOut) || ping(hostname, 22, timeOut);
}


int Foam::system(const std::string& command)
{
    return ::system(command.c_str());
}


void* Foam::dlOpen(const fileName& lib, const bool check)
{
    if (POSIX::debug)
    {
        std::cout<< "dlOpen(const fileName&)"
            << " : dlopen of " << lib << std::endl;
    }
    void* handle = ::dlopen(lib.c_str(), RTLD_LAZY|RTLD_GLOBAL);

    if (!handle && check)
    {
        WarningInFunction
            << "dlopen error : " << ::dlerror()
            << endl;
    }

    if (POSIX::debug)
    {
        std::cout
            << "dlOpen(const fileName&)"
            << " : dlopen of " << lib
            << " handle " << handle << std::endl;
    }

    return handle;
}


bool Foam::dlClose(void* handle)
{
    if (POSIX::debug)
    {
        std::cout
            << "dlClose(void*)"
            << " : dlclose of handle " << handle << std::endl;
    }
    return ::dlclose(handle) == 0;
}


void* Foam::dlSym(void* handle, const std::string& symbol)
{
    if (POSIX::debug)
    {
        std::cout
            << "dlSym(void*, const std::string&)"
            << " : dlsym of " << symbol << std::endl;
    }
    // clear any old errors - see manpage dlopen
    (void) ::dlerror();

    // get address of symbol
    void* fun = ::dlsym(handle, symbol.c_str());

    // find error (if any)
    char *error = ::dlerror();

    if (error)
    {
        WarningInFunction
            << "Cannot lookup symbol " << symbol << " : " << error
            << endl;
    }

    return fun;
}


bool Foam::dlSymFound(void* handle, const std::string& symbol)
{
    if (handle && !symbol.empty())
    {
        if (POSIX::debug)
        {
            std::cout
                << "dlSymFound(void*, const std::string&)"
                << " : dlsym of " << symbol << std::endl;
        }

        // clear any old errors - see manpage dlopen
        (void) ::dlerror();

        // get address of symbol
        (void) ::dlsym(handle, symbol.c_str());

        // symbol can be found if there was no error
        return !::dlerror();
    }
    else
    {
        return false;
    }
}


static int collectLibsCallback
(
    struct dl_phdr_info *info,
    size_t size,
    void *data
)
{
    Foam::DynamicList<Foam::fileName>* ptr =
        reinterpret_cast<Foam::DynamicList<Foam::fileName>*>(data);
    ptr->append(info->dlpi_name);
    return 0;
}


Foam::fileNameList Foam::dlLoaded()
{
    DynamicList<fileName> libs;
    dl_iterate_phdr(collectLibsCallback, &libs);
    if (POSIX::debug)
    {
        std::cout
            << "dlLoaded()"
            << " : determined loaded libraries :" << libs.size() << std::endl;
    }
    return libs;
}


void Foam::osRandomSeed(const label seed)
{
#ifdef USE_RANDOM
    srandom((unsigned int)seed);
#else
    srand48(seed);
#endif
}


Foam::label Foam::osRandomInteger()
{
#ifdef USE_RANDOM
    return random();
#else
    return lrand48();
#endif
}


Foam::scalar Foam::osRandomDouble()
{
#ifdef USE_RANDOM
    return (scalar)random()/INT_MAX;
#else
    return drand48();
#endif
}


// ************************************************************************* //
POSIX.C (29,928 bytes)   

wyldckat

2015-12-13 17:11

updater   ~0005740

@Henry: Attached is the file "POSIX.C" for the folder "src/OSspecific/POSIX" that has the ability to deal with paths with more than 256 characters in the method "Foam::cwd()".
It relies on "List<char>" instead of a hardcoded "char buf[256]" and resizes the list with +256 in length for each iteration that "getcwd" fails with "errno == ERANGE".

In theory, this will only break if the "setSize()" call fails to allocate as much memory as requested.
The attached file should work with both 3.0.x and dev, if I remember correctly that "POSIX.C" hasn't changed recently.

____________

@Karelke (cfdopenfoam): I didn't notice that the previous error I got about "uniformValueCoeffs" is because OpenFOAM 2.4/3.0/dev uses another naming convention. I changed the inlet in "zeta" to this for working with OpenFOAM 3.0/dev:

    inlet
    {
        type uniformFixedValue;
        uniformValue tableFile;
        tableFileCoeffs
        {
            outOfBounds warn;
            fileName "$FOAM_CASE/upZeta.txt";
        }
        uniformValueCoeffs
        {
          $tableFileCoeffs;
        }
    }

This way it works with both 2.3.0 and 2.4/3.0/dev versions.

As for sigFpe error you're getting due to the path with ~254 characters, it no longer occurs with the more recent versions of OpenFOAM.

But please do answer the questions I asked above, namely:

  Why exactly do you need a path so long?
  Is it because of the folder name for identifying the case?
  Or is it the path to the folder that is very long, due to the machine you're using being shared with several people?

henry

2015-12-13 17:18

manager   ~0005741

I think it would be slightly better to use DynamicList rather List given that the list is resized as necessary.

henry

2015-12-13 17:24

manager   ~0005742

I will make the change to DynamicList. Also I think it would be a good idea to include a hard-coded upper limit in case it goes into an allocation loop because errno is set to ERANGE due to some other problem. What should the upper limit be? If it is modest is it worth the effort of resizing, why not set the buffer to the upper limit? Or maybe set the size to 256 initially and the first time it goes over set it to the upper limit and if it goes over the upper-limit issue a fatal error?

wyldckat

2015-12-13 17:37

updater   ~0005743

I also thought about that, namely the issue with the upper limit not being bound.
In Linux, the limit is defined by PATH_MAX as 4096 in "/usr/include/linux/limits.h". Problem is that this isn't the POSIX way of defining this limit.

The other problem is mostly on how much future-proof the code should be.
As for always setting to 4096 as the default size for long paths, seems overkill in most situations... although the construction of "fileName" will automatically trim to the first null character, making it always shorter than 4096.

The file systems on Linux do not have hard-coded limits on the path lengths: https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits - it's only the interfacing code that is restricted, hence the 4096 value can change in future versions.


By the way, I later noticed that the attached POSIX.C won't work with 3.0.x, due to a small change made in the commit "ErrorIn -> ...ErrorInFunction".

henry

2015-12-13 17:44

manager   ~0005744

ErrorInFunction is also supported in OpenFOAM-3.0.x or did I miss some?

wyldckat

2015-12-13 17:49

updater   ~0005745

Last edited: 2015-12-13 17:50

I copied POSIX.C from dev to 3.0.x and it built without any error messages nor related warnings. But there are a lot of these updates that weren't done in 3.0.x yet, so I wasn't sure it would have worked.

henry

2015-12-13 18:37

manager   ~0005747

I have added an upper-limit which can be changed in POSIX.H as necessary in the future. See commit 72bc2ac4a901616d60fd5fe99f3965175838f9f8 in OpenFOAM-dev.

wyldckat

2015-12-13 19:04

updater   ~0005749

Tested with a 410 character path with success.
Tested with a 3602 character path and it gave me this error message:

    --> FOAM FATAL IO ERROR:
    string "/home/user/Desktop/mantis/bug1944/aaaaaaaaaaaaa/bbbbbbbbbbbbbbb/cccccccccccccccc..."
        is too long (max. 1024 characters)

    file: IStringStream.sourceFile at line 0.

        From function virtual Foam::Istream& Foam::ISstream::read(Foam::string&)
        in file db/IOstreams/Sstreams/ISstream.C at line 561.

    FOAM exiting


Took a look into the class "Foam::ISstream" and it has several hard-coded limits, some of 128, others of 1024 and others of 8000, depending on what each method is designed to read.

I still have to take a better look into how DynamicList does its job (namely if it resizes automatically upon usage), but perhaps simply replacing in "Foam::ISstream" these entries:

  static char buf[maxLen];

with

  static DynamicList<char> buf(maxLen);

and then adapting the limiter check to handle only when a resize fails, would make this class future-proof. Then again, this feels like performance sensitive class, so it really depends on how DynamicList can do this.

wyldckat

2015-12-13 21:14

updater  

ISstream.C (17,485 bytes)   
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
     \\/     M anipulation  |
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    OpenFOAM 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 General Public License
    for more details.

    You should have received a copy of the GNU General Public License
    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.

\*---------------------------------------------------------------------------*/

#include "ISstream.H"
#include "int.H"
#include "token.H"
#include <cctype>

// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //

char Foam::ISstream::nextValid()
{
    char c = 0;

    while (true)
    {
        // Get next non-whitespace character
        while (get(c) && isspace(c))
        {}

        // Return if stream is bad - ie, previous get() failed
        if (bad() || isspace(c))
        {
            break;
        }

        // Is this the start of a C/C++ comment?
        if (c == '/')
        {
            if (!get(c))
            {
                // cannot get another character - return this one
                return '/';
            }

            if (c == '/')
            {
                // C++ style single-line comment - skip through past end-of-line
                while (get(c) && c != '\n')
                {}
            }
            else if (c == '*')
            {
                // within a C-style comment
                while (true)
                {
                    // search for end of C-style comment - '*/'
                    if (get(c) && c == '*')
                    {
                        if (get(c))
                        {
                            if (c == '/')
                            {
                                // matched '*/'
                                break;
                            }
                            else if (c == '*')
                            {
                                // check again
                                putback(c);
                            }
                        }
                    }

                    if (!good())
                    {
                        return 0;
                    }
                }
            }
            else
            {
                // The '/' did not start a C/C++ comment - return it
                putback(c);
                return '/';
            }
        }
        else
        {
            // a valid character - return it
            return c;
        }
    }

    return 0;
}


void Foam::ISstream::readWordToken(token& t)
{
    word* wPtr = new word;

    if (read(*wPtr).bad())
    {
        delete wPtr;
        t.setBad();
    }
    else if (token::compound::isCompound(*wPtr))
    {
        t = token::compound::New(*wPtr, *this).ptr();
        delete wPtr;
    }
    else
    {
        t = wPtr;
    }
}


Foam::Istream& Foam::ISstream::read(token& t)
{
    // Return the put back token if it exists
    if (Istream::getBack(t))
    {
        return *this;
    }

    // Assume that the streams supplied are in working order.
    // Lines are counted by '\n'

    // Get next 'valid character': i.e. proceed through any whitespace
    // and/or comments until a semantically valid character is found

    char c = nextValid();

    // Set the line number of this token to the current stream line number
    t.lineNumber() = lineNumber();

    // return on error
    if (!c)
    {
        t.setBad();
        return *this;
    }

    // Analyse input starting with this character.
    switch (c)
    {
        // Check for punctuation first

        case token::END_STATEMENT :
        case token::BEGIN_LIST :
        case token::END_LIST :
        case token::BEGIN_SQR :
        case token::END_SQR :
        case token::BEGIN_BLOCK :
        case token::END_BLOCK :
        case token::COLON :
        case token::COMMA :
        case token::ASSIGN :
        case token::ADD :
        // NB: token::SUBTRACT handled later as the possible start of a Number
        case token::MULTIPLY :
        case token::DIVIDE :
        {
            t = token::punctuationToken(c);
            return *this;
        }


        // String: enclosed by double quotes.
        case token::BEGIN_STRING :
        {
            putback(c);
            string* sPtr = new string;

            if (read(*sPtr).bad())
            {
                delete sPtr;
                t.setBad();
            }
            else
            {
                t = sPtr;
            }

            return *this;
        }
        // Possible verbatim string or dictionary functionEntry
        case token::HASH :
        {
            char nextC;
            if (read(nextC).bad())
            {
                // Return hash as word
                t = token(word(c));
                return *this;
            }
            else if (nextC == token::BEGIN_BLOCK)
            {
                // Verbatim string
                string* sPtr = new string;

                if (readVerbatim(*sPtr).bad())
                {
                    delete sPtr;
                    t.setBad();
                }
                else
                {
                    t = sPtr;
                    t.type() = token::VERBATIMSTRING;
                }

                return *this;
            }
            else
            {
                // Word beginning with #
                putback(nextC);
                putback(c);

                readWordToken(t);

                return *this;
            }
        }

        case '$':
        {
            // Look ahead
            char nextC;
            if (read(nextC).bad())
            {
                // Return $ as word
                t = token(word(c));
                return *this;
            }
            else if (nextC == token::BEGIN_BLOCK)
            {
                putback(nextC);
                putback(c);

                string* sPtr = new string;

                if (readVariable(*sPtr).bad())
                {
                    delete sPtr;
                    t.setBad();
                }
                else
                {
                    t = sPtr;
                    t.type() = token::VARIABLE;
                }
                return *this;
            }
            else
            {
                putback(nextC);
                putback(c);
                readWordToken(t);
                return *this;
            }
        }

        // Number: integer or floating point
        //
        // ideally match the equivalent of this regular expression
        //
        //    /[-+]?([0-9]+\.?[0-9]*|\.[0-9]+)([Ee][-+]?[0-9]+)?/
        //
        case '-' :
        case '.' :
        case '0' : case '1' : case '2' : case '3' : case '4' :
        case '5' : case '6' : case '7' : case '8' : case '9' :
        {
            bool asLabel = (c != '.');

            int nChar = 0;
            buf(nChar++) = c;

            // get everything that could resemble a number and let
            // readScalar determine the validity
            while
            (
                is_.get(c)
             && (
                    isdigit(c)
                 || c == '+'
                 || c == '-'
                 || c == '.'
                 || c == 'E'
                 || c == 'e'
                )
            )
            {
                if (asLabel)
                {
                    asLabel = isdigit(c);
                }

                buf[nChar++] = c;
            }
            buf(nChar) = '\0';

            setState(is_.rdstate());
            if (is_.bad())
            {
                t.setBad();
            }
            else
            {
                is_.putback(c);

                if (nChar == 1 && buf[0] == '-')
                {
                    // a single '-' is punctuation
                    t = token::punctuationToken(token::SUBTRACT);
                }
                else
                {
                    if (asLabel)
                    {
                        label labelVal = 0;
                        if (Foam::read(buf.data(), labelVal))
                        {
                            t = labelVal;
                        }
                        else
                        {
                            // Maybe too big? Try as scalar
                            scalar scalarVal;
                            if (readScalar(buf.data(), scalarVal))
                            {
                                t = scalarVal;
                            }
                            else
                            {
                                t.setBad();
                            }
                        }
                    }
                    else
                    {
                        scalar scalarVal;
                        if (readScalar(buf.data(), scalarVal))
                        {
                            t = scalarVal;
                        }
                        else
                        {
                            t.setBad();
                        }
                    }
                }
            }

            return *this;
        }


        // Should be a word (which can also be a single character)
        default:
        {
            putback(c);
            readWordToken(t);

            return *this;
        }
    }
}


Foam::Istream& Foam::ISstream::read(char& c)
{
    c = nextValid();
    return *this;
}


Foam::Istream& Foam::ISstream::read(word& str)
{
    static const int errLen = 80; // truncate error message for readability

    int nChar = 0;
    int listDepth = 0;
    char c;

    while (get(c) && word::valid(c))
    {
        if (c == token::BEGIN_LIST)
        {
            listDepth++;
        }
        else if (c == token::END_LIST)
        {
            if (listDepth)
            {
                listDepth--;
            }
            else
            {
                break;
            }
        }

        buf(nChar++) = c;
    }

    // we could probably skip this check
    if (bad())
    {
        buf(errLen) = buf(nChar) = '\0';

        FatalIOErrorInFunction(*this)
            << "problem while reading word '" << buf.data() << "...' after "
            << nChar << " characters\n"
            << exit(FatalIOError);

        return *this;
    }

    if (nChar == 0)
    {
        FatalIOErrorInFunction(*this)
            << "invalid first character found : " << c
            << exit(FatalIOError);
    }

    // done reading
    buf[nChar] = '\0';
    str = buf.data();
    putback(c);

    return *this;
}


Foam::Istream& Foam::ISstream::read(string& str)
{
    static const int errLen = 80; // truncate error message for readability

    char c;

    if (!get(c))
    {
        FatalIOErrorInFunction(*this)
            << "cannot read start of string"
            << exit(FatalIOError);

        return *this;
    }

    // Note, we could also handle single-quoted strings here (if desired)
    if (c != token::BEGIN_STRING)
    {
        FatalIOErrorInFunction(*this)
            << "Incorrect start of string character found : " << c
            << exit(FatalIOError);

        return *this;
    }

    int nChar = 0;
    bool escaped = false;

    while (get(c))
    {
        if (c == token::END_STRING)
        {
            if (escaped)
            {
                escaped = false;
                nChar--;    // overwrite backslash
            }
            else
            {
                // done reading
                buf(nChar) = '\0';
                str = buf.data();
                return *this;
            }
        }
        else if (c == token::NL)
        {
            if (escaped)
            {
                escaped = false;
                nChar--;    // overwrite backslash
            }
            else
            {
                buf(errLen) = buf(nChar) = '\0';

                FatalIOErrorInFunction(*this)
                    << "found '\\n' while reading string \""
                    << buf.data() << "...\""
                    << exit(FatalIOError);

                return *this;
            }
        }
        else if (c == '\\')
        {
            escaped = !escaped;    // toggle state (retains backslashes)
        }
        else
        {
            escaped = false;
        }

        buf(nChar++) = c;
    }


    // don't worry about a dangling backslash if string terminated prematurely
    buf(errLen) = buf(nChar) = '\0';

    FatalIOErrorInFunction(*this)
        << "problem while reading string \"" << buf.data() << "...\""
        << exit(FatalIOError);

    return *this;
}


// Special handling of '{' in variables
Foam::Istream& Foam::ISstream::readVariable(string& str)
{
    static const int errLen = 80; // truncate error message for readability

    int nChar = 0;
    int blockCount = 0;
    char c;

    if (!get(c) || c != '$')
    {
        FatalIOErrorInFunction(*this)
            << "invalid first character found : " << c
            << exit(FatalIOError);
    }

    buf(nChar++) = c;

    // Read next character to see if '{'
    if (get(c) && c == token::BEGIN_BLOCK)
    {
        // Read, counting brackets
        buf(nChar++) = c;

        while
        (
            get(c)
         && (
                c == token::BEGIN_BLOCK
             || c == token::END_BLOCK
             || word::valid(c)
            )
        )
        {
            buf(nChar++) = c;

            if (c == token::BEGIN_BLOCK)
            {
                blockCount++;
            }
            else if (c == token::END_BLOCK)
            {
                if (blockCount)
                {
                    blockCount--;
                }
                else
                {
                    break;
                }
            }
        }
    }
    else
    {
        buf(nChar++) = c;

        while (get(c) && word::valid(c))
        {
            buf(nChar++) = c;
        }
    }

    // we could probably skip this check
    if (bad())
    {
        buf(errLen) = buf(nChar) = '\0';

        FatalIOErrorInFunction(*this)
            << "problem while reading string '" << buf.data() << "...' after "
            << nChar << " characters\n"
            << exit(FatalIOError);

        return *this;
    }

    if (nChar == 0)
    {
        FatalIOErrorInFunction(*this)
            << "invalid first character found : " << c
            << exit(FatalIOError);
    }

    // done reading
    buf(nChar) = '\0';
    str = buf.data();

    // Note: check if we exited due to '}' or just !word::valid.
    if (c != token::END_BLOCK)
    {
        putback(c);
    }

    return *this;
}


Foam::Istream& Foam::ISstream::readVerbatim(string& str)
{
    static const int errLen = 80; // truncate error message for readability

    char c;

    int nChar = 0;

    while (get(c))
    {
        if (c == token::HASH)
        {
            char nextC;
            get(nextC);
            if (nextC == token::END_BLOCK)
            {
                buf(nChar) = '\0';
                str = buf.data();
                return *this;
            }
            else
            {
                putback(nextC);
            }
        }

        buf(nChar++) = c;
    }


    // don't worry about a dangling backslash if string terminated prematurely
    buf(errLen) = buf(nChar) = '\0';

    FatalIOErrorInFunction(*this)
        << "problem while reading string \"" << buf.data() << "...\""
        << exit(FatalIOError);

    return *this;
}


Foam::Istream& Foam::ISstream::read(label& val)
{
    is_ >> val;
    setState(is_.rdstate());
    return *this;
}


Foam::Istream& Foam::ISstream::read(floatScalar& val)
{
    is_ >> val;
    setState(is_.rdstate());
    return *this;
}


Foam::Istream& Foam::ISstream::read(doubleScalar& val)
{
    is_ >> val;
    setState(is_.rdstate());
    return *this;
}


// read binary block
Foam::Istream& Foam::ISstream::read(char* buf, std::streamsize count)
{
    if (format() != BINARY)
    {
        FatalIOErrorInFunction(*this)
            << "stream format not binary"
            << exit(FatalIOError);
    }

    readBegin("binaryBlock");
    is_.read(buf, count);
    readEnd("binaryBlock");

    setState(is_.rdstate());

    return *this;
}


Foam::Istream& Foam::ISstream::rewind()
{
    stdStream().rdbuf()->pubseekpos(0);

    return *this;
}


// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //


std::ios_base::fmtflags Foam::ISstream::flags() const
{
    return is_.flags();
}


std::ios_base::fmtflags Foam::ISstream::flags(const ios_base::fmtflags f)
{
    return is_.flags(f);
}


// ************************************************************************* //
ISstream.C (17,485 bytes)   

wyldckat

2015-12-13 21:14

updater  

ISstream.H (5,739 bytes)   
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
     \\/     M anipulation  |
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    OpenFOAM 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 General Public License
    for more details.

    You should have received a copy of the GNU General Public License
    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.

Class
    Foam::ISstream

Description
    Generic input stream.

SourceFiles
    ISstreamI.H
    ISstream.C

\*---------------------------------------------------------------------------*/

#ifndef ISstream_H
#define ISstream_H

#include "Istream.H"
#include "fileName.H"
#include "DynamicList.H"
#include <iostream>

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

namespace Foam
{

/*---------------------------------------------------------------------------*\
                           Class ISstream Declaration
\*---------------------------------------------------------------------------*/

class ISstream
:
    public Istream
{
    // Private data

        fileName name_;
        istream& is_;
        DynamicList<char> buf;


    // Private Member Functions

        char nextValid();

        void readWordToken(token&);

    // Private Member Functions


        //- Read a verbatim string (excluding block delimiters).
        Istream& readVerbatim(string&);

        //- Read a variable name (includes '{')
        Istream& readVariable(string&);

        //- Disallow default bitwise assignment
        void operator=(const ISstream&);


public:

    // Constructors

        //- Construct as wrapper around istream
        inline ISstream
        (
            istream& is,
            const string& name,
            streamFormat format=ASCII,
            versionNumber version=currentVersion,
            compressionType compression=UNCOMPRESSED
        );


    //- Destructor
    virtual ~ISstream()
    {}


    // Member functions

        // Inquiry

            //- Return the name of the stream
            //  Useful for Fstream to return the filename
            virtual const fileName& name() const
            {
                return name_;
            }

            //- Return non-const access to the name of the stream
            //  Useful to alter the stream name
            virtual fileName& name()
            {
                return name_;
            }

            //- Return flags of output stream
            virtual ios_base::fmtflags flags() const;


        // Read functions

            //- Raw, low-level get character function.
            inline ISstream& get(char&);

            //- Raw, low-level peek function.
            //  Does not remove the character from the stream.
            //  Returns the next character in the stream or EOF if the
            //  end of file is read.
            inline int peek();

            //- Raw, low-level getline into a string function.
            inline ISstream& getLine(string&);

            //- Raw, low-level putback character function.
            inline ISstream& putback(const char&);

            //- Return next token from stream
            virtual Istream& read(token&);

            //- Read a character
            virtual Istream& read(char&);

            //- Read a word
            virtual Istream& read(word&);

            //- Read a string (including enclosing double-quotes).
            //  Backslashes are retained, except when escaping double-quotes
            //  and an embedded newline character.
            virtual Istream& read(string&);

            //- Read a label
            virtual Istream& read(label&);

            //- Read a floatScalar
            virtual Istream& read(floatScalar&);

            //- Read a doubleScalar
            virtual Istream& read(doubleScalar&);

            //- Read binary block
            virtual Istream& read(char*, std::streamsize);

            //- Rewind and return the stream so that it may be read again
            virtual Istream& rewind();


        // Stream state functions

            //- Set flags of output stream
            virtual ios_base::fmtflags flags(const ios_base::fmtflags flags);


        // STL stream

            //- Access to underlying std::istream
            virtual istream& stdStream()
            {
                return is_;
            }

            //- Const access to underlying std::istream
            virtual const istream& stdStream() const
            {
                return is_;
            }


        // Print

            //- Print description of IOstream to Ostream
            virtual void print(Ostream&) const;
};


// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

} // End namespace Foam

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#include "ISstreamI.H"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#endif

// ************************************************************************* //
ISstream.H (5,739 bytes)   

wyldckat

2015-12-13 21:14

updater  

ISstreamI.H (2,472 bytes)   
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
     \\/     M anipulation  |
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    OpenFOAM 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 General Public License
    for more details.

    You should have received a copy of the GNU General Public License
    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.

\*---------------------------------------------------------------------------*/

#include "ISstream.H"

#define INITIAL_BUFFER_SIZE 128

// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //

inline Foam::ISstream::ISstream
(
    istream& is,
    const string& name,
    streamFormat format,
    versionNumber version,
    compressionType compression
)
:
    Istream(format, version, compression),
    name_(name),
    is_(is),
    buf(INITIAL_BUFFER_SIZE)
{
    if (is_.good())
    {
        setOpened();
        setGood();
    }
    else
    {
        setState(is_.rdstate());
    }
}


// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //

inline Foam::ISstream& Foam::ISstream::get(char& c)
{
    is_.get(c);
    setState(is_.rdstate());

    if (c == '\n')
    {
        lineNumber_++;
    }

    return *this;
}


inline int Foam::ISstream::peek()
{
    return is_.peek();
}


inline Foam::ISstream& Foam::ISstream::getLine(string& s)
{
    getline(is_, s);
    setState(is_.rdstate());
    lineNumber_++;

    return *this;
}


inline Foam::ISstream& Foam::ISstream::putback(const char& c)
{
    if (c == '\n')
    {
        lineNumber_--;
    }

    if (!is_.putback(c))
    {
        setBad();
    }

    setState(is_.rdstate());

    return *this;
}


// ************************************************************************* //
ISstreamI.H (2,472 bytes)   

wyldckat

2015-12-13 21:25

updater   ~0005755

This is still a preliminary proposition, but I've attached 3 files for the folder "src/OpenFOAM/db/IOstreams/Sstreams" (for OpenFOAM-dev):

  - ISstream.H - Now using a private buffer "DynamicList<char> buf".

  - ISstreamI.H - The "buf" variable is initialized at 128 characters.

  - ISstream.C - Several changes, all related to dropping the "static char buf[maxLen]" local definition for each method that needed it and instead using the private "buf" dynamic list. Most of the "avoid buffer overflow" checks were removed, given that the limit is now triggered when the resizing fails on its own.

This still needs to be checked on:
 - how it impacts performance;
 - what happens when the resizing fails;
 - fully testing all read methods that use "buf" to double check they still parse properly.

I did do a few tests with:
 1 - generating with blockMesh a 2 million cell mesh, in "ascii" output format;
 2 - then running checkMesh;
 3 - then foamFormatConvert;
 4 - and then checkMesh again.

Then compared with using the same in OpenFOAM 3.0.0, i.e. with the original code. The mesh files were identical, apart from the version in the headers, and the output from checkMesh was also identical.

I won't be able to run these tests before the next weekend :(

user1281

2015-12-14 01:58

  ~0005758

thanks for your responsible efforts, Bruno and Henry.

@Bruno: my exact path of the case is /home/yk/OpenFOAM/yk-2.3.0/run/shallowPimpleFoam/rectChannel

i use this for identifying the case and if it is the exact casePath, then the foamToEnsight utility will do breakdown (as in the Description). and i never got the FOAM FATAL ERROR: Couldn't get the current working directory...

however, if the casePath is /home/qq/rectChannel, then i can make the data conversion using foamToEnsight with success.

it's strange that i only changed the case path so that i made foamToEnsight work.

Issue History

Date Modified Username Field Change
2015-12-09 10:55 user1281 New Issue
2015-12-09 10:55 user1281 File Added: channelToEnsight.zip
2015-12-10 21:08 wyldckat Note Added: 0005731
2015-12-11 02:24 user1281 File Added: upZeta.txt
2015-12-11 02:36 user1281 Note Added: 0005732
2015-12-13 15:54 wyldckat Note Added: 0005739
2015-12-13 16:59 wyldckat File Added: POSIX.C
2015-12-13 17:11 wyldckat Note Added: 0005740
2015-12-13 17:11 wyldckat Assigned To => henry
2015-12-13 17:11 wyldckat Status new => assigned
2015-12-13 17:18 henry Note Added: 0005741
2015-12-13 17:24 henry Note Added: 0005742
2015-12-13 17:37 wyldckat Note Added: 0005743
2015-12-13 17:44 henry Note Added: 0005744
2015-12-13 17:49 wyldckat Note Added: 0005745
2015-12-13 17:50 wyldckat Note Edited: 0005745
2015-12-13 18:37 henry Note Added: 0005747
2015-12-13 19:04 wyldckat Note Added: 0005749
2015-12-13 21:14 wyldckat File Added: ISstream.C
2015-12-13 21:14 wyldckat File Added: ISstream.H
2015-12-13 21:14 wyldckat File Added: ISstreamI.H
2015-12-13 21:25 wyldckat Note Added: 0005755
2015-12-14 01:58 user1281 Note Added: 0005758
2016-02-02 18:30 henry Status assigned => closed
2016-02-02 18:30 henry Resolution open => unable to reproduce