boot2docker で Docker の使用するポートが CrashPlan と競合するときの対処法

OS X で Docker を使えるようになったとのことだったのですが、私の環境でも下記の記事と同じように CrashPlan がインストールされていたのでポートが競合してしまい、boot2docker init がエラーになってしまいました。

$ boot2docker init
[2014-02-15 15:35:15] DOCKER_PORT=4243 on localhost is used by an other process! Change the port to a free port.

OS XでDockerをインストール(by boot2docker)時に競合するCrashPlanのポートを4243から変更する方法 - akiyan.com

この記事では CrashPlan の使用する方のポート番号を変更していましたが、私は Docker のほうが使用するポート番号を変えてみました。

やり方は以下のとおり。

$ mkdir -p ~/.boot2docker
$ echo "DOCKER_PORT=42430" >> ~/.boot2docker/profile

今回はデフォルトの 4243 から 42430 に変更しましたが、基本的には ~/.boot2docker/profile というファイルに DOCKER_PORT=xxxx という行を書くだけです。

boot2docker init コマンド実行時のエラーメッセージでこのことを説明するような Pull Request が取り込まれていたので、そのうち親切なエラーメッセージが表示されるようになるでしょう。

RSA 秘密鍵/公開鍵ファイルのフォーマット

openssl コマンドで生成される RSA 秘密鍵ファイルのフォーマットの中身が気になったので調べてみた。
初心者にわかりやすく説明されたサイトが意外と見当たらなかったようなのでまとめておく。

まず、鍵の生成に使ったコマンドはこんな感じ:

$ openssl genrsa 2048 > rsaprivate.key

2048 というのは鍵の bit 数。

以下の説明では、あまり長い鍵だとわかりにくくなっちゃうので短くして 256 bit の鍵にしてみた。
よい子のみんなはこんな短い鍵は使っちゃダメだよ。


256 bit の秘密鍵ファイルをダンプしてみるとこんな感じ:

$ cat rsaprivate.key
-----BEGIN RSA PRIVATE KEY-----
MIGrAgEAAiEAvnrd8LBnzAGxCW+i7KtVQSiTsssMtbwcs5styeKsn2kCAwEAAQIh
AKBF8glb5Xqa0cQG0ygg4hIFdipmvEJhiCuhX93krDCBAhEA51bAM0gFPvxyk9Xe
ioIOBQIRANLJEv4Xw7MwT7EEEARL5RUCEBa8bu1bUbCsDPK8nT+NoqUCEQCIzFCU
MY4j7BW8N3vBnhPlAhBgs4tSfe6RbpertixmCygk
-----END RSA PRIVATE KEY-----

秘密鍵の中身は本当はこんな公の場に晒しちゃいけないけど、この鍵は単に説明用に生成しただけで、実際には何にも使わないから心配しないでね。

現時点で主流の 2048 bit だともっと長くなるよ。

このファイルのフォーマットは PEM 形式といって、固定のヘッダ・フッタの間に BASE64エンコードされたデータが入っている。

こんなイメージ:

-----BEGIN RSA PRIVATE KEY-----
BASE64 ENCODED DATA
-----END RSA PRIVATE KEY-----


BASE64 をデコードして、元のデータを取り出してみよう。

$ cat rsaprivate.key | awk /^[^-]/{print} | base64 -d

awk でヘッダとフッタを取り除いたあとにデコードをしているよ。

なにやら文字化けしたようなデータが表示されてしまったかな?
この、デコードして得られた元のデータは、秘密鍵の情報を DER (Distinguished Encoding Rule) という形式でエンコードしたバイナリになっているらしい。

その DER のデータを読み解くと、秘密鍵の情報が得られるんだけど、その内容は ASN.1 という規則に則って以下のような Syntax だと定められているよ。

RSAPrivateKey ::= SEQUENCE {
    version           Version,
    modulus           INTEGER, -- n
    publicExponent    INTEGER, -- e
    privateExponent   INTEGER, -- d
    prime1            INTEGER, -- p
    prime2            INTEGER, -- q
    exponent1         INTEGER, -- d mod (p-1)
    exponent2         INTEGER, -- d mod (q-1)
    coefficient       INTEGER, -- (inverse of q) mod p
    otherPrimeInfos   OtherPrimeInfos OPTIONAL
}

参考(1): PKCS#1
参考(2): ITU-T X.690 PKCS#1

ここで、version は INTEGER 型なんだけど、取りうる値の範囲が 0 か 1 しかなくて、1 だと otherPrimeInfos があるけど 0 だと存在しないよ。


それじゃ、さっきデコードしたデータをとりあえず16進ダンプしてみよう。

