retireSakiの日記

たぶん引退した?ソフトウエアエンジニアのブログ

Linuxの基本ディレクト構成などのルールとglib(glibmm),Qtの基本ディレクトリーの取得関数

 今回は、アプリケーション開発に必要な知識の1つとしての基本ディレクトリーの構成などのルールの説明やGTK(glib, glibmm)とQtの基本ディレクトリーの取得を実例で比較してみます。

 QtだろうがGTK だろうがアプリケーションの多くは共通したディレクトリー構成の情報を取得し、各種設定やデータファイルを取得・保存しています。このとき、ある一定のルールに従って行わないと、システムだけでなく他のアプリに影響する場合もあります。
そこで、基本ディレクトリーについての基礎とglib,glimmのこれに関係した関数の一覧を列記したいと思います。

 

環境変数とユーザーディレクトリー

 多くのアプリケーションは実行しているユーザーのディレクトリーに各種情報を取得・保存します。
このときの重要となるのが、GTK_xxx という変数で、env や printenv コマンドなどで実際の変数内の値と確認できます。

f:id:retireSaki:20181016140137j:plain


実際の変数の定義ファイルは、"~/.config/user-dirs.dirs" です。

 XDG_DESKTOP_DIR="$HOME/デスクトップ"
 XDG_DOWNLOAD_DIR="$HOME/ダウンロード"
 XDG_TEMPLATES_DIR="$HOME/テンプレート"
 XDG_PUBLICSHARE_DIR="$HOME/公開"
 XDG_DOCUMENTS_DIR="$HOME/ドキュメント"
 XDG_MUSIC_DIR="$HOME/ミュージック"
 XDG_PICTURES_DIR="$HOME/ピクチャ"
 XDG_VIDEOS_DIR="$HOME/ビデオ"

というように記述されています。
これを見て分かるように、ログインユーザーごとに共通したディレクトリー構成に定義されています。
デフォルトの定義ファイルは、"/etc/xdg/user-dirs.defaults" です。

 XDG_xxx って

 "XDG" は "X Desktop Group" の省略です。

 Linuxディストリビューションの大半は、XDG Base Directory Specification に準拠しています。いわゆる XDG_xxx という環境変数のアレですね。
freedesktop.org は正式な標準化団体ではありません。しかし。多くの支持によりfreedesktop.orgディレクトリ仕様 に準拠することで、GNOME のデスクトップ間の互換性を向上させています。
 古いLinuxだと、ディストリビューションによってはデータなどの保存先がバラバラだったりしましたが、今ではバラツキもなく、こういった説明やアプリ内処理などがかなり楽になりました。

1) XDGベースディレクトリの基本概念

  1. $XDG_DATA_HOME
    ユーザー固有のデータファイルを書き込む相対的な単一のベースディレクトリー。
  2. $XDG_CONFIG_HOME
    ユーザー固有の構成ファイルを書き込む相対的な単一の基本ディレクトリー。
  3. $XDG_DATA_DIRS
    データファイルを検索するための優先順位の付いた一連の基本ディレクトリー。
  4. $XDG_CONFIG_DIRS
    設定ファイルが検索されるべきである相対的な順序付けられた基本ディレクトリー。
  5. $XDG_CACHE_HOME
    ユーザー固有の必須ではない(キャッシュ)データを書き込むための1つの基本ディレクトリー。
  6. $XDG_RUNTIME_DIR
    ユーザー固有のランタイムファイルやその他のファイルオブジェクトを配置する相対的な単一のベースディレクトリー。

 

