public
Last active

search filesystem for writable files

  • Download Gist
probeFs.c
C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
#define _CRT_SECURE_NO_WARNINGS
 
#include <Windows.h>
 
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
 
void* fallibleMalloc(int n);
 
enum PROG_ERRCODES {
OP_OK = 0,
OP_BAD_FIRST_FILE = 1 << 1,
OP_BAD_DRIVESTRINGS = 1 << 2,
OP_BAD_LAST_FIND_FILE = 1 << 3,
OP_BAD_FIND_CLOSE = 1 << 4,
OP_FAILED = 0xffffffff
};
 
enum PROG_ERRCODES walkDrives();
enum PROG_ERRCODES walkDirectoryTree(const char* const rootDirectoryStar);
enum PROG_ERRCODES processFile(const TCHAR* const filePath, const WIN32_FIND_DATA* const fDataPtr );
 
int main(int argc, char** argv) {
 
/* TODO: process command line arguments for optional start directory */
 
return walkDrives();
}
 
void* fallibleMalloc(int n) {
auto void* heapBlock = malloc(n);
assert(heapBlock);
return heapBlock;
}
 
enum PROG_ERRCODES walkDrives() {
auto int i;
auto int driveBufferLen = GetLogicalDriveStrings(0, NULL);
auto TCHAR* driveBuffer = (TCHAR*) fallibleMalloc(driveBufferLen+1);
 
if(!GetLogicalDriveStrings(driveBufferLen, driveBuffer)) {
free(driveBuffer);
return OP_BAD_DRIVESTRINGS;
}
 
for( i = 0; i < driveBufferLen; ++i) {
auto TCHAR* thisDriveString = NULL;
auto int startIndex = i;
auto int dLen = 0;
auto enum PROG_ERRCODES err;
 
while(driveBuffer[i] != 0) { ++i; }
 
dLen = i - startIndex + 1;
 
thisDriveString = (TCHAR*) fallibleMalloc(dLen+1+1);
strncpy(thisDriveString, driveBuffer + startIndex, dLen);
strcat(thisDriveString + startIndex + dLen - 1, "*");
 
if(!(err = walkDirectoryTree((const char* const) thisDriveString))) {
free(thisDriveString);
return err;
}
 
free(thisDriveString);
}
 
 
free(driveBuffer);
return OP_OK;
}
 
enum PROG_ERRCODES walkDirectoryTree(const char* const rootDirectoryStar) {
static const char charSuffix[] = "\\*";
static const int charSuffixLen = 2;
static const char symbolicDirName[] = ".";
static const char symbolicParentDirName[] = "..";
 
auto WIN32_FIND_DATA fData;
auto HANDLE hFind;
 
printf("D %s\n", rootDirectoryStar);
 
if ((hFind = FindFirstFile(rootDirectoryStar, &fData)) == INVALID_HANDLE_VALUE) {
return OP_BAD_FIRST_FILE;
}
 
do {
auto int cFileNameLen = strlen(fData.cFileName);
auto int rootDirectoryStarLen = strlen(rootDirectoryStar);
 
/* skip the symbolic directories */
if(strcmp(fData.cFileName, symbolicParentDirName) == 0 || strcmp(fData.cFileName, symbolicDirName) == 0) {
continue;
 
/* if we're dealing with a directory */
} else if(fData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
int nextRootDirectoryStarLen =
(rootDirectoryStarLen - 1 ) + /* length of root directory, minus one */
cFileNameLen + /* length of leaf directory */
charSuffixLen + /* for slash star */
1; /* for null terminator */
auto enum PROG_ERRCODES err;
auto TCHAR* nextRootDirectoryStar = (TCHAR*) fallibleMalloc(nextRootDirectoryStarLen);
 
memset(nextRootDirectoryStar, '\0', nextRootDirectoryStarLen);
strncpy(nextRootDirectoryStar, rootDirectoryStar, rootDirectoryStarLen - 1);
strncat(nextRootDirectoryStar, fData.cFileName, cFileNameLen);
strncat(nextRootDirectoryStar, charSuffix, charSuffixLen);
 
if( !(err=walkDirectoryTree(nextRootDirectoryStar)) ) {
/* something went wrong */
}
 
free(nextRootDirectoryStar);
 
/* otherwise treat it as a file */
} else {
auto int cFilePathLen = rootDirectoryStarLen - 1 + cFileNameLen + 1;
auto TCHAR* cFilePath = (TCHAR*) fallibleMalloc(cFilePathLen);
auto enum PROG_ERRCODES err;
 
/* concatenate root directory star minus the star and cfile name
* then call processFile(..) with the newly formed string */
 
memset(cFilePath, '\0', cFilePathLen);
strncpy(cFilePath, rootDirectoryStar, rootDirectoryStarLen - 1);
strncat(cFilePath, fData.cFileName, cFileNameLen);
 
if( !(err = processFile(cFilePath, (const WIN32_FIND_DATA* const) &fData ))) {
/* something went wrong */
}
 
free(cFilePath);
}
} while (FindNextFile(hFind, &fData));
 
if( GetLastError() != ERROR_NO_MORE_FILES ) {
if(!FindClose(hFind)) {
return OP_BAD_LAST_FIND_FILE;
} else {
return OP_BAD_LAST_FIND_FILE | OP_BAD_FIND_CLOSE;
}
}
 
if(!FindClose(hFind)) {
return OP_BAD_FIND_CLOSE;
}
 
return OP_OK;
}
 
enum PROG_ERRCODES processFile(const TCHAR* const filePath, const WIN32_FIND_DATA* const fDataPtr ) {
auto HANDLE fHandle;
 
printf("F %s ", filePath);
 
/* attempt to acquire write lock */
if ((fHandle = CreateFile(
filePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL)) == INVALID_HANDLE_VALUE ) {
printf("NW\n");
return OP_OK;
}
 
if(CloseHandle(fHandle)) {
printf("W\n");
return OP_OK;
} else {
printf("EW\n");
return OP_FAILED;
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.