Search code examples
c++linuxqtsysctl

"Not a directory" when writing kernel configurations


I am trying to toggle IPv6 on Linux systems using this function in Qt. The problem is that it fails opening the file and simply reports "Not a directory".

bool toggle_ipv6(const bool &enabled) {
    const std::vector<std::string> ipv6_kernel_option_files = {
        "/proc/sys/net/ipv6/conf/all/disable_ipv6"
        "/proc/sys/net/ipv6/conf/default/disable_ipv6"
        "/proc/sys/net/ipv6/conf/lo/disable_ipv6"
    };

    for (const auto &filename: ipv6_kernel_option_files) {
        QFile kernel_option_file( filename.c_str() );
        if ( kernel_option_file.open(QIODevice::WriteOnly) ) {
            QTextStream stream(&kernel_option_file);
            stream << (enabled ? "0" : "1");
            kernel_option_file.close();
        } else {
            const std::string error_message = kernel_option_file.errorString().toStdString();
            qDebug().nospace().noquote() << '[' << QTime::currentTime().toString() << "]: " << error_message.c_str();
            return false;
        }
    }

    return true;
}

I've tried searching the web but I can't find any other issue pertaining to QFile and this particular error message. How can I fix this?


Solution

  • Commas are missing in vector initialization:

    const std::vector<std::string> ipv6_kernel_option_files = {
        "/proc/sys/net/ipv6/conf/all/disable_ipv6"
        "/proc/sys/net/ipv6/conf/default/disable_ipv6"
        "/proc/sys/net/ipv6/conf/lo/disable_ipv6"
    };
    

    Hence the vector has only one element, which is a string made of the three paths, concatenated:

    "/proc/sys/net/ipv6/conf/all/disable_ipv6/proc/sys/net/ipv6/conf/default/disable_ipv6/proc/sys/net/ipv6/conf/lo/disable_ipv6"
    

    Considering that

    "/proc/sys/net/ipv6/conf/all/disable_ipv6"
    

    is a file, not a directory, it can't contain the rest of the path.

    Use commas to separate the paths in vector initialization:

    const std::vector<std::string> ipv6_kernel_option_files = {
        "/proc/sys/net/ipv6/conf/all/disable_ipv6",
        "/proc/sys/net/ipv6/conf/default/disable_ipv6",
        "/proc/sys/net/ipv6/conf/lo/disable_ipv6"
    };