Operating Systems. Exercise 12
ファイルにはそれぞれパーミッションや更新日時などの情報が付加されており,
OSが管理するファイルシステムがユーザにそれらの情報を提供します。
C言語にはファイル情報を取得する仕組みが用意されています。
それを使って, ファイルパーミッション, 所有者名, 所属グループ名, ファイルサイズ,
更新日時などの情報を取得することが出来ます。
以下のプログラムの流れを読んで、処理を理解してください。
FileStat.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
void PrintInfo(char *);
void PrintFileInfo(struct stat *pStat);
void PrintPermission(struct stat *pStat);
void PrintNumDirectories(struct stat *pStat);
void PrintUserInfo(struct stat *pStat);
void PrintGroupInfo(struct stat *pStat);
void PrintSize(struct stat *pStat);
void PrintFileAccessTime(struct stat *pStat);
int main (int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr,"usage:\n\t%s filename or\n\t%s directory_name\n", argv[0], argv[0]);
exit(1);
}
PrintInfo(argv[1]);
return 0;
}
void PrintInfo(char *sPath) {
//fileStatのアドレスを渡して, fileStatに"sPath"で渡されたファイル情報を格納する
struct stat fileStat;
int nStat = stat(sPath, &fileStat);
if (nStat != 0) {
printf("stat failed.... (parameter=[%s])\n", sPath);
exit(1);
}
//与えられた"sPath" が 通常ファイルでもディレクトリでもなければexitする
if ( !(fileStat.st_mode & S_IFREG) && !(fileStat.st_mode & S_IFDIR) ){
printf("%s seems neither a regular file nor a directory\n", sPath);
exit(1);
}
printf("FileName = %s\n", sPath);
PrintFileInfo(&fileStat);
}
void PrintFileInfo(struct stat *pStat) {
PrintPermission(pStat);
PrintNumDirectories(pStat);
PrintUserInfo(pStat);
PrintGroupInfo(pStat);
PrintSize(pStat);
PrintFileAccessTime(pStat);
}
void PrintPermission(struct stat *pStat) {
char sPermissionString[11] = "----------";
if (pStat->st_mode & S_IFDIR) sPermissionString[0] = 'd'; //ディレクトリか否か
if (pStat->st_mode & S_IRUSR) sPermissionString[1] = 'r'; //userに読み込み許可があるか
if (pStat->st_mode & S_IWUSR) sPermissionString[2] = 'w'; //userに書き込み許可があるか
if (pStat->st_mode & S_IXUSR) sPermissionString[3] = 'x'; //userに実行許可があるか
if (pStat->st_mode & S_IRGRP) sPermissionString[4] = 'r';
if (pStat->st_mode & S_IWGRP) sPermissionString[5] = 'w';
if (pStat->st_mode & S_IXGRP) sPermissionString[6] = 'x';
if (pStat->st_mode & S_IROTH) sPermissionString[7] = 'r';
if (pStat->st_mode & S_IWOTH) sPermissionString[8] = 'w';
if (pStat->st_mode & S_IXOTH) sPermissionString[9] = 'x';
printf("\tpermission = %12s\n", sPermissionString);
}
void PrintNumDirectories(struct stat *pStat) {
//pStatで状態を取得した"パス"の 子ディレクトリ/子ファイルの数("パス"がファイルの場合は1)
printf("\tdirectories = %ld\n", (long)pStat->st_nlink);
}
void PrintUserInfo(struct stat *pStat) {
//uid(ユーザID)に相当するユーザ情報をpPasswdに受け取る
struct passwd *pPasswd = getpwuid(pStat->st_uid);
//ユーザ情報のうちユーザ名とuidを出力する
printf("\tuser name = %8s (uid=%d)\n", pPasswd->pw_name, pStat->st_uid);
}
void PrintGroupInfo(struct stat *pStat) {
struct group *pGroup = getgrgid(pStat->st_gid);
printf("\tgroup name = %8s (gid=%d)\n", pGroup->gr_name, pStat->st_gid);
}
void PrintSize(struct stat *pStat) {
printf("\tsize = %lld bytes\n", (long long)pStat->st_size);
}
void PrintFileAccessTime(struct stat *pStat) {
//最終アクセス日時をstruct tm型に変換して受け取る
struct tm *pLastAccess = localtime(&(pStat->st_atime));
//最終更新日時をstruct tm型に変換して受け取る
struct tm *pLastModify = localtime(&(pStat->st_mtime));
//最終ファイル情報修正日時をstruct tm型に変換して受け取る
struct tm *pLastStatChange = localtime(&(pStat->st_ctime));
printf("\tLast access = %s", asctime(pLastAccess));
printf("\tLast modify = %s", asctime(pLastModify));
printf("\tLast stat change = %s", asctime(pLastStatChange));
}
II. ファイル情報表示 (配点100%)
導入: お馴染みの"ls -l"コマンドは引数として与えられたファイルの情報を表示します
コマンド
% ls -l FileStat.c
結果
-rw------- 1 user group 3758 8 17 18:08 FileStat.c
表示される情報は左から
"パーミッション",
"子ディレクトリ数"(ファイルの場合1),
"所有者名",
"所属グループ名", 課題
stat関数で得た情報を使って, 引数として与えられたファイルの情報を"ls -l"と同じ形式で出力するプログラム"lsl"を
作成してください。
ただし, 引数にはファイルのみが与えられるとします。
例:
コマンド
% ./lsl FileStat.c
結果
-rw------- 1 user group 3758 8 17 18:08 FileStat.c
補足
struct tm型は以下のメンバ変数を保持しています
struct tm {
int tm_sec; // 秒
int tm_min; // 分
int tm_hour; // 時
int tm_mday; // 日
int tm_mon; // 月( 1月=0 )
int tm_year; // 西暦年 - 1900
int tm_wday; // 曜日( 日=0 )
int tm_yday; // 日(年を通して)
int tm_isdst; // サマータイムフラグ
};