Androidアプリからのファイルパーミッションの制御

アプリ間のファイルアクセスの許可/禁止には unix のファイルパーミッションの仕組みが使われています。

Androidではアプリごとにuidとgidが割り当てられていて、パーミッションのうち、otherのread,write,execute ビットを変更することで他アプリからのアクセスを許可/禁止することができます。

パーミッションの設定はネイティブコードならchmod(2)を使うんですが、Javaからだとそのまま呼び出せるようにはなっていません。

そこで今回はアプリからファイルパーミッションを制御するにはどのようなAPIを使えばよいか確認してみます。

続きを読む

Windows Live ID が停止されてる件でたらいまわし続行中

  • SkyDrive Explorerで手持ちの画像を3GBくらいupしてみる
  • 原因はわからないがアカウント停止される
  • Webからサインインできない
  • カスタマー サポートにお問い合わせください。 いくつかの質問をさせていただき、お客様のアカウントが安全であるかをご確認いたします。」
  • MSKKのサイトで問い合わせ先は「Windows Live はコミュニティでのサポートをご利用ください。」
  • Windows Live Solution Center はサインインしないと使用できない
  • 別件でMSの人と話したら「別のメールアドレスでLive IDを作って問い合わせるといいよ」
  • フォーラムに投稿したら「SkyDriveの迷惑行為」の投稿先を伝えられる
  • SkyDriveの迷惑行為 のフォームに書いたら
現在、当サポート窓口では、サーバー側にて問題が発生しているとの
報告を受けておりませんため、本件につきましては、恐れ入りますが、
担当部署に報告し、確認をさせていただきたく存じます。

…どこまで続くんだコレ

Bitmapのカドを丸くする

「アイコン画像を角丸にしてくれ」 とか、割とよくある話だと思うんです

	public static Bitmap clip_radius(Bitmap src,int out_w,int out_h,float radius_x,float radius_y){
		// 入力と出力の矩形
		Rect rect_in = new Rect(0,0,src.getWidth(),src.getHeight());
		RectF rect_out = new RectF(0,0,out_w,out_h);
		// 出力ビットマップとその描画オブジェクトを作成する
		Bitmap dst = Bitmap.createBitmap(out_w,out_h,Bitmap.Config.ARGB_8888);
		Canvas c = new Canvas(dst);
		Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setFilterBitmap(true);
		// ゼロフィルして
		c.drawARGB(0,0,0,0);
		// 角丸矩形を書いて
		paint.setColor(0xffffffff);
		c.drawRoundRect (rect_out,radius_x,radius_y,paint);
		// 転送モードを工夫してから
		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		// ビットマップをコピー スケーリングあり
		c.drawBitmap(src,rect_in,rect_out,paint);
		//
		return dst;
	}

注意点

Bitmapはネイティブヒープというリソースを消費していて、これが解放されるのはrecycleが呼ばれるか、finalizeが呼ばれるかした時です。ただしjavaではファイナライズが呼び出されることは保証されていません。

purgeable bitmap の場合はOS側が適当なタイミングでネイティブヒープ側のリソースを管理してくれます。BitmapFactory.decode* で作った場合かビットマップか、レイアウトXMLで指定したdrawable resourceから自動的にbitmap drawableが生成された場合はビットマップをpurgeable bitmap にすることができます。参照と解放がそれほど頻繁でない場合は、OSによるpurgeに頼っても特に問題はありません。

Bitmap#createBitmap や Bitmap#copy で作ったビットマップはpurgeable にはできないので、自動ではネイティブヒープの解放は行われません。参照されなくなったビットマップは必ずUI階層からの参照を切って明示的にrecycle()する必要があります。地味に管理と検証が面倒くさいです。

cron-apt で自動アップデート

cron-aptを使うと毎日だいたい決まった時間にパッケージの自動更新を行える。

インストール

apt-get install cron-apt

/etc/cron-apt/config を編集

デフォルトでは全項目がコメントアウトされているので、変更したい部分だけ変更する。

APTCOMMAND=/usr/bin/apt-get
MAILTO="tateisu@juggler.jp"
MAILON="changes"
DEBUG="changes"
OPTIONS="-o quiet=1"

/etc/cron-apt/action.d/3-download を編集

dist-upgrade の -d (ダウンロードのみでインストールしない) オプションを削る。

変更前

autoclean -y
dist-upgrade -d -y -o APT::Get::Show-Upgraded=true

変更後

autoclean -y
dist-upgrade -y -o APT::Get::Show-Upgraded=true

/etc/cron.d/cron-apt を編集

0 4     * * *   root    test -x /usr/sbin/cron-apt && /usr/sbin/cron-apt

のようにcrontabの設定が書かれている。
実際にはcron-aptは1時間以内のランダムな時間だけsleepしてから処理を開始するのだが、それでもサーバが複数ある場合にはもっと大きく時間帯をずらした方が良いかもしれない。

動作確認

  • /usr/sbin/cron-apt を実行して、送られてくるメールを見る
  • 変更がないとメールが送られてこないので、 /var/log/cron-apt/log を見る
  • 自動アップデートが発生した際に送られてきたメールを見る

質問の省略

パッケージのアップデートの際に設定ファイルの更新などで質問されることがある。自動更新ありの場合はデフォルトでは既存の設定が保持されることが多いので、その場合には質問が省略されるように設定すると自動更新が捗る。…が、この設定はやや危険かもしれない。

dpkg-reconfigure debconf を実行すると設定を変更できる。

# 質問に使われるインタフェース
Interface to use:
→ (今回の設定には影響しないので、変更しないこと)

# これより重要性が低い質問を省略する
Ignore questions with a priority less than: 
→ critical

メールを受け取らないサーバでのexim4の設定

unixユーザアカウントが1つか2つ、メールを外部に送ることはあっても内部のローカルメールなんか見ないよという場合のexim4の設定。目新しくはないけど、よくやる設定なのでメモしておく。

今回の例では myhostname が設定するサーバのホスト名で、 myhostname.local がメールサーバのドメイン名、 tateisu がサーバ上のメインユーザのアカウント名とする。

/etc/exim4/update-exim4.conf.conf を編集

dc_eximconfig_configtype='satellite'
dc_other_hostnames='myhostname.local'
dc_local_interfaces='127.0.0.1'
dc_readhost='myhostname.local'
dc_relay_domains=''
dc_minimaldns='true'
dc_relay_nets=''
dc_smarthost='external.smtp.server::26'
CFILEMODE='644'
dc_use_split_config='false'
dc_hide_mailname='true'
dc_mailname_in_oh='true'
dc_localdelivery='mail_spool'

dc_smarthost の部分に外部のSMTPサーバのホスト名とポート番号を書く。ポート番号の区切りがコロン2つで間違えやすい。

dpkg-reconfigure exim4-config

編集が終わったら dpkg-reconfigure exim4-config する。
質問が出るので以下のように答える。

# メール設定の種別
General type of mail configuration: 
→ mail sent by smarthost; no local mail

# このメールサーバのドメイン名
System mail name: 
→ myhostname.local

# SMTP 待ち受けアドレス
IP-addresses to listen on for incoming SMTP connections: 
→ 127.0.0.1

# ほか、このメールサーバがSMTPで受け取るメールのドメイン名
Other destinations for which mail is accepted:
→ myhostname.local

# ローカルメールを外部に送信する際にメールアドレスに付与するドメイン名
Visible domain name for local users:
→ myhostname.local

# メールを外部に転送する先のSMTPサーバのホストとポート
IP address or host name of the outgoing smarthost:  
→ rings.juggler.jp::26

# なるべくDNSクエリを減らして、不要な自動ダイアルアップを抑制する?
Keep number of DNS-queries minimal (Dial-on-Demand)?
→ Yes

# 設定ファイルを分割する?
Split configuration into small files? 
→ No

最後の2つの質問は今回の設定には影響しない。好きな方を選んで構わない。

設定が終わると自動的にexim4が再起動される

/etc/email-addresses を編集

ローカルユーザ宛のメールをどこに転送するかを記述する…のだが、これを使う送信先のサーバでリレー失敗が出てしまう問題があった。

/etc/aliases を編集

1ユーザしか作っていない、ほとんど素のdebianだとこんな感じ

mailer-daemon: postmaster
postmaster: root
nobody: root
hostmaster: root
usenet: root
news: root
webmaster: root
www: root
ftp: root
abuse: root
noc: root
security: root
root: tateisu
tateisu: tateisu@juggler.jp

最後の行だけを追加した。
編集が終わっても再起動は特に必要ない。

動作確認

# mail tateisu
Subject: test 5
hoge
(Ctrl-Dを押す)
Cc: 
(何も入れずにEnter)

これでメールが配送されればOK。
ダメなら /var/log/exim4/mainlog や 送信先SMTPサーバのログを確認する。

サーバ上のメインユーザ以外にもrootとpostmasterくらいは確認しておく。

node でIRCボットを書いてみた

書いてみた。フラッドプロテクションもちゃんと実装した。
http://dl.dropbox.com/u/10049046/node-ircclient.tgz

node v0.7.4で動作確認。追加で node-iconv モジュールが必要。

チャネル内のユーザがURLを書いたらそこにアクセスしてタイトルを読みに行くサンプルを書いてみたけど、HTTPで取ってきたデータの文字コードの推測に使えそうなモジュールがない。その部分だけ子プロセスでperlスクリプトを起動して誤魔化してしまった…。

crontabを使えるユーザを制限する

目新しい話でもないけど、忘れがちなのでメモ

/etc/cron.allow に許可するユーザ名を列挙するか、もしくは /etc/dron.deny に 禁止したいユーザ名を書いておく。なお、 /etc/cron.allow が存在する場合はたとえその内容が空でも /etc/dron.deny は参照されない。
どちらのファイルも、1行に1つずつユーザ名を書く。

デフォルト厳しめの設定で、そうでなくても少なくともwww-dataユーザは制限しておくべき