Cleaning up obsolete file track stuff
parent
92853a4fbc
commit
c0c536651e
|
@ -1,275 +0,0 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 20.07.2016
|
||||
*
|
||||
* File tracking linux.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#include "4ed_file_track.h"
|
||||
#include "4ed_file_track_general.cpp"
|
||||
|
||||
#include <libgen.h> // dirname
|
||||
|
||||
struct Linux_File_Track_Vars{
|
||||
void *tables;
|
||||
int inotify;
|
||||
pthread_mutex_t lock;
|
||||
char *string_mem_begin;
|
||||
char *string_mem_end;
|
||||
};
|
||||
|
||||
struct Linux_File_Track_Entry{
|
||||
File_Index hash;
|
||||
char* dir;
|
||||
int ref_count;
|
||||
};
|
||||
|
||||
#define to_vars(s) ((Linux_File_Track_Vars*)(s))
|
||||
#define to_tables(v) ((File_Track_Tables*)(v->tables))
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
init_track_system(File_Track_System *system, Partition *scratch, void *table_memory, int32_t table_memory_size, void *listener_memory, int32_t listener_memory_size){
|
||||
File_Track_Result result = FileTrack_MemoryTooSmall;
|
||||
|
||||
Assert(sizeof(Linux_File_Track_Vars) <= sizeof(File_Track_System));
|
||||
|
||||
Linux_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
Assert(sizeof(Linux_File_Track_Entry) <= sizeof(File_Track_Entry));
|
||||
|
||||
if (enough_memory_to_init_table(table_memory_size)){
|
||||
|
||||
// NOTE(allen): Initialize main data tables
|
||||
vars->tables = (File_Track_Tables*) table_memory;
|
||||
File_Track_Tables *tables = to_tables(vars);
|
||||
init_table_memory(tables, table_memory_size);
|
||||
|
||||
vars->inotify = inotify_init1(IN_NONBLOCK);
|
||||
|
||||
pthread_mutex_init(&vars->lock, NULL);
|
||||
|
||||
vars->string_mem_begin = (char*)listener_memory;
|
||||
vars->string_mem_end = (char*)listener_memory + listener_memory_size;
|
||||
|
||||
result = FileTrack_Good;
|
||||
}
|
||||
|
||||
LINUX_FN_DEBUG("result: %d", result);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
add_listener(File_Track_System *system, Partition *scratch, u8 *filename){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Linux_File_Track_Vars *vars = to_vars(system);
|
||||
File_Track_Tables *tables = to_tables(vars);
|
||||
|
||||
pthread_mutex_lock(&vars->lock);
|
||||
|
||||
if(tracking_system_has_space(tables, 1)){
|
||||
char *dir = dirname(strdupa((char*)filename));
|
||||
size_t dir_len = strlen(dir) + 1;
|
||||
|
||||
if(vars->string_mem_end - vars->string_mem_begin >= dir_len){
|
||||
int wd = inotify_add_watch(vars->inotify, dir, IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVE);
|
||||
|
||||
if(wd != -1){
|
||||
File_Index key = { wd, 1 };
|
||||
File_Track_Entry *entry = tracking_system_lookup_entry(tables, key);
|
||||
Linux_File_Track_Entry *linux_entry = (Linux_File_Track_Entry*) entry;
|
||||
|
||||
if(entry_is_available(entry)){
|
||||
linux_entry->hash = key;
|
||||
linux_entry->dir = vars->string_mem_begin;
|
||||
linux_entry->ref_count = 1;
|
||||
memcpy(vars->string_mem_begin, dir, dir_len);
|
||||
vars->string_mem_begin += dir_len;
|
||||
++tables->tracked_count;
|
||||
} else {
|
||||
++linux_entry->ref_count;
|
||||
}
|
||||
} else {
|
||||
result = FileTrack_FileSystemError;
|
||||
}
|
||||
} else {
|
||||
result = FileTrack_OutOfListenerMemory;
|
||||
}
|
||||
} else {
|
||||
result = FileTrack_OutOfTableMemory;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&vars->lock);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
remove_listener(File_Track_System *system, Partition *scratch, u8 *filename){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Linux_File_Track_Vars *vars = to_vars(system);
|
||||
File_Track_Tables *tables = to_tables(vars);
|
||||
File_Track_Entry *entries = (File_Track_Entry*) to_ptr(tables, tables->file_table);
|
||||
|
||||
pthread_mutex_lock(&vars->lock);
|
||||
|
||||
char *dir = dirname(strdupa((char*)filename));
|
||||
// NOTE(inso): this assumes the filename was previously added
|
||||
|
||||
for(uint32_t i = 0; i < tables->max; ++i){
|
||||
Linux_File_Track_Entry *e = (Linux_File_Track_Entry*)(entries + i);
|
||||
if(e->hash.id[1] != 1) continue;
|
||||
if(strcmp(e->dir, dir) == 0){
|
||||
LINUX_FN_DEBUG("%s found as wd %d", filename, e->hash.id[0]);
|
||||
if(--e->ref_count == 0){
|
||||
LINUX_FN_DEBUG("refcount == 0, calling rm_watch");
|
||||
if(inotify_rm_watch(vars->inotify, e->hash.id[0]) == -1){
|
||||
perror("inotify_rm_watch");
|
||||
result = FileTrack_FileSystemError;
|
||||
}
|
||||
internal_free_slot(tables, (File_Track_Entry*)e);
|
||||
}
|
||||
// NOTE(inso): associated string memory in listeners would be freed here
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&vars->lock);
|
||||
|
||||
LINUX_FN_DEBUG("result: %d", result);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
move_track_system(File_Track_System *system, Partition *scratch, void *mem, int32_t size){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Linux_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
pthread_mutex_lock(&vars->lock);
|
||||
|
||||
{
|
||||
File_Track_Tables *original_tables = to_tables(vars);
|
||||
result = move_table_memory(original_tables, mem, size);
|
||||
if (result == FileTrack_Good){
|
||||
vars->tables = mem;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&vars->lock);
|
||||
|
||||
LINUX_FN_DEBUG("size: %d, %d", size, result);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
expand_track_system_listeners(File_Track_System *system, Partition *scratch, void *mem, int32_t size){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Linux_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
pthread_mutex_lock(&vars->lock);
|
||||
|
||||
// NOTE(inso): pointer to old string mem is lost here.
|
||||
// would need to keep it around if we want to free in the future
|
||||
|
||||
// NOTE(inso): assuming PATH_MAX is a reasonable lower bound of extra memory to get
|
||||
|
||||
if (size < PATH_MAX){
|
||||
result = FileTrack_MemoryTooSmall;
|
||||
}
|
||||
else{
|
||||
vars->string_mem_begin = (char*)mem;
|
||||
vars->string_mem_end = (char*)mem + size;;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&vars->lock);
|
||||
|
||||
LINUX_FN_DEBUG("size: %d, result: %d", size, result);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
get_change_event(File_Track_System *system, Partition *scratch, u8 *buffer, int32_t max, int32_t *size){
|
||||
File_Track_Result result = FileTrack_NoMoreEvents;
|
||||
Linux_File_Track_Vars *vars = to_vars(system);
|
||||
File_Track_Tables *tables = to_tables(vars);
|
||||
|
||||
pthread_mutex_lock(&vars->lock);
|
||||
|
||||
struct inotify_event *ev;
|
||||
char buff[sizeof(*ev) + NAME_MAX + 1] __attribute__((aligned(__alignof__(*ev))));
|
||||
|
||||
// NOTE(inso): make sure we only read one event
|
||||
size_t read_count = sizeof(*ev);
|
||||
ssize_t n;
|
||||
|
||||
do{
|
||||
n = read(vars->inotify, buff, read_count);
|
||||
read_count++;
|
||||
}while(n == -1 && errno == EINVAL);
|
||||
|
||||
if (n == -1 && errno != EAGAIN){
|
||||
perror("inotify read");
|
||||
}
|
||||
else if (n > 0){
|
||||
ev = (struct inotify_event*) buff;
|
||||
|
||||
File_Index key = { ev->wd, 1 };
|
||||
File_Track_Entry *entry = tracking_system_lookup_entry(tables, key);
|
||||
Linux_File_Track_Entry *linux_entry = (Linux_File_Track_Entry*) entry;
|
||||
|
||||
if (!entry_is_available(entry)){
|
||||
char* full_name = (char*) alloca(strlen(linux_entry->dir) + ev->len + 1);
|
||||
strcpy(full_name, linux_entry->dir);
|
||||
strcat(full_name, "/");
|
||||
strcat(full_name, ev->name);
|
||||
|
||||
size_t full_name_size = strlen(full_name);
|
||||
if (max < full_name_size){
|
||||
result = FileTrack_MemoryTooSmall;
|
||||
// NOTE(inso): this event will be dropped, needs to be stashed.
|
||||
}
|
||||
else{
|
||||
memcpy(buffer, full_name, full_name_size);
|
||||
*size = full_name_size;
|
||||
result = FileTrack_Good;
|
||||
}
|
||||
} else {
|
||||
//LINUX_FN_DEBUG("dead event from wd %d", ev->wd);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&vars->lock);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
shut_down_track_system(File_Track_System *system, Partition *scratch){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Linux_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
// NOTE(allen): Close all the global track system resources.
|
||||
if(close(vars->inotify) == -1){
|
||||
result = FileTrack_FileSystemError;
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&vars->lock);
|
||||
|
||||
LINUX_FN_DEBUG("result: %d", result);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 28.06.2017
|
||||
*
|
||||
* Mac file tracking C++ wrapper.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
File_Track_Result
|
||||
init_track_system(File_Track_System *system, Partition *scratch, void *table_memory, i32 table_memory_size, void *listener_memory, i32 listener_memory_size){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
// NOTE(allen): Do nothing???
|
||||
return(result);
|
||||
}
|
||||
|
||||
File_Track_Result
|
||||
add_listener(File_Track_System *system, Partition *scratch, u8 *filename){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
#if 1
|
||||
#if 1
|
||||
// HACK(allen) HACK(allen) HACK(allen)
|
||||
char strspace[1024];
|
||||
String str = make_fixed_width_string(strspace);
|
||||
copy(&str, (char*)filename);
|
||||
remove_last_folder(&str);
|
||||
--str.size;
|
||||
terminate_with_null(&str);
|
||||
osx_add_file_listener(str.str);
|
||||
#else
|
||||
osx_add_file_listener((char*)filename);
|
||||
#endif
|
||||
#endif
|
||||
return(result);
|
||||
}
|
||||
|
||||
File_Track_Result
|
||||
remove_listener(File_Track_System *system, Partition *scratch, u8 *filename){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
#if 1
|
||||
// HACK(allen) HACK(allen) HACK(allen)
|
||||
char strspace[1024];
|
||||
String str = make_fixed_width_string(strspace);
|
||||
copy(&str, (char*)filename);
|
||||
remove_last_folder(&str);
|
||||
--str.size;
|
||||
terminate_with_null(&str);
|
||||
osx_remove_file_listener(str.str);
|
||||
#else
|
||||
osx_remove_file_listener((char*)filename);
|
||||
#endif
|
||||
return(result);
|
||||
}
|
||||
|
||||
File_Track_Result
|
||||
move_track_system(File_Track_System *system, Partition *scratch, void *mem, i32 size){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
// NOTE(allen): Do nothing???
|
||||
return(result);
|
||||
}
|
||||
|
||||
File_Track_Result
|
||||
expand_track_system_listeners(File_Track_System *system, Partition *scratch, void *mem, i32 size){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
// NOTE(allen): Do nothing???
|
||||
return(result);
|
||||
}
|
||||
|
||||
File_Track_Result
|
||||
get_change_event(File_Track_System *system, Partition *scratch, u8 *buffer, i32 max, i32 *size){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
i32 status = osx_get_file_change_event((char*)buffer, max, size);
|
||||
if (status == 0){
|
||||
result = FileTrack_NoMoreEvents;
|
||||
}
|
||||
if (status == -1){
|
||||
result = FileTrack_MemoryTooSmall;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
File_Track_Result
|
||||
shut_down_track_system(File_Track_System *system, Partition *scratch){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
// NOTE(allen): Do nothing???
|
||||
return(result);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 14.11.2017
|
||||
*
|
||||
* Debuging helper for fd leaking
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define MAXPATHLEN 512
|
||||
|
||||
int
|
||||
descriptor_open(int fd){
|
||||
int is_open = true;
|
||||
if (fd != 0){
|
||||
char t[1];
|
||||
if (pread(fd, t, 1, 0) == -1){
|
||||
if (errno == EBADF){
|
||||
is_open = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(is_open);
|
||||
}
|
||||
|
||||
void
|
||||
print_open_file_descriptors(void){
|
||||
for (int fd = 1; fd < 256; ++fd){
|
||||
if (descriptor_open(fd)){
|
||||
char b[MAXPATHLEN + 1];
|
||||
fcntl(fd, F_GETPATH, b);
|
||||
//LOGF("FD(%d) = \"%s\"\n", fd, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//#define FD_CHECK() LOG("FD_CHECK\n"); print_open_file_descriptors()
|
||||
|
||||
// BOTTOM
|
|
@ -1,438 +0,0 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 20.07.2016
|
||||
*
|
||||
* File tracking win32.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#include "4ed_file_track.h"
|
||||
#include "4ed_file_track_general.cpp"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
struct Win32_Directory_Listener{
|
||||
OVERLAPPED overlapped;
|
||||
u8 result[2048];
|
||||
HANDLE dir;
|
||||
i32 user_count;
|
||||
};
|
||||
global_const OVERLAPPED null_overlapped = {};
|
||||
|
||||
struct Win32_Directory_Listener_Node{
|
||||
DLL_Node node;
|
||||
Win32_Directory_Listener listener;
|
||||
};
|
||||
|
||||
struct Win32_File_Track_Vars{
|
||||
HANDLE iocp;
|
||||
CRITICAL_SECTION table_lock;
|
||||
void *tables;
|
||||
DLL_Node free_sentinel;
|
||||
};
|
||||
|
||||
struct Win32_File_Track_Entry{
|
||||
File_Index hash;
|
||||
HANDLE dir;
|
||||
Win32_Directory_Listener_Node *listener_node;
|
||||
};
|
||||
|
||||
#define to_vars(s) ((Win32_File_Track_Vars*)(s))
|
||||
#define to_tables(v) ((File_Track_Tables*)(v->tables))
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
init_track_system(File_Track_System *system, Partition *scratch, void *table_memory, i32 table_memory_size, void *listener_memory, i32 listener_memory_size){
|
||||
File_Track_Result result = FileTrack_MemoryTooSmall;
|
||||
Win32_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
Assert(sizeof(Win32_File_Track_Entry) <= sizeof(File_Track_Entry));
|
||||
|
||||
if (enough_memory_to_init_table(table_memory_size) &&
|
||||
sizeof(Win32_Directory_Listener_Node) <= listener_memory_size){
|
||||
|
||||
// NOTE(allen): Initialize main data tables
|
||||
vars->tables = table_memory;
|
||||
File_Track_Tables *tables = to_tables(vars);
|
||||
init_table_memory(tables, table_memory_size);
|
||||
|
||||
// NOTE(allen): Initialize nodes of directory watching
|
||||
{
|
||||
init_sentinel_node(&vars->free_sentinel);
|
||||
|
||||
Win32_Directory_Listener_Node *listener = (Win32_Directory_Listener_Node*)listener_memory;
|
||||
i32 count = listener_memory_size / sizeof(Win32_Directory_Listener_Node);
|
||||
for (i32 i = 0; i < count; ++i, ++listener){
|
||||
insert_node(&vars->free_sentinel, &listener->node);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(allen): Prepare the file tracking synchronization objects.
|
||||
{
|
||||
InitializeCriticalSection(&vars->table_lock);
|
||||
vars->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 1);
|
||||
}
|
||||
|
||||
result = FileTrack_Good;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal i32
|
||||
internal_get_parent_name(u8 *out, i32 max, u8 *name){
|
||||
u8 *ptr = name;
|
||||
for (; *ptr != 0; ++ptr);
|
||||
i32 len = (i32)(ptr - name);
|
||||
|
||||
// TODO(allen): make this system real
|
||||
Assert(len < max);
|
||||
|
||||
i32 slash_i = len-1;
|
||||
for (;slash_i > 0 && name[slash_i] != '\\' && name[slash_i] != '/';--slash_i);
|
||||
|
||||
for (i32 i = 0; i < slash_i; ++i) out[i] = name[i];
|
||||
out[slash_i] = 0;
|
||||
|
||||
return(slash_i);
|
||||
}
|
||||
|
||||
internal File_Index
|
||||
internal_get_file_index(BY_HANDLE_FILE_INFORMATION info){
|
||||
File_Index hash;
|
||||
hash.id[0] = info.nFileIndexLow;
|
||||
hash.id[1] = info.nFileIndexHigh;
|
||||
hash.id[2] = info.dwVolumeSerialNumber;
|
||||
hash.id[3] = 0;
|
||||
return(hash);
|
||||
}
|
||||
|
||||
#define FLAGS ( \
|
||||
FILE_NOTIFY_CHANGE_FILE_NAME | \
|
||||
FILE_NOTIFY_CHANGE_DIR_NAME | \
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES | \
|
||||
FILE_NOTIFY_CHANGE_SIZE | \
|
||||
FILE_NOTIFY_CHANGE_LAST_WRITE | \
|
||||
FILE_NOTIFY_CHANGE_SECURITY | \
|
||||
FILE_NOTIFY_CHANGE_CREATION | \
|
||||
0)
|
||||
|
||||
//FILE_NOTIFY_CHANGE_LAST_ACCESS| \
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
add_listener(File_Track_System *system, Partition *scratch, u8 *filename){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Win32_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
EnterCriticalSection(&vars->table_lock);
|
||||
{
|
||||
File_Track_Tables *tables = to_tables(vars);
|
||||
|
||||
u8 dir_name[1024];
|
||||
internal_get_parent_name(dir_name, ArrayCount(dir_name), filename);
|
||||
|
||||
HANDLE dir = CreateFile_utf8(dir_name, FILE_LIST_DIRECTORY,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, 0);
|
||||
|
||||
if (dir != INVALID_HANDLE_VALUE){
|
||||
BY_HANDLE_FILE_INFORMATION dir_info = {};
|
||||
DWORD getinfo_result = GetFileInformationByHandle(dir, &dir_info);
|
||||
|
||||
if (getinfo_result){
|
||||
File_Index dir_hash = internal_get_file_index(dir_info);
|
||||
File_Track_Entry *dir_lookup = tracking_system_lookup_entry(tables, dir_hash);
|
||||
Win32_File_Track_Entry *win32_entry = (Win32_File_Track_Entry*)dir_lookup;
|
||||
|
||||
if (entry_is_available(dir_lookup)){
|
||||
if (tracking_system_has_space(tables, 1)){
|
||||
Win32_Directory_Listener_Node *node = (Win32_Directory_Listener_Node*)
|
||||
allocate_node(&vars->free_sentinel);
|
||||
if (node){
|
||||
if (CreateIoCompletionPort(dir, vars->iocp, (ULONG_PTR)node, 1)){
|
||||
node->listener.overlapped = null_overlapped;
|
||||
if (ReadDirectoryChangesW(dir, node->listener.result, sizeof(node->listener.result), 1, FLAGS, 0, &node->listener.overlapped, 0)){
|
||||
node->listener.dir = dir;
|
||||
node->listener.user_count = 1;
|
||||
|
||||
win32_entry->hash = dir_hash;
|
||||
win32_entry->dir = dir;
|
||||
win32_entry->listener_node = node;
|
||||
++tables->tracked_count;
|
||||
}
|
||||
else{
|
||||
result = FileTrack_FileSystemError;
|
||||
}
|
||||
}
|
||||
else{
|
||||
result = FileTrack_FileSystemError;
|
||||
}
|
||||
|
||||
if (result != FileTrack_Good){
|
||||
insert_node(&vars->free_sentinel, &node->node);
|
||||
}
|
||||
}
|
||||
else{
|
||||
result = FileTrack_OutOfListenerMemory;
|
||||
}
|
||||
}
|
||||
else{
|
||||
result = FileTrack_OutOfTableMemory;
|
||||
}
|
||||
}
|
||||
else{
|
||||
Win32_Directory_Listener_Node *node = win32_entry->listener_node;
|
||||
++node->listener.user_count;
|
||||
}
|
||||
}
|
||||
else{
|
||||
result = FileTrack_FileSystemError;
|
||||
}
|
||||
}
|
||||
else{
|
||||
result = FileTrack_FileSystemError;
|
||||
}
|
||||
|
||||
if (result != FileTrack_Good && dir != 0 && dir != INVALID_HANDLE_VALUE){
|
||||
CloseHandle(dir);
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&vars->table_lock);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
remove_listener(File_Track_System *system, Partition *scratch, u8 *filename){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Win32_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
EnterCriticalSection(&vars->table_lock);
|
||||
|
||||
File_Track_Tables *tables = to_tables(vars);
|
||||
|
||||
// TODO(allen): make this real!
|
||||
u8 dir_name[1024];
|
||||
internal_get_parent_name(dir_name, ArrayCount(dir_name), filename);
|
||||
|
||||
HANDLE dir = CreateFile_utf8(dir_name, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, 0);
|
||||
|
||||
if (dir != INVALID_HANDLE_VALUE){
|
||||
BY_HANDLE_FILE_INFORMATION dir_info = {};
|
||||
DWORD getinfo_result = GetFileInformationByHandle(dir, &dir_info);
|
||||
|
||||
if (getinfo_result){
|
||||
File_Index dir_hash = internal_get_file_index(dir_info);
|
||||
File_Track_Entry *dir_lookup = tracking_system_lookup_entry(tables, dir_hash);
|
||||
Win32_File_Track_Entry *win32_dir = (Win32_File_Track_Entry*)dir_lookup;
|
||||
|
||||
Assert(!entry_is_available(dir_lookup));
|
||||
Win32_Directory_Listener_Node *node = win32_dir->listener_node;
|
||||
--node->listener.user_count;
|
||||
|
||||
if (node->listener.user_count == 0){
|
||||
insert_node(&vars->free_sentinel, &node->node);
|
||||
CancelIo(win32_dir->dir);
|
||||
CloseHandle(win32_dir->dir);
|
||||
internal_free_slot(tables, dir_lookup);
|
||||
}
|
||||
}
|
||||
else{
|
||||
result = FileTrack_FileSystemError;
|
||||
}
|
||||
|
||||
CloseHandle(dir);
|
||||
}
|
||||
else{
|
||||
result = FileTrack_FileSystemError;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&vars->table_lock);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
move_track_system(File_Track_System *system, Partition *scratch, void *mem, i32 size){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Win32_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
EnterCriticalSection(&vars->table_lock);
|
||||
File_Track_Tables *original_tables = to_tables(vars);
|
||||
result = move_table_memory(original_tables, mem, size);
|
||||
if (result == FileTrack_Good){
|
||||
vars->tables = mem;
|
||||
}
|
||||
LeaveCriticalSection(&vars->table_lock);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
expand_track_system_listeners(File_Track_System *system, Partition *scratch, void *mem, i32 size){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Win32_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
EnterCriticalSection(&vars->table_lock);
|
||||
|
||||
if (sizeof(Win32_Directory_Listener_Node) <= size){
|
||||
Win32_Directory_Listener_Node *listener = (Win32_Directory_Listener_Node*)mem;
|
||||
i32 count = size / sizeof(Win32_Directory_Listener_Node);
|
||||
for (i32 i = 0; i < count; ++i, ++listener){
|
||||
insert_node(&vars->free_sentinel, &listener->node);
|
||||
}
|
||||
}
|
||||
else{
|
||||
result = FileTrack_MemoryTooSmall;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&vars->table_lock);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
get_change_event(File_Track_System *system, Partition *scratch, u8 *buffer, i32 max, i32 *size){
|
||||
File_Track_Result result = FileTrack_NoMoreEvents;
|
||||
Win32_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
local_persist i32 has_buffered_event = 0;
|
||||
local_persist DWORD offset = 0;
|
||||
local_persist Win32_Directory_Listener listener = {};
|
||||
|
||||
EnterCriticalSection(&vars->table_lock);
|
||||
|
||||
OVERLAPPED *overlapped = 0;
|
||||
DWORD length = 0;
|
||||
ULONG_PTR key = 0;
|
||||
|
||||
b32 has_result = 0;
|
||||
|
||||
if (has_buffered_event){
|
||||
has_buffered_event = 0;
|
||||
has_result = 1;
|
||||
}
|
||||
else{
|
||||
if (GetQueuedCompletionStatus(vars->iocp, &length, &key, &overlapped, 0)){
|
||||
Win32_Directory_Listener *listener_ptr = (Win32_Directory_Listener*)overlapped;
|
||||
|
||||
// NOTE(allen): Get a copy of the state of this node so we can set the node to work listening for changes again right away.
|
||||
listener = *listener_ptr;
|
||||
|
||||
listener_ptr->overlapped = null_overlapped;
|
||||
ReadDirectoryChangesW(listener_ptr->dir, listener_ptr->result, sizeof(listener_ptr->result), 1, FLAGS, 0, &listener_ptr->overlapped, 0);
|
||||
|
||||
offset = 0;
|
||||
has_result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_result){
|
||||
FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION*)(listener.result + offset);
|
||||
|
||||
i32 len = info->FileNameLength / 2;
|
||||
i32 dir_len = GetFinalPathNameByHandle_utf8(listener.dir, 0, 0, FILE_NAME_NORMALIZED);
|
||||
|
||||
i32 req_size = dir_len + (len + 1)*2;
|
||||
*size = req_size;
|
||||
|
||||
if (req_size < max){
|
||||
u32 path_pos = GetFinalPathNameByHandle_utf8(listener.dir, buffer, max, FILE_NAME_NORMALIZED);
|
||||
buffer[path_pos++] = '\\';
|
||||
|
||||
u32 name_max = max - path_pos;
|
||||
u8 *name_buffer = buffer + path_pos;
|
||||
|
||||
b32 convert_error = false;
|
||||
u32 name_pos = (u32)utf16_to_utf8_minimal_checking(name_buffer, name_max, (u16*)info->FileName, len, &convert_error);
|
||||
|
||||
if (name_pos < name_max){
|
||||
if (!convert_error){
|
||||
u32 pos = path_pos + name_pos;
|
||||
*size = pos;
|
||||
if (buffer[0] == '\\'){
|
||||
for (u32 i = 0; i+4 < pos; ++i){
|
||||
buffer[i] = buffer[i+4];
|
||||
}
|
||||
*size -= 4;
|
||||
}
|
||||
result = FileTrack_Good;
|
||||
}
|
||||
else{
|
||||
result = FileTrack_FileSystemError;
|
||||
}
|
||||
}
|
||||
else{
|
||||
result = FileTrack_MemoryTooSmall;
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
// TODO(allen): Need some way to stash this result so that if the
|
||||
// user comes back with more memory we can give them the change
|
||||
// notification they missed.
|
||||
result = FileTrack_MemoryTooSmall;
|
||||
}
|
||||
|
||||
if (info->NextEntryOffset != 0){
|
||||
// TODO(allen): We're not ready to handle this yet.
|
||||
// For now I am breaking. In the future, if there
|
||||
// are more results we should stash them and return
|
||||
// them in future calls.
|
||||
offset += info->NextEntryOffset;
|
||||
has_buffered_event = 1;
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&vars->table_lock);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
shut_down_track_system(File_Track_System *system, Partition *scratch){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Win32_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
DWORD win32_result = 0;
|
||||
|
||||
// NOTE(allen): Close all the handles stored in the table.
|
||||
{
|
||||
File_Track_Tables *tables = to_tables(vars);
|
||||
|
||||
File_Track_Entry *entries = (File_Track_Entry*)to_ptr(tables, tables->file_table);
|
||||
u32 max = tables->max;
|
||||
|
||||
for (u32 index = 0; index < max; ++index){
|
||||
File_Track_Entry *entry = entries + index;
|
||||
|
||||
if (!entry_is_available(entry)){
|
||||
Win32_File_Track_Entry *win32_entry = (Win32_File_Track_Entry*)entry;
|
||||
if (!CancelIo(win32_entry->dir)){
|
||||
win32_result = 1;
|
||||
}
|
||||
if (!CloseHandle(win32_entry->dir)){
|
||||
win32_result = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(allen): Close all the global track system resources.
|
||||
{
|
||||
if (!CloseHandle(vars->iocp)){
|
||||
win32_result = 1;
|
||||
}
|
||||
DeleteCriticalSection(&vars->table_lock);
|
||||
}
|
||||
|
||||
if (win32_result){
|
||||
result = FileTrack_FileSystemError;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
// BOTTOM
|
Loading…
Reference in New Issue