ディレクトリ(可変長の構造体の入出力)

システム・プログラム

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

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

■getdents(2)によるディレクトリの内容の取得

UNIXのディレクトリは、ディスク中では、可変長の構造体になっている。C言 語では、直接的には可変長の構造体を扱うことはできない。

IRIX では、getdents(2) システム・コールを使うと、ディスク中に保存され たディレクトリに近いデータを得ることができる。(システム・コールは、シ ステムにより異なる。システムによっては、ディレクトリについても、read() が使えるものがある。SunOS, Solaris でも、getdents()。HP-UX では、 getdirentries()


----------------------------------------------------------------------
   1:	/*
   2:	        dir-getdents.c -- ディレクトリの内容を表示するプログラム
   3:	        ~yas/syspro1/dir/dir-getdents.c
   4:	        $Header: /home/lab2/OS/yas/syspro1/dir/RCS/dir-getdents.c,v 1.2 1998/05/11 17:18:01 yas Exp $
   5:	        Start: 1995/03/07 21:44:51
   6:	*/
   7:	
   8:	#include <stdio.h>      /* fprintf(), stderr */
   9:	#include <sys/types.h>  /* open(2) */
  10:	#include <sys/stat.h>   /* open(2) */
  11:	#include <fcntl.h>      /* open(2) */
  12:	#include <sys/dirent.h> /* getdents(2) */
  13:	
  14:	#if     0
  15:	typedef struct dirent {                 /* data from readdir() */
  16:	        ino_t           d_ino;          /* inode number of entry */
  17:	        off_t           d_off;          /* offset of disk directory entry */
  18:	        unsigned short  d_reclen;       /* length of this record */
  19:	        char            d_name[1];      /* name of file */
  20:	} dirent_t;
  21:	#endif
  22:	
  23:	
  24:	extern  void dir_list( char *dirname );
  25:	extern  void xdump( unsigned char *buff, int n );
  26:	extern  void xdump16( unsigned char *buff, int n );
  27:	
  28:	main( int argc, char *argv[] )
  29:	{
  30:	        if( argc != 2 )
  31:	        {
  32:	            fprintf( stderr,"Usage:%% %s dirname \n",argv[0] );
  33:	            exit( 1 );
  34:	        }
  35:	        dir_list( argv[1] );
  36:	}
  37:	
  38:	void dir_list( char *dirname )
  39:	{
  40:	    int fd ;
  41:	    struct dirent *p ;
  42:	    char buff[BUFSIZ] ;
  43:	    int rcount ;
  44:	
  45:	        fd = open( dirname,O_RDONLY );
  46:	        if( fd == -1 )
  47:	        {
  48:	            perror( dirname );
  49:	            exit( 1 );
  50:	        }
  51:	
  52:	        while( (rcount=getdents(fd,(dirent_t *)buff,BUFSIZ)) >0 )
  53:	        {
  54:	            xdump( buff, rcount );
  55:	            for( p = (struct dirent *)buff ; (char *)p < &buff[rcount] ;
  56:	                 p=(struct dirent *) ((int)p+(p->d_reclen)) )
  57:	            {
  58:	                printf("p:%d, ", (char *)p - buff );
  59:	                printf("off:%u, ", p->d_off );  /* long */
  60:	                printf("ino:%u, ", p->d_ino );  /* unsigned long */
  61:	                printf("reclen:%d, ", p->d_reclen );
  62:	                printf("name:%s\n", p->d_name );
  63:	            }
  64:	        }
  65:	        close( fd );
  66:	}
  67:	
  68:	void xdump( unsigned char *buff, int n )
  69:	{
  70:	        if( n<0 || n>100000 )
  71:	            return;
  72:	        for( ; n>0 ; n-=16, buff+=16 )
  73:	            xdump16( buff,n>=16?16:n );
  74:	}
  75:	
  76:	void xdump16( unsigned char *buff, int n )
  77:	{
  78:	    register int i ;
  79:	        for( i=0 ; i<n ; i++ )
  80:	            printf("%02x ",buff[i] );
  81:	        for( i=n ; i<16 ; i++ )
  82:	            printf("   ");
  83:	        for( i=0 ; i<n ; i++ )
  84:	            printf("%c",isprint(buff[i])?buff[i]:'#');
  85:	        for( i=n ; i<16 ; i++ )
  86:	            printf(" ");
  87:	        printf("\n");
  88:	}
  89:	
----------------------------------------------------------------------

実行例。
----------------------------------------------------------------------
% ./dir-getdents dir1 [←]
00 07 a5 60 00 00 17 2e 00 0c 2e 00 01 8f 70 21 ###`###.##.###p!
6d 3b 32 b4 00 10 2e 2e 00 00 00 00 00 07 a5 63 m;2###..#######c
6d 3b 32 b7 00 10 66 69 6c 65 32 00 00 07 a5 61 m;2###file2####a
ff ff ff ff 00 10 66 69 6c 65 31 00             ######file1#    
p:0, off:5934, ino:501088, reclen:12, name:.
p:12, off:1832596148, ino:26177569, reclen:16, name:..
p:28, off:1832596151, ino:501091, reclen:16, name:file2
p:44, off:4294967295, ino:501089, reclen:16, name:file1
% []
----------------------------------------------------------------------

ディレクトリの構造

ディレクトリを読むためのライブラリ関数として、次のようなものがある。


----------------------------------------------------------------------
     #include <sys/types.h>
     #include <sys/dir.h>
     DIR *opendir(char *filename);
     struct direct *readdir(DIR *dirp);
     long telldir(DIR *dirp);
     void seekdir(DIR *dirp, long loc);
     void rewinddir(DIR *dirp);
     void closedir(DIR *dirp);
     int dirfd(DIR *dirp)
----------------------------------------------------------------------

このライブラリ関数は、システム・コールと比較して移植性が高い。

■ディレクトリの作成

ディレクトリを作成するには、mkdir(2) システム・コールを用いる。 mkdir(1) コマンドは、mkdir(2) システム・コールを使って作られている。

----------------------------------------------------------------------
   1:	/*
   2:	        dir-mkdir.c -- ディレクトリを作成するプログラム
   3:	        ~yas/syspro1/dir/dir-mkdir.c
   4:	        $Header: /home/lab2/OS/yas/syspro1/dir/RCS/dir-mkdir.c,v 1.2 1998/05/11 17:01:35 yas Exp $
   5:	        Start: 1997/05/12 21:26:10
   6:	*/
   7:	
   8:	#include <stdio.h>
   9:	#include <sys/stat.h>
  10:	
  11:	void main( int argc, char *argv[] )
  12:	{
  13:	        if( argc != 2 )
  14:	        {
  15:	            fprintf( stderr,"Usage:%% %s dirname \n",argv[0] );
  16:	            exit( 1 );
  17:	        }
  18:	        if( mkdir( argv[1],0777 ) == -1 )
  19:	        {
  20:	            perror( argv[1] );
  21:	        }
  22:	}
----------------------------------------------------------------------

単純に man mkdir と打つと、mkdir(1) コマンドのマニュアルが表示される。 mkdir(2) システム・コールを見るには、次のように打つ。
% man 2 mkdir [←]

■練習問題

★練習問題19 lsプログラム

opendir(3) を用いて、次のような動きをするプログラムを作りなさい。

注意: ls -l までやる必要はない。

★練習問題21 ディレクトリの削除

rmdir(2) を使ってディレクトリを削除するプログラムを作りなさい。
↑[もどる] ←[4月17日] ・[4月24日] →[5月01日] [課題]
Last updated: 2000/04/23 01:58:02
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>