ファイルの属性、アクセス制御

システム・プログラムI

                                       電子・情報工学系
                                       新城 靖
                                       <yas@is.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/syspro1-1998/1998-05-19
あるいは、次のページから手繰っていくこともできます。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/
http://www.hlla.is.tsukuba.ac.jp/~yas/index-j.html

■復習

レポートは、yas ではなくsyspro へ。

Subject: には、report1, report2 のように、番号を振るように。 report0 は不可。

プログラムを書く時に、実際に動く小さいプログラムの断片は、便利である。 日頃から自分で収集するといい。

コマンドがどんなどのシステム・コールを使っているかは、マニュアルの末尾 の SEE ALSO に出ている。

バッファ・オーバーランのバグ。

たとえば、100 バイトのメモリ領域しか割り当てていない時に、それ以上のメ モリを利用してしまうこと。インターネットからアクセスされるプログラムで は、このバグが狙われる。gets() や scanf(), sscanf() での %s、strcpy() などが危険。バイト数をチェックしない。

Java では、この問題は起きない。

■時刻の表現

UNIX では、時刻を 1970年1月1日0:00:00(GMT)からの秒数で表わす。 日付も時間も1つの変数で表わせるので、比較が簡単。 しかし、閏秒に弱い。
----------------------------------------------------------------------
   1:	/*
   2:	        get-time.c -- 現在の時刻を表示するプログラム。
   3:	        ~yas/syspro1/time/get-time.c
   4:	        $Header: /home/lab2/OS/yas/syspro1/time/RCS/get-time.c,v 1.2 1998/05/18 14:18:20 yas Exp $
   5:	        Start: 1998/05/18 22:29:17
   6:	*/
   7:	
   8:	#include <sys/types.h>  /* time(2) */
   9:	#include <time.h>       /* time(2) */
  10:	
  11:	/*
  12:	typedef long    time_t;
  13:	time_t time(time_t *tloc);
  14:	*/
  15:	
  16:	main()
  17:	{
  18:	    time_t t ;
  19:	        t = time( 0 );
  20:	        printf("%d: %s",t,ctime(&t) );
  21:	        t ++ ;
  22:	        printf("%d: %s",t,ctime(&t) );
  23:	        t = 0 ;
  24:	        printf("%d: %s",t,ctime(&t) );
  25:	}
----------------------------------------------------------------------

----------------------------------------------------------------------
% date [←]
1998年 5月18日(月曜日) 22時40分33秒 JST
% ./get-time [←]
895498835: Mon May 18 22:40:35 1998
895498836: Mon May 18 22:40:36 1998
0: Thu Jan  1 09:00:00 1970
% printenv TZ [←]
JST-9
% unsetenv TZ [←]
% date [←]
1998年 5月18日(月曜日) 13時41分03秒 GMT
% ./get-time [←]
895498869: Mon May 18 13:41:09 1998
895498870: Mon May 18 13:41:10 1998
0: Thu Jan  1 00:00:00 1970
% []
----------------------------------------------------------------------

環境変数 TZ で、ctime(3) ライブラリ関数の動きが変わる。

■ユーザの表現

IRIX では、ユーザを32ビット(伝統的なUNIXでは16ビット)の整数で表わす。 この整数を UID と呼ぶ。プロセスやファイルには、属性としてUID がある。
----------------------------------------------------------------------
   1:	/*
   2:	        proc-uid-print.c -- 現在のプロセスのUIDを表示するプログラム。
   3:	        ~yas/syspro1/proc/proc-uid-print.c
   4:	        $Header: /home/lab2/OS/yas/syspro1/user/RCS/uid-print.c,v 1.2 1998/05/18 14:43:10 yas Exp $
   5:	        Start: 1998/05/18 23:20:16
   6:	*/
   7:	
   8:	#include <sys/types.h>  /* getuid(2) */
   9:	#include <unistd.h>     /* getuid(2) */
  10:	#include <pwd.h>        /* getpwuid(3) */
  11:	#include <grp.h>        /* getgrgid(3) */
  12:	
  13:	#if     0
  14:	typedef o_uid_t o_gid_t;                /* old GID type         */
  15:	typedef long            uid_t;
  16:	extern uid_t getuid(void);
  17:	#endif
  18:	
  19:	extern  char *uid2uname(uid_t uid);
  20:	extern  char *gid2gname(gid_t gid);
  21:	
  22:	main()
  23:	{
  24:	    uid_t uid ;
  25:	        uid = getuid();
  26:	        printf("%d: %s\n",uid,uid2uname(uid) );
  27:	        uid = 0 ;
  28:	        printf("%d: %s\n",uid,uid2uname(uid) );
  29:	}
  30:	
  31:	char *uid2uname(uid_t uid)
  32:	{
  33:	    struct passwd *pwd ;
  34:	        pwd = getpwuid( uid );
  35:	        if( pwd )
  36:	            return( pwd->pw_name );
  37:	        else
  38:	        {
  39:	             static char buf[100] ; /* must be static, bad for multithreading */
  40:	             sprintf(buf,"%d",uid );
  41:	             return( buf );
  42:	        }
  43:	}
  44:	
  45:	char *gid2gname(gid_t gid)
  46:	{
  47:	    struct group *grp ;
  48:	        grp = getgrgid( gid );
  49:	        if( grp )
  50:	            return( grp->gr_name );
  51:	        else
  52:	        {
  53:	             static char buf[100] ; /* must be static, bad for multithreading */
  54:	             sprintf(buf,"%d",gid );
  55:	             return( buf );
  56:	        }
  57:	}