$ xxd <(cat rsaprivate.key | awk /^[^-]/{print} | base64 -d)
0000000: 3081 ab02 0100 0221 00be 7add f0b0 67cc  0......!..z...g.
0000010: 01b1 096f a2ec ab55 4128 93b2 cb0c b5bc  ...o...UA(......
0000020: 1cb3 9b2d c9e2 ac9f 6902 0301 0001 0221  ...-....i......!
0000030: 00a0 45f2 095b e57a 9ad1 c406 d328 20e2  ..E..[.z.....( .
0000040: 1205 762a 66bc 4261 882b a15f dde4 ac30  ..v*f.Ba.+._...0
0000050: 8102 1100 e756 c033 4805 3efc 7293 d5de  .....V.3H.>.r...
0000060: 8a82 0e05 0211 00d2 c912 fe17 c3b3 304f  ..............0O
0000070: b104 1004 4be5 1502 1016 bc6e ed5b 51b0  ....K......n.[Q.
0000080: ac0c f2bc 9d3f 8da2 a502 1100 88cc 5094  .....?........P.
0000090: 318e 23ec 15bc 377b c19e 13e5 0210 60b3  1.#...7{......`.
00000a0: 8b52 7dee 916e 97ab b62c 660b 2824       .R}..n...,f.($


さっきも言ったけどこのバイナリデータは DER というフォーマットになっている。
DER フォーマットは、ASN.1 というツリー構造のデータをバイナリに変換する(シリアライズする)ときに使われるフォーマットの一つで、同じデータから複数の表現が出てこないようになっているらしい。

例えば整数の表現は DER では可変長なんだけど、1 という数(データ)を表現するときには可変長なので 0x01 とも表現できるし 0x00000001 とも表現できるはずなんだけども、DER ではオクテット(バイト)単位で一番短くなる 0x01 しか認めていないんだ。

秘密鍵のバイナリデータが違うから違う鍵だと思っていたら実は同じ鍵だった!なんてことがあったら悪い人に悪用されて困ったことになりそうだから、きっとそうならないようにしているのかな。


DER フォーマットは基本的
ID(可変長)、コンテンツの長さ(可変長)、コンテンツ
という、いわゆる TLV の繰り返し・入れ子の構造になっているよ。

ID は本当は可変長なんだけど、RSA 秘密鍵のファイルの場合は 1 バイト固定だと思って構わないよ。

ID の 1 バイトめは、さらにビットごとに以下のようにわかれている。

bit 7 6 5 4 3 2 1 0
クラス プリミティブ型か複合型か タグ

ここでタグの値が 31(5 bit 全部 1)なら後続のオクテットがあって可変長になるんだけど、RSA 秘密鍵ではここが 31 になることはないよ。

クラスというのは、以下の表のようになっていて、タグが公式のものかはたまたプライベートなものか、というようなことを表しているよ。
RSA 秘密鍵では Universal しか出てこなくて、タグは全部公式な規格で定められたものしか使われていないよ。

bit 7 bit 6 意味
0 0 Universal
0 1 Application 固有
1 0 Context 固有
1 1 Private

bit 5 は、コンテンツの型がプリミティブ型なのか複合型なのかを表していて、0 だとプリミティブ型、1 だと複合型になる。
複合型というのは、プリミティブや他の複合型を組み合わせて作られる型で、C 言語でいう構造体とか配列みたいなものだと思っておけば OK。

というわけで、最初に ID の 1 バイトを読むと、そのコンテンツがどんな型のデータなのかがわかる。

さっきの例だと先頭の1バイトは 0x30 になっているね。

bit 7 bit 6 bit 5 bit 4 3 2 1 0
0 0 1 1 0 0 0 0

こうだね。

bit 5 が 1 になっているのでこれは複合型。
タグが 0x10 なので、コンテンツは SEQUENCE 型という複合型になっていることがわかる。
(タグの値と型の対応は ITU-T Rec. X.680 のセクション 8.4 にある Table 1 - Universal class tag assignments に定められているよ。)


SEQUENCE は、コンテンツの中に TLV がまた現れて、その出現順も決められているときに使われる複合型だよ。
秘密鍵の場合は n とか e とか p とか q とかの記録されている順番が大事だから SEQUENCE になっているんだね。


さて、つぎはその SEQUENCE の長さを見てみよう。
「長さフィールド」の長さ自体も可変長なんだけど、これは最初の1バイトを読んでみれば全体で何バイト読み取ればよいのかがわかるよ。

さっきの例だと 0x30 の次は 0x81 になっているね。

0x81

bit 7 6 5 4 3 2 1 0
1 0 0 0 0 0 0 1

0x81 は最上位ビット(bit 7)が立っているので、長さフィールドは1バイトに収まっていないことを意味する。逆に最上位ビットが立っていない場合はその1バイト自体がコンテンツの長さになるよ。
最上位ビット以外のビット(bit 6〜0)を見ると、0x01 になっている。

これは続く 1 バイトで長さを表しているということになる。

なので次の1バイトを読む。
0xab だね。

つまり、この SEQUENCE 型のコンテンツは 0xab(= 171 バイト)だっていうこと。
ちなみに 0xab の次のバイトから 171 バイト読み進めると、EOF に到達するね。
つまりこのデータにはこの SEQUENCE 型しか入っていないことになる。

コンテンツの解読を進めていこう。

SEQUENCE 型のコンテンツは、TLV が再び繰り返し入っていると説明したね。
でも各 TLV は可変長なので、何個の TLV が入っているかはよくわからない。
RSA 秘密鍵の ASN.1 の定義からは、少なくとも 9 個の INTEGER 型のデータが入っているはずだけどね。

じゃあ早速最初のデータの TLV を見てみよう。

0xab の次のバイトは 0x02 になっているね。
この ID は、Universal クラス、Primitive 型で INTEGER 型のタグを持っている。

つまり、SQEUQNCE の中に入っている最初の TLV は INTEGER 型のデータだってこと。

長さを見てみよう。
まずは1バイト読み取る。0x01 だね。最上位ビットが立っていないので、この 0x01 という値そのものがコンテンツの長さを表している。
つまりこの INTEGER 型は 1 バイトのデータだということがわかる。

じゃあ次の 1 バイトのコンテンツを読み取ろう。0x00 だね。この INTEGER 型の値は 0 ということだ。

RSA 秘密鍵の ASN.1 による定義を見てみると、これは version = 0 ということに相当するね。

次の TLV を見てみよう。
つぎの ID も 0x02 だ。これまた INTEGER 型。
長さは 0x21 つまり 33 バイト。

00 be 7a dd f0 b0 67 cc 01 b1 09 6f a2 ec ab 55
41 28 93 b2 cb 0c b5 bc 1c b3 9b 2d c9 e2 ac 9f
69

33バイトの整数って、ピンと来ないかもしれないけど、いわゆる多倍長整数というやつだね。
256 bit の鍵なので、32バイトで十分なんだけど、最上位ビットが立ってしまうのを防ぐために最上位に 0 のバイトをくっつけているので 33 バイトになってしまうんだね。

これは RSA 秘密鍵の modulus が 0x00be7addf0b067cc01b1096fa2ecab55412893b2cb0cb5bc1cb39b2dc9e2ac9f69 という多倍長整数だということだね。大きすぎてよくわからないけど、10進数に直すと
86156528347631080411887474184796200056952828735035413778633685555551033663337
という数みたいだよ。

256 bit の鍵でこんな大きな数になるのに、この程度の長さの鍵だとコンピュータの力をもってすれば解くことができてしまうんだね。


さて、33バイト読み取った次のデータは何だろう。
また ID は 0x02 だけど今度は長さは 0x03 だね。3バイトの整数ということだ。
3バイトは 0x01 0x00 0x01 になっているよ。

これは RSA 秘密鍵の e (publicExponent) に相当するね。
0x010001 = 65537 だよ。

同様にして、最後まで読んでいくと
d (privateExponent) = 0x00a045f2095be57a9ad1c406d32820e21205762a66bc4261882ba15fdde4ac3081
p (prime1) = 0x00e756c03348053efc7293d5de8a820e05
q (prime2) = 0x00d2c912fe17c3b3304fb10410044be515
d mod (p-1) (exponent1) = 0x16bc6eed5b51b0ac0cf2bc9d3f8da2a5
d mod (q-1) (exponent2) = 0x0088cc5094318e23ec15bc377bc19e13e5
(inverse of q) mod p (coefficient) = 0x60b38b527dee916e97abb62c660b2824
ということがわかるね。

簡単だったでしょ?



ちなみに、こんな面倒なことをしなくても、

$ openssl asn1parse -inform PEM < rsaprivate.key 
    0:d=0  hl=3 l= 171 cons: SEQUENCE          
    3:d=1  hl=2 l=   1 prim: INTEGER           :00
    6:d=1  hl=2 l=  33 prim: INTEGER           :BE7ADDF0B067CC01B1096FA2ECAB55412893B2CB0CB5BC1CB39B2DC9E2AC9F69
   41:d=1  hl=2 l=   3 prim: INTEGER           :010001
   46:d=1  hl=2 l=  33 prim: INTEGER           :A045F2095BE57A9AD1C406D32820E21205762A66BC4261882BA15FDDE4AC3081
   81:d=1  hl=2 l=  17 prim: INTEGER           :E756C03348053EFC7293D5DE8A820E05
  100:d=1  hl=2 l=  17 prim: INTEGER           :D2C912FE17C3B3304FB10410044BE515
  119:d=1  hl=2 l=  16 prim: INTEGER           :16BC6EED5B51B0AC0CF2BC9D3F8DA2A5
  137:d=1  hl=2 l=  17 prim: INTEGER           :88CC5094318E23EC15BC377BC19E13E5
  156:d=1  hl=2 l=  16 prim: INTEGER           :60B38B527DEE916E97ABB62C660B2824

これで一発だよ。


ちなみに、公開鍵っていうのは秘密鍵から modulus と publicExponent だけを抜き出したものだよ。

だから、ここまで来ることができたあなたは、公開鍵の PEM ファイルも読めるようになったはずだよ。

Ruby をソースからビルドして rbenv で使う方法

まず、Ruby 本体に手を加えてそれをフィードバックする可能性があるなら、GitHub 上で fork してからそれを clone ましょう。そうでなくて単に最新の Ruby を追いかけたい!というような場合は、https://github.com/ruby/ruby.git を clone すればよいでしょう。

clone したら trunk ブランチをチェックアウトします。(GitHub 上でデフォルトのブランチを trunk ブランチにしておくと良いと思います。)

$ git clone git@github.com:<username>/ruby.git ~/ruby 

もしくは

$ git clone https://github.com/ruby/ruby.git ~/ruby

その後、

$ cd ~/ruby
$ git checkout trunk

とします。
チェックアウトしたばかりだと configure ファイルがないので、README に書かれているとおりに autoconf を実行します。

$ autoconf

これで configure が生成されます。

次に、以下の記事に書かれているような方法で、./configure を実行します。
このとき、--prefix オプションで ~/.rbenv の中にインストールされるようにします。
独自ビルドした ruby を rbenv で使う

$ ./configure --prefix=$HOME/.rbenv/versions/fix9367 --enable-shared --enable-debug-env CPPFLAGS='-DRUBY_DEBUG_ENV -DARRAY_DEBUG'

私の場合は Bug#9367 の修正を行いたかったので、インストール先は ~/.rbenv/versions/fix9367 としました。

それ以外のオプションは上記記事と同じにしてあります。

configure が完了したら、make します。

$ make

その後、README に従って make check を行いましょう。

$ make check

なんか私の環境ではエラーが起きてしまいました(汗)

とりあえずインストールしてみましょう。

$ make install

こちらは無事成功したようです。

$ rbenv versions
  system
  
    :

  fix9367

インストールしたバージョンが一覧に現れました。

$ mkdir ~/tmp
$ cd $_
$ rbenv local fix9367

これで ~/tmp 以下にいるときは fix9367 が使われるようになります。

$ cat .ruby-version
fix9367

試しにバージョンを確認してみると:

$ ruby -v
ruby 2.2.0dev (2014-01-05 trunk 44507) [x86_64-linux]

このあたりの表示は clone してきた時の最新の状態になっているようですね。ソースツリーのどこかのファイルを書き換えたりするとこのバージョン表記も変更できるのかもしれません。

gcc などの出力に色をつけるプログラム

コマンドラインgcc などのコンパイラを実行したり複数のファイルを make によってビルドするときなどに、ついついコンパイラからの出力メッセージを目視してしまう私のような情弱は、ある程度規模が大きなプログラムになると警告やエラーメッセージが他の正常な出力に埋もれて見つけにくくなってしまいます。
EmacsVim から直接コマンドを起動して出力をエディタの中でゴニョゴニョしているというスーパーハカーなあなたはこの記事を読まなくてもよいかもしれません)


膨大な出力メッセージがあってもエラーが発生した場合は最終的にビルドが止まりますので気づくことができますが、警告は見逃してしまいがちです。

そこで colorgcc 他、いろいろとコンパイラの出力に色をつける系のプログラムが世の中にはあります。

しかし以下のような理由で、既存のプログラムではなかなか私のような用途には対応しづらそうな感じがしました。

  1. 複数のバージョンのコンパイラやクロスコンパイラを使っていると、colorgcc 他各種ツールのような「コンパイラ置換えアプローチ」は使いづらい
  2. 人から送られてきたビルドログや CI サーバに残っているビルドログをあとから簡単に色付けして見たいけど、それをやってくれるプログラムはなさそう

これらのことを簡単に実現するには、コンパイラの出力をパイプで受け取り色づけして出力するようなフィルタプログラムがあれば良いのではないかと思って探して見ましたがなかなか見つかりません。

仕方が無いので作ってみたのですが、どうしてそういうフィルタプログラムが存在しないのか、作ってみてわかった気がします。

  1. コンパイラ等はたいていエラーメッセージを stderr に出力します。しかしフィルタプログラムが stderr をパイプ経由で渡してもらうにはひと手間必要です(2>&1 のような余計なものをユーザに書いてもらう必要が生じ、普段使いには敷居が高いです)
  2. フィルタプログラム側からは、コンパイラの終了コードを簡単には取得できません。しかしながらコンパイラの終了コードを透過的にフィルタプログラムの終了コードとしてあげないと、コンパイルの成功・失敗に応じて処理を分ける場合にそのフィルタプログラムが使えなくなります。
  3. コンパイラを置き換えると既存のビルドスクリプト等に全く手を加えなくても色付けできますが、フィルタアプローチの場合はビルドスクリプトを書き換えないと色付けすることができない場合があるかもしれません。ただ、何らかの事情によりビルドスクリプトを変更できない場合でも、そのビルドスクリプト自体からの出力を受け取って色付けすれば良さそうなのでそれほど問題ないかもしれません。(個人的には、ビルド環境のコンパイラを置き換えるよりはビルドスクリプトを書き換えるほうがマシな気はしますが)

おそらくこのあたりの理由で、既存のプログラムはコンパイラそのものを置き換える仕組みになっているのではないかと思います。(全然違うかもしれませんが)

今回、シェルスクリプトと組み合わせることによってそれらの問題をある程度解決することができた気がするので GitHub に上げてみました。
https://github.com/bearmini/crror

crror という名前は color + error から来ています。(カラー、もしくはクラーとでも発音しましょうかね)

使い方は至って簡単で、既存のコンパイルのコマンドの先頭に crror とつけていただくだけです。
たとえば、

$ crror make clean all

という感じです。これで、make clean all の出力に色がつきます。
終了コードも make コマンドの終了コードを透過的に使用します。

また、build.log というファイルがあって、その内容を色付けして見たい場合は

$ crror build.log | less -R

という感じでイケます。

現時点ではいろいろ制約があります。たとえば起動スクリプトbash のみサポートですし、stderr を拾うために結局フィルタではなくコマンドっぽく使わないといけない感じになってしまいました。すなわち、make | crror という感じで使いたかったのですが、crror make というふうに使わないといけなくなりました。
(内部的にはフィルタで実装してしまったので、stderr と stdout が統合されてしまっているのが欠点といえば欠点かもしれません)

clang (LLVM) はデフォルトで色付きの出力をサポートしているようですし、gcc も 4.9 からは色つき出力をサポートするようですので、このプログラムもそれが一般的になるまでのつなぎ程度でしかないですが、また、私の気づいていない他の欠点もあるとは思いますが、よろしければ使ってみてください。

Ruby コミュニティにコードを contribute する方法

うっかり Ruby の標準添付ライブラリに好ましくないと思われる挙動を見つけてしまって、直してはみたもののその修正をどうやって contribute すればよいのかと思って調べてみたけどよくわからなかったので http://www.ruby-lang.org/en/ の説明をいろいろ漁ってこんな感じかな〜と思った手順をまとめてみます。(日本語 http://www.ruby-lang.org/ja/ の方は英語版と若干異なる内容だったのと、なんとなく情報量少なめだったので英語の方を参考にしました。ただ、英語のほうも svn 主体の説明になっていてなんとなく outdated な感じでした)

私がやってみたのは以下のような手順です。

  1. Ruby のコードに修正したいバグ(もしくは追加したい機能)を見つける
  2. Redmineruby-trunk プロジェクト (https://bugs.ruby-lang.org/projects/ruby-trunk) に報告する(新しいチケットを作る)
  3. GitHubruby/ruby (https://github.com/ruby/ruby) を fork する
  4. fork したリポジトリをローカルに clone してきて trunk ブランチを checkout する
  5. バグを修正する(もしくは機能を追加する)
  6. もちろんテストも書く
  7. GitHub でプルリクする ← イマココ

まだ PR が取り込まれたわけではないのでこの手順で合ってるかどうかよくわかりません。


今後も継続的に開発に参加するつもりならメーリングリストを購読したりすべきなんでしょうけど、普段は Ruby のユーザで、自分のプログラムのバグかと思って問題を追いかけていたらたまたま Ruby 本体のバグにあたってしまった、というような状況の私みたいな人には、ML に参加して云々というのはちょっと敷居が高いですね。

Redmine で Issue 発行して GitHub でプルリクするだけなら、私のような一見さんでも気軽に貢献できるというものです。

ただ、自分の修正をテストするときに、ローカルで変更した Ruby を使ってテストを走らせるようにする方法がよくわかりませんでした。

なので私は仕方が無いので ~/.rbenv/ の下の当該 .rb ファイルを直接書き換えたりしてテストしました・・・
単一の .rb ファイルで変更はそれほど多くなかったからそのような方法でなんとかなったものの、.c とかを修正したらどうやってテストすればいいのでしょうかね。

そのあたりの情報、どなたか教えてプリーズ

[追記]
多分、以下のような方法で自前 Ruby を rbenv に取り込んで、そいつを使ってデバッグしたりすると既存の環境を壊したりしなくて済むので良い気がします。

Ruby をソースからビルドして rbenv で使う方法 - bearmini's blog

Android SDK のコマンドを実行しようとしたら No such file or directory と言われて焦った件

dexdump を使おうとして、2 回もハマったので、自分用メモ。

結論から言うと、

$ sudo apt-get install ia32-libs

で解決。

私は Ubuntu 12.04 の x86_64 バージョンを使っているので Android SDK も 64bit 版のものをダウンロードして使っていますが、Android SDK のツールの中には 32bit のものがあるんですね。これを実行するのに多分 ia32-libs が要るんだと思います。

$ which dexdump 

してもちゃんと見つかるし、

$ dexdump
-bash: /home/username/adb-bundle-linux-x86_64/sdk/build-tools/android-4.3/dexdump: No such file or directory

という感じにそもそも bash のエラーメッセージにはちゃんと dexdump までのパスが表示されてるので、PATH が解決できてないというわけでもなさそう。

ls -l でパーミッションとかオーナーとか見ても問題なし、どうして見つからないのか??と小一時間悩んだ挙句、StackOverflow で http://stackoverflow.com/questions/13571145/android-adb-not-found を発見して無事解決。

Tizen Native API のメソッド名末尾についてる N の意味

この記事は Tizen Advent Calendar 2013 に参加予定の記事です。



Tizen で Native アプリを開発していると、ときどき API の関数名の末尾に N が付いているのを見かけます。

たとえば身近なところでいうと

  • Tizen::Base::Collection::ArrayList::GetEnumeratorN()
  • Tizen::Net::Http::HttpRequest::ReadBodyN()
  • Tizen::Ui::Control::GetCanvasN()

といったようなメソッドたちです。

これは、「このメソッドの中で new によってメモリの確保が行われるので呼び出し元が責任を持ってそのメモリを解放してね♥」 という意味です。

覚え方: New の N(メソッドの中でオブジェクトを new している)

N で終わるメソッドを呼び出すときは可能ならば戻り値を std::auto_ptr とか std::shared_ptr とか std::unique_ptr とかを使って受け取るなどして、解放忘れを防ぎましょう。


なお、イベントハンドラ名に N が付いている場合、そこに渡されてくる引数のポインタを delete しなければならないという意味になります。

たとえば身近なところでいうと

  • Tizen::App::App::OnUserEventReceivedN()
  • Tizen::Io::IMessagePortListener::OnMessageReceivedN()

などがあります。

これらのメソッドをオーバーライドして実装するときは、引数のポインタを忘れずに delete しましょう。


余談ですが、このようにプラットフォームが確保したメモリをユーザコードの中で解放する、あるいは逆にユーザコードの中で確保したメモリをプラットフォーム側で解放する(Tizen::Ui::Container::AddControl() など)、というコーディング規約は当初すっごく気持ち悪く感じました。(今でもだいぶ気持ち悪いけど)

あと、Tizen::Ui::Container::AddControl() で思い出しましたが、今でこそ Deprecated になった Tizen::Ui::Container::AddControl(const Control& control) というメソッドは、そのメソッドの仕様を二度見、三度見(えっ、・・・えっ・・・、えっ・・?!?)しましたし、軽く冷や汗をかいてひと通り我が目を疑った後にこのライブラリと今後しばらく付き合っていくのかと考えると意識がうっすらと遠のいたのを今でも覚えています。
const 参照で渡したコントロールのインスタンスを、コンテナ側で delete してくれるってどういうことよ!?っていう。
今は Tizen::Ui::Container::AddControl(Control* pControl) になったのでいくらかマシですね。


クラスライブラリの設計の筋の良さ的にはぜひ Qt for Tizen に普及してもらいたいです。

Tizen の sdb コマンド向け bash completion のご紹介

この記事は Tizen Advent Calendar 2013 に参加予定の記事です。


Tizen でアプリを開発していると、コマンドラインからアプリのインストールやアンインストール、ファイルのコピー、デバイスのシェルへのアクセスなど、いろいろと便利な sdb コマンドを使い倒されている方も多いかと思います。sdb コマンドは Android の adb コマンドみたいなものですね。

sdb コマンド自体は大変便利なのですが、デバイス上のファイルを開発用 PC にコピーしてきたいといった時にファイルのパスが補完されなくてちょっと残念です。

ということで、sdb コマンドでも補完を使うための bash completion を以前作りました。

https://github.com/bearmini/tizen_bash_completion

(もし標準でもっと高機能なのがあったり、他の誰かがすでに作ってたりしたら恥ずかしいなぁ。まあ見つけられなかったから作ったんだけど・・・)

使い方は github から clone したあと tizen_sdb_bash_completion.sh を .bashrc かどこかで source するだけです。
(GitHub の README には、/etc/bash_completion.d/ にコピーしろという侵襲的な説明を書いてしまいましたが、そんなことしなくても使えます)


今のところ、補完対象サブコマンドは以下のとおりです:

  • install

ローカル側のファイル名(*.tpk, *.wgt など)を補完してインストールできます。

  • uninstall

デバイスにインストール済みのアプリのパッケージ ID 一覧を補完してアンインストールできます。

  • push

ローカル側のファイルパスおよびデバイス側の push 先パスを補完できます。

  • pull

デバイス上のファイルパスおよびローカル側の pull 先パスを補完できます。

  • その他 dlog とか root とかもサポートしていますがおまけみたいなものですね

複数のデバイスが接続されているときは -d/-e/-s などでデバイスを特定する必要があります。-s に指定するシリアル番号も補完対象です。

sdb pull の補完では末尾に余計な記号がついちゃう場合があります。
(ディレクトリ名の末尾に / を付けたかったので、デバイス上で実行する ls コマンドに F オプションをつけたのですが、そうすると他の種類のファイルの末尾に * とか @ とかがついてしまうことがあります。これがついたまま実行すると、エラーになりがちです。)
これはなんとかしたいですね。
(scp の補完も同じ感じだった気がするから難しいのかもしれないけど・・・)






上記 4 つのコマンドの補完が効くだけでも大幅に効率アップすること請け合いですが、追加でサポートしてほしいサブコマンドや sdb 以外のコマンドのご要望がありましたらコメントなり何なりでお知らせください。
pull request も絶賛受付中です。

Linux (Ubuntu) から NTFS でフォーマットされた外付け USB HDD へファイルをコピーしたらシンボリックリンクがシンボリックリンクのままだったでござるの巻

表題の通りなんですが、シンボリックリンク先の実体は外付け HDD にはコピーされていなかったので意味のない状態になってしまい、困りました。

ちなみにコピー先が NTFS ではなく FAT32 でフォーマットされた外付け HDD だと「シンボリックリンクを作れない」というようなエラーになりました。

GUI のファイルブラウザでコピーしても cp コマンドで(オプションは特に指定せず)コピーしてもそうなったので、まあそういうものなんでしょう。


cp コマンドに -L オプションをつけることで解決。
シンボリックリンクがリンク先の実体としてコピーされる)

btrfs で複数のデバイスを使うときにやったことメモ

1TB の HDD のおさがりをもらったのでさっそく Linux PC に搭載して、前から気になっていた btrfs でフォーマットして使ってみました。

この記事に書く予定のシナリオとしては、

1. ディスク単体で btrfs フォーマットしてマウントして使用開始
2. ディスクを増設して一つのボリューム(?)として使用継続

という程度のもので、スナップショットがどうしたとか透過的圧縮がこうしたとかルートファイルシステムをどうのこうのとかいったような高度な話は一切出て来ません。

それでも例によっていろいろハマったので、後の自分のためにハマりポイントなどをメモ。

環境は Ubuntu 12.04.3 LTS。




最初に btrfs-tools パッケージをインストールした気がします。
(記憶があやふや)


それからディスクを btrfs でフォーマット。

$ sudo mkfs.btrfs <device file>

な感じですね。ここまではちょっとググればすぐにわかります。

<device file> には /dev/sdb とかそんな感じのデバイスファイル名を指定します。
ここからは /dev/sdb で話を進めます。(この記事を読んでくださっている皆さんはご自身の環境にあわせて読み替えてください。)

ちなみに、最初 /dev/sdb1 とかのパーティション?を指定してしまってエラーになってしまいました。よく考えたら当たり前なのかもしれませんが・・・。
(おさがりだったので事前になんらかのファイルシステムでフォーマットされていたのかもしれません)



次にこのディスクを単体でマウントします。
このあたりまでは旧来のファイルシステムと同じ感覚でやってたのですが問題なくできてました。

$ mkdir /mnt/btrfs_test
$ sudo mount /dev/sdb /mnt/btrfs_test

/mnt/btrfs_test はマウントポイントですね。
もしファイルシステムのタイプがどうのこうのというエラーになったら -t btrfs をつけると良いと思います。

これでもう /mnt/btrfs_test 以下には好き放題にファイルを作ったりできちゃうのですが、便利に使うためにもうあといくつか作業をします。



このままでは、PC を再起動するたびにマウントしなおさないといけなくなるので、/etc/fstab に以下の内容を書いておきましょう。

/dev/sdb    /mnt/btrfs_test    btrfs  noatime,nodiratime  0  0

/dev/sdb は最初に初期化したデバイスファイル名なのでみなさんの環境にあわせて変えてください。
/mnt/btrfs_test はマウントポイントです。
つぎの btrfs はファイルシステムのタイプで、
その次の noatime,nodiratime はパフォーマンスがよくなる(ファイルやディレクトリの最終アクセス日時をいちいち更新するのをやめる)ということです。これらのオプションはつけても付けなくても良いと思います。




さらに、サブボリュームと呼ばれるものを作っておくと、そのサブボリューム単位でスナップショットをとったりすることができて便利になるようです。

$ cd /mnt/btrfs_test
$ sudo btrfs subvolume create <subvolume name>


マウントするときは、このサブボリュームの単位でマウントすることもできるようです。




しばらくこの状態で使っていたら、もう一台 1TB HDD のおさがりをもらいました。
いったん PC をシャットダウンしてその HDD を接続したあと PC を起動し、/dev/sdc が認識されていることを確認しました。

この /dev/sdc も btrfs でフォーマットしました。

これを単体でマウントして別々のディスクとして扱うのではせっかく btrfs にした意味がないので、既存の /mnt/btrfs_test の容量を増やすようにしたいと思います。

それには、以下のコマンドでファイルシステムにデバイスを追加します。

$ sudo btrfs device add /dev/sdc /mnt/btrfs_test

これだけで完了です。簡単ですね。

ただ、この状態では、古い方(/dev/sdb)の 1TB のディスクにばかりデータが書きこまれていて、新しい方(/dev/sdc)にはまったくデータが書きこまれていないというアンバランスな状態となっていますので、これをバランスさせます。

$ sudo btrfs filesystem balance /mnt/btrfs_test

このコマンドは実行にかなり時間がかかります。

このコマンドが完了してから df コマンドを実行すると、無事 /mnt/btrfs_test の容量が約 2TB になっていることが確認できました。


なお、デバイスを追加しても、fstab は書き換えなくても大丈夫なようです。ファイルシステムに追加されたデバイスのうちどれか一つを指定してマウントすると、すべてのデバイスがまとめて使用可能になるようです。





以上、僕が知りたかった情報(なぜサブボリュームを作るのか、等の理由も含めて)があまりまとめられていなかったのでまとめてみました。

間違いの指摘やアドバイス等、よろしくおねがいします。

Ruby で特定のパターンが出現するまで簡単にファイルを読み飛ばす方法

テキストファイルの処理をしてると、たまに表題のようなことをやりたくなりますね。

ヘッダーの1行だけ読み飛ばすとか固定行数読み飛ばすだけならその行数の分だけ gets() を呼べばいいのですが、何行目に現れるかわからない特定のパターンまで読み飛ばすというのは、C 言語脳な僕には gets() して目的のパターンかどうか比較してそうでなければ次の行・・・みたいなループを書いてしまいがちです。

Ruby 脳的にはどうするのがいいかなと思っていたのですが、gets() の rs 引数としてその特定のパターンを渡せばよいようです。

すなわち、

aaaaa
bb
ccccc
ddd
eeeeeee
fff
<<<DATA
data 1
data 2
data 3
  :

という感じのファイルがあったとして、<<

open('data.txt') do |f|
  f.gets("\n<<<DATA\n")
     :
  # 本来の目的の処理
end

と1行で読み飛ばせてしまうことがわかりました。

"\n<<<DATA\n" を行の区切りとして、そこまでを一行として読み取ってしまうという荒業ですね。(そうでもない?)

前後の \n によって、その文字列だけからなる行があるということを意味しています。

逆に特定のパターンが行の途中に現れるとかだとすると \n を除かないといけません。
ただ、後ろの \n が無いと、本来の処理に入ってから一回だけゴミが渡されてきちゃうような気がしますので要注意かも。といっても gets() (引数なし)をもう一回呼べばいいだけですかね。

パターンとして正規表現が使えたら最強な気もしますが、rs のデフォルトが $/ ということはそれはできないのかな?


多分、年に2回くらい使うので忘れないようにメモ。

ssh サーバに公開鍵をワンライナーで登録する方法

2014.05.09 追記

$ ssh-copy-id user@hostname

でいいかも。
(公開鍵ファイルを指定したい場合は -i オプションを使用する)





$ ssh user@hostname "echo `cat ~/.ssh/id_rsa.pub` >> ~/.ssh/authorized_keys"

以上。
たまにやりたくなるんだけどいつも忘れるのでメモ。

`〜` はローカル側のシェルで置き換えられてから ssh コマンドが実行され、echo 〜 はリモートサーバ上で実行される。

ちなみに bash の man の EXPANSION の項によると、

  1. ワード分割
  2. ブレース展開(a{b, c, d}e を abe, ace, ade に分割)
  3. チルダ展開(~ をホームディレクトリなどに展開)
  4. 以下の展開が同時に行われる(左から右の順で評価される)
    1. パラメータ、変数および算術展開(${〜} や $((〜)) を展開)
    2. プロセス置換(<(〜) や >(〜) を置換。名前付きパイプ(FIFO)をサポートしている環境のみ)
    3. コマンド置換($(〜) や `〜` を置換)
  5. ワード分割(ここまでの展開で生成されたワードに基づいて再度分割)
  6. パス名展開(* や ? や [〜] を展開)

の順で処理されてから実行されるようです。

Java とか Android (DEX) の MUTF-8 (Modified UTF-8) って何者よ?っていう話

Android の APK の DEX をゴニョゴニョしてたら、DEX の string 領域に格納されている文字列は実は UTF-8 じゃなくてちょっと modify された MUTF-8 (Modified UTF-8) だということが判明して軽くショックを受けています。

Wikipedia の UTF-8 の項によりますと、標準の UTF-8 から以下の 2 つの変更点があるようです。

後者に関しては端的にいうと CESU-8 (Compatibility Encoding Scheme for UTF-16: 8-Bit) というエンコード方法に則っているということのようです。

Wikipedia のページにも例がありますが、U+10400 というコードポイントを普通に UTF-8 でエンコーディングしたら 0xF0, 0x90, 0x90, 0x80 という 4 バイトのバイト列になるのですが、CESU-8 だと 0xED, 0xA0, 0x81, 0xED, 0xB0, 0x80 という 6 バイトのバイト列になります。

これは U+10400 を UTF-16 でエンコーディングすると 0xD801, 0xDC00 というサロゲートペアになるのですが、それぞれ、0xD801 を UTF-8 のようにエンコーディングすると 0xED, 0xA0, 0x81 となり、0xDC00 を UTF-8 のようにエンコーディングすると 0xED, 0xB0, 0x80 となるためなんですね。

これら 2 つのルールを整理しますと、以下の表のようになります。

Unicode コードポイント U+0000 U+0001 〜 U+007F U+0080 〜 U+07FF U+0800 〜 U+FFFF U+10000 〜 U+10FFFF
通常の UTF-8 0x00 0x01 〜 0x7F 0xC4,0x80 〜 0xDF,0xBF 0xE0,0xA0,0x80 〜 0xEF,0xBF,0xBF 0xF0,0x90,0x80,0x80 〜 0xF0,0x90,0xBF,0xBF
UTF-16F 0x0000 0x0001 〜 0x007F 0x0080 〜 0x7FFF 0x0800 〜 0xFFFF 0xD800,0xDC00 〜 0xDBFF,0xDFFF
Modified UTF-8 0xC0,0x80 0x01 〜 0x7F 0xC4,0x80 〜 0xDF,0xBF 0xE0,0xA0,0x80 〜 0xEF,0xBF,0xBF 0xED,0xA0,0x80,0xED,0xB0,0x80 〜 0xED,0xAF,0xBF,0xED,0xBF,0xBF


ちなみに、MUTF-8 を UTF-16 に戻したり、逆に UTF-16 を MUTF-8 に変換したりするコードは Android のソースの
dalvik/dx/src/com/android/dx/rop/cst/CstString.java
あたりにあります。
(関数名 utf8BytesToString() や stringToUtf8Bytes() が該当します)


その他、参考 URL
http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/types.html#wp16542

HTML5/JavaScript/CSS3 でクロスプラットフォームなデスクトップ GUI アプリを作れるフレームワークの決定版を見つけた(かもしれない)件

[追記 2015/05/19]
2015年時点では HTML5/JavaScript/CSS でデスクトップ GUI アプリを作るなら、Electron 一択でしょうね。electron.atom.io

[追記ここまで]


私はデスクトップアプリケーション開発歴はすでに20年近い老人ですが、数年前から「HTML5 でデスクトップ GUI アプリを開発するのが今後主流になるはず」と言い続けてきました。

最近になってやっと、その説をサポートしてくれてかつ人に紹介しても恥ずかしくなさそうなフレームワークに出会えたので(それも一気に 2 つも)、紹介したいと思います。


ちなみに、私のデスクトップアプリ開発に使ってきたフレームワークの遍歴は、以下のような感じです。(抜けてるのもあるかも)

他にも、大学の計算機の授業の課題で SunOS の上で生の Motif を書いたりしたし、趣味でいろんなフレームワークをつまみ食いしたりしてチュートリアル程度はやったというのを含めるとこのリストは倍くらいになるかもしれない。

で、一時期 Web アプリやモバイルアプリの開発なんかもやってみて思ったのが、結局どのフレームワークでも、コントロールやウィジェットと呼ばれる GUI 部品を座標とか大きさを指定したりレイアウトマネージャー的なものにそのへんを任せたりしつつ配置して、それぞれの部品のアクションに応じてイベントハンドラ書いたり、MVC モデルとか使ってデータが更新されたら見た目も更新する(もしくはその逆)みたいなことをしたり、結局はどれもこれも似たようなことやってるだけだなと。なのに、新しい環境が出てきたら毎回毎回新しい言葉を覚えて新しい習慣を身につけないといけないと。
WPF やってるくらいのころに、「もうこれ HTML でいいじゃん」とマイクロソフトを呪ったわけです。なんでまた新しいマークアップとかバインディングとか覚えないといけないのと。

たぶんそれが 2006〜2007 年くらい。

で、新しもの好きがたたって(?)一時期 Titanium Desktop とかに可能性を感じてみちゃったりしたわけです(結局 Appcelerator は Titanium Desktop を手放してオープンソース化されて Tide SDK ?とかになって細々とやってるのかな)。

AppJS っていうのを見つけたりしてこれもいいかもと思ったんだけど、実際使ってみるとどうも思ったとおり動いてくれない(Windows 64bit 環境だと起動もせずにクラッシュした。そのうち直るかもしれないけど)し、ドキュメントとかも圧倒的に足りてない感じ。→ 今は deskshell っていうプロジェクトに引き継がれているようですが、どうなることやら。

最近は Chrome App がいい感じかな〜とも思ったけど、お手軽さという意味ではいいんだけどやっぱりブラウザに縛られるというか普通にローカルのファイルを見に行けないとかそういう息苦しさみたいなものはある。作れるアプリが限定されちゃうというか。必要なデータは全部 Web からかき集めてきて、保存するときもクラウド、みたいな Web ネイティブなイマドキのアプリにはいいのかもしれない。(実際、2 つくらい自分用の実用的な小さなアプリを Chrome App で作ってみた)


前置きが長くなったけど、そんな中で見つけたのが node-webkitQt

node-webkit

node-webkit は、数ある「WebKit と LL を組み合わせて見ました」系のフレームワークとは一線を画す感じで、ちょっと使ってみた感じでも商用アプリを作るのに耐える品質を備えているんじゃないかと思ったフレームワーク。開発も活発に続いている。ドキュメント等、情報も他のものに比べると十分そろっていると思う。(少なくとも、今までアプリを作ってて困ったことがあってぐぐったら全部答えが見つかっている)

少しだけ特徴をあげてみると、

  • 作ったアプリをバイナリ単体で配布できる(Windows なら単一の .exe ファイルにできるし、Mac ならパッケージを作れる。Linux でも 1 つの実行ファイルにして配布できる)
  • node.js で DOM をいじれる

→ これ結構気持ちのいいパラダイムシフト。サーバサイドの人もクライアントサイドの人も到達したことのない境地のはず。「サーバサイドとクライアントサイドの言語が統一できますよ」っていうの(一瞬うれしそうだけど全然嬉しくないやつ)のレベルじゃない。たとえば、AngularJS のコントローラの中で SQLite で直にファイルからデータを読みだしたりできるんだぜ?
CoffeeScript とか LESS とかソレ系のやつを grunt で毎回コンパイルしたりしなくてよい。GUI アプリとして実行される時にコンパイルすれば良いから。で、シングルページアプリケーションとして動かして DOM をグリグリいじって画面の更新をするようにすれば再読み込みが発生しないのでパフォーマンスにもインパクト小(起動時に一回だけコンパイルされるだけ)。どうしてもそれも許せないなら普通に事前に JS や CSS へとコンパイルしてもいい。

→ パフォーマンスは逆に悪化するらしいが、秘密にしたいコードを(若干ではあるが)隠せる。

などなど。
node-webkit を使って、これも 2 つくらいアプリを書き始めてみたところ。

Qt

Qt なんて、見つけたというか温故知新というか僕が今まで気づいてなかっただけで、C++ のごっつい旧世代のフレームワークくらいにしか思ってなかったんだけど、実は Webkit ベースで HTML5 アプリを作れて C++ の世界(QObject)とのインタラクションが快適そうなので急浮上してきた。

実際ちょっと使ってみたら、Qt って名前の通り結構キュートなやつなのな。クラスライブラリの設計とかもちゃんとモダンな標準に従っててエレガントな感じがしてさわり心地がいい。C++er としてはホント今まで気づいてあげられなくてごめんよという感じ。
node-webkit ほどの気持ちよさは無いけど、パフォーマンスを極限まで追求したいとかどうしてもシステムコール呼びたいとか、ポインタが無いと生きていけないとかそんな下寄りに行きたい、でもイマドキっぽいかっこいい GUI も欲しいとかいうようなときは(どんなときだよ)、今後は僕は Qt を選ぶと思う。(node-webkit + native extension に行っちゃうかもしれないけど)

一つ実験的に規模大きめの GUI アプリを書き始めてみた。

まとめ

Web/モバイル全盛のこの時代、デスクトップアプリ自体がオワコンっていう話もあるのかもしれないけど、たぶん HTML5 ベースのデスクトップアプリによって一回揺り戻しが来るんじゃないかな〜なんて考えています。

久しぶりにワクワクしながら GUI アプリを書いている今日このごろです。

chef で remote_directory リソースで一気にファイルをコピーしようとしたら空ディレクトリがコピーされなくて困った件(解決策もあるよ)

仕事では vagrant + chef を使って Hermetic なテスト環境を誰でも簡単に作れるようにしようという取り組みをしています。

モバイルアプリからアクセスするバックエンドのサーバは、現時点では本番環境かテスト環境かというくらいしかないのですが、これを vagrant と chef で誰でもローカルの仮想マシン上にセットアップできるようにしちゃおうという目論見です。

バックエンドサーバのコードは自社製のレガシーなものがすでにありますので、まずはそれをデプロイしたいなと。
chef のリポジトリの site-cookbooks/<cookbook-name>/files/default/ あたりにそのバックエンドサーバの実行に必要なファイル一式を用意しておいて、まるっと仮想マシンにコピーしたいわけです。

で、chef のリソースについてのドキュメントなんかを読むと、どうやら remote_directory というリソースを使えば cookbook に入れておいたファイルたちをディレクトリごとまるっとコピーしてくれるようだということがわかります。

そこで早速使ってみたのですが、一つ問題に気づいてしまいました。

空っぽのディレクトリが仮想マシン側の環境にコピーされていないのです。

ログを出すためのディレクトリとか、ユーザからのアップロードを受け付けるためのディレクトリだとかそんな感じのディレクトリの一つや二つ、ありますよね?
そういう空のディレクトリが cookbook の files の下にあっても、仮想マシン側にはそれがコピー(作成)されないのです。

一つや二つなら、実行時にどうせ作られるし別に気にしないのですが、今回いじってるサーバはちょっとわけあって100個くらいそういう空のディレクトリがあります。
しかも、本番環境やテスト環境と差分がないことを diff とったりして確認したいので、100個も差分があると本当の差分が埋もれてしまって困ることになります。

で、解決策がここにありました。
https://github.com/higanworks-cookbooks/mongodb-10gen/issues/3

やはり同じ事で困っている人はいるみたいです。


解決策を大雑把に説明すると、コピー元の cookbook の files の下の空ディレクトリになんでもいいからダミーの空ファイルを入れておけということのようです。

私の場合は

find ${COOKBOOK_FILES_DEFAULT_DIR} -type d -empty -exec touch {}/delete.me \;

という感じで一括して delete.me という名前のファイルを空ディレクトリの中に作成しました。

で、レシピには、

execute 'delete delete.me files' do
  command "find #{dst_dir} -name 'delete.me' -exec rm {} \\;"             
end

こんな感じのコードを書いておくと knife solo cook したときに delete.me が消えてなくなります。