今回は、-sオプションで元ファイルよりもサイズを小さく指定した場合の、切り詰めする処理を作ります。
前回のプログラム。
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$
元ファイルのデータを保存する場所としてtmp配列を追加します。
使用するときの制約として元ファイルが100Byteを超えたらダメです。
5 int main(int argc, char* argv[])
6 {
7 FILE *fp;
8 int i,len,size=0;
9 int value=0;
10 int ch,tmp[100];
元ファイルの読み込んでtmp配列に格納する処理です。
38 }else{
39 fp = fopen(argv[optind],"r");
40 for(len=0; (ch=fgetc(fp)) != EOF; len++){
41 tmp[len]=ch;
42 }
43 fclose(fp);
-sで指定したサイズがファイルサイズよりも小さい場合の処理を追加しています。ファイルオープンのモードを”w+”とすることで、ファイルサイズを0に切り詰めた後に、データを書き込んでいます。
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 fp = fopen(argv[optind],"w+");
51 for(i=0; i<size; i++)
52 fputc(tmp[i],fp);
53 fclose(fp);
54 }
全体です。
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,tmp[100];
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 tmp[len]=ch;
42 }
43 fclose(fp);
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 fp = fopen(argv[optind],"w+");
51 for(i=0; i<size; i++)
52 fputc(tmp[i],fp);
53 fclose(fp);
54 }
55 }
56 }
57 return 0;
58 }
59
takk@deb9:~/tmp$
確認する前に、odコマンドが面倒なので、bashでdump関数を作っておきます。
takk@deb9:~/tmp$ dump(){
> for i in $@;do echo -n $i ;od -tx1 -An $i;done
> }
takk@deb9:~/tmp$
ビルドして、実行。5Byte長の値が0x0aのバイナリファイルを3つ作ります。
takk@deb9:~/tmp$ gcc t.c
takk@deb9:~/tmp$ ./a.out -s5 -v10 {1..3}.bin
takk@deb9:~/tmp$ ls -l
合計 28
-rw-r--r-- 1 takk takk 5 4月 8 21:42 1.bin
-rw-r--r-- 1 takk takk 5 4月 8 21:42 2.bin
-rw-r--r-- 1 takk takk 5 4月 8 21:42 3.bin
-rwxr-xr-x 1 takk takk 9024 4月 8 21:42 a.out
-rw-r--r-- 1 takk takk 1027 4月 8 21:41 t.c
生成したファイルをダンプ。
takk@deb9:~/tmp$ dump *.bin 1.bin 0a 0a 0a 0a 0a 2.bin 0a 0a 0a 0a 0a 3.bin 0a 0a 0a 0a 0a takk@deb9:~/tmp$
では、ファイル長を伸ばします。1.binと2.binだけ2Byte伸ばします。追加するデータは0x0cです。
takk@deb9:~/tmp$ ./a.out -s7 -v12 1.bin 2.bin takk@deb9:~/tmp$ dump *.bin 1.bin 0a 0a 0a 0a 0a 0c 0c 2.bin 0a 0a 0a 0a 0a 0c 0c 3.bin 0a 0a 0a 0a 0a takk@deb9:~/tmp$
本題。3Byteに切り詰めます。1.binと3.binのみ変更します。
takk@deb9:~/tmp$ ./a.out -s3 1.bin 3.bin takk@deb9:~/tmp$ dump *.bin 1.bin 0a 0a 0a 2.bin 0a 0a 0a 0a 0a 0c 0c 3.bin 0a 0a 0a takk@deb9:~/tmp$
上手くいきました。まあ、サイズが100Byte以内の制約があるので使い道がありませんが、truncateの理屈はきっとこんなもんだろうなあ、と思います。
次回は本物のtruncateソースで、答え合わせをしてみます。


コメント