腕時計その後

Alba のクォーツのやつを壊しちゃったのだけど、昨日お店から電話がかかってきて6000円で直るそうだ。
わーい。
ゼンマイの自動巻のやつは便利だが、じっと閉じこもっていたりとか、チャリに乗って生活していたり (自転車にのるときは腕時計とか付けないので) すると止まっちゃうんだよ。あたりまえだけど。
それに較べて、光発電のやつは、そのへんに置いておけば勝手に光合成 (違うって) して充電してくれるわけで、放っておいても安心。まさに永久機関というやつです (だから違うんだってば)。

gethostbyaddr

gethostbyaddr() で得られるホスト名がどうなってるか調べるには、
perl -e ‘printf(“%s¥n”, gethostbyaddr(pack(“C4”, split(/¥./, “192.168.0.XX”)), 2));’
とかすればいい。perl 便利だな。awk には gethostbyaddr() はないからな(笑)。

飯田

久しぶりに大垣行きの夜行列車に乗って、
豊橋を6時に出る天竜峡行きで信州へ。
目が覚めたら中部天竜を過ぎていて、唐笠駅でおりて下條温泉へ。
上り坂は、日差しが暑いけど、風が涼しかった。
天竜峡までタクシーで下って、また電車に乗って鼎へ。
電車の中から、Tour of Japan の日に走った赤い橋なんかが山の上にみえて、
懐かしかった。また行きたいなー。
鼎では「赤門や」にいってお菓子を買って、
向かいの cafe glam hearts でお昼ご飯。ランチは780円で大充実。
東京じゃ、1000円以上払わないと考えられない値段と内容。
飯田できんつばを買って、
飯島でまた温泉。で、帰る。
飯島駅から、中央アルプスに沈む夕陽がきれいに見えた。
一日中歩いて電車乗って、の繰り返し。それもいい。

rmt その後

FreeBSD の struct mtget は 76bytes あるが、rmt が 24bytes で切ってしまう。
xfsdump の BUFMAGIC が 64 に設定されており、76bytes 返されたら死ぬ。
というわけで、これはそれぞれあっという間に修正できるわけだが。
mt_gstat = 0 だと、drive not ready ということになってしまうらしい (笑)。そこで、猛烈に乱暴なやりかただが、rmtioctl.c で、
dstp->mt_gstat = 0;
dstp->mt_gstat |= GMT_ONLINE(0xffffffff);
と書いてみた。しかし、これではテープの終わりが正しく検出できなかったようで、
xfsdump: NOTE: dump interrupted: 18019 seconds elapsed: may resume later using -R option
xfsdump: Dump Status: INTERRUPT
ということで終わってしまった。つまり、正しく次のテープを要求させるには何らかの仕掛けが必要なのだが、これは FreeBSD 側の rmt の改造も含めて、けっこうがんばらないといけないのではないだろうか。うーん。EOT が正しく検出できればいいのかなあ。

EmacsでTAB連打?

俺は Linux が好きじゃないというのは、まわりの人ならみんな知ってることですが、
何が許せないかというと、こういうコードが平然と書かれているってことです。

struct  irix_mtget   {
short   mt_type;          /* type of magtape device */
unsigned short  mt_dsreg; /* ``drive status'' register */
short   mt_erreg;         /* ``error'' register */
short   mt_resid;         /* residual count */
int     mt_fileno;        /* file number of current position */
int     mt_blkno;         /* block number of current position */
};
struct linux32_mtget
{
int32_t mt_type;           /* Type of magtape device.  */
int32_t mt_resid;          /* Residual count: */
/* The following registers are device dependent.  */
int32_t mt_dsreg;          /* Status register.  */
int32_t mt_gstat;          /* Generic (device independent) status.  */
int32_t mt_erreg;          /* Error register.  */
/* The next two fields are not always used.  */
int32_t mt_fileno;        /* Number of current file on tape.  */
int32_t mt_blkno;         /* Current block number.  */
};

