diff options
Diffstat (limited to 'native/fileWatcher/fileWatcher3.cpp')
-rw-r--r-- | native/fileWatcher/fileWatcher3.cpp | 757 |
1 files changed, 350 insertions, 407 deletions
diff --git a/native/fileWatcher/fileWatcher3.cpp b/native/fileWatcher/fileWatcher3.cpp index 7e3669ecdec7..07dbe52095a5 100644 --- a/native/fileWatcher/fileWatcher3.cpp +++ b/native/fileWatcher/fileWatcher3.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,20 +14,23 @@ * limitations under the License. */ -#include "stdafx.h" +#include <process.h> +#include <stdio.h> +#include <tchar.h> +#include <windows.h> struct WatchRootInfo { - char driveLetter; - HANDLE hThread; - HANDLE hStopEvent; - bool bInitialized; - bool bUsed; - bool bFailed; + char driveLetter; + HANDLE hThread; + HANDLE hStopEvent; + bool bInitialized; + bool bUsed; + bool bFailed; }; struct WatchRoot { - char *path; - WatchRoot *next; + char *path; + WatchRoot *next; }; const int ROOT_COUNT = 26; @@ -38,139 +41,123 @@ WatchRoot *firstWatchRoot = NULL; CRITICAL_SECTION csOutput; -void NormalizeSlashes(char *path, char slash) -{ - for(char *p=path; *p; p++) - if (*p == '\\' || *p == '/') - *p = slash; +void NormalizeSlashes(char *path, char slash) { + for (char *p = path; *p; p++) + if (*p == '\\' || *p == '/') + *p = slash; } // -- Watchable root checks --------------------------------------------------- -bool IsNetworkDrive(const char *name) -{ +bool IsNetworkDrive(const char *name) { const int BUF_SIZE = 1024; char buffer[BUF_SIZE]; - UNIVERSAL_NAME_INFO* uni = (UNIVERSAL_NAME_INFO*) buffer; + UNIVERSAL_NAME_INFO *uni = (UNIVERSAL_NAME_INFO *) buffer; DWORD size = BUF_SIZE; DWORD result = WNetGetUniversalNameA( - name, // path for network resource - UNIVERSAL_NAME_INFO_LEVEL, // level of information - buffer, // name buffer - &size // size of buffer + name, // path for network resource + UNIVERSAL_NAME_INFO_LEVEL, // level of information + buffer, // name buffer + &size // size of buffer ); return result == NO_ERROR; } -bool IsUnwatchableFS(const char *path) -{ +bool IsUnwatchableFS(const char *path) { char volumeName[MAX_PATH]; - char fsName[MAX_PATH]; - DWORD fsFlags; - DWORD maxComponentLength; - SetErrorMode(SEM_FAILCRITICALERRORS); - if (!GetVolumeInformationA(path, volumeName, MAX_PATH-1, NULL, &maxComponentLength, &fsFlags, fsName, MAX_PATH-1)) - return false; - if (strcmp(fsName, "NTFS") && strcmp(fsName, "FAT") && strcmp(fsName, "FAT32") && stricmp(fsName, "exFAT")) - return true; - - if (!strcmp(fsName, "NTFS") && maxComponentLength != 255 && !(fsFlags & FILE_SUPPORTS_REPARSE_POINTS)) - { - // SAMBA reports itself as NTFS - return true; - } - - return false; + char fsName[MAX_PATH]; + DWORD fsFlags; + DWORD maxComponentLength; + SetErrorMode(SEM_FAILCRITICALERRORS); + if (!GetVolumeInformationA(path, volumeName, MAX_PATH - 1, NULL, &maxComponentLength, &fsFlags, fsName, MAX_PATH - 1)) + return false; + if (strcmp(fsName, "NTFS") && strcmp(fsName, "FAT") && strcmp(fsName, "FAT32") && _stricmp(fsName, "exFAT") && _stricmp(fsName, "reFS")) + return true; + + if (!strcmp(fsName, "NTFS") && maxComponentLength != 255 && !(fsFlags & FILE_SUPPORTS_REPARSE_POINTS)) { + // SAMBA reports itself as NTFS + return true; + } + + return false; } -bool IsWatchable(const char *path) -{ - if (IsNetworkDrive(path)) - return false; - if (IsUnwatchableFS(path)) - return false; - return true; +bool IsWatchable(const char *path) { + if (IsNetworkDrive(path)) + return false; + if (IsUnwatchableFS(path)) + return false; + return true; } // -- Substed drive checks ---------------------------------------------------- -void PrintRemapForSubstDrive(char driveLetter) -{ +void PrintRemapForSubstDrive(char driveLetter) { const int BUF_SIZE = 1024; char targetPath[BUF_SIZE]; - char rootPath[8]; - sprintf_s(rootPath, 8, "%c:", driveLetter); + char rootPath[8]; + sprintf_s(rootPath, 8, "%c:", driveLetter); DWORD result = QueryDosDeviceA(rootPath, targetPath, BUF_SIZE); if (result == 0) { return; } - else - { - if (targetPath[0] == '\\' && targetPath[1] == '?' && targetPath[2] == '?' && targetPath[3] == '\\') - { - // example path: \??\C:\jetbrains\idea - NormalizeSlashes(targetPath, '/'); - printf("%c:\n%s\n", driveLetter, targetPath+4); - } + else { + if (targetPath[0] == '\\' && targetPath[1] == '?' && targetPath[2] == '?' && targetPath[3] == '\\') { + // example path: \??\C:\jetbrains\idea + NormalizeSlashes(targetPath, '/'); + printf("%c:\n%s\n", driveLetter, targetPath + 4); + } } } -void PrintRemapForSubstDrives() -{ - for(int i=0; i<ROOT_COUNT; i++) - { - if (watchRootInfos [i].bUsed) - { - PrintRemapForSubstDrive(watchRootInfos [i].driveLetter); - } - } +void PrintRemapForSubstDrives() { + for (int i = 0; i < ROOT_COUNT; i++) { + if (watchRootInfos[i].bUsed) { + PrintRemapForSubstDrive(watchRootInfos[i].driveLetter); + } + } } // -- Mount point enumeration ------------------------------------------------- const int BUFSIZE = 1024; -void PrintDirectoryReparsePoint(const char *path) -{ - int size = strlen(path)+2; - char *directory = (char *) malloc(size); - strcpy_s(directory, size, path); - NormalizeSlashes(directory, '\\'); - if (directory [strlen(directory)-1] != '\\') - strcat_s(directory, size, "\\"); - - char volumeName[_MAX_PATH]; - int rc = GetVolumeNameForVolumeMountPointA(directory, volumeName, sizeof(volumeName)); - if (rc) - { - char volumePathNames[_MAX_PATH]; - DWORD returnLength; - rc = GetVolumePathNamesForVolumeNameA(volumeName, volumePathNames, sizeof(volumePathNames), &returnLength); - if (rc) - { - char *p = volumePathNames; - while(*p) - { - if (_stricmp(p, directory)) // if it's not the path we've already found - { - NormalizeSlashes(directory, '/'); - NormalizeSlashes(p, '/'); - puts(directory); - puts(p); - } - p += strlen(p)+1; - } - } - } - free(directory); +void PrintDirectoryReparsePoint(const char *path) { + int size = strlen(path) + 2; + char *directory = (char *) malloc(size); + strcpy_s(directory, size, path); + NormalizeSlashes(directory, '\\'); + if (directory[strlen(directory) - 1] != '\\') + strcat_s(directory, size, "\\"); + + char volumeName[_MAX_PATH]; + int rc = GetVolumeNameForVolumeMountPointA(directory, volumeName, sizeof(volumeName)); + if (rc) { + char volumePathNames[_MAX_PATH]; + DWORD returnLength; + rc = GetVolumePathNamesForVolumeNameA(volumeName, volumePathNames, sizeof(volumePathNames), &returnLength); + if (rc) { + char *p = volumePathNames; + while (*p) { + if (_stricmp(p, directory)) // if it's not the path we've already found + { + NormalizeSlashes(directory, '/'); + NormalizeSlashes(p, '/'); + puts(directory); + puts(p); + } + p += strlen(p) + 1; + } + } + } + free(directory); } -bool PrintMountPointsForVolume(HANDLE hVol, const char* volumePath, char *Buf) -{ +bool PrintMountPointsForVolume(HANDLE hVol, const char *volumePath, char *Buf) { HANDLE hPt; // handle for mount point scan char Path[BUFSIZE]; // string buffer for mount points DWORD dwSysFlags; // flags that describe the file system @@ -182,39 +169,38 @@ bool PrintMountPointsForVolume(HANDLE hVol, const char* volumePath, char *Buf) // Detect support for reparse points, and therefore for volume // mount points, which are implemented using reparse points. - if (! (dwSysFlags & FILE_SUPPORTS_REPARSE_POINTS)) { - return true; + if (!(dwSysFlags & FILE_SUPPORTS_REPARSE_POINTS)) { + return true; } // Start processing mount points on this volume. hPt = FindFirstVolumeMountPointA( - Buf, // root path of volume to be scanned - Path, // pointer to output string - BUFSIZE // size of output buffer + Buf, // root path of volume to be scanned + Path, // pointer to output string + BUFSIZE // size of output buffer ); // Shall we error out? if (hPt == INVALID_HANDLE_VALUE) { - return GetLastError() != ERROR_ACCESS_DENIED; + return GetLastError() != ERROR_ACCESS_DENIED; } // Process the volume mount point. - char *buf = new char[MAX_PATH]; + char *buf = new char[MAX_PATH]; do { - strcpy_s(buf, MAX_PATH, volumePath); - strcat_s(buf, MAX_PATH, Path); - PrintDirectoryReparsePoint(buf); + strcpy_s(buf, MAX_PATH, volumePath); + strcat_s(buf, MAX_PATH, Path); + PrintDirectoryReparsePoint(buf); } while (FindNextVolumeMountPointA(hPt, Path, BUFSIZE)); FindVolumeMountPointClose(hPt); - return true; + return true; } -bool PrintMountPoints(const char *path) -{ - char volumeUniqueName[128]; - BOOL res = GetVolumeNameForVolumeMountPointA(path, volumeUniqueName, 128); - if (!res) { +bool PrintMountPoints(const char *path) { + char volumeUniqueName[128]; + BOOL res = GetVolumeNameForVolumeMountPointA(path, volumeUniqueName, 128); + if (!res) { return false; } @@ -222,7 +208,7 @@ bool PrintMountPoints(const char *path) HANDLE hVol; // handle for the volume scan // Open a scan for volumes. - hVol = FindFirstVolumeA(buf, BUFSIZE ); + hVol = FindFirstVolumeA(buf, BUFSIZE); // Shall we error out? if (hVol == INVALID_HANDLE_VALUE) { @@ -230,329 +216,286 @@ bool PrintMountPoints(const char *path) } bool success = true; - do { - if (!strcmp(buf, volumeUniqueName)) { - success = PrintMountPointsForVolume(hVol, path, buf); - if (!success) break; - } + do { + if (!strcmp(buf, volumeUniqueName)) { + success = PrintMountPointsForVolume(hVol, path, buf); + if (!success) break; + } } while (FindNextVolumeA(hVol, buf, BUFSIZE)); FindVolumeClose(hVol); - return success; + return success; } // -- Searching for mount points in watch roots (fallback) -------------------- -void PrintDirectoryReparsePoints(const char *path) -{ - char *const buf = _strdup(path); - while(strchr(buf, '/')) - { - DWORD attributes = GetFileAttributesA(buf); - if (attributes == INVALID_FILE_ATTRIBUTES) - break; - if (attributes & FILE_ATTRIBUTE_REPARSE_POINT) - { - PrintDirectoryReparsePoint(buf); - } - char *pSlash = strrchr(buf, '/'); - if (pSlash) - { - *pSlash = '\0'; - } - } - free(buf); +void PrintDirectoryReparsePoints(const char *path) { + char *const buf = _strdup(path); + while (strchr(buf, '/')) { + DWORD attributes = GetFileAttributesA(buf); + if (attributes == INVALID_FILE_ATTRIBUTES) + break; + if (attributes & FILE_ATTRIBUTE_REPARSE_POINT) { + PrintDirectoryReparsePoint(buf); + } + char *pSlash = strrchr(buf, '/'); + if (pSlash) { + *pSlash = '\0'; + } + } + free(buf); } // This is called if we got an ERROR_ACCESS_DENIED when trying to enumerate all mount points for volume. // In this case, we walk the directory tree up from each watch root, and look at each parent directory // to check whether it's a reparse point. -void PrintWatchRootReparsePoints() -{ - WatchRoot *pWatchRoot = firstWatchRoot; - while(pWatchRoot) - { - PrintDirectoryReparsePoints(pWatchRoot->path); - pWatchRoot = pWatchRoot->next; - } +void PrintWatchRootReparsePoints() { + WatchRoot *pWatchRoot = firstWatchRoot; + while (pWatchRoot) { + PrintDirectoryReparsePoints(pWatchRoot->path); + pWatchRoot = pWatchRoot->next; + } } // -- Watcher thread ---------------------------------------------------------- -void PrintChangeInfo(char *rootPath, FILE_NOTIFY_INFORMATION *info) -{ - char FileNameBuffer[_MAX_PATH]; - int converted = WideCharToMultiByte(CP_ACP, 0, info->FileName, info->FileNameLength/sizeof(WCHAR), FileNameBuffer, _MAX_PATH-1, NULL, NULL); - FileNameBuffer[converted] = '\0'; - char *command; - if (info->Action == FILE_ACTION_ADDED || info->Action == FILE_ACTION_RENAMED_OLD_NAME) - { - command = "CREATE"; - } - else if (info->Action == FILE_ACTION_REMOVED || info->Action == FILE_ACTION_RENAMED_OLD_NAME) - { - command = "DELETE"; - } - else if (info->Action == FILE_ACTION_MODIFIED) - { - command = "CHANGE"; - } - else - { - return; // unknown command - } - - EnterCriticalSection(&csOutput); - puts(command); - printf("%s", rootPath); - puts(FileNameBuffer); - fflush(stdout); - LeaveCriticalSection(&csOutput); +void PrintChangeInfo(char *rootPath, FILE_NOTIFY_INFORMATION *info) { + char FileNameBuffer[_MAX_PATH]; + int converted = WideCharToMultiByte(CP_ACP, 0, info->FileName, info->FileNameLength / sizeof(WCHAR), FileNameBuffer, _MAX_PATH - 1, NULL, NULL); + FileNameBuffer[converted] = '\0'; + char *command; + if (info->Action == FILE_ACTION_ADDED || info->Action == FILE_ACTION_RENAMED_OLD_NAME) { + command = "CREATE"; + } + else if (info->Action == FILE_ACTION_REMOVED || info->Action == FILE_ACTION_RENAMED_OLD_NAME) { + command = "DELETE"; + } + else if (info->Action == FILE_ACTION_MODIFIED) { + command = "CHANGE"; + } + else { + return; // unknown command + } + + EnterCriticalSection(&csOutput); + puts(command); + printf("%s", rootPath); + puts(FileNameBuffer); + fflush(stdout); + LeaveCriticalSection(&csOutput); } -void PrintEverythingChangedUnderRoot(char *rootPath) -{ - EnterCriticalSection(&csOutput); - puts("RECDIRTY"); - puts(rootPath); - fflush(stdout); - LeaveCriticalSection(&csOutput); +void PrintEverythingChangedUnderRoot(char *rootPath) { + EnterCriticalSection(&csOutput); + puts("RECDIRTY"); + puts(rootPath); + fflush(stdout); + LeaveCriticalSection(&csOutput); } -DWORD WINAPI WatcherThread(void *param) -{ - WatchRootInfo *info = (WatchRootInfo *) param; - - OVERLAPPED overlapped; - memset(&overlapped, 0, sizeof(overlapped)); - overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - - char rootPath[8]; - sprintf_s(rootPath, 8, "%c:\\", info->driveLetter); - HANDLE hRootDir = CreateFileA(rootPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); - - int buffer_size = 10240; - char *buffer = new char[buffer_size]; - - HANDLE handles [2]; - handles [0] = info->hStopEvent; - handles [1] = overlapped.hEvent; - while(true) - { - int rcDir = ReadDirectoryChangesW(hRootDir, buffer, buffer_size, TRUE, - FILE_NOTIFY_CHANGE_FILE_NAME | - FILE_NOTIFY_CHANGE_DIR_NAME | - FILE_NOTIFY_CHANGE_ATTRIBUTES | - FILE_NOTIFY_CHANGE_SIZE | - FILE_NOTIFY_CHANGE_LAST_WRITE, - NULL, - &overlapped, - NULL); - if (rcDir == 0) - { - info->bFailed = true; - break; - } - - int rc = WaitForMultipleObjects(2, handles, FALSE, INFINITE); - if (rc == WAIT_OBJECT_0) - { - break; - } - if (rc == WAIT_OBJECT_0+1) - { - DWORD dwBytesReturned; - if(!GetOverlappedResult(hRootDir, &overlapped, &dwBytesReturned, FALSE)) - { - info->bFailed = true; - break; - } - - if (dwBytesReturned == 0) - { - // don't send dirty too much, everything is changed anyway - if (WaitForSingleObject(info->hStopEvent, 500) == WAIT_OBJECT_0) - break; - - // Got a buffer overflow => current changes lost => send RECDIRTY on root - PrintEverythingChangedUnderRoot(rootPath); - } else { - FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION *) buffer; - while(true) - { - PrintChangeInfo(rootPath, info); - if (!info->NextEntryOffset) - break; - info = (FILE_NOTIFY_INFORMATION *) ((char *) info + info->NextEntryOffset); - } - } - } - } - CloseHandle(overlapped.hEvent); - CloseHandle(hRootDir); - delete[] buffer; - return 0; +DWORD WINAPI WatcherThread(void *param) { + WatchRootInfo *info = (WatchRootInfo *) param; + + OVERLAPPED overlapped; + memset(&overlapped, 0, sizeof(overlapped)); + overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + char rootPath[8]; + sprintf_s(rootPath, 8, "%c:\\", info->driveLetter); + HANDLE hRootDir = CreateFileA(rootPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); + + int buffer_size = 10240; + char *buffer = new char[buffer_size]; + + HANDLE handles[2]; + handles[0] = info->hStopEvent; + handles[1] = overlapped.hEvent; + while (true) { + int rcDir = ReadDirectoryChangesW(hRootDir, buffer, buffer_size, TRUE, + FILE_NOTIFY_CHANGE_FILE_NAME | + FILE_NOTIFY_CHANGE_DIR_NAME | + FILE_NOTIFY_CHANGE_ATTRIBUTES | + FILE_NOTIFY_CHANGE_SIZE | + FILE_NOTIFY_CHANGE_LAST_WRITE, + NULL, + &overlapped, + NULL); + if (rcDir == 0) { + info->bFailed = true; + break; + } + + int rc = WaitForMultipleObjects(2, handles, FALSE, INFINITE); + if (rc == WAIT_OBJECT_0) { + break; + } + if (rc == WAIT_OBJECT_0 + 1) { + DWORD dwBytesReturned; + if (!GetOverlappedResult(hRootDir, &overlapped, &dwBytesReturned, FALSE)) { + info->bFailed = true; + break; + } + + if (dwBytesReturned == 0) { + // don't send dirty too much, everything is changed anyway + if (WaitForSingleObject(info->hStopEvent, 500) == WAIT_OBJECT_0) + break; + + // Got a buffer overflow => current changes lost => send RECDIRTY on root + PrintEverythingChangedUnderRoot(rootPath); + } else { + FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION *) buffer; + while (true) { + PrintChangeInfo(rootPath, info); + if (!info->NextEntryOffset) + break; + info = (FILE_NOTIFY_INFORMATION *)((char *) info + info->NextEntryOffset); + } + } + } + } + CloseHandle(overlapped.hEvent); + CloseHandle(hRootDir); + delete[] buffer; + return 0; } // -- Roots update ------------------------------------------------------------ -void MarkAllRootsUnused() -{ - for(int i=0; i<ROOT_COUNT; i++) - { - watchRootInfos [i].bUsed = false; - } +void MarkAllRootsUnused() { + for (int i = 0; i < ROOT_COUNT; i++) { + watchRootInfos[i].bUsed = false; + } } -void StartRoot(WatchRootInfo *info) -{ - info->hStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - info->hThread = CreateThread(NULL, 0, &WatcherThread, info, 0, NULL); - info->bInitialized = true; +void StartRoot(WatchRootInfo *info) { + info->hStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + info->hThread = CreateThread(NULL, 0, &WatcherThread, info, 0, NULL); + info->bInitialized = true; } -void StopRoot(WatchRootInfo *info) -{ - SetEvent(info->hStopEvent); - WaitForSingleObject(info->hThread, INFINITE); - CloseHandle(info->hThread); - CloseHandle(info->hStopEvent); - info->bInitialized = false; +void StopRoot(WatchRootInfo *info) { + SetEvent(info->hStopEvent); + WaitForSingleObject(info->hThread, INFINITE); + CloseHandle(info->hThread); + CloseHandle(info->hStopEvent); + info->bInitialized = false; } -void UpdateRoots() -{ - char infoBuffer [256]; - strcpy_s(infoBuffer, "UNWATCHEABLE\n"); - for(int i=0; i<ROOT_COUNT; i++) - { - if (watchRootInfos [i].bInitialized && (!watchRootInfos [i].bUsed || watchRootInfos [i].bFailed)) - { - StopRoot(&watchRootInfos [i]); - watchRootInfos [i].bFailed = false; - } - if (watchRootInfos [i].bUsed) - { - char rootPath[8]; - sprintf_s(rootPath, 8, "%c:\\", watchRootInfos [i].driveLetter); - if (!IsWatchable(rootPath)) - { - strcat_s(infoBuffer, rootPath); - strcat_s(infoBuffer, "\n"); - continue; - } - if (!watchRootInfos [i].bInitialized) - { - StartRoot(&watchRootInfos [i]); - } - } - } - EnterCriticalSection(&csOutput); - fprintf(stdout, "%s", infoBuffer); - puts("#\nREMAP"); - PrintRemapForSubstDrives(); - bool printedMountPoints = true; - for(int i=0; i<ROOT_COUNT; i++) - { - if (watchRootInfos [i].bUsed) - { - char rootPath[8]; - sprintf_s(rootPath, 8, "%c:\\", watchRootInfos [i].driveLetter); - if (!PrintMountPoints(rootPath)) - printedMountPoints = false; - } - } - if (!printedMountPoints) - { - PrintWatchRootReparsePoints(); - } - puts("#"); - fflush(stdout); - LeaveCriticalSection(&csOutput); +void UpdateRoots() { + char infoBuffer[256]; + strcpy_s(infoBuffer, "UNWATCHEABLE\n"); + for (int i = 0; i < ROOT_COUNT; i++) { + if (watchRootInfos[i].bInitialized && (!watchRootInfos[i].bUsed || watchRootInfos[i].bFailed)) { + StopRoot(&watchRootInfos[i]); + watchRootInfos[i].bFailed = false; + } + if (watchRootInfos[i].bUsed) { + char rootPath[8]; + sprintf_s(rootPath, 8, "%c:\\", watchRootInfos[i].driveLetter); + if (!IsWatchable(rootPath)) { + strcat_s(infoBuffer, rootPath); + strcat_s(infoBuffer, "\n"); + continue; + } + if (!watchRootInfos[i].bInitialized) { + StartRoot(&watchRootInfos[i]); + } + } + } + EnterCriticalSection(&csOutput); + fprintf(stdout, "%s", infoBuffer); + puts("#\nREMAP"); + PrintRemapForSubstDrives(); + bool printedMountPoints = true; + for (int i = 0; i < ROOT_COUNT; i++) { + if (watchRootInfos[i].bUsed) { + char rootPath[8]; + sprintf_s(rootPath, 8, "%c:\\", watchRootInfos[i].driveLetter); + if (!PrintMountPoints(rootPath)) + printedMountPoints = false; + } + } + if (!printedMountPoints) { + PrintWatchRootReparsePoints(); + } + puts("#"); + fflush(stdout); + LeaveCriticalSection(&csOutput); } -void AddWatchRoot(const char *path) -{ - WatchRoot *watchRoot = (WatchRoot *) malloc(sizeof(WatchRoot)); - watchRoot->next = NULL; - watchRoot->path = _strdup(path); - watchRoot->next = firstWatchRoot; - firstWatchRoot = watchRoot; +void AddWatchRoot(const char *path) { + WatchRoot *watchRoot = (WatchRoot *) malloc(sizeof(WatchRoot)); + watchRoot->next = NULL; + watchRoot->path = _strdup(path); + watchRoot->next = firstWatchRoot; + firstWatchRoot = watchRoot; } -void FreeWatchRootsList() -{ - WatchRoot *pWatchRoot = firstWatchRoot; - WatchRoot *pNext; - while(pWatchRoot) - { - pNext = pWatchRoot->next; - free(pWatchRoot->path); - free(pWatchRoot); - pWatchRoot=pNext; - } - firstWatchRoot = NULL; +void FreeWatchRootsList() { + WatchRoot *pWatchRoot = firstWatchRoot; + WatchRoot *pNext; + while (pWatchRoot) { + pNext = pWatchRoot->next; + free(pWatchRoot->path); + free(pWatchRoot); + pWatchRoot = pNext; + } + firstWatchRoot = NULL; } // -- Main - filewatcher protocol --------------------------------------------- -int _tmain(int argc, _TCHAR* argv[]) -{ - InitializeCriticalSection(&csOutput); - - for(int i=0; i<26; i++) - { - watchRootInfos [i].driveLetter = 'A' + i; - watchRootInfos [i].bInitialized = false; - watchRootInfos [i].bUsed = false; - } - - char buffer[8192]; - while(true) - { - if (!gets_s(buffer, sizeof(buffer)-1)) - break; - - if (!strcmp(buffer, "ROOTS")) - { - MarkAllRootsUnused(); - FreeWatchRootsList(); - bool failed = false; - while(true) - { - if (!gets_s(buffer, sizeof(buffer)-1)) - { - failed = true; - break; - } - if (buffer [0] == '#') - break; - int driveLetterPos = 0; - char *pDriveLetter = buffer; - if (*pDriveLetter == '|') - pDriveLetter++; - - AddWatchRoot(pDriveLetter); - - _strupr_s(buffer, sizeof(buffer)-1); - char driveLetter = *pDriveLetter; - if (driveLetter >= 'A' && driveLetter <= 'Z') - { - watchRootInfos [driveLetter-'A'].bUsed = true; - } - } - if (failed) - break; - - UpdateRoots(); - } - if (!strcmp(buffer, "EXIT")) - break; - } - - MarkAllRootsUnused(); - UpdateRoots(); - - DeleteCriticalSection(&csOutput); +int _tmain(int argc, _TCHAR *argv[]) { + InitializeCriticalSection(&csOutput); + + for (int i = 0; i < 26; i++) { + watchRootInfos[i].driveLetter = 'A' + i; + watchRootInfos[i].bInitialized = false; + watchRootInfos[i].bUsed = false; + } + + char buffer[8192]; + while (true) { + if (!gets_s(buffer, sizeof(buffer) - 1)) + break; + + if (!strcmp(buffer, "ROOTS")) { + MarkAllRootsUnused(); + FreeWatchRootsList(); + bool failed = false; + while (true) { + if (!gets_s(buffer, sizeof(buffer) - 1)) { + failed = true; + break; + } + if (buffer[0] == '#') + break; + int driveLetterPos = 0; + char *pDriveLetter = buffer; + if (*pDriveLetter == '|') + pDriveLetter++; + + AddWatchRoot(pDriveLetter); + + _strupr_s(buffer, sizeof(buffer) - 1); + char driveLetter = *pDriveLetter; + if (driveLetter >= 'A' && driveLetter <= 'Z') { + watchRootInfos[driveLetter - 'A'].bUsed = true; + } + } + if (failed) + break; + + UpdateRoots(); + } + if (!strcmp(buffer, "EXIT")) + break; + } + + MarkAllRootsUnused(); + UpdateRoots(); + + DeleteCriticalSection(&csOutput); } |