filex.c

C:\home\SVGCats_src\src\filex.c

[目次 | 関数 | マクロ]

目次

関数一覧

マクロ一覧


   1|/**************************************************************************
   2|  1. <<< ファイルの拡張 (FileX) >>> 
   3|【補足】
   4|・標準ライブラリに無い特殊なファイル処理です。
   5|・ファイルパスに関する処理は、StrX コンポーネントを参照してください。
   6|・FILE 構造体だけでなく DOS ファイルハンドルも扱います。
   7|***************************************************************************/
   8|
   9|#include "mixer_precomp.h"  /* Auto precompiled header, Look at mixer-... folder */
  10|// #pragma hdrstop
  11|
  12|#ifdef  UNDER_CE  /* FOR_WINCE */
  13| #error  not support
  14|#endif
  15|
  16|#if ( defined(_WIN32) || defined(FOR_DOS32) ) && !defined(__BORLANDC__)
  17| //#include  <windows.h>
  18|#endif
  19|#include  <ctype.h>
  20|#define  STDLIBS_INCLUDE_STRING_H
  21|#define  STDLIBS_INCLUDE_STDLIB_H
  22|#ifdef  USES_MXP_AUTOINC
  23| #include "filex.ah"  /* Auto include header, Look at mixer-... folder */
  24|#endif
  25|
  26|#include  <io.h>
  27|#include  <direct.h>
  28|#include  <sys\types.h>
  29|#include  <sys\stat.h>
  30|#ifdef  USES_TIMEDATE
  31| #include  <sys\utime.h>
  32|#endif
  33|
  34|static char  FileX_buf[1024];
  35|bool  FileX_bCopyFailed = false;
  36|
  37|
  38| 
  39|/***************************************************************************
  40|  2. <<< [FileX_FNames_path] ファイル名バッファ >>> 
  41|【補足】
  42|・FileX_open したファイル名の記録です。
  43|・過去 FileX_FNames_m 個のファイルの FILE* 型アドレスとファイル名を記録します。
  44|***************************************************************************/
  45|#ifndef  NDEBUG
  46|  enum { FileX_FNames_m = 30 };
  47|  int    FileX_FNames_i = 0;     /* 次に格納する番号(ローテーションします)*/
  48|  FILE*  FileX_FNames_file[FileX_FNames_m];
  49|  char   FileX_FNames_path[FileX_FNames_m][_MAX_PATH];
  50|#endif
  51|
  52| 
  53|/***************************************************************************
  54|  3. <<< [FileX_getOpenedFName] 開いたファイル名を返す >>> 
  55|【引数】
  56|  ・FILE*  fp;    ファイルポインタ
  57|【補足】
  58|・FileX_open したファイル名のみ記録してあります。
  59|***************************************************************************/
  60|char*  FileX_getOpenedFName( FILE* fp )
  61|{
  62|  #ifndef  NDEBUG
  63|    int  i;
  64|
  65|    for ( i = FileX_FNames_i - 1; i != FileX_FNames_i; i-- ) {
  66|      if ( i < 0 ) {
  67|        i = FileX_FNames_m - 1;
  68|        if ( i == FileX_FNames_i )
  69|          break;
  70|      }
  71|      if ( fp == FileX_FNames_file[i] )
  72|        return  FileX_FNames_path[i];
  73|    }
  74|    if ( fp == FileX_FNames_file[i] )
  75|      return  FileX_FNames_path[i];
  76|
  77|    return  "(Not Opened or Deleted from Record)";
  78|  #else
  79|    return  "(FileName not Recorded)";
  80|  #endif
  81|}
  82|
  83|
  84| 
  85|/***************************************************************************
  86|  4. <<< [FileX_open] FILE* 型のファイルを開く >>> 
  87|【補足】
  88|・例外付きの fopen 関数です。
  89|***************************************************************************/
  90|#ifdef  USES_STRX
  91|FILE*  FileX_open( const char* path, const char* mode )
  92|{
  93|  FILE*  file;
  94|
  95|  ASSERT( path != NULL );
  96|  ASSERT( *path != 0 );
  97|  if ( strcmp( path, "\\\"" ) == 0 )
  98|    ((char*)(path))[1] = ' ';
  99|  file = fopen( path, mode );
 100|  if ( file == NULL ) {
 101|    char  path2[_MAX_PATH];
 102|
 103|//WS( mode );
 104|    if ( strchr( mode, 'w' ) != NULL ) {
 105|      StrX_cpyFolder( path2, path );
 106|//WS( path2 );
 107|      if ( path2[0] != '\0' && ! FileX_isDir( path2 ) )
 108|        error2_1( FileX_Err_CannotWriteOpen,
 109|          "ファイルを格納するフォルダが無いので、ファイル \"%s\" が書きこめません", path );
 110|      else
 111|        error2_1( FileX_Err_CannotWriteOpen,
 112|          "ファイル \"%s\" が書きこめません(読み込み専用属性が付いているか、"
 113|          "フォルダです)", path );
 114|    }
 115|    else {
 116|      _getcwd( path2, sizeof(path2) );
 117|      error2_2( FileX_Err_CannotReadOpen,
 118|        "ファイル \"%s\" が見つかりません\n"
 119|        "カレント=%s", path, path2 );
 120|    }
 121|  }
 122|
 123|  #ifndef  NDEBUG
 124|    FileX_FNames_file[FileX_FNames_i] = file;
 125|    strcpy( FileX_FNames_path[FileX_FNames_i], path );
 126|    FileX_FNames_i ++;
 127|    if ( FileX_FNames_i == FileX_FNames_m )  FileX_FNames_i = 0;
 128|  #endif
 129|
 130|  return  file;
 131|}
 132|#endif
 133|
 134| 
 135|/***************************************************************************
 136|  5. <<< [FileX_getCSV] CSV 形式の1項目を入力する >>> 
 137|【引数】
 138|  ・char*  data;       項目を格納する文字列バッファ
 139|  ・int  data_maxLen;  data に格納できる最大のサイズ(\0含まず)
 140|【補足】
 141|・次に読み込むファイルポインタを、読み込む項目の先頭に移動してから呼び出し
 142|  てください。
 143|・次に読み込むファイルポインタは、',' または '\n' または EOF に移ります。
 144|・次の項目を読み込む前に ',' または '\n' を読み飛ばしてください。
 145|【例】
 146|・例1: abc,"abc,d""ef",123 (\n) なら data=[abc], ファイルポインタ = ','
 147|・例2: "abc,d""ef",123 (\n)     なら data=[abc,d"ef], ファイルポインタ = ','
 148|・例3: 123 (\n)                 なら data=[123], ファイルポインタ = '\n'
 149|***************************************************************************/
 150|void  FileX_getCSV( FILE* file, char* data, int data_maxLen )
 151|{
 152|  int    c, c2;
 153|  char*  data_over = data + data_maxLen;
 154|
 155|  c = fgetc( file );
 156|
 157|  /* "" の間を読み込む場合 */
 158|  if ( c == '"' ) {
 159|    c = fgetc( file );
 160|    c2 = fgetc( file );
 161|    while ( (c != '"' || c2 =='"') && c != EOF ) {
 162|      if ( data < data_over - 1 )
 163|        *data++ = (char)c;
 164|      if ( c == '"' && c2 == '"' )  c = fgetc( file );
 165|      else  c = c2;
 166|      c2 = fgetc( file );
 167|    }
 168|  }
 169|  /* , まで読み込む場合 */
 170|  else {
 171|    while ( c != ','  && c!= '\n' && c!= EOF ) {
 172|      if ( data < data_over - 1 )
 173|        *data++ = (char)c;
 174|      c = fgetc( file );
 175|    }
 176|    ungetc( c, file );
 177|  }
 178|  *data = '\0';
 179|}
 180|
 181|
 182| 
 183|/***************************************************************************
 184|  6. <<< [FileX_skipCSV] CSV 形式の1項目をスキップする >>> 
 185|【補足】
 186|・次に読み込むファイルポインタは、',' または '\n' または EOF に移ります。
 187|・次の項目を読み込む前に ',' または '\n' を読み飛ばしてください。
 188|***************************************************************************/
 189|void  FileX_skipCSV( FILE* file )
 190|{
 191|  char  c;
 192|
 193|  FileX_getCSV( file, &c, 0 );
 194|}
 195|
 196|
 197| 
 198|/***************************************************************************
 199|  7. <<< [FileX_putCSV] CSV 形式の1項目を出力する >>> 
 200|【補足】
 201|・必要に応じて "" で囲んだり " 文字を "" にします。
 202|・','や'\n'を出力しないので、別に行ってください。
 203|***************************************************************************/
 204|void  FileX_putCSV( FILE* file, char* data )
 205|{
 206|  bool  kakomu;  /* "" で囲むか */
 207|
 208|  kakomu = ( strchr( data, ',' ) || strchr( data, '"' ) );
 209|
 210|  if ( kakomu )  fprintf( file, "\"" );
 211|
 212|  while ( *data != '\0' ) {
 213|    if ( *data == '"' )  fprintf( file, "\"\"" );
 214|    else                 fprintf( file, "%c", *data );
 215|    data++;
 216|  }
 217|
 218|  if ( kakomu )  fprintf( file, "\"" );
 219|}
 220|
 221|
 222| 
 223|/************************************************************************
 224|  8. <<< [FileX_isExist] ファイルの存在を確かめる >>> 
 225|【引数】
 226|  ・char* fname;  ファイルへのパス名
 227|  ・bool 返り値;  ファイル or フォルダの存在
 228|【補足】
 229|・相対パスによって指定する場合、現在実行中のフォルダからの相対パスに
 230|  なります。
 231|・指定したパスがフォルダに一致する場合も、true を返します。
 232|*************************************************************************/
 233|#ifdef  USES_STRX
 234|#ifdef  USES_EXCEPT3
 235|bool  FileX_isExist( const char* fname )
 236|{
 237|  if ( strstr( fname, ".." ) != NULL ) {
 238|    char  path[_MAX_PATH];
 239|
 240|    c_try {
 241|      StrX_getRunFullPath( path, fname, sizeof(path) );
 242|    }
 243|    c_catch ( Errors_Msg*, err ) {
 244|      if ( err->code == StrX_Err_NoMoreParentDir )
 245|        strcpy( path, ".." );
 246|    } c_end_catch;
 247|    if ( strstr( path, ".." ) != NULL )
 248|      return  false;
 249|  }
 250|  return  (_access( fname, 0 ) == 0);
 251|}
 252|#endif
 253|#endif
 254| 
 255|/************************************************************************
 256|  9. <<< [FileX_isDir] フォルダの存在を確かめる >>> 
 257|【引数】
 258|  ・const char* fname;  フォルダへのパス名
 259|  ・bool 返り値;        フォルダの存在
 260|【補足】
 261|・相対パスによって指定する場合、現在実行中のフォルダからの相対パスに
 262|  なります。
 263|・指定したパスがファイルに一致する場合、false を返します。
 264|*************************************************************************/
 265|#ifdef  USES_STRX
 266|bool  FileX_isDir( const char* path )
 267|{
 268|  struct _stat  stat;
 269|  char  path2[_MAX_PATH];
 270|
 271|  strcpy( path2, path );
 272|  StrX_cutLastOf2( path2, '/' );
 273|  StrX_cutLastOf2( path2, '\\' );
 274|  if ( path2[2]== '\0' && path2[1] == ':' && isalpha( path2[0] ) )
 275|    return  true;
 276|
 277|  if ( _stat( path2, &stat ) )  return  false;
 278|  return ( stat.st_mode & _S_IFDIR ) ? true : false;
 279|}
 280|#endif
 281|
 282|
 283| 
 284|/************************************************************************
 285|  10. <<< [FileX_getOneExistWild] ワイルドカードに一致するファイルパスを得る >>> 
 286|【引数】
 287|  ・char*  wild_path;   ワイルドカードを含んだファイルパス
 288|  ・char*  first_path;  一致したパス(一致したうちの1つ)(サイズは _MAX_PATH)
 289|  ・int  返り値;        一致したファイルの数
 290|*************************************************************************/
 291|int  FileX_getOneExistWild( const char* wild_path, char* first_path )
 292|{
 293|  long  handle;
 294|  int  n = 0;
 295|  struct _finddata_t  data;
 296|
 297|  handle = _findfirst( (char*)wild_path, &data );
 298|  if ( handle != -1 ) {
 299|
 300|    StrX_cpyFolder( first_path, wild_path );
 301|    StrX_addFName( first_path, data.name );
 302|    n ++;
 303|
 304|    while ( _findnext( handle, &data ) != -1 )
 305|      n++;
 306|
 307|    _findclose( handle );
 308|  }
 309|
 310|  return  n;
 311|}
 312|
 313| 
 314|/************************************************************************
 315|  11. <<< [FileX_getUpdate] ファイルの更新日時を取得する >>> 
 316|【引数】
 317|  ・time_t*  date;  更新日時を格納するアドレス
 318|【補足】
 319|・相対パスによって指定する場合、現在実行中のフォルダからの相対パスに
 320|  なります。
 321|・ファイルが存在しない場合、動作未定義です。
 322|・time_t 型は、ctime や difftime などの標準関数に使うことが出来ます。
 323|*************************************************************************/
 324|#ifdef  USES_STDPLUS
 325|void  FileX_getUpdate( const char* fName, time_t* date )
 326|{
 327|  int  r;
 328|  struct _stat  status;
 329|
 330|  r = _stat( fName, &status );
 331|  if ( r != 0 ) {
 332|    StdPlus_printErrno();
 333|    error();
 334|  }
 335|
 336|  *date = status.st_mtime;
 337|}
 338|#endif  /* USES_STDPLUS */
 339|
 340|
 341| 
 342|/************************************************************************
 343|  12. <<< [FileX_setUpdate] ファイルの更新日時を変更する >>> 
 344|【引数】
 345|  ・time_t*  date;  更新日時を格納するアドレス
 346|【補足】
 347|・相対パスによって指定する場合、現在実行中のフォルダからの相対パスに
 348|  なります。
 349|*************************************************************************/
 350|#if  defined(USES_STDPLUS) && defined(USES_TIMEDATE)
 351|void  FileX_setUpdate( const char* path, time_t* date )
 352|{
 353|  struct _utimbuf  tim;
 354|
 355|  time( &tim.actime );
 356|  tim.modtime = *date;
 357|  if ( _utime( path, &tim ) == -1 )
 358|    error();
 359|}
 360|#endif
 361|
 362|
 363| 
 364|/************************************************************************
 365|  13. <<< [FileX_getSize] ファイルサイズを返す >>> 
 366|【補足】
 367|・相対パスによって指定する場合、現在実行中のフォルダからの相対パスに
 368|  なります。
 369|・使用サイズを取得するには、FileX_FreeSpc_getUseFileSize 関数を使用して
 370|  ください。
 371|・ファイルが存在しない場合や無効なパスを指定したときは、0 を返します。
 372|*************************************************************************/
 373|int   FileX_getSize( const char* path )
 374|{
 375|  int  r;
 376|  struct _stat  status;
 377|
 378|  r = _stat( path, &status );
 379|  if ( r != 0 )  return  0;
 380|
 381|  return  status.st_size;
 382|}
 383| 
 384|/************************************************************************
 385|  14. <<< [FileX_getSftSum] シフトチェックサムの値を返す >>> 
 386|【引数】
 387|  ・int  maxFileSize;  調査する最大のファイルサイズ(-1=ファイル全部)
 388|【補足】
 389|・シフトチェックサムの値は、ファイルの先頭から1バイトごとに合計した値ですが、
 390|  ファイルアドレスを7で割った余りの分だけ左シフトしてから加算します。
 391|・maxFileSize を指定すると、先頭から指定のバイト数までの合計をします。
 392|・相対パスによって指定する場合、現在実行中のフォルダからの相対パスに
 393|  なります。
 394|*************************************************************************/
 395|int   FileX_getSftSum( const char* path, int maxFileSize )
 396|{
 397|  FILE*  f;
 398|  int  c;
 399|  int  sum = 0;
 400|  int  adr = 0;
 401|  int  adr_mod7 = 0;   /* ファイルアドレスを7で割った余り */
 402|
 403|  f = FileX_open( path, "rb" );
 404|  while ( ( c = fgetc( f ) ) != EOF && adr < maxFileSize ) {
 405|    sum += ( c << adr_mod7 );
 406|    adr ++;
 407|    adr_mod7 = ( adr_mod7 == 6 ? 0 : adr_mod7 + 1 );
 408|  }
 409|
 410|  fclose( f );
 411|
 412|  return  sum;
 413|}
 414| 
 415|/************************************************************************
 416|  15. <<< [FileX_getPathes] フォルダに入っているファイルパスを取得する >>> 
 417|【引数】
 418|  ・char*  folder;      フォルダパス(絶対パス)
 419|  ・StrX_Mem*  files;   ファイルパスの格納場所(初期化済みを指定)
 420|【補足】
 421|・絶対パスで格納します。
 422|・ファイルパスは、StrX_Mem_alloc で確保した領域に格納ます。
 423|*************************************************************************/
 424|#ifdef  USES_FILEFIND
 425|#ifdef  USES_STRX
 426|void  FileX_getPathes( const char* folder, StrX_Mem* files )
 427|{
 428|  FileFind  find;
 429|  char*  s;
 430|
 431|  FileFind_init( &find, folder );
 432|
 433|  while ( FileFind_next( &find ) == 0 ) {
 434|    if ( ! FileFind_isDir( &find ) ) {
 435|      s = StrX_Mem_alloc( files );
 436|      strcpy( s, folder );  s = strchr( s, '\0' );
 437|      *s = '\\';  s++;
 438|      strcpy( s, FileFind_getFName( &find ) );
 439|    }
 440|  }
 441|  FileFind_finish( &find );
 442|}
 443|#endif  /* USES_STRX */
 444|#endif  /* USES_FILEFIND */
 445|
 446|
 447| 
 448|/************************************************************************
 449|  16. <<< [FileX_repairExt] ファイルの内容を調べて拡張子を直す >>> 
 450|【引数】
 451|  ・char*  path;    (入力)ファイルパス、(出力)拡張子を修正したパス
 452|  ・bool  返り値;   ファイルタイプを識別できたかどうか
 453|【補足】
 454|・拡張子を修正した場合、path 変数の内容だけでなく、ファイルの名前も変わります。
 455|*************************************************************************/
 456|#ifdef  USES_STRX
 457|bool  FileX_repairExt( char* path )
 458|{
 459|  FILE*  f;
 460|  char  head[16];
 461|  char*  ext = NULL;
 462|  char  path2[_MAX_PATH];
 463|
 464|  if ( ! FileX_isExist( path ) )  return  false;
 465|
 466|  f = FileX_open( path, "rb" );
 467|  fread( head, 1, sizeof(head), f );
 468|  fclose( f );
 469|
 470|  if ( strncmp( head, "GIF", 3 ) == 0 )  ext = "gif";
 471|  else if ( strncmp( head + 1, "PNG", 3 ) == 0 )  ext = "png";
 472|  else if ( strncmp( head + 6, "JFIF", 4 ) == 0 )  ext = "jpg";
 473|
 474|  if ( ext == NULL )  return  false;
 475|
 476|  if ( stricmp( StrX_refExt( path ), ext ) != 0 ) {
 477|    strcpy( path2, path );
 478|    StrX_chgExt( path, ext );
 479|    remove( path );
 480|    MoveFile( path2, path );
 481|  }
 482|
 483|  return  true;
 484|}
 485|#endif
 486| 
 487|/************************************************************************
 488|  17. <<< [FileX_isUpdate] ファイルが同一バージョンか判断する >>> 
 489|【機能】
 490|・ファイルの更新日時が秒単位なのを利用して、ファイルが同一バージョンか
 491|  どうか判断します。
 492|【引数】
 493|  ・const char* fName;  判断するファイル名
 494|  ・time_t* date;       入力は、比較対象となるバージョンの更新日付
 495|                        出力は、fName のファイルの更新日付
 496|  ・bool  返り値;       同一バージョンかどうか
 497|【補足】
 498|・もし、時計のずれや、頻繁な更新のために、偶然に同一時刻になった場合、
 499|  正しく判断できません。
 500|**************************************************************************/
 501|bool  FileX_isUpdate( const char* fName, time_t* date )
 502|{
 503|  bool  ret;
 504|  int  r;
 505|  struct _stat  status;
 506|
 507|  r = _stat( fName, &status );
 508|  ASSERT( r == 0 );
 509|
 510|  ret = (*date == status.st_mtime );
 511|  *date = status.st_mtime;
 512|  return  ret;
 513|}
 514|
 515|
 516| 
 517|/************************************************************************
 518|  18. <<< [FileX_cmpTime] ファイルの更新日時を比較する >>> 
 519|【引数】
 520|  ・int 返り値;  0=等しい、0より大(>) fNameA のファイルが新しい
 521|                           0より小(<) fNameB のファイルが新しい
 522|【補足】
 523|・相対パスによって指定する場合、現在実行中のフォルダからの相対パスに
 524|  なります。
 525|・ファイルの存在と更新日時に対する返り値の関係は次の通りです。
 526|   [fNameA] [更新日時] [fNameB] [返り値]
 527|     存在       ==       存在      0
 528|     存在       >        存在      1
 529|     存在       <        存在     -1
 530|     存在                なし      2
 531|     なし                存在     -2
 532|     なし                なし      0
 533|・新しいファイルを上書きコピーするものと同じアルゴリズムを使って、
 534|  新しいファイルを作る(コピーする)ことができます。
 535|・引数にファイル名を指定しない場合、TimeDate_cmpTime 関数を用います。
 536|*************************************************************************/
 537|#ifdef  USES_STDPLUS
 538|#ifdef  USES_EXCEPT3
 539|int  FileX_cmpTime( const char* fNameA, const char* fNameB )
 540|{
 541|  time_t  timeA, timeB;
 542|  double  diffTime;
 543|
 544|  // ファイルの存在しない場合、最も古いものとして比較する
 545|  if ( ! FileX_isExist( fNameA ) ) {
 546|    if ( ! FileX_isExist( fNameB ) )  return  0;
 547|    else  return  -2;
 548|  }
 549|  else if ( ! FileX_isExist( fNameB ) )  return  2;
 550|
 551|  // 両方のファイルの日付を比較する
 552|  FileX_getUpdate( fNameA, &timeA );
 553|  FileX_getUpdate( fNameB, &timeB );
 554|  diffTime = difftime( timeA, timeB );
 555|  if ( diffTime > 0 )  return  1;
 556|  else if ( diffTime < 0 )  return  -1;
 557|  else  return  0;
 558|}
 559|#endif
 560|#endif /* USES_STDPLUS */
 561|
 562|
 563| 
 564|/***********************************************************************
 565|  19. <<< [FileX_getTmpPath] テンポラリファイルのパスを作成する >>> 
 566|【引数】
 567|  ・char*  prefix;   ファイル名に付ける接頭辞
 568|  ・char*  path;     作成したパスを格納するアドレス(サイズは _MAX_PATH)
 569|【補足】
 570|・Windows の場合、通常 c:\Windows\Temp フォルダの中のファイルへのパスを
 571|  作成します。
 572|************************************************************************/
 573|void  FileX_getTmpPath( const char* prefix, char* path )
 574|{
 575|  static char*  defTmpDir = "\\";
 576|  char*  s;
 577|
 578|  s = _tempnam( defTmpDir, (char*)prefix );
 579|  strcpy( path, s );
 580|
 581|  #ifdef  STDPLUS_USES_STDNAME
 582|    #undef  free
 583|  #endif
 584|
 585|  free( s );
 586|
 587|  #ifdef  STDPLUS_USES_STDNAME
 588|    #define  free  StdPlus_free
 589|  #endif
 590|}
 591|
 592| 
 593|/***********************************************************************
 594|  20. <<< [FileX_getTmpPath2] テンポラリファイルのパスを作成する(フォルダ指定) >>> 
 595|【引数】
 596|  ・char*  prefix;   ファイル名に付ける接頭辞
 597|  ・char*  path;     作成したパスを格納するアドレス(サイズは _MAX_PATH)
 598|  ・char*  folder;   テンポラリファイルを作成するフォルダ(絶対パス)
 599|************************************************************************/
 600|#ifdef  USES_STRX
 601|#ifdef  USES_EXCEPT3
 602|void   FileX_getTmpPath2( const char* prefix, const char* folder, char* path )
 603|{
 604|  int  i = 1;
 605|  int  bDir = FileX_isDir( folder );
 606|
 607|  for (;;) {
 608|    if ( bDir ) {
 609|      if ( StrX_getLast( folder ) == '\\' )
 610|        sprintf( path, "%s%s%d", folder, prefix, i );
 611|      else
 612|        sprintf( path, "%s\\%s%d", folder, prefix, i );
 613|    }
 614|    else {
 615|      StrX_cpyFolder( path, folder );
 616|      sprintf( strchr( path, '\0' ), "\\%s%d", prefix, i );
 617|    }
 618|    if ( ! FileX_isExist( path ) )  return;
 619|    i++;
 620|  }
 621|}
 622|#endif
 623|#endif
 624| 
 625|/***********************************************************************
 626|  21. <<< [FileX_getTmpPath2] テンポラリファイルのパスを作成する(フォルダ指定) >>> 
 627|【引数】
 628|  ・char*  prefix;   ファイル名に付ける接頭辞
 629|  ・char*  path;     作成したパスを格納するアドレス(サイズは _MAX_PATH)
 630|  ・char*  folder;   テンポラリファイルを作成するフォルダ(絶対パス)
 631|************************************************************************/
 632|#if  defined(USES_WINX) && defined(USES_STRX) && defined(USES_EXCEPT3)
 633|void  FileX_getTmpPath3( const char* folder, const char* prefix, const char* ext, char* path )
 634|{
 635|  int   i = 1;
 636|  bool  b;
 637|
 638|  if ( folder == NULL || ! FileX_isDir( folder ) ) {
 639|    folder = WinX_getTempPath();
 640|  }
 641|
 642|  b = ( StrX_getLast( folder ) == '\\' );
 643|
 644|  for (;;) {
 645|    if ( b )
 646|      sprintf( path, "%s%s%d.%s", folder, prefix, i, ext );
 647|    else
 648|      sprintf( path, "%s\\%s%d.%s", folder, prefix, i, ext );
 649|
 650|    if ( ! FileX_isExist( path ) )  return;
 651|    i++;
 652|  }
 653|}
 654|#endif
 655| 
 656|/*************************************************************************
 657|  22. <<< [FileX_isDiff] 2つのファイルの内容が同一かどうか調べる >>> 
 658|【引数】
 659|  ・int  返り値;   0=同一、 1=異なる、-1=fname1 が開けない、
 660|                  -2=fname2 が開けない、-3=fname1,fname2 とも開けない
 661|【補足】
 662|・両方のファイルが存在して、内容が同一かどうかを判定するならば、
 663|  返り値は bool 値(0か0以外か)として判定することができます。
 664|**************************************************************************/
 665|int  FileX_isDiff( const char* fNameA, const char* fNameB )
 666|{
 667|  int  ret;
 668|  FILE  *file1, *file2;
 669|  int  size1, size2;
 670|  static char  buf1[256], buf2[256];
 671|
 672|  file1 = fopen( fNameA, "rb" );
 673|  file2 = fopen( fNameB, "rb" );
 674|
 675|  if ( file1 == NULL ) {
 676|    if ( file2 == NULL )  return  -3;
 677|    else {
 678|      fclose( file2 );
 679|      return -1;
 680|    }
 681|  }
 682|  if ( file2 == NULL ) {
 683|    fclose( file1 );
 684|    return -2;
 685|  }
 686|
 687|  ret = 1;
 688|  for (;;) {
 689|    size1 = fread( buf1, 1, 256, file1 );
 690|    size2 = fread( buf2, 1, 256, file2 );
 691|
 692|    if ( size1 != size2 )  break;
 693|    if ( memcmp( buf1, buf2, size1 ) != 0 )  break;
 694|
 695|    if ( size1 != 256 )  { ret = 0; break; }
 696|  }
 697|
 698|  fclose( file1 );
 699|  fclose( file2 );
 700|
 701|  return  ret;
 702|}
 703|
 704|
 705| 
 706|/*************************************************************************
 707|  23. <<< [FileX_copy] ファイルをコピーする >>> 
 708|【補足】
 709|・to_path は、フォルダ名だけでなく、ファイル名まで指定してください。
 710|**************************************************************************/
 711|#if  defined(USES_STDPLUS) && defined(USES_STRX)
 712|#if  defined(USES_BIGSTACK) && defined(USES_EXCEPT3) && defined(USES_TIMEDATE)
 713|#if  defined(FOR_WIN32) || defined(FOR_DOS32)
 714|void  FileX_copy( const char* to_path, const char* from_path )
 715|{
 716|  FileX_copy2( to_path, from_path, NULL, NULL );
 717|}
 718|#endif
 719|#endif
 720|#endif
 721|
 722| 
 723|/*************************************************************************
 724|  24. <<< [FileX_copy2] ファイルをコピーする(コールバック付き) >>> 
 725|【引数】
 726|  ・FileX_CopyBack  callback;  進捗状況表示のためのコールバック関数
 727|【補足】
 728|・to_path は、フォルダ名だけでなく、ファイル名まで指定してください。
 729|・fwrite を実行するたびに callback 関数を呼び出します。
 730|・書き込みに失敗した場合、エラーになり、それまでにコピーしたデータは削除されます。
 731|**************************************************************************/
 732|#if  defined(USES_STDPLUS) && defined(USES_STRX)
 733|#if  defined(USES_BIGSTACK) && defined(USES_EXCEPT3) && defined(USES_TIMEDATE)
 734|#if  defined(WIN32) || defined(FOR_DOS32)
 735|void  FileX_copy2( const char* to_path, const char* from_path,
 736|  FileX_CallBack callback, void* obj )
 737|{
 738|  FILE*  to_file;
 739|  FILE*  from_file;
 740|  size_t  size;
 741|  struct _utimbuf  tim;
 742|  time_t  date;
 743|  int     now = 0, all;
 744|  DWORD   attr;
 745|  BOOL    bSuccess;
 746|
 747|  if ( ! FileX_isExist( from_path ) ) {
 748|    error2_1( FileX_Err_NotFindCopySrc, "コピー元が見つかりません %s",
 749|      from_path );
 750|  }
 751|
 752|  /* ファイルの属性を取得する */
 753|  attr = GetFileAttributes( from_path );
 754|  if ( attr == 0xFFFFFFFF )  error();
 755|  FileX_getUpdate( from_path, &date );
 756|  all = FileX_getSize( from_path );
 757|
 758|  /* ファイルを開く */
 759|  FileX_mkdir2( to_path, true );
 760|  if ( FileX_isExist( to_path ) )  FileX_setReadOnly( to_path, false );
 761|  to_file = FileX_open( to_path, "wb" );
 762|  from_file = FileX_open( from_path, "rb" );
 763|
 764|  /* ファイルの内容をコピーする */
 765|  if ( callback != NULL )  callback( obj, now, all );
 766|  do {
 767|    size = fread( FileX_buf, 1, sizeof(FileX_buf), from_file );
 768|    if ( fwrite( FileX_buf, 1, size, to_file ) != size ) {
 769|      fclose( to_file );  fclose( from_file );
 770|      remove( to_path );
 771|      FileX_bCopyFailed = true;
 772|      error2_1( FileX_Err_CannotWrite, "%s の書きこみに失敗しました。",
 773|        to_path );
 774|    }
 775|    now += size;
 776|    if ( callback != NULL )  callback( obj, now, all );
 777|  } while ( size == sizeof(FileX_buf) );
 778|
 779|  /* ファイルを閉じる */
 780|  fclose( to_file );
 781|  fclose( from_file );
 782|
 783|  /* 更新日付やファイル属性を元のファイルと同じにする */
 784|  time( &tim.actime );
 785|  tim.modtime = date;
 786|  _utime( to_path, &tim );
 787|  bSuccess = SetFileAttributes( to_path, attr );
 788|  if ( ! bSuccess )  error();
 789|}
 790|#endif
 791|#endif
 792|#endif
 793|
 794| 
 795|/*************************************************************************
 796|  25. <<< [FileX_move] ファイルまたはフォルダを移動する >>> 
 797|【補足】
 798|・from_path にフォルダのパスを指定することも出来ます。
 799|・to_path は、格納するフォルダ名だけでなく、ファイル名(フォルダ名)まで
 800|  指定してください。
 801|・ドライブが異なる場合、コピーを実行するためパフォーマンスが落ちることがあります。
 802|・移動先にファイルがある場合は上書きします。
 803|・移動先にフォルダがある場合、フォルダに含まれるファイル名が一致するときのみ
 804|  ファイルを上書きします。
 805|・書き込みに一度でも失敗した場合、データ保護のためコピー元の削除を一切
 806|  行わなくなります。この状態から復元するには、FileX_bCopyFailed グローバル変数を
 807|  false にしてください。
 808|**************************************************************************/
 809|#ifdef  USES_STRX
 810|#ifdef  USES_STDPLUS
 811|#ifdef  USES_FILEFIND
 812|#ifdef  USES_NESTFIND
 813|#ifdef  USES_BIGSTACK
 814|#ifdef  USES_WINX
 815|void  FileX_move( const char* to_path, const char* from_path )
 816|{
 817|  if ( MoveFile( from_path, to_path ) == 0 ) {
 818|    if ( FileX_isDir( from_path ) ) {
 819|      FileX_copyFolder( to_path, from_path, true );
 820|      if ( ! FileX_bCopyFailed )
 821|        FileX_removeFolder( from_path );
 822|    }
 823|    else {
 824|      FileX_copy2( to_path, from_path, NULL, NULL );
 825|      if ( ! FileX_bCopyFailed ) {
 826|        if ( remove( from_path ) == -1 )
 827|          error2_1( FileX_Err_AccessDenied, "%s が削除できません", from_path );
 828|      }
 829|    }
 830|  }
 831|}
 832|#endif
 833|#endif
 834|#endif
 835|#endif
 836|#endif
 837|#endif
 838|
 839| 
 840|/*************************************************************************
 841|  26. <<< [FileX_copyPickup] ファイルの一部をコピーする >>> 
 842|【引数】
 843|  ・char*  to_path;    コピー先(絶対パス)
 844|  ・char*  from_path;  コピー元(絶対パス)
 845|  ・int  startPos;     開始ファイルアドレス
 846|  ・int  endPos;       終了ファイルアドレスの次(FILEX_TO_LAST, FILEX_TO_FULLも可)
 847|  ・int  返り値        コピーしたファイルのサイズ
 848|【補足】
 849|・to_path は、フォルダ名だけでなく、ファイル名まで指定してください。
 850|・endPos のアドレスの直前までコピーします。endPos のアドレスの内容はコピーしません。
 851|・endPos に FILEX_TO_LAST を指定すると最後までコピーします。
 852|  FILEX_TO_FULL を指定するとディスクの容量をチェックしてできる限りコピーします。
 853|**************************************************************************/
 854|#if  defined(USES_STDPLUS) && defined(USES_STRX)
 855|#if  defined(USES_BIGSTACK) && defined(USES_EXCEPT3) && defined(USES_TIMEDATE)
 856|#if  defined(WIN32) || defined(FOR_DOS32)
 857|int   FileX_copyPickup( const char* to_path, const char* from_path,
 858|  int startPos, int endPos )
 859|{
 860|  return  FileX_copyPickup2( to_path, from_path,
 861|     startPos, endPos, NULL, NULL );
 862|}
 863|#endif
 864|#endif
 865|#endif
 866|
 867| 
 868|/*************************************************************************
 869|  27. <<< [FileX_copyPickup2] ファイルの一部をコピーする >>> 
 870|【引数】
 871|  ・char*  to_path;    コピー先(絶対パス)
 872|  ・char*  from_path;  コピー元(絶対パス)
 873|  ・int  startPos;     開始ファイルアドレス
 874|  ・int  endPos;       終了ファイルアドレスの次(FILEX_TO_LAST, FILEX_TO_FULLも可)
 875|  ・int  返り値        コピーしたファイルのサイズ
 876|【補足】
 877|・to_path は、フォルダ名だけでなく、ファイル名まで指定してください。
 878|・endPos のアドレスの直前までコピーします。endPos のアドレスの内容はコピーしません。
 879|・endPos に FILEX_TO_LAST を指定すると最後までコピーします。
 880|  FILEX_TO_FULL を指定するとディスクの容量をチェックしてできる限りコピーします。
 881|**************************************************************************/
 882|#ifdef  WIN32
 883|#ifdef  USES_STRX
 884|#ifdef  USES_EXCEPT3
 885|#ifdef  USES_BIGSTACK
 886|int   FileX_copyPickup2( const char* to_path, const char* from_path,
 887|  int startPos, int endPos, FileX_CallBack callback, void* obj )
 888|{
 889|  char  root_path[4];
 890|  FILE*  to_file;
 891|  FILE*  from_file;
 892|  int    size, leftSize;
 893|  int    now = 0, all;
 894|
 895|  if ( endPos == FILEX_TO_FULL ) {
 896|    FileX_FreeSpc  spc;
 897|
 898|    FileX_FreeSpc_init( &spc );
 899|    strncpy( root_path, to_path, 3 );  root_path[3] = '\0';
 900|    ASSERT( root_path[1] == ':' );
 901|    FileX_FreeSpc_scan( &spc, root_path );
 902|    endPos = startPos + FileX_FreeSpc_getFreeSize( &spc ) +
 903|      FileX_FreeSpc_getUseFileSize( &spc, to_path );
 904|  }
 905|  else if ( endPos == FILEX_TO_LAST ) {
 906|    endPos = INT_MAX;
 907|  }
 908|
 909|  all = FileX_getSize( from_path );
 910|  if ( all < endPos )  all = endPos;
 911|  all -= startPos;
 912|
 913|  FileX_mkdir2( to_path, true );
 914|  to_file = FileX_open( to_path, "wb" );
 915|  from_file = FileX_open( from_path, "rb" );
 916|
 917|  fseek( from_file, startPos, SEEK_SET );
 918|  leftSize = endPos - startPos;
 919|  if ( callback != NULL )  callback( obj, now, all );
 920|  do {
 921|    size = fread( FileX_buf, 1, sizeof(FileX_buf), from_file );
 922|    if ( size > leftSize )  size = leftSize;
 923|    if ( fwrite( FileX_buf, 1, size, to_file ) != (unsigned)size ) {
 924|      fclose( to_file );  fclose( from_file );
 925|      remove( to_path );
 926|      FileX_bCopyFailed = true;
 927|      error2_1( FileX_Err_CannotWrite, "%s の書きこみに失敗しました。",
 928|        to_path );
 929|    }
 930|    leftSize -= size;
 931|    now += size;
 932|    if ( callback != NULL )  callback( obj, now, all );
 933|  } while ( size == sizeof(FileX_buf) );
 934|
 935|  fclose( to_file );
 936|  fclose( from_file );
 937|
 938|  return  now;
 939|}
 940|#endif
 941|#endif
 942|#endif
 943|#endif
 944|
 945| 
 946|/***********************************************************************
 947|  28. <<< [FileX_outPart] ファイルの一部を出力する >>> 
 948|【引数】
 949|  ・FILE*  out;       出力先
 950|  ・FILE*  in;        入力
 951|  ・int    in_start;  入力開始位置
 952|  ・int    in_over;   入力終了の次の位置
 953|【補足】
 954|・out と in は、バイナリファイルで開いてください。
 955|************************************************************************/
 956|void  FileX_outPart( FILE* out, FILE* in, int in_start, int in_over )
 957|{
 958|  int   leftSize = in_over - in_start;
 959|  int   size;
 960|  char  buf[2048];
 961|
 962|  #if ERRORS_DEBUG_FALSE
 963|    Errors_printf( "in_start = %d, in_over = %d", in_start, in_over );
 964|    fprintf( out, "------------------------in_start = %d, in_over = %d\n", in_start, in_over );
 965|  #endif
 966|
 967|  ASSERT( in_start <= in_over );
 968|
 969|  fseek( in, in_start, SEEK_SET );
 970|
 971|  do {
 972|    size = ( leftSize < sizeof(buf) ) ? leftSize : sizeof(buf);
 973|    size = fread( buf, 1, size, in );
 974|    if ( fwrite( buf, 1, size, out ) != (unsigned)size ) {
 975|      error2_0( FileX_Err_CannotWrite, "書きこみに失敗しました。" );
 976|    }
 977|    leftSize -= size;
 978|  } while ( size == sizeof(buf) );
 979|}
 980| 
 981|/*************************************************************************
 982|  29. <<< [FileX_copyFolder] フォルダごとコピーする >>> 
 983|【引数】
 984|  ・bool  bSub;   サブフォルダもコピーする
 985|【補足】
 986|・コピー先のフォルダに含まれるファイル名が一致するときのみファイルを上書きします。
 987|・書きこみに失敗したら、エラーになり、書き込み中だったコピー先のファイルは
 988|  削除されます。すでに書きこんだファイルはそのまま残ります。
 989|**************************************************************************/
 990|#ifdef  USES_FILEFIND
 991|#ifdef  USES_NESTFIND
 992|#if  defined(USES_STDPLUS) && defined(USES_STRX)
 993|#if  defined(USES_BIGSTACK) && defined(USES_EXCEPT3) && defined(USES_TIMEDATE)
 994|#if  defined(WIN32) || defined(FOR_DOS32)
 995|void  FileX_copyFolder( const char* to_path, const char* from_path,
 996|  bool bSub )
 997|{
 998|  NestFind  find;
 999|  char  from_path2[_MAX_PATH];
1000|  char  to_path2[_MAX_PATH];
1001|
1002|  if ( FileX_isExist( to_path ) && ! FileX_isDir( to_path ) ) {
1003|    error2_1( FileX_Err_CannotWrite, "%s の書きこみに失敗しました。",
1004|      to_path );
1005|  }
1006|  FileX_mkdir2( to_path, 0 );
1007|
1008|#if 0
1009|  ASSERT( ! bSub );
1010|  FileFind_init( &find, from_path );
1011|  c_try {
1012|    while ( FileFind_next( &find ) == 0 ) {
1013|      if ( ! FileFind_isDir( &find ) ) {
1014|        char* fname = FileFind_getFName( &find );
1015|        StrX_cpyAbsPath( from_path2, fname, _MAX_PATH, from_path );
1016|        StrX_cpyAbsPath( to_path2, fname, _MAX_PATH, to_path );
1017|        if ( FileX_isExist( from_path2 ) )
1018|          FileX_copy( to_path2, from_path2 );
1019|      }
1020|    }
1021|  }
1022|  c_finally {
1023|    FileFind_finish( &find );
1024|  } c_end_finally;
1025|#else
1026|  NestFind_init( &find, from_path, false );
1027|  c_try {
1028|    while ( NestFind_next( &find ) ) {
1029|      char* fname = NestFind_getPath( &find );
1030|      StrX_cpyAbsPath( from_path2, fname, _MAX_PATH, from_path );
1031|      StrX_cpyAbsPath( to_path2, fname, _MAX_PATH, to_path );
1032|      if ( FileX_isExist( from_path2 ) )
1033|        FileX_copy( to_path2, from_path2 );
1034|    }
1035|  }
1036|  c_finally {
1037|    NestFind_finish( &find );
1038|  } c_end_finally;
1039|#endif
1040|}
1041|#endif
1042|#endif
1043|#endif
1044|#endif
1045|#endif
1046| 
1047|/*************************************************************************
1048|  30. <<< [FileX_removeFolder] フォルダごと削除する >>> 
1049|【補足】
1050|・バックアップを取ってから実行してください。
1051|・システム領域は削除しないで下さい。
1052|・ごみ箱には格納されません。
1053|**************************************************************************/
1054|#ifdef  USES_NESTFIND
1055|#ifdef  USES_WINX
1056|#ifdef  USES_EXCEPT3
1057|void  FileX_removeFolder( const char* path )
1058|{
1059|  NestFind  find;
1060|
1061|  #ifdef  NDEBUG
1062|    #ifdef  FOR_WIN32
1063|    {
1064|      char  s[_MAX_PATH];
1065|      if ( stricmp( path, WinX_getWindowsPath() ) == 0 )  error();
1066|      GetSystemDirectory( s, sizeof(s) );
1067|      if ( stricmp( path, s ) == 0 )  error();
1068|    }
1069|    #else
1070|    #endif
1071|  #endif
1072|
1073|  if ( ! FileX_isExist( path ) )  return;
1074|
1075|  NestFind_init( &find, path, true );
1076|  while ( NestFind_next( &find ) ) {
1077|    if ( FileX_isDir( NestFind_getAbsPath( &find ) ) )
1078|      _rmdir( NestFind_getAbsPath( &find ) );
1079|    else {
1080|      _chmod( NestFind_getAbsPath( &find ), _S_IREAD | _S_IWRITE );
1081|      remove( NestFind_getAbsPath( &find ) );
1082|    }
1083|  }
1084|  NestFind_finish( &find );
1085|
1086|  {
1087|    char s[_MAX_PATH];
1088|    _getcwd( s, sizeof(s) );
1089|    if ( stricmp( s, path ) == 0 )
1090|      _chdir( ".." );
1091|  }
1092|  if ( ! RemoveDirectory( path ) )  WinX_error();
1093|}
1094|#endif
1095|#endif
1096|#endif
1097| 
1098|/*************************************************************************
1099|  31. <<< [FileX_removeWild] ワイルドカードを指定してファイルを削除する >>> 
1100|【補足】
1101|・wildPath の例:"c:\home\*.bak"
1102|・サブディレクトリは削除しません。
1103|・Visual C++ 専用です。
1104|・バックアップを取ってから実行してください。
1105|・システム領域は削除しないで下さい。
1106|・ごみ箱には格納されません。
1107|**************************************************************************/
1108|void  FileX_removeWild( const char* wildPath )
1109|{
1110|  struct _finddata_t  find;
1111|  long   handle;
1112|  int    done;
1113|  int    isdir;
1114|  char   folder[_MAX_PATH];
1115|  char   path[_MAX_PATH];
1116|
1117|  StrX_cpyFolder( folder, wildPath );
1118|  handle = _findfirst( wildPath, &find );
1119|  done = (handle == -1);
1120|  while ( !done ) {
1121|    isdir = ( ( find.attrib & _A_SUBDIR ) != 0 );
1122|    if ( ! isdir ) {
1123|      strcpy( path, folder );  strcat( path, "\\" );
1124|      strcat( path, find.name );  remove( path );
1125|    }
1126|    done = _findnext( handle, &find );
1127|  }
1128|  _findclose( handle );
1129|}
1130|
1131|
1132| 
1133|/*************************************************************************
1134|  32. <<< [FileX_setReadOnly] ファイルの読み込み専用属性を変更する >>> 
1135|【引数】
1136|  ・char*  path;       読み込み専用属性を変更するファイルのパス
1137|  ・bool  bReadOnly;   設定する値(true=読み込み専用)
1138|**************************************************************************/
1139|#if  defined(USES_STDPLUS) && ( defined(FOR_WIN32) || defined(FOR_DOS32) )
1140|void  FileX_setReadOnly( const char* path, bool bReadOnly )
1141|{
1142|  bool  bSuccess;
1143|  DWORD  attr = GetFileAttributes( path );
1144|  if ( attr == 0xFFFFFFFF )
1145|    error();  /* ファイルが存在しないかも */
1146|
1147|  if ( bReadOnly )  attr |= FILE_ATTRIBUTE_READONLY;
1148|  else  attr &= ~FILE_ATTRIBUTE_READONLY;
1149|
1150|  bSuccess = SetFileAttributes( path, attr );
1151|  if ( ! bSuccess )  error();
1152|}
1153|#endif
1154| 
1155|/*************************************************************************
1156|  33. <<< [FileX_cat] ファイルを連結する >>> 
1157|**************************************************************************/
1158|void  FileX_cat( const char* to_path, const char* from_path )
1159|{
1160|  FILE*  to_file = FileX_open( to_path, "ab" );
1161|  FILE*  from_file = FileX_open( from_path, "rb" );
1162|  size_t  size;
1163|
1164|  do {
1165|    size = fread( FileX_buf, 1, sizeof(FileX_buf), from_file );
1166|    fwrite( FileX_buf, 1, size, to_file );
1167|  } while ( size == sizeof(FileX_buf) );
1168|
1169|  fclose( to_file );
1170|  fclose( from_file );
1171|}
1172|
1173|
1174| 
1175|/*************************************************************************
1176|  34. <<< [FileX_include] ファイルを埋めこむ >>> 
1177|【引数】
1178|・int  mode;   to のモード{テキスト='t', バイナリ='b'}
1179|**************************************************************************/
1180|void  FileX_include( FILE* to, const char* from_path, int mode )
1181|{
1182|  FILE*  from_file;
1183|  size_t  size;
1184|  char  mode2[3];
1185|
1186|  strcpy( mode2, "rt" );  mode2[1] = mode;
1187|  from_file = FileX_open( from_path, mode2 );
1188|
1189|  do {
1190|    size = fread( FileX_buf, 1, sizeof(FileX_buf), from_file );
1191|    fwrite( FileX_buf, 1, size, to );
1192|  } while ( size == sizeof(FileX_buf) );
1193|
1194|  fclose( from_file );
1195|}
1196|
1197|
1198|
1199| 
1200|/*************************************************************************
1201|  35. <<< [FileX_putBase64] バイナリファイルを base64 に変換して出力する >>> 
1202|【引数】
1203|  ・FILE*  f;        出力先(カレント・ファイルポインタへ出力)
1204|  ・char*  srcPath;  変換するバイナリファイルのパス
1205|  ・char*  retCh;    base64 に格納する改行文字(Windows なら "\r\n")
1206|**************************************************************************/
1207|void  FileX_putBase64( FILE* f, const char* srcPath, const char* retCh )
1208|{
1209|  FILE*  f2 = FileX_open( srcPath, "rb" );
1210|  int    binUnit = ( 32768 / StrX_unitOfBase64 ) * StrX_unitOfBase64;
1211|  int    textSize = StrX_getEncodedSizeOfBase64( binUnit, retCh );
1212|  char*  bin = (char*)malloc( binUnit );
1213|  char*  text = (char*)malloc( textSize );
1214|  int    bin_size;
1215|
1216|  while ( ! feof( f2 ) ) {
1217|    bin_size = fread( bin, 1, binUnit, f2 );
1218|    StrX_encodeBase64( text, bin, bin_size, retCh );
1219|    fputs( text, f );
1220|  }
1221|
1222|  free( text );
1223|  free( bin );
1224|  fclose( f2 );
1225|}
1226|
1227|
1228| 
1229|/*************************************************************************
1230|  36. <<< [FileX_scanBase64] base64 からバイナリファイルを出力する >>> 
1231|【引数】
1232|  ・FILE*  f;        出力先(カレント・ファイルポインタへ出力)
1233|  ・long  pos;       f のスキャンを開始するファイルポインタ(-1=カレントから)
1234|  ・char*  outPath;  出力するバイナリファイルのパス
1235|【補足】
1236|・base64 のデータの最後は、'\"' や '\'' など、base64 で使われない文字が
1237|  あるところです。
1238|**************************************************************************/
1239|void  FileX_scanBase64( FILE* f, long pos, const char* outPath )
1240|{
1241|  FILE*  f2 = FileX_open( outPath, "wb" );
1242|  char   text[80];
1243|  char   bin[80];
1244|  int    bin_size;
1245|  char*  p;
1246|
1247|  if ( pos != -1 )  fseek( f, pos, SEEK_SET );
1248|
1249|  while ( ! feof( f ) ) {
1250|    fgets( text, sizeof(text), f );
1251|    p = strchr( text, '\"' );  if ( p != NULL )  *p = '\0';
1252|    bin_size = StrX_decodeBase64( text, bin );
1253|    fwrite( bin, 1, bin_size, f2 );
1254|    if ( bin_size < StrX_unitOfBase64 )  break;
1255|  }
1256|
1257|  fclose( f2 );
1258|}
1259|
1260|
1261| 
1262|/*************************************************************************
1263|  37. <<< [FileX_mkdir2] フォルダを作成する >>> 
1264|【引数】
1265|  ・char* path;  実行中のフォルダからの相対パス、または絶対パス
1266|  ・int  bFile;  path は、ファイルなら 1, フォルダなら 0
1267|【補足】
1268|・作成するフォルダを格納するフォルダが無ければ、再帰的に
1269|  フォルダを作成します。
1270|  例:c:\a\b で a フォルダが無ければ、b フォルダだけでなく a フォルダも
1271|      作成します。
1272|・bFile を 1 にすると、path に指定したファイルを格納するフォルダを
1273|  作成します。
1274|**************************************************************************/
1275|#ifdef USES_STRX
1276|#ifdef USES_BIGSTACK
1277|void  FileX_mkdir2( const char* path, int bFile )
1278|{
1279|  static char   path2[_MAX_PATH];
1280|  static char*  p;  /* フォルダ区切り記号の位置(走査用) */
1281|
1282|  strcpy( path2, path );
1283|  StrX_getRunFullPath( path2, path2, _MAX_PATH - 1 );
1284|  if ( bFile )  StrX_cutFName( path2 );
1285|  StrX_cutLastOf2( path2, StrX_DirMark_char );
1286|
1287|  if ( path2[1] == ':' )   p = path2 + 2;
1288|  else                     p = path2 - 1;
1289|
1290|  while ( (p= StrX_strchr2( p + 1, StrX_DirMark_char )) != NULL ) {
1291|    *p = '\0';
1292|    if ( ! FileX_isDir( path2 ) )
1293|      _mkdir( path2 );   /* フォルダを格納するフォルダを作成 */
1294|    *p = StrX_DirMark_char;
1295|  }
1296|
1297|  if ( bFile ) {
1298|    strcpy( path2, path );
1299|    StrX_cutFName( path2 );
1300|    _mkdir( path2 );
1301|  }
1302|  else {
1303|    _mkdir( path );
1304|  }
1305|}
1306|#endif  /* #ifdef USES_BIGSTACK */
1307|#endif  /* USES_STRX */
1308|
1309|
1310| 
1311|/*************************************************************************
1312|  38. <<< [FileX_backup] ファイルのバックアップをとる >>> 
1313|【補足】
1314|・backup フォルダを作成して、そこに「移動」します。
1315|・backup フォルダには最新のバックアップと最古のバックアップが存在する
1316|  ようになります。
1317|・バックアップ後の(最新の)ファイルパスは、FileX_toBackupPath 関数から
1318|  取得します。
1319|・path のファイルが存在しない場合、何もしません。
1320|**************************************************************************/
1321|#if  defined(USES_STDPLUS) && defined(USES_STRX)
1322|#if  defined(USES_BIGSTACK) && defined(USES_EXCEPT3) && defined(USES_TIMEDATE)
1323|#if  defined(WIN32) || defined(FOR_DOS32)
1324|void  FileX_backup( const char* path )
1325|{
1326|  int  i;
1327|  char  s[_MAX_PATH];
1328|  #ifdef  USES_TIMEDATE
1329|    char  s2[_MAX_PATH];
1330|    time_t  t;
1331|    time_t  today;
1332|    struct tm*  tm;
1333|  #endif
1334|
1335|  if ( FileX_isExist( path ) ) {
1336|
1337|    /* バックアップを格納するフォルダを作成する */
1338|    for ( i = 0; ; i++ ) {
1339|      StrX_cpyFolder( s, path );
1340|      StrX_addFName( s, "backup" );
1341|      if ( i >= 1 )  sprintf( strchr( s, '\0' ), "%d", i );
1342|      if ( FileX_isDir( s ) )  break;
1343|      if ( FileX_isExist( s ) )  continue;
1344|      if ( _mkdir( s ) == -1 )
1345|        error2_1( FileX_Err_CannotMkdir, "フォルダ %s が作成できませんでした", s );
1346|      if ( FileX_isDir( s ) )  break;
1347|    }
1348|
1349|    /* ファイルをバックアップフォルダにコピーする(最新のバックアップ) */
1350|    StrX_addFName( s, StrX_refFName( path ) );
1351|    FileX_copy( s, path );
1352|    FileX_setReadOnly( s, false );  /* 上書きできるようにする */
1353|
1354|    /* ファイルをバックアップフォルダに移動する(本日最古のバックアップ) */
1355|    #ifdef  USES_TIMEDATE
1356|      strcpy( s2, s );  StrX_ins( StrX_refExt( s2 ) - 1, "#1" );
1357|      if ( ! FileX_isExist( s2 ) ) {
1358|        FileX_copy( s2, s );
1359|      }
1360|      else {
1361|        FileX_getUpdate( s2, &t );
1362|        time( &today );  tm = localtime( &today );
1363|        TimeDate_set( &today, tm->tm_year + 1900, tm->tm_mon + 1,
1364|          tm->tm_mday, 0,0,0 );
1365|        if ( difftime( t, today ) <= 0 )
1366|          FileX_copy( s2, s );
1367|      }
1368|    #endif
1369|
1370|    /* ファイルをバックアップフォルダに移動する(最古のバックアップ) */
1371|    strcpy( s2, s );  StrX_ins( StrX_refExt( s2 ) - 1, "#2" );
1372|    rename( path, s );
1373|  }
1374|}
1375|#endif
1376|#endif
1377|#endif
1378|
1379| 
1380|/*************************************************************************
1381|  39. <<< [FileX_toBackupPath] ファイルのバックアップのパスに変更する >>> 
1382|【引数】
1383|  ・char*  path;   FileX_backup 関数に渡した引数
1384|【補足】
1385|・FileX_backup 関数で移動した先のパスを取得します。
1386|**************************************************************************/
1387|#ifdef  USES_STRX
1388|void  FileX_toBackupPath( char* path )
1389|{
1390|  StrX_cdFName( path, "backup" );
1391|}
1392|#endif
1393|
1394|
1395| 
1396|/*************************************************************************
1397|  40. <<< [FileX_write] 指定データをそのままファイルにする(バックアップ付き) >>> 
1398|【引数】
1399|  ・char*  flag;   "wb" または "wt"
1400|**************************************************************************/
1401|#if  defined(USES_STDPLUS) && defined(USES_STRX)
1402|#if  defined(USES_BIGSTACK) && defined(USES_EXCEPT3) && defined(USES_TIMEDATE)
1403|#if  defined(WIN32) || defined(FOR_DOS32)
1404|void  FileX_write( const char* path, const char* flag, void* data, int size )
1405|{
1406|  FILE*  f;
1407|
1408|  ASSERT( strchr( flag, 'r' ) == NULL );
1409|
1410|  FileX_backup( path );
1411|  FileX_mkdir2( path, true );
1412|  f = FileX_open( path, flag );
1413|  fwrite( data, 1, size, f );
1414|  fclose( f );
1415|}
1416|#endif
1417|#endif
1418|#endif
1419|
1420| 
1421|/*************************************************************************
1422|  41. <<< [FileX_read0] ファイルの内容をそのままデータにする >>> 
1423|【引数】
1424|  ・char*  flag;   "wb" または "wt"
1425|  ・void*  data;   データを格納する領域の先頭アドレス
1426|  ・int  size;     data のサイズ
1427|  ・int  返り値;   ファイルサイズ
1428|【補足】
1429|・データの末尾には '\0' が付きます。付ける必要が無ければ、標準関数の
1430|  fread が使えます。
1431|・返り値(ファイルサイズ)が size より大きいときは、size - 1 まで
1432|  読み込みます。
1433|**************************************************************************/
1434|#ifdef  USES_STRX
1435|int  FileX_read0( const char* path, const char* flag, void* data, int size )
1436|{
1437|  FILE*  f;
1438|  int  fsize;
1439|
1440|  if ( strchr( flag, 'w' ) != NULL || strchr( flag, 'a' ) != NULL )
1441|    { error();  return 0; }
1442|
1443|  fsize = FileX_getSize( path );
1444|  f = FileX_open( path, flag );
1445|  if ( fsize < size ) {
1446|    fsize = fread( data, 1, fsize, f );
1447|    ((char*)data)[ fsize ] = '\0';
1448|  }
1449|  else {
1450|    size = fread( data, 1, size * 2, f );
1451|    ((char*)data)[ size ] = '\0';
1452|  }
1453|  fclose( f );
1454|
1455|  return  fsize;
1456|}
1457|#endif
1458| 
1459|#if  defined(FOR_WIN32) || defined(FOR_DOS32) 
1460| 
1461|/*--------------------------------------------------------------------*/
1462|/* 42. <<<◆(FileX_UniRead) UNICODE ファイルを Shift-JIS として読み込むフィルタ >>> */ 
1463|/*--------------------------------------------------------------------*/
1464|
1465| 
1466|/***********************************************************************
1467|  43. <<< [FileX_UniRead_init] 読み込むファイルにフィルタをかける >>> 
1468|【引数】
1469|  ・char*  path;    読み込むファイルのパス
1470|  ・char*  返り値;  代わりに開くファイルパス、fopen 等に指定する
1471|【補足】
1472|・通常のファイル・オープンからクローズまでの外を FileX_UniRead_init と
1473|  FileX_UniRead_finish で囲んでください。その際、通常のファイル・
1474|  オープンに使うファイルパスは、本関数の返り値を指定してください。
1475|・Shift JIS でフォーマットされた一時ファイルを作成して、そのパスを返します。
1476|・path は UNICODE ファイルでなくても構いません。そのとき、一時ファイルは
1477|  作成しません。
1478|************************************************************************/
1479|char*  FileX_UniRead_init( FileX_UniRead* m, const char* path )
1480|{
1481|  ERRORS_INITCHK( m, 0 );
1482|
1483|  if ( FileX_isUnicodeFIle( path ) ) {
1484|    FileX_getTmpPath( "unitmp", m->tmp_path );
1485|    FileX_copyUni2SJis( m->tmp_path, path );
1486|    return  m->tmp_path;
1487|  }
1488|  else {
1489|    m->tmp_path[0] = '\0';
1490|    return  (char*)path;
1491|  }
1492|}
1493|
1494|
1495|
1496| 
1497|/***********************************************************************
1498|  44. <<< [FileX_UniRead_finish] 読み込むファイルのフィルタを除く >>> 
1499|************************************************************************/
1500|void  FileX_UniRead_finish( FileX_UniRead* m )
1501|{
1502|  ERRORS_INITCHK( m, 1 );
1503|
1504|  if ( m->tmp_path[0] != '\0' )
1505|    remove( m->tmp_path );
1506|}
1507|
1508|
1509| 
1510|/***********************************************************************
1511|  45. <<< [FileX_isUnicodeFIle] UNICODE のテキストファイルかどうかを返す >>> 
1512|************************************************************************/
1513|bool  FileX_isUnicodeFIle( const char* path )
1514|{
1515|  FILE*  f;
1516|  unsigned int    size;
1517|  unsigned short  buf;
1518|
1519|  f = FileX_open( path, "rb" );
1520|
1521|  size = fread( &buf, 1, 2, f );
1522|  fclose( f );
1523|
1524|  return  ( size == 2 && buf == 0xFEFF );
1525|}
1526|
1527| 
1528|/***********************************************************************
1529|  46. <<< [FileX_copyUni2SJis] UNICODE のファイルを Shift JIS に変換コピーする >>> 
1530|************************************************************************/
1531|void   FileX_copyUni2SJis( const char* toSjisPath, const char* fromUniPath )
1532|{
1533|  short* p;
1534|  FILE*  from_file;
1535|  FILE*  to_file;
1536|  unsigned int    size, size2;
1537|  unsigned short  buf[2048];
1538|  unsigned char   buf2[4096];
1539|
1540|  /* ファイルを開く */
1541|  to_file = FileX_open( toSjisPath, "wb" );
1542|  if ( to_file == NULL )  Errors_errorStdlib();
1543|  from_file = FileX_open( fromUniPath, "rb" );
1544|  ASSERT( from_file != NULL );
1545|
1546|  /* UNICODE ファイルのヘッダをチェックする */
1547|  size = fread( buf, 1, 2, from_file );
1548|  if ( size < 2 || *buf != 0xFEFF ) {
1549|    fclose( to_file );  fclose( from_file );
1550|    error2_0( FileX_Err_NotUnicodeFile, "UNICODE ファイルではありません" );
1551|  }
1552|
1553|  /* ファイルの内容をコピーする */
1554|  do {
1555|    size = fread( buf, 1, sizeof(buf) - 2, from_file );
1556|    p = (short*)( (char*)buf + size );  *p = (short)0;
1557|    StrX_unicode2sjis( buf2, buf, sizeof(buf2) );
1558|    size2 = strlen( buf2 );
1559|    if ( fwrite( buf2, 1, size2, to_file ) != size2 ) {
1560|      fclose( to_file );  fclose( from_file );
1561|      remove( toSjisPath );
1562|      FileX_bCopyFailed = true;
1563|      error2_1( FileX_Err_CannotWrite, "%s の書きこみに失敗しました。",
1564|        toSjisPath );
1565|    }
1566|  } while ( size == sizeof(buf) - 2 );
1567|
1568|  /* ファイルを閉じる */
1569|  fclose( to_file );
1570|  fclose( from_file );
1571|}
1572|
1573| 
1574|/*--------------------------------------------------------------------*/
1575|/* 47. <<<◆(FileX_UniWrite) Shift-JIS 形式で書き込む UNICODE ファイルフィルタ >>> */ 
1576|/*--------------------------------------------------------------------*/
1577| 
1578|/***********************************************************************
1579|  48. <<< [FileX_UniWrite_init] 書き込むファイルにフィルタをかける >>> 
1580|【引数】
1581|  ・char*  path;    書き込むファイルのパス
1582|  ・char*  返り値;  代わりに開くファイルパス、fopen 等に指定する
1583|【補足】
1584|・通常のファイル・オープンからクローズまでの外を FileX_UniWrite_init と
1585|  FileX_UniWrite_finish で囲んでください。その際、通常のファイル・
1586|  オープンに使うファイルパスは、本関数の返り値を指定してください。
1587|・FileX_UniWrite_finish で、作成した一時ファイルを UNICODE へ変換します。
1588|************************************************************************/
1589|char*  FileX_UniWrite_init( FileX_UniWrite* m, const char* path )
1590|{
1591|  ERRORS_INITCHK( m, 0 );
1592|
1593|  FileX_getTmpPath( "unitmp", m->tmp_path );
1594|  strcpy( m->path, path );
1595|
1596|  return  m->tmp_path;
1597|}
1598|
1599|
1600|
1601| 
1602|/***********************************************************************
1603|  49. <<< [FileX_UniWrite_finish] 書き込むファイルのフィルタを除く >>> 
1604|************************************************************************/
1605|void   FileX_UniWrite_finish( FileX_UniWrite* m )
1606|{
1607|  ERRORS_INITCHK( m, 1 );
1608|
1609|  FileX_copySJis2Uni( m->path, m->tmp_path );
1610|  remove( m->tmp_path );
1611|}
1612|
1613|
1614| 
1615|/***********************************************************************
1616|  50. <<< [FileX_copySJis2Uni] Shift JIS のファイルを UNICODE に変換コピーする >>> 
1617|************************************************************************/
1618|void   FileX_copySJis2Uni( const char* toUniPath, const char* fromSJisPath )
1619|{
1620|  char*  p;
1621|  FILE*  from_file;
1622|  FILE*  to_file;
1623|  unsigned int    size, size2;
1624|  unsigned char   buf[2048];
1625|  unsigned short  buf2[2048];
1626|
1627|  /* ファイルを開く */
1628|  to_file = FileX_open( toUniPath, "wb" );
1629|  if ( to_file == NULL )  Errors_errorStdlib();
1630|  from_file = FileX_open( fromSJisPath, "rb" );
1631|  ASSERT( from_file != NULL );
1632|
1633|  /* UNICODE ファイルのヘッダを出力する */
1634|  *buf2 = 0xFEFF;
1635|  if ( fwrite( buf2, 1, 2, to_file ) != 2 ) {
1636|    fclose( to_file );  fclose( from_file );
1637|    remove( toUniPath );
1638|    FileX_bCopyFailed = true;
1639|    error2_1( FileX_Err_CannotWrite, "%s の書きこみに失敗しました。",
1640|      toUniPath );
1641|  }
1642|
1643|  /* ファイルの内容をコピーする */
1644|  do {
1645|    size = fread( buf, 1, sizeof(buf) - 1, from_file );
1646|    if ( size == 0 )  break;
1647|
1648|    p = buf + size - 1;  *(p + 1) = '\0';
1649|    if ( StrX_isSJis1byte( buf, p ) )  *p = '\0';
1650|    StrX_sjis2unicode( buf2, buf, sizeof(buf2) );
1651|    size2 = wcslen( buf2 ) * 2;
1652|
1653|    if ( fwrite( buf2, 1, size2, to_file ) != size2 ) {
1654|      fclose( to_file );  fclose( from_file );
1655|      remove( toUniPath );
1656|      FileX_bCopyFailed = true;
1657|      error2_1( FileX_Err_CannotWrite, "%s の書きこみに失敗しました。",
1658|        toUniPath );
1659|    }
1660|
1661|    if ( *p == '\0' )  fseek( from_file, -1, SEEK_CUR );
1662|
1663|  } while ( size == sizeof(buf) - 1 );
1664|
1665|  /* ファイルを閉じる */
1666|  fclose( to_file );
1667|  fclose( from_file );
1668|}
1669| 
1670|#endif 
1671| 
1672|/*--------------------------------------------------------------------*/
1673|/* 51. <<<◆(FileX_CurDir) カレントフォルダ・スタック >>> */ 
1674|/*--------------------------------------------------------------------*/
1675|
1676|
1677| 
1678|/*************************************************************************
1679|  52. <<< [FileX_CurDir_init] カレントフォルダをスタック的に変更する >>> 
1680|【引数】
1681|  ・char*  path;  新しいカレントフォルダ、またはファイルのパス
1682|【補足】
1683|・この関数は、BigStack_start から BigStack_end の間に入れる必要があります。
1684|・m は、この関数を呼び出すたびに、新しくスタック変数として用意してください。
1685|・path にファイルを指定した場合、そのファイルを格納しているフォルダに
1686|  カレントフォルダを変更します。
1687|・path は、相対パスでも絶対パスでも構いません。
1688|・相対パスで path に指定したファイルを開くときは、新しいカレントフォルダを
1689|  指定することに注意してください。
1690|【例】
1691|  void  func( char* fname )
1692|  {
1693|     FileX_CurDir  cur;
1694|
1695|     BigStack_start();
1696|     FileX_CurDir_init( &cur, fname );  // fname のあるフォルダへ
1697|     FileX_open( StrX_refFName( fname ), "rt" );  // カレントで開く
1698|      ...
1699|     FileX_CurDir_finish( &cur );  // 戻す
1700|     BigStack_end();
1701|  }
1702|**************************************************************************/
1703|#ifdef USES_STRX
1704|#ifdef USES_BIGSTACK
1705|void  FileX_CurDir_init( FileX_CurDir* m, const char* path )
1706|{
1707|  char*  newDir;
1708|
1709|  /* カレント・フォルダをとっておく */
1710|  m->curPath = BigStack_alloc( _MAX_PATH );
1711|  _getcwd( m->curPath, _MAX_PATH );
1712|
1713|  /* カレント・フォルダを変更する */
1714|  if ( FileX_isDir( path ) ) {
1715|    _chdir( path );
1716|  }
1717|  else {
1718|    BigStack_start();
1719|    newDir = BigStack_alloc( _MAX_PATH );
1720|    strcpy( newDir, path );
1721|    StrX_cutFName( newDir );
1722|    _chdir( newDir );
1723|    BigStack_end();
1724|  }
1725|}
1726|#endif /* USES_BIGSTACK */
1727|#endif /* USES_STRX */
1728|
1729|
1730| 
1731|/*************************************************************************
1732|  53. <<< [FileX_CurDir_finish] カレントフォルダを戻す >>> 
1733|【補足】
1734|・この関数は、BigStack_start から BigStack_end の間に入れる必要があります。
1735|**************************************************************************/
1736|#ifdef USES_BIGSTACK
1737|void  FileX_CurDir_finish( FileX_CurDir* m )
1738|{
1739|  _chdir( m->curPath );
1740|}
1741|#endif /* USES_BIGSTACK */
1742|
1743|
1744| 
1745|/*---------------------------------------------------------------------*/
1746|/* 54. <<<◆(FileX_FreeSpc) ディスクの空き容量 >>> */ 
1747|/*---------------------------------------------------------------------*/
1748|
1749|#ifdef  FILEX_FREESIZE
1750|  FileX_FreeSpc  FileX_freeSpcSym;
1751|#endif
1752|
1753| 
1754|/*************************************************************************
1755|  55. <<< [FileX_FreeSpc_init] 初期化する >>> 
1756|【補足】
1757|・FileX_FreeSpc_scan してから、空き容量の変数が有効になります。
1758|**************************************************************************/
1759|void  FileX_FreeSpc_init( FileX_FreeSpc* m )
1760|{
1761|  m->sectorsPerCluster = 0;
1762|  m->bytesPerSector = 0;
1763|  m->numberOfFreeClusters = 0;
1764|  m->totalNumberOfClusters = 0;
1765|}
1766|
1767| 
1768|/*************************************************************************
1769|  56. <<< [FileX_FreeSpc_scan] 空き容量をディスクから取得する >>> 
1770|【引数】
1771|  ・char*  root_path;  ルートのパス(例:"c:\\")
1772|【補足】
1773|・取得したサイズは、FileX_FreeSpc_getFreeSize 関数などから取得します。
1774|・FILEX_FREESIZE を #define すると、空き容量をシミュレートできます。
1775|  FileX_freeSpcSym グローバル変数(FileX_FreeSpc型)のメンバ変数に
1776|  設定してください。
1777|**************************************************************************/
1778|#ifdef  WIN32
1779|void  FileX_FreeSpc_scan( FileX_FreeSpc* m, const char* root_path )
1780|{
1781|  #ifdef  FILEX_FREESIZE
1782|    *m = FileX_freeSpcSym;
1783|  #else
1784|    if ( ! GetDiskFreeSpace( root_path, &m->sectorsPerCluster,
1785|        &m->bytesPerSector, &m->numberOfFreeClusters,
1786|        &m->totalNumberOfClusters ) ) {
1787|      m->sectorsPerCluster = 0;
1788|      m->bytesPerSector = 0;
1789|      m->numberOfFreeClusters = 0;
1790|      m->totalNumberOfClusters = 0;
1791|    }
1792|  #endif
1793|}
1794|#endif
1795| 
1796|/*************************************************************************
1797|  57. <<< [FileX_FreeSpc_getFreeSize] 空き容量を計算する >>> 
1798|【補足】
1799|・書き込みできるかどうか判断するときは、上書きすることを考慮に入れてください。
1800|  → FileX_FreeSpc_getUseFileSize 関数
1801|・1KB = 1024byte, 1MB = 1024KB
1802|**************************************************************************/
1803|int  FileX_FreeSpc_getFreeSize( FileX_FreeSpc* m )
1804|{
1805|  return  m->sectorsPerCluster *
1806|    m->bytesPerSector * m->numberOfFreeClusters;
1807|}
1808|
1809| 
1810|/*************************************************************************
1811|  58. <<< [FileX_FreeSpc_getTotalSize] 総容量を計算する >>> 
1812|【補足】
1813|・1KB = 1024byte, 1MB = 1024KB, 1GB = 1024MB
1814|**************************************************************************/
1815|int  FileX_FreeSpc_getTotalSize( FileX_FreeSpc* m )
1816|{
1817|  return  m->sectorsPerCluster *
1818|    m->bytesPerSector * m->totalNumberOfClusters;
1819|}
1820|
1821| 
1822|/*************************************************************************
1823|  59. <<< [FileX_FreeSpc_getUseFileSize] ファイルの使用サイズを返す >>> 
1824|【引数】
1825|  ・FileX_FreeSpc*  m;  ドライブの空き容量
1826|  ・char*  path;           ファイルパス
1827|  ・int  返り値;           ファイルの使用サイズ
1828|【補足】
1829|・m を初期化してから使用してください。
1830|・ファイルシステムでは、クラスタ単位で領域を扱っているため、実際の
1831|  ファイルサイズより大きめの領域を使用しています。その領域のサイズを
1832|  返します。
1833|・指定したファイルが存在しない場合は、0 を返します。
1834|・m と path のドライブが異なる場合、path のファイルを m の
1835|  ドライブに格納したときの使用サイズを返します。
1836|**************************************************************************/
1837|#ifdef  USES_EXCEPT3
1838|int  FileX_FreeSpc_getUseFileSize( FileX_FreeSpc* m, const char* path )
1839|{
1840|  int  size;
1841|  int  nCluster;
1842|  int  bytesPerCluster = m->sectorsPerCluster * m->bytesPerSector;
1843|
1844|  if ( ! FileX_isExist( path ) )  return  0;
1845|  size = FileX_getSize( path );
1846|  nCluster = FileX_FreeSpc_culcNCluster( m, size );
1847|  return  nCluster * bytesPerCluster;
1848|}
1849|#endif
1850|
1851| 
1852|/*************************************************************************
1853|  60. <<< [FileX_FreeSpc_culcNCluster] 指定サイズが使うクラスタ数を返す >>> 
1854|【引数】
1855|  ・int  size;  ファイルのサイズ(バイト)
1856|**************************************************************************/
1857|int  FileX_FreeSpc_culcNCluster( FileX_FreeSpc* m, int size )
1858|{
1859|  int  bytesPerCluster = m->sectorsPerCluster * m->bytesPerSector;
1860|
1861|  return  ( size + bytesPerCluster - 1 ) / bytesPerCluster;
1862|}
1863|
1864| 
1865|