システム・プログラム
電子・情報工学系
新城 靖
<yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/syspro-2000/2000-05-01
/file-attr.html
あるいは、次のページから手繰っていくこともできます。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/
http://www.is.tsukuba.ac.jp/~yas/index-j.html
----------------------------------------------------------------------
1: /*
2: ystat.c -- stat システム・コールのシェル・インタフェース
3: ~yas/syspro1/file/ystat.c
4: $Header: /home/lab2/OS/yas/syspro1/file/RCS/ystat.c,v 1.4 1998/05/18 13:20:36 yas Exp $
5: Start: 1995/03/07 20:59:12
6: */
7:
8: #include <sys/types.h> /* stat(2) */
9: #include <sys/stat.h> /* stat(2) */
10: #include <sys/sysmacros.h> /* major(), minor() */
11: #include <stdio.h>
12:
13: #if 0
14: struct stat {
15: dev_t st_dev;
16: long st_pad1[3]; /* reserved for network id */
17: ino_t st_ino;
18: mode_t st_mode;
19: nlink_t st_nlink;
20: uid_t st_uid;
21: gid_t st_gid;
22: dev_t st_rdev;
23: long st_pad2[2]; /* dev and off_t expansion */
24: off_t st_size;
25: long st_pad3; /* future off_t expansion */
26: timestruc_t st_atim;
27: timestruc_t st_mtim;
28: timestruc_t st_ctim;
29: long st_blksize;
30: blkcnt_t st_blocks;
31: char st_fstype[_ST_FSTYPSZ];
32: long st_pad4[8]; /* expansion area */
33: };
34: #endif
35:
36: extern void stat_print( char *path );
37:
38: main( int argc, char *argv[] )
39: {
40: if( argc != 2 )
41: {
42: fprintf( stderr,"Usage:%% %s filename \n",argv[0] );
43: exit( 1 );
44: }
45: stat_print( argv[1] ); /* 引数はファイル */
46: }
47:
48: void stat_print( char *path )
49: {
50: struct stat buf ;
51: if( stat( path,&buf ) == -1 )
52: {
53: perror( path );
54: exit( 1 );
55: }
56:
57: printf("path: %s\n",path );
58: printf("dev: %d,%d\n",major(buf.st_dev),minor(buf.st_dev) );
59: printf("ino: %d\n",buf.st_ino );
60: printf("mode: 0%o\n",buf.st_mode );
61: printf("nlink: %d\n",buf.st_nlink );
62: printf("uid: %d\n",buf.st_uid );
63: printf("gid: %d\n",buf.st_gid );
64: printf("rdev: %d,%d\n",major(buf.st_rdev),minor(buf.st_rdev) );
65: printf("size: %d\n",buf.st_size );
66: printf("atime: %s",ctime(&buf.st_atime) );
67: printf("mtime: %s",ctime(&buf.st_mtime) );
68: printf("ctime: %s",ctime(&buf.st_ctime) );
69: printf("blksize: %d\n",buf.st_blksize );
70: printf("blocks: %d\n",buf.st_blocks );
71: }
----------------------------------------------------------------------
この実行結果から次のようなことがわかる。---------------------------------------------------------------------- % ./ystat ystat.cpath: ystat.c dev: 8,3 ino: 17639075 mode: 0100644 nlink: 1 uid: 1231 gid: 40 rdev: 0,0 size: 1767 atime: Mon May 18 22:20:44 1998 mtime: Mon May 18 22:20:44 1998 ctime: Mon May 18 22:20:44 1998 blksize: 8192 blocks: 4 % /sbin/stat ystat.c
ystat.c: inode 17639075; dev 2097155; links 1; size 1767 regular; mode is rw-r--r--; uid 1231 (yas); gid 40 (lab) st_fstype: nfs3 change time - Mon May 18 22:20:44 1998 <895497644> access time - Mon May 18 22:20:44 1998 <895497644> modify time - Mon May 18 22:20:44 1998 <895497644> %
----------------------------------------------------------------------
0100644の上位4ビット、つまり、0170000と AND (C言語のでは、
&演算子)をとった結果は 0100000 となる。この値は、普通のファ
イル(regular file)を意味する。ディレクトリの場合、0040000 となる。こ
れらの数は、
----------------------------------------------------------------------
#define S_IFMT 0xF000 /* type of file */
#define S_IFIFO 0x1000 /* fifo */
#define S_IFCHR 0x2000 /* character special */
#define S_IFDIR 0x4000 /* directory */
#define S_IFBLK 0x6000 /* block special */
#define S_IFREG 0x8000 /* regular */
#define S_IFLNK 0xA000 /* symbolic link */
#define S_IFSOCK 0xC000 /* socket */
#define S_ISFIFO(mode) ((mode&S_IFMT) == S_IFIFO)
#define S_ISCHR(mode) ((mode&S_IFMT) == S_IFCHR)
#define S_ISDIR(mode) ((mode&S_IFMT) == S_IFDIR)
#define S_ISBLK(mode) ((mode&S_IFMT) == S_IFBLK)
#define S_ISREG(mode) ((mode&S_IFMT) == S_IFREG)
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
----------------------------------------------------------------------
プログラム中では、次のようにしてファイルの型を調べることができる。
----------------------------------------------------------------------
switch( buf.st_mode & S_IFMT )
{
case S_IFREG:
ファイルの時の処理;
break;
case S_IFDIR: ...
ディレクトリの時の処理;
break;
....
}
----------------------------------------------------------------------
あるいは、
----------------------------------------------------------------------
if( S_ISREG(buf.st_mode) )
{
ファイルの時の処理;
}
else if( S_ISDIR(buf.st_mode) )
{
ディレクトリの時の処理;
}
----------------------------------------------------------------------
モードの下位9ビット(上の例では、8進数で 644 )は、許可されたアクセス 方法を表している。その9ビットは、3ビットづつに区切られおり、上位から 所有者(owner)、グループ(group)、その他(others)に許可(permission) されているアクセス方式を表している。所有者(owner)の代りに、利用者 (user)という言葉が使われることもある。
各3ビットは次の様なアクセス方法が許可されていることを意味する。
---------------------------------------------------------------------- ls -l 3ビット値 アクセス権 ---------------------------------------------------------------------- r 4 読込み可能 w 2 書込み可能 x 1 実行可能(ディレクトリの場合は、検索可能) ----------------------------------------------------------------------このように、普通のファイルとディレクトリで "x" の意味が異なる。
ls -l では、3つの時刻のうち、どの時刻が表示されているのかを調べなさい。 また、他の2つの時刻を表示させる方法を調べなさい。
myls-l の結果の表示形式は、ls -l と完全に一致しなくてもよい。たとえば、 時刻の表示は、上の ystat.c の結果と同じでもよい。 localtime()やstrftime() ライブラリ関数 を利用すると、時刻の表示をより簡単に ls -l の 表示に近づけることができるであろう。
uid (st_uid) については、ls -l では、ユーザ名(ログイン名)で表示され る。myls-l では、数字のままでよい。ライブラリ関数 getpwuid() を使えば、 UID からユーザ名を調べることができる。 ~yas/syspro1/proc/proc-uid-print.c にあるuid2uname(), gid2gname() を参 考にするとよい。
プログラムの引数となるファイルの数は、1個とする。複数のファイルについ て、ls -l と同様の表示をするように拡張してもよい。
引数としてディレクトリの名前が与えられた場合にも、ディレクトリの内容で はなくディレクトリ自身の属性を表示する。シンボリック・リンクには対応し なくてもよい。(よって正確には、ls -l filename ではなく、ls -ldL filename である。)
余裕があれば、lstat() と readlink() の、2つのシステム・コールを用いて、 ls -l と同じようにシンボリック・リンクの内容を表示しなさい。
さらに、opendir(3) や scandir(3) を使って、ディレクトリの内容を表示 するようにしてもよい。
% access_check filename user readでは、ユーザ名(または、UID)が user のユーザがfilename で与えられたファ イルを読むことができるかどうかを調べる。user は、番号(UID)かユーザ名で 与える。アクセス方法には、次のようなものがある。