2) 各環境変数について

  1. $XDG_DATA_HOMEが設定されていないか空である場合、 $HOME /.local/shareに等しいデフォルト値を使用する必要があります。
  2. $XDG_CONFIG_HOMEが設定されていないか空の場合は、 $HOME /.configと同じデフォルト値を使用する必要があります。
  3. $XDG_DATA_DIRSディレクトリは、コロン ':'で区切ってください。
    $XDG_DATA_DIRSが設定されていないか空の場合は、/ usr / local / share /:/ usr / share /に等しい値を使用する必要があります。
  4. $XDG_CONFIG_DIRSディレクトリは、コロン ':'で区切ってください。
    $XDG_CONFIG_DIRSが設定されていないか空の場合、/ etc / xdgに等しい値を使用する必要があります。
  5. $XDG_CACHE_HOMEが設定されていないか空の場合は、 $HOME / cacheと同じデフォルト値を使用する必要があります。
  6. $XDG_RUNTIME_DIRは、ユーザー固有の重要でない実行時ファイルやその他のファイルオブジェクト(ソケット、名前付きパイプなど)を格納する必要のあるベースディレクトリを定義。
      ディレクトリはユーザが所有していなければならず、読み書きアクセス権を持つ唯一のものでなければならない。アクセスモードは0700でなければなりません。

 

  • $XDG_DATA_DIRS, $XDG_CONFIG_DIRS の順序について
     リストされている最初のディレクトリが最も重要です。同じ情報が複数の場所で定義されている場合、より重要なベースディレクトリに関連して定義された情報が先行します。
     $XDG_DATA_HOME定義されたベースディレクトリは、 $XDG_DATA_DIRS定義されたベースディレクトリよりも重要とみなされます。
     $XDG_CONFIG_HOME定義されたベースディレクトリは、 $XDG_CONFIG_DIRS定義されたベースディレクトリよりも重要とみなされます。
  • ディレクトリの存続期間は、ログインしているユーザに縛られなければならない。
     ユーザが最初にログインしたときに作成されなければならず、ユーザがディレクトリを完全にログアウトしなければならない。
     ユーザーが複数回ログインすると、同じディレクトリを指し示すべきである。
     最初のログインからシステムの最後のログアウトまでディレクトリが存在し続け、その間に削除されないことが必須です。
      ディレクトリ内のファイルは、再起動またはフル・ログアウト/ログイン・サイクルで存続してはならない。
  • ディレクトリはローカルファイルシステム上に存在し、他のシステムとは共有されていなければならない。
  • XDG_RUNTIME_DIRが設定されていない場合、アプリケーションは同様の機能を持つ置換ディレクトリに戻り、警告メッセージを出力する必要がある。
     アプリケーションは通信や同期の目的でこのディレクトリを使用する必要がある。
     ランタイムメモリに常駐する可能性があり、必ずしもディスクにスワップアウトする必要がないため、大きなファイルを置くべきではない。

 desktop エントリー

1) ファイルの命名

 デスクトップエントリファイルは.desktop拡張子を持つ必要があります。
拡張子に基づいてファイルタイプを決定すると、ファイルタイプを非常に簡単かつ迅速に決定できます。

 アプリケーションの場合、 .desktop拡張の前のデスクトップファイルの名前の部分は、有効なD-Busのよく知られた名前でなければなりません。これは、ドットで区切られた空ではない要素の並びであり(U+002E FULL STOP)、数字で始まるものではなく、ASCII文字、数字、ダッシュ(U + 002D HYPHEN-MINUS)およびアンダースコア(U + 005F LOW LINE)のセット[A〜Z,a〜z,0〜9,-,_]の文字のみが含まれています。


 デスクトップエントリの名前は、「逆DNS」の規則に従う必要があります。小文字で、アプリケーションの作成者によって制御される逆のDNSドメイン名で始まる必要があります。
たとえば、 example.orgの所有者が「Foo Viewer」と書いた場合、 org.example.FooViewerという名前が選択され、 org.example.FooViewerという名前のファイルがorg.example.FooViewer.desktopます。

 

 ダッシュを含むよく知られた名前は許可されていますが、D-Busオブジェクトパスやインターフェイス名、FlatpakアプリIDなど、逆のDNS名の関連する使用ではダッシュが許可されていないため推奨されません。
作成者のドメイン名にダッシュが含まれている場合は、アンダースコアをアンダースコアに置き換えることを推奨。DNSドメイン名にアンダースコアが使用できないため、あいまいさは発生しません。
作成者のドメイン名にD-Busの既知の名前では許可されていない数字で始まるラベルが含まれている場合は、デスクトップエントリ名のその要素にアンダースコアを付加することを推奨。

たとえば、7-zip.orgはorg._7_zip.Archiverという名前のアプリケーションをリリースするかもしれません。


2) アプリケーションのデスクトップエントリ( <application>.desktop )の保存場所

 アプリケーションを表す各デスクトップエントリは、ファイル名に基づいてデスクトップファイルIDによって識別されます。
デスクトップファイルのIDを確認するには、デスクトップファイルがインストールされている$XDG_DATA_DIRSコンポーネントを基準にした完全パスを作成し、 "applications /"接頭辞を削除し、 "/"を ' - 'にします。
"/usr/share/applications/foo/bar.desktop"にはデスクトップファイルID foo-bar.desktopがあります。
複数のファイルが同じデスクトップファイルIDを持つ場合、$ XDG_DATA_DIRS優先順位の最初のものを使用。
デスクトップファイルが$ XDG_DATA_DIRSコンポーネントのアプリケーションサブディレクトリにインストールされていない場合は、IDはありません。


 この他にも $XDG_DATA_DIRS/applications/ など基本ディレクトリー下の使い方やカテゴライズなども定義しています。