インデント幅くらい揃えてくれ!

FreeBSD と Linux の rmt

研究室のファイルサーバは幾つかあるが、メジャーな奴は (残念なことに) Linux で、xfs を使っている。で、テープドライブのつながっているホストは FreeBSD なのだが、こいつに xfsdump しようとすると、
rmtopen: remote host type, “FreeBSD”, is unknown to librmt.
というメッセージが出て、dump は始まるものの、ファイルサイズなどは無視されて、テープの終わりまでに dump が終了しなければそのまま abort 、という結末になってしまう。で、昔 Solaris と FreeBSD と Linux をごっちゃにして使っていた頃は、そんなの気にしたことなかったので、なんでだろうなー、と調べていると、librmt というのはどうやら、xfsdump のソースに含まれているライブラリらしい。それに、Linux の rmt はどうやら BSD 由来のものであり、rmt が理解するコマンドは Linux でも FreeBSD でも全く同じようだ。rmt のコマンドには、uname を返すようなものはないので、
ということで、xfsdump のソース取ってきて眺めてみた。librmt/rmtopen.c が怪しい。
まず、uname は rsh 経由で呼ばれているようだ。

170 snprintf(cmd, sizeof(cmd), “%s %s uname”, rsh_path, system);
173 rmt_f = popen(cmd, “r”);
183 char *c = fgets(uname, sizeof(uname), rmt_f);

検索に使われているテーブルはたぶんこれ。

50 struct uname_table uname_table[] =
51 { {UNAME_LINUX, “Linux”}, {UNAME_IRIX, “IRIX”}, {0,0} };

で、ここまでは簡単そうなのだが、rmt が I とか S で扱う構造体には互換性がなさそうだ。rmtioctl.c を見る限り、I (MTIOCOP) は使っていなそうだが、S (MTIOCGET) のほうは使う模様。これは、mtget 構造体をそのまま返すんじゃないかと思う。
rmtioctl.c には、

47 struct linux32_mtget
48 {
49 int32_t mt_type; /* Type of magtape device. */
50 int32_t mt_resid; /* Residual count: */
51 /* The following registers are device dependent. */
52 int32_t mt_dsreg; /* Status register. */
53 int32_t mt_gstat; /* Generic (device independent) status. */
54 int32_t mt_erreg; /* Error register. */
55 /* The next two fields are not always used. */
56 int32_t mt_fileno; /* Number of current file on tape. */
57 int32_t mt_blkno; /* Current block number. */
58 };

というのがあり、一方 FreeBSD の /usr/include/sys/mtio.h

110 struct mtget {
111 short mt_type; /* type of magtape device */
112 /* the following two registers are grossly device dependent */
113 short mt_dsreg; /* “drive status” register */
114 short mt_erreg; /* “error” register */
115 /* end device-dependent registers */
122 short mt_resid; /* residual count */
123 #if defined (__FreeBSD__)
124 int32_t mt_blksiz; /* presently operating blocksize */
125 int32_t mt_density; /* presently operating density */
126 u_int32_t mt_comp; /* presently operating compression */
127 int32_t mt_blksiz0; /* blocksize for mode 0 */
128 int32_t mt_blksiz1; /* blocksize for mode 1 */
129 int32_t mt_blksiz2; /* blocksize for mode 2 */
130 int32_t mt_blksiz3; /* blocksize for mode 3 */
131 int32_t mt_density0; /* density for mode 0 */
132 int32_t mt_density1; /* density for mode 1 */
133 int32_t mt_density2; /* density for mode 2 */
134 int32_t mt_density3; /* density for mode 3 */
135 /* the following are not yet implemented */
136 u_int32_t mt_comp0; /* compression type for mode 0 */
137 u_int32_t mt_comp1; /* compression type for mode 1 */
138 u_int32_t mt_comp2; /* compression type for mode 2 */
139 u_int32_t mt_comp3; /* compression type for mode 3 */
140 /* end not yet implemented */
141 #endif
142 int32_t mt_fileno; /* relative file number of current posit
ion */
143 int32_t mt_blkno; /* relative block number of current posi
tion */
144 };

