ラベル Lucid の投稿を表示しています。 すべての投稿を表示
ラベル Lucid の投稿を表示しています。 すべての投稿を表示

☆ドライバのソースを変更した場合、バイナリの何処が変わるか調べてみました

前回の ☆バイナリファイルを書き換えてUSB無線LANクライアントを認識させる は、depmodが調べているセクション、シンボルをとりあえず書き換えてみただけです。
この2箇所の書き換えは、必要ではありますが、必要十分であるかは不明です。
本当はUSB無線LANクラアントのカーネルモジュールが備えるべきインターフェースの仕様がわかればよいのですが、検索してもそのものズバリは見つけられませんでした。

2010/06/01 追記
USB_DEVICEマクロを使ってIdVendor,IdProductの指定をしている
("__mod_usb_device_table"のmatch_flagsが0x03)
場合は前回の方法で問題ないとおもわれますが、match_flagsの値がそれ以外の場合は十分でないようです。
hitoさんによる此方の投稿を参照してください。
https://forums.ubuntulinux.jp/viewtopic.php?pid=60947#p60947

そこでカーネルモジュールのソースの箇所だけUSBデバイス認識用の"idProduct"を書き換え、ビルドしてバイナリファイルの何処が変わったか比較してみることにしました。
RT2870_LinuxSTA_V2.3.0.0.tar.tar.bz2を使用して検証します。(これは私の環境で正攻法で動かなかったものなので、材料としては若干不安なのですが。)
結果を先に書くと、前回のバイナリ書き換えはおそらく正解(必要十分)であろうと思われます。

比較用のモジュールをビルドする際は同一のパスでビルドする方が良いです。
".rodata.str1.4"にはパスを保持している箇所があって、比較の際にそこが差分として出てくるとかなり面倒です。
パスの長さが違うとファイルサイズやシンボルのファイル先頭からのオフセットも違ってくる可能性がありそうです。

●ソースコードの変更箇所(および自動的に変更された箇所)

■common/rtusb_dev_id.c

下記がソースを手で変更する唯一の箇所です。

--- a/common/rtusb_dev_id.c 2009-11-26 15:22:40.000000000 +0900
+++ b/common/rtusb_dev_id.c 2010-05-30 21:14:50.800580320 +0900
@@ -59,7 +59,7 @@
  {USB_DEVICE(0x0DF6,0x002D)}, /* Sitecom */
  {USB_DEVICE(0x14B2,0x3C06)}, /* Conceptronic */
  {USB_DEVICE(0x14B2,0x3C28)}, /* Conceptronic */
- {USB_DEVICE(0x2019,0xED06)}, /* Planex Communications, Inc. */
+ {USB_DEVICE(0x2019,0xED14)}, /* Planex Communications, Inc. */
  {USB_DEVICE(0x07D1,0x3C09)}, /* D-Link */
  {USB_DEVICE(0x07D1,0x3C11)}, /* D-Link */
  {USB_DEVICE(0x14B2,0x3C07)}, /* AL */

■os/linux/rt2870sta.mod.c

RT2870_LinuxSTA_V2.3.0.0.tar.tar.bz2では自動で変更されます。
MODULE_INFOの部分が変わるのは実施前に想定していませんでした。

--- a/os/linux/rt2870sta.mod.c 2010-05-30 21:17:10.616580922 +0900
+++ b/os/linux/rt2870sta.mod.c 2010-05-30 21:19:10.388580922 +0900
@@ -151,7 +151,7 @@
 MODULE_ALIAS("usb:v0DF6p002Dd*dc*dsc*dp*ic*isc*ip*");
 MODULE_ALIAS("usb:v14B2p3C06d*dc*dsc*dp*ic*isc*ip*");
 MODULE_ALIAS("usb:v14B2p3C28d*dc*dsc*dp*ic*isc*ip*");
-MODULE_ALIAS("usb:v2019pED06d*dc*dsc*dp*ic*isc*ip*");
+MODULE_ALIAS("usb:v2019pED14d*dc*dsc*dp*ic*isc*ip*");
 MODULE_ALIAS("usb:v07D1p3C09d*dc*dsc*dp*ic*isc*ip*");
 MODULE_ALIAS("usb:v07D1p3C11d*dc*dsc*dp*ic*isc*ip*");
 MODULE_ALIAS("usb:v14B2p3C07d*dc*dsc*dp*ic*isc*ip*");
@@ -198,4 +198,4 @@
 MODULE_ALIAS("usb:v100Dp9031d*dc*dsc*dp*ic*isc*ip*");
 MODULE_ALIAS("usb:v0DB0p6899d*dc*dsc*dp*ic*isc*ip*");
 
-MODULE_INFO(srcversion, "BFE72125F5BC16053AC2BDE");
+MODULE_INFO(srcversion, "F9CA397B948AAF46EC1F3E8");

●バイナリが変わった箇所

"cmp -l"を使用してカーネルモジュールが変わった位置を調べました。
出力は下記の通りでした。

"cmp -l"はreadelfやodと違いファイルの先頭バイトの位置が"1"になっているので、"cmp -l"で出た差分をodで調べる際はオフセットの値に注意が必要です。
値は8進数でダンプされます。

そのままでは見にくいので、連続する領域の先頭アドレスと長さ、該当するセクションに変換すると下記の通りです。

start   length  Section
    68  20      .note.gnu.build-i
486964   1      .rodata.str1.1
491211  23      .modinfo
494162   2      .modinfo
520852   1      .data

