1

Are there any methods/functions that can I use with int file = open(filepath, flag); because I am trying to implement flock and because ifstream file; file.open("filepath"); won't work with flock() ?

I am trying to learn how to implement flock() in C++ and I have found some examples online. This is what I've written:

  int file;
  char configPath[] = "data/configuration.txt";
  file = open(configPath, O_RDONLY);
  if(file != -1) {
    std::cout<<"Successfully opened file: "<<configPath<<std::endl;
    if(flock(file,1) == 0) {
      //do things with the file
    }
  }

But now I don't know how to do things with the file. I would like to get the content line by line.

Here is how I did it before:

int readConfig(std::ifstream& configFile, std::string (&string)[10], int counter) {
  std::cout<<"void readConfiguration\n";
  if(!configFile) {
    std::cout<<"configuration.txt couldn't be opened\n";
  } else {
      // Get content line by line of txt file
      int i = 0;
      while(getline(configFile,string[i++]));
      //for debug only
      for(int k = 0; k<i; k++) std::cout<<"string[k]= "<<string[k]<<"\n";
    }

    return counter;
}

  configFile.open("data/configuration.txt");
  std::string inputs[10];
  int counter;
  readConfig(configFile, inputs, counter);

But I can't use flock() when I open the file using std::ifstream::open() because flock() takes two ints as arguments:

extern int flock (int __fd, int __operation) __THROW;

EDIT:

This is what I came up with help from @MSalters :

int readConfig(std::istream& configFile, std::string (&string)[10], int counter) {
  std::cout<<"void readConfiguration\n";
  if(!configFile) {
    std::cout<<"configuration.txt couldn't be opened\n";
  } else {
      // Get content line by line of txt file
      int i = 0;
      while(getline(configFile, string[i++]));
      //for debug only
      for(int k = 0; k<i; k++) std::cout<<"string[k]= "<<string[k]<<"\n";
      counter = i;
    }
    return counter;
}

int main()
{
  int file;
  char configPath[] = "data/configuration.txt";
  file = open(configPath, O_RDONLY);
  if(file != -1) {
    std::cout<<"Successfully opened file: "<<configPath<<std::endl;
    if(flock(file,1) == 0) {
      __gnu_cxx::stdio_filebuf<char> fd_file_buf{file, std::ios_base::out | std::ios_base::binary};
      std::istream fd_stream{&fd_file_buf};
      std::string inputs[10];
      int counter;
      readConfig(fd_stream, inputs, counter);
      flock(file,8);
      file = close(file);
    }
  }
}

It compiles and runs, but std::cout<<"string[k]= "<<string[k]<<"\n"; returns string[k]= and that's it.

EDIT2:

I have a web-page written in PHP that gives the user the ability to input 6 values:

URL
URL Refresh Interval
Brightness
Color1 in hex
Color2 in hex
Color3 in hex

These values will be written in configuration.txt.

Each time the web-page is accessed configuration.txt gets opened, the PHP gets some values from there and then closes it. configuration.txt is also opened when one or more of the above values are submitted and then it gets closed.

Next, I have a bash that regularly wgets the URL from configuration.txt and writes the output to a different file, called url_response.txt.

while [ 0 ]
do
    line=$(head -n 1 data/configuration.txt)
    wget -q -i $line -O url_response.txt
    sleep 2
done

This script will be put inside a C++ program.

Finally, the same C++ program will have to access url_response.txt to get and parse some strings from it and it will also have to access configuration.txt to get the three colors from it.

So I want to implement flock() in all of these programs.

Everything will run on a Raspberry Pi 4 that runs on Linux raspberrypi 4.19.58-v7l+.

Community
  • 1
  • 1
bleah1
  • 471
  • 3
  • 18
  • Use the "regular" C file interface? – molbdnilo Sep 05 '19 at 11:16
  • @molbdnilo If I knew how to do that or even what that was I wouldn't have posted here, would I ? I am reading online on what I need and what I can use ! But I do not have the big picture, nor the knowledge. I am learning on the go. – bleah1 Sep 05 '19 at 11:19
  • 1
    Here is what you can do with the `int file`: [C-style file input/output](https://en.cppreference.com/w/cpp/io/c) – acraig5075 Sep 05 '19 at 11:24
  • @acraig5075: Nope, that's with a C style `FILE*`. This is with a POSIX `int fd`. – MSalters Sep 05 '19 at 12:08
  • Meaning that I need to read here: https://www.mkompf.com/cplus/posixlist.html#files_and_directories ? – bleah1 Sep 05 '19 at 12:10
  • @bleah1: Much simpler - see https://stackoverflow.com/a/11558715/15416. Gcc has a C++ class to wrap the `int fd` from `open()` (and clang too, I think). – MSalters Sep 05 '19 at 12:12
  • @MSalters That basically means that it transforms `int fd = open()` into an `ifstream file`, correct ? I am not sure about the gcc part, because I will run this project on the Raspberry and I have no idea which compiler it uses. This gets harder and harded... – bleah1 Sep 05 '19 at 12:18
  • @bleah1: Technically, into an `istream file` (the base class of `ifstream`) but that doesn't matter for `>>` and `<<`. Raspberry's generally use GCC. The chief not-GCC platform is Windows where you mostly see Microsoft Visual C++ – MSalters Sep 05 '19 at 12:21
  • Sooo... `__gnu_cxx::stdio_filebuf fd_file_buf{file, std::ios_base::out | std::ios_base::binary}; std::ostream fd_stream{&fd_file_buf};` is way over my understanding. Which one is the newly created stream file ? Is it `fd_file_buf` ? – bleah1 Sep 05 '19 at 12:38
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/199008/discussion-between-bleah1-and-msalters). – bleah1 Sep 05 '19 at 12:44
  • @bleah1 commendation for a full description. I am not bash aficionado, but I am wondering how did C++ came into question? Would this not be possible to develop in bash only? Including the file locking too? – Chef Gladiator Sep 06 '19 at 12:41
  • @ChefGladiator I actually thought of something else. And it doesn't involve `flock` at all. I will put the script inside the c++ program. And the files will be accessed in an orderly fashion. Take a look here: https://stackoverflow.com/questions/57822336/system-path-to-bash-returns-file-txt-permission-denied – bleah1 Sep 06 '19 at 12:49
  • Technically you are not putting the script inside the program. You are calling it from the program. That confused me a lot. Still, I can not see why exactly you use compiled C++ programs. Why is not the entire solution made of one or more bash scripts? – Chef Gladiator Sep 06 '19 at 14:06
  • @ChefGladiator Because the rest of the program consists of using this: https://github.com/hzeller/rpi-rgb-led-matrix – bleah1 Sep 06 '19 at 14:13
  • @bleah1 I suggest you need to rethink the architecture of your app. I might be so bold to suggest to do this with C++/C written service(s) running on Raspbery. Used from javascript running from behind a browser. In that scenario all of your app server side, is written in C++ and running on the Raspbery side. I was told this is worth looking at -- http://cppmicroservices.org/ -- date is still 2017 though. – Chef Gladiator Sep 07 '19 at 19:26

