今回は自作lsコマンドに-lオプションを付けて

アクセス権限やユーザ名、グループ名などを表示するlsライクなプログラムを作りました。

今回はやるべきことを分けて紹介します
目次の方から飛んでみていただければと思います。

以下に、コードを載せます。

 

 Main関数内

16行目からmain関数です。

オプション"-l"を付ける場合、つけない場合、

ディレクトリを指定する場合、指定しない場合で4通りの分岐をさせました。

ディレクトリを指定しない場合

lsだけ打つ時です。

21行目で、コマンドライン引数が1つだけの場合はカレントディレクトリの内容を表示するために、do_ls関数には"."を引数にして渡します。

ディレクトリを指定しない場合(-lオプション)

ls -lだけ打つ時です。

23行目、argv[1]が"-l"で、ディレクトリの指定がない場合

つまり ls -l の時も

do_lsl関数に"."を渡します。

ディレクトリを指定する場合(-lオプション)

26行目、条件はargv[1]が-lであることだけです。

よって引数の数が何個でもokです。

$ls -l . dir1 dir2

と入力した場合の処理をここでします。

27行目のfor文で分かるように

argv[2]から順番にdo_lsl関数を実行していきます。

ディレクトリを指定する場合

31行目からです。

やっていることは一つ前のと同じことです。

さて、関数に入っていきます。

ディレクトリを読み込んで表示する(通常のlsコマンド)

ディレクトリを読み込んで表示するのは

do_lsでもdo_lslでも同じ処理です。

37行目からですね。

  1. ディレクトリpathをdにオープンする。
  2. readdir(d)でディレクトリ内のファイル,ディレクトリをentに読み込む。
  3. printfで名前を表示

 

pathディレクトリのストリームが終わると

readdirはNULLを返すので

while(ent=readdir(d))としています。

40行目のchar point[1]="."

というのは

通常、lsコマンドでは"."から始まるディレクトリは特別扱いされ、表示されないのでそれ用に宣言します。

49行目のwhileでディレクトリ名を表示する前に

"."チェックを行い、真ならばcontinueで

printfを行わずにループの初めに戻ります。

構造体struct direntの構造体はこのようになっています。

 

いくつかメンバがありますが今回使うのは

d_name[256]のみです。

lsはこんなに簡単にできてしまいます。

アクセス権限を表示する

オプション-lについてはここからになります。

アクセス制限を表示させるために

stat構造体 / マクロ

を使いました。

構造体のメンバはこのようになっています。

 

太字のメンバが今回使用したものです。

st_modeにはファイルやアクセス権限についての情報が入っていてS_IFMTとビット積を取ると

それがディレクトリかファイルか分かります。

103行目 (buf.st_mode & S_IRWXU) & S_RUSUR

について

buf.st_mode&S_IRWXUをすると

bufの"ファイル所有者" のアクセス権限について

ファイルの読み、書き、実行の順に

権限ありなら1,無しなら0という値がかえります。

返ってきた値とS_RUSURをすると

読みの権限があれば1が返ってきて

printf("r")を表示します。

同様に、w,xも勧めて行って、権限があるかないかいで"w"や"-","x"と表示出来ます。

ちょっとここは自信がないのですが

buf.st_modeは

111 101 110みたいになっていて(所有者/グループ/他人)

ビットマスクをすると

110 101  110

&  S_RUSUR  (所有者についてのビットマスク)

(111 000 000だと思われる)

----------------------

110  000 000

自分が調べたい範囲(所有者やグループ)のアクセス権限に応じて

マスクの値が変わっているんだろうなぁ、という認識です。

正直、まだまだ理解が浅くてうまく説明できていません。

参考にしたサイトをそれぞれ挙げていきます。

Man page of STAT

 

ユーザ名、グループ名を表示する

まず

 #include<pwd.h>

#include<grp.h>

をします。

これをしていなかったせいで2時間くらい時間ロスしたのを思い出しました。忘れないように.