cmp -l の出力
69  53  51
    70 324 343
    71 114 131
    72 302 122
    73 262 135
    74 153 213
    75 225 136
    76 260 221
    77 334 157
    78 243  75
    79 213 135
    80 141 361
    81 154 145
    82  17 350
    83  52 224
    84   6 232
    85 147 104
    86 342  21
    87 215 246
    88 102 253
486965  67  71
491212 102 106
491213 106  71
491214 105 103
491215  67 101
491216  62  63
491217  61  71
491218  62  67
491219  65 102
491220 106  71
491221  65  64
491222 102  70
491223 103 101
491224  61 101
491225  66 106
491226  60  64
491227  65  66
491228  63 105
491229 101 103
491230 103  61
491231  62 106
491232 102  63
491233 104 105
491234 105  70
494163  60  61
494164  66  64
520853   6  24

■ソース修正が反映されるバイナリの箇所
▼".modinfo"セクションのalias

"elfdump -p '.modinfo'"の出力の差分だけ示します。(-uをつけないdiff)
srcversionの変更は予想していなかったものですが、ソースの変更がそのまま反映されています。
下記の2箇所に相当します。

start   length  Section
491211  23      .modinfo
494162   2      .modinfo

9c9
<   [    e0]  srcversion=BFE72125F5BC16053AC2BDE
---
>   [    e0]  srcversion=F9CA397B948AAF46EC1F3E8
55c55
<   [   c60]  alias=usb:v2019pED06d*dc*dsc*dp*ic*isc*ip*
---
>   [   c60]  alias=usb:v2019pED14d*dc*dsc*dp*ic*isc*ip*

▼".data"セクションの"__mod_usb_device_table"シンボル

前回と同じ要領で"__mod_usb_device_table"シンボルをダンプした結果の差分だけ示します。
下記の箇所に相当します。

start   length  Section
520852   1      .data

21c21
< 0520848 0003 2019 ed06 0000 0000 0000 0000 0000 0000 0000
---
> 0520848 0003 2019 ed14 0000 0000 0000 0000 0000 0000 0000

■変わると想定していなかったが変わったバイナリの箇所
▼".note.gnu.build-i"セクション
start   length  Section
    68  20      .note.gnu.build-i

このセクションは こちらに よると
"ファイルを識別する為のユニークなビットフィールド"が埋め込まれているようです。
20Byteの長さにわたって差分が出たので160-bit SHA1 hash だと思われます。
ひょっとしたら改ざんを検出するためにこの部分をチェックするシステムも存在するのかもしれませんが、
前回のエントリで動いていたのでUbuntuはチェックしていないと思われます。

▼".rodata.str1.1"セクションのビルドした時刻
start   length  Section
486964   1      .rodata.str1.1

"readelf -p '.rodata.str1.1'"でセクションの内容を見てみると、主にメッセージに使用される文字列などが格納されているようです。
変更前後のセクションのダンプを比較すると下記の様になっていました。
ビルドしたタイムスタンプが格納されている部分で違っています。
ここはバイナリを直接書き換える際に修正しなくても問題なさそうです。
@@ -968,7 +968,7 @@
 
   [  246b]  ConnStatus is not connected
 
-  [  2488]  21:17:00
+  [  2488]  21:19:00
   [  2491]  May 30 2010
   [  249d]  2.3.0.0
   [  24a5]  Driver version-%s, %s %s

☆バイナリファイルを書き換えてUSB無線LANクライアントを認識させる

このエントリに記載している方法は危険かもしれません。実施される方は自己責任で行ってください。

2010/06/01 追記
USB_DEVICEマクロを使ってIdVendor,IdProductの指定をしている
("__mod_usb_device_table"のmatch_flagsが0x03)
場合はこの方法で問題ないとおもわれますが、match_flagsの値がそれ以外の場合は十分でないようです。
hitoさんによる此方の投稿を参照してください。
https://forums.ubuntulinux.jp/viewtopic.php?pid=60947#p60947

Ubuntuでインストール後にすぐ使用できるコマンドだけでカーネルモジュールを直接書き換えて
USB無線LANクライアントを認識させる方法を下記に記述します。
(readelf,od,strings,perlおよびテキストエディタを使用)

成功例が一つ(rt2870sta)だけであるため、別のモジュールで有効であるか不明ですが、
どうしても有線LANの接続が確保できない場合やビルド環境の導入が困難である場合に
試してみる価値はあると思います。

使用するUSB無線LANクラアント(GW-USMicroN)がLucid,Karmicで
デフォルトで認識されてしまうので例はJauntyで実施しました。
カーネルは2.6.28-11-generic。GW-USMicroNのIDは2019:ed14です。
これだけでは心もとないので、Lucidで2019:ed14を取り除いたモジュールをビルドし、同じ要領を実施しました。
これも認識、接続に成功しています。
実はRalinkのドライバ(RT2870_LinuxSTA_V2.3.0.0.tar.tar.bz2)で試そうと思ったのですが、なぜかソースに2019:ed14を追加してビルドした場合でもGW-USMicroNで接続が出来ませんでした。(Lucid,Karmicとも)

前提条件は対象のUSB無線LANクライアントが使用しているチップを駆動するカーネルモジュールが既知で
あること。(そしてデフォルトでモジュールが存在するが、子機が認識されないこと。)
USB無線LAN子機のidVendor,idProductのペアがmodules.alias,modules.usbmapに
存在しない場合、下記の方法で接続できる可能性があります。