----------------------------------------------------------------------

----------------------------------------------------------------------
% ./proc-uid-print [←]
1231: yas
0: root
% []
----------------------------------------------------------------------

■ファイルの属性

UNIXでは、stat() (あるいは、lstat(), fstat())システム・コールを 用いてファイルの属性を調べることができる。ファイルの属性を調べ、画面に 出力するプログラムを stat.c に示す。
----------------------------------------------------------------------
   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.c [←]
path: 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>
% []
----------------------------------------------------------------------

この実行結果から次のようなことがわかる。
  1. ファイル名は、ystat.c である。
  2. 存在するデバイスは、メジャー番号8, マイナー番号3で識別される。
  3. アイノード番号は、17639075である。
  4. モードは、0100644である。
  5. リンク数は、1である。
  6. ファイルの所有者のIDは、1231である。
  7. ファイルのグループは、40である。
  8. デバイスの識別子は、メジャー番号0, マイナー番号0である。 (この場合無効。デバイス・ファイルのみ有効。)
  9. ファイルの大きさは、1767バイトである。
  10. 最終アクセス時刻は、atime: Mon May 18 22:20:44 1998 である。
  11. 最終更新時刻は、mtime: Mon May 18 22:20:44 1998 である。
  12. 最終変更時刻は、ctime: Mon May 18 22:20:44 1998である。
  13. 入出力に適したブロックサイズは、8192バイトである。
  14. ディスク中で実際に消費しているのは、4ブロックである。
ここで、モードが8進数で 0100644 (C言語の文法で、0から始まる数は、8進 数)であることから、ファイルの型(普通のファイルかディレクトリかという 情報)を調べることができる。

UNIXのモード

0100644の上位4ビット、つまり、0170000と AND (C言語のでは、 &演算子)をとった結果は 0100000 となる。この値は、普通のファ イル(regular file)を意味する。ディレクトリの場合、0040000 となる。こ れらの数は、 (/usr/include/sys/stat.h)で定義されている。

----------------------------------------------------------------------
#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;
	....
	}
----------------------------------------------------------------------
あるいは、 に含まれている S_ISREG(), S_ISDIR() というマク ロを用いて、次のように記述する方法もある。
----------------------------------------------------------------------
	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" の意味が異なる。

■umaskの影響

ファイルやディレクトリを新たに作る時にどのようなモードになるかは、次の 2つで決まる。
  1. ファイルやディレクトリを作るプログラムの中で指定したモード
  2. マスク
実際に作られるファイルのモードは、1. から 2. を引いた値になる。同じプ ログラムを使ったとしても、マスクの値によっては、作られるファイルのモー ドが違ってくる。

マスクの影響と操作

マスクの表示

マスクを見るには、umask コマンドコマンドを使う。
----------------------------------------------------------------------
% umask [←]
22
% []
----------------------------------------------------------------------
YHM_umask コマンドは、シェルの 内部コマンドである。マスクは、プロセスの属性の1つで、 子プロセス、孫プロセスと代々受け 継がれていきく。現在のシェルのマスクを見れば、 シェルから実行されるプロセスのマスクがわかる。

umask を操作するシステム・コールは、umask(コマンドと同じ名前)である。

マスクは、モードと同じく8進数で考える。たとえば、022 は、次のように 読む。

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

   ---       000 新しいファイルは、自分自身は、読み書き自由。
      -w-    020 同じグループの人は、ファイルの書込みを禁止する。
+)       -w- 002 その他の人も、ファイルの書込みを禁止する。
----------------
             022

----------------------------------------------------------------------
このように、モードの逆になる。

マスクを変えよう

マスクを変えるには、umask コマンドに、引数を与えて実行します。
----------------------------------------------------------------------
% umask [←]
22
%
% umask 066 [←]
% umask [←]
66
% []
----------------------------------------------------------------------
この例では、シェルのマスクを 022 から 066 へ変更しています。

