GIO GFileのサンプルはgvfsが良さげ

glibのGIOのGFileを使うサンプルを物色していたけど、gvfsに素敵なサンプルがたくさんあった。gvfsコマンドラインから実行できるアプリケーション群のソースを眺めてみると、GFileの使い方がよく分かる。RPM系のディストリビューションなら。

$ rpm -q gvfs
gvfs-1.5.3-2m.mo7.i686
$ rpm -ql gvfs | grep bin
/usr/bin/gvfs-cat
/usr/bin/gvfs-copy
/usr/bin/gvfs-info
/usr/bin/gvfs-less
/usr/bin/gvfs-ls
/usr/bin/gvfs-mkdir
/usr/bin/gvfs-monitor-dir
/usr/bin/gvfs-monitor-file
/usr/bin/gvfs-mount
/usr/bin/gvfs-move
/usr/bin/gvfs-open
/usr/bin/gvfs-rename
/usr/bin/gvfs-rm
/usr/bin/gvfs-save
/usr/bin/gvfs-set-attribute
/usr/bin/gvfs-trash
/usr/bin/gvfs-tree

とりあえず、こんな感じです。
ソースを file-roller で展開する。GNOMEユーザはtarなんか使わないよ〜

$ file-roller -e . gvfs-1.5.3.tar.bz2
$ cd gvfs-1.5.3
$ ls programs/
Makefile.am              gvfs-ls.c            gvfs-rename.c
Makefile.in              gvfs-mkdir.c         gvfs-rm.c
gvfs-bash-completion.sh  gvfs-monitor-dir.c   gvfs-save.c
gvfs-cat.c               gvfs-monitor-file.c  gvfs-set-attribute.c
gvfs-copy.c              gvfs-mount.c         gvfs-trash.c
gvfs-info.c              gvfs-move.c          gvfs-tree.c
gvfs-less                gvfs-open.c

とりあえず、gvfs-open.cを眺めてみる。最初にstaticなグローバル変数locationとentriesがある。このlocationにプログラムの引数(オプションを除く)が入るので、それをGFileオブジェクトとして利用している。
main関数から見ていくと、GETTEXT関係は飛ばして、

  g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
  g_option_context_parse (context, &argc, &argv, &error);

これでentries引数(locationのポインタが含まれている)をparseして、locationに開きたいファイルの配列ができあがる。
エラー処理は飛ばして、重要なのは、

  do
    {
      file = g_file_new_for_commandline_arg (locations[i]);
      open (file, locations[i]);
      g_object_unref (file);
    }
  while (locations[++i] != NULL);

これだけ。コマンドライン引数からGFileオブジェクトfileを作成し、fileをopen()し、参照を消すことを繰り返します。
open()の味噌は、

  app = g_file_query_default_handler (file, NULL, &error);

これで、fileに適したアプリケーションハンドルを取得し、

  if (g_file_is_native (file) && !is_file_uri_with_anchor (arg_string))
    {
      /* For normal files, pass in the canonicalized GFile as path */
      l.data = file;
      res = g_app_info_launch (app, &l,
			       NULL, &error);
    }
  else
    {
      /* However, for uris, use the original string, as it might be
	 modified by passing throught GFile (e.g. mailto: links)
      */
      l.data = arg_string;
      res = g_app_info_launch_uris (app, &l,
				    NULL, &error);
    }

g_file_is_native()且つis_file_uri_with_anchor()でない場合は、g_app_info_launch()で起動し、それ以外ではg_app_info_launch_uris()でアプリケーションを起動します。最後にg_object_unref (app);で参照を消せば完了。

$ gvfs-open http://www.example.com/

などで、適切なウェブブラウザで表示してくれます。

以前は、gnome-openというコマンドがlibgnomeから提供されていて、gnome-vfs経由でaplicationを呼び出していたのですが、libgnomeはまもなくObsoletesされてしまうので、今後はgfvs-openを使った方が良いでしょう。

ファイルを開いて処理する方法は、gvfs-cat.cを見て、cat()を調べてみて下さい。g_file_read()でストリームを開いて、g_input_stream_read()で読み込み、write()システムコール(?)で標準出力に書きだし、g_input_stream_close()でストリームを閉じます(buffer[1024 * 8 + 1];これって安全なのかな?)。

GFileの使い方が何となくわかってきた。