Category Archives: 仕分け中

マイtruncateを作る(その7)

続きです。エラー処理を入れていきます。

     7	int main(int argc, char* argv[])
     8	{
     9		FILE *fp;
    10		int i,len,size=0;
    11		int value=0;
    12		int ch,tmp[100];
    13		struct stat buf;
    14	

tmp配列は必要なくなったので削除して、argvを多用していると、何の文字列だかわからなくなるので、filename変数を作りました。

     7	int main(int argc, char* argv[])
     8	{
     9		FILE *fp;
    10		int i,len,size=0;
    11		int value=0;
    >>		int ch;
    13		struct stat buf;
    >>		char *filename;

以下のargv[optind]を、

    34		for(; optind<argc; optind++){
    35			if(stat(argv[optind],&buf) != 0){
    36				fp = fopen(argv[optind],"w");
    37				for(i=0; i<size; i++)
    38					fputc(value,fp);	
    39				fclose(fp);
    40			}else{
    41				len = buf.st_size;
    42				if(len < size){
    43					fp = fopen(argv[optind],"a");
    44					for(i=len; i<size; i++)
    45						fputc(value,fp);	
    46					fclose(fp);
    47				}else if(len > size){
    48					truncate(argv[optind],size);
    49				}
    50			}
    51		}

filenameに置き換えます。

    34		for(; optind<argc; optind++){
    >>			filename = argv[optind];
    35			if(stat(filename,&buf) != 0){
    >>				fp = fopen(filename,"w");
    37				for(i=0; i<size; i++)
    38					fputc(value,fp);	
    39				fclose(fp);
    40			}else{
    41				len = buf.st_size;
    42				if(len < size){
    >>					fp = fopen(filename,"a");
    44					for(i=len; i<size; i++)
    45						fputc(value,fp);	
    46					fclose(fp);
    47				}else if(len > size){
    >>					truncate(filename,size);
    49				}
    50			}
    51		}

随分見やすくなりました。
次は、fopenやtruncateを実行後にエラー処理を追加します。一律同じものを入れておきました。

    34		for(; optind<argc; optind++){
      			filename = argv[optind];
    35			if(stat(filename,&buf) != 0){
      				fp = fopen(filename,"w");
    >>				if(fp == NULL){
    >>					perror(filename);
    >>					continue;
    >>				}
    37				for(i=0; i<size; i++)
    38					fputc(value,fp);	
    39				fclose(fp);
    40			}else{
    41				len = buf.st_size;
    42				if(len < size){
      					fp = fopen(filename,"a");
    >>					if(fp == NULL){
    >>						perror(filename);
    >>						continue;
    >>					}
    44					for(i=len; i<size; i++)
    45						fputc(value,fp);	
    46					fclose(fp);
    47				}else if(len > size){
      					truncate(filename,size);
    >>					if(fp == NULL){
    >>						perror(filename);
    >>						continue;
    >>					}
    49				}
    50			}
    51		}

さてビルドして実行。

takk@deb9:~/tmp$ ./a.out -s3 -v100 {1..3}.bin
takk@deb9:~/tmp$ ls
1.bin  2.bin  3.bin  a.out  mytruncate.c
takk@deb9:~/tmp$ dump(){
> for i in $@;do echo -n $i ;od -tx1 -An $i;done
> }
takk@deb9:~/tmp$ dump *.bin
1.bin 64 64 64
2.bin 64 64 64
3.bin 64 64 64
takk@deb9:~/tmp$ 

新規作成は問題なさそうです。

takk@deb9:~/tmp$ ./a.out -s5 -v50 {1,3}.bin
takk@deb9:~/tmp$ dump *.bin
1.bin 64 64 64 32 32
2.bin 64 64 64
3.bin 64 64 64 32 32
takk@deb9:~/tmp$ 

サイズ追加も大丈夫そうです。

次はサイズカット。

takk@deb9:~/tmp$ ./a.out -s2 3.bin
3.bin: Success
takk@deb9:~/tmp$ dump *.bin
1.bin 64 64 64 32 32
2.bin 64 64 64
3.bin 64 64
takk@deb9:~/tmp$ 

あれ、3.binでSuccessと出てしまいました。
成功したのに、メッセージが出るということは、判定方法が真偽逆なのでしょうか。
grepしてみます。全部NULLかどうかのチェックを入れていたはずです。

takk@deb9:~/tmp$ grep -nC3 NULL mytruncate.c 
36-		filename = argv[optind];
37-		if(stat(filename,&buf) != 0){
38-			fp = fopen(filename,"w");
39:			if(fp == NULL){
40-				perror(filename);
41-				continue;
42-			}
--
47-			len = buf.st_size;
48-			if(len < size){
49-				fp = fopen(filename,"a");
50:				if(fp == NULL){
51-					perror(filename);
52-					continue;
53-				}
--
56-				fclose(fp);
57-			}else if(len > size){
58-				truncate(filename,size);
59:				if(fp == NULL){
60-					perror(filename);
61-					continue;
62-				}
takk@deb9:~/tmp$ 

ああtruncateのエラー処理、思いっきり間違えてます。ファイルポインタじゃないのに、fpと比較してます。truncateのmanを確認します。
man 2 truncate

返り値
       成功した場合は 0 が返される。エラーの場合は  -1  が返され、
       errno が適切に設定される。


truncateの戻り値が-1かどうか判定するように修正。

    58					if(truncate(filename,size) == -1){
    59						perror(filename);
    60						continue;
    61					}

ビルドして確認します。

takk@deb9:~/tmp$ !g
gcc mytruncate.c 
takk@deb9:~/tmp$ !./a
./a.out -s2 3.bin
takk@deb9:~/tmp$ !du
dump *.bin
1.bin 64 64 64 32 32
2.bin 64 64 64
3.bin 64 64
takk@deb9:~/tmp$ 

OK。今度はSuccessは出ませんでした。
続いて、アクセス権限を変更して確認。

takk@deb9:~/tmp$ sudo chown root.root 2.bin
takk@deb9:~/tmp$ sudo chmod 600 2.bin
takk@deb9:~/tmp$ ./a.out -s9 *.bin
2.bin: Permission denied
takk@deb9:~/tmp$ dump *.bin
1.bin 64 64 64 32 32 00 00 00 00
2.binod: 2.bin: 許可がありません
3.bin 64 64 00 00 00 00 00 00 00
takk@deb9:~/tmp$

Permission deniedと出てくれました。OKですね。
odでアクセスできないので、
lsでサイズを確認します。サイズも変わってません。

takk@deb9:~/tmp$ ls -l *.bin
-rw-r--r-- 1 takk takk 9  4月 22 19:49 1.bin
-rw------- 1 root root 3  4月 22 19:25 2.bin
-rw-r--r-- 1 takk takk 9  4月 22 19:49 3.bin
takk@deb9:~/tmp$

権限ありで再実行。

takk@deb9:~/tmp$ sudo ./a.out -s9 *.bin
takk@deb9:~/tmp$ ls -l *.bin
-rw-r--r-- 1 takk takk 9  4月 22 19:49 1.bin
-rw------- 1 root root 9  4月 22 19:52 2.bin
-rw-r--r-- 1 takk takk 9  4月 22 19:49 3.bin
takk@deb9:~/tmp$

マイtruncateできました。

全ソースです。

takk@deb9:~/tmp$ cat -n mytruncate.c
     1	#include <stdio.h>
     2	#include <stdlib.h>
     3	#include <sys/types.h>
     4	#include <sys/stat.h>
     5	#include <unistd.h>
     6	
     7	int main(int argc, char* argv[])
     8	{
     9		FILE *fp;
    10		int i,len,size=0;
    11		int value=0;
    12		int ch;
    13		struct stat buf;
    14		char *filename;
    15	
    16		while ((ch = getopt(argc, argv, "s:v:")) != -1){
    17			switch (ch) {
    18			case 's':   
    19				size = atoi(optarg);
    20				break;
    21			case 'v':   
    22				value = atoi(optarg);
    23				break;
    24			default:
    25				printf("parameter error\n");
    26				return 1;
    27			}
    28		}
    29	
    30		if(optind >= argc){
    31			printf("parameter error\n");
    32			return 1;
    33		}
    34	
    35		for(; optind<argc; optind++){
    36			filename = argv[optind];
    37			if(stat(filename,&buf) != 0){
    38				fp = fopen(filename,"w");
    39				if(fp == NULL){
    40					perror(filename);
    41					continue;
    42				}
    43				for(i=0; i<size; i++)
    44					fputc(value,fp);	
    45				fclose(fp);
    46			}else{
    47				len = buf.st_size;
    48				if(len < size){
    49					fp = fopen(filename,"a");
    50					if(fp == NULL){
    51						perror(filename);
    52						continue;
    53					}
    54					for(i=len; i<size; i++)
    55						fputc(value,fp);	
    56					fclose(fp);
    57				}else if(len > size){
    58					if(truncate(filename,size) == -1){
    59						perror(filename);
    60						continue;
    61					}
    62				}
    63			}
    64		}
    65		return 0;
    66	}
    67	
takk@deb9:~/tmp$