Androidの“マーケティングの除外”について

ここ暫くAndroidアプリケーションをマーケットに登録するのに色々と忙しかった。
Androidマーケットへのアプリの登録は色々なブログ等で説明されているので、ここで書くことはない。が、ただ一つだけ、どの記述を見ても良く解らないことがあった。

アプリの登録ページの中ほどに

マーケティングの除外: □ Android マーケットや Google 所有のオンライン/モバイル サイト以外ではアプリケーションを宣伝しません。この設定への変更が有効になるまでに 60 日程度かかることについて了承しています。

という箇所がある。この意味が分からなかった。Androidマーケット以外で私が宣伝するしないを決めるということで何が違うのだろう? iPhoneとの共通アプリに差別化するためなのだろうか? Androidマーケット専用で登録すると何かメリットがあるのだろうか?(逆にAndroidマーケット以外で宣伝すると何か不利になるのだろうか?)という疑問が湧いてくる。日本語を読む限り、そう解釈できる。気持ち的には“私はAndroidマーケットだけでしか宣伝しません。Androidに忠誠を誓います”という宣誓書に見える。

これは、英語の原文を見てみないと分かららない。が、登録ページを英語表示にできない。で、いろいろ探して、原文は次のようになっていることが分かった。

Marketing Opt-Out: □ Do not promote my application except in Android Market and in any Google-owned online or mobile properties. I understand that any changes to this preference may take sixty days to take effect.

日本語だと“私が宣伝する、しない”の事の様に取れるが、原文を見ると“Googleに対してさせる、させない”ということだとわかる。

以降の解釈は私の勝手な解釈であり、Googleからの説明ではない。この文面の解釈は各自の自己責任でお願いしたい。

私の解釈では、開発者のアセット(=資産)であるアイコンやキャプチャー画面、動画などをGoogleがマーケット以外で勝手に使っても良いかの選択、ということだと思う。どの様な理由があるか想像し難いが、何らかの理由でAndroidマーケット以外のところで宣伝して欲しくない時にチェックを付けるようになっているらしい。また、もし、最初Androidマーケット以外での宣伝を許可して、気が変わってAndroidマーケットだけに限定して欲しいとチェックしても、マーケット以外での宣伝が無くなるまで60日程かかるということを覚悟して欲しい、ということらしい。

まぁ、そう思って改めて日本語の文章を読んでみると、それらしい表現にはなっているのだが。(日本語では主語を明確しないと意味が曖昧になってしまうことが良くある。ここでも頭に「Googleは」と明記すべきだろう。)

次のページにも説明が書いてあるが、やっぱり日本語だと分かりにくい。

http://www.google.com/support/androidmarket/developer/bin/answer.py?answer=1078870

日本語では

Google がリクエストする各種画像アセットは、Android マーケットや、場合によっては Google の他のサービスでもアプリケーションの紹介や宣伝に使用されます。アプリケーションのマーケティングAndroid マーケットだけで行う場合は、デベロッパー コンソールで [マーケティングの除外] を選択すると、他でのマーケティングを除外できます。

原文では

The different graphic assets we request are used to highlight and promote your application in Android Market, and possibly other Google-owned properties. If you’d like to restrict the marketing of your app to just Android Market, you have the option of opting-out of marketing by selecting the "Marketing Opt-Out" in the Developer Console.

IBM 5100

閑話。

昔、IBM 5100というポータブル・コンピュータを使ったことがあった。どこで使ったのか覚えてないのだが、APLで簡単なプログラムを入力して遊んだ記憶がある。

コンピュータオタクの私にもAPLは取っ付き難い言語だった。というか、普通のコンピュータでは扱えない言語だ。何故なら特殊な記号を使う。例えば(漢字ではなくて)△、▽、「、∈、等々である。
http://ja.wikipedia.org/wiki/APL
だから、普通のASCIIキーボードのコンピュータでは“そのままでは”使えない。メタ文字を使って、特殊記号の代わりとなる文字列を使う(つまり、スケープ文字+通常のアルファベット文字)処理系もあり、メインフレームなどでは利用できた。私もAPLを使ってみたくてメインフレームで四苦八苦しながらプログラムを組んでみた経験があるが、やはりイケてない。APLを本格的に使うにはAPLキーボードを持ったコンピュータでないと面白くない。で、暫く諦めていたのだけど、どこかの会社(IBM?)に行った時だったか記憶が定かではないのだが、IBM 1500を使った。

私が使ってきたプログラム言語のなかではAPLはかなり特殊だった。一般的な言語ではループ構造を使うベクトルや配列の計算を数文字で表現することができる。ただ、なかなか慣れるのが大変だ。私も入門書にあるサンプル+α程度のプログラムしか組んだことがないので、“使った”とは言えないが。(ちなみに私的に第2位はProlog。毎度の“通産省の物にならないプロジェクト”で採用された言語だが、言語自身は面白かった。第五世代とかは余り興味がなかったが。)

また、ハードウェアとしても面白いのは、ミニコン並みの性能をもったものが“ポータブル”で作られていたことだ。キーボード、(とても小さな)ディスプレ、テープドライブが一体になっていた。当時としては最新テクノロジの結晶だったのだろう。ただ、“ボータブル”と言っても、“移動可能”という程度の意味で、その大きさと重さから“持ち運ぶ”気にはならない。勿論、電源はコンセントから取るので、電源のある場所でなければ利用できない。今のノートPCとは全く異なる。

更に、アーキテクチャがマイクロコードを基本としているので、他のコンピュータをエミュレートできる点もすごい。実際にIBM System/370とSystem/3をエミュレートして動いていたらしい。

なんか、最近のコンピュータって、こういった思い切った発想のものが少なくなって来たような気がする。iPhoneがクールかと言えば確かにクールだが、クレイジーではないよな。昔と違って、今は売れるか売れないか分からないものにはお金を掛けられない、というご時世なのかも知れない。2000年の.comバブルの辺りから株主至上主義が定着してしまったせいかも。VMwareも株式公開するまではVMware Serverといった実験的製品を出していたが、株式公開した途端に実質上無くなってしまった。

finish()ではプロセスは終わらない

Androidのメソッドの一つにfinish()というのがある。これはアクティビティを終了させたい時に呼び出す。のだが、気をつけないとハマるので、ちょっと注意が必要。

finish()を呼び出すとexitのようにプロセスが終了するかと思えば、そうではない。アクティビティは“停止状態”になり、(AndroidOSつまりLinuxの)プロセスとしては生き続けている。

試しに次のような簡単なプログラムを作ってテストしてみよう。

package com.example.android.finishtest;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class FinishTest extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        finish();
        Log.d("FinishTest", "Called finish()");
    }

    @Override
    protected void onDestroy() {
        Log.d("FinishTest", "onDestroy");
    	super.onDestroy();
    }
}

onCreateされた途端にfinishしてみる。このアプリを実行した時のLogの出力は以下の通り。

04-27 19:50:02.197: DEBUG/FinishTest(1145): Called finish()
04-27 19:50:02.727: DEBUG/FinishTest(1145): onDestroy

つまり、onCrateでfinish()を呼び出すと、このアクティビティをdestoryするようにスケジュールするだけで、またonCreateに戻ってくる。そしてfinish()の次の行にあるログ出力のメソッドを呼び出してからonCreateを抜ける。そして、その直後にonDestroyが呼び出されて、アクティビティはdestoryされる。

