mikan's technical note

仕事&趣味で実験した小技の備忘録です(Linux,windows,DOS等)

MENU

【C言語】windowsでtouchコマンドもどき

//
// 【touchコマンドもどき】※Windows2000で動作確認済み
// (c) 2017 mikan
// ※使用にあたっては利用者の自己責任でお願いします。
//
//     実行形式)touch ファイル名 年月日時分秒
//
//         年月日時分の書式:[[CC]YY]MMDDhhmm[.SS]
//
//         実行例: touch hoge.txt 201701141355
//

#include <windows.h>

int get_ParamDate(char *, SYSTEMTIME *);

int main(int argc, char **argv)
{

    SYSTEMTIME  system_time;    // システム日時
    FILETIME    CreationTime;   // 作成日時
    FILETIME    LastAccessTime; // 最終アクセス日時
    FILETIME    LastWriteTime;  // 最終更新日時
    FILETIME    w_FileTime;     // ファイル時刻

    HANDLE    handle = INVALID_HANDLE_VALUE;
    BOOL    brts;

    int        irts;
    int        size;
    char    fullpath[MAX_PATH];

    // パラメータ数をチェック
    if(argc == 1 || argc >= 4) {
        return -1;
    }

    // システム日時を取得
    GetLocalTime(&system_time);

    if(argc == 3) {
        // パラメータの日時を取得
        irts = get_ParamDate(argv[2], &system_time);
    }

    // システム日時をファイル時刻へ変換
    // ありえない日付(2月31日、25時90分、等)はここで失敗する
    brts = SystemTimeToFileTime(&system_time, &w_FileTime);
    if(brts == FALSE) {
        return -1;
    }

    // ローカルのファイル時刻を、世界協定時刻(UTC)に基づくファイル時刻へ変換
    // これをやらないと9時間ずれる
    brts = LocalFileTimeToFileTime(&w_FileTime, &CreationTime);
    LastAccessTime = CreationTime;
    LastWriteTime = CreationTime;

    // フルパスファイル名
    memset(fullpath, 0x00, sizeof(fullpath));
    size = GetCurrentDirectory(sizeof(fullpath), fullpath);
    strcat(fullpath, "\\"); 
    strcat(fullpath, argv[1]); 

    // ファイルオープン(存在しない場合は作成する)
    handle = CreateFile(fullpath,
                        GENERIC_WRITE,
                        FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
                        NULL,
                        OPEN_ALWAYS,
                        // FILE_ATTRIBUTE_NORMAL,   // ファイルだけならこれでもよい
                        FILE_FLAG_BACKUP_SEMANTICS, // ディレクトリも対応するならこっち
                        NULL);
    if(handle == INVALID_HANDLE_VALUE) {
        return -1;
    }

    // ファイルタイムスタンプ変更
    brts = SetFileTime(handle,
                        &CreationTime,   // 作成日時
                        &LastAccessTime, // 最終アクセス日時
                        &LastWriteTime); // 最終更新日時

    // ファイルクローズ
    brts = CloseHandle(handle);

    if(brts == FALSE) {
        return -1;
    }

    return 0;
}

// パラメータの時刻を取得 書式:[[CC]YY]MMDDhhmm[.SS]
int get_ParamDate(char *work, SYSTEMTIME *system_time)
{
    int    size;
    char    CC[4];
    char    YY[4];
    char    MM[4];
    char    DD[4];
    char    hh[4];
    char    mm[4];
    char    SS[4];

    memset(CC, 0x00, sizeof(CC));
    memset(YY, 0x00, sizeof(YY));
    memset(MM, 0x00, sizeof(MM));
    memset(DD, 0x00, sizeof(DD));
    memset(hh, 0x00, sizeof(hh));
    memset(mm, 0x00, sizeof(mm));
    memset(SS, 0x00, sizeof(SS));

    size = strlen(work);

    // 秒
    if(size == 15 && work[12] == '.') {
        memcpy(SS, &work[13], 2);
        size = 12;
    }
    else if(size == 13 && work[10] == '.') {
        memcpy(SS, &work[11], 2);
        size = 10;
    }
    else if(size == 11 && work[8] == '.') {
        memcpy(SS, &work[9], 2);
        size = 8;
    }
    else {
        strcpy(SS, "00");
    }

    // 年月日時分
    if(size == 12) {      // CCYYMMDDhhmm
        memcpy(CC, &work[0], 2);
        memcpy(YY, &work[2], 2);
        memcpy(MM, &work[4], 2);
        memcpy(DD, &work[6], 2);
        memcpy(hh, &work[8], 2);
        memcpy(mm, &work[10], 2);
    }
    else if(size == 10) { // YYMMDDhhmm
        memcpy(YY, &work[0], 2);
        memcpy(MM, &work[2], 2);
        memcpy(DD, &work[4], 2);
        memcpy(hh, &work[6], 2);
        memcpy(mm, &work[8], 2);
    }
    else if(size == 8) {  // MMDDhhmm
        memcpy(MM, &work[0], 2);
        memcpy(DD, &work[2], 2);
        memcpy(hh, &work[4], 2);
        memcpy(mm, &work[6], 2);
    }

    // 年を数値型に変換して設定
    if(CC[0] == 0x00) {
        if(YY[0] == 0x00) {
            ;
        }
        else {
            system_time->wYear = system_time->wYear / 100 * 100;
            system_time->wYear += atoi(YY);
        }
    }
    else if(YY[0] != 0x00) {
        system_time->wYear = atoi(CC) * 100 + atoi(YY);
    }

    // 月日時分秒を数値型に変換して設定
    system_time->wMonth = atoi(MM);
    system_time->wDay = atoi(DD);
    system_time->wHour = atoi(hh);
    system_time->wMinute = atoi(mm);
    system_time->wSecond = atoi(SS);
    system_time->wMilliseconds = 0;

    return 0;
}