umask コマンドによるマスクの設定は、 普通、~/.cshrc~/.login に入れる。 rsh コマンド時も実行さ れるように、~/.cshrc に入れて置くのが無難である。

普通のファイルを作る時のマスクの影響

新しくファイルを作る時、そのモードは、最大 666 (rw-rw-rw-)になることが多い。これは、ファイルを作るプロ グラム(cp, mule などで)で、次のようにファイルを作っていることに由来す る。
	open("file1",O_CREAT|O_TRUNC,0666);
すると、UNIXオペレーティング・システムのカーネルは、システム・コールの 引数とマスクを保持している変数 mask を使って
	mode = 0666 & ~mask ;
というモードのファイルを作る。「&」 は、ビットごとのAND、「~」は、ビット反 転である。この場合、繰り下がりがないので、
	mode = 0666 - mask ;
と考えてもよい。結果として、マスクの部分のビットが落ちたモード を持つファイルが作られる。

たとえば、マスクが 022 の時、作 成されるファイルのモードは、666からマスクの022を引くので、次のように 644 (rw-r--r--) になる。


----------------------------------------------------------------------
% umask [←]
22
% echo "This is file1" > file1 [←]
% ls -l file1 [←]
-rw-r--r--  1 yas            14 Sep 14 17:25 file1
% []
----------------------------------------------------------------------
マスクを 0 にして、同じことをすると、モードが 666 になる。

----------------------------------------------------------------------
% umask 000 [←]
% umask [←]
0
% rm file1 [←]
% echo "This is file1" > file1 [←]
% ls -l file1 [←]
-rw-rw-rw-  1 yas            14 Sep 14 17:29 file1
% []
----------------------------------------------------------------------

マスクは、新しくファイルを作る時にのみ有効である。すでに、ファイルが存 在する場合、ファイルに書込みをしても、モードは変わらない。たとえば、


----------------------------------------------------------------------
% chmod 777 file1 [←]
% ls -l file1 [←]
-rwxrwxrwx  1 yas            14 Jan 23 16:28 file1
% umask 022 [←]
% echo "a" > file1 [←]
% ls -l file1 [←]
-rwxrwxrwx  1 yas             2 Jan 23 18:05 file1
% []
----------------------------------------------------------------------

ディレクトリを作る時のマスクの影響

新しくディレクトリを作る時、そのモードは、最大 777 (rwxrwxrwx)になることが多い。これは、ディレクトリを作る プログラムが、
	mkdir("dir1",0777 );
となっているからである。この結果、ファイルと同様に
	mode = 0777 & ~mask
というモードを持つディレクトリが作られる。

たとえば、マスクが 022 の時、作成されるディレクトリのモードは、777から マスクの022を引くので、次のように 755 (rwxr-xr-x) に なる。


----------------------------------------------------------------------
% umask [←]
22
% mkdir dir1 [←]
% ls -ld dir1 [←]
drwxr-xr-x  2 yas           512 Jan 23 18:09 dir1
% []
----------------------------------------------------------------------
マスクを 0 にして、同じことをすると、

----------------------------------------------------------------------
% umask 0 [←]
% rmdir dir1 [←]
% mkdir dir1 [←]
% ls -ld dir1 [←]
drwxrwxrwx  2 yas           512 Jan 23 18:09 dir1
% []
----------------------------------------------------------------------
新しく YHM_mkdir() コマンドで作ったディレクトリの モードが 777 になる。

■アクセス制御

アクセス制御(access control) とは、あるプロセスが、ファイルや他のプロセスにたいして、許されている操 作だけを実行させることである。 ファイルであれば、内容の読出し・書き込み・実行、属性の読出し・変更がで きるかどうかを調べる。 プロセスでは、シグナルを送れるかどうかを調べる。許されれば、その操作 は実行されて、許されなければ、エラーになる。

UNIXは、マルチユーザのシステムなので、ユーザ1人ひとりを認識するような アクセス制御の仕組みを持っている。たとえば、UNIX では、共同プロジェク トに関連したファイルは、他のユーザにも見せてもよいが、個人の電子メール は、他の人には見せないといった制御ができる。

これに対して、パーソナル・コンピュータ用のオペレーティング・システムで は、このような複数のユーザを識別したアクセス制御はできない。

図? 実世界のユーザとUNIX中のプロセス・ファイル

ファイルに対するアクセス制御

UNIXでは、ファイルの「内容」のアクセス制御を次の3段階で行う。
ユーザ
ファイルのUID(所有者)が、プロセスのUIDと同じ
グループ
ファイルのGIDが、プロセスのGIDのリストのどれかと同じ
その他
上の2つに当てはまらない時
これをつかって、モード属性の下位9ビットのうち、どの3ビットを使うかを 決める。そして、そのビットが1になっていれば、その操作が許される。

ファイルの「内容」のアクセス3段階であるが、ファイルの「属性」次の2段 階である。