さて、destoryされた後のプロセスの状態を見てみると次のようになっている。

android@android:~$ adb shell
# ps
USER     PID   PPID  VSIZE  RSS     WCHAN    PC         NAME
root      1     0     296    204   c009a694 0000c93c S /init
	:
app_31    1145  30    127296 18644 ffffffff afe0da04 S com.example.android.finishtest
	:
#

と、確かに、まだプロセスとしては存在している。また、SDKのDDMS(Dalvik Debug Monitor Server)で眺めても確かにプロセスとして存在している。

つまり、finish()を呼び出してもアプリケーションとしては終了するもののプロセスとしては(他のアプリケーションの起動によりメモリが不足するなどの状態にならない限りは)存在し続けて、次回の起動時に再利用(リサイクル)され、onCreateが呼び出される(らしい)。メモリへの展開やライブラリとのリンクはコンピュータにとっては負担の大きな作業なので、携帯電話のような限られたハードウェアでは自然な方法だろう。

それがどうした?

finish()を呼び出してもプロセスとしては存在し続ける。だから、それがどうした? 次回の再利用でプロセスを再生成する必要がないので、いいじゃん。ハードウェアへの負担も小さいから、いいじゃん。

ところが、アプリを作っていて、ちょっとハマってしまった。

アクティビティのクラスを定義する際にスタティックなメンバ変数の初期化を宣言部分で行っていた。まぁ、普通にJavaでプログラムする場合の常套手段だ。スタティックなメンバ変数を宣言部で初期化するということは、そのクラスがメモリ上に展開された時に自動的に初期値が代入される。定数でなければ(つまりfinal宣言でなければ)プログラムの進行に伴い変数値も変化する。しかし、アプリケーションを終了して、再度起動した場合は自動的に初期化されるので、元の値に戻ってから始められる。

ところが、Androidのアクティビティはちょっと違う。上で検証したようにfinish()を呼び出しても、アクティビティはDestroyはされるものの、プロセスとして残っていて(つまりメモリ上にクラスがロードされた状態で残っていて)、次回、再利用する時にはスタティックなメンバ変数の初期化は行ってくれない。

ハマりました。先入観でfinish()は“exit()+α”程度に思っていたので。

アクティビティ開始時に値が定まっていなければならないメンバ変数の初期化は、宣言時ではなく、onCreate、もしくは必要の応じて、onStart、onResumeで実行する必要がある。勿論、プログラム開始時に値が未定であって構わない変数は気にする必要がないし、一方で初期化が必要な場合は初期化のタイミングによって、どのコールバックメソッドで初期化するか気をつけて決めなければならない。

IS-04のマイナー・アップデート

さて、原爆事故については連日、東電と政府(安全委、保安院を含む)が被災者不在や国民不在の対応をしてくれるので、突っ込みだしたらキリがないので、このブログでは止めにして、IT系ブログに戻そう。早く、解散総選挙を望むところだ。

4月7日にKDDIからIS-04のアップデートが出ていた。先週末に試してみた。今回のアップデートは残念ながらAndroid 2.2へのバージョンアップではなく、メールアプリ等のバグ修正などがメインだ。メール関係だけであればGmailをメインで使っていので関係ないのだが、充電制御のバグ更新もあったので更新して置いた方がよさそうだ。
au携帯電話「IS04」の「ソフトウェア更新」についてのお知らせ

アップデートには2つの方法がある。

  1. IS-04の携帯アップデートを使って更新する
  2. PCでダウンロードした更新ファイルをIS-O4のモニタプログラムで更新する

1の方法を使うのが一般的だろう。しかしケイタイアップデートではWiFiは使えず、3G(携帯データ通信)で250MBものファイルをダウンロードするので気が遠くなるほど時間がかかる。2時間以上かかるそうだ。また、電波状況の悪いとこではダウンロードに失敗して(やり直しのため)更に時間が掛かる恐れもある。(何でKDDIWiFiによるダウンロードを提供しないのだろう? その方がKDDIにとっても設備負荷を軽減できると思うのだが。)

そこで、私は2の方法を使った。予めPCで更新ファイルをダウンロードして、USBを使ってIS-04のSDカードにコピー、その後、IS-04を再起動してモニタモードで起動、フラッシュROMを更新する方法である。フラッシュの更新自身は15分程度で終わる。(プロバイダの帯域にも依るがダウンロードも数分で終わる。)
携帯電話(IS04) - FMWORLD.NET(個人) : 富士通
ただし、この方法では、携帯に設定してある全ての設定がリセットされる、という問題もある。つまり、ほぼ工場出荷の状態になってしまう。(勿論、電話番号とのヒモ付けなどのごく基本的な情報は保持される。)従って、更新後は再度、全ての設定が必要になると覚悟した方がいい。Eメールの設定、アカウントの設定、マーケットからのアプリの再インストール、待ち受け等の設定、などなどである。電話帳のデータも消えるので上の富士通のホームページで解説されているように幾つかのアプリケではデータのバックアップが必要となる。

でも、その代り、スッキリ綺麗な状態に戻るので、それはそれで嬉しい。あと、この方法にはもう一つのメリットがる(と思われる)。実際には試してない(というか試す状況に陥ってない)のだが、root化アプリなどでIS-04が文鎮状態(つまり再起動しても立ち上がらない状態)になった場合に、モニタモードで起動できれば、フラッシュを再度書き換えて復帰できるのではないか、と思う。(そのためには、更新ファイルを常にSDカードに保持しておく必要があるが。)その内、文鎮になってしまったら試してみたい。

更新に入るまでの手順は、上の富士通のページに書いているので、更新が始まった後の画面を参考までに表示しておく。モニタモードで起動して、アップデートが開始されると次のような画面になる。


更新の状況は“#”印で表されている。2行あり、下側が全体の進行状況、上側が現在更新中のファイル(?)の更新状況と思われる。

更新が終わると自動的に再起動する。

ファームのバージョン番号が....

ところで、ちょっと以外だったのが、更新ファイルのファイル名が何と“IS04_RC2_DL.zip”。RCって普通はRelease Candidateの訳で使うのだけど。まさか、Release Candedate(正式版に近い完成度を持つものとしてテスト公開されるバージョン)を製品に詰め込んで販売していたとは。アップデート版がRC2だから、当初、出荷されていたのはRC1ってことか? しかも、アップデート版でもRCの範疇を出ていないとは! もしそうだとしたら、さすがにヒドイ。他に“RC”の訳があるのかな。思いつかないが。

まぁ、正式リリースはAndroid 2.2を想定しているとも解釈できるわけだが、このままAndroid 2.2版がリリースされなれば、RC3、RC4、…と上がっていくのだろうか?

ファイル名位は誤魔化しておけばよいものを....。

z4rootで携帯がtelnetサーバにもなる

Android携帯にz4rootというroot化のアプリを入れた。z4rootをインストールするとbusyboxというLinuxの標準コマンドが使えるようになるツールも一緒にインストールされる(busyboxについては“こちら”)。

で、busyboxの中身をもう一度よく見たら「おや、telnetd がある」と気が付いた。これはTelnetのサーバのプログラム。つまりこのbusyboxの中のtelnetdの機能を使えばネットワーク経由でアンドロイド端末にアクセスできる様になる。極端に言えばAndroid端末をTelnetサーバにできることになる。Telnetsshに比べセキュリティは低いが、まさか携帯電話をインターネット上でサーバとして運用するわけでもなく、LANに接続してアクセスする程度の話なので十分だろう。Android版のsshdもあるようだが、少ないメモリに色々なアプリも入れたくないし。

