在Linux(GCC 4.6)上聚集C ++ ifstream [英] flock-ing a C++ ifstream on Linux (GCC 4.6)

查看:210
本文介绍了在Linux(GCC 4.6)上聚集C ++ ifstream的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在慢慢地用C ++编写一个专用的Web服务器应用程序(使用C 洋葱http服务器库 JSONCPP库用于JSON序列化(如果需要的话).),用于具有GCC 4.6编译器的Linux系统(我不必担心可移植到非Linux系统,4.5之前的GCC或3.0之前的Clang的可移植性.

I'm slowly writing a specialized web server application in C++ (using the C onion http server library and the JSONCPP library for JSON serialization, if that matters)., for a Linux system with GCC 4.6 compiler (I don't care about portability to non Linux systems, or to GCC before 4.5 or to Clang before 3.0).

我决定以JSON格式保留用户数据库"(用户很少,可能只有一两个,所以性能不是问题,并且O(n)访问时间是可以接受的) JSON对象数组,例如

I decided to keep the user "database" (there will be very few users, probably one or two, so performance is not a concern, and O(n) access time is acceptable) in JSON format, probably as a small array of JSON objects like

 { "_user" : "basile" ;
   "_crypasswd" : "XYZABC123" ; 
   "_email" : "basile@starynkevitch.net" ;
   "firstname" : "Basile" ;
   "lastname" : "Starynkevitch" ;
   "privileges" : "all" ;
 }

按照惯例(),_crypasswd字段是 crypt( 3)用户密码的加密",以_user名称为基;

with the convention (à la .htpasswd) that the _crypasswd field is the crypt(3) "encryption" of the user password, salted by the _user name;

我想通过Json对象描述用户的原因是我的应用程序可能在此类描述用户的Json对象中添加(而不是替换)一些JSON字段(例如上述privileges).我正在使用 JsonCpp 作为C ++的Json解析库.该库希望解析ifstream.

The reason I want to describe users by Json objects is that my application might add (not replace) some JSON fields (like e.g. privileges above) in such Json objects describing users. I'm using JsonCpp as a Json parsing library for C++. This library wants an ifstream to be parsed.

所以我正在使用读取密码文件

So I am reading my password file with

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 Kreckel的文件号(我觉得很完整,但有点疯狂)获取std::ifstream的文件描述符,但我不确定构造函数是否会预读其中的一部分.因此,我的问题:


question

Obviously, I want to flock or lockf the password file, to ensure that only one process is reading or writing it. To call these functions, I need to get the file descriptor (in Unix parlance) of the ifstream jsinpass. But Google gives me mostly Kreckel's fileno (which I find complete, but a bit insane) to get the file descriptor of an std::ifstream and I am not sure that the constructor won't pre-read some of it. Hence my question:

(或者您是否找到其他方法来解决该问题?)

(Or do you find some other way to tackle that issue?)

谢谢

推荐答案

我对此问题的解决方案来自于以下答案: https: //stackoverflow.com/a/19749019/5899976

My solution to this problem is derived from this answer: https://stackoverflow.com/a/19749019/5899976

我只在GCC 4.8.5上进行过测试.

I've only tested it with GCC 4.8.5.

#include <cstring>  // for strerror()
#include <iostream> // for std::cerr
#include <fstream>
#include <ext/stdio_filebuf.h>

extern "C" {
#include <errno.h>
#include <sys/file.h>  // for flock()
}

    // Atomically increments a persistent counter, stored in /tmp/counter.txt
int increment_counter()
{
    std::fstream file( "/tmp/counter.txt" );
    if (!file) file.open( "/tmp/counter.txt", std::fstream::out );

    int fd = static_cast< __gnu_cxx::stdio_filebuf< char > * const >( file.rdbuf() )->fd();
    if (flock( fd, LOCK_EX ))
    {
        std::cerr << "Failed to lock file: " << strerror( errno ) << "\n";
    }

    int value = 0;
    file >> value;
    file.clear();   // clear eof bit.
    file.seekp( 0 );
    file << ++value;

    return value;

    // When 'file' goes out of scope, it's closed.  Moreover, since flock() is
    //  tied to the file descriptor, it gets released when the file is closed.
}

这篇关于在Linux(GCC 4.6)上聚集C ++ ifstream的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