ユーザ
ファイルのUID(所有者)が、プロセスのUIDと同じ
それ以外
ファイルのUID(所有者)が、プロセスのUIDと異なる
ユーザの権限では、ファイルの属性(モード、グループ、時刻)を変更する ことができる。それ以外の権 限では、属性を読み出すことはできるが、変更は一切できない。 つまり、ファイルの内容がアクセスできなくても、ls -l, stat(2) で 属性を調べることはでる。

■リンクと名前

UNIXでは、ファイル名は、枝(リンク)に付いている。UNIXでは、ファイルの 名前には、次の2種類がある。 本名は、ファイルの寿命と関係している。普通のファイルは、1である。複数 の本名を持っているファイルもある。

----------------------------------------------------------------------
% ls -li /usr/bsd/{compress,uncompress,zcat} [←]
1048720 -rwxr-xr-x    1 root     sys        33700   3月 28日 10時57分 /usr/bsd/compress
1048618 lrwxr-xr-x    1 root     sys            8   2月  4日 05時50分 /usr/bsd/uncompress -> compress
1048620 lrwxr-xr-x    1 root     sys            8   2月  4日 05時50分 /usr/bsd/zcat -> compress
% []
----------------------------------------------------------------------

ディレクトリを stat(2) で調べると、リンク数が2以上になっている。 "." と 子ディレクトリの ".." の分だけ増えている。

本名は、open(), creat(), mkdir() の時に作られる。それ以外に、link() シ ステム・コールで増やすことができる。リンクを減らすには、unlink() シス テム・コールを使う。リンクが1つしかないファイルに unlink() を行うと、 ファイルが削除される。

シンボリック・リンクは、別のファイルの名前(シンボル)を含んでいる特殊 なファイルである。シンボリック・リンクは、symlink() システム・コールで 作成することができる。

■練習問題と課題

★練習問題22 localtime(3)、strftime(3) の利用

localtime(3)やstrftime(3)を使って、ctime() や dateコマンドとは異なる形 式で時刻の表示するプログラムを作りなさい。

★練習問題23 gidの表示

プロセスの GID属性を表示するプログラムを作りなさい。 GID は、複数ある。

★練習問題24 ls-lプログラム

stat() システム・コールを用いて ls -l filename と似たような結果を出力 するプログラムを作りなさい。このプログラムの名前を myls-l とする。

ls -l では、3つの時刻のうち、どの時刻が表示されているのかを調べなさい。 また、他の2つの時刻を表示させる方法を調べなさい。

myls-l の結果の表示形式は、ls -l と完全に一致しなくてもよい。たとえば、 時刻の表示は、上の ystat.c の結果と同じでもよい。ocaltime(), 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) を使って、ディレクトリの内容を表示 するようにしてもよい。

★練習問題25 chmod プログラム

ファイルのモードを変更するコマンド chmod に似たコマンドを作りなさい。

★練習問題26 touch プログラム

ファイルの時刻を変更するコマンド touch に似たコマンドを作りなさい。

★練習問題27 リンクの作成

link(2) を使ってリンクを作成するプログラム(ln コマンドに似た動きをす るプログラム)を作りなさい。

★練習問題28 リンクの削除

unlink(2) を使って、リンクを削除するプログラム(rm コマンドと似た動きを するプログラム)を作りなさい。

★練習問題29 リンクの削除

symlink(2) を使って、シンボリック・リンクを作成するプログラム(ln -s と 似た動きをするプログラム)を作りなさい。

★練習問題30 名前の変更

rename(2) を使って、ファイルの名前を変えるするプログラム(mv コマンドと 似た動きをするプログラム)を作りなさい。

★練習問題31 tail プログラム

mmap() システム・コールを使って、tail コマンドに似たコマンドを作りなさ い。

★練習問題32 アクセス権を調べるプログラム

ファイルに対するアクセス権を調べるプログラムを作りなさい。 たとえば、
% access_check filename user read
では、ユーザ名(または、UID)が user のユーザがfilename で与えられたファ イルを読むことができるかどうかを調べる。user は、番号(UID)かユーザ名で 与える。アクセス方法には、次のようなものがある。

★練習問題33 出席判定プログラム

あるユーザが、ある与えられた時刻の範囲内にログインしていたかどうかを調 べるプログラムを作りなさい。 たとえば、
% present user 1998/05/19-10:10 1998/05/19-11:30
と与えると、ユーザ名user のユーザが、その時間にログインしていたら、OK を返す。

■課題

次の練習問題を1つ以上やりなさい。 締切は、1997年6月2日とする。当日の日付有効。

■課題提出方法


↑[もどる] [課題提出方法] ←[5月12日] ・[5月19日] →[5月26日]
Last updated: 1998/05/19 00:19:08
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>