こんな感じでさっそくroot化してtelnetdを起動してみた。

# busybox telnetd

“ps”コマンドで確認すると、ちゃんと動いているようだが、PCからアクセスできない。telnetdのヘルプを見ていて気付いたのだが、telnetdはクライアントからのアクセスがあると標準では/bin/loginというコマンドを起動してユーザがログインするようになっている。しかしAndroidにはログインなんて概念はなく/bin/loginもある筈もない。動かないわけだ。
そこでクライアントからのアクセスがあった場合に/bin/loginではなく、/system/bin/sh を起動するようにしたら、すんなり動いた。つまり、PCからtelnetを掛けるとログイン画面ではなく、いきなりrootのプロンプトが現れる(telnetdがroot権限で動いているため)。

セキュリティ的にはちょっと危険だが、別にIS04をサーバにするわけでもなく、ちょっとrootでファイルをいじくりたい時に使うのだから逆に便利とも言える。(suしないで(rootにならないで)telentdの起動を試みたがソケットがバインドできなくてtelnetd自身が起動しない。)

さて、起動の方法だが、次のようにadbで入ってtelnetdを起動するだけ。何の設定も要らない。

android@android:~$ adb shell
$ su
# busybox telnetd -l /system/bin/sh
# 

端末をUSBデバッグモードにして(もっともz4rootを動かすためにはデバッグモードにしておかないとならないが)、adbで端末に入ってsuしてtelnetdを起動するだけ。これでPCからtelnetでアクセスできるようになる。(勿論、携帯が無線LAN等でIPネットワークに接続されていなければならない。)

試しにPCからアクセスしてみる。その前に携帯のIPアドレスが分からないとアクセスできないので、busyboxのifconfigを使って確かめる。

# busybox ifconfig
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:1784 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1784 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:89200 (87.1 KiB)  TX bytes:89200 (87.1 KiB)

wlan0     Link encap:Ethernet  HWaddr 5C:DA:D4:12:34:56  
          inet addr:192.168.1.3  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::abcd:ffff:ff12:3456/64 Scope:Link
          UP BROADCAST RUNNING  MTU:1500  Metric:1
          RX packets:564 errors:0 dropped:0 overruns:0 frame:0
          TX packets:459 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:89681 (87.5 KiB)  TX bytes:9488 (9.2 KiB)

この例では、端末のIPアドレスは“192.168.1.3”となっていることがわかる。早速、接続。Windowsでもtelnetは使えるのでここでは敢えてDOS窓のサンプルを載せておく。(勿論、TeraTermで使った方がより便利だが。)PCのDOS窓から“telnet 192.168.1.3”と打ち込む。

なんか拍子抜けする画面だが、確かにAndroidのシェルが動いている。

最初にUSBを使てadbで入らないければならないが、あとはネットワーク経由でアクセスできるので楽になる。私は ConnectBot という仮想端末ソフト(sshクライアントになる)を入れているが、このアプリはlocalに接続してAndroidのシェル端末として使うこともできる。これを入れておけば、USB経由のadbを使うことなしに端末でtelnetdを起動することができる。

なお、以上の方法でtelnetdを起動するとシェルはbusybox内蔵のB-Shellもどきではなく、Androidのshなのでちょっと不便だ。telnetで入って改めて

# busybox sh

と実行する必要がある。いきなりbusyboxのshを起動するにはtelnetdを次のように起動する。

# busybox telnetd -l /sdcard/lbin/sh

ただし、“/sdcard/lbin/sh”はbusyboxへのシンボリックリンクになっている必要があり、予め設定しておかなければならない。

# ls -l /sdcard/lbin/sh
lrwxrwxrwx root     root              2011-03-01 09:30 sh -> /system/bin/busybox

シンボリックリンクの設定についても“こちら”を参照のこと。(私の携帯ではbusyboxへのリンクを作ってあるので、イチイチ busyboxを打ち込む必要はない。)

あと、busyboxの中にはloginも含まれているが、こちらはとか色々と環境を設定しないと動きそうもないので使っていない。

syslinuxの設定ファイルに関する工夫

Linuxを使ったネットワークブートで一般的に使うのはsyslinuxによる2次ローダとそれに続くOS本体のダウンロードだろう。syslinuxを呼び出すまでにはDHCPとtftpという仕組み(総括してPXEと呼んでいるが)を使っているが、これについての工夫は別に紹介するとして、まずはPXEで呼び出されたsyslinuxの設定ファイルの構成に関する工夫についてメモっておく。

ここではsyslinuxの中でもPXEブートに関する設定に絞っている。つまり標準で、/tftpboot/syslinux/pxelinux.cfgディレクトリの下のファイル構成が中心となる。

PXEブートにより各クライアントからの要求に対して、“その”クライアントに対する設定ファイルを用意することで、クライアント毎に違うブート設定を実現できる。クライアントの区別は、クライアントのMACアドレス、もしくはIPアドレスで行う。“01-xx-xx-xx-xx-xx-xx”というファイル名を用意することで“xx:xx:xx:xx:xx:xx”というMACアドレスのクライアントに対するブート設定を記述する(IPアドレスを使った方法もあるが説明を簡単にするためにここではMACアドレスによる指定だけに限定する)。等と言うことはマニュアルなどに書いてあるので(ここ)、一般には/tftpboot/syslinux/pxelinux.cfgディレクトリの下は、クライアントMACアドレスに対応するファイル名が多数できる。これを管理するのは結構手間がかかる。もっとも、クライアント個々で全く異なるカーネルやパラメータを使うことは無いので、雛形になるファイルを作り、そのファイルに個々のMACアドレスのファイルをシンボリックリンクすることになる。例えば、

root@ubuntu# cd /tftpboot/syslinux/pxelinux.cfg
root@ubuntu# ls -l
total 8
lrwxrwxrwx 1 root root 23 2011-02-27 18:44 01-aa-bb-cc-dd-ee-00 -> default.ubuntu1004xd32e
lrwxrwxrwx 1 root root 23 2011-02-27 18:44 01-aa-bb-cc-dd-ee-ff -> default.ubuntu1004xd32e
lrwxrwxrwx 1 root root 23 2011-02-27 18:44 01-ff-ee-dd-cc-bb-00 -> default.ubuntu1004xd64e
lrwxrwxrwx 1 root root 23 2011-02-27 18:44 01-ff-ee-dd-cc-bb-aa -> default.ubuntu1004xd64e
-rw-r--r-- 1 root root 53 2011-02-27 18:42 default.ubuntu1004xd32e
-rw-r--r-- 1 root root 53 2011-02-27 18:42 default.ubuntu1004xd64e

root@ubuntu# cat default.ubuntu1004xd32e
DEFAULT ubuntu1004xd32e

LABEL ubuntu1004xd32e
        KERNEL  /diskless/root/ubuntu1004xd32e/vmlinuz
        APPEND  initrd=/diskless/root/ubuntu1004xd32e/initrd.img boot=casper nfsroot=192.168.1.1:/diskless/root/ubuntu1004xd32e netboot=nfs quiet --

