X-Git-Url: http://git.iain.cx/?a=blobdiff_plain;f=io.cpp;h=30deb726008d88ed4c32ea808475f8e2a59a19e9;hb=2f219930f488b2551326900df5c201de2e9304f2;hp=0ab92c350b41df2b9ba1e0630b6e275f3be9de9c;hpb=c1bc67d13894b1b9456fb85abdabc4dbb5d71bcc;p=nssm.git diff --git a/io.cpp b/io.cpp index 0ab92c3..30deb72 100644 --- a/io.cpp +++ b/io.cpp @@ -1,12 +1,12 @@ #include "nssm.h" /* Get path, share mode, creation disposition and flags for a stream. */ -int get_createfile_parameters(HKEY key, char *prefix, char *path, unsigned long *sharing, unsigned long default_sharing, unsigned long *disposition, unsigned long default_disposition, unsigned long *flags, unsigned long default_flags) { - char value[NSSM_STDIO_LENGTH]; +int get_createfile_parameters(HKEY key, TCHAR *prefix, TCHAR *path, unsigned long *sharing, unsigned long default_sharing, unsigned long *disposition, unsigned long default_disposition, unsigned long *flags, unsigned long default_flags) { + TCHAR value[NSSM_STDIO_LENGTH]; /* Path. */ - if (_snprintf_s(value, sizeof(value), _TRUNCATE, "%s", prefix) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, prefix, "get_createfile_parameters()", 0); + if (_sntprintf_s(value, _countof(value), _TRUNCATE, _T("%s"), prefix) < 0) { + log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, prefix, _T("get_createfile_parameters()"), 0); return 1; } switch (expand_parameter(key, value, path, MAX_PATH, true, false)) { @@ -15,8 +15,8 @@ int get_createfile_parameters(HKEY key, char *prefix, char *path, unsigned long } /* ShareMode. */ - if (_snprintf_s(value, sizeof(value), _TRUNCATE, "%s%s", prefix, NSSM_REG_STDIO_SHARING) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, NSSM_REG_STDIO_SHARING, "get_createfile_parameters()", 0); + if (_sntprintf_s(value, _countof(value), _TRUNCATE, _T("%s%s"), prefix, NSSM_REG_STDIO_SHARING) < 0) { + log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, NSSM_REG_STDIO_SHARING, _T("get_createfile_parameters()"), 0); return 3; } switch (get_number(key, value, sharing, false)) { @@ -26,8 +26,8 @@ int get_createfile_parameters(HKEY key, char *prefix, char *path, unsigned long } /* CreationDisposition. */ - if (_snprintf_s(value, sizeof(value), _TRUNCATE, "%s%s", prefix, NSSM_REG_STDIO_DISPOSITION) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, NSSM_REG_STDIO_DISPOSITION, "get_createfile_parameters()", 0); + if (_sntprintf_s(value, _countof(value), _TRUNCATE, _T("%s%s"), prefix, NSSM_REG_STDIO_DISPOSITION) < 0) { + log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, NSSM_REG_STDIO_DISPOSITION, _T("get_createfile_parameters()"), 0); return 5; } switch (get_number(key, value, disposition, false)) { @@ -37,8 +37,8 @@ int get_createfile_parameters(HKEY key, char *prefix, char *path, unsigned long } /* Flags. */ - if (_snprintf_s(value, sizeof(value), _TRUNCATE, "%s%s", prefix, NSSM_REG_STDIO_FLAGS) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, NSSM_REG_STDIO_FLAGS, "get_createfile_parameters()", 0); + if (_sntprintf_s(value, _countof(value), _TRUNCATE, _T("%s%s"), prefix, NSSM_REG_STDIO_FLAGS) < 0) { + log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, NSSM_REG_STDIO_FLAGS, _T("get_createfile_parameters()"), 0); return 7; } switch (get_number(key, value, flags, false)) { @@ -50,18 +50,18 @@ int get_createfile_parameters(HKEY key, char *prefix, char *path, unsigned long return 0; } -int set_createfile_parameter(HKEY key, char *prefix, char *suffix, unsigned long number) { - char value[NSSM_STDIO_LENGTH]; +int set_createfile_parameter(HKEY key, TCHAR *prefix, TCHAR *suffix, unsigned long number) { + TCHAR value[NSSM_STDIO_LENGTH]; - if (_snprintf_s(value, sizeof(value), _TRUNCATE, "%s%s", prefix, suffix) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, suffix, "set_createfile_parameter()", 0); + if (_sntprintf_s(value, _countof(value), _TRUNCATE, _T("%s%s"), prefix, suffix) < 0) { + log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, suffix, _T("set_createfile_parameter()"), 0); return 1; } return set_number(key, value, number); } -HANDLE append_to_file(char *path, unsigned long sharing, SECURITY_ATTRIBUTES *attributes, unsigned long disposition, unsigned long flags) { +HANDLE append_to_file(TCHAR *path, unsigned long sharing, SECURITY_ATTRIBUTES *attributes, unsigned long disposition, unsigned long flags) { HANDLE ret; /* Try to append to the file first. */ @@ -81,9 +81,79 @@ HANDLE append_to_file(char *path, unsigned long sharing, SECURITY_ATTRIBUTES *at return CreateFile(path, FILE_WRITE_DATA, sharing, attributes, disposition, flags, 0); } -int get_output_handles(HKEY key, STARTUPINFO *si) { - char path[MAX_PATH]; - char stdout_path[MAX_PATH]; +void rotate_file(TCHAR *service_name, TCHAR *path, unsigned long seconds, unsigned long low, unsigned long high) { + unsigned long error; + + /* Now. */ + SYSTEMTIME st; + GetSystemTime(&st); + + BY_HANDLE_FILE_INFORMATION info; + + /* Try to open the file to check if it exists and to get attributes. */ + HANDLE file = CreateFile(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (file) { + /* Get file attributes. */ + if (! GetFileInformationByHandle(file, &info)) { + /* Reuse current time for rotation timestamp. */ + seconds = low = high = 0; + SystemTimeToFileTime(&st, &info.ftLastWriteTime); + } + + CloseHandle(file); + } + else { + error = GetLastError(); + if (error == ERROR_FILE_NOT_FOUND) return; + log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_ROTATE_FILE_FAILED, service_name, path, _T("CreateFile()"), path, error_string(error), 0); + /* Reuse current time for rotation timestamp. */ + seconds = low = high = 0; + SystemTimeToFileTime(&st, &info.ftLastWriteTime); + } + + /* Check file age. */ + if (seconds) { + FILETIME ft; + SystemTimeToFileTime(&st, &ft); + + ULARGE_INTEGER s; + s.LowPart = ft.dwLowDateTime; + s.HighPart = ft.dwHighDateTime; + s.QuadPart -= seconds * 10000000LL; + ft.dwLowDateTime = s.LowPart; + ft.dwHighDateTime = s.HighPart; + if (CompareFileTime(&info.ftLastWriteTime, &ft) > 0) return; + } + + /* Check file size. */ + if (low || high) { + if (info.nFileSizeHigh < high) return; + if (info.nFileSizeHigh == high && info.nFileSizeLow < low) return; + } + + /* Get new filename. */ + FileTimeToSystemTime(&info.ftLastWriteTime, &st); + + TCHAR buffer[MAX_PATH]; + memmove(buffer, path, sizeof(buffer)); + TCHAR *ext = PathFindExtension(buffer); + TCHAR extension[MAX_PATH]; + _sntprintf_s(extension, _countof(extension), _TRUNCATE, _T("-%04u%02u%02uT%02u%02u%02u.%03u%s"), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, ext); + *ext = _T('\0'); + TCHAR rotated[MAX_PATH]; + _sntprintf_s(rotated, _countof(rotated), _TRUNCATE, _T("%s%s"), buffer, extension); + + /* Rotate. */ + if (MoveFile(path, rotated)) return; + error = GetLastError(); + + log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_ROTATE_FILE_FAILED, service_name, path, _T("MoveFile()"), rotated, error_string(error), 0); + return; +} + +int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) { + TCHAR path[MAX_PATH]; + TCHAR stdout_path[MAX_PATH]; unsigned long sharing, disposition, flags; bool set_flags = false; @@ -107,11 +177,12 @@ int get_output_handles(HKEY key, STARTUPINFO *si) { if (get_createfile_parameters(key, NSSM_REG_STDOUT, path, &sharing, NSSM_STDOUT_SHARING, &disposition, NSSM_STDOUT_DISPOSITION, &flags, NSSM_STDOUT_FLAGS)) return 3; if (path[0]) { /* Remember path for comparison with stderr. */ - if (_snprintf_s(stdout_path, sizeof(stdout_path), _TRUNCATE, "%s", path) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "stdout_path", "get_output_handles", 0); + if (_sntprintf_s(stdout_path, _countof(stdout_path), _TRUNCATE, _T("%s"), path) < 0) { + log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("stdout_path"), _T("get_output_handles"), 0); return 4; } + if (service->rotate_files) rotate_file(service->name, path, service->rotate_seconds, service->rotate_bytes_low, service->rotate_bytes_high); si->hStdOutput = append_to_file(path, sharing, &attributes, disposition, flags); if (! si->hStdOutput) return 5; set_flags = true; @@ -121,7 +192,7 @@ int get_output_handles(HKEY key, STARTUPINFO *si) { /* stderr */ if (get_createfile_parameters(key, NSSM_REG_STDERR, path, &sharing, NSSM_STDERR_SHARING, &disposition, NSSM_STDERR_DISPOSITION, &flags, NSSM_STDERR_FLAGS)) return 6; if (path[0]) { - /* Same as stdin? */ + /* Same as stdout? */ if (str_equiv(path, stdout_path)) { /* Two handles to the same file will create a race. */ if (! DuplicateHandle(GetCurrentProcess(), si->hStdOutput, GetCurrentProcess(), &si->hStdError, 0, true, DUPLICATE_SAME_ACCESS)) { @@ -130,6 +201,7 @@ int get_output_handles(HKEY key, STARTUPINFO *si) { } } else { + if (service->rotate_files) rotate_file(service->name, path, service->rotate_seconds, service->rotate_bytes_low, service->rotate_bytes_high); si->hStdError = append_to_file(path, sharing, &attributes, disposition, flags); if (! si->hStdError) { log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEFILE_FAILED, path, error_string(GetLastError()));