/**
 *  @file TmpFile.c
 *  @brief  テンポラリディレクトリにテンポラリファイルを作成.
 *  @author tenk*
 *  @note
 *      Public Domain Software
 */

#include "TmpFile.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

// このファイル内限定で、基本的な名前も辻褄あわせ.
#ifdef _WIN32
 #include <windows.h>
 #include <tchar.h>
 #include <io.h>
 #include <tchar.h>
 #define DISK_MAX_PATH  _MAX_PATH
 #define uint64_t       unsigned __int64
#else   // win以外ではcharのみ.
 #include <stddef.h>
 #include <unistd.h>
 #define _T(x)          x
 #define TCHAR          char
 #define _tcslen(s)     strlen(s)
 #define _tcsncpy       strncpy
 #define _tsnprintf     snprintf
 #define DISK_MAX_PATH  4096
#endif


//===========================================================================
// テンポラリ・ファイル.
//===========================================================================

#if defined _WIN32 || defined MSDOS
/** 環境変数tmp か temp があればその内容を、なければ"."を入れて返す.
 *  @return     0:tmp,tempが無かった.  1:あった.
 */
int TmpFile_getTmpEnv(TCHAR tmpEnv[], size_t size)
{
    int          f = 1;
    const TCHAR* p = _tgetenv(_T("TMP"));
    assert(tmpEnv && size > 0);
    if (p == NULL) {
        p = _tgetenv(_T("TEMP"));
        if (p == NULL) {
            p = _T(".");
            f = 0;
        }
    }
    _tcsncpy(tmpEnv, p, size-1);
    tmpEnv[size-1] = 0;
    return f;
}
#else
/** /tmp を返す.
 *  @return     1
 */
int TmpFile_getTmpEnv(TCHAR tmpEnv[], size_t size)
{
    _tcsncpy(tmpEnv, "/tmp", size-1);
    tmpEnv[size-1] = 0;
    return 1;
}
#endif



/** テンポラリファイル作成. 成功するとhandleを返す.
 */
#ifdef _WIN32
//static HANDLE TmpFile_open(TCHAR name[], size_t size, const TCHAR* prefix)
//{
//  if (TmpFile_openName(name, size, prefix)) {
//      return CreateFile(name, GENERIC_WRITE, 0, CREATE_ALWAYS,FILE_ATTRIBUTE_TEMPORARY, 0);
//  }
//}
#else
static int    TmpFile_open(TCHAR name[], size_t size, const TCHAR* prefix)
{
    TCHAR   nm[ DISK_MAX_PATH + 2 ];
    int     hdl;
    assert(name != 0 && size > 0 && prefix != 0);
    _tsnprintf( nm, DISK_MAX_PATH, _T("/tmp/%s.XXXXXX"), prefix );
    hdl = mkstemp( nm );
    if (hdl >= 0) {
        if (_tcslen(nm) < size) {
            _tcsncpy(name, nm, size-1);
            name[size-1] = 0;
        } else {    // ファイル名をちゃんと返せないなら失敗扱い.
            close(hdl);
            remove(nm);
            hdl = -1;
        }
    }
    return hdl;
}
#endif



/** テンポラリファイル名作成. 成功するとnameを返し、失敗だとNULL.
 *  prefix はwindowsだと3バイト.
 *  成功すると、テンポラリディレクトリにその名前のファイルができているので注意.(close済)
 *  (つまり自分で削除しないと駄目)
 */
TCHAR* TmpFile_make(TCHAR name[], size_t size, const TCHAR* prefix)
{
  #ifdef _WIN32
    TCHAR   tmpd[ DISK_MAX_PATH + 2];
    TCHAR   nm[ DISK_MAX_PATH + 2 ];
    int     val;
    assert(name != 0 && size > 0 && prefix != 0);
    TmpFile_getTmpEnv(tmpd, DISK_MAX_PATH);
    val = GetTempFileName( tmpd, prefix, 0, nm );
    if (val > 0) {
        _tcsncpy(name, nm, size-1);
        name[size-1] = 0;
        return name;
    }
    return 0;
  #else
    int hdl = TmpFile_open(name, size, prefix);
    if (hdl >= 0) { // ハンドルが取得できていたら、win側に似せるため、ファイルはcloseして帰る.
        close(hdl);
        return name;
    } else {
        return 0;
    }
  #endif
}



#ifdef FNAME_INCLUDED   // fname を使う場合.
/** 環境変数tmp か temp からテンポラリディレクトリ名を取得. なければカレント"./"を返す.
 *  @return     0:tmp,tempが無かった.  1:あった.
 */
int TmpFile_getTmpDir(TCHAR *dirName, size_t dirNameLen)
{
  #if defined _WIN32
    // winNT/2kのGetTempPathだとTMP,TEMPがなかったときwindowsディレクトリらしいのでやめて自前.
    TCHAR   nm[DISK_MAX_PATH+2];
    int     f = TmpFile_getTmpEnv(nm, DISK_MAX_PATH);
    fname_addSep(nm, DISK_MAX_PATH);
    fname_cat(nm, DISK_MAX_PATH, _T("*.*"));
    fname_fullpath(dirName, dirNameLen, nm, "/");
    fname_getDir(dirName, dirNameLen, dirName);
  #else
    fname_cpy(dirName, dirNameLen, "/tmp");
  #endif
    return f;
}
#endif