diff --git a/applications/test/fileName/Test-fileName.C b/applications/test/fileName/Test-fileName.C index fb87672743..37ad0c9039 100644 --- a/applications/test/fileName/Test-fileName.C +++ b/applications/test/fileName/Test-fileName.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -34,6 +34,7 @@ Description #include "IOobject.H" #include "IOstreams.H" #include "OSspecific.H" +#include "POSIX.H" using namespace Foam; @@ -99,6 +100,98 @@ int main() } + + // Test some copying and deletion + { + const fileName dirA("dirA"); + const fileName lnA("lnA"); + const fileName lnB("lnB"); + const fileName dirB("dirB"); + + Foam::rmDir(dirA); + Foam::rm(lnA); + Foam::rm(lnB); + Foam::rmDir(dirB); + + + Info<< "Creating directory " << dirA << endl; + Foam::mkDir(dirA); + + + const int oldPosix = POSIX::debug; + POSIX::debug = 1; + + + // Create link and test it + Info<< "Creating softlink " << lnA << endl; + Foam::ln(dirA, lnA); + + fileName::Type lnAType = lnA.type(false); + + if (lnAType != fileName::LINK) + { + FatalErrorIn("Test-fileName") << "Type of softlink " << lnA + << " should be " << fileName::LINK + << " but is " << lnAType << exit(FatalError); + } + + fileName::Type dirAType = lnA.type(true); + + if (dirAType != fileName::DIRECTORY) + { + FatalErrorIn("Test-fileName") << "Type of what softlink " << lnA + << " points to should be " << fileName::DIRECTORY + << " but is " << dirAType << exit(FatalError); + } + + // Copy link only + { + Info<< "Copying (non-follow) softlink " << lnA << " to " << lnB + << endl; + + Foam::cp(lnA, lnB, false); + if (lnB.type(false) != fileName::LINK) + { + FatalErrorIn("Test-fileName") << "Type of softlink " << lnB + << " should be " << fileName::LINK + << " but is " << lnB.type(false) << exit(FatalError); + } + if (lnB.type(true) != fileName::DIRECTORY) + { + FatalErrorIn("Test-fileName") << "Type of softlink " << lnB + << " should be " << fileName::DIRECTORY + << " but is " << lnB.type(true) << exit(FatalError); + } + + // Delete + Foam::rm(lnB); + } + + // Copy contents of link + { + Info<< "Copying (contents of) softlink " << lnA << " to " << lnB + << endl; + + Foam::cp(lnA, lnB, true); + if (lnB.type(false) != fileName::DIRECTORY) + { + FatalErrorIn("Test-fileName") << "Type of softlink " << lnB + << " should be " << fileName::DIRECTORY + << " but is " << lnB.type(false) << exit(FatalError); + } + + // Delete + Foam::rm(lnB); + } + + POSIX::debug = oldPosix; + + Foam::rmDir(dirA); + Foam::rm(lnA); + } + + + // test findEtcFile Info<< "\n\nfindEtcFile tests:" << nl << " controlDict => " << findEtcFile("controlDict") << nl diff --git a/src/OSspecific/POSIX/POSIX.C b/src/OSspecific/POSIX/POSIX.C index 0b9a541d94..41645bf736 100644 --- a/src/OSspecific/POSIX/POSIX.C +++ b/src/OSspecific/POSIX/POSIX.C @@ -593,9 +593,9 @@ bool Foam::chMod(const fileName& name, const mode_t m) } -mode_t Foam::mode(const fileName& name) +mode_t Foam::mode(const fileName& name, const bool followLink) { - fileStat fileStatus(name); + fileStat fileStatus(name, followLink); if (fileStatus.isValid()) { return fileStatus.status().st_mode; @@ -607,14 +607,18 @@ mode_t Foam::mode(const fileName& name) } -Foam::fileName::Type Foam::type(const fileName& name) +Foam::fileName::Type Foam::type(const fileName& name, const bool followLink) { - mode_t m = mode(name); + mode_t m = mode(name, followLink); if (S_ISREG(m)) { return fileName::FILE; } + else if (S_ISLNK(m)) + { + return fileName::LINK; + } else if (S_ISDIR(m)) { return fileName::DIRECTORY; @@ -626,27 +630,39 @@ Foam::fileName::Type Foam::type(const fileName& name) } -bool Foam::exists(const fileName& name, const bool checkGzip) +bool Foam::exists +( + const fileName& name, + const bool checkGzip, + const bool followLink +) { - return mode(name) || isFile(name, checkGzip); + return mode(name, followLink) || isFile(name, checkGzip, followLink); } -bool Foam::isDir(const fileName& name) +bool Foam::isDir(const fileName& name, const bool followLink) { - return S_ISDIR(mode(name)); + return S_ISDIR(mode(name, followLink)); } -bool Foam::isFile(const fileName& name, const bool checkGzip) +bool Foam::isFile +( + const fileName& name, + const bool checkGzip, + const bool followLink +) { - return S_ISREG(mode(name)) || (checkGzip && S_ISREG(mode(name + ".gz"))); + return + S_ISREG(mode(name, followLink)) + || (checkGzip && S_ISREG(mode(name + ".gz", followLink))); } -off_t Foam::fileSize(const fileName& name) +off_t Foam::fileSize(const fileName& name, const bool followLink) { - fileStat fileStatus(name); + fileStat fileStatus(name, followLink); if (fileStatus.isValid()) { return fileStatus.status().st_size; @@ -658,9 +674,9 @@ off_t Foam::fileSize(const fileName& name) } -time_t Foam::lastModified(const fileName& name) +time_t Foam::lastModified(const fileName& name, const bool followLink) { - fileStat fileStatus(name); + fileStat fileStatus(name, followLink); if (fileStatus.isValid()) { return fileStatus.status().st_mtime; @@ -676,7 +692,8 @@ Foam::fileNameList Foam::readDir ( const fileName& directory, const fileName::Type type, - const bool filtergz + const bool filtergz, + const bool followLink ) { // Initial filename list size @@ -717,10 +734,10 @@ Foam::fileNameList Foam::readDir { fileName fName(list->d_name); - // ignore files begining with ., i.e. '.', '..' and '.*' + // ignore files beginning with ., i.e. '.', '..' and '.*' if (fName.size() && fName[0] != '.') { - word fExt = fName.ext(); + const word fExt = fName.ext(); if ( @@ -736,7 +753,7 @@ Foam::fileNameList Foam::readDir ) ) { - if ((directory/fName).type() == type) + if ((directory/fName).type(followLink) == type) { if (nEntries >= dirEntries.size()) { @@ -766,7 +783,7 @@ Foam::fileNameList Foam::readDir } -bool Foam::cp(const fileName& src, const fileName& dest) +bool Foam::cp(const fileName& src, const fileName& dest, const bool followLink) { // Make sure source exists. if (!exists(src)) @@ -777,7 +794,8 @@ bool Foam::cp(const fileName& src, const fileName& dest) fileName destFile(dest); // Check type of source file. - if (src.type() == fileName::FILE) + const fileName::Type srcType = src.type(followLink); + if (srcType == fileName::FILE) { // If dest is a directory, create the destination file name. if (destFile.type() == fileName::DIRECTORY) @@ -817,7 +835,23 @@ bool Foam::cp(const fileName& src, const fileName& dest) return false; } } - else if (src.type() == fileName::DIRECTORY) + else if (srcType == fileName::LINK) + { + // 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; + } + + ln(src, destFile); + } + else if (srcType == fileName::DIRECTORY) { // If dest is a directory, create the destination file name. if (destFile.type() == fileName::DIRECTORY) @@ -832,7 +866,7 @@ bool Foam::cp(const fileName& src, const fileName& dest) } // Copy files - fileNameList contents = readDir(src, fileName::FILE, false); + fileNameList contents = readDir(src, fileName::FILE, false, followLink); forAll(contents, i) { if (POSIX::debug) @@ -843,11 +877,17 @@ bool Foam::cp(const fileName& src, const fileName& dest) } // File to file. - cp(src/contents[i], destFile/contents[i]); + cp(src/contents[i], destFile/contents[i], followLink); } // Copy sub directories. - fileNameList subdirs = readDir(src, fileName::DIRECTORY); + fileNameList subdirs = readDir + ( + src, + fileName::DIRECTORY, + false, + followLink + ); forAll(subdirs, i) { if (POSIX::debug) @@ -858,9 +898,13 @@ bool Foam::cp(const fileName& src, const fileName& dest) } // Dir to Dir. - cp(src/subdirs[i], destFile); + cp(src/subdirs[i], destFile, followLink); } } + else + { + return false; + } return true; } @@ -903,7 +947,7 @@ bool Foam::ln(const fileName& src, const fileName& dst) } -bool Foam::mv(const fileName& src, const fileName& dst) +bool Foam::mv(const fileName& src, const fileName& dst, const bool followLink) { if (POSIX::debug) { @@ -914,7 +958,7 @@ bool Foam::mv(const fileName& src, const fileName& dst) if ( dst.type() == fileName::DIRECTORY - && src.type() != fileName::DIRECTORY + && src.type(followLink) != fileName::DIRECTORY ) { const fileName dstName(dst/src.name()); @@ -1016,7 +1060,7 @@ bool Foam::rmDir(const fileName& directory) { fileName path = directory/fName; - if (path.type() == fileName::DIRECTORY) + if (path.type(false) == fileName::DIRECTORY) { if (!rmDir(path)) { diff --git a/src/OSspecific/POSIX/fileStat.C b/src/OSspecific/POSIX/fileStat.C index 9826983d64..f40192f03b 100644 --- a/src/OSspecific/POSIX/fileStat.C +++ b/src/OSspecific/POSIX/fileStat.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -29,6 +29,7 @@ License #include #include +#include // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -38,7 +39,12 @@ Foam::fileStat::fileStat() {} -Foam::fileStat::fileStat(const fileName& fName, const unsigned int maxTime) +Foam::fileStat::fileStat +( + const fileName& fName, + const bool followLink, + const unsigned int maxTime +) { // Work on volatile volatile bool locIsValid = false; @@ -47,13 +53,13 @@ Foam::fileStat::fileStat(const fileName& fName, const unsigned int maxTime) if (!timedOut(myTimer)) { - if (::stat(fName.c_str(), &status_) != 0) + if (followLink) { - locIsValid = false; + locIsValid = (::stat(fName.c_str(), &status_) == 0); } else { - locIsValid = true; + locIsValid = (::lstat(fName.c_str(), &status_) == 0); } } diff --git a/src/OSspecific/POSIX/fileStat.H b/src/OSspecific/POSIX/fileStat.H index fe16d20470..634d0f59bd 100644 --- a/src/OSspecific/POSIX/fileStat.H +++ b/src/OSspecific/POSIX/fileStat.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -25,7 +25,7 @@ Class Foam::fileStat Description - Wrapper for stat() system call. + Wrapper for stat() and lstat() system calls. Warning on Linux (an maybe on others) a stat() of an nfs mounted (remote) @@ -79,8 +79,21 @@ public: //- Empty constructor fileStat(); - //- Construct from components - fileStat(const fileName& fName, const unsigned int maxTime=0); + //- Construct from components. + // \param fName \n + // The file name or directory name to stat. + // + // \param followLink \n + // If it is a link, get the status of the source file/directory. + // + // \param maxTime \n + // The timeout value. + fileStat + ( + const fileName& fName, + const bool followLink = true, + const unsigned int maxTime = 0 + ); //- Construct from Istream fileStat(Istream&); @@ -96,7 +109,7 @@ public: return status_; } - //- Did constructor fail + //- Was file-stat successful? bool isValid() const { return isValid_; diff --git a/src/OpenFOAM/include/OSspecific.H b/src/OpenFOAM/include/OSspecific.H index d190f67045..79a2417319 100644 --- a/src/OpenFOAM/include/OSspecific.H +++ b/src/OpenFOAM/include/OSspecific.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -132,44 +132,60 @@ bool mkDir(const fileName&, mode_t=0777); bool chMod(const fileName&, const mode_t); //- Return the file mode -mode_t mode(const fileName&); +mode_t mode(const fileName&, const bool followLink=true); //- Return the file type: DIRECTORY or FILE -fileName::Type type(const fileName&); +fileName::Type type(const fileName&, const bool followLink=true); //- Does the name exist (as DIRECTORY or FILE) in the file system? // Optionally enable/disable check for gzip file. -bool exists(const fileName&, const bool checkGzip=true); +bool exists +( + const fileName&, + const bool checkGzip=true, + const bool followLink=true +); //- Does the name exist as a DIRECTORY in the file system? -bool isDir(const fileName&); +bool isDir(const fileName&, const bool followLink=true); //- Does the name exist as a FILE in the file system? // Optionally enable/disable check for gzip file. -bool isFile(const fileName&, const bool checkGzip=true); +bool isFile +( + const fileName&, + const bool checkGzip=true, + const bool followLink=true +); //- Return size of file -off_t fileSize(const fileName&); +off_t fileSize(const fileName&, const bool followLink=true); //- Return time of last file modification -time_t lastModified(const fileName&); +time_t lastModified(const fileName&, const bool followLink=true); //- Read a directory and return the entries as a string list fileNameList readDir ( const fileName&, const fileName::Type=fileName::FILE, - const bool filtergz=true + const bool filtergz=true, + const bool followLink=true ); //- Copy, recursively if necessary, the source to the destination -bool cp(const fileName& src, const fileName& dst); +bool cp(const fileName& src, const fileName& dst, const bool followLink=true); //- Create a softlink. dst should not exist. Returns true if successful. bool ln(const fileName& src, const fileName& dst); //- Rename src to dst -bool mv(const fileName& src, const fileName& dst); +bool mv +( + const fileName& src, + const fileName& dst, + const bool followLink=false +); //- Rename to a corresponding backup file // If the backup file already exists, attempt with "01" .. "99" suffix diff --git a/src/OpenFOAM/primitives/strings/fileName/fileName.C b/src/OpenFOAM/primitives/strings/fileName/fileName.C index becb5db393..0dd888c737 100644 --- a/src/OpenFOAM/primitives/strings/fileName/fileName.C +++ b/src/OpenFOAM/primitives/strings/fileName/fileName.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -48,9 +48,9 @@ Foam::fileName::fileName(const wordList& lst) // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -Foam::fileName::Type Foam::fileName::type() const +Foam::fileName::Type Foam::fileName::type(const bool followLink) const { - return ::Foam::type(*this); + return ::Foam::type(*this, followLink); } @@ -94,6 +94,7 @@ bool Foam::fileName::clean() ( string::size_type src = nChar; src < maxLen; + /*nil*/ ) { char c = operator[](src++); diff --git a/src/OpenFOAM/primitives/strings/fileName/fileName.H b/src/OpenFOAM/primitives/strings/fileName/fileName.H index 288da061b8..e45844eaeb 100644 --- a/src/OpenFOAM/primitives/strings/fileName/fileName.H +++ b/src/OpenFOAM/primitives/strings/fileName/fileName.H @@ -154,8 +154,9 @@ public: // Interrogation - //- Return the file type: FILE, DIRECTORY or UNDEFINED - Type type() const; + //- Return the file type: FILE, DIRECTORY, UNDEFINED or + // LINK (only if followLink=false) + Type type(const bool followLink = true) const; //- Return true if file name is absolute bool isAbsolute() const;