という感じでリンクを張ることで、クライアントによってブートするUbuntuを32bit版(i386)か64bit版(amd64)の指定できるようになる。(なお、以下のサンプルではsyslinuxの設定ファイル中で、syslinuxの予約語となっている単語(DEFUALT、LABEL、KERNEL等)は大文字にしてある。これらの予約語は大文字でも小文字でも関係ないので、私は予約語として認識し易くするために大文字を使っている。)

ただ、シンボリックリンクを使ってまとめたとしても雛形のファイル(シンボリック先のファイル、この例では“default.xxxxxx”)も種類がだんだん増えてきて管理が面倒になる。そこで、雛形ファイルを1つにまとめてしまうことを考えた。例えば次のうに“labels”というファイルを作り、そこに設定をまとめてしまう。

root@ubuntu# ls -l
total 12
lrwxrwxrwx 1 root root  23 2011-02-27 18:44 01-aa-bb-cc-dd-ee-00 -> default.ubuntu1004xd32e
lrwxrwxrwx 1 root root  23 2011-02-27 18:44 01-aa-bb-cc-dd-ee-ff -> default.ubuntu1004xd32e
lrwxrwxrwx 1 root root  23 2011-02-27 18:44 01-ff-ee-dd-cc-bb-00 -> default.ubuntu1004xd64e
lrwxrwxrwx 1 root root  23 2011-02-27 18:44 01-ff-ee-dd-cc-bb-aa -> default.ubuntu1004xd64e
-rw-r--r-- 1 root root  53 2011-02-27 19:01 default.ubuntu1004xd32e
-rw-r--r-- 1 root root  53 2011-02-27 19:02 default.ubuntu1004xd64e
-rw-r--r-- 1 root root 503 2011-02-27 18:59 labels

root@ubuntu# cat labels
LABEL ubuntu1004xd32e
	KERNEL  /diskless/root/ubuntu1004xd32e/vmlinuz
	APPEND  initrd=/diskless/root/ubuntu1004xd32e/initrd.img boot=casper nfsroot=192.168.1.1:/diskless/root/ubuntu1004xd32e netboot=nfs quiet --

################################################################################

LABEL ubuntu1004xd64e
	KERNEL  /diskless/root/ubuntu1004xd64e/vmlinuz
	APPEND  initrd=/diskless/root/ubuntu1004xd64e/initrd.img boot=casper nfsroot=192.168.1.1:/diskless/root/ubuntu1004xd64e netboot=nfs quiet --

と、しておく。このlabelsファイルにはLABELの項目だけが含まれ、DEFAULTの行はない。DEFAULTの指定は雛形ファイル(defaul.xxxxxx)で記述する。例えば次のようになる:

root@ubuntu# cat default.ubuntu1004xd32e
INCLUDE pxelinux.cfg/labels
DEFAULT ubuntu1004xd32e

雛形ファイルはlabelsファイルを読み込み、デフォルトを指定しているだけである。(この2行の順番は逆でも構わないが、誤ってlabelsファイルの方にDEFAULTの記述があっても、それを上書きするようにDEFAULT行はINCLUDE行の後にしている。)

この例では2つのエントリーしかないので、このように分けるメリットが余り感じられないが、もっと多様なブート設定が増えてきてもlabelsファイルだけを管理すれば良いので管理が楽になる。

私の環境で更に、クライアントのブート時にどのOSをブートするか指定できるようにメニューも出せるようにしているが、その場合は次の様に default.menuという雛形を作っている。

root@ubuntu# ls -l
total 16
lrwxrwxrwx 1 root root  23 2011-02-27 18:44 01-aa-bb-cc-dd-ee-00 -> default.ubuntu1004xd32e
lrwxrwxrwx 1 root root  23 2011-02-27 18:44 01-aa-bb-cc-dd-ee-ff -> default.ubuntu1004xd32e
lrwxrwxrwx 1 root root  12 2011-02-27 19:24 01-ab-cd-ef-12-34-56 -> default.menu
lrwxrwxrwx 1 root root  23 2011-02-27 18:44 01-ff-ee-dd-cc-bb-00 -> default.ubuntu1004xd64e
lrwxrwxrwx 1 root root  23 2011-02-27 18:44 01-ff-ee-dd-cc-bb-aa -> default.ubuntu1004xd64e
-rw-r--r-- 1 root root  45 2011-02-27 19:23 default.menu
-rw-r--r-- 1 root root  53 2011-02-27 19:01 default.ubuntu1004xd32e
-rw-r--r-- 1 root root  53 2011-02-27 19:02 default.ubuntu1004xd64e
-rw-r--r-- 1 root root 580 2011-02-27 19:33 labels

root@ubuntu# cat default.menu
INCLUDE pxelinux.cfg/labels
DEFAULT menu.c32

この様に設定しておくと“ab:cd:ef:12:34:56”というMACアドレスを持ったPCをPXEブートすると、画面に32bit版のUbuntuを起動するのかか64bit版のUbuntuを起動するのかメニューが表示される。その際に、“ubuntu1004xd32e”といった管理用のファイル名ではなく“Ubuntu 10.04 Desktop i386”というメッセージを出力するようにlabelsファイルでメニューラベルも指定しておく。

root@ubuntu# cat labels
LABEL ubuntu1004xd32e
        MENU LABEL Ubuntu 10.04 Desktop i386
        KERNEL  /diskless/root/ubuntu1004xd32e/vmlinuz
        APPEND  initrd=/diskless/root/ubuntu1004xd32e/initrd.img boot=casper nfsroot=192.168.1.1:/diskless/root/ubuntu1004xd32e netboot=nfs quiet --

################################################################################

LABEL ubuntu1004xd64e
        MENU LABEL Ubuntu 10.04 Desktop amd64
        KERNEL  /diskless/root/ubuntu1004xd64e/vmlinuz
        APPEND  initrd=/diskless/root/ubuntu1004xd64e/initrd.img boot=casper nfsroot=192.168.1.1:/diskless/root/ubuntu1004xd64e netboot=nfs quiet --

この様にLABEL記述だけを別ファイルに独立させることで、メニューを出す雛形も作れるし、(メニューを出さずに)特定のOSを即ブートする雛形も作れる。

以下は、実際に私の環境で使っている例である:

root@ubuntu# cat labels
LABEL mt86plus
        MENU LABEL Memory Test
        KERNEL mt86plus

################################################################################

LABEL gpxe
        MENU LABEL gPXE Boot
        KERNEL gpxe.0

################################################################################

LABEL ubuntu08044s32e-vmrc
        MENU LABEL VMware Remote Console
        KERNEL  /diskless/root/ubuntu08044s32e-vmrc/vmlinuz
        APPEND  initrd=/diskless/root/ubuntu08044s32e-vmrc/initrd.img boot=casper nfsroot=192.168.1.1:/diskless/root/ubuntu08044s32e-vmrc netboot=nfs quiet --

################################################################################

LABEL ubuntu1004xd32e
        MENU LABEL Ubuntu 10.04 Desktop i386
        KERNEL  /diskless/root/ubuntu1004xd32e/vmlinuz
        APPEND  initrd=/diskless/root/ubuntu1004xd32e/initrd.img boot=casper nfsroot=192.168.1.1:/diskless/root/ubuntu1004xd32e netboot=nfs quiet --

################################################################################

