HPCメモ

HPC(High Performance Computing)に関連したりしなかったりすることのメモ書き

node.jsのfs.Statsからファイルのパーミッションを読み取る

node.jsのfs.stat, fs.lstat, fs.fstatが返すfs.Statsクラスには、その名もずばりのmodeというpropertyがあるのですが、この値からファイルのパーミッションを直接知る手段が標準では用意されていません。1 まーそんなに難しい話ではないので、頭の体操がてらちょちょいとコードを書いてみましょう。

まず、fs.Stats.modeの値の正体ですが、これはそのまんまstat(), lstat(), fstat()が返すstat構造体のst_modeフィールドの値と同じようなので、下位の(8進数で)3桁をマスクしてやれば通常のパーミッションが値として取得できます。 javascriptでのbit演算はCと同じで、&がbit-wise ANDなのでmode & maskとすればOKです。

developer.mozilla.org

ただし、modeの値は10進数だけど、我々が普段使っているumask値は8進数なので、この変換を行う必要があります。 といっても、parseInt関数を使えばOKでparseInt(777,8)で下位3桁のmaskが作れます。 もしスティッキービットとかも必要だったら7777にすればOKです。

developer.mozilla.org

これで、ファイルのパーミッションが10進数の整数値として取得できたので、最後に8進数の表現に直します。 こちらも、javascriptの標準の範囲内でできてしまって、toString()に引数として8を渡してあげればOKです。

developer.mozilla.org

この3つを組み合わせて、カレントディレクトリのファイルのパーミッションを8進数で表示するプログラムを作るとこんな感じになります。

const {promisify} = require('util');
const fs = require('fs');

async function getFileMode(filename){
  let stats = await promisify(fs.stat)(filename);
  return (stats.mode & parseInt(777, 8)).toString(8);
}

async function main(){
  let files = await promisify(fs.readdir)('./');
  files.forEach(async (file)=>{
    console.log(file, await getFileMode(file));
  });
}

main();

テスト結果

$ ls -l .
total 8
---xrwxrwx  1 so5  staff    0 12 13 23:06 file177
--w-rwxrwx  1 so5  staff    0 12 13 23:07 file277
--wxrwxrwx  1 so5  staff    0 12 13 23:07 file377
-r--rwxrwx  1 so5  staff    0 12 13 23:06 file477
-r-xrwxrwx  1 so5  staff    0 12 13 23:08 file577
-rw-rwxrwx  1 so5  staff    0 12 13 23:07 file677
-rwx--xrwx  1 so5  staff    0 12 13 23:11 file717
-rwx-w-rwx  1 so5  staff    0 12 13 23:11 file727
-rwx-wxrwx  1 so5  staff    0 12 13 23:11 file737
-rwxr--rwx  1 so5  staff    0 12 13 23:11 file747
-rwxr-xrwx  1 so5  staff    0 12 13 23:11 file757
-rwxrw-rwx  1 so5  staff    0 12 13 23:11 file767
-rwxrwx--x  1 so5  staff    0 12 13 23:11 file771
-rwxrwx-w-  1 so5  staff    0 12 13 23:11 file772
-rwxrwx-wx  1 so5  staff    0 12 13 23:11 file773
-rwxrwxr--  1 so5  staff    0 12 13 23:11 file774
-rwxrwxr-x  1 so5  staff    0 12 13 23:11 file775
-rwxrwxrw-  1 so5  staff    0 12 13 23:11 file776
-rwxrwxrwx  1 so5  staff    0 12 13 23:11 file777
-rw-r--r--  1 so5  staff  378 12 13 23:35 test.js
$ node test.js 
file177 177
file277 277
file377 377
file477 477
file577 577
file677 677
file717 717
file727 727
file737 737
file747 747
file757 757
file767 767
file771 771
file772 772
file773 773
file774 774
file775 775
file776 776
file777 777
test.js 644

10進数->8進数(もちろん2進数や16進数も)の変換にtoStringを使うっていうのは違和感がありますが、JSだと10進数以外の整数は文字列として表すしかないから当然といえば当然かもしれませんが。


  1. fs.accessの方は引数にパーミッションの条件を指定できるので、ファイルのパーミッションが見たけりゃstat系じゃなくてこっちを使ってねってことかと思いますが。