Gedit, не сохраняющий расширенные атрибуты на редактировании файла

Я работаю над проектом, где я полагаюсь главным образом на расширенный атрибут файла, который я установил, когда я создаю файл. Но я сталкиваюсь с проблемой при изменении файла.

Пример:

Когда я редактирую текстовый файл в Сублимированном тексте, все расширенные атрибуты сохраняются, также значение inode остается тем же как прежде. Но когда я делаю то же в Gedit, оно создает новый файл вместо того, чтобы изменить существующий. Так inode значение, определяемый пользователем / расширился, атрибуты не сохраняются.

Я вижу, что эта проблема происходит из-за поведения копирования Gedit.

Существует ли способ сохранить их при использовании Gedit?

2
задан 21 August 2015 в 02:36

1 ответ

Ответ - нет. Вам нужно будет отправить отчет об ошибке или выполнить форк проекта и реализовать протокол расширенных атрибутов.

В C ++ / Qt я написал библиотеку, которая выполняет это с помощью . Это то, что вам нужно будет прикрепить к QFile, и если это что-то, что вы хотите объединить в Gedit, вам придется преобразовать его в код C. Во всяком случае, это пример реализации. Основной заголовок

#ifndef QXATTR_H
#define QXATTR_H

#include <QObject>
#include <QFile>
#include <sys/xattr.h>

class QXattr : public QObject
{
    Q_OBJECT
public:
    explicit QXattr(QFile &parent);

    template<typename T> bool        insert  ( const QString &name, T value ); // Returns true if properly serialized
    template<typename T> T           value   ( const QString &name ); // Gets value of name. Returns Null pointer if none found.
    template<typename T> QString     name    ( T value ); // Returns first name of given value
    template<typename T> QStringList names   ( T value ); // Returns all names of a given value
                         QStringList names   ();          // Returns all names
                         bool        contains( const QString &name ); // Returns true if name exists.
                         bool        remove  ( const QString &name ); // Returns true if something was removed.

    QString errorString(); // Last registered errno

protected:
    inline const char *fileName();
    void setErrorString(const QString &error);
    void getNames(); // Should trigger on a move action in case the filesystem changed

signals:
    void namesChanged();
    void errorStringChanged( QString error );
    // More signals will be placed here

private:
    QStringList m_Names;
    QFile &m_File;
    QString m_ErrorString;
};

#endif // QXATTR_H

Основной источник.

#include "qxattr.h"
#include "qconsoletoolkit.h"

QXattr::QXattr(QFile &parent)
    : QObject(&parent)
        , m_File(parent)
{

}

/* Insertion Templates */
template<typename T> bool QXattr::insert(const QString &name, T value)
{
    Q_UNUSED(name)
    Q_UNUSED(value)
    return false;
}
template<> bool QXattr::insert<QByteArray> (const QString &name, QByteArray  value)
{
    int error = setxattr(fileName(), name.toLocal8Bit().data(), value.data(), size_t(value.size()), 0 );
    ct_Check(error == -1, strerror(errno));
    this->getNames();
    return true;
}
template<> bool QXattr::insert<QString>    (const QString &name, QString     value)
{
    return this->insert<QByteArray>(name, value.toLocal8Bit());
}
template<> bool QXattr::insert<const char*>(const QString &name, const char* value)
{
    return this->insert<QByteArray>(name, QByteArray(value));
}

/* Value Templates */
template<typename T> T QXattr::value(const QString &name)
{
    Q_UNUSED(name)
}
template<> QByteArray QXattr::value<QByteArray>(const QString &name)
{
    ssize_t valueLength;
    valueLength = getxattr(fileName(), name.toLocal8Bit().data(), nullptr, 0);
    ct_Check(valueLength == -1, strerror(errno));
    if (!valueLength) { return QByteArray(); }

    QByteArray val(int(valueLength), ' ');
    valueLength = getxattr(fileName(), name.toLocal8Bit().data(), val.data(), size_t(valueLength));
    ct_Check(valueLength == -1, strerror(errno));
    return val;
}

/* Name Templates */
template<typename T> QString QXattr::name(T value)
{
    Q_UNUSED(value)
    return QString();
}
template<> QString QXattr::name<const char *>(const char* value)
{
    getNames();
    QByteArray ba(value);
    for ( int i = 0; i < m_Names.length(); i++ ) {
        if (ba == this->value<QByteArray>(m_Names.at(i))) { return m_Names.at(i); }
    }
    return QString();
}

/* Names Templates */
template<class T> QStringList QXattr::names(T value)
{
    Q_UNUSED(value)
    return QStringList();
}
template<> QStringList QXattr::names<const char *>(const char* value)
{
    getNames();
    QByteArray ba(value);
    QStringList names;
    for ( int i = 0; i < m_Names.length(); i++ ) {
        if (ba == this->value<QByteArray>(m_Names.at(i))) { names << m_Names.at(i); }
    }
    return names;
}
QStringList QXattr::names()
{
    getNames();
    return m_Names;
}

/* Regular Functions */
bool QXattr::contains(const QString &name)
{
    getNames();
    return m_Names.contains(name);
}
bool QXattr::remove(const QString &name)
{
    // Returns false if error.
    // Error can mean, that the name simply did not exist.
    if ( removexattr(fileName(), name.toLocal8Bit().data()) == -1 ) {
        setErrorString(strerror(errno));
        return false;
    }
    return true;
}

/* Convenience Functions */
const char* QXattr::fileName()
{
    return m_File.fileName().toLocal8Bit().data();
}
void QXattr::setErrorString(const QString &error)
{
    m_ErrorString = error;
    emit errorStringChanged( error );
}
void QXattr::getNames()
{
    m_Names.clear();
    ssize_t bufferLength(0);
    ssize_t nameLength;
    char *name;

    /* Determine the length of the buffer needed. */
    bufferLength = listxattr(fileName(), nullptr, 0);
    ct_Check(bufferLength == -1, strerror(errno));
    if (!bufferLength) { return; }

    /* Allocate the buffer. */
    QByteArray buffer(int(bufferLength), ' ');

    /* Copy the list of attribute keys to the buffer. */
    bufferLength = listxattr(fileName(), buffer.data(), size_t(bufferLength));
    ct_Check(bufferLength == -1, strerror(errno));

    /* Loop over the list of zero terminated strings with the attribute keys.
     * Use the remaining buffer length to determine the end of the list. */
    name = buffer.data();
    QStringList names;
    while (bufferLength > 0) {
        m_Names << name;

        /* Forward to next attribute name. */
        nameLength = ssize_t(strlen(name) + 1);
        bufferLength -= nameLength;
        name += nameLength ;
    }
}

Вам нужно будет добавить больше шаблонов, чтобы обрабатывать сериализацию различных типов данных. Исходные функции принимают пустые указатели, поэтому на самом деле вы можете поместить в них что угодно. Как это будет выглядеть на C? Не могу вам помочь.

https://wiki.gnome.org/Apps/Gedit/ReportingBugs

1
ответ дан 26 December 2019 в 21:10

Другие вопросы по тегам:

Похожие вопросы: