サブフィールドコーディング
ビット演算でマスキングしてファイル種別を判定する方法を紹介します。
マスキング
次のような郵便番号があります。
100-6002 100-6009 100-6090 101-0029 101-0063 ...
100-6002、100-6009と100-6090は東京都千代田区霞が関霞が関ビルを表わしています。
これは100-60XXという事から判断ができます。
上記のような郵便番号から霞が関ビルを表わす番号を調べる場合は、先頭の5ケタ以外を0に変換してからそれが100-6000と一致するかどうかを考える事ができます。
このように、必要でない数字を0に置き換えて、必要なフィールドだけが見える状態にすることをマスキングと呼びます。
マスキングとビット演算
ビット演算を使うと次のようにマスキングを行う事ができます。
サンプルコード
#!/usr/bin/perl use strict; use warnings; my $hoge = "1_010"; my $fuga = "1_100"; print $hoge & $fuga, "\n"; my $foo = "0_110_101_101"; my $bar = "0_110_000_000"; print $foo & $bar, "\n";
実行
:!perl %
1_000
0_110_000_000
8進法にする
2進法の3桁の整数を、1桁の8進法にまとめると人間に優しくなるそうです。
my $foo = "0755"; my $bar = "0700"; print $foo & $bar;
:!perl mask1.pl 0700
どこかで見たことがある数値だと思いますが、その他ユーザーがこのファイルを実行できるか、という判定をするアレです。
#!/usr/bin/perl use strict; use warnings; my $foo = "0755"; my $bar = "0001"; print $foo & $bar;
:!perl % 0001
ということでマスキングはわりと身近で使われる処理ということです。
ファイルタイプ解読
stat構造体
stat構造体はsys/stat.h(もしかしたらbits/stat.h)に記述があり、次のメンバで構成されています。
st_mode | タイプとパーミッション |
st_uid | オーナーのID |
st_gid | グループのID |
st_size | ファイルのバイト数 |
st_nlink | ファイルに対するリンクの数 |
st_mtime | 最終変更日時 |
st_atime | 最終アクセス日時 |
st_ctime | 最終プロパティ変更日時 |
ファイル種別
Linuxでは以下のファイル種別が存在します。
これはst_modeの最初の4ビットで表現されています。
具体的には次のような処理で判定できます。
#!/usr/bin/perl use strict; use warnings; =pod SEE ALSO: sys/stat.h and bits/stat.h =cut my $s_ifmt = 0170000; # ファイルのタイプ my $s_ifreg = 0100000; # 通常 my $s_ifdir = 0040000; # ディレクトリ my $s_ifblk = 0060000; # ブロックデバイス my $s_ifchr = 0020000; # キャラクタデバイス my $s_ififo = 0010000; # FIFO(名前付きパイプ) my $s_iflnk = 0120000; # シンボリックリンク my $s_ifsock = 0140000; # ソケット print "this is regular file\n" if is_reg(100664); sub is_reg { my $mode = shift; return ($mode & $s_ifmt) == $s_ifreg ? 1 : 0; }
とりあえずst_modeの先頭4bitを調べるだけで、ファイルの種別を判定する事ができました。ほかにもsuid,sgid,スティッキービット、ユーザー権限、グループ権限、その他ユーザー権限の情報もst_modeにふくまれています。
というわけでサブフィールドコーディングと呼ばれる手法をかけあしで紹介しました。