2

Is there any (simple) way to detect in some_function() if ofs is writing to /dev/null or not?

#include <fstream>

some_function(std::ofstream & ofs);

int main()
{
    std::ofstream ofs("/dev/null");
    ofs << "lorem ipsum";

    some_function(ofs); // Testing in here

    return 0;
}
Acorn
  • 24,970
  • 5
  • 40
  • 69
user2725742
  • 398
  • 2
  • 12
  • This doesn't address the question, but you don't need that call to `ofs.close()`. The destructor will do that. – Pete Becker May 16 '18 at 20:35
  • Possible duplicate of [Getting a FILE\* from a std::fstream](https://stackoverflow.com/questions/109449/getting-a-file-from-a-stdfstream) –  May 16 '18 at 20:36
  • 2
    @Frank Not sure if that's a dupe. – HolyBlackCat May 16 '18 at 20:36
  • 2
    Quick hack: check the size of `/dev/null` before and after the call ;-) ;-) ;-) – Sergey Kalinichenko May 16 '18 at 20:37
  • 1
    More likely, this one: [Getting filename (or path) from fstream](https://stackoverflow.com/questions/10773391/getting-filename-or-path-from-fstream) – Acorn May 16 '18 at 20:37
  • Are you asking whether you can test that the constructor did what you told it to do, or are you asking how to get back information that you've thrown away? If writing to /dev/null means something special, keep a note that that's what you're doing. – Pete Becker May 16 '18 at 20:37
  • With C++ standard library, you *cannot* do that. Targeting a specific platform, you can use different tricks. (E.g. if you know you have just one file open, you can query the Linux /proc and get the file open by your process). Anyway if you reach the "implementation" level you can do that using some platform dependent call. – BiagioF May 16 '18 at 20:47
  • 1
    What are you trying to solve here? Is your question academic, or are you trying to solve a specific issue? – Stephen Newell May 16 '18 at 20:56

2 Answers2

1

is there any (simple) way to detect in some_function(std::ofstream ofs) if ofs is writing to /dev/null or not?

No, there isn't.

The fact that you are looking for a way to get that information indicates to me that some_function has branching code depending on whether you are writing to /dev/null or not.

You can address that problem by adding another argument to the function and let the client code provide that information to you.

void some_function(std::ofstream& ofs, bool isDevNull);

and use it as:

std::ofstream ofs ("/dev/null", std::ofstream::out);
ofs << "lorem ipsum";
some_function(ofs, true);
R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

from std::ofstream, no.

From a FILE*, yes but it's not portable.

Here's a version for linux:

#include <fstream>
#include <unistd.h>
#include <stdio.h>
#include <memory>
#include <stdexcept>
#include <iostream>
#include <sstream>

struct file_closer
{
    void operator()(FILE*p) const noexcept
    {
        if (p)
            fclose(p);
    }
};

auto open_write(const char* path) -> std::unique_ptr<FILE, file_closer>
{
    auto result = std::unique_ptr<FILE, file_closer>(fopen(path, "w"));

    if (!result.get())
        throw std::runtime_error("not opened");
    return result;
}

size_t do_readlink(const char* path, char* buffer, size_t buflen)
{
    auto len = readlink(path, buffer, buflen);
    if (len < 0)
        throw std::runtime_error("failed to read link");
    return size_t(len);
}

bool is_dev_null(FILE* fp)
{
    int fd = fileno(fp);
    std::ostringstream procpath;
    procpath << "/proc/self/fd/" << fd;
    auto spath = procpath.str(); 

    size_t bufs = 1024;
    std::string path(bufs, ' ');
    auto len = do_readlink(spath.c_str(), &path[0], bufs);
    while(len > bufs)
    {
        bufs = len;
        path.resize(bufs);
        len = do_readlink(spath.c_str(), &path[0], bufs);
    }

    path.resize(len);
    return path == "/dev/null";
}

int main()
{
    auto fp = open_write("/dev/null");
    std::cout << is_dev_null(fp.get());
}
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142