【发布时间】:2012-01-29 20:31:11
【问题描述】:
上下文
我正在慢慢地用 C++ 编写一个专门的 Web 服务器应用程序(使用 C onion http server library 和 JSONCPP library 进行 JSON 序列化,如果这很重要的话)。对于带有 GCC 4.6 编译器的 Linux 系统(我不关心到非 Linux 系统的可移植性,或 4.5 之前的 GCC 或 3.0 之前的 Clang)。
我决定将用户“数据库”(用户很少,可能只有一两个,所以性能不是问题,并且 O(n) 访问时间是可以接受的)为 JSON 格式,可能很小JSON 对象数组,如
{ "_user" : "basile" ;
"_crypasswd" : "XYZABC123" ;
"_email" : "basile@starynkevitch.net" ;
"firstname" : "Basile" ;
"lastname" : "Starynkevitch" ;
"privileges" : "all" ;
}
按照惯例(.htpasswd),_crypasswd 字段是用户密码的crypt(3)“加密”,由_user 名称加盐;
我想通过 Json 对象来描述用户的原因是我的应用程序可能会在描述用户的此类 Json 对象中添加(而不是替换)一些 JSON 字段(例如上面的 privileges)。我使用 JsonCpp 作为 C++ 的 Json 解析库。这个库想要解析 ifstream。
所以我正在阅读我的密码文件
extern char* iaca_passwd_path; // the path of the password file
std::ifstream jsinpass(iaca_passwd_path);
Json::Value jpassarr;
Json::Reader reader;
reader.parse(jsinpass,jpassarr,true);
jsinpass.close();
assert (jpassarr.isArray());
for (int ix=0; ix<nbu; ix++) {
const Json::Value&jcuruser= jpassarr[ix];
assert(jcuruser.isObject());
if (jcuruser["_user"].compare(user) == 0) {
std::string crypasswd = jcuruser["_crypasswd"].asString();
if (crypasswd.compare(crypted_password(user,password)) == 0) {
// good user
}
}
}
问题
显然,我想flock 或lockf 密码文件,以确保只有一个进程在读取或写入它。要调用这些函数,我需要获取ifstream jsinpass 的文件描述符(用 Unix 的说法)。但谷歌主要给了我Kreckel's fileno(我觉得很完整,但有点疯狂)来获取std::ifstream的文件描述符,我不确定构造函数不会预读其中的一些。因此我的问题:
如何锁定 C++ ifstream(Linux、GCC 4.6)?
(或者您是否找到其他方法来解决该问题?)
谢谢
【问题讨论】:
-
要获取文件描述符,请尝试gcc.gnu.org/onlinedocs/libstdc++/manual/ext_io.html(免责声明:我自己没有尝试过)
-
好吧,我不确定是否会遵循,这与 Kreckel 的解决方案有何不同?还是您建议我应该从已经
open(2)-ed 的文件描述符构造一个std::ifstream?怎么样? -
您的问题之一是如何获取文件描述符。我认为 GNU 明确为此目的提供的功能会很有用。如果您想从现有文件描述符构造一个流,您是否尝试查看页面为此目的提到的
stdio_filebuf类? -
flock()是咨询锁,你要的是fcntl()。 -
@fge: fcntl() 也是建议性的,除非你想使用 Linux 特定的强制标志(需要挂载选项,有问题等等)。