マイtruncateを作る(その6)

stat関数のことが分かってきたので、自作truncateコマンドもstat関数を使ってきれいにしてみます。
改造前のプログラム。

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,tmp[100];
    13		struct stat buf;
    14	
    15		while ((ch = getopt(argc, argv, "s:v:")) != -1){
    16			switch (ch) {
    17			case 's':   
    18				size = atoi(optarg);
    19				break;
    20			case 'v':   
    21				value = atoi(optarg);
    22				break;
    23			default:
    24				printf("parameter error\n");
    25				return 1;
    26			}
    27		}
    28	
    29		if(optind >= argc){
    30			printf("parameter error\n");
    31			return 1;
    32		}
    33	
    34		for(; optind<argc; optind++){
    35			fp = fopen(argv[optind],"r");
    36			if(fp == NULL){
    37				fp = fopen(argv[optind],"w");
    38				for(i=0; i<size; i++)
    39					fputc(value,fp);	
    40				fclose(fp);
    41			}else{
    42				stat(argv[optind],&buf);
    43				len = buf.st_size;
    44				if(len < size){
    45					fp = fopen(argv[optind],"a");
    46					for(i=len; i<size; i++)
    47						fputc(value,fp);	
    48					fclose(fp);
    49				}else if(len > size){
    50					truncate(argv[optind],size);
    51				}
    52			}
    53		}
    54		return 0;
    55	}
    56	
takk@deb9:~/tmp$ 

今回statを使って改善する部分です。

    34		for(; optind<argc; optind++){
    35			fp = fopen(argv[optind],"r");
    36			if(fp == NULL){
    37				fp = fopen(argv[optind],"w");
    38				for(i=0; i<size; i++)
    39					fputc(value,fp);	
    40				fclose(fp);
    41			}else{
    42				stat(argv[optind],&buf);
    43				len = buf.st_size;
    44				if(len < size){

35行目でfopenして、さらに37行目でfopenしてます。これをstatを使えば、2度同じことをしなくてもよくなります。
35行目のfopenをstatにすると、42行目のstatとかぶってしまいますので、42行目のstatは削除します。

    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){

すっきりしました。ビルドして実行。
新規パターン。

takk@deb9:~/tmp$ gcc -o mytruncate mytruncate.c
takk@deb9:~/tmp$ ./a.out -s5 -v100 test.bin
takk@deb9:~/tmp$ od -tx1 -An test.bin
 64 64 64 64 64
takk@deb9:~/tmp$ 

追加パターン。

takk@deb9:~/tmp$ ./a.out -s12 -v10 test.bin
takk@deb9:~/tmp$ od -tx1 -An test.bin
 64 64 64 64 64 0a 0a 0a 0a 0a 0a 0a
takk@deb9:~/tmp$

削除パターン。

takk@deb9:~/tmp$ ./a.out -s10 test.bin
takk@deb9:~/tmp$ od -tx1 -An test.bin
 64 64 64 64 64 0a 0a 0a 0a 0a
takk@deb9:~/tmp$

上手くいきました。

改造後の全ソースです。

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,tmp[100];
    13		struct stat buf;
    14	
    15		while ((ch = getopt(argc, argv, "s:v:")) != -1){
    16			switch (ch) {
    17			case 's':   
    18				size = atoi(optarg);
    19				break;
    20			case 'v':   
    21				value = atoi(optarg);
    22				break;
    23			default:
    24				printf("parameter error\n");
    25				return 1;
    26			}
    27		}
    28	
    29		if(optind >= argc){
    30			printf("parameter error\n");
    31			return 1;
    32		}
    33	
    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		}
    52		return 0;
    53	}
    54	
takk@deb9:~/tmp$ 

コメント

タイトルとURLをコピーしました