#include #include #include #include #include #include #ifdef _RUN_THREADED #include #endif const char* _prog_name = "fcmp"; __attribute__((noreturn, noinline)) void usage() { fprintf(stderr, "fcmp: compare files for identity\n"); fprintf(stderr, "usage: %s \n", _prog_name); exit(-1); } _FORCE_INLINE const void* die_with_usage_if_null(const void* ptr) { if (!ptr) usage(); else return ptr; } static void unprep_map(mmap_t* restrict map, bool free) { //TODO: Should we actually bother to call this before unmapping? if(!unset_preload_map(map, (int)free)) fprintf(stderr, "Error: failed to unprep map %p (%d)%s, continuing anyway\n", map->ptr, map->fd, (free ? " before closing" : "")); else dprintf("unprep'd %p (%d)", map->ptr, map->fd); } static int unmap_all(mmap_t ptrs[], size_t len) { register int rval=1; dprintf("Unmapping %lu entries", len); for (register size_t i=0;ilen != map2.len) rval = 2; else if (memcmp(map1->ptr, map2.ptr, map1->len) != 0) rval = 1; if(!unmap_and_close(map2)) { fprintf(stderr, "Failed to unmap and close"); rval=-1; } return rval; } static void prep_map(mmap_t* restrict map) { if(!set_preload_map(map)) fprintf(stderr, "Error: failed to prep map %p (%d), continuing anyway\n", map->ptr, map->fd); else dprintf("prep'd %p (%d)", map->ptr, map->fd); } #ifdef _RUN_THREADED struct t_task { _Atomic int* _ALIAS othis; _Atomic bool* _ALIAS ocontinue; int ithis; const char* fthis; mmap_t mthis; const mmap_t* map1; }; void proc_thread(vec_t* restrict v_tasks) { struct t_task * tasks = v_tasks->ptr; mmap_t mrest[v_tasks->len]; #ifdef DEBUG const char* frest[v_tasks->len]; #endif int nrest = v_tasks->len; const mmap_t* map1; { for(register int i=0;ilen;i++) { // Copy map into local buffer mrest[i] = tasks[i].mthis; // Prep this map prep_map(&mrest[i]); #ifdef DEBUG frest[i] = tasks[i].fthis; #endif } map1 = tasks[0].map1; } register int rval=0; for(register int i=0;i