BUG: UListIO: byteSize overflowing on really big faceLists
[OpenFOAM-2.0.x.git] / src / OpenFOAM / db / dynamicLibrary / dynamicCode / dynamicCode.C
blob2f975771b89604cda8698a17bb60b786e9a42c84
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
9     This file is part of OpenFOAM.
11     OpenFOAM is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by
13     the Free Software Foundation, either version 3 of the License, or
14     (at your option) any later version.
16     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "dynamicCode.H"
27 #include "dynamicCodeContext.H"
28 #include "stringOps.H"
29 #include "IFstream.H"
30 #include "OFstream.H"
31 #include "OSspecific.H"
32 #include "dictionary.H"
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 int Foam::dynamicCode::allowSystemOperations
38     Foam::debug::infoSwitch("allowSystemOperations", 0)
42 const Foam::word Foam::dynamicCode::codeTemplateEnvName
43     = "FOAM_CODE_TEMPLATES";
45 const Foam::fileName Foam::dynamicCode::codeTemplateDirName
46     = "codeTemplates/dynamicCode";
48 const char* const Foam::dynamicCode::libTargetRoot =
49     "LIB = $(PWD)/../platforms/$(WM_OPTIONS)/lib/lib";
51 const char* const Foam::dynamicCode::topDirName = "dynamicCode";
54 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
56 void Foam::dynamicCode::checkSecurity
58     const char* title,
59     const dictionary& dict
62     if (isAdministrator())
63     {
64         FatalIOErrorIn
65         (
66             title,
67             dict
68         )   << "This code should not be executed by someone with administrator"
69             << " rights due to security reasons." << nl
70             << "(it writes a shared library which then gets loaded "
71             << "using dlopen)"
72             << exit(FatalIOError);
73     }
75     if (!allowSystemOperations)
76     {
77         FatalIOErrorIn
78         (
79             title,
80             dict
81         )   << "Loading a shared library using case-supplied code is not"
82             << " enabled by default" << nl
83             << "because of security issues. If you trust the code you can"
84             << " enable this" << nl
85             << "facility be adding to the InfoSwitches setting in the system"
86             << " controlDict:" << nl << nl
87             << "    allowSystemOperations 1" << nl << nl
88             << "The system controlDict is either" << nl << nl
89             << "    ~/.OpenFOAM/$WM_PROJECT_VERSION/controlDict" << nl << nl
90             << "or" << nl << nl
91             << "    $WM_PROJECT_DIR/etc/controlDict" << nl
92             << endl
93             << exit(FatalIOError);
94     }
98 Foam::word Foam::dynamicCode::libraryBaseName(const fileName& libPath)
100     word libName(libPath.name(true));
101     libName.erase(0, 3);    // remove leading 'lib' from name
102     return libName;
107 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
109 void Foam::dynamicCode::copyAndFilter
111     ISstream& is,
112     OSstream& os,
113     const HashTable<string>& mapping
116     if (!is.good())
117     {
118         FatalErrorIn
119         (
120             "dynamicCode::copyAndFilter()"
121             " const"
122         )   << "Failed opening for reading " << is.name()
123             << exit(FatalError);
124     }
126     if (!os.good())
127     {
128         FatalErrorIn
129         (
130             "dynamicCode::copyAndFilter()"
131             " const"
132         )   << "Failed writing " << os.name()
133             << exit(FatalError);
134     }
136     // Copy file while rewriting $VARS and ${VARS}
137     string line;
138     do
139     {
140         is.getLine(line);
142         // expand according to mapping
143         // expanding according to env variables might cause too many
144         // surprises
145         stringOps::inplaceExpand(line, mapping);
146         os.writeQuoted(line, false) << nl;
147     }
148     while (is.good());
152 bool Foam::dynamicCode::resolveTemplates
154     const UList<fileName>& templateNames,
155     DynamicList<fileName>& resolvedFiles,
156     DynamicList<fileName>& badFiles
159     // try to get template from FOAM_CODESTREAM_TEMPLATES
160     const fileName templateDir(Foam::getEnv(codeTemplateEnvName));
162     bool allOkay = true;
163     forAll(templateNames, fileI)
164     {
165         const fileName& templateName = templateNames[fileI];
167         fileName file;
168         if (!templateDir.empty() && isDir(templateDir))
169         {
170             file = templateDir/templateName;
171             if (!isFile(file, false))
172             {
173                 file.clear();
174             }
175         }
177         // not found - fallback to ~OpenFOAM expansion
178         if (file.empty())
179         {
180             file = findEtcFile(codeTemplateDirName/templateName);
181         }
183         if (file.empty())
184         {
185             badFiles.append(templateName);
186             allOkay = false;
187         }
188         else
189         {
190             resolvedFiles.append(file);
191         }
192     }
194     return allOkay;
198 bool Foam::dynamicCode::writeCommentSHA1(Ostream& os) const
200     const bool hasSHA1 = filterVars_.found("SHA1sum");
202     if (hasSHA1)
203     {
204         os  << "/* dynamicCode:\n * SHA1 = ";
205         os.writeQuoted(filterVars_["SHA1sum"], false) << "\n */\n";
206     }
208     return hasSHA1;
212 bool Foam::dynamicCode::createMakeFiles() const
214     // Create Make/files
215     if (compileFiles_.empty())
216     {
217         return false;
218     }
220     const fileName dstFile(this->codePath()/"Make/files");
222     // Create dir
223     mkDir(dstFile.path());
225     OFstream os(dstFile);
226     //Info<< "Writing to " << dstFile << endl;
227     if (!os.good())
228     {
229         FatalErrorIn
230             (
231                 "dynamicCode::createMakeFiles()"
232                 " const"
233             )   << "Failed writing " << dstFile
234                 << exit(FatalError);
235     }
237     writeCommentSHA1(os);
239     // Write compile files
240     forAll(compileFiles_, fileI)
241     {
242         os.writeQuoted(compileFiles_[fileI], false) << nl;
243     }
245     os  << nl
246         << libTargetRoot << codeName_.c_str() << nl;
248     return true;
252 bool Foam::dynamicCode::createMakeOptions() const
254     // Create Make/options
255     if (compileFiles_.empty() || makeOptions_.empty())
256     {
257         return false;
258     }
260     const fileName dstFile(this->codePath()/"Make/options");
262     // Create dir
263     mkDir(dstFile.path());
265     OFstream os(dstFile);
266     //Info<< "Writing to " << dstFile << endl;
267     if (!os.good())
268     {
269         FatalErrorIn
270             (
271                 "dynamicCode::createMakeOptions()"
272                 " const"
273             )   << "Failed writing " << dstFile
274                 << exit(FatalError);
275     }
277     writeCommentSHA1(os);
278     os.writeQuoted(makeOptions_, false) << nl;
280     return true;
284 bool Foam::dynamicCode::writeDigest(const SHA1Digest& sha1) const
286     const fileName file = digestFile();
287     mkDir(file.path());
289     OFstream os(file);
290     sha1.write(os, true) << nl;
292     return os.good();
296 bool Foam::dynamicCode::writeDigest(const std::string& sha1) const
298     const fileName file = digestFile();
299     mkDir(file.path());
301     OFstream os(file);
302     os  << '_';
303     os.writeQuoted(sha1, false) << nl;
305     return os.good();
309 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
311 Foam::dynamicCode::dynamicCode(const word& codeName, const word& codeDirName)
313     codeRoot_(stringOps::expand("$FOAM_CASE")/topDirName),
314     libSubDir_(stringOps::expand("platforms/$WM_OPTIONS/lib")),
315     codeName_(codeName),
316     codeDirName_(codeDirName)
318     if (codeDirName_.empty())
319     {
320         codeDirName_ = codeName_;
321     }
323     clear();
327 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
329 Foam::fileName Foam::dynamicCode::codeRelPath() const
331     return topDirName/codeDirName_;
335 Foam::fileName Foam::dynamicCode::libRelPath() const
337     return codeRelPath()/libSubDir_/"lib" + codeName_ + ".so";
341 void Foam::dynamicCode::clear()
343     compileFiles_.clear();
344     copyFiles_.clear();
345     createFiles_.clear();
346     filterVars_.clear();
347     filterVars_.set("typeName", codeName_);
348     filterVars_.set("SHA1sum", SHA1Digest().str());
350     // provide default Make/options
351     makeOptions_ =
352         "EXE_INC = -g\n"
353         "\n\nLIB_LIBS = ";
357 void Foam::dynamicCode::reset
359     const dynamicCodeContext& context
362     clear();
363     setFilterContext(context);
367 void Foam::dynamicCode::addCompileFile(const fileName& name)
369     compileFiles_.append(name);
373 void Foam::dynamicCode::addCopyFile(const fileName& name)
375     copyFiles_.append(name);
379 void Foam::dynamicCode::addCreateFile
381     const fileName& name,
382     const string& contents
385     createFiles_.append(fileAndContent(name, contents));
389 void Foam::dynamicCode::setFilterContext
391     const dynamicCodeContext& context
394     filterVars_.set("localCode", context.localCode());
395     filterVars_.set("code", context.code());
396     filterVars_.set("codeInclude", context.include());
397     filterVars_.set("SHA1sum", context.sha1().str());
401 void Foam::dynamicCode::setFilterVariable
403     const word& key,
404     const std::string& value
407     filterVars_.set(key, value);
411 void Foam::dynamicCode::setMakeOptions(const std::string& content)
413     makeOptions_ = content;
417 bool Foam::dynamicCode::copyOrCreateFiles(const bool verbose) const
419     if (verbose)
420     {
421         Info<< "Creating new library in " << this->libRelPath() << endl;
422     }
424     const label nFiles = compileFiles_.size() + copyFiles_.size();
426     DynamicList<fileName> resolvedFiles(nFiles);
427     DynamicList<fileName> badFiles(nFiles);
429     // resolve template, or add to bad-files
430     resolveTemplates(compileFiles_, resolvedFiles, badFiles);
431     resolveTemplates(copyFiles_, resolvedFiles, badFiles);
433     if (!badFiles.empty())
434     {
435         FatalErrorIn
436         (
437             "dynamicCode::copyFilesContents(..)"
438         )   << "Could not find the code template(s): "
439             << badFiles << nl
440             << "Under the $" << codeTemplateEnvName
441             << " directory or via via the ~OpenFOAM/"
442             << codeTemplateDirName << " expansion"
443             << exit(FatalError);
444     }
448     // Create dir
449     const fileName outputDir = this->codePath();
451     // Create dir
452     mkDir(outputDir);
454     // Copy/filter files
455     forAll(resolvedFiles, fileI)
456     {
457         const fileName& srcFile = resolvedFiles[fileI];
458         const fileName  dstFile(outputDir/srcFile.name());
460         IFstream is(srcFile);
461         //Info<< "Reading from " << is.name() << endl;
462         if (!is.good())
463         {
464             FatalErrorIn
465             (
466                 "dynamicCode::copyFilesContents(const fileName&)"
467                 " const"
468             )   << "Failed opening " << srcFile
469                 << exit(FatalError);
470         }
472         OFstream os(dstFile);
473         //Info<< "Writing to " << dstFile.name() << endl;
474         if (!os.good())
475         {
476             FatalErrorIn
477             (
478                 "dynamicCode::copyFilesContents(const fileName&)"
479                 " const"
480             )   << "Failed writing " << dstFile
481                 << exit(FatalError);
482         }
484         // Copy lines while expanding variables
485         copyAndFilter(is, os, filterVars_);
486     }
489     // Create files:
490     forAll(createFiles_, fileI)
491     {
492         const fileName dstFile
493         (
494             outputDir/stringOps::expand(createFiles_[fileI].first())
495         );
497         mkDir(dstFile.path());
498         OFstream os(dstFile);
499         //Info<< "Writing to " << createFiles_[fileI].first() << endl;
500         if (!os.good())
501         {
502             FatalErrorIn
503             (
504                 "dynamicCode::copyOrCreateFiles()"
505                 " const"
506             )   << "Failed writing " << dstFile
507                 << exit(FatalError);
508         }
509         os.writeQuoted(createFiles_[fileI].second(), false) << nl;
510     }
513     // Create Make/files + Make/options
514     createMakeFiles();
515     createMakeOptions();
517     writeDigest(filterVars_["SHA1sum"]);
519     return true;
523 bool Foam::dynamicCode::wmakeLibso() const
525     const Foam::string wmakeCmd("wmake -s libso " + this->codePath());
526     Info<< "Invoking " << wmakeCmd << endl;
528     if (Foam::system(wmakeCmd))
529     {
530         return false;
531     }
532     else
533     {
534         return true;
535     }
539 bool Foam::dynamicCode::upToDate(const SHA1Digest& sha1) const
541     const fileName file = digestFile();
543     if (!exists(file, false) || SHA1Digest(IFstream(file)()) != sha1)
544     {
545         return false;
546     }
548     return true;
552 bool Foam::dynamicCode::upToDate(const dynamicCodeContext& context) const
554     return upToDate(context.sha1());
558 // ************************************************************************* //