グローバル関数 ローカル関数
mssCloseFPW
mssOpenFPW
mssWriteChr
mssWriteDate
mssWriteDbe
mssWriteDbl
mssWriteDlm
mssWriteFld
mssWriteInt
mssWriteLong
mssWriteNull
mssWriteRet
mssWriteStr
mssWriteTime
fwOpenErr
mkDir
zwOpenErr
0001: /**
0002: * # CHAPTER #
0003: * ============================================================================
0004: * MUSASHIで用いられるデータの出力関連の関数
0005: * ============================================================================
0006: */
0007:
0008: #include <mssConfig.h>
0009: #include <mssOutput.h>
0010: #include <mssBase.h>
0011:
0012: #include <stdio.h>
0013: #include <stdlib.h>
0014: #include <string.h>
0015: #include <zlib.h>
0016: #include <sys/types.h>
0017: #include <sys/stat.h>
0018: #include <errno.h>
0019:
0020: /**
0021: * # FUNCTION #
0022: * 圧縮ファイルの書き込みオープンエラーの表示&終了。
0023: */
0024: static void zwOpenErr(char *fName)
0025: {
0026: mssShowErrMsg("gz file write open error :\"%s\"",fName);
0027: mssEnd(mssErrorNoDefault);
0028: }
0029:
0030: /**
0031: * # FUNCTION #
0032: * 通常ファイルの書き込みオープンエラーの表示&終了。
0033: */
0034: static void fwOpenErr(char *fName)
0035: {
0036: mssShowErrMsg("file write open error :\"%s\"",fName);
0037: mssEnd(mssErrorNoDefault);
0038: }
0039:
0040: /**
0041: * # FUNCTION #
0042: * ファイル名から必要なディレクトリを作成する。
0043: * ex.)
0044: * fileName="abc/def/ghi/dat.xt"
0045: * -> カレントディレクトリにおいて、abc/dec/ghiのディレクトリを作成。
0046: * 最後の/以下は通常ファイルとみなす。
0047: */
0048: static void mkDir(char *fileName)
0049: {
0050: char fn[MssFileNameMaxLen];
0051: char *slaPos;
0052: char *dirTbl[100];
0053: int cnt=0;
0054: int i;
0055: int rt=0; /*ルートが指定されているかフラグ'/tmp'*/
0056: int err;
0057: char dirStr[MssFileNameMaxLen];
0058:
0059: if(*fileName=='/'){
0060: fileName++;
0061: rt=1;
0062: }
0063:
0064: strcpy(fn,fileName);
0065:
0066: slaPos = strtok(fn,"/");
0067: while(slaPos != NULL) {
0068: dirTbl[cnt]=slaPos;
0069: slaPos = strtok(NULL,"/");
0070: cnt++;
0071: if(cnt>=100) {
0072: mssShowErrMsg("too deep");
0073: mssEnd(mssErrorNoDefault);
0074: }
0075: }
0076: if(cnt<=1) return;
0077:
0078: if(rt){
0079: dirStr[0]='/'; dirStr[1]='\0';
0080: }else{
0081: dirStr[0]='\0';
0082: }
0083:
0084: for(i=0; i<cnt-1; i++){
0085: strcat(dirStr,dirTbl[i]);
0086: strcat(dirStr,"/");
0087: err=mkdir(dirStr,S_IRWXU|S_IRWXG|S_IRWXO);
0088: if(err==-1 && errno==EEXIST) continue;
0089: if(err==0) continue;
0090: mssShowErrMsg("can not make directory(%d) : \"%s\"",errno,dirStr);
0091: mssEnd(mssErrorNoDefault);
0092: }
0093: }
0094:
0095: /**
0096: * # FUNCTION #
0097: * 書き込みファイルをオープンする。
0098: * ファイル名(fileName)がNULLの場合は標準出力、1の場合は標準エラー出力として
0099: * オープンする。
0100: * 第二引数が1の場合は、圧縮ファイルとしてオープンし、書き込み結果は全て
0101: * gzip圧縮される。
0102: * 第三引数が1の場合は、ファイル名に含まれるディレクトリを強制的に作成する。
0103: */
0104: struct mssFPW *mssOpenFPW( char *fileName, int z, int d)
0105: {
0106: struct mssFPW *fp;
0107: int len;
0108:
0109: if(d) mkDir(fileName);
0110:
0111: fp=mssMalloc(sizeof(struct mssFPW),"openFPW");
0112: if(fileName==NULL || fileName==(char *)1){
0113: fp->fName=fileName;
0114: }else{
0115: fp->fName=mssMalloc(sizeof(char)*(strlen(fileName)+1),"openFPW");
0116: strcpy(fp->fName,fileName);
0117: }
0118:
0119: if(z){
0120: if(fileName == NULL){
0121: fp->zfd=gzdopen(1,"wb"); /*stdout*/
0122: }else if(fileName==(char *)1){
0123: fp->zfd=gzdopen(2,"wb"); /*stderr*/
0124: }else{
0125: fp->zfd=gzopen(fileName,"wb");
0126: }
0127: if(fp->zfd == NULL) zwOpenErr(fileName);
0128: fp->zflg=1;
0129: }else{
0130: if(fileName == NULL){
0131: fp->fp=stdout; /*stdout*/
0132: fp->zflg=0;
0133: }else if(fileName==(char *)1){
0134: fp->fp=stderr; /*stderr*/
0135: fp->zflg=0;
0136: }else{
0137: len=strlen(fileName);
0138: if(0==strcmp(fileName+len-3,".gz") ){
0139: fp->zfd=gzopen(fileName,"wb");
0140: if(fp->zfd == NULL) zwOpenErr(fileName);
0141: fp->zflg=1;
0142: }else{
0143: fp->fp=fopen(fileName,"w");
0144: if(fp->fp == NULL) fwOpenErr(fileName);
0145: fp->zflg=0;
0146: }
0147: }
0148: }
0149: return(fp);
0150: }
0151:
0152: /**
0153: * # FUNCTION #
0154: * 書き込みファイルをクローズする。
0155: */
0156: void mssCloseFPW(struct mssFPW *fp){
0157:
0158: if(fp==NULL) return;
0159:
0160: if(fp->fName!=NULL && fp->fName!=(char *)1){
0161: if(fp->zflg){
0162: gzclose(fp->zfd);
0163: }else{
0164: fclose(fp->fp);
0165: }
0166: }
0167: if(fp->fName!=NULL && fp->fName!=(char *)1 ) mssFree(fp->fName);
0168: mssFree(fp);
0169: }
0170:
0171: /**
0172: * # FUNCTION #
0173: * xmlTableの項目デリミター文字(MssFieldDelim)の出力。
0174: */
0175: void mssWriteDlm(struct mssFPW *fp){
0176: if(fp->zflg){
0177: gzputc(fp->zfd,MssFieldDelim);
0178: }else{
0179: putc(MssFieldDelim,fp->fp);
0180: }
0181: }
0182:
0183: /**
0184: * # FUNCTION #
0185: * 改行文字の出力。
0186: */
0187: void mssWriteRet(struct mssFPW *fp){
0188: if(fp->zflg){
0189: gzputc(fp->zfd,'\n');
0190: }else{
0191: putc('\n',fp->fp);
0192: }
0193: }
0194:
0195: /**
0196: * # FUNCTION #
0197: * 文字列の出力。
0198: */
0199: void mssWriteStr(char *str,struct mssFPW *fp){
0200: if(fp->zflg){
0201: gzputs(fp->zfd, str);
0202: }else{
0203: fputs(str, fp->fp);
0204: }
0205: }
0206:
0207: /**
0208: * # FUNCTION #
0209: * 文字の出力。
0210: */
0211: void mssWriteChr(char chr,struct mssFPW *fp){
0212: if(fp->zflg){
0213: gzputc(fp->zfd, chr);
0214: }else{
0215: putc(chr, fp->fp);
0216: }
0217: }
0218:
0219: /**
0220: * # FUNCTION #
0221: * 整数(int)の出力。
0222: */
0223: void mssWriteInt(int num,struct mssFPW *fp){
0224: if(fp->zflg){
0225: gzprintf(fp->zfd,"%d",num);
0226: }else{
0227: fprintf(fp->fp,"%d",num);
0228: }
0229: }
0230:
0231: /**
0232: * # FUNCTION #
0233: * Long整数(long)の出力。
0234: */
0235: void mssWriteLong(long num,struct mssFPW *fp){
0236: if(fp->zflg){
0237: gzprintf(fp->zfd,"%ld",num);
0238: }else{
0239: fprintf(fp->fp,"%ld",num);
0240: }
0241: }
0242:
0243: /**
0244: * # FUNCTION #
0245: * Double型実数(double)を全て10進浮動小数点表記("整数部.小数部")の書式で出力。
0246: */
0247: void mssWriteDbl(double num, struct mssFPW *fp){
0248: char *buf;
0249:
0250: buf=mssFtoA(num);
0251: mssWriteStr(buf,fp);
0252: mssFree(buf);
0253: }
0254:
0255: /**
0256: * # FUNCTION #
0257: * Double型実数(double)を数の大きさに応じて10進浮動小数点表記もしくは
0258: * 10進指数表記(ex.3.14152e+10)の書式で出力。
0259: */
0260: void mssWriteDbe(double num, struct mssFPW *fp){
0261: char buf[100];
0262:
0263: sprintf(buf,"%g",num);
0264: mssWriteStr(buf,fp);
0265: }
0266:
0267: /**
0268: * # FUNCTION #
0269: * NULL値(MssNullChr)の出力。
0270: */
0271: void mssWriteNull(struct mssFPW *fp){
0272: mssWriteChr(MssNullChr,fp);
0273: }
0274:
0275: /**
0276: * # FUNCTION #
0277: * 現在時刻の出力。
0278: * sepFlgを1に指定すると、"HH:MM:SS"の書式で出力。
0279: * それ以外は"HHMMSS"の書式で出力。
0280: */
0281: void mssWriteTime(struct mssFPW *fp,int sepFlg){
0282: time_t long_time;
0283: struct tm *nt;
0284: char msg[100];
0285:
0286: time(&long_time);
0287: nt = localtime(&long_time);
0288:
0289: if(sepFlg){
0290: sprintf(msg, "%02d:%02d:%02d",
0291: nt->tm_hour,
0292: nt->tm_min,
0293: nt->tm_sec);
0294: }else{
0295: sprintf(msg, "%02d%02d%02d",
0296: nt->tm_hour,
0297: nt->tm_min,
0298: nt->tm_sec);
0299: }
0300: mssWriteStr(msg,fp);
0301: }
0302:
0303: /**
0304: * # FUNCTION #
0305: * 現在日付の出力。
0306: * sepFlgを1に指定すると、"YYYY/MM/DD"の書式で出力。
0307: * それ以外は"YYYYMMDD"の書式で出力。
0308: */
0309: void mssWriteDate(struct mssFPW *fp,int sepFlg){
0310: time_t long_time;
0311: struct tm *nt;
0312: char msg[100];
0313:
0314: time(&long_time);
0315: nt = localtime(&long_time);
0316:
0317: /*日付*/
0318: if(sepFlg){
0319: sprintf(msg, "%04d/%02d/%02d",
0320: nt->tm_year + 1900,
0321: nt->tm_mon + 1,
0322: nt->tm_mday);
0323: }else{
0324: sprintf(msg, "%04d%02d%02d",
0325: nt->tm_year + 1900,
0326: nt->tm_mon + 1,
0327: nt->tm_mday);
0328: }
0329: mssWriteStr(msg,fp);
0330: }
0331:
0332: /**
0333: * # FUNCTION #
0334: * 文字列配列のcnt個の文字列を出力し、末尾文字列としてendStrを出力する。
0335: * 出力される文字列と文字列の間にはMssFieldDelimが出力される。
0336: * この関数は、通常、データ一行を出力するために利用する。
0337: *
0338: */
0339: void mssWriteFld(char **str, int cnt, char *endStr, struct mssFPW *fp){
0340: int i;
0341: for(i=0; i<cnt-1; i++){
0342: mssWriteStr(*(str+i),fp);
0343: mssWriteDlm(fp);
0344: }
0345: mssWriteStr(*(str+i),fp);
0346: mssWriteStr(endStr,fp);
0347: }