summaryrefslogtreecommitdiffabout
path: root/lib
authorMichael Krelin <hacker@klever.net>2005-03-30 15:50:28 (UTC)
committer Michael Krelin <hacker@klever.net>2005-03-30 15:50:28 (UTC)
commit3ddbfeafde93d1aab16a710498d86eef4e787406 (patch) (side-by-side diff)
treed53ef21cf3b2bddfeb957c98344d0be8759ed555 /lib
parent642dc685bd0a3f1526e22827a4539aa0e06aeff7 (diff)
downloadsitecing-3ddbfeafde93d1aab16a710498d86eef4e787406.zip
sitecing-3ddbfeafde93d1aab16a710498d86eef4e787406.tar.gz
sitecing-3ddbfeafde93d1aab16a710498d86eef4e787406.tar.bz2
1. preprocessor doesn't touch unchanged files anymore
2. doublechedk on whether file is up to date when making 3. changed the way preprocessor targets depend on the timestamp file 4. a bugfix in strip_suffix/strip_prefix
Diffstat (limited to 'lib') (more/less context) (show whitespace changes)
-rw-r--r--lib/component_factory.cc19
-rw-r--r--lib/file_factory.cc1
-rw-r--r--lib/sitecing_enflesher.ll76
-rw-r--r--lib/sitecing_util.cc4
4 files changed, 80 insertions, 20 deletions
diff --git a/lib/component_factory.cc b/lib/component_factory.cc
index f8666dc..b8f5a16 100644
--- a/lib/component_factory.cc
+++ b/lib/component_factory.cc
@@ -1,175 +1,180 @@
#ifdef USE_PCH
#include "pch.h"
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <vector>
using namespace std;
#include "sitecing/component_factory.h"
#include "sitecing/sitecing_util.h"
#include "sitecing/sitecing_parser.h"
#include "sitecing/sitecing_exception.h"
#endif
namespace sitecing {
- static const char *pp_targets[] = { ".cc", ".h", ".imports", ".classname", ".baseclassname", ".ancestors" };
+ static const char *pp_targets[] = { ".cc", ".h", ".imports", ".classname", ".baseclassname", ".ancestors", ".pp_stamp" };
static const char *cc_targets[] = { ".o", ".d" };
component_factory::component_factory(configuration& c)
: config(c),
root_source(normalize_path(c.root_source,strip_trailing_slash)+'/'),
root_intermediate(normalize_path(c.root_intermediate,strip_trailing_slash)+'/'),
root_so(normalize_path(c.root_so,strip_trailing_slash)+'/') {
}
void component_factory::get_dependencies(const string& dst,file_list_t& deps) {
deps.clear();
string dp = normalize_path(dst,strip_trailing_slash);
// source documents
try { // XXX: or just compare it off?
string noro = strip_prefix(dp,root_source);
return;
}catch(utility_no_affix& una) {
}
// .so binaries
try {
string noso = strip_suffix(dp,".so");
string noro = strip_prefix(noso,root_so);
deps.push_back(root_intermediate+noro+".o");
config_options *co_so_deps = config.lookup_config(noro,config_options::flag_so_deps);
if(co_so_deps) {
for(list<string>::const_iterator i=co_so_deps->so_deps.begin();i!=co_so_deps->so_deps.end();++i)
deps.push_back(*i);
}
return;
}catch(utility_no_prefix& unp) {
throw konforka::exception(CODEPOINT,"component is outside of component root");
}catch(utility_no_suffix& uns) {
}
// preprocessor targets
for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) {
try {
string nos = strip_suffix(dp,pp_targets[ppt]);
string noro = strip_prefix(nos,root_intermediate);
deps.push_back(root_source+noro);
ifstream imports((root_intermediate+noro+".imports").c_str(),ios::in);
if(imports.good()) {
string str;
while(!imports.eof()) {
imports >> str;
if(!str.empty())
deps.push_back(root_intermediate+str+".classname");
}
}
ifstream ancestors((root_intermediate+noro+".ancestors").c_str(),ios::in);
if(ancestors.good()) {
string str;
while(!ancestors.eof()) {
ancestors >> str;
if(!str.empty())
deps.push_back(root_intermediate+str+".classname");
}
}
config_options *co_intermediate_deps = config.lookup_config(noro,config_options::flag_intermediate_deps);
if(co_intermediate_deps) {
for(list<string>::const_iterator i=co_intermediate_deps->intermediate_deps.begin();i!=co_intermediate_deps->intermediate_deps.end();++i)
deps.push_back(*i);
}
return;
}catch(utility_no_affix& una) {
// do nothing. must be a cpp dependency.
}
}
// compiler targets
for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) {
try {
string nos = strip_suffix(dp,cc_targets[cct]);
string noro = strip_prefix(nos,root_intermediate);
deps.push_back(root_intermediate+noro+".cc");
config_options *co_cpp_deps = config.lookup_config(noro,config_options::flag_cpp_deps);
if( (!co_cpp_deps) || co_cpp_deps->cpp_deps) {
ifstream df((root_intermediate+noro+".d").c_str(),ios::in);
if(df.good()) {
string str;
while(!df.eof()) {
df >> str;
if(str.find_first_of("\\:")==string::npos)
deps.push_back(combine_path(config.root_source+noro,str));
}
}
}
// XXX: extra deps like IntermediateDeps?
}catch(utility_no_affix& una) {
// do nothing.
}
}
}
bool component_factory::is_uptodate(const string& dst,file_list_t *deps) {
string dp = normalize_path(dst,strip_trailing_slash);
// XXX: or just compare it off, instead of throwing things around.
try {
- strip_prefix(dp,root_intermediate);
- return file_factory::is_uptodate(dst,deps);
- }catch(utility_no_prefix& unp) {
+ string noro = strip_prefix(dp,root_intermediate);
+ for(int ppt=0;(ppt+1)<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) {
+ try {
+ string nos = strip_suffix(noro,pp_targets[ppt]);
+ return file_factory::is_uptodate(root_intermediate+nos+".pp_stamp",deps);
+ }catch(utility_no_suffix& uns) { }
}
+ bool rv = file_factory::is_uptodate(dst,deps);
+ return rv;
+ }catch(utility_no_prefix& unp) { }
try {
strip_prefix(dp,root_so);
return file_factory::is_uptodate(dst,deps);
- }catch(utility_no_prefix& unp) {
- }
+ }catch(utility_no_prefix& unp) { }
return true;
}
void component_factory::build(const string& dst) {
string dp = normalize_path(dst,strip_trailing_slash);
// sources
try {
string noro = strip_prefix(dp,root_source);
// building the sources is left up to developer
return;
}catch(utility_no_prefix& unp) {
}
// .so files
try {
string noso = strip_suffix(dp,".so");
string noro = strip_prefix(noso,root_so);
string o = root_intermediate+noro+".o";
if(access(o.c_str(),R_OK))
throw konforka::exception(CODEPOINT,string("can't access compiled component code (")+o+")");
make_path(dir_name(root_so+noro),0755);
file_lock lock_cc(root_intermediate+noro+".o.lock");
file_lock lock_so(root_so+noro+".so.lock");
int stdO = open((root_intermediate+noro+".ld.stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664);
if(stdO<0)
throw konforka::exception(CODEPOINT,"failed to open/create linker stdout");
int stdE = open((root_intermediate+noro+".ld.stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664);
if(stdE<0) {
close(stdO);
throw konforka::exception(CODEPOINT,"failed to open/create linker stderr");
}
list<string> args;
config_options *co_ld_flags = config.lookup_config(noro,config_options::flag_ld_flags);
if(co_ld_flags) {
args.insert(args.end(),co_ld_flags->ld_flags.begin(),co_ld_flags->ld_flags.end());
}
args.push_back("-shared");
args.push_back(o);
file_list_t ancestors;
get_ancestors(noro,ancestors);
for(file_list_t::const_iterator i=ancestors.begin();i!=ancestors.end();++i) {
string aso=root_so+*i+".so";
make(aso);
args.push_back(aso);
}
args.push_back("-o"); args.push_back(dp);
// TODO: "g++" configurable
int rv = execute("g++",args,stdO,stdE);
if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) )
@@ -204,96 +209,98 @@ namespace sitecing {
}
list<string> args;
config_options *co_cpp_flags = config.lookup_config(noro,config_options::flag_cpp_flags);
if(co_cpp_flags) {
args.insert(args.end(),co_cpp_flags->cpp_flags.begin(),co_cpp_flags->cpp_flags.end());
}
// TODO: maybe move it to separare config option like CoreCPPFLags?
args.push_back("-I"+root_intermediate);
args.push_back("-I"+root_source);
args.push_back("-MD"); args.push_back("-MF"); args.push_back(root_intermediate+noro+".d");
args.push_back("-c");
args.push_back(cc);
args.push_back("-o"); args.push_back(o);
// TODO: "g++" configurable
int rv = execute("g++",args,stdO,stdE);
if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) )
throw compile_error(CODEPOINT,"failed to compile component",noro);
return;
}catch(utility_no_affix& una) {
// do nothing, not a compiler target
}
}
// preprocessor targets
for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) {
try {
string nos = strip_suffix(dp,pp_targets[ppt]);
string noro = strip_prefix(nos,root_intermediate);
string src = root_source+noro;
if(access(src.c_str(),R_OK))
throw konforka::exception(CODEPOINT,string("can't access component source (")+src+")");
make_path(dir_name(root_intermediate+noro),0755);
file_lock lock(root_intermediate+noro+".lock");
sitecing_parser parser(*this);
config_options *co_skeleton = config.lookup_config(noro,config_options::flag_skeleton);
if(co_skeleton)
parser.skeleton = co_skeleton->skeleton;
static const char *id_chars = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ";
parser.class_name = normalize_path(noro,strip_leading_slash|strip_trailing_slash);
for(string::size_type illc = parser.class_name.find_first_not_of(id_chars);illc!=string::npos;illc=parser.class_name.find_first_not_of(id_chars,illc)) {
string::size_type lc = parser.class_name.find_first_of(id_chars,illc);
int n = ((lc==string::npos)?parser.class_name.length():lc)-illc;
parser.class_name.replace(illc,n,n,'_');
}
parser.class_name = "_SCC_"+parser.class_name;
parser.output_basename = nos;
parser.component_basename = noro;
try {
parser.preprocess(src);
+ string sf = root_intermediate+noro+".pp_stamp";
+ ofstream sfs(sf.c_str(),ios::trunc|ios::out); // touch .pp_stamp
}catch(preprocessor_error& pe) {
pe.component_name = noro;
pe.see(CODEPOINT);
throw;
}
return;
}catch(utility_no_affix& una) {
// must be a crap from .d file
}
}
cerr << "ignoring build request for " << dp << endl;
}
int component_factory::execute(const string& cmd, const list<string>& args,int stdo,int stde) {
// XXX: is it right that we do stdio/stderr tricks outside of the function?
cerr << "executing: " << cmd;
vector<const char*> argv(args.size()+2);
argv[0]=cmd.c_str();
int an = 1;
for(list<string>::const_iterator i=args.begin();i!=args.end();i++) {
cerr << " " << *i ;
argv[an++] = i->c_str();
}
cerr << endl;
argv[an++]=NULL;
pid_t pid = vfork();
if(pid==-1) {
close(stdo); close(stde);
throw konforka::exception(CODEPOINT,"failed to vfork()");
}
if(!pid) {
// child
if(dup2(stdo,1)!=1)
_exit(-1);
if(dup2(stde,2)!=2)
_exit(-1);
close(0);
execvp(cmd.c_str(),(char**)&argv.front());
_exit(-1);
}
// parent
close(stdo); close(stde);
int rv;
if(waitpid(pid,&rv,0)<0)
throw konforka::exception(CODEPOINT,"failed to waitpid()");
return rv;
}
diff --git a/lib/file_factory.cc b/lib/file_factory.cc
index c6b5748..7ca7b86 100644
--- a/lib/file_factory.cc
+++ b/lib/file_factory.cc
@@ -1,55 +1,56 @@
#ifdef USE_PCH
#include "pch.h"
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <konforka/exception.h>
using namespace std;
#include "sitecing/file_factory.h"
#endif
namespace sitecing {
bool file_factory::is_uptodate(const string& dst,file_list_t* deps) {
file_list_t deplist;
file_list_t *fl = deps?deps:&deplist;
get_dependencies(dst,*fl);
struct stat stdst;
if(stat(dst.c_str(),&stdst))
return false;
for(file_list_t::const_iterator i=fl->begin();i!=fl->end();i++) {
struct stat stdep;
if(stat(i->c_str(),&stdep))
return false;
if(stdst.st_mtime<stdep.st_mtime)
return false;
if(!is_uptodate(*i))
return false;
}
return true;
}
void file_factory::make(const string& dst) {
try {
depth++;
if(depth>25)
throw konforka::exception(CODEPOINT,"recursed too deeply.");
file_list_t deps;
if(!is_uptodate(dst,&deps)) {
for(file_list_t::const_iterator i=deps.begin();i!=deps.end();i++)
make(*i);
+ if(!is_uptodate(dst,&deps))
build(dst);
}
depth--;
}catch(konforka::exception& ke) {
depth--;
ke.see(CODEPOINT);
throw;
}catch(...) {
depth--;
throw;
}
}
}
diff --git a/lib/sitecing_enflesher.ll b/lib/sitecing_enflesher.ll
index 5f631d7..46489c7 100644
--- a/lib/sitecing_enflesher.ll
+++ b/lib/sitecing_enflesher.ll
@@ -1,91 +1,81 @@
%{
#include <iostream>
#include <fstream>
#include <cassert>
#include <stdexcept>
using namespace std;
#include "sitecing/sitecing_exception.h"
using namespace sitecing;
#define sitecing_enflesher_flexlexer_once
#include "sitecing/sitecing_enflesher.h"
#include "sitecing/sitecing_parser.h"
#undef yyFlexLexer
#define yyFlexLexer sitecing_enflesherFlexLexer
%}
%option 8bit c++ verbose noyywrap yyclass="sitecing_enflesher" yylineno prefix="sitecing_enflesher" stack debug
ID [A-Za-z_][A-Za-z0-9_]*
%%
^\%\%\#[^\n]+\n {
string line = yytext;
line.erase(0,3);
line.erase(line.length()-1);
- outs.flush();
- outs.close();
- outs.clear();
- outs.open((parser.output_basename+line).c_str(),ios::trunc);
- if(!outs.good())
- throw preprocessor_error(CODEPOINT,"failed to write preprocessor output");
+ outs_open(parser.output_basename+line);
anchor();
anchoraged = true;
}
^\%\%[^\n]+\n {
string line = yytext;
line.erase(0,2);
line.erase(line.length()-1);
- outs.flush();
- outs.close();
- outs.clear();
- outs.open((parser.output_basename+line).c_str(),ios::trunc);
- if(!outs.good())
- throw preprocessor_error(CODEPOINT,"failed to write preprocessor output");
+ outs_open(parser.output_basename+line);
anchoraged = false;
}
\<\%component_basename\%\> outs << parser.component_basename; anchor_time = true;
\<\%impl\%\> outs << parser.impl; anchor_time = true;
\<\%member_functions:impl\%\> {
for(sitecing_parser::member_functions_t::const_iterator i=parser.member_functions.begin();i!=parser.member_functions.end();i++) {
outs << i->type << " " << parser.class_name << "::";
if(i->name.empty()) {
outs << parser.class_name << "()";
bool first = true;
for(sitecing_parser::member_variables_t::iterator i=parser.member_variables.begin();i!=parser.member_variables.end();i++) {
if(i->initializer.empty())
continue;
if(first) {
outs << ":";
first=false;
}else{
outs << ",";
}
if(i->bComponent) {
outs << i->name << "(NULL)";
}else {
outs << i->name << "(" << i->initializer << ")";
}
}
}else if(i->name == "~")
outs << "~" << parser.class_name << "()";
else
outs << i->name << i->args;
outs << "{\n" << i->body << "\n}\n";
}
anchor_time = true;
}
\<\%class_name\%\> outs << parser.class_name; anchor_time = true;
\<\%baseclass_header\%\> outs << parser.base_header; anchor_time = true;
\<\%decl\%\> outs << parser.decl; anchor_time = true;
\<\%baseclass_name\%\> outs << parser.base_class; anchor_time = true;
\<\%member_variables:decl\%\> {
for(sitecing_parser::member_variables_t::iterator i=parser.member_variables.begin();i!=parser.member_variables.end();i++) {
if(i->bComponent) {
if(i->type.empty()) {
i->type = parser.factory.get_classname(i->initializer);
}
if(i->bTypeOnly) {
outs << "typedef " << i->type << " " << i->name << ";\n";
}else{
outs << "typedef " << i->type << " __type_" << i->name << ";\nsitecing::so_component __soc_" << i->name << ";\n__type_" << i->name << " *" << i->name << ";\n";
@@ -152,51 +142,113 @@ ID [A-Za-z_][A-Za-z0-9_]*
}
anchor_time = true;
}
\<\%ancestors:base_clause_part\%\> {
for(sitecing_parser::ancestor_classes_t::const_iterator i=parser.ancestor_classes.begin();i!=parser.ancestor_classes.end();++i) {
outs << ", virtual public " << parser.factory.get_classname(i->path);
}
}
\<\%ancestors:typedefs\%\> {
for(sitecing_parser::ancestor_classes_t::const_iterator i=parser.ancestor_classes.begin();i!=parser.ancestor_classes.end();++i) {
outs << "typedef class " << parser.factory.get_classname(i->path) << " " << i->name << ";\n";
}
anchor_time = true;
}
\<\%ancestors:import\%\> {
for(sitecing_parser::ancestor_classes_t::const_iterator i=parser.ancestor_classes.begin();i!=parser.ancestor_classes.end();++i) {
outs << i->name << "::__do_imports();\n";
}
anchor_time = true;
}
\n {
if(anchor_time)
anchor();
ECHO;
}
. ECHO;
%%
void sitecing_enflesher::LexerOutput(const char *buf,int size) {
outs.write(buf,size);
}
void sitecing_enflesher::enflesh() {
ifstream ifs(parser.skeleton.c_str());
if(!ifs.good())
throw preprocessor_error(CODEPOINT,"failed to open skeleton file");
switch_streams(&ifs,NULL);
yylex();
}
void sitecing_enflesher::anchor() {
if(!anchoraged)
return;
outs << "\n#line " << lineno() << " \"" << parser.skeleton << "\"\n";
anchor_time = false;
}
+
+void sitecing_enflesher::outs_open(const string& nfile) {
+ if(!outs_filename.empty()) {
+ outs.flush();
+ outs.close();
+ outs.clear();
+ /*
+ * compare source and destination files.
+ *
+ * one can also keep a hash for the old one and compute one for the
+ * output while writing, but I'm not sure if it's any better. Surely a
+ * bit less accurate, unless we're going to compare it in case of
+ * difference, anyway.
+ */
+ bool overwrite = false;
+ struct stat st_s, st_d;
+ string fn_s = outs_filename+".new";
+ string fn_d = outs_filename;
+ if(stat(fn_d.c_str(),&st_d)) {
+ overwrite = true;
+ }else{
+ if(stat(fn_s.c_str(),&st_s))
+ throw preprocessor_error(CODEPOINT,"failed to stat() supposedly created file");
+ if(st_s.st_size!=st_d.st_size) {
+ overwrite = true;
+ }else{
+ ifstream i_s(fn_s.c_str(),ios::in);
+ if(!i_s)
+ throw preprocessor_error(CODEPOINT,"failed to open supposedly created file");
+ ifstream i_d(fn_d.c_str(),ios::in);
+ if(!i_d)
+ throw preprocessor_error(CODEPOINT,"failed to open the old preprocessed source");
+ off_t remaining = st_s.st_size;
+ char t1[2048];
+ char t2[sizeof(t1)];
+ while(remaining) {
+ int rb = remaining;
+ if(rb>sizeof(t1))
+ rb = sizeof(t1);
+ if(i_s.read(t1,rb).gcount()!=rb)
+ throw preprocessor_error(CODEPOINT,"error reading just created file");
+ if(i_d.read(t2,rb).gcount()!=rb)
+ throw preprocessor_error(CODEPOINT,"error reading the old preprocessed source");
+ if(memcmp(t1,t2,rb)) {
+ overwrite = true;
+ break;
+ }
+ remaining -= rb;
+ }
+ }
+ }
+ if(overwrite) {
+ cerr << "renaming '" << fn_s << "'" << endl;
+ if(rename(fn_s.c_str(),fn_d.c_str()))
+ throw preprocessor_error(CODEPOINT,"failed to rename() generated output");
+ }
+ }
+ outs_filename = nfile;
+ outs.open((nfile+".new").c_str(),ios::trunc);
+ if(!outs.good())
+ throw preprocessor_error(CODEPOINT,"failed to write preprocessor output");
+}
/*
* vim:set ft=lex:
*/
diff --git a/lib/sitecing_util.cc b/lib/sitecing_util.cc
index 5466b28..f892a60 100644
--- a/lib/sitecing_util.cc
+++ b/lib/sitecing_util.cc
@@ -11,103 +11,103 @@
#include <iostream>
#include <fstream>
#include <cassert>
#include "sitecing/sitecing_util.h"
#endif
namespace sitecing {
/*
* XXX: all of these utilities could be sheerly optimized.
*/
string normalize_path(const string& path,int opts) {
const char *s = path.c_str();
string rv;
string::size_type notslash = 0;
if( (*s)=='.' && s[1]=='/' )
s+=2;
if(opts&strip_leading_slash)
for(;(*s) && (*s)=='/';s++);
for(;*s;s++) {
if( (*s)=='/' ) {
if(s[1]=='/')
continue;
if(s[1]=='.' && s[2]=='/') {
s+=2;
continue;
}
}
if(opts&restrict_dotdot) {
if(
( rv.empty() && s[0]=='.' && s[1]=='.' && s[2]=='/' ) // "^../"
|| ( s[0]=='/' && s[1]=='.' && s[2]=='.' && (s[3]==0 || s[3]=='/') ) // "/..(/|$)"
)
throw utility_restricted_sequence(CODEPOINT,"restricted updir sequence encountered");
}
rv += *s;
if( (*s) != '/' )
notslash=rv.length();
}
if(!(opts&strip_trailing_slash))
notslash++;
if(notslash<rv.length())
rv.erase(notslash); // XXX: check the logic of stripping/not strippling trailing slash
return rv;
}
string strip_prefix(const string& str,const string& prefix) {
- if(str.compare(0,prefix.length(),prefix))
+ if( (str.length()<prefix.length()) || str.compare(0,prefix.length(),prefix))
throw utility_no_prefix(CODEPOINT,"no such prefix");
return str.substr(prefix.length());
}
string strip_suffix(const string& str,const string& suffix) {
- if(str.compare(str.length()-suffix.length(),suffix.length(),suffix))
+ if( (str.length()<suffix.length()) || str.compare(str.length()-suffix.length(),suffix.length(),suffix))
throw utility_no_suffix(CODEPOINT,"no such suffix");
return str.substr(0,str.length()-suffix.length());
}
string dir_name(const string& filename) {
string::size_type sl = filename.find_last_of('/');
if(sl==string::npos)
return ""; // no slashes -- no dir.
string::size_type nosl = filename.find_last_not_of('/',sl);
if(nosl==string::npos)
return ""; // only slashes -- no dir. XXX: only slashes after the last slash... does it mean no dir?
return filename.substr(0,nosl+1);
}
void make_path(const string& path,mode_t mode) {
struct stat st;
for(string::size_type sl=0;sl!=string::npos;sl=path.find('/',sl+1)) {
if(!sl)
continue;
string p = path.substr(0,sl);
if(stat(p.c_str(),&st) || !S_ISDIR(st.st_mode)) {
if(mkdir(p.c_str(),mode))
throw konforka::exception(CODEPOINT,"failed to mkdir()");
}
}
if(stat(path.c_str(),&st) || !S_ISDIR(st.st_mode)) {
if(mkdir(path.c_str(),mode))
throw konforka::exception(CODEPOINT,"failed to mkdir()");
}
}
void file_lock::lock(const string& f) {
unlock();
fd = open(f.c_str(),O_CREAT|O_RDWR,S_IRUSR|S_IWUSR);
if(fd<0)
throw konforka::exception(CODEPOINT,"failed to open/create lockfile");
try {
lock();
}catch(konforka::exception& ke) {
ke.see(CODEPOINT);
close(fd); fd=-1;
throw;
}catch(...) {
close(fd); fd=-1;
throw;
}
}
void file_lock::lock() {