1 Answers1

2

I think it can be easily done with C API. Use family of functions for file IO inherited from C: fopen(), fclose(), fgets() and so on.

Simple file read example to start with (and link to docs). Just add your looking routines where needed.

#include <cstdio>
#include <cstdlib>

int main()
{
    FILE* fp = std::fopen("test.txt", "r");
    if(!fp) {
        std::perror("File opening failed");
        return EXIT_FAILURE;
    }

    int c; // note: int, not char, required to handle EOF
    while ((c = std::fgetc(fp)) != EOF) { // standard C I/O file reading loop
       std::putchar(c);
    }

    if (std::ferror(fp))
        std::puts("I/O error when reading");
    else if (std::feof(fp))
        std::puts("End of file reached successfully");

    std::fclose(fp);
}
f4f
  • 891
  • 5
  • 13
  • 1
    And just to mention, C API is typically what you need when implementing your own low-level routines to replace on from C++ STL. – f4f Sep 05 '19 at 11:26
  • And where can I add `flock()` there ? I don't really want to use C, because things will get hard fast. – bleah1 Sep 05 '19 at 11:27
  • 1
    It's still a long way to go. File locks may be implemented via file-lock table (stored in a lock-file in the current directory). If so you shall put flock() before opening a file (and flock() in its turn will encapsulate opening of and reading from a file-lock table). Anyway check whether lock is free (and locking if so) will go before working file IO. – f4f Sep 05 '19 at 11:37
  • 1
    @bleah1 by your own admission you do not know a lot, which is fine, but you seem to know "things will get hard fast" if you try the C routines as patient people have suggested. That seems like a veteran developer opinion. Sadly wrong. – Chef Gladiator Sep 05 '19 at 12:04
  • @ChefGladiator nice thoughts. But using C routines without being aware of what you doing is generally a bad idea, even though there is quite a big project with plain C++ of the latest standard %) – f4f Sep 05 '19 at 12:14
  • @ChefGladiator Mate, I would love to know what I'm talking about, but I don't. I have been coding for the past half a year on a daily basis and before that I studied C and C++ in high school and at the uni. I wouldn't call me a veteran. I know that C is hard because I saw a lot of threads with C in them when I was looking for my answers. And also, if you search: "Is C hard" or "How hard is C" everybody will tell you the same thing: that C is very hard to learn, understand and use. – bleah1 Sep 05 '19 at 12:14
  • 1
    @bleah1 C might be hard, but IMHO it's a lot simpler and cleaner than C++, which has the tendency to include every feature under the sun and make the syntax so complex and difficult to read – Waqar Sep 05 '19 at 12:22
  • @bleah1 it's OK that you prefer not to use what you don't know well. Proficient codding in C is worth years of developing and supporting big applications and libraries. But knowing general features of C language is very useful for C++ programmer it's OK to use such knowledge (of C programming) when needed with high attention to details, coding rules, best practices and common mistakes even in C++ coding (especially while writing libraries). – f4f Sep 05 '19 at 12:39
  • @bleah1 please do let us know a lot more about your requirement: what is the OS you want/need to run on? C++17? As an examle WIN32 LockFile might be just what you need: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-lockfile ... but then I am not even sure do you wnt to know how is `flock` implemented ot you simply want to read file contents using what seems to be C API? Plese edit and clarify your question. – Chef Gladiator Sep 05 '19 at 13:32
  • 1
    Done ! I've edited it and added all of the details. – bleah1 Sep 05 '19 at 14:52
  • @f4f cutting a potato without "knowing of what you doing" is a bad idea too ..same applies to every software building activity. I have to say I am trying, last few years, to convince myself not to go back to C, after two decades of C++ in the meantime. – Chef Gladiator Sep 06 '19 at 12:29