QSettings problem when input file is a link



  • Hi, i'm having problems loading settings with QSettings on a windows machine.
    I have a symlink file in the Project/debug folder that points to another file in another folder (writable and readable) when I try to read some setting from that file it behave like the file doesn't exists, when I try to write some settings on that link it overwrites the entire file deleting all the settings in it.
    The link file is a symlink, not a normal shortcut (that doesn't work either, the same behavior is triggered) is created with the windows tool mklink

    main.cpp:

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QSettings>
    #include <Qdir>
    #include <QCoreApplication>
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        qInfo(QString(QCoreApplication::applicationDirPath()+"/test.ini").toLatin1().data());
        QSettings* _persisted_repository = new QSettings(QCoreApplication::applicationDirPath()+"/test.ini", QSettings::IniFormat);
        _persisted_repository->setValue("aa","false");
        //_persisted_repository->setValue("bb","false");
        _persisted_repository->setValue("cc","false");
    
        qInfo(_persisted_repository->value("bb").toString().toLatin1().data());
    
        _persisted_repository->sync();
    
        return app.exec();
    }
    
    

    even if the setting "bb=false" is originally in the file it disappear and this line has a null output in the console:

     qInfo(_persisted_repository->value("bb").toString().toLatin1().data());
    

    P.S: this behavior is not triggered with a file that is not a link or a simlink, the same code with "test.ini" as a normal file works fine



  • Hi @damre22

    a link should be something like "test.ini.lnk". Maybe you just have some confusion with the file names, due to the fact that WINDOWS by default does not show the ".lnk" extension in the explorer.

    -Michael.


  • Lifetime Qt Champion

    @m.sue
    Hi, the mklink windows tools makes file system level links. it is not .lnk files.
    Its similar to the ones seen on linux.



  • @m-sue I tried that too but I got the same behavior and @mrjj is correct, it's not a ".lnk" file. Thanks :)


  • Lifetime Qt Champion

    @damre22
    Im a bit surprised the symbolic link dont work.
    Most programs sees the actual file and have no awareness of
    of the link.
    Did you try both types (symbolic and hard link ) ?



  • @mrjj sadly the file i need to reference is on another partition so my only option is symlink, I cannot use hard link between different drives


  • Lifetime Qt Champion

    @damre22
    ah, i forgot that limitation.
    Have you tried with QFile and see if that will read correctly via the link?
    It might be a deeper issue that QSettings.



  • @mrjj said in QSettings problem when input file is a link:

    Have you tried with QFile and see if that will read correctly via the link?

    Yes I tried, the file is not even considered a link.

        QFile file("test.ini");
        qInfo(file.symLinkTarget().toLatin1().data());
    

    returns a null string but is binded to the correct file. However i think this is correct because that file technically is not a link

    It might be a deeper issue that QSettings.

    I think I can agree on that


  • Lifetime Qt Champion

    Ok
    it seems that symbolic links are not considered for symLinkTarget()
    as docs says
    "Returns the absolute path of the file or directory a symlink (or shortcut on Windows) points to"

    So it sounds like only .lnk is handled/known

    Just to be sure i understand your setup.
    In the build folder/deploy you have test.ini link to the real
    file on other partition?
    And using that with QSettings do odd things where as same code with
    real file directly in place, just works?



  • @mrjj said in QSettings problem when input file is a link:

    In the build folder/deploy you have test.ini link to the real
    file on other partition?

    Exaclty

    And using that with QSettings do odd things where as same code with
    real file directly in place, just works?

    yes, with the real file the same code works fine, by the way I opened a bug on bugreports.qt.io
    https://bugreports.qt.io/browse/QTBUG-64121
    because I think this is a problem with QSettings


  • Qt Champions 2017

    Check if a regular file QFile can be opened, read and written when it's a symlink. If that is okay, then the problem is with QSettings, if not probably the problem is with the underlying file system('s API/integration).


  • Lifetime Qt Champion

    @damre22
    Good i was about to suggest that since it seems reproducible in small sample and
    it sounds like you tested its not just a "user" error.

    Could you perhaps, show the mklink commandline you used in the bug report for
    completeness. ?



  • @mrjj yes I will update the bug report, thank you so much



  • @kshegunov I will check that too and I will update the bug report if I find something new, thank you



  • Hi,

    I also had a QSettings::AccessError when trying to QSettings::sync() on a config.ini file on file system ext4 + symlink with Qt 5.7.1 on raspbian OS Stretch

    Here is my snipet to reproduce locally:

        mysettings->sync();
        QSettings::Status s = mysettings->status();
        QString msg;
        switch(s)
        {
        case QSettings::NoError:
            msg = "No error occurred";
            break;
        case QSettings::AccessError:
            msg = "An access error occurred (e.g. trying to write to a read-only file).";
            break;
        case QSettings::FormatError:
            msg = "A format error occurred (e.g. loading a malformed INI file).";
            break;
        }
        qDebug() << "writing configuration_file" << mysettings->fileName() << "status:" << msg << endl;
    

    In my debug output I get:

    2019-04-01 12:08:53 : writing configuration_file "/home/pi/config.ini" status: "An access error occurred (e.g. trying to write to a read-only file)." 
    

    and the file

    pi@machine:~ $ ls -l config.ini 
    lrwxrwxrwx 1 pi pi 28 avril  1 12:08 config.ini -> /etc/config/config.ini
    

    the file is actually perfectly writable by pi users

    pi@machine:~ $ ls -l /etc/config/config.ini 
    -rw-r--r-- 1 pi pi 829 avril  1 12:08 /etc/config/config.ini
    

    Is it fixed in newer version of Qt?

    The idea behind using symlink, is a backward compatible path, + using etckeeper in /etc/

    A suggestion for work around?

    Regards,
    Sylvain.



  • Replying to myself:

    The bugrepport said is is fixed for 5.10.1

    https://bugreports.qt.io/browse/QTBUG-64121

    And it can be made to work with correct folder permissions :

    $ ls -ld /etc/config/
    drwxr-xr-x 2 root root 4096 avril  1 11:15 /etc/config/
    $ sudo chgrp pi /etc/config/ 
    $ sudo chmod g+w /etc/config/
    $ ls -ld /etc/cleandrop/
    drwxrwxr-x 2 root pi 4096 avril  1 11:15 /etc/config/
    

    resolving simlink doesn't helps

        // resolve symlink
        // https://bugreports.qt.io/browse/QTBUG-64121
        QFileInfo info(_configuration_file);
        if (info.isSymLink())
            _configuration_file = info.symLinkTarget();
    

    So I removed this fix, and fixed the folder permission and it worked.


 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.