という具合に、基本的概念や扱い方を細かくルール付けしています。


詳しくは freedesktop.org を参照してください。


 これらのことは、OSやシステムツール側でチェックされていますが、アプリケーション開発者も知っておくと良いでしょう。

 glib, glibmm, Qt でユーザー基本ディレクトリーの取得関数

以下にXDG_xxxでの基本ディレクトリーの取得関数を掲載しました。
※ 多分これであっていると思いますが、普段あまり使わないものは検証はしていませんので間違っている場合ご指摘ください。

※今回の取得例は Qt と GTK+ アプリを作って Ubuntu 18.04 LTS (bionic) にて確認しました。

Qtでの確認画面

f:id:retireSaki:20181016150748j:plain

GTK+での確認画面

f:id:retireSaki:20181016141702j:plain
  1. $HOME
    glib const gchar * g_get_home_dir()
    glibmm std::string Glib::get_home_dir()
    Qt QStringList QStandardPaths::standardLocations(QStandardPaths::HomeLocation)
    glib /home/<user name>
    Qt /home/<user name>
  2. $XDG_DATA_HOME
    glib const gchar * g_get_user_data_dir()
    glibmm std::string Glib::get_user_data_dir()
    Qt QStringList QStandardPaths::standardLocations(QStandardPaths::AppDataLocation)
    glib $HOME/.local/share
    Qt $HOME/.local/share/<APP name>, /usr/share/ubuntu/<APP name>, $HOME/.local/share/flatpak/exports/share/<APP name>, /var/lib/flatpak/exports/share/<APP name>, /usr/local/share/<APP name>, /usr/share/<APP name>, /var/lib/snapd/desktop/<APP name>
  3. $XDG_CONFIG_HOME
    glib const gchar * g_get_user_config_dir()
    glibmm std::string Glib::get_user_config_dir()
    Qt QStringList QStandardPaths::standardLocations(QStandardPaths::ConfigLocation)
    glib $HOME/.config
    Qt $HOME/.config, /etc/xdg/xdg-ubuntu, /etc/xdg
  4. $XDG_DATA_DIRS
    glib const gchar * g_get_system_data_dirs()
    glibmm std::string Glib::get_system_data_dirs()
    Qt QStringList QStandardPaths::standardLocations(QStandardPaths::DataLocation)
    glib /usr/share/ubuntu, $HOME/.local/share/flatpak/exports/share/, /var/lib/flatpak/exports/share/, /usr/local/share/, /usr/share/, /var/lib/snapd/desktop
    Qt $HOME/.local/share/<APP name>, /usr/share/ubuntu/<APP name>, $HOME/.local/share/flatpak/exports/share/<APP name>, /var/lib/flatpak/exports/share/<APP name>, /usr/local/share/<APP name>, /usr/share/<APP name>, /var/lib/snapd/desktop/<APP name>
  5. $XDG_CONFIG_DIRS
    glib const gchar * g_get_system_config_dirs()
    glibmm std::string Glib::get_system_config_dirs()
    Qt QStringList QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation)
    glib /etc/xdg/xdg-ubuntu, /etc/xdg
    Qt $HOME/.config, /etc/xdg/xdg-ubuntu, /etc/xdg
  6. $XDG_CACHE_HOME
    glib const gchar * g_get_user_cache_dir()
    glibmm std::string Glib::get_user_cache_dir()
    Qt QStringList QStandardPaths::standardLocations(QStandardPaths::CacheLocation)
    glib $HOME/.cache
    Qt $HOME/.cache/<APP name>
  7. $XDG_RUNTIME_DIR
    glib const gchar * g_get_user_runtime_dir()
    glibmm (現時点未実装でした)
    Qt QStringList QStandardPaths::standardLocations(QStandardPaths::RuntimeLocation)
    glib /run/user/<USER>
    Qt /run/user/<USER>