LABEL ubuntu1004xd64e
        MENU LABEL Ubuntu 10.04 Desktop amd64
        KERNEL  /diskless/root/ubuntu1004xd64e/vmlinuz
        APPEND  initrd=/diskless/root/ubuntu1004xd64e/initrd.img boot=casper nfsroot=192.168.1.1:/diskless/root/ubuntu1004xd64e netboot=nfs quiet --

################################################################################

LABEL ubuntu_32_-installer
        MENU LABEL Install Ubuntu i386
        KERNEL ubuntu-installer/i386/boot-screens/vesamenu.c32
        APPEND ubuntu-installer/i386/boot-screens/menu.cfg

################################################################################

LABEL ubuntu_64_-installer
        MENU LABEL Install Ubuntu amd64
        KERNEL ubuntu-installer/amd64/boot-screens/vesamenu.c32
        APPEND ubuntu-installer/amd64/boot-screens/menu.cfg

この様にlabelファイルを記述しておけば、先ほどのdefault.menuの雛形を使ったPCからPXEブートすると次のようなメニュー画面が表示される:

“Memory Test”はOSをブートするのではなくMemory Testプログラムを起動実行する。syslinuxに付属するmt86plus(旧memtest86+)を起動しているだけ。
“gPXE”を選択すると、gPXEを使って再ブートに入りiSCSIでのブートが可能となる。ここで、どのiSCSIディスクを使ってブートするのかメニュー化したかったのだが、現バージョン(1.0.1)のgPXEに対してパラメータを渡すことができないようなので、ここだけはマシン依存になってしまう(詳細はgPXEの設定の所で)。今のところはAndroidの開発環境をブートするのに使っている。
VMware Remote Desktop”はシンクライアントとしてPCを立ち上げて、サーバ上で動いている仮想マシンのリモートコンソールとして使う。捨てられずに置いてある昔のPCのための設定である。
Ubuntu 10.04 Desktop i386”、“Ubuntu 10.04 Desktop amd64”は(iSCSIを使わず)ディスクレス形態でUbuntuをブートする。ちょうどUbuntuのライブCDを起動したのと同じ状態をPXEでネットブートする形になる。この設定があると普段はWindowsを動かしているPCでも気軽にUbuntuを起動することができ、マシンの保守などのために利用する。Windowsマシンのバックアップ取る場合はLinuxをブートしてHDD(もしくはシステム・パーティション)を丸ごとイメージとしてバックアップするのに使う。また、HDDからブートできない!とかいう場合にも使う。
“Install Ubuntu i386”、“Install Ubuntu amd64”はUbuntuのインストールに使う。この様に設定しておけば、いちいちインストール用のDVDを焼かずにBIOSからPXEブートを選ぶだけでUbuntuのインストールが可能となる(ただGUI画面ではくCUI画面でのインストールになるが)。

z4rootをインストールしてしまった

ついに禁断のアプリをIS04に入れてしまった。z4root。
ただ、私的にはrootになることよりも、z4rootがどの様に動いているのか知りたかった。で、z4rootがおまけでインストールしてくれるbusyboxを使ってほぼ標準のLinuxコマンドが使えるようになったので、色々と見てみた。

(ソースを見ているわけではないので、勿論憶測だが)どうもz4rootのtemporary rootというのは、/system/binの内容をext2イメージのファイル(/data/data/com.z4mod.z4root/files/temproot.ext)にコピー(バックアップ)して、そこにsuとbusyoxを追加、そしてそのファイルを/system/binへloopマウントしているようだ。私はpermanent rootは実行していないので、更に推測になるがpermanentでは/system/binの内容をバックアップせずに、直接/system/binにsuやbusyboxを追加するのではないか?と思う。多分、temporary rootであればルート化の痕跡を最小限の抑えることが出来るように作られているのではないだろうか? IS04の場合はAndroid 2.2へのバージョンアップが控えているので、あまりファイルシステムをいじくって、ファームアップ時にトラブルになりたくはない。そういった意味でtemporary rootはありがたいかも。(ただ、あまりrootであちこちいじると収集が付かなくなってしまうが。)

ちなみに、z4root(1.0.3)がインストールするbusyboxのバージョンはv1.17.2で、入っているのは次のコマンド:

Currently defined functions:
	[, [[, acpid, addgroup, adduser, adjtimex, arp, arping, ash, awk,
	basename, beep, blkid, bootchartd, brctl, bunzip2, bzcat, bzip2, cal,
	cat, catv, chat, chattr, chgrp, chmod, chown, chpasswd, chpst, chroot,
	chrt, chvt, cksum, clear, cmp, comm, cp, cpio, crond, crontab, cryptpw,
	cttyhack, cut, date, dc, dd, deallocvt, delgroup, deluser, depmod,
	devmem, df, dhcprelay, diff, dirname, dmesg, dnsd, dnsdomainname,
	dos2unix, du, dumpkmap, dumpleases, echo, ed, egrep, eject, env,
	envdir, envuidgid, ether-wake, expand, expr, fakeidentd, false, fbset,
	fbsplash, fdflush, fdformat, fdisk, fgconsole, fgrep, find, findfs,
	flock, fold, free, freeramdisk, fsck, fsck.minix, fsync, ftpd, ftpget,
	ftpput, fuser, getopt, getty, grep, gunzip, gzip, halt, hd, hdparm,
	head, hexdump, hostid, hostname, httpd, hush, hwclock, id, ifconfig,
	ifdown, ifenslave, ifplugd, ifup, inetd, init, insmod, install, ionice,
	ip, ipaddr, ipcalc, ipcrm, ipcs, iplink, iproute, iprule, iptunnel,
	kbd_mode, kill, killall, killall5, klogd, last, length, less, linux32,
	linux64, linuxrc, ln, loadfont, loadkmap, logger, login, logname,
	logread, losetup, lpd, lpq, lpr, ls, lsattr, lsmod, lspci, lsusb,
	lzcat, lzma, lzop, lzopcat, makedevs, makemime, man, md5sum, mdev,
	mesg, microcom, mkdir, mkdosfs, mke2fs, mkfifo, mkfs.ext2, mkfs.minix,
	mkfs.vfat, mknod, mkpasswd, mkswap, mktemp, modinfo, modprobe, more,
	mount, mountpoint, mt, mv, nameif, nc, netstat, nice, nmeter, nohup,
	nslookup, ntpd, od, openvt, passwd, patch, pgrep, pidof, ping, ping6,
	pipe_progress, pivot_root, pkill, popmaildir, poweroff, printenv,
	printf, ps, pscan, pwd, raidautorun, rdate, rdev, readahead, readlink,
	readprofile, realpath, reboot, reformime, renice, reset, resize, rev,
	rm, rmdir, rmmod, route, rpm, rpm2cpio, rtcwake, run-parts, runlevel,
	runsv, runsvdir, rx, script, scriptreplay, sed, sendmail, seq, setarch,
	setconsole, setfont, setkeycodes, setlogcons, setsid, setuidgid, sh,
	sha1sum, sha256sum, sha512sum, showkey, slattach, sleep, smemcap,
	softlimit, sort, split, start-stop-daemon, stat, strings, stty, su,
	sulogin, sum, sv, svlogd, swapoff, swapon, switch_root, sync, sysctl,
	syslogd, tac, tail, tar, tcpsvd, tee, telnet, telnetd, test, tftp,
	tftpd, time, timeout, top, touch, tr, traceroute, traceroute6, true,
	tty, ttysize, tunctl, udhcpc, udhcpd, udpsvd, umount, uname, unexpand,
	uniq, unix2dos, unlzma, unlzop, unxz, unzip, uptime, usleep, uudecode,
	uuencode, vconfig, vi, vlock, volname, wall, watch, watchdog, wc, wget,
	which, who, whoami, xargs, xz, xzcat, yes, zcat, zcip

これだけあれば、大抵のことは出来る。Linuxの標準コマンドと完全互換とはいかないが、基本機能は押えてくれているのでLinux愛好家としては嬉しい限りだ。色々とシェルスクリプトも組めるし。(ちなみに、Linuxbusyboxについては“3種類のbusyboxは何が違うのか?”にメモってある。随分昔のメモで恐縮だが。)

【追記:2011/03/09】
このbusyboxに入っているコマンドを見ているとtelnetdが入っている。と、いうことはTelnetサーバにできるということ。詳しくは“z4rootで携帯がtelnetサーバにもなる”にメモした。

busyboxに入っているshはB shellライクでTABによるファイル名補完もできるので助かる。最初に

# busybox sh

を実行しておけば、busybox内のshが使える。

busyboxは本来シンボリックリンクして使うのが王道だが、/systemの下をいじくるのは避けたい。/sdcardの下に lbin とか言うディレクトリを作って、そこにシンボリックリンクを集約できればいいのだけど、そうもいかない。そこで、z4rootを見習って次のような方法でシンボリックリンクを作ってみた。これを入れておけば標準的なLinuxとほぼ同じ感覚で使えるようになる。

まず、Linuxマシンを使ってrootで次のコマンドを実行する(/tmpなどの作業用ディレクトリで)。

#! /bin/sh
dd if=/dev/zero of=lbin.ext bs=1M count=3
mkfs.ext2 -F lbin.ext
tune2fs -c 0 -i 0 lbin.ext
mkdir ./mnt
mount -o loop lbin.ext ./mnt
ln -s /system/bin/busybox "./mnt/["
ln -s /system/bin/busybox "./mnt/[["
ln -s /system/bin/busybox ./mnt/acpid
ln -s /system/bin/busybox ./mnt/addgroup
ln -s /system/bin/busybox ./mnt/adduser
ln -s /system/bin/busybox ./mnt/adjtimex
ln -s /system/bin/busybox ./mnt/arp
ln -s /system/bin/busybox ./mnt/arping
ln -s /system/bin/busybox ./mnt/ash
ln -s /system/bin/busybox ./mnt/awk
ln -s /system/bin/busybox ./mnt/basename
ln -s /system/bin/busybox ./mnt/beep
ln -s /system/bin/busybox ./mnt/blkid
ln -s /system/bin/busybox ./mnt/bootchartd
ln -s /system/bin/busybox ./mnt/brctl
ln -s /system/bin/busybox ./mnt/bunzip2
ln -s /system/bin/busybox ./mnt/bzcat
ln -s /system/bin/busybox ./mnt/bzip2
ln -s /system/bin/busybox ./mnt/cal
ln -s /system/bin/busybox ./mnt/cat
ln -s /system/bin/busybox ./mnt/catv
ln -s /system/bin/busybox ./mnt/chat
ln -s /system/bin/busybox ./mnt/chattr
ln -s /system/bin/busybox ./mnt/chgrp
ln -s /system/bin/busybox ./mnt/chmod
ln -s /system/bin/busybox ./mnt/chown
ln -s /system/bin/busybox ./mnt/chpasswd
ln -s /system/bin/busybox ./mnt/chpst
ln -s /system/bin/busybox ./mnt/chroot
ln -s /system/bin/busybox ./mnt/chrt
ln -s /system/bin/busybox ./mnt/chvt
ln -s /system/bin/busybox ./mnt/cksum
ln -s /system/bin/busybox ./mnt/clear
ln -s /system/bin/busybox ./mnt/cmp
ln -s /system/bin/busybox ./mnt/comm
ln -s /system/bin/busybox ./mnt/cp
ln -s /system/bin/busybox ./mnt/cpio
ln -s /system/bin/busybox ./mnt/crond
ln -s /system/bin/busybox ./mnt/crontab
ln -s /system/bin/busybox ./mnt/cryptpw
ln -s /system/bin/busybox ./mnt/cttyhack
ln -s /system/bin/busybox ./mnt/cut
ln -s /system/bin/busybox ./mnt/date
ln -s /system/bin/busybox ./mnt/dc
ln -s /system/bin/busybox ./mnt/dd
ln -s /system/bin/busybox ./mnt/deallocvt
ln -s /system/bin/busybox ./mnt/delgroup
ln -s /system/bin/busybox ./mnt/deluser
ln -s /system/bin/busybox ./mnt/depmod
ln -s /system/bin/busybox ./mnt/devmem
ln -s /system/bin/busybox ./mnt/df
ln -s /system/bin/busybox ./mnt/dhcprelay
ln -s /system/bin/busybox ./mnt/diff
ln -s /system/bin/busybox ./mnt/dirname
ln -s /system/bin/busybox ./mnt/dmesg
ln -s /system/bin/busybox ./mnt/dnsd
ln -s /system/bin/busybox ./mnt/dnsdomainname
ln -s /system/bin/busybox ./mnt/dos2unix
ln -s /system/bin/busybox ./mnt/du
ln -s /system/bin/busybox ./mnt/dumpkmap
ln -s /system/bin/busybox ./mnt/dumpleases
ln -s /system/bin/busybox ./mnt/echo
ln -s /system/bin/busybox ./mnt/ed
ln -s /system/bin/busybox ./mnt/egrep
ln -s /system/bin/busybox ./mnt/eject
ln -s /system/bin/busybox ./mnt/env
ln -s /system/bin/busybox ./mnt/envuidgid
ln -s /system/bin/busybox ./mnt/ether-wake
ln -s /system/bin/busybox ./mnt/expand
ln -s /system/bin/busybox ./mnt/expr
ln -s /system/bin/busybox ./mnt/fakeidentd
ln -s /system/bin/busybox ./mnt/false
ln -s /system/bin/busybox ./mnt/fbset
ln -s /system/bin/busybox ./mnt/fbsplash
ln -s /system/bin/busybox ./mnt/fdflush
ln -s /system/bin/busybox ./mnt/fdformat
ln -s /system/bin/busybox ./mnt/fdisk
ln -s /system/bin/busybox ./mnt/fgconsole
ln -s /system/bin/busybox ./mnt/fgrep
ln -s /system/bin/busybox ./mnt/find
ln -s /system/bin/busybox ./mnt/findfs
ln -s /system/bin/busybox ./mnt/flock
ln -s /system/bin/busybox ./mnt/fold
ln -s /system/bin/busybox ./mnt/free
ln -s /system/bin/busybox ./mnt/freeramdisk
ln -s /system/bin/busybox ./mnt/fsck
ln -s /system/bin/busybox ./mnt/fsck.minix
ln -s /system/bin/busybox ./mnt/fsync
ln -s /system/bin/busybox ./mnt/ftpd
ln -s /system/bin/busybox ./mnt/ftpget
ln -s /system/bin/busybox ./mnt/ftpput
ln -s /system/bin/busybox ./mnt/fuser
ln -s /system/bin/busybox ./mnt/getopt
ln -s /system/bin/busybox ./mnt/getty
ln -s /system/bin/busybox ./mnt/grep
ln -s /system/bin/busybox ./mnt/gunzip
ln -s /system/bin/busybox ./mnt/gzip
ln -s /system/bin/busybox ./mnt/halt
ln -s /system/bin/busybox ./mnt/hd
ln -s /system/bin/busybox ./mnt/hdparm
ln -s /system/bin/busybox ./mnt/head
ln -s /system/bin/busybox ./mnt/hexdump
ln -s /system/bin/busybox ./mnt/hostid
ln -s /system/bin/busybox ./mnt/hostname
ln -s /system/bin/busybox ./mnt/httpd
ln -s /system/bin/busybox ./mnt/hush
ln -s /system/bin/busybox ./mnt/hwclock
ln -s /system/bin/busybox ./mnt/id
ln -s /system/bin/busybox ./mnt/ifconfig
ln -s /system/bin/busybox ./mnt/ifdown
ln -s /system/bin/busybox ./mnt/ifenslave
ln -s /system/bin/busybox ./mnt/ifplugd
ln -s /system/bin/busybox ./mnt/ifup
ln -s /system/bin/busybox ./mnt/inetd
ln -s /system/bin/busybox ./mnt/init
ln -s /system/bin/busybox ./mnt/insmod
ln -s /system/bin/busybox ./mnt/install
ln -s /system/bin/busybox ./mnt/ionice
ln -s /system/bin/busybox ./mnt/ip
ln -s /system/bin/busybox ./mnt/ipaddr
ln -s /system/bin/busybox ./mnt/ipcalc
ln -s /system/bin/busybox ./mnt/ipcrm
ln -s /system/bin/busybox ./mnt/ipcs
ln -s /system/bin/busybox ./mnt/iplink
ln -s /system/bin/busybox ./mnt/iproute
ln -s /system/bin/busybox ./mnt/iprule
ln -s /system/bin/busybox ./mnt/iptunnel
ln -s /system/bin/busybox ./mnt/kbd_mode
ln -s /system/bin/busybox ./mnt/kill
ln -s /system/bin/busybox ./mnt/killall
ln -s /system/bin/busybox ./mnt/killall5
ln -s /system/bin/busybox ./mnt/klogd
ln -s /system/bin/busybox ./mnt/last
ln -s /system/bin/busybox ./mnt/length
ln -s /system/bin/busybox ./mnt/less
ln -s /system/bin/busybox ./mnt/linux32
ln -s /system/bin/busybox ./mnt/linux64
ln -s /system/bin/busybox ./mnt/linuxrc
ln -s /system/bin/busybox ./mnt/ln
ln -s /system/bin/busybox ./mnt/loadfont
ln -s /system/bin/busybox ./mnt/loadkmap
ln -s /system/bin/busybox ./mnt/logger
ln -s /system/bin/busybox ./mnt/login
ln -s /system/bin/busybox ./mnt/logname
ln -s /system/bin/busybox ./mnt/logread
ln -s /system/bin/busybox ./mnt/losetup
ln -s /system/bin/busybox ./mnt/lpd
ln -s /system/bin/busybox ./mnt/lpq
ln -s /system/bin/busybox ./mnt/lpr
ln -s /system/bin/busybox ./mnt/ls
ln -s /system/bin/busybox ./mnt/lsattr
ln -s /system/bin/busybox ./mnt/lsmod
ln -s /system/bin/busybox ./mnt/lspci
ln -s /system/bin/busybox ./mnt/lsusb
ln -s /system/bin/busybox ./mnt/lzcat
ln -s /system/bin/busybox ./mnt/lzma
ln -s /system/bin/busybox ./mnt/lzop
ln -s /system/bin/busybox ./mnt/lzopcat
ln -s /system/bin/busybox ./mnt/makedevs
ln -s /system/bin/busybox ./mnt/makemime
ln -s /system/bin/busybox ./mnt/man
ln -s /system/bin/busybox ./mnt/md5sum
ln -s /system/bin/busybox ./mnt/mdev
ln -s /system/bin/busybox ./mnt/mesg
ln -s /system/bin/busybox ./mnt/microcom
ln -s /system/bin/busybox ./mnt/mkdir
ln -s /system/bin/busybox ./mnt/mkdosfs
ln -s /system/bin/busybox ./mnt/mke2fs
ln -s /system/bin/busybox ./mnt/mkfifo
ln -s /system/bin/busybox ./mnt/mkfs.ext2
ln -s /system/bin/busybox ./mnt/mkfs.minix
ln -s /system/bin/busybox ./mnt/mkfs.vfat
ln -s /system/bin/busybox ./mnt/mknod
ln -s /system/bin/busybox ./mnt/mkpasswd
ln -s /system/bin/busybox ./mnt/mkswap
ln -s /system/bin/busybox ./mnt/mktemp
ln -s /system/bin/busybox ./mnt/modinfo
ln -s /system/bin/busybox ./mnt/modprobe
ln -s /system/bin/busybox ./mnt/more
ln -s /system/bin/busybox ./mnt/mount
ln -s /system/bin/busybox ./mnt/mountpoint
ln -s /system/bin/busybox ./mnt/mt
ln -s /system/bin/busybox ./mnt/mv
ln -s /system/bin/busybox ./mnt/nameif
ln -s /system/bin/busybox ./mnt/nc
ln -s /system/bin/busybox ./mnt/netstat
ln -s /system/bin/busybox ./mnt/nice
ln -s /system/bin/busybox ./mnt/nmeter
ln -s /system/bin/busybox ./mnt/nohup
ln -s /system/bin/busybox ./mnt/nslookup
ln -s /system/bin/busybox ./mnt/ntpd
ln -s /system/bin/busybox ./mnt/od
ln -s /system/bin/busybox ./mnt/openvt
ln -s /system/bin/busybox ./mnt/passwd
ln -s /system/bin/busybox ./mnt/patch
ln -s /system/bin/busybox ./mnt/pgrep
ln -s /system/bin/busybox ./mnt/pidof
ln -s /system/bin/busybox ./mnt/ping
ln -s /system/bin/busybox ./mnt/ping6
ln -s /system/bin/busybox ./mnt/pipe_progress
ln -s /system/bin/busybox ./mnt/pivot_root
ln -s /system/bin/busybox ./mnt/pkill
ln -s /system/bin/busybox ./mnt/popmaildir
ln -s /system/bin/busybox ./mnt/poweroff
ln -s /system/bin/busybox ./mnt/printenv
ln -s /system/bin/busybox ./mnt/printf
ln -s /system/bin/busybox ./mnt/ps
ln -s /system/bin/busybox ./mnt/pscan
ln -s /system/bin/busybox ./mnt/pwd
ln -s /system/bin/busybox ./mnt/raidautorun
ln -s /system/bin/busybox ./mnt/rdate
ln -s /system/bin/busybox ./mnt/rdev
ln -s /system/bin/busybox ./mnt/readahead
ln -s /system/bin/busybox ./mnt/readlink
ln -s /system/bin/busybox ./mnt/readprofile
ln -s /system/bin/busybox ./mnt/realpath
ln -s /system/bin/busybox ./mnt/reboot
ln -s /system/bin/busybox ./mnt/reformime
ln -s /system/bin/busybox ./mnt/renice
ln -s /system/bin/busybox ./mnt/reset
ln -s /system/bin/busybox ./mnt/resize
ln -s /system/bin/busybox ./mnt/rev
ln -s /system/bin/busybox ./mnt/rm
ln -s /system/bin/busybox ./mnt/rmdir
ln -s /system/bin/busybox ./mnt/rmmod
ln -s /system/bin/busybox ./mnt/route
ln -s /system/bin/busybox ./mnt/rpm
ln -s /system/bin/busybox ./mnt/rpm2cpio
ln -s /system/bin/busybox ./mnt/rtcwake
ln -s /system/bin/busybox ./mnt/run-parts
ln -s /system/bin/busybox ./mnt/runlevel
ln -s /system/bin/busybox ./mnt/runsv
ln -s /system/bin/busybox ./mnt/runsvdir
ln -s /system/bin/busybox ./mnt/rx
ln -s /system/bin/busybox ./mnt/script
ln -s /system/bin/busybox ./mnt/scriptreplay
ln -s /system/bin/busybox ./mnt/sed
ln -s /system/bin/busybox ./mnt/sendmail
ln -s /system/bin/busybox ./mnt/seq
ln -s /system/bin/busybox ./mnt/setarch
ln -s /system/bin/busybox ./mnt/setconsole
ln -s /system/bin/busybox ./mnt/setfont
ln -s /system/bin/busybox ./mnt/setkeycodes
ln -s /system/bin/busybox ./mnt/setlogcons
ln -s /system/bin/busybox ./mnt/setsid
ln -s /system/bin/busybox ./mnt/setuidgid
ln -s /system/bin/busybox ./mnt/sh
ln -s /system/bin/busybox ./mnt/sha1sum
ln -s /system/bin/busybox ./mnt/sha256sum
ln -s /system/bin/busybox ./mnt/sha512sum
ln -s /system/bin/busybox ./mnt/showkey
ln -s /system/bin/busybox ./mnt/slattach
ln -s /system/bin/busybox ./mnt/sleep
ln -s /system/bin/busybox ./mnt/smemcap
ln -s /system/bin/busybox ./mnt/softlimit
ln -s /system/bin/busybox ./mnt/sort
ln -s /system/bin/busybox ./mnt/split
ln -s /system/bin/busybox ./mnt/start-stop-daemon
ln -s /system/bin/busybox ./mnt/stat
ln -s /system/bin/busybox ./mnt/strings
ln -s /system/bin/busybox ./mnt/stty
ln -s /system/bin/busybox ./mnt/su
ln -s /system/bin/busybox ./mnt/sulogin
ln -s /system/bin/busybox ./mnt/sum
ln -s /system/bin/busybox ./mnt/sv
ln -s /system/bin/busybox ./mnt/svlogd
ln -s /system/bin/busybox ./mnt/swapoff
ln -s /system/bin/busybox ./mnt/swapon
ln -s /system/bin/busybox ./mnt/switch_root
ln -s /system/bin/busybox ./mnt/sync
ln -s /system/bin/busybox ./mnt/sysctl
ln -s /system/bin/busybox ./mnt/syslogd
ln -s /system/bin/busybox ./mnt/tac
ln -s /system/bin/busybox ./mnt/tail
ln -s /system/bin/busybox ./mnt/tar
ln -s /system/bin/busybox ./mnt/tcpsvd
ln -s /system/bin/busybox ./mnt/tee
ln -s /system/bin/busybox ./mnt/telnet
ln -s /system/bin/busybox ./mnt/telnetd
ln -s /system/bin/busybox ./mnt/test
ln -s /system/bin/busybox ./mnt/tftp
ln -s /system/bin/busybox ./mnt/tftpd
ln -s /system/bin/busybox ./mnt/time
ln -s /system/bin/busybox ./mnt/timeout
ln -s /system/bin/busybox ./mnt/top
ln -s /system/bin/busybox ./mnt/touch
ln -s /system/bin/busybox ./mnt/tr
ln -s /system/bin/busybox ./mnt/traceroute
ln -s /system/bin/busybox ./mnt/traceroute6
ln -s /system/bin/busybox ./mnt/true
ln -s /system/bin/busybox ./mnt/tty
ln -s /system/bin/busybox ./mnt/ttysize
ln -s /system/bin/busybox ./mnt/tunctl
ln -s /system/bin/busybox ./mnt/udhcpc
ln -s /system/bin/busybox ./mnt/udhcpd
ln -s /system/bin/busybox ./mnt/udpsvd
ln -s /system/bin/busybox ./mnt/umount
ln -s /system/bin/busybox ./mnt/uname
ln -s /system/bin/busybox ./mnt/unexpand
ln -s /system/bin/busybox ./mnt/uniq
ln -s /system/bin/busybox ./mnt/unix2dos
ln -s /system/bin/busybox ./mnt/unlzma
ln -s /system/bin/busybox ./mnt/unlzop
ln -s /system/bin/busybox ./mnt/unxz
ln -s /system/bin/busybox ./mnt/unzip
ln -s /system/bin/busybox ./mnt/uptime
ln -s /system/bin/busybox ./mnt/usleep
ln -s /system/bin/busybox ./mnt/uudecode
ln -s /system/bin/busybox ./mnt/uuencode
ln -s /system/bin/busybox ./mnt/vconfig
ln -s /system/bin/busybox ./mnt/vi
ln -s /system/bin/busybox ./mnt/vlock
ln -s /system/bin/busybox ./mnt/volname
ln -s /system/bin/busybox ./mnt/wall
ln -s /system/bin/busybox ./mnt/watch
ln -s /system/bin/busybox ./mnt/watchdog
ln -s /system/bin/busybox ./mnt/wc
ln -s /system/bin/busybox ./mnt/wget
ln -s /system/bin/busybox ./mnt/which
ln -s /system/bin/busybox ./mnt/who
ln -s /system/bin/busybox ./mnt/whoami
ln -s /system/bin/busybox ./mnt/xargs
ln -s /system/bin/busybox ./mnt/xz
ln -s /system/bin/busybox ./mnt/xzcat
ln -s /system/bin/busybox ./mnt/yes
ln -s /system/bin/busybox ./mnt/zcat
ln -s /system/bin/busybox ./mnt/zcip
cat > ./mnt/.shrc << EOF
export PATH=/sdcard/lbin:\$PATH
EOF
umount ./mnt
rmdir ./mnt

次に今作ったlbin.extというファイルをAndroid端末にコピーする。

adb push lbin.ext /sdcard

そして、Android端末に入って、

adb shell
su -
mkdir /sdcard/lbin
busybox sh
busybox mount -o ro,loop /sdcard/lbin.ext /sdcard/lbin
.  /sdcard/lbin/.shrc

(最後の行はピリオッドの後に空白を開けて。)
adb shellで端末に入った時に suの後にmountと“.”を実行すれば、イチイチ busyboxと入力しなくても直接コマンドを実行できる。

/ # ls -a
.                       etc                     proc
..                      init                    root
cache                   init.goldfish.rc        sbin
config                  init.qcom.post_boot.sh  sdcard
d                       init.qcom.rc            sphinx_tmp
data                    init.qcom.sh            sqlite_stmt_journals
default.prop            init.rc                 sys
dev                     persist                 system
/ # 

となる。ただし、busybox内蔵のコマンドがAndroidのコマンドより優先になってしまうので、思わぬトラブルが発生する可能性があるので注意が必要だ。

しかし、
root権限取得後のz4rootの環境設定はなんとなく見えたが、それ以前にどうやってroot権限を取得しているのだろうか? しばらく遊べそうだ。