Conversation
8進数に変換したファイルモードの数値列から、lsコマンドで表示する文字列形式に変換するメソッド - ファイルの種類はfile_mode.ftypeから取得し、予め作成しているFILE_TYPEのhashから対応する文字をとってくる - ファイルの読み書き権限などは8進数数値列の4~6番目が対応しているため、その部分を取り出してFILE_MODEのhashから対応する文字列を取得した
ファイルモードの書き換えを実行するために、SPECIAL_MODEを作成、置き換える文字を定義 置き換えが発生するかどうかは8進数変換した場合の3文字目に存在するため、そこが'0'であればこの処理は実行されない
map関数でfile_pathひとつを送り、返り血としてファイルモードの情報を得る
| 'characterSpecial' => 'c', | ||
| 'directory' => 'd', | ||
| 'blockSpecial' => 'b', | ||
| 'file' => 'f', |
| SPECIAL_MODE.each do |mode| | ||
| if special_modes == mode[:bit] | ||
| permissions[mode[:index]] == 'x' ? mode[:exec] : mode[:no_exec] | ||
| end | ||
| end | ||
| permissions |
There was a problem hiding this comment.
スティッキービットなどの判別にもとりくまれているようですね 👍
ただ、うまく動いていないようです。手元で組み込みのlsでは s や T などになるファイルを作ってみましたが、判別できませんでした。
組み込みls(Linux環境)
合計 12
-rw-r--r-- 1 yoshitsugu yoshitsugu 21 2月 9 2023 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt
lrwxrwxrwx 1 yoshitsugu yoshitsugu 9 4月 20 2023 symlink1.txt -> test1.txt
-rw-r--r-- 1 yoshitsugu yoshitsugu 13 2月 9 2023 test1.txt
-rw-r--r-- 1 yoshitsugu yoshitsugu 0 2月 14 2023 test10.txt
-rw-r--r-- 1 yoshitsugu yoshitsugu 0 2月 9 2023 test111.txt
-rw-r--r-- 1 yoshitsugu yoshitsugu 30 2月 9 2023 test2.txt
-rw-r--r-- 1 yoshitsugu yoshitsugu 0 2月 7 2023 test3.txt
-rw-r--r-- 1 yoshitsugu yoshitsugu 0 2月 9 2023 test4.txt
-rw-r--r-- 1 yoshitsugu yoshitsugu 0 2月 9 2023 test5.txt
-rw-r--r-T 1 yoshitsugu yoshitsugu 0 1月 19 09:16 test6.txt
-rwxr-xr-t 1 yoshitsugu yoshitsugu 0 2月 9 2023 test7.txt
-rwsr-sr-x 1 yoshitsugu yoshitsugu 0 2月 9 2023 test8.txt
-rwSr--r-- 1 yoshitsugu yoshitsugu 0 2月 9 2023 test9.txt
今回実装してもらったもの
total 24
frw-r--r-- 1 yoshitsugu yoshitsugu 21 2 09 14:30 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt
lrwxrwxrwx 1 yoshitsugu yoshitsugu 9 4 20 08:02 symlink1.txt
frw-r--r-- 1 yoshitsugu yoshitsugu 13 2 09 14:29 test1.txt
frw-r--r-- 1 yoshitsugu yoshitsugu 0 2 14 08:41 test10.txt
frw-r--r-- 1 yoshitsugu yoshitsugu 0 2 09 14:30 test111.txt
frw-r--r-- 1 yoshitsugu yoshitsugu 30 2 09 14:29 test2.txt
frw-r--r-- 1 yoshitsugu yoshitsugu 0 2 07 07:35 test3.txt
frw-r--r-- 1 yoshitsugu yoshitsugu 0 2 09 14:29 test4.txt
frw-r--r-- 1 yoshitsugu yoshitsugu 0 2 09 14:29 test5.txt
frw-r--r-- 1 yoshitsugu yoshitsugu 0 1 19 09:16 test6.txt
frwxr-xr-x 1 yoshitsugu yoshitsugu 0 2 09 14:29 test7.txt
frwxr-xr-x 1 yoshitsugu yoshitsugu 0 2 09 14:29 test8.txt
frw-r--r-- 1 yoshitsugu yoshitsugu 0 2 09 14:30 test9.txt
There was a problem hiding this comment.
指摘ありがとうございます。
確認したところ、権限の判別はできていたのですが、その後の文字列に対して反映する処置が正しくありませんでした。失礼しました。
現在、手元で確認のための環境を作成し、正常に動作していることを確認しました。
実行例に関しては課題ページに追記する形で反映しておきます。
| file_mode = FILE_TYPE[file_stat.ftype].to_s | ||
| file_permissions = file_mode_octal.slice(3..-1).chars.map { |char| FILE_MODE[char] }.join | ||
| # 特殊権限の確認 | ||
| file_permissions = apply_special_modes(file_mode_octal[2], file_permissions) if file_mode_octal[2] != '0' |
There was a problem hiding this comment.
特殊権限もowner, group, otherの3通りチェックしないといけないですね。
There was a problem hiding this comment.
このコードでは最初に特殊権限なしの0であるかどうかを判定し、0であった場合はスキップするように書いていました。
実際のowner, group, otherの3通りのチェックはapply_special_modesでやっているのですが、
if文の判定の位置と相まって少し処理の流れがわかりづらいと考えたので、0を弾く判定をapply_special_modes内に移動しました。
コード自体はほぼ手を加えていませんが、私としてはapply_special_modesで3通りのチェックが実行できていると考えています。
フィヨルドに載せている実行結果においても、本家lsコマンドとの実行結果に違いはないように見られるのですが、もし現状でチェックしきれていないことがあるのであればコメントいただけるとありがたいです。
There was a problem hiding this comment.
@1mori なるほど。現状認知している問題としては、組み込みのlsで
-rwsr-sr-x 1 yoshitsugu yoshitsugu 0 2月 9 2023 test8.txt
となるものに対して
-rwxr-xr-x 1 yoshitsugu yoshitsugu 0 2 09 14:29 test8.txt
となっています。 s の表示ロジックがおかしいのかもしれませんね。
There was a problem hiding this comment.
指摘ありがとうございます。
前提として、特殊権限は1つしか付与できないと勘違いした状態で実装をしておりました。
そのため、8進数変換された状態で特殊権限の完全一致検索(1か2か4)をしていたため、SUID+GUID(8進数変換された数値では'6')などを検知できないジックで実装していました。
このような場合2進数のビット演算で実装するのが適しているとは思いますが、今回は変換の手間を削減するため、8進数(処理上は10進数)のまま処理を行いました。
0, 1, 2, 4の判定はapply_special_modes内で行った方が処理としてわかりやすいと考えたから
特殊権限は1つしか付与できないと勘違いしていたため、それぞれの権限の確認を1回ずつしかしてこなかった 今回は特殊権限をSUID(4), GUID(2), Sticky Bit(1)の順で確認し、存在していた場合は数値を減算するロジックを組んだ このような計算であれば2進数の方が適しているが、今回はわかりやすさのために8進数変換された状態(コードは10進数)で計算するようにした
| return permissions if special_modes.zero? | ||
|
|
||
| SPECIAL_MODE.each do |mode| | ||
| next unless special_modes >= mode[:bit] |
There was a problem hiding this comment.
細かいですが、
next if special_modes < mode[:bit]
のほうが見やすいかなと思いました。
| next unless special_modes >= mode[:bit] | ||
|
|
||
| special_modes -= mode[:bit] | ||
| permissions[mode[:index]] = if permissions[mode[:index]] == 'x' | ||
| mode[:exec] | ||
| else | ||
| mode[:no_exec] | ||
| end |
There was a problem hiding this comment.
書いてもらってもいますが、ビット演算のほうが簡単じゃないですか?
ある程度の大きさまでの整数であれば Fixnum クラスとなり、これは & でビット演算の論理積ができます。
https://docs.ruby-lang.org/ja/2.1.0/method/Fixnum/i/=26.html
たとえば3ビット目が1のもの(4)を確認したかったら、 special_modes & 4 > 0 で大丈夫です。
There was a problem hiding this comment.
確かに論理積を使うと計算量が削減されてすっきりと書けました。指摘ありがとうございます!
&を用い、ビット演算の論理積で2進数ごとの桁の判定を行った
関連ページ
https://bootcamp.fjord.jp/practices/224
最終更新
2024/06/20
やりたいこと
-lオプションの実装やったこと
-lオプションが指定されているときとそれ以外でif文で分岐をしたtotal xxxの形で出力したljust,rjustで列を揃えたapply_special_modesで文字列に変更を加える処理を追加した