さらにユーザーディレクトリー内の各フォルダーをチェック

  1. $XDG_DESKTOP_DIR
    glib const gchar * g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP)
    glibmm std::string Glib::get_user_special_dir(Glib::USER_DIRECTORY_DESKTOP)
    Qt QStringList QStandardPaths::standardLocations(QStandardPaths::DesktopLocation)
    glib $HOME/デスクトップ
    Qt $HOME/デスクトップ
  2. $XDG_DOWNLOAD_DIR
    glib const gchar * g_get_user_special_dir(G_USER_DIRECTORY_DOWNLOAD)
    glibmm std::string Glib::get_user_special_dir(Glib::USER_DIRECTORY_DOWNLOAD)
    Qt QStringList QStandardPaths::standardLocations(QStandardPaths::DownloadLocation)
    glib $HOME/ダウンロード
    Qt $HOME/ダウンロード
  3. $XDG_TEMPLATES_DIR
    glib const gchar * g_get_user_special_dir(G_USER_DIRECTORY_TEMPLATES)
    glibmm std::string Glib::get_user_special_dir(Glib::USER_DIRECTORY_TEMPLATES)
    Qt (QStandardPaths 内に未実装)
    glib $HOME/テンプレート
    Qt  
  4. $XDG_PUBLICSHARE_DIR
    glib const gchar * g_get_user_special_dir(G_USER_DIRECTORY_PUBLIC_SHARE)
    glibmm std::string Glib::get_user_special_dir(Glib::USER_DIRECTORY_PUBLIC_SHARE)
    Qt (QStandardPaths 内に未実装)
    glib $HOME/公開
    Qt  
  5. $XDG_DOCUMENTS_DIR
    glib const gchar * g_get_user_special_dir(G_USER_DIRECTORY_DOCUMENTS)
    glibmm std::string Glib::get_user_special_dir(Glib::USER_DIRECTORY_DOCUMENTS)
    Qt QStringList QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation)
    glib $HOME/ドキュメント
    Qt $HOME/ドキュメント
  6. $XDG_MUSIC_DIR
    glib const gchar * g_get_user_special_dir(G_USER_DIRECTORY_MUSIC)
    glibmm std::string Glib::get_user_special_dir(Glib::USER_DIRECTORY_MUSIC)
    Qt QStringList QStandardPaths::standardLocations(QStandardPaths::MusicLocation)
    glib $HOME/ミュージック
    Qt $HOME/ミュージック
  7. $XDG_PICTURES_DIR
    glib const gchar * g_get_user_special_dir(G_USER_DIRECTORY_PICTURES)
    glibmm std::string Glib::get_user_special_dir(Glib::USER_DIRECTORY_PICTURES)
    Qt QStringList QStandardPaths::standardLocations(QStandardPaths::PicturesLocation)
    glib $HOME/ピクチャ
    Qt $HOME/ピクチャ
  8. $XDG_VIDEOS_DIR
    glib const gchar * g_get_user_special_dir(G_USER_DIRECTORY_VIDEOS)
    glibmm std::string Glib::get_user_special_dir(Glib::USER_DIRECTORY_VIDEOS)
    Qt QStringList QStandardPaths::standardLocations(QStandardPaths::MoviesLocation)
    glib $HOME/ビデオ
    Qt $HOME/ビデオ

 
glib(gibmm)は、仕様に忠実です。
一方。Qtには同じよう結果となる引数、Qt側でおそらく"頻繁に使う"もしくは"OS間の互換性のため?"のディレクトリーを付与した結果となるケースが多かったので、XDGルールとは違うようです。
例えば、
 AppDataLocation と AppLocalDataLocation
AppLocalDataLocationはWindows用に用意されたもので、Linux等の他のOSでは、AppDataLocationと同じ結果になります。
Qtのヘルプに結果サンプルが掲載されているので、チェックしながら使うと良いでしょう。

ちなみに環境変数の取得は
glib)  gchar ** g_get_environ (void);
    const gchar * g_getenv (const gchar *variable);
glibmm) Glib::ArrayHandle<std::string> Glib::listenv ();
    std::string Glib::getenv (const std::string & variable);
 qt)  QStringList QProcessEnvironment::toStringList () const
    QString QProcessEnvironment::value (const QString &name, const QString &defaultValue = QString()) const

 

最後に作成したプログラムのソースコードします。
※ 15分程度で作ったソースコードなので適当です。

 プログラムのソースコードをダウンロードする

www.mediafire.com

Linuxの理解のために、こういった本は読んでおくと良いかも。
図書館に購入依頼したいかも。

動くメカニズムを図解&実験! Linux超入門 (My Linuxシリーズ)

動くメカニズムを図解&実験! Linux超入門 (My Linuxシリーズ)

 
日経Linux 2018年 3 月号

日経Linux 2018年 3 月号

 

 

 

注目記事

「Amazon.co.jpアソシエイト」または「[乙の名称を挿入]は、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイトプログラムである、Amazonアソシエイト・プログラムの参加者です。