みたいな感じで、圧倒的に FreeBSD のほうが詳しい情報が返ってくるのであり、こりゃ互換性はないね。というわけで、大幅に手を加える必要がありそうだ。IRIX の場合、最終的には

364 if (RMTHOST(fildes) == UNAME_IRIX) {
365 struct mtget *dstp = (struct mtget *)arg;
366 struct irix_mtget *srcp = (struct irix_mtget *)irixget;
367 short status = srcp->mt_dsreg;
368
369 dstp->mt_type = srcp->mt_type;
370 dstp->mt_erreg = srcp->mt_erreg;
371 dstp->mt_resid = srcp->mt_resid;
372 dstp->mt_fileno = srcp->mt_fileno;
373 dstp->mt_blkno = srcp->mt_blkno;
374 dstp->mt_dsreg = srcp->mt_dsreg; /* different semantics */
375
376 /* need to do tape status conversions */
377 dstp->mt_gstat = 0;
378 if (status & IRIX_MT_EOT)
379 dstp->mt_gstat |= GMT_EOT(0xffffffff);
380 if (status & IRIX_MT_BOT)
381 dstp->mt_gstat |= GMT_BOT(0xffffffff);
382 if (status & IRIX_MT_WPROT)
383 dstp->mt_gstat |= GMT_WR_PROT(0xffffffff);
384 if (status & IRIX_MT_ONL)
385 dstp->mt_gstat |= GMT_ONLINE(0xffffffff);
386 if (status & IRIX_MT_EOD)
387 dstp->mt_gstat |= GMT_EOD(0xffffffff);
388 if (status & IRIX_MT_FMK)
389 dstp->mt_gstat |= GMT_EOF(0xffffffff);
390 if (status & IRIX_MT_EW)
391 ;/* No GMT_ to map it to */
392 }

みたいにして、32bit Linux な mtget に反映されるし、32bit Linux の場合は、

393 else if (islinux32) {
394 struct mtget *dstp = (struct mtget *)arg;
395 struct linux32_mtget *srcp = (struct linux32_mtget *)linux32get;
396
397 dstp->mt_type = srcp->mt_type;
398 dstp->mt_erreg = srcp->mt_erreg;
399 dstp->mt_resid = srcp->mt_resid;
400 dstp->mt_fileno = srcp->mt_fileno;
401 dstp->mt_blkno = srcp->mt_blkno;
402 dstp->mt_dsreg = srcp->mt_dsreg;
403 dstp->mt_gstat = srcp->mt_gstat;
404 }

とするだけだ。こんな感じのを書いてやれば良さそう (ほんとはこの手前で、必要な場合にはバイトオーダの変換を行っているのだけれど、僕が使うのは今のところぜんぶ x86 だから手抜きをすることにする。Solaris なファイルサーバがあるという理想的な環境では、話が変わるわけだが…)。
FreeBSD の mtget から Linux の mtget にそのまま値を渡して良さそうなのは、
– mt_type (short → int32)
– mt_resid (short → int32: でもこれって 32kB だとすぐあふれるから、違う IOCTL を使うべきらしい)
– mt_dsreg (short → int32)
– mt_erreg (short → int32)
– mt_fileno (int32 → int32)
– mt_blkno (int32 → int32)
で、変換しなければならない (かもしれない) のは、
– mt_gstat ( ? → int32)
なのだが、これは FreeBSD の mtget には、該当する値がない気がする。これはつまり、テープの終わりとかが検出できないのであり、何本ものテープにまたがって dump する場合には非常に問題なような気もする。しかし、実際のところ xfsdump はこの変数を使っていないように見えるので、とりあえず 0 にしときゃいいんではないだろうか…?
(きっと、続く)

今日の自転車

朝まで働いて、午前中はちょっと寝て、午後は友人がきたので一緒に出かけて、夕方から自転車で出勤。夕暮れの多摩川沿いに出ると、猛烈に身体が軽く感じた。
夕方のサイクリング道路は危ない。人が多いし、無灯火とか、そもそもどこ見て走ってるんだかわからない奴もたくさんいるし、こっちがフルブレーキして回避してるのに、全然気づいてくれなかったりするわけで。人間というのはたいてい、自分以上の速度で動くものを意識して行動することはできないものらしい。
そういうわけで、大変いい感じにもかかわらず、徐行を強いられるケースが多いわけで、往路は平均 26.8km/h. 復路は府中街道経由で、平均 29km/h くらい出してた。一番トバしたのは世田谷通りで、車の流れにのってズバァーっと加速して、48km/h くらい出てた。チャリに抜かれそうになって慌てて加速する自動車、というのはすごく怖い。だって、前が詰まってるんだからブレーキかけるのは必至なわけで、それくらいだったらおとなしく先に行かせていただきたいわけです。
一応明日から大学は休みですが、残念ながら出勤です。
36.69km @ 27.9kmh (1h17m46s) odo 3727.6km

LDAPその後

一晩中必死で root 仕事して、機器室で朝を迎えた28の夜 (朝だけど)。
netgroup も LDAP にしたぜ!
NIS format から hosts / netgroup を LDAP サーバに押し込む script を書いたので、FreeBSD では NIS, Linux では LDAP で生きていけるようになった。FreeBSD の libnss_ldap もちゃんと使えるようになるといいんだけどな。
あ、おまえが libnss_ldap を hack しろって?
おっしゃる通りです、ほんとすみません。
netgroup を LDAP に放り込んだのは、ログインできるユーザを制限したかったからなのだが、
passwd: compat
passwd_compat: files ldap
にして、+@ とか使って書くと、ちゃんと制限できてるようなのだが、getent とか finger では、LDAP なユーザが見えなくなっちゃって、つまり Linux なら LDAP support は完璧かというと、そうでもない模様。

ゼンマイ教

銀座で LASIK の術前検診を受けたときに、腕時計を修理に出したのが、先週帰ってきた。祖父が使っていた、Omega Seamaster で、巻き芯が折れてリュウズが取れちゃってたのを直して、さびていた文字盤も再生してくれた。時計屋さんの web に写真を載せていただいたのだが、まあなんというか、動かなかった時計が日差 2 秒 (!) で動くようになるのだから、これは仁術だ。日差2秒なんて、秒針の拘束機構がない時計ならどうせ秒のところは合わせられないのであり、まったく気にならないといっても差し支えない。
普段使っている腕時計は、ALBA のソーラーの奴であり、こいつはたった1万3千円なのにもかかわらず、クォーツの驚異的な精度と、ネジを巻いたり電池を替えたりする必要もないという、すごい奴で、買ったのは大学3年のときだから、もう8年くらい使っている。たまに日付 (31日ない月もあるわけで) や時間を合わせてやらないといけないけどね。で、Seamaster が修理終わったとたんにこいつをぶつけてしまい、風防のガラスが破損して現在修理中。ガラスの破片がカレンダー窓から中に入ってしまうと OH が必要になるかもしれないそうだ。なるほどね。
そういうわけで、時計は 1960 年代のゼンマイ式であり、写真を撮るのも同じ年代の Nikon F であり、普段手を触れる機械がみんなゼンマイで動くというのは愉快だ。だって、電池いらないんだぜ!エコロジーとかいうなら、まずこういうのを追求するべきでしょう。コンピュータはさすがにゼンマイじゃ動かないけどな。
60年代のテクノロジっていうのはいまでも充分現役なのであり、いま僕らが使っている、あるいは作っている電子機器っていうのは、そんな寿命があるものかしらん、とも思う。工業製品ってのは、本来そういうものじゃないといけないと思うんだけどね。