123.124行目で完結しています。

ちょっとややこしくなっていますね。

一つずつ読み解いてきましょう。

まず、buf.st_uid

これはstat構造体の中にある

所有者のユーザIDを示す値が入っています。

ユーザIDです。ユーザ名ではありません。

ユーザIDからユーザ名を取得するために

getpwuidを使います。

getpwuidはユーザ名が入っている構造体へのポインタを戻り値とします。

構造体のメンバにpw_nameというユーザ名があるのでgetpwuidの後にアロー演算子を使って

ユーザ名を表示しています。

グループ名も同様です。

参考にしたサイトがこちらです

IBM Knowledge Center

最終修正時刻を表示する

こちらもまたstat構造体のst_mtimeというメンバに入っています。

ただ、ここに入っているのは時間の数字なので

ctimeで数字から文字列に変換します

(MayとかSatへ)

問題となったのがctime関数

こいつは最後に無条件で'\n'を入れてしまいます。

ls -lコマンドでは1行で表示するため

改行は不要なのです。

そこで考えたのが

改行の手前まで別の配列にコピーする

です。

月日 曜日 時間

はどのファイルも文字数は同じです。

なのですべてのファイルの最終修正時刻

ctime(&buf.st_mtime)について

24文字目まで他の配列にコピーして表示しました。

これにて完成です。

実行結果を示しておきます。

$ ./myls
file
file2
file3
kadai2
kadai207.o
mycat
mycat.c
mycat.o
myhead
myhead.c
myhead.o
myls
myls.c
myls.o
pra
pra.c
report
whoami.c

$ ./myls -l
total 200
-r-xr-xr-x 1 root root 117 Sat May 5 19:15:22 2018 file
-rwxrwxrwx 1 root root 115 Sat May 5 19:18:07 2018 file2
-rwxrwxrwx 1 root root 232 Sat May 5 19:18:40 2018 file3
drwxrwxrwx 0 root root 512 Wed Jun 6 18:20:42 2018 kadai2
-rwxrwxrwx 1 root root 2303 Mon May 7 17:50:53 2018 kadai207.o
-rwxrwxrwx 1 root root 9008 Wed May 16 14:30:53 2018 mycat
-r-xr-xr-x 1 root root 2093 Wed May 16 14:30:50 2018 mycat.c
-rwxrwxrwx 1 root root 1583 Wed May 16 14:30:50 2018 mycat.o
-rwxrwxrwx 1 root root 9280 Sun May 6 15:37:18 2018 myhead
-rwxrwxrwx 1 root root 1018 Sun May 6 15:36:47 2018 myhead.c
-rwxrwxrwx 1 root root 1685 Sun May 6 15:36:47 2018 myhead.o
-rwxrwxrwx 1 root root 13504 Sat Jun 9 13:46:01 2018 myls
-rwxrwxrwx 1 root root 2952 Sat Jun 9 13:45:59 2018 myls.c
-rwxrwxrwx 1 root root 1362 Sun May 6 23:21:41 2018 myls.o
-rwxrwxrwx 1 root root 8928 Sun May 13 14:52:32 2018 pra
-r-xr-xr-x 1 root root 1516 Sun May 13 14:47:45 2018 pra.c
drwxrwxrwx 0 root root 512 Fri Jun 1 15:21:02 2018 report
-rwxrwxrwx 1 root root 165 Sun May 13 08:25:52 2018 whoami.c

作成に参考にした本も載せておきます。

ふつうのLinuxプログラミング

前半ではシステムコールやプロセス、ストリーム、標準入出力など、初学者に対して曖昧さで殴ってくる部分がわかりやすく書いてあります。

後半ではHTTPサーバを実装するためにのあれこれなどネットワークプログラミングにつて触れてあります。

図やプログラムが多めなので、文字だけで理解するのが難しいという方にお勧めです。

 

おすすめの記事
SponsoredLink