マイtruncateを作る

前回の続き。今まではファイルがない前提で新規にファイルを生成していましたが、ファイルが存在する場合は、指定サイズにファイルサイズを伸長するように改造してみます。
元プログラムです。

takk@deb9:~/tmp$ cat -n t.c
     1	#include <stdio.h>
     2	#include <stdlib.h>
     3	#include <unistd.h>
     4	
     5	int main(int argc, char* argv[])
     6	{
     7		FILE *fp;
     8		int i,size=0;
     9		int value=0;
    10		int ch;
    11	
    12		while ((ch = getopt(argc, argv, "s:v:")) != -1){
    13			switch (ch) {
    14			case 's':   
    15				size = atoi(optarg);
    16				break;
    17			case 'v':   
    18				value = atoi(optarg);
    19				break;
    20			default:
    21				printf("parameter error\n");
    22				return 1;
    23			}
    24		}
    25	
    26		if(optind >= argc){
    27			printf("parameter error\n");
    28			return 1;
    29		}
    30	
    31		for(; optind<argc; optind++){
    32			fp = fopen(argv[optind],"w");
    33			for(i=0; i<size; i++)
    34				fputc(value,fp);	
    35			fclose(fp);
    36		}
    37		return 0;
    38	}
    39	
takk@deb9:~/tmp$ 

ファイルが存在する場合のファイル長を収める変数としてlenを定義します。

     5	int main(int argc, char* argv[])
     6	{
     7		FILE *fp;
     8		int i,len,size=0;

ファイルの存在チェックはfopenでやることにします。存在しない場合は、NULLが戻るので、NULLなら、前回までのバイナリ生成をすればよいです。`

    32			fp = fopen(argv[optind],"r");
    33			if(fp == NULL){
    34				fp = fopen(argv[optind],"w");
    35				for(i=0; i<size; i++)
    36					fputc(value,fp);	
    37				fclose(fp);

ファイルが存在した場合は、ファイルサイズを取得するためにfgetcを回しています。こんなことしなくても存在チェックもByte長もstat関数を使えば良いのですが、今回は使いません。

    38			}else{
    39				fp = fopen(argv[optind],"r");
    40				for(len=0; (ch=fgetc(fp)) != EOF; len++)
    41					;
    42				fclose(fp);
    43				if(len < size){
    44					fp = fopen(argv[optind],"a");
    45					for(i=len; i<size; i++)
    46						fputc(value,fp);	
    47					fclose(fp);
    48				}
    49			}

ファイルサイズ(len)が、-sで指定した長さ未満の場合のみ指定サイズまで-vで指定した値で拡張します。

毎度ですが、全ソース。

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

確認してみます。gccでビルドしてから、

takk@deb9:~/tmp$ ./a.out -s5 -v1 1.bin
takk@deb9:~/tmp$ od -tx1 1.bin
0000000 01 01 01 01 01
0000005
takk@deb9:~/tmp$ ./a.out -s7 -v2 1.bin
takk@deb9:~/tmp$ od -tx1 1.bin
0000000 01 01 01 01 01 02 02
0000007
takk@deb9:~/tmp$ 

-sと-vは、自分で作ったオプションなので、分かりやすいです。

ファイルと同じサイズを指定した場合は、以下のとおりファイルは更新されません。

takk@deb9:~/tmp$ ls -l 1.bin
-rw-r--r-- 1 takk takk 7  4月  7 20:22 1.bin
takk@deb9:~/tmp$ sleep 10
takk@deb9:~/tmp$ ./a.out -s7 -v3 1.bin
takk@deb9:~/tmp$ ls -l 1.bin
-rw-r--r-- 1 takk takk 7  4月  7 20:22 1.bin
takk@deb9:~/tmp$ 

数列をバイナリにしてみます。1~16までの値が詰まったバイナリデータとなります。

takk@deb9:~/tmp$ rm *.bin
takk@deb9:~/tmp$ for i in `seq 16`;do ./a.out -s$i -v$i a.bin b.bin;done
takk@deb9:~/tmp$ ls -l *.bin
-rw-r--r-- 1 takk takk 16  4月  7 20:27 a.bin
-rw-r--r-- 1 takk takk 16  4月  7 20:27 b.bin
takk@deb9:~/tmp$ od -tx1 -Ax a.bin
000000 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10
000010
takk@deb9:~/tmp$ cmp a.bin b.bin
takk@deb9:~/tmp$ 

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA