tsselectをLinux等でコンパイル出来るように書き換えてみた

tsselect linuxは2GBを超えるファイルを扱えないみたいなので、元のtsselectのソースをLinux等でコンパイル出来るように書き換えてみた。offset等が正しく表示されないバグがあったので2019/11/26にパッチ内容および書き換え手順を修正した。
パッチとしてtsselect-0.1.8-linux.diffも作っておいた。以下のような手順でパッチを適用してコンパイルとインストール出来る。パッチを当てる前にソースの改行コードを変更している。

wget http://www.areanine.gr.jp/~nyano/archives/nikki/tsselect-0.1.8-linux.diff
wget https://www.marumo.ne.jp/junk/tsselect-0.1.8.lzh
mkdir tsselect-0.1.8
cd tsselect-0.1.8
lhasa x ../tsselect-0.1.8.lzh
cd src
sed -i -e 's/\r//g' tsselect.c
patch -p2 < ../../tsselect-0.1.8-linux.diff
gcc tsselect.c -o tsselect
strip tsselect
cp tsselect /usr/local/bin/

基本的には、Visual C++で2GBを超えるファイルを扱うためにヘッダーにを指定して_open、_close、_read、_write、_lseeki64、_telli64を使っている個所を、_LARGEFILE_SOURCEを定義して2GB超を扱えるfseekoとfteeloを使えるようにして、_FILE_OFFSET_BITSに64を定義してコンパイル時にfopen等をfopen64等に自動的に置き換えるようにし、先ほどの関数をfopen、fclose、fread、fwrite、fseeko、ftelloに置き換えるだけ。
あとは、_openの引数である_O_BINARY|_O_RDONLY|_O_SEQUENTIALは"rb"に_O_WRONLY|_O_BINARY|_O_CREAT|_O_TRUNC, _S_IREAD|_S_IWRITEは"wb"に置き換え、_readと_writeの引数の順番がファイルディスクリプタ、格納先、サイズなのを、格納先、サイズの単位(1でいい)、サイズとなるように変更、ファイル開けたか否かの判定を0以上か未満かではなく、NULL以外かNULLかに変更、intで定義してるファイルディスクリプタをFILEで定義するファイルポインタに変更して、ファイルデスクリプタを-1で初期化する部分は要らないので削除する。他に__int64型をlong long型に置き換えるのと、printf等の書式で使っている%I64dや%I64x等を%lldや%llxに置き換えるのも必要。
てな訳で、具体的に行った手順は以下の通り。

apt-get -y install lhasa
wget https://www.marumo.ne.jp/junk/tsselect-0.1.8.lzh
lhasa x tsselect-0.1.8.lzh
cd src
sed -i -e 's/\r//g' tsselect.c
sed -i -e '1i\#define _LARGEFILE_SOURCE\n#define _FILE_OFFSET_BITS 64' tsselect.c
sed -i -e '/#include <io.h>/d' tsselect.c
sed -i -e 's/__int64/long long/' tsselect.c
sed -i -e 's/I64d/lld/g' tsselect.c
sed -i -e 's/I64x/llx/g' tsselect.c
sed -i -e 's/int sfd,dfd;/FILE *sfp,*dfp;/' tsselect.c
sed -i -e 's/int fd;/FILE *fp;/' tsselect.c
sed -i -e '/sfd = -1;/d' tsselect.c
sed -i -e '/dfd = -1;/d' tsselect.c
sed -i -e '/fd = -1;/d' tsselect.c
sed -i -e 's/sfd = _open(src, _O_BINARY|_O_RDONLY|_O_SEQUENTIAL);/sfp = fopen(src, "rb");/' tsselect.c
sed -i -e 's/dfd = _open(dst, _O_WRONLY|_O_BINARY|_O_CREAT|_O_TRUNC, _S_IREAD|_S_IWRITE);/dfp = fopen(dst, "wb");/' tsselect.c
sed -i -e 's/fd = _open(path, _O_BINARY|_O_RDONLY|_O_SEQUENTIAL);/fp = fopen(path, "rb");/' tsselect.c
sed -i -e 's/if(sfd < 0)/if(sfp == NULL)/' tsselect.c
sed -i -e 's/if(dfd < 0)/if(dfp == NULL)/' tsselect.c
sed -i -e 's/if(fd < 0)/if(fp == NULL)/' tsselect.c
sed -i -e 's/if(sfd >= 0)/if(sfp != NULL)/' tsselect.c
sed -i -e 's/if(dfd >= 0)/if(dfp != NULL)/' tsselect.c
sed -i -e 's/if(fd >= 0)/if(fp != NULL)/' tsselect.c
sed -i -e 's/_lseeki64(sfd, 0, SEEK_END);/fseeko(sfp, 0, SEEK_END);/' tsselect.c
sed -i -e 's/_lseeki64(fd, 0, SEEK_END);/fseeko(fp, 0, SEEK_END);/' tsselect.c
sed -i -e 's/total = _telli64(sfd);/total = ftello(sfp);/g' tsselect.c
sed -i -e 's/total = _telli64(fd);/total = ftello(fp);/g' tsselect.c
sed -i -e 's/_lseeki64(sfd, 0, SEEK_SET);/fseeko(sfp, 0, SEEK_SET);/' tsselect.c
sed -i -e 's/_lseeki64(fd, 0, SEEK_SET);/fseeko(fp, 0, SEEK_SET);/' tsselect.c
sed -i -e 's/n = _read(sfd, buf, sizeof(buf));/n = fread(buf, 1, sizeof(buf), sfp);/' tsselect.c
sed -i -e 's/n = _read(fd, buf, sizeof(buf));/n = fread(buf, 1, sizeof(buf), fp);/' tsselect.c
sed -i -e 's/m = _read(sfd, buf+n, sizeof(buf)-n);/m = fread(buf+n, 1, sizeof(buf)-n, sfp);/' tsselect.c
sed -i -e 's/m = _read(fd, buf+n, sizeof(buf)-n);/m = fread(buf+n, 1, sizeof(buf)-n, fp);/' tsselect.c
sed -i -e 's/m = _write(dfd, curr, 188);/m = fwrite(curr, 1, 188, dfp);/' tsselect.c
sed -i -e 's/_close(sfd);/fclose(sfp);/' tsselect.c
sed -i -e 's/_close(dfd);/fclose(dfp);/' tsselect.c
sed -i -e 's/_close(fd);/fclose(fp);/' tsselect.c
gcc tsselect.c -o tsselect
strip tsselect
cp tsselect /usr/local/bin/