目次

●1.前置き(きっかけ)

●2.readelf,od,stringsで収集する情報

●3.書き換え作業

●4.モジュールの認識



●1.前置き(きっかけ)

きっかけはdepmodコマンドで更新される[/lib/modules/$(uname-r)/]のmodules.* にlsbusbで出力されるidVendor,idProductと同じ値を見つけたことに始まります。

当該の値が含まれているファイルはmodules.aliasとmodules.usbmapで下記のようなものでした。

■modules.aliasの内容
(先頭行と一部抜粋)
# Aliases extracted from modules themselves.
alias rt3070sta rt2870sta
alias usb:v0411p015Dd*dc*dsc*dp*ic*isc*ip* rt2870sta
alias usb:v1737p0077d*dc*dsc*dp*ic*isc*ip* rt2870sta
■modules.usbmapの内容
(先頭行と一部抜粋)
# usb module         match_flags idVendor idProduct bcdDevice_lo bcdDevice_hi bDeviceClass bDeviceSubClass bDeviceProtocol bInterfaceClass bInterfaceSubClass bInterfaceProtocol driver_info
rt2870sta            0x0003      0x148f   0x2770    0x0000       0x0000       0x00         0x00            0x00            0x00            0x00               0x00               0x0
rt2870sta            0x0003      0x1737   0x0071    0x0000       0x0000       0x00         0x00            0x00            0x00            0x00               0x00               0x0
rt2870sta            0x0003      0x1737   0x0070    0x0000       0x0000       0x00         0x00            0x00            0x00            0x00               0x00               0x0
rt2870sta            0x0003      0x148f   0x2870    0x0000       0x0000       0x00         0x00            0x00            0x00            0x00               0x00               0x0

これらの値はそれぞれdepmodコマンドがモジュールのファイルから読み出したものです。
depmodのソースから調べてみると下記の部分から取得していました。

■modules.aliasの元情報

モジュールの ".modinfo" セクションを元に作成されています。

$ readelf -p .modinfo モジュールファイルのパス
で簡単に見ることができます。

モジュールのソースにおていこの情報は
linux/module.hで定義されているMODULE_ALIASマクロを使って宣言されているようです。

#define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias)

#define MODULE_DEVICE_TABLE(type,name)  \
  MODULE_GENERIC_TABLE(type##_device,name)

■modules.usbmapの元情報

モジュールの"__mod_usb_device_table"シンボルに格納されています。
バイナリなので容易には見ることができません。
depmodを含むmodule-init-toolsのソースパッケージではtables.hで
その構造とサイズを定義しています。
(usb_device_id構造体、サイズはUSB_DEVICE_SIZE32,USB_DEVICE_SIZE64)

モジュールのソースにおていこの情報は
linux/usb.hで定義されている下記のマクロを使って宣言されているようです。

#define USB_DEVICE(vend,prod) \
 .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
 .idVendor = (vend), \
 .idProduct = (prod)

Ralinkのドライバ(RT2870_LinuxSTA_V2.3.0.0.tar.tar.bz2)では
USB_DEVICEを使用しているソースからMODULE_ALIASを使用するソースを
自動で生成しているようです。

●2.readelf,od,stringsで収集する情報

書き換え対象のidVendor,idProductとそのモジュール上の位置を知る必要があります。 ここでは"__mod_usb_device_table"シンボルの先頭のIDを対象にします。 そして対応する".modinfo"のエントリのオフセットを探します。

■モジュールの退避、バックアップの作成

対象モジュールを作業ディレクトリにコピーし、念のためバックアップを作っておきます。

$ sudo cp -p /lib/modules/$(uname -r)/kernel/drivers/staging/rt2870/rt2870sta.ko ./
$ TRG_MOD=./rt2870sta.ko
$ sudo cp -p $TRG_MOD ${TRG_MOD}.org
■"__mod_usb_device_table"の最初のエントリの位置と値の取得

まずreadelfコマンドで"__mod_usb_device_table"シンボルがが格納されている
セクションとその先頭からのオフセット、サイズを取得します。
コマンドの実行結果から25番目のセクションに格納されていて、
先頭からのオフセットが16進で0x4140、サイズが1220Byteであることが分かります。
(先頭だけを対象にするのでサイズは特に必要ありません。)

$ TRG_MOD=/lib/modules/2.6.28-11-generic/kernel/drivers/staging/rt2870/rt2870sta.ko
$ readelf -s $TRG_MOD | sed -ne '1,3p;/__mod_usb_device_table/p;'

Symbol table '.symtab' contains 1267 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
   555: 00004140  1220 OBJECT  GLOBAL DEFAULT   25 __mod_usb_device_table

25番目のセクションを探します。".data"セクションです。
ファイルの先頭から16進で0x6c980で始まっていることが分かります。
(別のモジュールで試してみると番号[Nr]はモジュールによって違いますが、
セクション名は".data"でした。基本的に".data"セクションを探せばよさそうです。)

$ readelf -S $TRG_MOD | sed -ne '1,4p;/\[25\]/p;'
There are 35 section headers, starting at offset 0x73830:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [25] .data             PROGBITS        00000000 06c980 004694 00  WA  0   0 32

開始アドレスを計算してodコマンドで内容を表示します。
1レコードが20Byteで先頭5項目はunsigned shortであることが分かっているので
(depmodのソースtable.h参照)
odのオプションに -N 20 --width=20 -t x2 を指定します。

ここで -t x1 とすると、x86はリトルエンディアンなのでunsigned shortの
上位バイトと下位バイトが逆になって表示されます。
出力から書き換え箇所はファイル先頭からのオフセットが十進で(461504 + 2) Byte
そこからunsigned shortを2つ分(計4byte)を書き換え対象にします。

$ perl -e 'print 0x4140 + 0x6c980 ,"\n"'
461504
$ od -j 461504 -N 20 -v -A d -t x2 --width=20 $TRG_MOD
0461504 0003 148f 2770 0000 0000 0000 0000 0000 0000 0000
■modules.aliasの元になる情報の書き換え位置

次にmodules.aliasの元になる情報の書き換え位置を調べます。
これは文字列なのでstringsコマンドに-tdオプションを指定することで
比較的簡単に調べることができます。
十進でファイルの先頭からのオフセット438048Byte,長さ20Byteを書き換えます。
("alias=usb:v148Fp2770" を "alias=usb:v2019pED14"へ)

$ strings -td $TRG_MOD | grep -i -e 148f.2770
 438048 alias=usb:v148Fp2770d*dc*dsc*dp*ic*isc*ip*

●3.書き換え作業

perlを使って書き換えを行ないます。

■"__mod_usb_device_table"の先頭書き換え

write_vp.plというスクリプトを書きました。
ネット接続不可の状況でも、その場ですぐにかけるような内容です。
書換え後のidVendor,idProductは直書きです。
引数は対象ファイルとオフセットです。

### スクリプト内容の表示
$ cat ./write_vp.pl
#!/usr/bin/perl

if($#ARGV != 1){
    print STDERR "usage $0 filepath offset\n";
}

my($file) = shift;
my($offset) = shift;

open FH, "+< " . $file or die "$!:$file";
seek(FH, $offset, 0);
my($buf) = pack "SS", 0x2019, 0xed14;
syswrite(FH, $buf, 4) or die "$!";

### 実行
$ sudo ./write_vp.pl $TRG_MOD 461506
### 確認
$ od -j 461504 -N 20 -v -A d -t x2 --width=20 $TRG_MOD
0461504 0003 2019 ed14 0000 0000 0000 0000 0000 0000 0000
■".modinfo"セクションの書き換え

write_alias.plというスクリプトを書きました。
write_vp.plと同じく短いものです。

### スクリプト内容の表示
$ cat ./write_alias.pl
#!/usr/bin/perl

if($#ARGV != 1){
    print STDERR "usage $0 filepath offset\n";
}

my($file) = shift;
my($offset) = shift;

open FH, "+< " . $file or die "$!:$file";
seek(FH, $offset, 0);
syswrite(FH,"alias=usb:v2019pED14",20);
seek(FH, $offset, 0);
sysread(FH,$buf,20);
print $buf,"\n";

### 実行
$ sudo ./write_alias.pl $TRG_MOD 438048
alias=usb:v2019pED14
### 確認
$ strings -td $TRG_MOD | grep -e 2019.ED14
 438048 alias=usb:v2019pED14d*dc*dsc*dp*ic*isc*ip*

●4.モジュールの認識

モジュールを正式な位置に書き戻してdepmodで依存情報を更新し、modprobeでモジュールを読み込みます。

$ sudo cp $TRG_MOD /lib/modules/$(uname -r)/kernel/drivers/staging/rt2870/
$ sudo depmod -a $(uname -r)
$ sudo modprobe rt2870sta

あとはNetworkManagerで認証関係の設定を行えば接続できるはずです。

☆HDDに置いたISOからブートしてUbuntuをインストールする

このエントリに記載している方法は危険かもしれません。実施される方は自己責任で行ってください。

vine_userさんのサイトでHDDに保存したISOイメージをGRUB2で直接起動する方法《Ubuntu 9.10対応》を見ました。
これはとても快適です。

調子に乗って、この方法をつかってブートし、UbiquityでLucidのインストールを試みたのですが、
実際にインストールを開始する段階の最初でアンマウントできない旨のメッセージが出てインストールできません。

悔しいので、気合を入れてUbiquityのソースを見てみたのですが、結構複雑で追いかけるのはかなりきついです。
基本的にPythonなのですが、GUIがある上に裏でシェルを使っていたりします。
そこで、エラーメッセージが出るところまで進めておいて、pstree -alp でそのときに走っているプロセスと
そのオプションを見てみました。関係ありそうな部分は下記です。

pstree -alp の一部分
|-gksudo,3123 --preserve-env --desktop /home/ubuntu/Desktop/ubiquity-gtkui.desktop -- /usr/bin/ubiquity gtk_ui
  |   `-udisks,3125 --inhibit -- /usr/lib/ubiquity/bin/ubiquity gtk_ui
  |       `-ubiquity,3128 /usr/lib/ubiquity/bin/ubiquity gtk_ui
  |           |-debconf-communi,4062 -w /usr/bin/debconf-communicate -fnoninteractive ubiquity
  |           |-ibus-daemon,4041 --xim
  |           |   |-ibus-gconf,4055
  |           |   |-python,4057 /usr/share/ibus/ui/gtk/main.py
  |           |   |-python,4060 /usr/share/ibus-anthy/engine/main.py --ibus
  |           |   `-{ibus-daemon},4056
  |           |-log-output,11685 -t ubiquity --pass-stdout /bin/partman-commit
  |           |   `-partman-commit,11686 /bin/partman-commit
  |           |       `-01unmount_busy,12462 /lib/partman/commit.d/01unmount_busy
  |           `-{ubiquity},11682

名前からして怪しいのが"/lib/partman/commit.d/01unmount_busy"です。
見てみると、確かにumountを実行しています。
GUIのエラーメッセージもここから出しているようで、そのおかげでpstreeの出力にも出てくれたみたいです。
debconfの機能を使ってumoutを実行するかどうかを調べているようです。
debconf経由でubiquity/partman-skip-unmountをtrueにするのがスマートなのでしょうが、
やりかたがわからなかったので下のコードのように処理を始める前に"exit 0"で正常終了するようにしました。
この修正を実施してからインストールを開始すればISOイメージとは別のパーティションにUbuntuをインストールできるようになります。
下図のダイアログが出たら、[Ubuntu 10.04 を試す]のボタンを選択していったんGnomeのデスクトップ環境を表示されて修正を行います。

立ち上がった直後はキーボードレイアウトに英語配列になっているので"Setting"->"Preferences"->"Keybord"で設定を日本語配列にしてから編集したほうが良いでしょう。

"/lib/partman/commit.d/01unmount_busy" の修正内容(わざわざdiffを表示するほどのものではないですが)
@@ -1,13 +1,13 @@
 #! /bin/sh
 
 # This should largely be unnecessary now that partman-base/init.d/parted
 # checks for mounted partitions at startup, but it may still serve as
 # insurance against partitions being mounted while the partitioner is
 # running.
-
+exit 0
 . /lib/partman/lib/base.sh
 
 db_get ubiquity/partman-skip-unmount
 if [ "$RET" = true ]; then
     exit 0
 fi

☆GmrunのキーバインドをBashに少しだけ近づける

私はGmrunが大好きです。
Mihai Bazonさん、すばらしいソフトウェアを作ってくれてありがとうございます。
さて、前回の「☆gmrun で Ctrl+PをUp、Ctrl+NをDownキーと同じように動作させる」に引き続き、
2つだけBashのキーバインドを付け加えてみました。
Ctrl+K、Ctrl+Uです。文字列を選択した状態はBashではありえない状態なので、
どういう仕様にするか迷ったのですがコーディングが楽な使用にしました。
パッチはこれです。
適用の手順は下記の通りです。
/usr/bin/gmrunだけ圧縮したアーカイブも用意しました。gmrun_0.9.1-4_i386.msll-patched.20100505.tar.gz
開発環境を入れたくない方はapt-getでgmrunを導入した後、/usr/bin/gmrunだけ入れ替えればOKです。
(ビルドしたパッケージをdpkgで導入すると更新がなくてもupdate-managerで
更新対象としてリストされるので、自分でビルドした場合でも一旦apt-getでgmrunを導入してから、
/usr/bin/gmrunだけ入れ替える方が良いかもしれません。
ちゃんとパッケージした方法で作れば良いのでしょうが、方法がわからず...)

ソース、パッチの取得とビルド
$ mkdir gmrun
$ apt-get source gmrun
$ sudo apt-get build-dep gmrun
$ wget http://sites.google.com/site/midspeclowload/files/gmrun-0.9.1-4.msll-20100505.patch?attredirects=0&d=1
$ patch -p1 < gmrun-0.9.1-4.msll-20100505.patch
$ cd gmrun-0.9.1/
$ debuild -r
gmrun-0.9.1-4.msll-20100505.patch
--- a/gmrun-0.9.1/src/gtkcompletionline.cc	2003-06-22 08:14:34.000000000 +0900
+++ b/gmrun-0.9.1/src/gtkcompletionline.cc	2010-05-05 22:14:05.296882925 +0900
@@ -975,6 +975,34 @@
       STOP_PRESS;
       return TRUE;
 
+     case GDK_K:
+     case GDK_k:
+      if (event->state & GDK_CONTROL_MASK) {
+        int pos = gtk_editable_get_position(GTK_EDITABLE(cl));
+        int len = gtk_entry_get_text_length(GTK_ENTRY(cl));
+        gtk_editable_delete_text(GTK_EDITABLE(cl), pos, len);
+        gtk_editable_select_region(GTK_EDITABLE(cl), pos, pos);
+        if (MODE_SRC)
+          search_off(cl);
+        return TRUE;
+      } else goto ordinary;
+
+     case GDK_U:
+     case GDK_u:
+      if (event->state & GDK_CONTROL_MASK) {
+        int pos = gtk_editable_get_position(GTK_EDITABLE(cl));
+        gtk_editable_delete_text(GTK_EDITABLE(cl), 0, pos);
+        gtk_editable_select_region(GTK_EDITABLE(cl), 0, 0);
+        if (MODE_SRC)
+          search_off(cl);
+        return TRUE;
+      } else goto ordinary;
+
+     case GDK_P:
+     case GDK_p:
+      if (event->state & GDK_CONTROL_MASK) {
+		;/* fall to 'case GDK_Up:'*/
+      } else goto ordinary;
      case GDK_Up:
       if (cl->win_compl != NULL) {
         int &item = cl->list_compl_items_where;
@@ -1010,6 +1038,11 @@
      }
      return FALSE;
 
+     case GDK_N:
+     case GDK_n:
+      if (event->state & GDK_CONTROL_MASK) {
+		;/* fall to 'case GDK_Down:'*/
+      } else goto ordinary;
      case GDK_Down:
       if (cl->win_compl != NULL) {
         int &item = cl->list_compl_items_where;

☆fsarchiverでパーティションをコピーしてみました

5/2 追記
5/1 当初の手順だと不足がありました。
grub.cfgのsearchの行とlinuxの行でUUIDの齟齬が生じて
結局 linux行が優先され、/dev/sda8をルートとして起動してしまいます。
修正した手順の確認がとれたので修正済みのものを掲載しました。
修正した点は、実行していたにもかかわらず記載していなかった7.update-grubの実行と
本質的に欠けていた6.のところのgrub.cfgの編集です。

Ubuntu 10.04 Lucid Lynxが正式リリースされました。
本格的に弄るのは日本語Rimixが出てからのつもりですが、一応インストールしました。
インストールすれば弄りたくなるのが人情です。
弄っておかしくなった場合や、バグ報告のを考慮すると、あまり弄っていない状態をすぐに作れるようにしておくと便利です。
パーティション丸ごとのバックアップといえばddやpartimageがメジャーですが、ddは敷居が高く、partimageはext4に対応していません。
そこでfsarchiverを使用してバックアップを作成し、これを別パーティションに復元して弄ることにしました。
fsarchiverはLucidからuniverseのリポジトリに入りました。バージョンはまだ0.6.8ですが...
幸いパーティションはMaxの16まで切ってあるので、空きはいっぱいあります。
とりあえず、/dev/sda8にdesktop-i386をインストール。
その後、sda9,sda10,sda11にコピーをしました。
(バックアップからのリストアは1つあたり3分くらいだったので調子に乗って3つもコピーしてしまいました。)

手順の概略
1.とりあえず10.04を/dev/sda8へインストール
2./dev/sda1にインストールしてあったKarmicを起動
3.fsarchiverで/dev/sda8を丸ごとバックアップ
4.fsarchiverで別のパーティション(/dev/sda9)へリストア
5.tune2fsでリストアしたパーティション(/dev/sda9)のUUIDを変更
6.リストアしたパーティション(/dev/sda9)に入っている設定ファイルを修正
7.リストアしたパーティションを起動時に選択可能にするためupdate-grubを実行
8.リブートして/dev/sda9から起動、dpkg-reconfigureでgrub-pcのインストール先を修正

(私の環境では"/home"や"/var"を分けずに"/"の1パーティションだけで運用しています。 "/home"は個別のパーティションにする理由は設定ファイルをシステムごとに別にするためです。 データ用のパーティションは別に用意して$HOMEのしたからシンボリックリンクを張っています。)

以下で3以降の手順を細かく説明します。

3.fsarchiverで/dev/sda8を丸ごとバックアップ

bzip2 -2と同一の圧縮レベルで、圧縮用のスレッドを2つ使用してバックアップ

$ sudo fsarchiver -z5 -j2 savefs sda8.fsa /dev/sda8

4.fsarchiverで別のパーティション(/dev/sda9)へリストア

$ sudo fsarchiver restfs sda8.fsa id=0,dest=/dev/sda9

5.tune2fsでリストアしたパーティション(/dev/sda9)のUUIDを変更

リストアしたパーティションのUUIDはバックアップしたパーティションと同じになっているので変更します。 tune2fsのmanページで見ると-Uのあとにrandomやtimeをしてできそうなのですが、なぜかうまくいきません。 普通にuuidgenの出力を使うことにしました。

$ sudo tune2fs -U $(uuidgen) /dev/sda9
# fstabを書き換えるためにUUIDを確認
$ sudo blkid /dev/sda9
/dev/sda9: UUID="2bd68985-c6cf-4eb5-9c55-aaee3b173656" TYPE="ext4" 

6.リストアしたパーティション(/dev/sda9)に入っている設定ファイルを修正

fstabとgrub.cfgを修正します。
grub.cfgの修正が必要な理由は、update-grubの実行時に走る/etc/grub.d/30_os-proberの中で
/usr/lib/linux-boot-probes/40grub2 が実行されるのですが、これがリストアしたパーティションにある
grug.cfgを参照してるからです。

$ sudo mkdir /mnt/sda9
# fstabのUUIDを書き換える。ついでにduring installationのコメントも/dev/sda9に変更
$ sudo vi /mnt/sda9/etc/fstab
$ sudo vi /mnt/sda9/boot/grub.cfg
fstabの修正内容
@@ -7,4 +7,4 @@
 #                
 proc            /proc           proc    nodev,noexec,nosuid 0       0
 # / was on /dev/sda10 during installation
-UUID=32c50640-99e1-49c1-837f-05701e9e7def /               ext4    errors=remount-ro 0       1
+UUID=2bd68985-c6cf-4eb5-9c55-aaee3b173656 /               ext4    errors=remount-ro 0       1
grub.cfgの修正内容(書込みは:w!で強制書込みをします)
UUIDの書き換えが必要な箇所は"### BEGIN /etc/grub.d/10_linux ###"から"### END /etc/grub.d/10_linux ###"の間にある
"linux"始まる行です。(ほかの部分は8.のdpkg-reconfigureの時に直ります。)
--- sda10_grub.cfg.org 2010-05-02 20:28:18.581936565 +0900
+++ sda10_grub.cfg.new 2010-05-02 20:31:53.980286836 +0900
@@ -63,22 +63,22 @@
 ### BEGIN /etc/grub.d/10_linux ###
 menuentry 'Ubuntu, with Linux 2.6.32-21-generic' --class ubuntu --class gnu-linux --class gnu --class os {
    recordfail
    insmod ext2
    set root='(hd0,8)'
    search --no-floppy --fs-uuid --set 32c50640-99e1-49c1-837f-05701e9e7def
-   linux   /boot/vmlinuz-2.6.32-21-generic root=UUID=32c50640-99e1-49c1-837f-05701e9e7def ro   quiet splash
+   linux   /boot/vmlinuz-2.6.32-21-generic root=UUID=2bd68985-c6cf-4eb5-9c55-aaee3b173656 ro   quiet splash
    initrd  /boot/initrd.img-2.6.32-21-generic
 }
 menuentry 'Ubuntu, with Linux 2.6.32-21-generic (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os {
    recordfail
    insmod ext2
    set root='(hd0,8)'
    search --no-floppy --fs-uuid --set 32c50640-99e1-49c1-837f-05701e9e7def
    echo    'Loading Linux 2.6.32-21-generic ...'
-   linux   /boot/vmlinuz-2.6.32-21-generic root=UUID=32c50640-99e1-49c1-837f-05701e9e7def ro single 
+   linux   /boot/vmlinuz-2.6.32-21-generic root=UUID=2bd68985-c6cf-4eb5-9c55-aaee3b173656 ro single 
    echo    'Loading initial ramdisk ...'
    initrd  /boot/initrd.img-2.6.32-21-generic
 }
 ### END /etc/grub.d/10_linux ###
 
 ### BEGIN /etc/grub.d/20_memtest86+ ###

7.リストアしたパーティションを起動時に選択可能にするためupdate-grubを実行

$ sudo update-grub

8.リブートして/dev/sda9から起動、dpkg-reconfigureでgrub-pcのインストール先を修正

$ sudo dpkg-reconfigure grub-pc
2つほど設定を訊かれますがデフォルトで進めると下記のような画面が出るので grubのインストール先を選択しなおします。

☆LucidのGnome-Sudokuにパッチをあてる

Lucid(Ubuntu 10.04)のGnome数独(Gnome-sudoku 2.30)はKarmicで悪化した経過時間の表示が修正されています。
Karmicの時はセルの上側にメモ用の数字を入力すると経過時間がやたら増えたのですが、これも直っているようです。
(完全ではないようで、多少修正されています。)
しかし、残念ながら特定の場合にコンフリクトした値が赤くならないバグと終了判定が正しくないバグが残っています。
(すでにGnomeの新しいリビジョンでは修正されているので次のリリースでは修正されているはずです。)
これを修正するパッチを用意しました。

gnome-sudoku.2.30.0-0ubuntu6.patchをダウンロードして下記の要領でパッチしてください。
ファイルは ~/Download ディレクトリにダウンロードした前提で記述しています。

$ cd /usr/lib/python2.6/dist-packages/gnome_sudoku
$ sudo patch -p1 < ~/Download/gnome-sudoku.2.30.0-0ubuntu6.patch

注意点はgnome-games-commonとgnome-sudokuパッケージの両方にダブってsduoku.py,timer.pyが含まれていることです。
実際に使われているのはgnome-games-commonの方のsduoku.py,timer.pyですのでパッチを当てるファイルを間違わないように気をつけてください。

suoku.pyに対するパッチの内容はGnomeで実際に適用されたものではなく、私が書いたものです。
gitの使い方を多少学んだのですが、2.30からいくつかコミットが行われていてどれが該当するのかわからなかったのでorz.
(Gnomeで実際に適用されたパッチの方が良かった気がするのですが)
timer.pyの方の修正はGnomeで行われた修正を取り込みました。
こちらは変更が少ないのでgitで変更したコミットが簡単に特定でしました。

gnome-games$ find ./ -name 'timer.py'
../gnome-sudoku/src/lib/timer.py
gnome-games$ git blame -L '/^        if currently_timing:/,+1' -- ./gnome-sudoku/src/lib/timer.py
f235e03e (Jim Ross 2010-03-31 03:53:55 -0400 142)         if currently_timing:
gnome-games$ git log f235e03e^..f235e03e
commit f235e03e98e960a69627f5b4afacb9f14d599bad
Author: Jim Ross <jimbo@dimensia.com>
Date:   Wed Mar 31 03:53:55 2010 -0400

    sudoku: Fixed mark timing
    
    The problem is, when the main window is not active(timer paused) and
    the auto-save kicks in - the timer always gets restarted in mark_timing().
    
    This patch fixes it by storing the current value of self.is_timing at the st
    of mark_timing() and then checking it before calling resume_timing().
    
    Fixes bug #562782
gnome-games$ git show f235e03e
commit f235e03e98e960a69627f5b4afacb9f14d599bad
Author: Jim Ross 
Date:   Wed Mar 31 03:53:55 2010 -0400

    sudoku: Fixed mark timing
    
    The problem is, when the main window is not active(timer paused) and
    the auto-save kicks in - the timer always gets restarted in mark_timing().
    
    This patch fixes it by storing the current value of self.is_timing at the st
    of mark_timing() and then checking it before calling resume_timing().
    
    Fixes bug #562782

diff --git a/gnome-sudoku/src/lib/timer.py b/gnome-sudoku/src/lib/timer.py
index bd5e2de..c37511a 100644
--- a/gnome-sudoku/src/lib/timer.py
+++ b/gnome-sudoku/src/lib/timer.py
@@ -132,13 +132,15 @@ class ActiveTimer (gobject.GObject):
         self.resume_timing()
 
     def mark_timing(self):
+        currently_timing = self.is_timing
         self.pause_timing()
         if self.active_time < 1:
             self.active_time = 1
         # dirty hack: never let total time be less than active time
         if self.active_time > self.total_time:
             self.total_time = self.active_time
-        self.resume_timing()
+        if currently_timing:
+            self.resume_timing()
 
     def finish_timing (self):
         self.mark_timing()

☆LucidのNautilusに再びエンピツのトグルボタンを

Lucid(Ubuntu 10.04)のNautilus(2.30)では"text location bar"と"button bar"を切り替えるエンピツのトグルボタンがなくなってしまいました。
さるお方にアドバイスを頂いて、どなたかPPAで公開してくれる事を願ってPatchをLaunchPadに投稿したのですが、
今のところPPAにアップしてくれた方はいらっしゃらないようです。
ということで自分でパッケージをビルドしたものを公開してみます。
この投稿に提示した操作により損害が発生しても保障はいたしません。適用は自己責任でお願いいたします。

nautilus_2.30.0-0ubuntu4_i386.deb
nautilus_2.30.1-0ubuntu1_i386.deb

本来はパッケージ名を変えたりすべきなのですだと思うのですが、なにぶん良くわからないのでそのままです。
ダウンロードして下記のようにすれば、元々のパッケージと置き換えられます。

# ファイル名はバージョンに合わせて読み替えてください
$ sudo dpkg -i nautilus_2.30.1-0ubuntu1_i386.deb
$ pkill nautilus
※ログイン時にバックグラウンドでnautilusが起動されているのですが、これがいる限り新しいバイナリのnautilusは起動できません。

ソースからビルドしたい方はUbuntu Weekly Recipe 第16回を参照してビルドできる環境を整えてください。
ビルドできる環境が整ったら下記のようにしてビルドします。
正規の手続きではないと思うのですが、一応パッケージは作成されます。
(最後のほうで"running debsign failed"と出るのですが、パッケージは生成されています。)
ディレクトリの名称は適当に置き換えてください。 パスに日本語が含まれていると失敗するかもしれません。ディレクトリ名は英数字だけにしておくのが無難だと思います。

# ディレクトリ名はnautilusである必要はありません
$ mkdir nautilus
$ cd nautilus
# ソースの取得と展開
$ apt-get source nautilus
# ビルドに必要なパッケージの取得
$ sudo apt-get build-dep nautilus
# パッチのダウンロード
$ wget http://launchpadlibrarian.net/44697678/nautilus-2.30.0_add_location_togglebutton.patch
# ディレクトリはバージョンに合わせて読み替えてください。
$ cd nautilus-2.30.1/
# パッチの適用
$ patch -p1 < ../nautilus-2.30.0_add_location_togglebutton.patch
# ビルドの実行
$ debuild -r fakeroot

パッケージのメタ情報を何もいじらなかったせいか、更新がなくてもアップデートマネージャに更新対象として表示されてしまいます。
バージョンがまったく変わっていないときは手動でチェックを外さないと元に戻ってしまうみたいです。

☆軽量で操作性の良いTwitterクライアントPino

少し前に見つけたPinoというTwitterクライアントの紹介です。
TwitterのほかにIdenti.ca というのにも対応しているようです。
Valaとう言語で書かれています。
Version 0.21では日本語が入力できなかったのですが、0.24になって日本語入力できるようになりました。
残念ならが日本語化されていません。
本家サイトはこちら
pino-twitter - Project Hosting on Google Code

導入方法は本家サイトにも書いてある通りで、Karmic以上であれば下記のコマンドで導入できます。
Lucid Beta-1でも同じ操作で導入できることを確認しています。

$ sudo add-apt-repository ppa:vala-team/ppa 
$ sudo add-apt-repository ppa:troorl/pino
$ sudo apt-get update
$ sudo apt-get install pino

画面はLucidに入っているGwibberと似ています。検索機能や複数のTLを流す機能はありません。
気にいっている点は、
・軽快な動作
・Ctrl+1,Ctrl+2,Ctrl+3,Ctrl+4でHome、Mentions、Direct Message、User Infoを切替可能
・投稿はAlt+Enter
最後の投稿操作は何処にも書いていなかったので迷いました。
しかし私は漢字変換の確定にEnterを使うので、誤ってPostしてしまうことが少なくてよいと思っています。


メイン画面のスクリーンショット

User InfoはHome TimelineやMentionsでプロフィール画像をダブルクリックして表示する方法と、
ユーザ名を入力する表示する方法の2種類があります。
残念ながらダイレクトメッセージを頂いたことがないのでDirect Messagesはさびしいスクリーンショットになってしまいました。

Home Timeline (Ctrl+1) Mentions (Ctrl+2) Direct Messages (Ctrl+3) User Info (Ctrl+4) [Show User]押下後のUser Info

メニューの中身

これは見たまんまです。特に説明は不要だと思います。
複数のアカウントを登録して切り替えることが出来そうですが、一つしかアカウントを持っていないのでわかりません。

[Pino] [Edit] [View] [Help]

Preferences(設定画面)

デフォルトではフォントサイズが9ポイントなのですが、日本語は9ポイントではちょっときついと思うので大きくすることをお勧めします。
[Enable Spell checking]はオフの方がいいと思います。(これを書いていて気付きました。)

Main Desktop Account Appearance